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