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()
{
if (list) free(list);
list = nullptr;
if (list) {
free(list);
list = nullptr;
}
cnt = reserved = 0;
}
~SvgVector()
{
if (list) free(list);
}
};
struct SvgDocNode

View file

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

View file

@ -23,9 +23,8 @@
#ifndef _TVG_SVG_PATH_H_
#define _TVG_SVG_PATH_H_
#include <vector>
#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_

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)
{
SvgVector<PathCommand> cmds;
SvgVector<Point> pts;
switch (node->type) {
case SvgNodeType::Path: {
if (node->node.path.path) {
auto pathResult = svgPathToTvgPath(node->node.path.path->c_str());
shape->appendPath(get<0>(pathResult).data(), get<0>(pathResult).size(), get<1>(pathResult).data(), get<1>(pathResult).size());
if (svgPathToTvgPath(node->node.path.path->c_str(), cmds, pts))
shape->appendPath(cmds.list, cmds.cnt, pts.list, pts.cnt);
}
break;
}