Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Long-press reader shortcuts that open another screen no longer close or confirm it again when releasing the shortcut button.
- RoundedRaff's header battery icon and percentage now sit lower to avoid clipping at the top edge.
- Lyra Carousel now redraws the Home header when restoring cached carousel frames so battery percentage and clock values stay current while navigating between books.
- EPUB ornamental breaks now show their hidden text fallback when the decorative image uses an unsupported format.
- Reader-launched settings screens no longer jump back two screens after pressing Back.
- Web file manager multi-delete now handles larger selections without failing after a small batch.

Expand Down
30 changes: 27 additions & 3 deletions lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ bool attributeContainsToken(const char* value, const char* token) {
return false;
}

bool classContainsToken(const std::string& value, const char* token) {
return attributeContainsToken(value.c_str(), token);
}

bool isHeaderOrBlock(const char* name) {
return matches(name, HEADER_TAGS, std::size(HEADER_TAGS)) || matches(name, BLOCK_TAGS, std::size(BLOCK_TAGS));
}
Expand Down Expand Up @@ -899,8 +903,18 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*

// Skip elements with display:none before all fast paths (tables, links, etc.).
if (cssStyle.hasDisplay() && cssStyle.display == CssDisplay::None) {
self->skipCurrentElement();
return;
const bool isHiddenOrnamentalTextFallback = strcmp(name, "p") == 0 && self->unsupportedOrnamentalBreakDepth >= 0 &&
self->ornamentalBreakDepth == self->unsupportedOrnamentalBreakDepth &&
classContainsToken(classAttr, "ornamental-break-as-text");
if (!isHiddenOrnamentalTextFallback) {
self->skipCurrentElement();
return;
}
}

if (self->ornamentalBreakDepth < 0 && classContainsToken(classAttr, "ornamental-break")) {
self->ornamentalBreakDepth = self->depth;
self->unsupportedOrnamentalBreakDepth = -1;
}

// Special handling for tables/cells: buffer simple tables for grid layout, with
Expand Down Expand Up @@ -1111,7 +1125,12 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
// Resolve the image path relative to the HTML file
std::string resolvedPath = FsHelpers::normalisePath(FsHelpers::decodeUriEscapes(self->contentBase + src));

if (ImageDecoderFactory::isFormatSupported(resolvedPath)) {
const bool supportedFormat = ImageDecoderFactory::isFormatSupported(resolvedPath);
if (!supportedFormat && alt.empty() && self->ornamentalBreakDepth >= 0) {
self->unsupportedOrnamentalBreakDepth = self->ornamentalBreakDepth;
}

if (supportedFormat) {
// Create a unique filename for the cached image
std::string ext;
size_t extPos = resolvedPath.rfind('.');
Expand Down Expand Up @@ -1977,6 +1996,11 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
self->skipEndElementStateUntilDepth = INT_MAX;
}

if (self->ornamentalBreakDepth == self->depth) {
self->ornamentalBreakDepth = -1;
self->unsupportedOrnamentalBreakDepth = -1;
}

if (self->tableDepth == 1 && (strcmp(name, "td") == 0 || strcmp(name, "th") == 0)) {
self->finalizeCurrentTableCell();
self->nextWordContinues = false;
Expand Down
2 changes: 2 additions & 0 deletions lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class ChapterHtmlSlimParser {
bool lowMemoryImageFallback = false;
bool lowMemoryAbort = false;
bool attemptedTextLayoutFontCacheRelease = false;
int ornamentalBreakDepth = -1;
int unsupportedOrnamentalBreakDepth = -1;

// Style tracking (replaces depth-based approach)
struct StyleStackEntry {
Expand Down
Loading