2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef _TVG_SHAPE_PATH_CPP_
18 #define _TVG_SHAPE_PATH_CPP_
20 #include "tvgCommon.h"
22 /************************************************************************/
23 /* Internal Class Implementation */
24 /************************************************************************/
28 PathCommand* cmds = nullptr;
30 size_t reservedCmdCnt = 0;
34 size_t reservedPtsCnt = 0;
39 if (cmds) delete(cmds);
43 void reserveCmd(size_t cmdCnt)
45 if (cmdCnt <= reservedCmdCnt) return;
46 reservedCmdCnt = cmdCnt;
47 cmds = static_cast<PathCommand*>(realloc(cmds, sizeof(PathCommand) * reservedCmdCnt));
51 void reservePts(size_t ptsCnt)
53 if (ptsCnt <= reservedPtsCnt) return;
54 reservedPtsCnt = ptsCnt;
55 pts = static_cast<Point*>(realloc(pts, sizeof(Point) * reservedPtsCnt));
59 void grow(size_t cmdCnt, size_t ptsCnt)
61 reserveCmd(this->cmdCnt + cmdCnt);
62 reservePts(this->ptsCnt + ptsCnt);
71 void append(const PathCommand* cmds, size_t cmdCnt, const Point* pts, size_t ptsCnt)
73 memcpy(this->cmds + this->cmdCnt, cmds, sizeof(PathCommand) * cmdCnt);
74 memcpy(this->pts + this->ptsCnt, pts, sizeof(Point) * ptsCnt);
75 this->cmdCnt += cmdCnt;
76 this->ptsCnt += ptsCnt;
79 void moveTo(float x, float y)
81 if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
82 if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
84 cmds[cmdCnt++] = PathCommand::MoveTo;
85 pts[ptsCnt++] = {x, y};
88 void lineTo(float x, float y)
90 if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
91 if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
93 cmds[cmdCnt++] = PathCommand::LineTo;
94 pts[ptsCnt++] = {x, y};
97 void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
99 if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
100 if (ptsCnt + 3 > reservedPtsCnt) reservePts((ptsCnt + 3) * 2);
102 cmds[cmdCnt++] = PathCommand::CubicTo;
103 pts[ptsCnt++] = {cx1, cy1};
104 pts[ptsCnt++] = {cx2, cy2};
105 pts[ptsCnt++] = {x, y};
110 if (cmdCnt > 0 && cmds[cmdCnt - 1] == PathCommand::Close) return;
112 if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
113 cmds[cmdCnt++] = PathCommand::Close;
116 bool bounds(float& x, float& y, float& w, float& h)
118 if (ptsCnt == 0) return false;
120 Point min = { pts[0].x, pts[0].y };
121 Point max = { pts[0].x, pts[0].y };
123 for(size_t i = 1; i < ptsCnt; ++i) {
124 if (pts[i].x < min.x) min.x = pts[i].x;
125 if (pts[i].y < min.y) min.y = pts[i].y;
126 if (pts[i].x > max.x) max.x = pts[i].x;
127 if (pts[i].y > max.y) max.y = pts[i].y;
138 bool rotate(float degree)
140 constexpr auto PI = 3.141592f;
142 if (fabsf(degree) <= FLT_EPSILON) return false;
145 if (!bounds(x, y, w, h)) return false;
147 auto radian = degree / 180.0f * PI;
148 auto cx = x + w * 0.5f;
149 auto cy = y + h * 0.5f;
150 auto cosVal = cosf(radian);
151 auto sinVal = sinf(radian);
153 for(size_t i = 0; i < ptsCnt; ++i) {
154 auto dx = pts[i].x - cx;
155 auto dy = pts[i].y - cy;
156 pts[i].x = (cosVal * dx - sinVal * dy) + cx;
157 pts[i].y = (sinVal * dx + cosVal * dy) + cy;
163 bool scale(float factor)
165 if (fabsf(factor - 1) <= FLT_EPSILON) return false;
168 if (!bounds(x, y, w, h)) return false;
170 auto cx = x + w * 0.5f;
171 auto cy = y + h * 0.5f;
173 for(size_t i = 0; i < ptsCnt; ++i) {
174 pts[i].x = (pts[i].x - cx) * factor + cx;
175 pts[i].y = (pts[i].y - cy) * factor + cy;
182 #endif //_TVG_SHAPE_PATH_CPP_