1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 19:42:17 +02:00

CSS processing (in progress, alignment style setting works)

This commit is contained in:
Nikolay Pultsin 2012-05-08 13:53:17 +01:00
parent fce4306ea0
commit 094afe8652
22 changed files with 230 additions and 51 deletions

View file

@ -27,6 +27,7 @@ DONE Chinese/Tamil UTF16 files
* show-hide temporary activity after brightness changing (to switch off the button lights)
DONE encodings list for native plugins
* native: CSS!
* CSS: parse tag lists like 'h1,h2,h3'
* embedded fonts (ePub)
* предупреждение "не могу открыть зашифрованный файл"
* API от Paragon

View file

@ -113,10 +113,17 @@ void BookReader::addControl(FBTextKind kind, bool start) {
}
}
void BookReader::addControl(const ZLTextStyleEntry &entry) {
void BookReader::addStyleEntry(const ZLTextStyleEntry &entry) {
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addControl(entry);
myCurrentTextModel->addStyleEntry(entry);
}
}
void BookReader::addStyleCloseEntry() {
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addStyleCloseEntry();
}
}

View file

@ -56,7 +56,8 @@ public:
void endParagraph();
bool paragraphIsOpen() const;
void addControl(FBTextKind kind, bool start);
void addControl(const ZLTextStyleEntry &entry);
void addStyleEntry(const ZLTextStyleEntry &entry);
void addStyleCloseEntry();
void addHyperlinkControl(FBTextKind kind, const std::string &label);
void addHyperlinkLabel(const std::string &label);
void addHyperlinkLabel(const std::string &label, int paragraphNumber);

View file

