ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
reflow_layout.c
Go to the documentation of this file.
1
31
32#include <stddef.h>
33#include <stdint.h>
34
35#include "ra8_attributes.h"
36#include "ra8_err.h"
37#include "reflow.h"
38#include "reflow_internal.h"
40#include "stb_truetype.h"
41
68{
69 return (tag == (uint8_t)k_reflow_tag_li) || (tag == (uint8_t)k_reflow_tag_blockquote);
70}
71
93 int32_t advance,
94 int32_t right_limit,
95 uint8_t line_has_content)
96{
97 return ((cursor_x + advance) > right_limit) && (line_has_content != 0U);
98}
99
115bool priv_reflow_internal_xhtml_invalid(const void* xhtml_buf, size_t xhtml_len)
116{
117 return (xhtml_buf == nullptr) || (xhtml_len == 0U);
118}
119
135bool priv_reflow_internal_final_page_needed(uint32_t page_count, uint32_t token_count)
136{
137 return (page_count == 0U) && (token_count > 0U);
138}
139
141void priv_reflow_layout_byte_zero(uint8_t* dst, size_t n)
142{
143 for (size_t i = 0U; i < n; ++i) {
144 dst[i] = 0U;
145 }
146}
147
148/* ===========================================================================
149 * Helpers
150 *
151 * The internal sizing constants (`priv_layout_consts_t`) and the mutable
152 * layout cursor (`priv_cursor_t`) are shared across the layout translation
153 * units and live in `reflow_layout_internal.h`.
154 * ===========================================================================
155 */
156
158ra8_err_t priv_reflow_layout_init_font(const reflow_t* engine, stbtt_fontinfo* out_font)
159{
160 const int32_t offset = stbtt_GetFontOffsetForIndex(engine->font_data, 0);
161 if (offset < 0) {
163 }
164 if (stbtt_InitFont(out_font, engine->font_data, (int)engine->font_len, offset) == 0) {
166 }
167 return k_ra8_ok;
168}
169
171uint16_t priv_reflow_layout_line_height(uint16_t font_px)
172{
173 const uint32_t lh =
174 ((uint32_t)font_px * (uint32_t)k_reflow_line_spacing_num) / (uint32_t)k_reflow_line_spacing_den;
175 return (uint16_t)lh;
176}
177
195static uint16_t internal_block_font_px(uint16_t body_px, reflow_html_tag_t tag)
196{
197 uint32_t pct = k_reflow_pct_full;
198 switch (tag) {
199 case k_reflow_tag_h1:
201 break;
202 case k_reflow_tag_h2:
204 break;
205 case k_reflow_tag_h3:
207 break;
208 case k_reflow_tag_h4:
210 break;
211 case k_reflow_tag_h5:
213 break;
214 case k_reflow_tag_h6:
216 break;
217 default:
218 pct = k_reflow_pct_full;
219 break;
220 }
221 return (uint16_t)(((uint32_t)body_px * pct) / k_reflow_pct_full);
222}
223
225int32_t priv_reflow_layout_glyph_advance(const stbtt_fontinfo* font, uint16_t font_px, int32_t cp)
226{
227 const float scale = stbtt_ScaleForPixelHeight(font, (float)font_px);
228 int advance_units = 0;
229 int lsb = 0;
230 stbtt_GetCodepointHMetrics(font, cp, &advance_units, &lsb);
231 return (int32_t)((float)advance_units * scale);
232}
233
236 int32_t x,
237 int32_t y,
238 int32_t cp,
239 uint16_t font_px,
240 uint8_t style,
241 uint32_t color,
242 uint8_t link_id)
243{
244 if (engine->glyph_count >= k_reflow_max_glyphs) {
245 return false;
246 }
247 reflow_glyph_t* g = &engine->glyphs[engine->glyph_count];
248 g->x = x;
249 g->y = y;
250 g->cp = cp;
251 g->color = color;
252 g->font_px = font_px;
253 g->style = style;
254 g->reserved = link_id; /* 1-based `<a>` link id (0 = not a link) */
255 engine->glyph_count++;
256 return true;
257}
258
261{
262 if (engine->page_count >= k_reflow_max_pages) {
263 return false;
264 }
265 const uint32_t count = engine->glyph_count - cur->page_first_glyph;
266 reflow_page_t* page = &engine->pages[engine->page_count];
267 page->glyph_first = cur->page_first_glyph;
268 page->glyph_count = count;
269 engine->page_count++;
270 cur->page_first_glyph = engine->glyph_count;
271 cur->page_first_image = engine->image_box_count;
272 cur->line_first_glyph = engine->glyph_count;
273 cur->y = (int32_t)k_reflow_margin_px;
274 cur->line_top = cur->y;
275 cur->x = (int32_t)k_reflow_margin_px + (int32_t)cur->indent_px;
276 cur->line_has_content = 0U;
277 return true;
278}
279
305static void internal_justify_glyphs(reflow_t* engine, uint32_t lo, uint32_t hi, int32_t slack)
306{
307 uint32_t spaces = 0U;
308 for (uint32_t i = lo; i < hi; ++i) {
309 if (engine->glyphs[i].cp == (int32_t)' ') {
310 spaces++;
311 }
312 }
313 if (spaces == 0U) {
314 return;
315 }
316 const int32_t per = slack / (int32_t)spaces;
317 const int32_t rem = slack % (int32_t)spaces;
318 int32_t added = 0;
319 uint32_t seen = 0U;
320 for (uint32_t i = lo; i < hi; ++i) {
321 engine->glyphs[i].x += added;
322 if (engine->glyphs[i].cp == (int32_t)' ') {
323 added += per;
324 if ((int32_t)seen < rem) {
325 added += 1;
326 }
327 seen++;
328 }
329 }
330}
331
358static void internal_finish_line(reflow_t* engine, priv_cursor_t* cur, bool allow_justify)
359{
360 if (cur->align == (uint8_t)k_reflow_align_left) {
361 return;
362 }
363 const uint32_t lo = cur->line_first_glyph;
364 uint32_t hi = engine->glyph_count;
365 if (hi <= lo) {
366 return;
367 }
368 int32_t content_right = cur->x;
369 if (engine->glyphs[hi - 1U].cp == (int32_t)' ') {
370 content_right = engine->glyphs[hi - 1U].x;
371 hi--;
372 }
373 const int32_t right_limit = (int32_t)engine->viewport_w - (int32_t)k_reflow_margin_px;
374 const int32_t slack = right_limit - content_right;
375 if ((hi <= lo) || (slack <= 0)) {
376 return;
377 }
378 if (cur->align == (uint8_t)k_reflow_align_justify) {
379 if (allow_justify) {
380 internal_justify_glyphs(engine, lo, hi, slack);
381 }
382 return;
383 }
384 const int32_t offset = (cur->align == (uint8_t)k_reflow_align_center) ? (slack / 2) : slack;
385 for (uint32_t i = lo; i < hi; ++i) {
386 engine->glyphs[i].x += offset;
387 }
388}
389
391bool priv_reflow_layout_newline(reflow_t* engine, priv_cursor_t* cur, bool allow_justify)
392{
393 internal_finish_line(engine, cur, allow_justify);
394 cur->y += (int32_t)cur->line_height_px;
395 cur->line_top = cur->y;
396 cur->x = (int32_t)k_reflow_margin_px + (int32_t)cur->indent_px;
397 cur->line_has_content = 0U;
398 cur->line_first_glyph = engine->glyph_count;
399
400 const int32_t bottom_limit = (int32_t)engine->viewport_h - (int32_t)k_reflow_margin_px;
401 if (cur->y + (int32_t)cur->line_height_px > bottom_limit) {
402 if (!priv_reflow_layout_finish_page(engine, cur)) {
403 return false;
404 }
405 }
406 return true;
407}
408
443 priv_cursor_t* cur,
444 const stbtt_fontinfo* font,
445 int32_t cp,
446 uint32_t color,
447 uint8_t link_id)
448{
449 const int32_t advance = priv_reflow_layout_glyph_advance(font, cur->active_font_px, cp);
450 const int32_t advance_clamped =
451 (advance < (int32_t)k_priv_min_word_w_px) ? (int32_t)k_priv_min_word_w_px : advance;
452
453 const int32_t right_limit = (int32_t)engine->viewport_w - (int32_t)k_reflow_margin_px;
455 advance_clamped,
456 right_limit,
457 cur->line_has_content)) {
458 if (!priv_reflow_layout_newline(engine, cur, true)) { /* wrap -> previous line may justify */
459 return k_ra8_err_no_mem;
460 }
461 }
463 cur->x,
464 cur->y,
465 cp,
466 cur->active_font_px,
467 cur->active_style,
468 color,
469 link_id)) {
470 return k_ra8_err_no_mem;
471 }
472 cur->x += advance_clamped;
473 cur->line_has_content = 1U;
474 return k_ra8_ok;
475}
476
497 priv_cursor_t* cur,
498 const stbtt_fontinfo* font,
499 const reflow_token_t* tok)
500{
501 const uint8_t* base = &engine->text_pool[tok->text_off];
502 const uint32_t len = tok->text_len;
503 const uint8_t link_id = tok->reserved; /* 1-based `<a>` link id (0 = none) */
504 /* Colour precedence: an explicit CSS `color` (#140) wins; otherwise a link run
505 * uses the link colour and ordinary text the body colour. Link colour is keyed
506 * on actual link membership, not the underline style bit, so CSS
507 * `text-decoration: underline` (#111) on non-link text keeps the body colour. */
508 const uint32_t fallback = (link_id != 0U) ? engine->link_color : engine->body_color;
509 const uint32_t color = (tok->color != (uint32_t)k_reflow_color_inherit) ? tok->color : fallback;
510
511 /* Pre-scan to find each word boundary. Greedy: if word_w + cursor_x
512 * exceeds the right margin AND the line already has content, break
513 * before emitting the word. */
514 uint32_t i = 0U;
515 while (i < len) {
516 /* Emit any leading whitespace as one space (already collapsed by
517 * the parser). */
518 if (base[i] == (uint8_t)' ') {
519 ra8_err_t err = internal_emit_char(engine, cur, font, ' ', color, link_id);
520 if (err != k_ra8_ok) {
521 return err;
522 }
523 ++i;
524 continue;
525 }
526
527 /* Word: bytes up to the next space. Pre-measure for greedy break. */
528 uint32_t word_end = i;
529 int32_t word_w = 0;
530 while ((word_end < len) && (base[word_end] != (uint8_t)' ')) {
531 word_w +=
532 priv_reflow_layout_glyph_advance(font, cur->active_font_px, (int32_t)base[word_end]);
533 ++word_end;
534 }
535 const int32_t right_limit = (int32_t)engine->viewport_w - (int32_t)k_reflow_margin_px;
537 word_w,
538 right_limit,
539 cur->line_has_content)) {
540 if (!priv_reflow_layout_newline(engine, cur, true)) { /* wrap -> previous line may justify */
541 return k_ra8_err_no_mem;
542 }
543 }
544 while (i < word_end) {
545 ra8_err_t err = internal_emit_char(engine, cur, font, (int32_t)base[i], color, link_id);
546 if (err != k_ra8_ok) {
547 return err;
548 }
549 ++i;
550 }
551 }
552 return k_ra8_ok;
553}
554
573static bool internal_open_block(reflow_t* engine, priv_cursor_t* cur, const reflow_token_t* tok)
574{
575 if (cur->line_has_content != 0U) {
576 if (!priv_reflow_layout_newline(engine, cur, false)) {
577 return false;
578 }
579 }
580 /* The block's text alignment travels in the block-start token's reserved byte
581 * (set by the tokenizer from `style="text-align:..."`). */
582 cur->align = tok->reserved;
583 /* Record an `id=` anchor (carried in the block-start token's slice) at this
584 * block's page + top, for same-chapter `#fragment` jumps. */
585 if ((tok->text_len > 0U) && (engine->anchor_count < (uint32_t)k_reflow_max_anchors)) {
586 reflow_anchor_t* anchor = &engine->anchors[engine->anchor_count];
587 anchor->id_off = tok->text_off;
588 anchor->id_len = tok->text_len;
589 anchor->page_index = engine->page_count;
590 anchor->y = cur->y;
591 engine->anchor_count++;
592 }
593 /* CSS `font-size` (#140) on the block-start token wins; else the UA default
594 * (body size or heading scale). 0 = no CSS font, so unstyled content is
595 * byte-identical. */
596 cur->active_font_px = (tok->css_font_px != 0U)
597 ? tok->css_font_px
600 if (priv_reflow_internal_is_indent_tag((uint8_t)tok->tag)) {
602 cur->x = (int32_t)k_reflow_margin_px + (int32_t)cur->indent_px;
603 }
604 return true;
605}
606
624static bool internal_close_block(reflow_t* engine, priv_cursor_t* cur, const reflow_token_t* tok)
625{
626 if (cur->line_has_content != 0U) {
627 if (!priv_reflow_layout_newline(engine, cur, false)) {
628 return false;
629 }
630 }
631 /* Paragraph gap. */
632 cur->y += (int32_t)k_reflow_paragraph_gap_px;
633 cur->line_top = cur->y;
634 cur->x = (int32_t)k_reflow_margin_px;
635 if (priv_reflow_internal_is_indent_tag((uint8_t)tok->tag)) {
636 cur->indent_px = 0U;
637 }
638 cur->active_font_px = engine->font_px;
640
641 const int32_t bottom_limit = (int32_t)engine->viewport_h - (int32_t)k_reflow_margin_px;
642 if (cur->y + (int32_t)cur->line_height_px > bottom_limit) {
643 if (!priv_reflow_layout_finish_page(engine, cur)) {
644 return false;
645 }
646 }
647 return true;
648}
649
667{
668 if (cur->line_has_content != 0U) {
669 if (!priv_reflow_layout_newline(engine, cur, false)) {
670 return false;
671 }
672 }
673 cur->y += (int32_t)k_priv_hr_thickness_px;
674 cur->line_top = cur->y;
675 return true;
676}
677
708 const stbtt_fontinfo* font,
709 uint32_t lo,
710 uint32_t hi,
711 uint8_t link,
712 uint32_t page)
713{
714 if (engine->link_rect_count >= (uint32_t)k_reflow_max_link_rects) {
715 return;
716 }
717 const reflow_glyph_t* gfirst = &engine->glyphs[lo];
718 const reflow_glyph_t* glast = &engine->glyphs[hi - 1U];
719 const int32_t fpx = (int32_t)gfirst->font_px;
720 const int32_t x1 = glast->x + priv_reflow_layout_glyph_advance(font, glast->font_px, glast->cp);
721 reflow_link_rect_t* rect = &engine->link_rects[engine->link_rect_count];
722 rect->x = gfirst->x;
723 rect->y = gfirst->y - fpx;
724 rect->w = (x1 > gfirst->x) ? (x1 - gfirst->x) : 1;
725 rect->h = fpx + (fpx / 2);
726 rect->target = (uint32_t)link - 1U; /* 1-based -> 0-based */
727 rect->page_index = page;
728 engine->link_rect_count++;
729}
730
732void priv_reflow_layout_build_link_rects(reflow_t* engine, const stbtt_fontinfo* font)
733{
734 for (uint32_t p = 0U; p < engine->page_count; ++p) {
735 const reflow_page_t* page = &engine->pages[p];
736 const uint32_t base = page->glyph_first;
737 uint32_t k = 0U;
738 while (k < page->glyph_count) {
739 const uint8_t link = engine->glyphs[base + k].reserved;
740 if (link == 0U) {
741 ++k;
742 continue;
743 }
744 const int32_t y = engine->glyphs[base + k].y;
745 uint32_t e = k + 1U;
746 while ((e < page->glyph_count) && (engine->glyphs[base + e].reserved == link) &&
747 (engine->glyphs[base + e].y == y)) {
748 ++e;
749 }
750 internal_emit_link_rect(engine, font, base + k, base + e, link, p);
751 k = e;
752 }
753 }
754}
755
758 priv_cursor_t* cur,
759 const stbtt_fontinfo* font,
760 const reflow_token_t* tok)
761{
762 /* Pack the per-run embedded-face index (stamped on the token by the cascade,
763 * #109) into the free high nibble of the style stamp; bits 0-2 keep the
764 * bold/italic/underline emphasis. Single-face content carries face 0, so the
765 * style byte is unchanged. */
766 cur->active_style =
767 (uint8_t)(tok->style | (uint8_t)(((uint32_t)tok->reserved16 & (uint32_t)k_reflow_face_mask)
768 << (uint32_t)k_reflow_face_shift));
769 switch (tok->kind) {
771 return internal_open_block(engine, cur, tok) ? k_ra8_ok : k_ra8_err_no_mem;
773 return internal_close_block(engine, cur, tok) ? k_ra8_ok : k_ra8_err_no_mem;
775 return internal_layout_text(engine, cur, font, tok);
777 return priv_reflow_layout_newline(engine, cur, false) ? k_ra8_ok : k_ra8_err_no_mem;
779 return internal_apply_rule(engine, cur) ? k_ra8_ok : k_ra8_err_no_mem;
781 return priv_reflow_layout_apply_image(engine, cur, tok) ? k_ra8_ok : k_ra8_err_no_mem;
782 default:
783 return k_ra8_ok;
784 }
785}
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_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
HTML / CSS reflow + paginate engine for the ra8d2 ereader.
Test-access surface for reflow internal helpers (MC/DC).
bool priv_reflow_layout_newline(reflow_t *engine, priv_cursor_t *cur, bool allow_justify)
Implementation of priv_reflow_layout_newline() – align, advance, page-break.
bool priv_reflow_internal_is_indent_tag(uint8_t tag)
Return true iff tag is a block-level indent tag.
static ra8_err_t internal_emit_char(reflow_t *engine, priv_cursor_t *cur, const stbtt_fontinfo *font, int32_t cp, uint32_t color, uint8_t link_id)
Append one ASCII code point at the current cursor, wrapping if it would overflow the right margin.
bool priv_reflow_internal_final_page_needed(uint32_t page_count, uint32_t token_count)
AND helper for the synthesise-final-page decision.
int32_t priv_reflow_layout_glyph_advance(const stbtt_fontinfo *font, uint16_t font_px, int32_t cp)
Implementation of priv_reflow_layout_glyph_advance() – scaled hmetrics.
void priv_reflow_layout_build_link_rects(reflow_t *engine, const stbtt_fontinfo *font)
Implementation of priv_reflow_layout_build_link_rects() – per-page link runs.
ra8_err_t priv_reflow_layout_apply_token(reflow_t *engine, priv_cursor_t *cur, const stbtt_fontinfo *font, const reflow_token_t *tok)
Implementation of priv_reflow_layout_apply_token() – per-token switch.
static bool internal_open_block(reflow_t *engine, priv_cursor_t *cur, const reflow_token_t *tok)
Apply a block_start token: flush current line, set heading font size, set indent.
static bool internal_close_block(reflow_t *engine, priv_cursor_t *cur, const reflow_token_t *tok)
Apply a block_end token: flush line + add paragraph gap.
static void internal_finish_line(reflow_t *engine, priv_cursor_t *cur, bool allow_justify)
Apply the active block alignment to the just-completed line.
bool priv_reflow_internal_xhtml_invalid(const void *xhtml_buf, size_t xhtml_len)
OR helper for the cached-XHTML invalid decision.
bool priv_reflow_layout_push_glyph(reflow_t *engine, int32_t x, int32_t y, int32_t cp, uint16_t font_px, uint8_t style, uint32_t color, uint8_t link_id)
Implementation of priv_reflow_layout_push_glyph() – append + bounds check.
static ra8_err_t internal_layout_text(reflow_t *engine, priv_cursor_t *cur, const stbtt_fontinfo *font, const reflow_token_t *tok)
Lay out one text token: walk byte-by-byte, breaking at whitespace, and emit each character through in...
static void internal_justify_glyphs(reflow_t *engine, uint32_t lo, uint32_t hi, int32_t slack)
Spread slack across the inter-word gaps of glyphs [lo, hi).
static bool internal_apply_rule(reflow_t *engine, priv_cursor_t *cur)
Apply a <hr> rule token: flush the line and bump the cursor.
bool priv_reflow_layout_finish_page(reflow_t *engine, priv_cursor_t *cur)
Implementation of priv_reflow_layout_finish_page() – flush + reset cursor.
void priv_reflow_layout_byte_zero(uint8_t *dst, size_t n)
Implementation of priv_reflow_layout_byte_zero() – bounded byte-walk.
static uint16_t internal_block_font_px(uint16_t body_px, reflow_html_tag_t tag)
Pick the font size for a given block tag.
ra8_err_t priv_reflow_layout_init_font(const reflow_t *engine, stbtt_fontinfo *out_font)
Implementation of priv_reflow_layout_init_font() – parse the TTF blob.
static void internal_emit_link_rect(reflow_t *engine, const stbtt_fontinfo *font, uint32_t lo, uint32_t hi, uint8_t link, uint32_t page)
Record one tappable link rect spanning glyphs [lo, hi).
bool priv_reflow_internal_right_overflow_break(int32_t cursor_x, int32_t advance, int32_t right_limit, uint8_t line_has_content)
AND helper for the right-margin overflow break decision.
uint16_t priv_reflow_layout_line_height(uint16_t font_px)
Implementation of priv_reflow_layout_line_height() – scaled integer ratio.
bool priv_reflow_layout_apply_image(reflow_t *engine, priv_cursor_t *cur, const reflow_token_t *tok)
Apply an <img> token: real image when a loader is bound, else a placeholder.
Cross-TU shared declarations for the reflow layout engine.
@ k_priv_min_word_w_px
Minimum word width before forcing a break.
@ k_priv_hr_thickness_px
Pixel thickness of an <hr> (placeholder).
reflow_html_tag_t
Recognised HTML element kinds.
@ k_reflow_tag_blockquote
Blockquote indent.
@ k_reflow_tag_h5
Heading level 5.
@ k_reflow_tag_h1
Heading level 1.
@ k_reflow_tag_h4
Heading level 4.
@ k_reflow_tag_li
List item.
@ k_reflow_tag_h2
Heading level 2.
@ k_reflow_tag_h6
Heading level 6.
@ k_reflow_tag_h3
Heading level 3.
@ k_reflow_color_inherit
No per-run CSS colour.
@ k_reflow_max_anchors
Max id= anchor positions.
@ k_reflow_max_link_rects
Max positioned link rectangles.
@ k_reflow_max_glyphs
Total positioned glyphs.
@ k_reflow_max_pages
Max paginated pages.
@ k_reflow_paragraph_gap_px
Vertical gap after a block.
@ k_reflow_margin_px
Page edge inset, pixels.
@ k_reflow_h6_scale_pct
H6 size = 100 % of body.
@ k_reflow_h2_scale_pct
H2 size = 175 % of body.
@ k_reflow_h5_scale_pct
H5 size = 110 % of body.
@ k_reflow_h1_scale_pct
H1 size = 200 % of body.
@ k_reflow_h4_scale_pct
H4 size = 125 % of body.
@ k_reflow_h3_scale_pct
H3 size = 150 % of body.
@ k_reflow_line_spacing_den
Line height denominator.
@ k_reflow_line_spacing_num
Line height numerator (= 1.2x).
@ k_reflow_indent_px
Indent for blockquote / li.
@ k_reflow_pct_full
Percentage denominator.
@ k_reflow_align_center
Centred.
@ k_reflow_align_justify
Justified (last line left-aligned).
@ k_reflow_align_left
Left (default, ragged right).
@ k_reflow_tok_block_end
Close of a block-flow element.
@ k_reflow_tok_break
Forced line break (<br>).
@ k_reflow_tok_image
Image placeholder (<img>).
@ k_reflow_tok_text
Text run (slice into pool).
@ k_reflow_tok_block_start
Open of a block-flow element.
@ k_reflow_tok_rule
Horizontal rule (<hr>).
@ k_reflow_face_shift
Bit position of the face index in style.
@ k_reflow_face_mask
Face-index mask once shifted down.
Mutable state carried through the layout loop.
uint32_t page_first_image
First image-box index of the active page.
uint8_t line_has_content
1 once any glyph landed on this line.
int32_t line_top
Pixel row of the current line's top.
uint16_t active_font_px
Active font size (body or heading).
uint32_t page_first_glyph
First glyph index of the active page.
int32_t x
Pixel column for next glyph.
uint32_t line_first_glyph
First glyph index of the active line.
uint16_t line_height_px
Active line height in pixels.
int32_t y
Pixel row baseline for next glyph.
uint8_t align
Active block alignment (reflow_align_t).
uint16_t indent_px
Active left indent (li, blockquote).
uint8_t active_style
Active inline-style stamp.
A laid-out element id, for same-chapter #fragment jumps.
uint32_t page_index
Page the id landed on.
uint32_t id_len
Id slice length, bytes.
uint32_t id_off
Id slice offset into the text pool.
int32_t y
Page-local top y of the element.
One positioned glyph after layout.
uint8_t style
Font-style bitmask.
uint8_t reserved
Padding.
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.
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.
const uint8_t * font_data
TTF blob; outlives the engine.
uint32_t link_color
Anchor text colour (0xRRGGBB).
reflow_glyph_t glyphs[k_reflow_max_glyphs]
Positioned glyphs.
uint32_t glyph_count
Glyphs used.
reflow_link_rect_t link_rects[k_reflow_max_link_rects]
Tappable rects.
reflow_page_t pages[k_reflow_max_pages]
Page index ranges.
uint8_t text_pool[k_reflow_text_pool_bytes]
Text bytes.
reflow_anchor_t anchors[k_reflow_max_anchors]
id= anchor positions.
size_t font_len
Length of font_data, bytes.
uint16_t font_px
Body font size in pixels.
uint16_t viewport_w
Viewport width, pixels.
uint32_t anchor_count
Anchor positions used.
uint16_t viewport_h
Viewport height, pixels.
uint32_t body_color
Body text colour (0xRRGGBB).
uint32_t image_box_count
Image boxes used.
uint32_t link_rect_count
Link rects used.
One parsed token in the engine's token stream.
uint16_t css_font_px
Block-start CSS font px (0 = none -> UA default).
uint32_t text_off
Byte offset into the text pool.
uint32_t text_len
Byte length within the text pool.
uint32_t color
0xRRGGBB CSS colour, or k_reflow_color_inherit.
uint8_t kind
reflow_token_kind_t.
uint8_t tag
reflow_html_tag_t (0 if N/A).
uint8_t style
Font-style bitmask.
uint16_t reserved16
Padding to 4-byte stride.
uint8_t reserved
Block align / <a> link id.