12#define COLOR_TABLE_SIZE 1024
56 uint32_t alpha = lroundf(
color->
a * opacity * 255);
57 uint32_t pr = lroundf(
color->
r * alpha);
58 uint32_t pg = lroundf(
color->
g * alpha);
59 uint32_t pb = lroundf(
color->
b * alpha);
60 return (alpha << 24) | (pr << 16) | (pg << 8) | (pb);
65 uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
66 t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
69 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
70 x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
78 uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
82 x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
90 uint32_t t = (x & 0xff00ff) * a;
91 t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
94 x = ((x >> 8) & 0xff00ff) * a;
95 x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
105#include <emmintrin.h>
111 __m128i vector_data = _mm_set_epi32(value, value, value, value);
112 while(length && ((uintptr_t)dest & 0xf)) {
117 while(length >= 32) {
118 _mm_store_si128((__m128i*)(dest), vector_data);
119 _mm_store_si128((__m128i*)(dest + 4), vector_data);
120 _mm_store_si128((__m128i*)(dest + 8), vector_data);
121 _mm_store_si128((__m128i*)(dest + 12), vector_data);
122 _mm_store_si128((__m128i*)(dest + 16), vector_data);
123 _mm_store_si128((__m128i*)(dest + 20), vector_data);
124 _mm_store_si128((__m128i*)(dest + 24), vector_data);
125 _mm_store_si128((__m128i*)(dest + 28), vector_data);
132 _mm_store_si128((__m128i*)(dest), vector_data);
133 _mm_store_si128((__m128i*)(dest + 4), vector_data);
134 _mm_store_si128((__m128i*)(dest + 8), vector_data);
135 _mm_store_si128((__m128i*)(dest + 12), vector_data);
142 _mm_store_si128((__m128i*)(dest), vector_data);
143 _mm_store_si128((__m128i*)(dest + 4), vector_data);
150 _mm_store_si128((__m128i*)(dest), vector_data);
181 ipos = ipos < 0 ? limit + ipos : ipos;
195#define FIXPT_SIZE (1 << FIXPT_BITS)
211 float rx = 0, ry = 0;
218 t = v->
dx * rx + v->
dy * ry + v->
off;
224 const uint32_t* end = buffer + length;
225 if(inc > -1e-5f && inc < 1e-5f) {
228 if(t + inc * length < (
float)(INT_MAX >> (
FIXPT_BITS + 1)) && t + inc * length > (
float)(INT_MIN >> (
FIXPT_BITS + 1))) {
231 while(buffer < end) {
233 t_fixed += inc_fixed;
237 while(buffer < end) {
259 float inv_a = 1.f / (2.f * v->
a);
260 float delta_rx = gradient->
matrix.
a;
261 float delta_ry = gradient->
matrix.
b;
264 float delta_b = 2 * (delta_rx * v->
dx + delta_ry * v->
dy);
265 float b_delta_b = 2 * b * delta_b;
266 float delta_b_delta_b = 2 * delta_b * delta_b;
269 float delta_bb = delta_b * delta_b;
274 float rxrxryry = rx * rx + ry * ry;
275 float delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
276 float rx_plus_ry = 2 * (rx * delta_rx + ry * delta_ry);
277 float delta_rx_plus_ry = 2 * delta_rxrxryry;
281 float det = (bb - 4 * v->
a * (v->
sqrfr - rxrxryry)) * inv_a;
282 float delta_det = (b_delta_b + delta_bb + 4 * v->
a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
283 float delta_delta_det = (delta_b_delta_b + 4 * v->
a * delta_rx_plus_ry) * inv_a;
285 const uint32_t* end = buffer + length;
287 while(buffer < end) {
290 float w = sqrtf(det) - b;
298 delta_det += delta_delta_det;
303 while(buffer < end) {
306 delta_det += delta_delta_det;
314 if(const_alpha == 255) {
317 uint32_t ialpha = 255 - const_alpha;
318 for(
int i = 0; i < length; i++) {
319 dest[i] =
BYTE_MUL(dest[i], ialpha);
326 if(const_alpha == 255) {
329 uint32_t ialpha = 255 - const_alpha;
331 for(
int i = 0; i < length; i++) {
343 if(const_alpha != 255)
346 for(
int i = 0; i < length; i++) {
353 if(const_alpha != 255)
355 for(
int i = 0; i < length; i++) {
356 uint32_t d = dest[i];
363 if(const_alpha == 255) {
364 for(
int i = 0; i < length; i++) {
369 uint32_t cia = 255 - const_alpha;
370 for(
int i = 0; i < length; i++) {
371 uint32_t d = dest[i];
380 if(const_alpha != 255)
381 a =
BYTE_MUL(a, const_alpha) + 255 - const_alpha;
382 for(
int i = 0; i < length; i++) {
389 if(const_alpha == 255) {
390 for(
int i = 0; i < length; i++) {
395 uint32_t cia = 255 - const_alpha;
396 for(
int i = 0; i < length; i++) {
397 uint32_t d = dest[i];
406 if(const_alpha != 255)
407 a =
BYTE_MUL(a, const_alpha) + 255 - const_alpha;
408 for(
int i = 0; i < length; i++) {
415 if(const_alpha != 255)
418 for(
int i = 0; i < length; i++) {
419 uint32_t d = dest[i];
427 if(const_alpha != 255) {
432 for(
int i = 0; i < length; i++) {
433 uint32_t d = dest[i];
440 if(const_alpha != 255)
443 for(
int i = 0; i < length; i++) {
444 uint32_t d = dest[i];
461 return (x * y + 127) / 255;
464template<operator_t Mode>
483template<operator_t Mode>
491 uint32_t result = uint32_t(ar) << 24;
492 for(
int shift = 16; shift >= 0; shift -= 8) {
493 int c = blend_mode_channel<Mode>(
int((src >> shift) & 0xff),
int((dest >> shift) & 0xff), as, ab);
495 result |= uint32_t(c) << shift;
501template<operator_t Mode>
504 for(
int i = 0; i < length; i++) {
505 uint32_t s = const_alpha == 255 ? src[i] :
BYTE_MUL(src[i], const_alpha);
506 dest[i] = blend_mode_pixel<Mode>(dest[i], s);
510template<operator_t Mode>
513 if(const_alpha != 255)
515 for(
int i = 0; i < length; i++)
516 dest[i] = blend_mode_pixel<Mode>(dest[i],
color);
534 composition_solid_blend_mode<NOVASVG_OPERATOR_MULTIPLY>,
535 composition_solid_blend_mode<NOVASVG_OPERATOR_SCREEN>,
536 composition_solid_blend_mode<NOVASVG_OPERATOR_DARKEN>,
537 composition_solid_blend_mode<NOVASVG_OPERATOR_LIGHTEN>,
538 composition_solid_blend_mode<NOVASVG_OPERATOR_DIFFERENCE>,
539 composition_solid_blend_mode<NOVASVG_OPERATOR_EXCLUSION>
544 if(const_alpha == 255) {
547 uint32_t ialpha = 255 - const_alpha;
548 for(
int i = 0; i < length; i++) {
549 dest[i] =
BYTE_MUL(dest[i], ialpha);
556 if(const_alpha == 255) {
557 memcpy(dest, src, length *
sizeof(uint32_t));
559 uint32_t ialpha = 255 - const_alpha;
560 for(
int i = 0; i < length; i++) {
572 if(const_alpha == 255) {
573 for(
int i = 0; i < length; i++) {
575 if(s >= 0xff000000) {
582 for(
int i = 0; i < length; i++) {
583 uint32_t s =
BYTE_MUL(src[i], const_alpha);
591 if(const_alpha == 255) {
592 for(
int i = 0; i < length; i++) {
593 uint32_t d = dest[i];
597 for(
int i = 0; i < length; i++) {
598 uint32_t d = dest[i];
599 uint32_t s =
BYTE_MUL(src[i], const_alpha);
607 if(const_alpha == 255) {
608 for(
int i = 0; i < length; i++) {
612 uint32_t cia = 255 - const_alpha;
613 for(
int i = 0; i < length; i++) {
614 uint32_t d = dest[i];
615 uint32_t s =
BYTE_MUL(src[i], const_alpha);
623 if(const_alpha == 255) {
624 for(
int i = 0; i < length; i++) {
628 uint32_t cia = 255 - const_alpha;
629 for(
int i = 0; i < length; i++) {
638 if(const_alpha == 255) {
639 for(
int i = 0; i < length; i++) {
643 uint32_t cia = 255 - const_alpha;
644 for(
int i = 0; i < length; i++) {
645 uint32_t s =
BYTE_MUL(src[i], const_alpha);
646 uint32_t d = dest[i];
654 if(const_alpha == 255) {
655 for(
int i = 0; i < length; i++) {
659 uint32_t cia = 255 - const_alpha;
660 for(
int i = 0; i < length; i++) {
669 if(const_alpha == 255) {
670 for(
int i = 0; i < length; i++) {
672 uint32_t d = dest[i];
676 for(
int i = 0; i < length; i++) {
677 uint32_t s =
BYTE_MUL(src[i], const_alpha);
678 uint32_t d = dest[i];
686 if(const_alpha == 255) {
687 for(
int i = 0; i < length; i++) {
689 uint32_t d = dest[i];
693 uint32_t cia = 255 - const_alpha;
694 for(
int i = 0; i < length; i++) {
695 uint32_t s =
BYTE_MUL(src[i], const_alpha);
696 uint32_t d = dest[i];
705 if(const_alpha == 255) {
706 for(
int i = 0; i < length; i++) {
707 uint32_t d = dest[i];
712 for(
int i = 0; i < length; i++) {
713 uint32_t d = dest[i];
714 uint32_t s =
BYTE_MUL(src[i], const_alpha);
735 composition_blend_mode<NOVASVG_OPERATOR_MULTIPLY>,
736 composition_blend_mode<NOVASVG_OPERATOR_SCREEN>,
737 composition_blend_mode<NOVASVG_OPERATOR_DARKEN>,
738 composition_blend_mode<NOVASVG_OPERATOR_LIGHTEN>,
739 composition_blend_mode<NOVASVG_OPERATOR_DIFFERENCE>,
740 composition_blend_mode<NOVASVG_OPERATOR_EXCLUSION>
755#define BUFFER_SIZE 1024
775 int length = spans->
len;
781 func(target, l, buffer, spans->
coverage);
806 int length = spans->
len;
812 func(target, l, buffer, spans->
coverage);
825 const int image_width = texture->
width;
826 const int image_height = texture->
height;
828 int xoff = (int)(texture->
matrix.
e);
829 int yoff = (int)(texture->
matrix.
f);
835 int length = spans->
len;
837 int sy = yoff + spans->
y;
838 if(sy >= 0 && sy < image_height && sx < image_width) {
845 if(sx + length > image_width)
846 length = image_width - sx;
849 const uint32_t* src = (
const uint32_t*)(texture->
data + sy * texture->
stride) + sx;
851 func(dest, length, src, coverage);
859#define FIXED_SCALE (1 << 16)
865 int image_width = texture->
width;
866 int image_height = texture->
height;
876 const float cx = spans->
x + 0.5f;
877 const float cy = spans->
y + 0.5f;
882 int length = spans->
len;
886 const uint32_t* end = buffer + l;
887 uint32_t* b = buffer;
891 if((px < 0) || (px >= image_width) || (py < 0) || (py >= image_height)) {
894 *b = ((
const uint32_t*)(texture->
data + py * texture->
stride))[px];
902 func(target, l, buffer, coverage);
915 int image_width = texture->
width;
916 int image_height = texture->
height;
918 int xoff = (int)(texture->
matrix.
e) % image_width;
919 int yoff = (int)(texture->
matrix.
f) % image_height;
924 yoff += image_height;
931 int length = spans->
len;
932 int sx = (xoff + spans->
x) % image_width;
933 int sy = (spans->
y + yoff) % image_height;
945 const uint32_t* src = (
const uint32_t*)(texture->
data + sy * texture->
stride) + sx;
947 func(dest, l, src, coverage);
951 if(sx >= image_width) {
965 int image_width = texture->
width;
966 int image_height = texture->
height;
967 const int scanline_offset = texture->
stride / 4;
976 const uint32_t* image_bits = (
const uint32_t*)texture->
data;
978 const float cx = spans->
x + 0.5f;
979 const float cy = spans->
y + 0.5f;
985 int length = spans->
len;
988 const uint32_t* end = buffer + l;
989 uint32_t* b = buffer;
995 if(px < 0) px += image_width;
996 if(py < 0) py += image_height;
997 int y_offset = py * scanline_offset;
999 assert(px >= 0 && px < image_width);
1000 assert(py >= 0 && py < image_height);
1002 *b = image_bits[y_offset + px];
1008 func(target, l, buffer, coverage);
1019 uint32_t idistx = 256 - distx;
1020 uint32_t idisty = 256 - disty;
1026#define HALF_POINT (1 << 15)
1032 int image_width = texture->
width;
1033 int image_height = texture->
height;
1043 const float cx = spans->
x + 0.5f;
1044 const float cy = spans->
y + 0.5f;
1053 int length = spans->
len;
1056 const uint32_t* end = buffer + l;
1057 uint32_t* b = buffer;
1059 int x1 = (fx >> 16) % image_width;
1060 int y1 = (fy >> 16) % image_height;
1062 if(x1 < 0) x1 += image_width;
1063 if(y1 < 0) y1 += image_height;
1065 int x2 = (x1 + 1) % image_width;
1066 int y2 = (y1 + 1) % image_height;
1068 const uint32_t* s1 = (
const uint32_t*)(texture->
data + y1 * texture->
stride);
1069 const uint32_t* s2 = (
const uint32_t*)(texture->
data + y2 * texture->
stride);
1071 uint32_t tl = s1[x1];
1072 uint32_t tr = s1[x2];
1073 uint32_t bl = s2[x1];
1074 uint32_t br = s2[x2];
1076 int distx = (fx & 0x0000ffff) >> 8;
1077 int disty = (fy & 0x0000ffff) >> 8;
1085 func(target, l, buffer, coverage);
1109 if(gradient->
nstops == 0)
1118 int i, pos = 0, nstops = gradient->
nstops;
1120 uint32_t curr_color, next_color, last_color;
1121 uint32_t dist, idist;
1122 float delta, t, incr, fpos;
1125 start = gradient->
stops;
1133 while(fpos <= curr->offset) {
1139 for(i = 0; i < nstops - 1; i++) {
1141 next = (start + i + 1);
1147 t = (fpos - curr->
offset) * delta;
1148 dist = (uint32_t)(255 * t);
1155 curr_color = next_color;
1158 last = start + nstops - 1;
1207 }
else if(fabsf(
matrix->
b) > 1e-6f || fabsf(
matrix->
c) > 1e-6f) {
#define NOVASVG_MAX(a, b)
#define NOVASVG_MIN(a, b)
NOVASVG_INLINE void composition_solid_destination_over(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE uint32_t premultiply_color_with_opacity(const color_t *color, float opacity)
NOVASVG_INLINE void fetch_radial_gradient(uint32_t *buffer, const radial_gradient_values_t *v, const gradient_data_t *gradient, int y, int x, int length)
NOVASVG_INLINE void composition_solid_destination(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE int gradient_clamp(const gradient_data_t *gradient, int ipos)
NOVASVG_INLINE void blend_color(canvas_t *canvas, const color_t *color, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_source_in(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_solid_blend_mode(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void blend_solid(surface_t *surface, operator_t op, uint32_t solid, const span_buffer_t *span_buffer)
@ NOVASVG_TEXTURE_TYPE_PLAIN
Plain texture.
NOVASVG_INLINE void blend_gradient(canvas_t *canvas, const gradient_paint_t *gradient, const span_buffer_t *span_buffer)
NOVASVG_INLINE void blend_untransformed_argb(surface_t *surface, operator_t op, const texture_data_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_destination_atop(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE int blend_mode_channel(int cs, int cb, int as, int ab)
NOVASVG_INLINE void composition_solid_source_atop(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE uint32_t blend_mode_pixel(uint32_t dest, uint32_t src)
NOVASVG_INLINE void blend_texture(canvas_t *canvas, const texture_paint_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_solid_source_out(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE uint32_t gradient_pixel_fixed(const gradient_data_t *gradient, int fixed_pos)
NOVASVG_INLINE void composition_solid_destination_out(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void composition_source(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_source_over(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void blend_untransformed_tiled_argb(surface_t *surface, operator_t op, const texture_data_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE const composition_function_t composition_table[]
NOVASVG_INLINE uint32_t gradient_pixel(const gradient_data_t *gradient, float pos)
NOVASVG_INLINE int blend_mul255(int x, int y)
NOVASVG_INLINE void composition_solid_destination_atop(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void composition_destination_in(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_solid_source(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void composition_solid_clear(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
void(* composition_function_t)(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_destination_over(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_source_out(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE uint32_t INTERPOLATE_PIXEL_255(uint32_t x, uint32_t a, uint32_t y, uint32_t b)
NOVASVG_INLINE void composition_solid_source_in(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void blend_transformed_bilinear_tiled_argb(surface_t *surface, operator_t op, const texture_data_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE bool matrix_invert(const matrix_t *matrix, matrix_t *inverse)
Calculates the inverse of matrix and stores it in inverse.
NOVASVG_INLINE void composition_solid_destination_in(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void blend_linear_gradient(surface_t *surface, operator_t op, const gradient_data_t *gradient, const span_buffer_t *span_buffer)
NOVASVG_INLINE uint32_t INTERPOLATE_PIXEL_256(uint32_t x, uint32_t a, uint32_t y, uint32_t b)
NOVASVG_INLINE void blend(canvas_t *canvas, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_xor(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void fetch_linear_gradient(uint32_t *buffer, const linear_gradient_values_t *v, const gradient_data_t *gradient, int y, int x, int length)
NOVASVG_INLINE void blend_transformed_argb(surface_t *surface, operator_t op, const texture_data_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_source_atop(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void blend_radial_gradient(surface_t *surface, operator_t op, const gradient_data_t *gradient, const span_buffer_t *span_buffer)
NOVASVG_INLINE void composition_clear(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
operator_t
Defines compositing operations.
@ NOVASVG_OPERATOR_SRC
Source replaces destination.
@ NOVASVG_OPERATOR_MULTIPLY
Backdrop * source: darkens, white is neutral.
@ NOVASVG_OPERATOR_LIGHTEN
The lighter of backdrop and source, per channel.
@ NOVASVG_OPERATOR_DARKEN
The darker of backdrop and source, per channel.
@ NOVASVG_OPERATOR_SRC_OVER
Source is composited over destination.
@ NOVASVG_OPERATOR_DIFFERENCE
Absolute difference of backdrop and source, per channel.
@ NOVASVG_OPERATOR_SCREEN
Inverse of multiply: lightens, black is neutral.
NOVASVG_INLINE void memfill32(unsigned int *dest, int length, unsigned int value)
NOVASVG_INLINE void blend_transformed_tiled_argb(surface_t *surface, operator_t op, const texture_data_t *texture, const span_buffer_t *span_buffer)
NOVASVG_INLINE uint32_t BYTE_MUL(uint32_t x, uint32_t a)
NOVASVG_INLINE void matrix_multiply(matrix_t *matrix, const matrix_t *left, const matrix_t *right)
Multiplies left and right matrices and stores the result in matrix.
spread_method_t
Defines the spread method for gradients.
@ NOVASVG_SPREAD_METHOD_REFLECT
Reflect the gradient beyond its bounds.
@ NOVASVG_SPREAD_METHOD_REPEAT
Repeat the gradient pattern.
NOVASVG_INLINE void composition_destination_out(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE void composition_solid_xor(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void composition_blend_mode(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
NOVASVG_INLINE uint32_t interpolate_4_pixels(uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br, uint32_t distx, uint32_t disty)
void(* composition_solid_function_t)(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE void composition_destination(uint32_t *dest, int length, const uint32_t *src, uint32_t const_alpha)
@ NOVASVG_PAINT_TYPE_GRADIENT
@ NOVASVG_PAINT_TYPE_COLOR
@ NOVASVG_GRADIENT_TYPE_LINEAR
NOVASVG_INLINE void composition_solid_source_over(uint32_t *dest, int length, uint32_t color, uint32_t const_alpha)
NOVASVG_INLINE const composition_solid_function_t composition_solid_table[]
Main namespace for the NovaSVG library.
Represents a color with red, green, blue, and alpha components.
float b
Blue component (0 to 1).
float g
Green component (0 to 1).
float a
Alpha (opacity) component (0 to 1).
float r
Red component (0 to 1).
union novasvg::render::gradient_data_t::@0 values
struct novasvg::render::gradient_data_t::@0::@2 radial
struct novasvg::render::gradient_data_t::@0::@1 linear
uint32_t colortable[1024]
Represents a gradient stop.
color_t color
The color of the gradient stop.
float offset
The offset of the gradient stop, as a value between 0 and 1.
A structure representing a 2D transformation matrix.
float d
The vertical scaling factor.
float c
The horizontal shearing factor.
float f
The vertical translation offset.
float e
The horizontal translation offset.
float b
The vertical shearing factor.
float a
The horizontal scaling factor.
struct novasvg::render::span_buffer_t::@12 spans