ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
epub_img_tiles.h File Reference

Page a large in-EPUB image through ra8_tile_cache + a real reflow <img> loader off the streaming reader (#231). More...

#include <stddef.h>
#include <stdint.h>
#include "epub.h"
#include "jof.h"
#include "jof_produce.h"
#include "ra8_err.h"
#include "ra8_tile_cache.h"
Include dependency graph for epub_img_tiles.h:

Go to the source code of this file.

Data Structures

struct  epub_tile_source_t
 One registered atlas image (private to the binder; treat as opaque). More...
struct  epub_tile_binder_t
 Binds up to k_epub_tile_max_sources images to one tile cache. More...
struct  epub_img_loader_t
 Context for the real reflow <img> loader (epub_reflow_img_load). More...
struct  epub_atlas_store_t
 Where an on-device-produced atlas lives: sink to write, pread to read back (DIP – an SDRAM memstore and an SD file both fit). More...
struct  epub_atlas_import_cfg_t
 Import-time transcode knobs: tile geometry, budget caps, work arena and the destination store. More...

Enumerations

enum  epub_tile_limits_t : uint8_t { k_epub_tile_max_sources = 8U }
 Binder capacity limits. More...

Functions

ra8_err_t epub_tile_binder_init (epub_tile_binder_t *binder, const ra8_tile_cache_cfg_t *storage, uint8_t *scratch, uint32_t scratch_cap)
 Initialise a tile binder over caller-supplied tile-cache storage (#231).
ra8_err_t epub_tile_binder_add (epub_tile_binder_t *binder, epub_book_t *book, const char *path, uint32_t image_id)
 Register a stored in-archive JOF atlas entry under image_id (#231).
ra8_err_t epub_tile_binder_add_ext (epub_tile_binder_t *binder, jof_pread_fn pread, void *pread_ctx, uint64_t total_size, uint32_t image_id)
 Register an externally-backed JOF atlas under image_id (#231).
ra8_err_t epub_tile_binder_import (epub_tile_binder_t *binder, epub_book_t *book, const char *href, uint32_t image_id, const epub_atlas_import_cfg_t *cfg)
 Import a manifest image through the transcode producer and register it for tile paging (#231 – the open-path wiring).
ra8_err_t epub_tile_binder_info (const epub_tile_binder_t *binder, uint32_t image_id, jof_info_t *out_info)
 Report a registered image's parsed geometry (#231).
ra8_err_t epub_tile_binder_get (epub_tile_binder_t *binder, uint32_t image_id, uint16_t tile_x, uint16_t tile_y, ra8_tile_t *out_tile)
 Get (and pin) one decoded tile of a registered image (#231).
ra8_err_t epub_tile_binder_put (epub_tile_binder_t *binder, const uint8_t *pixels)
 Release one pin taken by epub_tile_binder_get() (#231).
ra8_err_t epub_tile_binder_prefetch_pan (epub_tile_binder_t *binder, uint32_t image_id, const ra8_tile_rect_t *view, ra8_tile_pan_dir_t dir, uint16_t max_tiles, uint16_t *out_warmed)
 Predictively warm the tiles one step ahead of a panning image (#341).
ra8_err_t epub_reflow_img_load (void *ctx, const char *href, uint32_t href_len, const uint8_t **out_bytes, size_t *out_len)
 Real reflow <img> byte loader off an EPUB book (#231).

Detailed Description

Page a large in-EPUB image through ra8_tile_cache + a real reflow <img> loader off the streaming reader (#231).

Tag
[Ring 4 / EPUB] {World: NS}

A full-page manga scan in an all-image EPUB inflates to tens of megabytes – too big to decode whole into the ~10 MB working set. This module supplies the #231 runtime pieces, all bounded-RAM by construction and all reading off the streaming reader (epub_open_streamed) so the whole archive is never resident:

  1. Tile binder (epub_tile_binder_*): pages JOF tile atlases (jof.h – the display-native band-tile format shared with the longstrip scroll #289 and the #290 codec policy) through ::ra8_tile_cache, decode-on-demand keyed by (image_id, tile_x, tile_y). An atlas backs onto either a stored archive entry (epub_tile_binder_add(), host-baked books) or any external pread seam (epub_tile_binder_add_ext() – an SDRAM memstore or SD file holding an atlas produced on device). Resident decoded pixels stay bounded by the cache's cell budget regardless of the image size, with no downscaling.
  2. Import-time transcode (epub_tile_binder_import()): the #231 producer wired to the open path. Resolves a manifest href, streams the encoded JPEG/PNG (or, with a webp_work arena, WebP) through jof_produce() into a caller-supplied atlas store, and registers the result – after which a page larger than SDRAM at native resolution renders full-res via decode-on-demand tiles. Every source codec converges on the one JOF container (#290). An entry that already IS a stored JOF atlas registers in place with no transcode.
  3. Reflow <img> loader (epub_reflow_img_load): the real reflow_image_loader_fn – resolves an <img src> href to an EPUB manifest resource and returns its encoded bytes in a caller-owned bounded scratch. Images that fit the scratch (covers, figures) render exactly as before; an image larger than the scratch is reported unavailable rather than blowing the budget (the tile binder is the path for those).
See also
jof.h The JOF atlas format + reader.
jof_produce.h The import-time transcode producer.
Since
0.1.0

Definition in file epub_img_tiles.h.

Enumeration Type Documentation

◆ epub_tile_limits_t

enum epub_tile_limits_t : uint8_t

Binder capacity limits.

k_epub_tile_max_sources is how many distinct images one binder can serve from a single cache.

Enumerator
k_epub_tile_max_sources 

Distinct images per binder.

Definition at line 73 of file epub_img_tiles.h.

Function Documentation

◆ epub_reflow_img_load()

ra8_err_t epub_reflow_img_load ( void * ctx,
const char * href,
uint32_t href_len,
const uint8_t ** out_bytes,
size_t * out_len )
nodiscard

Real reflow <img> byte loader off an EPUB book (#231).

A reflow_image_loader_fn (matching signature) that resolves href to an EPUB manifest resource and returns its encoded bytes in the bound scratch (epub_get_resource, which streams from the reader on demand). The scratch capacity is the RAM ceiling: an image that does not fit is reported unavailable (k_ra8_err_no_mem), which the reflow engine treats as "skip / placeholder" rather than exceeding the budget. Wire it into the engine with reflow_set_image_loader(), passing a epub_img_loader_t as ctx.

Parameters
[in]ctxA epub_img_loader_t* (book + scratch).
[in]href<img src> string (not NUL-terminated).
[in]href_lenLength of href, bytes.
[out]out_bytesReceives a pointer to the encoded bytes (into the scratch).
[out]out_lenReceives the encoded byte count.
Returns
ra8_err_t
Return values
k_ra8_okResource resolved into the scratch.
k_ra8_err_null_ptrctx, href, out_bytes, or out_len is NULL.
k_ra8_err_invalid_arghref_len is 0 or exceeds the path buffer.
k_ra8_err_no_memThe resource does not fit the bound scratch.
otherPropagated from epub_get_resource.
Precondition
ctx binds a live book, a non-NULL scratch, and scratch_cap > 0.
href holds href_len readable bytes.
Postcondition
On success *out_bytes / *out_len describe the scratch contents.
On any error *out_len == 0 and the engine falls back to a placeholder.
Note
Not thread-safe; the scratch is single-decode.
Since
0.1.0

◆ epub_tile_binder_add()

ra8_err_t epub_tile_binder_add ( epub_tile_binder_t * binder,
epub_book_t * book,
const char * path,
uint32_t image_id )
nodiscard

Register a stored in-archive JOF atlas entry under image_id (#231).

Resolves path (OPF-relative, then archive-rooted), measures the entry, and validates the atlas structure via jof_parse() over the entry pread seam. The entry must be stored (uncompressed) in the ZIP so tiles can be windowed with positioned reads. After this, tiles of the image are fetched with epub_tile_binder_get() keyed by image_id.

Parameters
[in,out]binderInitialised binder.
[in]bookOpen book whose archive holds path.
[in]pathAtlas entry path, OPF-relative or archive-rooted.
[in]image_idCaller-chosen id (must be unique within the binder).
Returns
ra8_err_t
Return values
k_ra8_okImage registered.
k_ra8_err_null_ptrbinder, book, or path is NULL.
k_ra8_err_no_memThe binder's source table is full.
k_ra8_err_invalid_argimage_id already registered / bad path length.
k_ra8_err_validation_failedThe entry is not a structurally valid atlas.
k_ra8_err_not_supportedThe entry is DEFLATE-compressed in the ZIP.
otherPropagated from the entry reader.
Precondition
binder came from epub_tile_binder_init().
path is longer than 0 and shorter than k_epub_max_path_len.
Postcondition
On success source_count grew by one and the geometry is queryable.
On any error the source table is unchanged.
Note
Not thread-safe.
See also
epub_tile_binder_get()
Since
0.1.0

◆ epub_tile_binder_add_ext()

ra8_err_t epub_tile_binder_add_ext ( epub_tile_binder_t * binder,
jof_pread_fn pread,
void * pread_ctx,
uint64_t total_size,
uint32_t image_id )
nodiscard

Register an externally-backed JOF atlas under image_id (#231).

The external seam serves atlases that live outside the archive: an SDRAM memstore or SD file filled by the import-time transcode (epub_tile_binder_import() calls this itself), or any other backing. The atlas structure is validated via jof_parse() before the source is accepted.

Parameters
[in,out]binderInitialised binder.
[in]preadAtlas read seam (non-NULL).
[in]pread_ctxContext for pread (must out-live the binder).
[in]total_sizeAtlas byte length.
[in]image_idCaller-chosen id (unique within the binder).
Returns
ra8_err_t
Return values
k_ra8_okImage registered.
k_ra8_err_null_ptrbinder or pread is NULL.
k_ra8_err_no_memThe binder's source table is full.
k_ra8_err_invalid_argimage_id already registered.
k_ra8_err_invalid_sizetotal_size cannot hold an atlas.
k_ra8_err_validation_failedThe backing is not a valid atlas.
otherPropagated from pread.
Precondition
binder came from epub_tile_binder_init().
pread serves the atlas bytes for [0, total_size).
Postcondition
On success source_count grew by one and the geometry is queryable.
On any error the source table is unchanged.
Note
Not thread-safe.
See also
epub_tile_binder_import()
Since
0.1.0

◆ epub_tile_binder_get()

ra8_err_t epub_tile_binder_get ( epub_tile_binder_t * binder,
uint32_t image_id,
uint16_t tile_x,
uint16_t tile_y,
ra8_tile_t * out_tile )
nodiscard

Get (and pin) one decoded tile of a registered image (#231).

Builds the tile-cache key (image_id, tile_x, tile_y) and fetches it through the owned cache. On a miss the tile's stored stream is read off the atlas backing and decoded into one cache cell (jof_read_tile()); on a hit the cell is reused. The returned pixels are tightly packed (out_tile->width * bpp bytes per row) and stay valid until epub_tile_binder_put(). Edge tiles report their true (smaller) size.

Parameters
[in]binderBinder with image_id registered.
[in]image_idImage to fetch a tile of.
[in]tile_xTile column, [0, tile_cols).
[in]tile_yTile row, [0, tile_rows).
[out]out_tileReceives the pinned tile view.
Returns
ra8_err_t
Return values
k_ra8_okTile resident + pinned; *out_tile set.
k_ra8_err_null_ptrbinder or out_tile is NULL.
k_ra8_err_not_foundimage_id is not registered.
k_ra8_err_out_of_rangetile_x / tile_y is outside the grid.
k_ra8_err_no_memEvery cell is pinned, or the tile exceeds the cell/scratch budget.
k_ra8_err_validation_failedThe atlas backing is corrupt.
Precondition
binder is initialised and image_id registered.
The caller will epub_tile_binder_put() the returned tile.
Postcondition
On success the cell's pin count grew by one.
On any error no new pin is held.
Note
Not thread-safe.
See also
epub_tile_binder_put()
Since
0.1.0

◆ epub_tile_binder_import()

ra8_err_t epub_tile_binder_import ( epub_tile_binder_t * binder,
epub_book_t * book,
const char * href,
uint32_t image_id,
const epub_atlas_import_cfg_t * cfg )
nodiscard

Import a manifest image through the transcode producer and register it for tile paging (#231 – the open-path wiring).

Resolves href against the book, then:

  1. If the entry is already a stored JOF atlas, registers it in place (epub_tile_binder_add()) – the host-baked fast path, no transcode and no store writes.
  2. Otherwise streams the entry's encoded bytes through jof_produce() (JPEG/PNG in bounded stripes so the whole decoded image is never resident; WebP whole-frame through the cfg->webp_work arena) into cfg->store, then registers the produced atlas via epub_tile_binder_add_ext().

After a successful import, epub_tile_binder_get() pages the image's full-resolution tiles on demand – the #231 goal: a manga page larger than SDRAM at native resolution renders without whole-image decode and without downscaling.

Parameters
[in,out]binderInitialised binder.
[in]bookOpen book (streamed or resident).
[in]hrefManifest image href, NUL-terminated.
[in]image_idCaller-chosen id (unique within the binder).
[in]cfgTranscode knobs + work arena + atlas store.
Returns
ra8_err_t
Return values
k_ra8_okImage registered (either path).
k_ra8_err_null_ptrA required pointer is NULL.
k_ra8_err_invalid_argBad href length / duplicate id / bad cfg.
k_ra8_err_no_memSource table full, or the store filled.
k_ra8_err_not_foundhref resolves to no archive entry.
k_ra8_err_not_supportedThe entry is not JPEG/PNG/WebP/atlas, a WebP with no webp_work arena, or an unsupported variant.
k_ra8_err_invalid_sizeSource exceeds the caps / arena too small.
k_ra8_err_protocol_errorMalformed / hostile source structure.
k_ra8_err_validation_failedProducer or atlas validation failed.
otherPropagated from the reader / store.
Precondition
binder came from epub_tile_binder_init().
cfg->work is sized per jof_work_bytes().
Postcondition
On success the image's tiles are servable by image_id.
On any error the source table is unchanged (a partial store write is abandoned and must be reset by the caller before reuse).
Note
Not thread-safe.
See also
epub_tile_binder_get()
Since
0.1.0

◆ epub_tile_binder_info()

ra8_err_t epub_tile_binder_info ( const epub_tile_binder_t * binder,
uint32_t image_id,
jof_info_t * out_info )
nodiscard

Report a registered image's parsed geometry (#231).

Parameters
[in]binderBinder with image_id registered.
[in]image_idImage to query.
[out]out_infoReceives the atlas geometry on success.
Returns
ra8_err_t
Return values
k_ra8_okGeometry reported.
k_ra8_err_null_ptrbinder or out_info is NULL.
k_ra8_err_not_foundimage_id is not registered.
Precondition
binder is initialised; out_info is writable.
image_id was registered via an add/import call.
Postcondition
On success *out_info holds the image geometry.
On failure *out_info is unmodified.
Note
Not thread-safe.
Since
0.1.0

◆ epub_tile_binder_init()

ra8_err_t epub_tile_binder_init ( epub_tile_binder_t * binder,
const ra8_tile_cache_cfg_t * storage,
uint8_t * scratch,
uint32_t scratch_cap )
nodiscard

Initialise a tile binder over caller-supplied tile-cache storage (#231).

Wires storage into an owned ::ra8_tile_cache whose decode-on-miss is this module's JOF tile reader. The storage decode / decode_ctx fields are ignored (the binder sets them); all other fields (cell memory + geometry + key/dim/meta arrays + hash buckets) are the caller's and must out-live the binder. scratch stages one stored (compressed) tile during a deflate decode-on-miss: size it with jof_stored_bound() over the cell size; a binder serving only raw atlases may pass NULL/0.

Parameters
[out]binderBinder to populate (zero-initialised by the caller).
[in]storageTile-cache storage config; decode/decode_ctx unused.
[in]scratchStored-tile staging buffer (may be NULL for raw-only).
[in]scratch_capCapacity of scratch, bytes.
Returns
ra8_err_t
Return values
k_ra8_okBinder ready; no images registered yet.
k_ra8_err_null_ptrbinder or storage (or a required array) NULL.
k_ra8_err_invalid_sizeA zero cell/bucket geometry in storage.
Precondition
binder points at zeroed storage.
storage arrays and scratch out-live the binder.
Postcondition
On success the cache is empty and no source is registered.
On failure binder is left unusable.
Note
Not thread-safe.
See also
epub_tile_binder_add()
Since
0.1.0

◆ epub_tile_binder_prefetch_pan()

ra8_err_t epub_tile_binder_prefetch_pan ( epub_tile_binder_t * binder,
uint32_t image_id,
const ra8_tile_rect_t * view,
ra8_tile_pan_dir_t dir,
uint16_t max_tiles,
uint16_t * out_warmed )
nodiscard

Predictively warm the tiles one step ahead of a panning image (#341).

The image-render counterpart of book_src_prefetch_chapter's text read-ahead: on a pan of a tiled page (the #231 all-image EPUB path, and the comic-tiling path that shares this binder), warms the tile row or column just beyond view in dir so the next tiles the viewport exposes are resident before they are needed. The binder supplies the image's tile-grid extent to ra8_tile_cache_prefetch_pan, which clamps the lead edge to the grid (a pan already at the image edge warms nothing) and caps the count at max_tiles – the caller's spare-capacity budget – so read-ahead can neither exceed the cache budget nor evict an on-screen tile. Best-effort and transparent: warming changes only residency, never the bytes a later epub_tile_binder_get() returns, so goldens hold.

Parameters
[in,out]binderInitialised binder with image_id registered.
[in]image_idImage being panned.
[in]viewThe tiles the viewport currently straddles.
[in]dirDirection of viewport travel.
[in]max_tilesResidency budget: warm at most this many tiles.
[out]out_warmedTiles warmed by this call (may be NULL).
Returns
ra8_err_t
Return values
k_ra8_okThe sweep ran (0 or more tiles warmed).
k_ra8_err_null_ptrbinder or view is NULL.
k_ra8_err_not_foundimage_id is not registered.
k_ra8_err_invalid_argview is unordered or lies outside the grid.
Precondition
binder came from epub_tile_binder_init().
view is a valid inclusive tile rectangle of image_id.
Postcondition
On success at most max_tiles lead-edge tiles are resident.
No on-screen (already-visible) tile is evicted by this call.
Note
Not thread-safe. Single-threaded read-ahead only.
See also
epub_tile_binder_get()
Since
0.1.0

◆ epub_tile_binder_put()

ra8_err_t epub_tile_binder_put ( epub_tile_binder_t * binder,
const uint8_t * pixels )
nodiscard

Release one pin taken by epub_tile_binder_get() (#231).

Parameters
[in]binderInitialised binder.
[in]pixelsThe pixels pointer from a returned ra8_tile_t.
Returns
ra8_err_t
Return values
k_ra8_okPin released.
k_ra8_err_null_ptrbinder or pixels is NULL.
k_ra8_err_invalid_argpixels is not a pinned cell of this binder.
Precondition
pixels came from epub_tile_binder_get() on this binder.
binder is initialised.
Postcondition
On success the cell's pin count dropped by one.
On any error no state changed.
Note
Not thread-safe.
Since
0.1.0