|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Scan / attribute / colour-parsing core of the minimal SVG subset (#112). More...
#include "reflow_svg.h"#include <string.h>#include "ra8_attributes.h"#include "reflow_svg_internal.h"Go to the source code of this file.
Functions | |
| bool | priv_ra8_svgp_ws (char c) |
| Test whether a character is XML whitespace. | |
| char | priv_ra8_svgp_lc (char c) |
| ASCII-fold a character to lower case. | |
| bool | priv_ra8_svgp_starts_ci (const uint8_t *s, size_t len, size_t at, const char *lit) |
| Test whether a byte span starts with a literal at a given offset, case-insensitively. | |
| size_t | priv_ra8_svgp_find_ci (const uint8_t *s, size_t len, size_t from, const char *lit) |
| Find the first case-insensitive occurrence of a literal in a byte span. | |
| static uint8_t | internal_hex (char c) |
| Convert a single hexadecimal digit character to its numeric value. | |
| int32_t | priv_ra8_svgp_num (const uint8_t *s, size_t len, size_t *i) |
Parse the integer part of one SVG number at s[*i], skipping leading separators (whitespace / commas); truncates any fraction. | |
| static bool | internal_attr_at (const uint8_t *s, size_t len, size_t at, const char *name) |
Test whether an attribute keyword begins at s[at] on a word boundary. | |
| bool | priv_ra8_svgp_attr (const uint8_t *s, size_t len, const char *name, size_t *voff, size_t *vlen) |
Find attribute name in tag span s[0..len); return its value slice. | |
| int32_t | priv_ra8_svgp_attr_num (const uint8_t *s, size_t len, const char *name, int32_t def) |
| Read an SVG attribute as a signed integer, returning a default when absent. | |
| static bool | internal_ci_eq (const uint8_t *s, size_t len, const char *lit) |
| Case-insensitive equality test between a byte span and a NUL-terminated literal. | |
| static uint32_t | internal_hex_color (const uint8_t *s, size_t len) |
| Parse a hex colour from raw digit bytes (no leading '#') into 0x00RRGGBB. | |
| static uint32_t | internal_named_color (const uint8_t *s, size_t len) |
| Map a named SVG colour keyword to its 0x00RRGGBB value. | |
| uint32_t | priv_ra8_svgp_paint (const uint8_t *s, size_t len) |
| Parse an SVG paint value ('#rgb'/'#rrggbb'/name/'none') to 0x00RRGGBB. | |
| uint32_t | priv_ra8_svgp_attr_paint (const uint8_t *s, size_t len, const char *name, uint32_t def) |
| Read an SVG attribute as a paint colour, returning a default when absent. | |
| int32_t | priv_match_grad (const svg_grads_t *grads, const uint8_t *val, size_t vlen) |
| Implementation of priv_match_grad() – linear id search over the document gradient set. | |
| uint32_t | priv_ra8_svgp_resolve_fill (const uint8_t *s, size_t len, const svg_xform_t *t, uint32_t def, int32_t *gi) |
Resolve a shape's 'fill': a solid colour, or a gradient index via gi. | |
Scan / attribute / colour-parsing core of the minimal SVG subset (#112).
Pure string-scanning leaf helpers for the SVG subset: XML whitespace and ASCII-fold classifiers, case-insensitive literal scans, integer parsing, attribute slicing, colour-keyword / hex-paint parsing, and the fill / gradient-reference resolver. The transform, shape, path, and document-walk stages live in the sibling reflow_svg_*.c files. No DOM, no heap. See reflow_svg.h for the public scope and reflow_svg_internal.h for the shared geometry types and cross-TU helper contracts.
[Ring 4 / Reflow] {World: NS}
Definition in file reflow_svg.c.
|
static |
Test whether an attribute keyword begins at s[at] on a word boundary.
Uses priv_ra8_svgp_starts_ci to confirm the case-insensitive match of name at position at, then validates two boundary conditions: the character immediately before at (when at > 0) must be XML whitespace so that a substring of a longer name is not accepted, and the character immediately after the matched name must be '=' or XML whitespace. These three checks together ensure that only a correctly delimited attribute keyword matches.
| [in] | s | Byte buffer containing the tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | at | Byte offset at which to test for the attribute name. |
| [in] | name | NUL-terminated ASCII attribute name to match; must not be NULL. |
| true | name matches at at with valid surrounding delimiters. |
| false | name does not match, or a boundary condition fails. |
s is a valid pointer to at least len bytes. name is a valid NUL-terminated ASCII string.s, len, at, and name are not modified. s are written.Definition at line 316 of file reflow_svg.c.
References priv_ra8_svgp_starts_ci(), priv_ra8_svgp_ws(), and strlen().
Referenced by priv_ra8_svgp_attr().
|
static |
Case-insensitive equality test between a byte span and a NUL-terminated literal.
Advances a shared index through both s and lit simultaneously, comparing each pair of characters after folding through priv_ra8_svgp_lc. The loop terminates as soon as a mismatch is found or the NUL terminator in lit is reached. Returns true only when the index equals len at the same point that lit[k] is '\0', ensuring both length equality and content equality.
| [in] | s | Byte span to compare; must not be NULL. |
| [in] | len | Number of valid bytes in s. |
| [in] | lit | NUL-terminated ASCII string to compare against; must not be NULL. |
s and lit are equal under case folding. | true | s[0..len) matches lit case-insensitively and lengths agree. |
| false | Any character differs, or the lengths do not match. |
s is a valid pointer to at least len bytes. lit is a valid NUL-terminated ASCII string.s and lit are not modified. Definition at line 464 of file reflow_svg.c.
References priv_ra8_svgp_lc().
Referenced by internal_named_color().
|
static |
Convert a single hexadecimal digit character to its numeric value.
Accepts '0'-'9', 'a'-'f', and 'A'-'F'. The alphabetic check is performed after ASCII-folding via priv_ra8_svgp_lc so both cases are handled uniformly. Returns the sentinel k_svg_hex_base (16) for any character that is not a valid hexadecimal digit, allowing callers to detect and propagate parse failures without a separate validity flag.
| [in] | c | Character to convert; expected to be a hex digit. |
| 0..9 | For '0'-'9'. |
| 10..15 | For 'a'-'f' or 'A'-'F'. |
| (uint8_t)k_svg_hex_base | c is not a hexadecimal digit. |
c is any value representable by char. c is not modified.Definition at line 211 of file reflow_svg.c.
References k_svg_hex_a10, k_svg_hex_base, and priv_ra8_svgp_lc().
Referenced by internal_hex_color().
|
static |
Parse a hex colour from raw digit bytes (no leading '#') into 0x00RRGGBB.
Accepts exactly k_svg_hex3 (3) or k_svg_hex6 (6) digit bytes. For a 6-digit input the bytes are read as pairs RR GG BB; each nibble is decoded via internal_hex and shifted into the 24-bit result. For a 3-digit input each nibble N is expanded to NN (i.e. the nibble value is placed in both the high and low nibble of the channel byte) to conform to the CSS shorthand rule. Any non-hex digit encountered causes an early return of k_svg_no_paint. Any length other than 3 or 6 also returns k_svg_no_paint.
| [in] | s | Pointer to the first hex digit byte (no '#'); must not be NULL. |
| [in] | len | Number of digit bytes available at s; must be 3 or 6 for success. |
| 0x000000..0xFFFFFF | Valid 24-bit colour when len is 3 or 6 and all digits are hex. |
| (uint32_t)k_svg_no_paint | len is neither 3 nor 6, or a non-hex digit is present. |
s is a valid pointer to at least len bytes. len equals k_svg_hex3 or k_svg_hex6 for a successful parse.s is not modified. Definition at line 505 of file reflow_svg.c.
References internal_hex(), k_svg_hex3, k_svg_hex6, k_svg_hex_base, k_svg_hex_chan, k_svg_hex_nib, and k_svg_no_paint.
Referenced by priv_ra8_svgp_paint().
|
static |
Map a named SVG colour keyword to its 0x00RRGGBB value.
Linearly searches a compile-time table of the twelve most common SVG/CSS colour keywords (black, white, red, green, blue, gray, grey, silver, maroon, navy, yellow, orange). Comparison is performed via internal_ci_eq so the keyword is accepted in any mix of upper and lower case. Returns k_svg_no_paint for the keyword "none" and for any name not present in the table; callers treat this sentinel as "no paint / transparent".
| [in] | s | Byte span holding the colour keyword; must not be NULL. |
| [in] | len | Number of valid bytes in s. |
| 0x000000..0xFFFFFF | When s matches one of the known colour names. |
| (uint32_t)k_svg_no_paint | When s is "none" or an unknown name. |
s is a valid pointer to at least len bytes. s contains only ASCII characters (colour keywords are ASCII-only).s is not modified. < Name.
< RGB.
Definition at line 561 of file reflow_svg.c.
References internal_ci_eq(), and k_svg_no_paint.
Referenced by priv_ra8_svgp_paint().
| int32_t priv_match_grad | ( | const svg_grads_t * | grads, |
| const uint8_t * | val, | ||
| size_t | vlen ) |
Implementation of priv_match_grad() – linear id search over the document gradient set.
Match a 'url(#id)' paint value to a gradient index in the document set.
Definition at line 665 of file reflow_svg.c.
References svg_grads::g, svg_grad_t::id, svg_grads::n, priv_ra8_svgp_starts_ci(), and strlen().
Referenced by priv_ra8_svgp_resolve_fill().
| bool priv_ra8_svgp_attr | ( | const uint8_t * | s, |
| size_t | len, | ||
| const char * | name, | ||
| size_t * | voff, | ||
| size_t * | vlen ) |
Find attribute name in tag span s[0..len); return its value slice.
Scans the tag byte span for the first occurrence of name that passes the word-boundary check via internal_attr_at. Once located, the scanner advances past the '=' separator and any surrounding whitespace to find the opening quote character ('"' or "'"). The matching closing quote is then located and the slice [*voff, *voff + *vlen) is set to the attribute value content between the two quote characters. Returns false if the name is not found, no '=' follows, or no opening quote is present.
| [in] | s | Byte buffer containing the tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | name | NUL-terminated ASCII attribute name to find; must not be NULL. |
| [out] | voff | Set to the byte offset of the first value character when found. |
| [out] | vlen | Set to the byte length of the value when found. |
| true | Attribute name found; *voff and *vlen are valid. |
| false | Attribute not found, missing '=', or missing opening quote. |
s is a valid pointer to at least len bytes. voff and vlen are valid non-NULL output pointers.*voff < len and *voff + *vlen <= len. *voff and *vlen are indeterminate and must not be used.Definition at line 364 of file reflow_svg.c.
References internal_attr_at(), priv_ra8_svgp_ws(), and strlen().
Referenced by internal_attr_numf(), internal_copy_attr_id(), internal_read_viewbox(), internal_stop_color(), internal_stop_offset(), priv_ra8_svgp_apply_xform(), priv_ra8_svgp_attr_num(), priv_ra8_svgp_attr_paint(), priv_ra8_svgp_draw_path(), priv_ra8_svgp_draw_polygon(), priv_ra8_svgp_draw_polyline(), priv_ra8_svgp_resolve_fill(), ra8_svg_image_href(), and ra8_svg_size().
| int32_t priv_ra8_svgp_attr_num | ( | const uint8_t * | s, |
| size_t | len, | ||
| const char * | name, | ||
| int32_t | def ) |
Read an SVG attribute as a signed integer, returning a default when absent.
Read an SVG attribute as a signed integer, returning def when absent.
Calls priv_ra8_svgp_attr to locate the attribute value slice, then forwards that slice to priv_ra8_svgp_num starting at offset zero. If the attribute is absent, returns def without modifying any output. Fractional parts of the attribute value are truncated by priv_ra8_svgp_num. Useful for reading integer-valued SVG geometry attributes such as x, y, width, and height.
| [in] | s | Byte buffer containing the SVG tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | name | NUL-terminated ASCII attribute name; must not be NULL. |
| [in] | def | Value to return when the attribute is absent. |
def when the attribute is absent. | def | Attribute name was not found in s. |
| n | The signed integer parsed from the attribute value. |
s is a valid pointer to at least len bytes. name is a valid NUL-terminated ASCII string.s and name are not modified. def when priv_ra8_svgp_attr returns false.Definition at line 424 of file reflow_svg.c.
References priv_ra8_svgp_attr(), and priv_ra8_svgp_num().
Referenced by internal_read_viewbox(), priv_ra8_svgp_draw_circle(), priv_ra8_svgp_draw_line(), priv_ra8_svgp_draw_rect(), and ra8_svg_size().
| uint32_t priv_ra8_svgp_attr_paint | ( | const uint8_t * | s, |
| size_t | len, | ||
| const char * | name, | ||
| uint32_t | def ) |
Read an SVG attribute as a paint colour, returning a default when absent.
Read an SVG attribute as a paint colour, returning def when absent.
Calls priv_ra8_svgp_attr to locate the attribute value slice, then forwards that slice to priv_ra8_svgp_paint. If the attribute is absent, returns def unchanged. Useful for reading 'fill' and 'stroke' attributes where a sentinel of k_svg_no_paint means the shape uses no paint for that role.
| [in] | s | Byte buffer containing the SVG tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | name | NUL-terminated ASCII attribute name; must not be NULL. |
| [in] | def | Default paint value returned when the attribute is absent. |
def when the attribute is absent. | def | Attribute name was not found in s. |
| 0x000000..0xFFFFFF | Successfully parsed solid paint colour. |
| (uint32_t)k_svg_no_paint | Attribute present but parses to no-paint. |
s is a valid pointer to at least len bytes. name is a valid NUL-terminated ASCII string.s and name are not modified. def when the attribute is absent.Definition at line 654 of file reflow_svg.c.
References priv_ra8_svgp_attr(), and priv_ra8_svgp_paint().
Referenced by priv_ra8_svgp_draw_line(), and priv_ra8_svgp_draw_polyline().
| size_t priv_ra8_svgp_find_ci | ( | const uint8_t * | s, |
| size_t | len, | ||
| size_t | from, | ||
| const char * | lit ) |
Find the first case-insensitive occurrence of a literal in a byte span.
Find the first case-insensitive occurrence of lit in s[from..len).
Scans s[from .. len) for the first position where priv_ra8_svgp_starts_ci returns true for lit. If lit is empty (zero-length), returns len immediately as a defined sentinel rather than matching at every position. The inner loop advances the position by one byte per iteration; the loop bound is len - strlen(lit) + 1, so the scan is O(len * len(lit)).
| [in] | s | Byte buffer to search; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | from | Starting byte offset; must be <= len. |
| [in] | lit | NUL-terminated ASCII literal to find; must not be NULL. |
len if not found. | [from..len) | Offset of the first case-insensitive occurrence of lit. |
| len | lit was not found, or lit is empty. |
s is a valid pointer to at least len bytes. from is <= len.s and lit are not modified. from, len].Definition at line 166 of file reflow_svg.c.
References priv_ra8_svgp_starts_ci(), and strlen().
Referenced by internal_parse_stops(), internal_scan_grads(), and internal_tag_span().
| char priv_ra8_svgp_lc | ( | char | c | ) |
ASCII-fold a character to lower case.
Converts uppercase ASCII letters ('A'-'Z') to their lowercase equivalents by adding the ('a' - 'A') offset. All other characters, including non-ASCII bytes, digits, punctuation, and control characters, are returned unchanged. Used by case-insensitive string comparisons throughout the SVG parser (element names, attribute names, colour names).
| [in] | c | Character to fold. |
c, or c unchanged. | 'a'..'z' | When c was an uppercase ASCII letter. |
| c | When c was already lowercase or not an ASCII letter. |
c is any value representable by char. c was an uppercase letter. Definition at line 88 of file reflow_svg.c.
Referenced by internal_ci_eq(), internal_hex(), internal_parse_path(), and priv_ra8_svgp_starts_ci().
| int32_t priv_ra8_svgp_num | ( | const uint8_t * | s, |
| size_t | len, | ||
| size_t * | i ) |
Parse the integer part of one SVG number at s[*i], skipping leading separators (whitespace / commas); truncates any fraction.
Parse the integer part of one SVG number at s[*i]; truncate fractions.
First advances *i past any leading whitespace or comma separators. Then reads an optional sign ('+'/'-') followed by consecutive decimal digit characters to form an int32_t. If a decimal point is found immediately after the integer digits, the fractional digits are consumed and discarded so that the next call begins at the correct position. On return *i points one past the last character consumed.
| [in] | s | Byte buffer holding the SVG text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in,out] | i | Current parse cursor; updated to one past the consumed number. |
| 0 | No digit characters were found after the sign (or no sign either). |
| n | The value of the decimal integer scanned from s[*i]. |
s is a valid pointer to at least len bytes. i is not NULL, and *i is <= len.*i is advanced past any whitespace, sign, integer digits, and fraction. *i <= len.Definition at line 255 of file reflow_svg.c.
References k_svg_dec, and priv_ra8_svgp_ws().
Referenced by internal_parse_path(), internal_parse_points(), internal_read_viewbox(), priv_ra8_svgp_attr_num(), and ra8_svg_size().
| uint32_t priv_ra8_svgp_paint | ( | const uint8_t * | s, |
| size_t | len ) |
Parse an SVG paint value ('#rgb'/'#rrggbb'/name/'none') to 0x00RRGGBB.
Routes the span to either internal_hex_color (when the first byte is '#', strip it first) or internal_named_color for keyword colours. An empty span immediately returns k_svg_no_paint. The keyword "none" is handled by internal_named_color returning k_svg_no_paint so callers skip the paint.
| [in] | s | Byte span containing the paint value; must not be NULL. |
| [in] | len | Number of valid bytes in s. |
| 0x000000..0xFFFFFF | Successfully parsed solid colour. |
| (uint32_t)k_svg_no_paint | Empty span, "none", or unrecognised value. |
s is a valid pointer to at least len bytes. len is the exact byte length of the attribute value to parse.s is not modified. Definition at line 614 of file reflow_svg.c.
References internal_hex_color(), internal_named_color(), and k_svg_no_paint.
Referenced by internal_stop_color(), priv_ra8_svgp_attr_paint(), and priv_ra8_svgp_resolve_fill().
| uint32_t priv_ra8_svgp_resolve_fill | ( | const uint8_t * | s, |
| size_t | len, | ||
| const svg_xform_t * | t, | ||
| uint32_t | def, | ||
| int32_t * | gi ) |
Resolve a shape's 'fill': a solid colour, or a gradient index via gi.
Sets *gi to the matched gradient index (>= 0) for a 'fill="url(#id)"' that resolves in t->grads, returning k_svg_no_paint so the solid path is skipped. A 'url(#id)' with no match also returns k_svg_no_paint with *gi == -1 (graceful skip). An absent 'fill' returns def; otherwise the solid colour parsed from the attribute.
| [in] | s | Byte buffer containing the SVG tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | t | Active coordinate transform carrying the gradient set pointer. |
| [in] | def | Default solid colour when the 'fill' attribute is absent. |
| [out] | gi | Set to the matched gradient index, or -1 when not a gradient. |
| def | 'fill' attribute is absent. |
| (uint32_t)k_svg_no_paint | 'fill' is a 'url(#id)' reference (gradient). |
| 0x000000..0xFFFFFF | Solid colour from the 'fill' attribute. |
s is a valid pointer to at least len bytes. gi is a valid non-NULL output pointer.*gi is always written before return. *gi >= 0, the return value is k_svg_no_paint.Definition at line 721 of file reflow_svg.c.
References svg_xform_t::grads, k_svg_no_paint, priv_match_grad(), priv_ra8_svgp_attr(), priv_ra8_svgp_paint(), and priv_ra8_svgp_starts_ci().
Referenced by priv_ra8_svgp_draw_circle(), priv_ra8_svgp_draw_path(), priv_ra8_svgp_draw_polygon(), and priv_ra8_svgp_draw_rect().
| bool priv_ra8_svgp_starts_ci | ( | const uint8_t * | s, |
| size_t | len, | ||
| size_t | at, | ||
| const char * | lit ) |
Test whether a byte span starts with a literal at a given offset, case-insensitively.
Case-insensitive prefix test of lit at at within s[0..len).
Computes the length of lit via strlen, then verifies that s[at .. at+n) matches lit character-for-character after folding both sides through priv_ra8_svgp_lc. Returns false immediately when the remaining span s[at .. len) is shorter than lit, avoiding any out-of-bounds access. Matching is done byte-by-byte with no locale dependence.
| [in] | s | Byte buffer to search; must not be NULL. |
| [in] | len | Total number of valid bytes in s. |
| [in] | at | Byte offset within s at which to start the comparison. |
| [in] | lit | NUL-terminated ASCII literal to match; must not be NULL. |
| true | s[at .. at+strlen(lit)) matches lit case-insensitively. |
| false | at + strlen(lit) > len, or any character differs. |
s is a valid pointer to at least len bytes. lit is a valid NUL-terminated ASCII string.s and lit are not modified. at and len are not modified.Definition at line 123 of file reflow_svg.c.
References priv_ra8_svgp_lc(), and strlen().
Referenced by internal_attr_at(), internal_elem_at(), internal_xform_kind(), priv_match_grad(), priv_ra8_svgp_find_ci(), priv_ra8_svgp_resolve_fill(), and ra8_svg_is_svg().
| bool priv_ra8_svgp_ws | ( | char | c | ) |
Test whether a character is XML whitespace.
Classifies c as an XML whitespace character according to the XML 1.0 specification: space (0x20), horizontal tab (0x09), line feed (0x0A), carriage return (0x0D), or form feed (0x0C). Used throughout the parser to skip inter-token gaps and attribute boundaries without invoking libc locale.
| [in] | c | Character to test. |
| true | c is one of the five XML whitespace characters. |
| false | c is not an XML whitespace character. |
c is any value representable by char (no range restriction). Definition at line 58 of file reflow_svg.c.
Referenced by internal_attr_at(), internal_elem_at(), internal_next_cmd(), internal_parse_points(), internal_parse_xform(), internal_xform_read(), priv_ra8_svgp_attr(), priv_ra8_svgp_num(), priv_ra8_svgp_numf(), and ra8_svg_is_svg().