This Array is promoted from SvgVector to use it widely in tvg.
It's similar with std::vector, we can use it instead of it.
Also, svg_loader replaced with it subsequently.
Change-Id: I1ddca958508ed7ceae9f173c6f8167b5318e1604
--- /dev/null
+/*
+ * 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<class T>
+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<T*>(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_
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)
{
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;
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;
}
return result;
}
-static void _cloneGradStops(SvgVector<Fill::ColorStop*>* dst, SvgVector<Fill::ColorStop*>* src)
+static void _cloneGradStops(Array<Fill::ColorStop*>* dst, Array<Fill::ColorStop*>* src)
{
- for (uint32_t i = 0; i < src->cnt; ++i) {
+ for (uint32_t i = 0; i < src->count; ++i) {
auto stop = static_cast<Fill::ColorStop *>(malloc(sizeof(Fill::ColorStop)));
- *stop = *src->list[i];
+ *stop = *src->data[i];
dst->push(stop);
}
}
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);
}
}
loader->doc = node;
} else {
if (!strcmp(tagName, "svg")) return; //Already loadded <svg>(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);
}
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))) {
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]);
}
}
}
{
_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<SvgStyleGradient*>* gradients, string* id)
+static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* 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;
}
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
}
-static void _updateGradient(SvgNode* node, SvgVector<SvgStyleGradient*>* gradidents)
+static void _updateGradient(SvgNode* node, Array<SvgStyleGradient*>* 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 {
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);
}
}
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();
_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);
}
{
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();
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;
}
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);
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;
}
this->done();
if (root) return move(root);
else return nullptr;
-}
-
+}
\ No newline at end of file
#define _TVG_SVG_LOADER_COMMON_H_
#include "tvgCommon.h"
+#include "tvgArray.h"
enum class SvgNodeType
{
struct SvgNode;
struct SvgStyleGradient;
-template<class T>
-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<T*>(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
{
struct SvgDefsNode
{
- SvgVector<SvgStyleGradient*> gradients;
+ Array<SvgStyleGradient*> gradients;
};
struct SvgArcNode
struct SvgDash
{
- SvgVector<float> array;
+ Array<float> array;
};
struct SvgStyleGradient
SvgRadialGradient* radial;
SvgLinearGradient* linear;
Matrix* transform;
- SvgVector<Fill::ColorStop *> stops;
+ Array<Fill::ColorStop *> stops;
bool userSpace;
bool usePercentage;
};
{
SvgNodeType type;
SvgNode* parent;
- SvgVector<SvgNode*> child;
+ Array<SvgNode*> child;
string *id;
SvgStyleProperty *style;
Matrix* transform;
struct SvgLoaderData
{
- SvgVector<SvgNode *> stack = {nullptr, 0, 0};
+ Array<SvgNode *> stack = {nullptr, 0, 0};
SvgNode* doc = nullptr;
SvgNode* def = nullptr;
- SvgVector<SvgStyleGradient*> gradients;
+ Array<SvgStyleGradient*> gradients;
SvgStyleGradient* latestGradient = nullptr; //For stops
SvgParser* svgParse = nullptr;
int level = 0;
return true;
}
-void _pathAppendArcTo(SvgVector<PathCommand>* cmds, SvgVector<Point>* pts, Point* cur, Point* curCtl, float x, float y, float rx, float ry, float angle, bool largeArc, bool sweep)
+void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* 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;
}
-static void _processCommand(SvgVector<PathCommand>* cmds, SvgVector<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic)
+static void _processCommand(Array<PathCommand>* cmds, Array<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic)
{
int i;
switch (cmd) {
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;
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;
}
-bool svgPathToTvgPath(const char* svgPath, SvgVector<PathCommand>& cmds, SvgVector<Point>& pts)
+bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts)
{
float numberArray[7];
int numberCount = 0;
#include "tvgSvgLoaderCommon.h"
-bool svgPathToTvgPath(const char* svgPath, SvgVector<PathCommand>& cmds, SvgVector<Point>& pts);
+bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts);
#endif //_TVG_SVG_PATH_H_
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;
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;
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);
}
}
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) {
//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);
}
}
bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh)
{
- SvgVector<PathCommand> cmds;
- SvgVector<Point> pts;
+ Array<PathCommand> cmds;
+ Array<Point> 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;
}
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 {
//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);
}
}