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

Content-CSS stylesheet scanner, cascade, and face lookup (#111). More...

#include <stddef.h>
#include <string.h>
#include "ra8_attributes.h"
#include "reflow.h"
#include "reflow_css.h"
#include "reflow_css_internal.h"
Include dependency graph for reflow_css_cascade.c:

Go to the source code of this file.

Enumerations

enum  priv_css_consts_t : uint16_t {
  k_priv_rank_inherited = 0U ,
  k_priv_spec_type = 1U ,
  k_priv_spec_class = 100U ,
  k_priv_spec_id = 10000U
}
 Cascade specificity weights (packed id > class > type > universal). More...
enum  priv_css_scan_t : uint8_t { k_priv_cmt_marker = 2U }
 Token lengths used by the top-level stylesheet scanner. 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).
static size_t internal_skip_comment (const char *css, size_t len, size_t start)
 Step over a C-style comment starting at start.
static bool internal_find_block (const char *css, size_t len, size_t i, size_t *out_open, size_t *out_close)
 Locate the { ... } block beginning at selector offset i.
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.
static bool internal_class_list_has (const char *list, size_t list_len, const char *name, size_t nlen)
 True iff a space-separated class list contains name exactly.
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.
static bool internal_anc_matches (const ra8_css_anc_t *anc, const ra8_css_element_t *el, const ra8_css_sheet_t *sheet)
 True if descendant ancestor part anc matches element el.
static bool internal_rule_matches_ctx (const ra8_css_rule_t *rule, const ra8_css_element_t *el, const ra8_css_element_t *ancestors, uint8_t n_anc, const ra8_css_sheet_t *sheet)
 Full match of a (possibly descendant) rule against el + ancestors.
static uint16_t internal_rule_rank (const ra8_css_rule_t *rule)
 Packed specificity (id*10000 + class*100 + type), summing all parts.
static const ra8_css_style_tinternal_resolve (uint8_t setbit, const ra8_css_style_t *inherited, const ra8_css_sheet_t *sheet, const bool *matched, const ra8_css_style_t *inl)
 Resolve the winning declaration for one property across all sources.
static void internal_cascade_emphasis (ra8_css_style_t *out, const ra8_css_sheet_t *sheet, const bool *matched, const ra8_css_style_t *inherited, const ra8_css_style_t *inl)
 Resolve the bold / italic / underline emphasis bits into out.
static void internal_cascade_scalars (ra8_css_style_t *out, const ra8_css_sheet_t *sheet, const bool *matched, const ra8_css_style_t *inherited, const ra8_css_style_t *inl)
 Resolve the scalar properties (align / colour / font-size / display).
static void internal_cascade_family (ra8_css_style_t *out, const ra8_css_sheet_t *sheet, const bool *matched, const ra8_css_style_t *inherited, const ra8_css_style_t *inl)
 Resolve the inherited font-family slice into out.
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.
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.
static bool internal_ci_eq_span (const char *a, size_t alen, const char *b, size_t blen)
 Case-insensitive equality of two byte spans.
static bool internal_family_eq (const ra8_css_sheet_t *sheet, const ra8_css_fontface_t *f, const char *family, size_t family_len)
 True iff face f's family equals family (case-insensitive).
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

