38#include "stb_truetype.h"
49typedef enum : uint16_t {
76 const stbtt_fontinfo*
font;
131 if (((
size_t)rc->
w * (
size_t)rc->
h) > (
size_t)cell_bytes) {
134 stbtt_MakeCodepointBitmap(rc->
font,
142 *out_w = (uint16_t)rc->
w;
143 *out_h = (uint16_t)rc->
h;
165 const int32_t offset = stbtt_GetFontOffsetForIndex(engine->
font_data, 0);
169 if (stbtt_InitFont(out_font, engine->
font_data, (
int)engine->
font_len, offset) == 0) {
197 const unsigned char* bitmap,
205 for (
int row = 0; row < h; ++row) {
206 for (
int col = 0; col < w; ++col) {
207 const uint8_t alpha = (uint8_t)bitmap[((
size_t)row * (
size_t)w) + (size_t)col];
211 const int32_t px = g->
x + (int32_t)col + (int32_t)xoff + ox;
212 const int32_t py = g->
y + (int32_t)row + (int32_t)yoff + oy;
241 int advance_units = 0;
243 stbtt_GetCodepointHMetrics(font, g->
cp, &advance_units, &lsb);
244 const int32_t advance = (int32_t)((
float)advance_units * scale);
246 for (int32_t i = 0; i < advance; ++i) {
291 const size_t total = (size_t)w * (
size_t)h;
292 if (total <=
sizeof s_glyph_mask) {
293 stbtt_MakeCodepointBitmap(font, s_glyph_mask, w, h, w, scale, scale, g->
cp);
339 const stbtt_fontinfo* font,
357 key.
face_id = (uint16_t)face_id;
397 const stbtt_fontinfo* font,
402 const float scale = stbtt_ScaleForPixelHeight(font, (
float)g->
font_px);
407 stbtt_GetCodepointBitmapBox(font, g->
cp, scale, scale, &x0, &y0, &x1, &y1);
408 const int w = x1 - x0;
409 const int h = y1 - y0;
419 if ((w > 0) && (h > 0)) {
421 if (atlas !=
nullptr) {
422 drawn =
internal_glyph_render_cached(atlas, face_id, font, scale, g, w, h, x0, y0, ox, oy);
484 if (hlen >=
sizeof(href)) {
487 (void)
memcpy(href, &svg[hoff], hlen);
488 const uint8_t* rbytes =
nullptr;
532 const uint8_t* bytes =
nullptr;
537 const int32_t bx = box->
x + ox;
538 const int32_t by = box->
y + oy;
634 for (uint8_t k = 0U; k < engine->
face_count; ++k) {
635 const uint8_t* blob = engine->
faces[k].
blob;
636 const int32_t offset = stbtt_GetFontOffsetForIndex(blob, 0);
638 (stbtt_InitFont(&faces[k + 1U], blob, (
int)engine->
faces[k].
len, offset) == 0)) {
639 faces[k + 1U] = faces[0];
690 if (engine ==
nullptr) {
693 if (engine->
in_use == 0U) {
711 for (uint32_t i = 0U; i < page->
glyph_count; ++i) {
740 if (engine ==
nullptr) {
743 if (engine->
in_use == 0U) {
746 if (atlas ==
nullptr) {
750 if (storage ==
nullptr) {
761 .meta = storage->
meta,
762 .keys = storage->
keys,
763 .dims = storage->
dims,
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Software 2D graphics primitives layered on top of a caller-ownedframebuffer (DRW / D/AVE 2D / GLCDC r...
ra8_err_t ra8_gfx_pixel(int32_t x, int32_t y, uint32_t color)
Set a single pixel.
Fixed-RAM-budget glyph cache with LRU eviction (Layer 3, #147).
ra8_err_t ra8_glyph_atlas_put(ra8_glyph_atlas_t *atlas, const uint8_t *bitmap)
Release one pin on a glyph previously returned by ra8_glyph_atlas_get.
ra8_err_t ra8_glyph_atlas_get(ra8_glyph_atlas_t *atlas, const ra8_glyph_key_t *key, ra8_glyph_t *out_glyph)
Get (and pin) the rendered glyph for key.
ra8_err_t ra8_glyph_atlas_init(ra8_glyph_atlas_t *atlas, const ra8_glyph_atlas_cfg_t *cfg)
Initialise a glyph atlas over caller-supplied storage.
HTML / CSS reflow + paginate engine for the ra8d2 ereader.
ra8_err_t ra8_img_decode_blit(ra8_img_arena_t *arena, const uint8_t *bytes, size_t len, int32_t dst_x, int32_t dst_y, int32_t box_w, int32_t box_h, int32_t *out_w, int32_t *out_h)
Decode bytes and blit it, scaled to fit, into the bound framebuffer.
ra8_err_t reflow_render_page(const reflow_t *engine, uint32_t page_idx, void *framebuffer)
Render one page into the active ra8_gfx framebuffer.
static void internal_glyph_render_direct(const stbtt_fontinfo *font, float scale, const reflow_glyph_t *g, int w, int h, int x0, int y0, int32_t ox, int32_t oy)
Rasterise one glyph into a function-local static mask and blit it.
static ra8_err_t internal_init_font(const reflow_t *engine, stbtt_fontinfo *out_font)
Initialise an stbtt_fontinfo from the engine's font blob.
static ra8_err_t internal_atlas_render_glyph(void *ctx, const ra8_glyph_key_t *key, uint8_t *cell, uint32_t cell_bytes, uint16_t *out_w, uint16_t *out_h)
Glyph-atlas render-on-miss callback: rasterise one glyph into a cell.
static void internal_blit_glyph(ra8_glyph_atlas_t *atlas, uint8_t face_id, const stbtt_fontinfo *font, const reflow_glyph_t *g, int32_t ox, int32_t oy)
Rasterise one glyph at its baseline position into the bound framebuffer.
static priv_glyph_render_ctx_t s_glyph_render_ctx
File-static render context shared with the bound glyph atlas.
ra8_err_t reflow_set_glyph_atlas(reflow_t *engine, ra8_glyph_atlas_t *atlas, const reflow_glyph_atlas_storage_t *storage)
Bind a Layer-3 glyph cache to the engine's render path (#164).
static ra8_err_t internal_init_faces(const reflow_t *engine, stbtt_fontinfo *faces, uint8_t *out_n)
Build the per-render stbtt_fontinfo set: default at 0, faces at 1..N.
static void internal_render_one_image(const reflow_t *engine, const reflow_image_box_t *box, int32_t ox, int32_t oy)
Render one image box: SVG-route or raster-decode at the page offset.
static void internal_render_images(const reflow_t *engine, uint32_t page_idx, int32_t ox, int32_t oy)
Decode and blit every laid-out image that belongs to one page.
static void internal_blit_alpha_mask(const reflow_glyph_t *g, const unsigned char *bitmap, int w, int h, int xoff, int yoff, int32_t ox, int32_t oy)
Walk one glyph bitmap and blit any sufficiently-covered pixels into the bound framebuffer.
static bool internal_glyph_render_cached(ra8_glyph_atlas_t *atlas, uint8_t face_id, const stbtt_fontinfo *font, float scale, const reflow_glyph_t *g, int w, int h, int x0, int y0, int32_t ox, int32_t oy)
Draw one glyph through the bound glyph atlas (cache hit or render-miss).
static void internal_draw_underline(const stbtt_fontinfo *font, const reflow_glyph_t *g, float scale, int32_t ox, int32_t oy)
Draw the underline strip for a link glyph.
priv_render_consts_t
Internal sizing knobs for the render pass.
@ k_priv_underline_offset_px
Pixels below baseline for the underline.
@ k_priv_glyph_mode_aa
Glyph-cache render mode: stb coverage AA.
@ k_priv_alpha_threshold
Coverage cutoff for binary blit.
@ k_priv_alpha_max_byte
Upper bound from stb's mask.
@ k_priv_svg_href_max
Max unwrapped SVG cover-image href length.
@ k_priv_underline_thick_px
Thickness of the anchor underline.
@ k_priv_glyph_dim_max
Mask edge bound = 2 * k_reflow_max_font_px.
static ra8_err_t internal_render_page(const reflow_t *engine, uint32_t page_idx, int32_t ox, int32_t oy)
Shared render body for one page, offsetting every element by (ox, oy).
ra8_err_t reflow_render_page_at(const reflow_t *engine, uint32_t page_idx, int32_t origin_x, int32_t origin_y)
Render one page offset by (origin_x, origin_y) into the bound framebuffer.
static void internal_render_svg(const reflow_t *engine, const uint8_t *svg, size_t len, int32_t x, int32_t y, int32_t w, int32_t h)
Render an SVG image box: unwrap a cover <image> href, else draw shapes.
Minimal SVG handling for the reflow ereader (#112).
ra8_err_t ra8_svg_image_href(const uint8_t *svg, size_t len, size_t *out_off, size_t *out_len)
Extract the href of a cover-wrapper <svg><image .../></svg>.
ra8_err_t ra8_svg_render(const uint8_t *svg, size_t len, int32_t x, int32_t y, int32_t w, int32_t h)
Render an SVG's vector shapes into a box.
bool ra8_svg_is_svg(const uint8_t *bytes, size_t len)
Heuristically decide whether bytes are an SVG document.
@ k_reflow_max_faces
Max embedded @font-face typefaces.
@ k_reflow_style_underline
Underlined run.
@ k_reflow_face_shift
Bit position of the face index in style.
@ k_reflow_face_mask
Face-index mask once shifted down.
Per-glyph state handed to the glyph-atlas render-on-miss callback.
const stbtt_fontinfo * font
Font for the in-flight glyph.
float scale
stb pixel-height scale for that glyph.
int h
Glyph bitmap height (from the box query).
int w
Glyph bitmap width (from the box query).
Caller-supplied storage + renderer for ra8_glyph_atlas_init.
Glyph-cache state (caller-owned; treat as private).
Identifies one rendered glyph.
uint16_t face_id
Font face identifier.
uint16_t mode
Render mode (AA / mono / hinting variant).
uint16_t size_px
Pixel size.
uint32_t glyph_id
Font glyph index.
A pinned view of a cached glyph bitmap returned by ra8_glyph_atlas_get.
const uint8_t * bitmap
Glyph coverage bitmap (width*height bytes).
uint16_t height
Glyph height in pixels.
uint16_t width
Glyph width in pixels.
const uint8_t * blob
TTF/OTF bytes; caller-owned, outlives engine.
size_t len
Length of blob, bytes.
Caller-owned backing storage for the render-path glyph cache (#164).
ra8_glyph_dims_t * dims
cell_count dimension descriptors.
ra8_glyph_key_t * keys
cell_count key-storage entries.
uint8_t * cell_mem
cell_count * cell_bytes of bitmap storage.
int32_t * buckets
bucket_count hash-bucket heads.
uint32_t cell_count
Number of cells (the glyph-cache budget).
ra8_keycache_cell_t * meta
cell_count link-metadata entries.
uint32_t cell_bytes
Bytes per cell (>= largest cached glyph).
uint32_t bucket_count
Number of hash buckets (>= 1).
One positioned glyph after layout.
uint8_t style
Font-style bitmask.
int32_t cp
Unicode code point.
uint32_t color
32-bit RGB colour.
int32_t x
Pixel column of glyph baseline-left.
uint16_t font_px
Pixel size used for this glyph.
int32_t y
Pixel row of glyph baseline.
One laid-out <img> rectangle (decoded + blitted at render time).
uint32_t src_len
Href slice length, bytes.
int32_t y
Page-local top edge, pixels.
int32_t x
Page-local left edge, pixels.
uint32_t page_index
Page this image belongs to.
int32_t w
Scaled box width, pixels.
uint32_t src_off
Href slice offset into text pool.
int32_t h
Scaled box height, pixels.
Index range of glyphs that belong to one page.
uint32_t glyph_count
Number of glyphs in this page.
uint32_t glyph_first
Index of first glyph in this page.
Reflow / pagination engine state.
uint32_t page_count
Pages used.
reflow_image_loader_fn img_loader
<img> byte loader (NULL = off).
const uint8_t * font_data
TTF blob; outlives the engine.
ra8_img_arena_t * img_arena
Decode scratch (NULL = off).
reflow_glyph_t glyphs[k_reflow_max_glyphs]
Positioned glyphs.
reflow_page_t pages[k_reflow_max_pages]
Page index ranges.
uint8_t text_pool[k_reflow_text_pool_bytes]
Text bytes.
reflow_face_t faces[k_reflow_max_faces]
Embedded @font-face set.
ra8_glyph_atlas_t * glyph_atlas
Glyph bitmap cache, or NULL for direct raster.
uint8_t in_use
1 = initialized, 0 = closed.
size_t font_len
Length of font_data, bytes.
void * img_loader_ctx
Opaque context for img_loader.
reflow_image_box_t image_boxes[k_reflow_max_images]
Laid-out images.
uint32_t image_box_count
Image boxes used.
uint8_t face_count
Embedded face count (0 = single-face).