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