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 "./blmatrix_p.h"
9#include "./blpattern_p.h"
10#include "./blruntime_p.h"
11#include "./blsupport_p.h"
12#include "./blvariant.h"
13
14// ============================================================================
15// [Global Variables]
16// ============================================================================
17
18static BLWrap<BLInternalPatternImpl> blNullPatternImpl;
19
20static constexpr const BLRectI blPatternNoArea(0, 0, 0, 0);
21
22// ============================================================================
23// [BLPattern - Internals]
24// ============================================================================
25
26static BL_INLINE BLInternalPatternImpl* blPatternImplNew(const BLImageCore* image, const BLRectI* area, uint32_t extendMode, uint32_t matrixType, const BLMatrix2D* matrix) noexcept {
27 uint16_t memPoolData;
28 BLInternalPatternImpl* impl = blRuntimeAllocImplT<BLInternalPatternImpl>(sizeof(BLInternalPatternImpl), &memPoolData);
29
30 if (BL_UNLIKELY(!impl))
31 return impl;
32
33 blImplInit(impl, BL_IMPL_TYPE_PATTERN, BL_IMPL_TRAIT_MUTABLE, memPoolData);
34 impl->image.impl = blImplIncRef(image->impl);
35 impl->reservedHeader[0] = nullptr;
36 impl->reservedHeader[1] = nullptr;
37 impl->patternType = 0;
38 impl->extendMode = uint8_t(extendMode);
39 impl->matrixType = uint8_t(matrixType);
40 impl->reserved[0] = 0;
41 impl->matrix = *matrix;
42 impl->area = *area;
43
44 return impl;
45}
46
47// Cannot be static, called by `BLVariant` implementation.
48BLResult blPatternImplDelete(BLPatternImpl* impl_) noexcept {
49 BLInternalPatternImpl* impl = blInternalCast(impl_);
50 blImageReset(&impl->image);
51
52 uint8_t* implBase = reinterpret_cast<uint8_t*>(impl);
53 size_t implSize = sizeof(BLInternalPatternImpl);
54 uint32_t implTraits = impl->implTraits;
55 uint32_t memPoolData = impl->memPoolData;
56
57 if (implTraits & BL_IMPL_TRAIT_EXTERNAL) {
58 implSize += sizeof(BLExternalImplPreface);
59 implBase -= sizeof(BLExternalImplPreface);
60 blImplDestroyExternal(impl);
61 }
62
63 if (implTraits & BL_IMPL_TRAIT_FOREIGN)
64 return BL_SUCCESS;
65 else
66 return blRuntimeFreeImpl(implBase, implSize, memPoolData);
67}
68
69static BL_INLINE BLResult blPatternImplRelease(BLInternalPatternImpl* impl) noexcept {
70 if (blImplDecRefAndTest(impl))
71 return blPatternImplDelete(impl);
72 return BL_SUCCESS;
73}
74
75static BL_NOINLINE BLResult blPatternMakeMutableCopyOf(BLPatternCore* self, BLInternalPatternImpl* impl) noexcept {
76 BLInternalPatternImpl* newI = blPatternImplNew(&impl->image, &impl->area, impl->extendMode, impl->matrixType, &impl->matrix);
77 if (BL_UNLIKELY(!newI))
78 return blTraceError(BL_ERROR_OUT_OF_MEMORY);
79
80 BLInternalPatternImpl* oldI = blInternalCast(self->impl);
81 self->impl = newI;
82 return blPatternImplRelease(oldI);
83}
84
85static BL_INLINE BLResult blPatternMakeMutable(BLPatternCore* self) noexcept {
86 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
87 if (!blImplIsMutable(selfI))
88 return blPatternMakeMutableCopyOf(self, selfI);
89 else
90 return BL_SUCCESS;
91}
92
93static BL_INLINE bool blPatternIsAreaValid(const BLRectI* area, int w, int h) noexcept {
94 if ((unsigned(area->x) <= unsigned(w)) &
95 (unsigned(area->y) <= unsigned(h)) &
96 ((unsigned(area->w) - unsigned(area->x)) <= unsigned(w)) &
97 ((unsigned(area->h) - unsigned(area->y)) <= unsigned(h)))
98 return true;
99
100 return false;
101}
102
103// ============================================================================
104// [BLPattern - Init / Reset]
105// ============================================================================
106
107BLResult blPatternInit(BLPatternCore* self) noexcept {
108 self->impl = &blNullPatternImpl;
109 return BL_SUCCESS;
110}
111
112BLResult blPatternInitAs(BLPatternCore* self, const BLImageCore* image, const BLRectI* area, uint32_t extendMode, const BLMatrix2D* matrix) noexcept {
113 if (!image)
114 image = &BLImage::none();
115
116 if (!area)
117 area = &blPatternNoArea;
118 else if (BL_UNLIKELY(!blPatternIsAreaValid(area, image->impl->size.w, image->impl->size.h)))
119 return blTraceError(BL_ERROR_INVALID_VALUE);
120
121 if (BL_UNLIKELY(extendMode >= BL_EXTEND_MODE_COMPLEX_COUNT))
122 return blTraceError(BL_ERROR_INVALID_VALUE);
123
124 uint32_t matrixType = BL_MATRIX2D_TYPE_IDENTITY;
125 if (!matrix)
126 matrix = &blMatrix2DIdentity;
127 else
128 matrixType = matrix->type();
129
130 BLInternalPatternImpl* impl = blPatternImplNew(image, area, extendMode, matrixType, matrix);
131 if (BL_UNLIKELY(!impl))
132 return blTraceError(BL_ERROR_OUT_OF_MEMORY);
133
134 self->impl = impl;
135 return BL_SUCCESS;
136}
137
138BLResult blPatternReset(BLPatternCore* self) noexcept {
139 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
140 self->impl = &blNullPatternImpl;
141 return blPatternImplRelease(selfI);
142}
143
144// ============================================================================
145// [BLPattern - Assign / Create]
146// ============================================================================
147
148BLResult blPatternAssignMove(BLPatternCore* self, BLPatternCore* other) noexcept {
149 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
150 BLInternalPatternImpl* otherI = blInternalCast(other->impl);
151
152 self->impl = otherI;
153 other->impl = &blNullPatternImpl;
154
155 return blPatternImplRelease(selfI);
156}
157
158BLResult blPatternAssignWeak(BLPatternCore* self, const BLPatternCore* other) noexcept {
159 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
160 BLInternalPatternImpl* otherI = blInternalCast(other->impl);
161
162 self->impl = blImplIncRef(otherI);
163 return blPatternImplRelease(selfI);
164}
165
166BLResult blPatternAssignDeep(BLPatternCore* self, const BLPatternCore* other) noexcept {
167 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
168 BLInternalPatternImpl* otherI = blInternalCast(other->impl);
169
170 if (!blImplIsMutable(selfI))
171 return blPatternMakeMutableCopyOf(self, otherI);
172
173 selfI->patternType = 0;
174 selfI->extendMode = otherI->extendMode;
175 selfI->matrixType = otherI->matrixType;
176 selfI->matrix = otherI->matrix;
177 selfI->area = otherI->area;
178 return blImageAssignWeak(&selfI->image, &otherI->image);
179}
180
181BLResult blPatternCreate(BLPatternCore* self, const BLImageCore* image, const BLRectI* area, uint32_t extendMode, const BLMatrix2D* matrix) noexcept {
182 if (!image)
183 image = &BLImage::none();
184
185 if (!area)
186 area = &blPatternNoArea;
187 else if (BL_UNLIKELY(!blPatternIsAreaValid(area, image->impl->size.w, image->impl->size.h)))
188 return blTraceError(BL_ERROR_INVALID_VALUE);
189
190 if (BL_UNLIKELY(extendMode >= BL_EXTEND_MODE_COMPLEX_COUNT))
191 return blTraceError(BL_ERROR_INVALID_VALUE);
192
193 uint32_t matrixType = BL_MATRIX2D_TYPE_IDENTITY;
194 if (!matrix)
195 matrix = &blMatrix2DIdentity;
196 else
197 matrixType = matrix->type();
198
199 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
200 if (!blImplIsMutable(selfI)) {
201 BLInternalPatternImpl* newI = blPatternImplNew(image, area, extendMode, matrixType, matrix);
202 if (BL_UNLIKELY(!newI))
203 return blTraceError(BL_ERROR_OUT_OF_MEMORY);
204
205 self->impl = newI;
206 return blPatternImplRelease(selfI);
207 }
208 else {
209 selfI->extendMode = uint8_t(extendMode);
210 selfI->matrixType = uint8_t(matrixType);
211 selfI->matrix = *matrix;
212 selfI->area = *area;
213 return blImageAssignWeak(&selfI->image, image);
214 }
215}
216
217// ============================================================================
218// [BLPattern - Properties]
219// ============================================================================
220
221BLResult blPatternSetImage(BLPatternCore* self, const BLImageCore* image, const BLRectI* area) noexcept {
222 if (!image)
223 image = &BLImage::none();
224
225 if (!area)
226 area = &blPatternNoArea;
227 else if (!blPatternIsAreaValid(area, image->impl->size.w, image->impl->size.h))
228 return blTraceError(BL_ERROR_INVALID_VALUE);
229
230 BL_PROPAGATE(blPatternMakeMutable(self));
231 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
232
233 selfI->area = *area;
234 return blImageAssignWeak(&selfI->image, image);
235}
236
237BLResult blPatternSetArea(BLPatternCore* self, const BLRectI* area) noexcept {
238 if (!area) {
239 area = &blPatternNoArea;
240 }
241 else {
242 BLImageImpl* imageImpl = self->impl->image.impl;
243 if (!blPatternIsAreaValid(area, imageImpl->size.w, imageImpl->size.h))
244 return blTraceError(BL_ERROR_INVALID_VALUE);
245 }
246
247 BL_PROPAGATE(blPatternMakeMutable(self));
248 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
249
250 selfI->area = *area;
251 return BL_SUCCESS;
252}
253
254BLResult blPatternSetExtendMode(BLPatternCore* self, uint32_t extendMode) noexcept {
255 if (BL_UNLIKELY(extendMode >= BL_EXTEND_MODE_COMPLEX_COUNT))
256 return blTraceError(BL_ERROR_INVALID_VALUE);
257
258 BL_PROPAGATE(blPatternMakeMutable(self));
259 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
260
261 selfI->extendMode = uint8_t(extendMode);
262 return BL_SUCCESS;
263}
264
265// ============================================================================
266// [BLPattern - Matrix]
267// ============================================================================
268
269BLResult blPatternApplyMatrixOp(BLPatternCore* self, uint32_t opType, const void* opData) noexcept {
270 if (BL_UNLIKELY(opType >= BL_MATRIX2D_OP_COUNT))
271 return blTraceError(BL_ERROR_INVALID_VALUE);
272
273 BLInternalPatternImpl* selfI = blInternalCast(self->impl);
274 if (opType == 0 && selfI->matrixType == BL_MATRIX2D_TYPE_IDENTITY)
275 return BL_SUCCESS;
276
277 BL_PROPAGATE(blPatternMakeMutable(self));
278 selfI = blInternalCast(self->impl);
279
280 blMatrix2DApplyOp(&selfI->matrix, opType, opData);
281 selfI->matrixType = uint8_t(selfI->matrix.type());
282
283 return BL_SUCCESS;
284}
285
286// ============================================================================
287// [BLPattern - Equals]
288// ============================================================================
289
290bool blPatternEquals(const BLPatternCore* a, const BLPatternCore* b) noexcept {
291 const BLPatternImpl* aI = a->impl;
292 const BLPatternImpl* bI = b->impl;
293
294 if (aI == bI)
295 return true;
296
297 bool eq = (aI->patternType == bI->patternType) &
298 (aI->extendMode == bI->extendMode ) &
299 (aI->matrixType == bI->matrixType ) &
300 (aI->matrix == bI->matrix ) &
301 (aI->area == bI->area ) ;
302 return eq && aI->image == bI->image;
303}
304
305// ============================================================================
306// [BLPattern - Runtime Init]
307// ============================================================================
308
309void blPatternRtInit(BLRuntimeContext* rt) noexcept {
310 BL_UNUSED(rt);
311
312 BLInternalPatternImpl* impl = &blNullPatternImpl;
313 blCallCtor(impl->image);
314 impl->implType = uint8_t(BL_IMPL_TYPE_PATTERN);
315 impl->implTraits = uint8_t(BL_IMPL_TRAIT_NULL);
316 impl->patternType = 0;
317 impl->extendMode = uint8_t(BL_EXTEND_MODE_REPEAT);
318 impl->matrix.reset();
319 impl->area.reset(0, 0, 0, 0);
320 blAssignBuiltInNull(impl);
321
322 // Checks whether the initialization order is correct.
323 BL_ASSERT(impl->image.impl != nullptr);
324}
325