diff --git a/lib/Epub/Epub/blocks/ImageBlock.cpp b/lib/Epub/Epub/blocks/ImageBlock.cpp index ddf99f90..1ecc2421 100644 --- a/lib/Epub/Epub/blocks/ImageBlock.cpp +++ b/lib/Epub/Epub/blocks/ImageBlock.cpp @@ -104,6 +104,16 @@ void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) { return; } + // Tiled grayscale (#2190): skip the whole image when it doesn't touch the + // active band. The per-pixel writer already clips off-band pixels, but without + // this each of the ~7 bands per plane re-ran the full cache load / pixel walk + // and discarded the result — the dominant cost of AA on image pages. The check + // is orientation-aware and returns true when no strip is active, so the BW + // pass and non-tiled controllers render the image exactly as before. + if (!renderer.glyphIntersectsStrip(x, y, x + width - 1, y + height - 1)) { + return; + } + // Try to render from cache first std::string cachePath = getCachePath(imagePath); if (renderFromCache(renderer, cachePath, x, y, width, height)) { diff --git a/open-x4-sdk b/open-x4-sdk index 344c479b..26648d64 160000 --- a/open-x4-sdk +++ b/open-x4-sdk @@ -1 +1 @@ -Subproject commit 344c479b0818cdac8f4c1e43d8c3732d638eb6bc +Subproject commit 26648d643a1c883ab2f71e1869d05fe2a0c9d498 diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 98174ee7..ca608eaa 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -940,7 +940,13 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or } else { renderer.displayBuffer(HalDisplay::HALF_REFRESH); } - // Double FAST_REFRESH handles ghosting for image pages; don't count toward full refresh cadence + // The image's own page is handled above and doesn't count toward the full + // refresh cadence. But the grayscale pass below leaves gray charge in the + // image region that a plain fast diff on the *next* page can't clear, so + // text there ghosts gray (#2190). Force the next ordinary page onto the + // HALF ghost-cleanup path, which drives every pixel to its target + // regardless of residue. + pagesUntilFullRefresh = 1; } else { ReaderUtils::displayWithRefreshCycle(renderer, pagesUntilFullRefresh); }