|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <string.h></string.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdlib.h></stdlib.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <math.h></math.h>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <qtextstream></qtextstream>
|
|
Toshihiro Shimizu |
890ddd |
#include <qfile></qfile>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tiio_svg.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokeoutline.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcurves.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace //svg_parser
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath {
|
|
Toshihiro Shimizu |
890ddd |
float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
|
|
Toshihiro Shimizu |
890ddd |
int npts; // Total number of bezier points.
|
|
Toshihiro Shimizu |
890ddd |
char closed; // Flag indicating if shapes should be treated as closed.
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *next; // Pointer to next path, or NULL if last element.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape {
|
|
Toshihiro Shimizu |
890ddd |
unsigned int fillColor; // Fill color
|
|
Toshihiro Shimizu |
890ddd |
unsigned int strokeColor; // Stroke color
|
|
Toshihiro Shimizu |
890ddd |
float strokeWidth; // Stroke width (scaled)
|
|
Toshihiro Shimizu |
890ddd |
char hasFill; // Flag indicating if fill exists.
|
|
Toshihiro Shimizu |
890ddd |
char hasStroke; // Flag indicating id store exists
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *paths; // Linked list of paths in the image.
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape *next; // Pointer to next shape, or NULL if last element.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage {
|
|
Toshihiro Shimizu |
890ddd |
float width; // Width of the image, or -1.0f of not set.
|
|
Toshihiro Shimizu |
890ddd |
float height; // Height of the image, or -1.0f of not set.
|
|
Toshihiro Shimizu |
890ddd |
char wunits[8]; // Units of the width attribute
|
|
Toshihiro Shimizu |
890ddd |
char hunits[8]; // Units of the height attribute
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape *shapes; // Linked list of shapes in the image.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_PI 3.14159265358979323846264338327f
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_KAPPA90 0.5522847493f // Lenght proportional to radius of a cubic bezier handle for 90deg arcs.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _MSC_VER
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(disable : 4996) // Switch off security warnings
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings
|
|
Toshihiro Shimizu |
890ddd |
#ifdef __cplusplus
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_INLINE inline
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_INLINE
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_INLINE inline
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__isspace(char c)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return strchr(" \t\n\v\f\r", c) != 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__isdigit(char c)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return strchr("0123456789", c) != 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__isnum(char c)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return strchr("0123456789+-.eE", c) != 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Simple XML parser
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_XML_TAG 1
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_XML_CONTENT 2
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_XML_MAX_ATTRIBS 256
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseContent(char *s,
|
|
Toshihiro Shimizu |
890ddd |
void (*contentCb)(void *ud, const char *s),
|
|
Toshihiro Shimizu |
890ddd |
void *ud)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Trim start white spaces
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isspace(*s))
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (!*s)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (contentCb)
|
|
Toshihiro Shimizu |
890ddd |
(*contentCb)(ud, s);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseElement(char *s,
|
|
Toshihiro Shimizu |
890ddd |
void (*startelCb)(void *ud, const char *el, const char **attr),
|
|
Toshihiro Shimizu |
890ddd |
void (*endelCb)(void *ud, const char *el),
|
|
Toshihiro Shimizu |
890ddd |
void *ud)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const char *attr[NSVG_XML_MAX_ATTRIBS];
|
|
Toshihiro Shimizu |
890ddd |
int nattr = 0;
|
|
Toshihiro Shimizu |
890ddd |
char *name;
|
|
Toshihiro Shimizu |
890ddd |
int start = 0;
|
|
Toshihiro Shimizu |
890ddd |
int end = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Skip white space after the '<'
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isspace(*s))
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Check if the tag is end tag
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '/') {
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
end = 1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
start = 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Skip comments, data and preprocessor stuff.
|
|
Toshihiro Shimizu |
890ddd |
if (!*s || *s == '?' || *s == '!')
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Get tag name
|
|
Toshihiro Shimizu |
890ddd |
name = s;
|
|
Toshihiro Shimizu |
890ddd |
while (*s && !nsvg__isspace(*s))
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (*s) {
|
|
Toshihiro Shimizu |
890ddd |
*s++ = '\0';
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Get attribs
|
|
Toshihiro Shimizu |
890ddd |
while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
|
|
Toshihiro Shimizu |
890ddd |
// Skip white space before the attrib name
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isspace(*s))
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (!*s)
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '/') {
|
|
Toshihiro Shimizu |
890ddd |
end = 1;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
attr[nattr++] = s;
|
|
Toshihiro Shimizu |
890ddd |
// Find end of the attrib name.
|
|
Toshihiro Shimizu |
890ddd |
while (*s && !nsvg__isspace(*s) && *s != '=')
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (*s) {
|
|
Toshihiro Shimizu |
890ddd |
*s++ = '\0';
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// Skip until the beginning of the value.
|
|
Toshihiro Shimizu |
890ddd |
while (*s && *s != '\"')
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (!*s)
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
// Store value and find the end of it.
|
|
Toshihiro Shimizu |
890ddd |
attr[nattr++] = s;
|
|
Toshihiro Shimizu |
890ddd |
while (*s && *s != '\"')
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (*s) {
|
|
Toshihiro Shimizu |
890ddd |
*s++ = '\0';
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// List terminator
|
|
Toshihiro Shimizu |
890ddd |
attr[nattr++] = 0;
|
|
Toshihiro Shimizu |
890ddd |
attr[nattr++] = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Call callbacks.
|
|
Toshihiro Shimizu |
890ddd |
if (start && startelCb)
|
|
Toshihiro Shimizu |
890ddd |
(*startelCb)(ud, name, attr);
|
|
Toshihiro Shimizu |
890ddd |
if (end && endelCb)
|
|
Toshihiro Shimizu |
890ddd |
(*endelCb)(ud, name);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseXML(char *input,
|
|
Toshihiro Shimizu |
890ddd |
void (*startelCb)(void *ud, const char *el, const char **attr),
|
|
Toshihiro Shimizu |
890ddd |
void (*endelCb)(void *ud, const char *el),
|
|
Toshihiro Shimizu |
890ddd |
void (*contentCb)(void *ud, const char *s),
|
|
Toshihiro Shimizu |
890ddd |
void *ud)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
char *s = input;
|
|
Toshihiro Shimizu |
890ddd |
char *mark = s;
|
|
Toshihiro Shimizu |
890ddd |
int state = NSVG_XML_CONTENT;
|
|
Toshihiro Shimizu |
890ddd |
while (*s) {
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '<' && state == NSVG_XML_CONTENT) {
|
|
Toshihiro Shimizu |
890ddd |
// Start of a tag
|
|
Toshihiro Shimizu |
890ddd |
*s++ = '\0';
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseContent(mark, contentCb, ud);
|
|
Toshihiro Shimizu |
890ddd |
mark = s;
|
|
Toshihiro Shimizu |
890ddd |
state = NSVG_XML_TAG;
|
|
Toshihiro Shimizu |
890ddd |
} else if (*s == '>' && state == NSVG_XML_TAG) {
|
|
Toshihiro Shimizu |
890ddd |
// Start of a content or new tag.
|
|
Toshihiro Shimizu |
890ddd |
*s++ = '\0';
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseElement(mark, startelCb, endelCb, ud);
|
|
Toshihiro Shimizu |
890ddd |
mark = s;
|
|
Toshihiro Shimizu |
890ddd |
state = NSVG_XML_CONTENT;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* Simple SVG parser. */
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_MAX_ATTR 128
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib {
|
|
Toshihiro Shimizu |
890ddd |
float xform[6];
|
|
Toshihiro Shimizu |
890ddd |
unsigned int fillColor;
|
|
Toshihiro Shimizu |
890ddd |
unsigned int strokeColor;
|
|
Toshihiro Shimizu |
890ddd |
float fillOpacity;
|
|
Toshihiro Shimizu |
890ddd |
float strokeOpacity;
|
|
Toshihiro Shimizu |
890ddd |
float strokeWidth;
|
|
Toshihiro Shimizu |
890ddd |
char hasFill;
|
|
Toshihiro Shimizu |
890ddd |
char hasStroke;
|
|
Toshihiro Shimizu |
890ddd |
char visible;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser {
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib attr[NSVG_MAX_ATTR];
|
|
Toshihiro Shimizu |
890ddd |
int attrHead;
|
|
Toshihiro Shimizu |
890ddd |
float *pts;
|
|
Toshihiro Shimizu |
890ddd |
int npts;
|
|
Toshihiro Shimizu |
890ddd |
int cpts;
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *plist;
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage *image;
|
|
Toshihiro Shimizu |
890ddd |
char pathFlag;
|
|
Toshihiro Shimizu |
890ddd |
char defsFlag;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetIdentity(float *t)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t[0] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetTranslation(float *t, float tx, float ty)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t[0] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = tx;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = ty;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetScale(float *t, float sx, float sy)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t[0] = sx;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = sy;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetSkewX(float *t, float a)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t[0] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = tanf(a);
|
|
Toshihiro Shimizu |
890ddd |
t[3] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetSkewY(float *t, float a)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
t[0] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = tanf(a);
|
|
Toshihiro Shimizu |
890ddd |
t[2] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformSetRotation(float *t, float a)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float cs = cosf(a), sn = sinf(a);
|
|
Toshihiro Shimizu |
890ddd |
t[0] = cs;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = sn;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = -sn;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = cs;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformMultiply(float *t, float *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float t0 = t[0] * s[0] + t[1] * s[2];
|
|
Toshihiro Shimizu |
890ddd |
float t2 = t[2] * s[0] + t[3] * s[2];
|
|
Toshihiro Shimizu |
890ddd |
float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
|
|
Toshihiro Shimizu |
890ddd |
t[1] = t[0] * s[1] + t[1] * s[3];
|
|
Toshihiro Shimizu |
890ddd |
t[3] = t[2] * s[1] + t[3] * s[3];
|
|
Toshihiro Shimizu |
890ddd |
t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
|
|
Toshihiro Shimizu |
890ddd |
t[0] = t0;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = t2;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = t4;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformPremultiply(float *t, float *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float s2[6];
|
|
Toshihiro Shimizu |
890ddd |
memcpy(s2, s, sizeof(float) * 6);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformMultiply(s2, t);
|
|
Toshihiro Shimizu |
890ddd |
memcpy(t, s2, sizeof(float) * 6);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformPoint(float *dx, float *dy, float x, float y, float *t)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
*dx = x * t[0] + y * t[2] + t[4];
|
|
Toshihiro Shimizu |
890ddd |
*dy = x * t[1] + y * t[3] + t[5];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__xformVec(float *dx, float *dy, float x, float y, float *t)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
*dx = x * t[0] + y * t[2];
|
|
Toshihiro Shimizu |
890ddd |
*dy = x * t[1] + y * t[3];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser *nsvg__createParser()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser *p;
|
|
Toshihiro Shimizu |
890ddd |
p = (struct NSVGParser *)malloc(sizeof(struct NSVGParser));
|
|
Toshihiro Shimizu |
890ddd |
if (p == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
memset(p, 0, sizeof(struct NSVGParser));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
p->image = (struct NSVGimage *)malloc(sizeof(struct NSVGimage));
|
|
Toshihiro Shimizu |
890ddd |
if (p->image == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
memset(p->image, 0, sizeof(struct NSVGimage));
|
|
Toshihiro Shimizu |
890ddd |
p->image->width = -1.0f;
|
|
Toshihiro Shimizu |
890ddd |
p->image->height = -1.0f;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Init style
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetIdentity(p->attr[0].xform);
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].fillColor = 0;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].strokeColor = 0;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].fillOpacity = 1;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].strokeOpacity = 1;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].strokeWidth = 1;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].hasFill = 0;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].hasStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
p->attr[0].visible = 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return p;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
if (p) {
|
|
Toshihiro Shimizu |
890ddd |
if (p->image)
|
|
Toshihiro Shimizu |
890ddd |
free(p->image);
|
|
Toshihiro Shimizu |
890ddd |
free(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return NULL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__deletePaths(struct NSVGpath *path)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
while (path) {
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *next = path->next;
|
|
Toshihiro Shimizu |
890ddd |
if (path->pts != NULL)
|
|
Toshihiro Shimizu |
890ddd |
free(path->pts);
|
|
Toshihiro Shimizu |
890ddd |
free(path);
|
|
Toshihiro Shimizu |
890ddd |
path = next;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvgDelete(struct NSVGimage *image)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape *next, *shape;
|
|
Toshihiro Shimizu |
890ddd |
if (image == NULL)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
shape = image->shapes;
|
|
Toshihiro Shimizu |
890ddd |
while (shape != NULL) {
|
|
Toshihiro Shimizu |
890ddd |
next = shape->next;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__deletePaths(shape->paths);
|
|
Toshihiro Shimizu |
890ddd |
free(shape);
|
|
Toshihiro Shimizu |
890ddd |
shape = next;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
free(image);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__deleteParser(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (p != NULL) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__deletePaths(p->plist);
|
|
Toshihiro Shimizu |
890ddd |
nsvgDelete(p->image);
|
|
Toshihiro Shimizu |
890ddd |
free(p->pts);
|
|
Toshihiro Shimizu |
890ddd |
free(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__resetPath(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
p->npts = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__addPoint(struct NSVGParser *p, float x, float y)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts + 1 > p->cpts) {
|
|
Toshihiro Shimizu |
890ddd |
p->cpts = p->cpts ? p->cpts * 2 : 8;
|
|
Toshihiro Shimizu |
890ddd |
p->pts = (float *)realloc(p->pts, p->cpts * 2 * sizeof(float));
|
|
Toshihiro Shimizu |
890ddd |
if (!p->pts)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
p->pts[p->npts * 2 + 0] = x;
|
|
Toshihiro Shimizu |
890ddd |
p->pts[p->npts * 2 + 1] = y;
|
|
Toshihiro Shimizu |
890ddd |
p->npts++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__moveTo(struct NSVGParser *p, float x, float y)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, x, y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__lineTo(struct NSVGParser *p, float x, float y)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float px, py, dx, dy;
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts > 0) {
|
|
Toshihiro Shimizu |
890ddd |
px = p->pts[(p->npts - 1) * 2 + 0];
|
|
Toshihiro Shimizu |
890ddd |
py = p->pts[(p->npts - 1) * 2 + 1];
|
|
Toshihiro Shimizu |
890ddd |
dx = x - px;
|
|
Toshihiro Shimizu |
890ddd |
dy = y - py;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, x, y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__cubicBezTo(struct NSVGParser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, cpx1, cpy1);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, cpx2, cpy2);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPoint(p, x, y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib *nsvg__getAttr(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return &p->attr[p->attrHead];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pushAttr(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (p->attrHead < NSVG_MAX_ATTR - 1) {
|
|
Toshihiro Shimizu |
890ddd |
p->attrHead++;
|
|
Toshihiro Shimizu |
890ddd |
memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(struct NSVGAttrib));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__popAttr(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (p->attrHead > 0)
|
|
Toshihiro Shimizu |
890ddd |
p->attrHead--;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__addShape(struct NSVGParser *p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib *attr = nsvg__getAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
float scale = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape *shape, *cur, *prev;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (p->plist == NULL)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
shape = (struct NSVGshape *)malloc(sizeof(struct NSVGshape));
|
|
Toshihiro Shimizu |
890ddd |
if (shape == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
memset(shape, 0, sizeof(struct NSVGshape));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
scale = nsvg__maxf(fabsf(attr->xform[0]), fabsf(attr->xform[3]));
|
|
Toshihiro Shimizu |
890ddd |
shape->hasFill = attr->hasFill;
|
|
Toshihiro Shimizu |
890ddd |
shape->hasStroke = attr->hasStroke;
|
|
Toshihiro Shimizu |
890ddd |
shape->strokeWidth = attr->strokeWidth * scale;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
shape->fillColor = attr->fillColor;
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasFill)
|
|
Toshihiro Shimizu |
890ddd |
shape->fillColor |= (unsigned int)(attr->fillOpacity * 255) << 24;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
shape->strokeColor = attr->strokeColor;
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasStroke)
|
|
Toshihiro Shimizu |
890ddd |
shape->strokeColor |= (unsigned int)(attr->strokeOpacity * 255) << 24;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
shape->paths = p->plist;
|
|
Toshihiro Shimizu |
890ddd |
p->plist = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Add to tail
|
|
Toshihiro Shimizu |
890ddd |
prev = NULL;
|
|
Toshihiro Shimizu |
890ddd |
cur = p->image->shapes;
|
|
Toshihiro Shimizu |
890ddd |
while (cur != NULL) {
|
|
Toshihiro Shimizu |
890ddd |
prev = cur;
|
|
Toshihiro Shimizu |
890ddd |
cur = cur->next;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (prev == NULL)
|
|
Toshihiro Shimizu |
890ddd |
p->image->shapes = shape;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
prev->next = shape;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
if (shape)
|
|
Toshihiro Shimizu |
890ddd |
free(shape);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__addPath(struct NSVGParser *p, char closed)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib *attr = nsvg__getAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *path = NULL;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (closed)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, p->pts[0], p->pts[1]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
path = (struct NSVGpath *)malloc(sizeof(struct NSVGpath));
|
|
Toshihiro Shimizu |
890ddd |
if (path == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
memset(path, 0, sizeof(struct NSVGpath));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
|
|
Toshihiro Shimizu |
890ddd |
if (path->pts == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
path->closed = closed;
|
|
Toshihiro Shimizu |
890ddd |
path->npts = p->npts;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Transform path.
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < p->npts; ++i)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPoint(&path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
path->next = p->plist;
|
|
Toshihiro Shimizu |
890ddd |
p->plist = path;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
if (path != NULL) {
|
|
Toshihiro Shimizu |
890ddd |
if (path->pts != NULL)
|
|
Toshihiro Shimizu |
890ddd |
free(path->pts);
|
|
Toshihiro Shimizu |
890ddd |
free(path);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const char *nsvg__getNextPathItem(const char *s, char *it)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
it[0] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
// Skip white spaces and commas
|
|
Toshihiro Shimizu |
890ddd |
while (*s && (nsvg__isspace(*s) || *s == ','))
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (!*s)
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '-' || *s == '+' || nsvg__isdigit(*s)) {
|
|
Toshihiro Shimizu |
890ddd |
// sign
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '-' || *s == '+') {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// integer part
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isdigit(*s)) {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '.') {
|
|
Toshihiro Shimizu |
890ddd |
// decimal point
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
// fraction part
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isdigit(*s)) {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// exponent
|
|
Toshihiro Shimizu |
890ddd |
if (*s == 'e' || *s == 'E') {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
if (*s == '-' || *s == '+') {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
while (*s && nsvg__isdigit(*s)) {
|
|
Toshihiro Shimizu |
890ddd |
if (i < 63)
|
|
Toshihiro Shimizu |
890ddd |
it[i++] = *s;
|
|
Toshihiro Shimizu |
890ddd |
s++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
it[i] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
// Parse command
|
|
Toshihiro Shimizu |
890ddd |
it[0] = *s++;
|
|
Toshihiro Shimizu |
890ddd |
it[1] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
unsigned int nsvg__parseColorHex(const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
unsigned int c = 0, r = 0, g = 0, b = 0;
|
|
Toshihiro Shimizu |
890ddd |
int n = 0;
|
|
Toshihiro Shimizu |
890ddd |
str++; // skip #
|
|
Toshihiro Shimizu |
890ddd |
// Calculate number of characters.
|
|
Toshihiro Shimizu |
890ddd |
while (str[n] && !nsvg__isspace(str[n]))
|
|
Toshihiro Shimizu |
890ddd |
n++;
|
|
Toshihiro Shimizu |
890ddd |
if (n == 6) {
|
|
Toshihiro Shimizu |
890ddd |
sscanf(str, "%x", &c);
|
|
Toshihiro Shimizu |
890ddd |
} else if (n == 3) {
|
|
Toshihiro Shimizu |
890ddd |
sscanf(str, "%x", &c);
|
|
Toshihiro Shimizu |
890ddd |
c = (c & 0xf) | ((c & 0xf0) << 4) | ((c & 0xf00) << 8);
|
|
Toshihiro Shimizu |
890ddd |
c |= c << 4;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
r = (c >> 16) & 0xff;
|
|
Toshihiro Shimizu |
890ddd |
g = (c >> 8) & 0xff;
|
|
Toshihiro Shimizu |
890ddd |
b = c & 0xff;
|
|
Toshihiro Shimizu |
890ddd |
return NSVG_RGB(r, g, b);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
unsigned int nsvg__parseColorRGB(const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int r = -1, g = -1, b = -1;
|
|
Toshihiro Shimizu |
890ddd |
char s1[32] = "", s2[32] = "";
|
|
Toshihiro Shimizu |
890ddd |
sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
|
|
Toshihiro Shimizu |
890ddd |
if (strchr(s1, '%')) {
|
|
Toshihiro Shimizu |
890ddd |
return NSVG_RGB((r * 255) / 100, (g * 255) / 100, (b * 255) / 100);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
return NSVG_RGB(r, g, b);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGNamedColor {
|
|
Toshihiro Shimizu |
890ddd |
const char *name;
|
|
Toshihiro Shimizu |
890ddd |
unsigned int color;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGNamedColor nsvg__colors[] = {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{"red", NSVG_RGB(255, 0, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"green", NSVG_RGB(0, 128, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"blue", NSVG_RGB(0, 0, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"yellow", NSVG_RGB(255, 255, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"cyan", NSVG_RGB(0, 255, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"magenta", NSVG_RGB(255, 0, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"black", NSVG_RGB(0, 0, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"grey", NSVG_RGB(128, 128, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"gray", NSVG_RGB(128, 128, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"white", NSVG_RGB(255, 255, 255)},
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
{"aliceblue", NSVG_RGB(240, 248, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"antiquewhite", NSVG_RGB(250, 235, 215)},
|
|
Toshihiro Shimizu |
890ddd |
{"aqua", NSVG_RGB(0, 255, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"aquamarine", NSVG_RGB(127, 255, 212)},
|
|
Toshihiro Shimizu |
890ddd |
{"azure", NSVG_RGB(240, 255, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"beige", NSVG_RGB(245, 245, 220)},
|
|
Toshihiro Shimizu |
890ddd |
{"bisque", NSVG_RGB(255, 228, 196)},
|
|
Toshihiro Shimizu |
890ddd |
{"blanchedalmond", NSVG_RGB(255, 235, 205)},
|
|
Toshihiro Shimizu |
890ddd |
{"blueviolet", NSVG_RGB(138, 43, 226)},
|
|
Toshihiro Shimizu |
890ddd |
{"brown", NSVG_RGB(165, 42, 42)},
|
|
Toshihiro Shimizu |
890ddd |
{"burlywood", NSVG_RGB(222, 184, 135)},
|
|
Toshihiro Shimizu |
890ddd |
{"cadetblue", NSVG_RGB(95, 158, 160)},
|
|
Toshihiro Shimizu |
890ddd |
{"chartreuse", NSVG_RGB(127, 255, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"chocolate", NSVG_RGB(210, 105, 30)},
|
|
Toshihiro Shimizu |
890ddd |
{"coral", NSVG_RGB(255, 127, 80)},
|
|
Toshihiro Shimizu |
890ddd |
{"cornflowerblue", NSVG_RGB(100, 149, 237)},
|
|
Toshihiro Shimizu |
890ddd |
{"cornsilk", NSVG_RGB(255, 248, 220)},
|
|
Toshihiro Shimizu |
890ddd |
{"crimson", NSVG_RGB(220, 20, 60)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkblue", NSVG_RGB(0, 0, 139)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkcyan", NSVG_RGB(0, 139, 139)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkgoldenrod", NSVG_RGB(184, 134, 11)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkgray", NSVG_RGB(169, 169, 169)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkgreen", NSVG_RGB(0, 100, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkgrey", NSVG_RGB(169, 169, 169)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkkhaki", NSVG_RGB(189, 183, 107)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkmagenta", NSVG_RGB(139, 0, 139)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkolivegreen", NSVG_RGB(85, 107, 47)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkorange", NSVG_RGB(255, 140, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkorchid", NSVG_RGB(153, 50, 204)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkred", NSVG_RGB(139, 0, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"darksalmon", NSVG_RGB(233, 150, 122)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkseagreen", NSVG_RGB(143, 188, 143)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkslateblue", NSVG_RGB(72, 61, 139)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkslategray", NSVG_RGB(47, 79, 79)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkslategrey", NSVG_RGB(47, 79, 79)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkturquoise", NSVG_RGB(0, 206, 209)},
|
|
Toshihiro Shimizu |
890ddd |
{"darkviolet", NSVG_RGB(148, 0, 211)},
|
|
Toshihiro Shimizu |
890ddd |
{"deeppink", NSVG_RGB(255, 20, 147)},
|
|
Toshihiro Shimizu |
890ddd |
{"deepskyblue", NSVG_RGB(0, 191, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"dimgray", NSVG_RGB(105, 105, 105)},
|
|
Toshihiro Shimizu |
890ddd |
{"dimgrey", NSVG_RGB(105, 105, 105)},
|
|
Toshihiro Shimizu |
890ddd |
{"dodgerblue", NSVG_RGB(30, 144, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"firebrick", NSVG_RGB(178, 34, 34)},
|
|
Toshihiro Shimizu |
890ddd |
{"floralwhite", NSVG_RGB(255, 250, 240)},
|
|
Toshihiro Shimizu |
890ddd |
{"forestgreen", NSVG_RGB(34, 139, 34)},
|
|
Toshihiro Shimizu |
890ddd |
{"fuchsia", NSVG_RGB(255, 0, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"gainsboro", NSVG_RGB(220, 220, 220)},
|
|
Toshihiro Shimizu |
890ddd |
{"ghostwhite", NSVG_RGB(248, 248, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"gold", NSVG_RGB(255, 215, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"goldenrod", NSVG_RGB(218, 165, 32)},
|
|
Toshihiro Shimizu |
890ddd |
{"greenyellow", NSVG_RGB(173, 255, 47)},
|
|
Toshihiro Shimizu |
890ddd |
{"honeydew", NSVG_RGB(240, 255, 240)},
|
|
Toshihiro Shimizu |
890ddd |
{"hotpink", NSVG_RGB(255, 105, 180)},
|
|
Toshihiro Shimizu |
890ddd |
{"indianred", NSVG_RGB(205, 92, 92)},
|
|
Toshihiro Shimizu |
890ddd |
{"indigo", NSVG_RGB(75, 0, 130)},
|
|
Toshihiro Shimizu |
890ddd |
{"ivory", NSVG_RGB(255, 255, 240)},
|
|
Toshihiro Shimizu |
890ddd |
{"khaki", NSVG_RGB(240, 230, 140)},
|
|
Toshihiro Shimizu |
890ddd |
{"lavender", NSVG_RGB(230, 230, 250)},
|
|
Toshihiro Shimizu |
890ddd |
{"lavenderblush", NSVG_RGB(255, 240, 245)},
|
|
Toshihiro Shimizu |
890ddd |
{"lawngreen", NSVG_RGB(124, 252, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"lemonchiffon", NSVG_RGB(255, 250, 205)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightblue", NSVG_RGB(173, 216, 230)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightcoral", NSVG_RGB(240, 128, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightcyan", NSVG_RGB(224, 255, 255)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightgray", NSVG_RGB(211, 211, 211)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightgreen", NSVG_RGB(144, 238, 144)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightgrey", NSVG_RGB(211, 211, 211)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightpink", NSVG_RGB(255, 182, 193)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightsalmon", NSVG_RGB(255, 160, 122)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightseagreen", NSVG_RGB(32, 178, 170)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightskyblue", NSVG_RGB(135, 206, 250)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightslategray", NSVG_RGB(119, 136, 153)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightslategrey", NSVG_RGB(119, 136, 153)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightsteelblue", NSVG_RGB(176, 196, 222)},
|
|
Toshihiro Shimizu |
890ddd |
{"lightyellow", NSVG_RGB(255, 255, 224)},
|
|
Toshihiro Shimizu |
890ddd |
{"lime", NSVG_RGB(0, 255, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"limegreen", NSVG_RGB(50, 205, 50)},
|
|
Toshihiro Shimizu |
890ddd |
{"linen", NSVG_RGB(250, 240, 230)},
|
|
Toshihiro Shimizu |
890ddd |
{"maroon", NSVG_RGB(128, 0, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumaquamarine", NSVG_RGB(102, 205, 170)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumblue", NSVG_RGB(0, 0, 205)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumorchid", NSVG_RGB(186, 85, 211)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumpurple", NSVG_RGB(147, 112, 219)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumseagreen", NSVG_RGB(60, 179, 113)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumslateblue", NSVG_RGB(123, 104, 238)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumspringgreen", NSVG_RGB(0, 250, 154)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumturquoise", NSVG_RGB(72, 209, 204)},
|
|
Toshihiro Shimizu |
890ddd |
{"mediumvioletred", NSVG_RGB(199, 21, 133)},
|
|
Toshihiro Shimizu |
890ddd |
{"midnightblue", NSVG_RGB(25, 25, 112)},
|
|
Toshihiro Shimizu |
890ddd |
{"mintcream", NSVG_RGB(245, 255, 250)},
|
|
Toshihiro Shimizu |
890ddd |
{"mistyrose", NSVG_RGB(255, 228, 225)},
|
|
Toshihiro Shimizu |
890ddd |
{"moccasin", NSVG_RGB(255, 228, 181)},
|
|
Toshihiro Shimizu |
890ddd |
{"navajowhite", NSVG_RGB(255, 222, 173)},
|
|
Toshihiro Shimizu |
890ddd |
{"navy", NSVG_RGB(0, 0, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"oldlace", NSVG_RGB(253, 245, 230)},
|
|
Toshihiro Shimizu |
890ddd |
{"olive", NSVG_RGB(128, 128, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"olivedrab", NSVG_RGB(107, 142, 35)},
|
|
Toshihiro Shimizu |
890ddd |
{"orange", NSVG_RGB(255, 165, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"orangered", NSVG_RGB(255, 69, 0)},
|
|
Toshihiro Shimizu |
890ddd |
{"orchid", NSVG_RGB(218, 112, 214)},
|
|
Toshihiro Shimizu |
890ddd |
{"palegoldenrod", NSVG_RGB(238, 232, 170)},
|
|
Toshihiro Shimizu |
890ddd |
{"palegreen", NSVG_RGB(152, 251, 152)},
|
|
Toshihiro Shimizu |
890ddd |
{"paleturquoise", NSVG_RGB(175, 238, 238)},
|
|
Toshihiro Shimizu |
890ddd |
{"palevioletred", NSVG_RGB(219, 112, 147)},
|
|
Toshihiro Shimizu |
890ddd |
{"papayawhip", NSVG_RGB(255, 239, 213)},
|
|
Toshihiro Shimizu |
890ddd |
{"peachpuff", NSVG_RGB(255, 218, 185)},
|
|
Toshihiro Shimizu |
890ddd |
{"peru", NSVG_RGB(205, 133, 63)},
|
|
Toshihiro Shimizu |
890ddd |
{"pink", NSVG_RGB(255, 192, 203)},
|
|
Toshihiro Shimizu |
890ddd |
{"plum", NSVG_RGB(221, 160, 221)},
|
|
Toshihiro Shimizu |
890ddd |
{"powderblue", NSVG_RGB(176, 224, 230)},
|
|
Toshihiro Shimizu |
890ddd |
{"purple", NSVG_RGB(128, 0, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"rosybrown", NSVG_RGB(188, 143, 143)},
|
|
Toshihiro Shimizu |
890ddd |
{"royalblue", NSVG_RGB(65, 105, 225)},
|
|
Toshihiro Shimizu |
890ddd |
{"saddlebrown", NSVG_RGB(139, 69, 19)},
|
|
Toshihiro Shimizu |
890ddd |
{"salmon", NSVG_RGB(250, 128, 114)},
|
|
Toshihiro Shimizu |
890ddd |
{"sandybrown", NSVG_RGB(244, 164, 96)},
|
|
Toshihiro Shimizu |
890ddd |
{"seagreen", NSVG_RGB(46, 139, 87)},
|
|
Toshihiro Shimizu |
890ddd |
{"seashell", NSVG_RGB(255, 245, 238)},
|
|
Toshihiro Shimizu |
890ddd |
{"sienna", NSVG_RGB(160, 82, 45)},
|
|
Toshihiro Shimizu |
890ddd |
{"silver", NSVG_RGB(192, 192, 192)},
|
|
Toshihiro Shimizu |
890ddd |
{"skyblue", NSVG_RGB(135, 206, 235)},
|
|
Toshihiro Shimizu |
890ddd |
{"slateblue", NSVG_RGB(106, 90, 205)},
|
|
Toshihiro Shimizu |
890ddd |
{"slategray", NSVG_RGB(112, 128, 144)},
|
|
Toshihiro Shimizu |
890ddd |
{"slategrey", NSVG_RGB(112, 128, 144)},
|
|
Toshihiro Shimizu |
890ddd |
{"snow", NSVG_RGB(255, 250, 250)},
|
|
Toshihiro Shimizu |
890ddd |
{"springgreen", NSVG_RGB(0, 255, 127)},
|
|
Toshihiro Shimizu |
890ddd |
{"steelblue", NSVG_RGB(70, 130, 180)},
|
|
Toshihiro Shimizu |
890ddd |
{"tan", NSVG_RGB(210, 180, 140)},
|
|
Toshihiro Shimizu |
890ddd |
{"teal", NSVG_RGB(0, 128, 128)},
|
|
Toshihiro Shimizu |
890ddd |
{"thistle", NSVG_RGB(216, 191, 216)},
|
|
Toshihiro Shimizu |
890ddd |
{"tomato", NSVG_RGB(255, 99, 71)},
|
|
Toshihiro Shimizu |
890ddd |
{"turquoise", NSVG_RGB(64, 224, 208)},
|
|
Toshihiro Shimizu |
890ddd |
{"violet", NSVG_RGB(238, 130, 238)},
|
|
Toshihiro Shimizu |
890ddd |
{"wheat", NSVG_RGB(245, 222, 179)},
|
|
Toshihiro Shimizu |
890ddd |
{"whitesmoke", NSVG_RGB(245, 245, 245)},
|
|
Toshihiro Shimizu |
890ddd |
{"yellowgreen", NSVG_RGB(154, 205, 50)},
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
unsigned int nsvg__parseColorName(const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i, ncolors = sizeof(nsvg__colors) / sizeof(struct NSVGNamedColor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < ncolors; i++) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(nsvg__colors[i].name, str) == 0) {
|
|
Toshihiro Shimizu |
890ddd |
return nsvg__colors[i].color;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return NSVG_RGB(128, 128, 128);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
unsigned int nsvg__parseColor(const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int len = 0;
|
|
Toshihiro Shimizu |
890ddd |
while (*str == ' ')
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
len = (int)strlen(str);
|
|
Toshihiro Shimizu |
890ddd |
if (len >= 1 && *str == '#')
|
|
Toshihiro Shimizu |
890ddd |
return nsvg__parseColorHex(str);
|
|
Toshihiro Shimizu |
890ddd |
else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
|
|
Toshihiro Shimizu |
890ddd |
return nsvg__parseColorRGB(str);
|
|
Toshihiro Shimizu |
890ddd |
return nsvg__parseColorName(str);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
float nsvg__parseFloat(const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
while (*str == ' ')
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
return (float)atof(str);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseTransformArgs(const char *str, float *args, int maxNa, int *na)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const char *end;
|
|
Toshihiro Shimizu |
890ddd |
const char *ptr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*na = 0;
|
|
Toshihiro Shimizu |
890ddd |
ptr = str;
|
|
Toshihiro Shimizu |
890ddd |
while (*ptr && *ptr != '(')
|
|
Toshihiro Shimizu |
890ddd |
++ptr;
|
|
Toshihiro Shimizu |
890ddd |
if (*ptr == 0)
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
end = ptr;
|
|
Toshihiro Shimizu |
890ddd |
while (*end && *end != ')')
|
|
Toshihiro Shimizu |
890ddd |
++end;
|
|
Toshihiro Shimizu |
890ddd |
if (*end == 0)
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (ptr < end) {
|
|
Toshihiro Shimizu |
890ddd |
if (nsvg__isnum(*ptr)) {
|
|
Toshihiro Shimizu |
890ddd |
if (*na >= maxNa)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
args[(*na)++] = (float)atof(ptr);
|
|
Toshihiro Shimizu |
890ddd |
while (ptr < end && nsvg__isnum(*ptr))
|
|
Toshihiro Shimizu |
890ddd |
++ptr;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
++ptr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return (int)(end - str);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseMatrix(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, t, 6, &na);
|
|
Toshihiro Shimizu |
890ddd |
if (na != 6)
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseTranslate(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float args[2];
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, args, 2, &na);
|
|
Toshihiro Shimizu |
890ddd |
if (na == 1)
|
|
Toshihiro Shimizu |
890ddd |
args[1] = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetTranslation(t, args[0], args[1]);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseScale(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float args[2];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, args, 2, &na);
|
|
Toshihiro Shimizu |
890ddd |
if (na == 1)
|
|
Toshihiro Shimizu |
890ddd |
args[1] = args[0];
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetScale(t, args[0], args[1]);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseSkewX(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float args[1];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, args, 1, &na);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseSkewY(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float args[1];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, args, 1, &na);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseRotate(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float args[3];
|
|
Toshihiro Shimizu |
890ddd |
int na = 0;
|
|
Toshihiro Shimizu |
890ddd |
float t[6];
|
|
Toshihiro Shimizu |
890ddd |
int len = nsvg__parseTransformArgs(str, args, 3, &na);
|
|
Toshihiro Shimizu |
890ddd |
if (na == 1)
|
|
Toshihiro Shimizu |
890ddd |
args[1] = args[2] = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (na > 1) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetTranslation(t, -args[1], -args[2]);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (na > 1) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformSetTranslation(t, args[1], args[2]);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPremultiply(nsvg__getAttr(p)->xform, t);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return len;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseTransform(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
while (*str) {
|
|
Toshihiro Shimizu |
890ddd |
if (strncmp(str, "matrix", 6) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseMatrix(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else if (strncmp(str, "translate", 9) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseTranslate(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else if (strncmp(str, "scale", 5) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseScale(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else if (strncmp(str, "rotate", 6) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseRotate(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else if (strncmp(str, "skewX", 5) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseSkewX(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else if (strncmp(str, "skewY", 5) == 0)
|
|
Toshihiro Shimizu |
890ddd |
str += nsvg__parseSkewY(p, str);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseStyle(struct NSVGParser *p, const char *str);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseAttr(struct NSVGParser *p, const char *name, const char *value)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGAttrib *attr = nsvg__getAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
if (!attr)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(name, "style") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseStyle(p, value);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "display") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(value, "none") == 0)
|
|
Toshihiro Shimizu |
890ddd |
attr->visible = 0;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
attr->visible = 1;
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "fill") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(value, "none") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
attr->hasFill = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
attr->hasFill = 1;
|
|
Toshihiro Shimizu |
890ddd |
attr->fillColor = nsvg__parseColor(value);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "fill-opacity") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
attr->fillOpacity = nsvg__parseFloat(value);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "stroke") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(value, "none") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
attr->hasStroke = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
attr->hasStroke = 1;
|
|
Toshihiro Shimizu |
890ddd |
attr->strokeColor = nsvg__parseColor(value);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "stroke-width") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
attr->strokeWidth = nsvg__parseFloat(value);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "stroke-opacity") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
attr->strokeOpacity = nsvg__parseFloat(value);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(name, "transform") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseTransform(p, value);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__parseNameValue(struct NSVGParser *p, const char *start, const char *end)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const char *str;
|
|
Toshihiro Shimizu |
890ddd |
const char *val;
|
|
Toshihiro Shimizu |
890ddd |
char name[512];
|
|
Toshihiro Shimizu |
890ddd |
char value[512];
|
|
Toshihiro Shimizu |
890ddd |
int n;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
str = start;
|
|
Toshihiro Shimizu |
890ddd |
while (str < end && *str != ':')
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
val = str;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Right Trim
|
|
Toshihiro Shimizu |
890ddd |
while (str > start && (*str == ':' || nsvg__isspace(*str)))
|
|
Toshihiro Shimizu |
890ddd |
--str;
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
n = (int)(str - start);
|
|
Toshihiro Shimizu |
890ddd |
if (n > 511)
|
|
Toshihiro Shimizu |
890ddd |
n = 511;
|
|
Toshihiro Shimizu |
890ddd |
if (n)
|
|
Toshihiro Shimizu |
890ddd |
memcpy(name, start, n);
|
|
Toshihiro Shimizu |
890ddd |
name[n] = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (val < end && (*val == ':' || nsvg__isspace(*val)))
|
|
Toshihiro Shimizu |
890ddd |
++val;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
n = (int)(end - val);
|
|
Toshihiro Shimizu |
890ddd |
if (n > 511)
|
|
Toshihiro Shimizu |
890ddd |
n = 511;
|
|
Toshihiro Shimizu |
890ddd |
if (n)
|
|
Toshihiro Shimizu |
890ddd |
memcpy(value, val, n);
|
|
Toshihiro Shimizu |
890ddd |
value[n] = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return nsvg__parseAttr(p, name, value);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseStyle(struct NSVGParser *p, const char *str)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const char *start;
|
|
Toshihiro Shimizu |
890ddd |
const char *end;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (*str) {
|
|
Toshihiro Shimizu |
890ddd |
// Left Trim
|
|
Toshihiro Shimizu |
890ddd |
while (*str && nsvg__isspace(*str))
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
start = str;
|
|
Toshihiro Shimizu |
890ddd |
while (*str && *str != ';')
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
end = str;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Right Trim
|
|
Toshihiro Shimizu |
890ddd |
while (end > start && (*end == ';' || nsvg__isspace(*end)))
|
|
Toshihiro Shimizu |
890ddd |
--end;
|
|
Toshihiro Shimizu |
890ddd |
++end;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseNameValue(p, start, end);
|
|
Toshihiro Shimizu |
890ddd |
if (*str)
|
|
Toshihiro Shimizu |
890ddd |
++str;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseAttribs(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "style") == 0)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseStyle(p, attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseAttr(p, attr[i], attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nsvg__getArgsPerElement(char cmd)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
switch (cmd) {
|
|
Toshihiro Shimizu |
890ddd |
case 'v':
|
|
Toshihiro Shimizu |
890ddd |
case 'V':
|
|
Toshihiro Shimizu |
890ddd |
case 'h':
|
|
Toshihiro Shimizu |
890ddd |
case 'H':
|
|
Toshihiro Shimizu |
890ddd |
return 1;
|
|
Toshihiro Shimizu |
890ddd |
case 'm':
|
|
Toshihiro Shimizu |
890ddd |
case 'M':
|
|
Toshihiro Shimizu |
890ddd |
case 'l':
|
|
Toshihiro Shimizu |
890ddd |
case 'L':
|
|
Toshihiro Shimizu |
890ddd |
case 't':
|
|
Toshihiro Shimizu |
890ddd |
case 'T':
|
|
Toshihiro Shimizu |
890ddd |
return 2;
|
|
Toshihiro Shimizu |
890ddd |
case 'q':
|
|
Toshihiro Shimizu |
890ddd |
case 'Q':
|
|
Toshihiro Shimizu |
890ddd |
case 's':
|
|
Toshihiro Shimizu |
890ddd |
case 'S':
|
|
Toshihiro Shimizu |
890ddd |
return 4;
|
|
Toshihiro Shimizu |
890ddd |
case 'c':
|
|
Toshihiro Shimizu |
890ddd |
case 'C':
|
|
Toshihiro Shimizu |
890ddd |
return 6;
|
|
Toshihiro Shimizu |
890ddd |
case 'a':
|
|
Toshihiro Shimizu |
890ddd |
case 'A':
|
|
Toshihiro Shimizu |
890ddd |
return 7;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathMoveTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
*cpx += args[0];
|
|
Toshihiro Shimizu |
890ddd |
*cpy += args[1];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
*cpx = args[0];
|
|
Toshihiro Shimizu |
890ddd |
*cpy = args[1];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, *cpx, *cpy);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathLineTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
*cpx += args[0];
|
|
Toshihiro Shimizu |
890ddd |
*cpy += args[1];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
*cpx = args[0];
|
|
Toshihiro Shimizu |
890ddd |
*cpy = args[1];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, *cpx, *cpy);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathHLineTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (rel)
|
|
Toshihiro Shimizu |
890ddd |
*cpx += args[0];
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
*cpx = args[0];
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, *cpx, *cpy);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathVLineTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (rel)
|
|
Toshihiro Shimizu |
890ddd |
*cpy += args[0];
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
*cpy = args[0];
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, *cpx, *cpy);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathCubicBezTo(struct NSVGParser *p, float *cpx, float *cpy,
|
|
Toshihiro Shimizu |
890ddd |
float *cpx2, float *cpy2, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x1 = *cpx;
|
|
Toshihiro Shimizu |
890ddd |
y1 = *cpy;
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
cx1 = *cpx + args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy1 = *cpy + args[1];
|
|
Toshihiro Shimizu |
890ddd |
cx2 = *cpx + args[2];
|
|
Toshihiro Shimizu |
890ddd |
cy2 = *cpy + args[3];
|
|
Toshihiro Shimizu |
890ddd |
x2 = *cpx + args[4];
|
|
Toshihiro Shimizu |
890ddd |
y2 = *cpy + args[5];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cx1 = args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy1 = args[1];
|
|
Toshihiro Shimizu |
890ddd |
cx2 = args[2];
|
|
Toshihiro Shimizu |
890ddd |
cy2 = args[3];
|
|
Toshihiro Shimizu |
890ddd |
x2 = args[4];
|
|
Toshihiro Shimizu |
890ddd |
y2 = args[5];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*cpx2 = cx2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy2 = cy2;
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathCubicBezShortTo(struct NSVGParser *p, float *cpx, float *cpy,
|
|
Toshihiro Shimizu |
890ddd |
float *cpx2, float *cpy2, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x1 = *cpx;
|
|
Toshihiro Shimizu |
890ddd |
y1 = *cpy;
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
cx2 = *cpx + args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy2 = *cpy + args[1];
|
|
Toshihiro Shimizu |
890ddd |
x2 = *cpx + args[2];
|
|
Toshihiro Shimizu |
890ddd |
y2 = *cpy + args[3];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cx2 = args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy2 = args[1];
|
|
Toshihiro Shimizu |
890ddd |
x2 = args[2];
|
|
Toshihiro Shimizu |
890ddd |
y2 = args[3];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cx1 = 2 * x1 - *cpx2;
|
|
Toshihiro Shimizu |
890ddd |
cy1 = 2 * y1 - *cpy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*cpx2 = cx2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy2 = cy2;
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathQuadBezTo(struct NSVGParser *p, float *cpx, float *cpy,
|
|
Toshihiro Shimizu |
890ddd |
float *cpx2, float *cpy2, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x1, y1, x2, y2, cx, cy;
|
|
Toshihiro Shimizu |
890ddd |
float cx1, cy1, cx2, cy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x1 = *cpx;
|
|
Toshihiro Shimizu |
890ddd |
y1 = *cpy;
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
cx = *cpx + args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy = *cpy + args[1];
|
|
Toshihiro Shimizu |
890ddd |
x2 = *cpx + args[2];
|
|
Toshihiro Shimizu |
890ddd |
y2 = *cpy + args[3];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cx = args[0];
|
|
Toshihiro Shimizu |
890ddd |
cy = args[1];
|
|
Toshihiro Shimizu |
890ddd |
x2 = args[2];
|
|
Toshihiro Shimizu |
890ddd |
y2 = args[3];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Convert to cubix bezier
|
|
Toshihiro Shimizu |
890ddd |
cx1 = x1 + 2.0f / 3.0f * (cx - x1);
|
|
Toshihiro Shimizu |
890ddd |
cy1 = y1 + 2.0f / 3.0f * (cy - y1);
|
|
Toshihiro Shimizu |
890ddd |
cx2 = x2 + 2.0f / 3.0f * (cx - x2);
|
|
Toshihiro Shimizu |
890ddd |
cy2 = y2 + 2.0f / 3.0f * (cy - y2);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*cpx2 = cx;
|
|
Toshihiro Shimizu |
890ddd |
*cpy2 = cy;
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathQuadBezShortTo(struct NSVGParser *p, float *cpx, float *cpy,
|
|
Toshihiro Shimizu |
890ddd |
float *cpx2, float *cpy2, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x1, y1, x2, y2, cx, cy;
|
|
Toshihiro Shimizu |
890ddd |
float cx1, cy1, cx2, cy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x1 = *cpx;
|
|
Toshihiro Shimizu |
890ddd |
y1 = *cpy;
|
|
Toshihiro Shimizu |
890ddd |
if (rel) {
|
|
Toshihiro Shimizu |
890ddd |
x2 = *cpx + args[0];
|
|
Toshihiro Shimizu |
890ddd |
y2 = *cpy + args[1];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
x2 = args[0];
|
|
Toshihiro Shimizu |
890ddd |
y2 = args[1];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cx = 2 * x1 - *cpx2;
|
|
Toshihiro Shimizu |
890ddd |
cy = 2 * y1 - *cpy2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Convert to cubix bezier
|
|
Toshihiro Shimizu |
890ddd |
cx1 = x1 + 2.0f / 3.0f * (cx - x1);
|
|
Toshihiro Shimizu |
890ddd |
cy1 = y1 + 2.0f / 3.0f * (cy - y1);
|
|
Toshihiro Shimizu |
890ddd |
cx2 = x2 + 2.0f / 3.0f * (cx - x2);
|
|
Toshihiro Shimizu |
890ddd |
cy2 = y2 + 2.0f / 3.0f * (cy - y2);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*cpx2 = cx;
|
|
Toshihiro Shimizu |
890ddd |
*cpy2 = cy;
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
float nsvg__sqr(float x) { return x * x; }
|
|
Toshihiro Shimizu |
890ddd |
float nsvg__vmag(float x, float y) { return sqrtf(x * x + y * y); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
float nsvg__vecrat(float ux, float uy, float vx, float vy)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
float nsvg__vecang(float ux, float uy, float vx, float vy)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float r = nsvg__vecrat(ux, uy, vx, vy);
|
|
Toshihiro Shimizu |
890ddd |
if (r < -1.0f)
|
|
Toshihiro Shimizu |
890ddd |
r = -1.0f;
|
|
Toshihiro Shimizu |
890ddd |
if (r > 1.0f)
|
|
Toshihiro Shimizu |
890ddd |
r = 1.0f;
|
|
Toshihiro Shimizu |
890ddd |
return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__pathArcTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, int rel)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Ported from canvg (https://code.google.com/p/canvg/)
|
|
Toshihiro Shimizu |
890ddd |
float rx, ry, rotx;
|
|
Toshihiro Shimizu |
890ddd |
float x1, y1, x2, y2, cx, cy, dx, dy, d;
|
|
Toshihiro Shimizu |
890ddd |
float x1p, y1p, cxp, cyp, s, sa, sb;
|
|
Toshihiro Shimizu |
890ddd |
float ux, uy, vx, vy, a1, da;
|
|
Toshihiro Shimizu |
890ddd |
float x, y, tanx, tany, a, px, py, ptanx, ptany, t[6];
|
|
Toshihiro Shimizu |
890ddd |
float sinrx, cosrx;
|
|
Toshihiro Shimizu |
890ddd |
int fa, fs;
|
|
Toshihiro Shimizu |
890ddd |
int i, ndivs;
|
|
Toshihiro Shimizu |
890ddd |
float hda, kappa;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rx = fabsf(args[0]); // y radius
|
|
Toshihiro Shimizu |
890ddd |
ry = fabsf(args[1]); // x radius
|
|
Toshihiro Shimizu |
890ddd |
rotx = args[2] / 180.0f * NSVG_PI; // x rotation engle
|
|
Toshihiro Shimizu |
890ddd |
fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
|
|
Toshihiro Shimizu |
890ddd |
fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
|
|
Toshihiro Shimizu |
890ddd |
x1 = *cpx; // start point
|
|
Toshihiro Shimizu |
890ddd |
y1 = *cpy;
|
|
Toshihiro Shimizu |
890ddd |
if (rel) { // end point
|
|
Toshihiro Shimizu |
890ddd |
x2 = *cpx + args[5];
|
|
Toshihiro Shimizu |
890ddd |
y2 = *cpy + args[6];
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
x2 = args[5];
|
|
Toshihiro Shimizu |
890ddd |
y2 = args[6];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
dx = x1 - x2;
|
|
Toshihiro Shimizu |
890ddd |
dy = y1 - y2;
|
|
Toshihiro Shimizu |
890ddd |
d = sqrtf(dx * dx + dy * dy);
|
|
Toshihiro Shimizu |
890ddd |
if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
|
|
Toshihiro Shimizu |
890ddd |
// The arc degenerates to a line
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sinrx = sinf(rotx);
|
|
Toshihiro Shimizu |
890ddd |
cosrx = cosf(rotx);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Convert to center point parameterization.
|
|
Toshihiro Shimizu |
890ddd |
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
|
|
Toshihiro Shimizu |
890ddd |
// 1) Compute x1', y1'
|
|
Toshihiro Shimizu |
890ddd |
x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
|
|
Toshihiro Shimizu |
890ddd |
y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
|
|
Toshihiro Shimizu |
890ddd |
d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry);
|
|
Toshihiro Shimizu |
890ddd |
if (d > 1) {
|
|
Toshihiro Shimizu |
890ddd |
d = sqrtf(d);
|
|
Toshihiro Shimizu |
890ddd |
rx *= d;
|
|
Toshihiro Shimizu |
890ddd |
ry *= d;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// 2) Compute cx', cy'
|
|
Toshihiro Shimizu |
890ddd |
s = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) - nsvg__sqr(ry) * nsvg__sqr(x1p);
|
|
Toshihiro Shimizu |
890ddd |
sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p);
|
|
Toshihiro Shimizu |
890ddd |
if (sa < 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
sa = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
if (sb > 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
s = sqrtf(sa / sb);
|
|
Toshihiro Shimizu |
890ddd |
if (fa == fs)
|
|
Toshihiro Shimizu |
890ddd |
s = -s;
|
|
Toshihiro Shimizu |
890ddd |
cxp = s * rx * y1p / ry;
|
|
Toshihiro Shimizu |
890ddd |
cyp = s * -ry * x1p / rx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// 3) Compute cx,cy from cx',cy'
|
|
Toshihiro Shimizu |
890ddd |
cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp;
|
|
Toshihiro Shimizu |
890ddd |
cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// 4) Calculate theta1, and delta theta.
|
|
Toshihiro Shimizu |
890ddd |
ux = (x1p - cxp) / rx;
|
|
Toshihiro Shimizu |
890ddd |
uy = (y1p - cyp) / ry;
|
|
Toshihiro Shimizu |
890ddd |
vx = (-x1p - cxp) / rx;
|
|
Toshihiro Shimizu |
890ddd |
vy = (-y1p - cyp) / ry;
|
|
Toshihiro Shimizu |
890ddd |
a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle
|
|
Toshihiro Shimizu |
890ddd |
da = nsvg__vecang(ux, uy, vx, vy); // Delta angle
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
|
|
Toshihiro Shimizu |
890ddd |
// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (fa) {
|
|
Toshihiro Shimizu |
890ddd |
// Choose large arc
|
|
Toshihiro Shimizu |
890ddd |
if (da > 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
da = da - 2 * NSVG_PI;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
da = 2 * NSVG_PI + da;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Approximate the arc using cubic spline segments.
|
|
Toshihiro Shimizu |
890ddd |
t[0] = cosrx;
|
|
Toshihiro Shimizu |
890ddd |
t[1] = sinrx;
|
|
Toshihiro Shimizu |
890ddd |
t[2] = -sinrx;
|
|
Toshihiro Shimizu |
890ddd |
t[3] = cosrx;
|
|
Toshihiro Shimizu |
890ddd |
t[4] = cx;
|
|
Toshihiro Shimizu |
890ddd |
t[5] = cy;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Split arc into max 90 degree segments.
|
|
Toshihiro Shimizu |
890ddd |
ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 0.5f);
|
|
Toshihiro Shimizu |
890ddd |
hda = (da / (float)ndivs) / 2.0f;
|
|
Toshihiro Shimizu |
890ddd |
kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
|
|
Toshihiro Shimizu |
890ddd |
if (da < 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
kappa = -kappa;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i <= ndivs; i++) {
|
|
Toshihiro Shimizu |
890ddd |
a = a1 + da * (i / (float)ndivs);
|
|
Toshihiro Shimizu |
890ddd |
dx = cosf(a);
|
|
Toshihiro Shimizu |
890ddd |
dy = sinf(a);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position
|
|
Toshihiro Shimizu |
890ddd |
nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent
|
|
Toshihiro Shimizu |
890ddd |
if (i > 0)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y);
|
|
Toshihiro Shimizu |
890ddd |
px = x;
|
|
Toshihiro Shimizu |
890ddd |
py = y;
|
|
Toshihiro Shimizu |
890ddd |
ptanx = tanx;
|
|
Toshihiro Shimizu |
890ddd |
ptany = tany;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*cpx = x2;
|
|
Toshihiro Shimizu |
890ddd |
*cpy = y2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parsePath(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const char *s;
|
|
Toshihiro Shimizu |
890ddd |
char cmd;
|
|
Toshihiro Shimizu |
890ddd |
float args[10];
|
|
Toshihiro Shimizu |
890ddd |
int nargs;
|
|
Toshihiro Shimizu |
890ddd |
int rargs;
|
|
Toshihiro Shimizu |
890ddd |
float cpx, cpy, cpx2, cpy2;
|
|
Toshihiro Shimizu |
890ddd |
const char *tmp[4];
|
|
Toshihiro Shimizu |
890ddd |
char closedFlag;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
char item[64];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "d") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
s = attr[i + 1];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
cpx = 0;
|
|
Toshihiro Shimizu |
890ddd |
cpy = 0;
|
|
Toshihiro Shimizu |
890ddd |
closedFlag = 0;
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (*s) {
|
|
Toshihiro Shimizu |
890ddd |
s = nsvg__getNextPathItem(s, item);
|
|
Toshihiro Shimizu |
890ddd |
if (!*item)
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
if (nsvg__isnum(item[0])) {
|
|
Toshihiro Shimizu |
890ddd |
if (nargs < 10)
|
|
Toshihiro Shimizu |
890ddd |
args[nargs++] = (float)atof(item);
|
|
Toshihiro Shimizu |
890ddd |
if (nargs >= rargs) {
|
|
Toshihiro Shimizu |
890ddd |
switch (cmd) {
|
|
Toshihiro Shimizu |
890ddd |
case 'm':
|
|
Toshihiro Shimizu |
890ddd |
case 'M':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
// Moveto can be followed by multiple coordinate pairs,
|
|
Toshihiro Shimizu |
890ddd |
// which should be treated as linetos.
|
|
Toshihiro Shimizu |
890ddd |
cmd = (cmd == 'm') ? 'l' : 'L';
|
|
Toshihiro Shimizu |
890ddd |
rargs = nsvg__getArgsPerElement(cmd);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'l':
|
|
Toshihiro Shimizu |
890ddd |
case 'L':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'H':
|
|
Toshihiro Shimizu |
890ddd |
case 'h':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'V':
|
|
Toshihiro Shimizu |
890ddd |
case 'v':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'C':
|
|
Toshihiro Shimizu |
890ddd |
case 'c':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'S':
|
|
Toshihiro Shimizu |
890ddd |
case 's':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'Q':
|
|
Toshihiro Shimizu |
890ddd |
case 'q':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'T':
|
|
Toshihiro Shimizu |
890ddd |
case 't':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case 'A':
|
|
Toshihiro Shimizu |
890ddd |
case 'a':
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
if (nargs >= 2) {
|
|
Toshihiro Shimizu |
890ddd |
cpx = args[nargs - 2];
|
|
Toshihiro Shimizu |
890ddd |
cpy = args[nargs - 1];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cmd = item[0];
|
|
Toshihiro Shimizu |
890ddd |
rargs = nsvg__getArgsPerElement(cmd);
|
|
Toshihiro Shimizu |
890ddd |
if (cmd == 'M' || cmd == 'm') {
|
|
Toshihiro Shimizu |
890ddd |
// Commit path.
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts > 0)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, closedFlag);
|
|
Toshihiro Shimizu |
890ddd |
// Start new subpath.
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
closedFlag = 0;
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else if (cmd == 'Z' || cmd == 'z') {
|
|
Toshihiro Shimizu |
890ddd |
closedFlag = 1;
|
|
Toshihiro Shimizu |
890ddd |
// Commit path.
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts > 0)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, closedFlag);
|
|
Toshihiro Shimizu |
890ddd |
// Start new subpath.
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
closedFlag = 0;
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
// Commit path.
|
|
Toshihiro Shimizu |
890ddd |
if (p->npts)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, closedFlag);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
tmp[0] = attr[i];
|
|
Toshihiro Shimizu |
890ddd |
tmp[1] = attr[i + 1];
|
|
Toshihiro Shimizu |
890ddd |
tmp[2] = 0;
|
|
Toshihiro Shimizu |
890ddd |
tmp[3] = 0;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseAttribs(p, tmp);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseRect(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float y = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float w = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float h = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float rx = -1.0f; // marks not set
|
|
Toshihiro Shimizu |
890ddd |
float ry = -1.0f;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "x") == 0)
|
|
Toshihiro Shimizu |
890ddd |
x = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "y") == 0)
|
|
Toshihiro Shimizu |
890ddd |
y = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "width") == 0)
|
|
Toshihiro Shimizu |
890ddd |
w = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "height") == 0)
|
|
Toshihiro Shimizu |
890ddd |
h = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "rx") == 0)
|
|
Toshihiro Shimizu |
890ddd |
rx = fabsf(nsvg__parseFloat(attr[i + 1]));
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "ry") == 0)
|
|
Toshihiro Shimizu |
890ddd |
ry = fabsf(nsvg__parseFloat(attr[i + 1]));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rx < 0.0f && ry > 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
rx = ry;
|
|
Toshihiro Shimizu |
890ddd |
if (ry < 0.0f && rx > 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
ry = rx;
|
|
Toshihiro Shimizu |
890ddd |
if (rx < 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
rx = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
if (ry < 0.0f)
|
|
Toshihiro Shimizu |
890ddd |
ry = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
if (rx > w / 2.0f)
|
|
Toshihiro Shimizu |
890ddd |
rx = w / 2.0f;
|
|
Toshihiro Shimizu |
890ddd |
if (ry > h / 2.0f)
|
|
Toshihiro Shimizu |
890ddd |
ry = h / 2.0f;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (w != 0.0f && h != 0.0f) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rx < 0.00001f || ry < 0.0001f) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, x, y);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x + w, y);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x + w, y + h);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x, y + h);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
// Rounded rectangle
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, x + rx, y);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x + w - rx, y);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, x + w - rx * (1 - NSVG_KAPPA90), y, x + w, y + ry * (1 - NSVG_KAPPA90), x + w, y + ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x + w, y + h - ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, x + w, y + h - ry * (1 - NSVG_KAPPA90), x + w - rx * (1 - NSVG_KAPPA90), y + h, x + w - rx, y + h);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x + rx, y + h);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, x + rx * (1 - NSVG_KAPPA90), y + h, x, y + h - ry * (1 - NSVG_KAPPA90), x, y + h - ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x, y + ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseCircle(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float cx = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float cy = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float r = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "cx") == 0)
|
|
Toshihiro Shimizu |
890ddd |
cx = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "cy") == 0)
|
|
Toshihiro Shimizu |
890ddd |
cy = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "r") == 0)
|
|
Toshihiro Shimizu |
890ddd |
r = fabsf(nsvg__parseFloat(attr[i + 1]));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (r > 0.0f) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, cx + r, cy);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseEllipse(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float cx = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float cy = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float rx = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
float ry = 0.0f;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "cx") == 0)
|
|
Toshihiro Shimizu |
890ddd |
cx = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "cy") == 0)
|
|
Toshihiro Shimizu |
890ddd |
cy = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "rx") == 0)
|
|
Toshihiro Shimizu |
890ddd |
rx = fabsf(nsvg__parseFloat(attr[i + 1]));
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "ry") == 0)
|
|
Toshihiro Shimizu |
890ddd |
ry = fabsf(nsvg__parseFloat(attr[i + 1]));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rx > 0.0f && ry > 0.0f) {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, cx + rx, cy);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__cubicBezTo(p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseLine(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
float x1 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
float y1 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
float x2 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
float y2 = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "x1") == 0)
|
|
Toshihiro Shimizu |
890ddd |
x1 = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "y1") == 0)
|
|
Toshihiro Shimizu |
890ddd |
y1 = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "x2") == 0)
|
|
Toshihiro Shimizu |
890ddd |
x2 = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "y2") == 0)
|
|
Toshihiro Shimizu |
890ddd |
y2 = nsvg__parseFloat(attr[i + 1]);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, x1, y1);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, x2, y2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parsePoly(struct NSVGParser *p, const char **attr, int closeFlag)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
const char *s;
|
|
Toshihiro Shimizu |
890ddd |
float args[2];
|
|
Toshihiro Shimizu |
890ddd |
int nargs, npts = 0;
|
|
Toshihiro Shimizu |
890ddd |
char item[64];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__resetPath(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "points") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
s = attr[i + 1];
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
while (*s) {
|
|
Toshihiro Shimizu |
890ddd |
s = nsvg__getNextPathItem(s, item);
|
|
Toshihiro Shimizu |
890ddd |
args[nargs++] = (float)atof(item);
|
|
Toshihiro Shimizu |
890ddd |
if (nargs >= 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (npts == 0)
|
|
Toshihiro Shimizu |
890ddd |
nsvg__moveTo(p, args[0], args[1]);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
nsvg__lineTo(p, args[0], args[1]);
|
|
Toshihiro Shimizu |
890ddd |
nargs = 0;
|
|
Toshihiro Shimizu |
890ddd |
npts++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addPath(p, (char)closeFlag);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__addShape(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__parseSVG(struct NSVGParser *p, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; attr[i]; i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(attr[i], "width") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
p->image->wunits[0] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
sscanf(attr[i + 1], "%f%s", &p->image->width, p->image->wunits);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(attr[i], "height") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
p->image->hunits[0] = '\0';
|
|
Toshihiro Shimizu |
890ddd |
sscanf(attr[i + 1], "%f%s", &p->image->height, p->image->hunits);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__startElement(void *ud, const char *el, const char **attr)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser *p = (struct NSVGParser *)ud;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Skip everything in defs
|
|
Toshihiro Shimizu |
890ddd |
if (p->defsFlag)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(el, "g") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseAttribs(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "path") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (p->pathFlag) // Do not allow nested paths.
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parsePath(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "rect") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseRect(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "circle") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseCircle(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "ellipse") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseEllipse(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "line") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseLine(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "polyline") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parsePoly(p, attr, 0);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "polygon") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__pushAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parsePoly(p, attr, 1);
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "defs") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
p->defsFlag = 1;
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "svg") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseSVG(p, attr);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__endElement(void *ud, const char *el)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser *p = (struct NSVGParser *)ud;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (strcmp(el, "g") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
nsvg__popAttr(p);
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "path") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
p->pathFlag = 0;
|
|
Toshihiro Shimizu |
890ddd |
} else if (strcmp(el, "defs") == 0) {
|
|
Toshihiro Shimizu |
890ddd |
p->defsFlag = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void nsvg__content(void *ud, const char *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// empty
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void dump(struct NSVGimage *image)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGshape *shape;
|
|
Toshihiro Shimizu |
890ddd |
if (image == NULL)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
shape = image->shapes;
|
|
Toshihiro Shimizu |
890ddd |
while (shape != NULL) {
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGpath *path;
|
|
Toshihiro Shimizu |
890ddd |
path = shape->paths;
|
|
Toshihiro Shimizu |
890ddd |
while (path)
|
|
Toshihiro Shimizu |
890ddd |
path = path->next;
|
|
Toshihiro Shimizu |
890ddd |
shape = shape->next;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage *nsvgParse(char *input)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGParser *p;
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage *ret = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
p = nsvg__createParser();
|
|
Toshihiro Shimizu |
890ddd |
if (p == NULL) {
|
|
Toshihiro Shimizu |
890ddd |
return NULL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ret = p->image;
|
|
Toshihiro Shimizu |
890ddd |
p->image = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
dump(ret);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvg__deleteParser(p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return ret;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage *nsvgParseFromFile(const char *filename)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
FILE *fp = NULL;
|
|
Toshihiro Shimizu |
890ddd |
int size;
|
|
Toshihiro Shimizu |
890ddd |
char *data = NULL;
|
|
Toshihiro Shimizu |
890ddd |
struct NSVGimage *image = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fp = fopen(filename, "rb");
|
|
Toshihiro Shimizu |
890ddd |
if (!fp)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
fseek(fp, 0, SEEK_END);
|
|
Toshihiro Shimizu |
890ddd |
size = ftell(fp);
|
|
Toshihiro Shimizu |
890ddd |
fseek(fp, 0, SEEK_SET);
|
|
Toshihiro Shimizu |
890ddd |
data = (char *)malloc(size + 1);
|
|
Toshihiro Shimizu |
890ddd |
if (data == NULL)
|
|
Toshihiro Shimizu |
890ddd |
goto error;
|
|
Toshihiro Shimizu |
890ddd |
fread(data, size, 1, fp);
|
|
Toshihiro Shimizu |
890ddd |
data[size] = '\0'; // Must be null terminated.
|
|
Toshihiro Shimizu |
890ddd |
fclose(fp);
|
|
Toshihiro Shimizu |
890ddd |
image = nsvgParse(data);
|
|
Toshihiro Shimizu |
890ddd |
free(data);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return image;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
if (fp)
|
|
Toshihiro Shimizu |
890ddd |
fclose(fp);
|
|
Toshihiro Shimizu |
890ddd |
if (data)
|
|
Toshihiro Shimizu |
890ddd |
free(data);
|
|
Toshihiro Shimizu |
890ddd |
if (image)
|
|
Toshihiro Shimizu |
890ddd |
nsvgDelete(image);
|
|
Toshihiro Shimizu |
890ddd |
return NULL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace svg_parser
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//=------------------------------------------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class TImageWriterSvg : public TImageWriter
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterSvg(const TFilePath &, TPropertyGroup *);
|
|
Toshihiro Shimizu |
890ddd |
~TImageWriterSvg() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
//double m_maxThickness;
|
|
Toshihiro Shimizu |
890ddd |
//not implemented
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterSvg(const TImageWriterSvg &);
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterSvg &operator=(const TImageWriterSvg &src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
void save(const TImageP &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
class TImageReaderSvg : public TImageReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TLevelP m_level;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderSvg(const TFilePath &path, TLevelP &level) : TImageReader(path), m_level(level) {}
|
|
Toshihiro Shimizu |
890ddd |
virtual TImageP load();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterP TLevelWriterSvg::getFrameWriter(TFrameId fid)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterSvg *iwm = new TImageWriterSvg(m_path.withFrame(fid), getProperties());
|
|
Toshihiro Shimizu |
890ddd |
return TImageWriterP(iwm);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
TImageWriterSvg::TImageWriterSvg(const TFilePath &f, TPropertyGroup *prop)
|
|
Toshihiro Shimizu |
890ddd |
: TImageWriter(f)
|
|
Toshihiro Shimizu |
890ddd |
//, m_maxThickness(0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setProperties(prop);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelWriterSvg::TLevelWriterSvg(const TFilePath &path, TPropertyGroup *winfo)
|
|
Toshihiro Shimizu |
890ddd |
: TLevelWriter(path, winfo)
|
|
Toshihiro Shimizu |
890ddd |
//, m_pli (0)
|
|
Toshihiro Shimizu |
890ddd |
//, m_frameNumber (0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void writeRegion(TRegion *r, TPalette *plt, QTextStream &out, double ly)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (r->getEdgeCount() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<const *="" tquadratic=""> quadsOutline;</const>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < (int)r->getEdgeCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
TEdge *e = r->getEdge(i);
|
|
Toshihiro Shimizu |
890ddd |
TStroke *s = e->m_s;
|
|
Toshihiro Shimizu |
890ddd |
int index0, index1;
|
|
Toshihiro Shimizu |
890ddd |
double t0, t1;
|
|
Toshihiro Shimizu |
890ddd |
double w0 = e->m_w0, w1 = e->m_w1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (w0 > w1) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *s1 = new TStroke(*s);
|
|
Toshihiro Shimizu |
890ddd |
s1->changeDirection();
|
|
Toshihiro Shimizu |
890ddd |
double totalLength = s->getLength();
|
|
Toshihiro Shimizu |
890ddd |
w0 = s1->getParameterAtLength(totalLength - s->getLength(w0));
|
|
Toshihiro Shimizu |
890ddd |
w1 = s1->getParameterAtLength(totalLength - s->getLength(w1));
|
|
Toshihiro Shimizu |
890ddd |
s = s1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(w0 <= w1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
s->getChunkAndT(w0, index0, t0);
|
|
Toshihiro Shimizu |
890ddd |
s->getChunkAndT(w1, index1, t1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int j = index0; j <= index1; j++) {
|
|
Toshihiro Shimizu |
890ddd |
const TQuadratic *q = s->getChunk(j);
|
|
Toshihiro Shimizu |
890ddd |
if (j == index0 && t0 != 0) {
|
|
Toshihiro Shimizu |
890ddd |
TQuadratic q1, *q2 = new TQuadratic();
|
|
Toshihiro Shimizu |
890ddd |
q->split(t0, q1, *q2);
|
|
Toshihiro Shimizu |
890ddd |
q = q2;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (j == index1 && t1 != 1) {
|
|
Toshihiro Shimizu |
890ddd |
TQuadratic *q1 = new TQuadratic(), q2;
|
|
Toshihiro Shimizu |
890ddd |
q->split(t1, *q1, q2);
|
|
Toshihiro Shimizu |
890ddd |
q = q1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
quadsOutline.push_back(q);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (quadsOutline.empty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 col = plt->getStyle(r->getStyle())->getMainColor();
|
|
Toshihiro Shimizu |
890ddd |
if (col == TPixel::Transparent)
|
|
Toshihiro Shimizu |
890ddd |
col == TPixel::White;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "style=\"fill:rgb(" << col.r << "," << col.g << "," << col.b << ")\" \n";
|
|
Toshihiro Shimizu |
890ddd |
out << "d=\"M " << quadsOutline[0]->getP0().x << " " << ly - quadsOutline[0]->getP0().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < quadsOutline.size(); i++)
|
|
Toshihiro Shimizu |
890ddd |
out << "Q " << quadsOutline[i]->getP1().x << "," << ly - quadsOutline[i]->getP1().y << "," << quadsOutline[i]->getP2().x << "," << ly - quadsOutline[i]->getP2().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
out << " \" /> \n";
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < (int)r->getSubregionCount(); i++)
|
|
Toshihiro Shimizu |
890ddd |
writeRegion(r->getSubregion(i), plt, out, ly);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void writeOutlineStroke(TStroke *s, TPalette *plt, QTextStream &out, double ly, double quality)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (s->getChunkCount() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
if (s->getMaxThickness() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<tquadratic *=""> quadsOutline;</tquadratic>
|
|
Toshihiro Shimizu |
890ddd |
computeOutlines(s, 0, s->getChunkCount() - 1, quadsOutline, quality);
|
|
Toshihiro Shimizu |
890ddd |
if (quadsOutline.empty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 col = plt->getStyle(s->getStyle())->getMainColor();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "style=\"fill:rgb(" << col.r << "," << col.g << "," << col.b << ")\" \n";
|
|
Toshihiro Shimizu |
890ddd |
out << "d=\"M " << quadsOutline[0]->getP0().x << " " << ly - quadsOutline[0]->getP0().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < quadsOutline.size(); i++)
|
|
Toshihiro Shimizu |
890ddd |
out << "Q " << quadsOutline[i]->getP1().x << "," << ly - quadsOutline[i]->getP1().y << "," << quadsOutline[i]->getP2().x << "," << ly - quadsOutline[i]->getP2().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
out << " \" /> \n";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double computeAverageThickness(const TStroke *s)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int count = s->getControlPointCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double resThick = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < s->getControlPointCount(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
double thick = s->getControlPoint(i).thick;
|
|
Toshihiro Shimizu |
890ddd |
if (i >= 2 && i < s->getControlPointCount() - 2)
|
|
Toshihiro Shimizu |
890ddd |
resThick += thick;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (count < 6)
|
|
Toshihiro Shimizu |
890ddd |
return s->getControlPoint(count / 2 + 1).thick;
|
|
Toshihiro Shimizu |
890ddd |
return resThick / (s->getControlPointCount() - 4);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void writeCenterlineStroke(TStroke *s, TPalette *plt, QTextStream &out, double ly)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (s->getChunkCount() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
if (s->getMaxThickness() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double thick = 2 * computeAverageThickness(s);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 col = plt->getStyle(s->getStyle())->getMainColor();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "style=\"stroke:rgb(" << col.r << "," << col.g << "," << col.b << ")\" stroke-width=\"" << thick << " \" \n";
|
|
Toshihiro Shimizu |
890ddd |
out << "d=\"M " << s->getChunk(0)->getP0().x << " " << ly - s->getChunk(0)->getP0().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < s->getChunkCount(); i++)
|
|
Toshihiro Shimizu |
890ddd |
out << "Q " << s->getChunk(i)->getP1().x << "," << ly - s->getChunk(i)->getP1().y << "," << s->getChunk(i)->getP2().x << "," << ly - s->getChunk(i)->getP2().y << "\n";
|
|
Toshihiro Shimizu |
890ddd |
out << " \" /> \n";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Tiio::SvgWriterProperties::SvgWriterProperties()
|
|
Toshihiro Shimizu |
890ddd |
: m_strokeMode("Stroke Mode"), m_outlineQuality("Outline Quality")
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_strokeMode.addValue(L"Centerline");
|
|
Toshihiro Shimizu |
890ddd |
m_strokeMode.addValue(L"Outline");
|
|
Toshihiro Shimizu |
890ddd |
m_outlineQuality.addValue(L"High");
|
|
Toshihiro Shimizu |
890ddd |
m_outlineQuality.addValue(L"Medium");
|
|
Toshihiro Shimizu |
890ddd |
m_outlineQuality.addValue(L"Low");
|
|
Toshihiro Shimizu |
890ddd |
bind(m_strokeMode);
|
|
Toshihiro Shimizu |
890ddd |
bind(m_outlineQuality);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//void writeSvg(QString path, TVectorImageP v)
|
|
Toshihiro Shimizu |
890ddd |
void TImageWriterSvg::save(const TImageP &img)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TVectorImageP v = (const TVectorImageP)img;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (v->getStrokeCount() == 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPalette *plt = v->getPalette();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRectD r = v->getBBox();
|
|
Toshihiro Shimizu |
890ddd |
double ly = r.getP00().y + r.getP11().y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QFile file(this->getFilePath().getQString());
|
|
Toshihiro Shimizu |
890ddd |
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTextStream out(&file);
|
|
Toshihiro Shimizu |
890ddd |
out.setRealNumberPrecision(1);
|
|
Toshihiro Shimizu |
890ddd |
out.setRealNumberNotation(QTextStream::FixedNotation);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "\n";
|
|
Toshihiro Shimizu |
890ddd |
out << "\n";
|
|
Toshihiro Shimizu |
890ddd |
out << "<svg version="\"1.1\"" xmlns:xmlns="\"http://www.w3.org/2000/svg\"">\n";</svg>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << "<g ")\"="" ","="" -r.getp00().x="" -r.getp00().y="" <<="" fill="\"none\"" stroke-width="\"0\"" transform="\"translate("">\n";</g>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isCenterline = ((TEnumProperty *)(m_properties->getProperty("Stroke Mode")))->getValue() == L"Centerline";
|
|
Toshihiro Shimizu |
890ddd |
double quality = 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isCenterline) {
|
|
Toshihiro Shimizu |
890ddd |
if (((TEnumProperty *)(m_properties->getProperty("Outline Quality")))->getValue() == L"Low")
|
|
Toshihiro Shimizu |
890ddd |
quality = 200;
|
|
Toshihiro Shimizu |
890ddd |
else if (((TEnumProperty *)(m_properties->getProperty("Outline Quality")))->getValue() == L"Medium")
|
|
Toshihiro Shimizu |
890ddd |
quality = 10;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < (int)v->getRegionCount(); j++)
|
|
Toshihiro Shimizu |
890ddd |
writeRegion(v->getRegion(j), plt, out, ly);
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < (int)v->getStrokeCount(); j++)
|
|
Toshihiro Shimizu |
890ddd |
if (isCenterline)
|
|
Toshihiro Shimizu |
890ddd |
writeCenterlineStroke(v->getStroke(j), plt, out, ly);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
writeOutlineStroke(v->getStroke(j), plt, out, ly, quality);
|
|
Toshihiro Shimizu |
890ddd |
out << " \n";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
out << " \n";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int addColorToPalette(TPalette *plt, unsigned int _color)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPixel color(_color & 0xFF, (_color >> 8) & 0xFF, _color >> 16);
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < plt->getStyleCount(); i++)
|
|
Toshihiro Shimizu |
890ddd |
if (plt->getStyle(i)->getMainColor() == color)
|
|
Toshihiro Shimizu |
890ddd |
return i;
|
|
Toshihiro Shimizu |
890ddd |
TPalette::Page *page = plt->getPage(0);
|
|
Toshihiro Shimizu |
890ddd |
int index = page->addStyle(color);
|
|
Toshihiro Shimizu |
890ddd |
return index; //plt->addStyle(color);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int findColor(TPalette *plt, unsigned int _color)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPixel color(_color & 0xFF, (_color >> 8) & 0xFF, _color >> 16);
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < plt->getStyleCount(); i++)
|
|
Toshihiro Shimizu |
890ddd |
if (plt->getStyle(i)->getMainColor() == color)
|
|
Toshihiro Shimizu |
890ddd |
return i;
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
return -1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TStroke *buildStroke(NSVGpath *path, float width)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert((path->npts - 1) % 3 == 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint p0 = TThickPoint(path->pts[0], -path->pts[1], width);
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
points.push_back(p0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 1; i < path->npts; i += 3) {
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<tthickquadratic *=""> chunkArray;</tthickquadratic>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
computeQuadraticsFromCubic(p0,
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint(path->pts[2 * i], -path->pts[2 * i + 1], width),
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint(path->pts[2 * i + 2], -path->pts[2 * i + 3], width),
|
|
Toshihiro Shimizu |
890ddd |
TThickPoint(path->pts[2 * i + 4], -path->pts[2 * i + 5], width), 0.01, chunkArray);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < chunkArray.size(); j++) {
|
|
Toshihiro Shimizu |
890ddd |
points.push_back(chunkArray[j]->getP1());
|
|
Toshihiro Shimizu |
890ddd |
points.push_back(chunkArray[j]->getP2());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
p0 = chunkArray.back()->getP2();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (points.empty())
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (path->closed) {
|
|
Toshihiro Shimizu |
890ddd |
if (points.back() != points.front()) {
|
|
Toshihiro Shimizu |
890ddd |
points.push_back(0.5 * (points.back() + points.front()));
|
|
Toshihiro Shimizu |
890ddd |
points.push_back(points.front());
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
int gasp = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
TStroke *s = new TStroke(points);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
s->setSelfLoop(path->closed);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return s;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageP TImageReaderSvg::load()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
NSVGimage *svgImg = nsvgParseFromFile(m_path.getQString().toStdString().c_str());
|
|
Toshihiro Shimizu |
890ddd |
if (!svgImg)
|
|
Toshihiro Shimizu |
890ddd |
return TImageP();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPalette *plt = m_level->getPalette();
|
|
Toshihiro Shimizu |
890ddd |
assert(plt);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImage *vimage = new TVectorImage();
|
|
Toshihiro Shimizu |
890ddd |
vimage->setPalette(plt);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (NSVGshape *shape = svgImg->shapes; shape; shape = shape->next) {
|
|
Toshihiro Shimizu |
890ddd |
int inkIndex, paintIndex;
|
|
Toshihiro Shimizu |
890ddd |
NSVGpath *path = shape->paths;
|
|
Toshihiro Shimizu |
890ddd |
if (!path)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//TVectorImageP vapp = new TVectorImage();
|
|
Toshihiro Shimizu |
890ddd |
//TPalette* appPlt = new TPalette();
|
|
Toshihiro Shimizu |
890ddd |
//vapp->setPalette(appPlt);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPixel color(shape->fillColor & 0xFF, (shape->fillColor >> 8) & 0xFF, shape->fillColor >> 16);
|
|
Toshihiro Shimizu |
890ddd |
if (!shape->hasFill) {
|
|
Toshihiro Shimizu |
890ddd |
assert(color == TPixel::Black);
|
|
Toshihiro Shimizu |
890ddd |
shape->hasFill = true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasStroke)
|
|
Toshihiro Shimizu |
890ddd |
inkIndex = findColor(plt, shape->strokeColor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasFill)
|
|
Toshihiro Shimizu |
890ddd |
paintIndex = findColor(plt, shape->fillColor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//vapp->setPalette(plt.getPointer());
|
|
Toshihiro Shimizu |
890ddd |
int startStrokeIndex = vimage->getStrokeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (; path; path = path->next) {
|
|
Toshihiro Shimizu |
890ddd |
TStroke *s = buildStroke(path, shape->hasStroke ? shape->strokeWidth : 0);
|
|
Toshihiro Shimizu |
890ddd |
if (!s)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
s->setStyle(shape->hasStroke ? inkIndex : 0);
|
|
Toshihiro Shimizu |
890ddd |
vimage->addStroke(s);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (startStrokeIndex == vimage->getStrokeCount())
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vimage->group(startStrokeIndex, vimage->getStrokeCount() - startStrokeIndex);
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasFill) {
|
|
Toshihiro Shimizu |
890ddd |
vimage->enterGroup(startStrokeIndex);
|
|
Toshihiro Shimizu |
890ddd |
vimage->selectFill(TRectD(-9999999, -9999999, 9999999, 9999999), 0, paintIndex, true, true, false);
|
|
Toshihiro Shimizu |
890ddd |
vimage->exitGroup();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* vapp->findRegions();
|
|
Toshihiro Shimizu |
890ddd |
if (paintIndex!=-1)
|
|
Toshihiro Shimizu |
890ddd |
for (int i=0; i<(int)vapp->getRegionCount(); i++)
|
|
Toshihiro Shimizu |
890ddd |
vapp->getRegion(i)->setStyle(paintIndex);
|
|
Shinya Kitaoka |
3bfa54 |
std::vector<int> indexes(vapp->getStrokeCount());</int>
|
|
Toshihiro Shimizu |
890ddd |
for (int i=0; i<(int)vapp->getStrokeCount() ;i++)
|
|
Toshihiro Shimizu |
890ddd |
indexes[i] = vimage->getStrokeCount()+i;
|
|
Toshihiro Shimizu |
890ddd |
vimage->insertImage(vapp, indexes);*/
|
|
Toshihiro Shimizu |
890ddd |
//delete appPlt;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvgDelete(svgImg);
|
|
Toshihiro Shimizu |
890ddd |
//if (m_level)
|
|
Toshihiro Shimizu |
890ddd |
// m_level->setPalette(plt);
|
|
Toshihiro Shimizu |
890ddd |
return TImageP(vimage);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelReaderSvg::TLevelReaderSvg(const TFilePath &path)
|
|
Toshihiro Shimizu |
890ddd |
: TLevelReader(path)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TImageReaderP TLevelReaderSvg::getFrameReader(TFrameId fid)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return new TImageReaderSvg(getFilePath().withFrame(fid), m_level);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TLevelP TLevelReaderSvg::loadInfo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_level = TLevelReader::loadInfo();
|
|
Toshihiro Shimizu |
890ddd |
TPalette *plt = new TPalette();
|
|
Toshihiro Shimizu |
890ddd |
TLevel::Iterator it = m_level->begin();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; it != m_level->end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
NSVGimage *svgImg = nsvgParseFromFile(m_path.withFrame(it->first).getQString().toStdString().c_str());
|
|
Toshihiro Shimizu |
890ddd |
if (!svgImg)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (NSVGshape *shape = svgImg->shapes; shape; shape = shape->next) {
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasStroke)
|
|
Toshihiro Shimizu |
890ddd |
addColorToPalette(plt, shape->strokeColor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (shape->hasFill)
|
|
Toshihiro Shimizu |
890ddd |
addColorToPalette(plt, shape->fillColor);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
nsvgDelete(svgImg);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_level->setPalette(plt);
|
|
Toshihiro Shimizu |
890ddd |
return m_level;
|
|
Toshihiro Shimizu |
890ddd |
}
|