|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
End-to-end EPUB -> RABOOK1 compile pipeline (#149). More...
#include "ra8_rabook_pipeline.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "book.h"#include "epub.h"#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_fs.h"#include "ra8_img_arena.h"#include "ra8_log.h"#include "ra8_rabook_gray4.h"#include "ra8_rabook_pipeline_internal.h"#include "ra8_rabook_xml_shim.h"#include "rabook_compile.h"#include "reflow_image.h"#include "stb_image.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_pipeline_limits_t : uint16_t { k_pipeline_max_chapters = 64U , k_pipeline_max_toc = 64U } |
| Static bounds used for NASA Rule 2 loop annotations. More... | |
| enum | ra8_pipeline_stbi_t : uint8_t { k_stbi_grey = 1U } |
| stb_image channel-count selector (no magic literals). More... | |
Functions | |
| static const uint8_t * | internal_downscale_if_needed (const ra8_rabook_pipeline_scratch_t *scr, const uint8_t *pixels, uint16_t sw, uint16_t sh, uint16_t ow, uint16_t oh) |
| Resolve the gray source buffer for the encode, downscaling if required. | |
| static ra8_err_t | internal_encode_gray (const ra8_rabook_pipeline_scratch_t *scr, const uint8_t *gray_src, uint16_t ow, uint16_t oh, uint32_t *out_size) |
Encode gray_src into scr->image_raw at the device-profile depth. | |
| static uint32_t | internal_transcode_image (ra8_rabook_ctx_t *ctx, const ra8_rabook_pipeline_scratch_t *scr, uint32_t id_off, size_t raw_len) |
| Decode one raw image, transcode to the profile's gray depth, add to builder. | |
| static const char * | internal_chapter_title (const epub_book_t *epub, uint16_t chapter_idx, uint16_t toc_count, epub_toc_entry_t *entry_buf) |
| Find the TOC title for one spine chapter (first-entry-wins). | |
| ra8_err_t | priv_rabook_pipeline_check_common (const epub_book_t *epub, const ra8_rabook_buffers_t *bufs, const ra8_rabook_pipeline_scratch_t *scr) |
| Reject any NULL among the three arguments common to both compile entry points (rabook_compile_from_epub and the buffer variant). | |
| static ra8_err_t | internal_compile_stylesheets (ra8_rabook_ctx_t *ctx, const ra8_rabook_pipeline_scratch_t *scr, epub_book_t *epub) |
| Emit each text/css manifest item as a stylesheet, in OPF order. | |
| static uint32_t | internal_add_manifest_image (ra8_rabook_ctx_t *ctx, const ra8_rabook_pipeline_scratch_t *scr, epub_book_t *epub, const epub_manifest_item_t *item) |
| Add one manifest item to the builder if it is an image. | |
| static ra8_err_t | internal_compile_images (ra8_rabook_ctx_t *ctx, const ra8_rabook_pipeline_scratch_t *scr, epub_book_t *epub, uint32_t *cover_index_out) |
| Compile every manifest image into the builder, resolving the cover. | |
| static ra8_err_t | internal_compile_chapters (epub_book_t *epub, const ra8_rabook_pipeline_scratch_t *scr, ra8_rabook_ctx_t *ctx) |
| Parse every spine chapter into the builder DOM. | |
| static ra8_err_t | internal_compile_metadata (ra8_rabook_ctx_t *ctx, epub_book_t *epub, uint32_t cover_image_index) |
| Intern the Dublin Core metadata and record it (the final emit stage). | |
| static ra8_err_t | internal_compile_to_blob (epub_book_t *epub, const ra8_rabook_buffers_t *bufs, const ra8_rabook_pipeline_scratch_t *scr, const void **out_blob, uint32_t *out_len) |
Run the compile stages and finalize the RABOOK1 blob in bufs->out. | |
| ra8_err_t | rabook_compile_from_epub_to_buffer (epub_book_t *epub, const ra8_rabook_buffers_t *bufs, const ra8_rabook_pipeline_scratch_t *scr, const void **out_blob, uint32_t *out_len) |
Compile an open EPUB into a RABOOK1 blob left in bufs->out, with no filesystem write. | |
Variables | |
| static const char *const | s_tag = "ra8_rabook_pipeline" |
End-to-end EPUB -> RABOOK1 compile pipeline (#149).
Coordinates EPUB parsing, chapter compilation, image conversion, and final RABOOK publication through explicit caller-owned workspaces.
Definition in file ra8_rabook_pipeline.c.
| enum ra8_pipeline_limits_t : uint16_t |
Static bounds used for NASA Rule 2 loop annotations.
| Enumerator | |
|---|---|
| k_pipeline_max_chapters | == k_epub_max_chapters (cross-check). |
| k_pipeline_max_toc | == k_epub_max_toc (cross-check). |
Definition at line 41 of file ra8_rabook_pipeline.c.
| enum ra8_pipeline_stbi_t : uint8_t |
stb_image channel-count selector (no magic literals).
| Enumerator | |
|---|---|
| k_stbi_grey | Request 8-bit grayscale output from stb_image. |
Definition at line 56 of file ra8_rabook_pipeline.c.
|
static |
Add one manifest item to the builder if it is an image.
Mirrors the desktop epub_compile.py image arm exactly: a image/svg+xml item is stored verbatim (vector, width=height=0); any other image/ * item is decoded + transcoded to 4-bpp gray via internal_transcode_image (downscaled only above the panel edge). The item href is interned as the image id. A non-image item, an item absent from the archive, or one that fails to decode is skipped (returns nil) – the desktop's try/except pass – so one bad image never fails the whole compile.
| [in,out] | ctx | Builder the image is appended to (non-NULL). |
| [in] | scr | Scratch buffers for the resource load / transcode (non-NULL). |
| [in,out] | epub | Open book the resource bytes are read from (non-NULL). |
| [in] | item | Manifest item to consider (non-NULL). |
| k_book_nil | Not an image / absent / undecodable (skipped). |
ctx, scr, epub and item are non-NULL (caller-validated). scr->image_raw / image_cap can hold the resource bytes. scr->image_raw is clobbered (resource bytes, then encoded nibbles). Definition at line 387 of file ra8_rabook_pipeline.c.
References epub_get_resource(), epub_manifest_item_t::href, ra8_rabook_pipeline_scratch_t::image_cap, ra8_rabook_pipeline_scratch_t::image_raw, internal_transcode_image(), k_book_image_gray4, k_book_image_svg, k_book_nil, k_book_pixfmt_gray4, k_ra8_ok, epub_manifest_item_t::media_type, ra8_log_error, ra8_rabook_add_image(), ra8_rabook_intern(), s_tag, strcmp(), strlen(), and strncmp().
Referenced by internal_compile_images().
|
static |
Find the TOC title for one spine chapter (first-entry-wins).
Scans the TOC entries in order; the first entry that maps to chapter_idx supplies the title. A miss (no TOC entry references the chapter, or the lookups fail) yields the empty string.
| [in] | epub | Open book to read TOC entries from (non-NULL). |
| [in] | chapter_idx | Spine index of the chapter whose title is wanted. |
| [in] | toc_count | Number of TOC entries to scan (0 disables the scan). |
| [out] | entry_buf | Caller-owned scratch for the matched entry (non-NULL). |
| "" | No TOC entry references chapter_idx, or the readers failed. |
epub and entry_buf are non-NULL (caller-validated). toc_count does not exceed k_pipeline_max_toc. entry_buf holds the matched entry on a hit; indeterminate on a miss. epub is not modified. entry_buf, so it is valid only until the next reuse of that buffer. Not thread-safe. Definition at line 262 of file ra8_rabook_pipeline.c.
References epub_get_toc_entry(), epub_toc_entry_to_chapter(), k_ra8_ok, and epub_toc_entry_t::title.
Referenced by internal_compile_chapters().
|
static |
Parse every spine chapter into the builder DOM.
Loads each chapter's XHTML into scr->xhtml, resolves its TOC title, and hands it to ra8_rabook_xml_parse_chapter, stopping at the first error.
| [in,out] | epub | Open book providing the spine chapters (non-NULL). |
| [in] | scr | Scratch buffers for the chapter XHTML load (non-NULL). |
| [in,out] | ctx | Builder the chapter DOMs are appended to (non-NULL). |
| k_ra8_ok | Every spine chapter parsed and added. |
| <reader | error> The first chapter count / load failure, propagated. |
| <parser | error> The first ra8_rabook_xml_parse_chapter failure. |
epub, scr and ctx are non-NULL (caller-validated). scr->xhtml is large enough for the largest chapter. Definition at line 509 of file ra8_rabook_pipeline.c.
References epub_book_t::chapter_paths, epub_get_chapter_count(), epub_get_toc_count(), epub_load_chapter(), internal_chapter_title(), k_ra8_ok, ra8_rabook_xml_parse_chapter(), ra8_rabook_pipeline_scratch_t::xhtml, ra8_rabook_pipeline_scratch_t::xhtml_cap, and ra8_rabook_pipeline_scratch_t::xml_workspace.
Referenced by internal_compile_to_blob().
|
static |
Compile every manifest image into the builder, resolving the cover.
Walks the manifest in OPF document order – the same order the desktop epub_compile.py iterates manifest.items() – adding each image item via internal_add_manifest_image so the image table indices match. The cover index is the table index of the item whose href equals epub->cover_path (epub already resolves that from properties="cover-image" or the legacy <meta name="cover">), which is the same image the desktop's id_to_image[cover_id] yields.
When scr->skip_images is set the whole stage is a no-op: no image is added and the cover index stays nil, exactly like the desktop --no-images path (its manifest.items() image loop iterates the empty tuple and cover_id never resolves), producing a text/CSS-only blob byte-identical to the desktop --no-images golden.
| [in,out] | ctx | Builder the images are appended to (non-NULL). |
| [in] | scr | Scratch buffers for load / transcode (non-NULL). |
| [in,out] | epub | Open book providing the manifest (non-NULL). |
| [out] | cover_index_out | Receives the cover image index, or nil (non-NULL). |
| k_ra8_ok | Images walked; *cover_index_out set (nil if no cover image). |
ctx, scr, epub and cover_index_out are non-NULL. scr->skip_images) the image table is left empty. *cover_index_out is the cover image index, or nil when absent / skipped. Definition at line 463 of file ra8_rabook_pipeline.c.
References epub_book_t::cover_path, epub_manifest_count(), epub_manifest_item(), epub_manifest_item_t::href, internal_add_manifest_image(), k_book_nil, k_ra8_ok, ra8_rabook_pipeline_scratch_t::skip_images, and strcmp().
Referenced by internal_compile_to_blob().
|
static |
Intern the Dublin Core metadata and record it (the final emit stage).
Runs LAST, after the chapters, so the title/author/language/identifier strings land after the chapter DOM strings in the pool – matching the desktop epub_compile.py serialize(meta) order the #151 byte-identity gate requires. Interning metadata earlier shifts every string offset.
| [in,out] | ctx | Builder receiving the metadata (non-NULL). |
| [in] | epub | Open book to read the Dublin Core fields from. |
| [in] | cover_image_index | Cover image index resolved earlier, or nil. |
| k_ra8_ok | Metadata interned and recorded in the builder header. |
| k_ra8_err_invalid_arg | epub_get_metadata rejected epub. |
| k_ra8_err_no_mem | The string pool or header could not hold the metadata. |
ctx is initialised and the chapters are already emitted. epub is an open book record. Definition at line 565 of file ra8_rabook_pipeline.c.
References epub_metadata_t::author, epub_get_metadata(), epub_metadata_t::identifier, k_ra8_ok, epub_metadata_t::language, ra8_rabook_intern(), ra8_rabook_set_metadata(), and epub_metadata_t::title.
Referenced by internal_compile_to_blob().
|
static |
Emit each text/css manifest item as a stylesheet, in OPF order.
Walks the manifest in document order; for every item whose media-type is exactly text/css, loads its bytes via epub_get_resource into scr->css, NUL-terminates them, interns the source string, and appends a book-wide stylesheet (scope k_book_nil). An item absent from the archive (k_ra8_err_not_found) is skipped, matching the desktop epub_compile.py "only if present" rule; the pass order and emit order match it too, so the stylesheet table + pool stay byte-identical.
| [in,out] | ctx | Builder the stylesheets are appended to (non-NULL). |
| [in] | scr | Scratch buffers (provides css / css_cap), non-NULL. |
| [in,out] | epub | Open book the CSS resources are read from (non-NULL). |
| k_ra8_ok | All present CSS items added (or none declared). |
| <reader | error> Any non-not_found error loading a CSS resource. |
ctx, scr and epub are non-NULL (caller-validated). scr->css has capacity for the largest stylesheet plus a NUL. Definition at line 333 of file ra8_rabook_pipeline.c.
References ra8_rabook_pipeline_scratch_t::css, ra8_rabook_pipeline_scratch_t::css_cap, epub_get_resource(), epub_manifest_count(), epub_manifest_item(), epub_manifest_item_t::href, k_book_nil, k_ra8_err_not_found, k_ra8_ok, epub_manifest_item_t::media_type, ra8_rabook_add_stylesheet(), ra8_rabook_intern(), and strcmp().
Referenced by internal_compile_to_blob().
|
static |
Run the compile stages and finalize the RABOOK1 blob in bufs->out.
The shared core of both public entry points: initialises the builder and emits the stages in the desktop epub_compile.py order (stylesheets -> images -> chapters -> metadata interned LAST) so the blob is byte-identical, then finalises. The blob lives in bufs->out and stays valid as long as that arena does.
| [in] | epub | Open book (validated non-NULL by the caller). |
| [in] | bufs | Builder arenas (validated non-NULL by the caller). |
| [in] | scr | Scratch buffers (validated non-NULL by the caller). |
| [out] | out_blob | Receives a pointer to the finalized blob in bufs->out. |
| [out] | out_len | Receives the blob length in bytes. |
| k_ra8_ok | Blob emitted; *out_blob / *out_len set. |
| <stage | err> The first failing stage / finalize error, propagated. |
epub, bufs, scr, out_blob and out_len are non-NULL. epub->in_use == 1 and the arenas are sized for the book. *out_blob addresses a valid RABOOK1 blob of *out_len. bufs->out may hold a partial layout. Definition at line 607 of file ra8_rabook_pipeline.c.
References internal_compile_chapters(), internal_compile_images(), internal_compile_metadata(), internal_compile_stylesheets(), k_book_nil, k_ra8_ok, ra8_rabook_finalize(), and rabook_compile_init().
Referenced by rabook_compile_from_epub_to_buffer().
|
static |
Resolve the gray source buffer for the encode, downscaling if required.
When the target dimensions equal the source the decoded pixels are used in place; otherwise the pixels are bilinear-downscaled into scr->gray (after a capacity check) and that buffer is returned.
| [in] | scr | Scratch buffers (provides gray / gray_cap), non-NULL. |
| [in] | pixels | Decoded 8-bit grayscale source pixels, non-NULL. |
| [in] | sw | Source width in pixels (> 0). |
| [in] | sh | Source height in pixels (> 0). |
| [in] | ow | Target output width in pixels (> 0). |
| [in] | oh | Target output height in pixels (> 0). |
pixels or scr->gray), or nullptr if the gray scratch is too small or the downscale failed. | nullptr | Gray scratch capacity exceeded or downscale error. |
scr and pixels are non-NULL (caller-validated). ow * oh does not exceed the encode/gray scratch the caller sized. ow * oh gray bytes. pixels is unchanged unless it is itself the returned buffer. Definition at line 94 of file ra8_rabook_pipeline.c.
References ra8_rabook_pipeline_scratch_t::gray, ra8_rabook_pipeline_scratch_t::gray_cap, k_ra8_ok, ra8_log_error, ra8_rabook_gray4_downscale(), and s_tag.
Referenced by internal_transcode_image().
|
static |
Encode gray_src into scr->image_raw at the device-profile depth.
Dispatches on scr->pixel_format: k_book_pixfmt_gray8 copies the pixels out verbatim at 8-bpp (1 byte/pixel), any other value quantises + nibble-packs to 4-bpp (2 pixels/byte). The output is written into scr->image_raw in place, so it must not overlap the still-live gray_src (see ra8_rabook_pipeline_scratch_t).
| [in] | scr | Scratch buffers (provides image_raw / image_cap / pixel_format), non-NULL. |
| [in] | gray_src | Gray pixels to encode: ow * oh readable bytes, non-NULL. |
| [in] | ow | Output width in pixels. |
| [in] | oh | Output height in pixels. |
| [out] | out_size | Receives the encoded byte length written to image_raw. |
| k_ra8_ok | Encoded; *out_size bytes written to image_raw. |
| k_ra8_err_no_mem | image_cap is too small for the encoded output. |
scr, gray_src and out_size are non-NULL (caller-validated). gray_src holds at least ow * oh readable bytes. scr->image_raw holds *out_size encoded bytes. gray_src is not modified (read-only encode). Definition at line 138 of file ra8_rabook_pipeline.c.
References ra8_rabook_pipeline_scratch_t::image_cap, ra8_rabook_pipeline_scratch_t::image_raw, k_book_pixfmt_gray8, ra8_rabook_pipeline_scratch_t::pixel_format, ra8_rabook_gray4_encode(), and ra8_rabook_gray8_encode().
Referenced by internal_transcode_image().
|
static |
Decode one raw image, transcode to the profile's gray depth, add to builder.
Binds scr->img_arena before calling stb_image and unbinds on every return path. The encoded output (4-bpp nibbles or the 8-bpp copy, per scr->pixel_format) is written into scr->image_raw (reusing the buffer that held the raw bytes), so the source and encode buffers must not overlap (see ra8_rabook_pipeline_scratch_t).
| [in,out] | ctx | Builder the transcoded image is appended to (non-NULL). |
| [in] | scr | Scratch buffers for decode / downscale / encode (non-NULL). |
| [in] | id_off | String-pool offset of the image href / manifest id. |
| [in] | raw_len | Length of the encoded source bytes in scr->image_raw. |
| k_book_nil | Decode / capacity / downscale / encode / append failed. |
ctx and scr are non-NULL (caller-validated). scr->image_raw holds raw_len readable encoded bytes. scr->pixel_format depth. Definition at line 183 of file ra8_rabook_pipeline.c.
References ra8_rabook_pipeline_scratch_t::image_raw, ra8_rabook_pipeline_scratch_t::img_arena, internal_downscale_if_needed(), internal_encode_gray(), k_book_image_gray4, k_book_nil, k_ra8_ok, k_stbi_grey, ra8_rabook_pipeline_scratch_t::max_image_edge, ra8_rabook_pipeline_scratch_t::pixel_format, ra8_img_arena_bind(), ra8_img_arena_unbind(), ra8_log_error, ra8_rabook_add_image(), ra8_rabook_gray4_output_dims(), and s_tag.
Referenced by internal_add_manifest_image().
| ra8_err_t priv_rabook_pipeline_check_common | ( | const epub_book_t * | epub, |
| const ra8_rabook_buffers_t * | bufs, | ||
| const ra8_rabook_pipeline_scratch_t * | scr ) |
Reject any NULL among the three arguments common to both compile entry points (rabook_compile_from_epub and the buffer variant).
Validate arguments common to both RABOOK pipeline entry points.
Centralises the shared null guards so each public function stays flat; the FS-write entry adds its own mount / out_path guards, the buffer entry its own out_blob / out_len guards.
| [in] | epub | Open book pointer to validate. |
| [in] | bufs | Builder arenas pointer to validate. |
| [in] | scr | Scratch buffers pointer to validate. |
| k_ra8_ok | All three arguments are non-NULL. |
| k_ra8_err_null_ptr | One of the arguments is NULL. |
Definition at line 298 of file ra8_rabook_pipeline.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_PRIV, s_tag, and ra8_rabook_pipeline_scratch_t::xml_workspace.
Referenced by rabook_compile_from_epub(), and rabook_compile_from_epub_to_buffer().
| ra8_err_t rabook_compile_from_epub_to_buffer | ( | epub_book_t * | epub, |
| const ra8_rabook_buffers_t * | bufs, | ||
| const ra8_rabook_pipeline_scratch_t * | scr, | ||
| const void ** | out_blob, | ||
| uint32_t * | out_len ) |
Compile an open EPUB into a RABOOK1 blob left in bufs->out, with no filesystem write.
Identical compile to rabook_compile_from_epub – same stages, same byte-identical desktop emit order – but it stops at ra8_rabook_finalize and returns the blob in place instead of calling ra8_fs_write_file. This is the entry point for callers with no filesystem: notably the Cortex-M33 offload (#149), which finalises into a shared SDRAM buffer and lets the M85 own the SD write. The returned *out_blob aliases bufs->out and is valid only while that arena is. A build defining RA8_RABOOK_NO_RASTER (the M33 text/CSS/SVG image) links no stb_image: raster manifest images are skipped, SVG verbatim and text/CSS are unaffected.
| [in,out] | epub | Open book (in_use == 1); chapters extracted in-place. |
| [in] | bufs | Builder arenas (all non-NULL, sized for the book). |
| [in] | scr | Scratch buffers for XHTML load + image decode + gray. |
| [out] | out_blob | Receives a pointer to the blob inside bufs->out. |
| [out] | out_len | Receives the blob length in bytes. |
| k_ra8_ok | Book compiled; *out_blob / *out_len set. |
| k_ra8_err_null_ptr | Any required pointer is NULL. |
epub->in_use == 1. *out_blob addresses a valid RABOOK1 blob in bufs->out. Definition at line 644 of file ra8_rabook_pipeline.c.
References internal_compile_to_blob(), k_ra8_ok, priv_rabook_pipeline_check_common(), RA8_CHECK_NULL_PTR, and s_tag.
Referenced by compile_fixture(), internal_compile_temp(), and rabook_compile_from_epub().
|
static |
Definition at line 60 of file ra8_rabook_pipeline.c.