Commit Graph
537 Commits
Author SHA1 Message Date
Justin Mitchell 17e4230068 Add async display refresh to overlap CPU work
Introduces non-blocking display refresh methods that allow CPU work (like grayscale rendering) to overlap with the e-ink panel's refresh time. The async path starts the waveform and returns immediately, with the caller responsible for waiting via waitRefreshComplete(). Falls back to blocking refresh when fadingFix is enabled or the panel lacks deferral support.
2026-07-14 04:42:27 -04:00
Justin Mitchell 34e7ed249b Merge remote-tracking branch 'origin/develop' into feat-bluetooth 2026-07-14 04:20:50 -04:00
Husam Younis 2a19eb9e0d feat: Arabic/Farsi/Urdu glyphs in built-in UI fonts - PR 2/3 (#2596) 2026-07-13 22:35:47 +03:00
Uri Tauber fae3423dec feat: add portuguese-PT.yaml (#2597) 2026-07-13 22:27:23 +03:00
Husam YounisandUri Tauber 932a472835 feat: Arabic/Farsi/Urdu bidi reordering and contextual shaping — PR 1/3 (#2541)
Co-authored-by: Uri Tauber <uritaube@gmail.com>
2026-07-13 16:02:21 +03:00
Jan Steinke 552b2683e6 fix: keep list item bullet inline with nested paragraph text (#2589) 2026-07-13 12:06:43 +03:00
Mr.Catfood bfa1d706b1 feat: Hidden wifi ssid support (#2360) 2026-07-13 02:33:48 -04:00
Nick Perez 3a97f3e63e feat: Send optional document metadata with KOSync progress uploads (#1820) 2026-07-12 23:50:38 -04:00
Matthías Páll Gissurarson 39ea4b045f feat: render placeholders while waiting for images to render (#1003) 2026-07-12 21:40:07 +03:00
Justin Mitchell 444d87de82 fix: Add framebuffer release/realloc and improved lazy indexing (#2563) 2026-07-12 13:16:48 -04:00
Leopoldo Pla Sempere 859f6cb0d5 chore: update Spanish, Catalan, and Valencian Wi-Fi strings (#2578) 2026-07-12 12:13:06 +03:00
hooligan333andErica Jensen d8139e9605 perf: release CSS rule map after warm open (#2439)
Co-authored-by: Erica Jensen <erica@mailershaven.com>
2026-07-11 22:59:31 -04:00
hooligan333andErica Jensen b596f21e61 perf: stream NCX/NAV TOC into parser, drop temp-file round-trip (#2440)
Co-authored-by: Erica Jensen <erica@mailershaven.com>
2026-07-11 22:57:48 -04:00
hooligan333andErica Jensen 5fbc657aeb perf: always binary-search idref lookups in content.opf (#2433)
Co-authored-by: Erica Jensen <erica@mailershaven.com>
2026-07-11 22:56:28 -04:00
Alexander Hoff ❍andAlexander Hoffer 5202bbf911 feat: auto-connect saved Wi-Fi networks (#2189)
Co-authored-by: Alexander Hoffer <git@alexanderhoffer.com>
2026-07-11 22:47:26 -04:00
hooligan333andErica Jensen e0253a8664 perf: reserve CSS rule map before loading from cache (#2435)
Co-authored-by: Erica Jensen <erica@mailershaven.com>
2026-07-11 22:24:43 -04:00
hooligan333andErica Jensen e142e88ce7 perf: drop per-image delay(50) on chapter build, retry getDimensions (#2434)
Co-authored-by: Erica Jensen <erica@mailershaven.com>
2026-07-11 22:23:52 -04:00
Timo 6add0b91bc feat: Add Finnish hyphenation (#2084) 2026-07-11 22:16:42 -04:00
Leopoldo Pla Sempere 287457f7dd fix: handle low-bit-depth, upscaled, and SVG EPUB images (#2503) 2026-07-11 21:45:53 -04:00
Justin Mitchell 3e627112f6 fix: oom exceptions for OPDS, KOSync, and OTA via wolfssl (#2475) 2026-07-12 01:53:26 +03:00
Stefan Blixten Karlsson 1f5669a08a fix: Swedish translation (#2577) 2026-07-11 23:20:20 +03:00
Ing. Jan Kaláb 0dc92c142c fix: update czech.yaml (#2574) 2026-07-11 21:09:09 +03:00
Leopoldo Pla Sempere 4b34a576eb chore: update Spanish, Catalan, and Valencian translations (#2566) 2026-07-10 17:45:40 +03:00
Justin Mitchell 05c1e9aa46 Add framebuffer lending for memory-intensive builds
Temporarily release framebuffer memory during section pagination to reduce heap pressure. The framebuffer can be released before memory-intensive operations and restored afterward, allowing BLE stack startup threshold to be lowered from 80KB to 70KB. Implements RAII-style FrameBufferBuildLoan class to ensure proper cleanup and automatic restart on restoration failure.
2026-07-09 00:04:11 -04:00
Justin Mitchell f3da5e4f06 Merge branch 'develop' of https://github.com/crosspoint-reader/crosspoint-reader into feat-bluetooth 2026-07-08 22:13:16 -04:00
Matteo Scopel a43061305a chore: update the Italian translation (#2559) 2026-07-08 22:22:47 +03:00
Uri Tauber 7ec07b4d9d fix: show "Failed to index" when failing to parse epub (#2556) 2026-07-08 21:22:35 +03:00
Uri Tauber c2c1badc7e chore: Refactor stores to use PersistableStore CRTP template (#2464) 2026-07-08 12:44:52 +03:00
Nick 5776911af0 fix: FontDecompressor OOM aborts on the render path (-fno-exceptions makes vector resize fatal) (#2526) 2026-07-07 09:06:18 +03:00
Justin Mitchell 6f5c5a0900 fix: Flatten TextBlock word storage into single allocation (#2547) 2026-07-06 23:41:00 +03:00
Uri TauberandBrooks Ilg 44ff313740 fix: render <br> between paragraphs as a visible section break (#2548)
Co-authored-by: Brooks Ilg <brooksmilg@gmail.com>
2026-07-06 20:10:31 +03:00
Justin Mitchell 1c13913713 Implement keep-if-fits buffer reuse to reduce heap fragmentation
Replace per-page buffer free+realloc pattern with capacity tracking that only reallocates when needed size exceeds current capacity. This prevents heap fragmentation from non-coalescing holes that occurred when each page's freed block rarely fit the next page's allocation. After a few page turns, capacities converge on the book's maximum and page turns stop touching the allocator entirely.
2026-07-06 08:30:17 -04:00
Justin Mitchell 613371b716 Add heap pressure management for BLE and rendering
Prevent OOM aborts by shedding BLE stack when free heap drops below 24KB before rendering. Lower BLE start threshold from 100KB to 80KB to match steady-state heap levels (~84KB). Reserve vector capacity upfront in page parsing to avoid reallocation crashes on fragmented heaps. Gate background section builds on heap availability.
2026-07-06 08:12:11 -04:00
Justin Mitchell 4c93950771 Merge branch 'pr-2527' into feat-bluetooth
# Conflicts:
#	src/activities/reader/EpubReaderActivity.cpp
2026-07-06 02:10:55 -04:00
Justin Mitchell 9bf6e5f43c Merge remote-tracking branch 'origin/develop' into feat-bluetooth
# Conflicts:
#	.gitmodules
#	freeink-sdk
#	platformio.ini
#	src/activities/reader/EpubReaderActivity.cpp
2026-07-06 02:04:38 -04:00
Tom-Inge Larsen 3e1dd31e53 feat(reader): End of Book next-book suggestions (#2499) (#2532) 2026-07-04 23:12:59 +03:00
685d4e88f9 feat: Lazy incremental EPUB section indexing (#2452)
Co-authored-by: Uri Tauber <uritaube@gmail.com>
Co-authored-by: Julia Nguyen <julia@uxj.io>
2026-07-04 21:21:24 +03:00
Jakub Sypiański 79b4d63ee2 fix: settings persist on font clear, reserve() before push_back, minor (#2519) 2026-07-03 18:58:24 +03:00
Nick 793685e76b feat: user path to resume BT from low-memory pause via reader menu toggle
Field session: after a recovery teardown the heap settles at ~72 KB --
below the 100 KB start floor -- and never recovers on its own (the
defrag silent-restart only fires when a build FAILS, and builds succeed
now). BT stayed paused forever, the menu toggle claimed ON, and toggling
off/on changed nothing.

- Menu label tells the truth: ON / PAUSED (enabled but stack down) / OFF
  (new STR_STATE_PAUSED string)
- Toggling BT on below the heap floor silent-restarts into the current
  book: the fresh boot's ~118 KB passes the gate and BT auto-starts on
  resume. Explicit user intent is the right trigger for the defrag.
- Hoist the floor to bleinput::kStartMinFreeHeap, shared by the
  lifecycle gate and the toggle
2026-07-02 17:25:34 -05:00
Leopoldo Pla SempereandJiangoJ 57447a56a6 feat(epub): improve text-decoration support (#2397)
Co-authored-by: JiangoJ <jiangj2620@gmail.com>
2026-07-02 12:35:24 +03:00
Justin Mitchell e7f3406704 fix: Add socket module import to build-sd-fonts script (#2504) (#2505) 2026-07-01 12:10:15 -04:00
Bastian 6f08a88b12 fix: changing translation in czech to fix overflowing navigation (#2502) 2026-07-01 11:58:24 -04:00
Tom-Inge LarsenandClaude Opus 4.8 e4d3981469 fix(reader): correct slider side-button direction and legend on X3 (#2402) (#2428)
## Summary

* **What is the goal of this PR?** Fixes #2402. On the X3, the "Time to
Sleep"
picker's 5-minute side buttons were inverted (left increased, right
decreased)
  and the on-screen legend didn't match the physical buttons.
* **What changes are included?**
  * Flip the large-step (±5 min) direction on X3 so the left side button
decreases and the right increases, matching the layout. X4 is unchanged.
* Add a device-specific step-hint string
(`STR_SLEEP_TIMER_STEP_HINT_X3`)
selected via `gpio.deviceIsX3()`. X3 shows `+/-: 1 min Side buttons: 5
min`;
    X4 keeps the original `Left/Right: 1 min  Up/Down: 5 min`.
* Same fix applied to both slider pickers that read the raw up/down side
    buttons: the Time-to-Sleep picker and the "Go to %" picker
(`EpubReaderPercentSelectionActivity`), each with its own X3 hint string
    (`STR_SLEEP_TIMER_STEP_HINT_X3`, `STR_PERCENT_STEP_HINT_X3`).

## Additional Context

* **Root cause:** the X3's side buttons sit one on each edge of the
screen
(power on top), whereas the X4 has a vertical up/down rocker on the
right
edge. So `BTN_UP` is physically the *left* button on X3 but the *top*
button
  on X4. The picker mapped up→+5 / down→−5 unconditionally, which reads
naturally on the X4 rocker but inverted on the X3's left/right buttons.
The
  static legend ("Up/Down: 5 min") had the same X3-only mismatch.
* The codebase already detects the device at runtime and handles this
layout
difference elsewhere (e.g. `LyraTheme::drawSideButtonHints` draws "Up on
left,
Down on right" for X3), so this reuses the same `gpio.deviceIsX3()`
signal.
* Swept the codebase for other side-button sliders:
`ClockOffsetActivity` already
uses the `Next/Previous` (`ButtonNavigator`) abstraction, which resolves
to
left=decrement / right=increment on X3, so it needs no change. List/page
navigation (Wi-Fi, KOReader sync, BMP viewer) and the keyboard cursor
are also
unaffected. The two slider pickers above were the only ones using raw
up/down.
* **X4 is untouched** — same direction, same legend wording as before.
* **Tested on X3 hardware:** left side button now decreases, right
increases, and
  the legend matches. X4 not yet tested on device (no unit on hand); its
  behaviour and strings are unchanged from master.
* **Translations:** the new `STR_SLEEP_TIMER_STEP_HINT_X3` and
`STR_PERCENT_STEP_HINT_X3` were added to all 26 languages, but the
non-English
  ones are AI-generated and would benefit from a native-speaker pass —
particularly Hebrew (RTL ordering with a leading `+/-`), Kazakh, and
Vietnamese.

---

### AI Usage

Did you use AI tools to help write this code? _**YES**_

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 11:06:31 -04:00
Pietro Campagnano 28255061fb fix(icons): align home menu icons with their labels (#2470) 2026-06-29 13:59:54 -04:00
Julia Nguyen 43ff1b6644 Merge remote-tracking branch 'origin/master' into develop 2026-06-29 12:29:58 -04:00
Егор Мартынов 2754a5ff01 feat: add Vollkorn font (#2473)
CI (build) / clang-format (push) Canceled after 0s
CI (build) / cppcheck (push) Canceled after 0s
CI (build) / build (push) Canceled after 0s
CI (build) / unit-tests (push) Canceled after 0s
CI (build) / Test Status (push) Canceled after 0s
2026-06-29 15:54:01 +03:00
Rodrigo Matsuura a11517a62d fix: update Portuguese (Brasil) translations (#2458) 2026-06-28 15:07:52 +03:00
Julia Nguyen b6ce599b20 fix: address release review feedback 2026-06-26 16:22:20 -04:00
Juliaandcoderabbitai[bot] f54eab2725 fix: typo in STR_ORIENTATION_INVERTED Spanish translation
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-06-26 16:13:19 -04:00
Uri TauberandRyan Mercado a2f2eea79e perf: Optimize fillRectDither with Byte-Aligned fillRectImpl (#2270)
## Summary

* **What is the goal of this PR?**
Replace the pixel-by-pixel `fillRectDither` implementation with a new
byte-aligned `fillRectImpl` that eliminates per-pixel
`rotateCoordinates` calls and Read-Modify-Write bitwise loops, yielding
a significant rendering speedup on ESP32 E-ink framebuffers.

Ported from @rhythmerc's crosspoint-reader fork commit 27ea625.

* **What changes are included?**

- **`GfxRenderer.cpp` — `fillRectDither` refactor:** The existing
`if/else if` chain is replaced with a `switch` statement that delegates
each `Color` case to the new `fillRectImpl<Color>()` template,
eliminating runtime branching.

- **`GfxRenderer.cpp` — new `fillRectImpl<C>()` template:** Core of the
optimization. Key behaviors:
    - Clips the rectangle in logical space upfront.
- Rotates only **2 opposing corner points** (top-left and bottom-right)
into physical framebuffer space instead of rotating every pixel
individually.
- Derives physical-space `byteStart`/`byteEnd` and precomputes
`headMask` / `tailMask` for MSB-first partial-byte boundaries,
performing RMW only on the edge bytes.
- **Solid fills (`Black` / `White`):** Uses `memset` for all interior
full-byte runs per row — no per-pixel writes.
- **Dithered fills (`LightGray` / `DarkGray`):** Precomputes both parity
variants of `blackMask` (even/odd `py`) **outside** the row loop,
eliminating the previously re-evaluated 8-bit construction loop on every
physical row. Interior full bytes are then written with a single
`memset(whiteMask)`.
- Uses `if constexpr` throughout to dispatch on `Color` at compile time,
generating zero runtime branches per template instantiation.

- **`GfxRenderer.h`:** Declares the new private `fillRectImpl<Color>()`
template method with an explanatory doc-comment.

- **Explicit template instantiations** added for all four active `Color`
variants (`Black`, `White`, `LightGray`, `DarkGray`).

## Additional Context

* **Performance:** The primary motivation is ESP32 E-ink framebuffer
performance. The old path called `rotateCoordinates` and did a full RMW
for every single pixel in the rectangle. The new path calls
`rotateCoordinates` exactly **twice** per fill regardless of rectangle
size, then operates at byte granularity — a complexity reduction from
O(W×H) coordinate transforms to O(1).
* **Dither correctness:** The `blackMask` precomputation relies on the
dither pattern having period 2 in both logical X and Y, which makes the
per-row byte pattern repeat with period 2 in `py`. Reviewers should
verify the `lxBase`/`lyBase` derivations for all four orientations
(`Portrait`, `PortraitInverted`, `LandscapeClockwise`,
`LandscapeCounterClockwise`) match the inverse of `rotateCoordinates`.
* **Edge case — single-byte rows:** When `byteStart == byteEnd`, the
head and tail masks are ANDed together into a single `rectMask` to avoid
double-masking the same byte. This path should be tested with narrow
rectangles (width < 8px).
* **No behavioral change for `Color::Clear`:** The `Clear` case exits
early via `if constexpr` and is a no-op, matching the original behavior.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< YES >**_

---------

Co-authored-by: Ryan Mercado <rmercado@firstdollar.com>
2026-06-26 12:16:25 -04:00