Content-CSS stylesheet scanner, cascade, and face lookup (#111).

The top-level stylesheet scanner (ra8_css_parse, comment + block skipping), the selector-matching and specificity cascade, and the @font-face lookup API for the v1 CSS subset documented in reflow_css.h. The scanner walks selector { ... } blocks and hands each to priv_reflow_css_parse_one_block in a sibling translation unit; the cascade resolves inherited / rule / inline sources into a single ra8_css_style_t. No MMIO, no heap; all state lives in the caller-owned ra8_css_sheet_t.

[Ring 4 / Reflow] {World: NS}

Since
0.1.0

Definition in file reflow_css_cascade.c.

Enumeration Type Documentation

◆ priv_css_consts_t

enum priv_css_consts_t : uint16_t

Cascade specificity weights (packed id > class > type > universal).

A rule's specificity is the sum of one weight per present constraint (id + class + type), each at most 1 in our compound model; the packed value orders the cascade. Inheritance is the lowest priority (weight 0); a universal selector (no constraints) is also 0 but beats inheritance on source order.

Enumerator
k_priv_rank_inherited 

Inheritance / universal weight.

k_priv_spec_type 

A type constraint adds this.

k_priv_spec_class 

A class constraint adds this.

k_priv_spec_id 

An id constraint adds this.

Definition at line 45 of file reflow_css_cascade.c.

◆ priv_css_scan_t

enum priv_css_scan_t : uint8_t

Token lengths used by the top-level stylesheet scanner.

Stand-ins for the / + * comment delimiters so the parse loop carries no bare numeric literals when stepping over comments and blocks.

Invariant
k_priv_cmt_marker is the byte count of / + * (or * + /).
See also
ra8_css_parse
Since
0.1.0
Enumerator
k_priv_cmt_marker 

Byte length of a CSS comment delimiter pair.

Definition at line 63 of file reflow_css_cascade.c.

Function Documentation

◆ internal_anc_matches()

bool internal_anc_matches ( const ra8_css_anc_t * anc,
const ra8_css_element_t * el,
const ra8_css_sheet_t * sheet )
static

True if descendant ancestor part anc matches element el.

Checks each non-zero constraint field of anc against el:

  • tag: el->tag must equal anc->tag when the tag is not unknown.
  • class_len: el->class_str must contain the interned class name via internal_class_list_has().
  • id_len: el->id must equal the interned id byte for byte. Returns true only when all present constraints match. An anc with all fields zero (universal) always returns true.
Parameters
[in]ancAncestor constraint part to test.
[in]elElement to test the constraint against.
[in]sheetSheet owning the name pool for interned class/id names.
Returns
bool Whether anc matches el.
Return values
trueAll constraints in anc are satisfied by el.
falseAt least one constraint in anc is not satisfied.
Precondition
anc, el, and sheet are non-NULL.
Class/id offsets in anc are valid indices into sheet->names.
Postcondition
No state is mutated; the function is pure.
anc, el, and sheet are not modified.
Note
Thread-safe; pure function with no shared mutable state.
Since
0.1.0

Definition at line 320 of file reflow_css_cascade.c.

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

Referenced by internal_rule_matches_ctx().

◆ internal_cascade_emphasis()

void internal_cascade_emphasis ( ra8_css_style_t * out,
const ra8_css_sheet_t * sheet,
const bool * matched,
const ra8_css_style_t * inherited,
const ra8_css_style_t * inl )
static

Resolve the bold / italic / underline emphasis bits into out.

Iterates over a fixed table of three emphasis properties (bold, italic, underline) and calls internal_resolve() for each to find the winning style source. When a winner is found, the corresponding set bit is OR'd into out->set and the style bit is conditionally OR'd into out->style based on the winner's style field. The table has a statically known size of 3, making the loop provably bounded.

Parameters
[in,out]outStyle record to write the resolved emphasis bits into.
[in]sheetSheet providing the matching rules.
[in]matchedBoolean array parallel to sheet->rules[]; true for each rule that matched the current element.
[in]inheritedStyle inherited from the parent element.
[in]inlInline style from the element's style attribute.
Returns
Nothing.
Precondition
out, sheet, matched, inherited, and inl are non-NULL.
matched has at least sheet->rule_count elements.
Postcondition
out->set and out->style have the resolved emphasis bits written.
inherited and inl are not modified.
Note
Thread-safe with respect to distinct out instances.
Since
0.1.0

< Setbit.

< Stylebit.

Definition at line 531 of file reflow_css_cascade.c.

References internal_resolve(), k_ra8_css_set_bold, k_ra8_css_set_italic, k_ra8_css_set_underline, k_reflow_style_bold, k_reflow_style_italic, k_reflow_style_underline, ra8_css_style_t::set, and ra8_css_style_t::style.

Referenced by ra8_css_cascade_ctx().

◆ internal_cascade_family()

void internal_cascade_family ( ra8_css_style_t * out,
const ra8_css_sheet_t * sheet,
const bool * matched,
const ra8_css_style_t * inherited,
const ra8_css_style_t * inl )
static

Resolve the inherited font-family slice into out.

Calls internal_resolve() for the k_ra8_css_set_family property and, when a winning style is found, copies (family_off, family_len) from the winner into out and OR's k_ra8_css_set_family into out->set. The family name itself lives in the sheet's name pool and is referenced by offset and length; no string copy is performed.

Parameters
[in,out]outStyle record to write the resolved family reference into.
[in]sheetSheet providing the matching rules and name pool.
[in]matchedBoolean array parallel to sheet->rules[]; true for each rule that matched the current element.
[in]inheritedStyle inherited from the parent element.
[in]inlInline style from the element's style attribute.
Returns
Nothing.
Precondition
out, sheet, matched, inherited, and inl are non-NULL.
matched has at least sheet->rule_count elements.
Postcondition
When a winning font-family source exists, out->family_off and out->family_len are set and k_ra8_css_set_family is OR'd into out->set.
inherited and inl are not modified.
Note
Thread-safe with respect to distinct out instances.
Since
0.1.0

Definition at line 649 of file reflow_css_cascade.c.

References ra8_css_style_t::family_len, ra8_css_style_t::family_off, internal_resolve(), k_ra8_css_set_family, and ra8_css_style_t::set.

Referenced by ra8_css_cascade_ctx().

◆ internal_cascade_scalars()

void internal_cascade_scalars ( ra8_css_style_t * out,
const ra8_css_sheet_t * sheet,
const bool * matched,
const ra8_css_style_t * inherited,
const ra8_css_style_t * inl )
static

Resolve the scalar properties (align / colour / font-size / display).

Calls internal_resolve() for each of the four scalar CSS properties (text-align, color, font-size, display) and, when a winner is found, copies the winning value into out and OR's the corresponding set bit. font-size and display are resolved from rules and inline styles only; inheritance for those is handled by the caller to avoid double-application of percentage font-size values.

Parameters
[in,out]outStyle record to write the resolved scalar values into.
[in]sheetSheet providing the matching rules.
[in]matchedBoolean array parallel to sheet->rules[]; true for each rule that matched the current element.
[in]inheritedStyle inherited from the parent element.
[in]inlInline style from the element's style attribute.
Returns
Nothing.
Precondition
out, sheet, matched, inherited, and inl are non-NULL.
matched has at least sheet->rule_count elements.
Postcondition
out reflects the winning scalar values for all four properties.
inherited and inl are not modified.
Note
Thread-safe with respect to distinct out instances.
Since
0.1.0

Definition at line 585 of file reflow_css_cascade.c.

References ra8_css_style_t::align, ra8_css_style_t::color, ra8_css_style_t::display, ra8_css_style_t::font_unit, ra8_css_style_t::font_val, internal_resolve(), k_ra8_css_set_align, k_ra8_css_set_color, k_ra8_css_set_display, k_ra8_css_set_fontsize, and ra8_css_style_t::set.

Referenced by ra8_css_cascade_ctx().

◆ internal_ci_eq_span()

bool internal_ci_eq_span ( const char * a,
size_t alen,
const char * b,
size_t blen )
static

Case-insensitive equality of two byte spans.

Compares a[0..alen) and b[0..blen) byte-by-byte after ASCII case-folding via priv_reflow_css_lower(). Returns false immediately when either pointer is NULL or the lengths differ. The comparison loop is bounded by alen (which equals blen when lengths match).

Parameters
[in]aFirst byte span (need not be NUL-terminated).
[in]alenLength of a in bytes.
[in]bSecond byte span (need not be NUL-terminated).
[in]blenLength of b in bytes.
Returns
bool Comparison result.
Return values
trueBoth spans have equal length and compare equal case-insensitively.
falseEither pointer is NULL, lengths differ, or any byte differs.
Precondition
a points to at least alen readable bytes, or is NULL.
b points to at least blen readable bytes, or is NULL.
Postcondition
No state is mutated; the function is pure.
a and b are not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 720 of file reflow_css_cascade.c.

References priv_reflow_css_lower().

Referenced by internal_family_eq().

◆ internal_class_list_has()

bool internal_class_list_has ( const char * list,
size_t list_len,
const char * name,
size_t nlen )
static

True iff a space-separated class list contains name exactly.

Tokenises list[0..list_len) on whitespace and performs a byte-exact (not case-folded) comparison of each token against name[0..nlen), byte by byte. The outer loop is bounded by list_len; each pass skips leading whitespace, extracts the next token, and compares it. Returns true on the first matching token; false if no token matches.

Parameters
[in]listSpace-separated class attribute value span.
[in]list_lenNumber of bytes in list.
[in]nameInterned class name to search for.
[in]nlenLength of name in bytes.
Returns
bool Search result.
Return values
trueAt least one whitespace-delimited token in list equals name.
falseNo token in list matches name, or list is empty.
Precondition
list points to at least list_len readable bytes.
name points to at least nlen readable bytes.
Postcondition
No state is mutated; the function is pure.
list and name are not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 233 of file reflow_css_cascade.c.

References priv_reflow_css_is_ws().

Referenced by internal_anc_matches(), and ra8_css_rule_matches().

◆ internal_family_eq()

bool internal_family_eq ( const ra8_css_sheet_t * sheet,
const ra8_css_fontface_t * f,
const char * family,
size_t family_len )
static

True iff face f's family equals family (case-insensitive).

Retrieves the interned family name from sheet->names using f->family_off and f->family_len, then delegates to internal_ci_eq_span() for a case-insensitive comparison against family[0..family_len).

Parameters
[in]sheetSheet owning the name pool referenced by f.
[in]fFont face whose interned family name to compare.
[in]familyByte span of the family name to match.
[in]family_lenNumber of bytes in family.
Returns
bool Comparison result.
Return values
truef's interned family name equals family case-insensitively.
falseThe names differ in length or any byte differs.
Precondition
sheet and f are non-NULL.
f->family_off + f->family_len <= sheet->names_used.
Postcondition
No state is mutated; the function is pure relative to sheet.
family is not modified.
Note
Thread-safe; no shared mutable state.
Since
0.1.0

Definition at line 760 of file reflow_css_cascade.c.

References ra8_css_fontface_t::family_len, ra8_css_fontface_t::family_off, internal_ci_eq_span(), and ra8_css_sheet_t::names.

Referenced by ra8_css_match_face().

◆ internal_find_block()

bool internal_find_block ( const char * css,
size_t len,
size_t i,
size_t * out_open,
size_t * out_close )
static

Locate the { ... } block beginning at selector offset i.

Scans forward for the block-open byte, then the block-close byte, writing both offsets out. Returns false when no block-open is present, which the caller treats as end-of-input.

Parameters
[in]cssStylesheet text (non-NULL, validated by the caller).
[in]lenTotal length of css, bytes.
[in]iOffset of the selector list start.
[out]out_openOffset of the block-open byte (valid only on true).
[out]out_closeOffset of the block-close byte, or len if missing.
Returns
True iff a block-open byte was found at or after i.
Return values
trueA block-open was found; out_open / out_close are set.
falseNo block-open exists in [i, len).
Precondition
css, out_open, out_close are non-NULL.
i <= len.
Postcondition
On true, *out_open < len and *out_close <= len.
No state other than the out-params is mutated.
Note
Thread-safe; operates on caller-owned memory only.
Since
0.1.0

Definition at line 145 of file reflow_css_cascade.c.

Referenced by ra8_css_parse().

◆ internal_resolve()

const ra8_css_style_t * internal_resolve ( uint8_t setbit,
const ra8_css_style_t * inherited,
const ra8_css_sheet_t * sheet,
const bool * matched,
const ra8_css_style_t * inl )
static

Resolve the winning declaration for one property across all sources.

Returns
Pointer to the winning style (inherited / a rule decl / inline), or NULL if no source declares setbit.

Definition at line 467 of file reflow_css_cascade.c.

References ra8_css_rule_t::decl, internal_rule_rank(), k_priv_rank_inherited, ra8_css_rule_t::order, ra8_css_sheet_t::rule_count, ra8_css_sheet_t::rules, and ra8_css_style_t::set.

Referenced by internal_cascade_emphasis(), internal_cascade_family(), and internal_cascade_scalars().

◆ internal_rule_matches_ctx()

bool internal_rule_matches_ctx ( const ra8_css_rule_t * rule,
const ra8_css_element_t * el,
const ra8_css_element_t * ancestors,
uint8_t n_anc,
const ra8_css_sheet_t * sheet )
static

Full match of a (possibly descendant) rule against el + ancestors.

The subject must match el via ra8_css_rule_matches(); when rule->anc_count is 0 that check is sufficient. For rules with ancestor constraints, a greedy right-to-left scan walks the ancestor stack from innermost (ancestors[n_anc-1]) to outermost (ancestors[0]), consuming one rule ancestor part per stack element that matches via internal_anc_matches(). The descendant combinator allows any depth between parts. Returns true only when all ancestor parts are consumed (ai < 0 at loop exit).

Parameters
[in]ruleRule to match (subject + ancestor constraints).
[in]elSubject element to match the rule's subject compound.
[in]ancestorsArray of ancestor elements; index 0 is outermost.
[in]n_ancNumber of elements in ancestors.
[in]sheetSheet owning the name pool for interned names.
Returns
bool Whether the rule matches the element in context.
Return values
trueThe rule's subject and all ancestor constraints are satisfied.
falseThe subject does not match el, or at least one ancestor constraint has no matching ancestor in the stack.
Precondition
rule, el, and sheet are non-NULL.
ancestors points to at least n_anc readable elements, or is NULL when n_anc is 0.
Postcondition
No state is mutated; the function is pure.
rule, el, ancestors, and sheet are not modified.
Note
Thread-safe; pure function with no shared mutable state.
Since
0.1.0

Definition at line 381 of file reflow_css_cascade.c.

References ra8_css_rule_t::anc, ra8_css_rule_t::anc_count, internal_anc_matches(), and ra8_css_rule_matches().

Referenced by ra8_css_cascade_ctx().

◆ internal_rule_rank()

uint16_t internal_rule_rank ( const ra8_css_rule_t * rule)
static

Packed specificity (id*10000 + class*100 + type), summing all parts.

Computes the CSS cascade specificity of rule by summing weights for each present constraint across the subject and all ancestor parts:

  • k_priv_spec_id (10000) for each non-empty id field.
  • k_priv_spec_class (100) for each non-empty class field.
  • k_priv_spec_type (1) for each non-unknown tag. The ancestor loop is bounded by rule->anc_count. The result is used by internal_resolve() to determine which rule wins during the cascade.
Parameters
[in]ruleRule whose specificity to compute.
Returns
uint16_t Packed specificity value.
Return values
0When no type, class, or id constraints are present (universal).
>0The summed specificity per CSS cascade rules.
Precondition
rule is non-NULL.
rule->anc_count is accurate (within bounds of rule->anc[]).
Postcondition
No state is mutated; the function is pure.
rule is not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 433 of file reflow_css_cascade.c.

References ra8_css_rule_t::anc, ra8_css_rule_t::anc_count, ra8_css_anc_t::class_len, ra8_css_rule_t::class_len, ra8_css_anc_t::id_len, ra8_css_rule_t::id_len, k_priv_spec_class, k_priv_spec_id, k_priv_spec_type, k_reflow_tag_unknown, ra8_css_rule_t::sel_tag, and ra8_css_anc_t::tag.

Referenced by internal_resolve().

◆ internal_skip_comment()

size_t internal_skip_comment ( const char * css,
size_t len,
size_t start )
static

Step over a C-style comment starting at start.

Assumes css[start..start+1] is the open delimiter and scans to the matching close delimiter, returning the offset just past it (clamped to len when the comment is unterminated).

Parameters
[in]cssStylesheet text (non-NULL, validated by the caller).
[in]lenTotal length of css, bytes.
[in]startOffset of the comment open delimiter.
Returns
Offset of the first byte after the comment, in [start, len].
Return values
lenThe comment ran to the end of the buffer (unterminated).
Precondition
css is non-NULL.
start < len.
Postcondition
The return value is in [start, len].
No state is mutated (pure function).
Note
Thread-safe; operates on caller-owned memory only.
Since
0.1.0

Definition at line 106 of file reflow_css_cascade.c.

References k_priv_cmt_marker.

Referenced by ra8_css_parse().

◆ 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_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().