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-rle.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

View file

@ -15,10 +15,7 @@
/* */
/***************************************************************************/
#include "sw_ft_math.h"
#include <math.h>
//form https://github.com/chromium/chromium/blob/59afd8336009c9d97c22854c52e0382b62b3aa5e/third_party/abseil-cpp/absl/base/internal/bits.h
#include "plutovg-ft-math.h"
#if defined(_MSC_VER)
#include <intrin.h>
@ -30,9 +27,9 @@ static unsigned int __inline clz(unsigned int x) {
}
return r;
}
#define SW_FT_MSB(x) (clz(x))
#define PVG_FT_MSB(x) (clz(x))
#elif defined(__GNUC__)
#define SW_FT_MSB(x) (31 - __builtin_clz(x))
#define PVG_FT_MSB(x) (31 - __builtin_clz(x))
#else
static unsigned int __inline clz(unsigned int x) {
int c = 31;
@ -44,66 +41,61 @@ static unsigned int __inline clz(unsigned int x) {
if (n & 0x55555555) c -= 1;
return c;
}
#define SW_FT_MSB(x) (clz(x))
#define PVG_FT_MSB(x) (clz(x))
#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 */
#define SW_FT_MOVE_SIGN(x, s) \
SW_FT_BEGIN_STMNT \
#define PVG_FT_MOVE_SIGN(x, s) \
PVG_FT_BEGIN_STMNT \
if (x < 0) { \
x = -x; \
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;
SW_FT_Long c;
PVG_FT_Int s = 1;
PVG_FT_Long c;
SW_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s);
PVG_FT_MOVE_SIGN(a, 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;
}
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;
SW_FT_Long d;
PVG_FT_Int s = 1;
PVG_FT_Long d;
SW_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s);
SW_FT_MOVE_SIGN(c, s);
PVG_FT_MOVE_SIGN(a, s);
PVG_FT_MOVE_SIGN(b, 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;
}
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;
SW_FT_Long q;
PVG_FT_Int s = 1;
PVG_FT_Long q;
SW_FT_MOVE_SIGN(a, s);
SW_FT_MOVE_SIGN(b, s);
PVG_FT_MOVE_SIGN(a, 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);
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 */
#define SW_FT_TRIG_SCALE 0xDBD95B16UL
#define PVG_FT_TRIG_SCALE 0xDBD95B16UL
/* the highest bit in overflow-safe vector components, */
/* 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 */
#define SW_FT_TRIG_MAX_ITERS 23
/* this table was generated for PVG_FT_PI = 180L << 16, i.e. degrees */
#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,
7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 57L,
29L, 14L, 7L, 4L, 2L, 1L};
/* 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;
SW_FT_Int64 v;
PVG_FT_Fixed s;
PVG_FT_Int64 v;
s = val;
val = SW_FT_ABS(val);
val = PVG_FT_ABS(val);
v = (val * (SW_FT_Int64)SW_FT_TRIG_SCALE) + 0x100000000UL;
val = (SW_FT_Fixed)(v >> 32);
v = (val * (PVG_FT_Int64)PVG_FT_TRIG_SCALE) + 0x100000000UL;
val = (PVG_FT_Fixed)(v >> 32);
return (s >= 0) ? val : -val;
}
/* 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;
SW_FT_Int shift;
PVG_FT_Pos x, y;
PVG_FT_Int shift;
x = vec->x;
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) {
shift = SW_FT_TRIG_SAFE_MSB - shift;
vec->x = (SW_FT_Pos)((SW_FT_ULong)x << shift);
vec->y = (SW_FT_Pos)((SW_FT_ULong)y << shift);
if (shift <= PVG_FT_TRIG_SAFE_MSB) {
shift = PVG_FT_TRIG_SAFE_MSB - shift;
vec->x = (PVG_FT_Pos)((PVG_FT_ULong)x << shift);
vec->y = (PVG_FT_Pos)((PVG_FT_ULong)y << shift);
} else {
shift -= SW_FT_TRIG_SAFE_MSB;
shift -= PVG_FT_TRIG_SAFE_MSB;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
@ -178,36 +170,36 @@ static SW_FT_Int ft_trig_prenorm(SW_FT_Vector* vec)
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;
SW_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed* arctanptr;
PVG_FT_Int i;
PVG_FT_Fixed x, y, xtemp, b;
const PVG_FT_Fixed* arctanptr;
x = vec->x;
y = vec->y;
/* Rotate inside [-PI/4,PI/4] sector */
while (theta < -SW_FT_ANGLE_PI4) {
while (theta < -PVG_FT_ANGLE_PI4) {
xtemp = y;
y = -x;
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;
y = x;
x = xtemp;
theta -= SW_FT_ANGLE_PI2;
theta -= PVG_FT_ANGLE_PI2;
}
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
SW_FT_Fixed v1 = ((y + b) >> i);
SW_FT_Fixed v2 = ((x + b) >> i);
for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
PVG_FT_Fixed v1 = ((y + b) >> i);
PVG_FT_Fixed v2 = ((x + b) >> i);
if (theta < 0) {
xtemp = x + v1;
y = y - v2;
@ -225,12 +217,12 @@ static void ft_trig_pseudo_rotate(SW_FT_Vector* vec, SW_FT_Angle theta)
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;
SW_FT_Int i;
SW_FT_Fixed x, y, xtemp, b;
const SW_FT_Fixed* arctanptr;
PVG_FT_Angle theta;
PVG_FT_Int i;
PVG_FT_Fixed x, y, xtemp, b;
const PVG_FT_Fixed* arctanptr;
x = vec->x;
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 */
if (y > x) {
if (y > -x) {
theta = SW_FT_ANGLE_PI2;
theta = PVG_FT_ANGLE_PI2;
xtemp = y;
y = -x;
x = xtemp;
} 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;
y = -y;
}
} else {
if (y < -x) {
theta = -SW_FT_ANGLE_PI2;
theta = -PVG_FT_ANGLE_PI2;
xtemp = -y;
y = x;
x = xtemp;
@ -261,9 +253,9 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for (i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
SW_FT_Fixed v1 = ((y + b) >> i);
SW_FT_Fixed v2 = ((x + b) >> i);
for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) {
PVG_FT_Fixed v1 = ((y + b) >> i);
PVG_FT_Fixed v2 = ((x + b) >> i);
if (y > 0) {
xtemp = x + v1;
y = y - v2;
@ -279,9 +271,9 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
/* round theta */
if (theta >= 0)
theta = SW_FT_PAD_ROUND(theta, 32);
theta = PVG_FT_PAD_ROUND(theta, 32);
else
theta = -SW_FT_PAD_ROUND(-theta, 32);
theta = -PVG_FT_PAD_ROUND(-theta, 32);
vec->x = x;
vec->y = theta;
@ -289,11 +281,11 @@ static void ft_trig_pseudo_polarize(SW_FT_Vector* vec)
/* 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;
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 */
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 */
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;
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 */
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;
@ -338,65 +330,58 @@ SW_FT_Angle SW_FT_Atan2(SW_FT_Fixed dx, SW_FT_Fixed dy)
/* 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;
ft_trig_pseudo_rotate(vec, angle);
vec->x = (vec->x + 0x80L) >> 8;
vec->y = (vec->y + 0x80L) >> 8;
}
/* these macros return 0 for positive numbers,
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)
void PVG_FT_Vector_Rotate(PVG_FT_Vector* vec, PVG_FT_Angle angle)
{
SW_FT_Int shift;
SW_FT_Vector v;
PVG_FT_Int shift;
PVG_FT_Vector v = *vec;
v.x = vec->x;
v.y = vec->y;
if ( v.x == 0 && v.y == 0 )
return;
if (angle && (v.x != 0 || v.y != 0)) {
shift = ft_trig_prenorm(&v);
ft_trig_pseudo_rotate(&v, angle);
v.x = ft_trig_downscale(v.x);
v.y = ft_trig_downscale(v.y);
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_rotate( &v, angle );
v.x = ft_trig_downscale( v.x );
v.y = ft_trig_downscale( v.y );
if (shift > 0) {
SW_FT_Int32 half = (SW_FT_Int32)1L << (shift - 1);
if ( shift > 0 )
{
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;
} else {
shift = -shift;
vec->x = (SW_FT_Pos)((SW_FT_ULong)v.x << shift);
vec->y = (SW_FT_Pos)((SW_FT_ULong)v.y << shift);
vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift;
vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift;
}
else
{
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 */
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;
SW_FT_Vector v;
PVG_FT_Int shift;
PVG_FT_Vector v;
v = *vec;
/* handle trivial cases */
if (v.x == 0) {
return SW_FT_ABS(v.y);
return PVG_FT_ABS(v.y);
} else if (v.y == 0) {
return SW_FT_ABS(v.x);
return PVG_FT_ABS(v.x);
}
/* 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;
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 */
void SW_FT_Vector_Polarize(SW_FT_Vector* vec, SW_FT_Fixed* length,
SW_FT_Angle* angle)
void PVG_FT_Vector_Polarize(PVG_FT_Vector* vec, PVG_FT_Fixed* length,
PVG_FT_Angle* angle)
{
SW_FT_Int shift;
SW_FT_Vector v;
PVG_FT_Int shift;
PVG_FT_Vector v;
v = *vec;
@ -428,32 +413,32 @@ void SW_FT_Vector_Polarize(SW_FT_Vector* vec, SW_FT_Fixed* length,
v.x = ft_trig_downscale(v.x);
*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;
}
/* documentation is in fttrigon.h */
void SW_FT_Vector_From_Polar(SW_FT_Vector* vec, SW_FT_Fixed length,
SW_FT_Angle angle)
void PVG_FT_Vector_From_Polar(PVG_FT_Vector* vec, PVG_FT_Fixed length,
PVG_FT_Angle angle)
{
vec->x = length;
vec->y = 0;
SW_FT_Vector_Rotate(vec, angle);
PVG_FT_Vector_Rotate(vec, angle);
}
/* 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 )
delta += SW_FT_ANGLE_2PI;
while ( delta <= -PVG_FT_ANGLE_PI )
delta += PVG_FT_ANGLE_2PI;
while ( delta > SW_FT_ANGLE_PI )
delta -= SW_FT_ANGLE_2PI;
while ( delta > PVG_FT_ANGLE_PI )
delta -= PVG_FT_ANGLE_2PI;
return delta;
}

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> */
/* SW_FT_Fixed */
/* PVG_FT_Fixed */
/* */
/* <Description> */
/* This type is used to store 16.16 fixed-point values, like scaling */
/* values or matrix coefficients. */
/* */
typedef signed long SW_FT_Fixed;
typedef signed long PVG_FT_Fixed;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Int */
/* PVG_FT_Int */
/* */
/* <Description> */
/* A typedef for the int type. */
/* */
typedef signed int SW_FT_Int;
typedef signed int PVG_FT_Int;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_UInt */
/* PVG_FT_UInt */
/* */
/* <Description> */
/* A typedef for the unsigned int type. */
/* */
typedef unsigned int SW_FT_UInt;
typedef unsigned int PVG_FT_UInt;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Long */
/* PVG_FT_Long */
/* */
/* <Description> */
/* A typedef for signed long. */
/* */
typedef signed long SW_FT_Long;
typedef signed long PVG_FT_Long;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_ULong */
/* PVG_FT_ULong */
/* */
/* <Description> */
/* A typedef for unsigned long. */
/* */
typedef unsigned long SW_FT_ULong;
typedef unsigned long PVG_FT_ULong;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Short */
/* PVG_FT_Short */
/* */
/* <Description> */
/* A typedef for signed short. */
/* */
typedef signed short SW_FT_Short;
typedef signed short PVG_FT_Short;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Byte */
/* PVG_FT_Byte */
/* */
/* <Description> */
/* A simple typedef for the _unsigned_ char type. */
/* */
typedef unsigned char SW_FT_Byte;
typedef unsigned char PVG_FT_Byte;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Bool */
/* PVG_FT_Bool */
/* */
/* <Description> */
/* A typedef of unsigned char, used for simple booleans. As usual, */
/* values 1 and~0 represent true and false, respectively. */
/* */
typedef unsigned char SW_FT_Bool;
typedef unsigned char PVG_FT_Bool;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Error */
/* PVG_FT_Error */
/* */
/* <Description> */
/* The FreeType error code type. A value of~0 is always interpreted */
/* as a successful operation. */
/* */
typedef int SW_FT_Error;
typedef int PVG_FT_Error;
/*************************************************************************/
/* */
/* <Type> */
/* SW_FT_Pos */
/* PVG_FT_Pos */
/* */
/* <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 */
/* units, or 16.16, or 26.6 fixed-point pixel coordinates. */
/* */
typedef signed long SW_FT_Pos;
typedef signed long PVG_FT_Pos;
/*************************************************************************/
/* */
/* <Struct> */
/* SW_FT_Vector */
/* PVG_FT_Vector */
/* */
/* <Description> */
/* A simple structure used to store a 2D vector; coordinates are of */
/* the SW_FT_Pos type. */
/* the PVG_FT_Pos type. */
/* */
/* <Fields> */
/* x :: The horizontal coordinate. */
/* y :: The vertical coordinate. */
/* */
typedef struct SW_FT_Vector_
typedef struct PVG_FT_Vector_
{
SW_FT_Pos x;
SW_FT_Pos y;
PVG_FT_Pos x;
PVG_FT_Pos y;
} SW_FT_Vector;
} PVG_FT_Vector;
typedef long long int SW_FT_Int64;
typedef unsigned long long int SW_FT_UInt64;
typedef long long int PVG_FT_Int64;
typedef unsigned long long int PVG_FT_UInt64;
typedef signed int SW_FT_Int32;
typedef unsigned int SW_FT_UInt32;
typedef signed int PVG_FT_Int32;
typedef unsigned int PVG_FT_UInt32;
#define SW_FT_BOOL( x ) ( (SW_FT_Bool)( x ) )
#define SW_FT_SIZEOF_LONG 4
#define PVG_FT_BOOL( x ) ( (PVG_FT_Bool)( x ) )
#ifndef TRUE
#define TRUE 1
@ -156,5 +170,4 @@ typedef unsigned int SW_FT_UInt32;
#define FALSE 0
#endif
#endif // SW_FT_TYPES_H
#endif // PLUTOVG_FT_TYPES_H

View file

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

View file

@ -1,26 +1,24 @@
#include "plutovg-private.h"
#include "sw_ft_raster.h"
#include "sw_ft_stroker.h"
#include "sw_ft_types.h"
#include "sw_ft_math.h"
#include "plutovg-ft-raster.h"
#include "plutovg-ft-stroker.h"
#include <math.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));
ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector));
ft->tags = malloc((size_t)(points + contours) * sizeof(char));
ft->contours = malloc((size_t)contours * sizeof(int));
ft->contours_flag = malloc((size_t)contours * sizeof(char));
PVG_FT_Outline* ft = malloc(sizeof(PVG_FT_Outline));
ft->points = malloc((points + contours) * sizeof(PVG_FT_Vector));
ft->tags = malloc((points + contours) * sizeof(char));
ft->contours = malloc(contours * sizeof(int));
ft->contours_flag = malloc(contours * sizeof(char));
ft->n_points = ft->n_contours = 0;
ft->flags = 0x0;
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->tags);
@ -29,14 +27,13 @@ static void sw_ft_outline_destroy(SW_FT_Outline* ft)
free(ft);
}
#define FT_COORD(x) (SW_FT_Pos)((x) * 64)
static void sw_ft_outline_move_to(SW_FT_Outline* ft, double x, double y)
#define FT_COORD(x) (PVG_FT_Pos)((x) * 64)
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].y = FT_COORD(y);
ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON;
if(ft->n_points)
{
ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
if(ft->n_points) {
ft->contours[ft->n_contours] = ft->n_points - 1;
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++;
}
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].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++;
}
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].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->points[ft->n_points].x = FT_COORD(x2);
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->points[ft->n_points].x = FT_COORD(x3);
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++;
}
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;
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].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++;
}
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->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_point_t* points = path->points.data;
plutovg_point_t p[3];
for(int i = 0;i < path->elements.size;i++)
{
switch(elements[i])
{
for(int i = 0;i < path->elements.size;i++) {
switch(elements[i]) {
case plutovg_path_element_move_to:
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;
break;
case plutovg_path_element_line_to:
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;
break;
case plutovg_path_element_cubic_to:
plutovg_matrix_map_point(matrix, &points[0], &p[0]);
plutovg_matrix_map_point(matrix, &points[1], &p[1]);
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;
break;
case plutovg_path_element_close:
sw_ft_outline_close(outline);
ft_outline_close(outline);
points += 1;
break;
}
}
sw_ft_outline_end(outline);
ft_outline_end(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);
SW_FT_Outline* outline = sw_ft_outline_convert(dashed, matrix);
PVG_FT_Outline* outline = ft_outline_convert(dashed, matrix);
plutovg_path_destroy(dashed);
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_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;
}
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* rle = malloc(sizeof(plutovg_rle_t));
@ -180,28 +165,28 @@ void plutovg_rle_destroy(plutovg_rle_t* rle)
#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)
{
SW_FT_Raster_Params params;
params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA;
PVG_FT_Raster_Params params;
params.flags = PVG_FT_RASTER_FLAG_DIRECT | PVG_FT_RASTER_FLAG_AA;
params.gray_spans = generation_callback;
params.bbox_cb = bbox_callback;
params.user = rle;
if(clip)
{
params.flags |= SW_FT_RASTER_FLAG_CLIP;
params.clip_box.xMin = (SW_FT_Pos)clip->x;
params.clip_box.yMin = (SW_FT_Pos)clip->y;
params.clip_box.xMax = (SW_FT_Pos)(clip->x + clip->w);
params.clip_box.yMax = (SW_FT_Pos)(clip->y + clip->h);
if(clip) {
params.flags |= PVG_FT_RASTER_FLAG_CLIP;
params.clip_box.xMin = (PVG_FT_Pos)clip->x;
params.clip_box.yMin = (PVG_FT_Pos)clip->y;
params.clip_box.xMax = (PVG_FT_Pos)(clip->x + clip->w);
params.clip_box.yMax = (PVG_FT_Pos)(clip->y + clip->h);
}
if(stroke)
{
SW_FT_Outline* outline = stroke->dash ? sw_ft_outline_convert_dash(path, matrix, stroke->dash) : sw_ft_outline_convert(path, matrix);
SW_FT_Stroker_LineCap ftCap;
SW_FT_Stroker_LineJoin ftJoin;
SW_FT_Fixed ftWidth;
SW_FT_Fixed ftMiterLimit;
if(stroke) {
PVG_FT_Outline* outline;
if(stroke->dash == NULL)
outline = ft_outline_convert(path, matrix);
else
outline = ft_outline_convert_dash(path, matrix, stroke->dash);
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 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;
ftWidth = (SW_FT_Fixed)(stroke->width * scale * 0.5 * (1 << 6));
ftMiterLimit = (SW_FT_Fixed)(stroke->miterlimit * (1 << 16));
ftWidth = (PVG_FT_Fixed)(stroke->width * scale * 0.5 * (1 << 6));
ftMiterLimit = (PVG_FT_Fixed)(stroke->miterlimit * (1 << 16));
switch(stroke->cap)
{
switch(stroke->cap) {
case plutovg_line_cap_square:
ftCap = SW_FT_STROKER_LINECAP_SQUARE;
ftCap = PVG_FT_STROKER_LINECAP_SQUARE;
break;
case plutovg_line_cap_round:
ftCap = SW_FT_STROKER_LINECAP_ROUND;
ftCap = PVG_FT_STROKER_LINECAP_ROUND;
break;
default:
ftCap = SW_FT_STROKER_LINECAP_BUTT;
ftCap = PVG_FT_STROKER_LINECAP_BUTT;
break;
}
switch(stroke->join)
{
switch(stroke->join) {
case plutovg_line_join_bevel:
ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL;
ftJoin = PVG_FT_STROKER_LINEJOIN_BEVEL;
break;
case plutovg_line_join_round:
ftJoin = SW_FT_STROKER_LINEJOIN_ROUND;
ftJoin = PVG_FT_STROKER_LINEJOIN_ROUND;
break;
default:
ftJoin = SW_FT_STROKER_LINEJOIN_MITER_FIXED;
ftJoin = PVG_FT_STROKER_LINEJOIN_MITER_FIXED;
break;
}
SW_FT_Stroker stroker;
SW_FT_Stroker_New(&stroker);
SW_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit);
SW_FT_Stroker_ParseOutline(stroker, outline);
PVG_FT_Stroker stroker;
PVG_FT_Stroker_New(&stroker);
PVG_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit);
PVG_FT_Stroker_ParseOutline(stroker, outline);
SW_FT_UInt points;
SW_FT_UInt contours;
SW_FT_Stroker_GetCounts(stroker, &points, &contours);
PVG_FT_UInt points;
PVG_FT_UInt contours;
PVG_FT_Stroker_GetCounts(stroker, &points, &contours);
SW_FT_Outline* strokeOutline = sw_ft_outline_create((int)points, (int)contours);
SW_FT_Stroker_Export(stroker, strokeOutline);
SW_FT_Stroker_Done(stroker);
PVG_FT_Outline* strokeOutline = ft_outline_create(points, contours);
PVG_FT_Stroker_Export(stroker, strokeOutline);
PVG_FT_Stroker_Done(stroker);
strokeOutline->flags = SW_FT_OUTLINE_NONE;
strokeOutline->flags = PVG_FT_OUTLINE_NONE;
params.source = strokeOutline;
sw_ft_grays_raster.raster_render(NULL, &params);
sw_ft_outline_destroy(outline);
sw_ft_outline_destroy(strokeOutline);
PVG_FT_Raster_Render(&params);
ft_outline_destroy(outline);
ft_outline_destroy(strokeOutline);
} else {
PVG_FT_Outline* outline = ft_outline_convert(path, matrix);
switch(winding) {
case plutovg_fill_rule_even_odd:
outline->flags = PVG_FT_OUTLINE_EVEN_ODD_FILL;
break;
default:
outline->flags = PVG_FT_OUTLINE_NONE;
break;
}
else
{
SW_FT_Outline* outline = sw_ft_outline_convert(path, matrix);
outline->flags = winding == plutovg_fill_rule_even_odd ? SW_FT_OUTLINE_EVEN_ODD_FILL : SW_FT_OUTLINE_NONE;
params.source = outline;
sw_ft_grays_raster.raster_render(NULL, &params);
sw_ft_outline_destroy(outline);
PVG_FT_Raster_Render(&params);
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))

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)
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)
option(BUILD_SHARED_LIBS "Builds as shared library" OFF)
@ -12,7 +12,6 @@ add_library(lunasvg)
add_subdirectory(include)
add_subdirectory(source)
add_subdirectory(3rdparty/software)
add_subdirectory(3rdparty/plutovg)
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)
[![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_line_cap_t to_plutovg_line_cap(LineCap cap);
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_path(plutovg_t* pluto, const Path& path);
@ -59,7 +59,7 @@ Canvas::~Canvas()
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)
@ -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 matrix = to_plutovg_matrix(transform);
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_set_source_gradient(pluto, 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 matrix = to_plutovg_matrix(transform);
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_set_source_gradient(pluto, 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;
}
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;
}
@ -238,7 +238,7 @@ static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops&
{
auto offset = std::get<0>(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 {
ClipPathElement::ClipPathElement()
: GraphicsElement(ElementId::ClipPath)
: GraphicsElement(ElementID::ClipPath)
{
}
Units ClipPathElement::clipPathUnits() const
{
auto& value = get(PropertyId::ClipPathUnits);
auto& value = get(PropertyID::ClipPathUnits);
return Parser::parseUnits(value, Units::UserSpaceOnUse);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,7 +8,7 @@ namespace lunasvg {
class GraphicsElement : public StyledElement
{
public:
GraphicsElement(ElementId id);
GraphicsElement(ElementID id);
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);
}
LayoutContext::LayoutContext(const ParseDocument* document, LayoutSymbol* root)
: m_document(document), m_root(root)
LayoutContext::LayoutContext(const TreeBuilder* builder, LayoutSymbol* root)
: m_builder(builder), m_root(root)
{
}
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
@ -517,7 +517,7 @@ LayoutMask* LayoutContext::getMasker(const std::string& id)
return static_cast<LayoutMask*>(ref);
auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::Mask)
if(element == nullptr || element->id != ElementID::Mask)
return nullptr;
auto masker = static_cast<MaskElement*>(element)->getMasker(this);
@ -534,7 +534,7 @@ LayoutClipPath* LayoutContext::getClipper(const std::string& id)
return static_cast<LayoutClipPath*>(ref);
auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::ClipPath)
if(element == nullptr || element->id != ElementID::ClipPath)
return nullptr;
auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this);
@ -551,7 +551,7 @@ LayoutMarker* LayoutContext::getMarker(const std::string& id)
return static_cast<LayoutMarker*>(ref);
auto element = getElementById(id);
if(element == nullptr || element->id != ElementId::Marker)
if(element == nullptr || element->id != ElementID::Marker)
return nullptr;
auto marker = static_cast<MarkerElement*>(element)->getMarker(this);

View file

@ -346,14 +346,14 @@ private:
RenderMode m_mode;
};
class ParseDocument;
class TreeBuilder;
class StyledElement;
class GeometryElement;
class LayoutContext
{
public:
LayoutContext(const ParseDocument* document, LayoutSymbol* root);
LayoutContext(const TreeBuilder* builder, LayoutSymbol* root);
Element* getElementById(const std::string& id) const;
LayoutObject* getResourcesById(const std::string& id) const;
@ -373,7 +373,7 @@ public:
bool hasReference(const Element* element) const;
private:
const ParseDocument* m_document;
const TreeBuilder* m_builder;
LayoutSymbol* m_root;
std::map<std::string, LayoutObject*> m_resourcesCache;
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)
{
ParseDocument parser;
if(!parser.parse(data, size))
TreeBuilder builder;
if(!builder.parse(data, size))
return nullptr;
auto root = parser.layout();
auto root = builder.build();
if(!root || root->children.empty())
return nullptr;

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
#define PARSER_H
#include <map>
#include <set>
#include "property.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 parseNumberList(const char*& ptr, const char* end, double* values, int count);
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 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
{
@ -78,20 +82,19 @@ struct AttributeSelector
Contains
};
PropertyId id{PropertyId::Unknown};
std::string value;
MatchType matchType{MatchType::None};
PropertyID id{PropertyID::Unknown};
std::string value;
};
using SelectorList = std::vector<Selector>;
struct PseudoClass
struct PseudoClassSelector
{
enum class Type
{
Unknown,
Empty,
Root,
Is,
Not,
FirstChild,
LastChild,
@ -102,7 +105,9 @@ struct PseudoClass
};
Type type{Type::Unknown};
SelectorList notSelectors;
int16_t a{0};
int16_t b{0};
SelectorList subSelectors;
};
struct SimpleSelector
@ -115,16 +120,10 @@ struct SimpleSelector
InDirectAdjacent
};
ElementId id{ElementId::Star};
std::vector<AttributeSelector> attributeSelectors;
std::vector<PseudoClass> pseudoClasses;
Combinator combinator{Combinator::Descendant};
};
struct Selector
{
std::vector<SimpleSelector> simpleSelectors;
int specificity{0};
ElementID id{ElementID::Star};
std::vector<AttributeSelector> attributeSelectors;
std::vector<PseudoClassSelector> pseudoClassSelectors;
};
struct Rule
@ -133,21 +132,47 @@ struct Rule
PropertyList declarations;
};
class RuleMatchContext
{
class RuleData {
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;
private:
bool selectorMatch(const Selector* selector, const Element* element) const;
bool simpleSelectorMatch(const SimpleSelector& selector, const Element* element) const;
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;
std::multiset<RuleData> m_rules;
uint32_t m_position{0};
};
class CSSParser
@ -155,35 +180,29 @@ class CSSParser
public:
CSSParser() = default;
bool parseMore(const std::string& value);
const std::vector<Rule>& rules() const { return m_rules; }
static bool parseSheet(StyleSheet* sheet, const std::string& value);
private:
bool parseAtRule(const char*& ptr, const char* end) const;
bool parseRule(const char*& ptr, const char* end, Rule& rule) const;
bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) const;
bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations) const;
bool parseSelector(const char*& ptr, const char* end, Selector& selector) const;
bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) const;
private:
std::vector<Rule> m_rules;
static bool parseAtRule(const char*& ptr, const char* end);
static bool parseRule(const char*& ptr, const char* end, Rule& rule);
static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
static bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations);
static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
};
class LayoutSymbol;
class ParseDocument
{
class TreeBuilder {
public:
ParseDocument();
~ParseDocument();
TreeBuilder();
~TreeBuilder();
bool parse(const char* data, std::size_t size);
SVGElement* rootElement() const { return m_rootElement.get(); }
Element* getElementById(const std::string& id) const;
std::unique_ptr<LayoutSymbol> layout() const;
std::unique_ptr<LayoutSymbol> build() const;
private:
std::unique_ptr<SVGElement> m_rootElement;

View file

@ -2,21 +2,26 @@
#include "styledelement.h"
#include "lunasvg.h"
#include <algorithm>
#include <cmath>
namespace lunasvg {
const Color Color::Black{0, 0, 0, 1};
const Color Color::White{1, 1, 1, 1};
const Color Color::Red{1, 0, 0, 1};
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};
const Color Color::Black(0xFF000000);
const Color Color::White(0xFFFFFFFF);
const Color Color::Transparent(0x00000000);
Color::Color(double r, double g, double b, double a)
: r(r), g(g), b(b), a(a)
Color& Color::combine(double opacity)
{
*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)

View file

@ -68,23 +68,27 @@ class Color
{
public:
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 White;
static const Color Red;
static const Color Green;
static const Color Blue;
static const Color Yellow;
static const Color Transparent;
public:
double r{0};
double g{0};
double b{0};
double a{1};
private:
uint32_t m_value{0};
};
class Paint

View file

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

View file

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

View file

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

View file

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

View file

@ -5,47 +5,47 @@
namespace lunasvg {
SVGElement::SVGElement()
: GraphicsElement(ElementId::Svg)
: GraphicsElement(ElementID::Svg)
{
}
Length SVGElement::x() const
{
auto& value = get(PropertyId::X);
auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
}
Length SVGElement::y() const
{
auto& value = get(PropertyId::Y);
auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
}
Length SVGElement::width() const
{
auto& value = get(PropertyId::Width);
auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
}
Length SVGElement::height() const
{
auto& value = get(PropertyId::Height);
auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
}
Rect SVGElement::viewBox() const
{
auto& value = get(PropertyId::ViewBox);
auto& value = get(PropertyID::ViewBox);
return Parser::parseViewBox(value);
}
PreserveAspectRatio SVGElement::preserveAspectRatio() const
{
auto& value = get(PropertyId::PreserveAspectRatio);
auto& value = get(PropertyID::PreserveAspectRatio);
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())
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->opacity = opacity();
LayoutContext context(document, root.get());
LayoutContext context(builder, root.get());
root->masker = context.getMasker(mask());
root->clipper = context.getClipper(clip_path());
layoutChildren(&context, root.get());

View file

@ -5,7 +5,7 @@
namespace lunasvg {
class ParseDocument;
class TreeBuilder;
class LayoutSymbol;
class SVGElement : public GraphicsElement
@ -20,7 +20,7 @@ public:
Rect viewBox() 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;
std::unique_ptr<Node> clone() const;

View file

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

View file

@ -8,47 +8,47 @@
namespace lunasvg {
UseElement::UseElement()
: GraphicsElement(ElementId::Use)
: GraphicsElement(ElementID::Use)
{
}
Length UseElement::x() const
{
auto& value = get(PropertyId::X);
auto& value = get(PropertyID::X);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
}
Length UseElement::y() const
{
auto& value = get(PropertyId::Y);
auto& value = get(PropertyID::Y);
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
}
Length UseElement::width() const
{
auto& value = get(PropertyId::Width);
auto& value = get(PropertyID::Width);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
}
Length UseElement::height() const
{
auto& value = get(PropertyId::Height);
auto& value = get(PropertyID::Height);
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
}
std::string UseElement::href() const
{
auto& value = get(PropertyId::Href);
auto& value = get(PropertyID::Href);
return Parser::parseHref(value);
}
void UseElement::transferWidthAndHeight(Element* element) const
{
auto& width = get(PropertyId::Width);
auto& height = get(PropertyId::Height);
auto& width = get(PropertyID::Width);
auto& height = get(PropertyID::Height);
element->set(PropertyId::Width, width, 0x0);
element->set(PropertyId::Height, height, 0x0);
element->set(PropertyID::Width, width, 0x0);
element->set(PropertyID::Height, height, 0x0);
}
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 _y = lengthContext.valueForLength(y(), LengthMode::Height);
auto transform = get(PropertyId::Transform);
auto transform = get(PropertyID::Transform);
transform += "translate(";
transform += std::to_string(_x);
transform += ' ';
transform += std::to_string(_y);
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>();
transferWidthAndHeight(element.get());