Brings ~55 mod-exclusive files to the upstream-based mod/master-resync branch: Activities (migrated to new ActivityManager pattern): - Clock/Time: SetTimeActivity, SetTimezoneOffsetActivity, NtpSyncActivity - Dictionary: DictionaryDefinitionActivity, DictionarySuggestionsActivity, DictionaryWordSelectActivity, LookedUpWordsActivity - Bookmark: EpubReaderBookmarkSelectionActivity - Book management: BookManageMenuActivity, EndOfBookMenuActivity - OPDS: OpdsServerListActivity, OpdsSettingsActivity - Utility: DirectoryPickerActivity, NumericStepperActivity Utilities (unchanged): - BookManager, BookSettings, BookmarkStore, BootNtpSync - Dictionary, LookupHistory, TimeSync, OpdsServerStore Libraries: PlaceholderCover, TableData, ChapterXPathIndexer Scripts: inject_mod_version, generate_book_icon, preview_placeholder_cover Docs: KOReader sync XPath mapping Migration changes: - ActivityWithSubactivity -> Activity base class - Callback constructors -> finish()/setResult() pattern - enterNewActivity() -> startActivityForResult() - Activity::RenderLock&& -> RenderLock&& These files won't compile yet - they reference mod settings and I18n strings that will be added in subsequent phases. Made-with: Cursor
2.1 KiB
2.1 KiB
Letterbox Fill: Hash-Based Block Dithering Fix & Cleanup
Date: 2026-02-13
Task Description
Resolved an e-ink display crosstalk issue where a specific book cover ("The World in a Grain") became completely washed out and invisible when using "Dithered" letterbox fill mode. The root cause was pixel-level Bayer dithering creating a high-frequency checkerboard pattern in the BW pass for gray values in the 171-254 range (level-2/level-3 boundary), which caused display crosstalk during HALF_REFRESH.
Solution
Hash-based block dithering with 2x2 pixel blocks for gray values in the problematic BW-boundary range (171-254). Each 2x2 block gets a uniform level (2 or 3) determined by a spatial hash, with the proportion approximating the target gray. Standard Bayer dithering is used for all other gray ranges.
Changes Made
Modified Files
src/activities/boot_sleep/SleepActivity.cpp— AddedbayerCrossesBwBoundary()andhashBlockDither()functions;drawLetterboxFill()uses hash-based block dithering for BW-boundary gray values, standard Bayer for everything else. Removed all debug instrumentation (H1-H20 logs, frame buffer checksums, edge histograms, rewind verification).src/CrossPointSettings.h— Reordered letterbox fill enum toDITHERED=0, SOLID=1, NONE=2withDITHEREDas default.src/SettingsList.h— Updated settings UI labels to match new enum order.lib/GfxRenderer/GfxRenderer.h— RemovedgetRenderMode()getter (was only needed by debug instrumentation).
Deleted Files
- 16 debug log files from
.cursor/directory
Key Findings
- Single-pixel alternation (block=1) causes display crosstalk regardless of pattern regularity (Bayer or hash).
- 2x2 minimum pixel runs are sufficient to avoid crosstalk on this e-ink display.
- The irregular hash pattern is less visually noticeable than a regular Bayer grid at the same block size.
- The issue only affects gray values 171-254 where Bayer produces a level-2/level-3 mix (the BW pass boundary).
Follow-up Items
- None. Feature is stable and working for all tested book covers.