diff --git a/fbreader/fbreader/fbreader/src/formats/css/StyleSheetTable.cpp b/fbreader/fbreader/fbreader/src/formats/css/StyleSheetTable.cpp index e5d8c30..a040f3b 100644 --- a/fbreader/fbreader/fbreader/src/formats/css/StyleSheetTable.cpp +++ b/fbreader/fbreader/fbreader/src/formats/css/StyleSheetTable.cpp @@ -147,7 +147,7 @@ bool StyleSheetTable::parseMargin(const std::string &toParse, short &size, ZLTex return true; } else if (toParse == "auto") { size = 0; - unit = ZLTextStyleEntry::SIZE_UNIT_PIXEL; + unit = ZLTextStyleEntry::SIZE_UNIT_AUTO; return true; } else { return false; @@ -307,6 +307,7 @@ void StyleSheetTable::updateTextStyle(ZLTextStyleEntry &entry, const AttributeMa } else { if (ZLTextStyleEntry::parseLength(value, size, unit)) { switch (unit) { + case ZLTextStyleEntry::SIZE_UNIT_AUTO: case ZLTextStyleEntry::SIZE_UNIT_PIXEL: // What to do with pixels? break; @@ -355,6 +356,9 @@ void StyleSheetTable::updateTextStyle(ZLTextStyleEntry &entry, const AttributeMa entry.setOpacity((unsigned char)((value < 0) ? 0 : (value > 255) ? 255 : value)); } + static const std::string WIDTH("width"); + setLength(entry, ZLTextStyleEntry::LENGTH_WIDTH, styles, WIDTH); + // Margins will overwrite padding, sorry static const std::string PADDING_TOP("padding-top"); static const std::string PADDING_BOTTOM("padding-bottom"); diff --git a/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.cpp b/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.cpp index ead6f48..a618984 100644 --- a/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.cpp +++ b/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.cpp @@ -39,7 +39,6 @@ size_t ZLTextEntry::dataLength() const { int ZLTextStyleEntry::hlength(int size, SizeUnit unit, const Metrics &metrics) { switch (unit) { - default: case SIZE_UNIT_PIXEL: return size; case SIZE_UNIT_EM_100: @@ -48,13 +47,15 @@ int ZLTextStyleEntry::hlength(int size, SizeUnit unit, const Metrics &metrics) return (size * metrics.FontXHeight + 50) / 100; case SIZE_UNIT_PERCENT: return (size * metrics.FullWidth + 50) / 100; + case SIZE_UNIT_AUTO: + return metrics.FullWidth / 2; } + return 0; } int ZLTextStyleEntry::vlength(int size, SizeUnit unit, const Metrics &metrics) { switch (unit) { - default: case SIZE_UNIT_PIXEL: return size; case SIZE_UNIT_EM_100: @@ -63,20 +64,26 @@ int ZLTextStyleEntry::vlength(int size, SizeUnit unit, const Metrics &metrics) return (size * metrics.FontXHeight + 50) / 100; case SIZE_UNIT_PERCENT: return (size * metrics.FullHeight + 50) / 100; + case SIZE_UNIT_AUTO: + return metrics.FullHeight / 2; } + return 0; } short ZLTextStyleEntry::length(Length name, const Metrics &metrics) const { switch (name) { - default: case LENGTH_LEFT_INDENT: case LENGTH_RIGHT_INDENT: case LENGTH_FIRST_LINE_INDENT_DELTA: + case LENGTH_WIDTH: return hlength(myLengths[name].Size, myLengths[name].Unit, metrics); case LENGTH_SPACE_BEFORE: case LENGTH_SPACE_AFTER: return vlength(myLengths[name].Size, myLengths[name].Unit, metrics); + case NUMBER_OF_LENGTHS: + break; } + return 0; } ZLTextStyleEntry::ZLTextStyleEntry(char *address) { diff --git a/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.h b/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.h index 6ec7b24..2053dd6 100644 --- a/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.h +++ b/fbreader/fbreader/zlibrary/text/src/model/ZLTextParagraph.h @@ -68,7 +68,8 @@ public: SIZE_UNIT_PIXEL, SIZE_UNIT_EM_100, SIZE_UNIT_EX_100, - SIZE_UNIT_PERCENT + SIZE_UNIT_PERCENT, + SIZE_UNIT_AUTO }; struct Metrics { @@ -86,7 +87,8 @@ public: LENGTH_FIRST_LINE_INDENT_DELTA = 2, LENGTH_SPACE_BEFORE = 3, LENGTH_SPACE_AFTER = 4, - NUMBER_OF_LENGTHS = 5, + LENGTH_WIDTH = 5, + NUMBER_OF_LENGTHS = 6 }; private: @@ -111,6 +113,8 @@ public: bool isEmpty() const; bool lengthSupported(Length name) const; + bool autoLeftRightMargins() const; + SizeUnit lengthUnit(Length name) const; short length(Length name, const Metrics &metrics) const; short length(Length name, SizeUnit &unit) const; void setLength(Length name, short length, SizeUnit unit); @@ -374,12 +378,18 @@ inline bool ZLTextStyleEntry::operator == (const ZLTextStyleEntry &other) const inline ZLTextStyleEntry &ZLTextStyleEntry::operator = (const ZLTextStyleEntry &other) { reset(); apply(other); return *this; } inline bool ZLTextStyleEntry::lengthSupported(Length name) const { return (myMask & (1 << name)) != 0; } +inline ZLTextStyleEntry::SizeUnit ZLTextStyleEntry::lengthUnit(Length name) const { return myLengths[name].Unit; } inline short ZLTextStyleEntry::length(Length name, SizeUnit &unit) const { unit = myLengths[name].Unit; return myLengths[name].Size; } inline void ZLTextStyleEntry::setLength(Length name, short length, SizeUnit unit) { myLengths[name].Size = length; myLengths[name].Unit = unit; myMask |= 1 << name; } +inline bool ZLTextStyleEntry::autoLeftRightMargins() const { + return (myMask & ((1 << LENGTH_LEFT_INDENT) | (1 << LENGTH_RIGHT_INDENT))) == ((1 << LENGTH_LEFT_INDENT) | (1 << LENGTH_RIGHT_INDENT)) && + myLengths[LENGTH_LEFT_INDENT].Unit == SIZE_UNIT_AUTO && + myLengths[LENGTH_RIGHT_INDENT].Unit == SIZE_UNIT_AUTO; +} inline bool ZLTextStyleEntry::opacitySupported() const { return (myMask & SUPPORT_OPACITY) != 0; } inline unsigned char ZLTextStyleEntry::opacity() const { return myOpacity; } diff --git a/fbreader/fbreader/zlibrary/text/src/style/ZLTextDecoratedStyle.cpp b/fbreader/fbreader/zlibrary/text/src/style/ZLTextDecoratedStyle.cpp index 88ad1c7..028abb7 100644 --- a/fbreader/fbreader/zlibrary/text/src/style/ZLTextDecoratedStyle.cpp +++ b/fbreader/fbreader/zlibrary/text/src/style/ZLTextDecoratedStyle.cpp @@ -75,13 +75,13 @@ short ZLTextFullDecoratedStyle::spaceAfter(const ZLTextStyleEntry::Metrics &metr } short ZLTextFullDecoratedStyle::lineStartIndent(const ZLTextStyleEntry::Metrics &metrics, bool rtl) const { - return base()->lineEndIndent(metrics, rtl) + (rtl ? + return base()->lineStartIndent(metrics, rtl) + (rtl ? ZLTextStyleEntry::hlength(myDecoration.LineEndIndentOption.value(), myDecoration.LineEndIndentOptionUnit, metrics) : ZLTextStyleEntry::hlength(myDecoration.LineStartIndentOption.value(), myDecoration.LineStartIndentOptionUnit, metrics)); } short ZLTextFullDecoratedStyle::lineEndIndent(const ZLTextStyleEntry::Metrics &metrics, bool rtl) const { - return base()->lineStartIndent(metrics, rtl) + (rtl ? + return base()->lineEndIndent(metrics, rtl) + (rtl ? ZLTextStyleEntry::hlength(myDecoration.LineStartIndentOption.value(), myDecoration.LineStartIndentOptionUnit, metrics) : ZLTextStyleEntry::hlength(myDecoration.LineEndIndentOption.value(), myDecoration.LineEndIndentOptionUnit, metrics)); } @@ -193,28 +193,51 @@ short ZLTextForcedStyle::lineStartIndent(const ZLTextStyleEntry::Metrics &metric ZLTextStyleEntry::Length lengthType = rtl ? ZLTextStyleEntry::LENGTH_RIGHT_INDENT : ZLTextStyleEntry::LENGTH_LEFT_INDENT; - if (myEntry.lengthSupported(lengthType)) { - const short baseLen = base()->lineStartIndent(metrics, rtl); - ZLTextStyleEntry::Metrics adjusted(metrics); - adjusted.FullWidth -= baseLen + base()->lineEndIndent(metrics, rtl); - return baseLen + myEntry.length(lengthType, adjusted); - } else { + if (!myEntry.lengthSupported(lengthType)) { return base()->lineStartIndent(metrics, rtl); } + + const short baseLen = base()->lineStartIndent(metrics, rtl); + ZLTextStyleEntry::Metrics adjusted(metrics); + adjusted.FullWidth -= baseLen + base()->lineEndIndent(metrics, rtl); + if (adjusted.FullWidth < 0) adjusted.FullWidth = 0; + if (myEntry.lengthUnit(lengthType) != ZLTextStyleEntry::SIZE_UNIT_AUTO) { + return baseLen + myEntry.length(lengthType, adjusted); + } + + if (myEntry.autoLeftRightMargins() && myEntry.lengthSupported(ZLTextStyleEntry::LENGTH_WIDTH)) { + int x = adjusted.FullWidth - myEntry.length(ZLTextStyleEntry::LENGTH_WIDTH, adjusted); + if (x < 0) x = 0; + return x/2; + } + + return baseLen; } short ZLTextForcedStyle::lineEndIndent(const ZLTextStyleEntry::Metrics &metrics, bool rtl) const { ZLTextStyleEntry::Length lengthType = rtl ? ZLTextStyleEntry::LENGTH_LEFT_INDENT : ZLTextStyleEntry::LENGTH_RIGHT_INDENT; - if (myEntry.lengthSupported(lengthType)) { - const short baseLen = base()->lineEndIndent(metrics, rtl); - ZLTextStyleEntry::Metrics adjusted(metrics); - adjusted.FullWidth -= baseLen + base()->lineStartIndent(metrics, rtl); - return baseLen + myEntry.length(lengthType, adjusted); - } else { - return base()->lineEndIndent(metrics, rtl); + + if (!myEntry.lengthSupported(lengthType)) { + return base()->lineStartIndent(metrics, rtl); } + + const short baseLen = base()->lineEndIndent(metrics, rtl); + ZLTextStyleEntry::Metrics adjusted(metrics); + adjusted.FullWidth -= baseLen + base()->lineStartIndent(metrics, rtl); + if (adjusted.FullWidth < 0) adjusted.FullWidth = 0; + if (myEntry.lengthUnit(lengthType) != ZLTextStyleEntry::SIZE_UNIT_AUTO) { + return baseLen + myEntry.length(lengthType, adjusted); + } + + if (myEntry.autoLeftRightMargins() && myEntry.lengthSupported(ZLTextStyleEntry::LENGTH_WIDTH)) { + int x = adjusted.FullWidth - myEntry.length(ZLTextStyleEntry::LENGTH_WIDTH, adjusted); + if (x < 0) x = 0; + return x/2; + } + + return baseLen; } short ZLTextForcedStyle::spaceBefore(const ZLTextStyleEntry::Metrics &metrics) const { diff --git a/test/test-css/data/test1/out.css b/test/test-css/data/test1/out.css index 0d54527..40fc40c 100644 --- a/test/test-css/data/test1/out.css +++ b/test/test-css/data/test1/out.css @@ -104,11 +104,13 @@ color: #333333; } .table { + width: 100%; margin-bottom: 16px; margin-top: 0; text-indent: 0; } .table1 { + width: 100%; margin-bottom: 16px; margin-top: 0; text-indent: 0; diff --git a/test/test-css/data/test2/out.css b/test/test-css/data/test2/out.css index c311dfe..56e4cd9 100644 --- a/test/test-css/data/test2/out.css +++ b/test/test-css/data/test2/out.css @@ -4,6 +4,9 @@ body.cover { margin-top: 0; margin-right: 0; } +svg.cover-svg { + width: 100%; +} .z { margin-right: 8px; font-family: "Times New Roman", "serif"; diff --git a/test/test-css/main.cpp b/test/test-css/main.cpp index c2bb5cf..b76e6b0 100644 --- a/test/test-css/main.cpp +++ b/test/test-css/main.cpp @@ -79,6 +79,9 @@ dump_length( case ZLTextStyleEntry::SIZE_UNIT_PERCENT: out << length->Size << "%"; break; + case ZLTextStyleEntry::SIZE_UNIT_AUTO: + out << "auto"; + break; } } out << ";\n"; @@ -90,6 +93,7 @@ dump_style( const StyleSheetTable::Style& style, std::ostream& out) { + dump_length(style.TextStyle, ZLTextStyleEntry::LENGTH_WIDTH, "width", out); dump_length(style.TextStyle, ZLTextStyleEntry::LENGTH_LEFT_INDENT, "margin-left", out); dump_length(style.TextStyle, ZLTextStyleEntry::LENGTH_SPACE_AFTER, "margin-bottom", out); dump_length(style.TextStyle, ZLTextStyleEntry::LENGTH_SPACE_BEFORE, "margin-top", out);