diff --git a/src/lib/tvgArray.h b/src/lib/tvgArray.h new file mode 100644 index 00000000..7036cda8 --- /dev/null +++ b/src/lib/tvgArray.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_ARRAY_H_ +#define _TVG_ARRAY_H_ + + +namespace tvg +{ + +template +struct Array +{ + T* data = nullptr; + uint32_t count = 0; + uint32_t reserved = 0; + + void push(T element) + { + if (count + 1 > reserved) { + reserved = (count + 1) * 2; + data = static_cast(realloc(data, sizeof(T) * reserved)); + } + data[count++] = element; + } + + void pop() + { + if (count > 0) --count; + } + + void clear() + { + if (data) { + free(data); + data = nullptr; + } + count = reserved = 0; + } + + ~Array() + { + if (data) free(data); + } +}; + +} + +#endif //_TVG_ARRAY_H_ diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index ec9a5c1d..9ec874a9 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -244,7 +244,7 @@ _parseDashArray(const char *str, SvgDash* dash) str = _skipComma(end); } //If dash array size is 1, it means that dash and gap size are the same. - if ((*dash).array.cnt == 1) (*dash).array.push((*dash).array.list[0]); + if ((*dash).array.count == 1) (*dash).array.push((*dash).array.data[0]); } static string* _idFromUrl(const char* url) @@ -1435,8 +1435,8 @@ static SvgNode* _findChildById(SvgNode* node, const char* id) { if (!node) return nullptr; - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { if (((*child)->id != nullptr) && !strcmp((*child)->id->c_str(), id)) return (*child); } return nullptr; @@ -1447,9 +1447,9 @@ static SvgNode* _findNodeById(SvgNode *node, string* id) SvgNode* result = nullptr; if (node->id && !node->id->compare(*id)) return node; - if (node->child.cnt > 0) { - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { result = _findNodeById(*child, id); if (result) break; } @@ -1457,11 +1457,11 @@ static SvgNode* _findNodeById(SvgNode *node, string* id) return result; } -static void _cloneGradStops(SvgVector* dst, SvgVector* src) +static void _cloneGradStops(Array* dst, Array* src) { - for (uint32_t i = 0; i < src->cnt; ++i) { + for (uint32_t i = 0; i < src->count; ++i) { auto stop = static_cast(malloc(sizeof(Fill::ColorStop))); - *stop = *src->list[i]; + *stop = *src->data[i]; dst->push(stop); } } @@ -1571,8 +1571,8 @@ static void _cloneNode(SvgNode* from, SvgNode* parent) newNode = _createNode(parent, from->type); _copyAttr(newNode, from); - auto child = from->child.list; - for (uint32_t i = 0; i < from->child.cnt; ++i, ++child) { + auto child = from->child.data; + for (uint32_t i = 0; i < from->child.count; ++i, ++child) { _cloneNode(*child, newNode); } } @@ -2079,7 +2079,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, loader->doc = node; } else { if (!strcmp(tagName, "svg")) return; //Already loadded (SvgNodeType::Doc) tag - if (loader->stack.cnt > 0) parent = loader->stack.list[loader->stack.cnt - 1]; + if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1]; else parent = loader->doc; node = method(loader, parent, attrs, attrsLength); } @@ -2092,7 +2092,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, loader->stack.push(node); } } else if ((method = _findGraphicsFactory(tagName))) { - if (loader->stack.cnt > 0) parent = loader->stack.list[loader->stack.cnt - 1]; + if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1]; else parent = loader->doc; node = method(loader, parent, attrs, attrsLength); } else if ((gradientMethod = _findGradientFactory(tagName))) { @@ -2194,10 +2194,10 @@ static void _styleInherit(SvgStyleProperty* child, SvgStyleProperty* parent) child->stroke.width = parent->stroke.width; } if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Dash)) { - if (parent->stroke.dash.array.cnt > 0) { + if (parent->stroke.dash.array.count > 0) { child->stroke.dash.array.clear(); - for (uint32_t i = 0; i < parent->stroke.dash.array.cnt; ++i) { - child->stroke.dash.array.push(parent->stroke.dash.array.list[i]); + for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) { + child->stroke.dash.array.push(parent->stroke.dash.array.data[i]); } } } @@ -2214,20 +2214,20 @@ static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle) { _styleInherit(node->style, parentStyle); - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { _updateStyle(*child, node->style); } } -static SvgStyleGradient* _gradientDup(SvgVector* gradients, string* id) +static SvgStyleGradient* _gradientDup(Array* gradients, string* id) { SvgStyleGradient* result = nullptr; - auto gradList = gradients->list; + auto gradList = gradients->data; - for (uint32_t i = 0; i < gradients->cnt; ++i) { + for (uint32_t i = 0; i < gradients->count; ++i) { if (!((*gradList)->id->compare(*id))) { result = _cloneGradient(*gradList); break; @@ -2236,10 +2236,10 @@ static SvgStyleGradient* _gradientDup(SvgVector* gradients, s } if (result && result->ref) { - gradList = gradients->list; - for (uint32_t i = 0; i < gradients->cnt; ++i) { + gradList = gradients->data; + for (uint32_t i = 0; i < gradients->count; ++i) { if (!((*gradList)->id->compare(*result->ref))) { - if (result->stops.cnt > 0) { + if (result->stops.count > 0) { _cloneGradStops(&result->stops, &(*gradList)->stops); } //TODO: Properly inherit other property @@ -2253,11 +2253,11 @@ static SvgStyleGradient* _gradientDup(SvgVector* gradients, s } -static void _updateGradient(SvgNode* node, SvgVector* gradidents) +static void _updateGradient(SvgNode* node, Array* gradidents) { - if (node->child.cnt > 0) { - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + if (node->child.data > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { _updateGradient(*child, gradidents); } } else { @@ -2275,9 +2275,9 @@ static void _updateComposite(SvgNode* node, SvgNode* root) SvgNode *findResult = _findNodeById(root, node->style->comp.url); if (findResult) node->style->comp.node = findResult; } - if (node->child.cnt > 0) { - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { _updateComposite(*child, root); } } @@ -2293,8 +2293,8 @@ static void _freeGradientStyle(SvgStyleGradient* grad) free(grad->linear); if (grad->transform) free(grad->transform); - for (uint32_t i = 0; i < grad->stops.cnt; ++i) { - auto colorStop = grad->stops.list[i]; + for (uint32_t i = 0; i < grad->stops.count; ++i) { + auto colorStop = grad->stops.data[i]; free(colorStop); } grad->stops.clear(); @@ -2308,7 +2308,7 @@ static void _freeNodeStyle(SvgStyleProperty* style) _freeGradientStyle(style->fill.paint.gradient); delete style->fill.paint.url; _freeGradientStyle(style->stroke.paint.gradient); - if (style->stroke.dash.array.cnt > 0) style->stroke.dash.array.clear(); + if (style->stroke.dash.array.count > 0) style->stroke.dash.array.clear(); delete style->stroke.paint.url; free(style); } @@ -2317,8 +2317,8 @@ static void _freeNode(SvgNode* node) { if (!node) return; - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { _freeNode(*child); } node->child.clear(); @@ -2344,8 +2344,8 @@ static void _freeNode(SvgNode* node) break; } case SvgNodeType::Defs: { - auto gradients = node->node.defs.gradients.list; - for (size_t i = 0; i < node->node.defs.gradients.cnt; ++i) { + auto gradients = node->node.defs.gradients.data; + for (size_t i = 0; i < node->node.defs.gradients.count; ++i) { _freeGradientStyle(*gradients); ++gradients; } @@ -2445,7 +2445,7 @@ void SvgLoader::run(unsigned tid) auto defs = loaderData.doc->node.doc.defs; if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients); - if (loaderData.gradients.cnt > 0) _updateGradient(loaderData.doc, &loaderData.gradients); + if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients); _updateComposite(loaderData.doc, loaderData.doc); if (defs) _updateComposite(loaderData.doc, defs); @@ -2535,8 +2535,8 @@ bool SvgLoader::close() free(loaderData.svgParse); loaderData.svgParse = nullptr; } - auto gradients = loaderData.gradients.list; - for (size_t i = 0; i < loaderData.gradients.cnt; ++i) { + auto gradients = loaderData.gradients.data; + for (size_t i = 0; i < loaderData.gradients.count; ++i) { _freeGradientStyle(*gradients); ++gradients; } @@ -2555,5 +2555,4 @@ unique_ptr SvgLoader::scene() this->done(); if (root) return move(root); else return nullptr; -} - +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 6e3f272e..61d309cb 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -23,6 +23,7 @@ #define _TVG_SVG_LOADER_COMMON_H_ #include "tvgCommon.h" +#include "tvgArray.h" enum class SvgNodeType { @@ -125,41 +126,6 @@ enum class SvgParserLengthType struct SvgNode; struct SvgStyleGradient; -template -struct SvgVector -{ - T* list = nullptr; - uint32_t cnt = 0; - uint32_t reserved = 0; - - void push(T element) - { - if (cnt + 1 > reserved) { - reserved = (cnt + 1) * 2; - list = static_cast(realloc(list, sizeof(T) * reserved)); - } - list[cnt++] = element; - } - - void pop() - { - if (cnt > 0) --cnt; - } - - void clear() - { - if (list) { - free(list); - list = nullptr; - } - cnt = reserved = 0; - } - - ~SvgVector() - { - if (list) free(list); - } -}; struct SvgDocNode { @@ -179,7 +145,7 @@ struct SvgGNode struct SvgDefsNode { - SvgVector gradients; + Array gradients; }; struct SvgArcNode @@ -278,7 +244,7 @@ struct SvgPaint struct SvgDash { - SvgVector array; + Array array; }; struct SvgStyleGradient @@ -290,7 +256,7 @@ struct SvgStyleGradient SvgRadialGradient* radial; SvgLinearGradient* linear; Matrix* transform; - SvgVector stops; + Array stops; bool userSpace; bool usePercentage; }; @@ -332,7 +298,7 @@ struct SvgNode { SvgNodeType type; SvgNode* parent; - SvgVector child; + Array child; string *id; SvgStyleProperty *style; Matrix* transform; @@ -371,10 +337,10 @@ struct SvgParser struct SvgLoaderData { - SvgVector stack = {nullptr, 0, 0}; + Array stack = {nullptr, 0, 0}; SvgNode* doc = nullptr; SvgNode* def = nullptr; - SvgVector gradients; + Array gradients; SvgStyleGradient* latestGradient = nullptr; //For stops SvgParser* svgParse = nullptr; int level = 0; diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index f72e569c..0b08777a 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -59,7 +59,7 @@ static bool _parseFlag(char** content, int* number) return true; } -void _pathAppendArcTo(SvgVector* cmds, SvgVector* pts, Point* cur, Point* curCtl, float x, float y, float rx, float ry, float angle, bool largeArc, bool sweep) +void _pathAppendArcTo(Array* cmds, Array* pts, Point* cur, Point* curCtl, float x, float y, float rx, float ry, float angle, bool largeArc, bool sweep) { float cxp, cyp, cx, cy; float sx, sy; @@ -283,7 +283,7 @@ static int _numberCount(char cmd) } -static void _processCommand(SvgVector* cmds, SvgVector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic) +static void _processCommand(Array* cmds, Array* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic) { int i; switch (cmd) { @@ -353,7 +353,7 @@ static void _processCommand(SvgVector* cmds, SvgVector* pts, case 's': case 'S': { Point p[3], ctrl; - if ((cmds->cnt > 1) && (cmds->list[cmds->cnt - 1] == PathCommand::CubicTo) && + if ((cmds->count > 1) && (cmds->data[cmds->count - 1] == PathCommand::CubicTo) && !(*isQuadratic)) { ctrl.x = 2 * cur->x - curCtl->x; ctrl.y = 2 * cur->y - curCtl->y; @@ -394,7 +394,7 @@ static void _processCommand(SvgVector* cmds, SvgVector* pts, case 't': case 'T': { Point p[3], ctrl; - if ((cmds->cnt > 1) && (cmds->list[cmds->cnt - 1] == PathCommand::CubicTo) && + if ((cmds->count > 1) && (cmds->data[cmds->count - 1] == PathCommand::CubicTo) && *isQuadratic) { ctrl.x = 2 * cur->x - curCtl->x; ctrl.y = 2 * cur->y - curCtl->y; @@ -499,7 +499,7 @@ static char* _nextCommand(char* path, char* cmd, float* arr, int* count) } -bool svgPathToTvgPath(const char* svgPath, SvgVector& cmds, SvgVector& pts) +bool svgPathToTvgPath(const char* svgPath, Array& cmds, Array& pts) { float numberArray[7]; int numberCount = 0; diff --git a/src/loaders/svg/tvgSvgPath.h b/src/loaders/svg/tvgSvgPath.h index 2dbc2f41..86074cb7 100644 --- a/src/loaders/svg/tvgSvgPath.h +++ b/src/loaders/svg/tvgSvgPath.h @@ -25,6 +25,6 @@ #include "tvgSvgLoaderCommon.h" -bool svgPathToTvgPath(const char* svgPath, SvgVector& cmds, SvgVector& pts); +bool svgPathToTvgPath(const char* svgPath, Array& cmds, Array& pts); #endif //_TVG_SVG_PATH_H_ diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index e45c31a2..57b7d2ba 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -94,11 +94,11 @@ unique_ptr _applyLinearGradientProperty(SvgStyleGradient* g, Sha fillGrad->spread(g->spread); //Update the stops - stopCount = g->stops.cnt; + stopCount = g->stops.count; if (stopCount > 0) { stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); - for (uint32_t i = 0; i < g->stops.cnt; ++i) { - auto colorStop = g->stops.list[i]; + for (uint32_t i = 0; i < g->stops.count; ++i) { + auto colorStop = g->stops.data[i]; //Use premultiplied color stops[i].r = colorStop->r; stops[i].g = colorStop->g; @@ -176,11 +176,11 @@ unique_ptr _applyRadialGradientProperty(SvgStyleGradient* g, Sha fillGrad->spread(g->spread); //Update the stops - stopCount = g->stops.cnt; + stopCount = g->stops.count; if (stopCount > 0) { stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); - for (uint32_t i = 0; i < g->stops.cnt; ++i) { - auto colorStop = g->stops.list[i]; + for (uint32_t i = 0; i < g->stops.count; ++i) { + auto colorStop = g->stops.data[i]; //Use premultiplied color stops[i].r = colorStop->r; stops[i].g = colorStop->g; @@ -197,9 +197,9 @@ unique_ptr _applyRadialGradientProperty(SvgStyleGradient* g, Sha void _appendChildShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh) { _appendShape(node, shape, vx, vy, vw, vh); - if (node->child.cnt > 0) { - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) _appendChildShape(*child, shape, vx, vy, vw, vh); + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) _appendChildShape(*child, shape, vx, vy, vw, vh); } } @@ -240,8 +240,8 @@ void _applyProperty(SvgNode* node, Shape* vg, float vx, float vy, float vw, floa vg->stroke(style->stroke.width); vg->stroke(style->stroke.cap); vg->stroke(style->stroke.join); - if (style->stroke.dash.array.cnt > 0) - vg->stroke(style->stroke.dash.array.list, style->stroke.dash.array.cnt); + if (style->stroke.dash.array.count > 0) + vg->stroke(style->stroke.dash.array.data, style->stroke.dash.array.count); //If stroke property is nullptr then do nothing if (style->stroke.paint.none) { @@ -264,10 +264,10 @@ void _applyProperty(SvgNode* node, Shape* vg, float vx, float vy, float vw, floa //Composite ClipPath if (((int)style->comp.flags & (int)SvgCompositeFlags::ClipPath)) { auto compNode = style->comp.node; - if (compNode->child.cnt > 0) { + if (compNode->child.count > 0) { auto comp = Shape::gen(); - auto child = compNode->child.list; - for (uint32_t i = 0; i < compNode->child.cnt; ++i, ++child) _appendChildShape(*child, comp.get(), vx, vy, vw, vh); + auto child = compNode->child.data; + for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) _appendChildShape(*child, comp.get(), vx, vy, vw, vh); vg->composite(move(comp), CompositeMethod::ClipPath); } } @@ -283,14 +283,14 @@ unique_ptr _shapeBuildHelper(SvgNode* node, float vx, float vy, float vw, bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh) { - SvgVector cmds; - SvgVector pts; + Array cmds; + Array pts; switch (node->type) { case SvgNodeType::Path: { if (node->node.path.path) { if (svgPathToTvgPath(node->node.path.path->c_str(), cmds, pts)) - shape->appendPath(cmds.list, cmds.cnt, pts.list, pts.cnt); + shape->appendPath(cmds.data, cmds.count, pts.data, pts.count); } break; } @@ -344,8 +344,8 @@ unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, if (node->transform) scene->transform(*node->transform); if (node->display && node->style->opacity != 0) { - auto child = node->child.list; - for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { if (_isGroupType((*child)->type)) { scene->push(_sceneBuildHelper(*child, vx, vy, vw, vh)); } else { @@ -358,10 +358,10 @@ unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, //Composite ClipPath if (((int)node->style->comp.flags & (int)SvgCompositeFlags::ClipPath)) { auto compNode = node->style->comp.node; - if (compNode->child.cnt > 0) { + if (compNode->child.count > 0) { auto comp = Shape::gen(); - auto child = compNode->child.list; - for (uint32_t i = 0; i < compNode->child.cnt; ++i, ++child) _appendChildShape(*child, comp.get(), vx, vy, vw, vh); + auto child = compNode->child.data; + for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) _appendChildShape(*child, comp.get(), vx, vy, vw, vh); scene->composite(move(comp), CompositeMethod::ClipPath); } }