@ -226,5 +226,6 @@ void RtfBookReader::setEncoding(int) {
void RtfBookReader::setAlignment() {
ZLTextStyleEntry entry;
entry.setAlignmentType(myState.Alignment);
myBookReader.addControl(entry);
myBookReader.addStyleEntry(entry);
// TODO: call addStyleCloseEntry somewhere (?)
}

View file

@ -511,7 +511,7 @@ bool XHTMLReader::readFile(const ZLFile &file, const std::string &referenceName)
void XHTMLReader::addStyleEntry(const std::string tag, const std::string aClass) {
shared_ptr<ZLTextStyleEntry> entry = myStyleSheetTable.control(tag, aClass);
if (!entry.isNull()) {
myModelReader.addControl(*entry);
myModelReader.addStyleEntry(*entry);
myStyleEntryStack.push_back(entry);
}
}
@ -546,7 +546,7 @@ void XHTMLReader::startElementHandler(const char *tag, const char **attributes)
if (style != 0) {
ZLLogger::Instance().println("CSS", std::string("parsing style attribute: ") + style);
shared_ptr<ZLTextStyleEntry> entry = myStyleParser.parseString(style);
myModelReader.addControl(*entry);
myModelReader.addStyleEntry(*entry);
myStyleEntryStack.push_back(entry);
}
myCSSStack.push_back(myStyleEntryStack.size() - sizeBefore);
@ -554,7 +554,7 @@ void XHTMLReader::startElementHandler(const char *tag, const char **attributes)
void XHTMLReader::endElementHandler(const char *tag) {
for (int i = myCSSStack.back(); i > 0; --i) {
myModelReader.addControl(REGULAR, false);
myModelReader.addStyleCloseEntry();
}
myStylesToRemove = myCSSStack.back();
myCSSStack.pop_back();
@ -580,7 +580,7 @@ void XHTMLReader::beginParagraph() {
myModelReader.beginParagraph();
bool doBlockSpaceBefore = false;
for (std::vector<shared_ptr<ZLTextStyleEntry> >::const_iterator it = myStyleEntryStack.begin(); it != myStyleEntryStack.end(); ++it) {
myModelReader.addControl(**it);
myModelReader.addStyleEntry(**it);
doBlockSpaceBefore =
doBlockSpaceBefore ||
(*it)->isFeatureSupported(ZLTextStyleEntry::LENGTH_SPACE_BEFORE);
@ -593,7 +593,7 @@ void XHTMLReader::beginParagraph() {
0,
ZLTextStyleEntry::SIZE_UNIT_PIXEL
);
myModelReader.addControl(blockingEntry);
myModelReader.addStyleEntry(blockingEntry);
}
}
@ -611,10 +611,10 @@ void XHTMLReader::endParagraph() {
0,
ZLTextStyleEntry::SIZE_UNIT_PIXEL
);
myModelReader.addControl(blockingEntry);
myModelReader.addStyleEntry(blockingEntry);
}
for (; myStylesToRemove > 0; --myStylesToRemove) {
myModelReader.addControl(*myStyleEntryStack.back());
myModelReader.addStyleEntry(*myStyleEntryStack.back());
myStyleEntryStack.pop_back();
}
myModelReader.endParagraph();

View file

@ -271,7 +271,7 @@ void ZLTextModel::addControl(ZLTextKind textKind, bool isStart) {
//static int EntryCount = 0;
//static int EntryLen = 0;
void ZLTextModel::addControl(const ZLTextStyleEntry &entry) {
void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry) {
// +++ calculating entry size
size_t len = 4; // entry type + feature mask
for (int i = 0; i < ZLTextStyleEntry::NUMBER_OF_LENGTHS; ++i) {
@ -337,6 +337,17 @@ void ZLTextModel::addControl(const ZLTextStyleEntry &entry) {
++myParagraphLengths.back();
}
void ZLTextModel::addStyleCloseEntry() {
myLastEntryStart = myAllocator->allocate(2);
char *address = myLastEntryStart;
*address++ = ZLTextParagraphEntry::STYLE_CLOSE_ENTRY;
*address++ = 0;
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label) {
ZLUnicodeUtil::Ucs2String ucs2label;
ZLUnicodeUtil::utf8ToUcs2(ucs2label, label);

View file

@ -72,7 +72,8 @@ public:
ZLTextMark previousMark(ZLTextMark position) const;
*/
void addControl(ZLTextKind textKind, bool isStart);
void addControl(const ZLTextStyleEntry &entry);
void addStyleEntry(const ZLTextStyleEntry &entry);
void addStyleCloseEntry();
void addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label);
void addText(const std::string &text);
void addText(const std::vector<std::string> &text);

View file

@ -42,8 +42,9 @@ public:
CONTROL_ENTRY = 3,
HYPERLINK_CONTROL_ENTRY = 4,
STYLE_ENTRY = 5,
FIXED_HSPACE_ENTRY = 6,
RESET_BIDI_ENTRY = 7,
STYLE_CLOSE_ENTRY = 6,
FIXED_HSPACE_ENTRY = 7,
RESET_BIDI_ENTRY = 8,
};
protected:

View file

@ -26,8 +26,9 @@ public interface ZLTextParagraph {
byte CONTROL = 3;
byte HYPERLINK_CONTROL = 4;
byte STYLE = 5;
byte FIXED_HSPACE = 6;
byte RESET_BIDI = 7;
byte STYLE_CLOSE = 6;
byte FIXED_HSPACE = 7;
byte RESET_BIDI = 8;
}
interface EntryIterator {
@ -44,6 +45,7 @@ public interface ZLTextParagraph {
String getHyperlinkId();
ZLImageEntry getImageEntry();
ZLTextStyleEntry getStyleEntry();
short getFixedHSpaceLength();

View file

@ -215,8 +215,11 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature {
myStyleEntry = entry;
}
case ZLTextParagraph.Entry.STYLE_CLOSE:
// No data
break;
case ZLTextParagraph.Entry.RESET_BIDI:
// No data => skip
// No data
break;
}
++myCounter;

View file

@ -20,7 +20,7 @@
package org.geometerplus.zlibrary.text.model;
public final class ZLTextStyleEntry {
interface Feature {
public interface Feature {
int LENGTH_LEFT_INDENT = 0;
int LENGTH_RIGHT_INDENT = 1;
int LENGTH_FIRST_LINE_INDENT_DELTA = 2;
@ -64,7 +64,6 @@ public final class ZLTextStyleEntry {
void setAlignmentType(byte alignmentType) {
myFeatureMask |= 1 << Feature.ALIGNMENT_TYPE;
System.err.println("setting alignment to " + alignmentType);
myAlignmentType = alignmentType;
}
@ -74,7 +73,6 @@ public final class ZLTextStyleEntry {
void setFontSizeMagnification(byte fontSizeMagnification) {
myFeatureMask |= 1 << Feature.FONT_SIZE_MAGNIFICATION;
System.err.println("setting font size magnification to " + fontSizeMagnification);
myFontSizeMagnification = fontSizeMagnification;
}

View file

@ -22,5 +22,6 @@ package org.geometerplus.zlibrary.text.view;
public class ZLTextElement {
final static ZLTextElement HSpace = new ZLTextElement();
final static ZLTextElement AfterParagraph = new ZLTextElement();
final static ZLTextElement IndentElement = new ZLTextElement();
final static ZLTextElement Indent = new ZLTextElement();
final static ZLTextElement StyleClose = new ZLTextElement();
}

View file

@ -101,7 +101,10 @@ public final class ZLTextParagraphCursor {
}
break;
case ZLTextParagraph.Entry.STYLE:
// TODO: implement
elements.add(new ZLTextStyleElement(it.getStyleEntry()));
break;
case ZLTextParagraph.Entry.STYLE_CLOSE:
elements.add(ZLTextElement.StyleClose);
break;
case ZLTextParagraph.Entry.FIXED_HSPACE:
elements.add(ZLTextFixedHSpaceElement.getElement(it.getFixedHSpaceLength()));

View file

@ -24,7 +24,7 @@ public abstract class ZLTextStyle {
public final ZLTextHyperlink Hyperlink;
protected ZLTextStyle(ZLTextStyle base, ZLTextHyperlink hyperlink) {
Base = (base != null) ? base : this;
Base = base != null ? base : this;
Hyperlink = hyperlink;
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2007-2012 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.zlibrary.text.view;
import org.geometerplus.zlibrary.text.model.ZLTextStyleEntry;
public class ZLTextStyleElement extends ZLTextElement {
public final ZLTextStyleEntry Entry;
ZLTextStyleElement(ZLTextStyleEntry entry) {
Entry = entry;
}
}

View file

@ -544,7 +544,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
final float charWidth = computeCharWidth();
final int indentWidth = getElementWidth(ZLTextElement.IndentElement, 0);
final int indentWidth = getElementWidth(ZLTextElement.Indent, 0);
final float effectiveWidth = textWidth - (indentWidth + 0.5f * textWidth) / charsPerParagraph;
float charsPerLine = Math.min(effectiveWidth / charWidth,
charsPerParagraph * 1.2f);
@ -830,7 +830,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
resetTextStyle();
final ZLTextParagraphCursor paragraphCursor = result.getParagraphCursor();
final int wordIndex = result.getElementIndex();
applyControls(paragraphCursor, 0, wordIndex);
applyStyleChanges(paragraphCursor, 0, wordIndex);
ZLTextLineInfo info = new ZLTextLineInfo(paragraphCursor, wordIndex, result.getCharIndex(), getTextStyle());
final int endIndex = info.ParagraphCursorLength;
while (info.EndElementIndex != endIndex) {
@ -866,7 +866,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
final ZLTextLineInfo info = new ZLTextLineInfo(paragraphCursor, startIndex, startCharIndex, getTextStyle());
final ZLTextLineInfo cachedInfo = myLineInfoCache.get(info);
if (cachedInfo != null) {
applyControls(paragraphCursor, startIndex, cachedInfo.EndElementIndex);
applyStyleChanges(paragraphCursor, startIndex, cachedInfo.EndElementIndex);
return cachedInfo;
}
@ -876,8 +876,8 @@ public abstract class ZLTextView extends ZLTextViewBase {
if (isFirstLine) {
ZLTextElement element = paragraphCursor.getElement(currentElementIndex);
while (element instanceof ZLTextControlElement) {
applyControl((ZLTextControlElement)element);
while (isStyleChangeElement(element)) {
applyStyleChangeElement(element);
++currentElementIndex;
currentCharIndex = 0;
if (currentElementIndex == endIndex) {
@ -930,11 +930,11 @@ public abstract class ZLTextView extends ZLTextViewBase {
} else if (element instanceof ZLTextWord) {
wordOccurred = true;
isVisible = true;
} else if (element instanceof ZLTextControlElement) {
applyControl((ZLTextControlElement)element);
} else if (element instanceof ZLTextImageElement) {
wordOccurred = true;
isVisible = true;
} else if (isStyleChangeElement(element)) {
applyStyleChangeElement(element);
}
if (newWidth > maxWidth) {
if (info.EndElementIndex != startIndex || element instanceof ZLTextWord) {
@ -1127,8 +1127,8 @@ public abstract class ZLTextView extends ZLTextViewBase {
));
changeStyle = false;
wordOccurred = true;
} else if (element instanceof ZLTextControlElement) {
applyControl((ZLTextControlElement)element);
} else if (isStyleChangeElement(element)) {
applyStyleChangeElement(element);
changeStyle = true;
}
x += width;
@ -1402,7 +1402,7 @@ public abstract class ZLTextView extends ZLTextViewBase {
final int endElementIndex = paragraphCursor.getParagraphLength();
resetTextStyle();
applyControls(paragraphCursor, 0, cursor.getElementIndex());
applyStyleChanges(paragraphCursor, 0, cursor.getElementIndex());
while (!cursor.isEndOfParagraph() && (size > 0)) {
ZLTextLineInfo info = processTextLine(paragraphCursor, cursor.getElementIndex(), cursor.getCharIndex(), endElementIndex);

View file

@ -25,8 +25,7 @@ import org.geometerplus.zlibrary.core.view.ZLView;
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleCollection;
import org.geometerplus.zlibrary.text.view.style.ZLTextStyleDecoration;
import org.geometerplus.zlibrary.text.view.style.*;
abstract class ZLTextViewBase extends ZLView {
private ZLTextStyle myTextStyle;
@ -94,7 +93,30 @@ abstract class ZLTextViewBase extends ZLView {
setTextStyle(ZLTextStyleCollection.Instance().getBaseStyle());
}
void applyControl(ZLTextControlElement control) {
boolean isStyleChangeElement(ZLTextElement element) {
return
element == ZLTextElement.StyleClose ||
element instanceof ZLTextStyleElement ||
element instanceof ZLTextControlElement;
}
void applyStyleChangeElement(ZLTextElement element) {
if (element == ZLTextElement.StyleClose) {
applyStyleClose();
} else if (element instanceof ZLTextStyleElement) {
applyStyle((ZLTextStyleElement)element);
} else if (element instanceof ZLTextControlElement) {
applyControl((ZLTextControlElement)element);
}
}
void applyStyleChanges(ZLTextParagraphCursor cursor, int index, int end) {
for (; index != end; ++index) {
applyStyleChangeElement(cursor.getElement(index));
}
}
private void applyControl(ZLTextControlElement control) {
if (control.IsStart) {
final ZLTextStyleDecoration decoration =
ZLTextStyleCollection.Instance().getDecoration(control.Kind);
@ -108,13 +130,12 @@ abstract class ZLTextViewBase extends ZLView {
}
}
void applyControls(ZLTextParagraphCursor cursor, int index, int end) {
for (; index != end; ++index) {
final ZLTextElement element = cursor.getElement(index);
if (element instanceof ZLTextControlElement) {
applyControl((ZLTextControlElement)element);
}
private void applyStyle(ZLTextStyleElement element) {
setTextStyle(new ZLTextExplicitlyDecoratedStyle(myTextStyle, element.Entry));
}
private void applyStyleClose() {
setTextStyle(myTextStyle.Base);
}
final int getElementWidth(ZLTextElement element, int charIndex) {
@ -130,7 +151,7 @@ abstract class ZLTextViewBase extends ZLView {
: ZLPaintContext.ScalingType.IntegerCoefficient
);
return size != null ? size.Width : 0;
} else if (element == ZLTextElement.IndentElement) {
} else if (element == ZLTextElement.Indent) {
return myTextStyle.getFirstLineIndentDelta();
} else if (element instanceof ZLTextFixedHSpaceElement) {
return myContext.getSpaceWidth() * ((ZLTextFixedHSpaceElement)element).Length;

View file

@ -0,0 +1,98 @@
/*
* Copyright (C) 2007-2012 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.zlibrary.text.view.style;
import org.geometerplus.zlibrary.text.view.ZLTextStyle;
import org.geometerplus.zlibrary.text.model.ZLTextStyleEntry;
public class ZLTextExplicitlyDecoratedStyle extends ZLTextStyle implements ZLTextStyleEntry.Feature {
private final ZLTextStyleEntry myEntry;
public ZLTextExplicitlyDecoratedStyle(ZLTextStyle base, ZLTextStyleEntry entry) {
super(base, base.Hyperlink);
myEntry = entry;
}
public String getFontFamily() {
// TODO: implement
return Base.getFontFamily();
}
public int getFontSize() {
// TODO: implement
return Base.getFontSize();
}
public boolean isBold() {
// TODO: implement
return Base.isBold();
}
public boolean isItalic() {
// TODO: implement
return Base.isItalic();
}
public boolean isUnderline() {
// TODO: implement
return Base.isUnderline();
}
public boolean isStrikeThrough() {
// TODO: implement
return Base.isStrikeThrough();
}
public int getLeftIndent() {
// TODO: implement
return Base.getLeftIndent();
}
public int getRightIndent() {
// TODO: implement
return Base.getRightIndent();
}
public int getFirstLineIndentDelta() {
// TODO: implement
return Base.getFirstLineIndentDelta();
}
public int getLineSpacePercent() {
// TODO: implement
return Base.getLineSpacePercent();
}
public int getVerticalShift() {
// TODO: implement
return Base.getVerticalShift();
}
public int getSpaceBefore() {
// TODO: implement
return Base.getSpaceBefore();
}
public int getSpaceAfter() {
// TODO: implement
return Base.getSpaceAfter();
}
public byte getAlignment() {
return
myEntry.isFeatureSupported(ALIGNMENT_TYPE)
? myEntry.getAlignmentType()
: Base.getAlignment();
}
public boolean allowHyphenations() {
// TODO: implement
return Base.allowHyphenations();
}
}

View file

@ -49,6 +49,6 @@ public class ZLTextFullStyleDecoration extends ZLTextStyleDecoration {
}
public ZLTextStyle createDecoratedStyle(ZLTextStyle base, ZLTextHyperlink hyperlink) {
return new ZLTextFullDecoratedStyle(base, this, hyperlink);
return new ZLTextFullyDecoratedStyle(base, this, hyperlink);
}
}

View file

@ -23,10 +23,10 @@ import org.geometerplus.zlibrary.text.view.ZLTextStyle;
import org.geometerplus.zlibrary.text.view.ZLTextHyperlink;
import org.geometerplus.zlibrary.text.model.ZLTextAlignmentType;
public class ZLTextFullDecoratedStyle extends ZLTextPartialDecoratedStyle {
public class ZLTextFullyDecoratedStyle extends ZLTextPartiallyDecoratedStyle {
private final ZLTextFullStyleDecoration myFullDecoration;
ZLTextFullDecoratedStyle(ZLTextStyle base, ZLTextFullStyleDecoration decoration, ZLTextHyperlink hyperlink) {
ZLTextFullyDecoratedStyle(ZLTextStyle base, ZLTextFullStyleDecoration decoration, ZLTextHyperlink hyperlink) {
super(base, decoration, hyperlink);
myFullDecoration = decoration;
}

View file

@ -22,10 +22,10 @@ package org.geometerplus.zlibrary.text.view.style;
import org.geometerplus.zlibrary.text.view.ZLTextStyle;
import org.geometerplus.zlibrary.text.view.ZLTextHyperlink;
class ZLTextPartialDecoratedStyle extends ZLTextDecoratedStyle {
class ZLTextPartiallyDecoratedStyle extends ZLTextDecoratedStyle {
private final ZLTextStyleDecoration myDecoration;
ZLTextPartialDecoratedStyle(ZLTextStyle base, ZLTextStyleDecoration decoration, ZLTextHyperlink hyperlink) {
ZLTextPartiallyDecoratedStyle(ZLTextStyle base, ZLTextStyleDecoration decoration, ZLTextHyperlink hyperlink) {
super(base, hyperlink);
myDecoration = decoration;
}

View file

@ -56,7 +56,7 @@ public class ZLTextStyleDecoration {
}
public ZLTextStyle createDecoratedStyle(ZLTextStyle base, ZLTextHyperlink hyperlink) {
return new ZLTextPartialDecoratedStyle(base, this, hyperlink);
return new ZLTextPartiallyDecoratedStyle(base, this, hyperlink);
}
public String getName() {