Files
crosspoint-reader-mod/mod/prs/sleep-screen-tweaks.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

49 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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**_