1 | // [Blend2D] |
2 | // 2D Vector Graphics Powered by a JIT Compiler. |
3 | // |
4 | // [License] |
5 | // Zlib - See LICENSE.md file in the package. |
6 | |
7 | #ifndef BLEND2D_BLCONTEXT_H |
8 | #define BLEND2D_BLCONTEXT_H |
9 | |
10 | #include "./blfont.h" |
11 | #include "./blgeometry.h" |
12 | #include "./blimage.h" |
13 | #include "./blmatrix.h" |
14 | #include "./blpath.h" |
15 | #include "./blrgba.h" |
16 | #include "./blregion.h" |
17 | #include "./blvariant.h" |
18 | |
19 | //! \addtogroup blend2d_api_rendering |
20 | //! \{ |
21 | |
22 | // ============================================================================ |
23 | // [Constants] |
24 | // ============================================================================ |
25 | |
26 | //! Rendering context type. |
27 | BL_DEFINE_ENUM(BLContextType) { |
28 | //! No rendering context. |
29 | BL_CONTEXT_TYPE_NONE = 0, |
30 | //! Dummy rendering context. |
31 | BL_CONTEXT_TYPE_DUMMY = 1, |
32 | |
33 | /* |
34 | //! Proxy rendering context. |
35 | BL_CONTEXT_TYPE_PROXY = 2, |
36 | */ |
37 | |
38 | //! Software-accelerated rendering context. |
39 | BL_CONTEXT_TYPE_RASTER = 3, |
40 | |
41 | //! Count of rendering context types. |
42 | BL_CONTEXT_TYPE_COUNT = 4 |
43 | }; |
44 | |
45 | //! Rendering context hint. |
46 | BL_DEFINE_ENUM(BLContextHint) { |
47 | //! Rendering quality. |
48 | BL_CONTEXT_HINT_RENDERING_QUALITY = 0, |
49 | //! Gradient quality. |
50 | BL_CONTEXT_HINT_GRADIENT_QUALITY = 1, |
51 | //! Pattern quality. |
52 | BL_CONTEXT_HINT_PATTERN_QUALITY = 2, |
53 | |
54 | //! Count of rendering context hints. |
55 | BL_CONTEXT_HINT_COUNT = 8 |
56 | }; |
57 | |
58 | //! Describes a rendering operation type - fill or stroke. |
59 | //! |
60 | //! The rendering context allows to get and set fill & stroke options directly |
61 | //! or via "style" functions that take the rendering operation type (`opType`) |
62 | //! and dispatch the call to the right function. |
63 | BL_DEFINE_ENUM(BLContextOpType) { |
64 | //! Fill operation type. |
65 | BL_CONTEXT_OP_TYPE_FILL = 0, |
66 | //! Stroke operation type. |
67 | BL_CONTEXT_OP_TYPE_STROKE = 1, |
68 | |
69 | //! Count of rendering operations. |
70 | BL_CONTEXT_OP_TYPE_COUNT = 2 |
71 | }; |
72 | |
73 | //! Rendering context flush-flags, use with `BLContext::flush()`. |
74 | BL_DEFINE_ENUM(BLContextFlushFlags) { |
75 | //! Wait for completion (will block). |
76 | BL_CONTEXT_FLUSH_SYNC = 0x80000000u |
77 | }; |
78 | |
79 | //! Rendering context create-flags. |
80 | BL_DEFINE_ENUM(BLContextCreateFlags) { |
81 | //! When creating an asynchronous rendering context that uses threads for |
82 | //! rendering, the rendering context can sometimes allocate less threads |
83 | //! than specified if the built-in thread-pool doesn't have enough threads |
84 | //! available. This flag will force the thread-pool to override the thread |
85 | //! limit temporarily to fulfill the thread count requirement. |
86 | //! |
87 | //! \note This flag is ignored if `BLContextCreateInfo::threadCount == 0`. |
88 | BL_CONTEXT_CREATE_FLAG_FORCE_THREADS = 0x00000001u, |
89 | |
90 | //! Fallback to synchronous rendering in case that acquiring threads from |
91 | //! thread-pool failed. This flag only makes sense when asynchronous mode |
92 | //! was specified by having non-zero thread count. In that case if the |
93 | //! rendering context fails to acquire at least one thread it would fallback |
94 | //! to synchronous mode instead. |
95 | //! |
96 | //! \note This flag is ignored if `BLContextCreateInfo::threadCount == 0`. |
97 | BL_CONTEXT_CREATE_FLAG_FALLBACK_TO_SYNC = 0x00000002u, |
98 | |
99 | //! If this flag is specified and asynchronous rendering is enabled then |
100 | //! the context would create its own isolated thread-pool, which is useful |
101 | //! for debugging purposes. |
102 | //! |
103 | //! Do not use this flag in production as rendering contexts with isolated |
104 | //! thread-pool have to create and destroy all threads they use. This flag |
105 | //! is only useful for testing, debugging, and isolated benchmarking. |
106 | BL_CONTEXT_CREATE_FLAG_ISOLATED_THREADS = 0x00000010u, |
107 | |
108 | //! If this flag is specified and JIT pipeline generation enabled then the |
109 | //! rendering context would create its own isolated JIT runtime. which is |
110 | //! useful for debugging purposes. This flag will be ignored if JIT pipeline |
111 | //! generation is either not supported or was disabled by other flags. |
112 | //! |
113 | //! Do not use this flag in production as rendering contexts with isolated |
114 | //! JIT runtime do not use global pipeline cache, that's it, after the |
115 | //! rendering context is destroyed the JIT runtime is destroyed with it with |
116 | //! all compiled pipelines. This flag is only useful for testing, debugging, |
117 | //! and isolated benchmarking. |
118 | BL_CONTEXT_CREATE_FLAG_ISOLATED_JIT = 0x00000020u, |
119 | |
120 | //! Override CPU features when creating isolated context. |
121 | BL_CONTEXT_CREATE_FLAG_OVERRIDE_CPU_FEATURES = 0x00000040u |
122 | }; |
123 | |
124 | //! Clip mode. |
125 | BL_DEFINE_ENUM(BLClipMode) { |
126 | //! Clipping to a rectangle that is aligned to the pixel grid. |
127 | BL_CLIP_MODE_ALIGNED_RECT = 0, |
128 | //! Clipping to a rectangle that is not aligned to pixel grid. |
129 | BL_CLIP_MODE_UNALIGNED_RECT = 1, |
130 | //! Clipping to a non-rectangular area that is defined by using mask. |
131 | BL_CLIP_MODE_MASK = 2, |
132 | |
133 | //! Count of clip modes. |
134 | BL_CLIP_MODE_COUNT = 3 |
135 | }; |
136 | |
137 | //! Composition & blending operator. |
138 | BL_DEFINE_ENUM(BLCompOp) { |
139 | //! Source-over [default]. |
140 | BL_COMP_OP_SRC_OVER = 0, |
141 | //! Source-copy. |
142 | BL_COMP_OP_SRC_COPY = 1, |
143 | //! Source-in. |
144 | BL_COMP_OP_SRC_IN = 2, |
145 | //! Source-out. |
146 | BL_COMP_OP_SRC_OUT = 3, |
147 | //! Source-atop. |
148 | BL_COMP_OP_SRC_ATOP = 4, |
149 | //! Destination-over. |
150 | BL_COMP_OP_DST_OVER = 5, |
151 | //! Destination-copy [nop]. |
152 | BL_COMP_OP_DST_COPY = 6, |
153 | //! Destination-in. |
154 | BL_COMP_OP_DST_IN = 7, |
155 | //! Destination-out. |
156 | BL_COMP_OP_DST_OUT = 8, |
157 | //! Destination-atop. |
158 | BL_COMP_OP_DST_ATOP = 9, |
159 | //! Xor. |
160 | BL_COMP_OP_XOR = 10, |
161 | //! Clear. |
162 | BL_COMP_OP_CLEAR = 11, |
163 | //! Plus. |
164 | BL_COMP_OP_PLUS = 12, |
165 | //! Minus. |
166 | BL_COMP_OP_MINUS = 13, |
167 | //! Multiply. |
168 | BL_COMP_OP_MULTIPLY = 14, |
169 | //! Screen. |
170 | BL_COMP_OP_SCREEN = 15, |
171 | //! Overlay. |
172 | BL_COMP_OP_OVERLAY = 16, |
173 | //! Darken. |
174 | BL_COMP_OP_DARKEN = 17, |
175 | //! Lighten. |
176 | BL_COMP_OP_LIGHTEN = 18, |
177 | //! Color dodge. |
178 | BL_COMP_OP_COLOR_DODGE = 19, |
179 | //! Color burn. |
180 | BL_COMP_OP_COLOR_BURN = 20, |
181 | //! Linear burn. |
182 | BL_COMP_OP_LINEAR_BURN = 21, |
183 | //! Linear light. |
184 | BL_COMP_OP_LINEAR_LIGHT = 22, |
185 | //! Pin light. |
186 | BL_COMP_OP_PIN_LIGHT = 23, |
187 | //! Hard-light. |
188 | BL_COMP_OP_HARD_LIGHT = 24, |
189 | //! Soft-light. |
190 | BL_COMP_OP_SOFT_LIGHT = 25, |
191 | //! Difference. |
192 | BL_COMP_OP_DIFFERENCE = 26, |
193 | //! Exclusion. |
194 | BL_COMP_OP_EXCLUSION = 27, |
195 | |
196 | //! Count of composition & blending operators. |
197 | BL_COMP_OP_COUNT = 28 |
198 | }; |
199 | |
200 | //! Gradient rendering quality. |
201 | BL_DEFINE_ENUM(BLGradientQuality) { |
202 | //! Nearest neighbor. |
203 | BL_GRADIENT_QUALITY_NEAREST = 0, |
204 | |
205 | //! Count of gradient quality options. |
206 | BL_GRADIENT_QUALITY_COUNT = 1 |
207 | }; |
208 | |
209 | //! Pattern quality. |
210 | BL_DEFINE_ENUM(BLPatternQuality) { |
211 | //! Nearest neighbor. |
212 | BL_PATTERN_QUALITY_NEAREST = 0, |
213 | //! Bilinear. |
214 | BL_PATTERN_QUALITY_BILINEAR = 1, |
215 | |
216 | //! Count of pattern quality options. |
217 | BL_PATTERN_QUALITY_COUNT = 2 |
218 | }; |
219 | |
220 | //! Rendering quality. |
221 | BL_DEFINE_ENUM(BLRenderingQuality) { |
222 | //! Render using anti-aliasing. |
223 | BL_RENDERING_QUALITY_ANTIALIAS = 0, |
224 | |
225 | //! Count of rendering quality options. |
226 | BL_RENDERING_QUALITY_COUNT = 1 |
227 | }; |
228 | |
229 | // ============================================================================ |
230 | // [BLContext - CreateInfo] |
231 | // ============================================================================ |
232 | |
233 | //! Information that can be used to customize the rendering context. |
234 | struct BLContextCreateInfo { |
235 | //! Create flags, see `BLContextCreateFlags`. |
236 | uint32_t flags; |
237 | |
238 | //! Number of threads to acquire from thread-pool and use for rendering. |
239 | //! |
240 | //! If `threadCount` is zero it means to initialize the context for synchronous |
241 | //! rendering. This means that every operation will take effect immediately. |
242 | //! If the number is `1` or greater it means to initialize the context for |
243 | //! asynchronous rendering - in this case `threadCount` specifies how many |
244 | //! threads can execute in parallel. |
245 | uint32_t threadCount; |
246 | |
247 | //! CPU features to use in isolated JIT runtime (if supported), only used |
248 | //! when `flags` contains `BL_CONTEXT_CREATE_FLAG_OVERRIDE_CPU_FEATURES`. |
249 | uint32_t cpuFeatures; |
250 | |
251 | //! Reserved for future use, must be zero. |
252 | uint32_t reserved[5]; |
253 | |
254 | // -------------------------------------------------------------------------- |
255 | #ifdef __cplusplus |
256 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
257 | #endif |
258 | // -------------------------------------------------------------------------- |
259 | }; |
260 | |
261 | // ============================================================================ |
262 | // [BLContext - Cookie] |
263 | // ============================================================================ |
264 | |
265 | //! Holds an arbitrary 128-bit value (cookie) that can be used to match other |
266 | //! cookies. Blend2D uses cookies in places where it allows to "lock" some |
267 | //! state that can only be unlocked by a matching cookie. Please don't confuse |
268 | //! cookies with a security of any kind, it's just an arbitrary data that must |
269 | //! match to proceed with a certain operation. |
270 | //! |
271 | //! Cookies can be used with `BLContext::save()` and `BLContext::restore()` |
272 | //! functions |
273 | struct BLContextCookie { |
274 | uint64_t data[2]; |
275 | |
276 | // -------------------------------------------------------------------------- |
277 | #ifdef __cplusplus |
278 | |
279 | BL_INLINE bool operator==(const BLContextCookie& other) const noexcept { return equals(other); } |
280 | BL_INLINE bool operator!=(const BLContextCookie& other) const noexcept { return !equals(other); } |
281 | |
282 | BL_INLINE bool empty() const noexcept { |
283 | return this->data[0] == 0 && this->data[1] == 0; |
284 | } |
285 | |
286 | BL_INLINE void reset() noexcept { reset(0, 0); } |
287 | BL_INLINE void reset(const BLContextCookie& other) noexcept { reset(other.data[0], other.data[1]); } |
288 | |
289 | BL_INLINE void reset(uint64_t data0, uint64_t data1) noexcept { |
290 | this->data[0] = data0; |
291 | this->data[1] = data1; |
292 | } |
293 | |
294 | BL_INLINE bool equals(const BLContextCookie& other) const noexcept { |
295 | return blEquals(this->data[0], other.data[0]) & |
296 | blEquals(this->data[1], other.data[1]); |
297 | } |
298 | |
299 | #endif |
300 | // -------------------------------------------------------------------------- |
301 | }; |
302 | |
303 | // ============================================================================ |
304 | // [BLContext - Hints] |
305 | // ============================================================================ |
306 | |
307 | //! Rendering context hints. |
308 | struct BLContextHints { |
309 | union { |
310 | struct { |
311 | uint8_t renderingQuality; |
312 | uint8_t gradientQuality; |
313 | uint8_t patternQuality; |
314 | }; |
315 | |
316 | uint8_t hints[BL_CONTEXT_HINT_COUNT]; |
317 | }; |
318 | |
319 | // -------------------------------------------------------------------------- |
320 | #ifdef __cplusplus |
321 | |
322 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
323 | |
324 | #endif |
325 | // -------------------------------------------------------------------------- |
326 | }; |
327 | |
328 | // ============================================================================ |
329 | // [BLContext - State] |
330 | // ============================================================================ |
331 | |
332 | //! Rendering context state. |
333 | //! |
334 | //! This state is not meant to be created by users, it's only provided for users |
335 | //! that want to introspect it and for C++ API that accesses it directly. |
336 | struct BLContextState { |
337 | //! Current context hints. |
338 | BLContextHints hints; |
339 | //! Current composition operator. |
340 | uint8_t compOp; |
341 | //! Current fill rule. |
342 | uint8_t fillRule; |
343 | //! Current type of a style for fill and stroke operations, see `BLContextOpType`. |
344 | uint8_t styleType[2]; |
345 | //! Reserved for future use, must be zero. |
346 | uint8_t reserved[4]; |
347 | |
348 | //! Approximation options. |
349 | BLApproximationOptions approximationOptions; |
350 | |
351 | //! Current global alpha value [0, 1]. |
352 | double globalAlpha; |
353 | //! Current fill or stroke alpha, see `BLContextOpType`. |
354 | double styleAlpha[2]; |
355 | |
356 | //! Current stroke options. |
357 | BL_TYPED_MEMBER(BLStrokeOptionsCore, BLStrokeOptions, strokeOptions); |
358 | |
359 | //! Current meta transformation matrix. |
360 | BLMatrix2D metaMatrix; |
361 | //! Current user transformation matrix. |
362 | BLMatrix2D userMatrix; |
363 | |
364 | //! Count of saved states in the context. |
365 | size_t savedStateCount; |
366 | |
367 | BL_HAS_TYPED_MEMBERS(BLContextState) |
368 | }; |
369 | |
370 | // ============================================================================ |
371 | // [BLContext - Core] |
372 | // ============================================================================ |
373 | |
374 | //! Rendering context [C Interface - Virtual Function Table]. |
375 | struct BLContextVirt { |
376 | BLResult (BL_CDECL* destroy )(BLContextImpl* impl) BL_NOEXCEPT; |
377 | BLResult (BL_CDECL* flush )(BLContextImpl* impl, uint32_t flags) BL_NOEXCEPT; |
378 | |
379 | BLResult (BL_CDECL* save )(BLContextImpl* impl, BLContextCookie* cookie) BL_NOEXCEPT; |
380 | BLResult (BL_CDECL* restore )(BLContextImpl* impl, const BLContextCookie* cookie) BL_NOEXCEPT; |
381 | |
382 | BLResult (BL_CDECL* matrixOp )(BLContextImpl* impl, uint32_t opType, const void* opData) BL_NOEXCEPT; |
383 | BLResult (BL_CDECL* userToMeta )(BLContextImpl* impl) BL_NOEXCEPT; |
384 | |
385 | BLResult (BL_CDECL* setHint )(BLContextImpl* impl, uint32_t hintType, uint32_t value) BL_NOEXCEPT; |
386 | BLResult (BL_CDECL* setHints )(BLContextImpl* impl, const BLContextHints* hints) BL_NOEXCEPT; |
387 | BLResult (BL_CDECL* setFlattenMode )(BLContextImpl* impl, uint32_t mode) BL_NOEXCEPT; |
388 | BLResult (BL_CDECL* setFlattenTolerance )(BLContextImpl* impl, double tolerance) BL_NOEXCEPT; |
389 | BLResult (BL_CDECL* setApproximationOptions)(BLContextImpl* impl, const BLApproximationOptions* options) BL_NOEXCEPT; |
390 | |
391 | BLResult (BL_CDECL* setCompOp )(BLContextImpl* impl, uint32_t compOp) BL_NOEXCEPT; |
392 | BLResult (BL_CDECL* setGlobalAlpha )(BLContextImpl* impl, double alpha) BL_NOEXCEPT; |
393 | |
394 | // Allows to dispatch fill/stroke by `BLContextOpType`. |
395 | BLResult (BL_CDECL* setStyleAlpha[2] )(BLContextImpl* impl, double alpha) BL_NOEXCEPT; |
396 | BLResult (BL_CDECL* getStyle[2] )(BLContextImpl* impl, void* object) BL_NOEXCEPT; |
397 | BLResult (BL_CDECL* getStyleRgba32[2] )(BLContextImpl* impl, uint32_t* rgba32) BL_NOEXCEPT; |
398 | BLResult (BL_CDECL* getStyleRgba64[2] )(BLContextImpl* impl, uint64_t* rgba64) BL_NOEXCEPT; |
399 | BLResult (BL_CDECL* setStyle[2] )(BLContextImpl* impl, const void* object) BL_NOEXCEPT; |
400 | BLResult (BL_CDECL* setStyleRgba32[2] )(BLContextImpl* impl, uint32_t rgba32) BL_NOEXCEPT; |
401 | BLResult (BL_CDECL* setStyleRgba64[2] )(BLContextImpl* impl, uint64_t rgba64) BL_NOEXCEPT; |
402 | |
403 | BLResult (BL_CDECL* setFillRule )(BLContextImpl* impl, uint32_t fillRule) BL_NOEXCEPT; |
404 | |
405 | BLResult (BL_CDECL* setStrokeWidth )(BLContextImpl* impl, double width) BL_NOEXCEPT; |
406 | BLResult (BL_CDECL* setStrokeMiterLimit )(BLContextImpl* impl, double miterLimit) BL_NOEXCEPT; |
407 | BLResult (BL_CDECL* setStrokeCap )(BLContextImpl* impl, uint32_t position, uint32_t strokeCap) BL_NOEXCEPT; |
408 | BLResult (BL_CDECL* setStrokeCaps )(BLContextImpl* impl, uint32_t strokeCap) BL_NOEXCEPT; |
409 | BLResult (BL_CDECL* setStrokeJoin )(BLContextImpl* impl, uint32_t strokeJoin) BL_NOEXCEPT; |
410 | BLResult (BL_CDECL* setStrokeDashOffset )(BLContextImpl* impl, double dashOffset) BL_NOEXCEPT; |
411 | BLResult (BL_CDECL* setStrokeDashArray )(BLContextImpl* impl, const BLArrayCore* dashArray) BL_NOEXCEPT; |
412 | BLResult (BL_CDECL* setStrokeTransformOrder)(BLContextImpl* impl, uint32_t transformOrder) BL_NOEXCEPT; |
413 | BLResult (BL_CDECL* setStrokeOptions )(BLContextImpl* impl, const BLStrokeOptionsCore* options) BL_NOEXCEPT; |
414 | |
415 | BLResult (BL_CDECL* clipToRectI )(BLContextImpl* impl, const BLRectI* rect) BL_NOEXCEPT; |
416 | BLResult (BL_CDECL* clipToRectD )(BLContextImpl* impl, const BLRect* rect) BL_NOEXCEPT; |
417 | BLResult (BL_CDECL* restoreClipping )(BLContextImpl* impl) BL_NOEXCEPT; |
418 | |
419 | BLResult (BL_CDECL* clearAll )(BLContextImpl* impl) BL_NOEXCEPT; |
420 | BLResult (BL_CDECL* clearRectI )(BLContextImpl* impl, const BLRectI* rect) BL_NOEXCEPT; |
421 | BLResult (BL_CDECL* clearRectD )(BLContextImpl* impl, const BLRect* rect) BL_NOEXCEPT; |
422 | |
423 | BLResult (BL_CDECL* fillAll )(BLContextImpl* impl) BL_NOEXCEPT; |
424 | BLResult (BL_CDECL* fillRectI )(BLContextImpl* impl, const BLRectI* rect) BL_NOEXCEPT; |
425 | BLResult (BL_CDECL* fillRectD )(BLContextImpl* impl, const BLRect* rect) BL_NOEXCEPT; |
426 | BLResult (BL_CDECL* fillPathD )(BLContextImpl* impl, const BLPathCore* path) BL_NOEXCEPT; |
427 | BLResult (BL_CDECL* fillGeometry )(BLContextImpl* impl, uint32_t geometryType, const void* geometryData) BL_NOEXCEPT; |
428 | BLResult (BL_CDECL* fillTextI )(BLContextImpl* impl, const BLPointI* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) BL_NOEXCEPT; |
429 | BLResult (BL_CDECL* fillTextD )(BLContextImpl* impl, const BLPoint* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) BL_NOEXCEPT; |
430 | BLResult (BL_CDECL* fillGlyphRunI )(BLContextImpl* impl, const BLPointI* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) BL_NOEXCEPT; |
431 | BLResult (BL_CDECL* fillGlyphRunD )(BLContextImpl* impl, const BLPoint* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) BL_NOEXCEPT; |
432 | |
433 | BLResult (BL_CDECL* strokeRectI )(BLContextImpl* impl, const BLRectI* rect) BL_NOEXCEPT; |
434 | BLResult (BL_CDECL* strokeRectD )(BLContextImpl* impl, const BLRect* rect) BL_NOEXCEPT; |
435 | BLResult (BL_CDECL* strokePathD )(BLContextImpl* impl, const BLPathCore* path) BL_NOEXCEPT; |
436 | BLResult (BL_CDECL* strokeGeometry )(BLContextImpl* impl, uint32_t geometryType, const void* geometryData) BL_NOEXCEPT; |
437 | BLResult (BL_CDECL* strokeTextI )(BLContextImpl* impl, const BLPointI* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) BL_NOEXCEPT; |
438 | BLResult (BL_CDECL* strokeTextD )(BLContextImpl* impl, const BLPoint* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) BL_NOEXCEPT; |
439 | BLResult (BL_CDECL* strokeGlyphRunI )(BLContextImpl* impl, const BLPointI* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) BL_NOEXCEPT; |
440 | BLResult (BL_CDECL* strokeGlyphRunD )(BLContextImpl* impl, const BLPoint* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) BL_NOEXCEPT; |
441 | |
442 | BLResult (BL_CDECL* blitImageI )(BLContextImpl* impl, const BLPointI* pt, const BLImageCore* img, const BLRectI* imgArea) BL_NOEXCEPT; |
443 | BLResult (BL_CDECL* blitImageD )(BLContextImpl* impl, const BLPoint* pt, const BLImageCore* img, const BLRectI* imgArea) BL_NOEXCEPT; |
444 | BLResult (BL_CDECL* blitScaledImageI )(BLContextImpl* impl, const BLRectI* rect, const BLImageCore* img, const BLRectI* imgArea) BL_NOEXCEPT; |
445 | BLResult (BL_CDECL* blitScaledImageD )(BLContextImpl* impl, const BLRect* rect, const BLImageCore* img, const BLRectI* imgArea) BL_NOEXCEPT; |
446 | }; |
447 | |
448 | //! Rendering context [C Interface - Impl]. |
449 | struct BLContextImpl { |
450 | //! Virtual function table. |
451 | const BLContextVirt* virt; |
452 | //! Current state of the context. |
453 | const BLContextState* state; |
454 | //! Reserved header for future use. |
455 | void* ; |
456 | |
457 | //! Reference count. |
458 | volatile size_t refCount; |
459 | //! Impl type. |
460 | uint8_t implType; |
461 | //! Impl traits. |
462 | uint8_t implTraits; |
463 | //! Memory pool data. |
464 | uint16_t memPoolData; |
465 | //! Type of the context, see `BLContextType`. |
466 | uint32_t contextType; |
467 | |
468 | //! Current size of the target in abstract units, pixels if rendering to `BLImage`. |
469 | BLSize targetSize; |
470 | }; |
471 | |
472 | //! Rendering context [C Interface - Core]. |
473 | struct BLContextCore { |
474 | BLContextImpl* impl; |
475 | }; |
476 | |
477 | // ============================================================================ |
478 | // [BLContext - C++] |
479 | // ============================================================================ |
480 | |
481 | #ifdef __cplusplus |
482 | //! Rendering context [C++ API]. |
483 | class BLContext : public BLContextCore { |
484 | public: |
485 | //! \cond INTERNAL |
486 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_CONTEXT; |
487 | |
488 | // Only used by `BLContext` to make invocation of functions in `BLContextVirt`. |
489 | enum OpType : uint32_t { |
490 | kOpFill = BL_CONTEXT_OP_TYPE_FILL, |
491 | kOpStroke = BL_CONTEXT_OP_TYPE_STROKE |
492 | }; |
493 | //! \endcond |
494 | |
495 | //! \name Construction & Destruction |
496 | //! \{ |
497 | |
498 | //! Creates a default constructed rendering context. |
499 | //! |
500 | //! Default constructed means that the instance is valid, but uninitialized, |
501 | //! which means the rendering context does not have attached any target. Any |
502 | //! attempt to use uninitialized context results in `BL_ERROR_NOT_INITIALIZED` |
503 | //! error. |
504 | BL_INLINE BLContext() noexcept { this->impl = none().impl; } |
505 | |
506 | //! Move constructor. |
507 | //! |
508 | //! Moves the `other` rendering context into this one and resets the `other`. |
509 | BL_INLINE BLContext(BLContext&& other) noexcept { blVariantInitMove(this, &other); } |
510 | |
511 | //! Copy constructor. |
512 | //! |
513 | //! Creates a weak-copy of the `other` rendering context by increasing it's |
514 | //! internal reference counter. This context and `other` would point to the |
515 | //! same data and would be otherwise identical. Any change to `other` would |
516 | //! also affect this context. |
517 | //! |
518 | //! This function is mostly provided for C++ users that may keep a global |
519 | //! reference to the same rendering context, for example, otherwise sharing |
520 | //! is not that useful as they also share a state. |
521 | //! |
522 | //! Two weak copies of the same rendering context cannot be used by different |
523 | //! threads simultaneously. |
524 | BL_INLINE BLContext(const BLContext& other) noexcept { blVariantInitWeak(this, &other); } |
525 | |
526 | //! Initializes this `BLContext` class with rendering context `impl`. |
527 | //! |
528 | //! Mostly for internal purposes and to keep the API consistent. |
529 | BL_INLINE explicit BLContext(BLContextImpl* impl) noexcept { this->impl = impl; } |
530 | |
531 | //! Creates a new rendering context for rendering to the image `target`. |
532 | BL_INLINE explicit BLContext(BLImage& target) noexcept { blContextInitAs(this, &target, nullptr); } |
533 | //! Creates a new rendering context for rendering to the image `target`. |
534 | //! |
535 | //! This overload accepts create options that can be used to change the |
536 | //! implementation of the rendering context. |
537 | BL_INLINE BLContext(BLImage& target, const BLContextCreateInfo& options) noexcept { blContextInitAs(this, &target, &options); } |
538 | //! \overload |
539 | BL_INLINE BLContext(BLImage& target, const BLContextCreateInfo* options) noexcept { blContextInitAs(this, &target, options); } |
540 | |
541 | //! Destroys the rendering context. |
542 | //! |
543 | //! Waits for all operations, detaches the target from the rendering context |
544 | //! and then destroys it. Does nothing if the context is not initialized. |
545 | BL_INLINE ~BLContext() noexcept { blContextReset(this); } |
546 | |
547 | //! \} |
548 | |
549 | //! \name Overloaded Operators |
550 | //! \{ |
551 | |
552 | //! Returns true if the rendering context is initialized (has target attached). |
553 | //! |
554 | //! Provided for users that want to use bool idiom in C++ to check for the |
555 | //! status of the object. |
556 | //! |
557 | //! ``` |
558 | //! if (ctx) { |
559 | //! // Rendering context is initialized. |
560 | //! } |
561 | //! ``` |
562 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
563 | |
564 | BL_INLINE BLContext& operator=(BLContext&& other) noexcept { blContextAssignMove(this, &other); return *this; } |
565 | BL_INLINE BLContext& operator=(const BLContext& other) noexcept { blContextAssignWeak(this, &other); return *this; } |
566 | |
567 | //! Returns whether this and `other` point to the same rendering context. |
568 | BL_INLINE bool operator==(const BLContext& other) const noexcept { return equals(other); } |
569 | //! Returns whether this and `other` are different rendering contexts. |
570 | BL_INLINE bool operator!=(const BLContext& other) const noexcept { return !equals(other); } |
571 | |
572 | //! \} |
573 | |
574 | //! \name Target Information |
575 | //! \{ |
576 | |
577 | //! Returns target size in abstract units (pixels in case of `BLImage`). |
578 | BL_INLINE BLSize targetSize() const noexcept { return impl->targetSize; } |
579 | //! Returns target width in abstract units (pixels in case of `BLImage`). |
580 | BL_INLINE double targetWidth() const noexcept { return impl->targetSize.w; } |
581 | //! Returns target height in abstract units (pixels in case of `BLImage`). |
582 | BL_INLINE double targetHeight() const noexcept { return impl->targetSize.h; } |
583 | |
584 | //! \} |
585 | |
586 | //! \name Context Lifetime and Others |
587 | //! \{ |
588 | |
589 | //! Returns the type of this context, see `BLContextType`. |
590 | BL_INLINE uint32_t contextType() const noexcept { return impl->contextType; } |
591 | |
592 | //! Tests whether the context is a built-in null instance. |
593 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
594 | |
595 | //! Returns whether this and `other` point to the same rendering context. |
596 | BL_INLINE bool equals(const BLContext& other) const noexcept { return this->impl == other.impl; } |
597 | |
598 | //! Resets this rendering context to the default constructed one. |
599 | //! |
600 | //! Similar behavior to the destructor, but the context will still be valid |
601 | //! after `reset()` and would behave like a default constructed context. |
602 | BL_INLINE BLResult reset() noexcept { return blContextReset(this); } |
603 | |
604 | BL_INLINE BLResult assign(BLContext&& other) noexcept { return blContextAssignMove(this, &other); } |
605 | BL_INLINE BLResult assign(const BLContext& other) noexcept { return blContextAssignWeak(this, &other); } |
606 | |
607 | //! Begins rendering to the given `image`. |
608 | //! |
609 | //! If this operation succeeds then the rendering context will have exclusive |
610 | //! access to the image data. This means that no other renderer can use it |
611 | //! during rendering. |
612 | BL_INLINE BLResult begin(BLImage& image) noexcept { return blContextBegin(this, &image, nullptr); } |
613 | //! \overload |
614 | BL_INLINE BLResult begin(BLImage& image, const BLContextCreateInfo& options) noexcept { return blContextBegin(this, &image, &options); } |
615 | //! \overload |
616 | BL_INLINE BLResult begin(BLImage& image, const BLContextCreateInfo* options) noexcept { return blContextBegin(this, &image, options); } |
617 | |
618 | //! Waits for completion of all render commands and detaches the rendering |
619 | //! context from the rendering target. After `end()` completes the rendering |
620 | //! context implementation would be released and replaced by a built-in null |
621 | //! instance (no context). |
622 | BL_INLINE BLResult end() noexcept { return blContextEnd(this); } |
623 | |
624 | //! Flushes the context, see `BLContextFlushFlags`. |
625 | BL_INLINE BLResult flush(uint32_t flags) noexcept { return impl->virt->flush(impl, flags); } |
626 | |
627 | //! \} |
628 | |
629 | //! \name State Management |
630 | //! \{ |
631 | |
632 | //! Returns the number of saved states in the context (0 means no saved states). |
633 | BL_INLINE size_t savedStateCount() const noexcept { return impl->state->savedStateCount; } |
634 | |
635 | //! Saves the current rendering context state. |
636 | //! |
637 | //! Blend2D uses optimizations that make `save()` a cheap operation. Only core |
638 | //! values are actually saved in `save()`, others will only be saved if they |
639 | //! are modified. This means that consecutive calls to `save()` and `restore()` |
640 | //! do almost nothing. |
641 | BL_INLINE BLResult save() noexcept { return impl->virt->save(impl, nullptr); } |
642 | |
643 | //! Saves the current rendering context state and creates a restoration `cookie`. |
644 | //! |
645 | //! If you use a `cookie` to save a state you have to use the same cookie to |
646 | //! restore it otherwise the `restore()` would fail. Please note that cookies |
647 | //! are not a means of security, they are provided for making it easier to |
648 | //! guarantee that a code that you may not control won't break your context. |
649 | BL_INLINE BLResult save(BLContextCookie& cookie) noexcept { return impl->virt->save(impl, &cookie); } |
650 | |
651 | //! Restores the top-most saved context-state. |
652 | //! |
653 | //! Possible return conditions: |
654 | //! |
655 | //! * `BL_SUCCESS` - State was restored successfully. |
656 | //! * `BL_ERROR_NO_STATES_TO_RESTORE` - There are no saved states to restore. |
657 | //! * `BL_ERROR_NO_MATCHING_COOKIE` - Previous state was saved with cookie, |
658 | //! which was not provided. You would need the correct cookie to restore |
659 | //! such state. |
660 | BL_INLINE BLResult restore() noexcept { return impl->virt->restore(impl, nullptr); } |
661 | |
662 | //! Restores to the point that matches the given `cookie`. |
663 | //! |
664 | //! More than one state can be restored in case that the `cookie` points to |
665 | //! some previous state in the list. |
666 | //! |
667 | //! Possible return conditions: |
668 | //! |
669 | //! * `BL_SUCCESS` - Matching state was restored successfully. |
670 | //! * `BL_ERROR_NO_STATES_TO_RESTORE` - There are no saved states to restore. |
671 | //! * `BL_ERROR_NO_MATCHING_COOKIE` - The cookie did't match any saved state. |
672 | BL_INLINE BLResult restore(const BLContextCookie& cookie) noexcept { return impl->virt->restore(impl, &cookie); } |
673 | |
674 | //! \} |
675 | |
676 | //! \name Transformations |
677 | //! \{ |
678 | |
679 | //! Returns meta-matrix. |
680 | //! |
681 | //! Meta matrix is a core transformation matrix that is normally not changed |
682 | //! by transformations applied to the context. Instead it acts as a secondary |
683 | //! matrix used to create the final transformation matrix from meta and user |
684 | //! matrices. |
685 | //! |
686 | //! Meta matrix can be used to scale the whole context for HI-DPI rendering |
687 | //! or to change the orientation of the image being rendered, however, the |
688 | //! number of use-cases is unlimited. |
689 | //! |
690 | //! To change the meta-matrix you must first change user-matrix and then call |
691 | //! `userToMeta()`, which would update meta-matrix and clear user-matrix. |
692 | //! |
693 | //! See `userMatrix()` and `userToMeta()`. |
694 | BL_INLINE const BLMatrix2D& metaMatrix() const noexcept { return impl->state->metaMatrix; } |
695 | |
696 | //! Returns user-matrix. |
697 | //! |
698 | //! User matrix contains all transformations that happened to the rendering |
699 | //! context unless the context was restored or `userToMeta()` was called. |
700 | BL_INLINE const BLMatrix2D& userMatrix() const noexcept { return impl->state->userMatrix; } |
701 | |
702 | //! Applies a matrix operation to the current transformation matrix (internal). |
703 | BL_INLINE BLResult _applyMatrixOp(uint32_t opType, const void* opData) noexcept { |
704 | return impl->virt->matrixOp(impl, opType, opData); |
705 | } |
706 | |
707 | //! \cond INTERNAL |
708 | //! Applies a matrix operation to the current transformation matrix (internal). |
709 | template<typename... Args> |
710 | BL_INLINE BLResult _applyMatrixOpV(uint32_t opType, Args&&... args) noexcept { |
711 | double opData[] = { double(args)... }; |
712 | return impl->virt->matrixOp(impl, opType, opData); |
713 | } |
714 | //! \endcond |
715 | |
716 | //! Sets user matrix to `m`. |
717 | BL_INLINE BLResult setMatrix(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_ASSIGN, &m); } |
718 | //! Resets user matrix to identity. |
719 | BL_INLINE BLResult resetMatrix() noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_RESET, nullptr); } |
720 | |
721 | BL_INLINE BLResult translate(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_TRANSLATE, x, y); } |
722 | BL_INLINE BLResult translate(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_TRANSLATE, p.x, p.y); } |
723 | BL_INLINE BLResult translate(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_TRANSLATE, &p); } |
724 | BL_INLINE BLResult scale(double xy) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, xy, xy); } |
725 | BL_INLINE BLResult scale(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, x, y); } |
726 | BL_INLINE BLResult scale(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SCALE, p.x, p.y); } |
727 | BL_INLINE BLResult scale(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_SCALE, &p); } |
728 | BL_INLINE BLResult skew(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_SKEW, x, y); } |
729 | BL_INLINE BLResult skew(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_SKEW, &p); } |
730 | BL_INLINE BLResult rotate(double angle) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_ROTATE, &angle); } |
731 | BL_INLINE BLResult rotate(double angle, double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, x, y); } |
732 | BL_INLINE BLResult rotate(double angle, const BLPoint& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, p.x, p.y); } |
733 | BL_INLINE BLResult rotate(double angle, const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_ROTATE_PT, angle, p.x, p.y); } |
734 | BL_INLINE BLResult transform(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_TRANSFORM, &m); } |
735 | |
736 | BL_INLINE BLResult postTranslate(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_TRANSLATE, x, y); } |
737 | BL_INLINE BLResult postTranslate(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_TRANSLATE, p.x, p.y); } |
738 | BL_INLINE BLResult postTranslate(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_TRANSLATE, &p); } |
739 | BL_INLINE BLResult postScale(double xy) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, xy, xy); } |
740 | BL_INLINE BLResult postScale(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, x, y); } |
741 | BL_INLINE BLResult postScale(const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SCALE, p.x, p.y); } |
742 | BL_INLINE BLResult postScale(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_SCALE, &p); } |
743 | BL_INLINE BLResult postSkew(double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_SKEW, x, y); } |
744 | BL_INLINE BLResult postSkew(const BLPoint& p) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_SKEW, &p); } |
745 | BL_INLINE BLResult postRotate(double angle) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_ROTATE, &angle); } |
746 | BL_INLINE BLResult postRotate(double angle, double x, double y) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, x, y); } |
747 | BL_INLINE BLResult postRotate(double angle, const BLPoint& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, p.x, p.y); } |
748 | BL_INLINE BLResult postRotate(double angle, const BLPointI& p) noexcept { return _applyMatrixOpV(BL_MATRIX2D_OP_POST_ROTATE_PT, angle, p.x, p.y); } |
749 | BL_INLINE BLResult postTransform(const BLMatrix2D& m) noexcept { return _applyMatrixOp(BL_MATRIX2D_OP_POST_TRANSFORM, &m); } |
750 | |
751 | //! Store the result of combining the current `MetaMatrix` and `UserMatrix` |
752 | //! to `MetaMatrix` and reset `UserMatrix` to identity as shown below: |
753 | //! |
754 | //! ``` |
755 | //! MetaMatrix = MetaMatrix x UserMatrix |
756 | //! UserMatrix = Identity |
757 | //! ``` |
758 | //! |
759 | //! Please note that this operation is irreversible. The only way to restore |
760 | //! both matrices to the state before the call to `userToMeta()` is to use |
761 | //! `save()` and `restore()` functions. |
762 | BL_INLINE BLResult userToMeta() noexcept { return impl->virt->userToMeta(impl); } |
763 | |
764 | //! \} |
765 | |
766 | //! \name Rendering Hints |
767 | //! \{ |
768 | |
769 | //! Returns rendering hints. |
770 | BL_INLINE const BLContextHints& hints() const noexcept { return impl->state->hints; } |
771 | |
772 | //! Sets the given rendering hint `hintType` to the `value`. |
773 | BL_INLINE BLResult setHint(uint32_t hintType, uint32_t value) noexcept { return impl->virt->setHint(impl, hintType, value); } |
774 | //! Sets all rendering hints of this context to the given `hints`. |
775 | BL_INLINE BLResult setHints(const BLContextHints& hints) noexcept { return impl->virt->setHints(impl, &hints); } |
776 | |
777 | BL_INLINE BLResult setRenderingQuality(uint32_t value) noexcept { return setHint(BL_CONTEXT_HINT_RENDERING_QUALITY, value); } |
778 | BL_INLINE BLResult setGradientQuality(uint32_t value) noexcept { return setHint(BL_CONTEXT_HINT_GRADIENT_QUALITY, value); } |
779 | BL_INLINE BLResult setPatternQuality(uint32_t value) noexcept { return setHint(BL_CONTEXT_HINT_PATTERN_QUALITY, value); } |
780 | |
781 | //! \} |
782 | |
783 | //! \name Approximation Options |
784 | //! \{ |
785 | |
786 | //! Returns approximation options. |
787 | BL_INLINE const BLApproximationOptions& approximationOptions() const noexcept { return impl->state->approximationOptions; } |
788 | |
789 | //! Returns flatten mode (how curves are flattened), see `BLFlattenMmode`. |
790 | BL_INLINE uint32_t flattenMode() const noexcept { return impl->state->approximationOptions.flattenMode; } |
791 | //! Sets flatten `mode` (how curves are flattened), see `BLFlattenMmode`. |
792 | BL_INLINE BLResult setFlattenMode(uint32_t mode) noexcept { return impl->virt->setFlattenMode(impl, mode); } |
793 | |
794 | //! Returns tolerance used for curve flattening. |
795 | BL_INLINE double flattenTolerance() const noexcept { return impl->state->approximationOptions.flattenTolerance; } |
796 | //! Sets tolerance used for curve flattening. |
797 | BL_INLINE BLResult setFlattenTolerance(double tolerance) noexcept { return impl->virt->setFlattenTolerance(impl, tolerance); } |
798 | |
799 | //! \} |
800 | |
801 | //! \name Composition Options |
802 | //! \{ |
803 | |
804 | //! Returns composition operator. |
805 | BL_INLINE uint32_t compOp() const noexcept { return impl->state->compOp; } |
806 | //! Sets composition operator to `compOp`, see `BLCompOp`. |
807 | BL_INLINE BLResult setCompOp(uint32_t compOp) noexcept { return impl->virt->setCompOp(impl, compOp); } |
808 | |
809 | //! Returns global alpha value. |
810 | BL_INLINE double globalAlpha() const noexcept { return impl->state->globalAlpha; } |
811 | //! Sets global alpha value. |
812 | BL_INLINE BLResult setGlobalAlpha(double alpha) noexcept { return impl->virt->setGlobalAlpha(impl, alpha); } |
813 | |
814 | //! \} |
815 | |
816 | //! \name Style Options |
817 | //! \{ |
818 | |
819 | BL_INLINE uint32_t styleType(uint32_t opType) const noexcept { |
820 | return opType <= BL_CONTEXT_OP_TYPE_COUNT ? uint32_t(impl->state->styleType[opType]) : uint32_t(0); |
821 | } |
822 | |
823 | //! Returns fill or alpha value dependeing on the rendering operation `opType`. |
824 | //! |
825 | //! The function behaves like `fillAlpha()` or `strokeAlpha()` depending on |
826 | //! `opType` value, see `BLContextOpType`. |
827 | BL_INLINE double styleAlpha(uint32_t opType) const noexcept { |
828 | return opType < BL_CONTEXT_OP_TYPE_COUNT ? impl->state->styleAlpha[opType] : 0.0; |
829 | } |
830 | |
831 | //! Set fill or stroke `alpha` value depending on the rendering operation `opType`. |
832 | //! |
833 | //! The function behaves like `setFillAlpha()` or `setStrokeAlpha()` depending |
834 | //! on `opType` value, see `BLContextOpType`. |
835 | BL_INLINE BLResult setStyleAlpha(uint32_t opType, double alpha) noexcept { |
836 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
837 | return blTraceError(BL_ERROR_INVALID_VALUE); |
838 | return impl->virt->setStyleAlpha[opType](impl, alpha); |
839 | } |
840 | |
841 | BL_INLINE BLResult getStyle(uint32_t opType, BLRgba32& out) const noexcept { |
842 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
843 | return blTraceError(BL_ERROR_INVALID_VALUE); |
844 | return impl->virt->getStyleRgba32[opType](impl, &out.value); |
845 | } |
846 | |
847 | BL_INLINE BLResult getStyle(uint32_t opType, BLRgba64& out) const noexcept { |
848 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
849 | return blTraceError(BL_ERROR_INVALID_VALUE); |
850 | return impl->virt->getStyleRgba64[opType](impl, &out.value); |
851 | } |
852 | |
853 | BL_INLINE BLResult getStyle(uint32_t opType, BLPattern& out) const noexcept { |
854 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
855 | return blTraceError(BL_ERROR_INVALID_VALUE); |
856 | return impl->virt->getStyle[opType](impl, &out); |
857 | } |
858 | |
859 | BL_INLINE BLResult getStyle(uint32_t opType, BLGradient& out) const noexcept { |
860 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
861 | return blTraceError(BL_ERROR_INVALID_VALUE); |
862 | return impl->virt->getStyle[opType](impl, &out); |
863 | } |
864 | |
865 | BL_INLINE BLResult setStyle(uint32_t opType, const BLGradient& gradient) noexcept { |
866 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
867 | return blTraceError(BL_ERROR_INVALID_VALUE); |
868 | return impl->virt->setStyle[opType](impl, &gradient); |
869 | } |
870 | |
871 | BL_INLINE BLResult setStyle(uint32_t opType, const BLPattern& pattern) noexcept { |
872 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
873 | return blTraceError(BL_ERROR_INVALID_VALUE); |
874 | return impl->virt->setStyle[opType](impl, &pattern); |
875 | } |
876 | |
877 | BL_INLINE BLResult setStyle(uint32_t opType, const BLImage& image) noexcept { |
878 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
879 | return blTraceError(BL_ERROR_INVALID_VALUE); |
880 | return impl->virt->setStyle[opType](impl, &image); |
881 | } |
882 | |
883 | BL_INLINE BLResult setStyle(uint32_t opType, const BLVariant& variant) noexcept { |
884 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
885 | return blTraceError(BL_ERROR_INVALID_VALUE); |
886 | return impl->virt->setStyle[opType](impl, &variant); |
887 | } |
888 | |
889 | BL_INLINE BLResult setStyle(uint32_t opType, const BLRgba32& rgba32) noexcept { |
890 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
891 | return blTraceError(BL_ERROR_INVALID_VALUE); |
892 | return impl->virt->setStyleRgba32[opType](impl, rgba32.value); |
893 | } |
894 | |
895 | BL_INLINE BLResult setStyle(uint32_t opType, const BLRgba64& rgba64) noexcept { |
896 | if (BL_UNLIKELY(opType >= BL_CONTEXT_OP_TYPE_COUNT)) |
897 | return blTraceError(BL_ERROR_INVALID_VALUE); |
898 | return impl->virt->setStyleRgba64[opType](impl, rgba64.value); |
899 | } |
900 | |
901 | //! \} |
902 | |
903 | //! \name Fill Style & Options |
904 | //! \{ |
905 | |
906 | //! Returns fill alpha value. |
907 | BL_INLINE double fillAlpha() const noexcept { return impl->state->styleAlpha[kOpFill]; } |
908 | //! Sets fill `alpha` value. |
909 | BL_INLINE BLResult setFillAlpha(double alpha) noexcept { return impl->virt->setStyleAlpha[kOpFill](impl, alpha); } |
910 | |
911 | BL_INLINE uint32_t fillStyleType() const noexcept { return impl->state->styleType[kOpFill]; } |
912 | BL_INLINE BLResult getFillStyle(BLRgba32& out) const noexcept { return impl->virt->getStyleRgba32[kOpFill](impl, &out.value); } |
913 | BL_INLINE BLResult getFillStyle(BLRgba64& out) const noexcept { return impl->virt->getStyleRgba64[kOpFill](impl, &out.value); } |
914 | BL_INLINE BLResult getFillStyle(BLPattern& out) const noexcept { return impl->virt->getStyle[kOpFill](impl, &out); } |
915 | BL_INLINE BLResult getFillStyle(BLGradient& out) const noexcept { return impl->virt->getStyle[kOpFill](impl, &out); } |
916 | |
917 | BL_INLINE BLResult setFillStyle(const BLRgba32& rgba32) noexcept { return impl->virt->setStyleRgba32[kOpFill](impl, rgba32.value); } |
918 | BL_INLINE BLResult setFillStyle(const BLRgba64& rgba64) noexcept { return impl->virt->setStyleRgba64[kOpFill](impl, rgba64.value); } |
919 | BL_INLINE BLResult setFillStyle(const BLGradient& gradient) noexcept { return impl->virt->setStyle[kOpFill](impl, &gradient); } |
920 | BL_INLINE BLResult setFillStyle(const BLPattern& pattern) noexcept { return impl->virt->setStyle[kOpFill](impl, &pattern); } |
921 | BL_INLINE BLResult setFillStyle(const BLVariant& variant) noexcept { return impl->virt->setStyle[kOpFill](impl, &variant); } |
922 | |
923 | //! Returns fill-rule, see `BLFillRule`. |
924 | BL_INLINE uint32_t fillRule() const noexcept { return impl->state->fillRule; } |
925 | //! Sets fill-rule, see `BLFillRule`. |
926 | BL_INLINE BLResult setFillRule(uint32_t fillRule) noexcept { return impl->virt->setFillRule(impl, fillRule); } |
927 | |
928 | //! \} |
929 | |
930 | //! \name Stroke Style & Options |
931 | //! \{ |
932 | |
933 | //! Returns stroke alpha value. |
934 | BL_INLINE double strokeAlpha() const noexcept { return impl->state->styleAlpha[kOpStroke]; } |
935 | //! Sets stroke alpha value to `alpha`. |
936 | BL_INLINE BLResult setStrokeAlpha(double alpha) noexcept { return impl->virt->setStyleAlpha[kOpStroke](impl, alpha); } |
937 | |
938 | BL_INLINE uint32_t strokeStyleType() const noexcept { return impl->state->styleType[kOpStroke]; } |
939 | BL_INLINE BLResult getStrokeStyle(BLRgba32& out) const noexcept { return impl->virt->getStyleRgba32[kOpStroke](impl, &out.value); } |
940 | BL_INLINE BLResult getStrokeStyle(BLRgba64& out) const noexcept { return impl->virt->getStyleRgba64[kOpStroke](impl, &out.value); } |
941 | BL_INLINE BLResult getStrokeStyle(BLPattern& out) const noexcept { return impl->virt->getStyle[kOpStroke](impl, &out); } |
942 | BL_INLINE BLResult getStrokeStyle(BLGradient& out) const noexcept { return impl->virt->getStyle[kOpStroke](impl, &out); } |
943 | |
944 | BL_INLINE BLResult setStrokeStyle(const BLRgba32& rgba32) noexcept { return impl->virt->setStyleRgba32[kOpStroke](impl, rgba32.value); } |
945 | BL_INLINE BLResult setStrokeStyle(const BLRgba64& rgba64) noexcept { return impl->virt->setStyleRgba64[kOpStroke](impl, rgba64.value); } |
946 | BL_INLINE BLResult setStrokeStyle(const BLPattern& pattern) noexcept { return impl->virt->setStyle[kOpStroke](impl, &pattern); } |
947 | BL_INLINE BLResult setStrokeStyle(const BLGradient& gradient) noexcept { return impl->virt->setStyle[kOpStroke](impl, &gradient); } |
948 | BL_INLINE BLResult setStrokeStyle(const BLVariant& variant) noexcept { return impl->virt->setStyle[kOpStroke](impl, &variant); } |
949 | |
950 | //! Returns stroke width. |
951 | BL_INLINE double strokeWidth() const noexcept { return impl->state->strokeOptions.width; } |
952 | //! Returns stroke miter-limit. |
953 | BL_INLINE double strokeMiterLimit() const noexcept { return impl->state->strokeOptions.miterLimit; } |
954 | //! Returns stroke join, see `BLStrokeJoin`. |
955 | BL_INLINE uint32_t strokeJoin() const noexcept { return impl->state->strokeOptions.join; } |
956 | //! Returns stroke start-cap, see `BLStrokeCap`. |
957 | BL_INLINE uint32_t strokeStartCap() const noexcept { return impl->state->strokeOptions.startCap; } |
958 | //! Returns stroke end-cap, see `BLStrokeCap`. |
959 | BL_INLINE uint32_t strokeEndCap() const noexcept { return impl->state->strokeOptions.endCap; } |
960 | //! Returns stroke dash-offset. |
961 | BL_INLINE double strokeDashOffset() const noexcept { return impl->state->strokeOptions.dashOffset; } |
962 | //! Returns stroke dash-array. |
963 | BL_INLINE const BLArray<double>& strokeDashArray() const noexcept { return impl->state->strokeOptions.dashArray; } |
964 | //! Returns stroke transform order, see `BLStrokeTransformOrder`. |
965 | BL_INLINE uint32_t strokeTransformOrder() const noexcept { return impl->state->strokeOptions.transformOrder; } |
966 | //! Returns stroke options as a reference to `BLStrokeOptions`. |
967 | BL_INLINE const BLStrokeOptions& strokeOptions() const noexcept { return impl->state->strokeOptions; } |
968 | |
969 | //! Sets stroke width to `width`. |
970 | BL_INLINE BLResult setStrokeWidth(double width) noexcept { return impl->virt->setStrokeWidth(impl, width); } |
971 | //! Sets miter limit to `miterLimit`. |
972 | BL_INLINE BLResult setStrokeMiterLimit(double miterLimit) noexcept { return impl->virt->setStrokeMiterLimit(impl, miterLimit); } |
973 | //! Sets stroke join to `strokeJoin`, see `BLStrokeJoin`. |
974 | BL_INLINE BLResult setStrokeJoin(uint32_t strokeJoin) noexcept { return impl->virt->setStrokeJoin(impl, strokeJoin); } |
975 | //! Sets stroke cap of the specified `type` to `strokeCap`, see `BLStrokeCap`. |
976 | BL_INLINE BLResult setStrokeCap(uint32_t type, uint32_t strokeCap) noexcept { return impl->virt->setStrokeCap(impl, type, strokeCap); } |
977 | //! Sets stroke start cap to `strokeCap`, see `BLStrokeCap`. |
978 | BL_INLINE BLResult setStrokeStartCap(uint32_t strokeCap) noexcept { return setStrokeCap(BL_STROKE_CAP_POSITION_START, strokeCap); } |
979 | //! Sets stroke end cap to `strokeCap`, see `BLStrokeCap`. |
980 | BL_INLINE BLResult setStrokeEndCap(uint32_t strokeCap) noexcept { return setStrokeCap(BL_STROKE_CAP_POSITION_END, strokeCap); } |
981 | //! Sets all stroke caps to `strokeCap`, see `BLStrokeCap`. |
982 | BL_INLINE BLResult setStrokeCaps(uint32_t strokeCap) noexcept { return impl->virt->setStrokeCaps(impl, strokeCap); } |
983 | //! Sets stroke dash-offset to `dashOffset`. |
984 | BL_INLINE BLResult setStrokeDashOffset(double dashOffset) noexcept { return impl->virt->setStrokeDashOffset(impl, dashOffset); } |
985 | //! Sets stroke dash-array to `dashArray`. |
986 | BL_INLINE BLResult setStrokeDashArray(const BLArray<double>& dashArray) noexcept { return impl->virt->setStrokeDashArray(impl, &dashArray); } |
987 | //! Sets stroke transformation order to `transformOrder`, see `BLStrokeTransformOrder`. |
988 | BL_INLINE BLResult setStrokeTransformOrder(uint32_t transformOrder) noexcept { return impl->virt->setStrokeTransformOrder(impl, transformOrder); } |
989 | //! Sets all stroke `options`. |
990 | BL_INLINE BLResult setStrokeOptions(const BLStrokeOptions& options) noexcept { return impl->virt->setStrokeOptions(impl, &options); } |
991 | |
992 | //! \} |
993 | |
994 | //! \name Clip Operations |
995 | //! \{ |
996 | |
997 | //! Restores clipping to the last saved state or to the context default |
998 | //! clipping if there is no saved state. |
999 | //! |
1000 | //! If there are no saved states then it resets clipping completely to the |
1001 | //! initial state that was used when the rendering context was created. |
1002 | BL_INLINE BLResult restoreClipping() noexcept { return impl->virt->restoreClipping(impl); } |
1003 | |
1004 | BL_INLINE BLResult clipToRect(const BLRectI& rect) noexcept { return impl->virt->clipToRectI(impl, &rect); } |
1005 | BL_INLINE BLResult clipToRect(const BLRect& rect) noexcept { return impl->virt->clipToRectD(impl, &rect); } |
1006 | BL_INLINE BLResult clipToRect(double x, double y, double w, double h) noexcept { return clipToRect(BLRect(x, y, w, h)); } |
1007 | |
1008 | //! \} |
1009 | |
1010 | //! \name Clear Operations |
1011 | //! \{ |
1012 | |
1013 | //! Clear everything. |
1014 | BL_INLINE BLResult clearAll() noexcept { return impl->virt->clearAll(impl); } |
1015 | |
1016 | //! Clears a rectangle `rect`. |
1017 | BL_INLINE BLResult clearRect(const BLRectI& rect) noexcept { return impl->virt->clearRectI(impl, &rect); } |
1018 | //! Clears a rectangle `rect`. |
1019 | BL_INLINE BLResult clearRect(const BLRect& rect) noexcept { return impl->virt->clearRectD(impl, &rect); } |
1020 | //! \overload |
1021 | BL_INLINE BLResult clearRect(double x, double y, double w, double h) noexcept { return clearRect(BLRect(x, y, w, h)); } |
1022 | |
1023 | //! \} |
1024 | |
1025 | //! \name Fill Operations |
1026 | //! \{ |
1027 | |
1028 | //! Fills the passed geometry specified by `geometryType` and `geometryData` [Internal]. |
1029 | BL_INLINE BLResult fillGeometry(uint32_t geometryType, const void* geometryData) noexcept { return impl->virt->fillGeometry(impl, geometryType, geometryData); } |
1030 | |
1031 | //! Fills everything. |
1032 | BL_INLINE BLResult fillAll() noexcept { return impl->virt->fillAll(impl); } |
1033 | |
1034 | //! Fills a box. |
1035 | BL_INLINE BLResult fillBox(const BLBox& box) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_BOXD, &box); } |
1036 | // \overload |
1037 | BL_INLINE BLResult fillBox(const BLBoxI& box) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_BOXI, &box); } |
1038 | // \overload |
1039 | BL_INLINE BLResult fillBox(double x0, double y0, double x1, double y1) noexcept { return fillBox(BLBox(x0, y0, x1, y1)); } |
1040 | |
1041 | //! Fills a rectangle `rect`. |
1042 | BL_INLINE BLResult fillRect(const BLRectI& rect) noexcept { return impl->virt->fillRectI(impl, &rect); } |
1043 | //! Fills a rectangle `rect`. |
1044 | BL_INLINE BLResult fillRect(const BLRect& rect) noexcept { return impl->virt->fillRectD(impl, &rect); } |
1045 | //! \overload |
1046 | BL_INLINE BLResult fillRect(double x, double y, double w, double h) noexcept { return fillRect(BLRect(x, y, w, h)); } |
1047 | |
1048 | //! Fills a circle. |
1049 | BL_INLINE BLResult fillCircle(const BLCircle& circle) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_CIRCLE, &circle); } |
1050 | //! \overload |
1051 | BL_INLINE BLResult fillCircle(double cx, double cy, double r) noexcept { return fillCircle(BLCircle(cx, cy, r)); } |
1052 | |
1053 | //! Fills an ellipse. |
1054 | BL_INLINE BLResult fillEllipse(const BLEllipse& ellipse) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ELLIPSE, &ellipse); } |
1055 | //! \overload |
1056 | BL_INLINE BLResult fillEllipse(double cx, double cy, double rx, double ry) noexcept { return fillEllipse(BLEllipse(cx, cy, rx, ry)); } |
1057 | |
1058 | //! Fills a rounded rectangle. |
1059 | BL_INLINE BLResult fillRoundRect(const BLRoundRect& rr) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ROUND_RECT, &rr); } |
1060 | //! \overload |
1061 | BL_INLINE BLResult fillRoundRect(const BLRect& rect, double r) noexcept { return fillRoundRect(BLRoundRect(rect.x, rect.y, rect.w, rect.h, r)); } |
1062 | //! \overload |
1063 | BL_INLINE BLResult fillRoundRect(const BLRect& rect, double rx, double ry) noexcept { return fillRoundRect(BLRoundRect(rect.x, rect.y, rect.w, rect.h, rx, ry)); } |
1064 | //! \overload |
1065 | BL_INLINE BLResult fillRoundRect(double x, double y, double w, double h, double r) noexcept { return fillRoundRect(BLRoundRect(x, y, w, h, r)); } |
1066 | //! \overload |
1067 | BL_INLINE BLResult fillRoundRect(double x, double y, double w, double h, double rx, double ry) noexcept { return fillRoundRect(BLRoundRect(x, y, w, h, rx, ry)); } |
1068 | |
1069 | //! Fills a chord. |
1070 | BL_INLINE BLResult fillChord(const BLArc& chord) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_CHORD, &chord); } |
1071 | //! \overload |
1072 | BL_INLINE BLResult fillChord(double cx, double cy, double r, double start, double sweep) noexcept { return fillChord(BLArc(cx, cy, r, r, start, sweep)); } |
1073 | //! \overload |
1074 | BL_INLINE BLResult fillChord(double cx, double cy, double rx, double ry, double start, double sweep) noexcept { return fillChord(BLArc(cx, cy, rx, ry, start, sweep)); } |
1075 | |
1076 | //! Fills a pie. |
1077 | BL_INLINE BLResult fillPie(const BLArc& pie) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_PIE, &pie); } |
1078 | //! \overload |
1079 | BL_INLINE BLResult fillPie(double cx, double cy, double r, double start, double sweep) noexcept { return fillPie(BLArc(cx, cy, r, r, start, sweep)); } |
1080 | //! \overload |
1081 | BL_INLINE BLResult fillPie(double cx, double cy, double rx, double ry, double start, double sweep) noexcept { return fillPie(BLArc(cx, cy, rx, ry, start, sweep)); } |
1082 | |
1083 | //! Fills a triangle. |
1084 | BL_INLINE BLResult fillTriangle(const BLTriangle& triangle) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_TRIANGLE, &triangle); } |
1085 | //! \overload |
1086 | BL_INLINE BLResult fillTriangle(double x0, double y0, double x1, double y1, double x2, double y2) noexcept { return fillTriangle(BLTriangle(x0, y0, x1, y1, x2, y2)); } |
1087 | |
1088 | //! Fills a polygon. |
1089 | BL_INLINE BLResult fillPolygon(const BLArrayView<BLPoint>& poly) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_POLYGOND, &poly); } |
1090 | //! \overload |
1091 | BL_INLINE BLResult fillPolygon(const BLPoint* poly, size_t n) noexcept { return fillPolygon(BLArrayView<BLPoint>{poly, n}); } |
1092 | |
1093 | //! Fills a polygon. |
1094 | BL_INLINE BLResult fillPolygon(const BLArrayView<BLPointI>& poly) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_POLYGONI, &poly); } |
1095 | //! \overload |
1096 | BL_INLINE BLResult fillPolygon(const BLPointI* poly, size_t n) noexcept { return fillPolygon(BLArrayView<BLPointI>{poly, n}); } |
1097 | |
1098 | //! Fills an array of boxes. |
1099 | BL_INLINE BLResult fillBoxArray(const BLArrayView<BLBox>& array) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXD, &array); } |
1100 | //! \overload |
1101 | BL_INLINE BLResult fillBoxArray(const BLBox* data, size_t n) noexcept { return fillBoxArray(BLArrayView<BLBox>{data, n}); } |
1102 | |
1103 | //! Fills an array of boxes. |
1104 | BL_INLINE BLResult fillBoxArray(const BLArrayView<BLBoxI>& array) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXI, &array); } |
1105 | //! \overload |
1106 | BL_INLINE BLResult fillBoxArray(const BLBoxI* data, size_t n) noexcept { return fillBoxArray(BLArrayView<BLBoxI>{data, n}); } |
1107 | |
1108 | //! Fills an array of rectangles. |
1109 | BL_INLINE BLResult fillRectArray(const BLArrayView<BLRect>& array) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTD, &array); } |
1110 | //! \overload |
1111 | BL_INLINE BLResult fillRectArray(const BLRect* data, size_t n) noexcept { return fillRectArray(BLArrayView<BLRect>{data, n}); } |
1112 | |
1113 | //! Fills an array of rectangles. |
1114 | BL_INLINE BLResult fillRectArray(const BLArrayView<BLRectI>& array) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTI, &array); } |
1115 | //! \overload |
1116 | BL_INLINE BLResult fillRectArray(const BLRectI* data, size_t n) noexcept { return fillRectArray(BLArrayView<BLRectI>{data, n}); } |
1117 | |
1118 | //! Fills the given `region`. |
1119 | BL_INLINE BLResult fillRegion(const BLRegion& region) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_REGION, ®ion); } |
1120 | |
1121 | //! Fills the given `path`. |
1122 | BL_INLINE BLResult fillPath(const BLPath& path) noexcept { return fillGeometry(BL_GEOMETRY_TYPE_PATH, &path); } |
1123 | |
1124 | //! Fills the passed UTF-8 text by using the given `font`. |
1125 | BL_INLINE BLResult fillUtf8Text(const BLPointI& dst, const BLFont& font, const char* text, size_t size = SIZE_MAX) noexcept { |
1126 | return impl->virt->fillTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF8); |
1127 | } |
1128 | |
1129 | //! Fills the passed UTF-8 text by using the given `font`. |
1130 | BL_INLINE BLResult fillUtf8Text(const BLPoint& dst, const BLFont& font, const char* text, size_t size = SIZE_MAX) noexcept { |
1131 | return impl->virt->fillTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF8); |
1132 | } |
1133 | |
1134 | //! Fills the passed UTF-16 text by using the given `font`. |
1135 | BL_INLINE BLResult fillUtf16Text(const BLPointI& dst, const BLFont& font, const uint16_t* text, size_t size = SIZE_MAX) noexcept { |
1136 | return impl->virt->fillTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF16); |
1137 | } |
1138 | |
1139 | //! Fills the passed UTF-16 text by using the given `font`. |
1140 | BL_INLINE BLResult fillUtf16Text(const BLPoint& dst, const BLFont& font, const uint16_t* text, size_t size = SIZE_MAX) noexcept { |
1141 | return impl->virt->fillTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF16); |
1142 | } |
1143 | |
1144 | //! Fills the passed UTF-32 text by using the given `font`. |
1145 | BL_INLINE BLResult fillUtf32Text(const BLPointI& dst, const BLFont& font, const uint32_t* text, size_t size = SIZE_MAX) noexcept { |
1146 | return impl->virt->fillTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF32); |
1147 | } |
1148 | |
1149 | //! Fills the passed UTF-32 text by using the given `font`. |
1150 | BL_INLINE BLResult fillUtf32Text(const BLPoint& dst, const BLFont& font, const uint32_t* text, size_t size = SIZE_MAX) noexcept { |
1151 | return impl->virt->fillTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF32); |
1152 | } |
1153 | |
1154 | //! Fills the passed `glyphRun` by using the given `font`. |
1155 | BL_INLINE BLResult fillGlyphRun(const BLPointI& dst, const BLFont& font, const BLGlyphRun& glyphRun) noexcept { |
1156 | return impl->virt->fillGlyphRunI(impl, &dst, &font, &glyphRun); |
1157 | } |
1158 | |
1159 | //! Fills the passed `glyphRun` by using the given `font`. |
1160 | BL_INLINE BLResult fillGlyphRun(const BLPoint& dst, const BLFont& font, const BLGlyphRun& glyphRun) noexcept { |
1161 | return impl->virt->fillGlyphRunD(impl, &dst, &font, &glyphRun); |
1162 | } |
1163 | |
1164 | //! \} |
1165 | |
1166 | //! \name Stroke Operations |
1167 | //! \{ |
1168 | |
1169 | //! Strokes the passed geometry specified by `geometryType` and `geometryData` [Internal]. |
1170 | BL_INLINE BLResult strokeGeometry(uint32_t geometryType, const void* geometryData) noexcept { return impl->virt->strokeGeometry(impl, geometryType, geometryData); } |
1171 | |
1172 | //! Strokes a box. |
1173 | BL_INLINE BLResult strokeBox(const BLBox& box) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_BOXD, &box); } |
1174 | // \overload |
1175 | BL_INLINE BLResult strokeBox(const BLBoxI& box) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_BOXI, &box); } |
1176 | // \overload |
1177 | BL_INLINE BLResult strokeBox(double x0, double y0, double x1, double y1) noexcept { return strokeBox(BLBox(x0, y0, x1, y1)); } |
1178 | |
1179 | //! Strokes a rectangle. |
1180 | BL_INLINE BLResult strokeRect(const BLRect& rect) noexcept { return impl->virt->strokeRectD(impl, &rect); } |
1181 | //! \overload |
1182 | BL_INLINE BLResult strokeRect(const BLRectI& rect) noexcept { return impl->virt->strokeRectI(impl, &rect); } |
1183 | //! \overload |
1184 | BL_INLINE BLResult strokeRect(double x, double y, double w, double h) noexcept { return strokeRect(BLRect(x, y, w, h)); } |
1185 | |
1186 | //! Strokes a line. |
1187 | BL_INLINE BLResult strokeLine(const BLLine& line) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_LINE, &line); } |
1188 | //! \overload |
1189 | BL_INLINE BLResult strokeLine(const BLPoint& p0, const BLPoint& p1) noexcept { return strokeLine(BLLine(p0.x, p0.y, p1.x, p1.y)); } |
1190 | //! \overload |
1191 | BL_INLINE BLResult strokeLine(double x0, double y0, double x1, double y1) noexcept { return strokeLine(BLLine(x0, y0, x1, y1)); } |
1192 | |
1193 | //! Strokes a circle. |
1194 | BL_INLINE BLResult strokeCircle(const BLCircle& circle) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_CIRCLE, &circle); } |
1195 | //! \overload |
1196 | BL_INLINE BLResult strokeCircle(double cx, double cy, double r) noexcept { return strokeCircle(BLCircle(cx, cy, r)); } |
1197 | |
1198 | //! Strokes an ellipse. |
1199 | BL_INLINE BLResult strokeEllipse(const BLEllipse& ellipse) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ELLIPSE, &ellipse); } |
1200 | //! \overload |
1201 | BL_INLINE BLResult strokeEllipse(double cx, double cy, double rx, double ry) noexcept { return strokeEllipse(BLEllipse(cx, cy, rx, ry)); } |
1202 | |
1203 | //! Strokes a round. |
1204 | BL_INLINE BLResult strokeRoundRect(const BLRoundRect& rr) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ROUND_RECT, &rr); } |
1205 | //! \overload |
1206 | BL_INLINE BLResult strokeRoundRect(const BLRect& rect, double r) noexcept { return strokeRoundRect(BLRoundRect(rect.x, rect.y, rect.w, rect.h, r)); } |
1207 | //! \overload |
1208 | BL_INLINE BLResult strokeRoundRect(const BLRect& rect, double rx, double ry) noexcept { return strokeRoundRect(BLRoundRect(rect.x, rect.y, rect.w, rect.h, rx, ry)); } |
1209 | //! \overload |
1210 | BL_INLINE BLResult strokeRoundRect(double x, double y, double w, double h, double r) noexcept { return strokeRoundRect(BLRoundRect(x, y, w, h, r)); } |
1211 | //! \overload |
1212 | BL_INLINE BLResult strokeRoundRect(double x, double y, double w, double h, double rx, double ry) noexcept { return strokeRoundRect(BLRoundRect(x, y, w, h, rx, ry)); } |
1213 | |
1214 | //! Strokes an arc. |
1215 | BL_INLINE BLResult strokeArc(const BLArc& arc) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ARC, &arc); } |
1216 | //! \overload |
1217 | BL_INLINE BLResult strokeArc(double cx, double cy, double r, double start, double sweep) noexcept { return strokeArc(BLArc(cx, cy, r, r, start, sweep)); } |
1218 | //! \overload |
1219 | BL_INLINE BLResult strokeArc(double cx, double cy, double rx, double ry, double start, double sweep) noexcept { return strokeArc(BLArc(cx, cy, rx, ry, start, sweep)); } |
1220 | |
1221 | //! Strokes a chord. |
1222 | BL_INLINE BLResult strokeChord(const BLArc& chord) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_CHORD, &chord); } |
1223 | //! \overload |
1224 | BL_INLINE BLResult strokeChord(double cx, double cy, double r, double start, double sweep) noexcept { return strokeChord(BLArc(cx, cy, r, r, start, sweep)); } |
1225 | //! \overload |
1226 | BL_INLINE BLResult strokeChord(double cx, double cy, double rx, double ry, double start, double sweep) noexcept { return strokeChord(BLArc(cx, cy, rx, ry, start, sweep)); } |
1227 | |
1228 | //! Strokes a pie. |
1229 | BL_INLINE BLResult strokePie(const BLArc& pie) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_PIE, &pie); } |
1230 | //! \overload |
1231 | BL_INLINE BLResult strokePie(double cx, double cy, double r, double start, double sweep) noexcept { return strokePie(BLArc(cx, cy, r, r, start, sweep)); } |
1232 | //! \overload |
1233 | BL_INLINE BLResult strokePie(double cx, double cy, double rx, double ry, double start, double sweep) noexcept { return strokePie(BLArc(cx, cy, rx, ry, start, sweep)); } |
1234 | |
1235 | //! Strokes a triangle. |
1236 | BL_INLINE BLResult strokeTriangle(const BLTriangle& triangle) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_TRIANGLE, &triangle); } |
1237 | //! \overload |
1238 | BL_INLINE BLResult strokeTriangle(double x0, double y0, double x1, double y1, double x2, double y2) noexcept { return strokeTriangle(BLTriangle(x0, y0, x1, y1, x2, y2)); } |
1239 | |
1240 | //! Strokes a polyline. |
1241 | BL_INLINE BLResult strokePolyline(const BLArrayView<BLPoint>& poly) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_POLYLINED, &poly); } |
1242 | //! \overload |
1243 | BL_INLINE BLResult strokePolyline(const BLPoint* poly, size_t n) noexcept { return strokePolyline(BLArrayView<BLPoint>{poly, n}); } |
1244 | |
1245 | //! Strokes a polyline. |
1246 | BL_INLINE BLResult strokePolyline(const BLArrayView<BLPointI>& poly) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_POLYLINED, &poly); } |
1247 | //! \overload |
1248 | BL_INLINE BLResult strokePolyline(const BLPointI* poly, size_t n) noexcept { return strokePolyline(BLArrayView<BLPointI>{poly, n}); } |
1249 | |
1250 | //! Strokes a polygon. |
1251 | BL_INLINE BLResult strokePolygon(const BLArrayView<BLPoint>& poly) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_POLYGOND, &poly); } |
1252 | //! \overload |
1253 | BL_INLINE BLResult strokePolygon(const BLPoint* poly, size_t n) noexcept { return strokePolygon(BLArrayView<BLPoint>{poly, n}); } |
1254 | |
1255 | //! Strokes a polygon. |
1256 | BL_INLINE BLResult strokePolygon(const BLArrayView<BLPointI>& poly) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_POLYGONI, &poly); } |
1257 | //! \overload |
1258 | BL_INLINE BLResult strokePolygon(const BLPointI* poly, size_t n) noexcept { return strokePolygon(BLArrayView<BLPointI>{poly, n}); } |
1259 | |
1260 | //! Strokes an array of boxes. |
1261 | BL_INLINE BLResult strokeBoxArray(const BLArrayView<BLBox>& array) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXD, &array); } |
1262 | //! \overload |
1263 | BL_INLINE BLResult strokeBoxArray(const BLBox* data, size_t n) noexcept { return strokeBoxArray(BLArrayView<BLBox>{data, n}); } |
1264 | |
1265 | //! Strokes an array of boxes. |
1266 | BL_INLINE BLResult strokeBoxArray(const BLArrayView<BLBoxI>& array) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXI, &array); } |
1267 | //! \overload |
1268 | BL_INLINE BLResult strokeBoxArray(const BLBoxI* data, size_t n) noexcept { return strokeBoxArray(BLArrayView<BLBoxI>{data, n}); } |
1269 | |
1270 | //! Strokes an array of rectangles. |
1271 | BL_INLINE BLResult strokeRectArray(const BLArrayView<BLRect>& array) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTD, &array); } |
1272 | //! \overload |
1273 | BL_INLINE BLResult strokeRectArray(const BLRect* data, size_t n) noexcept { return strokeRectArray(BLArrayView<BLRect>{data, n}); } |
1274 | |
1275 | //! Strokes an array of rectangles. |
1276 | BL_INLINE BLResult strokeRectArray(const BLArrayView<BLRectI>& array) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTI, &array); } |
1277 | //! \overload |
1278 | BL_INLINE BLResult strokeRectArray(const BLRectI* data, size_t n) noexcept { return strokeRectArray(BLArrayView<BLRectI>{data, n}); } |
1279 | |
1280 | //! Strokes a path. |
1281 | BL_INLINE BLResult strokePath(const BLPath& path) noexcept { return strokeGeometry(BL_GEOMETRY_TYPE_PATH, &path); } |
1282 | |
1283 | //! Strokes the passed UTF-8 text by using the given `font`. |
1284 | BL_INLINE BLResult strokeUtf8Text(const BLPointI& dst, const BLFont& font, const char* text, size_t size = SIZE_MAX) noexcept { |
1285 | return impl->virt->strokeTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF8); |
1286 | } |
1287 | |
1288 | //! Strokes the passed UTF-8 text by using the given `font`. |
1289 | BL_INLINE BLResult strokeUtf8Text(const BLPoint& dst, const BLFont& font, const char* text, size_t size = SIZE_MAX) noexcept { |
1290 | return impl->virt->strokeTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF8); |
1291 | } |
1292 | |
1293 | //! Strokes the passed UTF-16 text by using the given `font`. |
1294 | BL_INLINE BLResult strokeUtf16Text(const BLPointI& dst, const BLFont& font, const uint16_t* text, size_t size = SIZE_MAX) noexcept { |
1295 | return impl->virt->strokeTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF16); |
1296 | } |
1297 | |
1298 | //! Strokes the passed UTF-16 text by using the given `font`. |
1299 | BL_INLINE BLResult strokeUtf16Text(const BLPoint& dst, const BLFont& font, const uint16_t* text, size_t size = SIZE_MAX) noexcept { |
1300 | return impl->virt->strokeTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF16); |
1301 | } |
1302 | |
1303 | //! Strokes the passed UTF-32 text by using the given `font`. |
1304 | BL_INLINE BLResult strokeUtf32Text(const BLPointI& dst, const BLFont& font, const uint32_t* text, size_t size = SIZE_MAX) noexcept { |
1305 | return impl->virt->strokeTextI(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF32); |
1306 | } |
1307 | |
1308 | //! Strokes the passed UTF-32 text by using the given `font`. |
1309 | BL_INLINE BLResult strokeUtf32Text(const BLPoint& dst, const BLFont& font, const uint32_t* text, size_t size = SIZE_MAX) noexcept { |
1310 | return impl->virt->strokeTextD(impl, &dst, &font, text, size, BL_TEXT_ENCODING_UTF32); |
1311 | } |
1312 | |
1313 | //! Strokes the passed `glyphRun` by using the given `font`. |
1314 | BL_INLINE BLResult strokeGlyphRun(const BLPointI& dst, const BLFont& font, const BLGlyphRun& glyphRun) noexcept { |
1315 | return impl->virt->strokeGlyphRunI(impl, &dst, &font, &glyphRun); |
1316 | } |
1317 | |
1318 | //! Strokes the passed `glyphRun` by using the given `font`. |
1319 | BL_INLINE BLResult strokeGlyphRun(const BLPoint& dst, const BLFont& font, const BLGlyphRun& glyphRun) noexcept { |
1320 | return impl->virt->strokeGlyphRunD(impl, &dst, &font, &glyphRun); |
1321 | } |
1322 | |
1323 | //! \} |
1324 | |
1325 | //! \name Image Blitting |
1326 | //! \{ |
1327 | |
1328 | //! Blits source image `src` at coordinates specified by `dst`.. |
1329 | BL_INLINE BLResult blitImage(const BLPoint& dst, const BLImage& src) noexcept { return impl->virt->blitImageD(impl, &dst, &src, nullptr); } |
1330 | //! Blits an area of source image `src` specified by `srcArea` at coordinates specified by `dst`. |
1331 | BL_INLINE BLResult blitImage(const BLPoint& dst, const BLImage& src, const BLRectI& srcArea) noexcept { return impl->virt->blitImageD(impl, &dst, &src, &srcArea); } |
1332 | |
1333 | //! Blits source image `src` at coordinates specified by `dst`. (int coordinates). |
1334 | BL_INLINE BLResult blitImage(const BLPointI& dst, const BLImage& src) noexcept { return impl->virt->blitImageI(impl, &dst, &src, nullptr); } |
1335 | //! Blits an area in source image `src` specified by `srcArea` at coordinates specified by `dst`. (int coordinates). |
1336 | BL_INLINE BLResult blitImage(const BLPointI& dst, const BLImage& src, const BLRectI& srcArea) noexcept { return impl->virt->blitImageI(impl, &dst, &src, &srcArea); } |
1337 | |
1338 | //! Blits a source image `src` scaled to fit into `dst` rectangle. |
1339 | BL_INLINE BLResult blitImage(const BLRect& dst, const BLImage& src) noexcept { return impl->virt->blitScaledImageD(impl, &dst, &src, nullptr); } |
1340 | //! Blits an area of source image `src` specified by `srcArea` scaled to fit into `dst` rectangle. |
1341 | BL_INLINE BLResult blitImage(const BLRect& dst, const BLImage& src, const BLRectI& srcArea) noexcept { return impl->virt->blitScaledImageD(impl, &dst, &src, &srcArea); } |
1342 | |
1343 | //! Blits a source image `src` scaled to fit into `dst` rectangle (int coordinates). |
1344 | BL_INLINE BLResult blitImage(const BLRectI& dst, const BLImage& src) noexcept { return impl->virt->blitScaledImageI(impl, &dst, &src, nullptr); } |
1345 | //! Blits an area of source image `src` specified by `srcArea` scaled to fit into `dst` rectangle (int coordinates). |
1346 | BL_INLINE BLResult blitImage(const BLRectI& dst, const BLImage& src, const BLRectI& srcArea) noexcept { return impl->virt->blitScaledImageI(impl, &dst, &src, &srcArea); } |
1347 | |
1348 | //! \} |
1349 | |
1350 | static BL_INLINE const BLContext& none() noexcept { return reinterpret_cast<const BLContext*>(blNone)[kImplType]; } |
1351 | }; |
1352 | #endif |
1353 | |
1354 | //! \} |
1355 | |
1356 | #endif // BLEND2D_BLCONTEXT_H |
1357 | |