1 /*
2  * Copyright (c) 2021 - 2024 the ThorVG project. 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 
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25 
26 template<typename PIXEL_T>
cRasterPixels(PIXEL_T * dst,PIXEL_T val,uint32_t offset,int32_t len)27 static void inline cRasterPixels(PIXEL_T* dst, PIXEL_T val, uint32_t offset, int32_t len)
28 {
29     dst += offset;
30 
31     //fix the misaligned memory
32     auto alignOffset = (long long) dst % 8;
33     if (alignOffset > 0) {
34         if (sizeof(PIXEL_T) == 4) alignOffset /= 4;
35         else if (sizeof(PIXEL_T) == 1) alignOffset = 8 - alignOffset;
36         while (alignOffset > 0 && len > 0) {
37             *dst++ = val;
38             --len;
39             --alignOffset;
40         }
41     }
42 
43     //64bits faster clear
44     if ((sizeof(PIXEL_T) == 4)) {
45         auto val64 = (uint64_t(val) << 32) | uint64_t(val);
46         while (len > 1) {
47             *reinterpret_cast<uint64_t*>(dst) = val64;
48             len -= 2;
49             dst += 2;
50         }
51     } else if (sizeof(PIXEL_T) == 1) {
52         auto val32 = (uint32_t(val) << 24) | (uint32_t(val) << 16) | (uint32_t(val) << 8) | uint32_t(val);
53         auto val64 = (uint64_t(val32) << 32) | val32;
54         while (len > 7) {
55             *reinterpret_cast<uint64_t*>(dst) = val64;
56             len -= 8;
57             dst += 8;
58         }
59     }
60 
61     //leftovers
62     while (len--) *dst++ = val;
63 }
64 
65 
cRasterTranslucentRle(SwSurface * surface,const SwRle * rle,uint8_t r,uint8_t g,uint8_t b,uint8_t a)66 static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
67 {
68     auto span = rle->spans;
69 
70     //32bit channels
71     if (surface->channelSize == sizeof(uint32_t)) {
72         auto color = surface->join(r, g, b, a);
73         uint32_t src;
74         for (uint32_t i = 0; i < rle->size; ++i, ++span) {
75             auto dst = &surface->buf32[span->y * surface->stride + span->x];
76             if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
77             else src = color;
78             auto ialpha = IA(src);
79             for (uint32_t x = 0; x < span->len; ++x, ++dst) {
80                 *dst = src + ALPHA_BLEND(*dst, ialpha);
81             }
82         }
83     //8bit grayscale
84     } else if (surface->channelSize == sizeof(uint8_t)) {
85         uint8_t src;
86         for (uint32_t i = 0; i < rle->size; ++i, ++span) {
87             auto dst = &surface->buf8[span->y * surface->stride + span->x];
88             if (span->coverage < 255) src = MULTIPLY(span->coverage, a);
89             else src = a;
90             auto ialpha = ~a;
91             for (uint32_t x = 0; x < span->len; ++x, ++dst) {
92                 *dst = src + MULTIPLY(*dst, ialpha);
93             }
94         }
95     }
96     return true;
97 }
98 
99 
cRasterTranslucentRect(SwSurface * surface,const SwBBox & region,uint8_t r,uint8_t g,uint8_t b,uint8_t a)100 static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
101 {
102     auto h = static_cast<uint32_t>(region.max.y - region.min.y);
103     auto w = static_cast<uint32_t>(region.max.x - region.min.x);
104 
105     //32bits channels
106     if (surface->channelSize == sizeof(uint32_t)) {
107         auto color = surface->join(r, g, b, a);
108         auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
109         auto ialpha = 255 - a;
110         for (uint32_t y = 0; y < h; ++y) {
111             auto dst = &buffer[y * surface->stride];
112             for (uint32_t x = 0; x < w; ++x, ++dst) {
113                 *dst = color + ALPHA_BLEND(*dst, ialpha);
114             }
115         }
116     //8bit grayscale
117     } else if (surface->channelSize == sizeof(uint8_t)) {
118         auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
119         auto ialpha = ~a;
120         for (uint32_t y = 0; y < h; ++y) {
121             auto dst = &buffer[y * surface->stride];
122             for (uint32_t x = 0; x < w; ++x, ++dst) {
123                 *dst = a + MULTIPLY(*dst, ialpha);
124             }
125         }
126     }
127     return true;
128 }
129 
130 
cRasterABGRtoARGB(RenderSurface * surface)131 static bool inline cRasterABGRtoARGB(RenderSurface* surface)
132 {
133     TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB [Size: %d x %d]", surface->w, surface->h);
134 
135     //64bits faster converting
136     if (surface->w % 2 == 0) {
137         auto buffer = reinterpret_cast<uint64_t*>(surface->buf32);
138         for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride / 2) {
139             auto dst = buffer;
140             for (uint32_t x = 0; x < surface->w / 2; ++x, ++dst) {
141                 auto c = *dst;
142                 //flip Blue, Red channels
143                 *dst = (c & 0xff000000ff000000) + ((c & 0x00ff000000ff0000) >> 16) + (c & 0x0000ff000000ff00) + ((c & 0x000000ff000000ff) << 16);
144             }
145         }
146     //default converting
147     } else {
148         auto buffer = surface->buf32;
149         for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) {
150             auto dst = buffer;
151             for (uint32_t x = 0; x < surface->w; ++x, ++dst) {
152                 auto c = *dst;
153                 //flip Blue, Red channels
154                 *dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16);
155             }
156         }
157     }
158     return true;
159 }
160 
161 
cRasterARGBtoABGR(RenderSurface * surface)162 static bool inline cRasterARGBtoABGR(RenderSurface* surface)
163 {
164     //exactly same with ABGRtoARGB
165     return cRasterABGRtoARGB(surface);
166 }
167 
168 #endif /* LV_USE_THORVG_INTERNAL */
169 
170