svg_loader: code refactoring

Use custom vector data algorithm for optimizing binary size.
Plus remove tuple usage since it leads unnecessary instance copying.

binary size comparison:

[libthorvg.so] 1811400 >> 1785448
[text] 122914 >> 121255
[data] 7824 >> 7792
[dec] 130810 >> 129119
This commit is contained in:
Hermet Park 2020-12-09 14:07:13 +09:00 committed by Hermet Park
parent 924490a7a5
commit ca6639bb2c
4 changed files with 52 additions and 46 deletions

View file

@ -148,10 +148,17 @@ struct SvgVector
void clear() void clear()
{ {
if (list) free(list); if (list) {
list = nullptr; free(list);
list = nullptr;
}
cnt = reserved = 0; cnt = reserved = 0;
} }
~SvgVector()
{
if (list) free(list);
}
}; };
struct SvgDocNode struct SvgDocNode

View file

@ -59,7 +59,7 @@ static bool _parseFlag(char** content, int* number)
return true; return true;
} }
void _pathAppendArcTo(vector<PathCommand>* cmds, vector<Point>* pts, Point* cur, Point* curCtl, float x, float y, float rx, float ry, float angle, bool largeArc, bool sweep) 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)
{ {
float cxp, cyp, cx, cy; float cxp, cyp, cx, cy;
float sx, sy; float sx, sy;
@ -92,8 +92,8 @@ void _pathAppendArcTo(vector<PathCommand>* cmds, vector<Point>* pts, Point* cur,
ry = fabsf(ry); ry = fabsf(ry);
if ((rx < 0.5f) || (ry < 0.5f)) { if ((rx < 0.5f) || (ry < 0.5f)) {
Point p = {x, y}; Point p = {x, y};
cmds->push_back(PathCommand::LineTo); cmds->push(PathCommand::LineTo);
pts->push_back(p); pts->push(p);
*cur = p; *cur = p;
return; return;
} }
@ -217,13 +217,13 @@ void _pathAppendArcTo(vector<PathCommand>* cmds, vector<Point>* pts, Point* cur,
//Second control point (based on end point ex,ey) //Second control point (based on end point ex,ey)
c2x = ex + bcp * (cosPhiRx * sinTheta2 + sinPhiRy * cosTheta2); c2x = ex + bcp * (cosPhiRx * sinTheta2 + sinPhiRy * cosTheta2);
c2y = ey + bcp * (sinPhiRx * sinTheta2 - cosPhiRy * cosTheta2); c2y = ey + bcp * (sinPhiRx * sinTheta2 - cosPhiRy * cosTheta2);
cmds->push_back(PathCommand::CubicTo); cmds->push(PathCommand::CubicTo);
p[0] = {c1x, c1y}; p[0] = {c1x, c1y};
p[1] = {c2x, c2y}; p[1] = {c2x, c2y};
p[2] = {ex, ey}; p[2] = {ex, ey};
pts->push_back(p[0]); pts->push(p[0]);
pts->push_back(p[1]); pts->push(p[1]);
pts->push_back(p[2]); pts->push(p[2]);
*curCtl = p[1]; *curCtl = p[1];
*cur = p[2]; *cur = p[2];
@ -283,7 +283,7 @@ static int _numberCount(char cmd)
} }
static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic) static void _processCommand(SvgVector<PathCommand>* cmds, SvgVector<Point>* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic)
{ {
int i; int i;
switch (cmd) { switch (cmd) {
@ -321,8 +321,8 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
case 'm': case 'm':
case 'M': { case 'M': {
Point p = {arr[0], arr[1]}; Point p = {arr[0], arr[1]};
cmds->push_back(PathCommand::MoveTo); cmds->push(PathCommand::MoveTo);
pts->push_back(p); pts->push(p);
*cur = {arr[0], arr[1]}; *cur = {arr[0], arr[1]};
*startPoint = {arr[0], arr[1]}; *startPoint = {arr[0], arr[1]};
break; break;
@ -330,21 +330,21 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
case 'l': case 'l':
case 'L': { case 'L': {
Point p = {arr[0], arr[1]}; Point p = {arr[0], arr[1]};
cmds->push_back(PathCommand::LineTo); cmds->push(PathCommand::LineTo);
pts->push_back(p); pts->push(p);
*cur = {arr[0], arr[1]}; *cur = {arr[0], arr[1]};
break; break;
} }
case 'c': case 'c':
case 'C': { case 'C': {
Point p[3]; Point p[3];
cmds->push_back(PathCommand::CubicTo); cmds->push(PathCommand::CubicTo);
p[0] = {arr[0], arr[1]}; p[0] = {arr[0], arr[1]};
p[1] = {arr[2], arr[3]}; p[1] = {arr[2], arr[3]};
p[2] = {arr[4], arr[5]}; p[2] = {arr[4], arr[5]};
pts->push_back(p[0]); pts->push(p[0]);
pts->push_back(p[1]); pts->push(p[1]);
pts->push_back(p[2]); pts->push(p[2]);
*curCtl = p[1]; *curCtl = p[1];
*cur = p[2]; *cur = p[2];
*isQuadratic = false; *isQuadratic = false;
@ -353,20 +353,20 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
case 's': case 's':
case 'S': { case 'S': {
Point p[3], ctrl; Point p[3], ctrl;
if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && if ((cmds->cnt > 1) && (cmds->list[cmds->cnt - 1] == PathCommand::CubicTo) &&
!(*isQuadratic)) { !(*isQuadratic)) {
ctrl.x = 2 * cur->x - curCtl->x; ctrl.x = 2 * cur->x - curCtl->x;
ctrl.y = 2 * cur->y - curCtl->y; ctrl.y = 2 * cur->y - curCtl->y;
} else { } else {
ctrl = *cur; ctrl = *cur;
} }
cmds->push_back(PathCommand::CubicTo); cmds->push(PathCommand::CubicTo);
p[0] = ctrl; p[0] = ctrl;
p[1] = {arr[0], arr[1]}; p[1] = {arr[0], arr[1]};
p[2] = {arr[2], arr[3]}; p[2] = {arr[2], arr[3]};
pts->push_back(p[0]); pts->push(p[0]);
pts->push_back(p[1]); pts->push(p[1]);
pts->push_back(p[2]); pts->push(p[2]);
*curCtl = p[1]; *curCtl = p[1];
*cur = p[2]; *cur = p[2];
*isQuadratic = false; *isQuadratic = false;
@ -379,13 +379,13 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
float ctrl_y0 = (cur->y + 2 * arr[1]) * (1.0 / 3.0); float ctrl_y0 = (cur->y + 2 * arr[1]) * (1.0 / 3.0);
float ctrl_x1 = (arr[2] + 2 * arr[0]) * (1.0 / 3.0); float ctrl_x1 = (arr[2] + 2 * arr[0]) * (1.0 / 3.0);
float ctrl_y1 = (arr[3] + 2 * arr[1]) * (1.0 / 3.0); float ctrl_y1 = (arr[3] + 2 * arr[1]) * (1.0 / 3.0);
cmds->push_back(PathCommand::CubicTo); cmds->push(PathCommand::CubicTo);
p[0] = {ctrl_x0, ctrl_y0}; p[0] = {ctrl_x0, ctrl_y0};
p[1] = {ctrl_x1, ctrl_y1}; p[1] = {ctrl_x1, ctrl_y1};
p[2] = {arr[2], arr[3]}; p[2] = {arr[2], arr[3]};
pts->push_back(p[0]); pts->push(p[0]);
pts->push_back(p[1]); pts->push(p[1]);
pts->push_back(p[2]); pts->push(p[2]);
*curCtl = {arr[0], arr[1]}; *curCtl = {arr[0], arr[1]};
*cur = p[2]; *cur = p[2];
*isQuadratic = true; *isQuadratic = true;
@ -394,7 +394,7 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
case 't': case 't':
case 'T': { case 'T': {
Point p[3], ctrl; Point p[3], ctrl;
if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && if ((cmds->cnt > 1) && (cmds->list[cmds->cnt - 1] == PathCommand::CubicTo) &&
*isQuadratic) { *isQuadratic) {
ctrl.x = 2 * cur->x - curCtl->x; ctrl.x = 2 * cur->x - curCtl->x;
ctrl.y = 2 * cur->y - curCtl->y; ctrl.y = 2 * cur->y - curCtl->y;
@ -405,13 +405,13 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
float ctrl_y0 = (cur->y + 2 * ctrl.y) * (1.0 / 3.0); float ctrl_y0 = (cur->y + 2 * ctrl.y) * (1.0 / 3.0);
float ctrl_x1 = (arr[0] + 2 * ctrl.x) * (1.0 / 3.0); float ctrl_x1 = (arr[0] + 2 * ctrl.x) * (1.0 / 3.0);
float ctrl_y1 = (arr[1] + 2 * ctrl.y) * (1.0 / 3.0); float ctrl_y1 = (arr[1] + 2 * ctrl.y) * (1.0 / 3.0);
cmds->push_back(PathCommand::CubicTo); cmds->push(PathCommand::CubicTo);
p[0] = {ctrl_x0, ctrl_y0}; p[0] = {ctrl_x0, ctrl_y0};
p[1] = {ctrl_x1, ctrl_y1}; p[1] = {ctrl_x1, ctrl_y1};
p[2] = {arr[0], arr[1]}; p[2] = {arr[0], arr[1]};
pts->push_back(p[0]); pts->push(p[0]);
pts->push_back(p[1]); pts->push(p[1]);
pts->push_back(p[2]); pts->push(p[2]);
*curCtl = {ctrl.x, ctrl.y}; *curCtl = {ctrl.x, ctrl.y};
*cur = p[2]; *cur = p[2];
*isQuadratic = true; *isQuadratic = true;
@ -420,22 +420,22 @@ static void _processCommand(vector<PathCommand>* cmds, vector<Point>* pts, char
case 'h': case 'h':
case 'H': { case 'H': {
Point p = {arr[0], cur->y}; Point p = {arr[0], cur->y};
cmds->push_back(PathCommand::LineTo); cmds->push(PathCommand::LineTo);
pts->push_back(p); pts->push(p);
cur->x = arr[0]; cur->x = arr[0];
break; break;
} }
case 'v': case 'v':
case 'V': { case 'V': {
Point p = {cur->x, arr[0]}; Point p = {cur->x, arr[0]};
cmds->push_back(PathCommand::LineTo); cmds->push(PathCommand::LineTo);
pts->push_back(p); pts->push(p);
cur->y = arr[0]; cur->y = arr[0];
break; break;
} }
case 'z': case 'z':
case 'Z': { case 'Z': {
cmds->push_back(PathCommand::Close); cmds->push(PathCommand::Close);
*cur = *startPoint; *cur = *startPoint;
break; break;
} }
@ -499,11 +499,8 @@ static char* _nextCommand(char* path, char* cmd, float* arr, int* count)
} }
tuple<vector<PathCommand>, vector<Point>> svgPathToTvgPath(const char* svgPath) bool svgPathToTvgPath(const char* svgPath, SvgVector<PathCommand>& cmds, SvgVector<Point>& pts)
{ {
vector<PathCommand> cmds;
vector<Point> pts;
float numberArray[7]; float numberArray[7];
int numberCount = 0; int numberCount = 0;
Point cur = { 0, 0 }; Point cur = { 0, 0 };
@ -527,5 +524,5 @@ tuple<vector<PathCommand>, vector<Point>> svgPathToTvgPath(const char* svgPath)
setlocale(LC_NUMERIC, curLocale); setlocale(LC_NUMERIC, curLocale);
if (curLocale) free(curLocale); if (curLocale) free(curLocale);
return make_tuple(cmds, pts); return true;
} }

View file

@ -23,9 +23,8 @@
#ifndef _TVG_SVG_PATH_H_ #ifndef _TVG_SVG_PATH_H_
#define _TVG_SVG_PATH_H_ #define _TVG_SVG_PATH_H_
#include <vector>
#include "tvgSvgLoaderCommon.h" #include "tvgSvgLoaderCommon.h"
tuple<vector<tvg::PathCommand>, vector<tvg::Point>> svgPathToTvgPath(const char* svg_path_data); bool svgPathToTvgPath(const char* svgPath, SvgVector<PathCommand>& cmds, SvgVector<Point>& pts);
#endif //_TVG_SVG_PATH_H_ #endif //_TVG_SVG_PATH_H_

View file

@ -283,11 +283,14 @@ unique_ptr<Shape> _shapeBuildHelper(SvgNode* node, float vx, float vy, float vw,
bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh) bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh)
{ {
SvgVector<PathCommand> cmds;
SvgVector<Point> pts;
switch (node->type) { switch (node->type) {
case SvgNodeType::Path: { case SvgNodeType::Path: {
if (node->node.path.path) { if (node->node.path.path) {
auto pathResult = svgPathToTvgPath(node->node.path.path->c_str()); if (svgPathToTvgPath(node->node.path.path->c_str(), cmds, pts))
shape->appendPath(get<0>(pathResult).data(), get<0>(pathResult).size(), get<1>(pathResult).data(), get<1>(pathResult).size()); shape->appendPath(cmds.list, cmds.cnt, pts.list, pts.cnt);
} }
break; break;
} }