Files
crosspoint-reader-mod/chat-summaries/2026-02-13_letterbox-extend-edges.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

50 lines
2.9 KiB
Markdown

# Letterbox Fill: Replace Dithering with Edge Replication ("Extend Edges")
**Date:** 2026-02-13
## Task Description
After implementing Bayer ordered dithering for the "Blended" letterbox fill mode (replacing earlier noise dithering), the user reported that the problematic cover (*The World in a Grain* by Vince Beiser) looked even worse. Investigation revealed that **any dithering technique** is fundamentally incompatible with the e-ink multi-pass rendering pipeline for large uniform fill areas:
- The BW HALF_REFRESH pass creates a visible dark/white pattern in the letterbox
- The subsequent greyscale correction can't cleanly handle mixed-level patterns in large uniform areas
- This causes crosstalk artifacts that can affect adjacent cover rendering
- Uniform fills (all same level, like Solid mode) work fine because all pixels go through identical correction
The user's key insight: the display already renders the cover's grayscale correctly (including Atkinson-dithered mixed levels). Instead of re-dithering an averaged color, replicate the cover's actual boundary pixels into the letterbox -- letting the display render them the same way it renders the cover itself.
## Changes Made
### `src/CrossPointSettings.h`
- Renamed `LETTERBOX_BLENDED` (value 2) → `LETTERBOX_EXTENDED`
- Updated comment to reflect "None / Solid / Extend Edges"
### `src/SettingsList.h`
- Changed UI label from `"Blended"``"Extend Edges"`
### `src/activities/boot_sleep/SleepActivity.cpp`
- **Removed**: `BAYER_4X4` matrix, `quantizeBayerDither()` function (all Bayer dithering code)
- **Added**: `getPackedPixel()`, `setPackedPixel()` helpers for packed 2-bit array access
- **Rewrote** `LetterboxFillData` struct:
- Added `edgeA`/`edgeB` (dynamically allocated packed 2-bit arrays) for per-pixel edge data
- Added `edgePixelCount`, `scale` for coordinate mapping
- Added `freeEdgeData()` cleanup method
- **Renamed** `computeEdgeAverages()``computeEdgeData()`:
- New `captureEdgePixels` parameter controls whether to allocate and fill edge arrays
- For horizontal letterboxing: captures first/last visible BMP rows
- For vertical letterboxing: captures leftmost/rightmost pixel per visible row
- Still computes averages for SOLID mode in the same pass
- **Rewrote** `drawLetterboxFill()`:
- SOLID mode: unchanged (uniform fill with snapped level)
- EXTENDED mode: maps screen coordinates → BMP coordinates via scale factor, looks up stored 2-bit pixel values from the cover's boundary row/column
- **Updated** `renderBitmapSleepScreen()`: new log messages, `freeEdgeData()` call at end
## Backward Compatibility
- Enum value 2 is unchanged (was `LETTERBOX_BLENDED`, now `LETTERBOX_EXTENDED`)
- Serialized settings files continue to work without migration
## Follow-up Items
- Test "Extend Edges" mode with both covers (Power Broker and World in a Grain)
- Test vertical letterboxing (left/right) if applicable covers are available
- Verify SOLID mode still works as expected