From ad282cadfeb9a526d0733e37bd7766ed59f17c1e Mon Sep 17 00:00:00 2001 From: cottongin Date: Thu, 19 Feb 2026 14:30:10 -0500 Subject: [PATCH] fix: Align double FAST_REFRESH image rendering with upstream PR #957 Reorder refresh branches so image+AA pages always use the double FAST_REFRESH technique instead of occasionally falling through to HALF_REFRESH when the refresh counter expires. Image pages no longer count toward the full refresh cadence. Remove experimental Method B toggle (USE_IMAGE_DOUBLE_FAST_REFRESH / displayWindow). Co-authored-by: Cursor --- src/activities/reader/EpubReaderActivity.cpp | 50 +++++--------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 2da34d12..4ed7a595 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -22,11 +22,6 @@ #include "util/BookmarkStore.h" #include "util/Dictionary.h" -// Image refresh optimization strategy: -// 0 = Use double FAST_REFRESH technique (default, feels snappier) -// 1 = Use displayWindow() for partial refresh (experimental) -#define USE_IMAGE_DOUBLE_FAST_REFRESH 0 - namespace { // pagesPerRefresh now comes from SETTINGS.getRefreshFrequency() constexpr unsigned long skipChapterMs = 700; @@ -1022,13 +1017,8 @@ void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageC void EpubReaderActivity::renderContents(std::unique_ptr page, const int orientedMarginTop, const int orientedMarginRight, const int orientedMarginBottom, const int orientedMarginLeft) { - // Determine if this page needs special image handling - bool pageHasImages = page->hasImages(); - bool useAntiAliasing = SETTINGS.textAntiAliasing; - - // Force half refresh for pages with images when anti-aliasing is on, - // as grayscale tones require half refresh to display correctly - bool forceFullRefresh = pageHasImages && useAntiAliasing; + // Force special handling for pages with images when anti-aliasing is on + bool imagePageWithAA = page->hasImages() && SETTINGS.textAntiAliasing; page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop); @@ -1048,42 +1038,26 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or } renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); - - // Check if half-refresh is needed (either entering Reader or pages counter reached) - if (pagesUntilFullRefresh <= 1) { - renderer.displayBuffer(HalDisplay::HALF_REFRESH); - pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); - } else if (forceFullRefresh) { - // OPTIMIZATION: For image pages with anti-aliasing, use fast double-refresh technique - // to reduce perceived lag. Only when pagesUntilFullRefresh > 1 (screen already clean). + if (imagePageWithAA) { + // Double FAST_REFRESH with selective image blanking (pablohc's technique): + // HALF_REFRESH sets particles too firmly for the grayscale LUT to adjust. + // Instead, blank only the image area and do two fast refreshes. int imgX, imgY, imgW, imgH; if (page->getImageBoundingBox(imgX, imgY, imgW, imgH)) { - int screenX = imgX + orientedMarginLeft; - int screenY = imgY + orientedMarginTop; - LOG_DBG("ERS", "Image page: fast double-refresh (page bbox: %d,%d %dx%d, screen: %d,%d %dx%d)", imgX, imgY, imgW, - imgH, screenX, screenY, imgW, imgH); + renderer.fillRect(imgX + orientedMarginLeft, imgY + orientedMarginTop, imgW, imgH, false); + renderer.displayBuffer(HalDisplay::FAST_REFRESH); -#if USE_IMAGE_DOUBLE_FAST_REFRESH == 0 - // Method A: Fill blank area + two FAST_REFRESH operations - renderer.fillRect(screenX, screenY, imgW, imgH, false); - renderer.displayBuffer(HalDisplay::FAST_REFRESH); page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); renderer.displayBuffer(HalDisplay::FAST_REFRESH); -#else - // Method B (experimental): Use displayWindow() for partial refresh - renderer.displayBuffer(HalDisplay::FAST_REFRESH); - page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop); - renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); - renderer.displayWindow(screenX, screenY, imgW, imgH, HalDisplay::FAST_REFRESH); -#endif } else { - LOG_DBG("ERS", "Image page but no bbox, using standard half refresh"); renderer.displayBuffer(HalDisplay::HALF_REFRESH); } - pagesUntilFullRefresh--; + // Double FAST_REFRESH handles ghosting for image pages; don't count toward full refresh cadence + } else if (pagesUntilFullRefresh <= 1) { + renderer.displayBuffer(HalDisplay::HALF_REFRESH); + pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); } else { - // Normal page without images, or images without anti-aliasing renderer.displayBuffer(); pagesUntilFullRefresh--; }