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