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