Commit Graph

478 Commits

Author SHA1 Message Date
cottongin
013a738144 chore: post-sync cleanup and clang-format
- Remove stale Lyra3CoversTheme.h (functionality merged into LyraTheme)
- Fix UITheme.cpp to use LyraTheme for LYRA_3_COVERS theme variant
- Update open-x4-sdk submodule to 91e7e2b (drawImageTransparent support)
- Run clang-format on all source files

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 10:46:25 -05:00
Adrian Wilkins-Caruana
c1d1e98909 perf: Reduce overall flash usage by 30.7% by compressing built-in fonts (#831)
**What is the goal of this PR?**

Compress reader font bitmaps to reduce flash usage by 30.7%.

**What changes are included?**

- New `EpdFontGroup` struct and extended `EpdFontData` with
`groups`/`groupCount` fields
- `--compress` flag in `fontconvert.py`: groups glyphs (ASCII base group
+ groups of 8) and compresses each with raw DEFLATE
- `FontDecompressor` class with 4-slot LRU cache for on-demand
decompression during rendering
- `GfxRenderer` transparently routes bitmap access through
`getGlyphBitmap()` (compressed or direct flash)
- Uses `uzlib` for decompression with minimal heap overhead.
- 48 reader fonts (Bookerly, NotoSans 12-18pt, OpenDyslexic) regenerated
with compression; 5 UI fonts unchanged
- Round-trip verification script (`verify_compression.py`) runs as part
of font generation

| | baseline | font-compression | Difference |
|--|--------|-----------------|------------|
| Flash (ELF) | 6,302,476 B (96.2%) | 4,365,022 B (66.6%) | -1,937,454 B
(-30.7%) |
| firmware.bin | 6,468,192 B | 4,531,008 B | -1,937,184 B (-29.9%) |
| RAM | 101,700 B (31.0%) | 103,076 B (31.5%) | +1,376 B (+0.5%) |

Comparison of uncompressed baseline vs script-based group compression
(4-slot LRU cache, cleared each page). Glyphs are grouped by Unicode
block (ASCII, Latin-1, Latin Extended-A, Combining Marks, Cyrillic,
General Punctuation, etc.) instead of sequential groups of 8.

| | Baseline | Compressed (cold cache) | Difference |
|---|---|---|---|
| **Median** | 414.9 ms | 431.6 ms | +16.7 ms (+4.0%) |
| **Pages** | 37 | 37 | |

| | Baseline | Compressed (cold cache) | Difference |
|---|---|---|---|
| **Heap free (median)** | 187.0 KB | 176.3 KB | -10.7 KB |
| **Heap free (min)** | 186.0 KB | 166.5 KB | -19.5 KB |
| **Largest block (median)** | 148.0 KB | 128.0 KB | -20.0 KB |
| **Largest block (min)** | 148.0 KB | 120.0 KB | -28.0 KB |

| | Misses/page | Hit rate |
|---|---|---|
| **Compressed (cold cache)** | 2.1 | 99.85% |

------

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**_
Implementation was done by Claude Code (Opus 4.6) based on a plan
developed collaboratively. All generated font headers were verified with
an automated round-trip decompression test. The firmware was compiled
successfully but has not yet been tested on-device.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 10:39:11 -05:00
Егор Мартынов
6403ce6309 fix: go to prev page on the first one, get teleported to the end of book (#970)
## Summary

1. Go to the first page in a .epub file.
2. Hit `Up` button
3. Get teleported to the last page :)

`TxtRenderActivity` seems to have this if check, but EPUB one does not.

---

### 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? _**NO**_
2026-02-19 10:36:57 -05:00
Sam Lord
109f95df78 feat: Scale cover images up if they're smaller than the device resolution (#964)
## Summary

**What is the goal of this PR?**
* Implement feature request
[#954](https://github.com/crosspoint-reader/crosspoint-reader/issues/954)
* Ensure cover images are scaled up to match the dimensions of the
screen, as well as scaled down

**What changes are included?**
* Naïve implementation for scaling up the source image

## Additional Context

If you find the extra comments to be excessive I can pare them back. 

Edit: Fixed title

---

### 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 >**_
2026-02-19 10:36:51 -05:00
Zach Nelson
de981f5072 fix: Correct word width and space calculations (#963)
## Summary

**What is the goal of this PR?**

This change fixes an issue I noticed while reading where occasionally,
especially in italics, some words would have too much space between
them. The problem was that word width calculations were including any
negative X overhang, and combined with a space before the word, that can
lead to an inconsistently large space.

## Additional Context

Screenshots of some problematic text:

| In CrossPoint 1.0 | With this change |
| -- | -- |
| <img
src="https://github.com/user-attachments/assets/87bf0e4b-341f-4ba9-b3ea-38c13bd26363"
width="400" /> | <img
src="https://github.com/user-attachments/assets/bf11ba20-c297-4ce1-aa07-43477ef86fc2"
width="400" /> |

---

### 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? _**NO**_
2026-02-19 10:36:44 -05:00
Sam Lord
2bcc1c1495 fix: Skip large CSS files to prevent crashes (#952)
## Summary

**What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
* Fixes:
https://github.com/crosspoint-reader/crosspoint-reader/issues/947

**What changes are included?**
* Check to see if there's free heap memory before processing CSS (should
we be doing this type of check or is it better to just crash if we
exhaust the memory?)
* Skip CSS files larger than 128kb

## Additional Context

* I found that a copy of `Release it` contained a 250kb+ CSS file, from
the homepage of the publisher. It has nothing to do with the epub, so we
should just skip it
* Major question: Are there better ways to detect CSS that doesn't
belong in a book, or is this size-based approach valid?
* Another question: Are there any epubs we know of that legitimately
include >128kb CSS files?

Code changes themselves created with an agent, all investigation and
write-up done by human. If you (the maintainers) would prefer a
different fix for this issue, let me know.

---

### 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 >**_
2026-02-19 10:36:38 -05:00
jpirnay
aa7c0a882a feat: Add 4bit bmp support (#944)
## Summary

* What is the goal of this PR?
- Allow users to create custom sleep screen images with standard tools
(ImageMagick, GIMP, etc.) that render cleanly on the e-ink display
without dithering artifacts. Previously, avoiding dithering required
non-standard 2-bit BMPs that no standard image editor can produce. ( see
issue #931 )

* What changes are included?
- Add 4-bit BMP format support to Bitmap.cpp (standard format, widely
supported by image tools)
- Auto-detect "native palette" images: if a BMP has ≤4 palette entries
and all luminances map within ±21 of the display's native gray levels
(0, 85, 170, 255), skip dithering entirely and direct-map pixels
- Clarify pixel processing strategy with three distinct paths:
error-diffusion dithering, simple quantization, or direct mapping
- Add scripts/generate_test_bmps.py for generating test images across
all supported BMP formats

## Additional Context

* The e-ink display has 4 native gray levels. When a BMP already uses
exactly those levels, dithering adds noise to what should be clean
output. The native palette detection uses a ±21 tolerance (~10%) to
handle slight rounding from color space conversions in image tools.
Users can now create a 4-color grayscale BMP with (imagemagic example):
```
convert input.png -colorspace Gray -colors 4 -depth 
```
---

### 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**_
2026-02-19 10:36:32 -05:00
Zach Nelson
950faf4cd2 perf: Avoid redundant font map lookups (#933)
## Summary

**What is the goal of this PR?**

Several methods in GfxRenderer were doing a `count()` followed by `at()`
on the fonts map, effectively doing the same map lookup unnecessarily.
This can be avoided by doing a single `find()` and reusing the iterator.

---

### 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? _**NO**_
2026-02-19 10:36:27 -05:00
jpirnay
e5d574a07a fix: add bresenham for arbitrary lines (#923)
## Summary

* GfxRender did handle horizontal and vertical lines but had a TODO for
arbitrary lines.
* Added integer based Bresenham line drawing 
  
## Additional Context

---

### 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? _**NO**_
2026-02-19 10:36:21 -05:00
jpirnay
c8ddb6b61d fix: Fix kosync repositioning issue (#783)
## Summary

* Original implementation had inconsistent positioning logic:
- When XPath parsing succeeded: incorrectly set pageNumber = 0 (always
beginning of chapter)
- When XPath parsing failed: used percentage for positioning (worked
correctly)
- Result: Positions restored to wrong locations depending on XPath
parsing success
  - Mentioned in Issue #581 
* Solution
- Unified ProgressMapper::toCrossPoint() to use percentage-based
positioning exclusively for both spine identification and intra-chapter
page calculation, eliminating unreliable XPath parsing entirely.

## Additional Context

* ProgressMapper.cpp: Simplified toCrossPoint() to always use percentage
for positioning, removed parseDocFragmentIndex() function
* ProgressMapper.h: Updated comments and removed unused function
declaration
* Tests confirmed appropriate positioning
* __Notabene: the syncing to another device will (most probably) end up
at the current chapter of crosspoints reading position. There is not
much we can do about it, as KOReader needs to have the correct XPath
information - we can only provide an apporximate position (plus
percentage) - the percentage information is not used in KOReaders
current implementation__
---

### 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
2026-02-19 10:36:15 -05:00
Zach Nelson
ef52af1a52 fix: Added missing up/down button labels (#935)
**What is the goal of this PR?**

In some places, button labels are omitted intentionally because the
button has no purpose in the activity. I noticed a few obvious cases,
like Home > File Transfer and Settings > System > Language, where the up
and down button labels were missing. This change fixes those and all
similar instances I could find.

---

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? _**NO**_
2026-02-19 10:36:03 -05:00
Uri Tauber
8a28755c69 fix: Update Translators list (#927)
## Summary

* **What is the goal of this PR?** Update translators.md to include all
the contributors from #728

---

### 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? _**< NO >**_
2026-02-19 10:35:18 -05:00
ariel-lindemann
4b713f40f1 feat: increase keyboard font size for classic theme (#897)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)

Adresses Feature Request #896 

* **What changes are included?**

Changed key dimensions, initial positions and margins.

## Additional Context

The keyboard now looks like this:

![image](https://github.com/user-attachments/assets/e2b8f3fe-e54a-4a44-9a29-2ef9f2c8dffb)

---

### 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? _**NO**_
2026-02-19 10:35:12 -05:00
Xuan-Son Nguyen
ab5e18aca3 feat: add script for listing objects in flash (#880)
## Summary

Adding a simple script to list objects and its size. I know `pio`
already had the "analyze" function but it never works in my case.

Ref discussion:
https://github.com/crosspoint-reader/crosspoint-reader/discussions/862

To use it:

```sh
scripts/script_profile_mem.sh
```

Example:

```
============================================
Top 10 largest symbols in section: .dram0.bss
Total section size: 85976 bytes (83.96 KB)
============================================
    0000bb98 (  46.90 KB)  display
    00000ed8 (   3.71 KB)  g_cnxMgr
    00000ad8 (   2.71 KB)  ftm_initiator
    00000830 (   2.05 KB)  xIsrStack
    000005b4 (   1.43 KB)  packet.8427
    000004e0 (   1.22 KB)  _ZN12_GLOBAL__N_17ctype_wE
    000004a0 (   1.16 KB)  dns_table
    0000049c (   1.15 KB)  s_wifi_nvs
    00000464 (   1.10 KB)  s_coredump_stack
    0000034c (   0.82 KB)  gWpaSm

============================================
Top 10 largest symbols in section: .dram0.data
Total section size: 13037 bytes (12.73 KB)
============================================
    000003c0 (   0.94 KB)  TxRxCxt
    00000328 (   0.79 KB)  phy_param
    000001d0 (   0.45 KB)  g_wifi_osi_funcs
    0000011b (   0.28 KB)  _ZN18CrossPointSettings8instanceE
    000000e6 (   0.22 KB)  country_info_24ghz
    000000dc (   0.21 KB)  g_eb_list_desc
    000000c0 (   0.19 KB)  s_fd_table
    000000b8 (   0.18 KB)  g_timer_info
    000000a8 (   0.16 KB)  rc11NSchedTbl
    000000a0 (   0.16 KB)  g_rmt_objects

============================================
Top 200 largest symbols in section: .flash.rodata
Total section size: 4564375 bytes (4457.40 KB)
============================================
    000325b7 ( 201.43 KB)  _ZL12de_trie_data
    0001cbd8 ( 114.96 KB)  _ZL29notosans_18_bolditalicBitmaps
    0001ca38 ( 114.55 KB)  _ZL29bookerly_18_bolditalicBitmaps
    0001bd3f ( 111.31 KB)  _ZL23bookerly_18_boldBitmaps
    0001af54 ( 107.83 KB)  _ZL23notosans_18_boldBitmaps
    0001abcc ( 106.95 KB)  _ZL25bookerly_18_italicBitmaps
    0001a341 ( 104.81 KB)  _ZL25notosans_18_italicBitmaps
    0001a0a5 ( 104.16 KB)  _ZL26bookerly_18_regularBitmaps
    0001890c (  98.26 KB)  _ZL26notosans_18_regularBitmaps
    000188cc (  98.20 KB)  _ZL33opendyslexic_14_bolditalicBitmaps
    000170ca (  92.20 KB)  _ZL29notosans_16_bolditalicBitmaps
    00015e7f (  87.62 KB)  _ZL29bookerly_16_bolditalicBitmaps
    00015acb (  86.70 KB)  _ZL23notosans_16_boldBitmaps
    00015140 (  84.31 KB)  _ZL23bookerly_16_boldBitmaps
    00014f0c (  83.76 KB)  _ZL25notosans_16_italicBitmaps
    00014d54 (  83.33 KB)  _ZL29opendyslexic_14_italicBitmaps
    00014766 (  81.85 KB)  _ZL27opendyslexic_14_boldBitmaps
    0001467f (  81.62 KB)  _ZL25bookerly_16_italicBitmaps
    00013c46 (  79.07 KB)  _ZL26bookerly_16_regularBitmaps
    00013934 (  78.30 KB)  _ZL26notosans_16_regularBitmaps
    00012572 (  73.36 KB)  _ZL33opendyslexic_12_bolditalicBitmaps
    00011cee (  71.23 KB)  _ZL29notosans_14_bolditalicBitmaps
    00011547 (  69.32 KB)  _ZL30opendyslexic_14_regularBitmaps
    0001153c (  69.31 KB)  _ZL29bookerly_14_bolditalicBitmaps
    00010c2e (  67.04 KB)  _ZL23notosans_14_boldBitmaps
    0001096e (  66.36 KB)  _ZL23bookerly_14_boldBitmaps
    000103d2 (  64.96 KB)  _ZL25notosans_14_italicBitmaps
    000100d5 (  64.21 KB)  _ZL25bookerly_14_italicBitmaps
    0000f83e (  62.06 KB)  _ZL26bookerly_14_regularBitmaps
    0000f7fc (  62.00 KB)  _ZL29opendyslexic_12_italicBitmaps
    0000f42b (  61.04 KB)  _ZL26notosans_14_regularBitmaps
    0000f229 (  60.54 KB)  _ZL27opendyslexic_12_boldBitmaps
    0000d301 (  52.75 KB)  _ZL29notosans_12_bolditalicBitmaps
    0000d22f (  52.55 KB)  _ZL30opendyslexic_12_regularBitmaps
    0000cff4 (  51.99 KB)  _ZL29bookerly_12_bolditalicBitmaps
    0000cd12 (  51.27 KB)  _ZL33opendyslexic_10_bolditalicBitmaps
    0000cad2 (  50.71 KB)  _ZL23bookerly_12_boldBitmaps
    0000c60a (  49.51 KB)  _ZL23notosans_12_boldBitmaps
    0000c147 (  48.32 KB)  _ZL25bookerly_12_italicBitmaps
    0000c120 (  48.28 KB)  _ZL25notosans_12_italicBitmaps
    0000ba7e (  46.62 KB)  _ZL26bookerly_12_regularBitmaps
    0000b454 (  45.08 KB)  _ZL26notosans_12_regularBitmaps
    0000b1e0 (  44.47 KB)  _ZL29opendyslexic_10_italicBitmaps
    0000a939 (  42.31 KB)  _ZL27opendyslexic_10_boldBitmaps
    0000a0dd (  40.22 KB)  _ZL13FilesPageHtml
    0000949d (  37.15 KB)  _ZL30opendyslexic_10_regularBitmaps
    00008415 (  33.02 KB)  _ZL32opendyslexic_8_bolditalicBitmaps
    00008240 (  32.56 KB)  _ZL15ru_ru_trie_data
    00007587 (  29.38 KB)  _ZL28opendyslexic_8_italicBitmaps
    00006f4d (  27.83 KB)  _ZL26opendyslexic_8_boldBitmaps
    00006943 (  26.32 KB)  _ZL15en_us_trie_data
    00006196 (  24.40 KB)  _ZL29opendyslexic_8_regularBitmaps
    00004990 (  18.39 KB)  _ZL21ubuntu_12_boldBitmaps
    000042ce (  16.70 KB)  _ZL24ubuntu_12_regularBitmaps
    000036d0 (  13.70 KB)  _ZL25notosans_18_regularGlyphs
    000036d0 (  13.70 KB)  _ZL25notosans_16_regularGlyphs
    000036d0 (  13.70 KB)  _ZL25notosans_14_regularGlyphs
    000036d0 (  13.70 KB)  _ZL25notosans_12_regularGlyphs
    000036d0 (  13.70 KB)  _ZL24notosans_8_regularGlyphs
    000036d0 (  13.70 KB)  _ZL22notosans_18_boldGlyphs
    000036d0 (  13.70 KB)  _ZL22notosans_16_boldGlyphs
    000036d0 (  13.70 KB)  _ZL22notosans_14_boldGlyphs
    000036d0 (  13.70 KB)  _ZL22notosans_12_boldGlyphs
    000036c0 (  13.69 KB)  _ZL28notosans_18_bolditalicGlyphs
    000036c0 (  13.69 KB)  _ZL28notosans_16_bolditalicGlyphs
    000036c0 (  13.69 KB)  _ZL28notosans_14_bolditalicGlyphs
    000036c0 (  13.69 KB)  _ZL28notosans_12_bolditalicGlyphs
    000036c0 (  13.69 KB)  _ZL24notosans_18_italicGlyphs
    000036c0 (  13.69 KB)  _ZL24notosans_16_italicGlyphs
    000036c0 (  13.69 KB)  _ZL24notosans_14_italicGlyphs
    000036c0 (  13.69 KB)  _ZL24notosans_12_italicGlyphs
    00003627 (  13.54 KB)  _ZL21ubuntu_10_boldBitmaps
    00003551 (  13.33 KB)  _ZL12es_trie_data
    000030c4 (  12.19 KB)  _ZL24ubuntu_10_regularBitmaps
    00002eb0 (  11.67 KB)  _ZL28bookerly_18_bolditalicGlyphs
    00002eb0 (  11.67 KB)  _ZL28bookerly_16_bolditalicGlyphs
    00002eb0 (  11.67 KB)  _ZL28bookerly_14_bolditalicGlyphs
    00002eb0 (  11.67 KB)  _ZL28bookerly_12_bolditalicGlyphs
    00002eb0 (  11.67 KB)  _ZL25bookerly_18_regularGlyphs
    00002eb0 (  11.67 KB)  _ZL25bookerly_16_regularGlyphs
    00002eb0 (  11.67 KB)  _ZL25bookerly_14_regularGlyphs
    00002eb0 (  11.67 KB)  _ZL25bookerly_12_regularGlyphs
    00002eb0 (  11.67 KB)  _ZL24bookerly_18_italicGlyphs
    00002eb0 (  11.67 KB)  _ZL24bookerly_16_italicGlyphs
    00002eb0 (  11.67 KB)  _ZL24bookerly_14_italicGlyphs
    00002eb0 (  11.67 KB)  _ZL24bookerly_12_italicGlyphs
    00002eb0 (  11.67 KB)  _ZL22bookerly_18_boldGlyphs
    00002eb0 (  11.67 KB)  _ZL22bookerly_16_boldGlyphs
    00002eb0 (  11.67 KB)  _ZL22bookerly_14_boldGlyphs
    00002eb0 (  11.67 KB)  _ZL22bookerly_12_boldGlyphs
    00002d50 (  11.33 KB)  _ZL32opendyslexic_14_bolditalicGlyphs
    00002d50 (  11.33 KB)  _ZL32opendyslexic_12_bolditalicGlyphs
    00002d50 (  11.33 KB)  _ZL32opendyslexic_10_bolditalicGlyphs
    00002d50 (  11.33 KB)  _ZL31opendyslexic_8_bolditalicGlyphs
    00002d50 (  11.33 KB)  _ZL29opendyslexic_14_regularGlyphs
    00002d50 (  11.33 KB)  _ZL29opendyslexic_12_regularGlyphs
    00002d50 (  11.33 KB)  _ZL29opendyslexic_10_regularGlyphs
    00002d50 (  11.33 KB)  _ZL28opendyslexic_8_regularGlyphs
    00002d50 (  11.33 KB)  _ZL28opendyslexic_14_italicGlyphs
    00002d50 (  11.33 KB)  _ZL28opendyslexic_12_italicGlyphs
    00002d50 (  11.33 KB)  _ZL28opendyslexic_10_italicGlyphs
    00002d50 (  11.33 KB)  _ZL27opendyslexic_8_italicGlyphs
    00002d50 (  11.33 KB)  _ZL26opendyslexic_14_boldGlyphs
    00002d50 (  11.33 KB)  _ZL26opendyslexic_12_boldGlyphs
    00002d50 (  11.33 KB)  _ZL26opendyslexic_10_boldGlyphs
    00002d50 (  11.33 KB)  _ZL25opendyslexic_8_boldGlyphs
    00002bca (  10.95 KB)  _ZL25notosans_8_regularBitmaps
    0000294c (  10.32 KB)  _ZL16SettingsPageHtml
    000024f0 (   9.23 KB)  _ZL23ubuntu_12_regularGlyphs
    000024f0 (   9.23 KB)  _ZL23ubuntu_10_regularGlyphs
    000024f0 (   9.23 KB)  _ZL20ubuntu_12_boldGlyphs
    000024f0 (   9.23 KB)  _ZL20ubuntu_10_boldGlyphs
    00001b4c (   6.82 KB)  _ZL12fr_trie_data
    000012e8 (   4.73 KB)  ciphersuite_definitions
    00000c8d (   3.14 KB)  _ZL12HomePageHtml
    00000708 (   1.76 KB)  _ZL7Logo120
    00000708 (   1.76 KB)  _ZL7Logo120
    00000688 (   1.63 KB)  esp_err_msg_table
    00000613 (   1.52 KB)  _ZL12it_trie_data
    00000500 (   1.25 KB)  namingBitmap
    00000450 (   1.08 KB)  _ZN4mime9mimeTableE
    00000404 (   1.00 KB)  _ZNSt8__detail12__prime_listE
    00000340 (   0.81 KB)  ciphersuite_preference
    00000300 (   0.75 KB)  _ZL31bookerly_18_bolditalicIntervals
    00000300 (   0.75 KB)  _ZL31bookerly_16_bolditalicIntervals
    00000300 (   0.75 KB)  _ZL31bookerly_14_bolditalicIntervals
    00000300 (   0.75 KB)  _ZL31bookerly_12_bolditalicIntervals
    00000300 (   0.75 KB)  _ZL28bookerly_18_regularIntervals
    00000300 (   0.75 KB)  _ZL28bookerly_16_regularIntervals
    00000300 (   0.75 KB)  _ZL28bookerly_14_regularIntervals
    00000300 (   0.75 KB)  _ZL28bookerly_12_regularIntervals
    00000300 (   0.75 KB)  _ZL27bookerly_18_italicIntervals
    00000300 (   0.75 KB)  _ZL27bookerly_16_italicIntervals
    00000300 (   0.75 KB)  _ZL27bookerly_14_italicIntervals
    00000300 (   0.75 KB)  _ZL27bookerly_12_italicIntervals
    00000300 (   0.75 KB)  _ZL25bookerly_18_boldIntervals
    00000300 (   0.75 KB)  _ZL25bookerly_16_boldIntervals
    00000300 (   0.75 KB)  _ZL25bookerly_14_boldIntervals
    00000300 (   0.75 KB)  _ZL25bookerly_12_boldIntervals
    000002a0 (   0.66 KB)  small_prime
    000002a0 (   0.66 KB)  _ZL35opendyslexic_14_bolditalicIntervals
    000002a0 (   0.66 KB)  _ZL35opendyslexic_12_bolditalicIntervals
    000002a0 (   0.66 KB)  _ZL35opendyslexic_10_bolditalicIntervals
    000002a0 (   0.66 KB)  _ZL34opendyslexic_8_bolditalicIntervals
    000002a0 (   0.66 KB)  _ZL32opendyslexic_14_regularIntervals
    000002a0 (   0.66 KB)  _ZL32opendyslexic_12_regularIntervals
    000002a0 (   0.66 KB)  _ZL32opendyslexic_10_regularIntervals
    000002a0 (   0.66 KB)  _ZL31opendyslexic_8_regularIntervals
    000002a0 (   0.66 KB)  _ZL31opendyslexic_14_italicIntervals
    000002a0 (   0.66 KB)  _ZL31opendyslexic_12_italicIntervals
    000002a0 (   0.66 KB)  _ZL31opendyslexic_10_italicIntervals
    000002a0 (   0.66 KB)  _ZL30opendyslexic_8_italicIntervals
    000002a0 (   0.66 KB)  _ZL29opendyslexic_14_boldIntervals
    000002a0 (   0.66 KB)  _ZL29opendyslexic_12_boldIntervals
    000002a0 (   0.66 KB)  _ZL29opendyslexic_10_boldIntervals
    000002a0 (   0.66 KB)  _ZL28opendyslexic_8_boldIntervals
    00000280 (   0.62 KB)  K
    000001c8 (   0.45 KB)  _ZL26ubuntu_12_regularIntervals
    000001c8 (   0.45 KB)  _ZL26ubuntu_10_regularIntervals
    000001c8 (   0.45 KB)  _ZL23ubuntu_12_boldIntervals
    000001c8 (   0.45 KB)  _ZL23ubuntu_10_boldIntervals
    0000016c (   0.36 KB)  utf8_encoding_ns
    0000016c (   0.36 KB)  utf8_encoding
    0000016c (   0.36 KB)  little2_encoding_ns
    0000016c (   0.36 KB)  little2_encoding
    0000016c (   0.36 KB)  latin1_encoding_ns
    0000016c (   0.36 KB)  latin1_encoding
    0000016c (   0.36 KB)  internal_utf8_encoding_ns
    0000016c (   0.36 KB)  internal_utf8_encoding
    0000016c (   0.36 KB)  big2_encoding_ns
    0000016c (   0.36 KB)  big2_encoding
    0000016c (   0.36 KB)  ascii_encoding_ns
    0000016c (   0.36 KB)  ascii_encoding
    0000016c (   0.36 KB)  __default_global_locale
    00000150 (   0.33 KB)  oid_sig_alg
    00000150 (   0.33 KB)  mbedtls_cipher_definitions
    00000140 (   0.31 KB)  adc_error_coef_atten
    00000140 (   0.31 KB)  NUM_ERROR_CORRECTION_CODEWORDS
    0000012c (   0.29 KB)  _ZL11lookupTable
    00000101 (   0.25 KB)  _ctype_
    00000100 (   0.25 KB)  unhex
    00000100 (   0.25 KB)  tokens
    00000100 (   0.25 KB)  nmstrtPages
    00000100 (   0.25 KB)  namePages
    00000100 (   0.25 KB)  __chclass
    00000100 (   0.25 KB)  FSb4
    00000100 (   0.25 KB)  FSb3
    00000100 (   0.25 KB)  FSb2
    00000100 (   0.25 KB)  FSb
    000000fc (   0.25 KB)  _C_time_locale
    000000f0 (   0.23 KB)  oid_ecp_grp
    000000d4 (   0.21 KB)  _ZL8mapTable
    000000c8 (   0.20 KB)  __mprec_tens
    000000c0 (   0.19 KB)  dh_group5_prime
    000000c0 (   0.19 KB)  dh_group5_order
    000000b4 (   0.18 KB)  _ZL31notosans_18_bolditalicIntervals
    000000b4 (   0.18 KB)  _ZL31notosans_16_bolditalicIntervals
    000000b4 (   0.18 KB)  _ZL31notosans_14_bolditalicIntervals
    000000b4 (   0.18 KB)  _ZL31notosans_12_bolditalicIntervals
    000000b4 (   0.18 KB)  _ZL28notosans_18_regularIntervals

============================================
Top 40 largest symbols in section: .flash.text
Total section size: 1431082 bytes (1397.54 KB)
============================================
    000025b8 (   9.43 KB)  http_parser_execute
    000023aa (   8.92 KB)  _vfprintf_r
    000022ce (   8.70 KB)  _svfprintf_r
    0000225a (   8.59 KB)  _svfwprintf_r
    00001fdc (   7.96 KB)  __ssvfscanf_r
    00001cb0 (   7.17 KB)  _Z15getSettingsListv
    00001bbc (   6.93 KB)  mbedtls_ssl_handshake_server_step
    00001ac2 (   6.69 KB)  __ssvfiscanf_r
    000018fe (   6.25 KB)  mbedtls_ssl_handshake_client_step
    000015fe (   5.50 KB)  mdns_parse_packet
    00001554 (   5.33 KB)  _vfiprintf_r
    0000146e (   5.11 KB)  _svfiprintf_r
    0000123a (   4.56 KB)  doProlog
    0000101e (   4.03 KB)  tcp_input
    0000100e (   4.01 KB)  unsignedCharToPrintable
    00000f4e (   3.83 KB)  pjpeg_decode_mcu
    00000ef6 (   3.74 KB)  nd6_input
    00000d4a (   3.32 KB)  _dtoa_r
    00000d44 (   3.32 KB)  little2_contentTok
    00000d44 (   3.32 KB)  big2_contentTok
    00000d36 (   3.30 KB)  _strtod_l
    00000d30 (   3.30 KB)  mbedtls_high_level_strerr
    00000cec (   3.23 KB)  ieee80211_sta_new_state
    00000ca6 (   3.16 KB)  tcp_receive
    00000c82 (   3.13 KB)  mbedtls_internal_sha512_process
    00000c14 (   3.02 KB)  _ZN9WebServer10_parseFormER10WiFiClient6Stringm
    00000bc0 (   2.94 KB)  qrcode_initBytes
    00000b62 (   2.85 KB)  __multf3
    00000b1c (   2.78 KB)  normal_contentTok
    00000a98 (   2.65 KB)  _ZN16ContentOpfParser12startElementEPvPKcPS2_
    00000a96 (   2.65 KB)  _ZN18JpegToBmpConverter27jpegFileToBmpStreamInternalER6FsFileR5Printiibb
    00000a82 (   2.63 KB)  _mdns_service_task
    00000a64 (   2.60 KB)  __strftime
    00000a64 (   2.60 KB)  _ZNK9BaseTheme19drawRecentBookCoverER11GfxRenderer4RectRKSt6vectorI10RecentBookSaIS4_EEiRbS9_S9_St8functionIFbvEE
    00000a60 (   2.59 KB)  __strftime
    000009cc (   2.45 KB)  _Z16start_ssl_clientP17sslclient_contextRK9IPAddressmPKciS5_bS5_S5_S5_S5_bPS5_
    000009c4 (   2.44 KB)  doContent
    0000099a (   2.40 KB)  wpa_sm_rx_eapol
    00000984 (   2.38 KB)  __divtf3
    00000974 (   2.36 KB)  _ZNSt6locale5_ImplC2Ej

============================================
Top 10 largest symbols in section: .iram0.text
Total section size: 57640 bytes (56.29 KB)
============================================
    00000668 (   1.60 KB)  rmt_driver_isr_default
    00000504 (   1.25 KB)  tlsf_realloc
    00000458 (   1.09 KB)  tlsf_free
    000003e8 (   0.98 KB)  tlsf_malloc
    000003d0 (   0.95 KB)  esp_sleep_start
    00000340 (   0.81 KB)  rtc_sleep_init
    00000218 (   0.52 KB)  spi_flash_mmap_pages
    000001fc (   0.50 KB)  esp_flash_erase_region
    000001fc (   0.50 KB)  call_start_cpu0
    000001de (   0.47 KB)  wdt_hal_init
```

---

### 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**
2026-02-19 10:35:07 -05:00
Bram Schulting
a8f0d63693 feat: Tweak Lyra popup UI (#768)
I want to preface this PR by stating that the proposed changes are
subjective to people's opinions. The following is just my suggestion,
but I'm of course open to changes.

The popups in the currently implemented version of the Lyra theme feel a
bit out of place. This PR suggests an updated version which looks a bit
more polished and in line with the rest of the theme.

I've also taken the liberty to remove the ellipsis behind the text of
the popups, as they made the popup feel a bit off balance (example
below).

With the applied changes, popups will look like this.

![IMG_0012](https://github.com/user-attachments/assets/a954de12-97b8-4102-be17-a702c0fe7d1e)

The vertical position is (more or less) aligned to be in line with the
sleep button. I'm aware the popup is used for other purposes aside from
the sleep message, but this still felt like a good place. It's also a
place where your eyes naturally 'rest'.

The popup has a small 2px white outline, neatly separating it from
whatever is behind it.

Initially I started out worked off the Figma design for the Lyra theme,
which [moves the
popups](https://www.figma.com/design/UhxoV4DgUnfrDQgMPPTXog/Lyra-Theme?node-id=2011-19296&t=Ppj6B2MrFRfUo9YX-1)
to the bottom of the screen. To me, this results in popups that are much
too easy to miss:

![IMG_0006](https://github.com/user-attachments/assets/b8ce3632-94a9-494e-8256-d87a6ee60cdf)

After this, I tried moving the popup back up (to the position of the
sleep button), but to me it still kinda disappeared into the text of the
book:

![IMG_0008](https://github.com/user-attachments/assets/4b05df7c-932e-432b-9c10-130da3109050)

Inverting the colors of the popup made things stand out the perfect
amount in my opinion. The white outline separates the popup from what is
behind it.

![IMG_0011](https://github.com/user-attachments/assets/77b1e8cc-0a57-4f4b-9abb-a9d10988d919)

This looked much better to me. The only thing that felt a bit off to me,
was the balance due to the ellipsis at the end of the popup text. Also,
"Entering Sleep..." felt a bit.. engineer-y. I felt something a bit more
'conversational' makes at all feel a bit more human-centric. But I'm no
copywriter, and English is not even my native language. So feel free to
chip in!

After tweaking that, I ended up with the final result:

_(Same picture as the first one shown in this PR)_

![IMG_0012](https://github.com/user-attachments/assets/a954de12-97b8-4102-be17-a702c0fe7d1e)

* Figma design:
https://www.figma.com/design/UhxoV4DgUnfrDQgMPPTXog/Lyra-Theme?node-id=2011-19296&t=Ppj6B2MrFRfUo9YX-1

---

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? _**NO**_
2026-02-19 10:34:58 -05:00
CaptainFrito
a8a89e35b8 feat: Lyra Icons (#725)
/!\ This PR depends on
https://github.com/crosspoint-reader/crosspoint-reader/pull/732 being
merged first

Also requires the
https://github.com/open-x4-epaper/community-sdk/pull/18 PR

Lyra theme icons on the home menu, in the file browser and on empty book
covers

![IMG_8023
Medium](https://github.com/user-attachments/assets/ba7c1407-94d2-4353-80ff-d5b800c6ac5b)
![IMG_8024
Medium](https://github.com/user-attachments/assets/edb59e13-b1c9-4c86-bef3-c61cc8134e64)
![IMG_7958
Medium](https://github.com/user-attachments/assets/d3079ce1-95f0-43f4-bbc7-1f747cc70203)
![IMG_8033
Medium](https://github.com/user-attachments/assets/f3e2e03b-0fa8-47b7-8717-c0b71361b7a8)

- Added a function to the open-x4-sdk renderer to draw transparent
images
- Added a scripts/convert_icon.py script to convert svg/png icons into a
C array that can be directly imported into the project. Usage:
```bash
python ./scripts/convert_icon.py 'path/to/icon.png' cover 32 32
```
This will create a components/icons/cover.h file with a C array called
CoverIcon, of size 32x32px. Lyra uses icons from
https://lucide.dev/icons with a stroke width of 2px, that can be
downloaded with any desired size on the site.

> The file browser is noticeably slower with the addition of icons, and
using an image buffer like on the home page doesn't help very much. Any
suggestions to optimize this are welcome.

---

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? _**PARTIALLY**_
The icon conversion python script was generated by Copilot as I am not a
python dev.

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-02-19 10:33:23 -05:00
CaptainFrito
724c1969b9 feat: Lyra screens (#732)
Implements Lyra theme for some more Crosspoint screens:

![IMG_7960
Medium](https://github.com/user-attachments/assets/5d97d91d-e5eb-4296-bbf4-917e142d9095)
![IMG_7961
Medium](https://github.com/user-attachments/assets/02d61964-2632-45ff-83c7-48b95882eb9c)
![IMG_7962
Medium](https://github.com/user-attachments/assets/cf42d20f-3a85-4669-b497-1cac4653fa5a)
![IMG_7963
Medium](https://github.com/user-attachments/assets/a8f59c37-db70-407c-a06d-3e40613a0f55)
![IMG_7964
Medium](https://github.com/user-attachments/assets/0fdaac72-077a-48f6-a8c5-1cd806a58937)
![IMG_7965
Medium](https://github.com/user-attachments/assets/5169f037-8ba8-4488-9a8a-06f5146ec1d9)

- A bit of refactoring for list scrolling logic

---

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? _**NO**_

---------

Co-authored-by: Dave Allie <dave@daveallie.com>
2026-02-19 10:32:36 -05:00
Dave Allie
21b81bd177 Update Ukrainian hyphenation 2026-02-19 10:25:45 -05:00
saslv
b5c48af3b2 feat: Added Ukrainian language hyphenation support (#646)
* **What is the goal of this PR?**
  Add proper hyphenation support for the Ukrainian language.

* **What changes are included?**
  - Added Ukrainian hyphenation rules/dictionary

---

Did you use AI tools to help write this code? _**NO**_
2026-02-19 10:25:32 -05:00
cottongin
426a978e44 feat: silent pre-indexing with configurable status bar indicator
Port PR #979's silent pre-indexing and add an Indexing Display setting
(Popup / Status Bar Text / Status Bar Icon) so users can choose how
indexing feedback is shown.

Silent pre-indexing runs on text-only penultimate pages when a status
bar option is selected, with a standard requestUpdate to clear the
indicator. Image pages skip silent indexing to avoid e-ink grayscale
pipeline conflicts; the normal popup handles those transitions. Direct
chapter jumps always show the original small popup regardless of setting.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 09:30:29 -05:00
cottongin
a1ac11ab51 feat: port upstream PRs #852, #965, #972, #971, #977, #975
Port 6 upstream PRs (PR #939 was already ported):

- #852: Complete HalPowerManager with RAII Lock class, WiFi check in
  setPowerSaving, skipLoopDelay overrides for ClearCache/OtaUpdate,
  and power lock in Activity render task loops
- #965: Fix paragraph formatting inside list items by tracking
  listItemUntilDepth to prevent unwanted line breaks
- #972: Micro-optimizations: std::move in insertFont, const ref for
  getDataFromBook parameter
- #971: Remove redundant hasPrintableChars pre-rendering pass from
  EpdFont, EpdFontFamily, and GfxRenderer
- #977: Skip unsupported image formats before extraction, add
  PARSE_BUFFER_SIZE constant and chapter parse timing
- #975: Fix UITheme memory leak by replacing raw pointer with
  std::unique_ptr for currentTheme

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-18 15:45:06 -05:00
cottongin
7819cf0f77 fix: correct book card highlight padding by increasing tile height
Instead of shrinking the highlight strip (which clipped author text),
increase homeCoverTileHeight from 310 to 318 for proper bottom padding.
Revert double-padding subtraction in bottomH/bottomSectionHeight.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 11:32:04 -05:00
cottongin
3d7340ca6f fix: add bottom padding to home screen book card highlight
The selection highlight had uniform padding on the top, left, and right
but none on the bottom, causing descenders in the author text to clip
past the highlight edge.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 03:53:31 -05:00
cottongin
966fbef3d1 mod: add clock settings tab, timezone support, and clock size option
Fix clock persistence bug caused by stale legacy read in settings
deserialization. Add clock size setting (Small/Medium/Large) and
timezone selection with North American presets plus custom UTC offset.
Move all clock-related settings into a dedicated Clock tab, rename
"Home Screen Clock" to "Clock", and move minute-change detection to
main loop so the header clock updates on every screen.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 03:46:06 -05:00
cottongin
38a87298f3 mod: fix clock bugs, add NTP auto-sync, show clock in all headers
- Fix SetTimeActivity immediately dismissing by changing wasReleased to
  wasPressed for all button inputs (matching other subactivities)
- Extract NTP sync into shared TimeSync utility (startNtpSync,
  waitForNtpSync, stopNtpSync) and trigger non-blocking NTP sync on
  every WiFi connection
- Move clock rendering into drawHeader (BaseTheme + LyraTheme) so it
  appears on all screens with a header, positioned symmetrically with
  the battery icon (12px margin, same Y offset, SMALL_FONT_ID)
- Add per-minute auto-refresh on home screen so clock updates without
  button press
- Add RTC time debug log on boot to verify time persistence across
  deep sleep

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 02:13:10 -05:00
Uri Tauber
ab4540b26f Fix dangling pointer 2026-02-17 01:31:51 -05:00
cottongin
7e15c9835f feat: long-press Confirm to open Table of Contents directly
Skip the reader menu when long-pressing Confirm (700ms) to jump
straight to the chapter selection screen. Short press behavior
(opening the menu) is unchanged. Extracts shared openChapterSelection()
helper to eliminate duplicated construction across three call sites.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 01:22:49 -05:00
cottongin
7b3de29c59 mod: improve home screen with adaptive layouts, clock, and set time
- 1-book view: horizontal layout with cover left, title/author right
- 2-3 book view: fix cover stretching by preserving aspect ratio
- 0-book view: show "Choose something to read" placeholder
- Selection highlight now fully contains title and author text
- Add optional clock display in home screen header (AM/PM or 24H)
- Add "Home Screen Clock" setting under Display
- Add "Set Time" activity for manual clock setting via Settings
- Increase homeCoverTileHeight to 310 for title/author breathing room

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 00:46:05 -05:00
cottongin
1d7971ae60 mod: overhaul reader menu with long-press actions and quick toggles
Consolidate dictionary items: remove "Lookup Word History" and
"Delete Dictionary Cache" from the menu. Long-press on "Lookup Word"
opens history; delete-dict-cache is now a sentinel entry at the bottom
of the history list.

Replace "Reading Orientation" with "Toggle Portrait/Landscape" that
toggles between two configurable preferred orientations (new settings:
Preferred Portrait, Preferred Landscape). Long-press opens a manual
4-option orientation sub-menu.

Add "Toggle Font Size" menu item that cycles through font sizes and
applies on menu exit (with section re-layout).

Rename "Letterbox Fill" to "Override Letterbox Fill" and
"Sync Progress" to "Sync Reading Progress" in reader menu.

All long-press flows use ignoreNextConfirmRelease to prevent the
button release from triggering actions on the subsequent screen.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 18:45:46 -05:00
cottongin
61fb11cae3 feat: Add PNG cover image support for EPUB books (#827)
Cherry-pick upstream PR #827 with conflict resolution for mod/master:

- Add PngToBmpConverter library for PNG cover → BMP conversion
- Add PNG thumbnail generation in generateThumbBmp()
- Fix generateCoverBmp() PNG block to use effectiveCoverImageHref
  (consistent with mod's fallback cover candidate probing)
- Add .png to getCoverCandidates() extensions
- Use LOG_ERR macro in ImageToFramebufferDecoder (mod standard)
- Upstream image converter refinements (ImageBlock, PixelCache,
  JpegToFramebufferConverter, PngToFramebufferConverter)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 17:04:33 -05:00
Егор Мартынов
424e332c75 chore: improve Russian language support (#926)
## Summary

This PR includes vocabulary and grammar fixes for Russian translation,
originally made as review comments
[here](https://github.com/crosspoint-reader/crosspoint-reader/pull/728).

---

### 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? _**NO**_
2026-02-16 17:00:43 -05:00
Zach Nelson
f21720dc79 perf: Skip constructing unnecessary std::string (#932)
## Summary

**What is the goal of this PR?**

Skip constructing a `std::string` just to get the underlying `c_str()`
buffer, when a string literal gives the same end result.

---

### 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? _**NO**_
2026-02-16 17:00:32 -05:00
cottongin
a9f5149444 mod: remove duplicate I18n.h include in HomeActivity.cpp
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 13:26:17 -05:00
cottongin
0222cbf19b mod: convert remaining manual render locks to RAII RenderLock
Replace xSemaphoreTake/Give(renderingMutex) with scoped
RenderLock in EpubReaderActivity popup rendering (bookmark
added/removed, dictionary cache deleted).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 13:24:48 -05:00
cottongin
02f2474e3b mod: adapt mod activities to #774 render() pattern
Migrate 5 mod Activity subclasses from old polling-based
display task pattern to the upstream render() super-class
pattern with freeRTOS notification:

- EpubReaderBookmarkSelectionActivity
- DictionaryWordSelectActivity
- DictionarySuggestionsActivity
- DictionaryDefinitionActivity
- LookedUpWordsActivity

Changes: remove own TaskHandle/SemaphoreHandle/updateRequired,
use requestUpdate() + render(RenderLock&&) override, fix
potential deadlocks around enterNewActivity() calls.

Also fix stale conflict marker in EpubReaderMenuActivity.h.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 13:22:40 -05:00
pablohc
f06e3a0a82 fix: align battery icon based on context (UI / Reader) (#796)
Issues solved: #729 and #739

## Summary

* **What is the goal of this PR?**
Currently, the battery icon and charge percentage were aligned to the
left even for the UI, where they were positioned on the right side of
the screen. This meant that when changing values of different numbers of
digits, the battery would shift, creating a block of icons and text that
was illegible.

* **What changes are included?**
- Add drawBatteryUi() method for right-aligned battery display in UI
headers
- Keep drawBattery() for left-aligned display in reader mode
- Extract drawBatteryIcon() helper to reduce code duplication
- Battery icon now stays fixed at right edge regardless of percentage
digits
- Text adjusts to left of icon in UI mode, to right of icon in reader
mode

## Additional Context

* Add any other information that might be helpful for the reviewer 
* This fix applies to both themes (Base and Lyra).

---

### 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 >**_
2026-02-16 13:14:44 -05:00
Andrew Brandt
a585f219f4 docs: add translators doc (#792)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
Add a translators document for us to track which individuals have
volunteered to contribute in which languages.

* **What changes are included?**
Add a new document that includes who the translators are and what
languages they have volunteered for.

## Additional Context

This is primarily to keep a handle on the volunteers coming into the
repo. This will serve as a master list of all volunteer translators.

---

### 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? **NO**

---------

Signed-off-by: Andrew Brandt <brandt.andrew89@gmail.com>
2026-02-16 13:14:30 -05:00
Lev Roland-Kalb
df6cc637ec docs: Updating webserver.md documentation to align with 1.0.0 features (#906)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)

Updating webserver.md documentation to align with 1.0.0 features

* **What changes are included?**

Added documentation for the following new features (including replacing
screenshots)

- file renaming
- file moving
- support for uploading any file type
- batch uploads

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).

Nothing comes to mind

---

### 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? _**NO**_
2026-02-16 13:13:05 -05:00
Lev Roland-Kalb
4cfe155488 fix: Removed white boxes extending passed the bounds of the empty button icon when hint text is blank/null (#884)
## Summary

* **What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)

Empty Button Icons (I.E. Back button in the home menu) were still
rendering the full sized white rectangles going passed the boarders of
the little button nub. This was not visible on the home screen due to
the white background, but it does cause issues if we ever want to have
bmp files displayed while buttons are visible or implement a dark mode.

* **What changes are included?**

Made it so that when a button hint text is empty string or null the
displayed mini button nub does not have a white rectangle extending
passed the bounds of the mini button nub

## Additional Context

* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks,
  specific areas to focus on).

Having that extended rectangle was likely never noticed due to the only
space where that feature is used being the main menu where the
background is completely white. I am working on some new features that
would have an image displayed while there are button hints and noticed
this issue while implementing that.

One other note is that this only affects the Lyra Theme

---

### 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**_
2026-02-16 13:12:50 -05:00
Uri Tauber
f1966f1e26 feat: User-Interface I18n System (#728)
**What is the goal of this PR?**
This PR introduces Internationalization (i18n) support, enabling users
to switch the UI language dynamically.

**What changes are included?**
- Core Logic: Added I18n class (`lib/I18n/I18n.h/cpp`) to manage
language state and string retrieval.

- Data Structures:

- `lib/I18n/I18nStrings.h/cpp`: Static string arrays for each supported
language.
  - `lib/I18n/I18nKeys.h`: Enum definitions for type-safe string access.
  - `lib/I18n/translations.csv`: single source of truth.

- Documentation: Added `docs/i18n.md` detailing the workflow for
developers and translators.

- New Settings activity:
`src/activities/settings/LanguageSelectActivity.h/cpp`

This implementation (building on concepts from #505) prioritizes
performance and memory efficiency.

The core approach is to store all localized strings for each language in
dedicated arrays and access them via enums. This provides O(1) access
with zero runtime overhead, and avoids the heap allocations, hashing,
and collision handling required by `std::map` or `std::unordered_map`.

The main trade-off is that enums and string arrays must remain perfectly
synchronized—any mismatch would result in incorrect strings being
displayed in the UI.

To eliminate this risk, I added a Python script that automatically
generates `I18nStrings.h/.cpp` and `I18nKeys.h` from a CSV file, which
will serve as the single source of truth for all translations. The full
design and workflow are documented in `docs/i18n.md`.

- [x] Python script `generate_i18n.py` to auto-generate C++ files from
CSV
- [x] Populate translations.csv with initial translations.

Currently available translations: English, Español, Français, Deutsch,
Čeština, Português (Brasil), Русский, Svenska.
Thanks, community!

**Status:** EDIT: ready to be merged.

As a proof of concept, the SPANISH strings currently mirror the English
ones, but are fully uppercased.

---

Did you use AI tools to help write this code? _**< PARTIALLY >**_
I used AI for the black work of replacing strings with I18n references
across the project, and for generating the documentation. EDIT: also
some help with merging changes from master.

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: yeyeto2788 <juanernestobiondi@gmail.com>
2026-02-16 13:12:29 -05:00
Xuan-Son Nguyen
ebcd3a8b94 fix: use RAII render lock everywhere (#916)
Follow-up to
https://github.com/crosspoint-reader/crosspoint-reader/pull/774

---

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? **NO**

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Refactor**
* Modernized internal synchronization mechanisms across multiple
components to improve code reliability and maintainability. All
functionality remains unchanged.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-16 13:03:50 -05:00
Xuan-Son Nguyen
ed8a0feac1 refactor: move render() to Activity super class, use freeRTOS notification (#774)
Currently, each activity has to manage their own `displayTaskLoop` which
adds redundant boilerplate code. The loop is a wait loop which is also
not the best practice, as the `updateRequested` boolean is not protected
by a mutex.

In this PR:
- Move `displayTaskLoop` to the super `Activity` class
- Replace `updateRequested` with freeRTOS's [direct to task
notification](https://www.freertos.org/Documentation/02-Kernel/02-Kernel-features/03-Direct-to-task-notifications/01-Task-notifications)
- For `ActivityWithSubactivity`, whenever a sub-activity is present, the
parent's `render()` automatically goes inactive

With this change, activities now only need to expose `render()`
function, and anywhere in the code base can call `requestUpdate()` to
request a new rendering pass.

In theory, this change may also make the battery life a bit better,
since one wait loop is removed. Although the equipment in my home lab
wasn't been able to verify it (the electric current is too noisy and
small). Would appreciate if anyone has any insights on this subject.

Update: I managed to hack [a small piece of
code](https://github.com/ngxson/crosspoint-reader/tree/xsn/measure_cpu_usage)
that allow tracking CPU idle time.

The CPU load does decrease a bit (1.47% down to 1.39%), which make
sense, because the display task is now sleeping most of the time unless
notified. This should translate to a slightly increase in battery life
in the long run.

```
PR:
[40012] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes
[40012] [IDLE] Idle time: 98.61% (CPU load: 1.39%)
[50017] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes
[50017] [IDLE] Idle time: 98.61% (CPU load: 1.39%)
[60022] [MEM] Free: 185856 bytes, Total: 231004 bytes, Min Free: 123316 bytes
[60022] [IDLE] Idle time: 98.61% (CPU load: 1.39%)

master:
[20012] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[20012] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
[30017] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[30017] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
[40022] [MEM] Free: 195016 bytes, Total: 231532 bytes, Min Free: 132460 bytes
[40022] [IDLE] Idle time: 98.53% (CPU load: 1.47%)
```

---

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? **NO**

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Refactor**
* Streamlined rendering architecture by consolidating update mechanisms
across all activities, improving efficiency and consistency.
* Modernized synchronization patterns for display updates to ensure
reliable, conflict-free rendering.

* **Bug Fixes**
* Enhanced rendering stability through improved locking mechanisms and
explicit update requests.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: znelson <znelson@users.noreply.github.com>
2026-02-16 13:01:42 -05:00
jpirnay
12cc7de49e fix: Add miniz directive to get rid of compilation warning (#858)
## Summary

* I am getting miniz warning during compilation: "Using fopen, ftello,
fseeko, stat() etc. path for file I/O - this path may not support large
files."
* Disable the io module from miniz as it is not used and get rid of the
warning

## Additional Context

* the ZipFile.cpp implementation only uses tinfl_decompressor,
tinfl_init(), and tinfl_decompress() (low-level API) and does all ZIP
file parsing manually using SD card file I/O
* it never uses miniz's high-level file functions like
mz_zip_reader_init_file()
* so we can disable Miniz io-stack be setting MINIZ_NO_STDIO to 1

### 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? partially, let claude
inspect the codebase
2026-02-16 12:43:25 -05:00
jpirnay
f622e87c10 fix: Correct multiple author display (#856)
## Summary

* If an EPUB has:
```
<dc:creator>J.R.R. Tolkien</dc:creator>
<dc:creator>Christopher Tolkien</dc:creator>
```
the current result for epub.author would provide : "J.R.R.
TolkienChristopher Tolkien" (no separator!)
* The fix will seperate multiple authors: "J.R.R. Tolkien, Christopher
Tolkien"

## Additional Context

* Simple fix in ContentOpfParser - I am not seeing any dependence on the
wrong concatenated result.

---

### 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? NO
2026-02-16 12:43:13 -05:00
Dave Allie
24c1df0308 docs: Include dictionary as in-scope (#917)
## Summary

* Include dictionary as in-scope

## Additional Context

* Discussion in
https://github.com/crosspoint-reader/crosspoint-reader/discussions/878

---

### 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? No
2026-02-16 12:43:02 -05:00
ThatCrispyToast
6cc68e828a fix: add distro agnostic shebang and clang-format check to clang-format-fix (#840)
## Summary

**What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)

Minor development tooling fix for nonstandard environments (NixOS,
FreeBSD, Guix, etc.)

**What changes are included?**

- environment relative shebang in `clang-format-fix`
- clang-format check in `clang-format-fix`
---

### 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? _**NO**_
2026-02-16 12:42:47 -05:00
jpirnay
6097ee03df fix: Auto calculate the settings size on serialization (#832)
* The constant SETTINGS_CONST was hardcoded and needed to be updated
whenever an additional setting was added
* This is no longer necessary as the settings size will be determined
automatically on settings persistence

* New settings need to be added (as previously) in saveToFile - that's
it

---

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: Xuan Son Nguyen <son@huggingface.co>
2026-02-16 12:42:35 -05:00
Xuan-Son Nguyen
d11ad45e59 perf: apply (micro) optimization on SerializedHyphenationPatterns (#689)
This PR applies a micro optimization on `SerializedHyphenationPatterns`,
which allow reading `rootOffset` directly without having to parse then
cache it.

It should not affect storage space since no new bytes are added.

This also gets rid of the linear cache search whenever
`liangBreakIndexes` is called. In theory, the performance should be
improved a bit, although it may be too small to be noticeable in
practice.

master branch:

```
english: 99.1023%
french: 100%
german: 97.7289%
russian: 97.2167%
spanish: 99.0236%
```

This PR:

```
english: 99.1023%
french: 100%
german: 97.7289%
russian: 97.2167%
spanish: 99.0236%
```

---

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? PARTIALLY - mostly IDE
tab-autocompletions
2026-02-16 12:39:23 -05:00
cottongin
b965ce9fb7 fix: Port upstream cover extraction fallback and outline improvements
Port PR #838 (epub cover fallback logic) and PR #907 (cover outlines):

- Add fallback cover filename probing when EPUB metadata lacks cover info
- Case-insensitive extension checking for cover images
- Detect and re-generate corrupt/empty thumbnail BMPs
- Always draw outline rect on cover tiles for legibility (PR #907)
- Upgrade Storage.exists() checks to Epub::isValidThumbnailBmp()
- Fallback chain: Real Cover → PlaceholderCoverGenerator → X-pattern marker
- Add epub.load retry logic (cache-only first, then full build)
- Adapt upstream Serial.printf calls to LOG_DBG/LOG_ERR macros

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 01:20:27 -05:00
cottongin
744d6160e8 Merge branch 'master' into mod/master-img
Merge upstream perf: Improve large CSS files handling (#779)

Conflicts resolved:
- Section.cpp: Combined mod's image support variables with master's
  CSS parser loading pattern
- CssParser.cpp: Accepted master's streaming parser rewrite, ported
  mod's width property handler into parseDeclarationIntoStyle()

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-15 20:36:48 -05:00