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#include "./blapi-build_p.h"
8#include "./blcontext_p.h"
9#include "./blruntime_p.h"
10#include "./raster/blrastercontext_p.h"
11
12// ============================================================================
13// [BLContext - Globals]
14// ============================================================================
15
16BLWrap<BLContextState> blNullContextState;
17BLAtomicUInt64Generator blContextIdGenerator;
18
19static BLContextVirt blNullContextVirt;
20static BLWrap<BLContextImpl> blNullContextImpl;
21
22// ============================================================================
23// [BLContext - Init / Reset]
24// ============================================================================
25
26BLResult blContextInit(BLContextCore* self) noexcept {
27 self->impl = BLContext::none().impl;
28 return BL_SUCCESS;
29}
30
31BLResult blContextInitAs(BLContextCore* self, BLImageCore* image, const BLContextCreateInfo* options) noexcept {
32 self->impl = BLContext::none().impl;
33 return blContextBegin(self, image, options);
34}
35
36BLResult blContextReset(BLContextCore* self) noexcept {
37 BLContextImpl* selfI = self->impl;
38 self->impl = &blNullContextImpl;
39 return blImplReleaseVirt(selfI);
40}
41
42// ============================================================================
43// [BLContext - Assign]
44// ============================================================================
45
46BLResult blContextAssignMove(BLContextCore* self, BLContextCore* other) noexcept {
47 BLContextImpl* selfI = self->impl;
48 BLContextImpl* otherI = other->impl;
49
50 self->impl = otherI;
51 other->impl = &blNullContextImpl;
52
53 return blImplReleaseVirt(selfI);
54}
55
56BLResult blContextAssignWeak(BLContextCore* self, const BLContextCore* other) noexcept {
57 BLContextImpl* selfI = self->impl;
58 BLContextImpl* otherI = other->impl;
59
60 self->impl = blImplIncRef(otherI);
61 return blImplReleaseVirt(selfI);
62}
63
64// ============================================================================
65// [BLContext - Properties]
66// ============================================================================
67
68BLResult blContextGetType(const BLContextCore* self) noexcept {
69 return self->impl->contextType;
70}
71
72// ============================================================================
73// [BLContext - Begin / End]
74// ============================================================================
75
76BLResult blContextBegin(BLContextCore* self, BLImageCore* image, const BLContextCreateInfo* options) noexcept {
77 // Reject empty images.
78 if (blDownCast(image)->empty())
79 return blTraceError(BL_ERROR_INVALID_VALUE);
80
81 // Reject images that already have a writer.
82 if (image->impl->writer != nullptr)
83 return blTraceError(BL_ERROR_BUSY);
84
85 BLContextCreateInfo noOptions {};
86 if (!options)
87 options = &noOptions;
88
89 BLContextImpl* newI;
90 BL_PROPAGATE(blRasterContextImplCreate(&newI, image, options));
91
92 BLContextImpl* oldI = self->impl;
93 self->impl = newI;
94 return blImplReleaseVirt(oldI);
95}
96
97BLResult blContextEnd(BLContextCore* self) noexcept {
98 // Currently mapped to `BLContext::reset()`.
99 return blContextReset(self);
100}
101
102// ============================================================================
103// [BLContext - Flush]
104// ============================================================================
105
106BLResult blContextFlush(BLContextCore* self, uint32_t flags) noexcept {
107 return self->impl->virt->flush(self->impl, flags);
108}
109
110// ============================================================================
111// [BLContext - Save / Restore]
112// ============================================================================
113
114BLResult blContextSave(BLContextCore* self, BLContextCookie* cookie) noexcept {
115 return self->impl->virt->save(self->impl, cookie);
116}
117
118BLResult blContextRestore(BLContextCore* self, const BLContextCookie* cookie) noexcept {
119 return self->impl->virt->restore(self->impl, cookie);
120}
121
122// ============================================================================
123// [BLContext - Transformations]
124// ============================================================================
125
126BLResult blContextGetMetaMatrix(const BLContextCore* self, BLMatrix2D* m) noexcept {
127 *m = self->impl->state->metaMatrix;
128 return BL_SUCCESS;
129}
130
131BLResult blContextGetUserMatrix(const BLContextCore* self, BLMatrix2D* m) noexcept {
132 *m = self->impl->state->userMatrix;
133 return BL_SUCCESS;
134}
135
136BLResult blContextUserToMeta(BLContextCore* self) noexcept {
137 return self->impl->virt->userToMeta(self->impl);
138}
139
140BLResult blContextMatrixOp(BLContextCore* self, uint32_t opType, const void* opData) noexcept {
141 return self->impl->virt->matrixOp(self->impl, opType, opData);
142}
143
144// ============================================================================
145// [BLContext - Rendering Hints]
146// ============================================================================
147
148BLResult blContextSetHint(BLContextCore* self, uint32_t hintType, uint32_t value) noexcept {
149 return self->impl->virt->setHint(self->impl, hintType, value);
150}
151
152BLResult blContextSetHints(BLContextCore* self, const BLContextHints* hints) noexcept {
153 return self->impl->virt->setHints(self->impl, hints);
154}
155
156// ============================================================================
157// [BLContext - Approximation Options]
158// ============================================================================
159
160BLResult blContextSetFlattenMode(BLContextCore* self, uint32_t mode) noexcept {
161 return self->impl->virt->setFlattenMode(self->impl, mode);
162}
163
164BLResult blContextSetFlattenTolerance(BLContextCore* self, double tolerance) noexcept {
165 return self->impl->virt->setFlattenTolerance(self->impl, tolerance);
166}
167
168BLResult blContextSetApproximationOptions(BLContextCore* self, const BLApproximationOptions* options) noexcept {
169 return self->impl->virt->setApproximationOptions(self->impl, options);
170}
171
172// ============================================================================
173// [BLContext - Composition Options]
174// ============================================================================
175
176BLResult blContextSetCompOp(BLContextCore* self, uint32_t compOp) noexcept {
177 return self->impl->virt->setCompOp(self->impl, compOp);
178}
179
180BLResult blContextSetGlobalAlpha(BLContextCore* self, double alpha) noexcept {
181 return self->impl->virt->setGlobalAlpha(self->impl, alpha);
182}
183
184// ============================================================================
185// [BLContext - Fill Options]
186// ============================================================================
187
188BLResult blContextSetFillAlpha(BLContextCore* self, double alpha) noexcept {
189 return self->impl->virt->setStyleAlpha[BL_CONTEXT_OP_TYPE_FILL](self->impl, alpha);
190}
191
192BLResult blContextGetFillStyle(const BLContextCore* self, void* object) noexcept {
193 return self->impl->virt->getStyle[BL_CONTEXT_OP_TYPE_FILL](self->impl, object);
194}
195
196BLResult blContextGetFillStyleRgba32(const BLContextCore* self, uint32_t* rgba32) noexcept {
197 return self->impl->virt->getStyleRgba32[BL_CONTEXT_OP_TYPE_FILL](self->impl, rgba32);
198}
199
200BLResult blContextGetFillStyleRgba64(const BLContextCore* self, uint64_t* rgba64) noexcept {
201 return self->impl->virt->getStyleRgba64[BL_CONTEXT_OP_TYPE_FILL](self->impl, rgba64);
202}
203
204BLResult blContextSetFillStyle(BLContextCore* self, const void* object) noexcept {
205 return self->impl->virt->setStyle[BL_CONTEXT_OP_TYPE_FILL](self->impl, object);
206}
207
208BLResult blContextSetFillStyleRgba32(BLContextCore* self, uint32_t rgba32) noexcept {
209 return self->impl->virt->setStyleRgba32[BL_CONTEXT_OP_TYPE_FILL](self->impl, rgba32);
210}
211
212BLResult blContextSetFillStyleRgba64(BLContextCore* self, uint64_t rgba64) noexcept {
213 return self->impl->virt->setStyleRgba64[BL_CONTEXT_OP_TYPE_FILL](self->impl, rgba64);
214}
215
216BLResult blContextSetFillRule(BLContextCore* self, uint32_t fillRule) noexcept {
217 return self->impl->virt->setFillRule(self->impl, fillRule);
218}
219
220// ============================================================================
221// [BLContext - Stroke Options]
222// ============================================================================
223
224BLResult blContextSetStrokeAlpha(BLContextCore* self, double alpha) noexcept {
225 return self->impl->virt->setStyleAlpha[BL_CONTEXT_OP_TYPE_STROKE](self->impl, alpha);
226}
227
228BLResult blContextGetStrokeStyle(const BLContextCore* self, void* object) noexcept {
229 return self->impl->virt->getStyle[BL_CONTEXT_OP_TYPE_STROKE](self->impl, object);
230}
231
232BLResult blContextGetStrokeStyleRgba32(const BLContextCore* self, uint32_t* rgba32) noexcept {
233 return self->impl->virt->getStyleRgba32[BL_CONTEXT_OP_TYPE_STROKE](self->impl, rgba32);
234}
235
236BLResult blContextGetStrokeStyleRgba64(const BLContextCore* self, uint64_t* rgba64) noexcept {
237 return self->impl->virt->getStyleRgba64[BL_CONTEXT_OP_TYPE_STROKE](self->impl, rgba64);
238}
239
240BLResult blContextSetStrokeStyle(BLContextCore* self, const void* object) noexcept {
241 return self->impl->virt->setStyle[BL_CONTEXT_OP_TYPE_STROKE](self->impl, object);
242}
243
244BLResult blContextSetStrokeStyleRgba32(BLContextCore* self, uint32_t rgba32) noexcept {
245 return self->impl->virt->setStyleRgba32[BL_CONTEXT_OP_TYPE_STROKE](self->impl, rgba32);
246}
247
248BLResult blContextSetStrokeStyleRgba64(BLContextCore* self, uint64_t rgba64) noexcept {
249 return self->impl->virt->setStyleRgba64[BL_CONTEXT_OP_TYPE_STROKE](self->impl, rgba64);
250}
251
252BLResult blContextSetStrokeWidth(BLContextCore* self, double width) noexcept {
253 return self->impl->virt->setStrokeWidth(self->impl, width);
254}
255
256BLResult blContextSetStrokeMiterLimit(BLContextCore* self, double miterLimit) noexcept {
257 return self->impl->virt->setStrokeMiterLimit(self->impl, miterLimit);
258}
259
260BLResult blContextSetStrokeCap(BLContextCore* self, uint32_t position, uint32_t strokeCap) noexcept {
261 return self->impl->virt->setStrokeCap(self->impl, position, strokeCap);
262}
263
264BLResult blContextSetStrokeCaps(BLContextCore* self, uint32_t strokeCap) noexcept {
265 return self->impl->virt->setStrokeCaps(self->impl, strokeCap);
266}
267
268BLResult blContextSetStrokeJoin(BLContextCore* self, uint32_t strokeJoin) noexcept {
269 return self->impl->virt->setStrokeJoin(self->impl, strokeJoin);
270}
271
272BLResult blContextSetStrokeDashOffset(BLContextCore* self, double dashOffset) noexcept {
273 return self->impl->virt->setStrokeDashOffset(self->impl, dashOffset);
274}
275
276BLResult blContextSetStrokeDashArray(BLContextCore* self, const BLArrayCore* dashArray) noexcept {
277 return self->impl->virt->setStrokeDashArray(self->impl, dashArray);
278}
279
280BLResult blContextSetStrokeTransformOrder(BLContextCore* self, uint32_t transformOrder) noexcept {
281 return self->impl->virt->setStrokeTransformOrder(self->impl, transformOrder);
282}
283
284BLResult blContextGetStrokeOptions(const BLContextCore* self, BLStrokeOptionsCore* options) noexcept {
285 return blStrokeOptionsAssignWeak(options, &self->impl->state->strokeOptions);
286}
287
288BLResult blContextSetStrokeOptions(BLContextCore* self, const BLStrokeOptionsCore* options) noexcept {
289 return self->impl->virt->setStrokeOptions(self->impl, options);
290}
291
292// ============================================================================
293// [BLContext - Clip Operations]
294// ============================================================================
295
296BLResult blContextClipToRectI(BLContextCore* self, const BLRectI* rect) noexcept {
297 return self->impl->virt->clipToRectI(self->impl, rect);
298}
299
300BLResult blContextClipToRectD(BLContextCore* self, const BLRect* rect) noexcept {
301 return self->impl->virt->clipToRectD(self->impl, rect);
302}
303
304BLResult blContextRestoreClipping(BLContextCore* self) noexcept {
305 return self->impl->virt->restoreClipping(self->impl);
306}
307
308// ============================================================================
309// [BLContext - Clear Operations]
310// ============================================================================
311
312BLResult blContextClearAll(BLContextCore* self) noexcept {
313 return self->impl->virt->clearAll(self->impl);
314}
315
316BLResult blContextClearRectI(BLContextCore* self, const BLRectI* rect) noexcept {
317 return self->impl->virt->clearRectI(self->impl, rect);
318}
319
320BLResult blContextClearRectD(BLContextCore* self, const BLRect* rect) noexcept {
321 return self->impl->virt->clearRectD(self->impl, rect);
322}
323
324// ============================================================================
325// [BLContext - Fill Operations]
326// ============================================================================
327
328BLResult blContextFillAll(BLContextCore* self) noexcept {
329 return self->impl->virt->fillAll(self->impl);
330}
331
332BLResult blContextFillRectI(BLContextCore* self, const BLRectI* rect) noexcept {
333 return self->impl->virt->fillRectI(self->impl, rect);
334}
335
336BLResult blContextFillRectD(BLContextCore* self, const BLRect* rect) noexcept {
337 return self->impl->virt->fillRectD(self->impl, rect);
338}
339
340BLResult blContextFillPathD(BLContextCore* self, const BLPathCore* path) noexcept {
341 return self->impl->virt->fillPathD(self->impl, path);
342}
343
344BLResult blContextFillGeometry(BLContextCore* self, uint32_t geometryType, const void* geometryData) noexcept {
345 return self->impl->virt->fillGeometry(self->impl, geometryType, geometryData);
346}
347
348BLResult blContextFillTextI(BLContextCore* self, const BLPointI* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) noexcept {
349 return self->impl->virt->fillTextI(self->impl, pt, font, text, size, encoding);
350}
351
352BLResult blContextFillTextD(BLContextCore* self, const BLPoint* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) noexcept {
353 return self->impl->virt->fillTextD(self->impl, pt, font, text, size, encoding);
354}
355
356BLResult blContextFillGlyphRunI(BLContextCore* self, const BLPointI* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) noexcept {
357 return self->impl->virt->fillGlyphRunI(self->impl, pt, font, glyphRun);
358}
359
360BLResult blContextFillGlyphRunD(BLContextCore* self, const BLPoint* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) noexcept {
361 return self->impl->virt->fillGlyphRunD(self->impl, pt, font, glyphRun);
362}
363
364// ============================================================================
365// [BLContext - Stroke Operations]
366// ============================================================================
367
368BLResult blContextStrokeRectI(BLContextCore* self, const BLRectI* rect) noexcept {
369 return self->impl->virt->strokeRectI(self->impl, rect);
370}
371
372BLResult blContextStrokeRectD(BLContextCore* self, const BLRect* rect) noexcept {
373 return self->impl->virt->strokeRectD(self->impl, rect);
374}
375
376BLResult blContextStrokePathD(BLContextCore* self, const BLPathCore* path) noexcept {
377 return self->impl->virt->strokePathD(self->impl, path);
378}
379
380BLResult blContextStrokeGeometry(BLContextCore* self, uint32_t geometryType, const void* geometryData) noexcept {
381 return self->impl->virt->strokeGeometry(self->impl, geometryType, geometryData);
382}
383
384BLResult blContextStrokeTextI(BLContextCore* self, const BLPointI* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) noexcept {
385 return self->impl->virt->strokeTextI(self->impl, pt, font, text, size, encoding);
386}
387
388BLResult blContextStrokeTextD(BLContextCore* self, const BLPoint* pt, const BLFontCore* font, const void* text, size_t size, uint32_t encoding) noexcept {
389 return self->impl->virt->strokeTextD(self->impl, pt, font, text, size, encoding);
390}
391
392BLResult blContextStrokeGlyphRunI(BLContextCore* self, const BLPointI* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) noexcept {
393 return self->impl->virt->strokeGlyphRunI(self->impl, pt, font, glyphRun);
394}
395
396BLResult blContextStrokeGlyphRunD(BLContextCore* self, const BLPoint* pt, const BLFontCore* font, const BLGlyphRun* glyphRun) noexcept {
397 return self->impl->virt->strokeGlyphRunD(self->impl, pt, font, glyphRun);
398}
399
400// ============================================================================
401// [BLContext - Blit Operations]
402// ============================================================================
403
404BLResult blContextBlitImageI(BLContextCore* self, const BLPointI* pt, const BLImageCore* img, const BLRectI* imgArea) noexcept {
405 return self->impl->virt->blitImageI(self->impl, pt, img, imgArea);
406}
407
408BLResult blContextBlitImageD(BLContextCore* self, const BLPoint* pt, const BLImageCore* img, const BLRectI* imgArea) noexcept {
409 return self->impl->virt->blitImageD(self->impl, pt, img, imgArea);
410}
411
412BLResult blContextBlitScaledImageI(BLContextCore* self, const BLRectI* rect, const BLImageCore* img, const BLRectI* imgArea) noexcept {
413 return self->impl->virt->blitScaledImageI(self->impl, rect, img, imgArea);
414}
415
416BLResult blContextBlitScaledImageD(BLContextCore* self, const BLRect* rect, const BLImageCore* img, const BLRectI* imgArea) noexcept {
417 return self->impl->virt->blitScaledImageD(self->impl, rect, img, imgArea);
418}
419
420// ============================================================================
421// [BLNullContext - Impl]
422// ============================================================================
423
424BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS)
425
426static BLResult BL_CDECL blNullContextImplNop(BLContextImpl*) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
427static BLResult BL_CDECL blNullContextImplU32(BLContextImpl*, uint32_t) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
428static BLResult BL_CDECL blNullContextImplU64(BLContextImpl*, uint64_t) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
429static BLResult BL_CDECL blNullContextImplDbl(BLContextImpl*, double) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
430static BLResult BL_CDECL blNullContextImplPtr(BLContextImpl*, const void*) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
431static BLResult BL_CDECL blNullContextImplU32Ptr(BLContextImpl*, const void*) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
432static BLResult BL_CDECL blNullContextImplU32U32(BLContextImpl*, uint32_t, uint32_t) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
433static BLResult BL_CDECL blNullContextImplText(BLContextImpl*, const void*, const BLFontCore*, const void*, size_t, uint32_t) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
434static BLResult BL_CDECL blNullContextImplGlyphRun(BLContextImpl*, const void*, const BLFontCore*, const BLGlyphRun*) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
435static BLResult BL_CDECL blNullContextImplBlit(BLContextImpl*, const void*, const BLImageCore*, const BLRectI*) noexcept { return blTraceError(BL_ERROR_INVALID_STATE); }
436
437BL_DIAGNOSTIC_POP
438
439// ============================================================================
440// [BLContext - Runtime Init]
441// ============================================================================
442
443void blContextRtInit(BLRuntimeContext* rt) noexcept {
444 BL_UNUSED(rt);
445
446 constexpr uint32_t F = BL_CONTEXT_OP_TYPE_FILL;
447 constexpr uint32_t S = BL_CONTEXT_OP_TYPE_STROKE;
448
449 // Initialize null context state.
450 blContextStateInit(&blNullContextState);
451
452 // Initialize null context virtual functions.
453 BLContextVirt* virt = &blNullContextVirt;
454
455 blAssignFunc(&virt->destroy , blNullContextImplNop);
456 blAssignFunc(&virt->flush , blNullContextImplU32);
457
458 blAssignFunc(&virt->save , blNullContextImplPtr);
459 blAssignFunc(&virt->restore , blNullContextImplPtr);
460
461 blAssignFunc(&virt->userToMeta , blNullContextImplNop);
462 blAssignFunc(&virt->matrixOp , blNullContextImplU32Ptr);
463
464 blAssignFunc(&virt->setHint , blNullContextImplU32U32);
465 blAssignFunc(&virt->setHints , blNullContextImplPtr);
466
467 blAssignFunc(&virt->setFlattenMode , blNullContextImplU32);
468 blAssignFunc(&virt->setFlattenTolerance , blNullContextImplDbl);
469 blAssignFunc(&virt->setApproximationOptions, blNullContextImplPtr);
470
471 blAssignFunc(&virt->setCompOp , blNullContextImplU32);
472 blAssignFunc(&virt->setGlobalAlpha , blNullContextImplDbl);
473
474 blAssignFunc(&virt->setStyleAlpha[F] , blNullContextImplDbl);
475 blAssignFunc(&virt->setStyleAlpha[S] , blNullContextImplDbl);
476 blAssignFunc(&virt->getStyle[F] , blNullContextImplPtr);
477 blAssignFunc(&virt->getStyle[S] , blNullContextImplPtr);
478 blAssignFunc(&virt->getStyleRgba32[F] , blNullContextImplPtr);
479 blAssignFunc(&virt->getStyleRgba32[S] , blNullContextImplPtr);
480 blAssignFunc(&virt->getStyleRgba64[F] , blNullContextImplPtr);
481 blAssignFunc(&virt->getStyleRgba64[S] , blNullContextImplPtr);
482 blAssignFunc(&virt->setStyle[F] , blNullContextImplPtr);
483 blAssignFunc(&virt->setStyle[S] , blNullContextImplPtr);
484 blAssignFunc(&virt->setStyleRgba32[F] , blNullContextImplU32);
485 blAssignFunc(&virt->setStyleRgba32[S] , blNullContextImplU32);
486 blAssignFunc(&virt->setStyleRgba64[F] , blNullContextImplU64);
487 blAssignFunc(&virt->setStyleRgba64[S] , blNullContextImplU64);
488
489 blAssignFunc(&virt->setFillRule , blNullContextImplU32);
490
491 blAssignFunc(&virt->setStrokeWidth , blNullContextImplDbl);
492 blAssignFunc(&virt->setStrokeMiterLimit , blNullContextImplDbl);
493 blAssignFunc(&virt->setStrokeCap , blNullContextImplU32U32);
494 blAssignFunc(&virt->setStrokeCaps , blNullContextImplU32);
495 blAssignFunc(&virt->setStrokeJoin , blNullContextImplU32);
496 blAssignFunc(&virt->setStrokeTransformOrder, blNullContextImplU32);
497 blAssignFunc(&virt->setStrokeDashOffset , blNullContextImplDbl);
498 blAssignFunc(&virt->setStrokeDashArray , blNullContextImplPtr);
499 blAssignFunc(&virt->setStrokeOptions , blNullContextImplPtr);
500
501 blAssignFunc(&virt->clipToRectI , blNullContextImplPtr);
502 blAssignFunc(&virt->clipToRectD , blNullContextImplPtr);
503 blAssignFunc(&virt->restoreClipping , blNullContextImplNop);
504
505 blAssignFunc(&virt->clearAll , blNullContextImplNop);
506 blAssignFunc(&virt->clearRectI , blNullContextImplPtr);
507 blAssignFunc(&virt->clearRectD , blNullContextImplPtr);
508
509 blAssignFunc(&virt->fillAll , blNullContextImplNop);
510 blAssignFunc(&virt->fillRectI , blNullContextImplPtr);
511 blAssignFunc(&virt->fillRectD , blNullContextImplPtr);
512 blAssignFunc(&virt->fillPathD , blNullContextImplPtr);
513 blAssignFunc(&virt->fillGeometry , blNullContextImplU32Ptr);
514 blAssignFunc(&virt->fillTextI , blNullContextImplText);
515 blAssignFunc(&virt->fillTextD , blNullContextImplText);
516 blAssignFunc(&virt->fillGlyphRunI , blNullContextImplGlyphRun);
517 blAssignFunc(&virt->fillGlyphRunD , blNullContextImplGlyphRun);
518
519 blAssignFunc(&virt->strokeRectI , blNullContextImplPtr);
520 blAssignFunc(&virt->strokeRectD , blNullContextImplPtr);
521 blAssignFunc(&virt->strokePathD , blNullContextImplPtr);
522 blAssignFunc(&virt->strokeGeometry , blNullContextImplU32Ptr);
523 blAssignFunc(&virt->strokeTextI , blNullContextImplText);
524 blAssignFunc(&virt->strokeTextD , blNullContextImplText);
525 blAssignFunc(&virt->strokeGlyphRunI , blNullContextImplGlyphRun);
526 blAssignFunc(&virt->strokeGlyphRunD , blNullContextImplGlyphRun);
527
528 blAssignFunc(&virt->blitImageI , blNullContextImplBlit);
529 blAssignFunc(&virt->blitImageD , blNullContextImplBlit);
530 blAssignFunc(&virt->blitScaledImageI , blNullContextImplBlit);
531 blAssignFunc(&virt->blitScaledImageD , blNullContextImplBlit);
532
533 // Initialize null context built-in instance.
534 BLContextImpl* impl = &blNullContextImpl;
535 impl->virt = &blNullContextVirt;
536 impl->state = &blNullContextState;
537 impl->implType = uint8_t(BL_IMPL_TYPE_CONTEXT);
538 impl->implTraits = uint8_t(BL_IMPL_TRAIT_NULL | BL_IMPL_TRAIT_VIRT);
539 blAssignBuiltInNull(impl);
540
541 // Initialize other context implementations.
542 blRasterContextRtInit(rt);
543}
544