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
49 lines
4.3 KiB
Markdown
49 lines
4.3 KiB
Markdown
# feat: Sleep screen letterbox fill and image upscaling
|
||
|
||
**Branch:** `mod/sleep-screen-tweaks`
|
||
|
||
## Summary
|
||
|
||
* **What is the goal of this PR?**
|
||
Improve the sleep screen experience for cover images that don't match the display's aspect ratio, and fix Fit mode for images smaller than the screen.
|
||
|
||
* **What changes are included?**
|
||
- Configurable letterbox fill for sleep screen cover images. Four fill modes:
|
||
- **Solid** — computes the dominant (average) shade from the image edge and fills the entire letterbox area with that single dithered color.
|
||
- **Blended** — fills using per-pixel sampled edge colors with noise dithering (no distance-based interpolation), producing a smooth edge-matching fill that varies along the image border.
|
||
- **Gradient** — interpolates per-pixel edge colors toward a configurable target color (white or black) over distance, creating a fade effect.
|
||
- **None** — plain white letterbox (original behavior).
|
||
- Image upscaling in Fit mode: images smaller than the display are now scaled up to fit while preserving aspect ratio. Previously, small images were simply centered without scaling.
|
||
- Edge data caching: the edge-sampling pass (which reads the full bitmap) is performed once per cover and cached as a compact binary file (~1KB) alongside the cover BMP in `.crosspoint/`. Subsequent sleeps load from cache, skipping the bitmap scan entirely. Cache is validated against screen dimensions and auto-regenerated when stale.
|
||
- Two new user-facing settings:
|
||
- **Letterbox Fill** — None / Solid / Blended / Gradient
|
||
- **Gradient Direction** — To White / To Black
|
||
|
||
## Files Changed
|
||
|
||
| File | Change |
|
||
|------|--------|
|
||
| `lib/GfxRenderer/GfxRenderer.cpp` | Unified block-fill scaling in `drawBitmap`/`drawBitmap1Bit` supporting both upscaling and downscaling; added `drawPixelGray` helper |
|
||
| `lib/GfxRenderer/GfxRenderer.h` | `drawPixelGray` declaration |
|
||
| `lib/GfxRenderer/BitmapHelpers.cpp` | Added `quantizeNoiseDither` — hash-based noise dithering for gradient/solid fills |
|
||
| `lib/GfxRenderer/BitmapHelpers.h` | `quantizeNoiseDither` declaration |
|
||
| `src/activities/boot_sleep/SleepActivity.cpp` | Edge sampling (`sampleBitmapEdges`), letterbox fill rendering (`drawLetterboxFill`), edge data cache (`loadEdgeCache`/`saveEdgeCache`), integration in `renderBitmapSleepScreen`/`renderCoverSleepScreen`; unconditional aspect-ratio scaling for Fit mode |
|
||
| `src/activities/boot_sleep/SleepActivity.h` | Updated `renderBitmapSleepScreen` signature with optional `edgeCachePath` parameter |
|
||
| `src/CrossPointSettings.h` | New enums `SLEEP_SCREEN_LETTERBOX_FILL` (4 values) and `SLEEP_SCREEN_GRADIENT_DIR`; new fields `sleepScreenLetterboxFill`, `sleepScreenGradientDir` |
|
||
| `src/CrossPointSettings.cpp` | Serialization of new settings fields (incremented `SETTINGS_COUNT`) |
|
||
| `src/SettingsList.h` | New "Letterbox Fill" and "Gradient Direction" setting entries in Display category |
|
||
|
||
## Additional Context
|
||
|
||
* **Performance:** The edge sampling pass reads the full bitmap row-by-row (~48KB for a full-screen 2-bit image). This is done once per cover image and cached. Subsequent sleeps for the same cover skip this pass entirely, loading ~1KB from the cache file instead.
|
||
* **Memory:** Edge sampling uses temporary `uint32_t` accumulator arrays (~10KB peak) which are freed immediately after processing. Final edge data arrays (~1.6KB max) persist only for the duration of rendering. The cache file is ~970 bytes for a 480-wide image.
|
||
* **Upscaling approach:** Nearest-neighbor via block-fill — each source pixel maps to a rectangle of destination pixels. No interpolation, which is appropriate for the 4-level grayscale e-ink display.
|
||
* **Cache invalidation:** Validated by cache version byte and screen dimensions (width × height). Orientation changes trigger regeneration. Each cover mode (Fit vs Crop) produces a different BMP and thus a different cache path. Cache files live in the book-specific `.crosspoint/epub_<hash>/` directory and are naturally scoped per-book.
|
||
* **Potential risks:** The `drawBitmap`/`drawBitmap1Bit` scaling refactor affects all bitmap rendering, not just sleep screens. The logic is functionally equivalent for downscaling (≤1.0) and 1:1 cases; upscaling (>1.0) is new behavior only triggered when both `maxWidth` and `maxHeight` are provided.
|
||
|
||
---
|
||
|
||
### AI Usage
|
||
|
||
Did you use AI tools to help write this code? _**YES**_
|