mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
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:
parent
0d52738239
commit
fd498ff35e
3
3rdparty/plutovg/CMakeLists.txt
vendored
3
3rdparty/plutovg/CMakeLists.txt
vendored
|
@ -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
|
||||
|
|
|
@ -15,95 +15,87 @@
|
|||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
#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>
|
||||
static unsigned int __inline clz(unsigned int x) {
|
||||
unsigned long r = 0;
|
||||
if (x != 0)
|
||||
{
|
||||
_BitScanReverse(&r, x);
|
||||
}
|
||||
return r;
|
||||
unsigned long r = 0;
|
||||
if (x != 0)
|
||||
{
|
||||
_BitScanReverse(&r, 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;
|
||||
x &= ~x + 1;
|
||||
if (n & 0x0000FFFF) c -= 16;
|
||||
if (n & 0x00FF00FF) c -= 8;
|
||||
if (n & 0x0F0F0F0F) c -= 4;
|
||||
if (n & 0x33333333) c -= 2;
|
||||
if (n & 0x55555555) c -= 1;
|
||||
return c;
|
||||
int c = 31;
|
||||
x &= ~x + 1;
|
||||
if (n & 0x0000FFFF) c -= 16;
|
||||
if (n & 0x00FF00FF) c -= 8;
|
||||
if (n & 0x0F0F0F0F) c -= 4;
|
||||
if (n & 0x33333333) c -= 2;
|
||||
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,34 +413,34 @@ 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;
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* END */
|
436
3rdparty/plutovg/plutovg-ft-math.h
vendored
Normal file
436
3rdparty/plutovg/plutovg-ft-math.h
vendored
Normal 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
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
420
3rdparty/plutovg/plutovg-ft-raster.h
vendored
Normal 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
320
3rdparty/plutovg/plutovg-ft-stroker.h
vendored
Normal 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
|
|
@ -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
|
6
3rdparty/plutovg/plutovg-private.h
vendored
6
3rdparty/plutovg/plutovg-private.h
vendored
|
@ -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;
|
||||
|
||||
|
|
215
3rdparty/plutovg/plutovg-rle.c
vendored
215
3rdparty/plutovg/plutovg-rle.c
vendored
|
@ -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, ¶ms);
|
||||
sw_ft_outline_destroy(outline);
|
||||
sw_ft_outline_destroy(strokeOutline);
|
||||
}
|
||||
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;
|
||||
PVG_FT_Raster_Render(¶ms);
|
||||
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;
|
||||
}
|
||||
|
||||
params.source = outline;
|
||||
sw_ft_grays_raster.raster_render(NULL, ¶ms);
|
||||
sw_ft_outline_destroy(outline);
|
||||
PVG_FT_Raster_Render(¶ms);
|
||||
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))
|
||||
|
|
11
3rdparty/software/CMakeLists.txt
vendored
11
3rdparty/software/CMakeLists.txt
vendored
|
@ -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}"
|
||||
)
|
438
3rdparty/software/sw_ft_math.h
vendored
438
3rdparty/software/sw_ft_math.h
vendored
|
@ -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
|
1423
3rdparty/software/sw_ft_raster.c
vendored
1423
3rdparty/software/sw_ft_raster.c
vendored
File diff suppressed because it is too large
Load diff
607
3rdparty/software/sw_ft_raster.h
vendored
607
3rdparty/software/sw_ft_raster.h
vendored
|
@ -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
|
319
3rdparty/software/sw_ft_stroker.h
vendored
319
3rdparty/software/sw_ft_stroker.h
vendored
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
DefsElement::DefsElement()
|
||||
: GraphicsElement(ElementId::Defs)
|
||||
: GraphicsElement(ElementID::Defs)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
GElement::GElement()
|
||||
: GraphicsElement(ElementId::G)
|
||||
: GraphicsElement(ElementID::G)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace lunasvg {
|
|||
class GraphicsElement : public StyledElement
|
||||
{
|
||||
public:
|
||||
GraphicsElement(ElementId id);
|
||||
GraphicsElement(ElementID id);
|
||||
|
||||
Transform transform() const;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
1052
source/parser.cpp
1052
source/parser.cpp
File diff suppressed because it is too large
Load diff
107
source/parser.h
107
source/parser.h
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace lunasvg {
|
|||
class StyledElement : public Element
|
||||
{
|
||||
public:
|
||||
StyledElement(ElementId id);
|
||||
StyledElement(ElementID id);
|
||||
|
||||
Paint fill() const;
|
||||
Paint stroke() const;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
StyleElement::StyleElement()
|
||||
: Element(ElementId::Style)
|
||||
: Element(ElementID::Style)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in a new issue