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

Minimal content-CSS cascade for the reflow ereader engine (#111). More...

#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for reflow_css.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_css_style_t
 A declared or computed style: a presence mask plus property values. More...
struct  ra8_css_anc_t
 One ancestor part of a descendant selector (e.g. More...
struct  ra8_css_rule_t
 One selector { ... } rule: a (possibly descendant) selector plus its declarations. More...
struct  ra8_css_fontface_t
 One parsed @font-face rule: family + weight/style + src href. More...
struct  ra8_css_sheet_t
 A parsed stylesheet: rule + @font-face arrays and a name byte pool. More...
struct  ra8_css_element_t
 The identity of one element, used to match selectors. More...

Enumerations

enum  ra8_css_limits_t : uint16_t {
  k_ra8_css_max_rules = 128U ,
  k_ra8_css_name_pool = 2048U ,
  k_ra8_css_max_classes = 8U ,
  k_ra8_css_name_max = 64U ,
  k_ra8_css_max_faces = 16U ,
  k_ra8_css_max_anc = 4U
}
 Static-allocation caps for one parsed stylesheet. More...
enum  ra8_css_face_match_t : int16_t { k_ra8_css_no_face = -1 }
 Sentinel for ra8_css_match_face when no @font-face entry matches. More...
enum  ra8_css_set_t : uint8_t {
  k_ra8_css_set_bold = 1U << 0U ,
  k_ra8_css_set_italic = 1U << 1U ,
  k_ra8_css_set_underline = 1U << 2U ,
  k_ra8_css_set_align = 1U << 3U ,
  k_ra8_css_set_color = 1U << 4U ,
  k_ra8_css_set_fontsize = 1U << 5U ,
  k_ra8_css_set_display = 1U << 6U ,
  k_ra8_css_set_family = 1U << 7U
}
 Which properties a declaration block actually set (presence bits). More...
enum  ra8_css_font_unit_t : uint8_t {
  k_ra8_css_font_px = 0U ,
  k_ra8_css_font_pct = 1U
}
 How a declared font-size value is interpreted. More...

Functions

ra8_err_t ra8_css_sheet_reset (ra8_css_sheet_t *sheet)
 Reset a stylesheet to empty (no rules, no names, order 0).
ra8_err_t ra8_css_parse (ra8_css_sheet_t *sheet, const char *css, uint32_t len)
 Parse one <style> block's CSS text, appending rules to sheet.
ra8_err_t ra8_css_parse_inline (const char *decls, uint32_t len, ra8_css_style_t *out)
 Parse an inline style="..." declaration body into one style.
bool ra8_css_rule_matches (const ra8_css_rule_t *rule, const ra8_css_element_t *el, const ra8_css_sheet_t *sheet)
 Test whether rule rule's selector matches element el.
ra8_css_style_t ra8_css_cascade (const ra8_css_sheet_t *sheet, const ra8_css_element_t *el, ra8_css_style_t inherited, ra8_css_style_t inline_decl)
 Compute an element's cascaded style.
ra8_css_style_t ra8_css_cascade_ctx (const ra8_css_sheet_t *sheet, const ra8_css_element_t *el, ra8_css_style_t inherited, ra8_css_style_t inline_decl, const ra8_css_element_t *ancestors, uint8_t n_anc)
 Compute an element's cascaded style with descendant-selector context.
int16_t ra8_css_match_face (const ra8_css_sheet_t *sheet, const char *family, uint16_t family_len, bool want_bold, bool want_italic)
 Pick the @font-face whose family + emphasis best fits a run.
bool ra8_css_face_src (const ra8_css_sheet_t *sheet, uint16_t idx, const char **out_src, uint16_t *out_len)
 Read a parsed @font-face entry's src href bytes.

Detailed Description

Minimal content-CSS cascade for the reflow ereader engine (#111).

A small, hand-written, zero-allocation CSS subset that lets EPUB content style itself. It sits inside apps/shared_libs/reflow as a peer of the HTML tokenizer: the tokenizer feeds <style> block text and inline style="..." attribute values in, and asks this module for the computed style of each element it opens.

Supported subset (v1)

  • Selectors (comma-grouped): * (universal), tag (type), .class, #id, compound (p.note), and descendant (div p, .chapter p, .a .b, up to k_ra8_css_max_anc ancestor parts). Multiple classes per compound (.a.b), child/sibling combinators and pseudo selectors are skipped (no match, no crash) – a documented limitation, not an error.
  • Properties (the ones that fold onto reflow's existing per-run style bits + per-block alignment, so no layout change is needed): font-weight (bold / normal), font-style (italic / normal), text-decoration (underline / none), text-align (left / right / center / justify).
  • Cascade: specificity rank id > class > type > universal; ties broken by source order (later wins); inline style="" beats every rule; inheritable properties (all four of the above) flow from parent to child.

color, font-size, display:none and external/linked stylesheets are out of v1 scope and tracked as follow-ups.

The module is pure (no MMIO, no allocation): a parsed ra8_css_sheet_t and the cascade are trivially host-unit-testable with MC/DC.

Tag / alignment / font-style values are carried as raw uint8_t (storage of reflow_html_tag_t, reflow_align_t, reflow_font_style_t) so this header stays free of a circular include back into reflow.h.

[Ring 4 / Reflow] {World: NS}

Since
0.1.0

Definition in file reflow_css.h.

Enumeration Type Documentation

◆ ra8_css_face_match_t

enum ra8_css_face_match_t : int16_t

Sentinel for ra8_css_match_face when no @font-face entry matches.

Enumerator
k_ra8_css_no_face 

No @font-face matched the requested family.

Definition at line 78 of file reflow_css.h.

◆ ra8_css_font_unit_t

enum ra8_css_font_unit_t : uint8_t

How a declared font-size value is interpreted.

em is normalised to a percentage at parse time (1em = 100%), so the engine only ever stores absolute pixels or a percentage of the inherited size.

Enumerator
k_ra8_css_font_px 

Value is an absolute pixel size.

k_ra8_css_font_pct 

Value is a percentage of inherited px.

Definition at line 108 of file reflow_css.h.

◆ ra8_css_limits_t

enum ra8_css_limits_t : uint16_t

Static-allocation caps for one parsed stylesheet.

Sized for the small author stylesheets EPUB chapters ship; anything larger is silently truncated (extra rules / names dropped), never an error.

Enumerator
k_ra8_css_max_rules 

Max rules kept across all <style> blocks.

k_ra8_css_name_pool 

Bytes of class / id / font name storage.

k_ra8_css_max_classes 

Max classes matched per element.

k_ra8_css_name_max 

Max bytes of one class / id / font name.

k_ra8_css_max_faces 

Max @font-face rules kept per sheet.

k_ra8_css_max_anc 

Max descendant-ancestor parts per selector.

Definition at line 65 of file reflow_css.h.

◆ ra8_css_set_t

enum ra8_css_set_t : uint8_t

Which properties a declaration block actually set (presence bits).

A property absent from this mask is "not declared" and so does not participate in the cascade for that rule (letting a lower-priority rule or the inherited value show through).

Enumerator
k_ra8_css_set_bold 

font-weight was declared.

k_ra8_css_set_italic 

font-style was declared.

k_ra8_css_set_underline 

text-decoration was declared.

k_ra8_css_set_align 

text-align was declared.

k_ra8_css_set_color 

color was declared.

k_ra8_css_set_fontsize 

font-size was declared.

k_ra8_css_set_display 

display was declared.

k_ra8_css_set_family 

font-family was declared.

Definition at line 90 of file reflow_css.h.

Function Documentation

◆ ra8_css_cascade()

ra8_css_style_t ra8_css_cascade ( const ra8_css_sheet_t * sheet,
const ra8_css_element_t * el,
ra8_css_style_t inherited,
ra8_css_style_t inline_decl )
nodiscard

Compute an element's cascaded style.

Folds, in increasing priority: inherited (inheritable properties only), every matching rule in sheet by (specificity, source order), then inline_decl (always wins). Each property resolves independently to its highest-priority setter.

Parameters
[in]sheetParsed stylesheet (may be empty).
[in]elElement identity.
[in]inheritedParent's computed style (inheritable props flow in).
[in]inline_declInline style="" declaration (set == 0 if none).
Returns
The computed ra8_css_style_t for el.
Precondition
sheet, el non-NULL (NULL sheet/el -> returns inherited).
None.
Postcondition
Every property bit in the result was set by the winning source.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 686 of file reflow_css_cascade.c.

References ra8_css_cascade_ctx().

◆ ra8_css_cascade_ctx()

ra8_css_style_t ra8_css_cascade_ctx ( const ra8_css_sheet_t * sheet,
const ra8_css_element_t * el,
ra8_css_style_t inherited,
ra8_css_style_t inline_decl,
const ra8_css_element_t * ancestors,
uint8_t n_anc )
nodiscard

Compute an element's cascaded style with descendant-selector context.

Identical to ra8_css_cascade but also resolves descendant selectors (.chapter p, div p): a rule with ancestor parts matches only when its subject matches el AND each ancestor part matches some element in ancestors (the open-element stack, outermost first), in order. ra8_css_cascade is the n_anc == 0 case (descendant rules never match without ancestor context). Each matched ancestor part also adds to the rule's specificity.

Parameters
[in]sheetParsed stylesheet (may be empty).
[in]elElement identity (the selector subject).
[in]inheritedParent's computed style (inheritable props flow in).
[in]inline_declInline style="" declaration (set == 0 if none).
[in]ancestorsOpen-element ancestors, outermost (root) first; may be NULL iff n_anc is 0.
[in]n_ancNumber of entries in ancestors (0 = no context).
Returns
The computed ra8_css_style_t for el.
Precondition
sheet, el non-NULL (NULL -> returns inherited).
ancestors non-NULL when n_anc > 0.
Postcondition
Every property bit in the result was set by the winning source.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 664 of file reflow_css_cascade.c.

References internal_cascade_emphasis(), internal_cascade_family(), internal_cascade_scalars(), internal_rule_matches_ctx(), k_ra8_css_max_rules, ra8_css_sheet_t::rule_count, and ra8_css_sheet_t::rules.

Referenced by internal_open_styled(), and ra8_css_cascade().

◆ ra8_css_face_src()

bool ra8_css_face_src ( const ra8_css_sheet_t * sheet,
uint16_t idx,
const char ** out_src,
uint16_t * out_len )
nodiscard

Read a parsed @font-face entry's src href bytes.

Returns the de-url()-wrapped manifest href slice for face idx (the value ra8_css_match_face's result indexes), so the caller can resolve it against the EPUB manifest. The bytes live in sheet's name pool and are valid for the sheet's lifetime; they are not NUL-terminated.

Parameters
[in]sheetParsed stylesheet owning the face table.
[in]idxFace index in [0, face_count).
[out]out_srcReceives a pointer to the href bytes.
[out]out_lenReceives the href length, bytes.
Returns
true iff idx is valid and the href was returned.
Return values
falseA NULL pointer, or idx out of range.
Precondition
sheet, out_src, out_len non-NULL.
None.
Postcondition
On true, *out_src/*out_len describe the face's href; else unchanged.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 799 of file reflow_css_cascade.c.

References ra8_css_sheet_t::face_count, ra8_css_sheet_t::faces, ra8_css_sheet_t::names, ra8_css_fontface_t::src_len, and ra8_css_fontface_t::src_off.

◆ ra8_css_match_face()

int16_t ra8_css_match_face ( const ra8_css_sheet_t * sheet,
const char * family,
uint16_t family_len,
bool want_bold,
bool want_italic )
nodiscard

Pick the @font-face whose family + emphasis best fits a run.

Scans sheet's parsed @font-face table for entries whose font-family equals family (case-insensitive, exact). Among those it prefers an exact (weight, style) match; failing that it falls back to the family's regular (non-bold, non-italic) face; failing that it reports k_ra8_css_no_face so the caller uses its default face. This is the face-selection decision #109's remainder consumes (it then resolves the winning entry's ra8_css_face_src href to a loaded typeface).

Parameters
[in]sheetParsed stylesheet (its faces table is scanned).
[in]familyResolved font-family bytes (e.g. a cascade result's name slice); need not be NUL-terminated.
[in]family_lenLength of family, bytes.
[in]want_boldWhether the run is bold.
[in]want_italicWhether the run is italic.
Returns
The matching faces index in [0, face_count), or k_ra8_css_no_face.
Precondition
sheet, family non-NULL and family_len > 0 (else no match).
None.
Postcondition
No state modified.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 771 of file reflow_css_cascade.c.

References ra8_css_sheet_t::face_count, ra8_css_sheet_t::faces, internal_family_eq(), k_ra8_css_no_face, ra8_css_fontface_t::style_italic, and ra8_css_fontface_t::weight_bold.

Referenced by priv_reflow_tok_resolve_face_slot().

◆ ra8_css_parse()

ra8_err_t ra8_css_parse ( ra8_css_sheet_t * sheet,
const char * css,
uint32_t len )
nodiscard

Parse one <style> block's CSS text, appending rules to sheet.

Handles /<star> comments <star>/, comma-grouped simple selectors, and the v1 property set. Unsupported selectors (compound / descendant / pseudo) and unknown properties are skipped, not errored. Rules beyond k_ra8_css_max_rules (or names beyond the pool) are dropped silently.

Parameters
[in,out]sheetStylesheet to grow.
[in]cssCSS source bytes (a <style> block body).
[in]lenLength of css, bytes.
Returns
ra8_err_t
Return values
k_ra8_okParsed (possibly with truncation).
k_ra8_err_null_ptrsheet or css is NULL.
Precondition
sheet, css non-NULL.
None.
Postcondition
New rules (if any room) are appended with ascending order.
sheet->rule_count never exceeds k_ra8_css_max_rules.
Note
Pure aside from writing sheet.
Since
0.1.0

Definition at line 167 of file reflow_css_cascade.c.

References internal_find_block(), internal_skip_comment(), k_ra8_err_null_ptr, k_ra8_ok, priv_reflow_css_is_ws(), and priv_reflow_css_parse_one_block().

Referenced by internal_handle_link(), and internal_handle_raw_text().

◆ ra8_css_parse_inline()

ra8_err_t ra8_css_parse_inline ( const char * decls,
uint32_t len,
ra8_css_style_t * out )
nodiscard

Parse an inline style="..." declaration body into one style.

Same property grammar as ra8_css_parse but with no selector and no braces – just prop: value; prop: value. The result carries the inline declaration; the caller applies it at the highest specificity.

Parameters
[in]declsDeclaration bytes (the style attribute value).
[in]lenLength of decls, bytes.
[out]outReceives the parsed declaration (set == 0 if empty).
Returns
ra8_err_t
Return values
k_ra8_okParsed (possibly empty).
k_ra8_err_null_ptrdecls or out is NULL.
Precondition
decls, out non-NULL.
None.
Postcondition
*out holds only the properties present in decls.
Unknown properties leave their set bit clear.
Note
Pure aside from writing out.
Since
0.1.0

Definition at line 805 of file reflow_css.c.

References k_ra8_err_null_ptr, k_ra8_ok, and priv_reflow_css_parse_decls().

Referenced by priv_reflow_tok_css_inline().

◆ ra8_css_rule_matches()

bool ra8_css_rule_matches ( const ra8_css_rule_t * rule,
const ra8_css_element_t * el,
const ra8_css_sheet_t * sheet )
nodiscard

Test whether rule rule's selector matches element el.

Parameters
[in]ruleRule whose selector is tested.
[in]elElement identity (tag + id + class list).
[in]sheetSheet owning the rule's name pool.
Returns
true iff the simple selector matches el.
Return values
falseA required pointer is NULL, or the selector does not match.
Precondition
rule, el, sheet non-NULL (NULL -> false).
None.
Postcondition
No state modified.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 259 of file reflow_css_cascade.c.

References ra8_css_element_t::class_len, ra8_css_rule_t::class_len, ra8_css_rule_t::class_off, ra8_css_element_t::class_str, ra8_css_element_t::id, ra8_css_element_t::id_len, ra8_css_rule_t::id_len, ra8_css_rule_t::id_off, internal_class_list_has(), k_reflow_tag_unknown, ra8_css_sheet_t::names, ra8_css_rule_t::sel_tag, and ra8_css_element_t::tag.

Referenced by internal_rule_matches_ctx().

◆ ra8_css_sheet_reset()

ra8_err_t ra8_css_sheet_reset ( ra8_css_sheet_t * sheet)
nodiscard

Reset a stylesheet to empty (no rules, no names, order 0).

Parameters
[out]sheetStylesheet to clear.
Returns
ra8_err_t
Return values
k_ra8_okCleared.
k_ra8_err_null_ptrsheet is NULL.
Precondition
sheet is non-NULL.
None.
Postcondition
sheet->rule_count == 0 and sheet->names_used == 0.
sheet->next_order == 0.
Note
Pure aside from writing sheet; not thread-safe relative to it.
Since
0.1.0

Definition at line 72 of file reflow_css_cascade.c.

References ra8_css_sheet_t::face_count, k_ra8_err_null_ptr, k_ra8_ok, ra8_css_sheet_t::names_used, ra8_css_sheet_t::next_order, and ra8_css_sheet_t::rule_count.

Referenced by priv_reflow_xml_walk().