2 * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 #ifndef _TVG_SW_COMMON_H_
23 #define _TVG_SW_COMMON_H_
25 #include "tvgCommon.h"
26 #include "tvgRender.h"
28 #ifdef THORVG_AVX_VECTOR_SUPPORT
29 #include <immintrin.h>
32 #ifdef THORVG_NEON_VECTOR_SUPPORT
38 static double timeStamp()
41 gettimeofday(&tv, NULL);
42 return (tv.tv_sec + tv.tv_usec / 1000000.0);
46 #define SW_CURVE_TYPE_POINT 0
47 #define SW_CURVE_TYPE_CUBIC 1
48 #define SW_ANGLE_PI (180L << 16)
49 #define SW_ANGLE_2PI (SW_ANGLE_PI << 1)
50 #define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1)
51 #define SW_ANGLE_PI4 (SW_ANGLE_PI >> 2)
53 using SwCoord = signed long;
54 using SwFixed = signed long long;
60 SwPoint& operator+=(const SwPoint& rhs)
67 SwPoint operator+(const SwPoint& rhs) const
69 return {x + rhs.x, y + rhs.y};
72 SwPoint operator-(const SwPoint& rhs) const
74 return {x - rhs.x, y - rhs.y};
77 bool operator==(const SwPoint& rhs) const
79 return (x == rhs.x && y == rhs.y);
82 bool operator!=(const SwPoint& rhs) const
84 return (x != rhs.x || y != rhs.y);
89 if (x == 0 && y == 0) return true;
96 if (abs(x) < 2 && abs(y) < 2) return true;
109 uint32_t* cntrs; //the contour end points
110 uint32_t cntrsCnt; //number of contours in glyph
111 uint32_t reservedCntrsCnt;
112 SwPoint* pts; //the outline's points
113 uint32_t ptsCnt; //number of points in the glyph
114 uint32_t reservedPtsCnt;
115 uint8_t* types; //curve type
117 bool opened; //opened path?
140 min.x = min.y = max.x = max.y = 0;
170 struct SwStrokeBorder
176 int32_t start; //index of current sub-path start point
177 bool movable; //true: for ends of lineto borders
186 SwFixed subPathAngle;
187 SwPoint ptStartSubPath;
188 SwFixed subPathLineLength;
193 StrokeJoin joinSaved;
194 SwFill* fill = nullptr;
196 SwStrokeBorder borders[2];
202 bool handleWideStrokes;
219 SwOutline* outline = nullptr;
220 SwStroke* stroke = nullptr;
221 SwFill* fill = nullptr;
222 SwRleData* rle = nullptr;
223 SwRleData* strokeRle = nullptr;
224 SwBBox bbox; //Keep it boundary without stroke region. Using for optimal filling.
226 bool rect = false; //Fast Track: Othogonal rectangle?
231 SwOutline* outline = nullptr;
232 SwRleData* rle = nullptr;
233 uint32_t* data = nullptr;
239 uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
240 uint32_t (*alpha)(uint32_t rgba);
245 struct SwSurface : Surface
247 SwBlender blender; //mandatory
248 SwCompositor* compositor = nullptr; //compositor (optional)
251 struct SwCompositor : Compositor
253 SwSurface* recoverSfc; //Recover surface when composition is started
254 SwCompositor* recoverCmp; //Recover compositor when composition is done
262 SwOutline* outline = nullptr;
263 SwOutline* strokeOutline = nullptr;
264 unsigned allocSize = 0;
267 static inline SwCoord TO_SWCOORD(float val)
269 return SwCoord(val * 64);
272 static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a)
274 return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) +
275 ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff));
278 static inline uint32_t COLOR_INTERPOLATE(uint32_t c1, uint32_t a1, uint32_t c2, uint32_t a2)
280 auto t = (((c1 & 0xff00ff) * a1 + (c2 & 0xff00ff) * a2) >> 8) & 0xff00ff;
281 c1 = (((c1 >> 8) & 0xff00ff) * a1 + ((c2 >> 8) & 0xff00ff) * a2) & 0xff00ff00;
285 static inline uint32_t ALPHA_MULTIPLY(uint32_t c, uint32_t a)
287 return ((c * a + 0xff) >> 8);
290 static inline SwCoord HALF_STROKE(float width)
292 return TO_SWCOORD(width * 0.5);
295 int64_t mathMultiply(int64_t a, int64_t b);
296 int64_t mathDivide(int64_t a, int64_t b);
297 int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
298 void mathRotate(SwPoint& pt, SwFixed angle);
299 SwFixed mathTan(SwFixed angle);
300 SwFixed mathAtan(const SwPoint& pt);
301 SwFixed mathCos(SwFixed angle);
302 SwFixed mathSin(SwFixed angle);
303 void mathSplitCubic(SwPoint* base);
304 SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
305 SwFixed mathLength(const SwPoint& pt);
306 bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
307 SwFixed mathMean(SwFixed angle1, SwFixed angle2);
308 SwPoint mathTransform(const Point* to, const Matrix* transform);
309 bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion);
311 void shapeReset(SwShape* shape);
312 bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
313 bool shapePrepared(const SwShape* shape);
314 bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias, bool hasComposite);
315 void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
316 void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
317 bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
318 void shapeFree(SwShape* shape);
319 void shapeDelStroke(SwShape* shape);
320 bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
321 bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
322 void shapeResetFill(SwShape* shape);
323 void shapeResetStrokeFill(SwShape* shape);
324 void shapeDelFill(SwShape* shape);
325 void shapeDelStrokeFill(SwShape* shape);
327 void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform);
328 bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
329 SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
330 void strokeFree(SwStroke* stroke);
332 bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
333 bool imagePrepared(const SwImage* image);
334 bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& renderRegion, bool antiAlias);
335 void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
336 void imageReset(SwImage* image);
337 void imageFree(SwImage* image);
339 bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
340 void fillReset(SwFill* fill);
341 void fillFree(SwFill* fill);
342 void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
343 void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
345 SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
346 void rleFree(SwRleData* rle);
347 void rleReset(SwRleData* rle);
348 void rleClipPath(SwRleData *rle, const SwRleData *clip);
349 void rleClipRect(SwRleData *rle, const SwBBox* clip);
351 SwMpool* mpoolInit(uint32_t threads);
352 bool mpoolTerm(SwMpool* mpool);
353 bool mpoolClear(SwMpool* mpool);
354 SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx);
355 void mpoolRetOutline(SwMpool* mpool, unsigned idx);
356 SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx);
357 void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
359 bool rasterCompositor(SwSurface* surface);
360 bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
361 bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
362 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
363 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
364 bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
365 bool rasterClear(SwSurface* surface);
367 static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
369 #if defined(THORVG_AVX_VECTOR_SUPPORT)
370 //1. calculate how many iterations we need to cover length
371 uint32_t iterations = len / 8;
372 uint32_t avxFilled = iterations * 8;
373 int32_t leftovers = 0;
375 //2. set beginning of the array
377 __m256i_u* avxDst = (__m256i_u*) dst;
380 for (uint32_t i = 0; i < iterations; ++i) {
381 *avxDst = _mm256_set1_epi32(val);
385 //4. fill leftovers (in first step we have to set pointer to place where avx job is done)
386 leftovers = len - avxFilled;
389 while (leftovers--) *dst++ = val;
390 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
391 uint32_t iterations = len / 4;
392 uint32_t neonFilled = iterations * 4;
393 int32_t leftovers = 0;
396 uint32x4_t vectorVal = { val, val, val, val };
398 for (uint32_t i = 0; i < iterations; ++i) {
399 vst1q_u32(dst, vectorVal);
403 leftovers = len - neonFilled;
404 while (leftovers--) *dst++ = val;
407 while (len--) *dst++ = val;
411 #endif /* _TVG_SW_COMMON_H_ */