mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
SvgLoader: Implement SVG Loader and SimpleXMLParser
Load svg using fstream and parse it using SimpleXMLparser. And Make a document tree composed of SvgNodes using the parsed data. Change-Id: I5715b466638195844798f7b66f54f6015e7c3ae6
This commit is contained in:
parent
4d6dee91e4
commit
3a8d6821ba
6 changed files with 2966 additions and 18 deletions
|
@ -1,5 +1,8 @@
|
|||
source_file = [
|
||||
'tvgSimpleXmlParser.h',
|
||||
'tvgSvgLoader.h',
|
||||
'tvgSvgLoaderCommon.h',
|
||||
'tvgSimpleXmlParser.cpp',
|
||||
'tvgSvgLoader.cpp',
|
||||
]
|
||||
|
||||
|
|
346
src/loaders/svg_loader/tvgSimpleXmlParser.cpp
Normal file
346
src/loaders/svg_loader/tvgSimpleXmlParser.cpp
Normal file
|
@ -0,0 +1,346 @@
|
|||
#include "tvgSimpleXmlParser.h"
|
||||
|
||||
static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd)
|
||||
{
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if (isspace((unsigned char)*itr)) break;
|
||||
}
|
||||
return itr;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlSkipWhiteSpace(const char* itr, const char* itrEnd)
|
||||
{
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if (!isspace((unsigned char)*itr)) break;
|
||||
}
|
||||
return itr;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlUnskipWhiteSpace(const char* itr, const char* itrStart)
|
||||
{
|
||||
for (itr--; itr > itrStart; itr--) {
|
||||
if (!isspace((unsigned char)*itr)) break;
|
||||
}
|
||||
return itr + 1;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd)
|
||||
{
|
||||
return (const char*)memchr(itr, '<', itrEnd - itr);
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlFindEndTag(const char* itr, const char* itrEnd)
|
||||
{
|
||||
bool insideQuote = false;
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if (*itr == '"') insideQuote = !insideQuote;
|
||||
if (!insideQuote) {
|
||||
if ((*itr == '>') || (*itr == '<'))
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlFindEndCommentTag(const char* itr, const char* itrEnd)
|
||||
{
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if ((*itr == '-') && ((itr + 1 < itrEnd) && (*(itr + 1) == '-')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlFindEndCdataTag(const char* itr, const char* itrEnd)
|
||||
{
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if ((*itr == ']') && ((itr + 1 < itrEnd) && (*(itr + 1) == ']')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static const char* _simpleXmlFindDoctypeChildEndTag(const char* itr, const char* itrEnd)
|
||||
{
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if (*itr == '>') return itr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data)
|
||||
{
|
||||
const char *itr = buf, *itrEnd = buf + bufLength;
|
||||
char* tmpBuf = (char*)alloca(bufLength + 1);
|
||||
|
||||
if (!buf) return false;
|
||||
if (!func) return false;
|
||||
|
||||
while (itr < itrEnd) {
|
||||
const char* p = _simpleXmlSkipWhiteSpace(itr, itrEnd);
|
||||
const char *key, *keyEnd, *value, *valueEnd;
|
||||
char* tval;
|
||||
|
||||
if (p == itrEnd) return true;
|
||||
|
||||
key = p;
|
||||
for (keyEnd = key; keyEnd < itrEnd; keyEnd++) {
|
||||
if ((*keyEnd == '=') || (isspace((unsigned char)*keyEnd))) break;
|
||||
}
|
||||
if (keyEnd == itrEnd) return false;
|
||||
if (keyEnd == key) continue;
|
||||
|
||||
if (*keyEnd == '=') value = keyEnd + 1;
|
||||
else {
|
||||
value = (const char*)memchr(keyEnd, '=', itrEnd - keyEnd);
|
||||
if (!value) return false;
|
||||
value++;
|
||||
}
|
||||
for (; value < itrEnd; value++) {
|
||||
if (!isspace((unsigned char)*value)) break;
|
||||
}
|
||||
if (value == itrEnd) return false;
|
||||
|
||||
if ((*value == '"') || (*value == '\'')) {
|
||||
valueEnd = (const char*)memchr(value + 1, *value, itrEnd - value);
|
||||
if (!valueEnd) return false;
|
||||
value++;
|
||||
} else {
|
||||
valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd);
|
||||
}
|
||||
|
||||
memcpy(tmpBuf, key, keyEnd - key);
|
||||
tmpBuf[keyEnd - key] = '\0';
|
||||
|
||||
tval = tmpBuf + (keyEnd - key) + 1;
|
||||
memcpy(tval, value, valueEnd - value);
|
||||
tval[valueEnd - value] = '\0';
|
||||
|
||||
if (!func((void*)data, tmpBuf, tval)) return false;
|
||||
|
||||
itr = valueEnd + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data)
|
||||
{
|
||||
const char *itr = buf, *itrEnd = buf + bufLength;
|
||||
|
||||
if (!buf) return false;
|
||||
if (!func) return false;
|
||||
|
||||
#define CB(type, start, end) \
|
||||
do { \
|
||||
size_t _sz = end - start; \
|
||||
bool _ret; \
|
||||
_ret = func((void*)data, type, start, start - buf, _sz); \
|
||||
if (!_ret) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
while (itr < itrEnd) {
|
||||
if (itr[0] == '<') {
|
||||
if (itr + 1 >= itrEnd) {
|
||||
CB(SimpleXMLType::Error, itr, itrEnd);
|
||||
return false;
|
||||
} else {
|
||||
SimpleXMLType type;
|
||||
size_t toff;
|
||||
const char* p;
|
||||
|
||||
if (itr[1] == '/') {
|
||||
type = SimpleXMLType::Close;
|
||||
toff = 1;
|
||||
} else if (itr[1] == '?') {
|
||||
type = SimpleXMLType::Processing;
|
||||
toff = 1;
|
||||
} else if (itr[1] == '!') {
|
||||
if ((itr + sizeof("<!DOCTYPE>") - 1 < itrEnd) && (!memcmp(itr + 2, "DOCTYPE", sizeof("DOCTYPE") - 1)) && ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || (isspace((unsigned char)itr[2 + sizeof("DOCTYPE") - 1])))) {
|
||||
type = SimpleXMLType::Doctype;
|
||||
toff = sizeof("!DOCTYPE") - 1;
|
||||
} else if ((itr + sizeof("<!---->") - 1 < itrEnd) && (!memcmp(itr + 2, "--", sizeof("--") - 1))) {
|
||||
type = SimpleXMLType::Comment;
|
||||
toff = sizeof("!--") - 1;
|
||||
} else if ((itr + sizeof("<![CDATA[]]>") - 1 < itrEnd) && (!memcmp(itr + 2, "[CDATA[", sizeof("[CDATA[") - 1))) {
|
||||
type = SimpleXMLType::CData;
|
||||
toff = sizeof("![CDATA[") - 1;
|
||||
} else if (itr + sizeof("<!>") - 1 < itrEnd) {
|
||||
type = SimpleXMLType::DoctypeChild;
|
||||
toff = sizeof("!") - 1;
|
||||
} else {
|
||||
type = SimpleXMLType::Open;
|
||||
toff = 0;
|
||||
}
|
||||
} else {
|
||||
type = SimpleXMLType::Open;
|
||||
toff = 0;
|
||||
}
|
||||
|
||||
if (type == SimpleXMLType::CData) p = _simpleXmlFindEndCdataTag(itr + 1 + toff, itrEnd);
|
||||
else if (type == SimpleXMLType::DoctypeChild) p = _simpleXmlFindDoctypeChildEndTag(itr + 1 + toff, itrEnd);
|
||||
else if (type == SimpleXMLType::Comment) p = _simpleXmlFindEndCommentTag(itr + 1 + toff, itrEnd);
|
||||
else p = _simpleXmlFindEndTag(itr + 1 + toff, itrEnd);
|
||||
|
||||
if ((p) && (*p == '<')) {
|
||||
type = SimpleXMLType::Error;
|
||||
toff = 0;
|
||||
}
|
||||
|
||||
if (p) {
|
||||
const char *start, *end;
|
||||
|
||||
start = itr + 1 + toff;
|
||||
end = p;
|
||||
|
||||
switch (type) {
|
||||
case SimpleXMLType::Open: {
|
||||
if (p[-1] == '/') {
|
||||
type = SimpleXMLType::OpenEmpty;
|
||||
end--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SimpleXMLType::CData: {
|
||||
if (!memcmp(p - 2, "]]", 2)) end -= 2;
|
||||
break;
|
||||
}
|
||||
case SimpleXMLType::Processing: {
|
||||
if (p[-1] == '?') end--;
|
||||
break;
|
||||
}
|
||||
case SimpleXMLType::Comment: {
|
||||
if (!memcmp(p - 2, "--", 2)) end -= 2;
|
||||
break;
|
||||
}
|
||||
case SimpleXMLType::OpenEmpty:
|
||||
case SimpleXMLType::Close:
|
||||
case SimpleXMLType::Data:
|
||||
case SimpleXMLType::Error:
|
||||
case SimpleXMLType::Doctype:
|
||||
case SimpleXMLType::DoctypeChild:
|
||||
case SimpleXMLType::Ignored: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((strip) && (type != SimpleXMLType::Error) && (type != SimpleXMLType::CData)) {
|
||||
start = _simpleXmlSkipWhiteSpace(start, end);
|
||||
end = _simpleXmlUnskipWhiteSpace(end, start + 1);
|
||||
}
|
||||
|
||||
CB(type, start, end);
|
||||
|
||||
if (type != SimpleXMLType::Error) itr = p + 1;
|
||||
else itr = p;
|
||||
} else {
|
||||
CB(SimpleXMLType::Error, itr, itrEnd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char *p, *end;
|
||||
|
||||
if (strip) {
|
||||
p = _simpleXmlSkipWhiteSpace(itr, itrEnd);
|
||||
if (p) {
|
||||
CB(SimpleXMLType::Ignored, itr, p);
|
||||
itr = p;
|
||||
}
|
||||
}
|
||||
|
||||
p = _simpleXmlFindStartTag(itr, itrEnd);
|
||||
if (!p) p = itrEnd;
|
||||
|
||||
end = p;
|
||||
if (strip) end = _simpleXmlUnskipWhiteSpace(end, itr);
|
||||
|
||||
if (itr != end) CB(SimpleXMLType::Data, itr, end);
|
||||
|
||||
if ((strip) && (end < p)) CB(SimpleXMLType::Ignored, end, p);
|
||||
|
||||
itr = p;
|
||||
}
|
||||
}
|
||||
|
||||
#undef CB
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data)
|
||||
{
|
||||
const char* end;
|
||||
char* key;
|
||||
char* val;
|
||||
char* next;
|
||||
|
||||
if (!buf) return false;
|
||||
|
||||
end = buf + strlen(buf);
|
||||
key = (char*)alloca(end - buf + 1);
|
||||
val = (char*)alloca(end - buf + 1);
|
||||
|
||||
if (buf == end) return true;
|
||||
|
||||
do {
|
||||
char* sep = (char*)strchr(buf, ':');
|
||||
next = (char*)strchr(buf, ';');
|
||||
|
||||
key[0] = '\0';
|
||||
val[0] = '\0';
|
||||
|
||||
if (next == nullptr && sep != nullptr) {
|
||||
memcpy(key, buf, sep - buf);
|
||||
key[sep - buf] = '\0';
|
||||
|
||||
memcpy(val, sep + 1, end - sep - 1);
|
||||
val[end - sep - 1] = '\0';
|
||||
} else if (sep < next && sep != nullptr) {
|
||||
memcpy(key, buf, sep - buf);
|
||||
key[sep - buf] = '\0';
|
||||
|
||||
memcpy(val, sep + 1, next - sep - 1);
|
||||
val[next - sep - 1] = '\0';
|
||||
} else if (next) {
|
||||
memcpy(key, buf, next - buf);
|
||||
key[next - buf] = '\0';
|
||||
}
|
||||
|
||||
if (key[0]) {
|
||||
if (!func((void*)data, key, val)) return false;
|
||||
}
|
||||
|
||||
buf = next + 1;
|
||||
} while (next != nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength)
|
||||
{
|
||||
const char *itr = buf, *itrEnd = buf + bufLength;
|
||||
|
||||
for (; itr < itrEnd; itr++) {
|
||||
if (!isspace((unsigned char)*itr)) {
|
||||
//User skip tagname and already gave it the attributes.
|
||||
if (*itr == '=') return buf;
|
||||
} else {
|
||||
itr = _simpleXmlSkipWhiteSpace(itr + 1, itrEnd);
|
||||
if (itr == itrEnd) return nullptr;
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
31
src/loaders/svg_loader/tvgSimpleXmlParser.h
Normal file
31
src/loaders/svg_loader/tvgSimpleXmlParser.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _TVG_SIMPLE_XML_PARSER_H_
|
||||
#define _TVG_SIMPLE_XML_PARSER_H_
|
||||
|
||||
#include <ctype.h>
|
||||
#include <cstring>
|
||||
#include <alloca.h>
|
||||
|
||||
enum class SimpleXMLType
|
||||
{
|
||||
Open = 0, //!< \<tag attribute="value"\>
|
||||
OpenEmpty, //!< \<tag attribute="value" /\>
|
||||
Close, //!< \</tag\>
|
||||
Data, //!< tag text data
|
||||
CData, //!< \<![cdata[something]]\>
|
||||
Error, //!< error contents
|
||||
Processing, //!< \<?xml ... ?\> \<?php .. ?\>
|
||||
Doctype, //!< \<!doctype html
|
||||
Comment, //!< \<!-- something --\>
|
||||
Ignored, //!< whatever is ignored by parser, like whitespace
|
||||
DoctypeChild //!< \<!doctype_child
|
||||
};
|
||||
|
||||
typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned offset, unsigned length);
|
||||
typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value);
|
||||
|
||||
bool simpleXmlParseAttributes(const char* buf, unsigned buflen, simpleXMLAttributeCb func, const void* data);
|
||||
bool simpleXmlParse(const char* buf, unsigned buflen, bool strip, simpleXMLCb func, const void* data);
|
||||
bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data);
|
||||
const char *simpleXmlFindAttributesTag(const char* buf, unsigned buflen);
|
||||
|
||||
#endif //_TVG_SIMPLE_XML_PARSER_H_
|
File diff suppressed because it is too large
Load diff
|
@ -17,12 +17,13 @@
|
|||
#ifndef _TVG_SVG_LOADER_H_
|
||||
#define _TVG_SVG_LOADER_H_
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgSvgLoaderCommon.h"
|
||||
|
||||
class SvgLoader : public Loader
|
||||
{
|
||||
private:
|
||||
//TODO:
|
||||
string content;
|
||||
SvgLoaderData loaderData;
|
||||
|
||||
public:
|
||||
SvgLoader();
|
||||
|
@ -35,4 +36,4 @@ public:
|
|||
};
|
||||
|
||||
|
||||
#endif //_TVG_SVG_LOADER_H_
|
||||
#endif //_TVG_SVG_LOADER_H_
|
||||
|
|
337
src/loaders/svg_loader/tvgSvgLoaderCommon.h
Normal file
337
src/loaders/svg_loader/tvgSvgLoaderCommon.h
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TVG_SVG_LOADER_COMMON_H_
|
||||
#define _TVG_SVG_LOADER_COMMON_H_
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgSimpleXmlParser.h"
|
||||
|
||||
enum class SvgNodeType
|
||||
{
|
||||
Doc,
|
||||
G,
|
||||
Defs,
|
||||
//Switch, //Not support
|
||||
Animation,
|
||||
Arc,
|
||||
Circle,
|
||||
Ellipse,
|
||||
Image,
|
||||
Line,
|
||||
Path,
|
||||
Polygon,
|
||||
Polyline,
|
||||
Rect,
|
||||
Text,
|
||||
TextArea,
|
||||
Tspan,
|
||||
Use,
|
||||
Video,
|
||||
//Custome_command, //Not support
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum class SvgLengthType
|
||||
{
|
||||
Percent,
|
||||
Px,
|
||||
Pc,
|
||||
Pt,
|
||||
Mm,
|
||||
Cm,
|
||||
In,
|
||||
};
|
||||
|
||||
enum class SvgFillFlags
|
||||
{
|
||||
Paint = 0x1,
|
||||
Opacity = 0x2,
|
||||
Gradient = 0x4,
|
||||
FillRule = 0x8
|
||||
};
|
||||
|
||||
enum class SvgStrokeFlags
|
||||
{
|
||||
Paint = 0x1,
|
||||
Opacity = 0x2,
|
||||
Gradient = 0x4,
|
||||
Scale = 0x8,
|
||||
Width = 0x10,
|
||||
Cap = 0x20,
|
||||
Join = 0x40,
|
||||
Dash = 0x80,
|
||||
};
|
||||
|
||||
enum class SvgGradientType
|
||||
{
|
||||
Linear,
|
||||
Radial
|
||||
};
|
||||
|
||||
enum class SvgStyleType
|
||||
{
|
||||
Quality,
|
||||
Fill,
|
||||
ViewportFill,
|
||||
Font,
|
||||
Stroke,
|
||||
SolidColor,
|
||||
Gradient,
|
||||
Transform,
|
||||
Opacity,
|
||||
CompOp
|
||||
};
|
||||
|
||||
enum class SvgGradientSpread
|
||||
{
|
||||
Pad = 0,
|
||||
Reflect,
|
||||
Repeat,
|
||||
Last
|
||||
};
|
||||
|
||||
enum class SvgFillRule
|
||||
{
|
||||
Winding = 0,
|
||||
OddEven = 1
|
||||
};
|
||||
|
||||
//Length type to recalculate %, pt, pc, mm, cm etc
|
||||
enum class SvgParserLengthType
|
||||
{
|
||||
Vertical,
|
||||
Horizontal,
|
||||
//In case of, for example, radius of radial gradient
|
||||
Other
|
||||
};
|
||||
|
||||
typedef struct _SvgNode SvgNode;
|
||||
typedef struct _SvgStyleGradient SvgStyleGradient;
|
||||
|
||||
struct SvgDocNode
|
||||
{
|
||||
float w;
|
||||
float h;
|
||||
float vx;
|
||||
float vy;
|
||||
float vw;
|
||||
float vh;
|
||||
SvgNode* defs;
|
||||
bool preserveAspect;
|
||||
};
|
||||
|
||||
struct SvgGNode
|
||||
{
|
||||
};
|
||||
|
||||
struct SvgDefsNode
|
||||
{
|
||||
vector<SvgStyleGradient *> gradients;
|
||||
};
|
||||
|
||||
struct SvgArcNode
|
||||
{
|
||||
};
|
||||
|
||||
struct SvgEllipseNode
|
||||
{
|
||||
float cx;
|
||||
float cy;
|
||||
float rx;
|
||||
float ry;
|
||||
};
|
||||
|
||||
struct SvgCircleNode
|
||||
{
|
||||
float cx;
|
||||
float cy;
|
||||
float r;
|
||||
};
|
||||
|
||||
struct SvgRectNode
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
float rx;
|
||||
float ry;
|
||||
};
|
||||
|
||||
struct SvgLineNode
|
||||
{
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
};
|
||||
|
||||
struct SvgPathNode
|
||||
{
|
||||
string* path;
|
||||
};
|
||||
|
||||
struct SvgPolygonNode
|
||||
{
|
||||
int pointsCount;
|
||||
float* points;
|
||||
};
|
||||
|
||||
struct SvgLinearGradient
|
||||
{
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
};
|
||||
|
||||
struct SvgRadialGradient
|
||||
{
|
||||
float cx;
|
||||
float cy;
|
||||
float fx;
|
||||
float fy;
|
||||
float r;
|
||||
};
|
||||
|
||||
struct SvgGradientStop
|
||||
{
|
||||
float offset;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
};
|
||||
|
||||
struct SvgPaint
|
||||
{
|
||||
SvgStyleGradient* gradient;
|
||||
string* url;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
bool none;
|
||||
bool curColor;
|
||||
};
|
||||
|
||||
struct SvgDash
|
||||
{
|
||||
float length;
|
||||
float gap;
|
||||
};
|
||||
|
||||
struct _SvgStyleGradient
|
||||
{
|
||||
SvgGradientType type;
|
||||
string* id;
|
||||
string* ref;
|
||||
SvgGradientSpread spread;
|
||||
vector<SvgGradientStop *> stops;
|
||||
SvgRadialGradient* radial;
|
||||
SvgLinearGradient* linear;
|
||||
Matrix* transform;
|
||||
bool userSpace;
|
||||
bool usePercentage;
|
||||
};
|
||||
|
||||
struct SvgStyleFill
|
||||
{
|
||||
SvgFillFlags flags;
|
||||
SvgPaint paint;
|
||||
int opacity;
|
||||
SvgFillRule fillRule;
|
||||
};
|
||||
|
||||
struct SvgStyleStroke
|
||||
{
|
||||
SvgStrokeFlags flags;
|
||||
SvgPaint paint;
|
||||
int opacity;
|
||||
float scale;
|
||||
float width;
|
||||
float centered;
|
||||
StrokeCap cap;
|
||||
StrokeJoin join;
|
||||
SvgDash* dash;
|
||||
int dashCount;
|
||||
};
|
||||
|
||||
struct SvgStyleProperty
|
||||
{
|
||||
SvgStyleFill fill;
|
||||
SvgStyleStroke stroke;
|
||||
int opacity;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
struct _SvgNode
|
||||
{
|
||||
SvgNodeType type;
|
||||
SvgNode* parent;
|
||||
vector<SvgNode*> child;
|
||||
string* id;
|
||||
SvgStyleProperty* style;
|
||||
Matrix* transform;
|
||||
union {
|
||||
SvgGNode g;
|
||||
SvgDocNode doc;
|
||||
SvgDefsNode defs;
|
||||
SvgArcNode arc;
|
||||
SvgCircleNode circle;
|
||||
SvgEllipseNode ellipse;
|
||||
SvgPolygonNode polygon;
|
||||
SvgPolygonNode polyline;
|
||||
SvgRectNode rect;
|
||||
SvgPathNode path;
|
||||
SvgLineNode line;
|
||||
} node;
|
||||
bool display;
|
||||
};
|
||||
|
||||
struct SvgParser
|
||||
{
|
||||
SvgNode* node;
|
||||
SvgStyleGradient* styleGrad;
|
||||
SvgGradientStop* gradStop;
|
||||
struct
|
||||
{
|
||||
int x, y;
|
||||
uint32_t w, h;
|
||||
} global;
|
||||
struct
|
||||
{
|
||||
bool parsedFx;
|
||||
bool parsedFy;
|
||||
} gradient;
|
||||
};
|
||||
|
||||
struct SvgLoaderData
|
||||
{
|
||||
vector<SvgNode *> stack;
|
||||
SvgNode* doc;
|
||||
SvgNode* def;
|
||||
vector<SvgStyleGradient*> gradients;
|
||||
SvgStyleGradient* latestGradient; //For stops
|
||||
SvgParser* svgParse;
|
||||
int level;
|
||||
bool result;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue