Commit Graph
71 Commits
Author SHA1 Message Date
dtourolle f18cec2da8 fix(layout): honour horizontal padding and page origin (S2)
paragraph_layouter placed lines at page.border_size while sizing them to
available_width, which subtracts both paddings. Text therefore started flush
against the left border and the entire padding budget accumulated on the right,
so lines broke well short of the right border.

Page now describes its content box directly - content_origin, content_rect and
remaining_height - and the layouters use it instead of each recomputing the
geometry from border_size. The four block layouters had all been computing
remaining space as size[1] - y_offset - border_size, subtracting the border but
not the bottom padding, so every block type could be placed into the bottom
padding; remaining_height fixes that too.

Page also gains an origin, defaulting to (0, 0). That is inert for a top-level
page but lets a page be positioned inside another surface, which table cells
need in order to be laid out by the normal engine.

Golden images regenerated: content now sits inside the padding on all sides.
2026-08-06 21:11:28 +02:00
dtourolle a57da8011e fix(ereader): keep resume position when a block spans a page (S11)
render_page_forward discarded new_pos on the failure path, but a block that
only partially fitted has still advanced the position: paragraph_layouter
reports the word it stopped at, and _layout_paragraph_on_page packs it into
new_pos. Dropping it told the caller no progress was made, so navigation
dead-ended on any paragraph larger than a single page - the reader saw "end of
document" mid-book.

A 2877-word paragraph at 800x600 rendered 26 lines and reported the start
position back; it now paginates across 12 pages.

Also guard the navigation loop: EreaderManager.next_page treats no-progress as
end-of-document, which is only correct at the actual end. Anywhere else it now
logs the offending block index and skips that block, so a future layout bug
costs one block rather than the rest of the book.
2026-08-06 21:06:29 +02:00
dtourolleandClaude Opus 5 e000068384 Cache word widths and glyph bitmaps to cut page render time ~3.5x
Rendering a page re-measured and re-rasterised the same words constantly: at
1404x1872 a page issued ~2800 textlength calls and ~2500 draw.text calls for
fewer than 1000 distinct (font, string) pairs. Profiling a page turn showed
FreeType glyph rendering at 57% of total time and width measurement at 38% of
layout.

Both are now cached. Measured on Crime and Punishment at 1404x1872, one page:

    layout  35ms -> 19ms
    render  84ms -> 41ms
    total  120ms -> 60ms

Eviction ranks by use count rather than recency. Word frequency in prose is
Zipfian and stationary, so the words worth keeping are the ones used most, and
unlike recency this lets a document's own frequencies be seeded up front --
see prewarm_caches(). Two details keep the policy from costing more than it
saves, since get() runs once per word drawn:

  - counting is O(1) with no reordering, because structures that reorder on
    every hit measured 3-5ms/page slower than the hit rate they bought;
  - eviction samples 8 entries and drops the least used of those, rather than
    maintaining a global order.

Aging (halving all counts periodically) is on by default. Without it a font
size change drove the hit rate to 0% on a real access trace: every key was new
and the previous size's entries held counts nothing could beat.

Both caches are bounded, since the glyph bitmaps reach ~19MB over a long
session and the target is a 512MB Pi Zero 2. Defaults are 4MB of bitmaps and
8192 widths; configure_text_caches() tunes them. Cache size barely affects
speed (2MB is within 13% of unbounded) because a miss costs only one ~44us
rasterisation, so the bound can be set for memory, not throughput.

EreaderLayoutManager.prewarm_caches() counts the book's word frequencies and
preloads the most common ones, seeding each with its document frequency. This
moves that rasterisation to open time and cut misses by 27%, for ~15% faster
page turns at a one-off ~300ms cost. It is opt-in; nothing calls it yet.

