diff --git a/lib/Epub/Epub/css/CssParser.cpp b/lib/Epub/Epub/css/CssParser.cpp index 8a17f4b8..afcf7e95 100644 --- a/lib/Epub/Epub/css/CssParser.cpp +++ b/lib/Epub/Epub/css/CssParser.cpp @@ -204,15 +204,15 @@ std::vector CssParser::splitWhitespace(const std::string& s) { // Property value interpreters -TextAlign CssParser::interpretAlignment(const std::string& val) { +CssTextAlign CssParser::interpretAlignment(const std::string& val) { const std::string v = normalized(val); - if (v == "left" || v == "start") return TextAlign::Left; - if (v == "right" || v == "end") return TextAlign::Right; - if (v == "center") return TextAlign::Center; - if (v == "justify") return TextAlign::Justify; + if (v == "left" || v == "start") return CssTextAlign::Left; + if (v == "right" || v == "end") return CssTextAlign::Right; + if (v == "center") return CssTextAlign::Center; + if (v == "justify") return CssTextAlign::Justify; - return TextAlign::None; + return CssTextAlign::Left; } CssFontStyle CssParser::interpretFontStyle(const std::string& val) { @@ -352,11 +352,8 @@ CssStyle CssParser::parseDeclarations(const std::string& declBlock) { // Match property and set value if (propName == "text-align") { - const TextAlign align = interpretAlignment(propValue); - if (align != TextAlign::None) { - style.alignment = align; - style.defined.alignment = 1; - } + style.textAlign = interpretAlignment(propValue); + style.defined.textAlign = 1; } else if (propName == "font-style") { style.fontStyle = interpretFontStyle(propValue); style.defined.fontStyle = 1; @@ -364,11 +361,11 @@ CssStyle CssParser::parseDeclarations(const std::string& declBlock) { style.fontWeight = interpretFontWeight(propValue); style.defined.fontWeight = 1; } else if (propName == "text-decoration" || propName == "text-decoration-line") { - style.decoration = interpretDecoration(propValue); - style.defined.decoration = 1; + style.textDecoration = interpretDecoration(propValue); + style.defined.textDecoration = 1; } else if (propName == "text-indent") { - style.indent = interpretLength(propValue); - style.defined.indent = 1; + style.textIndent = interpretLength(propValue); + style.defined.textIndent = 1; } else if (propName == "margin-top") { style.marginTop = interpretLength(propValue); style.defined.marginTop = 1; diff --git a/lib/Epub/Epub/css/CssParser.h b/lib/Epub/Epub/css/CssParser.h index 7a847b35..9915485d 100644 --- a/lib/Epub/Epub/css/CssParser.h +++ b/lib/Epub/Epub/css/CssParser.h @@ -85,7 +85,7 @@ class CssParser { static CssStyle parseDeclarations(const std::string& declBlock); // Individual property value parsers - static TextAlign interpretAlignment(const std::string& val); + static CssTextAlign interpretAlignment(const std::string& val); static CssFontStyle interpretFontStyle(const std::string& val); static CssFontWeight interpretFontWeight(const std::string& val); static CssTextDecoration interpretDecoration(const std::string& val); diff --git a/lib/Epub/Epub/css/CssStyle.h b/lib/Epub/Epub/css/CssStyle.h index 1bf0fba0..7b83da3f 100644 --- a/lib/Epub/Epub/css/CssStyle.h +++ b/lib/Epub/Epub/css/CssStyle.h @@ -2,10 +2,8 @@ #include -// Text alignment options matching CSS text-align property -enum class TextAlign : uint8_t { None = 0, Left = 1, Right = 2, Center = 3, Justify = 4 }; - -// CSS length unit types +// Matches order of PARAGRAPH_ALIGNMENT in CrossPointSettings +enum class CssTextAlign : uint8_t { Justify = 0, Left = 1, Center = 2, Right = 3 }; enum class CssUnit : uint8_t { Pixels = 0, Em = 1, Rem = 2, Points = 3 }; // Represents a CSS length value with its unit, allowing deferred resolution to pixels @@ -47,11 +45,11 @@ enum class CssTextDecoration : uint8_t { None = 0, Underline = 1 }; // Bitmask for tracking which properties have been explicitly set struct CssPropertyFlags { - uint16_t alignment : 1; + uint16_t textAlign : 1; uint16_t fontStyle : 1; uint16_t fontWeight : 1; - uint16_t decoration : 1; - uint16_t indent : 1; + uint16_t textDecoration : 1; + uint16_t textIndent : 1; uint16_t marginTop : 1; uint16_t marginBottom : 1; uint16_t marginLeft : 1; @@ -60,14 +58,13 @@ struct CssPropertyFlags { uint16_t paddingBottom : 1; uint16_t paddingLeft : 1; uint16_t paddingRight : 1; - uint16_t reserved : 3; CssPropertyFlags() - : alignment(0), + : textAlign(0), fontStyle(0), fontWeight(0), - decoration(0), - indent(0), + textDecoration(0), + textIndent(0), marginTop(0), marginBottom(0), marginLeft(0), @@ -75,16 +72,15 @@ struct CssPropertyFlags { paddingTop(0), paddingBottom(0), paddingLeft(0), - paddingRight(0), - reserved(0) {} + paddingRight(0) {} [[nodiscard]] bool anySet() const { - return alignment || fontStyle || fontWeight || decoration || indent || marginTop || marginBottom || marginLeft || - marginRight || paddingTop || paddingBottom || paddingLeft || paddingRight; + return textAlign || fontStyle || fontWeight || textDecoration || textIndent || marginTop || marginBottom || + marginLeft || marginRight || paddingTop || paddingBottom || paddingLeft || paddingRight; } void clearAll() { - alignment = fontStyle = fontWeight = decoration = indent = 0; + textAlign = fontStyle = fontWeight = textDecoration = textIndent = 0; marginTop = marginBottom = marginLeft = marginRight = 0; paddingTop = paddingBottom = paddingLeft = paddingRight = 0; } @@ -94,12 +90,12 @@ struct CssPropertyFlags { // Only stores properties relevant to e-ink text rendering // Length values are stored as CssLength (value + unit) for deferred resolution struct CssStyle { - TextAlign alignment = TextAlign::None; + CssTextAlign textAlign = CssTextAlign::Left; CssFontStyle fontStyle = CssFontStyle::Normal; CssFontWeight fontWeight = CssFontWeight::Normal; - CssTextDecoration decoration = CssTextDecoration::None; + CssTextDecoration textDecoration = CssTextDecoration::None; - CssLength indent; // First-line indent (deferred resolution) + CssLength textIndent; // First-line indent (deferred resolution) CssLength marginTop; // Vertical spacing before block CssLength marginBottom; // Vertical spacing after block CssLength marginLeft; // Horizontal spacing left of block @@ -114,66 +110,65 @@ struct CssStyle { // Apply properties from another style, only overwriting if the other style // has that property explicitly defined void applyOver(const CssStyle& base) { - if (base.defined.alignment) { - alignment = base.alignment; - defined.alignment = 1; + if (base.hasTextAlign()) { + textAlign = base.textAlign; + defined.textAlign = 1; } - if (base.defined.fontStyle) { + if (base.hasFontStyle()) { fontStyle = base.fontStyle; defined.fontStyle = 1; } - if (base.defined.fontWeight) { + if (base.hasFontWeight()) { fontWeight = base.fontWeight; defined.fontWeight = 1; } - if (base.defined.decoration) { - decoration = base.decoration; - defined.decoration = 1; + if (base.hasTextDecoration()) { + textDecoration = base.textDecoration; + defined.textDecoration = 1; } - if (base.defined.indent) { - indent = base.indent; - defined.indent = 1; + if (base.hasTextIndent()) { + textIndent = base.textIndent; + defined.textIndent = 1; } - if (base.defined.marginTop) { + if (base.hasMarginTop()) { marginTop = base.marginTop; defined.marginTop = 1; } - if (base.defined.marginBottom) { + if (base.hasMarginBottom()) { marginBottom = base.marginBottom; defined.marginBottom = 1; } - if (base.defined.marginLeft) { + if (base.hasMarginLeft()) { marginLeft = base.marginLeft; defined.marginLeft = 1; } - if (base.defined.marginRight) { + if (base.hasMarginRight()) { marginRight = base.marginRight; defined.marginRight = 1; } - if (base.defined.paddingTop) { + if (base.hasPaddingTop()) { paddingTop = base.paddingTop; defined.paddingTop = 1; } - if (base.defined.paddingBottom) { + if (base.hasPaddingBottom()) { paddingBottom = base.paddingBottom; defined.paddingBottom = 1; } - if (base.defined.paddingLeft) { + if (base.hasPaddingLeft()) { paddingLeft = base.paddingLeft; defined.paddingLeft = 1; } - if (base.defined.paddingRight) { + if (base.hasPaddingRight()) { paddingRight = base.paddingRight; defined.paddingRight = 1; } } - // Compatibility accessors for existing code that uses hasX pattern - [[nodiscard]] bool hasTextAlign() const { return defined.alignment; } + [[nodiscard]] bool hasTextAlign() const { return defined.textAlign; } [[nodiscard]] bool hasFontStyle() const { return defined.fontStyle; } [[nodiscard]] bool hasFontWeight() const { return defined.fontWeight; } - [[nodiscard]] bool hasTextDecoration() const { return defined.decoration; } - [[nodiscard]] bool hasTextIndent() const { return defined.indent; } + [[nodiscard]] bool hasTextDecoration() const { return defined.textDecoration; } + [[nodiscard]] bool hasTextIndent() const { return defined.textIndent; } [[nodiscard]] bool hasMarginTop() const { return defined.marginTop; } [[nodiscard]] bool hasMarginBottom() const { return defined.marginBottom; } [[nodiscard]] bool hasMarginLeft() const { return defined.marginLeft; } @@ -183,15 +178,12 @@ struct CssStyle { [[nodiscard]] bool hasPaddingLeft() const { return defined.paddingLeft; } [[nodiscard]] bool hasPaddingRight() const { return defined.paddingRight; } - // Merge another style (alias for applyOver for compatibility) - void merge(const CssStyle& other) { applyOver(other); } - void reset() { - alignment = TextAlign::None; + textAlign = CssTextAlign::Left; fontStyle = CssFontStyle::Normal; fontWeight = CssFontWeight::Normal; - decoration = CssTextDecoration::None; - indent = CssLength{}; + textDecoration = CssTextDecoration::None; + textIndent = CssLength{}; marginTop = marginBottom = marginLeft = marginRight = CssLength{}; paddingTop = paddingBottom = paddingLeft = paddingRight = CssLength{}; defined.clearAll(); diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index c6227557..68737279 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -64,8 +64,8 @@ BlockStyle createBlockStyleFromCss(const CssStyle& cssStyle, const float emSize) blockStyle.paddingLeft = cssStyle.paddingLeft.toPixelsInt16(emSize); blockStyle.paddingRight = cssStyle.paddingRight.toPixelsInt16(emSize); // Text indent - blockStyle.textIndent = cssStyle.indent.toPixelsInt16(emSize); - blockStyle.textIndentDefined = cssStyle.defined.indent; + blockStyle.textIndent = cssStyle.textIndent.toPixelsInt16(emSize); + blockStyle.textIndentDefined = cssStyle.defined.textIndent; return blockStyle; } @@ -75,7 +75,7 @@ void ChapterHtmlSlimParser::updateEffectiveInlineStyle() { effectiveBold = currentBlockStyle.hasFontWeight() && currentBlockStyle.fontWeight == CssFontWeight::Bold; effectiveItalic = currentBlockStyle.hasFontStyle() && currentBlockStyle.fontStyle == CssFontStyle::Italic; effectiveUnderline = - currentBlockStyle.hasTextDecoration() && currentBlockStyle.decoration == CssTextDecoration::Underline; + currentBlockStyle.hasTextDecoration() && currentBlockStyle.textDecoration == CssTextDecoration::Underline; // Apply inline style stack in order for (const auto& entry : inlineStyleStack) { @@ -255,7 +255,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* // Merge inline style (highest priority) if (!styleAttr.empty()) { CssStyle inlineStyle = CssParser::parseInlineStyle(styleAttr); - cssStyle.merge(inlineStyle); + cssStyle.applyOver(inlineStyle); } } @@ -263,17 +263,17 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* // Headers: center aligned, bold, apply CSS overrides TextBlock::Style alignment = TextBlock::CENTER_ALIGN; if (cssStyle.hasTextAlign()) { - switch (cssStyle.alignment) { - case TextAlign::Left: + switch (cssStyle.textAlign) { + case CssTextAlign::Left: alignment = TextBlock::LEFT_ALIGN; break; - case TextAlign::Right: + case CssTextAlign::Right: alignment = TextBlock::RIGHT_ALIGN; break; - case TextAlign::Center: + case CssTextAlign::Center: alignment = TextBlock::CENTER_ALIGN; break; - case TextAlign::Justify: + case CssTextAlign::Justify: alignment = TextBlock::JUSTIFIED; break; default: @@ -296,17 +296,17 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* // Determine alignment from CSS or default auto alignment = static_cast(self->paragraphAlignment); if (cssStyle.hasTextAlign()) { - switch (cssStyle.alignment) { - case TextAlign::Left: + switch (cssStyle.textAlign) { + case CssTextAlign::Left: alignment = TextBlock::LEFT_ALIGN; break; - case TextAlign::Right: + case CssTextAlign::Right: alignment = TextBlock::RIGHT_ALIGN; break; - case TextAlign::Center: + case CssTextAlign::Center: alignment = TextBlock::CENTER_ALIGN; break; - case TextAlign::Justify: + case CssTextAlign::Justify: alignment = TextBlock::JUSTIFIED; break; default: @@ -352,7 +352,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* } if (cssStyle.hasTextDecoration()) { entry.hasUnderline = true; - entry.underline = cssStyle.decoration == CssTextDecoration::Underline; + entry.underline = cssStyle.textDecoration == CssTextDecoration::Underline; } self->inlineStyleStack.push_back(entry); self->updateEffectiveInlineStyle(); @@ -369,7 +369,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* } if (cssStyle.hasTextDecoration()) { entry.hasUnderline = true; - entry.underline = cssStyle.decoration == CssTextDecoration::Underline; + entry.underline = cssStyle.textDecoration == CssTextDecoration::Underline; } self->inlineStyleStack.push_back(entry); self->updateEffectiveInlineStyle(); @@ -388,7 +388,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* } if (cssStyle.hasTextDecoration()) { entry.hasUnderline = true; - entry.underline = cssStyle.decoration == CssTextDecoration::Underline; + entry.underline = cssStyle.textDecoration == CssTextDecoration::Underline; } self->inlineStyleStack.push_back(entry); self->updateEffectiveInlineStyle();