Recognize css display:none, fixes #1431

This commit is contained in:
jpirnay
2026-03-20 14:48:41 +01:00
parent a01bb2902e
commit 9c8e64402d
4 changed files with 51 additions and 4 deletions
+15
View File
@@ -317,6 +317,9 @@ void CssParser::parseDeclarationIntoStyle(const std::string& decl, CssStyle& sty
style.imageWidth = len;
style.defined.imageWidth = 1;
}
} else if (propNameBuf == "display") {
style.display = (propValueBuf == "none") ? CssDisplay::None : CssDisplay::Block;
style.defined.display = 1;
}
}
@@ -692,6 +695,7 @@ bool CssParser::saveToCache() const {
writeLength(style.paddingRight);
writeLength(style.imageHeight);
writeLength(style.imageWidth);
file.write(static_cast<uint8_t>(style.display));
// Write defined flags as uint16_t
uint16_t definedBits = 0;
@@ -710,6 +714,7 @@ bool CssParser::saveToCache() const {
if (style.defined.paddingRight) definedBits |= 1 << 12;
if (style.defined.imageHeight) definedBits |= 1 << 13;
if (style.defined.imageWidth) definedBits |= 1 << 14;
if (style.defined.display) definedBits |= 1 << 15;
file.write(reinterpret_cast<const uint8_t*>(&definedBits), sizeof(definedBits));
}
@@ -820,6 +825,15 @@ bool CssParser::loadFromCache() {
return false;
}
// Read display value
uint8_t displayVal;
if (file.read(&displayVal, 1) != 1) {
rulesBySelector_.clear();
file.close();
return false;
}
style.display = static_cast<CssDisplay>(displayVal);
// Read defined flags
uint16_t definedBits = 0;
if (file.read(&definedBits, sizeof(definedBits)) != sizeof(definedBits)) {
@@ -842,6 +856,7 @@ bool CssParser::loadFromCache() {
style.defined.paddingRight = (definedBits & 1 << 12) != 0;
style.defined.imageHeight = (definedBits & 1 << 13) != 0;
style.defined.imageWidth = (definedBits & 1 << 14) != 0;
style.defined.display = (definedBits & 1 << 15) != 0;
rulesBySelector_[selector] = style;
}
+1 -1
View File
@@ -31,7 +31,7 @@
class CssParser {
public:
// Bump when CSS cache format or rules change; section caches are invalidated when this changes
static constexpr uint8_t CSS_CACHE_VERSION = 3;
static constexpr uint8_t CSS_CACHE_VERSION = 4;
explicit CssParser(std::string cachePath) : cachePath(std::move(cachePath)) {}
~CssParser() = default;
+15 -3
View File
@@ -54,6 +54,9 @@ enum class CssFontWeight : uint8_t { Normal = 0, Bold = 1 };
// Text decoration options
enum class CssTextDecoration : uint8_t { None = 0, Underline = 1 };
// Display options - only None and Block are relevant for e-ink rendering
enum class CssDisplay : uint8_t { Block = 0, None = 1 };
// Bitmask for tracking which properties have been explicitly set
struct CssPropertyFlags {
uint16_t textAlign : 1;
@@ -71,6 +74,7 @@ struct CssPropertyFlags {
uint16_t paddingRight : 1;
uint16_t imageHeight : 1;
uint16_t imageWidth : 1;
uint16_t display : 1;
CssPropertyFlags()
: textAlign(0),
@@ -87,19 +91,20 @@ struct CssPropertyFlags {
paddingLeft(0),
paddingRight(0),
imageHeight(0),
imageWidth(0) {}
imageWidth(0),
display(0) {}
[[nodiscard]] bool anySet() const {
return textAlign || fontStyle || fontWeight || textDecoration || textIndent || marginTop || marginBottom ||
marginLeft || marginRight || paddingTop || paddingBottom || paddingLeft || paddingRight || imageHeight ||
imageWidth;
imageWidth || display;
}
void clearAll() {
textAlign = fontStyle = fontWeight = textDecoration = textIndent = 0;
marginTop = marginBottom = marginLeft = marginRight = 0;
paddingTop = paddingBottom = paddingLeft = paddingRight = 0;
imageHeight = imageWidth = 0;
imageHeight = imageWidth = display = 0;
}
};
@@ -123,6 +128,7 @@ struct CssStyle {
CssLength paddingRight; // Padding right
CssLength imageHeight; // Height for img (e.g. 2em) width derived from aspect ratio when only height set
CssLength imageWidth; // Width for img when both or only width set
CssDisplay display = CssDisplay::Block; // display property (Block or None)
CssPropertyFlags defined; // Tracks which properties were explicitly set
@@ -189,6 +195,10 @@ struct CssStyle {
imageWidth = base.imageWidth;
defined.imageWidth = 1;
}
if (base.hasDisplay()) {
display = base.display;
defined.display = 1;
}
}
[[nodiscard]] bool hasTextAlign() const { return defined.textAlign; }
@@ -206,6 +216,7 @@ struct CssStyle {
[[nodiscard]] bool hasPaddingRight() const { return defined.paddingRight; }
[[nodiscard]] bool hasImageHeight() const { return defined.imageHeight; }
[[nodiscard]] bool hasImageWidth() const { return defined.imageWidth; }
[[nodiscard]] bool hasDisplay() const { return defined.display; }
void reset() {
textAlign = CssTextAlign::Left;
@@ -216,6 +227,7 @@ struct CssStyle {
marginTop = marginBottom = marginLeft = marginRight = CssLength{};
paddingTop = paddingBottom = paddingLeft = paddingRight = CssLength{};
imageHeight = imageWidth = CssLength{};
display = CssDisplay::Block;
defined.clearAll();
}
};
@@ -264,6 +264,19 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
return;
}
// Skip image if CSS display:none
if (self->cssParser) {
CssStyle imgDisplayStyle = self->cssParser->resolveStyle("img", classAttr);
if (!styleAttr.empty()) {
imgDisplayStyle.applyOver(CssParser::parseInlineStyle(styleAttr));
}
if (imgDisplayStyle.hasDisplay() && imgDisplayStyle.display == CssDisplay::None) {
self->skipUntilDepth = self->depth;
self->depth += 1;
return;
}
}
if (!src.empty() && self->imageRendering != 1) {
LOG_DBG("EHP", "Found image: src=%s", src.c_str());
@@ -526,6 +539,13 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
}
// Skip elements with display:none
if (cssStyle.hasDisplay() && cssStyle.display == CssDisplay::None) {
self->skipUntilDepth = self->depth;
self->depth += 1;
return;
}
const float emSize = static_cast<float>(self->renderer.getFontAscenderSize(self->fontId));
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
cssStyle, emSize, static_cast<CssTextAlign>(self->paragraphAlignment), self->viewportWidth);