diff --git a/ChangeLog b/ChangeLog index 594b9338e..65d19d4b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,9 @@ * (planned) Fixed authors list/tags list editing * (planned) CSS selectors priority +===== 2.2 beta 3 (Nov ??, 2014) ===== +* Added 'padding' and 'padding-*' CSS property support + ===== 2.2 beta 2 (Nov 02, 2014) ===== * Added '*' selector support in CSS * Optimised combined selectors processing diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp index eab7068d1..497cbfe65 100644 --- a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp @@ -123,17 +123,17 @@ void BookReader::addControl(FBTextKind kind, bool start) { } } -void BookReader::addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies) { +void BookReader::addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies, unsigned char depth) { if (paragraphIsOpen()) { flushTextBufferToParagraph(); - myCurrentTextModel->addStyleEntry(entry, fontFamilies); + myCurrentTextModel->addStyleEntry(entry, fontFamilies, depth); } } -void BookReader::addStyleEntry(const ZLTextStyleEntry &entry) { +void BookReader::addStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth) { if (paragraphIsOpen()) { flushTextBufferToParagraph(); - myCurrentTextModel->addStyleEntry(entry); + myCurrentTextModel->addStyleEntry(entry, depth); } } diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h index ab62bd944..d225f93ea 100644 --- a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.h @@ -61,8 +61,8 @@ public: void endParagraph(); bool paragraphIsOpen() const; void addControl(FBTextKind kind, bool start); - void addStyleEntry(const ZLTextStyleEntry &entry); - void addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies); + void addStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth); + void addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies, unsigned char depth); void addStyleCloseEntry(); void addHyperlinkControl(FBTextKind kind, const std::string &label); void addHyperlinkLabel(const std::string &label); diff --git a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetTable.cpp b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetTable.cpp index 383299f31..d095ab979 100644 --- a/jni/NativeFormats/fbreader/src/formats/css/StyleSheetTable.cpp +++ b/jni/NativeFormats/fbreader/src/formats/css/StyleSheetTable.cpp @@ -279,12 +279,35 @@ shared_ptr StyleSheetTable::createOrUpdateControl(const Attrib } } ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, split[0]); - ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, split[1]); + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_MARGIN_RIGHT, split[1]); ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, split[2]); - ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, split[3]); + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_MARGIN_LEFT, split[3]); } - setLength(*entry, ZLTextStyleEntry::LENGTH_LEFT_INDENT, styles, "margin-left"); - setLength(*entry, ZLTextStyleEntry::LENGTH_RIGHT_INDENT, styles, "margin-right"); + const std::string padding = value(styles, "padding"); + if (!padding.empty()) { + std::vector split = ZLStringUtil::split(padding, " ", true); + if (split.size() > 0) { + switch (split.size()) { + case 1: + split.push_back(split[0]); + // go through + case 2: + split.push_back(split[0]); + // go through + case 3: + split.push_back(split[1]); + break; + } + } + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, split[0]); + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_PADDING_RIGHT, split[1]); + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_AFTER, split[2]); + ::trySetLength(*entry, ZLTextStyleEntry::LENGTH_PADDING_LEFT, split[3]); + } + setLength(*entry, ZLTextStyleEntry::LENGTH_MARGIN_LEFT, styles, "margin-left"); + setLength(*entry, ZLTextStyleEntry::LENGTH_MARGIN_RIGHT, styles, "margin-right"); + setLength(*entry, ZLTextStyleEntry::LENGTH_PADDING_LEFT, styles, "padding-left"); + setLength(*entry, ZLTextStyleEntry::LENGTH_PADDING_RIGHT, styles, "padding-right"); setLength(*entry, ZLTextStyleEntry::LENGTH_FIRST_LINE_INDENT, styles, "text-indent"); setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, styles, "margin-top"); setLength(*entry, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, styles, "padding-top"); diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp index 9e559c4bd..74443e281 100644 --- a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp +++ b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp @@ -87,7 +87,7 @@ void DocBookReader::handleHardLinebreak() { } myModelReader.beginParagraph(); if (!myCurrentStyleEntry.isNull()) { - myModelReader.addStyleEntry(*myCurrentStyleEntry); + myModelReader.addStyleEntry(*myCurrentStyleEntry, 0); } for (std::size_t i = 0; i < myKindStack.size(); ++i) { myModelReader.addControl(myKindStack.at(i), true); @@ -276,7 +276,7 @@ void DocBookReader::handleParagraphStyle(const OleMainStream::Style &styleInfo) break; } myCurrentStyleEntry = entry; - myModelReader.addStyleEntry(*myCurrentStyleEntry); + myModelReader.addStyleEntry(*myCurrentStyleEntry, 0); // we should have the same font style, as for the previous paragraph, // if it has the same StyleIdCurrent diff --git a/jni/NativeFormats/fbreader/src/formats/html/HtmlBookReader.cpp b/jni/NativeFormats/fbreader/src/formats/html/HtmlBookReader.cpp index ec775d672..1230f4566 100644 --- a/jni/NativeFormats/fbreader/src/formats/html/HtmlBookReader.cpp +++ b/jni/NativeFormats/fbreader/src/formats/html/HtmlBookReader.cpp @@ -465,11 +465,12 @@ bool HtmlBookReader::tagHandler(const HtmlTag &tag) { if (tag.Start) { for (std::vector >::const_iterator it = myTagDataStack.begin(); it != myTagDataStack.end(); ++it) { + const unsigned char depth = it - myTagDataStack.begin() + 1; const std::vector > &entries = (*it)->StyleEntries; const bool inheritedOnly = it + 1 != myTagDataStack.end(); for (std::vector >::const_iterator jt = entries.begin(); jt != entries.end(); ++jt) { shared_ptr entry = inheritedOnly ? (*jt)->inherited() : *jt; - myBookReader.addStyleEntry(*entry); + myBookReader.addStyleEntry(*entry, depth); } } } diff --git a/jni/NativeFormats/fbreader/src/formats/rtf/RtfBookReader.cpp b/jni/NativeFormats/fbreader/src/formats/rtf/RtfBookReader.cpp index 19b68cea3..1f0a9014f 100644 --- a/jni/NativeFormats/fbreader/src/formats/rtf/RtfBookReader.cpp +++ b/jni/NativeFormats/fbreader/src/formats/rtf/RtfBookReader.cpp @@ -227,6 +227,7 @@ void RtfBookReader::setEncoding(int) { void RtfBookReader::setAlignment() { ZLTextStyleEntry entry(ZLTextStyleEntry::STYLE_OTHER_ENTRY); entry.setAlignmentType(myState.Alignment); - myBookReader.addStyleEntry(entry); + // TODO: replace 0 with depth? + myBookReader.addStyleEntry(entry, 0); // TODO: call addStyleCloseEntry somewhere (?) } diff --git a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp index 2d85f6460..1af6d3839 100644 --- a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp +++ b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp @@ -735,23 +735,23 @@ bool XHTMLReader::matches(const shared_ptr next, int dep } } -void XHTMLReader::addTextStyleEntry(const std::string &tag, const std::string &aClass) { +void XHTMLReader::addTextStyleEntry(const std::string &tag, const std::string &aClass, unsigned char depth) { std::vector > > controls = myStyleSheetTable.allControls(tag, aClass); for (std::vector > >::const_iterator it = controls.begin(); it != controls.end(); ++it) { if (matches(it->first.Next)) { shared_ptr entry = it->second; if (!entry.isNull()) { - addTextStyleEntry(*(entry->start())); + addTextStyleEntry(*(entry->start()), depth); myTagDataStack.back()->StyleEntries.push_back(entry); } } } } -void XHTMLReader::addTextStyleEntry(const ZLTextStyleEntry &entry) { +void XHTMLReader::addTextStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth) { if (!entry.isFeatureSupported(ZLTextStyleEntry::FONT_FAMILY)) { - myModelReader.addStyleEntry(entry); + myModelReader.addStyleEntry(entry, depth); return; } @@ -772,7 +772,7 @@ void XHTMLReader::addTextStyleEntry(const ZLTextStyleEntry &entry) { } if (!doFixFamiliesList) { - myModelReader.addStyleEntry(entry); + myModelReader.addStyleEntry(entry, depth); } else { std::vector realFamilies; for (std::vector::const_iterator it = families.begin(); it != families.end(); ++it) { @@ -783,7 +783,7 @@ void XHTMLReader::addTextStyleEntry(const ZLTextStyleEntry &entry) { realFamilies.push_back(*it); } } - myModelReader.addStyleEntry(entry, realFamilies); + myModelReader.addStyleEntry(entry, realFamilies, depth); } } @@ -835,17 +835,18 @@ void XHTMLReader::startElementHandler(const char *tag, const char **attributes) action->doAtStart(*this, attributes); } - addTextStyleEntry(ANY, EMPTY); - addTextStyleEntry(sTag, EMPTY); + const unsigned char depth = myTagDataStack.size(); + addTextStyleEntry(ANY, EMPTY, depth); + addTextStyleEntry(sTag, EMPTY, depth); for (std::vector::const_iterator it = classesList.begin(); it != classesList.end(); ++it) { - addTextStyleEntry(EMPTY, *it); - addTextStyleEntry(sTag, *it); + addTextStyleEntry(EMPTY, *it, depth); + addTextStyleEntry(sTag, *it, depth); } const char *style = attributeValue(attributes, "style"); if (style != 0) { //ZLLogger::Instance().println("CSS", std::string("parsing style attribute: ") + style); shared_ptr entry = myStyleParser->parseSingleEntry(style); - addTextStyleEntry(*entry); + addTextStyleEntry(*entry, depth); myTagDataStack.back()->StyleEntries.push_back(entry); } } @@ -859,10 +860,11 @@ void XHTMLReader::endElementHandler(const char *tag) { const TagData &tagData = *myTagDataStack.back(); const std::vector > &entries = tagData.StyleEntries; size_t entryCount = entries.size(); + const unsigned char depth = myTagDataStack.size(); for (std::vector >::const_iterator jt = entries.begin(); jt != entries.end(); ++jt) { shared_ptr endEntry = (*jt)->end(); if (!endEntry.isNull()) { - addTextStyleEntry(*endEntry); + addTextStyleEntry(*endEntry, depth); ++entryCount; } } @@ -894,9 +896,10 @@ void XHTMLReader::beginParagraph(bool restarted) { } const std::vector > &entries = (*it)->StyleEntries; bool inheritedOnly = !restarted || it + 1 != myTagDataStack.end(); + const unsigned char depth = it - myTagDataStack.begin() + 1; for (std::vector >::const_iterator jt = entries.begin(); jt != entries.end(); ++jt) { shared_ptr entry = inheritedOnly ? (*jt)->inherited() : (*jt)->start(); - addTextStyleEntry(*entry); + addTextStyleEntry(*entry, depth); } } } @@ -909,13 +912,14 @@ void XHTMLReader::restartParagraph() { if (myCurrentParagraphIsEmpty) { myModelReader.addFixedHSpace(1); } + const unsigned char depth = myTagDataStack.size(); ZLTextStyleEntry spaceAfterBlocker(ZLTextStyleEntry::STYLE_OTHER_ENTRY); spaceAfterBlocker.setLength( ZLTextStyleEntry::LENGTH_SPACE_AFTER, 0, ZLTextStyleEntry::SIZE_UNIT_PIXEL ); - addTextStyleEntry(spaceAfterBlocker); + addTextStyleEntry(spaceAfterBlocker, depth); endParagraph(); beginParagraph(true); ZLTextStyleEntry spaceBeforeBlocker(ZLTextStyleEntry::STYLE_OTHER_ENTRY); @@ -924,7 +928,7 @@ void XHTMLReader::restartParagraph() { 0, ZLTextStyleEntry::SIZE_UNIT_PIXEL ); - addTextStyleEntry(spaceBeforeBlocker); + addTextStyleEntry(spaceBeforeBlocker, depth); } void XHTMLReader::pushTextKind(FBTextKind kind) { diff --git a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.h b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.h index b502d33c7..5d482ea78 100644 --- a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.h +++ b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.h @@ -109,8 +109,8 @@ private: void restartParagraph(); const XHTMLTagInfoList &tagInfos(size_t depth) const; bool matches(const shared_ptr next, int depth = 0, int pos = -1) const; - void addTextStyleEntry(const std::string &tag, const std::string &aClass); - void addTextStyleEntry(const ZLTextStyleEntry &entry); + void addTextStyleEntry(const std::string &tag, const std::string &aClass, unsigned char depth); + void addTextStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth); void pushTextKind(FBTextKind kind); diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp index 7dc2e8c56..ed7894dc1 100644 --- a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp @@ -239,11 +239,11 @@ void ZLTextModel::addControl(ZLTextKind textKind, bool isStart) { //static int EntryCount = 0; //static int EntryLen = 0; -void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry) { - addStyleEntry(entry, entry.fontFamilies()); +void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth) { + addStyleEntry(entry, entry.fontFamilies(), depth); } -void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies) { +void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies, unsigned char depth) { // +++ calculating entry size std::size_t len = 4; // entry type + feature mask for (int i = 0; i < ZLTextStyleEntry::NUMBER_OF_LENGTHS; ++i) { @@ -278,7 +278,7 @@ void ZLTextModel::addStyleEntry(const ZLTextStyleEntry &entry, const std::vector char *address = myLastEntryStart; *address++ = entry.entryKind(); - *address++ = 0; + *address++ = depth; address = ZLCachedMemoryAllocator::writeUInt16(address, entry.myFeatureMask); for (int i = 0; i < ZLTextStyleEntry::NUMBER_OF_LENGTHS; ++i) { diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h index 2ea555b3b..cfd66a390 100644 --- a/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextModel.h @@ -67,8 +67,8 @@ public: ZLTextMark previousMark(ZLTextMark position) const; */ void addControl(ZLTextKind textKind, bool isStart); - void addStyleEntry(const ZLTextStyleEntry &entry); - void addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies); + void addStyleEntry(const ZLTextStyleEntry &entry, unsigned char depth); + void addStyleEntry(const ZLTextStyleEntry &entry, const std::vector &fontFamilies, unsigned char depth); void addStyleCloseEntry(); void addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label); void addText(const std::string &text); diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp index e1c8d893d..7d0e08eb6 100644 --- a/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp @@ -46,8 +46,10 @@ short ZLTextStyleEntry::length(Feature featureId, const Metrics &metrics) const case SIZE_UNIT_PERCENT: switch (featureId) { default: - case LENGTH_LEFT_INDENT: - case LENGTH_RIGHT_INDENT: + case LENGTH_MARGIN_LEFT: + case LENGTH_MARGIN_RIGHT: + case LENGTH_PADDING_LEFT: + case LENGTH_PADDING_RIGHT: case LENGTH_FIRST_LINE_INDENT: return (myLengths[featureId].Size * metrics.FullWidth + 50) / 100; case LENGTH_SPACE_BEFORE: diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.cpp b/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.cpp index bff2f81c7..4c29c2f3e 100644 --- a/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.cpp +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.cpp @@ -45,7 +45,14 @@ shared_ptr ZLTextStyleEntry::end() const { shared_ptr ZLTextStyleEntry::inherited() const { ZLTextStyleEntry *clone = new ZLTextStyleEntry(myEntryKind); - clone->myFeatureMask = myFeatureMask & ~(1 << LENGTH_SPACE_BEFORE) & ~(1 << LENGTH_SPACE_AFTER); + static const unsigned short skip = + //(1 << LENGTH_MARGIN_LEFT) | + //(1 << LENGTH_MARGIN_RIGHT) | + //(1 << LENGTH_PADDING_LEFT) | + //(1 << LENGTH_PADDING_RIGHT) | + (1 << LENGTH_SPACE_BEFORE) | + (1 << LENGTH_SPACE_AFTER); + clone->myFeatureMask = myFeatureMask & ~skip; for (int i = 0; i < NUMBER_OF_LENGTHS; ++i) { clone->myLengths[i] = myLengths[i]; } diff --git a/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.h b/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.h index d567a168d..9a672a9b2 100644 --- a/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.h +++ b/jni/NativeFormats/zlibrary/text/src/model/ZLTextStyleEntry.h @@ -62,14 +62,16 @@ public: }; enum Feature { - LENGTH_LEFT_INDENT = 0, - LENGTH_RIGHT_INDENT = 1, - LENGTH_FIRST_LINE_INDENT = 2, - LENGTH_SPACE_BEFORE = 3, - LENGTH_SPACE_AFTER = 4, - LENGTH_FONT_SIZE = 5, - LENGTH_VERTICAL_ALIGN = 6, - NUMBER_OF_LENGTHS = 7, + LENGTH_PADDING_LEFT = 0, + LENGTH_PADDING_RIGHT = 1, + LENGTH_MARGIN_LEFT = 2, + LENGTH_MARGIN_RIGHT = 3, + LENGTH_FIRST_LINE_INDENT = 4, + LENGTH_SPACE_BEFORE = 5, + LENGTH_SPACE_AFTER = 6, + LENGTH_FONT_SIZE = 7, + LENGTH_VERTICAL_ALIGN = 8, + NUMBER_OF_LENGTHS = 9, ALIGNMENT_TYPE = NUMBER_OF_LENGTHS, FONT_FAMILY = NUMBER_OF_LENGTHS + 1, FONT_STYLE_MODIFIER = NUMBER_OF_LENGTHS + 2, diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextCSSStyleEntry.java b/src/org/geometerplus/zlibrary/text/model/ZLTextCSSStyleEntry.java index 6c363e977..9f62e65e7 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextCSSStyleEntry.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextCSSStyleEntry.java @@ -20,6 +20,7 @@ package org.geometerplus.zlibrary.text.model; public final class ZLTextCSSStyleEntry extends ZLTextStyleEntry { - public ZLTextCSSStyleEntry() { + public ZLTextCSSStyleEntry(short depth) { + super(depth); } } diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextOtherStyleEntry.java b/src/org/geometerplus/zlibrary/text/model/ZLTextOtherStyleEntry.java index 7ed2c85ad..7b2a5f1c7 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextOtherStyleEntry.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextOtherStyleEntry.java @@ -21,5 +21,6 @@ package org.geometerplus.zlibrary.text.model; public final class ZLTextOtherStyleEntry extends ZLTextStyleEntry { public ZLTextOtherStyleEntry() { + super((short)0); } } diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java b/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java index 39d3437e4..1b1a54136 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextPlainModel.java @@ -147,14 +147,16 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { } dataOffset = 0; } - byte type = (byte)data[dataOffset]; + short first = (short)data[dataOffset]; + byte type = (byte)first; if (type == 0) { data = myStorage.block(++myDataIndex); if (data == null) { return false; } dataOffset = 0; - type = (byte)data[0]; + first = (short)data[0]; + type = (byte)first; } myType = type; ++dataOffset; @@ -205,9 +207,10 @@ public class ZLTextPlainModel implements ZLTextModel, ZLTextStyleEntry.Feature { case ZLTextParagraph.Entry.STYLE_CSS: case ZLTextParagraph.Entry.STYLE_OTHER: { + final short depth = (short)((first >> 8) & 0xFF); final ZLTextStyleEntry entry = type == ZLTextParagraph.Entry.STYLE_CSS - ? new ZLTextCSSStyleEntry() + ? new ZLTextCSSStyleEntry(depth) : new ZLTextOtherStyleEntry(); final short mask = (short)data[dataOffset++]; diff --git a/src/org/geometerplus/zlibrary/text/model/ZLTextStyleEntry.java b/src/org/geometerplus/zlibrary/text/model/ZLTextStyleEntry.java index 288bfe69f..e2596155f 100644 --- a/src/org/geometerplus/zlibrary/text/model/ZLTextStyleEntry.java +++ b/src/org/geometerplus/zlibrary/text/model/ZLTextStyleEntry.java @@ -28,14 +28,16 @@ import org.geometerplus.zlibrary.core.util.ZLBoolean3; public abstract class ZLTextStyleEntry { public interface Feature { - int LENGTH_LEFT_INDENT = 0; - int LENGTH_RIGHT_INDENT = 1; - int LENGTH_FIRST_LINE_INDENT = 2; - int LENGTH_SPACE_BEFORE = 3; - int LENGTH_SPACE_AFTER = 4; - int LENGTH_FONT_SIZE = 5; - int LENGTH_VERTICAL_ALIGN = 6; - int NUMBER_OF_LENGTHS = 7; + int LENGTH_PADDING_LEFT = 0; + int LENGTH_PADDING_RIGHT = 1; + int LENGTH_MARGIN_LEFT = 2; + int LENGTH_MARGIN_RIGHT = 3; + int LENGTH_FIRST_LINE_INDENT = 4; + int LENGTH_SPACE_BEFORE = 5; + int LENGTH_SPACE_AFTER = 6; + int LENGTH_FONT_SIZE = 7; + int LENGTH_VERTICAL_ALIGN = 8; + int NUMBER_OF_LENGTHS = 9; int ALIGNMENT_TYPE = NUMBER_OF_LENGTHS; int FONT_FAMILY = NUMBER_OF_LENGTHS + 1; int FONT_STYLE_MODIFIER = NUMBER_OF_LENGTHS + 2; @@ -78,6 +80,7 @@ public abstract class ZLTextStyleEntry { } } + public final short Depth; private short myFeatureMask; private Length[] myLengths = new Length[Feature.NUMBER_OF_LENGTHS]; @@ -91,7 +94,8 @@ public abstract class ZLTextStyleEntry { return (mask & (1 << featureId)) != 0; } - protected ZLTextStyleEntry() { + protected ZLTextStyleEntry(short depth) { + Depth = depth; } public final boolean isFeatureSupported(int featureId) { @@ -106,8 +110,10 @@ public abstract class ZLTextStyleEntry { private static int fullSize(ZLTextMetrics metrics, int fontSize, int featureId) { switch (featureId) { default: - case Feature.LENGTH_LEFT_INDENT: - case Feature.LENGTH_RIGHT_INDENT: + case Feature.LENGTH_MARGIN_LEFT: + case Feature.LENGTH_MARGIN_RIGHT: + case Feature.LENGTH_PADDING_LEFT: + case Feature.LENGTH_PADDING_RIGHT: case Feature.LENGTH_FIRST_LINE_INDENT: return metrics.FullWidth; case Feature.LENGTH_SPACE_BEFORE: diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextStyle.java b/src/org/geometerplus/zlibrary/text/view/ZLTextStyle.java index e76cfece4..a029228df 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextStyle.java @@ -41,8 +41,17 @@ public abstract class ZLTextStyle { public abstract boolean isUnderline(); public abstract boolean isStrikeThrough(); - public abstract int getLeftIndent(ZLTextMetrics metrics); - public abstract int getRightIndent(ZLTextMetrics metrics); + public final int getLeftIndent(ZLTextMetrics metrics) { + return getLeftMargin(metrics) + getLeftPadding(metrics); + } + public final int getRightIndent(ZLTextMetrics metrics) { + return getRightMargin(metrics) + getRightPadding(metrics); + } + public abstract int getLeftMargin(ZLTextMetrics metrics); + public abstract int getRightMargin(ZLTextMetrics metrics); + public abstract int getLeftPadding(ZLTextMetrics metrics); + public abstract int getRightPadding(ZLTextMetrics metrics); + public abstract int getFirstLineIndent(ZLTextMetrics metrics); public abstract int getLineSpacePercent(); public abstract int getVerticalAlign(ZLTextMetrics metrics); diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java index 369281394..f9631420c 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextBaseStyle.java @@ -111,12 +111,22 @@ public class ZLTextBaseStyle extends ZLTextStyle { } @Override - public int getLeftIndent(ZLTextMetrics metrics) { + public int getLeftMargin(ZLTextMetrics metrics) { return 0; } @Override - public int getRightIndent(ZLTextMetrics metrics) { + public int getRightMargin(ZLTextMetrics metrics) { + return 0; + } + + @Override + public int getLeftPadding(ZLTextMetrics metrics) { + return 0; + } + + @Override + public int getRightPadding(ZLTextMetrics metrics) { return 0; } diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextDecoratedStyle.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextDecoratedStyle.java index 2dd7652d9..f4920182f 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextDecoratedStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextDecoratedStyle.java @@ -43,8 +43,10 @@ public abstract class ZLTextDecoratedStyle extends ZLTextStyle { private int mySpaceBefore; private int mySpaceAfter; private int myVerticalAlign; - private int myLeftIndent; - private int myRightIndent; + private int myLeftMargin; + private int myRightMargin; + private int myLeftPadding; + private int myRightPadding; private int myFirstLineIndent; private ZLTextMetrics myMetrics; @@ -72,8 +74,10 @@ public abstract class ZLTextDecoratedStyle extends ZLTextStyle { mySpaceBefore = getSpaceBeforeInternal(metrics, myFontSize); mySpaceAfter = getSpaceAfterInternal(metrics, myFontSize); myVerticalAlign = getVerticalAlignInternal(metrics, myFontSize); - myLeftIndent = getLeftIndentInternal(metrics, myFontSize); - myRightIndent = getRightIndentInternal(metrics, myFontSize); + myLeftMargin = getLeftMarginInternal(metrics, myFontSize); + myRightMargin = getRightMarginInternal(metrics, myFontSize); + myLeftPadding = getLeftPaddingInternal(metrics, myFontSize); + myRightPadding = getRightPaddingInternal(metrics, myFontSize); myFirstLineIndent = getFirstLineIndentInternal(metrics, myFontSize); } @@ -159,22 +163,40 @@ public abstract class ZLTextDecoratedStyle extends ZLTextStyle { protected abstract int getVerticalAlignInternal(ZLTextMetrics metrics, int fontSize); @Override - public final int getLeftIndent(ZLTextMetrics metrics) { + public final int getLeftMargin(ZLTextMetrics metrics) { if (!metrics.equals(myMetrics)) { initMetricsCache(metrics); } - return myLeftIndent; + return myLeftMargin; } - protected abstract int getLeftIndentInternal(ZLTextMetrics metrics, int fontSize); + protected abstract int getLeftMarginInternal(ZLTextMetrics metrics, int fontSize); @Override - public final int getRightIndent(ZLTextMetrics metrics) { + public final int getRightMargin(ZLTextMetrics metrics) { if (!metrics.equals(myMetrics)) { initMetricsCache(metrics); } - return myRightIndent; + return myRightMargin; } - protected abstract int getRightIndentInternal(ZLTextMetrics metrics, int fontSize); + protected abstract int getRightMarginInternal(ZLTextMetrics metrics, int fontSize); + + @Override + public final int getLeftPadding(ZLTextMetrics metrics) { + if (!metrics.equals(myMetrics)) { + initMetricsCache(metrics); + } + return myLeftPadding; + } + protected abstract int getLeftPaddingInternal(ZLTextMetrics metrics, int fontSize); + + @Override + public final int getRightPadding(ZLTextMetrics metrics) { + if (!metrics.equals(myMetrics)) { + initMetricsCache(metrics); + } + return myRightPadding; + } + protected abstract int getRightPaddingInternal(ZLTextMetrics metrics, int fontSize); @Override public final int getFirstLineIndent(ZLTextMetrics metrics) { diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextExplicitlyDecoratedStyle.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextExplicitlyDecoratedStyle.java index 4f70c43b3..4dee9642c 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextExplicitlyDecoratedStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextExplicitlyDecoratedStyle.java @@ -63,16 +63,40 @@ public class ZLTextExplicitlyDecoratedStyle extends ZLTextDecoratedStyle impleme return allEntries; } + private ZLTextStyle myTreeParent; + private ZLTextStyle computeTreeParent() { + if (myEntry.Depth == 0) { + return Parent.Parent; + } + int count = 0; + ZLTextStyle p = Parent; + for (; p != p.Parent; p = p.Parent) { + if (p instanceof ZLTextExplicitlyDecoratedStyle) { + if (((ZLTextExplicitlyDecoratedStyle)p).myEntry.Depth != myEntry.Depth) { + return p; + } + } else { + if (++count > 1) { + return p; + } + } + } + return p; + } + private ZLTextStyle getTreeParent() { + if (myTreeParent == null) { + myTreeParent = computeTreeParent(); + } + return myTreeParent; + } + @Override protected int getFontSizeInternal(ZLTextMetrics metrics) { if (myEntry instanceof ZLTextCSSStyleEntry && !BaseStyle.UseCSSFontSizeOption.getValue()) { return Parent.getFontSize(metrics); } - // Yes, Parent.Parent, not Parent (parent = current tag pre-defined size, - // we want to override it) - // TODO: use _previous_tag_value_ - final int baseFontSize = Parent.Parent.getFontSize(metrics); + final int baseFontSize = getTreeParent().getFontSize(metrics); if (myEntry.isFeatureSupported(FONT_STYLE_MODIFIER)) { if (myEntry.getFontModifier(FONT_MODIFIER_INHERIT) == ZLBoolean3.B3_TRUE) { return baseFontSize; @@ -136,26 +160,48 @@ public class ZLTextExplicitlyDecoratedStyle extends ZLTextDecoratedStyle impleme } @Override - public int getLeftIndentInternal(ZLTextMetrics metrics, int fontSize) { + public int getLeftMarginInternal(ZLTextMetrics metrics, int fontSize) { if (myEntry instanceof ZLTextCSSStyleEntry && !BaseStyle.UseCSSMarginsOption.getValue()) { - return Parent.getLeftIndent(metrics); + return Parent.getLeftMargin(metrics); } - if (!myEntry.isFeatureSupported(LENGTH_LEFT_INDENT)) { - return Parent.getLeftIndent(metrics); + if (!myEntry.isFeatureSupported(LENGTH_MARGIN_LEFT)) { + return Parent.getLeftMargin(metrics); } - return myEntry.getLength(LENGTH_LEFT_INDENT, metrics, fontSize); + return getTreeParent().getLeftMargin(metrics) + myEntry.getLength(LENGTH_MARGIN_LEFT, metrics, fontSize); } @Override - public int getRightIndentInternal(ZLTextMetrics metrics, int fontSize) { + public int getRightMarginInternal(ZLTextMetrics metrics, int fontSize) { if (myEntry instanceof ZLTextCSSStyleEntry && !BaseStyle.UseCSSMarginsOption.getValue()) { - return Parent.getRightIndent(metrics); + return Parent.getRightMargin(metrics); } - if (!myEntry.isFeatureSupported(LENGTH_RIGHT_INDENT)) { - return Parent.getRightIndent(metrics); + if (!myEntry.isFeatureSupported(LENGTH_MARGIN_RIGHT)) { + return Parent.getRightMargin(metrics); } - return myEntry.getLength(LENGTH_RIGHT_INDENT, metrics, fontSize); + return getTreeParent().getRightMargin(metrics) + myEntry.getLength(LENGTH_MARGIN_RIGHT, metrics, fontSize); + } + @Override + public int getLeftPaddingInternal(ZLTextMetrics metrics, int fontSize) { + if (myEntry instanceof ZLTextCSSStyleEntry && !BaseStyle.UseCSSMarginsOption.getValue()) { + return Parent.getLeftPadding(metrics); + } + + if (!myEntry.isFeatureSupported(LENGTH_PADDING_LEFT)) { + return Parent.getLeftPadding(metrics); + } + return getTreeParent().getLeftPadding(metrics) + myEntry.getLength(LENGTH_PADDING_LEFT, metrics, fontSize); + } + @Override + public int getRightPaddingInternal(ZLTextMetrics metrics, int fontSize) { + if (myEntry instanceof ZLTextCSSStyleEntry && !BaseStyle.UseCSSMarginsOption.getValue()) { + return Parent.getRightPadding(metrics); + } + + if (!myEntry.isFeatureSupported(LENGTH_PADDING_RIGHT)) { + return Parent.getRightPadding(metrics); + } + return getTreeParent().getRightPadding(metrics) + myEntry.getLength(LENGTH_PADDING_RIGHT, metrics, fontSize); } @Override protected int getFirstLineIndentInternal(ZLTextMetrics metrics, int fontSize) { diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyle.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyle.java index 9d614510d..99449d2bb 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyle.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyle.java @@ -105,12 +105,20 @@ public class ZLTextNGStyle extends ZLTextDecoratedStyle { } @Override - protected int getLeftIndentInternal(ZLTextMetrics metrics, int fontSize) { - return myDescription.getLeftIndent(metrics, Parent.getLeftIndent(metrics), fontSize); + protected int getLeftMarginInternal(ZLTextMetrics metrics, int fontSize) { + return myDescription.getLeftMargin(metrics, Parent.getLeftMargin(metrics), fontSize); } @Override - protected int getRightIndentInternal(ZLTextMetrics metrics, int fontSize) { - return myDescription.getRightIndent(metrics, Parent.getRightIndent(metrics), fontSize); + protected int getRightMarginInternal(ZLTextMetrics metrics, int fontSize) { + return myDescription.getRightMargin(metrics, Parent.getRightMargin(metrics), fontSize); + } + @Override + protected int getLeftPaddingInternal(ZLTextMetrics metrics, int fontSize) { + return myDescription.getLeftPadding(metrics, Parent.getLeftPadding(metrics), fontSize); + } + @Override + protected int getRightPaddingInternal(ZLTextMetrics metrics, int fontSize) { + return myDescription.getRightPadding(metrics, Parent.getRightPadding(metrics), fontSize); } @Override protected int getFirstLineIndentInternal(ZLTextMetrics metrics, int fontSize) { diff --git a/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyleDescription.java b/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyleDescription.java index a0b04a17f..c00c27b80 100644 --- a/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyleDescription.java +++ b/src/org/geometerplus/zlibrary/text/view/style/ZLTextNGStyleDescription.java @@ -88,26 +88,34 @@ public class ZLTextNGStyleDescription { ); } - int getLeftIndent(ZLTextMetrics metrics, int base, int fontSize) { + int getLeftMargin(ZLTextMetrics metrics, int base, int fontSize) { final ZLTextStyleEntry.Length length = parseLength(MarginLeftOption.getValue()); if (length == null) { return base; } - return ZLTextStyleEntry.compute( - length, metrics, fontSize, ZLTextStyleEntry.Feature.LENGTH_LEFT_INDENT + return base + ZLTextStyleEntry.compute( + length, metrics, fontSize, ZLTextStyleEntry.Feature.LENGTH_MARGIN_LEFT ); } - int getRightIndent(ZLTextMetrics metrics, int base, int fontSize) { + int getRightMargin(ZLTextMetrics metrics, int base, int fontSize) { final ZLTextStyleEntry.Length length = parseLength(MarginRightOption.getValue()); if (length == null) { return base; } - return ZLTextStyleEntry.compute( - length, metrics, fontSize, ZLTextStyleEntry.Feature.LENGTH_RIGHT_INDENT + return base + ZLTextStyleEntry.compute( + length, metrics, fontSize, ZLTextStyleEntry.Feature.LENGTH_MARGIN_RIGHT ); } + int getLeftPadding(ZLTextMetrics metrics, int base, int fontSize) { + return base; + } + + int getRightPadding(ZLTextMetrics metrics, int base, int fontSize) { + return base; + } + int getFirstLineIndent(ZLTextMetrics metrics, int base, int fontSize) { final ZLTextStyleEntry.Length length = parseLength(TextIndentOption.getValue()); if (length == null) {