mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
3rdparty/nanosvg: Re-base on latest upstream.
Now based on upstream 9da543e8329fdd81b64eb48742d8ccb09377aed1. This fixes some issues with abbreviate path commands, gradients, and locale sensitivity when parsing percentace-style colours.
This commit is contained in:
parent
95f8e4aa01
commit
02eea1bd67
75
3rdparty/nanosvg/CMakeLists.txt
vendored
Normal file
75
3rdparty/nanosvg/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(NanoSVG C)
|
||||||
|
|
||||||
|
# CMake needs *.c files to do something useful
|
||||||
|
configure_file(src/nanosvg.h ${CMAKE_CURRENT_BINARY_DIR}/nanosvg.c)
|
||||||
|
configure_file(src/nanosvgrast.h ${CMAKE_CURRENT_BINARY_DIR}/nanosvgrast.c)
|
||||||
|
|
||||||
|
add_library(nanosvg ${CMAKE_CURRENT_BINARY_DIR}/nanosvg.c)
|
||||||
|
|
||||||
|
find_library(MATH_LIBRARY m) # Business as usual
|
||||||
|
if(MATH_LIBRARY)
|
||||||
|
target_link_libraries(nanosvg PUBLIC ${MATH_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(nanosvg PUBLIC $<INSTALL_INTERFACE:include/nanosvg>)
|
||||||
|
target_compile_definitions(nanosvg PRIVATE NANOSVG_IMPLEMENTATION)
|
||||||
|
|
||||||
|
# Same for nanosvgrast
|
||||||
|
add_library(nanosvgrast ${CMAKE_CURRENT_BINARY_DIR}/nanosvgrast.c)
|
||||||
|
target_link_libraries(nanosvgrast PUBLIC nanosvg)
|
||||||
|
target_include_directories(nanosvgrast PRIVATE src)
|
||||||
|
target_compile_definitions(nanosvgrast PRIVATE NANOSVGRAST_IMPLEMENTATION)
|
||||||
|
|
||||||
|
# Installation and export:
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
|
VERSION 1.0
|
||||||
|
COMPATIBILITY AnyNewerVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS nanosvg nanosvgrast
|
||||||
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
|
)
|
||||||
|
|
||||||
|
export(EXPORT ${PROJECT_NAME}Targets
|
||||||
|
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake"
|
||||||
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ConfigPackageLocation lib/cmake/${PROJECT_NAME})
|
||||||
|
|
||||||
|
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||||
|
INSTALL_DESTINATION ${ConfigPackageLocation}
|
||||||
|
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
src/nanosvg.h
|
||||||
|
src/nanosvgrast.h
|
||||||
|
DESTINATION
|
||||||
|
include/nanosvg
|
||||||
|
)
|
||||||
|
|
||||||
|
install(EXPORT ${PROJECT_NAME}Targets
|
||||||
|
FILE
|
||||||
|
${PROJECT_NAME}Targets.cmake
|
||||||
|
NAMESPACE
|
||||||
|
${PROJECT_NAME}::
|
||||||
|
DESTINATION
|
||||||
|
${ConfigPackageLocation}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
|
DESTINATION
|
||||||
|
${ConfigPackageLocation}
|
||||||
|
)
|
5
3rdparty/nanosvg/Config.cmake.in
vendored
Normal file
5
3rdparty/nanosvg/Config.cmake.in
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/NanoSVGTargets.cmake)
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/NanoSVGTargets.cmake")
|
||||||
|
endif ()
|
10
3rdparty/nanosvg/README.md
vendored
10
3rdparty/nanosvg/README.md
vendored
@ -78,6 +78,16 @@ By default, NanoSVG parses only the most common colors. In order to get support
|
|||||||
#include "nanosvg.h"
|
#include "nanosvg.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Alternatively, you can install the library using CMake and import it into your project using the standard CMake `find_package` command.
|
||||||
|
|
||||||
|
```CMake
|
||||||
|
add_executable(myexe main.c)
|
||||||
|
|
||||||
|
find_package(NanoSVG REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(myexe NanoSVG::nanosvg NanoSVG::nanosvgrast)
|
||||||
|
```
|
||||||
|
|
||||||
## Compiling Example Project
|
## Compiling Example Project
|
||||||
|
|
||||||
In order to compile the demo project, your will need to install [GLFW](http://www.glfw.org/) to compile.
|
In order to compile the demo project, your will need to install [GLFW](http://www.glfw.org/) to compile.
|
||||||
|
192
3rdparty/nanosvg/src/nanosvg.h
vendored
192
3rdparty/nanosvg/src/nanosvg.h
vendored
@ -72,6 +72,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum NSVGpaintType {
|
enum NSVGpaintType {
|
||||||
|
NSVG_PAINT_UNDEF = -1,
|
||||||
NSVG_PAINT_NONE = 0,
|
NSVG_PAINT_NONE = 0,
|
||||||
NSVG_PAINT_COLOR = 1,
|
NSVG_PAINT_COLOR = 1,
|
||||||
NSVG_PAINT_LINEAR_GRADIENT = 2,
|
NSVG_PAINT_LINEAR_GRADIENT = 2,
|
||||||
@ -119,7 +120,7 @@ typedef struct NSVGgradient {
|
|||||||
} NSVGgradient;
|
} NSVGgradient;
|
||||||
|
|
||||||
typedef struct NSVGpaint {
|
typedef struct NSVGpaint {
|
||||||
char type;
|
signed char type;
|
||||||
union {
|
union {
|
||||||
unsigned int color;
|
unsigned int color;
|
||||||
NSVGgradient* gradient;
|
NSVGgradient* gradient;
|
||||||
@ -144,14 +145,17 @@ typedef struct NSVGshape
|
|||||||
float opacity; // Opacity of the shape.
|
float opacity; // Opacity of the shape.
|
||||||
float strokeWidth; // Stroke width (scaled).
|
float strokeWidth; // Stroke width (scaled).
|
||||||
float strokeDashOffset; // Stroke dash offset (scaled).
|
float strokeDashOffset; // Stroke dash offset (scaled).
|
||||||
float strokeDashArray[8]; // Stroke dash array (scaled).
|
float strokeDashArray[8]; // Stroke dash array (scaled).
|
||||||
char strokeDashCount; // Number of dash values in dash array.
|
char strokeDashCount; // Number of dash values in dash array.
|
||||||
char strokeLineJoin; // Stroke join type.
|
char strokeLineJoin; // Stroke join type.
|
||||||
char strokeLineCap; // Stroke cap type.
|
char strokeLineCap; // Stroke cap type.
|
||||||
float miterLimit; // Miter limit
|
float miterLimit; // Miter limit
|
||||||
char fillRule; // Fill rule, see NSVGfillRule.
|
char fillRule; // Fill rule, see NSVGfillRule.
|
||||||
unsigned char flags; // Logical or of NSVG_FLAGS_* flags
|
unsigned char flags; // Logical or of NSVG_FLAGS_* flags
|
||||||
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
|
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
|
||||||
|
char fillGradient[64]; // Optional 'id' of fill gradient
|
||||||
|
char strokeGradient[64]; // Optional 'id' of stroke gradient
|
||||||
|
float xform[6]; // Root transformation for fill/stroke gradient
|
||||||
NSVGpath* paths; // Linked list of paths in the image.
|
NSVGpath* paths; // Linked list of paths in the image.
|
||||||
struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
|
struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
|
||||||
} NSVGshape;
|
} NSVGshape;
|
||||||
@ -182,12 +186,11 @@ void nsvgDelete(NSVGimage* image);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // NANOSVG_H
|
|
||||||
|
|
||||||
#ifdef NANOSVG_IMPLEMENTATION
|
#ifdef NANOSVG_IMPLEMENTATION
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define NSVG_PI (3.14159265358979323846264338327f)
|
#define NSVG_PI (3.14159265358979323846264338327f)
|
||||||
@ -396,7 +399,7 @@ typedef struct NSVGgradientData
|
|||||||
{
|
{
|
||||||
char id[64];
|
char id[64];
|
||||||
char ref[64];
|
char ref[64];
|
||||||
char type;
|
signed char type;
|
||||||
union {
|
union {
|
||||||
NSVGlinearData linear;
|
NSVGlinearData linear;
|
||||||
NSVGradialData radial;
|
NSVGradialData radial;
|
||||||
@ -615,7 +618,7 @@ static void nsvg__curveBounds(float* bounds, float* curve)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSVGparser* nsvg__createParser()
|
static NSVGparser* nsvg__createParser(void)
|
||||||
{
|
{
|
||||||
NSVGparser* p;
|
NSVGparser* p;
|
||||||
p = (NSVGparser*)malloc(sizeof(NSVGparser));
|
p = (NSVGparser*)malloc(sizeof(NSVGparser));
|
||||||
@ -819,9 +822,8 @@ static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
|
static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType)
|
||||||
{
|
{
|
||||||
NSVGattrib* attr = nsvg__getAttr(p);
|
|
||||||
NSVGgradientData* data = NULL;
|
NSVGgradientData* data = NULL;
|
||||||
NSVGgradientData* ref = NULL;
|
NSVGgradientData* ref = NULL;
|
||||||
NSVGgradientStop* stops = NULL;
|
NSVGgradientStop* stops = NULL;
|
||||||
@ -896,7 +898,7 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsvg__xformMultiply(grad->xform, data->xform);
|
nsvg__xformMultiply(grad->xform, data->xform);
|
||||||
nsvg__xformMultiply(grad->xform, attr->xform);
|
nsvg__xformMultiply(grad->xform, xform);
|
||||||
|
|
||||||
grad->spread = data->spread;
|
grad->spread = data->spread;
|
||||||
memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
|
memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
|
||||||
@ -961,6 +963,9 @@ static void nsvg__addShape(NSVGparser* p)
|
|||||||
|
|
||||||
memcpy(shape->id, attr->id, sizeof shape->id);
|
memcpy(shape->id, attr->id, sizeof shape->id);
|
||||||
memcpy(shape->title, attr->title, sizeof shape->title);
|
memcpy(shape->title, attr->title, sizeof shape->title);
|
||||||
|
memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient);
|
||||||
|
memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient);
|
||||||
|
memcpy(shape->xform, attr->xform, sizeof shape->xform);
|
||||||
scale = nsvg__getAverageScale(attr->xform);
|
scale = nsvg__getAverageScale(attr->xform);
|
||||||
shape->strokeWidth = attr->strokeWidth * scale;
|
shape->strokeWidth = attr->strokeWidth * scale;
|
||||||
shape->strokeDashOffset = attr->strokeDashOffset * scale;
|
shape->strokeDashOffset = attr->strokeDashOffset * scale;
|
||||||
@ -996,13 +1001,7 @@ static void nsvg__addShape(NSVGparser* p)
|
|||||||
shape->fill.color = attr->fillColor;
|
shape->fill.color = attr->fillColor;
|
||||||
shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
|
shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
|
||||||
} else if (attr->hasFill == 2) {
|
} else if (attr->hasFill == 2) {
|
||||||
float inv[6], localBounds[4];
|
shape->fill.type = NSVG_PAINT_UNDEF;
|
||||||
nsvg__xformInverse(inv, attr->xform);
|
|
||||||
nsvg__getLocalBounds(localBounds, shape, inv);
|
|
||||||
shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
|
|
||||||
if (shape->fill.gradient == NULL) {
|
|
||||||
shape->fill.type = NSVG_PAINT_NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set stroke
|
// Set stroke
|
||||||
@ -1013,12 +1012,7 @@ static void nsvg__addShape(NSVGparser* p)
|
|||||||
shape->stroke.color = attr->strokeColor;
|
shape->stroke.color = attr->strokeColor;
|
||||||
shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
|
shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
|
||||||
} else if (attr->hasStroke == 2) {
|
} else if (attr->hasStroke == 2) {
|
||||||
float inv[6], localBounds[4];
|
shape->stroke.type = NSVG_PAINT_UNDEF;
|
||||||
nsvg__xformInverse(inv, attr->xform);
|
|
||||||
nsvg__getLocalBounds(localBounds, shape, inv);
|
|
||||||
shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
|
|
||||||
if (shape->stroke.gradient == NULL)
|
|
||||||
shape->stroke.type = NSVG_PAINT_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
@ -1200,6 +1194,19 @@ static const char* nsvg__parseNumber(const char* s, char* it, const int size)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it)
|
||||||
|
{
|
||||||
|
it[0] = '\0';
|
||||||
|
while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
|
||||||
|
if (!*s) return s;
|
||||||
|
if (*s == '0' || *s == '1') {
|
||||||
|
it[0] = *s++;
|
||||||
|
it[1] = '\0';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* nsvg__getNextPathItem(const char* s, char* it)
|
static const char* nsvg__getNextPathItem(const char* s, char* it)
|
||||||
{
|
{
|
||||||
it[0] = '\0';
|
it[0] = '\0';
|
||||||
@ -1220,35 +1227,66 @@ static const char* nsvg__getNextPathItem(const char* s, char* it)
|
|||||||
|
|
||||||
static unsigned int nsvg__parseColorHex(const char* str)
|
static unsigned int nsvg__parseColorHex(const char* str)
|
||||||
{
|
{
|
||||||
unsigned int c = 0, r = 0, g = 0, b = 0;
|
unsigned int r=0, g=0, b=0;
|
||||||
int n = 0;
|
if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex
|
||||||
str++; // skip #
|
return NSVG_RGB(r, g, b);
|
||||||
// Calculate number of characters.
|
if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa
|
||||||
while(str[n] && !nsvg__isspace(str[n]))
|
return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), ..
|
||||||
n++;
|
return NSVG_RGB(128, 128, 128);
|
||||||
if (n == 6) {
|
|
||||||
sscanf(str, "%x", &c);
|
|
||||||
} else if (n == 3) {
|
|
||||||
sscanf(str, "%x", &c);
|
|
||||||
c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8);
|
|
||||||
c |= c<<4;
|
|
||||||
}
|
|
||||||
r = (c >> 16) & 0xff;
|
|
||||||
g = (c >> 8) & 0xff;
|
|
||||||
b = c & 0xff;
|
|
||||||
return NSVG_RGB(r,g,b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters).
|
||||||
|
// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors
|
||||||
|
// for backwards compatibility. Note: other image viewers return black instead.
|
||||||
|
|
||||||
static unsigned int nsvg__parseColorRGB(const char* str)
|
static unsigned int nsvg__parseColorRGB(const char* str)
|
||||||
{
|
{
|
||||||
int r = -1, g = -1, b = -1;
|
int i;
|
||||||
char s1[32]="", s2[32]="";
|
unsigned int rgbi[3];
|
||||||
sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
|
float rgbf[3];
|
||||||
if (strchr(s1, '%')) {
|
// try decimal integers first
|
||||||
return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100);
|
if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) {
|
||||||
} else {
|
// integers failed, try percent values (float, locale independent)
|
||||||
return NSVG_RGB(r,g,b);
|
const char delimiter[3] = {',', ',', ')'};
|
||||||
|
str += 4; // skip "rgb("
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces
|
||||||
|
if (*str == '+') str++; // skip '+' (don't allow '-')
|
||||||
|
if (!*str) break;
|
||||||
|
rgbf[i] = nsvg__atof(str);
|
||||||
|
|
||||||
|
// Note 1: it would be great if nsvg__atof() returned how many
|
||||||
|
// bytes it consumed but it doesn't. We need to skip the number,
|
||||||
|
// the '%' character, spaces, and the delimiter ',' or ')'.
|
||||||
|
|
||||||
|
// Note 2: The following code does not allow values like "33.%",
|
||||||
|
// i.e. a decimal point w/o fractional part, but this is consistent
|
||||||
|
// with other image viewers, e.g. firefox, chrome, eog, gimp.
|
||||||
|
|
||||||
|
while (*str && nsvg__isdigit(*str)) str++; // skip integer part
|
||||||
|
if (*str == '.') {
|
||||||
|
str++;
|
||||||
|
if (!nsvg__isdigit(*str)) break; // error: no digit after '.'
|
||||||
|
while (*str && nsvg__isdigit(*str)) str++; // skip fractional part
|
||||||
|
}
|
||||||
|
if (*str == '%') str++; else break;
|
||||||
|
while (nsvg__isspace(*str)) str++;
|
||||||
|
if (*str == delimiter[i]) str++;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
if (i == 3) {
|
||||||
|
rgbi[0] = roundf(rgbf[0] * 2.55f);
|
||||||
|
rgbi[1] = roundf(rgbf[1] * 2.55f);
|
||||||
|
rgbi[2] = roundf(rgbf[2] * 2.55f);
|
||||||
|
} else {
|
||||||
|
rgbi[0] = rgbi[1] = rgbi[2] = 128;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// clip values as the CSS spec requires
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (rgbi[i] > 255) rgbi[i] = 255;
|
||||||
|
}
|
||||||
|
return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct NSVGNamedColor {
|
typedef struct NSVGNamedColor {
|
||||||
@ -1478,8 +1516,8 @@ static int nsvg__isCoordinate(const char* s)
|
|||||||
// optional sign
|
// optional sign
|
||||||
if (*s == '-' || *s == '+')
|
if (*s == '-' || *s == '+')
|
||||||
s++;
|
s++;
|
||||||
// must have at least one digit
|
// must have at least one digit, or start by a dot
|
||||||
return nsvg__isdigit(*s);
|
return (nsvg__isdigit(*s) || *s == '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
|
static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
|
||||||
@ -1656,9 +1694,9 @@ static void nsvg__parseUrl(char* id, const char* str)
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
str += 4; // "url(";
|
str += 4; // "url(";
|
||||||
if (*str == '#')
|
if (*str && *str == '#')
|
||||||
str++;
|
str++;
|
||||||
while (i < 63 && *str != ')') {
|
while (i < 63 && *str && *str != ')') {
|
||||||
id[i] = *str++;
|
id[i] = *str++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -2192,7 +2230,12 @@ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args,
|
|||||||
// The loop assumes an iteration per end point (including start and end), this +1.
|
// The loop assumes an iteration per end point (including start and end), this +1.
|
||||||
ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
|
ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
|
||||||
hda = (da / (float)ndivs) / 2.0f;
|
hda = (da / (float)ndivs) / 2.0f;
|
||||||
kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
|
// Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite)
|
||||||
|
if ((hda < 1e-3f) && (hda > -1e-3f))
|
||||||
|
hda *= 0.5f;
|
||||||
|
else
|
||||||
|
hda = (1.0f - cosf(hda)) / sinf(hda);
|
||||||
|
kappa = fabsf(4.0f / 3.0f * hda);
|
||||||
if (da < 0.0f)
|
if (da < 0.0f)
|
||||||
kappa = -kappa;
|
kappa = -kappa;
|
||||||
|
|
||||||
@ -2249,7 +2292,11 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||||||
nargs = 0;
|
nargs = 0;
|
||||||
|
|
||||||
while (*s) {
|
while (*s) {
|
||||||
s = nsvg__getNextPathItem(s, item);
|
item[0] = '\0';
|
||||||
|
if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))
|
||||||
|
s = nsvg__getNextPathItemWhenArcFlag(s, item);
|
||||||
|
if (!*item)
|
||||||
|
s = nsvg__getNextPathItem(s, item);
|
||||||
if (!*item) break;
|
if (!*item) break;
|
||||||
if (cmd != '\0' && nsvg__isCoordinate(item)) {
|
if (cmd != '\0' && nsvg__isCoordinate(item)) {
|
||||||
if (nargs < 10)
|
if (nargs < 10)
|
||||||
@ -2594,7 +2641,7 @@ static void nsvg__parseSVG(NSVGparser* p, const char** attr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
|
static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
|
NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
|
||||||
@ -2955,6 +3002,36 @@ static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nsvg__createGradients(NSVGparser* p)
|
||||||
|
{
|
||||||
|
NSVGshape* shape;
|
||||||
|
|
||||||
|
for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
|
||||||
|
if (shape->fill.type == NSVG_PAINT_UNDEF) {
|
||||||
|
if (shape->fillGradient[0] != '\0') {
|
||||||
|
float inv[6], localBounds[4];
|
||||||
|
nsvg__xformInverse(inv, shape->xform);
|
||||||
|
nsvg__getLocalBounds(localBounds, shape, inv);
|
||||||
|
shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type);
|
||||||
|
}
|
||||||
|
if (shape->fill.type == NSVG_PAINT_UNDEF) {
|
||||||
|
shape->fill.type = NSVG_PAINT_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shape->stroke.type == NSVG_PAINT_UNDEF) {
|
||||||
|
if (shape->strokeGradient[0] != '\0') {
|
||||||
|
float inv[6], localBounds[4];
|
||||||
|
nsvg__xformInverse(inv, shape->xform);
|
||||||
|
nsvg__getLocalBounds(localBounds, shape, inv);
|
||||||
|
shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type);
|
||||||
|
}
|
||||||
|
if (shape->stroke.type == NSVG_PAINT_UNDEF) {
|
||||||
|
shape->stroke.type = NSVG_PAINT_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NSVGimage* nsvgParse(char* input, const char* units, float dpi)
|
NSVGimage* nsvgParse(char* input, const char* units, float dpi)
|
||||||
{
|
{
|
||||||
NSVGparser* p;
|
NSVGparser* p;
|
||||||
@ -2968,6 +3045,9 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
|
|||||||
|
|
||||||
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
|
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
|
||||||
|
|
||||||
|
// Create gradients after all definitions have been parsed
|
||||||
|
nsvg__createGradients(p);
|
||||||
|
|
||||||
// Scale to viewBox
|
// Scale to viewBox
|
||||||
nsvg__scaleToViewbox(p, units);
|
nsvg__scaleToViewbox(p, units);
|
||||||
|
|
||||||
@ -3054,4 +3134,6 @@ void nsvgDelete(NSVGimage* image)
|
|||||||
free(image);
|
free(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // NANOSVG_IMPLEMENTATION
|
||||||
|
|
||||||
|
#endif // NANOSVG_H
|
||||||
|
24
3rdparty/nanosvg/src/nanosvgrast.h
vendored
24
3rdparty/nanosvg/src/nanosvgrast.h
vendored
@ -25,6 +25,8 @@
|
|||||||
#ifndef NANOSVGRAST_H
|
#ifndef NANOSVGRAST_H
|
||||||
#define NANOSVGRAST_H
|
#define NANOSVGRAST_H
|
||||||
|
|
||||||
|
#include "nanosvg.h"
|
||||||
|
|
||||||
#ifndef NANOSVGRAST_CPLUSPLUS
|
#ifndef NANOSVGRAST_CPLUSPLUS
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -47,7 +49,7 @@ typedef struct NSVGrasterizer NSVGrasterizer;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Allocated rasterizer context.
|
// Allocated rasterizer context.
|
||||||
NSVGrasterizer* nsvgCreateRasterizer();
|
NSVGrasterizer* nsvgCreateRasterizer(void);
|
||||||
|
|
||||||
// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
|
// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
|
||||||
// r - pointer to rasterizer context
|
// r - pointer to rasterizer context
|
||||||
@ -72,11 +74,11 @@ void nsvgDeleteRasterizer(NSVGrasterizer*);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // NANOSVGRAST_H
|
|
||||||
|
|
||||||
#ifdef NANOSVGRAST_IMPLEMENTATION
|
#ifdef NANOSVGRAST_IMPLEMENTATION
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define NSVG__SUBSAMPLES 5
|
#define NSVG__SUBSAMPLES 5
|
||||||
#define NSVG__FIXSHIFT 10
|
#define NSVG__FIXSHIFT 10
|
||||||
@ -112,7 +114,7 @@ typedef struct NSVGmemPage {
|
|||||||
} NSVGmemPage;
|
} NSVGmemPage;
|
||||||
|
|
||||||
typedef struct NSVGcachedPaint {
|
typedef struct NSVGcachedPaint {
|
||||||
char type;
|
signed char type;
|
||||||
char spread;
|
char spread;
|
||||||
float xform[6];
|
float xform[6];
|
||||||
unsigned int colors[256];
|
unsigned int colors[256];
|
||||||
@ -148,7 +150,7 @@ struct NSVGrasterizer
|
|||||||
int width, height, stride;
|
int width, height, stride;
|
||||||
};
|
};
|
||||||
|
|
||||||
NSVGrasterizer* nsvgCreateRasterizer()
|
NSVGrasterizer* nsvgCreateRasterizer(void)
|
||||||
{
|
{
|
||||||
NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
|
NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
|
||||||
if (r == NULL) goto error;
|
if (r == NULL) goto error;
|
||||||
@ -956,7 +958,7 @@ static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a
|
|||||||
|
|
||||||
static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||||
{
|
{
|
||||||
return (r) | (g << 8) | (b << 16) | (a << 24);
|
return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
|
static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
|
||||||
@ -1406,7 +1408,8 @@ void nsvgRasterize(NSVGrasterizer* r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rasterize edges
|
// Rasterize edges
|
||||||
qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
|
if (r->nedges != 0)
|
||||||
|
qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
|
||||||
|
|
||||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||||
nsvg__initPaint(&cache, &shape->fill, shape->opacity);
|
nsvg__initPaint(&cache, &shape->fill, shape->opacity);
|
||||||
@ -1432,7 +1435,8 @@ void nsvgRasterize(NSVGrasterizer* r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rasterize edges
|
// Rasterize edges
|
||||||
qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
|
if (r->nedges != 0)
|
||||||
|
qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
|
||||||
|
|
||||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||||
nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
|
nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
|
||||||
@ -1449,4 +1453,6 @@ void nsvgRasterize(NSVGrasterizer* r,
|
|||||||
r->stride = 0;
|
r->stride = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // NANOSVGRAST_IMPLEMENTATION
|
||||||
|
|
||||||
|
#endif // NANOSVGRAST_H
|
||||||
|
Loading…
Reference in New Issue
Block a user