Squashed 'external/lunasvg/' changes from e0f786c9b..ead790126

ead790126 fix name conflict with rlottie #100
6192f2536 Fix fill default color #105
be5ec7a4f Release v2.3.4
29c32978d Fix std::clamp bug #105
41f21ccb1 Release v2.3.3

git-subtree-dir: external/lunasvg
git-subtree-split: ead790126004b86a2dbbe9f4aaf27e82e419721e
This commit is contained in:
Leon Styhre 2022-10-16 12:31:43 +02:00
parent 0d52738239
commit fd498ff35e
47 changed files with 4466 additions and 4397 deletions

View file

@ -6,6 +6,9 @@ PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/plutovg-blend.c" "${CMAKE_CURRENT_LIST_DIR}/plutovg-blend.c"
"${CMAKE_CURRENT_LIST_DIR}/plutovg-rle.c" "${CMAKE_CURRENT_LIST_DIR}/plutovg-rle.c"
"${CMAKE_CURRENT_LIST_DIR}/plutovg-dash.c" "${CMAKE_CURRENT_LIST_DIR}/plutovg-dash.c"
"${CMAKE_CURRENT_LIST_DIR}/plutovg-ft-raster.c"
"${CMAKE_CURRENT_LIST_DIR}/plutovg-ft-stroker.c"
"${CMAKE_CURRENT_LIST_DIR}/plutovg-ft-math.c"
) )
target_include_directories(lunasvg target_include_directories(lunasvg

View file

@ -15,95 +15,87 @@
/* */ /* */
/***************************************************************************/ /***************************************************************************/
#include "sw_ft_math.h" #include "plutovg-ft-math.h"
#include <math.h>
//form https://github.com/chromium/chromium/blob/59afd8336009c9d97c22854c52e0382b62b3aa5e/third_party/abseil-cpp/absl/base/internal/bits.h
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <intrin.h> #include <intrin.h>
static unsigned int __inline clz(unsigned int x) { static unsigned int __inline clz(unsigned int x) {
unsigned long r = 0; unsigned long r = 0;
if (x != 0) if (x != 0)
{ {
_BitScanReverse(&r, x); _BitScanReverse(&r, x);
} }
return r; return r;
} }
#define SW_FT_MSB(x) (clz(x)) #define PVG_FT_MSB(x) (clz(x))
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define SW_FT_MSB(x) (31 - __builtin_clz(x)) #define PVG_FT_MSB(x) (31 - __builtin_clz(x))
#else #else
static unsigned int __inline clz(unsigned int x) { static unsigned int __inline clz(unsigned int x) {
int c = 31; int c = 31;
x &= ~x + 1; x &= ~x + 1;
if (n & 0x0000FFFF) c -= 16; if (n & 0x0000FFFF) c -= 16;
if (n & 0x00FF00FF) c -= 8; if (n & 0x00FF00FF) c -= 8;
if (n & 0x0F0F0F0F) c -= 4; if (n & 0x0F0F0F0F) c -= 4;
if (n & 0x33333333) c -= 2; if (n & 0x33333333) c -= 2;
if (n & 0x55555555) c -= 1; if (n & 0x55555555) c -= 1;
return c; return c;
} }
#define SW_FT_MSB(x) (clz(x)) #define PVG_FT_MSB(x) (clz(x))
#endif #endif
#define PVG_FT_PAD_FLOOR(x, n) ((x) & ~((n)-1))
#define PVG_FT_PAD_ROUND(x, n) PVG_FT_PAD_FLOOR((x) + ((n) / 2), n)
#define PVG_FT_PAD_CEIL(x, n) PVG_FT_PAD_FLOOR((x) + ((n)-1), n)
#define PVG_FT_BEGIN_STMNT do {
#define PVG_FT_END_STMNT } while (0)
#define SW_FT_PAD_FLOOR(x, n) ((x) & ~((n)-1))
#define SW_FT_PAD_ROUND(x, n) SW_FT_PAD_FLOOR((x) + ((n) / 2), n)
#define SW_FT_PAD_CEIL(x, n) SW_FT_PAD_FLOOR((x) + ((n)-1), n)
#define SW_FT_BEGIN_STMNT do {
#define SW_FT_END_STMNT \
} \
while (0)
/* transfer sign leaving a positive number */ /* transfer sign leaving a positive number */
#define SW_FT_MOVE_SIGN(x, s) \ #define PVG_FT_MOVE_SIGN(x, s) \
SW_FT_BEGIN_STMNT \ PVG_FT_BEGIN_STMNT \
if (x < 0) { \ if (x < 0) { \
x = -x; \ x = -x; \
s = -s; \ s = -s; \
} \ } \
SW_FT_END_STMNT PVG_FT_END_STMNT
SW_FT_Long SW_FT_MulFix(SW_FT_Long a, SW_FT_Long b) PVG_FT_Long PVG_FT_MulFix(PVG_FT_Long a, PVG_FT_Long b)
{ {
SW_FT_Int s = 1; PVG_FT_Int s = 1;
SW_FT_Long c; PVG_FT_Long c;
SW_FT_MOVE_SIGN(a, s); PVG_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s); PVG_FT_MOVE_SIGN(b, s);
c = (SW_FT_Long)(((SW_FT_Int64)a * b + 0x8000L) >> 16); c = (PVG_FT_Long)(((PVG_FT_Int64)a * b + 0x8000L) >> 16);
return (s > 0) ? c : -c; return (s > 0) ? c : -c;
} }
SW_FT_Long SW_FT_MulDiv(SW_FT_Long a, SW_FT_Long b, SW_FT_Long c) PVG_FT_Long PVG_FT_MulDiv(PVG_FT_Long a, PVG_FT_Long b, PVG_FT_Long c)
{ {
SW_FT_Int s = 1; PVG_FT_Int s = 1;
SW_FT_Long d; PVG_FT_Long d;
SW_FT_MOVE_SIGN(a, s); PVG_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s); PVG_FT_MOVE_SIGN(b, s);
SW_FT_MOVE_SIGN(c, s); PVG_FT_MOVE_SIGN(c, s);
d = (SW_FT_Long)(c > 0 ? ((SW_FT_Int64)a * b + (c >> 1)) / c : 0x7FFFFFFFL); d = (PVG_FT_Long)(c > 0 ? ((PVG_FT_Int64)a * b + (c >> 1)) / c : 0x7FFFFFFFL);
return (s > 0) ? d : -d; return (s > 0) ? d : -d;
} }
SW_FT_Long SW_FT_DivFix(SW_FT_Long a, SW_FT_Long b) PVG_FT_Long PVG_FT_DivFix(PVG_FT_Long a, PVG_FT_Long b)
{ {
SW_FT_Int s = 1; PVG_FT_Int s = 1;
SW_FT_Long q; PVG_FT_Long q;
SW_FT_MOVE_SIGN(a, s); PVG_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s); PVG_FT_MOVE_SIGN(b, s);
q = (SW_FT_Long)(b > 0 ? (((SW_FT_UInt64)a << 16) + (b >> 1)) / b q = (PVG_FT_Long)(b > 0 ? (((PVG_FT_UInt64)a << 16) + (b >> 1)) / b
: 0x7FFFFFFFL); : 0x7FFFFFFFL);
return (s < 0 ? -q : q); return (s < 0 ? -q : q);
@ -124,52 +116,52 @@ SW_FT_Long SW_FT_DivFix(SW_FT_Long a, SW_FT_Long b)
/*************************************************************************/ /*************************************************************************/
/* the Cordic shrink factor 0.858785336480436 * 2^32 */ /* the Cordic shrink factor 0.858785336480436 * 2^32 */
#define SW_FT_TRIG_SCALE 0xDBD95B16UL #define PVG_FT_TRIG_SCALE 0xDBD95B16UL
/* the highest bit in overflow-safe vector components, */ /* the highest bit in overflow-safe vector components, */
/* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
#define SW_FT_TRIG_SAFE_MSB 29 #define PVG_FT_TRIG_SAFE_MSB 29
/* this table was generated for SW_FT_PI = 180L << 16, i.e. degrees */ /* this table was generated for PVG_FT_PI = 180L << 16, i.e. degrees */
#define SW_FT_TRIG_MAX_ITERS 23 #define PVG_FT_TRIG_MAX_ITERS 23
static const SW_FT_Fixed ft_trig_arctan_table[] = { static const PVG_FT_Fixed ft_trig_arctan_table[] = {
1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 14668L, 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 14668L,
7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 57L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 57L,
29L, 14L, 7L, 4L, 2L, 1L}; 29L, 14L, 7L, 4L, 2L, 1L};
/* multiply a given value by the CORDIC shrink factor */ /* multiply a given value by the CORDIC shrink factor */
static SW_FT_Fixed ft_trig_downscale(SW_FT_Fixed val) static PVG_FT_Fixed ft_trig_downscale(PVG_FT_Fixed val)
{ {
SW_FT_Fixed s; PVG_FT_Fixed s;
SW_FT_Int64 v; PVG_FT_Int64 v;
s = val; s = val;
val = SW_FT_ABS(val); val = PVG_FT_ABS(val);
v = (val * (SW_FT_Int64)SW_FT_TRIG_SCALE) + 0x100000000UL; v = (val * (PVG_FT_Int64)PVG_FT_TRIG_SCALE) + 0x100000000UL;
val = (SW_FT_Fixed)(v >> 32); val = (PVG_FT_Fixed)(v >> 32);
return (s >= 0) ? val : -val; return (s >= 0) ? val : -val;
} }
/* undefined and never called for zero vector */ /* undefined and never called for zero vector */
static SW_FT_Int ft_trig_prenorm(SW_FT_Vector* vec) static PVG_FT_Int ft_trig_prenorm(PVG_FT_Vector* vec)
{ {
SW_FT_Pos x, y; PVG_FT_Pos x, y;
SW_FT_Int shift; PVG_FT_Int shift;
x = vec->x; x = vec->x;
y = vec->y; y = vec->y;
shift = SW_FT_MSB(SW_FT_ABS(x) | SW_FT_ABS(y)); shift = PVG_FT_MSB(PVG_FT_ABS(x) | PVG_FT_ABS(y));
if (shift <= SW_FT_TRIG_SAFE_MSB) { if (shift <= PVG_FT_TRIG_SAFE_MSB) {
shift = SW_FT_TRIG_SAFE_MSB - shift; shift = PVG_FT_TRIG_SAFE_MSB - shift;
vec->x = (SW_FT_Pos)((SW_FT_ULong)x << shift); vec->x = (PVG_FT_Pos)((PVG_FT_ULong)x << shift);
vec->y = (SW_FT_Pos)((SW_FT_ULong)y << shift); vec->y = (PVG_FT_Pos)((PVG_FT_ULong)y << shift);
} else { } else {
shift -= SW_FT_TRIG_SAFE_MSB; shift -= PVG_FT_TRIG_SAFE_MSB;
vec->x = x >> shift; vec->x = x >> shift;
vec->y = y >> shift; vec->y = y >> shift;
shift = -shift; shift = -shift;
@ -178,36 +170,36 @@ static SW_FT_Int ft_trig_prenorm(SW_FT_Vector* vec)
return shift; return shift;
} }
static void ft_trig_pseudo_rotate(SW_FT_Vector* vec, SW_FT_Angle theta) static void ft_trig_pseudo_rotate(PVG_FT_Vector* vec, PVG_FT_Angle theta)
{ {
SW_FT_Int i; PVG_FT_Int i;
SW_FT_Fixed x, y, xtemp, b; PVG_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed* arctanptr; const PVG_FT_Fixed* arctanptr;
x = vec->x; x = vec->x;
y = vec->y; y = vec->y;
/* Rotate inside [-PI/4,PI/4] sector */ /* Rotate inside [-PI/4,PI/4] sector */
while (theta < -SW_FT_ANGLE_PI4) { while (theta < -PVG_FT_ANGLE_PI4) {
xtemp = y; xtemp = y;
y = -x; y = -x;
x = xtemp; x = xtemp;
theta += SW_FT_ANGLE_PI2; theta += PVG_FT_ANGLE_PI2;
} }
while (theta > SW_FT_ANGLE_PI4) { while (theta > PVG_FT_ANGLE_PI4) {
xtemp = -y; xtemp = -y;
y = x; y = x;
x = xtemp; x = xtemp;
theta -= SW_FT_ANGLE_PI2; theta -= PVG_FT_ANGLE_PI2;
} }
arctanptr = ft_trig_arctan_table; arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */ /* Pseudorotations, with right shifts */
for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) { for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
SW_FT_Fixed v1 = ((y + b) >> i); PVG_FT_Fixed v1 = ((y + b) >> i);
SW_FT_Fixed v2 = ((x + b) >> i); PVG_FT_Fixed v2 = ((x + b) >> i);
if (theta < 0) { if (theta < 0) {
xtemp = x + v1; xtemp = x + v1;
y = y - v2; y = y - v2;
@ -225,12 +217,12 @@ static void ft_trig_pseudo_rotate(SW_FT_Vector* vec, SW_FT_Angle theta)
vec->y = y; vec->y = y;
} }
static void ft_trig_pseudo_polarize(SW_FT_Vector* vec) static void ft_trig_pseudo_polarize(PVG_FT_Vector* vec)
{ {
SW_FT_Angle theta; PVG_FT_Angle theta;
SW_FT_Int i; PVG_FT_Int i;
SW_FT_Fixed x, y, xtemp, b; PVG_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed* arctanptr; const PVG_FT_Fixed* arctanptr;
x = vec->x; x = vec->x;
y = vec->y; y = vec->y;
@ -238,18 +230,18 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
/* Get the vector into [-PI/4,PI/4] sector */ /* Get the vector into [-PI/4,PI/4] sector */
if (y > x) { if (y > x) {
if (y > -x) { if (y > -x) {
theta = SW_FT_ANGLE_PI2; theta = PVG_FT_ANGLE_PI2;
xtemp = y; xtemp = y;
y = -x; y = -x;
x = xtemp; x = xtemp;
} else { } else {
theta = y > 0 ? SW_FT_ANGLE_PI : -SW_FT_ANGLE_PI; theta = y > 0 ? PVG_FT_ANGLE_PI : -PVG_FT_ANGLE_PI;
x = -x; x = -x;
y = -y; y = -y;
} }
} else { } else {
if (y < -x) { if (y < -x) {
theta = -SW_FT_ANGLE_PI2; theta = -PVG_FT_ANGLE_PI2;
xtemp = -y; xtemp = -y;
y = x; y = x;
x = xtemp; x = xtemp;
@ -261,9 +253,9 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
arctanptr = ft_trig_arctan_table; arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */ /* Pseudorotations, with right shifts */
for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) { for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
SW_FT_Fixed v1 = ((y + b) >> i); PVG_FT_Fixed v1 = ((y + b) >> i);
SW_FT_Fixed v2 = ((x + b) >> i); PVG_FT_Fixed v2 = ((x + b) >> i);
if (y > 0) { if (y > 0) {
xtemp = x + v1; xtemp = x + v1;
y = y - v2; y = y - v2;
@ -279,9 +271,9 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
/* round theta */ /* round theta */
if (theta >= 0) if (theta >= 0)
theta = SW_FT_PAD_ROUND(theta, 32); theta = PVG_FT_PAD_ROUND(theta, 32);
else else
theta = -SW_FT_PAD_ROUND(-theta, 32); theta = -PVG_FT_PAD_ROUND(-theta, 32);
vec->x = x; vec->x = x;
vec->y = theta; vec->y = theta;
@ -289,11 +281,11 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Fixed SW_FT_Cos(SW_FT_Angle angle) PVG_FT_Fixed PVG_FT_Cos(PVG_FT_Angle angle)
{ {
SW_FT_Vector v; PVG_FT_Vector v;
v.x = SW_FT_TRIG_SCALE >> 8; v.x = PVG_FT_TRIG_SCALE >> 8;
v.y = 0; v.y = 0;
ft_trig_pseudo_rotate(&v, angle); ft_trig_pseudo_rotate(&v, angle);
@ -302,29 +294,29 @@ SW_FT_Fixed SW_FT_Cos(SW_FT_Angle angle)
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Fixed SW_FT_Sin(SW_FT_Angle angle) PVG_FT_Fixed PVG_FT_Sin(PVG_FT_Angle angle)
{ {
return SW_FT_Cos(SW_FT_ANGLE_PI2 - angle); return PVG_FT_Cos(PVG_FT_ANGLE_PI2 - angle);
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Fixed SW_FT_Tan(SW_FT_Angle angle) PVG_FT_Fixed PVG_FT_Tan(PVG_FT_Angle angle)
{ {
SW_FT_Vector v; PVG_FT_Vector v;
v.x = SW_FT_TRIG_SCALE >> 8; v.x = PVG_FT_TRIG_SCALE >> 8;
v.y = 0; v.y = 0;
ft_trig_pseudo_rotate(&v, angle); ft_trig_pseudo_rotate(&v, angle);
return SW_FT_DivFix(v.y, v.x); return PVG_FT_DivFix(v.y, v.x);
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Angle SW_FT_Atan2(SW_FT_Fixed dx, SW_FT_Fixed dy) PVG_FT_Angle PVG_FT_Atan2(PVG_FT_Fixed dx, PVG_FT_Fixed dy)
{ {
SW_FT_Vector v; PVG_FT_Vector v;
if (dx == 0 && dy == 0) return 0; if (dx == 0 && dy == 0) return 0;
@ -338,65 +330,58 @@ SW_FT_Angle SW_FT_Atan2(SW_FT_Fixed dx, SW_FT_Fixed dy)
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
void SW_FT_Vector_Unit(SW_FT_Vector* vec, SW_FT_Angle angle) void PVG_FT_Vector_Unit(PVG_FT_Vector* vec, PVG_FT_Angle angle)
{ {
vec->x = SW_FT_TRIG_SCALE >> 8; vec->x = PVG_FT_TRIG_SCALE >> 8;
vec->y = 0; vec->y = 0;
ft_trig_pseudo_rotate(vec, angle); ft_trig_pseudo_rotate(vec, angle);
vec->x = (vec->x + 0x80L) >> 8; vec->x = (vec->x + 0x80L) >> 8;
vec->y = (vec->y + 0x80L) >> 8; vec->y = (vec->y + 0x80L) >> 8;
} }
/* these macros return 0 for positive numbers, void PVG_FT_Vector_Rotate(PVG_FT_Vector* vec, PVG_FT_Angle angle)
and -1 for negative ones */
#define SW_FT_SIGN_LONG(x) ((x) >> (SW_FT_SIZEOF_LONG * 8 - 1))
#define SW_FT_SIGN_INT(x) ((x) >> (SW_FT_SIZEOF_INT * 8 - 1))
#define SW_FT_SIGN_INT32(x) ((x) >> 31)
#define SW_FT_SIGN_INT16(x) ((x) >> 15)
/* documentation is in fttrigon.h */
void SW_FT_Vector_Rotate(SW_FT_Vector* vec, SW_FT_Angle angle)
{ {
SW_FT_Int shift; PVG_FT_Int shift;
SW_FT_Vector v; PVG_FT_Vector v = *vec;
v.x = vec->x; if ( v.x == 0 && v.y == 0 )
v.y = vec->y; return;
if (angle && (v.x != 0 || v.y != 0)) { shift = ft_trig_prenorm( &v );
shift = ft_trig_prenorm(&v); ft_trig_pseudo_rotate( &v, angle );
ft_trig_pseudo_rotate(&v, angle); v.x = ft_trig_downscale( v.x );
v.x = ft_trig_downscale(v.x); v.y = ft_trig_downscale( v.y );
v.y = ft_trig_downscale(v.y);
if (shift > 0) { if ( shift > 0 )
SW_FT_Int32 half = (SW_FT_Int32)1L << (shift - 1); {
PVG_FT_Int32 half = (PVG_FT_Int32)1L << ( shift - 1 );
vec->x = (v.x + half + SW_FT_SIGN_LONG(v.x)) >> shift;
vec->y = (v.y + half + SW_FT_SIGN_LONG(v.y)) >> shift; vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift;
} else { vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift;
shift = -shift; }
vec->x = (SW_FT_Pos)((SW_FT_ULong)v.x << shift); else
vec->y = (SW_FT_Pos)((SW_FT_ULong)v.y << shift); {
} shift = -shift;
vec->x = (PVG_FT_Pos)( (PVG_FT_ULong)v.x << shift );
vec->y = (PVG_FT_Pos)( (PVG_FT_ULong)v.y << shift );
} }
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Fixed SW_FT_Vector_Length(SW_FT_Vector* vec) PVG_FT_Fixed PVG_FT_Vector_Length(PVG_FT_Vector* vec)
{ {
SW_FT_Int shift; PVG_FT_Int shift;
SW_FT_Vector v; PVG_FT_Vector v;
v = *vec; v = *vec;
/* handle trivial cases */ /* handle trivial cases */
if (v.x == 0) { if (v.x == 0) {
return SW_FT_ABS(v.y); return PVG_FT_ABS(v.y);
} else if (v.y == 0) { } else if (v.y == 0) {
return SW_FT_ABS(v.x); return PVG_FT_ABS(v.x);
} }
/* general case */ /* general case */
@ -407,16 +392,16 @@ SW_FT_Fixed SW_FT_Vector_Length(SW_FT_Vector* vec)
if (shift > 0) return (v.x + (1 << (shift - 1))) >> shift; if (shift > 0) return (v.x + (1 << (shift - 1))) >> shift;
return (SW_FT_Fixed)((SW_FT_UInt32)v.x << -shift); return (PVG_FT_Fixed)((PVG_FT_UInt32)v.x << -shift);
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
void SW_FT_Vector_Polarize(SW_FT_Vector* vec, SW_FT_Fixed* length, void PVG_FT_Vector_Polarize(PVG_FT_Vector* vec, PVG_FT_Fixed* length,
SW_FT_Angle* angle) PVG_FT_Angle* angle)
{ {
SW_FT_Int shift; PVG_FT_Int shift;
SW_FT_Vector v; PVG_FT_Vector v;
v = *vec; v = *vec;
@ -428,34 +413,34 @@ void SW_FT_Vector_Polarize(SW_FT_Vector* vec, SW_FT_Fixed* length,
v.x = ft_trig_downscale(v.x); v.x = ft_trig_downscale(v.x);
*length = (shift >= 0) ? (v.x >> shift) *length = (shift >= 0) ? (v.x >> shift)
: (SW_FT_Fixed)((SW_FT_UInt32)v.x << -shift); : (PVG_FT_Fixed)((PVG_FT_UInt32)v.x << -shift);
*angle = v.y; *angle = v.y;
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
void SW_FT_Vector_From_Polar(SW_FT_Vector* vec, SW_FT_Fixed length, void PVG_FT_Vector_From_Polar(PVG_FT_Vector* vec, PVG_FT_Fixed length,
SW_FT_Angle angle) PVG_FT_Angle angle)
{ {
vec->x = length; vec->x = length;
vec->y = 0; vec->y = 0;
SW_FT_Vector_Rotate(vec, angle); PVG_FT_Vector_Rotate(vec, angle);
} }
/* documentation is in fttrigon.h */ /* documentation is in fttrigon.h */
SW_FT_Angle SW_FT_Angle_Diff( SW_FT_Angle angle1, SW_FT_Angle angle2 ) PVG_FT_Angle PVG_FT_Angle_Diff( PVG_FT_Angle angle1, PVG_FT_Angle angle2 )
{ {
SW_FT_Angle delta = angle2 - angle1; PVG_FT_Angle delta = angle2 - angle1;
while ( delta <= -SW_FT_ANGLE_PI ) while ( delta <= -PVG_FT_ANGLE_PI )
delta += SW_FT_ANGLE_2PI; delta += PVG_FT_ANGLE_2PI;
while ( delta > SW_FT_ANGLE_PI ) while ( delta > PVG_FT_ANGLE_PI )
delta -= SW_FT_ANGLE_2PI; delta -= PVG_FT_ANGLE_2PI;
return delta; return delta;
} }
/* END */ /* END */

436
3rdparty/plutovg/plutovg-ft-math.h vendored Normal file
View file

@ -0,0 +1,436 @@
/***************************************************************************/
/* */
/* fttrigon.h */
/* */
/* FreeType trigonometric functions (specification). */
/* */
/* Copyright 2001, 2003, 2005, 2007, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef PLUTOVG_FT_MATH_H
#define PLUTOVG_FT_MATH_H
#include "plutovg-ft-types.h"
/*************************************************************************/
/* */
/* The min and max functions missing in C. As usual, be careful not to */
/* write things like PVG_FT_MIN( a++, b++ ) to avoid side effects. */
/* */
#define PVG_FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
#define PVG_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
#define PVG_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
/*
* Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
* algorithm. We use alpha = 1, beta = 3/8, giving us results with a
* largest error less than 7% compared to the exact value.
*/
#define PVG_FT_HYPOT( x, y ) \
( x = PVG_FT_ABS( x ), \
y = PVG_FT_ABS( y ), \
x > y ? x + ( 3 * y >> 3 ) \
: y + ( 3 * x >> 3 ) )
/*************************************************************************/
/* */
/* <Function> */
/* PVG_FT_MulFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */
/* used to multiply a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. Use a 16.16 factor here whenever */
/* possible (see note below). */
/* */
/* <Return> */
/* The result of `(a*b)/0x10000'. */
/* */
/* <Note> */
/* This function has been optimized for the case where the absolute */
/* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
/* As this happens mainly when scaling from notional units to */
/* fractional pixels in FreeType, it resulted in noticeable speed */
/* improvements between versions 2.x and 1.x. */
/* */
/* As a conclusion, always try to place a 16.16 factor as the */
/* _second_ argument of this function; this can make a great */
/* difference. */
/* */
PVG_FT_Long
PVG_FT_MulFix( PVG_FT_Long a,
PVG_FT_Long b );
/*************************************************************************/
/* */
/* <Function> */
/* PVG_FT_MulDiv */
/* */
/* <Description> */
/* A very simple function used to perform the computation `(a*b)/c' */
/* with maximum accuracy (it uses a 64-bit intermediate integer */
/* whenever necessary). */
/* */
/* This function isn't necessarily as fast as some processor specific */
/* operations, but is at least completely portable. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. */
/* c :: The divisor. */
/* */
/* <Return> */
/* The result of `(a*b)/c'. This function never traps when trying to */
/* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
/* on the signs of `a' and `b'. */
/* */
PVG_FT_Long
PVG_FT_MulDiv( PVG_FT_Long a,
PVG_FT_Long b,
PVG_FT_Long c );
/*************************************************************************/
/* */
/* <Function> */
/* PVG_FT_DivFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */
/* used to divide a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The numerator. */
/* b :: The denominator. Use a 16.16 factor here. */
/* */
/* <Return> */
/* The result of `(a*0x10000)/b'. */
/* */
PVG_FT_Long
PVG_FT_DivFix( PVG_FT_Long a,
PVG_FT_Long b );
/*************************************************************************/
/* */
/* <Section> */
/* computations */
/* */
/*************************************************************************/
/*************************************************************************
*
* @type:
* PVG_FT_Angle
*
* @description:
* This type is used to model angle values in FreeType. Note that the
* angle is a 16.16 fixed-point value expressed in degrees.
*
*/
typedef PVG_FT_Fixed PVG_FT_Angle;
/*************************************************************************
*
* @macro:
* PVG_FT_ANGLE_PI
*
* @description:
* The angle pi expressed in @PVG_FT_Angle units.
*
*/
#define PVG_FT_ANGLE_PI ( 180L << 16 )
/*************************************************************************
*
* @macro:
* PVG_FT_ANGLE_2PI
*
* @description:
* The angle 2*pi expressed in @PVG_FT_Angle units.
*
*/
#define PVG_FT_ANGLE_2PI ( PVG_FT_ANGLE_PI * 2 )
/*************************************************************************
*
* @macro:
* PVG_FT_ANGLE_PI2
*
* @description:
* The angle pi/2 expressed in @PVG_FT_Angle units.
*
*/
#define PVG_FT_ANGLE_PI2 ( PVG_FT_ANGLE_PI / 2 )
/*************************************************************************
*
* @macro:
* PVG_FT_ANGLE_PI4
*
* @description:
* The angle pi/4 expressed in @PVG_FT_Angle units.
*
*/
#define PVG_FT_ANGLE_PI4 ( PVG_FT_ANGLE_PI / 4 )
/*************************************************************************
*
* @function:
* PVG_FT_Sin
*
* @description:
* Return the sinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The sinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @PVG_FT_Vector_Unit.
*
*/
PVG_FT_Fixed
PVG_FT_Sin( PVG_FT_Angle angle );
/*************************************************************************
*
* @function:
* PVG_FT_Cos
*
* @description:
* Return the cosinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The cosinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @PVG_FT_Vector_Unit.
*
*/
PVG_FT_Fixed
PVG_FT_Cos( PVG_FT_Angle angle );
/*************************************************************************
*
* @function:
* PVG_FT_Tan
*
* @description:
* Return the tangent of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The tangent value.
*
*/
PVG_FT_Fixed
PVG_FT_Tan( PVG_FT_Angle angle );
/*************************************************************************
*
* @function:
* PVG_FT_Atan2
*
* @description:
* Return the arc-tangent corresponding to a given vector (x,y) in
* the 2d plane.
*
* @input:
* x ::
* The horizontal vector coordinate.
*
* y ::
* The vertical vector coordinate.
*
* @return:
* The arc-tangent value (i.e. angle).
*
*/
PVG_FT_Angle
PVG_FT_Atan2( PVG_FT_Fixed x,
PVG_FT_Fixed y );
/*************************************************************************
*
* @function:
* PVG_FT_Angle_Diff
*
* @description:
* Return the difference between two angles. The result is always
* constrained to the ]-PI..PI] interval.
*
* @input:
* angle1 ::
* First angle.
*
* angle2 ::
* Second angle.
*
* @return:
* Constrained value of `value2-value1'.
*
*/
PVG_FT_Angle
PVG_FT_Angle_Diff( PVG_FT_Angle angle1,
PVG_FT_Angle angle2 );
/*************************************************************************
*
* @function:
* PVG_FT_Vector_Unit
*
* @description:
* Return the unit vector corresponding to a given angle. After the
* call, the value of `vec.x' will be `sin(angle)', and the value of
* `vec.y' will be `cos(angle)'.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
*
* @output:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
PVG_FT_Vector_Unit( PVG_FT_Vector* vec,
PVG_FT_Angle angle );
/*************************************************************************
*
* @function:
* PVG_FT_Vector_Rotate
*
* @description:
* Rotate a vector by a given angle.
*
* @inout:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
PVG_FT_Vector_Rotate( PVG_FT_Vector* vec,
PVG_FT_Angle angle );
/*************************************************************************
*
* @function:
* PVG_FT_Vector_Length
*
* @description:
* Return the length of a given vector.
*
* @input:
* vec ::
* The address of target vector.
*
* @return:
* The vector length, expressed in the same units that the original
* vector coordinates.
*
*/
PVG_FT_Fixed
PVG_FT_Vector_Length( PVG_FT_Vector* vec );
/*************************************************************************
*
* @function:
* PVG_FT_Vector_Polarize
*
* @description:
* Compute both the length and angle of a given vector.
*
* @input:
* vec ::
* The address of source vector.
*
* @output:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
PVG_FT_Vector_Polarize( PVG_FT_Vector* vec,
PVG_FT_Fixed *length,
PVG_FT_Angle *angle );
/*************************************************************************
*
* @function:
* PVG_FT_Vector_From_Polar
*
* @description:
* Compute vector coordinates from a length and angle.
*
* @output:
* vec ::
* The address of source vector.
*
* @input:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
PVG_FT_Vector_From_Polar( PVG_FT_Vector* vec,
PVG_FT_Fixed length,
PVG_FT_Angle angle );
#endif /* PLUTOVG_FT_MATH_H */

1632
3rdparty/plutovg/plutovg-ft-raster.c vendored Normal file

File diff suppressed because it is too large Load diff

420
3rdparty/plutovg/plutovg-ft-raster.h vendored Normal file
View file

@ -0,0 +1,420 @@
/***************************************************************************/
/* */
/* ftimage.h */
/* */
/* FreeType glyph image formats and default raster interface */
/* (specification). */
/* */
/* Copyright 1996-2010, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef PLUTOVG_FT_RASTER_H
#define PLUTOVG_FT_RASTER_H
#include "plutovg-ft-types.h"
/*************************************************************************/
/* */
/* <Struct> */
/* FT_BBox */
/* */
/* <Description> */
/* A structure used to hold an outline's bounding box, i.e., the */
/* coordinates of its extrema in the horizontal and vertical */
/* directions. */
/* */
/* <Fields> */
/* xMin :: The horizontal minimum (left-most). */
/* */
/* yMin :: The vertical minimum (bottom-most). */
/* */
/* xMax :: The horizontal maximum (right-most). */
/* */
/* yMax :: The vertical maximum (top-most). */
/* */
/* <Note> */
/* The bounding box is specified with the coordinates of the lower */
/* left and the upper right corner. In PostScript, those values are */
/* often called (llx,lly) and (urx,ury), respectively. */
/* */
/* If `yMin' is negative, this value gives the glyph's descender. */
/* Otherwise, the glyph doesn't descend below the baseline. */
/* Similarly, if `ymax' is positive, this value gives the glyph's */
/* ascender. */
/* */
/* `xMin' gives the horizontal distance from the glyph's origin to */
/* the left edge of the glyph's bounding box. If `xMin' is negative, */
/* the glyph extends to the left of the origin. */
/* */
typedef struct PVG_FT_BBox_
{
PVG_FT_Pos xMin, yMin;
PVG_FT_Pos xMax, yMax;
} PVG_FT_BBox;
/*************************************************************************/
/* */
/* <Struct> */
/* PVG_FT_Outline */
/* */
/* <Description> */
/* This structure is used to describe an outline to the scan-line */
/* converter. */
/* */
/* <Fields> */
/* n_contours :: The number of contours in the outline. */
/* */
/* n_points :: The number of points in the outline. */
/* */
/* points :: A pointer to an array of `n_points' @PVG_FT_Vector */
/* elements, giving the outline's point coordinates. */
/* */
/* tags :: A pointer to an array of `n_points' chars, giving */
/* each outline point's type. */
/* */
/* If bit~0 is unset, the point is `off' the curve, */
/* i.e., a Bézier control point, while it is `on' if */
/* set. */
/* */
/* Bit~1 is meaningful for `off' points only. If set, */
/* it indicates a third-order Bézier arc control point; */
/* and a second-order control point if unset. */
/* */
/* If bit~2 is set, bits 5-7 contain the drop-out mode */
/* (as defined in the OpenType specification; the value */
/* is the same as the argument to the SCANMODE */
/* instruction). */
/* */
/* Bits 3 and~4 are reserved for internal purposes. */
/* */
/* contours :: An array of `n_contours' shorts, giving the end */
/* point of each contour within the outline. For */
/* example, the first contour is defined by the points */
/* `0' to `contours[0]', the second one is defined by */
/* the points `contours[0]+1' to `contours[1]', etc. */
/* */
/* flags :: A set of bit flags used to characterize the outline */
/* and give hints to the scan-converter and hinter on */
/* how to convert/grid-fit it. See @PVG_FT_OUTLINE_FLAGS.*/
/* */
typedef struct PVG_FT_Outline_
{
int n_contours; /* number of contours in glyph */
int n_points; /* number of points in the glyph */
PVG_FT_Vector* points; /* the outline's points */
char* tags; /* the points flags */
int* contours; /* the contour end points */
char* contours_flag; /* the contour open flags */
int flags; /* outline masks */
} PVG_FT_Outline;
/*************************************************************************/
/* */
/* <Enum> */
/* PVG_FT_OUTLINE_FLAGS */
/* */
/* <Description> */
/* A list of bit-field constants use for the flags in an outline's */
/* `flags' field. */
/* */
/* <Values> */
/* PVG_FT_OUTLINE_NONE :: */
/* Value~0 is reserved. */
/* */
/* PVG_FT_OUTLINE_OWNER :: */
/* If set, this flag indicates that the outline's field arrays */
/* (i.e., `points', `flags', and `contours') are `owned' by the */
/* outline object, and should thus be freed when it is destroyed. */
/* */
/* PVG_FT_OUTLINE_EVEN_ODD_FILL :: */
/* By default, outlines are filled using the non-zero winding rule. */
/* If set to 1, the outline will be filled using the even-odd fill */
/* rule (only works with the smooth rasterizer). */
/* */
/* PVG_FT_OUTLINE_REVERSE_FILL :: */
/* By default, outside contours of an outline are oriented in */
/* clock-wise direction, as defined in the TrueType specification. */
/* This flag is set if the outline uses the opposite direction */
/* (typically for Type~1 fonts). This flag is ignored by the scan */
/* converter. */
/* */
/* */
/* */
/* There exists a second mechanism to pass the drop-out mode to the */
/* B/W rasterizer; see the `tags' field in @PVG_FT_Outline. */
/* */
/* Please refer to the description of the `SCANTYPE' instruction in */
/* the OpenType specification (in file `ttinst1.doc') how simple */
/* drop-outs, smart drop-outs, and stubs are defined. */
/* */
#define PVG_FT_OUTLINE_NONE 0x0
#define PVG_FT_OUTLINE_OWNER 0x1
#define PVG_FT_OUTLINE_EVEN_ODD_FILL 0x2
#define PVG_FT_OUTLINE_REVERSE_FILL 0x4
/* */
#define PVG_FT_CURVE_TAG( flag ) ( flag & 3 )
#define PVG_FT_CURVE_TAG_ON 1
#define PVG_FT_CURVE_TAG_CONIC 0
#define PVG_FT_CURVE_TAG_CUBIC 2
#define PVG_FT_Curve_Tag_On PVG_FT_CURVE_TAG_ON
#define PVG_FT_Curve_Tag_Conic PVG_FT_CURVE_TAG_CONIC
#define PVG_FT_Curve_Tag_Cubic PVG_FT_CURVE_TAG_CUBIC
/*************************************************************************/
/* */
/* <Function> */
/* PVG_FT_Outline_Check */
/* */
/* <Description> */
/* Check the contents of an outline descriptor. */
/* */
/* <Input> */
/* outline :: A handle to a source outline. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
PVG_FT_Error
PVG_FT_Outline_Check( PVG_FT_Outline* outline );
/*************************************************************************/
/* */
/* <Function> */
/* PVG_FT_Outline_Get_CBox */
/* */
/* <Description> */
/* Return an outline's `control box'. The control box encloses all */
/* the outline's points, including Bézier control points. Though it */
/* coincides with the exact bounding box for most glyphs, it can be */
/* slightly larger in some situations (like when rotating an outline */
/* that contains Bézier outside arcs). */
/* */
/* Computing the control box is very fast, while getting the bounding */
/* box can take much more time as it needs to walk over all segments */
/* and arcs in the outline. To get the latter, you can use the */
/* `ftbbox' component, which is dedicated to this single task. */
/* */
/* <Input> */
/* outline :: A pointer to the source outline descriptor. */
/* */
/* <Output> */
/* acbox :: The outline's control box. */
/* */
/* <Note> */
/* See @PVG_FT_Glyph_Get_CBox for a discussion of tricky fonts. */
/* */
void
PVG_FT_Outline_Get_CBox( const PVG_FT_Outline* outline,
PVG_FT_BBox *acbox );
/*************************************************************************/
/* */
/* <Struct> */
/* PVG_FT_Span */
/* */
/* <Description> */
/* A structure used to model a single span of gray (or black) pixels */
/* when rendering a monochrome or anti-aliased bitmap. */
/* */
/* <Fields> */
/* x :: The span's horizontal start position. */
/* */
/* len :: The span's length in pixels. */
/* */
/* coverage :: The span color/coverage, ranging from 0 (background) */
/* to 255 (foreground). Only used for anti-aliased */
/* rendering. */
/* */
/* <Note> */
/* This structure is used by the span drawing callback type named */
/* @PVG_FT_SpanFunc that takes the y~coordinate of the span as a */
/* parameter. */
/* */
/* The coverage value is always between 0 and 255. If you want less */
/* gray values, the callback function has to reduce them. */
/* */
typedef struct PVG_FT_Span_
{
int x;
int len;
int y;
unsigned char coverage;
} PVG_FT_Span;
/*************************************************************************/
/* */
/* <FuncType> */
/* PVG_FT_SpanFunc */
/* */
/* <Description> */
/* A function used as a call-back by the anti-aliased renderer in */
/* order to let client applications draw themselves the gray pixel */
/* spans on each scan line. */
/* */
/* <Input> */
/* y :: The scanline's y~coordinate. */
/* */
/* count :: The number of spans to draw on this scanline. */
/* */
/* spans :: A table of `count' spans to draw on the scanline. */
/* */
/* user :: User-supplied data that is passed to the callback. */
/* */
/* <Note> */
/* This callback allows client applications to directly render the */
/* gray spans of the anti-aliased bitmap to any kind of surfaces. */
/* */
/* This can be used to write anti-aliased outlines directly to a */
/* given background bitmap, and even perform translucency. */
/* */
/* Note that the `count' field cannot be greater than a fixed value */
/* defined by the `PVG_FT_MAX_GRAY_SPANS' configuration macro in */
/* `ftoption.h'. By default, this value is set to~32, which means */
/* that if there are more than 32~spans on a given scanline, the */
/* callback is called several times with the same `y' parameter in */
/* order to draw all callbacks. */
/* */
/* Otherwise, the callback is only called once per scan-line, and */
/* only for those scanlines that do have `gray' pixels on them. */
/* */
typedef void
(*PVG_FT_SpanFunc)( int count,
const PVG_FT_Span* spans,
void* user );
#define PVG_FT_Raster_Span_Func PVG_FT_SpanFunc
/*************************************************************************/
/* */
/* <Enum> */
/* PVG_FT_RASTER_FLAG_XXX */
/* */
/* <Description> */
/* A list of bit flag constants as used in the `flags' field of a */
/* @PVG_FT_Raster_Params structure. */
/* */
/* <Values> */
/* PVG_FT_RASTER_FLAG_DEFAULT :: This value is 0. */
/* */
/* PVG_FT_RASTER_FLAG_AA :: This flag is set to indicate that an */
/* anti-aliased glyph image should be */
/* generated. Otherwise, it will be */
/* monochrome (1-bit). */
/* */
/* PVG_FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */
/* rendering. In this mode, client */
/* applications must provide their own span */
/* callback. This lets them directly */
/* draw or compose over an existing bitmap. */
/* If this bit is not set, the target */
/* pixmap's buffer _must_ be zeroed before */
/* rendering. */
/* */
/* Note that for now, direct rendering is */
/* only possible with anti-aliased glyphs. */
/* */
/* PVG_FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
/* rendering mode. If set, the output will */
/* be clipped to a box specified in the */
/* `clip_box' field of the */
/* @PVG_FT_Raster_Params structure. */
/* */
/* Note that by default, the glyph bitmap */
/* is clipped to the target pixmap, except */
/* in direct rendering mode where all spans */
/* are generated if no clipping box is set. */
/* */
#define PVG_FT_RASTER_FLAG_DEFAULT 0x0
#define PVG_FT_RASTER_FLAG_AA 0x1
#define PVG_FT_RASTER_FLAG_DIRECT 0x2
#define PVG_FT_RASTER_FLAG_CLIP 0x4
/*************************************************************************/
/* */
/* <Struct> */
/* PVG_FT_Raster_Params */
/* */
/* <Description> */
/* A structure to hold the arguments used by a raster's render */
/* function. */
/* */
/* <Fields> */
/* target :: The target bitmap. */
/* */
/* source :: A pointer to the source glyph image (e.g., an */
/* @PVG_FT_Outline). */
/* */
/* flags :: The rendering flags. */
/* */
/* gray_spans :: The gray span drawing callback. */
/* */
/* black_spans :: The black span drawing callback. UNIMPLEMENTED! */
/* */
/* bit_test :: The bit test callback. UNIMPLEMENTED! */
/* */
/* bit_set :: The bit set callback. UNIMPLEMENTED! */
/* */
/* user :: User-supplied data that is passed to each drawing */
/* callback. */
/* */
/* clip_box :: An optional clipping box. It is only used in */
/* direct rendering mode. Note that coordinates here */
/* should be expressed in _integer_ pixels (and not in */
/* 26.6 fixed-point units). */
/* */
/* <Note> */
/* An anti-aliased glyph bitmap is drawn if the @PVG_FT_RASTER_FLAG_AA */
/* bit flag is set in the `flags' field, otherwise a monochrome */
/* bitmap is generated. */
/* */
/* If the @PVG_FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
/* raster will call the `gray_spans' callback to draw gray pixel */
/* spans, in the case of an aa glyph bitmap, it will call */
/* `black_spans', and `bit_test' and `bit_set' in the case of a */
/* monochrome bitmap. This allows direct composition over a */
/* pre-existing bitmap through user-provided callbacks to perform the */
/* span drawing/composition. */
/* */
/* Note that the `bit_test' and `bit_set' callbacks are required when */
/* rendering a monochrome bitmap, as they are crucial to implement */
/* correct drop-out control as defined in the TrueType specification. */
/* */
typedef struct PVG_FT_Raster_Params_
{
const void* source;
int flags;
PVG_FT_SpanFunc gray_spans;
void* user;
PVG_FT_BBox clip_box;
} PVG_FT_Raster_Params;
void
PVG_FT_Raster_Render(const PVG_FT_Raster_Params *params);
#endif // PLUTOVG_FT_RASTER_H

File diff suppressed because it is too large Load diff

320
3rdparty/plutovg/plutovg-ft-stroker.h vendored Normal file
View file

@ -0,0 +1,320 @@
/***************************************************************************/
/* */
/* ftstroke.h */
/* */
/* FreeType path stroker (specification). */
/* */
/* Copyright 2002-2006, 2008, 2009, 2011-2012 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef PLUTOVG_FT_STROKER_H
#define PLUTOVG_FT_STROKER_H
#include "plutovg-ft-raster.h"
/**************************************************************
*
* @type:
* PVG_FT_Stroker
*
* @description:
* Opaque handler to a path stroker object.
*/
typedef struct PVG_FT_StrokerRec_* PVG_FT_Stroker;
/**************************************************************
*
* @enum:
* PVG_FT_Stroker_LineJoin
*
* @description:
* These values determine how two joining lines are rendered
* in a stroker.
*
* @values:
* PVG_FT_STROKER_LINEJOIN_ROUND ::
* Used to render rounded line joins. Circular arcs are used
* to join two lines smoothly.
*
* PVG_FT_STROKER_LINEJOIN_BEVEL ::
* Used to render beveled line joins. The outer corner of
* the joined lines is filled by enclosing the triangular
* region of the corner with a straight line between the
* outer corners of each stroke.
*
* PVG_FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the
* miter limit is exceeded. The outer edges of the strokes
* for the two segments are extended until they meet at an
* angle. If the segments meet at too sharp an angle (such
* that the miter would extend from the intersection of the
* segments a distance greater than the product of the miter
* limit value and the border radius), then a bevel join (see
* above) is used instead. This prevents long spikes being
* created. PVG_FT_STROKER_LINEJOIN_MITER_FIXED generates a miter
* line join as used in PostScript and PDF.
*
* PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* PVG_FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if
* the miter limit is exceeded. The intersection of the
* strokes is clipped at a line perpendicular to the bisector
* of the angle between the strokes, at the distance from the
* intersection of the segments equal to the product of the
* miter limit value and the border radius. This prevents
* long spikes being created.
* PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line
* join as used in XPS. PVG_FT_STROKER_LINEJOIN_MITER is an alias
* for PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for
* backwards compatibility.
*/
typedef enum PVG_FT_Stroker_LineJoin_
{
PVG_FT_STROKER_LINEJOIN_ROUND = 0,
PVG_FT_STROKER_LINEJOIN_BEVEL = 1,
PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
PVG_FT_STROKER_LINEJOIN_MITER = PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE,
PVG_FT_STROKER_LINEJOIN_MITER_FIXED = 3
} PVG_FT_Stroker_LineJoin;
/**************************************************************
*
* @enum:
* PVG_FT_Stroker_LineCap
*
* @description:
* These values determine how the end of opened sub-paths are
* rendered in a stroke.
*
* @values:
* PVG_FT_STROKER_LINECAP_BUTT ::
* The end of lines is rendered as a full stop on the last
* point itself.
*
* PVG_FT_STROKER_LINECAP_ROUND ::
* The end of lines is rendered as a half-circle around the
* last point.
*
* PVG_FT_STROKER_LINECAP_SQUARE ::
* The end of lines is rendered as a square around the
* last point.
*/
typedef enum PVG_FT_Stroker_LineCap_
{
PVG_FT_STROKER_LINECAP_BUTT = 0,
PVG_FT_STROKER_LINECAP_ROUND,
PVG_FT_STROKER_LINECAP_SQUARE
} PVG_FT_Stroker_LineCap;
/**************************************************************
*
* @enum:
* PVG_FT_StrokerBorder
*
* @description:
* These values are used to select a given stroke border
* in @PVG_FT_Stroker_GetBorderCounts and @PVG_FT_Stroker_ExportBorder.
*
* @values:
* PVG_FT_STROKER_BORDER_LEFT ::
* Select the left border, relative to the drawing direction.
*
* PVG_FT_STROKER_BORDER_RIGHT ::
* Select the right border, relative to the drawing direction.
*
* @note:
* Applications are generally interested in the `inside' and `outside'
* borders. However, there is no direct mapping between these and the
* `left' and `right' ones, since this really depends on the glyph's
* drawing orientation, which varies between font formats.
*
* You can however use @PVG_FT_Outline_GetInsideBorder and
* @PVG_FT_Outline_GetOutsideBorder to get these.
*/
typedef enum PVG_FT_StrokerBorder_
{
PVG_FT_STROKER_BORDER_LEFT = 0,
PVG_FT_STROKER_BORDER_RIGHT
} PVG_FT_StrokerBorder;
/**************************************************************
*
* @function:
* PVG_FT_Stroker_New
*
* @description:
* Create a new stroker object.
*
* @input:
* library ::
* FreeType library handle.
*
* @output:
* astroker ::
* A new stroker object handle. NULL in case of error.
*
* @return:
* FreeType error code. 0~means success.
*/
PVG_FT_Error
PVG_FT_Stroker_New( PVG_FT_Stroker *astroker );
/**************************************************************
*
* @function:
* PVG_FT_Stroker_Set
*
* @description:
* Reset a stroker object's attributes.
*
* @input:
* stroker ::
* The target stroker handle.
*
* radius ::
* The border radius.
*
* line_cap ::
* The line cap style.
*
* line_join ::
* The line join style.
*
* miter_limit ::
* The miter limit for the PVG_FT_STROKER_LINEJOIN_MITER_FIXED and
* PVG_FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
* expressed as 16.16 fixed-point value.
*
* @note:
* The radius is expressed in the same units as the outline
* coordinates.
*/
void
PVG_FT_Stroker_Set( PVG_FT_Stroker stroker,
PVG_FT_Fixed radius,
PVG_FT_Stroker_LineCap line_cap,
PVG_FT_Stroker_LineJoin line_join,
PVG_FT_Fixed miter_limit );
/**************************************************************
*
* @function:
* PVG_FT_Stroker_ParseOutline
*
* @description:
* A convenience function used to parse a whole outline with
* the stroker. The resulting outline(s) can be retrieved
* later by functions like @PVG_FT_Stroker_GetCounts and @PVG_FT_Stroker_Export.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The source outline.
*
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* If `opened' is~0 (the default), the outline is treated as a closed
* path, and the stroker generates two distinct `border' outlines.
*
*
* This function calls @PVG_FT_Stroker_Rewind automatically.
*/
PVG_FT_Error
PVG_FT_Stroker_ParseOutline( PVG_FT_Stroker stroker,
const PVG_FT_Outline* outline);
/**************************************************************
*
* @function:
* PVG_FT_Stroker_GetCounts
*
* @description:
* Call this function once you have finished parsing your paths
* with the stroker. It returns the number of points and
* contours necessary to export all points/borders from the stroked
* outline/path.
*
* @input:
* stroker ::
* The target stroker handle.
*
* @output:
* anum_points ::
* The number of points.
*
* anum_contours ::
* The number of contours.
*
* @return:
* FreeType error code. 0~means success.
*/
PVG_FT_Error
PVG_FT_Stroker_GetCounts( PVG_FT_Stroker stroker,
PVG_FT_UInt *anum_points,
PVG_FT_UInt *anum_contours );
/**************************************************************
*
* @function:
* PVG_FT_Stroker_Export
*
* @description:
* Call this function after @PVG_FT_Stroker_GetBorderCounts to
* export all borders to your own @PVG_FT_Outline structure.
*
* Note that this function appends the border points and
* contours to your outline, but does not try to resize its
* arrays.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The target outline handle.
*/
void
PVG_FT_Stroker_Export( PVG_FT_Stroker stroker,
PVG_FT_Outline* outline );
/**************************************************************
*
* @function:
* PVG_FT_Stroker_Done
*
* @description:
* Destroy a stroker object.
*
* @input:
* stroker ::
* A stroker handle. Can be NULL.
*/
void
PVG_FT_Stroker_Done( PVG_FT_Stroker stroker );
#endif // PLUTOVG_FT_STROKER_H

View file

@ -1,152 +1,166 @@
#ifndef SW_FT_TYPES_H /****************************************************************************
#define SW_FT_TYPES_H *
* fttypes.h
*
* FreeType simple types definitions (specification only).
*
* Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef PLUTOVG_FT_TYPES_H
#define PLUTOVG_FT_TYPES_H
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Fixed */ /* PVG_FT_Fixed */
/* */ /* */
/* <Description> */ /* <Description> */
/* This type is used to store 16.16 fixed-point values, like scaling */ /* This type is used to store 16.16 fixed-point values, like scaling */
/* values or matrix coefficients. */ /* values or matrix coefficients. */
/* */ /* */
typedef signed long SW_FT_Fixed; typedef signed long PVG_FT_Fixed;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Int */ /* PVG_FT_Int */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef for the int type. */ /* A typedef for the int type. */
/* */ /* */
typedef signed int SW_FT_Int; typedef signed int PVG_FT_Int;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_UInt */ /* PVG_FT_UInt */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef for the unsigned int type. */ /* A typedef for the unsigned int type. */
/* */ /* */
typedef unsigned int SW_FT_UInt; typedef unsigned int PVG_FT_UInt;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Long */ /* PVG_FT_Long */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef for signed long. */ /* A typedef for signed long. */
/* */ /* */
typedef signed long SW_FT_Long; typedef signed long PVG_FT_Long;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_ULong */ /* PVG_FT_ULong */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef for unsigned long. */ /* A typedef for unsigned long. */
/* */ /* */
typedef unsigned long SW_FT_ULong; typedef unsigned long PVG_FT_ULong;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Short */ /* PVG_FT_Short */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef for signed short. */ /* A typedef for signed short. */
/* */ /* */
typedef signed short SW_FT_Short; typedef signed short PVG_FT_Short;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Byte */ /* PVG_FT_Byte */
/* */ /* */
/* <Description> */ /* <Description> */
/* A simple typedef for the _unsigned_ char type. */ /* A simple typedef for the _unsigned_ char type. */
/* */ /* */
typedef unsigned char SW_FT_Byte; typedef unsigned char PVG_FT_Byte;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Bool */ /* PVG_FT_Bool */
/* */ /* */
/* <Description> */ /* <Description> */
/* A typedef of unsigned char, used for simple booleans. As usual, */ /* A typedef of unsigned char, used for simple booleans. As usual, */
/* values 1 and~0 represent true and false, respectively. */ /* values 1 and~0 represent true and false, respectively. */
/* */ /* */
typedef unsigned char SW_FT_Bool; typedef unsigned char PVG_FT_Bool;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Error */ /* PVG_FT_Error */
/* */ /* */
/* <Description> */ /* <Description> */
/* The FreeType error code type. A value of~0 is always interpreted */ /* The FreeType error code type. A value of~0 is always interpreted */
/* as a successful operation. */ /* as a successful operation. */
/* */ /* */
typedef int SW_FT_Error; typedef int PVG_FT_Error;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Type> */ /* <Type> */
/* SW_FT_Pos */ /* PVG_FT_Pos */
/* */ /* */
/* <Description> */ /* <Description> */
/* The type SW_FT_Pos is used to store vectorial coordinates. Depending */ /* The type PVG_FT_Pos is used to store vectorial coordinates. Depending */
/* on the context, these can represent distances in integer font */ /* on the context, these can represent distances in integer font */
/* units, or 16.16, or 26.6 fixed-point pixel coordinates. */ /* units, or 16.16, or 26.6 fixed-point pixel coordinates. */
/* */ /* */
typedef signed long SW_FT_Pos; typedef signed long PVG_FT_Pos;
/*************************************************************************/ /*************************************************************************/
/* */ /* */
/* <Struct> */ /* <Struct> */
/* SW_FT_Vector */ /* PVG_FT_Vector */
/* */ /* */
/* <Description> */ /* <Description> */
/* A simple structure used to store a 2D vector; coordinates are of */ /* A simple structure used to store a 2D vector; coordinates are of */
/* the SW_FT_Pos type. */ /* the PVG_FT_Pos type. */
/* */ /* */
/* <Fields> */ /* <Fields> */
/* x :: The horizontal coordinate. */ /* x :: The horizontal coordinate. */
/* y :: The vertical coordinate. */ /* y :: The vertical coordinate. */
/* */ /* */
typedef struct SW_FT_Vector_ typedef struct PVG_FT_Vector_
{ {
SW_FT_Pos x; PVG_FT_Pos x;
SW_FT_Pos y; PVG_FT_Pos y;
} SW_FT_Vector; } PVG_FT_Vector;
typedef long long int SW_FT_Int64; typedef long long int PVG_FT_Int64;
typedef unsigned long long int SW_FT_UInt64; typedef unsigned long long int PVG_FT_UInt64;
typedef signed int SW_FT_Int32; typedef signed int PVG_FT_Int32;
typedef unsigned int SW_FT_UInt32; typedef unsigned int PVG_FT_UInt32;
#define PVG_FT_BOOL( x ) ( (PVG_FT_Bool)( x ) )
#define SW_FT_BOOL( x ) ( (SW_FT_Bool)( x ) )
#define SW_FT_SIZEOF_LONG 4
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
@ -156,5 +170,4 @@ typedef unsigned int SW_FT_UInt32;
#define FALSE 0 #define FALSE 0
#endif #endif
#endif // PLUTOVG_FT_TYPES_H
#endif // SW_FT_TYPES_H

View file

@ -66,9 +66,9 @@ struct plutovg_paint {
}; };
typedef struct { typedef struct {
short x; int x;
short y; int len;
unsigned short len; int y;
unsigned char coverage; unsigned char coverage;
} plutovg_span_t; } plutovg_span_t;

View file

@ -1,26 +1,24 @@
#include "plutovg-private.h" #include "plutovg-private.h"
#include "sw_ft_raster.h" #include "plutovg-ft-raster.h"
#include "sw_ft_stroker.h" #include "plutovg-ft-stroker.h"
#include "sw_ft_types.h"
#include "sw_ft_math.h"
#include <math.h> #include <math.h>
#include <limits.h> #include <limits.h>
static SW_FT_Outline* sw_ft_outline_create(int points, int contours) static PVG_FT_Outline* ft_outline_create(size_t points, size_t contours)
{ {
SW_FT_Outline* ft = malloc(sizeof(SW_FT_Outline)); PVG_FT_Outline* ft = malloc(sizeof(PVG_FT_Outline));
ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector)); ft->points = malloc((points + contours) * sizeof(PVG_FT_Vector));
ft->tags = malloc((size_t)(points + contours) * sizeof(char)); ft->tags = malloc((points + contours) * sizeof(char));
ft->contours = malloc((size_t)contours * sizeof(int)); ft->contours = malloc(contours * sizeof(int));
ft->contours_flag = malloc((size_t)contours * sizeof(char)); ft->contours_flag = malloc(contours * sizeof(char));
ft->n_points = ft->n_contours = 0; ft->n_points = ft->n_contours = 0;
ft->flags = 0x0; ft->flags = 0x0;
return ft; return ft;
} }
static void sw_ft_outline_destroy(SW_FT_Outline* ft) static void ft_outline_destroy(PVG_FT_Outline* ft)
{ {
free(ft->points); free(ft->points);
free(ft->tags); free(ft->tags);
@ -29,14 +27,13 @@ static void sw_ft_outline_destroy(SW_FT_Outline* ft)
free(ft); free(ft);
} }
#define FT_COORD(x) (SW_FT_Pos)((x) * 64) #define FT_COORD(x) (PVG_FT_Pos)((x) * 64)
static void sw_ft_outline_move_to(SW_FT_Outline* ft, double x, double y) static void ft_outline_move_to(PVG_FT_Outline* ft, double x, double y)
{ {
ft->points[ft->n_points].x = FT_COORD(x); ft->points[ft->n_points].x = FT_COORD(x);
ft->points[ft->n_points].y = FT_COORD(y); ft->points[ft->n_points].y = FT_COORD(y);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
if(ft->n_points) if(ft->n_points) {
{
ft->contours[ft->n_contours] = ft->n_points - 1; ft->contours[ft->n_contours] = ft->n_points - 1;
ft->n_contours++; ft->n_contours++;
} }
@ -45,33 +42,33 @@ static void sw_ft_outline_move_to(SW_FT_Outline* ft, double x, double y)
ft->n_points++; ft->n_points++;
} }
static void sw_ft_outline_line_to(SW_FT_Outline* ft, double x, double y) static void ft_outline_line_to(PVG_FT_Outline* ft, double x, double y)
{ {
ft->points[ft->n_points].x = FT_COORD(x); ft->points[ft->n_points].x = FT_COORD(x);
ft->points[ft->n_points].y = FT_COORD(y); ft->points[ft->n_points].y = FT_COORD(y);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
ft->n_points++; ft->n_points++;
} }
static void sw_ft_outline_cubic_to(SW_FT_Outline* ft, double x1, double y1, double x2, double y2, double x3, double y3) static void ft_outline_cubic_to(PVG_FT_Outline* ft, double x1, double y1, double x2, double y2, double x3, double y3)
{ {
ft->points[ft->n_points].x = FT_COORD(x1); ft->points[ft->n_points].x = FT_COORD(x1);
ft->points[ft->n_points].y = FT_COORD(y1); ft->points[ft->n_points].y = FT_COORD(y1);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_CUBIC; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_CUBIC;
ft->n_points++; ft->n_points++;
ft->points[ft->n_points].x = FT_COORD(x2); ft->points[ft->n_points].x = FT_COORD(x2);
ft->points[ft->n_points].y = FT_COORD(y2); ft->points[ft->n_points].y = FT_COORD(y2);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_CUBIC; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_CUBIC;
ft->n_points++; ft->n_points++;
ft->points[ft->n_points].x = FT_COORD(x3); ft->points[ft->n_points].x = FT_COORD(x3);
ft->points[ft->n_points].y = FT_COORD(y3); ft->points[ft->n_points].y = FT_COORD(y3);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
ft->n_points++; ft->n_points++;
} }
static void sw_ft_outline_close(SW_FT_Outline* ft) static void ft_outline_close(PVG_FT_Outline* ft)
{ {
ft->contours_flag[ft->n_contours] = 0; ft->contours_flag[ft->n_contours] = 0;
int index = ft->n_contours ? ft->contours[ft->n_contours - 1] + 1 : 0; int index = ft->n_contours ? ft->contours[ft->n_contours - 1] + 1 : 0;
@ -80,66 +77,63 @@ static void sw_ft_outline_close(SW_FT_Outline* ft)
ft->points[ft->n_points].x = ft->points[index].x; ft->points[ft->n_points].x = ft->points[index].x;
ft->points[ft->n_points].y = ft->points[index].y; ft->points[ft->n_points].y = ft->points[index].y;
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
ft->n_points++; ft->n_points++;
} }
static void sw_ft_outline_end(SW_FT_Outline* ft) static void ft_outline_end(PVG_FT_Outline* ft)
{ {
if(ft->n_points) if(ft->n_points) {
{
ft->contours[ft->n_contours] = ft->n_points - 1; ft->contours[ft->n_contours] = ft->n_points - 1;
ft->n_contours++; ft->n_contours++;
} }
} }
static SW_FT_Outline* sw_ft_outline_convert(const plutovg_path_t* path, const plutovg_matrix_t* matrix) static PVG_FT_Outline* ft_outline_convert(const plutovg_path_t* path, const plutovg_matrix_t* matrix)
{ {
SW_FT_Outline* outline = sw_ft_outline_create(path->points.size, path->contours); PVG_FT_Outline* outline = ft_outline_create(path->points.size, path->contours);
plutovg_path_element_t* elements = path->elements.data; plutovg_path_element_t* elements = path->elements.data;
plutovg_point_t* points = path->points.data; plutovg_point_t* points = path->points.data;
plutovg_point_t p[3]; plutovg_point_t p[3];
for(int i = 0;i < path->elements.size;i++) for(int i = 0;i < path->elements.size;i++) {
{ switch(elements[i]) {
switch(elements[i])
{
case plutovg_path_element_move_to: case plutovg_path_element_move_to:
plutovg_matrix_map_point(matrix, &points[0], &p[0]); plutovg_matrix_map_point(matrix, &points[0], &p[0]);
sw_ft_outline_move_to(outline, p[0].x, p[0].y); ft_outline_move_to(outline, p[0].x, p[0].y);
points += 1; points += 1;
break; break;
case plutovg_path_element_line_to: case plutovg_path_element_line_to:
plutovg_matrix_map_point(matrix, &points[0], &p[0]); plutovg_matrix_map_point(matrix, &points[0], &p[0]);
sw_ft_outline_line_to(outline, p[0].x, p[0].y); ft_outline_line_to(outline, p[0].x, p[0].y);
points += 1; points += 1;
break; break;
case plutovg_path_element_cubic_to: case plutovg_path_element_cubic_to:
plutovg_matrix_map_point(matrix, &points[0], &p[0]); plutovg_matrix_map_point(matrix, &points[0], &p[0]);
plutovg_matrix_map_point(matrix, &points[1], &p[1]); plutovg_matrix_map_point(matrix, &points[1], &p[1]);
plutovg_matrix_map_point(matrix, &points[2], &p[2]); plutovg_matrix_map_point(matrix, &points[2], &p[2]);
sw_ft_outline_cubic_to(outline, p[0].x, p[0].y, p[1].x, p[1].y, p[2].x, p[2].y); ft_outline_cubic_to(outline, p[0].x, p[0].y, p[1].x, p[1].y, p[2].x, p[2].y);
points += 3; points += 3;
break; break;
case plutovg_path_element_close: case plutovg_path_element_close:
sw_ft_outline_close(outline); ft_outline_close(outline);
points += 1; points += 1;
break; break;
} }
} }
sw_ft_outline_end(outline); ft_outline_end(outline);
return outline; return outline;
} }
static SW_FT_Outline* sw_ft_outline_convert_dash(const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_dash_t* dash) static PVG_FT_Outline* ft_outline_convert_dash(const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_dash_t* dash)
{ {
plutovg_path_t* dashed = plutovg_dash_path(dash, path); plutovg_path_t* dashed = plutovg_dash_path(dash, path);
SW_FT_Outline* outline = sw_ft_outline_convert(dashed, matrix); PVG_FT_Outline* outline = ft_outline_convert(dashed, matrix);
plutovg_path_destroy(dashed); plutovg_path_destroy(dashed);
return outline; return outline;
} }
static void generation_callback(int count, const SW_FT_Span* spans, void* user) static void generation_callback(int count, const PVG_FT_Span* spans, void* user)
{ {
plutovg_rle_t* rle = user; plutovg_rle_t* rle = user;
plutovg_array_ensure(rle->spans, count); plutovg_array_ensure(rle->spans, count);
@ -148,15 +142,6 @@ static void generation_callback(int count, const SW_FT_Span* spans, void* user)
rle->spans.size += count; rle->spans.size += count;
} }
static void bbox_callback(int x, int y, int w, int h, void* user)
{
plutovg_rle_t* rle = user;
rle->x = x;
rle->y = y;
rle->w = w;
rle->h = h;
}
plutovg_rle_t* plutovg_rle_create(void) plutovg_rle_t* plutovg_rle_create(void)
{ {
plutovg_rle_t* rle = malloc(sizeof(plutovg_rle_t)); plutovg_rle_t* rle = malloc(sizeof(plutovg_rle_t));
@ -180,28 +165,28 @@ void plutovg_rle_destroy(plutovg_rle_t* rle)
#define SQRT2 1.41421356237309504880 #define SQRT2 1.41421356237309504880
void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding) void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding)
{ {
SW_FT_Raster_Params params; PVG_FT_Raster_Params params;
params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA; params.flags = PVG_FT_RASTER_FLAG_DIRECT | PVG_FT_RASTER_FLAG_AA;
params.gray_spans = generation_callback; params.gray_spans = generation_callback;
params.bbox_cb = bbox_callback;
params.user = rle; params.user = rle;
if(clip) {
if(clip) params.flags |= PVG_FT_RASTER_FLAG_CLIP;
{ params.clip_box.xMin = (PVG_FT_Pos)clip->x;
params.flags |= SW_FT_RASTER_FLAG_CLIP; params.clip_box.yMin = (PVG_FT_Pos)clip->y;
params.clip_box.xMin = (SW_FT_Pos)clip->x; params.clip_box.xMax = (PVG_FT_Pos)(clip->x + clip->w);
params.clip_box.yMin = (SW_FT_Pos)clip->y; params.clip_box.yMax = (PVG_FT_Pos)(clip->y + clip->h);
params.clip_box.xMax = (SW_FT_Pos)(clip->x + clip->w);
params.clip_box.yMax = (SW_FT_Pos)(clip->y + clip->h);
} }
if(stroke) if(stroke) {
{ PVG_FT_Outline* outline;
SW_FT_Outline* outline = stroke->dash ? sw_ft_outline_convert_dash(path, matrix, stroke->dash) : sw_ft_outline_convert(path, matrix); if(stroke->dash == NULL)
SW_FT_Stroker_LineCap ftCap; outline = ft_outline_convert(path, matrix);
SW_FT_Stroker_LineJoin ftJoin; else
SW_FT_Fixed ftWidth; outline = ft_outline_convert_dash(path, matrix, stroke->dash);
SW_FT_Fixed ftMiterLimit; PVG_FT_Stroker_LineCap ftCap;
PVG_FT_Stroker_LineJoin ftJoin;
PVG_FT_Fixed ftWidth;
PVG_FT_Fixed ftMiterLimit;
plutovg_point_t p1 = {0, 0}; plutovg_point_t p1 = {0, 0};
plutovg_point_t p2 = {SQRT2, SQRT2}; plutovg_point_t p2 = {SQRT2, SQRT2};
@ -215,62 +200,90 @@ void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const
double scale = sqrt(p3.x*p3.x + p3.y*p3.y) / 2.0; double scale = sqrt(p3.x*p3.x + p3.y*p3.y) / 2.0;
ftWidth = (SW_FT_Fixed)(stroke->width * scale * 0.5 * (1 << 6)); ftWidth = (PVG_FT_Fixed)(stroke->width * scale * 0.5 * (1 << 6));
ftMiterLimit = (SW_FT_Fixed)(stroke->miterlimit * (1 << 16)); ftMiterLimit = (PVG_FT_Fixed)(stroke->miterlimit * (1 << 16));
switch(stroke->cap) switch(stroke->cap) {
{
case plutovg_line_cap_square: case plutovg_line_cap_square:
ftCap = SW_FT_STROKER_LINECAP_SQUARE; ftCap = PVG_FT_STROKER_LINECAP_SQUARE;
break; break;
case plutovg_line_cap_round: case plutovg_line_cap_round:
ftCap = SW_FT_STROKER_LINECAP_ROUND; ftCap = PVG_FT_STROKER_LINECAP_ROUND;
break; break;
default: default:
ftCap = SW_FT_STROKER_LINECAP_BUTT; ftCap = PVG_FT_STROKER_LINECAP_BUTT;
break; break;
} }
switch(stroke->join) switch(stroke->join) {
{
case plutovg_line_join_bevel: case plutovg_line_join_bevel:
ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL; ftJoin = PVG_FT_STROKER_LINEJOIN_BEVEL;
break; break;
case plutovg_line_join_round: case plutovg_line_join_round:
ftJoin = SW_FT_STROKER_LINEJOIN_ROUND; ftJoin = PVG_FT_STROKER_LINEJOIN_ROUND;
break; break;
default: default:
ftJoin = SW_FT_STROKER_LINEJOIN_MITER_FIXED; ftJoin = PVG_FT_STROKER_LINEJOIN_MITER_FIXED;
break; break;
} }
SW_FT_Stroker stroker; PVG_FT_Stroker stroker;
SW_FT_Stroker_New(&stroker); PVG_FT_Stroker_New(&stroker);
SW_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit); PVG_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit);
SW_FT_Stroker_ParseOutline(stroker, outline); PVG_FT_Stroker_ParseOutline(stroker, outline);
SW_FT_UInt points; PVG_FT_UInt points;
SW_FT_UInt contours; PVG_FT_UInt contours;
SW_FT_Stroker_GetCounts(stroker, &points, &contours); PVG_FT_Stroker_GetCounts(stroker, &points, &contours);
SW_FT_Outline* strokeOutline = sw_ft_outline_create((int)points, (int)contours); PVG_FT_Outline* strokeOutline = ft_outline_create(points, contours);
SW_FT_Stroker_Export(stroker, strokeOutline); PVG_FT_Stroker_Export(stroker, strokeOutline);
SW_FT_Stroker_Done(stroker); PVG_FT_Stroker_Done(stroker);
strokeOutline->flags = SW_FT_OUTLINE_NONE; strokeOutline->flags = PVG_FT_OUTLINE_NONE;
params.source = strokeOutline; params.source = strokeOutline;
sw_ft_grays_raster.raster_render(NULL, &params); PVG_FT_Raster_Render(&params);
sw_ft_outline_destroy(outline); ft_outline_destroy(outline);
sw_ft_outline_destroy(strokeOutline); ft_outline_destroy(strokeOutline);
} } else {
else PVG_FT_Outline* outline = ft_outline_convert(path, matrix);
{ switch(winding) {
SW_FT_Outline* outline = sw_ft_outline_convert(path, matrix); case plutovg_fill_rule_even_odd:
outline->flags = winding == plutovg_fill_rule_even_odd ? SW_FT_OUTLINE_EVEN_ODD_FILL : SW_FT_OUTLINE_NONE; outline->flags = PVG_FT_OUTLINE_EVEN_ODD_FILL;
break;
default:
outline->flags = PVG_FT_OUTLINE_NONE;
break;
}
params.source = outline; params.source = outline;
sw_ft_grays_raster.raster_render(NULL, &params); PVG_FT_Raster_Render(&params);
sw_ft_outline_destroy(outline); ft_outline_destroy(outline);
} }
if(rle->spans.size == 0) {
rle->x = 0;
rle->y = 0;
rle->w = 0;
rle->h = 0;
return;
}
plutovg_span_t* spans = rle->spans.data;
int x1 = INT_MAX;
int y1 = spans[0].y;
int x2 = 0;
int y2 = spans[rle->spans.size - 1].y;
for(int i = 0;i < rle->spans.size;i++)
{
if(spans[i].x < x1) x1 = spans[i].x;
if(spans[i].x + spans[i].len > x2) x2 = spans[i].x + spans[i].len;
}
rle->x = x1;
rle->y = y1;
rle->w = x2 - x1;
rle->h = y2 - y1 + 1;
} }
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))

View file

@ -1,11 +0,0 @@
target_sources(lunasvg
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/sw_ft_math.c"
"${CMAKE_CURRENT_LIST_DIR}/sw_ft_raster.c"
"${CMAKE_CURRENT_LIST_DIR}/sw_ft_stroker.c"
)
target_include_directories(lunasvg
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
)

View file

@ -1,438 +0,0 @@
#ifndef SW_FT_MATH_H
#define SW_FT_MATH_H
/***************************************************************************/
/* */
/* fttrigon.h */
/* */
/* FreeType trigonometric functions (specification). */
/* */
/* Copyright 2001, 2003, 2005, 2007, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "sw_ft_types.h"
/*************************************************************************/
/* */
/* The min and max functions missing in C. As usual, be careful not to */
/* write things like SW_FT_MIN( a++, b++ ) to avoid side effects. */
/* */
#define SW_FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
#define SW_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
#define SW_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
/*
* Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
* algorithm. We use alpha = 1, beta = 3/8, giving us results with a
* largest error less than 7% compared to the exact value.
*/
#define SW_FT_HYPOT( x, y ) \
( x = SW_FT_ABS( x ), \
y = SW_FT_ABS( y ), \
x > y ? x + ( 3 * y >> 3 ) \
: y + ( 3 * x >> 3 ) )
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_MulFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */
/* used to multiply a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. Use a 16.16 factor here whenever */
/* possible (see note below). */
/* */
/* <Return> */
/* The result of `(a*b)/0x10000'. */
/* */
/* <Note> */
/* This function has been optimized for the case where the absolute */
/* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
/* As this happens mainly when scaling from notional units to */
/* fractional pixels in FreeType, it resulted in noticeable speed */
/* improvements between versions 2.x and 1.x. */
/* */
/* As a conclusion, always try to place a 16.16 factor as the */
/* _second_ argument of this function; this can make a great */
/* difference. */
/* */
SW_FT_Long
SW_FT_MulFix( SW_FT_Long a,
SW_FT_Long b );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_MulDiv */
/* */
/* <Description> */
/* A very simple function used to perform the computation `(a*b)/c' */
/* with maximum accuracy (it uses a 64-bit intermediate integer */
/* whenever necessary). */
/* */
/* This function isn't necessarily as fast as some processor specific */
/* operations, but is at least completely portable. */
/* */
/* <Input> */
/* a :: The first multiplier. */
/* b :: The second multiplier. */
/* c :: The divisor. */
/* */
/* <Return> */
/* The result of `(a*b)/c'. This function never traps when trying to */
/* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
/* on the signs of `a' and `b'. */
/* */
SW_FT_Long
SW_FT_MulDiv( SW_FT_Long a,
SW_FT_Long b,
SW_FT_Long c );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_DivFix */
/* */
/* <Description> */
/* A very simple function used to perform the computation */
/* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */
/* used to divide a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
/* a :: The numerator. */
/* b :: The denominator. Use a 16.16 factor here. */
/* */
/* <Return> */
/* The result of `(a*0x10000)/b'. */
/* */
SW_FT_Long
SW_FT_DivFix( SW_FT_Long a,
SW_FT_Long b );
/*************************************************************************/
/* */
/* <Section> */
/* computations */
/* */
/*************************************************************************/
/*************************************************************************
*
* @type:
* SW_FT_Angle
*
* @description:
* This type is used to model angle values in FreeType. Note that the
* angle is a 16.16 fixed-point value expressed in degrees.
*
*/
typedef SW_FT_Fixed SW_FT_Angle;
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI
*
* @description:
* The angle pi expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI ( 180L << 16 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_2PI
*
* @description:
* The angle 2*pi expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_2PI ( SW_FT_ANGLE_PI * 2 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI2
*
* @description:
* The angle pi/2 expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI2 ( SW_FT_ANGLE_PI / 2 )
/*************************************************************************
*
* @macro:
* SW_FT_ANGLE_PI4
*
* @description:
* The angle pi/4 expressed in @SW_FT_Angle units.
*
*/
#define SW_FT_ANGLE_PI4 ( SW_FT_ANGLE_PI / 4 )
/*************************************************************************
*
* @function:
* SW_FT_Sin
*
* @description:
* Return the sinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The sinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @SW_FT_Vector_Unit.
*
*/
SW_FT_Fixed
SW_FT_Sin( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Cos
*
* @description:
* Return the cosinus of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The cosinus value.
*
* @note:
* If you need both the sinus and cosinus for a given angle, use the
* function @SW_FT_Vector_Unit.
*
*/
SW_FT_Fixed
SW_FT_Cos( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Tan
*
* @description:
* Return the tangent of a given angle in fixed-point format.
*
* @input:
* angle ::
* The input angle.
*
* @return:
* The tangent value.
*
*/
SW_FT_Fixed
SW_FT_Tan( SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Atan2
*
* @description:
* Return the arc-tangent corresponding to a given vector (x,y) in
* the 2d plane.
*
* @input:
* x ::
* The horizontal vector coordinate.
*
* y ::
* The vertical vector coordinate.
*
* @return:
* The arc-tangent value (i.e. angle).
*
*/
SW_FT_Angle
SW_FT_Atan2( SW_FT_Fixed x,
SW_FT_Fixed y );
/*************************************************************************
*
* @function:
* SW_FT_Angle_Diff
*
* @description:
* Return the difference between two angles. The result is always
* constrained to the ]-PI..PI] interval.
*
* @input:
* angle1 ::
* First angle.
*
* angle2 ::
* Second angle.
*
* @return:
* Constrained value of `value2-value1'.
*
*/
SW_FT_Angle
SW_FT_Angle_Diff( SW_FT_Angle angle1,
SW_FT_Angle angle2 );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Unit
*
* @description:
* Return the unit vector corresponding to a given angle. After the
* call, the value of `vec.x' will be `sin(angle)', and the value of
* `vec.y' will be `cos(angle)'.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
*
* @output:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
SW_FT_Vector_Unit( SW_FT_Vector* vec,
SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Rotate
*
* @description:
* Rotate a vector by a given angle.
*
* @inout:
* vec ::
* The address of target vector.
*
* @input:
* angle ::
* The input angle.
*
*/
void
SW_FT_Vector_Rotate( SW_FT_Vector* vec,
SW_FT_Angle angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Length
*
* @description:
* Return the length of a given vector.
*
* @input:
* vec ::
* The address of target vector.
*
* @return:
* The vector length, expressed in the same units that the original
* vector coordinates.
*
*/
SW_FT_Fixed
SW_FT_Vector_Length( SW_FT_Vector* vec );
/*************************************************************************
*
* @function:
* SW_FT_Vector_Polarize
*
* @description:
* Compute both the length and angle of a given vector.
*
* @input:
* vec ::
* The address of source vector.
*
* @output:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
SW_FT_Vector_Polarize( SW_FT_Vector* vec,
SW_FT_Fixed *length,
SW_FT_Angle *angle );
/*************************************************************************
*
* @function:
* SW_FT_Vector_From_Polar
*
* @description:
* Compute vector coordinates from a length and angle.
*
* @output:
* vec ::
* The address of source vector.
*
* @input:
* length ::
* The vector length.
*
* angle ::
* The vector angle.
*
*/
void
SW_FT_Vector_From_Polar( SW_FT_Vector* vec,
SW_FT_Fixed length,
SW_FT_Angle angle );
#endif // SW_FT_MATH_H

File diff suppressed because it is too large Load diff

View file

@ -1,607 +0,0 @@
#ifndef SW_FT_IMG_H
#define SW_FT_IMG_H
/***************************************************************************/
/* */
/* ftimage.h */
/* */
/* FreeType glyph image formats and default raster interface */
/* (specification). */
/* */
/* Copyright 1996-2010, 2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* Note: A `raster' is simply a scan-line converter, used to render */
/* SW_FT_Outlines into SW_FT_Bitmaps. */
/* */
/*************************************************************************/
#include "sw_ft_types.h"
/*************************************************************************/
/* */
/* <Struct> */
/* FT_BBox */
/* */
/* <Description> */
/* A structure used to hold an outline's bounding box, i.e., the */
/* coordinates of its extrema in the horizontal and vertical */
/* directions. */
/* */
/* <Fields> */
/* xMin :: The horizontal minimum (left-most). */
/* */
/* yMin :: The vertical minimum (bottom-most). */
/* */
/* xMax :: The horizontal maximum (right-most). */
/* */
/* yMax :: The vertical maximum (top-most). */
/* */
/* <Note> */
/* The bounding box is specified with the coordinates of the lower */
/* left and the upper right corner. In PostScript, those values are */
/* often called (llx,lly) and (urx,ury), respectively. */
/* */
/* If `yMin' is negative, this value gives the glyph's descender. */
/* Otherwise, the glyph doesn't descend below the baseline. */
/* Similarly, if `ymax' is positive, this value gives the glyph's */
/* ascender. */
/* */
/* `xMin' gives the horizontal distance from the glyph's origin to */
/* the left edge of the glyph's bounding box. If `xMin' is negative, */
/* the glyph extends to the left of the origin. */
/* */
typedef struct SW_FT_BBox_
{
SW_FT_Pos xMin, yMin;
SW_FT_Pos xMax, yMax;
} SW_FT_BBox;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Outline */
/* */
/* <Description> */
/* This structure is used to describe an outline to the scan-line */
/* converter. */
/* */
/* <Fields> */
/* n_contours :: The number of contours in the outline. */
/* */
/* n_points :: The number of points in the outline. */
/* */
/* points :: A pointer to an array of `n_points' @SW_FT_Vector */
/* elements, giving the outline's point coordinates. */
/* */
/* tags :: A pointer to an array of `n_points' chars, giving */
/* each outline point's type. */
/* */
/* If bit~0 is unset, the point is `off' the curve, */
/* i.e., a Bézier control point, while it is `on' if */
/* set. */
/* */
/* Bit~1 is meaningful for `off' points only. If set, */
/* it indicates a third-order Bézier arc control point; */
/* and a second-order control point if unset. */
/* */
/* If bit~2 is set, bits 5-7 contain the drop-out mode */
/* (as defined in the OpenType specification; the value */
/* is the same as the argument to the SCANMODE */
/* instruction). */
/* */
/* Bits 3 and~4 are reserved for internal purposes. */
/* */
/* contours :: An array of `n_contours' shorts, giving the end */
/* point of each contour within the outline. For */
/* example, the first contour is defined by the points */
/* `0' to `contours[0]', the second one is defined by */
/* the points `contours[0]+1' to `contours[1]', etc. */
/* */
/* flags :: A set of bit flags used to characterize the outline */
/* and give hints to the scan-converter and hinter on */
/* how to convert/grid-fit it. See @SW_FT_OUTLINE_FLAGS.*/
/* */
typedef struct SW_FT_Outline_
{
int n_contours; /* number of contours in glyph */
int n_points; /* number of points in the glyph */
SW_FT_Vector* points; /* the outline's points */
char* tags; /* the points flags */
int* contours; /* the contour end points */
char* contours_flag; /* the contour open flags */
int flags; /* outline masks */
} SW_FT_Outline;
/*************************************************************************/
/* */
/* <Enum> */
/* SW_FT_OUTLINE_FLAGS */
/* */
/* <Description> */
/* A list of bit-field constants use for the flags in an outline's */
/* `flags' field. */
/* */
/* <Values> */
/* SW_FT_OUTLINE_NONE :: */
/* Value~0 is reserved. */
/* */
/* SW_FT_OUTLINE_OWNER :: */
/* If set, this flag indicates that the outline's field arrays */
/* (i.e., `points', `flags', and `contours') are `owned' by the */
/* outline object, and should thus be freed when it is destroyed. */
/* */
/* SW_FT_OUTLINE_EVEN_ODD_FILL :: */
/* By default, outlines are filled using the non-zero winding rule. */
/* If set to 1, the outline will be filled using the even-odd fill */
/* rule (only works with the smooth rasterizer). */
/* */
/* SW_FT_OUTLINE_REVERSE_FILL :: */
/* By default, outside contours of an outline are oriented in */
/* clock-wise direction, as defined in the TrueType specification. */
/* This flag is set if the outline uses the opposite direction */
/* (typically for Type~1 fonts). This flag is ignored by the scan */
/* converter. */
/* */
/* */
/* */
/* There exists a second mechanism to pass the drop-out mode to the */
/* B/W rasterizer; see the `tags' field in @SW_FT_Outline. */
/* */
/* Please refer to the description of the `SCANTYPE' instruction in */
/* the OpenType specification (in file `ttinst1.doc') how simple */
/* drop-outs, smart drop-outs, and stubs are defined. */
/* */
#define SW_FT_OUTLINE_NONE 0x0
#define SW_FT_OUTLINE_OWNER 0x1
#define SW_FT_OUTLINE_EVEN_ODD_FILL 0x2
#define SW_FT_OUTLINE_REVERSE_FILL 0x4
/* */
#define SW_FT_CURVE_TAG( flag ) ( flag & 3 )
#define SW_FT_CURVE_TAG_ON 1
#define SW_FT_CURVE_TAG_CONIC 0
#define SW_FT_CURVE_TAG_CUBIC 2
#define SW_FT_Curve_Tag_On SW_FT_CURVE_TAG_ON
#define SW_FT_Curve_Tag_Conic SW_FT_CURVE_TAG_CONIC
#define SW_FT_Curve_Tag_Cubic SW_FT_CURVE_TAG_CUBIC
/*************************************************************************/
/* */
/* A raster is a scan converter, in charge of rendering an outline into */
/* a a bitmap. This section contains the public API for rasters. */
/* */
/* Note that in FreeType 2, all rasters are now encapsulated within */
/* specific modules called `renderers'. See `ftrender.h' for more */
/* details on renderers. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Raster */
/* */
/* <Description> */
/* A handle (pointer) to a raster object. Each object can be used */
/* independently to convert an outline into a bitmap or pixmap. */
/* */
typedef struct SW_FT_RasterRec_* SW_FT_Raster;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Span */
/* */
/* <Description> */
/* A structure used to model a single span of gray (or black) pixels */
/* when rendering a monochrome or anti-aliased bitmap. */
/* */
/* <Fields> */
/* x :: The span's horizontal start position. */
/* */
/* len :: The span's length in pixels. */
/* */
/* coverage :: The span color/coverage, ranging from 0 (background) */
/* to 255 (foreground). Only used for anti-aliased */
/* rendering. */
/* */
/* <Note> */
/* This structure is used by the span drawing callback type named */
/* @SW_FT_SpanFunc that takes the y~coordinate of the span as a */
/* parameter. */
/* */
/* The coverage value is always between 0 and 255. If you want less */
/* gray values, the callback function has to reduce them. */
/* */
typedef struct SW_FT_Span_
{
short x;
short y;
unsigned short len;
unsigned char coverage;
} SW_FT_Span;
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_SpanFunc */
/* */
/* <Description> */
/* A function used as a call-back by the anti-aliased renderer in */
/* order to let client applications draw themselves the gray pixel */
/* spans on each scan line. */
/* */
/* <Input> */
/* y :: The scanline's y~coordinate. */
/* */
/* count :: The number of spans to draw on this scanline. */
/* */
/* spans :: A table of `count' spans to draw on the scanline. */
/* */
/* user :: User-supplied data that is passed to the callback. */
/* */
/* <Note> */
/* This callback allows client applications to directly render the */
/* gray spans of the anti-aliased bitmap to any kind of surfaces. */
/* */
/* This can be used to write anti-aliased outlines directly to a */
/* given background bitmap, and even perform translucency. */
/* */
/* Note that the `count' field cannot be greater than a fixed value */
/* defined by the `SW_FT_MAX_GRAY_SPANS' configuration macro in */
/* `ftoption.h'. By default, this value is set to~32, which means */
/* that if there are more than 32~spans on a given scanline, the */
/* callback is called several times with the same `y' parameter in */
/* order to draw all callbacks. */
/* */
/* Otherwise, the callback is only called once per scan-line, and */
/* only for those scanlines that do have `gray' pixels on them. */
/* */
typedef void
(*SW_FT_SpanFunc)( int count,
const SW_FT_Span* spans,
void* user );
typedef void
(*SW_FT_BboxFunc)( int x, int y, int w, int h,
void* user);
#define SW_FT_Raster_Span_Func SW_FT_SpanFunc
/*************************************************************************/
/* */
/* <Enum> */
/* SW_FT_RASTER_FLAG_XXX */
/* */
/* <Description> */
/* A list of bit flag constants as used in the `flags' field of a */
/* @SW_FT_Raster_Params structure. */
/* */
/* <Values> */
/* SW_FT_RASTER_FLAG_DEFAULT :: This value is 0. */
/* */
/* SW_FT_RASTER_FLAG_AA :: This flag is set to indicate that an */
/* anti-aliased glyph image should be */
/* generated. Otherwise, it will be */
/* monochrome (1-bit). */
/* */
/* SW_FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */
/* rendering. In this mode, client */
/* applications must provide their own span */
/* callback. This lets them directly */
/* draw or compose over an existing bitmap. */
/* If this bit is not set, the target */
/* pixmap's buffer _must_ be zeroed before */
/* rendering. */
/* */
/* Note that for now, direct rendering is */
/* only possible with anti-aliased glyphs. */
/* */
/* SW_FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
/* rendering mode. If set, the output will */
/* be clipped to a box specified in the */
/* `clip_box' field of the */
/* @SW_FT_Raster_Params structure. */
/* */
/* Note that by default, the glyph bitmap */
/* is clipped to the target pixmap, except */
/* in direct rendering mode where all spans */
/* are generated if no clipping box is set. */
/* */
#define SW_FT_RASTER_FLAG_DEFAULT 0x0
#define SW_FT_RASTER_FLAG_AA 0x1
#define SW_FT_RASTER_FLAG_DIRECT 0x2
#define SW_FT_RASTER_FLAG_CLIP 0x4
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Raster_Params */
/* */
/* <Description> */
/* A structure to hold the arguments used by a raster's render */
/* function. */
/* */
/* <Fields> */
/* target :: The target bitmap. */
/* */
/* source :: A pointer to the source glyph image (e.g., an */
/* @SW_FT_Outline). */
/* */
/* flags :: The rendering flags. */
/* */
/* gray_spans :: The gray span drawing callback. */
/* */
/* black_spans :: The black span drawing callback. UNIMPLEMENTED! */
/* */
/* bit_test :: The bit test callback. UNIMPLEMENTED! */
/* */
/* bit_set :: The bit set callback. UNIMPLEMENTED! */
/* */
/* user :: User-supplied data that is passed to each drawing */
/* callback. */
/* */
/* clip_box :: An optional clipping box. It is only used in */
/* direct rendering mode. Note that coordinates here */
/* should be expressed in _integer_ pixels (and not in */
/* 26.6 fixed-point units). */
/* */
/* <Note> */
/* An anti-aliased glyph bitmap is drawn if the @SW_FT_RASTER_FLAG_AA */
/* bit flag is set in the `flags' field, otherwise a monochrome */
/* bitmap is generated. */
/* */
/* If the @SW_FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
/* raster will call the `gray_spans' callback to draw gray pixel */
/* spans, in the case of an aa glyph bitmap, it will call */
/* `black_spans', and `bit_test' and `bit_set' in the case of a */
/* monochrome bitmap. This allows direct composition over a */
/* pre-existing bitmap through user-provided callbacks to perform the */
/* span drawing/composition. */
/* */
/* Note that the `bit_test' and `bit_set' callbacks are required when */
/* rendering a monochrome bitmap, as they are crucial to implement */
/* correct drop-out control as defined in the TrueType specification. */
/* */
typedef struct SW_FT_Raster_Params_
{
const void* source;
int flags;
SW_FT_SpanFunc gray_spans;
SW_FT_BboxFunc bbox_cb;
void* user;
SW_FT_BBox clip_box;
} SW_FT_Raster_Params;
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_Outline_Check */
/* */
/* <Description> */
/* Check the contents of an outline descriptor. */
/* */
/* <Input> */
/* outline :: A handle to a source outline. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
SW_FT_Error
SW_FT_Outline_Check( SW_FT_Outline* outline );
/*************************************************************************/
/* */
/* <Function> */
/* SW_FT_Outline_Get_CBox */
/* */
/* <Description> */
/* Return an outline's `control box'. The control box encloses all */
/* the outline's points, including Bézier control points. Though it */
/* coincides with the exact bounding box for most glyphs, it can be */
/* slightly larger in some situations (like when rotating an outline */
/* that contains Bézier outside arcs). */
/* */
/* Computing the control box is very fast, while getting the bounding */
/* box can take much more time as it needs to walk over all segments */
/* and arcs in the outline. To get the latter, you can use the */
/* `ftbbox' component, which is dedicated to this single task. */
/* */
/* <Input> */
/* outline :: A pointer to the source outline descriptor. */
/* */
/* <Output> */
/* acbox :: The outline's control box. */
/* */
/* <Note> */
/* See @SW_FT_Glyph_Get_CBox for a discussion of tricky fonts. */
/* */
void
SW_FT_Outline_Get_CBox( const SW_FT_Outline* outline,
SW_FT_BBox *acbox );
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_NewFunc */
/* */
/* <Description> */
/* A function used to create a new raster object. */
/* */
/* <Input> */
/* memory :: A handle to the memory allocator. */
/* */
/* <Output> */
/* raster :: A handle to the new raster object. */
/* */
/* <Return> */
/* Error code. 0~means success. */
/* */
/* <Note> */
/* The `memory' parameter is a typeless pointer in order to avoid */
/* un-wanted dependencies on the rest of the FreeType code. In */
/* practice, it is an @SW_FT_Memory object, i.e., a handle to the */
/* standard FreeType memory allocator. However, this field can be */
/* completely ignored by a given raster implementation. */
/* */
typedef int
(*SW_FT_Raster_NewFunc)( SW_FT_Raster* raster );
#define SW_FT_Raster_New_Func SW_FT_Raster_NewFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_DoneFunc */
/* */
/* <Description> */
/* A function used to destroy a given raster object. */
/* */
/* <Input> */
/* raster :: A handle to the raster object. */
/* */
typedef void
(*SW_FT_Raster_DoneFunc)( SW_FT_Raster raster );
#define SW_FT_Raster_Done_Func SW_FT_Raster_DoneFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_ResetFunc */
/* */
/* <Description> */
/* FreeType provides an area of memory called the `render pool', */
/* available to all registered rasters. This pool can be freely used */
/* during a given scan-conversion but is shared by all rasters. Its */
/* content is thus transient. */
/* */
/* This function is called each time the render pool changes, or just */
/* after a new raster object is created. */
/* */
/* <Input> */
/* raster :: A handle to the new raster object. */
/* */
/* pool_base :: The address in memory of the render pool. */
/* */
/* pool_size :: The size in bytes of the render pool. */
/* */
/* <Note> */
/* Rasters can ignore the render pool and rely on dynamic memory */
/* allocation if they want to (a handle to the memory allocator is */
/* passed to the raster constructor). However, this is not */
/* recommended for efficiency purposes. */
/* */
typedef void
(*SW_FT_Raster_ResetFunc)( SW_FT_Raster raster,
unsigned char* pool_base,
unsigned long pool_size );
#define SW_FT_Raster_Reset_Func SW_FT_Raster_ResetFunc
/*************************************************************************/
/* */
/* <FuncType> */
/* SW_FT_Raster_RenderFunc */
/* */
/* <Description> */
/* Invoke a given raster to scan-convert a given glyph image into a */
/* target bitmap. */
/* */
/* <Input> */
/* raster :: A handle to the raster object. */
/* */
/* params :: A pointer to an @SW_FT_Raster_Params structure used to */
/* store the rendering parameters. */
/* */
/* <Return> */
/* Error code. 0~means success. */
/* */
/* <Note> */
/* The exact format of the source image depends on the raster's glyph */
/* format defined in its @SW_FT_Raster_Funcs structure. It can be an */
/* @SW_FT_Outline or anything else in order to support a large array of */
/* glyph formats. */
/* */
/* Note also that the render function can fail and return a */
/* `SW_FT_Err_Unimplemented_Feature' error code if the raster used does */
/* not support direct composition. */
/* */
/* XXX: For now, the standard raster doesn't support direct */
/* composition but this should change for the final release (see */
/* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */
/* for examples of distinct implementations that support direct */
/* composition). */
/* */
typedef int
(*SW_FT_Raster_RenderFunc)( SW_FT_Raster raster,
const SW_FT_Raster_Params* params );
#define SW_FT_Raster_Render_Func SW_FT_Raster_RenderFunc
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Raster_Funcs */
/* */
/* <Description> */
/* A structure used to describe a given raster class to the library. */
/* */
/* <Fields> */
/* glyph_format :: The supported glyph format for this raster. */
/* */
/* raster_new :: The raster constructor. */
/* */
/* raster_reset :: Used to reset the render pool within the raster. */
/* */
/* raster_render :: A function to render a glyph into a given bitmap. */
/* */
/* raster_done :: The raster destructor. */
/* */
typedef struct SW_FT_Raster_Funcs_
{
SW_FT_Raster_NewFunc raster_new;
SW_FT_Raster_ResetFunc raster_reset;
SW_FT_Raster_RenderFunc raster_render;
SW_FT_Raster_DoneFunc raster_done;
} SW_FT_Raster_Funcs;
extern const SW_FT_Raster_Funcs sw_ft_grays_raster;
#endif // SW_FT_IMG_H

View file

@ -1,319 +0,0 @@
#ifndef SW_FT_STROKER_H
#define SW_FT_STROKER_H
/***************************************************************************/
/* */
/* ftstroke.h */
/* */
/* FreeType path stroker (specification). */
/* */
/* Copyright 2002-2006, 2008, 2009, 2011-2012 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "sw_ft_raster.h"
/**************************************************************
*
* @type:
* SW_FT_Stroker
*
* @description:
* Opaque handler to a path stroker object.
*/
typedef struct SW_FT_StrokerRec_* SW_FT_Stroker;
/**************************************************************
*
* @enum:
* SW_FT_Stroker_LineJoin
*
* @description:
* These values determine how two joining lines are rendered
* in a stroker.
*
* @values:
* SW_FT_STROKER_LINEJOIN_ROUND ::
* Used to render rounded line joins. Circular arcs are used
* to join two lines smoothly.
*
* SW_FT_STROKER_LINEJOIN_BEVEL ::
* Used to render beveled line joins. The outer corner of
* the joined lines is filled by enclosing the triangular
* region of the corner with a straight line between the
* outer corners of each stroke.
*
* SW_FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the
* miter limit is exceeded. The outer edges of the strokes
* for the two segments are extended until they meet at an
* angle. If the segments meet at too sharp an angle (such
* that the miter would extend from the intersection of the
* segments a distance greater than the product of the miter
* limit value and the border radius), then a bevel join (see
* above) is used instead. This prevents long spikes being
* created. SW_FT_STROKER_LINEJOIN_MITER_FIXED generates a miter
* line join as used in PostScript and PDF.
*
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* SW_FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if
* the miter limit is exceeded. The intersection of the
* strokes is clipped at a line perpendicular to the bisector
* of the angle between the strokes, at the distance from the
* intersection of the segments equal to the product of the
* miter limit value and the border radius. This prevents
* long spikes being created.
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line
* join as used in XPS. SW_FT_STROKER_LINEJOIN_MITER is an alias
* for SW_FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for
* backwards compatibility.
*/
typedef enum SW_FT_Stroker_LineJoin_
{
SW_FT_STROKER_LINEJOIN_ROUND = 0,
SW_FT_STROKER_LINEJOIN_BEVEL = 1,
SW_FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
SW_FT_STROKER_LINEJOIN_MITER = SW_FT_STROKER_LINEJOIN_MITER_VARIABLE,
SW_FT_STROKER_LINEJOIN_MITER_FIXED = 3
} SW_FT_Stroker_LineJoin;
/**************************************************************
*
* @enum:
* SW_FT_Stroker_LineCap
*
* @description:
* These values determine how the end of opened sub-paths are
* rendered in a stroke.
*
* @values:
* SW_FT_STROKER_LINECAP_BUTT ::
* The end of lines is rendered as a full stop on the last
* point itself.
*
* SW_FT_STROKER_LINECAP_ROUND ::
* The end of lines is rendered as a half-circle around the
* last point.
*
* SW_FT_STROKER_LINECAP_SQUARE ::
* The end of lines is rendered as a square around the
* last point.
*/
typedef enum SW_FT_Stroker_LineCap_
{
SW_FT_STROKER_LINECAP_BUTT = 0,
SW_FT_STROKER_LINECAP_ROUND,
SW_FT_STROKER_LINECAP_SQUARE
} SW_FT_Stroker_LineCap;
/**************************************************************
*
* @enum:
* SW_FT_StrokerBorder
*
* @description:
* These values are used to select a given stroke border
* in @SW_FT_Stroker_GetBorderCounts and @SW_FT_Stroker_ExportBorder.
*
* @values:
* SW_FT_STROKER_BORDER_LEFT ::
* Select the left border, relative to the drawing direction.
*
* SW_FT_STROKER_BORDER_RIGHT ::
* Select the right border, relative to the drawing direction.
*
* @note:
* Applications are generally interested in the `inside' and `outside'
* borders. However, there is no direct mapping between these and the
* `left' and `right' ones, since this really depends on the glyph's
* drawing orientation, which varies between font formats.
*
* You can however use @SW_FT_Outline_GetInsideBorder and
* @SW_FT_Outline_GetOutsideBorder to get these.
*/
typedef enum SW_FT_StrokerBorder_
{
SW_FT_STROKER_BORDER_LEFT = 0,
SW_FT_STROKER_BORDER_RIGHT
} SW_FT_StrokerBorder;
/**************************************************************
*
* @function:
* SW_FT_Stroker_New
*
* @description:
* Create a new stroker object.
*
* @input:
* library ::
* FreeType library handle.
*
* @output:
* astroker ::
* A new stroker object handle. NULL in case of error.
*
* @return:
* FreeType error code. 0~means success.
*/
SW_FT_Error
SW_FT_Stroker_New( SW_FT_Stroker *astroker );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Set
*
* @description:
* Reset a stroker object's attributes.
*
* @input:
* stroker ::
* The target stroker handle.
*
* radius ::
* The border radius.
*
* line_cap ::
* The line cap style.
*
* line_join ::
* The line join style.
*
* miter_limit ::
* The miter limit for the SW_FT_STROKER_LINEJOIN_MITER_FIXED and
* SW_FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
* expressed as 16.16 fixed-point value.
*
* @note:
* The radius is expressed in the same units as the outline
* coordinates.
*/
void
SW_FT_Stroker_Set( SW_FT_Stroker stroker,
SW_FT_Fixed radius,
SW_FT_Stroker_LineCap line_cap,
SW_FT_Stroker_LineJoin line_join,
SW_FT_Fixed miter_limit );
/**************************************************************
*
* @function:
* SW_FT_Stroker_ParseOutline
*
* @description:
* A convenience function used to parse a whole outline with
* the stroker. The resulting outline(s) can be retrieved
* later by functions like @SW_FT_Stroker_GetCounts and @SW_FT_Stroker_Export.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The source outline.
*
*
* @return:
* FreeType error code. 0~means success.
*
* @note:
* If `opened' is~0 (the default), the outline is treated as a closed
* path, and the stroker generates two distinct `border' outlines.
*
*
* This function calls @SW_FT_Stroker_Rewind automatically.
*/
SW_FT_Error
SW_FT_Stroker_ParseOutline( SW_FT_Stroker stroker,
const SW_FT_Outline* outline);
/**************************************************************
*
* @function:
* SW_FT_Stroker_GetCounts
*
* @description:
* Call this function once you have finished parsing your paths
* with the stroker. It returns the number of points and
* contours necessary to export all points/borders from the stroked
* outline/path.
*
* @input:
* stroker ::
* The target stroker handle.
*
* @output:
* anum_points ::
* The number of points.
*
* anum_contours ::
* The number of contours.
*
* @return:
* FreeType error code. 0~means success.
*/
SW_FT_Error
SW_FT_Stroker_GetCounts( SW_FT_Stroker stroker,
SW_FT_UInt *anum_points,
SW_FT_UInt *anum_contours );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Export
*
* @description:
* Call this function after @SW_FT_Stroker_GetBorderCounts to
* export all borders to your own @SW_FT_Outline structure.
*
* Note that this function appends the border points and
* contours to your outline, but does not try to resize its
* arrays.
*
* @input:
* stroker ::
* The target stroker handle.
*
* outline ::
* The target outline handle.
*/
void
SW_FT_Stroker_Export( SW_FT_Stroker stroker,
SW_FT_Outline* outline );
/**************************************************************
*
* @function:
* SW_FT_Stroker_Done
*
* @description:
* Destroy a stroker object.
*
* @input:
* stroker ::
* A stroker handle. Can be NULL.
*/
void
SW_FT_Stroker_Done( SW_FT_Stroker stroker );
#endif // SW_FT_STROKER_H

View file

@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.3) cmake_minimum_required(VERSION 3.3)
project(lunasvg VERSION 2.3.2 LANGUAGES CXX C) project(lunasvg VERSION 2.3.4 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
option(BUILD_SHARED_LIBS "Builds as shared library" OFF) option(BUILD_SHARED_LIBS "Builds as shared library" OFF)
@ -12,7 +12,6 @@ add_library(lunasvg)
add_subdirectory(include) add_subdirectory(include)
add_subdirectory(source) add_subdirectory(source)
add_subdirectory(3rdparty/software)
add_subdirectory(3rdparty/plutovg) add_subdirectory(3rdparty/plutovg)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)

View file

@ -1,4 +1,4 @@
[![Releases](https://img.shields.io/badge/Version-2.3.2-orange.svg)](https://github.com/sammycage/lunasvg/releases) [![Releases](https://img.shields.io/badge/Version-2.3.4-orange.svg)](https://github.com/sammycage/lunasvg/releases)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sammycage/lunasvg/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sammycage/lunasvg/blob/master/LICENSE)
[![Build Status](https://github.com/sammycage/lunasvg/actions/workflows/ci.yml/badge.svg)](https://github.com/sammycage/lunasvg/actions) [![Build Status](https://github.com/sammycage/lunasvg/actions/workflows/ci.yml/badge.svg)](https://github.com/sammycage/lunasvg/actions)

View file

@ -9,7 +9,7 @@ static plutovg_fill_rule_t to_plutovg_fill_rule(WindRule winding);
static plutovg_operator_t to_plutovg_operator(BlendMode mode); static plutovg_operator_t to_plutovg_operator(BlendMode mode);
static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap); static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap);
static plutovg_line_join_t to_plutovg_line_join(LineJoin join); static plutovg_line_join_t to_plutovg_line_join(LineJoin join);
static plutovg_spread_method_t to_plutovg_spread_methood(SpreadMethod spread); static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread);
static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops); static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops);
static void to_plutovg_path(plutovg_t* pluto, const Path& path); static void to_plutovg_path(plutovg_t* pluto, const Path& path);
@ -59,7 +59,7 @@ Canvas::~Canvas()
void Canvas::setColor(const Color& color) void Canvas::setColor(const Color& color)
{ {
plutovg_set_source_rgba(pluto, color.r, color.g, color.b, color.a); plutovg_set_source_rgba(pluto, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0);
} }
void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const GradientStops& stops, SpreadMethod spread, const Transform& transform) void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const GradientStops& stops, SpreadMethod spread, const Transform& transform)
@ -67,7 +67,7 @@ void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const
auto gradient = plutovg_gradient_create_linear(x1, y1, x2, y2); auto gradient = plutovg_gradient_create_linear(x1, y1, x2, y2);
auto matrix = to_plutovg_matrix(transform); auto matrix = to_plutovg_matrix(transform);
to_plutovg_stops(gradient, stops); to_plutovg_stops(gradient, stops);
plutovg_gradient_set_spread(gradient, to_plutovg_spread_methood(spread)); plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
plutovg_gradient_set_matrix(gradient, &matrix); plutovg_gradient_set_matrix(gradient, &matrix);
plutovg_set_source_gradient(pluto, gradient); plutovg_set_source_gradient(pluto, gradient);
plutovg_gradient_destroy(gradient); plutovg_gradient_destroy(gradient);
@ -78,7 +78,7 @@ void Canvas::setRadialGradient(double cx, double cy, double r, double fx, double
auto gradient = plutovg_gradient_create_radial(cx, cy, r, fx, fy, 0); auto gradient = plutovg_gradient_create_radial(cx, cy, r, fx, fy, 0);
auto matrix = to_plutovg_matrix(transform); auto matrix = to_plutovg_matrix(transform);
to_plutovg_stops(gradient, stops); to_plutovg_stops(gradient, stops);
plutovg_gradient_set_spread(gradient, to_plutovg_spread_methood(spread)); plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
plutovg_gradient_set_matrix(gradient, &matrix); plutovg_gradient_set_matrix(gradient, &matrix);
plutovg_set_source_gradient(pluto, gradient); plutovg_set_source_gradient(pluto, gradient);
plutovg_gradient_destroy(gradient); plutovg_gradient_destroy(gradient);
@ -227,7 +227,7 @@ plutovg_line_join_t to_plutovg_line_join(LineJoin join)
return join == LineJoin::Miter ? plutovg_line_join_miter : join == LineJoin::Round ? plutovg_line_join_round : plutovg_line_join_bevel; return join == LineJoin::Miter ? plutovg_line_join_miter : join == LineJoin::Round ? plutovg_line_join_round : plutovg_line_join_bevel;
} }
static plutovg_spread_method_t to_plutovg_spread_methood(SpreadMethod spread) static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread)
{ {
return spread == SpreadMethod::Pad ? plutovg_spread_method_pad : spread == SpreadMethod::Reflect ? plutovg_spread_method_reflect : plutovg_spread_method_repeat; return spread == SpreadMethod::Pad ? plutovg_spread_method_pad : spread == SpreadMethod::Reflect ? plutovg_spread_method_reflect : plutovg_spread_method_repeat;
} }
@ -238,7 +238,7 @@ static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops&
{ {
auto offset = std::get<0>(stop); auto offset = std::get<0>(stop);
auto& color = std::get<1>(stop); auto& color = std::get<1>(stop);
plutovg_gradient_add_stop_rgba(gradient, offset, color.r, color.g, color.b, color.a); plutovg_gradient_add_stop_rgba(gradient, offset, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0);
} }
} }

View file

@ -5,13 +5,13 @@
namespace lunasvg { namespace lunasvg {
ClipPathElement::ClipPathElement() ClipPathElement::ClipPathElement()
: GraphicsElement(ElementId::ClipPath) : GraphicsElement(ElementID::ClipPath)
{ {
} }
Units ClipPathElement::clipPathUnits() const Units ClipPathElement::clipPathUnits() const
{ {
auto& value = get(PropertyId::ClipPathUnits); auto& value = get(PropertyID::ClipPathUnits);
return Parser::parseUnits(value, Units::UserSpaceOnUse); return Parser::parseUnits(value, Units::UserSpaceOnUse);
} }

View file

@ -3,7 +3,7 @@
namespace lunasvg { namespace lunasvg {
DefsElement::DefsElement() DefsElement::DefsElement()
: GraphicsElement(ElementId::Defs) : GraphicsElement(ElementID::Defs)
{ {
} }

View file

@ -4,7 +4,7 @@
namespace lunasvg { namespace lunasvg {
void PropertyList::set(PropertyId id, const std::string& value, int specificity) void PropertyList::set(PropertyID id, const std::string& value, int specificity)
{ {
auto property = get(id); auto property = get(id);
if(property == nullptr) if(property == nullptr)
@ -21,7 +21,7 @@ void PropertyList::set(PropertyId id, const std::string& value, int specificity)
property->value = value; property->value = value;
} }
Property* PropertyList::get(PropertyId id) const Property* PropertyList::get(PropertyID id) const
{ {
auto data = m_properties.data(); auto data = m_properties.data();
auto end = data + m_properties.size(); auto end = data + m_properties.size();
@ -59,19 +59,19 @@ std::unique_ptr<Node> TextNode::clone() const
return std::move(node); return std::move(node);
} }
Element::Element(ElementId id) Element::Element(ElementID id)
: id(id) : id(id)
{ {
} }
void Element::set(PropertyId id, const std::string& value, int specificity) void Element::set(PropertyID id, const std::string& value, int specificity)
{ {
properties.set(id, value, specificity); properties.set(id, value, specificity);
} }
static const std::string EmptyString; static const std::string EmptyString;
const std::string& Element::get(PropertyId id) const const std::string& Element::get(PropertyID id) const
{ {
auto property = properties.get(id); auto property = properties.get(id);
if(property == nullptr) if(property == nullptr)
@ -82,7 +82,7 @@ const std::string& Element::get(PropertyId id) const
static const std::string InheritString{"inherit"}; static const std::string InheritString{"inherit"};
const std::string& Element::find(PropertyId id) const const std::string& Element::find(PropertyID id) const
{ {
auto element = this; auto element = this;
do { do {
@ -95,12 +95,12 @@ const std::string& Element::find(PropertyId id) const
return EmptyString; return EmptyString;
} }
bool Element::has(PropertyId id) const bool Element::has(PropertyID id) const
{ {
return properties.get(id); return properties.get(id);
} }
Element* Element::previousSibling() const Element* Element::previousElement() const
{ {
if(parent == nullptr) if(parent == nullptr)
return nullptr; return nullptr;
@ -122,7 +122,7 @@ Element* Element::previousSibling() const
return nullptr; return nullptr;
} }
Element* Element::nextSibling() const Element* Element::nextElement() const
{ {
if(parent == nullptr) if(parent == nullptr)
return nullptr; return nullptr;
@ -162,15 +162,15 @@ Rect Element::currentViewport() const
if(parent == nullptr) if(parent == nullptr)
{ {
auto element = static_cast<const SVGElement*>(this); auto element = static_cast<const SVGElement*>(this);
if(element->has(PropertyId::ViewBox)) if(element->has(PropertyID::ViewBox))
return element->viewBox(); return element->viewBox();
return Rect{0, 0, 300, 150}; return Rect{0, 0, 300, 150};
} }
if(parent->id == ElementId::Svg) if(parent->id == ElementID::Svg)
{ {
auto element = static_cast<SVGElement*>(parent); auto element = static_cast<SVGElement*>(parent);
if(element->has(PropertyId::ViewBox)) if(element->has(PropertyID::ViewBox))
return element->viewBox(); return element->viewBox();
LengthContext lengthContext(element); LengthContext lengthContext(element);

View file

@ -8,7 +8,7 @@
namespace lunasvg { namespace lunasvg {
enum class ElementId enum class ElementID
{ {
Unknown = 0, Unknown = 0,
Star, Star,
@ -35,7 +35,7 @@ enum class ElementId
Use Use
}; };
enum class PropertyId enum class PropertyID
{ {
Unknown = 0, Unknown = 0,
Class, Class,
@ -108,7 +108,7 @@ enum class PropertyId
struct Property struct Property
{ {
PropertyId id; PropertyID id;
std::string value; std::string value;
int specificity; int specificity;
}; };
@ -118,10 +118,11 @@ class PropertyList
public: public:
PropertyList() = default; PropertyList() = default;
void set(PropertyId id, const std::string& value, int specificity); void set(PropertyID id, const std::string& value, int specificity);
Property* get(PropertyId id) const; Property* get(PropertyID id) const;
void add(const Property& property); void add(const Property& property);
void add(const PropertyList& properties); void add(const PropertyList& properties);
void clear() { m_properties.clear(); }
private: private:
std::vector<Property> m_properties; std::vector<Property> m_properties;
@ -164,15 +165,15 @@ using NodeList = std::list<std::unique_ptr<Node>>;
class Element : public Node class Element : public Node
{ {
public: public:
Element(ElementId id); Element(ElementID id);
void set(PropertyId id, const std::string& value, int specificity); void set(PropertyID id, const std::string& value, int specificity);
const std::string& get(PropertyId id) const; const std::string& get(PropertyID id) const;
const std::string& find(PropertyId id) const; const std::string& find(PropertyID id) const;
bool has(PropertyId id) const; bool has(PropertyID id) const;
Element* previousSibling() const; Element* previousElement() const;
Element* nextSibling() const; Element* nextElement() const;
Node* addChild(std::unique_ptr<Node> child); Node* addChild(std::unique_ptr<Node> child);
void layoutChildren(LayoutContext* context, LayoutContainer* current) const; void layoutChildren(LayoutContext* context, LayoutContainer* current) const;
Rect currentViewport() const; Rect currentViewport() const;
@ -208,7 +209,7 @@ public:
} }
public: public:
ElementId id; ElementID id;
NodeList children; NodeList children;
PropertyList properties; PropertyList properties;
}; };

View file

@ -4,7 +4,7 @@
namespace lunasvg { namespace lunasvg {
GElement::GElement() GElement::GElement()
: GraphicsElement(ElementId::G) : GraphicsElement(ElementID::G)
{ {
} }

View file

@ -6,7 +6,7 @@
namespace lunasvg { namespace lunasvg {
GeometryElement::GeometryElement(ElementId id) GeometryElement::GeometryElement(ElementID id)
: GraphicsElement(id) : GraphicsElement(id)
{ {
} }
@ -35,13 +35,13 @@ void GeometryElement::layout(LayoutContext* context, LayoutContainer* current) c
} }
PathElement::PathElement() PathElement::PathElement()
: GeometryElement(ElementId::Path) : GeometryElement(ElementID::Path)
{ {
} }
Path PathElement::d() const Path PathElement::d() const
{ {
auto& value = get(PropertyId::D); auto& value = get(PropertyID::D);
return Parser::parsePath(value); return Parser::parsePath(value);
} }
@ -55,19 +55,19 @@ std::unique_ptr<Node> PathElement::clone() const
return cloneElement<PathElement>(); return cloneElement<PathElement>();
} }
PolyElement::PolyElement(ElementId id) PolyElement::PolyElement(ElementID id)
: GeometryElement(id) : GeometryElement(id)
{ {
} }
PointList PolyElement::points() const PointList PolyElement::points() const
{ {
auto& value = get(PropertyId::Points); auto& value = get(PropertyID::Points);
return Parser::parsePointList(value); return Parser::parsePointList(value);
} }
PolygonElement::PolygonElement() PolygonElement::PolygonElement()
: PolyElement(ElementId::Polygon) : PolyElement(ElementID::Polygon)
{ {
} }
@ -92,7 +92,7 @@ std::unique_ptr<Node> PolygonElement::clone() const
} }
PolylineElement::PolylineElement() PolylineElement::PolylineElement()
: PolyElement(ElementId::Polyline) : PolyElement(ElementID::Polyline)
{ {
} }
@ -116,25 +116,25 @@ std::unique_ptr<Node> PolylineElement::clone() const
} }
CircleElement::CircleElement() CircleElement::CircleElement()
: GeometryElement(ElementId::Circle) : GeometryElement(ElementID::Circle)
{ {
} }
Length CircleElement::cx() const Length CircleElement::cx() const
{ {
auto& value = get(PropertyId::Cx); auto& value = get(PropertyID::Cx);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length CircleElement::cy() const Length CircleElement::cy() const
{ {
auto& value = get(PropertyId::Cy); auto& value = get(PropertyID::Cy);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length CircleElement::r() const Length CircleElement::r() const
{ {
auto& value = get(PropertyId::R); auto& value = get(PropertyID::R);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
@ -160,31 +160,31 @@ std::unique_ptr<Node> CircleElement::clone() const
} }
EllipseElement::EllipseElement() EllipseElement::EllipseElement()
: GeometryElement(ElementId::Ellipse) : GeometryElement(ElementID::Ellipse)
{ {
} }
Length EllipseElement::cx() const Length EllipseElement::cx() const
{ {
auto& value = get(PropertyId::Cx); auto& value = get(PropertyID::Cx);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length EllipseElement::cy() const Length EllipseElement::cy() const
{ {
auto& value = get(PropertyId::Cy); auto& value = get(PropertyID::Cy);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length EllipseElement::rx() const Length EllipseElement::rx() const
{ {
auto& value = get(PropertyId::Rx); auto& value = get(PropertyID::Rx);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
Length EllipseElement::ry() const Length EllipseElement::ry() const
{ {
auto& value = get(PropertyId::Ry); auto& value = get(PropertyID::Ry);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
@ -212,31 +212,31 @@ std::unique_ptr<Node> EllipseElement::clone() const
} }
LineElement::LineElement() LineElement::LineElement()
: GeometryElement(ElementId::Line) : GeometryElement(ElementID::Line)
{ {
} }
Length LineElement::x1() const Length LineElement::x1() const
{ {
auto& value = get(PropertyId::X1); auto& value = get(PropertyID::X1);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length LineElement::y1() const Length LineElement::y1() const
{ {
auto& value = get(PropertyId::Y1); auto& value = get(PropertyID::Y1);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length LineElement::x2() const Length LineElement::x2() const
{ {
auto& value = get(PropertyId::X2); auto& value = get(PropertyID::X2);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length LineElement::y2() const Length LineElement::y2() const
{ {
auto& value = get(PropertyId::Y2); auto& value = get(PropertyID::Y2);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
@ -260,43 +260,43 @@ std::unique_ptr<Node> LineElement::clone() const
} }
RectElement::RectElement() RectElement::RectElement()
: GeometryElement(ElementId::Rect) : GeometryElement(ElementID::Rect)
{ {
} }
Length RectElement::x() const Length RectElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length RectElement::y() const Length RectElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length RectElement::rx() const Length RectElement::rx() const
{ {
auto& value = get(PropertyId::Rx); auto& value = get(PropertyID::Rx);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown); return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
} }
Length RectElement::ry() const Length RectElement::ry() const
{ {
auto& value = get(PropertyId::Ry); auto& value = get(PropertyID::Ry);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown); return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
} }
Length RectElement::width() const Length RectElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
Length RectElement::height() const Length RectElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }

View file

@ -10,7 +10,7 @@ class LayoutShape;
class GeometryElement : public GraphicsElement class GeometryElement : public GraphicsElement
{ {
public: public:
GeometryElement(ElementId id); GeometryElement(ElementID id);
bool isGeometry() const { return true; } bool isGeometry() const { return true; }
virtual void layout(LayoutContext* context, LayoutContainer* current) const; virtual void layout(LayoutContext* context, LayoutContainer* current) const;
@ -31,7 +31,7 @@ public:
class PolyElement : public GeometryElement class PolyElement : public GeometryElement
{ {
public: public:
PolyElement(ElementId id); PolyElement(ElementID id);
PointList points() const; PointList points() const;
}; };

View file

@ -3,14 +3,14 @@
namespace lunasvg { namespace lunasvg {
GraphicsElement::GraphicsElement(ElementId id) GraphicsElement::GraphicsElement(ElementID id)
: StyledElement(id) : StyledElement(id)
{ {
} }
Transform GraphicsElement::transform() const Transform GraphicsElement::transform() const
{ {
auto& value = get(PropertyId::Transform); auto& value = get(PropertyID::Transform);
return Parser::parseTransform(value); return Parser::parseTransform(value);
} }

View file

@ -8,7 +8,7 @@ namespace lunasvg {
class GraphicsElement : public StyledElement class GraphicsElement : public StyledElement
{ {
public: public:
GraphicsElement(ElementId id); GraphicsElement(ElementID id);
Transform transform() const; Transform transform() const;
}; };

View file

@ -479,14 +479,14 @@ void RenderState::endGroup(RenderState& state, const BlendInfo& info)
state.canvas->blend(canvas.get(), BlendMode::Src_Over, m_mode == RenderMode::Display ? info.opacity : 1.0); state.canvas->blend(canvas.get(), BlendMode::Src_Over, m_mode == RenderMode::Display ? info.opacity : 1.0);
} }
LayoutContext::LayoutContext(const ParseDocument* document, LayoutSymbol* root) LayoutContext::LayoutContext(const TreeBuilder* builder, LayoutSymbol* root)
: m_document(document), m_root(root) : m_builder(builder), m_root(root)
{ {
} }
Element* LayoutContext::getElementById(const std::string& id) const Element* LayoutContext::getElementById(const std::string& id) const
{ {
return m_document->getElementById(id); return m_builder->getElementById(id);
} }
LayoutObject* LayoutContext::getResourcesById(const std::string& id) const LayoutObject* LayoutContext::getResourcesById(const std::string& id) const
@ -517,7 +517,7 @@ LayoutMask* LayoutContext::getMasker(const std::string& id)
return static_cast<LayoutMask*>(ref); return static_cast<LayoutMask*>(ref);
auto element = getElementById(id); auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::Mask) if(element == nullptr || element->id != ElementID::Mask)
return nullptr; return nullptr;
auto masker = static_cast<MaskElement*>(element)->getMasker(this); auto masker = static_cast<MaskElement*>(element)->getMasker(this);
@ -534,7 +534,7 @@ LayoutClipPath* LayoutContext::getClipper(const std::string& id)
return static_cast<LayoutClipPath*>(ref); return static_cast<LayoutClipPath*>(ref);
auto element = getElementById(id); auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::ClipPath) if(element == nullptr || element->id != ElementID::ClipPath)
return nullptr; return nullptr;
auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this); auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this);
@ -551,7 +551,7 @@ LayoutMarker* LayoutContext::getMarker(const std::string& id)
return static_cast<LayoutMarker*>(ref); return static_cast<LayoutMarker*>(ref);
auto element = getElementById(id); auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::Marker) if(element == nullptr || element->id != ElementID::Marker)
return nullptr; return nullptr;
auto marker = static_cast<MarkerElement*>(element)->getMarker(this); auto marker = static_cast<MarkerElement*>(element)->getMarker(this);

View file

@ -346,14 +346,14 @@ private:
RenderMode m_mode; RenderMode m_mode;
}; };
class ParseDocument; class TreeBuilder;
class StyledElement; class StyledElement;
class GeometryElement; class GeometryElement;
class LayoutContext class LayoutContext
{ {
public: public:
LayoutContext(const ParseDocument* document, LayoutSymbol* root); LayoutContext(const TreeBuilder* builder, LayoutSymbol* root);
Element* getElementById(const std::string& id) const; Element* getElementById(const std::string& id) const;
LayoutObject* getResourcesById(const std::string& id) const; LayoutObject* getResourcesById(const std::string& id) const;
@ -373,7 +373,7 @@ public:
bool hasReference(const Element* element) const; bool hasReference(const Element* element) const;
private: private:
const ParseDocument* m_document; const TreeBuilder* m_builder;
LayoutSymbol* m_root; LayoutSymbol* m_root;
std::map<std::string, LayoutObject*> m_resourcesCache; std::map<std::string, LayoutObject*> m_resourcesCache;
std::set<const Element*> m_references; std::set<const Element*> m_references;

View file

@ -292,11 +292,11 @@ std::unique_ptr<Document> Document::loadFromData(const std::string& string)
std::unique_ptr<Document> Document::loadFromData(const char* data, std::size_t size) std::unique_ptr<Document> Document::loadFromData(const char* data, std::size_t size)
{ {
ParseDocument parser; TreeBuilder builder;
if(!parser.parse(data, size)) if(!builder.parse(data, size))
return nullptr; return nullptr;
auto root = parser.layout(); auto root = builder.build();
if(!root || root->children.empty()) if(!root || root->children.empty())
return nullptr; return nullptr;

View file

@ -5,55 +5,55 @@
namespace lunasvg { namespace lunasvg {
MarkerElement::MarkerElement() MarkerElement::MarkerElement()
: StyledElement(ElementId::Marker) : StyledElement(ElementID::Marker)
{ {
} }
Length MarkerElement::refX() const Length MarkerElement::refX() const
{ {
auto& value = get(PropertyId::RefX); auto& value = get(PropertyID::RefX);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length MarkerElement::refY() const Length MarkerElement::refY() const
{ {
auto& value = get(PropertyId::RefY); auto& value = get(PropertyID::RefY);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length MarkerElement::markerWidth() const Length MarkerElement::markerWidth() const
{ {
auto& value = get(PropertyId::MarkerWidth); auto& value = get(PropertyID::MarkerWidth);
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
} }
Length MarkerElement::markerHeight() const Length MarkerElement::markerHeight() const
{ {
auto& value = get(PropertyId::MarkerHeight); auto& value = get(PropertyID::MarkerHeight);
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
} }
Angle MarkerElement::orient() const Angle MarkerElement::orient() const
{ {
auto& value = get(PropertyId::Orient); auto& value = get(PropertyID::Orient);
return Parser::parseAngle(value); return Parser::parseAngle(value);
} }
MarkerUnits MarkerElement::markerUnits() const MarkerUnits MarkerElement::markerUnits() const
{ {
auto& value = get(PropertyId::MarkerUnits); auto& value = get(PropertyID::MarkerUnits);
return Parser::parseMarkerUnits(value); return Parser::parseMarkerUnits(value);
} }
Rect MarkerElement::viewBox() const Rect MarkerElement::viewBox() const
{ {
auto& value = get(PropertyId::ViewBox); auto& value = get(PropertyID::ViewBox);
return Parser::parseViewBox(value); return Parser::parseViewBox(value);
} }
PreserveAspectRatio MarkerElement::preserveAspectRatio() const PreserveAspectRatio MarkerElement::preserveAspectRatio() const
{ {
auto& value = get(PropertyId::PreserveAspectRatio); auto& value = get(PropertyID::PreserveAspectRatio);
return Parser::parsePreserveAspectRatio(value); return Parser::parsePreserveAspectRatio(value);
} }

View file

@ -5,43 +5,43 @@
namespace lunasvg { namespace lunasvg {
MaskElement::MaskElement() MaskElement::MaskElement()
: StyledElement(ElementId::Mask) : StyledElement(ElementID::Mask)
{ {
} }
Length MaskElement::x() const Length MaskElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent); return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
} }
Length MaskElement::y() const Length MaskElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent); return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
} }
Length MaskElement::width() const Length MaskElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
} }
Length MaskElement::height() const Length MaskElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
} }
Units MaskElement::maskUnits() const Units MaskElement::maskUnits() const
{ {
auto& value = get(PropertyId::MaskUnits); auto& value = get(PropertyID::MaskUnits);
return Parser::parseUnits(value, Units::ObjectBoundingBox); return Parser::parseUnits(value, Units::ObjectBoundingBox);
} }
Units MaskElement::maskContentUnits() const Units MaskElement::maskContentUnits() const
{ {
auto& value = get(PropertyId::MaskContentUnits); auto& value = get(PropertyID::MaskContentUnits);
return Parser::parseUnits(value, Units::UserSpaceOnUse); return Parser::parseUnits(value, Units::UserSpaceOnUse);
} }

View file

@ -7,37 +7,37 @@
namespace lunasvg { namespace lunasvg {
PaintElement::PaintElement(ElementId id) PaintElement::PaintElement(ElementID id)
: StyledElement(id) : StyledElement(id)
{ {
} }
GradientElement::GradientElement(ElementId id) GradientElement::GradientElement(ElementID id)
: PaintElement(id) : PaintElement(id)
{ {
} }
Transform GradientElement::gradientTransform() const Transform GradientElement::gradientTransform() const
{ {
auto& value = get(PropertyId::GradientTransform); auto& value = get(PropertyID::GradientTransform);
return Parser::parseTransform(value); return Parser::parseTransform(value);
} }
SpreadMethod GradientElement::spreadMethod() const SpreadMethod GradientElement::spreadMethod() const
{ {
auto& value = get(PropertyId::SpreadMethod); auto& value = get(PropertyID::SpreadMethod);
return Parser::parseSpreadMethod(value); return Parser::parseSpreadMethod(value);
} }
Units GradientElement::gradientUnits() const Units GradientElement::gradientUnits() const
{ {
auto& value = get(PropertyId::GradientUnits); auto& value = get(PropertyID::GradientUnits);
return Parser::parseUnits(value, Units::ObjectBoundingBox); return Parser::parseUnits(value, Units::ObjectBoundingBox);
} }
std::string GradientElement::href() const std::string GradientElement::href() const
{ {
auto& value = get(PropertyId::Href); auto& value = get(PropertyID::Href);
return Parser::parseHref(value); return Parser::parseHref(value);
} }
@ -50,7 +50,7 @@ GradientStops GradientElement::buildGradientStops() const
if(child->isText()) if(child->isText())
continue; continue;
auto element = static_cast<Element*>(child.get()); auto element = static_cast<Element*>(child.get());
if(element->id != ElementId::Stop) if(element->id != ElementID::Stop)
continue; continue;
auto stop = static_cast<StopElement*>(element); auto stop = static_cast<StopElement*>(element);
auto offset = std::max(prevOffset, stop->offset()); auto offset = std::max(prevOffset, stop->offset());
@ -62,31 +62,31 @@ GradientStops GradientElement::buildGradientStops() const
} }
LinearGradientElement::LinearGradientElement() LinearGradientElement::LinearGradientElement()
: GradientElement(ElementId::LinearGradient) : GradientElement(ElementID::LinearGradient)
{ {
} }
Length LinearGradientElement::x1() const Length LinearGradientElement::x1() const
{ {
auto& value = get(PropertyId::X1); auto& value = get(PropertyID::X1);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length LinearGradientElement::y1() const Length LinearGradientElement::y1() const
{ {
auto& value = get(PropertyId::Y1); auto& value = get(PropertyID::Y1);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length LinearGradientElement::x2() const Length LinearGradientElement::x2() const
{ {
auto& value = get(PropertyId::X2); auto& value = get(PropertyID::X2);
return Parser::parseLength(value, AllowNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, AllowNegativeLengths, Length::HundredPercent);
} }
Length LinearGradientElement::y2() const Length LinearGradientElement::y2() const
{ {
auto& value = get(PropertyId::Y2); auto& value = get(PropertyID::Y2);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
@ -98,30 +98,30 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
while(true) while(true)
{ {
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform)) if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
attributes.setGradientTransform(current->gradientTransform()); attributes.setGradientTransform(current->gradientTransform());
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod)) if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
attributes.setSpreadMethod(current->spreadMethod()); attributes.setSpreadMethod(current->spreadMethod());
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits)) if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
attributes.setGradientUnits(current->gradientUnits()); attributes.setGradientUnits(current->gradientUnits());
if(!attributes.hasGradientStops()) if(!attributes.hasGradientStops())
attributes.setGradientStops(current->buildGradientStops()); attributes.setGradientStops(current->buildGradientStops());
if(current->id == ElementId::LinearGradient) if(current->id == ElementID::LinearGradient)
{ {
auto element = static_cast<const LinearGradientElement*>(current); auto element = static_cast<const LinearGradientElement*>(current);
if(!attributes.hasX1() && element->has(PropertyId::X1)) if(!attributes.hasX1() && element->has(PropertyID::X1))
attributes.setX1(element->x1()); attributes.setX1(element->x1());
if(!attributes.hasY1() && element->has(PropertyId::Y1)) if(!attributes.hasY1() && element->has(PropertyID::Y1))
attributes.setY1(element->y1()); attributes.setY1(element->y1());
if(!attributes.hasX2() && element->has(PropertyId::X2)) if(!attributes.hasX2() && element->has(PropertyID::X2))
attributes.setX2(element->x2()); attributes.setX2(element->x2());
if(!attributes.hasY2() && element->has(PropertyId::Y2)) if(!attributes.hasY2() && element->has(PropertyID::Y2))
attributes.setY2(element->y2()); attributes.setY2(element->y2());
} }
auto ref = context->getElementById(current->href()); auto ref = context->getElementById(current->href());
if(!ref || !(ref->id == ElementId::LinearGradient || ref->id == ElementId::RadialGradient)) if(!ref || !(ref->id == ElementID::LinearGradient || ref->id == ElementID::RadialGradient))
break; break;
processedGradients.insert(current); processedGradients.insert(current);
@ -164,37 +164,37 @@ std::unique_ptr<Node> LinearGradientElement::clone() const
} }
RadialGradientElement::RadialGradientElement() RadialGradientElement::RadialGradientElement()
: GradientElement(ElementId::RadialGradient) : GradientElement(ElementID::RadialGradient)
{ {
} }
Length RadialGradientElement::cx() const Length RadialGradientElement::cx() const
{ {
auto& value = get(PropertyId::Cx); auto& value = get(PropertyID::Cx);
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent); return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
} }
Length RadialGradientElement::cy() const Length RadialGradientElement::cy() const
{ {
auto& value = get(PropertyId::Cy); auto& value = get(PropertyID::Cy);
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent); return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
} }
Length RadialGradientElement::r() const Length RadialGradientElement::r() const
{ {
auto& value = get(PropertyId::R); auto& value = get(PropertyID::R);
return Parser::parseLength(value, ForbidNegativeLengths, Length::FiftyPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::FiftyPercent);
} }
Length RadialGradientElement::fx() const Length RadialGradientElement::fx() const
{ {
auto& value = get(PropertyId::Fx); auto& value = get(PropertyID::Fx);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length RadialGradientElement::fy() const Length RadialGradientElement::fy() const
{ {
auto& value = get(PropertyId::Fy); auto& value = get(PropertyID::Fy);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
@ -206,32 +206,32 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
while(true) while(true)
{ {
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform)) if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
attributes.setGradientTransform(current->gradientTransform()); attributes.setGradientTransform(current->gradientTransform());
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod)) if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
attributes.setSpreadMethod(current->spreadMethod()); attributes.setSpreadMethod(current->spreadMethod());
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits)) if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
attributes.setGradientUnits(current->gradientUnits()); attributes.setGradientUnits(current->gradientUnits());
if(!attributes.hasGradientStops()) if(!attributes.hasGradientStops())
attributes.setGradientStops(current->buildGradientStops()); attributes.setGradientStops(current->buildGradientStops());
if(current->id == ElementId::RadialGradient) if(current->id == ElementID::RadialGradient)
{ {
auto element = static_cast<const RadialGradientElement*>(current); auto element = static_cast<const RadialGradientElement*>(current);
if(!attributes.hasCx() && element->has(PropertyId::Cx)) if(!attributes.hasCx() && element->has(PropertyID::Cx))
attributes.setCx(element->cx()); attributes.setCx(element->cx());
if(!attributes.hasCy() && element->has(PropertyId::Cy)) if(!attributes.hasCy() && element->has(PropertyID::Cy))
attributes.setCy(element->cy()); attributes.setCy(element->cy());
if(!attributes.hasR() && element->has(PropertyId::R)) if(!attributes.hasR() && element->has(PropertyID::R))
attributes.setR(element->r()); attributes.setR(element->r());
if(!attributes.hasFx() && element->has(PropertyId::Fx)) if(!attributes.hasFx() && element->has(PropertyID::Fx))
attributes.setFx(element->fx()); attributes.setFx(element->fx());
if(!attributes.hasFy() && element->has(PropertyId::Fy)) if(!attributes.hasFy() && element->has(PropertyID::Fy))
attributes.setFy(element->fy()); attributes.setFy(element->fy());
} }
auto ref = context->getElementById(current->href()); auto ref = context->getElementById(current->href());
if(!ref || !(ref->id == ElementId::LinearGradient || ref->id == ElementId::RadialGradient)) if(!ref || !(ref->id == ElementID::LinearGradient || ref->id == ElementID::RadialGradient))
break; break;
processedGradients.insert(current); processedGradients.insert(current);
@ -278,67 +278,67 @@ std::unique_ptr<Node> RadialGradientElement::clone() const
} }
PatternElement::PatternElement() PatternElement::PatternElement()
: PaintElement(ElementId::Pattern) : PaintElement(ElementID::Pattern)
{ {
} }
Length PatternElement::x() const Length PatternElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length PatternElement::y() const Length PatternElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length PatternElement::width() const Length PatternElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
Length PatternElement::height() const Length PatternElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero); return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
} }
Transform PatternElement::patternTransform() const Transform PatternElement::patternTransform() const
{ {
auto& value = get(PropertyId::PatternTransform); auto& value = get(PropertyID::PatternTransform);
return Parser::parseTransform(value); return Parser::parseTransform(value);
} }
Units PatternElement::patternUnits() const Units PatternElement::patternUnits() const
{ {
auto& value = get(PropertyId::PatternUnits); auto& value = get(PropertyID::PatternUnits);
return Parser::parseUnits(value, Units::ObjectBoundingBox); return Parser::parseUnits(value, Units::ObjectBoundingBox);
} }
Units PatternElement::patternContentUnits() const Units PatternElement::patternContentUnits() const
{ {
auto& value = get(PropertyId::PatternContentUnits); auto& value = get(PropertyID::PatternContentUnits);
return Parser::parseUnits(value, Units::UserSpaceOnUse); return Parser::parseUnits(value, Units::UserSpaceOnUse);
} }
Rect PatternElement::viewBox() const Rect PatternElement::viewBox() const
{ {
auto& value = get(PropertyId::ViewBox); auto& value = get(PropertyID::ViewBox);
return Parser::parseViewBox(value); return Parser::parseViewBox(value);
} }
PreserveAspectRatio PatternElement::preserveAspectRatio() const PreserveAspectRatio PatternElement::preserveAspectRatio() const
{ {
auto& value = get(PropertyId::PreserveAspectRatio); auto& value = get(PropertyID::PreserveAspectRatio);
return Parser::parsePreserveAspectRatio(value); return Parser::parsePreserveAspectRatio(value);
} }
std::string PatternElement::href() const std::string PatternElement::href() const
{ {
auto& value = get(PropertyId::Href); auto& value = get(PropertyID::Href);
return Parser::parseHref(value); return Parser::parseHref(value);
} }
@ -353,29 +353,29 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
while(true) while(true)
{ {
if(!attributes.hasX() && current->has(PropertyId::X)) if(!attributes.hasX() && current->has(PropertyID::X))
attributes.setX(current->x()); attributes.setX(current->x());
if(!attributes.hasY() && current->has(PropertyId::Y)) if(!attributes.hasY() && current->has(PropertyID::Y))
attributes.setY(current->y()); attributes.setY(current->y());
if(!attributes.hasWidth() && current->has(PropertyId::Width)) if(!attributes.hasWidth() && current->has(PropertyID::Width))
attributes.setWidth(current->width()); attributes.setWidth(current->width());
if(!attributes.hasHeight() && current->has(PropertyId::Height)) if(!attributes.hasHeight() && current->has(PropertyID::Height))
attributes.setHeight(current->height()); attributes.setHeight(current->height());
if(!attributes.hasPatternTransform() && current->has(PropertyId::PatternTransform)) if(!attributes.hasPatternTransform() && current->has(PropertyID::PatternTransform))
attributes.setPatternTransform(current->patternTransform()); attributes.setPatternTransform(current->patternTransform());
if(!attributes.hasPatternUnits() && current->has(PropertyId::PatternUnits)) if(!attributes.hasPatternUnits() && current->has(PropertyID::PatternUnits))
attributes.setPatternUnits(current->patternUnits()); attributes.setPatternUnits(current->patternUnits());
if(!attributes.hasPatternContentUnits() && current->has(PropertyId::PatternContentUnits)) if(!attributes.hasPatternContentUnits() && current->has(PropertyID::PatternContentUnits))
attributes.setPatternContentUnits(current->patternContentUnits()); attributes.setPatternContentUnits(current->patternContentUnits());
if(!attributes.hasViewBox() && current->has(PropertyId::ViewBox)) if(!attributes.hasViewBox() && current->has(PropertyID::ViewBox))
attributes.setViewBox(current->viewBox()); attributes.setViewBox(current->viewBox());
if(!attributes.hasPreserveAspectRatio() && current->has(PropertyId::PreserveAspectRatio)) if(!attributes.hasPreserveAspectRatio() && current->has(PropertyID::PreserveAspectRatio))
attributes.setPreserveAspectRatio(current->preserveAspectRatio()); attributes.setPreserveAspectRatio(current->preserveAspectRatio());
if(!attributes.hasPatternContentElement() && current->children.size()) if(!attributes.hasPatternContentElement() && current->children.size())
attributes.setPatternContentElement(current); attributes.setPatternContentElement(current);
auto ref = context->getElementById(current->href()); auto ref = context->getElementById(current->href());
if(!ref || ref->id != ElementId::Pattern) if(!ref || ref->id != ElementID::Pattern)
break; break;
processedPatterns.insert(current); processedPatterns.insert(current);
@ -413,7 +413,7 @@ std::unique_ptr<Node> PatternElement::clone() const
} }
SolidColorElement::SolidColorElement() SolidColorElement::SolidColorElement()
: PaintElement(ElementId::SolidColor) : PaintElement(ElementID::SolidColor)
{ {
} }
@ -421,7 +421,7 @@ std::unique_ptr<LayoutObject> SolidColorElement::getPainter(LayoutContext*) cons
{ {
auto solid = std::make_unique<LayoutSolidColor>(); auto solid = std::make_unique<LayoutSolidColor>();
solid->color = solid_color(); solid->color = solid_color();
solid->color.a = solid_opacity(); solid->color.combine(solid_opacity());
return std::move(solid); return std::move(solid);
} }

View file

@ -11,7 +11,7 @@ class LayoutObject;
class PaintElement : public StyledElement class PaintElement : public StyledElement
{ {
public: public:
PaintElement(ElementId id); PaintElement(ElementID id);
bool isPaint() const { return true; } bool isPaint() const { return true; }
virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0; virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0;
@ -20,7 +20,7 @@ public:
class GradientElement : public PaintElement class GradientElement : public PaintElement
{ {
public: public:
GradientElement(ElementId id); GradientElement(ElementID id);
Transform gradientTransform() const; Transform gradientTransform() const;
SpreadMethod spreadMethod() const; SpreadMethod spreadMethod() const;

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
#define PARSER_H #define PARSER_H
#include <map> #include <map>
#include <set>
#include "property.h" #include "property.h"
#include "element.h" #include "element.h"
@ -58,12 +59,15 @@ private:
static bool parseLength(const char*& ptr, const char* end, double& value, LengthUnits& units, LengthNegativeValuesMode mode); static bool parseLength(const char*& ptr, const char* end, double& value, LengthUnits& units, LengthNegativeValuesMode mode);
static bool parseNumberList(const char*& ptr, const char* end, double* values, int count); static bool parseNumberList(const char*& ptr, const char* end, double* values, int count);
static bool parseArcFlag(const char*& ptr, const char* end, bool& flag); static bool parseArcFlag(const char*& ptr, const char* end, bool& flag);
static bool parseColorComponent(const char*& ptr, const char* end, double& value); static bool parseColorComponent(const char*& ptr, const char* end, int& component);
static bool parseUrlFragment(const char*& ptr, const char* end, std::string& ref); static bool parseUrlFragment(const char*& ptr, const char* end, std::string& ref);
static bool parseTransform(const char*& ptr, const char* end, TransformType& type, double* values, int& count); static bool parseTransform(const char*& ptr, const char* end, TransformType& type, double* values, int& count);
}; };
struct Selector; struct SimpleSelector;
using Selector = std::vector<SimpleSelector>;
using SelectorList = std::vector<Selector>;
struct AttributeSelector struct AttributeSelector
{ {
@ -78,20 +82,19 @@ struct AttributeSelector
Contains Contains
}; };
PropertyId id{PropertyId::Unknown};
std::string value;
MatchType matchType{MatchType::None}; MatchType matchType{MatchType::None};
PropertyID id{PropertyID::Unknown};
std::string value;
}; };
using SelectorList = std::vector<Selector>; struct PseudoClassSelector
struct PseudoClass
{ {
enum class Type enum class Type
{ {
Unknown, Unknown,
Empty, Empty,
Root, Root,
Is,
Not, Not,
FirstChild, FirstChild,
LastChild, LastChild,
@ -102,7 +105,9 @@ struct PseudoClass
}; };
Type type{Type::Unknown}; Type type{Type::Unknown};
SelectorList notSelectors; int16_t a{0};
int16_t b{0};
SelectorList subSelectors;
}; };
struct SimpleSelector struct SimpleSelector
@ -115,16 +120,10 @@ struct SimpleSelector
InDirectAdjacent InDirectAdjacent
}; };
ElementId id{ElementId::Star};
std::vector<AttributeSelector> attributeSelectors;
std::vector<PseudoClass> pseudoClasses;
Combinator combinator{Combinator::Descendant}; Combinator combinator{Combinator::Descendant};
}; ElementID id{ElementID::Star};
std::vector<AttributeSelector> attributeSelectors;
struct Selector std::vector<PseudoClassSelector> pseudoClassSelectors;
{
std::vector<SimpleSelector> simpleSelectors;
int specificity{0};
}; };
struct Rule struct Rule
@ -133,21 +132,47 @@ struct Rule
PropertyList declarations; PropertyList declarations;
}; };
class RuleMatchContext class RuleData {
{
public: public:
RuleMatchContext(const std::vector<Rule>& rules); RuleData(const Selector& selector, const PropertyList& properties, uint32_t specificity, uint32_t position)
: m_selector(selector), m_properties(properties), m_specificity(specificity), m_position(position)
{}
const Selector& selector() const { return m_selector; }
const PropertyList& properties() const { return m_properties; }
const uint32_t& specificity() const { return m_specificity; }
const uint32_t& position() const { return m_position; }
bool match(const Element* element) const;
private:
bool matchSimpleSelector(const SimpleSelector& selector, const Element* element) const;
bool matchAttributeSelector(const AttributeSelector& selector, const Element* element) const;
bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element) const;
private:
Selector m_selector;
PropertyList m_properties;
uint32_t m_specificity;
uint32_t m_position;
};
inline bool operator<(const RuleData& a, const RuleData& b) { return std::tie(a.specificity(), a.position()) < std::tie(b.specificity(), b.position()); }
inline bool operator>(const RuleData& a, const RuleData& b) { return std::tie(a.specificity(), a.position()) > std::tie(b.specificity(), b.position()); }
class StyleSheet {
public:
StyleSheet() = default;
void parse(const std::string& content);
void add(const Rule& rule);
bool empty() const { return m_position == 0; }
std::vector<const PropertyList*> match(const Element* element) const; std::vector<const PropertyList*> match(const Element* element) const;
private: private:
bool selectorMatch(const Selector* selector, const Element* element) const; std::multiset<RuleData> m_rules;
bool simpleSelectorMatch(const SimpleSelector& selector, const Element* element) const; uint32_t m_position{0};
bool attributeSelectorMatch(const AttributeSelector& selector, const Element* element) const;
bool pseudoClassMatch(const PseudoClass& pseudo, const Element* element) const;
private:
std::multimap<int, std::pair<const Selector*, const PropertyList*>, std::less<int>> m_selectors;
}; };
class CSSParser class CSSParser
@ -155,35 +180,29 @@ class CSSParser
public: public:
CSSParser() = default; CSSParser() = default;
bool parseMore(const std::string& value); static bool parseSheet(StyleSheet* sheet, const std::string& value);
const std::vector<Rule>& rules() const { return m_rules; }
private: private:
bool parseAtRule(const char*& ptr, const char* end) const; static bool parseAtRule(const char*& ptr, const char* end);
bool parseRule(const char*& ptr, const char* end, Rule& rule) const; static bool parseRule(const char*& ptr, const char* end, Rule& rule);
bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) const; static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations) const; static bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations);
bool parseSelector(const char*& ptr, const char* end, Selector& selector) const; static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) const; static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
private:
std::vector<Rule> m_rules;
}; };
class LayoutSymbol; class LayoutSymbol;
class ParseDocument class TreeBuilder {
{
public: public:
ParseDocument(); TreeBuilder();
~ParseDocument(); ~TreeBuilder();
bool parse(const char* data, std::size_t size); bool parse(const char* data, std::size_t size);
SVGElement* rootElement() const { return m_rootElement.get(); } SVGElement* rootElement() const { return m_rootElement.get(); }
Element* getElementById(const std::string& id) const; Element* getElementById(const std::string& id) const;
std::unique_ptr<LayoutSymbol> layout() const; std::unique_ptr<LayoutSymbol> build() const;
private: private:
std::unique_ptr<SVGElement> m_rootElement; std::unique_ptr<SVGElement> m_rootElement;

View file

@ -2,21 +2,26 @@
#include "styledelement.h" #include "styledelement.h"
#include "lunasvg.h" #include "lunasvg.h"
#include <algorithm>
#include <cmath> #include <cmath>
namespace lunasvg { namespace lunasvg {
const Color Color::Black{0, 0, 0, 1}; const Color Color::Black(0xFF000000);
const Color Color::White{1, 1, 1, 1}; const Color Color::White(0xFFFFFFFF);
const Color Color::Red{1, 0, 0, 1}; const Color Color::Transparent(0x00000000);
const Color Color::Green{0, 1, 0, 1};
const Color Color::Blue{0, 0, 1, 1};
const Color Color::Yellow{1, 1, 0, 1};
const Color Color::Transparent{0, 0, 0, 0};
Color::Color(double r, double g, double b, double a) Color& Color::combine(double opacity)
: r(r), g(g), b(b), a(a)
{ {
*this = combined(opacity);
return *this;
}
Color Color::combined(double opacity) const
{
auto rgb = m_value & 0x00FFFFFF;
auto a = static_cast<int>(std::clamp(opacity * alpha(), 0.0, 255.0));
return Color(rgb | a << 24);
} }
Paint::Paint(const Color& color) Paint::Paint(const Color& color)

View file

@ -68,23 +68,27 @@ class Color
{ {
public: public:
Color() = default; Color() = default;
Color(double r, double g, double b, double a = 1); explicit Color(uint32_t value) : m_value(value) {}
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : m_value(a << 24 | r << 16 | g << 8 | b) {}
bool isNone() const { return a == 0.0; } uint8_t alpha() const { return (m_value >> 24) & 0xff; }
uint8_t red() const { return (m_value >> 16) & 0xff; }
uint8_t green() const { return (m_value >> 8) & 0xff; }
uint8_t blue() const { return (m_value >> 0) & 0xff; }
uint32_t value() const { return m_value; }
Color& combine(double opacity);
Color combined(double opacity) const;
bool isNone() const { return m_value == 0; }
static const Color Black; static const Color Black;
static const Color White; static const Color White;
static const Color Red;
static const Color Green;
static const Color Blue;
static const Color Yellow;
static const Color Transparent; static const Color Transparent;
public: private:
double r{0}; uint32_t m_value{0};
double g{0};
double b{0};
double a{1};
}; };
class Paint class Paint

View file

@ -4,20 +4,20 @@
namespace lunasvg { namespace lunasvg {
StopElement::StopElement() StopElement::StopElement()
: StyledElement(ElementId::Stop) : StyledElement(ElementID::Stop)
{ {
} }
double StopElement::offset() const double StopElement::offset() const
{ {
auto& value = get(PropertyId::Offset); auto& value = get(PropertyID::Offset);
return Parser::parseNumberPercentage(value, 0.0); return Parser::parseNumberPercentage(value, 0.0);
} }
Color StopElement::stopColorWithOpacity() const Color StopElement::stopColorWithOpacity() const
{ {
auto color = stop_color(); auto color = stop_color();
color.a = stop_opacity(); color.combine(stop_opacity());
return color; return color;
} }

View file

@ -3,164 +3,164 @@
namespace lunasvg { namespace lunasvg {
StyledElement::StyledElement(ElementId id) StyledElement::StyledElement(ElementID id)
: Element(id) : Element(id)
{ {
} }
Paint StyledElement::fill() const Paint StyledElement::fill() const
{ {
auto& value = find(PropertyId::Fill); auto& value = find(PropertyID::Fill);
return Parser::parsePaint(value, this, Color::Black); return Parser::parsePaint(value, this, Color::Black);
} }
Paint StyledElement::stroke() const Paint StyledElement::stroke() const
{ {
auto& value = find(PropertyId::Stroke); auto& value = find(PropertyID::Stroke);
return Parser::parsePaint(value, this, Color::Transparent); return Parser::parsePaint(value, this, Color::Transparent);
} }
Color StyledElement::color() const Color StyledElement::color() const
{ {
auto& value = find(PropertyId::Color); auto& value = find(PropertyID::Color);
return Parser::parseColor(value, this, Color::Black); return Parser::parseColor(value, this, Color::Black);
} }
Color StyledElement::stop_color() const Color StyledElement::stop_color() const
{ {
auto& value = find(PropertyId::Stop_Color); auto& value = find(PropertyID::Stop_Color);
return Parser::parseColor(value, this, Color::Black); return Parser::parseColor(value, this, Color::Black);
} }
Color StyledElement::solid_color() const Color StyledElement::solid_color() const
{ {
auto& value = find(PropertyId::Solid_Color); auto& value = find(PropertyID::Solid_Color);
return Parser::parseColor(value, this, Color::Black); return Parser::parseColor(value, this, Color::Black);
} }
double StyledElement::opacity() const double StyledElement::opacity() const
{ {
auto& value = get(PropertyId::Opacity); auto& value = get(PropertyID::Opacity);
return Parser::parseNumberPercentage(value, 1.0); return Parser::parseNumberPercentage(value, 1.0);
} }
double StyledElement::fill_opacity() const double StyledElement::fill_opacity() const
{ {
auto& value = find(PropertyId::Fill_Opacity); auto& value = find(PropertyID::Fill_Opacity);
return Parser::parseNumberPercentage(value, 1.0); return Parser::parseNumberPercentage(value, 1.0);
} }
double StyledElement::stroke_opacity() const double StyledElement::stroke_opacity() const
{ {
auto& value = find(PropertyId::Stroke_Opacity); auto& value = find(PropertyID::Stroke_Opacity);
return Parser::parseNumberPercentage(value, 1.0); return Parser::parseNumberPercentage(value, 1.0);
} }
double StyledElement::stop_opacity() const double StyledElement::stop_opacity() const
{ {
auto& value = find(PropertyId::Stop_Opacity); auto& value = find(PropertyID::Stop_Opacity);
return Parser::parseNumberPercentage(value, 1.0); return Parser::parseNumberPercentage(value, 1.0);
} }
double StyledElement::solid_opacity() const double StyledElement::solid_opacity() const
{ {
auto& value = find(PropertyId::Solid_Opacity); auto& value = find(PropertyID::Solid_Opacity);
return Parser::parseNumberPercentage(value, 1.0); return Parser::parseNumberPercentage(value, 1.0);
} }
double StyledElement::stroke_miterlimit() const double StyledElement::stroke_miterlimit() const
{ {
auto& value = find(PropertyId::Stroke_Miterlimit); auto& value = find(PropertyID::Stroke_Miterlimit);
return Parser::parseNumber(value, 4.0); return Parser::parseNumber(value, 4.0);
} }
Length StyledElement::stroke_width() const Length StyledElement::stroke_width() const
{ {
auto& value = find(PropertyId::Stroke_Width); auto& value = find(PropertyID::Stroke_Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::One); return Parser::parseLength(value, ForbidNegativeLengths, Length::One);
} }
Length StyledElement::stroke_dashoffset() const Length StyledElement::stroke_dashoffset() const
{ {
auto& value = find(PropertyId::Stroke_Dashoffset); auto& value = find(PropertyID::Stroke_Dashoffset);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
LengthList StyledElement::stroke_dasharray() const LengthList StyledElement::stroke_dasharray() const
{ {
auto& value = find(PropertyId::Stroke_Dasharray); auto& value = find(PropertyID::Stroke_Dasharray);
return Parser::parseLengthList(value, ForbidNegativeLengths); return Parser::parseLengthList(value, ForbidNegativeLengths);
} }
WindRule StyledElement::fill_rule() const WindRule StyledElement::fill_rule() const
{ {
auto& value = find(PropertyId::Fill_Rule); auto& value = find(PropertyID::Fill_Rule);
return Parser::parseWindRule(value); return Parser::parseWindRule(value);
} }
WindRule StyledElement::clip_rule() const WindRule StyledElement::clip_rule() const
{ {
auto& value = find(PropertyId::Clip_Rule); auto& value = find(PropertyID::Clip_Rule);
return Parser::parseWindRule(value); return Parser::parseWindRule(value);
} }
LineCap StyledElement::stroke_linecap() const LineCap StyledElement::stroke_linecap() const
{ {
auto& value = find(PropertyId::Stroke_Linecap); auto& value = find(PropertyID::Stroke_Linecap);
return Parser::parseLineCap(value); return Parser::parseLineCap(value);
} }
LineJoin StyledElement::stroke_linejoin() const LineJoin StyledElement::stroke_linejoin() const
{ {
auto& value = find(PropertyId::Stroke_Linejoin); auto& value = find(PropertyID::Stroke_Linejoin);
return Parser::parseLineJoin(value); return Parser::parseLineJoin(value);
} }
Display StyledElement::display() const Display StyledElement::display() const
{ {
auto& value = get(PropertyId::Display); auto& value = get(PropertyID::Display);
return Parser::parseDisplay(value); return Parser::parseDisplay(value);
} }
Visibility StyledElement::visibility() const Visibility StyledElement::visibility() const
{ {
auto& value = find(PropertyId::Visibility); auto& value = find(PropertyID::Visibility);
return Parser::parseVisibility(value); return Parser::parseVisibility(value);
} }
Overflow StyledElement::overflow() const Overflow StyledElement::overflow() const
{ {
auto& value = get(PropertyId::Overflow); auto& value = get(PropertyID::Overflow);
return Parser::parseOverflow(value, parent == nullptr ? Overflow::Visible : Overflow::Hidden); return Parser::parseOverflow(value, parent == nullptr ? Overflow::Visible : Overflow::Hidden);
} }
std::string StyledElement::clip_path() const std::string StyledElement::clip_path() const
{ {
auto& value = get(PropertyId::Clip_Path); auto& value = get(PropertyID::Clip_Path);
return Parser::parseUrl(value); return Parser::parseUrl(value);
} }
std::string StyledElement::mask() const std::string StyledElement::mask() const
{ {
auto& value = get(PropertyId::Mask); auto& value = get(PropertyID::Mask);
return Parser::parseUrl(value); return Parser::parseUrl(value);
} }
std::string StyledElement::marker_start() const std::string StyledElement::marker_start() const
{ {
auto& value = find(PropertyId::Marker_Start); auto& value = find(PropertyID::Marker_Start);
return Parser::parseUrl(value); return Parser::parseUrl(value);
} }
std::string StyledElement::marker_mid() const std::string StyledElement::marker_mid() const
{ {
auto& value = find(PropertyId::Marker_Mid); auto& value = find(PropertyID::Marker_Mid);
return Parser::parseUrl(value); return Parser::parseUrl(value);
} }
std::string StyledElement::marker_end() const std::string StyledElement::marker_end() const
{ {
auto& value = find(PropertyId::Marker_End); auto& value = find(PropertyID::Marker_End);
return Parser::parseUrl(value); return Parser::parseUrl(value);
} }

View file

@ -8,7 +8,7 @@ namespace lunasvg {
class StyledElement : public Element class StyledElement : public Element
{ {
public: public:
StyledElement(ElementId id); StyledElement(ElementID id);
Paint fill() const; Paint fill() const;
Paint stroke() const; Paint stroke() const;

View file

@ -3,7 +3,7 @@
namespace lunasvg { namespace lunasvg {
StyleElement::StyleElement() StyleElement::StyleElement()
: Element(ElementId::Style) : Element(ElementID::Style)
{ {
} }

View file

@ -5,47 +5,47 @@
namespace lunasvg { namespace lunasvg {
SVGElement::SVGElement() SVGElement::SVGElement()
: GraphicsElement(ElementId::Svg) : GraphicsElement(ElementID::Svg)
{ {
} }
Length SVGElement::x() const Length SVGElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length SVGElement::y() const Length SVGElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length SVGElement::width() const Length SVGElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
Length SVGElement::height() const Length SVGElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
Rect SVGElement::viewBox() const Rect SVGElement::viewBox() const
{ {
auto& value = get(PropertyId::ViewBox); auto& value = get(PropertyID::ViewBox);
return Parser::parseViewBox(value); return Parser::parseViewBox(value);
} }
PreserveAspectRatio SVGElement::preserveAspectRatio() const PreserveAspectRatio SVGElement::preserveAspectRatio() const
{ {
auto& value = get(PropertyId::PreserveAspectRatio); auto& value = get(PropertyID::PreserveAspectRatio);
return Parser::parsePreserveAspectRatio(value); return Parser::parsePreserveAspectRatio(value);
} }
std::unique_ptr<LayoutSymbol> SVGElement::layoutDocument(const ParseDocument* document) const std::unique_ptr<LayoutSymbol> SVGElement::build(const TreeBuilder* builder) const
{ {
if(isDisplayNone()) if(isDisplayNone())
return nullptr; return nullptr;
@ -73,7 +73,7 @@ std::unique_ptr<LayoutSymbol> SVGElement::layoutDocument(const ParseDocument* do
root->clip = isOverflowHidden() ? preserveAspectRatio.getClip(_w, _h, viewBox) : Rect::Invalid; root->clip = isOverflowHidden() ? preserveAspectRatio.getClip(_w, _h, viewBox) : Rect::Invalid;
root->opacity = opacity(); root->opacity = opacity();
LayoutContext context(document, root.get()); LayoutContext context(builder, root.get());
root->masker = context.getMasker(mask()); root->masker = context.getMasker(mask());
root->clipper = context.getClipper(clip_path()); root->clipper = context.getClipper(clip_path());
layoutChildren(&context, root.get()); layoutChildren(&context, root.get());

View file

@ -5,7 +5,7 @@
namespace lunasvg { namespace lunasvg {
class ParseDocument; class TreeBuilder;
class LayoutSymbol; class LayoutSymbol;
class SVGElement : public GraphicsElement class SVGElement : public GraphicsElement
@ -20,7 +20,7 @@ public:
Rect viewBox() const; Rect viewBox() const;
PreserveAspectRatio preserveAspectRatio() const; PreserveAspectRatio preserveAspectRatio() const;
std::unique_ptr<LayoutSymbol> layoutDocument(const ParseDocument* document) const; std::unique_ptr<LayoutSymbol> build(const TreeBuilder* builder) const;
void layout(LayoutContext* context, LayoutContainer* current) const; void layout(LayoutContext* context, LayoutContainer* current) const;
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;

View file

@ -4,43 +4,43 @@
namespace lunasvg { namespace lunasvg {
SymbolElement::SymbolElement() SymbolElement::SymbolElement()
: StyledElement(ElementId::Symbol) : StyledElement(ElementID::Symbol)
{ {
} }
Length SymbolElement::x() const Length SymbolElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length SymbolElement::y() const Length SymbolElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length SymbolElement::width() const Length SymbolElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
Length SymbolElement::height() const Length SymbolElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
Rect SymbolElement::viewBox() const Rect SymbolElement::viewBox() const
{ {
auto& value = get(PropertyId::ViewBox); auto& value = get(PropertyID::ViewBox);
return Parser::parseViewBox(value); return Parser::parseViewBox(value);
} }
PreserveAspectRatio SymbolElement::preserveAspectRatio() const PreserveAspectRatio SymbolElement::preserveAspectRatio() const
{ {
auto& value = get(PropertyId::PreserveAspectRatio); auto& value = get(PropertyID::PreserveAspectRatio);
return Parser::parsePreserveAspectRatio(value); return Parser::parsePreserveAspectRatio(value);
} }

View file

@ -8,47 +8,47 @@
namespace lunasvg { namespace lunasvg {
UseElement::UseElement() UseElement::UseElement()
: GraphicsElement(ElementId::Use) : GraphicsElement(ElementID::Use)
{ {
} }
Length UseElement::x() const Length UseElement::x() const
{ {
auto& value = get(PropertyId::X); auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length UseElement::y() const Length UseElement::y() const
{ {
auto& value = get(PropertyId::Y); auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero); return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
} }
Length UseElement::width() const Length UseElement::width() const
{ {
auto& value = get(PropertyId::Width); auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
Length UseElement::height() const Length UseElement::height() const
{ {
auto& value = get(PropertyId::Height); auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent); return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
} }
std::string UseElement::href() const std::string UseElement::href() const
{ {
auto& value = get(PropertyId::Href); auto& value = get(PropertyID::Href);
return Parser::parseHref(value); return Parser::parseHref(value);
} }
void UseElement::transferWidthAndHeight(Element* element) const void UseElement::transferWidthAndHeight(Element* element) const
{ {
auto& width = get(PropertyId::Width); auto& width = get(PropertyID::Width);
auto& height = get(PropertyId::Height); auto& height = get(PropertyID::Height);
element->set(PropertyId::Width, width, 0x0); element->set(PropertyID::Width, width, 0x0);
element->set(PropertyId::Height, height, 0x0); element->set(PropertyID::Height, height, 0x0);
} }
void UseElement::layout(LayoutContext* context, LayoutContainer* current) const void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
@ -69,15 +69,15 @@ void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
auto _x = lengthContext.valueForLength(x(), LengthMode::Width); auto _x = lengthContext.valueForLength(x(), LengthMode::Width);
auto _y = lengthContext.valueForLength(y(), LengthMode::Height); auto _y = lengthContext.valueForLength(y(), LengthMode::Height);
auto transform = get(PropertyId::Transform); auto transform = get(PropertyID::Transform);
transform += "translate("; transform += "translate(";
transform += std::to_string(_x); transform += std::to_string(_x);
transform += ' '; transform += ' ';
transform += std::to_string(_y); transform += std::to_string(_y);
transform += ')'; transform += ')';
group->set(PropertyId::Transform, transform, 0x10); group->set(PropertyID::Transform, transform, 0x10);
if(ref->id == ElementId::Svg || ref->id == ElementId::Symbol) if(ref->id == ElementID::Svg || ref->id == ElementID::Symbol)
{ {
auto element = ref->cloneElement<SVGElement>(); auto element = ref->cloneElement<SVGElement>();
transferWidthAndHeight(element.get()); transferWidthAndHeight(element.get());