|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SVG document walk, gradient definitions, and the public render API (#112). More...
#include <string.h>#include "ra8_attributes.h"#include "reflow_svg.h"#include "reflow_svg_internal.h"Go to the source code of this file.
Functions | |
| static bool | internal_elem_at (const uint8_t *s, size_t len, size_t at, const char *name) |
Test whether an element keyword begins at s[at] with a valid delimiter. | |
| static bool | internal_tag_span (const uint8_t *s, size_t len, size_t from, const char *name, size_t *open, size_t *close) |
Locate the tag span [*open, *close) of element name at or after from. | |
| static void | internal_read_viewbox (const uint8_t *s, size_t len, svg_xform_t *t) |
Fill t's viewBox fields from the SVG root element. | |
| static void | internal_dispatch_shape (const uint8_t *s, size_t len, size_t at, size_t close, const svg_xform_t *t) |
| Dispatch one element tag span to the appropriate shape-drawing function. | |
| static void | internal_xform_with_group (const svg_xform_t *t, svg_utf_t g, svg_xform_t *out) |
Copy the base transform t into out and replace the user affine with g. | |
| static int32_t | internal_group_open (const uint8_t *s, size_t i, size_t close, const svg_xform_t *t, svg_utf_t *gstk, int32_t gsp) |
| Handle a 'g' open tag: compose its 'transform=' over the stack top and push. | |
| static void | internal_draw_shapes (const uint8_t *s, size_t len, const svg_xform_t *t) |
| Walk every element in document order and draw the supported shapes. | |
| static float | internal_attr_numf (const uint8_t *s, size_t len, const char *name, float def) |
| Read an SVG attribute as a floating-point number, returning a default when absent. | |
| static void | internal_copy_attr_id (const uint8_t *s, size_t len, char *dst) |
Copy the 'id' attribute value into dst as a NUL-terminated string. | |
| static float | internal_clamp01 (float v) |
| Clamp a float value to the unit interval [0, 1]. | |
| static float | internal_stop_offset (const uint8_t *tag, size_t tlen) |
| Parse a gradient 'stop' element's 'offset' attribute. | |
| static uint32_t | internal_stop_color (const uint8_t *tag, size_t tlen) |
| Parse a gradient 'stop' element's 'stop-color' attribute. | |
| static void | internal_parse_stops (const uint8_t *s, size_t from, size_t end, svg_grad_t *g) |
Parse the 'stop' child elements of a gradient definition into g. | |
| static void | internal_scan_grads (const uint8_t *s, size_t len, svg_grads_t *gs) |
Scan the document for gradient definitions and populate gs. | |
| bool | ra8_svg_is_svg (const uint8_t *bytes, size_t len) |
Heuristically decide whether bytes are an SVG document. | |
| ra8_err_t | ra8_svg_image_href (const uint8_t *svg, size_t len, size_t *out_off, size_t *out_len) |
| Extract the href of a cover-wrapper <svg><image .../></svg>. | |
| ra8_err_t | ra8_svg_size (const uint8_t *svg, size_t len, int32_t *out_w, int32_t *out_h) |
| Report an SVG's intrinsic size (width/height, else viewBox dimensions). | |
| ra8_err_t | ra8_svg_render (const uint8_t *svg, size_t len, int32_t x, int32_t y, int32_t w, int32_t h) |
| Render an SVG's vector shapes into a box. | |
Variables | |
| static const float | s_svg_unit = 1.0F |
| Gradient parameter / offset upper clamp. | |
SVG document walk, gradient definitions, and the public render API (#112).
The document-order element walk (with a bounded nested <g> transform stack), the <linearGradient> / <radialGradient> + <stop> gradient-definition scan, and the public ra8_svg_is_svg / ra8_svg_image_href / ra8_svg_size / ra8_svg_render entry points. Each shape is dispatched to its rasteriser in the sibling reflow_svg_*.c files. No DOM, no heap. See reflow_svg_internal.h for the shared geometry types and helper contracts.
[Ring 4 / Reflow] {World: NS}
Definition in file reflow_svg_doc.c.
|
static |
Read an SVG attribute as a floating-point number, returning a default when absent.
Calls priv_ra8_svgp_attr to locate the attribute value slice, then forwards that slice to priv_ra8_svgp_numf starting at offset zero. Returns def when the attribute is absent. Used for reading gradient geometry attributes (x1, y1, x2, y2, cx, cy, r) and stop offsets that are specified as decimal fractions.
| [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 absent. | def | Attribute name was not found. |
| n | The float value parsed from the attribute. |
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 429 of file reflow_svg_doc.c.
References priv_ra8_svgp_attr(), and priv_ra8_svgp_numf().
Referenced by internal_scan_grads().
|
static |
Clamp a float value to the unit interval [0, 1].
Returns 0.0F when v < 0.0F, returns s_svg_unit (1.0F) when v > s_svg_unit, and returns v unchanged otherwise. Used to clamp parsed gradient stop offsets to a valid range before they are stored in the gradient descriptor.
| [in] | v | Float value to clamp. |
| 0.0F | When v < 0.0F. |
| s_svg_unit | When v > s_svg_unit. |
| v | When v is already in [0.0F, 1.0F]. |
v is a finite float value. s_svg_unit is initialised to 1.0F (module-scope constant).v is not modified.Definition at line 507 of file reflow_svg_doc.c.
References s_svg_unit.
Referenced by internal_parse_stops().
|
static |
Copy the 'id' attribute value into dst as a NUL-terminated string.
Looks up the "id" attribute via priv_ra8_svgp_attr. If absent, writes a NUL byte at dst[0] and returns. Otherwise copies at most k_svg_grad_id - 1 bytes from the attribute value to dst and appends a NUL terminator. Used when scanning gradient definitions to store each gradient's id for later url(#id) resolution.
| [in] | s | Byte buffer containing the SVG tag text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [out] | dst | Output buffer of at least k_svg_grad_id bytes; must not be NULL. |
s is a valid pointer to at least len bytes. dst is a valid pointer to at least k_svg_grad_id bytes.dst[0..n] is NUL-terminated where n <= k_svg_grad_id - 1. s is not modified.Definition at line 465 of file reflow_svg_doc.c.
References k_svg_grad_id, and priv_ra8_svgp_attr().
Referenced by internal_scan_grads().
|
static |
Dispatch one element tag span to the appropriate shape-drawing function.
Slices s[at .. close) as the element tag, composes any element-level 'transform=' onto a local copy of t via priv_ra8_svgp_apply_xform, then selects the drawing function based on the element name: rect, circle, polygon, polyline, path, or line. Unsupported elements are silently ignored.
| [in] | s | Full SVG document byte buffer; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | at | Byte offset of the element opening tag in s. |
| [in] | close | Byte offset of the '>' terminator in s. |
| [in] | t | Inherited coordinate transform (from group context); must not be NULL. |
s is a valid pointer to at least len bytes. at <= close <= len.t is not modified; the local copy absorbs the element transform.Definition at line 218 of file reflow_svg_doc.c.
References internal_elem_at(), priv_ra8_svgp_apply_xform(), priv_ra8_svgp_draw_circle(), priv_ra8_svgp_draw_line(), priv_ra8_svgp_draw_path(), priv_ra8_svgp_draw_polygon(), priv_ra8_svgp_draw_polyline(), and priv_ra8_svgp_draw_rect().
Referenced by internal_draw_shapes().
|
static |
Walk every element in document order and draw the supported shapes.
Maintains a bounded group transform stack of depth k_svg_g_depth_max. Entering a 'g' element (via internal_group_open) composes its 'transform=' onto the current top and pushes. Encountering </g> pops. Each shape element inherits the top group transform via internal_xform_with_group, then composes its own element-level 'transform=' in internal_dispatch_shape. The scan is bounded: each iteration advances past one '<...>' tag or breaks.
| [in] | s | Full SVG document byte buffer; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | t | Base coordinate transform (box, viewBox, gradients); must not be NULL. |
s is a valid pointer to at least len bytes. t is a valid non-NULL pointer to an initialised svg_xform_t.s are drawn to the framebuffer. t is not modified; local copies absorb all transform composition.Definition at line 364 of file reflow_svg_doc.c.
References internal_dispatch_shape(), internal_elem_at(), internal_group_open(), internal_xform_with_group(), k_svg_g_depth_max, svg_xform_t::ua, svg_xform_t::ub, svg_xform_t::uc, svg_xform_t::ud, svg_xform_t::ue, and svg_xform_t::uf.
Referenced by ra8_svg_render().
|
static |
Test whether an element keyword begins at s[at] with a valid delimiter.
Uses priv_ra8_svgp_starts_ci to match name at at, then verifies that the character immediately following the keyword (when within len) is either XML whitespace, '>', or '/'. A match at end-of-buffer is accepted as a valid (self-closing or run-to-EOF) element. Used to identify element tag kinds during the document walk without allocating strings.
| [in] | s | Byte buffer containing the SVG text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | at | Byte offset at which to test for the element name. |
| [in] | name | NUL-terminated element keyword (including '<'); must not be NULL. |
name begins at at with a valid post-name delimiter. | true | name matches at at and is followed by a valid delimiter. |
| false | name does not match or the following character is not a delimiter. |
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. Definition at line 65 of file reflow_svg_doc.c.
References priv_ra8_svgp_starts_ci(), priv_ra8_svgp_ws(), and strlen().
Referenced by internal_dispatch_shape(), and internal_draw_shapes().
|
static |
Handle a 'g' open tag: compose its 'transform=' over the stack top and push.
Builds a local transform by composing the current stack-top affine with any 'transform=' attribute on the 'g' element via priv_ra8_svgp_apply_xform. Self-closing 'g/' elements (detected by '/' before '>') and groups that would exceed k_svg_g_depth_max are not pushed; in those cases gsp is returned unchanged. Otherwise the new affine is pushed as gstk[gsp+1] and gsp+1 is returned.
| [in] | s | Full SVG document byte buffer; must not be NULL. |
| [in] | i | Byte offset of the '<g' tag start. |
| [in] | close | Byte offset of the '>' terminator for the 'g' tag. |
| [in] | t | Base coordinate transform (box/viewBox); must not be NULL. |
| [in] | gstk | Group transform stack of at least k_svg_g_depth_max+1 elements; must not be NULL. |
| [in] | gsp | Current group stack pointer (index of the top entry). |
| gsp | Self-closing 'g' or depth-cap reached; stack unchanged. |
| gsp+1 | The new group's affine was pushed; stack pointer advanced. |
s is a valid pointer to at least close bytes. gsp is in [0, k_svg_g_depth_max].gstk[gsp+1] holds the composed affine when the return value is gsp+1. gstk and t are not modified when gsp is returned.Definition at line 310 of file reflow_svg_doc.c.
References internal_xform_with_group(), k_svg_g_depth_max, priv_ra8_svgp_apply_xform(), svg_xform_t::ua, svg_xform_t::ub, svg_xform_t::uc, svg_xform_t::ud, svg_xform_t::ue, and svg_xform_t::uf.
Referenced by internal_draw_shapes().
|
static |
Parse the 'stop' child elements of a gradient definition into g.
Scans s[from .. end) for '<stop' tags using priv_ra8_svgp_find_ci. For each found stop tag, extracts the offset via internal_stop_offset (clamped via internal_clamp01) and the colour via internal_stop_color, stores them in g->stops[g->nstops], and increments g->nstops. Bounded by k_svg_grad_stops; stops beyond the limit are silently dropped.
| [in] | s | Full SVG document byte buffer; must not be NULL. |
| [in] | from | Start offset of the gradient body (after the opening tag). |
| [in] | end | End offset (exclusive; position of the closing tag). |
| [in,out] | g | Gradient to populate; nstops and stops are updated. |
s is a valid pointer to at least end bytes. g is a valid non-NULL pointer with g->nstops <= k_svg_grad_stops.g->stops[0..nstops-1] hold the parsed stop data. g->nstops <= k_svg_grad_stops.Definition at line 625 of file reflow_svg_doc.c.
References svg_stop_t::col, internal_clamp01(), internal_stop_color(), internal_stop_offset(), k_svg_grad_stops, svg_grad_t::nstops, svg_stop_t::off, priv_ra8_svgp_find_ci(), and svg_grad_t::stops.
Referenced by internal_scan_grads().
|
static |
Fill t's viewBox fields from the SVG root element.
Searches for the first '<svg' tag and attempts to read a 'viewBox' attribute (four integers: min-x, min-y, width, height). If absent, falls back to 'width' and 'height' attributes. If those are also absent, the viewBox defaults to (0, 0, bw, bh) so that the SVG user space equals the target box with no scaling. Values with zero width or height are ignored.
| [in] | s | Byte buffer containing the full SVG document; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in,out] | t | Transform; vx, vy, vw, vh are written. |
s is a valid pointer to at least len bytes. t is a valid non-NULL pointer with t->bw and t->bh set.t->vx, t->vy, t->vw, t->vh reflect the parsed viewBox. t->vw > 0 and t->vh > 0 on exit.Definition at line 154 of file reflow_svg_doc.c.
References svg_xform_t::bh, svg_xform_t::bw, internal_tag_span(), k_svg_viewbox_n, priv_ra8_svgp_attr(), priv_ra8_svgp_attr_num(), priv_ra8_svgp_num(), svg_xform_t::vh, svg_xform_t::vw, svg_xform_t::vx, and svg_xform_t::vy.
Referenced by ra8_svg_render().
|
static |
Scan the document for gradient definitions and populate gs.
Searches the document for '<linearGradient' and '<radialGradient' opening tags in document order. For each found gradient, reads the 'id', 'x1', 'y1', 'x2', 'y2' (linear) or 'cx', 'cy', 'r' (radial) attributes and populates a new entry in gs->g. Then locates the matching closing tag and calls internal_parse_stops to fill the stop list. Bounded by k_svg_grad_max; additional gradients are silently dropped.
| [in] | s | Full SVG document byte buffer; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [out] | gs | Gradient set to populate; n and g are written. |
s is a valid pointer to at least len bytes. gs is a valid non-NULL pointer to a writable svg_grads_t.gs->n holds the count of parsed gradients (<= k_svg_grad_max). gs->g[0..n-1] are valid, fully-populated svg_grad_t entries.Definition at line 673 of file reflow_svg_doc.c.
References svg_grads::g, svg_grad_t::id, internal_attr_numf(), internal_copy_attr_id(), internal_parse_stops(), k_svg_grad_linear, k_svg_grad_max, k_svg_grad_radial, svg_grad_t::kind, svg_grads::n, svg_grad_t::nstops, priv_ra8_svgp_find_ci(), s_svg_unit, svg_grad_t::x1, svg_grad_t::x2, svg_grad_t::y1, and svg_grad_t::y2.
Referenced by ra8_svg_render().
|
static |
Parse a gradient 'stop' element's 'stop-color' attribute.
Reads the "stop-color" attribute from the stop tag via priv_ra8_svgp_attr and parses the value as a paint via priv_ra8_svgp_paint. If the attribute is absent or the paint parses to k_svg_no_paint (e.g. "none"), returns the SVG default fill colour k_svg_def_fill (black).
| [in] | tag | Byte span of the 'stop' element tag; must not be NULL. |
| [in] | tlen | Total valid bytes in tag. |
| (uint32_t)k_svg_def_fill | Attribute absent or parses to no-paint. |
| 0x000000..0xFFFFFF | The parsed solid stop colour. |
tag is a valid pointer to at least tlen bytes. tlen > 0 when the tag is expected to contain attributes.tag is not modified. Definition at line 588 of file reflow_svg_doc.c.
References k_svg_def_fill, k_svg_no_paint, priv_ra8_svgp_attr(), and priv_ra8_svgp_paint().
Referenced by internal_parse_stops().
|
static |
Parse a gradient 'stop' element's 'offset' attribute.
Reads the "offset" attribute from the stop tag via priv_ra8_svgp_attr and parses its value as a float via priv_ra8_svgp_numf. If a '' character is found anywhere in the attribute value span, the result is divided by the function-local 100.0F percentage scale to convert from percentage to fraction. Returns 0.0F when the attribute is absent. The caller is responsible for clamping via internal_clamp01.
| [in] | tag | Byte span of the 'stop' element tag; must not be NULL. |
| [in] | tlen | Total valid bytes in tag. |
| 0.0F | Attribute "offset" is absent. |
| n | Parsed offset; divide by 100 if given as a percentage. |
tag is a valid pointer to at least tlen bytes. tlen > 0 when the tag is expected to contain attributes.tag is not modified. Definition at line 543 of file reflow_svg_doc.c.
References priv_ra8_svgp_attr(), and priv_ra8_svgp_numf().
Referenced by internal_parse_stops().
|
static |
Locate the tag span [*open, *close) of element name at or after from.
Calls priv_ra8_svgp_find_ci to find the first occurrence of name in s[from .. len). If found, scans forward for the next '>' character to determine the end of the tag. Sets *open to the start of the match and *close to the position of '>'. If name is not found, returns false.
| [in] | s | Byte buffer containing the SVG text; must not be NULL. |
| [in] | len | Total valid bytes in s. |
| [in] | from | Start offset for the search; must be <= len. |
| [in] | name | NUL-terminated keyword to find; must not be NULL. |
| [out] | open | Set to the byte offset of the keyword match when found. |
| [out] | close | Set to the byte offset of the '>' terminator when found. |
| true | name found; *open and *close are valid. |
| false | name not found in s[from .. len). |
s is a valid pointer to at least len bytes. open and close are valid non-NULL output pointers.*open <= *close <= len. *open and *close are indeterminate.Definition at line 109 of file reflow_svg_doc.c.
References priv_ra8_svgp_find_ci().
Referenced by internal_read_viewbox(), ra8_svg_image_href(), and ra8_svg_size().
|
static |
Copy the base transform t into out and replace the user affine with g.
Copies all fields of t (box, viewBox, gradient set) into out, then overwrites the six user-affine fields (ua .. uf) with the corresponding components of g. This produces a transform that has the same viewBox/box mapping as t but uses the group's accumulated affine.
| [in] | t | Base transform whose box/viewBox/grads are preserved; must not be NULL. |
| [in] | g | Group affine to install in out. |
| [out] | out | Transform to write; must not be NULL; may alias t. |
t is a valid non-NULL pointer to an initialised svg_xform_t. out is a valid non-NULL pointer to a writable svg_xform_t.out->ua .. out->uf equal the fields of g. out equal those of t.Definition at line 266 of file reflow_svg_doc.c.
References svg_utf_t::a, svg_utf_t::b, svg_utf_t::c, svg_utf_t::d, svg_utf_t::e, svg_utf_t::f, svg_xform_t::ua, svg_xform_t::ub, svg_xform_t::uc, svg_xform_t::ud, svg_xform_t::ue, and svg_xform_t::uf.
Referenced by internal_draw_shapes(), and internal_group_open().
|
nodiscard |
Extract the href of a cover-wrapper <svg><image .../></svg>.
Scans for the first <image> element and returns its xlink:href / href attribute value as a slice into svg. The caller resolves + decodes that raster through its normal image path.
| [in] | svg | SVG document bytes. |
| [in] | len | Length of svg. |
| [out] | out_off | Receives the href slice offset into svg. |
| [out] | out_len | Receives the href slice length, bytes. |
| k_ra8_ok | An <image> href was found. |
| k_ra8_err_null_ptr | A required pointer is NULL. |
| k_ra8_err_not_found | No <image> with an href was present. |
svg, out_off, out_len non-NULL. svg. Definition at line 741 of file reflow_svg_doc.c.
References internal_tag_span(), k_ra8_err_not_found, k_ra8_err_null_ptr, k_ra8_ok, and priv_ra8_svgp_attr().
Referenced by internal_render_svg().
|
nodiscard |
Heuristically decide whether bytes are an SVG document.
Skips a leading UTF-8 BOM + whitespace and checks for <?xml or a <svg element start (case-insensitive). Used by the image path to route SVG bytes here instead of to the raster decoder.
| [in] | bytes | Candidate image bytes. |
| [in] | len | Length of bytes. |
bytes look like SVG. | false | bytes is NULL/empty or does not begin like SVG. |
Definition at line 723 of file reflow_svg_doc.c.
References k_svg_bom0, k_svg_bom1, k_svg_bom2, k_svg_bom_len, priv_ra8_svgp_starts_ci(), and priv_ra8_svgp_ws().
Referenced by internal_render_one_image(), and ra8_img_probe_size().
|
nodiscard |
Render an SVG's vector shapes into a box.
Establishes a coordinate transform from the SVG viewBox (or its width/height, defaulting to the box) onto the caller box (x,y,w,h), then walks the supported shapes (<rect> / <circle> / <polygon> filled, <line> / <polyline> stroked) and draws each through the bound ra8_gfx framebuffer with its fill or stroke colour. fill="none" shapes are skipped. Coordinates outside the box are clipped by ra8_gfx.
| [in] | svg | SVG document bytes. |
| [in] | len | Length of svg. |
| [in] | x | Box left, framebuffer pixels. |
| [in] | y | Box top, framebuffer pixels. |
| [in] | w | Box width, pixels (> 0). |
| [in] | h | Box height, pixels (> 0). |
| k_ra8_ok | Rendered (possibly zero shapes). |
| k_ra8_err_null_ptr | svg is NULL. |
| k_ra8_err_invalid_arg | w or h is non-positive. |
svg non-NULL; ra8_gfx_init() has bound a framebuffer. w > 0 and h > 0. (x,y,w,h). Definition at line 799 of file reflow_svg_doc.c.
References svg_xform_t::grads, internal_draw_shapes(), internal_read_viewbox(), internal_scan_grads(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, and k_ra8_ok.
Referenced by es_render_svg_or_halt(), and internal_render_svg().
|
nodiscard |
Report an SVG's intrinsic size (width/height, else viewBox dimensions).
Lets the layout reserve an <img src="*.svg"> box without a raster decode. Prefers the <svg> width/height attributes (units ignored), and falls back to the viewBox width/height.
| [in] | svg | SVG document bytes. |
| [in] | len | Length of svg. |
| [out] | out_w | Receives the intrinsic width, pixels. |
| [out] | out_h | Receives the intrinsic height, pixels. |
| k_ra8_ok | A positive size was determined. |
| k_ra8_err_null_ptr | A required pointer is NULL. |
| k_ra8_err_not_found | No <svg> or no positive size present. |
svg, out_w, out_h non-NULL. *out_w > 0 and *out_h > 0. Definition at line 764 of file reflow_svg_doc.c.
References internal_tag_span(), k_ra8_err_not_found, k_ra8_err_null_ptr, k_ra8_ok, k_svg_viewbox_n, priv_ra8_svgp_attr(), priv_ra8_svgp_attr_num(), and priv_ra8_svgp_num().
Referenced by es_render_svg_or_halt(), and ra8_img_probe_size().
|
static |
Gradient parameter / offset upper clamp.
Definition at line 28 of file reflow_svg_doc.c.
Referenced by internal_clamp01(), and internal_scan_grads().