1 /*
2  * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
3 
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:
10 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13 
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
20  * SOFTWARE.
21  */
22 
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25 
26 #ifndef _TVG_SW_COMMON_H_
27 #define _TVG_SW_COMMON_H_
28 
29 #include <algorithm>
30 #include "tvgCommon.h"
31 #include "tvgRender.h"
32 
33 #define SW_CURVE_TYPE_POINT 0
34 #define SW_CURVE_TYPE_CUBIC 1
35 #define SW_ANGLE_PI (180L << 16)
36 #define SW_ANGLE_2PI (SW_ANGLE_PI << 1)
37 #define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1)
38 
39 using SwCoord = signed long;
40 using SwFixed = signed long long;
41 
42 
TO_FLOAT(SwCoord val)43 static inline float TO_FLOAT(SwCoord val)
44 {
45     return static_cast<float>(val) / 64.0f;
46 }
47 
48 struct SwPoint
49 {
50     SwCoord x, y;
51 
52     SwPoint& operator+=(const SwPoint& rhs)
53     {
54         x += rhs.x;
55         y += rhs.y;
56         return *this;
57     }
58 
59     SwPoint operator+(const SwPoint& rhs) const
60     {
61         return {x + rhs.x, y + rhs.y};
62     }
63 
64     SwPoint operator-(const SwPoint& rhs) const
65     {
66         return {x - rhs.x, y - rhs.y};
67     }
68 
69     bool operator==(const SwPoint& rhs) const
70     {
71         return (x == rhs.x && y == rhs.y);
72     }
73 
74     bool operator!=(const SwPoint& rhs) const
75     {
76         return (x != rhs.x || y != rhs.y);
77     }
78 
zeroSwPoint79     bool zero() const
80     {
81         if (x == 0 && y == 0) return true;
82         else return false;
83     }
84 
smallSwPoint85     bool small() const
86     {
87         //2 is epsilon...
88         if (abs(x) < 2 && abs(y) < 2) return true;
89         else return false;
90     }
91 
toPointSwPoint92     Point toPoint() const
93     {
94         return {TO_FLOAT(x),  TO_FLOAT(y)};
95     }
96 };
97 
98 struct SwSize
99 {
100     SwCoord w, h;
101 };
102 
103 struct SwOutline
104 {
105     Array<SwPoint> pts;             //the outline's points
106     Array<uint32_t> cntrs;          //the contour end points
107     Array<uint8_t> types;           //curve type
108     Array<bool> closed;             //opened or closed path?
109     FillRule fillRule;
110 };
111 
112 struct SwSpan
113 {
114     uint16_t x, y;
115     uint16_t len;
116     uint8_t coverage;
117 };
118 
119 struct SwRle
120 {
121     SwSpan *spans;
122     uint32_t alloc;
123     uint32_t size;
124 };
125 
126 struct SwBBox
127 {
128     SwPoint min, max;
129 
resetSwBBox130     void reset()
131     {
132         min.x = min.y = max.x = max.y = 0;
133     }
134 };
135 
136 struct SwFill
137 {
138     struct SwLinear {
139         float dx, dy;
140         float offset;
141     };
142 
143     struct SwRadial {
144         float a11, a12, a13;
145         float a21, a22, a23;
146         float fx, fy, fr;
147         float dx, dy, dr;
148         float invA, a;
149     };
150 
151     union {
152         SwLinear linear;
153         SwRadial radial;
154     };
155 
156     uint32_t* ctable;
157     FillSpread spread;
158 
159     bool solid = false; //solid color fill with the last color from colorStops
160     bool translucent;
161 };
162 
163 struct SwStrokeBorder
164 {
165     uint32_t ptsCnt;
166     uint32_t maxPts;
167     SwPoint* pts;
168     uint8_t* tags;
169     int32_t start;     //index of current sub-path start point
170     bool movable;      //true: for ends of lineto borders
171 };
172 
173 struct SwStroke
174 {
175     SwFixed angleIn;
176     SwFixed angleOut;
177     SwPoint center;
178     SwFixed lineLength;
179     SwFixed subPathAngle;
180     SwPoint ptStartSubPath;
181     SwFixed subPathLineLength;
182     SwFixed width;
183     SwFixed miterlimit;
184 
185     StrokeCap cap;
186     StrokeJoin join;
187     StrokeJoin joinSaved;
188     SwFill* fill = nullptr;
189 
190     SwStrokeBorder borders[2];
191 
192     float sx, sy;
193 
194     bool firstPt;
195     bool closedSubPath;
196     bool handleWideStrokes;
197 };
198 
199 struct SwDashStroke
200 {
201     SwOutline* outline = nullptr;
202     float curLen = 0;
203     int32_t curIdx = 0;
204     Point ptStart = {0, 0};
205     Point ptCur = {0, 0};
206     float* pattern = nullptr;
207     uint32_t cnt = 0;
208     bool curOpGap = false;
209     bool move = true;
210 };
211 
212 struct SwShape
213 {
214     SwOutline*   outline = nullptr;
215     SwStroke*    stroke = nullptr;
216     SwFill*      fill = nullptr;
217     SwRle*   rle = nullptr;
218     SwRle*   strokeRle = nullptr;
219     SwBBox       bbox;           //Keep it boundary without stroke region. Using for optimal filling.
220 
221     bool         fastTrack = false;   //Fast Track: axis-aligned rectangle without any clips?
222 };
223 
224 struct SwImage
225 {
226     SwOutline*   outline = nullptr;
227     SwRle*   rle = nullptr;
228     union {
229         pixel_t*  data;      //system based data pointer
230         uint32_t* buf32;     //for explicit 32bits channels
231         uint8_t*  buf8;      //for explicit 8bits grayscale
232     };
233     uint32_t     w, h, stride;
234     int32_t      ox = 0;         //offset x
235     int32_t      oy = 0;         //offset y
236     float        scale;
237     uint8_t      channelSize;
238 
239     bool         direct = false;  //draw image directly (with offset)
240     bool         scaled = false;  //draw scaled image
241 };
242 
243 typedef uint8_t(*SwMask)(uint8_t s, uint8_t d, uint8_t a);                  //src, dst, alpha
244 typedef uint32_t(*SwBlender)(uint32_t s, uint32_t d, uint8_t a);            //src, dst, alpha
245 typedef uint32_t(*SwJoin)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);      //color channel join
246 typedef uint8_t(*SwAlpha)(uint8_t*);                                        //blending alpha
247 
248 struct SwCompositor;
249 
250 struct SwSurface : RenderSurface
251 {
252     SwJoin  join;
253     SwAlpha alphas[4];                    //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5
254     SwBlender blender = nullptr;          //blender (optional)
255     SwCompositor* compositor = nullptr;   //compositor (optional)
256     BlendMethod blendMethod = BlendMethod::Normal;
257 
alphaSwSurface258     SwAlpha alpha(CompositeMethod method)
259     {
260         auto idx = (int)(method) - 2;       //0: None, 1: ClipPath
261         return alphas[idx > 3 ? 0 : idx];   //CompositeMethod has only four Matting methods.
262     }
263 
SwSurfaceSwSurface264     SwSurface()
265     {
266     }
267 
SwSurfaceSwSurface268     SwSurface(const SwSurface* rhs) : RenderSurface(rhs)
269     {
270         join = rhs->join;
271         memcpy(alphas, rhs->alphas, sizeof(alphas));
272         blender = rhs->blender;
273         compositor = rhs->compositor;
274         blendMethod = rhs->blendMethod;
275      }
276 };
277 
278 struct SwCompositor : RenderCompositor
279 {
280     SwSurface* recoverSfc;                  //Recover surface when composition is started
281     SwCompositor* recoverCmp;               //Recover compositor when composition is done
282     SwImage image;
283     SwBBox bbox;
284     bool valid;
285 };
286 
287 struct SwMpool
288 {
289     SwOutline* outline;
290     SwOutline* strokeOutline;
291     SwOutline* dashOutline;
292     unsigned allocSize;
293 };
294 
TO_SWCOORD(float val)295 static inline SwCoord TO_SWCOORD(float val)
296 {
297     return SwCoord(val * 64.0f);
298 }
299 
JOIN(uint8_t c0,uint8_t c1,uint8_t c2,uint8_t c3)300 static inline uint32_t JOIN(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3)
301 {
302     return (c0 << 24 | c1 << 16 | c2 << 8 | c3);
303 }
304 
ALPHA_BLEND(uint32_t c,uint32_t a)305 static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a)
306 {
307     ++a;
308     return (((((c >> 8) & 0x00ff00ff) * a) & 0xff00ff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff));
309 }
310 
INTERPOLATE(uint32_t s,uint32_t d,uint8_t a)311 static inline uint32_t INTERPOLATE(uint32_t s, uint32_t d, uint8_t a)
312 {
313     return (((((((s >> 8) & 0xff00ff) - ((d >> 8) & 0xff00ff)) * a) + (d & 0xff00ff00)) & 0xff00ff00) + ((((((s & 0xff00ff) - (d & 0xff00ff)) * a) >> 8) + (d & 0xff00ff)) & 0xff00ff));
314 }
315 
INTERPOLATE8(uint8_t s,uint8_t d,uint8_t a)316 static inline uint8_t INTERPOLATE8(uint8_t s, uint8_t d, uint8_t a)
317 {
318     return (((s) * (a) + 0xff) >> 8) + (((d) * ~(a) + 0xff) >> 8);
319 }
320 
HALF_STROKE(float width)321 static inline SwCoord HALF_STROKE(float width)
322 {
323     return TO_SWCOORD(width * 0.5f);
324 }
325 
A(uint32_t c)326 static inline uint8_t A(uint32_t c)
327 {
328     return ((c) >> 24);
329 }
330 
IA(uint32_t c)331 static inline uint8_t IA(uint32_t c)
332 {
333     return (~(c) >> 24);
334 }
335 
C1(uint32_t c)336 static inline uint8_t C1(uint32_t c)
337 {
338     return ((c) >> 16);
339 }
340 
C2(uint32_t c)341 static inline uint8_t C2(uint32_t c)
342 {
343     return ((c) >> 8);
344 }
345 
C3(uint32_t c)346 static inline uint8_t C3(uint32_t c)
347 {
348     return (c);
349 }
350 
opBlendInterp(uint32_t s,uint32_t d,uint8_t a)351 static inline uint32_t opBlendInterp(uint32_t s, uint32_t d, uint8_t a)
352 {
353     return INTERPOLATE(s, d, a);
354 }
355 
opBlendNormal(uint32_t s,uint32_t d,uint8_t a)356 static inline uint32_t opBlendNormal(uint32_t s, uint32_t d, uint8_t a)
357 {
358     auto t = ALPHA_BLEND(s, a);
359     return t + ALPHA_BLEND(d, IA(t));
360 }
361 
opBlendPreNormal(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)362 static inline uint32_t opBlendPreNormal(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
363 {
364     return s + ALPHA_BLEND(d, IA(s));
365 }
366 
opBlendSrcOver(uint32_t s,TVG_UNUSED uint32_t d,TVG_UNUSED uint8_t a)367 static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNUSED uint8_t a)
368 {
369     return s;
370 }
371 
372 //TODO: BlendMethod could remove the alpha parameter.
opBlendDifference(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)373 static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
374 {
375     //if (s > d) => s - d
376     //else => d - s
377     auto c1 = (C1(s) > C1(d)) ? (C1(s) - C1(d)) : (C1(d) - C1(s));
378     auto c2 = (C2(s) > C2(d)) ? (C2(s) - C2(d)) : (C2(d) - C2(s));
379     auto c3 = (C3(s) > C3(d)) ? (C3(s) - C3(d)) : (C3(d) - C3(s));
380     return JOIN(255, c1, c2, c3);
381 }
382 
opBlendExclusion(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)383 static inline uint32_t opBlendExclusion(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
384 {
385     //A + B - 2AB
386     auto c1 = std::min(255, C1(s) + C1(d) - std::min(255, (C1(s) * C1(d)) << 1));
387     auto c2 = std::min(255, C2(s) + C2(d) - std::min(255, (C2(s) * C2(d)) << 1));
388     auto c3 = std::min(255, C3(s) + C3(d) - std::min(255, (C3(s) * C3(d)) << 1));
389     return JOIN(255, c1, c2, c3);
390 }
391 
opBlendAdd(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)392 static inline uint32_t opBlendAdd(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
393 {
394     // s + d
395     auto c1 = std::min(C1(s) + C1(d), 255);
396     auto c2 = std::min(C2(s) + C2(d), 255);
397     auto c3 = std::min(C3(s) + C3(d), 255);
398     return JOIN(255, c1, c2, c3);
399 }
400 
opBlendScreen(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)401 static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
402 {
403     // s + d - s * d
404     auto c1 = C1(s) + C1(d) - MULTIPLY(C1(s), C1(d));
405     auto c2 = C2(s) + C2(d) - MULTIPLY(C2(s), C2(d));
406     auto c3 = C3(s) + C3(d) - MULTIPLY(C3(s), C3(d));
407     return JOIN(255, c1, c2, c3);
408 }
409 
opBlendMultiply(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)410 static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
411 {
412     // s * d
413     auto c1 = MULTIPLY(C1(s), C1(d));
414     auto c2 = MULTIPLY(C2(s), C2(d));
415     auto c3 = MULTIPLY(C3(s), C3(d));
416     return JOIN(255, c1, c2, c3);
417 }
418 
opBlendOverlay(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)419 static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
420 {
421     // if (2 * d < da) => 2 * s * d,
422     // else => 1 - 2 * (1 - s) * (1 - d)
423     auto c1 = (C1(d) < 128) ? std::min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d))));
424     auto c2 = (C2(d) < 128) ? std::min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d))));
425     auto c3 = (C3(d) < 128) ? std::min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d))));
426     return JOIN(255, c1, c2, c3);
427 }
428 
opBlendDarken(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)429 static inline uint32_t opBlendDarken(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
430 {
431     // min(s, d)
432     auto c1 = std::min(C1(s), C1(d));
433     auto c2 = std::min(C2(s), C2(d));
434     auto c3 = std::min(C3(s), C3(d));
435     return JOIN(255, c1, c2, c3);
436 }
437 
opBlendLighten(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)438 static inline uint32_t opBlendLighten(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
439 {
440     // max(s, d)
441     auto c1 = std::max(C1(s), C1(d));
442     auto c2 = std::max(C2(s), C2(d));
443     auto c3 = std::max(C3(s), C3(d));
444     return JOIN(255, c1, c2, c3);
445 }
446 
opBlendColorDodge(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)447 static inline uint32_t opBlendColorDodge(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
448 {
449     // d / (1 - s)
450     auto is = 0xffffffff - s;
451     auto c1 = (C1(is) > 0) ? (C1(d) / C1(is)) : C1(d);
452     auto c2 = (C2(is) > 0) ? (C2(d) / C2(is)) : C2(d);
453     auto c3 = (C3(is) > 0) ? (C3(d) / C3(is)) : C3(d);
454     return JOIN(255, c1, c2, c3);
455 }
456 
opBlendColorBurn(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)457 static inline uint32_t opBlendColorBurn(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
458 {
459     // 1 - (1 - d) / s
460     auto id = 0xffffffff - d;
461     auto c1 = 255 - ((C1(s) > 0) ? (C1(id) / C1(s)) : C1(id));
462     auto c2 = 255 - ((C2(s) > 0) ? (C2(id) / C2(s)) : C2(id));
463     auto c3 = 255 - ((C3(s) > 0) ? (C3(id) / C3(s)) : C3(id));
464     return JOIN(255, c1, c2, c3);
465 }
466 
opBlendHardLight(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)467 static inline uint32_t opBlendHardLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
468 {
469     auto c1 = (C1(s) < 128) ? std::min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d))));
470     auto c2 = (C2(s) < 128) ? std::min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d))));
471     auto c3 = (C3(s) < 128) ? std::min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d))));
472     return JOIN(255, c1, c2, c3);
473 }
474 
opBlendSoftLight(uint32_t s,uint32_t d,TVG_UNUSED uint8_t a)475 static inline uint32_t opBlendSoftLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
476 {
477     //(255 - 2 * s) * (d * d) + (2 * s * b)
478     auto c1 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C1(s)), MULTIPLY(C1(d), C1(d))) + 2 * MULTIPLY(C1(s), C1(d)));
479     auto c2 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C2(s)), MULTIPLY(C2(d), C2(d))) + 2 * MULTIPLY(C2(s), C2(d)));
480     auto c3 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C3(s)), MULTIPLY(C3(d), C3(d))) + 2 * MULTIPLY(C3(s), C3(d)));
481     return JOIN(255, c1, c2, c3);
482 }
483 
484 
485 int64_t mathMultiply(int64_t a, int64_t b);
486 int64_t mathDivide(int64_t a, int64_t b);
487 int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
488 void mathRotate(SwPoint& pt, SwFixed angle);
489 SwFixed mathTan(SwFixed angle);
490 SwFixed mathAtan(const SwPoint& pt);
491 SwFixed mathCos(SwFixed angle);
492 SwFixed mathSin(SwFixed angle);
493 void mathSplitCubic(SwPoint* base);
494 void mathSplitLine(SwPoint* base);
495 SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
496 SwFixed mathLength(const SwPoint& pt);
497 int mathCubicAngle(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
498 SwFixed mathMean(SwFixed angle1, SwFixed angle2);
499 SwPoint mathTransform(const Point* to, const Matrix& transform);
500 bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
501 bool mathClipBBox(const SwBBox& clipper, SwBBox& clippee);
502 
503 void shapeReset(SwShape* shape);
504 bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite);
505 bool shapePrepared(const SwShape* shape);
506 bool shapeGenRle(SwShape* shape, const RenderShape* rshape, bool antiAlias);
507 void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
508 void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix& transform);
509 bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
510 void shapeFree(SwShape* shape);
511 void shapeDelStroke(SwShape* shape);
512 bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix& transform, SwSurface* surface, uint8_t opacity, bool ctable);
513 bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix& transform, SwSurface* surface, uint8_t opacity, bool ctable);
514 void shapeResetFill(SwShape* shape);
515 void shapeResetStrokeFill(SwShape* shape);
516 void shapeDelFill(SwShape* shape);
517 void shapeDelStrokeFill(SwShape* shape);
518 
519 void strokeReset(SwStroke* stroke, const RenderShape* shape, const Matrix& transform);
520 bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
521 SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
522 void strokeFree(SwStroke* stroke);
523 
524 bool imagePrepare(SwImage* image, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
525 bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias);
526 void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
527 void imageReset(SwImage* image);
528 void imageFree(SwImage* image);
529 
530 bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix& transform, SwSurface* surface, uint8_t opacity, bool ctable);
531 const Fill::ColorStop* fillFetchSolid(const SwFill* fill, const Fill* fdata);
532 void fillReset(SwFill* fill);
533 void fillFree(SwFill* fill);
534 
535 //OPTIMIZE_ME: Skip the function pointer access
536 void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t opacity);                                   //composite masking ver.
537 void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t opacity);                     //direct masking ver.
538 void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a);                                         //blending ver.
539 void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a);                          //blending + BlendingMethod(op2) ver.
540 void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity);     //matting ver.
541 
542 void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a);                                             //composite masking ver.
543 void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) ;                              //direct masking ver.
544 void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a);                                         //blending ver.
545 void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a);                          //blending + BlendingMethod(op2) ver.
546 void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity);     //matting ver.
547 
548 SwRle* rleRender(SwRle* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
549 SwRle* rleRender(const SwBBox* bbox);
550 void rleFree(SwRle* rle);
551 void rleReset(SwRle* rle);
552 void rleMerge(SwRle* rle, SwRle* clip1, SwRle* clip2);
553 void rleClip(SwRle* rle, const SwRle* clip);
554 void rleClip(SwRle* rle, const SwBBox* clip);
555 
556 SwMpool* mpoolInit(uint32_t threads);
557 bool mpoolTerm(SwMpool* mpool);
558 bool mpoolClear(SwMpool* mpool);
559 SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx);
560 void mpoolRetOutline(SwMpool* mpool, unsigned idx);
561 SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx);
562 void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
563 SwOutline* mpoolReqDashOutline(SwMpool* mpool, unsigned idx);
564 void mpoolRetDashOutline(SwMpool* mpool, unsigned idx);
565 
566 bool rasterCompositor(SwSurface* surface);
567 bool rasterGradientShape(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
568 bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
569 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity);
570 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
571 bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
572 bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val = 0);
573 void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
574 void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len);
575 void rasterXYFlip(uint32_t* src, uint32_t* dst, int32_t stride, int32_t w, int32_t h, const SwBBox& bbox, bool flipped);
576 void rasterUnpremultiply(RenderSurface* surface);
577 void rasterPremultiply(RenderSurface* surface);
578 bool rasterConvertCS(RenderSurface* surface, ColorSpace to);
579 
580 bool effectGaussianBlur(SwImage& image, SwImage& buffer, const SwBBox& bbox, const RenderEffectGaussian* params);
581 bool effectGaussianPrepare(RenderEffectGaussian* effect);
582 
583 #endif /* _TVG_SW_COMMON_H_ */
584 
585 #endif /* LV_USE_THORVG_INTERNAL */
586 
587