Files
crosspoint-reader-mod/chat-summaries/2026-02-13_cleanup-summary.md
cottongin dfbc931c14 mod: Phase 1 - bring forward mod-exclusive files with ActivityManager migration
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
2026-03-07 15:10:00 -05:00

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 — Added bayerCrossesBwBoundary() and hashBlockDither() 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 to DITHERED=0, SOLID=1, NONE=2 with DITHERED as default.
  • src/SettingsList.h — Updated settings UI labels to match new enum order.
  • lib/GfxRenderer/GfxRenderer.h — Removed getRenderMode() 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.