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_SW_SHAPE_H_
18 #define _TVG_SW_SHAPE_H_
20 #include "tvgSwCommon.h"
22 /************************************************************************/
23 /* Internal Class Implementation */
24 /************************************************************************/
26 static inline SwPoint TO_SWPOINT(const Point* pt)
28 return {SwCoord(pt->x * 64), SwCoord(pt->y * 64)};
32 static void _growOutlineContour(SwOutline& outline, size_t n)
36 outline.cntrs = nullptr;
38 outline.reservedCntrsCnt = 0;
41 if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return;
43 //cout << "Grow Cntrs: " << outline.reservedCntrsCnt << " -> " << outline.cntrsCnt + n << endl;;
44 outline.reservedCntrsCnt = n;
45 outline.cntrs = static_cast<size_t*>(realloc(outline.cntrs, n * sizeof(size_t)));
46 assert(outline.cntrs);
50 static void _growOutlinePoint(SwOutline& outline, size_t n)
54 outline.pts = nullptr;
56 outline.types = nullptr;
57 outline.reservedPtsCnt = 0;
62 if (outline.reservedPtsCnt >= outline.ptsCnt + n) return;
64 //cout << "Grow Pts: " << outline.reservedPtsCnt << " -> " << outline.ptsCnt + n << endl;
65 outline.reservedPtsCnt = n;
66 outline.pts = static_cast<SwPoint*>(realloc(outline.pts, n * sizeof(SwPoint)));
68 outline.types = static_cast<uint8_t*>(realloc(outline.types, n * sizeof(uint8_t)));
69 assert(outline.types);
73 static void _outlineEnd(SwOutline& outline)
75 _growOutlineContour(outline, 1);
76 if (outline.ptsCnt > 0) {
77 outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
83 static void _outlineMoveTo(SwOutline& outline, const Point* to)
87 _growOutlinePoint(outline, 1);
89 outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
90 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
92 if (outline.ptsCnt > 0) {
93 _growOutlineContour(outline, 1);
94 outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
102 static void _outlineLineTo(SwOutline& outline, const Point* to)
106 _growOutlinePoint(outline, 1);
108 outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
109 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
115 static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to)
117 assert(ctrl1 && ctrl2 && to);
119 _growOutlinePoint(outline, 3);
121 outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl1);
122 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
125 outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl2);
126 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
129 outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
130 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
135 static bool _outlineClose(SwOutline& outline)
139 if (outline.cntrsCnt > 0) {
140 i = outline.cntrs[outline.cntrsCnt - 1] + 1;
145 //Make sure there is at least one point in the current path
146 if (outline.ptsCnt == i) return false;
149 _growOutlinePoint(outline, 1);
151 outline.pts[outline.ptsCnt] = outline.pts[i];
152 outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
159 static void _initBBox(SwShape& sdata)
161 sdata.bbox.min.x = sdata.bbox.min.y = 0;
162 sdata.bbox.max.x = sdata.bbox.max.y = 0;
166 static bool _updateBBox(SwShape& sdata)
168 auto outline = sdata.outline;
171 auto pt = outline->pts;
174 if (outline->ptsCnt <= 0) {
186 for(size_t i = 1; i < outline->ptsCnt; ++i, ++pt) {
188 if (xMin > pt->x) xMin = pt->x;
189 if (xMax < pt->x) xMax = pt->x;
190 if (yMin > pt->y) yMin = pt->y;
191 if (yMax < pt->y) yMax = pt->y;
193 sdata.bbox.min.x = xMin >> 6;
194 sdata.bbox.max.x = (xMax + 63) >> 6;
195 sdata.bbox.min.y = yMin >> 6;
196 sdata.bbox.max.y = (yMax + 63) >> 6;
198 if (xMax - xMin < 1 || yMax - yMin < 1) return false;
204 void _deleteRle(SwShape& sdata)
207 if (sdata.rle->spans) free(sdata.rle->spans);
214 /************************************************************************/
215 /* External Class Implementation */
216 /************************************************************************/
218 bool shapeTransformOutline(const Shape& shape, SwShape& sdata)
220 constexpr auto PI = 3.141592f;
222 auto degree = shape.rotate();
223 auto scale = shape.scale();
224 bool rotateOn = false;
225 bool scaleOn = false;
227 if (fabsf(degree) > FLT_EPSILON) rotateOn = true;
228 if (fabsf(scale - 1) > FLT_EPSILON) scaleOn = true;
230 if (!rotateOn && !scaleOn) return true;
232 auto outline = sdata.outline;
236 shape.bounds(x, y, w, h);
238 auto cx = x + w * 0.5f;
239 auto cy = y + h * 0.5f;
241 float radian, cosVal, sinVal;
243 radian = degree / 180.0f * PI;
244 cosVal = cosf(radian);
245 sinVal = sinf(radian);
248 for(size_t i = 0; i < outline->ptsCnt; ++i) {
249 auto dx = static_cast<float>(outline->pts[i].x >> 6) - cx;
250 auto dy = static_cast<float>(outline->pts[i].y >> 6) - cy;
252 auto tx = (cosVal * dx - sinVal * dy);
253 auto ty = (sinVal * dx + cosVal * dy);
261 auto pt = Point{dx + cx, dy + cy};
262 outline->pts[i] = TO_SWPOINT(&pt);
269 bool shapeGenRle(const Shape& shape, SwShape& sdata, const SwSize& clip)
271 if (sdata.outline->ptsCnt == 0 || sdata.outline->cntrsCnt <= 0) goto end;
272 if (!_updateBBox(sdata)) goto end;
275 if ((sdata.bbox.min.x > clip.w || sdata.bbox.min.y > clip.h) ||
276 (sdata.bbox.min.x + sdata.bbox.max.x < 0) ||
277 (sdata.bbox.min.y + sdata.bbox.max.y < 0)) goto end;
279 sdata.rle = rleRender(sdata, clip);
282 if (sdata.rle) return true;
287 void shapeDelOutline(SwShape& sdata)
289 if (!sdata.outline) return;
291 SwOutline* outline = sdata.outline;
292 if (outline->cntrs) free(outline->cntrs);
293 if (outline->pts) free(outline->pts);
294 if (outline->types) free(outline->types);
297 sdata.outline = nullptr;
301 void shapeReset(SwShape& sdata)
303 shapeDelOutline(sdata);
309 bool shapeGenOutline(const Shape& shape, SwShape& sdata)
311 const PathCommand* cmds = nullptr;
312 auto cmdCnt = shape.pathCommands(&cmds);
314 const Point* pts = nullptr;
315 auto ptsCnt = shape.pathCoords(&pts);
317 //No actual shape data
318 if (cmdCnt == 0 || ptsCnt == 0) return false;
321 auto outlinePtsCnt = 0;
322 auto outlineCntrsCnt = 0;
324 for (size_t i = 0; i < cmdCnt; ++i) {
325 switch(*(cmds + i)) {
326 case PathCommand::Close: {
330 case PathCommand::MoveTo: {
335 case PathCommand::LineTo: {
339 case PathCommand::CubicTo: {
346 ++outlinePtsCnt; //for close
347 ++outlineCntrsCnt; //for end
349 SwOutline* outline = sdata.outline;
352 outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline)));
355 cout << "Outline was already allocated? How?" << endl;
358 _growOutlinePoint(*outline, outlinePtsCnt);
359 _growOutlineContour(*outline, outlineCntrsCnt);
362 while (cmdCnt-- > 0) {
364 case PathCommand::Close: {
365 _outlineClose(*outline);
368 case PathCommand::MoveTo: {
369 _outlineMoveTo(*outline, pts);
373 case PathCommand::LineTo: {
374 _outlineLineTo(*outline, pts);
378 case PathCommand::CubicTo: {
379 _outlineCubicTo(*outline, pts, pts + 1, pts + 2);
387 _outlineEnd(*outline);
390 //outline->flags = SwOutline::FillRule::Winding;
392 sdata.outline = outline;
398 #endif /* _TVG_SW_SHAPE_H_ */