142 const float dx = (float)r * cosf(ang);
143 const float dy = (float)r * sinf(ang);
239 while ((k < vlen) && (
priv_ra8_svgp_ws((
char)v[k]) || (v[k] == (uint8_t)
','))) {
280 for (int32_t i = 1; i < m; ++i) {
281 const int32_t key = a[i];
283 while ((j >= 0) && (a[j] > key)) {
328 for (int32_t i = 0; (i < n) && (m < (int32_t)
k_svg_poly_max); ++i) {
329 const int32_t j = (i + 1) % n;
330 const int32_t y0 = ys[i];
331 const int32_t y1 = ys[j];
333 if (((y0 <= y) && (y < y1)) || ((y1 <= y) && (y < y0))) {
334 const int32_t x0 = xs[i];
335 const int32_t x1 = xs[j];
336 const int64_t y_delta = (int64_t)y - (int64_t)y0;
337 const int64_t x_delta = (int64_t)x1 - (int64_t)x0;
338 const int64_t divisor = (int64_t)y1 - (int64_t)y0;
339 const int64_t offset = (y_delta * x_delta) / divisor;
340 xint[m] = x0 + (int32_t)offset;
376 int32_t ymin = ys[0];
377 int32_t ymax = ys[0];
378 for (int32_t i = 1; i < n; ++i) {
379 ymin = (ys[i] < ymin) ? ys[i] : ymin;
380 ymax = (ys[i] > ymax) ? ys[i] : ymax;
383 for (int32_t y = ymin; y <= ymax; ++y) {
387 for (int32_t k = 0; (k + 1) < m; k += 2) {
429 const int32_t ra = (int32_t)ra_bits;
430 const int32_t ga = (int32_t)ga_bits;
431 const int32_t ba = (int32_t)ba_bits;
432 const int32_t rb = (int32_t)rb_bits;
433 const int32_t gb = (int32_t)gb_bits;
434 const int32_t bb = (int32_t)bb_bits;
435 const int32_t rd = rb - ra;
436 const int32_t gd = gb - ga;
437 const int32_t bd = bb - ba;
438 const int32_t r = ra + (int32_t)((
float)rd * f);
439 const int32_t g = ga + (int32_t)((
float)gd * f);
440 const int32_t bl = ba + (int32_t)((
float)bd * f);
484 const float dx = px - g->
x1;
485 const float dy = py - g->
y1;
486 const float rr = (g->
x2 > 0.0F) ? g->
x2 : 1.0F;
487 p = sqrtf((dx * dx) + (dy * dy)) / rr;
489 const float vx = g->
x2 - g->
x1;
490 const float vy = g->
y2 - g->
y1;
491 const float len2 = (vx * vx) + (vy * vy);
492 p = (len2 > 0.0F) ? ((((px - g->
x1) * vx) + ((py - g->
y1) * vy)) / len2) : 0.0F;
494 if (p <= g->stops[0].off) {
497 const uint8_t last = (uint8_t)(g->
nstops - 1U);
502 for (uint8_t i = 0U; i < last; ++i) {
504 const float o1 = g->
stops[i + 1U].
off;
506 if ((p >= o0) && (p <= o1)) {
507 const float f = (o1 > o0) ? ((p - o0) / (o1 - o0)) : 0.0F;
549 int32_t xmin = xs[0];
550 int32_t xmax = xs[0];
551 int32_t ymin = ys[0];
552 int32_t ymax = ys[0];
553 for (int32_t i = 1; i < n; ++i) {
554 xmin = (xs[i] < xmin) ? xs[i] : xmin;
555 xmax = (xs[i] > xmax) ? xs[i] : xmax;
556 ymin = (ys[i] < ymin) ? ys[i] : ymin;
557 ymax = (ys[i] > ymax) ? ys[i] : ymax;
559 const float bw = (xmax > xmin) ? (
float)((int64_t)xmax - (int64_t)xmin) : 1.0F;
560 const float bh = (ymax > ymin) ? (
float)((int64_t)ymax - (int64_t)ymin) : 1.0F;
562 for (int32_t y = ymin; y <= ymax; ++y) {
566 const float py = (float)((int64_t)y - (int64_t)ymin) / bh;
567 for (int32_t k = 0; (k + 1) < m; k += 2) {
569 for (int32_t x = xint[k]; x <= xint[k + 1]; ++x) {
570 const float px = (float)((int64_t)x - (int64_t)xmin) / bw;
656 for (int32_t i = 0; (i + 1) < n; ++i) {
657 (void)
ra8_gfx_line(xs[i], ys[i], xs[i + 1], ys[i + 1], stroke);
688 return (v < 0.0F) ? -v : v;
754 const float rx2 = rx * rx;
755 const float ry2 = ry * ry;
756 const float num = (rx2 * ry2) - (rx2 * y1p * y1p) - (ry2 * x1p * x1p);
757 const float den = (rx2 * y1p * y1p) + (ry2 * x1p * x1p);
758 float co = sqrtf((num > 0.0F) ? (num / den) : 0.0F);
759 if (large == sweep) {
762 const float cxp = co * ((rx * y1p) / ry);
763 const float cyp = -co * ((ry * x1p) / rx);
766 a->
t1 = atan2f((y1p - cyp) / ry, (x1p - cxp) / rx);
767 float dt = atan2f((-y1p - cyp) / ry, (-x1p - cxp) / rx) - a->
t1;
768 if (!sweep && (dt > 0.0F)) {
770 }
else if (sweep && (dt < 0.0F)) {
824 static const float k_pi = 3.14159265F;
825 static const float k_deg_half = 180.0F;
826 static const float k_half = 0.5F;
830 if ((rx == 0.0F) || (ry == 0.0F) || ((p0.
x == p_end.
x) && (p0.
y == p_end.
y))) {
834 const float phi = (float)rot_deg * (k_pi / k_deg_half);
837 const float dx = (float)((int64_t)p0.
x - (int64_t)p_end.
x) * k_half;
838 const float dy = (float)((int64_t)p0.
y - (int64_t)p_end.
y) * k_half;
841 const float lam = ((x1p * x1p) / (rx * rx)) + ((y1p * y1p) / (ry * ry));
843 const float s = sqrtf(lam);
847 const float mx = (float)((int64_t)p0.
x + (int64_t)p_end.
x) * k_half;
848 const float my = (float)((int64_t)p0.
y + (int64_t)p_end.
y) * k_half;
880 static const float k_arc_step = 0.39269908F;
881 int32_t segs = (int32_t)(
internal_absf(dt) / k_arc_step) + 1;
941 for (int32_t j = 1; (j <= segs) && (*n < (int32_t)
k_svg_poly_max); ++j) {
942 const float th = a.
t1 + (a.
dt * ((float)j / (float)segs));
943 const float ex = a.
rx * cosf(th);
944 const float ey = a.
ry * sinf(th);
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Software 2D graphics primitives layered on top of a caller-ownedframebuffer (DRW / D/AVE 2D / GLCDC r...
ra8_err_t ra8_gfx_circle(int32_t cx, int32_t cy, int32_t r, uint32_t color, bool filled)
Draw a circle using midpoint algorithm.
ra8_err_t ra8_gfx_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
Draw a line from (x0,y0) to (x1,y1) with Bresenham's algorithm.
ra8_err_t ra8_gfx_pixel(int32_t x, int32_t y, uint32_t color)
Set a single pixel.
ra8_err_t ra8_gfx_rect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color, bool filled)
Draw an axis-aligned rectangle.
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);...
bool priv_ra8_svgp_ws(char c)
Test whether a character is XML whitespace.
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.
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.
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_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.
Cross-TU surface for the split minimal-SVG subset (#112).
int32_t priv_ra8_svgp_sx(const svg_xform_t *t, int32_t sw)
Scale a user-space length by the user x scale and the viewBox x ratio.
void priv_ra8_svgp_map_point(const svg_xform_t *t, int32_t ux, int32_t uy, int32_t *fx, int32_t *fy)
Map a user-space point through the FULL affine, then viewBox->box.
int32_t priv_ra8_svgp_mx(const svg_xform_t *t, int32_t sx)
Map a user-space x coordinate to a framebuffer x coordinate.
bool priv_ra8_svgp_has_rot(const svg_xform_t *t)
Test whether the user transform contains rotation or shear.
@ k_svg_grad_radial
<radialGradient> kind.
@ k_svg_def_fill
SVG default fill is black.
@ k_svg_arc_large
A arg index: large-arc flag.
@ k_svg_sh_r
Red shift within 0x00RRGGBB.
@ k_svg_arc_seg_max
Max segments per arc flatten.
@ k_svg_poly_min
Min points for a fillable polygon.
@ k_svg_arc_rx
A arg index: semi-axis X.
@ k_svg_hex_chan
Bits per colour channel.
@ k_svg_no_paint
none / absent paint sentinel.
@ k_svg_poly_max
Max points / scanline crossings.
@ k_svg_arc_ry
A arg index: semi-axis Y.
@ k_svg_arc_sweep
A arg index: sweep flag.
@ k_svg_rect_pts
Corner count of a rectangle.
@ k_svg_arc_rot
A arg index: x-axis rotation.
@ k_svg_circle_seg
N-gon segments for a transformed circle.
@ k_svg_chan_mask
One 8-bit RGB channel mask.
int32_t priv_ra8_svgp_my(const svg_xform_t *t, int32_t sy)
Map a user-space y coordinate to a framebuffer y coordinate.
static int32_t internal_parse_points(const uint8_t *v, size_t vlen, const svg_xform_t *t, int32_t *xs, int32_t *ys)
Parse a 'points' attribute value into framebuffer-space vertices.
static void internal_arc_solve(svg_arc_t *a, float x1p, float y1p, float rx, float ry, float mx, float my, bool large, bool sweep)
Solve an arc's centre + start/sweep angles (F.6.5.2 / F.6.5.5-6).
static void internal_sort_i32(int32_t *a, int32_t m)
Sort m int32 values in a into ascending order using insertion sort.
void priv_ra8_svgp_fill_poly_grad(const int32_t *xs, const int32_t *ys, int32_t n, const svg_grad_t *g)
Per-pixel gradient scanline fill of polygon (xs,ys)[0..n).
void priv_ra8_svgp_draw_circle(const uint8_t *s, size_t len, const svg_xform_t *t)
Draw one SVG 'circle' element using its fill colour or gradient.
void priv_ra8_svgp_draw_polygon(const uint8_t *s, size_t len, const svg_xform_t *t)
Draw one SVG 'polygon' element as a filled polygon.
void priv_ra8_svgp_fill_poly(const int32_t *xs, const int32_t *ys, int32_t n, uint32_t color)
Even-odd scanline fill of polygon (xs,ys)[0..n) with a solid colour.
void priv_ra8_svgp_draw_polyline(const uint8_t *s, size_t len, const svg_xform_t *t)
Draw one SVG 'polyline' element as connected stroke line segments.
static uint32_t internal_col_lerp(uint32_t a, uint32_t b, float f)
Linear-interpolate two 0x00RRGGBB colours by factor f in [0, 1].
void priv_ra8_svgp_draw_rect(const uint8_t *s, size_t len, const svg_xform_t *t)
Draw one SVG 'rect' element using its fill colour or gradient.
void priv_ra8_svgp_flatten_arc(const svg_xform_t *t, svg_pt_t p0, const int32_t *args, svg_pt_t p_end, int32_t *xs, int32_t *ys, int32_t *n)
Flatten an SVG elliptical arc into the polygon vertex array.
static int32_t internal_scanline_x(const int32_t *xs, const int32_t *ys, int32_t n, int32_t y, int32_t *xint)
Collect framebuffer X coordinates where polygon edges cross scanline y.
static int32_t internal_arc_segs(float dt)
Compute a bounded segment count for an arc of signed sweep dt.
void priv_ra8_svgp_draw_line(const uint8_t *s, size_t len, const svg_xform_t *t)
Draw one SVG 'line' element using its stroke colour.
static const float s_svg_2pi
2*Pi, for wrapping an arc's signed sweep into range.
static uint32_t internal_grad_eval(const svg_grad_t *g, float px, float py)
Evaluate gradient g at bbox-relative point (px, py).
static svg_arc_t internal_arc_center(svg_pt_t p0, svg_pt_t p_end, int32_t rx_in, int32_t ry_in, int32_t rot_deg, bool large, bool sweep)
Convert an SVG endpoint-parametrised arc to centre parametrisation.
static float internal_absf(float v)
Compute the absolute value of a float without using libm fabsf.
Centre-parametrisation of an SVG elliptical arc.
float cos_phi
cos(x-axis rotation).
float dt
Signed sweep, radians.
float sin_phi
sin(x-axis rotation).
float cx
Centre X (user space).
float rx
Corrected semi-axis X.
float t1
Start angle, radians.
bool ok
False => degenerate (draw a line).
float cy
Centre Y (user space).
float ry
Corrected semi-axis Y.
A parsed linear/radial gradient in objectBoundingBox units.
float x2
Linear end x / radial radius.
uint8_t kind
k_svg_grad_linear / k_svg_grad_radial.
float y1
Linear start y / radial centre y.
float y2
Linear end y (unused for radial).
uint8_t nstops
Number of valid stops.
float x1
Linear start x / radial centre x.
svg_stop_t stops[k_svg_grad_stops]
Colour stops, in document order.
svg_grad_t g[k_svg_grad_max]
The gradient table.
A 2-D point in SVG user space (an x/y pair).
float off
Stop offset, clamped to [0,1].
uint32_t col
Stop colour, 0x00RRGGBB.