sw_engine SWRaster: Initialize uninitialized local variable
[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
26 /************************************************************************/
27 /* Internal Class Implementation                                        */
28 /************************************************************************/
29 constexpr auto DOWN_SCALE_TOLERANCE = 0.5f;
30
31
32 static inline uint32_t _multiplyAlpha(uint32_t c, uint32_t a)
33 {
34     return ((c * a + 0xff) >> 8);
35 }
36
37
38 static inline uint32_t _colorAlpha(uint32_t c)
39 {
40     return (c >> 24);
41 }
42
43
44 static inline uint32_t _colorInvAlpha(uint32_t c)
45 {
46     return (~c >> 24);
47 }
48
49
50 static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
51 {
52     return (a << 24 | b << 16 | g << 8 | r);
53 }
54
55
56 static inline uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
57 {
58     return (a << 24 | r << 16 | g << 8 | b);
59 }
60
61
62 #include "tvgSwRasterTexmap.h"
63 #include "tvgSwRasterC.h"
64 #include "tvgSwRasterAvx.h"
65 #include "tvgSwRasterNeon.h"
66
67
68 static inline bool _compositing(const SwSurface* surface)
69 {
70     if (!surface->compositor || surface->compositor->method == CompositeMethod::None) return false;
71     return true;
72 }
73
74
75 static inline uint32_t _halfScale(float scale)
76 {
77     auto halfScale = static_cast<uint32_t>(0.5f / scale);
78     if (halfScale == 0) halfScale = 1;
79     return halfScale;
80 }
81
82 //Bilinear Interpolation
83 static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float sx, float sy)
84 {
85     auto rx = static_cast<uint32_t>(sx);
86     auto ry = static_cast<uint32_t>(sy);
87     auto rx2 = rx + 1;
88     if (rx2 >= w) rx2 = w - 1;
89     auto ry2 = ry + 1;
90     if (ry2 >= h) ry2 = h - 1;
91
92     auto dx = static_cast<uint32_t>((sx - rx) * 255.0f);
93     auto dy = static_cast<uint32_t>((sy - ry) * 255.0f);
94
95     auto c1 = img[rx + ry * w];
96     auto c2 = img[rx2 + ry * w];
97     auto c3 = img[rx2 + ry2 * w];
98     auto c4 = img[rx + ry2 * w];
99
100     return INTERPOLATE(dy, INTERPOLATE(dx, c3, c4), INTERPOLATE(dx, c2, c1));
101 }
102
103
104 //2n x 2n Mean Kernel
105 static uint32_t _interpDownScaler(const uint32_t *img, uint32_t w, uint32_t h, uint32_t rX, uint32_t rY, uint32_t n)
106 {
107     uint32_t c[4] = { 0 };
108     auto n2 = n * n;
109     auto src = img + rX - n + (rY - n) * w;
110     for (auto y = rY - n; y < rY + n; ++y) {
111         auto p = src;
112         for (auto x = rX - n; x < rX + n; ++x, ++p) {
113             c[0] += *p >> 24;
114             c[1] += (*p >> 16) & 0xff;
115             c[2] += (*p >> 8) & 0xff;
116             c[3] += *p & 0xff;
117         }
118         src += w;
119     }
120     for (auto i = 0; i < 4; ++i) {
121         c[i] = (c[i] >> 2) / n2;
122     }
123     return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
124 }
125
126
127 /************************************************************************/
128 /* Rect                                                                 */
129 /************************************************************************/
130
131 static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint32_t (*blendMethod)(uint32_t))
132 {
133     TVGLOG("SW_ENGINE", "Masked Rect");
134
135     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
136     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
137     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
138
139     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;   //compositor buffer
140
141     for (uint32_t y = 0; y < h; ++y) {
142         auto dst = &buffer[y * surface->stride];
143         auto cmp = &cbuffer[y * surface->stride];
144         for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp) {
145             auto tmp = ALPHA_BLEND(color, blendMethod(*cmp));
146             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
147         }
148     }
149     return true;
150 }
151
152
153 static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color)
154 {
155     auto buffer = surface->buffer + (region.min.y * surface->stride);
156     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
157     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
158
159     for (uint32_t y = 0; y < h; ++y) {
160         rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w);
161     }
162     return true;
163 }
164
165
166 static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint8_t opacity)
167 {
168     if (_compositing(surface)) {
169         if (surface->compositor->method == CompositeMethod::AlphaMask) {
170             return _rasterMaskedRect(surface, region, color, surface->blender.alpha);
171         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
172             return _rasterMaskedRect(surface, region, color, surface->blender.ialpha);
173         }
174     } else {
175         if (opacity == 255) {
176             return _rasterSolidRect(surface, region, color);
177         } else {
178 #if defined(THORVG_AVX_VECTOR_SUPPORT)
179             return avxRasterTranslucentRect(surface, region, color);
180 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
181             return neonRasterTranslucentRect(surface, region, color);
182 #else
183             return cRasterTranslucentRect(surface, region, color);
184 #endif
185         }
186     }
187     return false;
188 }
189
190
191 /************************************************************************/
192 /* Rle                                                                  */
193 /************************************************************************/
194
195 static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint32_t (*blendMethod)(uint32_t))
196 {
197     TVGLOG("SW_ENGINE", "Masked Rle");
198
199     auto span = rle->spans;
200     uint32_t src;
201     auto cbuffer = surface->compositor->image.data;
202
203     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
204         auto dst = &surface->buffer[span->y * surface->stride + span->x];
205         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
206         if (span->coverage == 255) src = color;
207         else src = ALPHA_BLEND(color, span->coverage);
208         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
209             auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
210             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
211         }
212     }
213     return true;
214 }
215
216
217 static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
218 {
219     auto span = rle->spans;
220
221     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
222         if (span->coverage == 255) {
223             rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len);
224         } else {
225             auto dst = &surface->buffer[span->y * surface->stride + span->x];
226             auto src = ALPHA_BLEND(color, span->coverage);
227             auto ialpha = 255 - span->coverage;
228             for (uint32_t x = 0; x < span->len; ++x, ++dst) {
229                 *dst = src + ALPHA_BLEND(*dst, ialpha);
230             }
231         }
232     }
233     return true;
234 }
235
236
237 static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8_t opacity)
238 {
239     if (!rle) return false;
240
241     if (_compositing(surface)) {
242         if (surface->compositor->method == CompositeMethod::AlphaMask) {
243             return _rasterMaskedRle(surface, rle, color, surface->blender.alpha);
244         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
245             return _rasterMaskedRle(surface, rle, color, surface->blender.ialpha);
246         }
247     } else {
248         if (opacity == 255) {
249             return _rasterSolidRle(surface, rle, color);
250         } else {
251 #if defined(THORVG_AVX_VECTOR_SUPPORT)
252             return avxRasterTranslucentRle(surface, rle, color);
253 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
254             return neonRasterTranslucentRle(surface, rle, color);
255 #else
256             return cRasterTranslucentRle(surface, rle, color);
257 #endif
258         }
259     }
260     return false;
261 }
262
263
264 /************************************************************************/
265 /* RLE Transformed RGBA Image                                           */
266 /************************************************************************/
267
268 static bool _rasterTransformedMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
269 {
270     TVGLOG("SW_ENGINE", "Transformed Masked Translucent Rle Image");
271
272     auto span = image->rle->spans;
273     auto img = image->data;
274     auto w = image->w;
275     auto h = image->h;
276     auto cbuffer = surface->compositor->image.data;
277
278     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
279         auto ey1 = span->y * itransform->e12 + itransform->e13;
280         auto ey2 = span->y * itransform->e22 + itransform->e23;
281         auto dst = &surface->buffer[span->y * surface->stride + span->x];
282         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
283         auto alpha = _multiplyAlpha(span->coverage, opacity);
284         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
285             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
286             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
287             if (rX >= w || rY >= h) continue;
288             auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
289             auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
290             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
291         }
292     }
293     return true;
294 }
295
296
297 static bool _rasterTransformedMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
298 {
299     TVGLOG("SW_ENGINE", "Transformed Masked Rle Image");
300
301     auto span = image->rle->spans;
302     auto img = image->data;
303     auto w = image->w;
304     auto h = image->h;
305     auto cbuffer = surface->compositor->image.data;
306
307     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
308         auto ey1 = span->y * itransform->e12 + itransform->e13;
309         auto ey2 = span->y * itransform->e22 + itransform->e23;
310         auto dst = &surface->buffer[span->y * surface->stride + span->x];
311         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
312          if (span->coverage == 255) {
313             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
314                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
315                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
316                 if (rX >= w || rY >= h) continue;
317                 auto tmp = ALPHA_BLEND(img[rY * image->stride + rX], blendMethod(*cmp));
318                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
319             }
320         } else {
321             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
322                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
323                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
324                 if (rX >= w || rY >= h) continue;
325                 auto src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
326                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
327                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
328             }
329         }
330     }
331     return true;
332 }
333
334
335 static bool _rasterTransformedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity)
336 {
337     auto span = image->rle->spans;
338     auto img = image->data;
339     auto w = image->w;
340     auto h = image->h;
341
342     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
343         auto ey1 = span->y * itransform->e12 + itransform->e13;
344         auto ey2 = span->y * itransform->e22 + itransform->e23;
345         auto dst = &surface->buffer[span->y * surface->stride + span->x];
346         auto alpha = _multiplyAlpha(span->coverage, opacity);
347         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
348             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
349             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
350             if (rX >= w || rY >= h) continue;
351             auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
352             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
353         }
354     }
355     return true;
356 }
357
358
359 static bool _rasterDownScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
360 {
361     TVGLOG("SW_ENGINE", "Down Scaled Masked Translucent Rle Image");
362
363     auto span = image->rle->spans;
364     auto img = image->data;
365     auto w = image->w;
366     auto h = image->h;
367     auto cbuffer = surface->compositor->image.data;
368
369     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
370         auto ey1 = span->y * itransform->e12 + itransform->e13;
371         auto ey2 = span->y * itransform->e22 + itransform->e23;
372         auto dst = &surface->buffer[span->y * surface->stride + span->x];
373         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
374         auto alpha = _multiplyAlpha(span->coverage, opacity);
375         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
376             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
377             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
378             if (rX >= w || rY >= h) continue;
379             uint32_t src;
380             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
381             else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
382             auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
383             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
384         }
385     }
386     return true;
387 }
388
389
390 static bool _rasterDownScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
391 {
392     TVGLOG("SW_ENGINE", "Down Scaled Masked Rle Image");
393
394     auto span = image->rle->spans;
395     auto img = image->data;
396     auto w = image->w;
397     auto h = image->h;
398     auto cbuffer = surface->compositor->image.data;
399
400     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
401         auto ey1 = span->y * itransform->e12 + itransform->e13;
402         auto ey2 = span->y * itransform->e22 + itransform->e23;
403         auto dst = &surface->buffer[span->y * surface->stride + span->x];
404         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
405         if (span->coverage == 255) {
406             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
407                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
408                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
409                 if (rX >= w || rY >= h) continue;
410                 uint32_t src;
411                 if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = img[rY * image->stride + rX];
412                 else src = _interpDownScaler(img, image->stride, h, rX, rY, halfScale);
413                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
414                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
415             }
416         } else {
417             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
418                 auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
419                 auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
420                 if (rX >= w || rY >= h) continue;
421                 uint32_t src;
422                 if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
423                 else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage);
424                 auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
425                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
426             }
427         }
428     }
429     return true;
430 }
431
432
433 static bool _rasterDownScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale)
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 rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
447             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
448             if (rX >= w || rY >= h) continue;
449             uint32_t src;
450             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
451             else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
452             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
453         }
454     }
455     return true;
456 }
457
458
459 static bool _rasterUpScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
460 {
461     TVGLOG("SW_ENGINE", "Up Scaled Masked Translucent Rle Image");
462
463     auto span = image->rle->spans;
464     auto img = image->data;
465     auto w = image->w;
466     auto h = image->h;
467     auto cbuffer = surface->compositor->image.data;
468
469     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
470         auto ey1 = span->y * itransform->e12 + itransform->e13;
471         auto ey2 = span->y * itransform->e22 + itransform->e23;
472         auto dst = &surface->buffer[span->y * surface->stride + span->x];
473         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
474         auto alpha = _multiplyAlpha(span->coverage, opacity);
475         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
476             auto fX = (span->x + x) * itransform->e11 + ey1;
477             auto fY = (span->x + x) * itransform->e21 + ey2;
478             auto rX = static_cast<uint32_t>(roundf(fX));
479             auto rY = static_cast<uint32_t>(roundf(fY));
480             if (rX >= w || rY >= h) continue;
481             uint32_t src;
482             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
483             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
484             auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
485             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
486         }
487     }
488     return true;
489 }
490
491
492 static bool _rasterUpScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
493 {
494     TVGLOG("SW_ENGINE", "Up Scaled Masked Rle Image");
495
496     auto span = image->rle->spans;
497     auto img = image->data;
498     auto w = image->w;
499     auto h = image->h;
500     auto cbuffer = surface->compositor->image.data;
501
502     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
503         auto ey1 = span->y * itransform->e12 + itransform->e13;
504         auto ey2 = span->y * itransform->e22 + itransform->e23;
505         auto dst = &surface->buffer[span->y * surface->stride + span->x];
506         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
507         if (span->coverage == 255) {
508             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
509                 auto fX = (span->x + x) * itransform->e11 + ey1;
510                 auto fY = (span->x + x) * itransform->e21 + ey2;
511                 auto rX = static_cast<uint32_t>(roundf(fX));
512                 auto rY = static_cast<uint32_t>(roundf(fY));
513                 if (rX >= w || rY >= h) continue;
514                 uint32_t src;
515                 if (rX == w - 1 || rY == h - 1) src = img[rY * image->stride + rX];
516                 else src = _interpUpScaler(img, image->stride, h, fX, fY);
517                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
518                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
519             }
520         } else {
521             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
522                 auto fX = (span->x + x) * itransform->e11 + ey1;
523                 auto fY = (span->x + x) * itransform->e21 + ey2;
524                 auto rX = static_cast<uint32_t>(roundf(fX));
525                 auto rY = static_cast<uint32_t>(roundf(fY));
526                 if (rX >= w || rY >= h) continue;
527                 uint32_t src;
528                 if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
529                 else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage);
530                 auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
531                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
532             }
533         }
534     }
535     return true;
536 }
537
538
539 static bool _rasterUpScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity)
540 {
541     auto span = image->rle->spans;
542     auto img = image->data;
543     auto w = image->w;
544     auto h = image->h;
545
546     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
547         auto ey1 = span->y * itransform->e12 + itransform->e13;
548         auto ey2 = span->y * itransform->e22 + itransform->e23;
549         auto dst = &surface->buffer[span->y * surface->stride + span->x];
550         auto alpha = _multiplyAlpha(span->coverage, opacity);
551         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
552             auto fX = (span->x + x) * itransform->e11 + ey1;
553             auto fY = (span->x + x) * itransform->e21 + ey2;
554             auto rX = static_cast<uint32_t>(roundf(fX));
555             auto rY = static_cast<uint32_t>(roundf(fY));
556             if (rX >= w || rY >= h) continue;
557             uint32_t src;
558             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
559             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
560             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
561         }
562     }
563     return true;
564 }
565
566
567 static bool _rasterTransformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
568 {
569     auto span = image->rle->spans;
570
571     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
572         auto ey1 = span->y * itransform->e12 + itransform->e13;
573         auto ey2 = span->y * itransform->e22 + itransform->e23;
574         auto dst = &surface->buffer[span->y * surface->stride + span->x];
575
576         for (uint32_t x = 0; x < span->len; ++x, ++dst) {
577             auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
578             auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
579             if (rX >= image->w || rY >= image->h) continue;
580             auto src = ALPHA_BLEND(image->data[rY * image->stride + rX], span->coverage);
581             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
582         }
583     }
584     return true;
585 }
586
587
588 static bool _rasterDownScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale)
589 {
590     auto span = image->rle->spans;
591     auto img = image->data;
592     auto w = image->w;
593     auto h = image->h;
594
595     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
596         auto ey1 = span->y * itransform->e12 + itransform->e13;
597         auto ey2 = span->y * itransform->e22 + itransform->e23;
598         auto dst = &surface->buffer[span->y * surface->stride + span->x];
599         for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
600             auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
601             auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
602             if (rX >= w || rY >= h) continue;
603
604             uint32_t src;
605             if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
606             else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage);
607             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
608         }
609     }
610     return true;
611 }
612
613
614 static bool _rasterUpScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
615 {
616     auto span = image->rle->spans;
617     auto img = image->data;
618     auto w = image->w;
619     auto h = image->h;
620
621     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
622         auto ey1 = span->y * itransform->e12 + itransform->e13;
623         auto ey2 = span->y * itransform->e22 + itransform->e23;
624         auto dst = &surface->buffer[span->y * surface->stride + span->x];
625         for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
626             auto fX = x * itransform->e11 + ey1;
627             auto fY = x * itransform->e21 + ey2;
628             auto rX = static_cast<uint32_t>(roundf(fX));
629             auto rY = static_cast<uint32_t>(roundf(fY));
630             if (rX >= w || rY >= h) continue;
631             uint32_t src;
632             if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
633             else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage);
634             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
635         }
636     }
637     return true;
638 }
639
640
641 static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, uint32_t opacity)
642 {
643     Matrix itransform;
644     mathIdentity(&itransform);
645     if (transform && !mathInverse(transform, &itransform)) return false;
646
647     auto halfScale = _halfScale(image->scale);
648
649     if (_compositing(surface)) {
650         if (opacity == 255) {
651             //Transformed
652             if (mathEqual(image->scale, 1.0f)) {
653                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
654                     return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, surface->blender.alpha);
655                 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
656                     return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, surface->blender.ialpha);
657                 }
658             //Transformed + Down Scaled
659             } else if (image->scale < DOWN_SCALE_TOLERANCE) {
660                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
661                     return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, surface->blender.alpha);
662                 } else  if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
663                     return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, surface->blender.ialpha);
664                 }
665             //Transformed + Up Scaled
666             } else {
667                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
668                     return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, surface->blender.alpha);
669                 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
670                     return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, surface->blender.ialpha);
671                 }
672             }
673         } else {
674             //Transformed
675             if (mathEqual(image->scale, 1.0f)) {
676                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
677                     return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, surface->blender.alpha);
678                 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
679                     return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, surface->blender.ialpha);
680                 }
681             //Transformed + Down Scaled
682             } else if (image->scale < DOWN_SCALE_TOLERANCE) {
683                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
684                     return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, surface->blender.alpha);
685                 } else  if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
686                     return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, surface->blender.ialpha);
687                 }
688             //Transformed + Up Scaled
689             } else {
690                 if (surface->compositor->method == CompositeMethod::AlphaMask) {
691                     return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, surface->blender.alpha);
692                 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
693                     return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, surface->blender.ialpha);
694                 }
695             }
696         }
697     } else {
698         if (opacity == 255) {
699             if (mathEqual(image->scale, 1.0f)) return _rasterTransformedRleRGBAImage(surface, image, &itransform);
700             else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledRleRGBAImage(surface, image, &itransform, halfScale);
701             else return _rasterUpScaledRleRGBAImage(surface, image, &itransform);
702         } else {
703             if (mathEqual(image->scale, 1.0f)) return _rasterTransformedTranslucentRleRGBAImage(surface, image, &itransform, opacity);
704             else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale);
705             else return _rasterUpScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity);
706         }
707     }
708     return false;
709 }
710
711 /************************************************************************/
712 /* RLE Scaled RGBA Image                                                */
713 /************************************************************************/
714
715 static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
716 {
717     TVGLOG("SW_ENGINE", "Scaled Masked Translucent Rle Image");
718
719     auto span = image->rle->spans;
720
721     //Center (Down-Scaled)
722     if (image->scale < DOWN_SCALE_TOLERANCE) {
723         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
724             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
725             if (sy >= image->h) continue;
726             auto dst = &surface->buffer[span->y * surface->stride + span->x];
727             auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
728             auto alpha = _multiplyAlpha(span->coverage, opacity);
729             for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
730                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
731                 if (sx >= image->w) continue;
732                 auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha);
733                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
734                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
735             }
736         }
737     //Center (Up-Scaled)
738     } else {
739         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
740             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
741             if (sy >= image->h) continue;
742             auto dst = &surface->buffer[span->y * surface->stride + span->x];
743             auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
744             auto alpha = _multiplyAlpha(span->coverage, opacity);
745             for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
746                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
747                 if (sx >= image->w) continue;
748                 auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
749                 auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
750                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
751             }
752         }
753     }
754     return true;
755 }
756
757
758 static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
759 {
760     TVGLOG("SW_ENGINE", "Scaled Masked Rle Image");
761
762     auto span = image->rle->spans;
763
764     //Center (Down-Scaled)
765     if (image->scale < DOWN_SCALE_TOLERANCE) {
766         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
767             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
768             if (sy >= image->h) continue;
769             auto dst = &surface->buffer[span->y * surface->stride + span->x];
770             auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
771             if (span->coverage == 255) {
772                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
773                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
774                     if (sx >= image->w) continue;
775                     auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
776                     *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
777                 }
778             } else {
779                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
780                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
781                     if (sx >= image->w) continue;
782                     auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage);
783                     auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
784                     *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
785                 }
786             }
787         }
788     //Center (Up-Scaled)
789     } else {
790         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
791             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
792             if (sy >= image->h) continue;
793             auto dst = &surface->buffer[span->y * surface->stride + span->x];
794             auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
795             if (span->coverage == 255) {
796                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
797                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
798                     if (sx >= image->w) continue;
799                     auto tmp = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
800                     *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
801                 }
802             } else {
803                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) {
804                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
805                     if (sx >= image->w) continue;
806                     auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
807                     auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
808                     *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
809                 }
810             }
811         }
812     }
813     return true;
814 }
815
816
817 static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
818 {
819     auto span = image->rle->spans;
820
821     //Center (Down-Scaled)
822     if (image->scale < DOWN_SCALE_TOLERANCE) {
823         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
824             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
825             if (sy >= image->h) continue;
826             auto dst = &surface->buffer[span->y * surface->stride + span->x];
827             auto alpha = _multiplyAlpha(span->coverage, opacity);
828             for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
829                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
830                 if (sx >= image->w) continue;
831                 auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha);
832                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
833             }
834         }
835     //Center (Up-Scaled)
836     } else {
837         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
838             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
839             if (sy >= image->h) continue;
840             auto dst = &surface->buffer[span->y * surface->stride + span->x];
841             auto alpha = _multiplyAlpha(span->coverage, opacity);
842             for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
843                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
844                 if (sx >= image->w) continue;
845                 auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
846                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
847             }
848         }
849     }
850     return true;
851 }
852
853
854 static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
855 {
856     auto span = image->rle->spans;
857
858     //Center (Down-Scaled)
859     if (image->scale < DOWN_SCALE_TOLERANCE) {
860         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
861             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
862             if (sy >= image->h) continue;
863             auto dst = &surface->buffer[span->y * surface->stride + span->x];
864             if (span->coverage == 255) {
865                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
866                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
867                     if (sx >= image->w) continue;
868                     auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale);
869                     *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
870                 }
871             } else {
872                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
873                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
874                     if (sx >= image->w) continue;
875                     auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage);
876                     *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
877                 }
878             }
879         }
880     //Center (Up-Scaled)
881     } else {
882         for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
883             auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23);
884             if (sy >= image->h) continue;
885             auto dst = &surface->buffer[span->y * surface->stride + span->x];
886             if (span->coverage == 255) {
887                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
888                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
889                     if (sx >= image->w) continue;
890                     auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
891                     *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
892                 }
893             } else {
894                 for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst) {
895                     auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
896                     if (sx >= image->w) continue;
897                     auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
898                     *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
899                 }
900             }
901         }
902     }
903     return true;
904 }
905
906
907 static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity)
908 {
909     Matrix itransform;
910     if (transform && !mathInverse(transform, &itransform)) return false;
911
912     auto halfScale = _halfScale(image->scale);
913
914     if (_compositing(surface)) {
915         if (opacity == 255) {
916             if (surface->compositor->method == CompositeMethod::AlphaMask) {
917                 return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.alpha);
918             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
919                 return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.ialpha);
920             }
921         } else {
922             if (surface->compositor->method == CompositeMethod::AlphaMask) {
923                 return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.alpha);
924             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
925                 return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.ialpha);
926             }
927         }
928     } else {
929         if (opacity == 255) return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity, halfScale);
930         else return _rasterScaledTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale);
931     }
932     return false;
933 }
934
935
936 /************************************************************************/
937 /* RLE Direct RGBA Image                                                */
938 /************************************************************************/
939
940 static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
941 {
942     TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
943
944     auto span = image->rle->spans;
945     auto cbuffer = surface->compositor->image.data;
946
947     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
948         auto dst = &surface->buffer[span->y * surface->stride + span->x];
949         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
950         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
951         auto alpha = _multiplyAlpha(span->coverage, opacity);
952         if (alpha == 255) {
953             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
954                 auto tmp = ALPHA_BLEND(*img, blendMethod(*cmp));
955                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
956             }
957         } else {
958             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
959                 auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(alpha, blendMethod(*cmp)));
960                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
961             }
962         }
963     }
964     return true;
965 }
966
967
968 static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t (*blendMethod)(uint32_t))
969 {
970     TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
971
972     auto span = image->rle->spans;
973     auto cbuffer = surface->compositor->image.data;
974
975     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
976         auto dst = &surface->buffer[span->y * surface->stride + span->x];
977         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
978         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
979         if (span->coverage == 255) {
980             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
981                 auto tmp = ALPHA_BLEND(*img, blendMethod(*cmp));
982                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
983             }
984         } else {
985             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) {
986                 auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
987                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
988             }
989         }
990     }
991     return true;
992 }
993
994
995 static bool _rasterDirectTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
996 {
997     auto span = image->rle->spans;
998
999     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
1000         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1001         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
1002         auto alpha = _multiplyAlpha(span->coverage, opacity);
1003         for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
1004             auto src = ALPHA_BLEND(*img, alpha);
1005             *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1006         }
1007     }
1008     return true;
1009 }
1010
1011
1012 static bool _rasterDirectRleRGBAImage(SwSurface* surface, const SwImage* image)
1013 {
1014     auto span = image->rle->spans;
1015
1016     for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
1017         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1018         auto img = image->data + (span->y + image->oy) * image->stride + (span->x + image->ox);
1019         if (span->coverage == 255) {
1020             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
1021                 *dst = *img + ALPHA_BLEND(*dst, surface->blender.ialpha(*img));
1022             }
1023         } else {
1024             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
1025                 auto src = ALPHA_BLEND(*img, span->coverage);
1026                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1027             }
1028         }
1029     }
1030     return true;
1031 }
1032
1033
1034 static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
1035 {
1036     if (_compositing(surface)) {
1037         if (opacity == 255) {
1038             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1039                 return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.alpha);
1040             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1041                 return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.ialpha);
1042             }
1043         } else {
1044             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1045                 return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.alpha);
1046             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1047                 return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.ialpha);
1048             }
1049         }
1050     } else {
1051         if (opacity == 255) return _rasterDirectRleRGBAImage(surface, image);
1052         else return _rasterDirectTranslucentRleRGBAImage(surface, image, opacity);
1053     }
1054     return false;
1055 }
1056
1057
1058 /************************************************************************/
1059 /* Transformed RGBA Image                                               */
1060 /************************************************************************/
1061
1062 static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity)
1063 {
1064     if (_compositing(surface)) {
1065         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1066             return _rasterTexmapPolygon(surface, image, transform, region, opacity, surface->blender.alpha);
1067         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1068             return _rasterTexmapPolygon(surface, image, transform, region, opacity, surface->blender.ialpha);
1069         }
1070     } else {
1071         return _rasterTexmapPolygon(surface, image, transform, region, opacity, nullptr);
1072     }
1073     return false;
1074 }
1075
1076
1077 /************************************************************************/
1078 /*Scaled RGBA Image                                                     */
1079 /************************************************************************/
1080
1081
1082 static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
1083 {
1084     TVGLOG("SW_ENGINE", "Scaled Masked Image");
1085
1086     auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
1087     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride + region.min.x);
1088
1089     // Down-Scaled
1090     if (image->scale < DOWN_SCALE_TOLERANCE) {
1091         for (auto y = region.min.y; y < region.max.y; ++y) {
1092             auto dst = dbuffer;
1093             auto cmp = cbuffer;
1094             auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
1095             for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
1096                 auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
1097                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
1098                 auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha);
1099                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1100             }
1101             dbuffer += surface->stride;
1102             cbuffer += surface->compositor->image.stride;
1103         }
1104     // Up-Scaled
1105     } else {
1106         for (auto y = region.min.y; y < region.max.y; ++y) {
1107             auto dst = dbuffer;
1108             auto cmp = cbuffer;
1109             auto sy = fabsf(y * itransform->e22 + itransform->e23);
1110             for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
1111                 auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
1112                 auto sx = fabsf(x * itransform->e11 + itransform->e13);
1113                 auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
1114                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1115             }
1116             dbuffer += surface->stride;
1117             cbuffer += surface->compositor->image.stride;
1118         }
1119     }
1120     return true;
1121 }
1122
1123
1124 static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
1125 {
1126     TVGLOG("SW_ENGINE", "Scaled Masked Image");
1127
1128     auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
1129     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride + region.min.x);
1130
1131     // Down-Scaled
1132     if (image->scale < DOWN_SCALE_TOLERANCE) {
1133         for (auto y = region.min.y; y < region.max.y; ++y) {
1134             auto dst = dbuffer;
1135             auto cmp = cbuffer;
1136             auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
1137             for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
1138                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
1139                 auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
1140                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1141             }
1142             dbuffer += surface->stride;
1143             cbuffer += surface->compositor->image.stride;
1144         }
1145     // Up-Scaled
1146     } else {
1147         for (auto y = region.min.y; y < region.max.y; ++y) {
1148             auto dst = dbuffer;
1149             auto cmp = cbuffer;
1150             auto sy = fabsf(y * itransform->e22 + itransform->e23);
1151             for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
1152                 auto sx = fabsf(x * itransform->e11 + itransform->e13);
1153                 auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
1154                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1155             }
1156             dbuffer += surface->stride;
1157             cbuffer += surface->compositor->image.stride;
1158         }
1159     }
1160     return true;
1161 }
1162
1163
1164 static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
1165 {
1166     auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
1167
1168     // Down-Scaled
1169     if (image->scale < DOWN_SCALE_TOLERANCE) {
1170         for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
1171             auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
1172             auto dst = dbuffer;
1173             for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
1174                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
1175                 auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), opacity);
1176                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1177             }
1178         }
1179     // Up-Scaled
1180     } else {
1181         for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
1182             auto sy = fabsf(y * itransform->e22 + itransform->e23);
1183             auto dst = dbuffer;
1184             for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
1185                 auto sx = fabsf(x * itransform->e11 + itransform->e13);
1186                 auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity);
1187                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1188             }
1189         }
1190     }
1191     return true;
1192 }
1193
1194
1195 static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale)
1196 {
1197     auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x);
1198
1199     // Down-Scaled
1200     if (image->scale < DOWN_SCALE_TOLERANCE) {
1201         for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
1202             auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
1203             auto dst = dbuffer;
1204             for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
1205                 auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13);
1206                 auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale);
1207                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1208             }
1209         }
1210     // Up-Scaled
1211     } else {
1212         for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
1213             auto sy = fabsf(y * itransform->e22 + itransform->e23);
1214             auto dst = dbuffer;
1215             for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
1216                 auto sx = fabsf(x * itransform->e11 + itransform->e13);
1217                 auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
1218                 *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src));
1219             }
1220         }
1221     }
1222     return true;
1223 }
1224
1225
1226 static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity)
1227 {
1228     Matrix itransform;
1229     if (transform && !mathInverse(transform, &itransform)) return false;
1230
1231     auto halfScale = _halfScale(image->scale);
1232
1233     if (_compositing(surface)) {
1234         if (opacity == 255) {
1235             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1236                 return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.alpha);
1237             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1238                 return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.ialpha);
1239             }
1240         } else {
1241             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1242                 return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.alpha);
1243             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1244                 return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.ialpha);
1245             }
1246         }
1247     } else {
1248         if (opacity == 255) return _rasterScaledRGBAImage(surface, image, &itransform, region, halfScale);
1249         else return _rasterScaledTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale);
1250     }
1251     return false;
1252 }
1253
1254
1255 /************************************************************************/
1256 /* Direct RGBA Image                                                    */
1257 /************************************************************************/
1258
1259 static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t (*blendMethod)(uint32_t))
1260 {
1261     TVGLOG("SW_ENGINE", "Direct Masked Image");
1262
1263     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1264     auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
1265     auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
1266
1267     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1268     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;   //compositor buffer
1269
1270     for (uint32_t y = 0; y < h2; ++y) {
1271         auto dst = buffer;
1272         auto cmp = cbuffer;
1273         auto src = sbuffer;
1274         for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
1275             auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1276             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1277         }
1278         buffer += surface->stride;
1279         cbuffer += surface->compositor->image.stride;
1280         sbuffer += image->stride;
1281     }
1282     return true;
1283 }
1284
1285
1286 static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
1287 {
1288     TVGLOG("SW_ENGINE", "Direct Masked Translucent Image");
1289
1290     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1291     auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
1292     auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
1293
1294     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1295     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;   //compositor buffer
1296
1297     for (uint32_t y = 0; y < h2; ++y) {
1298         auto dst = buffer;
1299         auto cmp = cbuffer;
1300         auto src = sbuffer;
1301         for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
1302             auto tmp = ALPHA_BLEND(*src, _multiplyAlpha(opacity, blendMethod(*cmp)));
1303             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1304         }
1305         buffer += surface->stride;
1306         cbuffer += surface->compositor->image.stride;
1307         sbuffer += image->stride;
1308     }
1309     return true;
1310 }
1311
1312
1313 static bool _rasterDirectTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity)
1314 {
1315     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
1316     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1317
1318     for (auto y = region.min.y; y < region.max.y; ++y) {
1319         auto dst = dbuffer;
1320         auto src = sbuffer;
1321         for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
1322             auto tmp = ALPHA_BLEND(*src, opacity);
1323             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1324         }
1325         dbuffer += surface->stride;
1326         sbuffer += image->stride;
1327     }
1328     return true;
1329 }
1330
1331
1332 static bool _rasterDirectRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region)
1333 {
1334     auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
1335     auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
1336
1337     for (auto y = region.min.y; y < region.max.y; ++y) {
1338         auto dst = dbuffer;
1339         auto src = sbuffer;
1340         for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
1341             *dst = *src + ALPHA_BLEND(*dst, surface->blender.ialpha(*src));
1342         }
1343         dbuffer += surface->stride;
1344         sbuffer += image->stride;
1345     }
1346     return true;
1347 }
1348
1349
1350 //Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent]
1351 static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity)
1352 {
1353     if (_compositing(surface)) {
1354         if (opacity == 255) {
1355             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1356                 return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.alpha);
1357             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1358                 return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.ialpha);
1359             }
1360         } else {
1361             if (surface->compositor->method == CompositeMethod::AlphaMask) {
1362                 return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.alpha);
1363             } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1364                 return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.ialpha);
1365             }
1366         }
1367     } else {
1368         if (opacity == 255) return _rasterDirectRGBAImage(surface, image, region);
1369         else return _rasterDirectTranslucentRGBAImage(surface, image, region, opacity);
1370     }
1371     return false;
1372 }
1373
1374
1375 //Blenders for the following scenarios: [RLE / Whole] * [Direct / Scaled / Transformed]
1376 static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity)
1377 {
1378     //RLE Image
1379     if (image->rle) {
1380         if (image->direct) return _directRleRGBAImage(surface, image, opacity);
1381         else if (image->scaled) return _scaledRleRGBAImage(surface, image, transform, region, opacity);
1382         //OPTIMIZE_ME: Replace with the TexMap Rasterizer
1383         else return _transformedRleRGBAImage(surface, image, transform, opacity);
1384     //Whole Image
1385     } else {
1386         if (image->direct) return _directRGBAImage(surface, image, region, opacity);
1387         else if (image->scaled) return _scaledRGBAImage(surface, image, transform, region, opacity);
1388         else return _transformedRGBAImage(surface, image, transform, region, opacity);
1389     }
1390 }
1391
1392
1393 /************************************************************************/
1394 /* Rect Linear Gradient                                                 */
1395 /************************************************************************/
1396
1397 static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1398 {
1399     if (fill->linear.len < FLT_EPSILON) return false;
1400
1401     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1402     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1403     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1404     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;
1405
1406     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1407     if (!sbuffer) return false;
1408
1409     for (uint32_t y = 0; y < h; ++y) {
1410         fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w);
1411         auto dst = buffer;
1412         auto cmp = cbuffer;
1413         auto src = sbuffer;
1414         for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
1415             auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1416             *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1417         }
1418         buffer += surface->stride;
1419         cbuffer += surface->stride;
1420     }
1421     return true;
1422 }
1423
1424
1425 static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1426 {
1427     if (fill->linear.len < FLT_EPSILON) return false;
1428
1429     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1430     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1431     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1432
1433     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1434     if (!sbuffer) return false;
1435
1436     for (uint32_t y = 0; y < h; ++y) {
1437         auto dst = buffer;
1438         fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w);
1439         for (uint32_t x = 0; x < w; ++x, ++dst) {
1440             *dst = sbuffer[x] + ALPHA_BLEND(*dst, surface->blender.ialpha(sbuffer[x]));
1441         }
1442         buffer += surface->stride;
1443     }
1444     return true;
1445 }
1446
1447
1448 static bool _rasterSolidLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1449 {
1450     if (fill->linear.len < FLT_EPSILON) return false;
1451
1452     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1453     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1454     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1455
1456     for (uint32_t y = 0; y < h; ++y) {
1457         fillFetchLinear(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, w);
1458     }
1459     return true;
1460 }
1461
1462
1463 static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1464 {
1465     if (_compositing(surface)) {
1466         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1467             return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.alpha);
1468         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1469             return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.ialpha);
1470         }
1471     } else {
1472         if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
1473         else _rasterSolidLinearGradientRect(surface, region, fill);
1474     }
1475     return false;   
1476 }
1477
1478
1479 /************************************************************************/
1480 /* Rle Linear Gradient                                                  */
1481 /************************************************************************/
1482
1483 static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1484 {
1485     if (fill->linear.len < FLT_EPSILON) return false;
1486
1487     auto span = rle->spans;
1488     auto cbuffer = surface->compositor->image.data;
1489     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1490     if (!buffer) return false;
1491
1492     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1493         fillFetchLinear(fill, buffer, span->y, span->x, span->len);
1494         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1495         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
1496         auto src = buffer;
1497         if (span->coverage == 255) {
1498             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1499                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1500                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1501             }
1502         } else {
1503             auto ialpha = 255 - span->coverage;
1504             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1505                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1506                 tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha);
1507                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1508             }
1509         }
1510     }
1511     return true;
1512 }
1513
1514
1515 static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1516 {
1517     if (fill->linear.len < FLT_EPSILON) return false;
1518
1519     auto span = rle->spans;
1520     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1521     if (!buffer) return false;
1522
1523     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1524         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1525         fillFetchLinear(fill, buffer, span->y, span->x, span->len);
1526         if (span->coverage == 255) {
1527             for (uint32_t i = 0; i < span->len; ++i, ++dst) {
1528                 *dst = buffer[i] + ALPHA_BLEND(*dst, surface->blender.ialpha(buffer[i]));
1529             }
1530         } else {
1531             for (uint32_t i = 0; i < span->len; ++i, ++dst) {
1532                 auto tmp = ALPHA_BLEND(buffer[i], span->coverage);
1533                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1534             }
1535         }
1536     }
1537     return true;
1538 }
1539
1540
1541 static bool _rasterSolidLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1542 {
1543     if (fill->linear.len < FLT_EPSILON) return false;
1544
1545     auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1546     if (!buf) return false;
1547
1548     auto span = rle->spans;
1549
1550     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1551         if (span->coverage == 255) {
1552             fillFetchLinear(fill, surface->buffer + span->y * surface->stride + span->x, span->y, span->x, span->len);
1553         } else {
1554             fillFetchLinear(fill, buf, span->y, span->x, span->len);
1555             auto dst = &surface->buffer[span->y * surface->stride + span->x];
1556             for (uint32_t i = 0; i < span->len; ++i) {
1557                 dst[i] = INTERPOLATE(span->coverage, buf[i], dst[i]);
1558             }
1559         }
1560     }
1561     return true;
1562 }
1563
1564
1565 static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1566 {
1567     if (!rle) return false;
1568
1569     if (_compositing(surface)) {
1570         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1571             return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.alpha);
1572         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1573             return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.ialpha);
1574         }
1575     } else {
1576         if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
1577         else return _rasterSolidLinearGradientRle(surface, rle, fill);
1578     }
1579     return false;
1580 }
1581
1582
1583 /************************************************************************/
1584 /* Rect Radial Gradient                                                 */
1585 /************************************************************************/
1586
1587 static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1588 {
1589     if (fill->radial.a < FLT_EPSILON) return false;
1590
1591     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1592     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1593     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1594     auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x;
1595
1596     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1597     if (!sbuffer) return false;
1598
1599     for (uint32_t y = 0; y < h; ++y) {
1600         fillFetchRadial(fill, sbuffer, region.min.y + y, region.min.x, w);
1601         auto dst = buffer;
1602         auto cmp = cbuffer;
1603         auto src = sbuffer;
1604         for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) {
1605              auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1606              *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1607         }
1608         buffer += surface->stride;
1609         cbuffer += surface->stride;
1610     }
1611     return true;
1612 }
1613
1614
1615 static bool _rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1616 {
1617     if (fill->radial.a < FLT_EPSILON) return false;
1618
1619     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1620     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1621     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1622
1623     auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
1624     if (!sbuffer) return false;
1625
1626     for (uint32_t y = 0; y < h; ++y) {
1627         auto dst = buffer;
1628         fillFetchRadial(fill, sbuffer, region.min.y + y, region.min.x, w);
1629         for (uint32_t x = 0; x < w; ++x, ++dst) {
1630             *dst = sbuffer[x] + ALPHA_BLEND(*dst, surface->blender.ialpha(sbuffer[x]));
1631         }
1632         buffer += surface->stride;
1633     }
1634     return true;
1635 }
1636
1637
1638 static bool _rasterSolidRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1639 {
1640     if (fill->radial.a < FLT_EPSILON) return false;
1641
1642     auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
1643     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
1644     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
1645
1646     for (uint32_t y = 0; y < h; ++y) {
1647         auto dst = &buffer[y * surface->stride];
1648         fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w);
1649     }
1650     return true;
1651 }
1652
1653
1654 static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
1655 {
1656     if (_compositing(surface)) {
1657         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1658             return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.alpha);
1659         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1660             return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.ialpha);
1661         }
1662     } else {
1663         if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
1664         else return _rasterSolidRadialGradientRect(surface, region, fill);
1665     }
1666     return false;
1667 }
1668
1669
1670 /************************************************************************/
1671 /* RLE Radial Gradient                                                  */
1672 /************************************************************************/
1673
1674 static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blendMethod)(uint32_t))
1675 {
1676     if (fill->radial.a < FLT_EPSILON) return false;
1677
1678     auto span = rle->spans;
1679     auto cbuffer = surface->compositor->image.data;
1680     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1681     if (!buffer) return false;
1682
1683     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1684         fillFetchRadial(fill, buffer, span->y, span->x, span->len);
1685         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1686         auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
1687         auto src = buffer;
1688         if (span->coverage == 255) {
1689             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1690                 auto tmp = ALPHA_BLEND(*src, blendMethod(*cmp));
1691                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1692             }
1693         } else {
1694             for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) {
1695                 auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, blendMethod(*cmp)), *dst);
1696                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1697             }
1698         }
1699     }
1700     return true;
1701 }
1702
1703
1704 static bool _rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1705 {
1706     if (fill->radial.a < FLT_EPSILON) return false;
1707
1708     auto span = rle->spans;
1709     auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1710     if (!buffer) return false;
1711
1712     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1713         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1714         fillFetchRadial(fill, buffer, span->y, span->x, span->len);
1715         if (span->coverage == 255) {
1716             for (uint32_t i = 0; i < span->len; ++i, ++dst) {
1717                 *dst = buffer[i] + ALPHA_BLEND(*dst, surface->blender.ialpha(buffer[i]));
1718             }
1719         } else {
1720            for (uint32_t i = 0; i < span->len; ++i, ++dst) {
1721                 auto tmp = ALPHA_BLEND(buffer[i], span->coverage);
1722                 *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp));
1723             }
1724         }
1725     }
1726     return true;
1727 }
1728
1729
1730 static bool _rasterSolidRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1731 {
1732     if (fill->radial.a < FLT_EPSILON) return false;
1733
1734     auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
1735     if (!buf) return false;
1736
1737     auto span = rle->spans;
1738
1739     for (uint32_t i = 0; i < rle->size; ++i, ++span) {
1740         auto dst = &surface->buffer[span->y * surface->stride + span->x];
1741         if (span->coverage == 255) {
1742             fillFetchRadial(fill, dst, span->y, span->x, span->len);
1743         } else {
1744             fillFetchRadial(fill, buf, span->y, span->x, span->len);
1745             auto ialpha = 255 - span->coverage;
1746             for (uint32_t i = 0; i < span->len; ++i, ++dst) {
1747                 *dst = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(*dst, ialpha);
1748             }
1749         }
1750     }
1751     return true;
1752 }
1753
1754
1755 static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
1756 {
1757     if (!rle) return false;
1758
1759     if (_compositing(surface)) {
1760         if (surface->compositor->method == CompositeMethod::AlphaMask) {
1761             return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.alpha);
1762         } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
1763             return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.ialpha);
1764         }
1765     } else {
1766         if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
1767         else return _rasterSolidRadialGradientRle(surface, rle, fill);
1768     }
1769     return false;
1770 }
1771
1772
1773 /************************************************************************/
1774 /* External Class Implementation                                        */
1775 /************************************************************************/
1776
1777 void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
1778 {
1779 #if defined(THORVG_AVX_VECTOR_SUPPORT)
1780     avxRasterRGBA32(dst, val, offset, len);
1781 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
1782     neonRasterRGBA32(dst, val, offset, len);
1783 #else
1784     cRasterRGBA32(dst, val, offset, len);
1785 #endif
1786 }
1787
1788
1789 bool rasterCompositor(SwSurface* surface)
1790 {
1791     if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) {
1792         surface->blender.join = _abgrJoin;
1793     } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
1794         surface->blender.join = _argbJoin;
1795     } else {
1796         //What Color Space ???
1797         return false;
1798     }
1799     surface->blender.alpha = _colorAlpha;
1800     surface->blender.ialpha = _colorInvAlpha;
1801
1802     return true;
1803 }
1804
1805
1806 bool rasterClear(SwSurface* surface)
1807 {
1808     if (!surface || !surface->buffer || surface->stride <= 0 || surface->w <= 0 || surface->h <= 0) return false;
1809
1810     if (surface->w == surface->stride) {
1811         rasterRGBA32(surface->buffer, 0x00000000, 0, surface->w * surface->h);
1812     } else {
1813         for (uint32_t i = 0; i < surface->h; i++) {
1814             rasterRGBA32(surface->buffer + surface->stride * i, 0x00000000, 0, surface->w);
1815         }
1816     }
1817     return true;
1818 }
1819
1820
1821 void rasterUnpremultiply(SwSurface* surface)
1822 {
1823     //TODO: Create simd avx and neon version
1824     for (uint32_t y = 0; y < surface->h; y++) {
1825         auto buffer = surface->buffer + surface->stride * y;
1826         for (uint32_t x = 0; x < surface->w; ++x) {
1827             uint8_t a = buffer[x] >> 24;
1828             if (a == 255) {
1829                 continue;
1830             } else if (a == 0) {
1831                 buffer[x] = 0x00ffffff;
1832             } else {
1833                 uint16_t r = ((buffer[x] >> 8) & 0xff00) / a;
1834                 uint16_t g = ((buffer[x]) & 0xff00) / a;
1835                 uint16_t b = ((buffer[x] << 8) & 0xff00) / a;
1836                 if (r > 0xff) r = 0xff;
1837                 if (g > 0xff) g = 0xff;
1838                 if (b > 0xff) b = 0xff;
1839                 buffer[x] = (a << 24) | (r << 16) | (g << 8) | (b);
1840             }
1841         }
1842     }
1843 }
1844
1845
1846 bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id)
1847 {
1848     if (!shape->fill) return false;
1849
1850     if (shape->fastTrack) {
1851         if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRect(surface, shape->bbox, shape->fill);
1852         else if (id == TVG_CLASS_ID_RADIAL)return _rasterRadialGradientRect(surface, shape->bbox, shape->fill);
1853     } else {
1854         if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->rle, shape->fill);
1855         else if (id == TVG_CLASS_ID_RADIAL) return _rasterRadialGradientRle(surface, shape->rle, shape->fill);
1856     }
1857     return false;
1858 }
1859
1860
1861 bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id)
1862 {
1863     if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false;
1864
1865     if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1866     else if (id == TVG_CLASS_ID_RADIAL) return _rasterRadialGradientRle(surface, shape->strokeRle, shape->stroke->fill);
1867
1868     return false;
1869 }
1870
1871
1872 bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
1873 {
1874     if (a < 255) {
1875         r = _multiplyAlpha(r, a);
1876         g = _multiplyAlpha(g, a);
1877         b = _multiplyAlpha(b, a);
1878     }
1879
1880     auto color = surface->blender.join(r, g, b, a);
1881
1882     if (shape->fastTrack) return _rasterRect(surface, shape->bbox, color, a);
1883     else return _rasterRle(surface, shape->rle, color, a);
1884 }
1885
1886
1887 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
1888 {
1889     if (a < 255) {
1890         r = _multiplyAlpha(r, a);
1891         g = _multiplyAlpha(g, a);
1892         b = _multiplyAlpha(b, a);
1893     }
1894
1895     auto color = surface->blender.join(r, g, b, a);
1896
1897     return _rasterRle(surface, shape->strokeRle, color, a);
1898 }
1899
1900
1901 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity)
1902 {
1903     //Verify Boundary
1904     if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= surface->w || bbox.min.y >= surface->h) return false;
1905
1906     //TOOD: switch (image->format)
1907     //TODO: case: _rasterRGBImage()
1908     //TODO: case: _rasterGrayscaleImage()
1909     //TODO: case: _rasterAlphaImage()
1910
1911     return _rasterRGBAImage(surface, image, transform, bbox, opacity);
1912 }