1 | /* |
2 | * Copyright (c) 2020 - 2023 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 | #ifndef _TVG_RENDER_H_ |
24 | #define _TVG_RENDER_H_ |
25 | |
26 | #include "tvgCommon.h" |
27 | #include "tvgArray.h" |
28 | |
29 | namespace tvg |
30 | { |
31 | |
32 | using RenderData = void*; |
33 | using pixel_t = uint32_t; |
34 | |
35 | enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; |
36 | |
37 | struct Surface; |
38 | |
39 | enum ColorSpace |
40 | { |
41 | ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. |
42 | ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. |
43 | ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. |
44 | ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. |
45 | Grayscale8, //One single channel data. |
46 | Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace. |
47 | }; |
48 | |
49 | struct Surface |
50 | { |
51 | union { |
52 | pixel_t* data; //system based data pointer |
53 | uint32_t* buf32; //for explicit 32bits channels |
54 | uint8_t* buf8; //for explicit 8bits grayscale |
55 | }; |
56 | uint32_t stride; |
57 | uint32_t w, h; |
58 | ColorSpace cs; |
59 | uint8_t channelSize; |
60 | |
61 | bool premultiplied; //Alpha-premultiplied |
62 | bool owner; //Only owner could modify the buffer |
63 | }; |
64 | |
65 | struct Compositor |
66 | { |
67 | CompositeMethod method; |
68 | uint8_t opacity; |
69 | }; |
70 | |
71 | struct RenderMesh |
72 | { |
73 | Polygon* triangles = nullptr; |
74 | uint32_t triangleCnt = 0; |
75 | |
76 | ~RenderMesh() |
77 | { |
78 | free(triangles); |
79 | } |
80 | }; |
81 | |
82 | struct RenderRegion |
83 | { |
84 | int32_t x, y, w, h; |
85 | |
86 | void intersect(const RenderRegion& rhs) |
87 | { |
88 | auto x1 = x + w; |
89 | auto y1 = y + h; |
90 | auto x2 = rhs.x + rhs.w; |
91 | auto y2 = rhs.y + rhs.h; |
92 | |
93 | x = (x > rhs.x) ? x : rhs.x; |
94 | y = (y > rhs.y) ? y : rhs.y; |
95 | w = ((x1 < x2) ? x1 : x2) - x; |
96 | h = ((y1 < y2) ? y1 : y2) - y; |
97 | |
98 | if (w < 0) w = 0; |
99 | if (h < 0) h = 0; |
100 | } |
101 | |
102 | void add(const RenderRegion& rhs) |
103 | { |
104 | if (rhs.x < x) { |
105 | w += (x - rhs.x); |
106 | x = rhs.x; |
107 | } |
108 | if (rhs.y < y) { |
109 | h += (y - rhs.y); |
110 | y = rhs.y; |
111 | } |
112 | if (rhs.x + rhs.w > x + w) w = (rhs.x + rhs.w) - x; |
113 | if (rhs.y + rhs.h > y + h) h = (rhs.y + rhs.h) - y; |
114 | } |
115 | }; |
116 | |
117 | struct RenderTransform |
118 | { |
119 | Matrix m; //3x3 Matrix Elements |
120 | float x = 0.0f; |
121 | float y = 0.0f; |
122 | float degree = 0.0f; //rotation degree |
123 | float scale = 1.0f; //scale factor |
124 | bool overriding = false; //user transform? |
125 | |
126 | bool update(); |
127 | void override(const Matrix& m); |
128 | |
129 | RenderTransform(); |
130 | RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); |
131 | }; |
132 | |
133 | struct RenderStroke |
134 | { |
135 | float width = 0.0f; |
136 | uint8_t color[4] = {0, 0, 0, 0}; |
137 | Fill *fill = nullptr; |
138 | float* dashPattern = nullptr; |
139 | uint32_t dashCnt = 0; |
140 | StrokeCap cap = StrokeCap::Square; |
141 | StrokeJoin join = StrokeJoin::Bevel; |
142 | float miterlimit = 4.0f; |
143 | bool strokeFirst = false; |
144 | |
145 | ~RenderStroke() |
146 | { |
147 | free(dashPattern); |
148 | delete(fill); |
149 | } |
150 | }; |
151 | |
152 | struct RenderShape |
153 | { |
154 | struct |
155 | { |
156 | Array<PathCommand> cmds; |
157 | Array<Point> pts; |
158 | } path; |
159 | |
160 | Fill *fill = nullptr; |
161 | RenderStroke *stroke = nullptr; |
162 | uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a |
163 | FillRule rule = FillRule::Winding; |
164 | |
165 | ~RenderShape() |
166 | { |
167 | delete(fill); |
168 | delete(stroke); |
169 | } |
170 | |
171 | void fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const |
172 | { |
173 | if (r) *r = color[0]; |
174 | if (g) *g = color[1]; |
175 | if (b) *b = color[2]; |
176 | if (a) *a = color[3]; |
177 | } |
178 | |
179 | float strokeWidth() const |
180 | { |
181 | if (!stroke) return 0; |
182 | return stroke->width; |
183 | } |
184 | |
185 | bool strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const |
186 | { |
187 | if (!stroke) return false; |
188 | |
189 | if (r) *r = stroke->color[0]; |
190 | if (g) *g = stroke->color[1]; |
191 | if (b) *b = stroke->color[2]; |
192 | if (a) *a = stroke->color[3]; |
193 | |
194 | return true; |
195 | } |
196 | |
197 | const Fill* strokeFill() const |
198 | { |
199 | if (!stroke) return nullptr; |
200 | return stroke->fill; |
201 | } |
202 | |
203 | uint32_t strokeDash(const float** dashPattern) const |
204 | { |
205 | if (!stroke) return 0; |
206 | if (dashPattern) *dashPattern = stroke->dashPattern; |
207 | return stroke->dashCnt; |
208 | } |
209 | |
210 | StrokeCap strokeCap() const |
211 | { |
212 | if (!stroke) return StrokeCap::Square; |
213 | return stroke->cap; |
214 | } |
215 | |
216 | StrokeJoin strokeJoin() const |
217 | { |
218 | if (!stroke) return StrokeJoin::Bevel; |
219 | return stroke->join; |
220 | } |
221 | |
222 | float strokeMiterlimit() const |
223 | { |
224 | if (!stroke) return 4.0f; |
225 | |
226 | return stroke->miterlimit;; |
227 | } |
228 | }; |
229 | |
230 | class RenderMethod |
231 | { |
232 | public: |
233 | virtual ~RenderMethod() {} |
234 | virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0; |
235 | virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0; |
236 | virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0; |
237 | virtual bool preRender() = 0; |
238 | virtual bool renderShape(RenderData data) = 0; |
239 | virtual bool renderImage(RenderData data) = 0; |
240 | virtual bool postRender() = 0; |
241 | virtual bool dispose(RenderData data) = 0; |
242 | virtual RenderRegion region(RenderData data) = 0; |
243 | virtual RenderRegion viewport() = 0; |
244 | virtual bool viewport(const RenderRegion& vp) = 0; |
245 | virtual bool blend(BlendMethod method) = 0; |
246 | virtual ColorSpace colorSpace() = 0; |
247 | |
248 | virtual bool clear() = 0; |
249 | virtual bool sync() = 0; |
250 | |
251 | virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0; |
252 | virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) = 0; |
253 | virtual bool endComposite(Compositor* cmp) = 0; |
254 | }; |
255 | |
256 | static inline bool MASK_OPERATION(CompositeMethod method) |
257 | { |
258 | switch(method) { |
259 | case CompositeMethod::AlphaMask: |
260 | case CompositeMethod::InvAlphaMask: |
261 | case CompositeMethod::LumaMask: |
262 | case CompositeMethod::InvLumaMask: |
263 | return false; |
264 | case CompositeMethod::AddMask: |
265 | case CompositeMethod::SubtractMask: |
266 | case CompositeMethod::IntersectMask: |
267 | case CompositeMethod::DifferenceMask: |
268 | return true; |
269 | default: |
270 | TVGERR("COMMON" , "Unsupported Composite Size! = %d" , (int)method); |
271 | return false; |
272 | } |
273 | } |
274 | |
275 | static inline uint8_t CHANNEL_SIZE(ColorSpace cs) |
276 | { |
277 | switch(cs) { |
278 | case ColorSpace::ABGR8888: |
279 | case ColorSpace::ABGR8888S: |
280 | case ColorSpace::ARGB8888: |
281 | case ColorSpace::ARGB8888S: |
282 | return sizeof(uint32_t); |
283 | case ColorSpace::Grayscale8: |
284 | return sizeof(uint8_t); |
285 | case ColorSpace::Unsupported: |
286 | default: |
287 | TVGERR("SW_ENGINE" , "Unsupported Channel Size! = %d" , (int)cs); |
288 | return 0; |
289 | } |
290 | } |
291 | |
292 | static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method) |
293 | { |
294 | switch(method) { |
295 | case CompositeMethod::AlphaMask: |
296 | case CompositeMethod::InvAlphaMask: |
297 | return ColorSpace::Grayscale8; |
298 | case CompositeMethod::LumaMask: |
299 | case CompositeMethod::InvLumaMask: |
300 | case CompositeMethod::AddMask: |
301 | case CompositeMethod::SubtractMask: |
302 | case CompositeMethod::IntersectMask: |
303 | case CompositeMethod::DifferenceMask: |
304 | return renderer.colorSpace(); |
305 | default: |
306 | TVGERR("COMMON" , "Unsupported Composite Size! = %d" , (int)method); |
307 | return ColorSpace::Unsupported; |
308 | } |
309 | } |
310 | |
311 | static inline uint8_t MULTIPLY(uint8_t c, uint8_t a) |
312 | { |
313 | return (((c) * (a) + 0xff) >> 8); |
314 | } |
315 | |
316 | |
317 | } |
318 | |
319 | #endif //_TVG_RENDER_H_ |
320 | |