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 = [
|
source_file = [
|
||||||
|
'tvgSimpleXmlParser.h',
|
||||||
'tvgSvgLoader.h',
|
'tvgSvgLoader.h',
|
||||||
|
'tvgSvgLoaderCommon.h',
|
||||||
|
'tvgSimpleXmlParser.cpp',
|
||||||
'tvgSvgLoader.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_
|
#ifndef _TVG_SVG_LOADER_H_
|
||||||
#define _TVG_SVG_LOADER_H_
|
#define _TVG_SVG_LOADER_H_
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgSvgLoaderCommon.h"
|
||||||
|
|
||||||
class SvgLoader : public Loader
|
class SvgLoader : public Loader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
//TODO:
|
string content;
|
||||||
|
SvgLoaderData loaderData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SvgLoader();
|
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