Rendering is no longer bit-identical. PIL positions text at sub-pixel offsets,
so the cache buckets that phase, defaulting to 2 buckets per axis. Total ink
per page is unchanged and the mean pixel difference is 3.6/255 -- a fifth of
one step of a 16-level e-ink panel. subpixel_steps=4 halves that if wanted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 20:49:32 +02:00
dtourolle 3bcd1bffb5 Tables now use ""dynamic page" allowing the contents to be anything that can be rendered ion a page.
Python CI / test (3.10) (push) Successful in 2m22s
Python CI / test (3.12) (push) Successful in 2m13s
Python CI / test (3.13) (push) Successful in 2m9s
2025-11-11 18:10:47 +01:00
dtourolle 303179865d tests for author names and metadata extraction
Python CI / test (3.10) (push) Successful in 2m16s
Python CI / test (3.12) (push) Successful in 2m7s
Python CI / test (3.13) (push) Successful in 2m2s
2025-11-10 13:54:36 +01:00
dtourolle fb52178cc6 fix for regresssion in fw/bw navigation
Python CI / test (3.10) (push) Successful in 2m15s
Python CI / test (3.12) (push) Successful in 2m7s
Python CI / test (3.13) (push) Successful in 2m0s
2025-11-10 13:25:04 +01:00
dtourolle a8e459bce5 fixed issue with cover and image rendering
Python CI / test (3.10) (push) Successful in 2m10s
Python CI / test (3.12) (push) Successful in 2m3s
Python CI / test (3.13) (push) Successful in 1m57s
2025-11-10 13:06:21 +01:00
dtourolle 9fb6792e10 fix missing images in paras
Python CI / test (3.10) (push) Successful in 2m6s
Python CI / test (3.12) (push) Successful in 1m58s
Python CI / test (3.13) (push) Successful in 1m51s
2025-11-09 22:25:23 +01:00
dtourolle 12ebddaa79 more examples 2025-11-09 21:40:50 +01:00
dtourolle 50b9aa5431 fixed issue with bounding box height being wrong
Python CI / test (3.10) (push) Has been cancelled
Python CI / test (3.12) (push) Has been cancelled
Python CI / test (3.13) (push) Has been cancelled
2025-11-09 17:10:50 +01:00
dtourolle 56c2c21021 fix backwards rendering
Python CI / test (3.10) (push) Successful in 7m36s
Python CI / test (3.12) (push) Successful in 7m19s
Python CI / test (3.13) (push) Successful in 7m5s
2025-11-09 15:56:00 +01:00
dtourolle 10612fefae undoing more autoflake8 damage
Python CI / test (push) Failing after 43s
2025-11-09 00:11:48 +01:00
dtourolle ce7293824e fixing unterminated fsting
Python CI / test (push) Failing after 46s
2025-11-09 00:09:04 +01:00
dtourolle 781a9b6c08 auto flake and corrections 2025-11-08 23:46:15 +01:00
dtourolle 1ea870eef5 yet more tests 2025-11-08 19:52:19 +01:00
dtourolle 00314c9b4f ADDITIOANL TEST
Python CI / test (push) Successful in 6m49s
2025-11-08 19:39:10 +01:00
dtourolle f8baf155e9 ereader manager tests 2025-11-08 12:59:57 +01:00
dtourolle b65c35d96d Add missing tests
Python CI / test (push) Successful in 6m40s
2025-11-08 12:43:39 +01:00
dtourolle 5c0b22569a fix tests 2025-11-08 12:42:17 +01:00
dtourolle 39622c7dd7 integration of functional elements
Python CI / test (push) Successful in 6m46s
2025-11-08 10:17:01 +01:00
dtourolle ea93681aaf refactoring the mixin system
Python CI / test (push) Successful in 6m46s
2025-11-08 08:08:02 +01:00
dtourolle 49d4e551f8 Some clean up and added interactable images.
Python CI / test (push) Successful in 6m34s
2025-11-07 22:56:35 +01:00
dtourolle 15305011dc moved gestures to application
Python CI / test (push) Successful in 6m36s
2025-11-07 22:18:24 +01:00
dtourolle 496f3bf334 end2end table layouter
Python CI / test (push) Successful in 6m35s
2025-11-07 21:13:01 +01:00
dtourolle 33e2cbc363 remove application from library
Python CI / test (push) Failing after 6m29s
2025-11-07 18:48:36 +01:00
dtourolle 1bd9fdb551 more repo cleaning
Python CI / test (push) Successful in 10m0s
2025-11-06 17:40:34 +01:00
dtourolle 84229ad4da update tests
Python CI / test (push) Successful in 10m1s
2025-11-05 22:47:49 +01:00
dtourolle 37505d3dcc Fix tests for CI?
Python CI / test (push) Failing after 7m45s
2025-11-04 22:30:04 +01:00
dtourolle 25d36566d0 fix cover issue, add copyleft text 2025-11-04 20:05:34 +01:00
dtourolle 12d6fcd5db Cleaning unusued prototypes
Python CI / test (push) Failing after 6m20s
2025-11-04 19:36:34 +01:00
dtourolle 4fe5f8cf60 Added links
Python CI / test (push) Failing after 6m34s
2025-11-04 13:39:21 +01:00
dtourolle de18b1c2cc Working version for ebook rendering!! 2025-11-04 12:57:15 +01:00
dtourolle fdb3023919 fix all tests
Python CI / test (push) Failing after 7m0s
2025-10-06 22:28:48 +02:00
dtourolle 718027f3c8 Fix tests
Python CI / test (push) Failing after 5m26s
2025-09-12 21:23:56 +02:00
dtourolle 65ab46556f big update with ok rendering
Python CI / test (push) Failing after 3m55s
2025-08-27 22:22:54 +02:00
dtourolle 36281be77a simplification of fonts
Python CI / test (push) Failing after 6m1s
2025-07-12 17:49:58 +02:00
dtourolle b1c4a1c125 added document layouter
Python CI / test (push) Failing after 4m51s
2025-06-28 22:02:39 +02:00
dtourolle 56a6ec19e8 Large clean up
Python CI / test (push) Failing after 5m5s
2025-06-28 21:10:30 +02:00
dtourolle d0153c6397 Fix tests
Python CI / test (push) Successful in 5m17s
2025-06-22 19:26:40 +02:00
dtourolle ae15fe54e8 new style handling
Python CI / test (push) Successful in 5m17s
2025-06-22 13:42:15 +02:00
dtourolle edac4de5b4 use font registry rather than make each time
Python CI / test (push) Successful in 5m6s
2025-06-21 11:38:53 +02:00
dtourolle ff5f840646 Added line overflow test
Python CI / test (push) Successful in 5m16s
2025-06-21 10:59:41 +02:00
dtourolle 210358913a added tests to ensure border is respected.
Python CI / test (push) Successful in 4m50s
2025-06-08 17:29:42 +02:00
dtourolle 27d029350a fixe
Python CI / test (push) Successful in 5m7s
2025-06-08 17:24:01 +02:00
dtourolle f6ae60217f clean up 2025-06-08 17:17:09 +02:00
dtourolle a014de854e fix to use same font in CI and local tests
Python CI / test (push) Failing after 4m7s
2025-06-08 17:10:47 +02:00
dtourolle c28cd0e6ea fix for CI
Python CI / test (push) Failing after 4m6s
2025-06-08 17:03:18 +02:00
dtourolle df775ee462 view port based browser and test
Python CI / test (push) Has been cancelled
2025-06-08 17:00:41 +02:00
dtourolle 4325c983b1 Fiuxed test from older version
Python CI / test (push) Failing after 4m8s
2025-06-08 15:24:43 +02:00
dtourolle 57d1b5f75c Adsditional fix 2025-06-08 15:11:35 +02:00