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_CPP_
18 #define _TVG_SHAPE_CPP_
20 #include "tvgCommon.h"
21 #include "tvgShapeImpl.h"
23 /************************************************************************/
24 /* Internal Class Implementation */
25 /************************************************************************/
26 constexpr auto PATH_KAPPA = 0.552284f;
29 /************************************************************************/
30 /* External Class Implementation */
31 /************************************************************************/
33 Shape :: Shape() : pImpl(make_unique<Impl>())
43 unique_ptr<Shape> Shape::gen() noexcept
45 return unique_ptr<Shape>(new Shape);
49 int Shape::reset() noexcept
51 auto impl = pImpl.get();
52 assert(impl && impl->path);
56 impl->flag |= RenderUpdateFlag::Path;
62 size_t Shape::pathCommands(const PathCommand** cmds) const noexcept
64 auto impl = pImpl.get();
65 assert(impl && impl->path && cmds);
67 *cmds = impl->path->cmds;
69 return impl->path->cmdCnt;
73 size_t Shape::pathCoords(const Point** pts) const noexcept
75 auto impl = pImpl.get();
76 assert(impl && impl->path && pts);
78 *pts = impl->path->pts;
80 return impl->path->ptsCnt;
84 int Shape::appendPath(const PathCommand *cmds, size_t cmdCnt, const Point* pts, size_t ptsCnt) noexcept
86 if (cmdCnt < 0 || ptsCnt < 0) return -1;
89 auto impl = pImpl.get();
90 assert(impl && impl->path);
92 impl->path->grow(cmdCnt, ptsCnt);
93 impl->path->append(cmds, cmdCnt, pts, ptsCnt);
95 impl->flag |= RenderUpdateFlag::Path;
101 int Shape::moveTo(float x, float y) noexcept
103 auto impl = pImpl.get();
104 assert(impl && impl->path);
106 impl->path->moveTo(x, y);
108 impl->flag |= RenderUpdateFlag::Path;
114 int Shape::lineTo(float x, float y) noexcept
116 auto impl = pImpl.get();
117 assert(impl && impl->path);
119 impl->path->lineTo(x, y);
121 impl->flag |= RenderUpdateFlag::Path;
127 int Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
129 auto impl = pImpl.get();
130 assert(impl && impl->path);
132 impl->path->cubicTo(cx1, cy1, cx2, cy2, x, y);
134 impl->flag |= RenderUpdateFlag::Path;
140 int Shape::close() noexcept
142 auto impl = pImpl.get();
143 assert(impl && impl->path);
147 impl->flag |= RenderUpdateFlag::Path;
153 int Shape::appendCircle(float cx, float cy, float radiusW, float radiusH) noexcept
155 auto impl = pImpl.get();
156 assert(impl && impl->path);
158 auto halfKappaW = radiusW * PATH_KAPPA;
159 auto halfKappaH = radiusH * PATH_KAPPA;
161 impl->path->grow(6, 13);
162 impl->path->moveTo(cx, cy - radiusH);
163 impl->path->cubicTo(cx + halfKappaW, cy - radiusH, cx + radiusW, cy - halfKappaH, cx + radiusW, cy);
164 impl->path->cubicTo(cx + radiusW, cy + halfKappaH, cx + halfKappaW, cy + radiusH, cx, cy + radiusH);
165 impl->path->cubicTo(cx - halfKappaW, cy + radiusH, cx - radiusW, cy + halfKappaH, cx - radiusW, cy);
166 impl->path->cubicTo(cx - radiusW, cy - halfKappaH, cx - halfKappaW, cy - radiusH, cx, cy - radiusH);
169 impl->flag |= RenderUpdateFlag::Path;
175 int Shape::appendRect(float x, float y, float w, float h, float cornerRadius) noexcept
177 auto impl = pImpl.get();
178 assert(impl && impl->path);
180 //clamping cornerRadius by minimum size
181 auto min = (w < h ? w : h) * 0.5f;
182 if (cornerRadius > min) cornerRadius = min;
185 if (cornerRadius == 0) {
186 impl->path->grow(5, 4);
187 impl->path->moveTo(x, y);
188 impl->path->lineTo(x + w, y);
189 impl->path->lineTo(x + w, y + h);
190 impl->path->lineTo(x, y + h);
193 } else if (w == h && cornerRadius * 2 == w) {
194 return appendCircle(x + (w * 0.5f), y + (h * 0.5f), cornerRadius, cornerRadius);
196 auto halfKappa = cornerRadius * 0.5;
197 impl->path->grow(10, 17);
198 impl->path->moveTo(x + cornerRadius, y);
199 impl->path->lineTo(x + w - cornerRadius, y);
200 impl->path->cubicTo(x + w - cornerRadius + halfKappa, y, x + w, y + cornerRadius - halfKappa, x + w, y + cornerRadius);
201 impl->path->lineTo(x + w, y + h - cornerRadius);
202 impl->path->cubicTo(x + w, y + h - cornerRadius + halfKappa, x + w - cornerRadius + halfKappa, y + h, x + w - cornerRadius, y + h);
203 impl->path->lineTo(x + cornerRadius, y + h);
204 impl->path->cubicTo(x + cornerRadius - halfKappa, y + h, x, y + h - cornerRadius + halfKappa, x, y + h - cornerRadius);
205 impl->path->lineTo(x, y + cornerRadius);
206 impl->path->cubicTo(x, y + cornerRadius - halfKappa, x + cornerRadius - halfKappa, y, x + cornerRadius, y);
210 impl->flag |= RenderUpdateFlag::Path;
216 int Shape::fill(size_t r, size_t g, size_t b, size_t a) noexcept
218 auto impl = pImpl.get();
225 impl->flag |= RenderUpdateFlag::Fill;
231 int Shape::fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept
233 auto impl = pImpl.get();
236 if (r) *r = impl->color[0];
237 if (g) *g = impl->color[1];
238 if (b) *b = impl->color[2];
239 if (a) *a = impl->color[3];
245 int Shape::scale(float factor) noexcept
247 auto impl = pImpl.get();
250 return impl->scale(factor);
254 int Shape::rotate(float degree) noexcept
256 auto impl = pImpl.get();
259 return impl->rotate(degree);
263 int Shape::translate(float x, float y) noexcept
265 auto impl = pImpl.get();
268 return impl->translate(x, y);
272 int Shape::bounds(float& x, float& y, float& w, float& h) const noexcept
274 auto impl = pImpl.get();
277 if (!impl->bounds(x, y, w, h)) return -1;
283 #endif //_TVG_SHAPE_CPP_