efecb63812c19e4ff7712568f015f936a78033fc
[platform/core/graphics/tizenvg.git] / src / lib / sw_engine / tvgSwRaster.cpp
1 /*
2  * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. 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 #include "tvgMath.h"
23 #include "tvgRender.h"
24 #include "tvgSwCommon.h"
25 #include "tvgSwRasterC.h"
26 #include "tvgSwRasterAvx.h"
27 #include "tvgSwRasterNeon.h"
28
29 /************************************************************************/
30 /* Internal Class Implementation                                        */
31 /************************************************************************/
32 constexpr auto DOWN_SCALE_TOLERANCE = 0.5f;
33
34
35 static inline uint32_t _multiplyAlpha(uint32_t c, uint32_t a)
36 {
37     return ((c * a + 0xff) >> 8);
38 }
39
40
41 static uint32_t _colorAlpha(uint32_t c)
42 {
43     return (c >> 24);
44 }
45
46
47 static uint32_t _colorInvAlpha(uint32_t c)
48 {
49     return (~c >> 24);
50 }
51
52
53 static uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
54 {
55     return (a << 24 | b << 16 | g << 8 | r);
56 }
57
58
59 static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
60 {
61     return (a << 24 | r << 16 | g << 8 | b);
62 }
63
64
65 static bool _translucent(const SwSurface* surface, uint8_t a)
66 {
67     if (a < 255) return true;
68     if (!surface->compositor || surface->compositor->method == CompositeMethod::None) return false;
69     return true;
70 }
71
72
73 //Bilinear Interpolation
74 static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float fX, float fY)
75 {
76     auto rX = static_cast<uint32_t>(fX);
77     auto rY = static_cast<uint32_t>(fY);
78
79     auto dX = static_cast<uint32_t>((fX - rX) * 255.0f);
80     auto dY = static_cast<uint32_t>((fY - rY) * 255.0f);
81
82     auto c1 = img[rX + (rY * w)];
83     auto c2 = img[(rX + 1) + (rY * w)];
84     auto c3 = img[(rX + 1) + ((rY + 1) * w)];
85     auto c4 = img[rX + ((rY + 1) * w)];
86
87     return COLOR_INTERPOLATE(COLOR_INTERPOLATE(c1, 255 - dX, c2, dX), 255 - dY, COLOR_INTERPOLATE(c4, 255 - dX, c3, dX), dY);
88 }
89
90
91 //2n x 2n Mean Kernel
92 static uint32_t _interpDownScaler(const uint32_t *img, uint32_t w, uint32_t h, uint32_t rX, uint32_t rY, uint32_t n)
93 {
94     uint32_t c[4] = { 0 };
95     auto n2 = n * n;
96     auto src = img + rX - n + (rY - n) * w;
97     for (auto y = rY - n; y < rY + n; ++y) {
98         auto p = src;
99         for (auto x = rX - n; x < rX + n; ++x, ++p) {
100             c[0] += *p >> 24;
101             c[1] += (*p >> 16) & 0xff;
102             c[2] += (*p >> 8) & 0xff;
103             c[3] += *p & 0xff;
104         }
105         src += w;
106     }
107     for (auto i = 0; i < 4; ++i) {
108         c[i] = (c[i] >> 2) / n2;
109     }
110     return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
111 }
112
113
114 /************************************************************************/
115 /* Rect                                                                 */
116 /************************************************************************/
117
118 static bool _rasterTranslucentMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint32_t (*blendMethod)(uint32_t))
119 {
120     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
121     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
122     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
123
124     TVGLOG("SW_ENGINE", "Translucent Masked Rect");
125
126     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x;   //compositor buffer
127
128     for (uint32_t y = 0; y < h; ++y) {
129         auto dst = &buffer[y * surface->stride];
130         auto cmp = &cbuffer[y * surface->stride];
131         for (uint32_t x = 0; x < w; ++x) {
132             auto tmp = ALPHA_BLEND(color, blendMethod(*cmp));
133             dst[x] = tmp + ALPHA_BLEND(dst[x], surface->blender.ialpha(tmp));
134             ++cmp;
135         }
136     }
137     return true;
138 }
139
140 static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
141 {
142     if (surface->compositor) {
143         if (surface->compositor->method == CompositeMethod::AlphaMask) {
144             return _rasterTranslucentMaskedRect(surface, region, color, surface->blender.alpha);
145         }
146         if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
147             return _rasterTranslucentMaskedRect(surface, region, color, surface->blender.ialpha);
148         }
149     }
150
151 #if defined(THORVG_AVX_VECTOR_SUPPORT)
152     return avxRasterTranslucentRect(surface, region, color);
153 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
154     return neonRasterTranslucentRect(surface, region, color);
155 #else
156     return cRasterTranslucentRect(surface, region, color);
157 #endif
158 }
159
160
161 static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color)
162 {
163     auto buffer = surface->buffer + (region.min.y * surface->stride);
164     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
165     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
166
167     for (uint32_t y = 0; y < h; ++y) {
168         rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w);
169     }
170     return true;
171 }
172
173
174 /************************************************************************/
175 /* Rle                                                                  */
176 /************************************************************************/
177
178 static bool _rasterTranslucentMaskedRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint32_t (*blendMethod)(uint32_t))
179 {
180     TVGLOG("SW_ENGINE", "Translucent Masked Rle");
181
182     auto span = rle->spans;
183     uint32_t src;
184     auto cbuffer = surface->compositor->image.data;
185
186     for (uint32_t i = 0; i < rle->size; ++i) {
187         auto dst = &surface->buffer[span->y * surface->stride + span->x];
188         auto cmp = &cbuffer[span->y * surface->stride + span->x];
189         if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
190         else src = color;
191         for (uint32_t x = 0; x < span->len; ++x) {
192             auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
193             dst[x] = tmp + ALPHA_BLEND(dst[x], surface->blender.ialpha(tmp));
194             ++cmp;
195         }
196         ++span;
197     }
198     return true;
199 }
200
201 static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t color)
202 {
203     if (!rle) return false;
204
205     if (surface->compositor) {
206         if (surface->compositor->method == CompositeMethod::AlphaMask) {
207             return _rasterTranslucentMaskedRle(surface, rle, color, surface->blender.alpha);
208         }
209         if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
210             return _rasterTranslucentMaskedRle(surface, rle, color, surface->blender.ialpha);
211         }
212     }
213
214 #if defined(THORVG_AVX_VECTOR_SUPPORT)
215     return avxRasterTranslucentRle(surface, rle, color);
216 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
217     return neonRasterTranslucentRle(surface, rle, color);
218 #else
219     return cRasterTranslucentRle(surface, rle, color);
220 #endif
221 }
222
223
224 static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
225 {
226     if (!rle) return false;
227
228     auto span = rle->spans;
229
230     for (uint32_t i = 0; i < rle->size; ++i) {
231         if (span->coverage == 255) {
232             rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len);
233         } else {
234             auto dst = &surface->buffer[span->y * surface->stride + span->x];
235             auto src = ALPHA_BLEND(color, span->coverage);
236             auto ialpha = 255 - span->coverage;
237             for (uint32_t i = 0; i < span->len; ++i) {
238                 dst[i] = src + ALPHA_BLEND(dst[i], ialpha);
239             }
240         }
241         ++span;
242     }
243     return true;
244 }
245
246
247 /************************************************************************/
248 /* RLE Transformed Translucent Image                                    */
249 /************************************************************************/
250
251 static bool _rasterTransformedMaskedRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
252 {
253     TVGLOG("SW_ENGINE", "Transformed Masked Rle Image");
254
255     auto span = image->rle->spans;
256     auto img = image->data;
257     auto w = image->w;
258     auto h = image->h;
259     auto cbuffer = surface->compositor->image.data;
260
261     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
262         auto ey1 = span->y * itransform->e12 + itransform->e13;
263         auto ey2 = span->y * itransform->e22 + itransform->e23;
264         auto dst = &surface->buffer[span->y * surface->stride + span->x];
265         auto cmp = &cbuffer[span->y * surface->stride + span->x];
266         auto alpha = _multiplyAlpha(span->coverage, opacity);
267         if (alpha == 255) {
268             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
269                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
270                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
271                 if (rX >= w || rY >= h) continue;
272                 auto tmp = ALPHA_BLEND(img[rY * image->stride + rX], blendMethod(*cmp));
273                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
274             }
275         } else {
276             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
277                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
278                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
279                 if (rX >= w || rY >= h) continue;
280                 auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
281                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
282                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
283             }
284         }
285     }
286     return true;
287 }
288
289
290 static bool _rasterTransformedTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform)
291 {
292     auto span = image->rle->spans;
293     auto img = image->data;
294     auto w = image->w;
295     auto h = image->h;
296
297     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
298         auto ey1 = span->y * itransform->e12 + itransform->e13;
299         auto ey2 = span->y * itransform->e22 + itransform->e23;
300         auto dst = &surface->buffer[span->y * surface->stride + span->x];
301         auto alpha = _multiplyAlpha(span->coverage, opacity);
302         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
303             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
304             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
305             if (rX >= w || rY >= h) continue;
306             auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
307             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
308         }
309     }
310     return true;
311 }
312
313
314 static bool _rasterDownScaledMaskedRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
315 {
316     TVGLOG("SW_ENGINE", "Down Scaled Masked Rle Image");
317
318     auto span = image->rle->spans;
319     auto img = image->data;
320     auto w = image->w;
321     auto h = image->h;
322     auto cbuffer = surface->compositor->image.data;
323
324     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
325         auto ey1 = span->y * itransform->e12 + itransform->e13;
326         auto ey2 = span->y * itransform->e22 + itransform->e23;
327         auto dst = &surface->buffer[span->y * surface->stride + span->x];
328         auto cmp = &cbuffer[span->y * surface->stride + span->x];
329         auto alpha = _multiplyAlpha(span->coverage, opacity);
330
331         if (alpha == 255) {
332             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
333                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
334                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
335                 if (rX >= w || rY >= h) continue;
336                 uint32_t src;
337                 if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
338                 else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
339                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
340                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
341             }
342         } else {
343             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
344                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
345                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
346                 if (rX >= w || rY >= h) continue;
347                 uint32_t src;
348                 if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
349                 else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
350                 auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
351                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
352             }
353         }
354     }
355     return true;
356 }
357
358
359 static bool _rasterDownScaledTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform, uint32_t halfScale)
360 {
361     auto span = image->rle->spans;
362     auto img = image->data;
363     auto w = image->w;
364     auto h = image->h;
365
366     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
367         auto ey1 = span->y * itransform->e12 + itransform->e13;
368         auto ey2 = span->y * itransform->e22 + itransform->e23;
369         auto dst = &surface->buffer[span->y * surface->stride + span->x];
370         auto alpha = _multiplyAlpha(span->coverage, opacity);
371         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
372             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
373             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
374             if (rX >= w || rY >= h) continue;
375             uint32_t src;
376             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
377             else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
378             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
379         }
380     }
381     return true;
382 }
383
384
385 static bool _rasterUpScaledMaskedRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
386 {
387     TVGLOG("SW_ENGINE", "Up Scaled Masked Rle Image");
388
389     auto span = image->rle->spans;
390     auto img = image->data;
391     auto w = image->w;
392     auto h = image->h;
393     auto cbuffer = surface->compositor->image.data;
394
395     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
396         auto ey1 = span->y * itransform->e12 + itransform->e13;
397         auto ey2 = span->y * itransform->e22 + itransform->e23;
398         auto dst = &surface->buffer[span->y * surface->stride + span->x];
399         auto cmp = &cbuffer[span->y * surface->stride + span->x];
400         auto alpha = _multiplyAlpha(span->coverage, opacity);
401         if (alpha == 255) {
402             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
403                 auto fX = (span->x + x) * itransform->e11 + ey1;
404                 auto fY = (span->x + x) * itransform->e21 + ey2;
405                 auto rX = static_cast<uint32_t>(roundf(fX));
406                 auto rY = static_cast<uint32_t>(roundf(fY));
407                 if (rX >= w || rY >= h) continue;
408                 uint32_t src;
409                 if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
410                 else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
411                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
412                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
413             }
414         } else {
415             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
416                 auto fX = (span->x + x) * itransform->e11 + ey1;
417                 auto fY = (span->x + x) * itransform->e21 + ey2;
418                 auto rX = static_cast<uint32_t>(roundf(fX));
419                 auto rY = static_cast<uint32_t>(roundf(fY));
420                 if (rX >= w || rY >= h) continue;
421                 uint32_t src;
422                 if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
423                 else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
424                 auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
425                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
426             }
427         }
428     }
429     return true;
430 }
431
432
433 static bool _rasterUpScaledTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform)
434 {
435     auto span = image->rle->spans;
436     auto img = image->data;
437     auto w = image->w;
438     auto h = image->h;
439
440     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
441         auto ey1 = span->y * itransform->e12 + itransform->e13;
442         auto ey2 = span->y * itransform->e22 + itransform->e23;
443         auto dst = &surface->buffer[span->y * surface->stride + span->x];
444         auto alpha = _multiplyAlpha(span->coverage, opacity);
445         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
446             auto fX = (span->x + x) * itransform->e11 + ey1;
447             auto fY = (span->x + x) * itransform->e21 + ey2;
448             auto rX = static_cast<uint32_t>(roundf(fX));
449             auto rY = static_cast<uint32_t>(roundf(fY));
450             if (rX >= w || rY >= h) continue;
451             uint32_t src;
452             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
453             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
454             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
455         }
456     }
457     return true;
458 }
459
460
461 static bool _rasterTransformedTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const Matrix* itransform, uint32_t halfScale)
462 {
463     //Transformed
464     if (mathEqual(image->scale, 1.0f)) {
465         if (surface->compositor) {
466             if (surface->compositor->method == CompositeMethod::AlphaMask) {
467                 return _rasterTransformedMaskedRleImage(surface, image, opacity, itransform, surface->blender.alpha);
468             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
469                 return _rasterTransformedMaskedRleImage(surface, image, opacity, itransform, surface->blender.ialpha);
470             }
471         }
472         return _rasterTransformedTranslucentRleImage(surface, image, opacity, itransform);
473     //Transformed + Down Scaled
474     } else if (image->scale < DOWN_SCALE_TOLERANCE) {
475         if (surface->compositor) {
476             if (surface->compositor->method == CompositeMethod::AlphaMask) {
477                 return _rasterDownScaledMaskedRleImage(surface, image, opacity, itransform, halfScale, surface->blender.alpha);
478             } else  if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
479                 return _rasterDownScaledMaskedRleImage(surface, image, opacity, itransform, halfScale, surface->blender.ialpha);
480             }
481         }
482         return _rasterDownScaledTranslucentRleImage(surface, image, opacity, itransform, halfScale);  
483     //Transformed + Up Scaled
484     } else {
485         if (surface->compositor) {
486             if (surface->compositor->method == CompositeMethod::AlphaMask) {
487                 return _rasterUpScaledMaskedRleImage(surface, image, opacity, itransform, surface->blender.alpha);
488             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
489                 return _rasterUpScaledMaskedRleImage(surface, image, opacity, itransform, surface->blender.ialpha);
490             }
491         }
492         return _rasterUpScaledTranslucentRleImage(surface, image, opacity, itransform);
493     }
494 }
495
496
497 /************************************************************************/
498 /* RLE Transformed Solid Image                                         */
499 /************************************************************************/
500
501 static bool _rasterSolidRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
502 {
503     auto span = image->rle->spans;
504     auto img = image->data;
505     auto w = image->w;
506     auto h = image->h;
507
508     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
509         auto ey1 = span->y * itransform->e12 + itransform->e13;
510         auto ey2 = span->y * itransform->e22 + itransform->e23;
511         auto dst = &surface->buffer[span->y * surface->stride + span->x];
512
513         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
514             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
515             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
516             if (rX >= w || rY >= h) continue;
517             auto src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
518             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
519         }
520     }
521     return true;
522 }
523
524
525 static bool _rasterDownScaledSolidRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale)
526 {
527     auto span = image->rle->spans;
528     auto img = image->data;
529     auto w = image->w;
530     auto h = image->h;
531
532     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
533         auto ey1 = span->y * itransform->e12 + itransform->e13;
534         auto ey2 = span->y * itransform->e22 + itransform->e23;
535         auto dst = &surface->buffer[span->y * surface->stride + span->x];
536         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
537             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
538             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
539             if (rX >= w || rY >= h) continue;
540
541             uint32_t src;
542             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
543             else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage);
544             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
545         }
546     }
547     return true;
548 }
549
550
551 static bool _rasterUpScaledSolidRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
552 {
553     auto span = image->rle->spans;
554     auto img = image->data;
555     auto w = image->w;
556     auto h = image->h;
557
558     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
559         auto ey1 = span->y * itransform->e12 + itransform->e13;
560         auto ey2 = span->y * itransform->e22 + itransform->e23;
561         auto dst = &surface->buffer[span->y * surface->stride + span->x];
562         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
563             auto fX = (span->x + x) * itransform->e11 + ey1;
564             auto fY = (span->x + x) * itransform->e21 + ey2;
565             auto rX = static_cast<uint32_t>(roundf(fX));
566             auto rY = static_cast<uint32_t>(roundf(fY));
567             if (rX >= w || rY >= h) continue;
568             uint32_t src;
569             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
570             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage);
571             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
572         }
573     }
574     return true;
575 }
576
577
578 static bool _rasterTransformedSolidRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale)
579 {  
580     if (mathEqual(image->scale, 1.0f)) return _rasterSolidRleImage(surface, image, itransform);
581     else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledSolidRleImage(surface, image, itransform, halfScale);
582     else return _rasterUpScaledSolidRleImage(surface, image, itransform);
583 }
584
585
586 /************************************************************************/
587 /* RLE Direct (Solid + Translucent) Image                              */
588 /************************************************************************/
589
590 static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
591 {
592     TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
593
594     auto span = image->rle->spans;
595     auto cbuffer = surface->compositor->image.data;
596
597     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
598         auto dst = &surface->buffer[span->y * surface->stride + span->x];
599         auto cmp = &cbuffer[span->y * surface->stride + span->x];
600         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
601         auto alpha = _multiplyAlpha(span->coverage, opacity);
602         if (alpha == 255) {
603             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
604                 auto tmp = ALPHA_BLEND(*img, blendMethod(*cmp));
605                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
606             }
607         } else {
608             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
609                 auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(alpha, blendMethod(*cmp)));
610                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
611             }
612         }
613     }
614     return true;
615 }
616
617
618 static bool __rasterDirectTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
619 {
620     auto span = image->rle->spans;
621
622     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
623         auto dst = &surface->buffer[span->y * surface->stride + span->x];
624         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
625         auto alpha = _multiplyAlpha(span->coverage, opacity);
626         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
627             auto src = ALPHA_BLEND(*img, alpha);
628             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
629         }
630     }
631     return true;
632 }
633
634
635 static bool _rasterDirectTranslucentRleImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
636 {
637     if (surface->compositor) {
638         if (surface->compositor->method == CompositeMethod::AlphaMask) {
639             return _rasterDirectMaskedRleImage(surface, image, opacity, surface->blender.alpha);
640         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
641             return _rasterDirectMaskedRleImage(surface, image, opacity, surface->blender.ialpha);
642         }
643     }
644     return __rasterDirectTranslucentRleImage(surface, image, opacity);
645 }
646
647
648 static bool _rasterDirectSolidRleImage(SwSurface* surface, const SwImage* image)
649 {
650     auto span = image->rle->spans;
651
652     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
653         auto dst = &surface->buffer[span->y * surface->stride + span->x];
654         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
655         if (span->coverage == 255) {
656             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
657                 *dst = *img;
658             }
659         } else {
660             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
661                 auto src = ALPHA_BLEND(*img, span->coverage);
662                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
663             }
664         }
665     }
666     return true;
667 }
668
669
670 /************************************************************************/
671 /* Whole Transformed Translucent Image                                  */
672 /************************************************************************/
673
674 static bool _rasterTransformedMaskedImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
675 {
676     TVGLOG("SW_ENGINE", "Transformed Masked Image");
677
678     auto img = image->data;
679     auto w = image->w;
680     auto h = image->h;
681     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
682     auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x];
683
684     for (auto y = region.min.y; y < region.max.y; ++y) {
685         auto dst = dbuffer;
686         auto cmp = cbuffer;
687         float ey1 = y * itransform->e12 + itransform->e13;
688         float ey2 = y * itransform->e22 + itransform->e23;
689         for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
690             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
691             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
692             if (rX >= w || rY >= h) continue;
693             auto src = ALPHA_BLEND(img[rX + (rY * image->stride)], _multiplyAlpha(opacity, blendMethod(*cmp)));
694             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
695         }
696         dbuffer += surface->stride;
697         cbuffer += surface->stride;
698     }
699     return true;
700 }
701
702
703 static bool _rasterTransformedTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform)
704 {
705     auto img = image->data;
706     auto w = image->w;
707     auto h = image->h;
708     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
709
710     for (auto y = region.min.y; y < region.max.y; ++y) {
711         auto dst = dbuffer;
712         auto ey1 = y * itransform->e12 + itransform->e13;
713         auto ey2 = y * itransform->e22 + itransform->e23;
714         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
715             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
716             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
717             if (rX >= w || rY >= h) continue;
718
719             auto src = ALPHA_BLEND(img[rX + (rY * image->stride)], opacity);
720             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
721         }
722         dbuffer += surface->stride;
723     }
724     return true;
725 }
726
727
728 static bool _rasterDownScaledMaskedImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
729 {
730     TVGLOG("SW_ENGINE", "Down Scaled Masked Image");
731
732     auto img = image->data;
733     auto w = image->w;
734     auto h = image->h;
735     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
736     auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x];
737
738     for (auto y = region.min.y; y < region.max.y; ++y) {
739         auto dst = dbuffer;
740         auto cmp = cbuffer;
741         float ey1 = y * itransform->e12 + itransform->e13;
742         float ey2 = y * itransform->e22 + itransform->e23;
743         for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
744             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
745             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
746             if (rX >= w || rY >= h) continue;
747             uint32_t src;
748             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) {
749                 src = ALPHA_BLEND(img[rX + (rY * image->stride)], _multiplyAlpha(opacity, blendMethod(*cmp)));
750             } else {
751                 src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), _multiplyAlpha(opacity, blendMethod(*cmp)));
752             }
753             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
754         }
755         dbuffer += surface->stride;
756         cbuffer += surface->stride;
757     }
758     return true;
759 }
760
761
762 static bool _rasterDownScaledTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale)
763 {
764     auto img = image->data;
765     auto w = image->w;
766     auto h = image->h;
767     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
768
769     for (auto y = region.min.y; y < region.max.y; ++y) {
770         auto dst = dbuffer;
771         auto ey1 = y * itransform->e12 + itransform->e13;
772         auto ey2 = y * itransform->e22 + itransform->e23;
773         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
774             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
775             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
776             if (rX >= w || rY >= h) continue;
777             uint32_t src;
778             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rX + (rY * w)], opacity);
779             else src = ALPHA_BLEND(_interpDownScaler(img, w, h, rX, rY, halfScale), opacity);
780             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
781         }
782         dbuffer += surface->stride;
783     }
784     return true;
785 }
786
787
788 static bool _rasterUpScaledMaskedImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
789 {
790     TVGLOG("SW_ENGINE", "Up Scaled Masked Image");
791
792     auto img = image->data;
793     auto w = image->w;
794     auto h = image->h;
795     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
796     auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x];
797
798     for (auto y = region.min.y; y < region.max.y; ++y) {
799         auto dst = dbuffer;
800         auto cmp = cbuffer;
801         float ey1 = y * itransform->e12 + itransform->e13;
802         float ey2 = y * itransform->e22 + itransform->e23;
803         for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
804             auto fX = x * itransform->e11 + ey1;
805             auto fY = x * itransform->e21 + ey2;
806             auto rX = static_cast<uint32_t>(roundf(fX));
807             auto rY = static_cast<uint32_t>(roundf(fY));
808             if (rX >= w || rY >= h) continue;
809             uint32_t src;
810             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rX + (rY * image->stride)], _multiplyAlpha(opacity, blendMethod(*cmp)));
811             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), _multiplyAlpha(opacity, blendMethod(*cmp)));
812             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
813         }
814         dbuffer += surface->stride;
815         cbuffer += surface->stride;
816     }
817     return true;
818 }
819
820
821 static bool _rasterUpScaledTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform)
822 {
823     auto img = image->data;
824     auto w = image->w;
825     auto h = image->h;
826     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
827
828     for (auto y = region.min.y; y < region.max.y; ++y) {
829         auto dst = dbuffer;
830         auto ey1 = y * itransform->e12 + itransform->e13;
831         auto ey2 = y * itransform->e22 + itransform->e23;
832         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
833             auto fX = x * itransform->e11 + ey1;
834             auto fY = x * itransform->e21 + ey2;
835             auto rX = static_cast<uint32_t>(roundf(fX));
836             auto rY = static_cast<uint32_t>(roundf(fY));
837             if (rX >= w || rY >= h) continue;
838             uint32_t src;
839             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rX + (rY * image->stride)], opacity);
840             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), opacity);
841             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
842         }
843         dbuffer += surface->stride;
844     }
845     return true;
846 }
847
848
849 static bool _rasterTransformedTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale)
850 {
851     //Transformd
852     if (mathEqual(image->scale, 1.0f)) {
853         if (surface->compositor) {
854             if (surface->compositor->method == CompositeMethod::AlphaMask) {
855                 return _rasterTransformedMaskedImage(surface, image, opacity, region, itransform, surface->blender.alpha);
856             }
857             if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
858                 return _rasterTransformedMaskedImage(surface, image, opacity, region, itransform, surface->blender.ialpha);
859             }
860         }
861         return _rasterTransformedTranslucentImage(surface, image, opacity, region, itransform);
862     //Transformed + DownScaled
863     } else if (image->scale < DOWN_SCALE_TOLERANCE) {
864         if (surface->compositor) {
865             if (surface->compositor->method == CompositeMethod::AlphaMask) {
866                 return _rasterDownScaledMaskedImage(surface, image, opacity, region, itransform, halfScale, surface->blender.alpha);
867             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
868                 return _rasterDownScaledMaskedImage(surface, image, opacity, region, itransform, halfScale, surface->blender.ialpha);
869             }
870         }
871         return _rasterDownScaledTranslucentImage(surface, image, opacity, region, itransform, halfScale);
872     //Transformed + UpScaled
873     } else {
874         if (surface->compositor) {
875             if (surface->compositor->method == CompositeMethod::AlphaMask) {
876                 return _rasterUpScaledMaskedImage(surface, image, opacity, region, itransform, surface->blender.alpha);
877             }else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
878                 return _rasterUpScaledMaskedImage(surface, image, opacity, region, itransform, surface->blender.ialpha);
879             }
880         }
881         return _rasterUpScaledTranslucentImage(surface, image, opacity, region, itransform);
882     }
883 }
884
885
886 /************************************************************************/
887 /* Whole Transformed Solid Image                                       */
888 /************************************************************************/
889
890 static bool _rasterTransformedSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform)
891 {
892     auto img = image->data;
893     auto w = image->w;
894     auto h = image->h;
895
896     for (auto y = region.min.y; y < region.max.y; ++y) {
897         auto dst = &surface->buffer[y * surface->stride + region.min.x];
898         auto ey1 = y * itransform->e12 + itransform->e13;
899         auto ey2 = y * itransform->e22 + itransform->e23;
900         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
901             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
902             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
903             if (rX >= w || rY >= h) continue;
904             *dst = img[rX + (rY * image->stride)];
905         }
906     }
907     return true;
908 }
909
910
911 static bool _rasterDownScaledSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform, uint32_t halfScale)
912 {
913     auto img = image->data;
914     auto w = image->w;
915     auto h = image->h;
916
917     for (auto y = region.min.y; y < region.max.y; ++y) {
918         auto dst = &surface->buffer[y * surface->stride + region.min.x];
919         auto ey1 = y * itransform->e12 + itransform->e13;
920         auto ey2 = y * itransform->e22 + itransform->e23;
921         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
922             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
923             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
924             if (rX >= w || rY >= h) continue;
925             uint32_t src;
926             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = img[rX + (rY * w)];
927             else src = _interpDownScaler(img, w, h, rX, rY, halfScale);
928             *dst = src;
929         }
930     }
931     return true;
932 }
933
934
935 static bool _rasterUpScaledSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform)
936 {
937     auto img = image->data;
938     auto w = image->w;
939     auto h = image->h;
940
941     for (auto y = region.min.y; y < region.max.y; ++y) {
942         auto dst = &surface->buffer[y * surface->stride + region.min.x];
943         auto ey1 = y * itransform->e12 + itransform->e13;
944         auto ey2 = y * itransform->e22 + itransform->e23;
945         for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
946             auto fX = x * itransform->e11 + ey1;
947             auto fY = x * itransform->e21 + ey2;
948             auto rX = static_cast<uint32_t>(roundf(fX));
949             auto rY = static_cast<uint32_t>(roundf(fY));
950             if (rX >= w || rY >= h) continue;
951             uint32_t src;
952             if (rX == w - 1 || rY == h - 1) src = img[rX + (rY * w)];
953             else src = _interpUpScaler(img, w, h, fX, fY);
954             *dst = src;
955         }
956     }
957     return true;
958 }
959
960
961 static bool _rasterTransformedSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform, uint32_t halfScale)
962 {  
963     if (mathEqual(image->scale, 1.0f)) return _rasterTransformedSolidImage(surface, image, region, itransform);
964     else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledSolidImage(surface, image, region, itransform, halfScale);
965     else return _rasterUpScaledSolidImage(surface, image, region, itransform);
966 }
967
968
969 /************************************************************************/
970 /* Whole (Solid + Translucent) Direct Image                            */
971 /************************************************************************/
972
973 static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, uint32_t (*blendMethod)(uint32_t))
974 {
975     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
976     auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
977     auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
978
979     TVGLOG("SW_ENGINE", "Direct Masked Image");
980
981     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
982     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x;   //compositor buffer
983
984     for (uint32_t y = 0; y < h2; ++y) {
985         auto dst = buffer;
986         auto cmp = cbuffer;
987         auto src = sbuffer;
988         for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
989             auto tmp = ALPHA_BLEND(*src, _multiplyAlpha(opacity, blendMethod(*cmp)));
990             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
991         }
992         buffer += surface->stride;
993         cbuffer += surface->stride;
994         sbuffer += image->stride;
995     }
996     return true;
997 }
998
999
1000 static bool __rasterDirectTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region)
1001 {
1002     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
1003     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1004
1005     for (auto y = region.min.y; y < region.max.y; ++y) {
1006         auto dst = dbuffer;
1007         auto src = sbuffer;
1008         for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
1009             auto p = ALPHA_BLEND(*src, opacity);
1010             *dst = p + ALPHA_BLEND(*dst, surface->blender.ialpha(p));
1011         }
1012         dbuffer += surface->stride;
1013         sbuffer += image->stride;
1014     }
1015     return true;
1016 }
1017
1018
1019 static bool _rasterDirectTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region)
1020 {
1021     if (surface->compositor) {
1022         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1023             return _rasterDirectMaskedImage(surface, image, opacity, region, surface->blender.alpha);
1024         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1025             return _rasterDirectMaskedImage(surface, image, opacity, region, surface->blender.ialpha);
1026         }
1027     }
1028     return __rasterDirectTranslucentImage(surface, image, opacity, region);
1029 }
1030
1031
1032 static bool _rasterDirectSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region)
1033 {
1034     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
1035     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1036
1037     for (auto y = region.min.y; y < region.max.y; ++y) {
1038         auto dst = dbuffer;
1039         auto src = sbuffer;
1040         for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
1041             *dst = *src;
1042         }
1043         dbuffer += surface->stride;
1044         sbuffer += image->stride;
1045     }
1046     return true;
1047 }
1048
1049
1050 /************************************************************************/
1051 /* Rect Linear Gradient                                                 */
1052 /************************************************************************/
1053
1054 static bool _rasterTranslucentLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1055 {
1056     if (fill->linear.len < FLT_EPSILON) return false;
1057
1058     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1059     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1060     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1061     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x;
1062
1063     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1064     if (!sbuffer) return false;
1065
1066     for (uint32_t y = 0; y < h; ++y) {
1067         fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w);
1068         auto dst = buffer;
1069         auto cmp = cbuffer;
1070         auto src = sbuffer;
1071         for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
1072             auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1073             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1074         }
1075         buffer += surface->stride;
1076         cbuffer += surface->stride;
1077     }
1078     return true;
1079 }
1080
1081
1082 static bool __rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1083 {
1084     if (fill->linear.len < FLT_EPSILON) return false;
1085
1086     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1087     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1088     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1089
1090     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1091     if (!sbuffer) return false;
1092
1093     auto dst = buffer;
1094     for (uint32_t y = 0; y < h; ++y) {
1095         fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w);
1096         for (uint32_t x = 0; x < w; ++x) {
1097             dst[x] = sbuffer[x] + ALPHA_BLEND(dst[x], surface->blender.ialpha(sbuffer[x]));
1098         }
1099         dst += surface->stride;
1100     }
1101     return true;
1102 }
1103
1104
1105 static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1106 {
1107     if (surface->compositor) {
1108         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1109             return _rasterTranslucentLinearGradientMaskedRect(surface, region, fill, surface->blender.alpha);
1110         }
1111         if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1112             return _rasterTranslucentLinearGradientMaskedRect(surface, region, fill, surface->blender.ialpha);
1113         }
1114     }
1115     return __rasterTranslucentLinearGradientRect(surface, region, fill);
1116 }
1117
1118
1119 static bool _rasterSolidLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1120 {
1121     if (fill->linear.len < FLT_EPSILON) return false;
1122
1123     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1124     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1125     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1126
1127     for (uint32_t y = 0; y < h; ++y) {
1128         fillFetchLinear(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, w);
1129     }
1130     return true;
1131 }
1132
1133
1134 /************************************************************************/
1135 /* Rle Linear Gradient                                                  */
1136 /************************************************************************/
1137
1138
1139 static bool _rasterTranslucentLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1140 {
1141     if (fill->linear.len < FLT_EPSILON) return false;
1142
1143     auto span = rle->spans;
1144     auto cbuffer = surface->compositor->image.data;
1145     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1146     if (!buffer) return false;
1147
1148     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1149         fillFetchLinear(fill, buffer, span->y, span->x, span->len);
1150         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1151         auto cmp = &cbuffer[span->y * surface->stride + span->x];
1152         auto src = buffer;
1153         if (span->coverage == 255) {
1154             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1155                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1156                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1157             }
1158         } else {
1159             auto ialpha = 255 - span->coverage;
1160             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1161                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1162                 tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha);
1163                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1164             }
1165         }
1166     }
1167     return true;
1168 }
1169
1170
1171 static bool __rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1172 {
1173     if (fill->linear.len < FLT_EPSILON) return false;
1174
1175     auto span = rle->spans;
1176     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1177     if (!buffer) return false;
1178
1179     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1180         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1181         fillFetchLinear(fill, buffer, span->y, span->x, span->len);
1182         if (span->coverage == 255) {
1183             for (uint32_t i = 0; i < span->len; ++i) {
1184                 dst[i] = buffer[i] + ALPHA_BLEND(dst[i], surface->blender.ialpha(buffer[i]));
1185             }
1186         } else {
1187             for (uint32_t i = 0; i < span->len; ++i) {
1188                 auto tmp = ALPHA_BLEND(buffer[i], span->coverage);
1189                 dst[i] = tmp + ALPHA_BLEND(dst[i], surface->blender.ialpha(tmp));
1190             }
1191         }
1192     }
1193     return true;
1194 }
1195
1196
1197 static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1198 {
1199     if (!rle) return false;
1200
1201     if (surface->compositor) {
1202         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1203             return _rasterTranslucentLinearGradientMaskedRle(surface, rle, fill, surface->blender.alpha);
1204         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1205             return _rasterTranslucentLinearGradientMaskedRle(surface, rle, fill, surface->blender.ialpha);
1206         }
1207     }
1208     return __rasterTranslucentLinearGradientRle(surface, rle, fill);
1209 }
1210
1211
1212 static bool _rasterSolidLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1213 {
1214     if (fill->linear.len < FLT_EPSILON) return false;
1215
1216     auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1217     if (!buf) return false;
1218
1219     auto span = rle->spans;
1220
1221     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1222         if (span->coverage == 255) {
1223             fillFetchLinear(fill, surface->buffer + span->y * surface->stride + span->x, span->y, span->x, span->len);
1224         } else {
1225             fillFetchLinear(fill, buf, span->y, span->x, span->len);
1226             auto ialpha = 255 - span->coverage;
1227             auto dst = &surface->buffer[span->y * surface->stride + span->x];
1228             for (uint32_t i = 0; i < span->len; ++i) {
1229                 dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha);
1230             }
1231         }
1232     }
1233     return true;
1234 }
1235
1236
1237 /************************************************************************/
1238 /* Rect Radial Gradient                                                 */
1239 /************************************************************************/
1240
1241 static bool _rasterTranslucentRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1242 {
1243     if (fill->radial.a < FLT_EPSILON) return false;
1244
1245     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1246     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1247     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1248     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x;
1249
1250     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1251     if (!sbuffer) return false;
1252
1253     for (uint32_t y = 0; y < h; ++y) {
1254         fillFetchRadial(fill, sbuffer, region.min.y + y, region.min.x, w);
1255         auto dst = buffer;
1256         auto cmp = cbuffer;
1257         auto src = sbuffer;
1258         for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
1259              auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1260              *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1261         }
1262         buffer += surface->stride;
1263         cbuffer += surface->stride;
1264     }
1265     return true;
1266 }
1267
1268
1269 static bool __rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1270 {
1271     if (fill->radial.a < FLT_EPSILON) return false;
1272
1273     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1274     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1275     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1276
1277     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1278     if (!sbuffer) return false;
1279
1280     auto dst = buffer;
1281     for (uint32_t y = 0; y < h; ++y) {
1282         fillFetchRadial(fill, sbuffer, region.min.y + y, region.min.x, w);
1283         for (uint32_t x = 0; x < w; ++x) {
1284             dst[x] = sbuffer[x] + ALPHA_BLEND(dst[x], surface->blender.ialpha(sbuffer[x]));
1285         }
1286         dst += surface->stride;
1287     }
1288     return true;
1289 }
1290
1291
1292 static bool _rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1293 {
1294     if (surface->compositor) {
1295         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1296             return _rasterTranslucentRadialGradientMaskedRect(surface, region, fill, surface->blender.alpha);
1297         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1298             return _rasterTranslucentRadialGradientMaskedRect(surface, region, fill, surface->blender.ialpha);
1299         }
1300     }
1301     return __rasterTranslucentRadialGradientRect(surface, region, fill);
1302 }
1303
1304
1305 static bool _rasterSolidRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1306 {
1307     if (fill->radial.a < FLT_EPSILON) return false;
1308
1309     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1310     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1311     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1312
1313     for (uint32_t y = 0; y < h; ++y) {
1314         auto dst = &buffer[y * surface->stride];
1315         fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w);
1316     }
1317     return true;
1318 }
1319
1320
1321 /************************************************************************/
1322 /* RLE Radial Gradient                                                  */
1323 /************************************************************************/
1324
1325
1326 static bool _rasterTranslucentRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1327 {
1328     if (fill->radial.a < FLT_EPSILON) return false;
1329
1330     auto span = rle->spans;
1331     auto cbuffer = surface->compositor->image.data;
1332     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1333     if (!buffer) return false;
1334
1335     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1336         fillFetchRadial(fill, buffer, span->y, span->x, span->len);
1337         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1338         auto cmp = &cbuffer[span->y * surface->stride + span->x];
1339         auto src = buffer;
1340         if (span->coverage == 255) {
1341             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1342                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1343                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1344             }
1345         } else {
1346             auto ialpha = 255 - span->coverage;
1347             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1348                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1349                 tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha);
1350                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1351             }
1352         }
1353     }
1354     return true;
1355 }
1356
1357
1358 static bool __rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1359 {
1360     if (fill->radial.a < FLT_EPSILON) return false;
1361
1362     auto span = rle->spans;
1363     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1364     if (!buffer) return false;
1365
1366     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1367         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1368         fillFetchRadial(fill, buffer, span->y, span->x, span->len);
1369         if (span->coverage == 255) {
1370             for (uint32_t i = 0; i < span->len; ++i) {
1371                 dst[i] = buffer[i] + ALPHA_BLEND(dst[i], surface->blender.ialpha(buffer[i]));
1372             }
1373         } else {
1374            for (uint32_t i = 0; i < span->len; ++i) {
1375                 auto tmp = ALPHA_BLEND(buffer[i], span->coverage);
1376                 dst[i] = tmp + ALPHA_BLEND(dst[i], surface->blender.ialpha(tmp));
1377             }
1378         }
1379     }
1380     return true;
1381 }
1382
1383
1384 static bool _rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1385 {
1386     if (!rle) return false;
1387
1388     if (surface->compositor) {
1389         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1390             return _rasterTranslucentRadialGradientMaskedRle(surface, rle, fill, surface->blender.alpha);
1391         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1392             return _rasterTranslucentRadialGradientMaskedRle(surface, rle, fill, surface->blender.ialpha);
1393         }
1394     }
1395     return __rasterTranslucentRadialGradientRle(surface, rle, fill);
1396 }
1397
1398
1399 static bool _rasterSolidRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1400 {
1401     if (fill->radial.a < FLT_EPSILON) return false;
1402
1403     auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1404     if (!buf) return false;
1405
1406     auto span = rle->spans;
1407
1408     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1409         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1410         if (span->coverage == 255) {
1411             fillFetchRadial(fill, dst, span->y, span->x, span->len);
1412         } else {
1413             fillFetchRadial(fill, buf, span->y, span->x, span->len);
1414             auto ialpha = 255 - span->coverage;
1415             for (uint32_t i = 0; i < span->len; ++i) {
1416                 dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha);
1417             }
1418         }
1419     }
1420     return true;
1421 }
1422
1423
1424 /************************************************************************/
1425 /* External Class Implementation                                        */
1426 /************************************************************************/
1427
1428 void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
1429 {
1430 #if defined(THORVG_AVX_VECTOR_SUPPORT)
1431     avxRasterRGBA32(dst, val, offset, len);
1432 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
1433     neonRasterRGBA32(dst, val, offset, len);
1434 #else
1435     cRasterRGBA32(dst, val, offset, len);
1436 #endif
1437 }
1438
1439
1440 bool rasterCompositor(SwSurface* surface)
1441 {
1442     if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) {
1443         surface->blender.join = _abgrJoin;
1444     } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
1445         surface->blender.join = _argbJoin;
1446     } else {
1447         //What Color Space ???
1448         return false;
1449     }
1450     surface->blender.alpha = _colorAlpha;
1451     surface->blender.ialpha = _colorInvAlpha;
1452
1453     return true;
1454 }
1455
1456
1457 bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id)
1458 {
1459     if (!shape->fill) return false;
1460
1461     auto translucent = shape->fill->translucent || (surface->compositor && surface->compositor->method != CompositeMethod::None);
1462
1463     //Fast Track
1464     if (shape->fastTrack) {
1465         if (id == TVG_CLASS_ID_LINEAR) {
1466             if (translucent) return _rasterTranslucentLinearGradientRect(surface, shape->bbox, shape->fill);
1467             return _rasterSolidLinearGradientRect(surface, shape->bbox, shape->fill);
1468         } else {
1469             if (translucent) return _rasterTranslucentRadialGradientRect(surface, shape->bbox, shape->fill);
1470             return _rasterSolidRadialGradientRect(surface, shape->bbox, shape->fill);
1471         }
1472     } else {
1473         if (!shape->rle) return false;
1474         if (id == TVG_CLASS_ID_LINEAR) {
1475             if (translucent) return _rasterTranslucentLinearGradientRle(surface, shape->rle, shape->fill);
1476             return _rasterSolidLinearGradientRle(surface, shape->rle, shape->fill);
1477         } else {
1478             if (translucent) return _rasterTranslucentRadialGradientRle(surface, shape->rle, shape->fill);
1479             return _rasterSolidRadialGradientRle(surface, shape->rle, shape->fill);
1480         }
1481     }
1482     return false;
1483 }
1484
1485
1486 bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
1487 {
1488     if (a < 255) {
1489         r = _multiplyAlpha(r, a);
1490         g = _multiplyAlpha(g, a);
1491         b = _multiplyAlpha(b, a);
1492     }
1493
1494     auto color = surface->blender.join(r, g, b, a);
1495     auto translucent = _translucent(surface, a);
1496
1497     //Fast Track
1498     if (shape->fastTrack) {
1499         if (translucent) return _rasterTranslucentRect(surface, shape->bbox, color);
1500         return _rasterSolidRect(surface, shape->bbox, color);
1501     }
1502     if (translucent) {
1503         return _rasterTranslucentRle(surface, shape->rle, color);
1504     }
1505     return _rasterSolidRle(surface, shape->rle, color);
1506 }
1507
1508
1509 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
1510 {
1511     if (a < 255) {
1512         r = _multiplyAlpha(r, a);
1513         g = _multiplyAlpha(g, a);
1514         b = _multiplyAlpha(b, a);
1515     }
1516
1517     auto color = surface->blender.join(r, g, b, a);
1518     auto translucent = _translucent(surface, a);
1519
1520     if (translucent) return _rasterTranslucentRle(surface, shape->strokeRle, color);
1521     return _rasterSolidRle(surface, shape->strokeRle, color);
1522 }
1523
1524
1525 bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id)
1526 {
1527     if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false;
1528
1529     auto translucent = shape->stroke->fill->translucent || (surface->compositor && surface->compositor->method != CompositeMethod::None);
1530
1531     if (id == TVG_CLASS_ID_LINEAR) {
1532         if (translucent) return _rasterTranslucentLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1533         return _rasterSolidLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1534     } else {
1535         if (translucent) return _rasterTranslucentRadialGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1536         return _rasterSolidRadialGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1537     }
1538
1539     return false;
1540 }
1541
1542
1543 bool rasterClear(SwSurface* surface)
1544 {
1545     if (!surface || !surface->buffer || surface->stride <= 0 || surface->w <= 0 || surface->h <= 0) return false;
1546
1547     if (surface->w == surface->stride) {
1548         rasterRGBA32(surface->buffer, 0x00000000, 0, surface->w * surface->h);
1549     } else {
1550         for (uint32_t i = 0; i < surface->h; i++) {
1551             rasterRGBA32(surface->buffer + surface->stride * i, 0x00000000, 0, surface->w);
1552         }
1553     }
1554     return true;
1555 }
1556
1557
1558 void rasterUnpremultiply(SwSurface* surface)
1559 {
1560     //TODO: Create simd avx and neon version
1561     for (uint32_t y = 0; y < surface->h; y++) {
1562         auto buffer = surface->buffer + surface->stride * y;
1563         for (uint32_t x = 0; x < surface->w; ++x) {
1564             uint8_t a = buffer[x] >> 24;
1565             if (a == 255) {
1566                 continue;
1567             } else if (a == 0) {
1568                 buffer[x] = 0x00ffffff;
1569             } else {
1570                 uint16_t r = ((buffer[x] >> 8) & 0xff00) / a;
1571                 uint16_t g = ((buffer[x]) & 0xff00) / a;
1572                 uint16_t b = ((buffer[x] << 8) & 0xff00) / a;
1573                 if (r > 0xff) r = 0xff;
1574                 if (g > 0xff) g = 0xff;
1575                 if (b > 0xff) b = 0xff;
1576                 buffer[x] = (a << 24) | (r << 16) | (g << 8) | (b);
1577             }
1578         }
1579     }
1580 }
1581
1582
1583 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity)
1584 {
1585     Matrix itransform;
1586     if (transform && !mathInverse(transform, &itransform)) return false;
1587
1588     auto halfScale = static_cast<uint32_t>(0.5f / image->scale);
1589     if (halfScale == 0) halfScale = 1;
1590
1591     auto translucent = _translucent(surface, opacity);
1592
1593     //Clipped Image
1594     if (image->rle) {
1595         if (image->direct) {
1596             if (translucent) return _rasterDirectTranslucentRleImage(surface, image, opacity);
1597             else return _rasterDirectSolidRleImage(surface, image);
1598         } else {
1599             if (translucent) return _rasterTransformedTranslucentRleImage(surface, image, opacity, &itransform, halfScale);
1600             else return _rasterTransformedSolidRleImage(surface, image, &itransform, halfScale);
1601         }
1602     //Whole Image
1603     } else {
1604         if (image->direct) {
1605             if (translucent) return _rasterDirectTranslucentImage(surface, image, opacity, bbox);
1606             else return _rasterDirectSolidImage(surface, image, bbox);
1607         } else {
1608             if (translucent) return _rasterTransformedTranslucentImage(surface, image, opacity, bbox, &itransform, halfScale);
1609             else return _rasterTransformedSolidImage(surface, image, bbox, &itransform, halfScale);
1610         }
1611     }
1612 }