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_BLFONT_H |
8 | #define BLEND2D_BLFONT_H |
9 | |
10 | #include "./blarray.h" |
11 | #include "./blfontdefs.h" |
12 | #include "./blgeometry.h" |
13 | #include "./blglyphbuffer.h" |
14 | #include "./blpath.h" |
15 | #include "./blstring.h" |
16 | #include "./blvariant.h" |
17 | |
18 | //! \addtogroup blend2d_api_text |
19 | //! \{ |
20 | |
21 | // ============================================================================ |
22 | // [BLFontData - Core] |
23 | // ============================================================================ |
24 | |
25 | //! Font data [C Interface - Virtual Function Table]. |
26 | struct BLFontDataVirt { |
27 | BLResult (BL_CDECL* destroy)(BLFontDataImpl* impl) BL_NOEXCEPT; |
28 | BLResult (BL_CDECL* listTags)(const BLFontDataImpl* impl, BLArrayCore* out) BL_NOEXCEPT; |
29 | size_t (BL_CDECL* queryTables)(const BLFontDataImpl* impl, BLFontTable* dst, const BLTag* tags, size_t n) BL_NOEXCEPT; |
30 | }; |
31 | |
32 | //! Font data [C Interface - Impl]. |
33 | struct BLFontDataImpl { |
34 | //! Virtual function table. |
35 | const BLFontDataVirt* virt; |
36 | //! Pointer to the start of font-data (null if the data is provided at table level). |
37 | void* data; |
38 | //! Size of `data` [in bytes] (zero if the data is provided at table level). |
39 | size_t size; |
40 | |
41 | //! Reference count. |
42 | volatile size_t refCount; |
43 | //! Impl type. |
44 | uint8_t implType; |
45 | //! Impl traits. |
46 | uint8_t implTraits; |
47 | //! Memory pool data. |
48 | uint16_t memPoolData; |
49 | //! Font-data flags. |
50 | uint32_t flags; |
51 | }; |
52 | |
53 | //! Font data [C Interface - Core]. |
54 | struct BLFontDataCore { |
55 | BLFontDataImpl* impl; |
56 | }; |
57 | |
58 | // ============================================================================ |
59 | // [BLFontData - C++] |
60 | // ============================================================================ |
61 | |
62 | #ifdef __cplusplus |
63 | //! Font data [C++ API]. |
64 | class BLFontData : public BLFontDataCore { |
65 | public: |
66 | //! \cond INTERNAL |
67 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_FONT_DATA; |
68 | //! \endcond |
69 | |
70 | //! \name Construction & Destruction |
71 | //! \{ |
72 | |
73 | BL_INLINE BLFontData() noexcept { this->impl = none().impl; } |
74 | BL_INLINE BLFontData(BLFontData&& other) noexcept { blVariantInitMove(this, &other); } |
75 | BL_INLINE BLFontData(const BLFontData& other) noexcept { blVariantInitWeak(this, &other); } |
76 | BL_INLINE explicit BLFontData(BLFontDataImpl* impl) noexcept { this->impl = impl; } |
77 | |
78 | //! Creates `BLFontData` from loader. |
79 | //! |
80 | //! This function does the same as `BLFontLoader::dataByFaceIndex(faceIndex)`. |
81 | //! If the `loader` is a font collection then `faceIndex` specifies the index |
82 | //! of the font in the collection, otherwise it must be zero. |
83 | BL_INLINE BLFontData(const BLFontLoader& loader, uint32_t faceIndex) noexcept; |
84 | |
85 | BL_INLINE ~BLFontData() noexcept { blFontDataReset(this); } |
86 | |
87 | //! \} |
88 | |
89 | //! \name Overloaded Operators |
90 | //! \{ |
91 | |
92 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
93 | |
94 | BL_INLINE BLFontData& operator=(BLFontData&& other) noexcept { blFontDataAssignMove(this, &other); return *this; } |
95 | BL_INLINE BLFontData& operator=(const BLFontData& other) noexcept { blFontDataAssignWeak(this, &other); return *this; } |
96 | |
97 | BL_INLINE bool operator==(const BLFontData& other) const noexcept { return equals(other); } |
98 | BL_INLINE bool operator!=(const BLFontData& other) const noexcept { return !equals(other); } |
99 | |
100 | //! \} |
101 | |
102 | //! \name Common Functionality |
103 | //! \{ |
104 | |
105 | BL_INLINE BLResult reset() noexcept { return blFontDataReset(this); } |
106 | BL_INLINE void swap(BLFontData& other) noexcept { std::swap(this->impl, other.impl); } |
107 | |
108 | BL_INLINE BLResult assign(BLFontData&& other) noexcept { return blFontDataAssignMove(this, &other); } |
109 | BL_INLINE BLResult assign(const BLFontData& other) noexcept { return blFontDataAssignWeak(this, &other); } |
110 | |
111 | //! Tests whether the font-data is a built-in null instance. |
112 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
113 | //! Tests whether the font-data is empty (which the same as `isNone()` in this case). |
114 | BL_INLINE bool empty() const noexcept { return isNone(); } |
115 | |
116 | BL_INLINE bool equals(const BLFontData& other) const noexcept { return blFontDataEquals(this, &other); } |
117 | |
118 | //! \} |
119 | |
120 | //! \name Create Functionality |
121 | //! \{ |
122 | |
123 | //! Creates `BLFontData` from loader. |
124 | //! |
125 | //! This function does the same as `BLFontLoader::dataByFaceIndex(faceIndex)`. |
126 | //! If the `loader` is a font collection then `faceIndex` specifies the index |
127 | //! of the font in the collection, otherwise it must be zero. |
128 | BL_INLINE BLResult createFromLoader(const BLFontLoader& loader, uint32_t faceIndex) noexcept; |
129 | |
130 | //! \} |
131 | |
132 | //! \name Font-Data Accessors |
133 | //! \{ |
134 | |
135 | BL_INLINE BLResult listTags(BLArray<BLTag>& dst) const noexcept { |
136 | // The same as blFontDataListTags() [C-API]. |
137 | return impl->virt->listTags(impl, &dst); |
138 | } |
139 | |
140 | BL_INLINE size_t queryTable(BLFontTable* dst, BLTag tag) const noexcept { |
141 | // The same as blFontDataQueryTables() [C-API]. |
142 | return impl->virt->queryTables(impl, dst, &tag, 1); |
143 | } |
144 | |
145 | BL_INLINE size_t queryTables(BLFontTable* dst, const BLTag* tags, size_t count) const noexcept { |
146 | // The same as blFontDataQueryTables() [C-API]. |
147 | return impl->virt->queryTables(impl, dst, tags, count); |
148 | } |
149 | |
150 | //! \} |
151 | |
152 | static BL_INLINE const BLFontData& none() noexcept { return reinterpret_cast<const BLFontData*>(blNone)[kImplType]; } |
153 | }; |
154 | #endif |
155 | |
156 | // ============================================================================ |
157 | // [BLFontLoader - Core] |
158 | // ============================================================================ |
159 | |
160 | //! Font loader [C Interface - Virtual Function Table]. |
161 | struct BLFontLoaderVirt { |
162 | BLResult (BL_CDECL* destroy)(BLFontLoaderImpl* impl) BL_NOEXCEPT; |
163 | BLFontDataImpl* (BL_CDECL* dataByFaceIndex)(BLFontLoaderImpl* impl, uint32_t faceIndex) BL_NOEXCEPT; |
164 | }; |
165 | |
166 | //! Font loader [C Interface - Impl]. |
167 | struct BLFontLoaderImpl { |
168 | //! Virtual function table. |
169 | const BLFontLoaderVirt* virt; |
170 | //! Pointer to the start of font-data (null if the data is provided at table level). |
171 | void* data; |
172 | //! Size of `data` [in bytes] (zero if the data is provided at table level). |
173 | size_t size; |
174 | |
175 | //! Reference count. |
176 | volatile size_t refCount; |
177 | //! Impl type. |
178 | uint8_t implType; |
179 | //! Impl traits. |
180 | uint8_t implTraits; |
181 | //! Memory pool data. |
182 | uint16_t memPoolData; |
183 | |
184 | uint8_t faceType; |
185 | uint32_t faceCount; |
186 | uint32_t loaderFlags; |
187 | }; |
188 | |
189 | //! Font loader [C Interface - Core]. |
190 | struct BLFontLoaderCore { |
191 | BLFontLoaderImpl* impl; |
192 | }; |
193 | |
194 | // ============================================================================ |
195 | // [BLFontLoader - C++] |
196 | // ============================================================================ |
197 | |
198 | #ifdef __cplusplus |
199 | //! Font loader [C++ API]. |
200 | class BLFontLoader : public BLFontLoaderCore { |
201 | public: |
202 | //! \cond INTERNAL |
203 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_FONT_LOADER; |
204 | //! \endcond |
205 | |
206 | //! \name Construction & Destruction |
207 | //! \{ |
208 | |
209 | BL_INLINE BLFontLoader() noexcept { this->impl = none().impl; } |
210 | BL_INLINE BLFontLoader(BLFontLoader&& other) noexcept { blVariantInitMove(this, &other); } |
211 | BL_INLINE BLFontLoader(const BLFontLoader& other) noexcept { blVariantInitWeak(this, &other); } |
212 | BL_INLINE explicit BLFontLoader(BLFontLoaderImpl* impl) noexcept { this->impl = impl; } |
213 | BL_INLINE ~BLFontLoader() noexcept { blFontLoaderReset(this); } |
214 | |
215 | //! \} |
216 | |
217 | //! \name Overloaded Operators |
218 | //! \{ |
219 | |
220 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
221 | |
222 | BL_INLINE BLFontLoader& operator=(BLFontLoader&& other) noexcept { blFontLoaderAssignMove(this, &other); return *this; } |
223 | BL_INLINE BLFontLoader& operator=(const BLFontLoader& other) noexcept { blFontLoaderAssignWeak(this, &other); return *this; } |
224 | |
225 | BL_INLINE bool operator==(const BLFontLoader& other) const noexcept { return equals(other); } |
226 | BL_INLINE bool operator!=(const BLFontLoader& other) const noexcept { return !equals(other); } |
227 | |
228 | //! \} |
229 | |
230 | //! \name Common Functionality |
231 | //! \{ |
232 | |
233 | BL_INLINE BLResult reset() noexcept { return blFontLoaderReset(this); } |
234 | BL_INLINE void swap(BLFontLoader& other) noexcept { std::swap(this->impl, other.impl); } |
235 | |
236 | BL_INLINE BLResult assign(BLFontLoader&& other) noexcept { return blFontLoaderAssignMove(this, &other); } |
237 | BL_INLINE BLResult assign(const BLFontLoader& other) noexcept { return blFontLoaderAssignWeak(this, &other); } |
238 | |
239 | //! Tests whether the font-loader is a built-in null instance. |
240 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
241 | //! Tests whether the font-loader is empty (which the same as `isNone()` in this case). |
242 | BL_INLINE bool empty() const noexcept { return isNone(); } |
243 | |
244 | BL_INLINE bool equals(const BLFontLoader& other) const noexcept { return blFontLoaderEquals(this, &other); } |
245 | |
246 | //! \} |
247 | |
248 | //! \name Create Functionality |
249 | //! \{ |
250 | |
251 | //! Creates a `BLFontLoader` from file specified by `fileName`. |
252 | //! |
253 | //! \remarks The `readFlags` argument allows to specify flags that will be passed |
254 | //! to `BLFileSystem::readFile()` to read the content of the file. It's possible to |
255 | //! use memory mapping to get its content, which is the recommended way for reading |
256 | //! system fonts. The best combination is to use `BL_FILE_READ_MMAP_ENABLED` flag |
257 | //! combined with `BL_FILE_READ_MMAP_AVOID_SMALL`. This combination means to try to |
258 | //! use memory mapping only when the size of the font is greater than a minimum value |
259 | //! (determined by Blend2D), and would fallback to a regular open/read in case the |
260 | //! memory mapping is not possible or failed for some other reason. Please note that |
261 | //! not all files can be memory mapped so `BL_FILE_READ_MMAP_NO_FALLBACK` flag is not |
262 | //! recommended. |
263 | BL_INLINE BLResult createFromFile(const char* fileName, uint32_t readFlags = 0) noexcept { |
264 | return blFontLoaderCreateFromFile(this, fileName, readFlags); |
265 | } |
266 | |
267 | //! Creates a `BLFontLoader` from the given `data` stored in `BLArray<uint8_t>` |
268 | //! |
269 | //! The loader makes a weak copy of the `data` if successful so the given array |
270 | //! can be destroyed after the function returns. |
271 | //! |
272 | //! \remarks The weak copy of the passed `data` is internal and there is no API |
273 | //! to access it after the function returns. The reason for making it internal |
274 | //! is that the loader is only responsible for providing `BLFontData`, which |
275 | //! doesn't have to store the data in a continuous buffer. |
276 | BL_INLINE BLResult createFromData(const BLArray<uint8_t>& data) noexcept { |
277 | return blFontLoaderCreateFromDataArray(this, &data); |
278 | } |
279 | |
280 | //! Creates ` \BLFontLoader` from the given `data` of the given `size`. |
281 | //! |
282 | //! \note Optionally a `destroyFunc` can be used as a notifier that will be |
283 | //! called when the data is no longer needed and `destroyData` acts as a user |
284 | //! data passed to `destroyFunc()`. Please note that all fonts created by the |
285 | //! loader would also reference the loader so `destroyFunc` will only be called |
286 | //! when there are no references to the loader possibly held by fonts or other |
287 | //! objects. |
288 | BL_INLINE BLResult createFromData(const void* data, size_t size, BLDestroyImplFunc destroyFunc = nullptr, void* destroyData = nullptr) noexcept { |
289 | return blFontLoaderCreateFromData(this, data, size, destroyFunc, destroyData); |
290 | } |
291 | |
292 | //! \} |
293 | |
294 | //! \name Properties |
295 | //! \{ |
296 | |
297 | //! Type of font-face of the loader content. |
298 | //! |
299 | //! It doesn't matter if the content is a single font or a collection. In |
300 | //! any case the `faceType()` would always return the type of the font-face |
301 | //! that will be created by `BLFontFace::createFromLoader()`. |
302 | BL_INLINE uint32_t faceType() const noexcept { return impl->faceType; } |
303 | |
304 | //! Returns the number of faces this loader provides. |
305 | //! |
306 | //! If the loader is not initialized the result would be always zero. If the |
307 | //! loader is initialized to a single font it would be 1, and if the loader |
308 | //! is initialized to a font collection then the return would correspond to |
309 | //! the number of font-faces within that collection. |
310 | BL_INLINE uint32_t faceCount() const noexcept { return impl->faceCount; } |
311 | |
312 | //! Returns loader flags, see `BLFontLoaderFlags`. |
313 | BL_INLINE uint32_t loaderFlags() const noexcept { return impl->loaderFlags; } |
314 | |
315 | //! \} |
316 | |
317 | //! \name Font-Data Access |
318 | //! \{ |
319 | |
320 | //! Returns `BLFontData` instance that matches the given `faceIndex`. |
321 | //! |
322 | //! Please note that this function never fails. If the `faceIndex` is out |
323 | //! of bounds then a default constructed instance of `BLFontData` will be |
324 | //! returned. |
325 | //! |
326 | //! Alternatively you can use `BLFontData::createFromLoader()`, which would |
327 | //! call virtual function `BLFontLoaderVirt::dataByFaceIndex()` behind the |
328 | //! scenes and return the appropriate error if `faceIndex` is invalid or if |
329 | //! the loader is not initialized. |
330 | BL_INLINE BLFontData dataByFaceIndex(uint32_t faceIndex) const noexcept { |
331 | return BLFontData(impl->virt->dataByFaceIndex(impl, faceIndex)); |
332 | } |
333 | |
334 | //! \} |
335 | |
336 | static BL_INLINE const BLFontLoader& none() noexcept { return reinterpret_cast<const BLFontLoader*>(blNone)[kImplType]; } |
337 | }; |
338 | |
339 | // BLFontData API that depends on BLFontLoader. |
340 | //! \cond |
341 | BL_INLINE BLFontData::BLFontData(const BLFontLoader& loader, uint32_t faceIndex) noexcept { |
342 | blFontDataInitFromLoader(this, &loader, faceIndex); |
343 | } |
344 | |
345 | BL_INLINE BLResult BLFontData::createFromLoader(const BLFontLoader& loader, uint32_t faceIndex) noexcept { |
346 | return blFontDataCreateFromLoader(this, &loader, faceIndex); |
347 | } |
348 | //! \endcond |
349 | #endif |
350 | |
351 | // ============================================================================ |
352 | // [BLFontFace - Core] |
353 | // ============================================================================ |
354 | |
355 | |
356 | //! Font face [C Interface - Virtual Function Table]. |
357 | struct BLFontFaceVirt { |
358 | BLResult (BL_CDECL* destroy)(BLFontFaceImpl* impl) BL_NOEXCEPT; |
359 | }; |
360 | |
361 | //! Font face [C Interface - Impl]. |
362 | struct BLFontFaceImpl { |
363 | //! Virtual function table. |
364 | const BLFontFaceVirt* virt; |
365 | //! Font data. |
366 | BL_TYPED_MEMBER(BLFontDataCore, BLFontData, data); |
367 | //! Font loader used to load `BLFontData`. |
368 | BL_TYPED_MEMBER(BLFontLoaderCore, BLFontLoader, loader); |
369 | |
370 | //! Reference count. |
371 | volatile size_t refCount; |
372 | //! Impl type. |
373 | uint8_t implType; |
374 | //! Impl traits. |
375 | uint8_t implTraits; |
376 | //! Memory pool data. |
377 | uint16_t memPoolData; |
378 | |
379 | //! Font-face default weight (1..1000) [0 if font-face is not initialized]. |
380 | uint16_t weight; |
381 | //! Font-face default stretch (1..9) [0 if font-face is not initialized]. |
382 | uint8_t stretch; |
383 | //! Font-face default style. |
384 | uint8_t style; |
385 | |
386 | //! Font-face information. |
387 | BLFontFaceInfo faceInfo; |
388 | |
389 | //! Unique face id assigned by Blend2D for caching. |
390 | uint64_t faceUniqueId; |
391 | |
392 | //! Full name. |
393 | BL_TYPED_MEMBER(BLStringCore, BLString, fullName); |
394 | //! Family name. |
395 | BL_TYPED_MEMBER(BLStringCore, BLString, familyName); |
396 | //! Subfamily name. |
397 | BL_TYPED_MEMBER(BLStringCore, BLString, subfamilyName); |
398 | //! PostScript name. |
399 | BL_TYPED_MEMBER(BLStringCore, BLString, postScriptName); |
400 | |
401 | //! Font-face metrics in design units. |
402 | BLFontDesignMetrics designMetrics; |
403 | //! Font-face unicode coverage (specified in OS/2 header). |
404 | BLFontUnicodeCoverage unicodeCoverage; |
405 | //! Font-face panose classification. |
406 | BLFontPanose panose; |
407 | |
408 | BL_HAS_TYPED_MEMBERS(BLFontFaceImpl) |
409 | }; |
410 | |
411 | //! Font face [C Interface - Core]. |
412 | struct BLFontFaceCore { |
413 | BLFontFaceImpl* impl; |
414 | }; |
415 | |
416 | // ============================================================================ |
417 | // [BLFontFace - C++] |
418 | // ============================================================================ |
419 | |
420 | #ifdef __cplusplus |
421 | //! Font face [C++ API]. |
422 | class BLFontFace : public BLFontFaceCore { |
423 | public: |
424 | //! \cond INTERNAL |
425 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_FONT_FACE; |
426 | //! \endcond |
427 | |
428 | //! \name Construction & Destruction |
429 | //! \{ |
430 | |
431 | BL_INLINE BLFontFace() noexcept { this->impl = none().impl; } |
432 | BL_INLINE BLFontFace(BLFontFace&& other) noexcept { blVariantInitMove(this, &other); } |
433 | BL_INLINE BLFontFace(const BLFontFace& other) noexcept { blVariantInitWeak(this, &other); } |
434 | BL_INLINE explicit BLFontFace(BLFontFaceImpl* impl) noexcept { this->impl = impl; } |
435 | BL_INLINE ~BLFontFace() noexcept { blFontFaceReset(this); } |
436 | |
437 | //! \} |
438 | |
439 | //! \name Overloaded Operators |
440 | //! \{ |
441 | |
442 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
443 | |
444 | BL_INLINE BLFontFace& operator=(BLFontFace&& other) noexcept { blFontFaceAssignMove(this, &other); return *this; } |
445 | BL_INLINE BLFontFace& operator=(const BLFontFace& other) noexcept { blFontFaceAssignWeak(this, &other); return *this; } |
446 | |
447 | BL_INLINE bool operator==(const BLFontFace& other) const noexcept { return equals(other); } |
448 | BL_INLINE bool operator!=(const BLFontFace& other) const noexcept { return !equals(other); } |
449 | |
450 | //! \} |
451 | |
452 | //! \name Common Functionality |
453 | //! \{ |
454 | |
455 | BL_INLINE BLResult reset() noexcept { return blFontFaceReset(this); } |
456 | BL_INLINE void swap(BLFontFace& other) noexcept { std::swap(this->impl, other.impl); } |
457 | |
458 | BL_INLINE BLResult assign(BLFontFace&& other) noexcept { return blFontFaceAssignMove(this, &other); } |
459 | BL_INLINE BLResult assign(const BLFontFace& other) noexcept { return blFontFaceAssignWeak(this, &other); } |
460 | |
461 | //! Tests whether the font-face is a built-in null instance. |
462 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
463 | //! Tests whether the font-face is empty (which the same as `isNone()` in this case). |
464 | BL_INLINE bool empty() const noexcept { return isNone(); } |
465 | |
466 | BL_INLINE bool equals(const BLFontFace& other) const noexcept { return blFontFaceEquals(this, &other); } |
467 | |
468 | //! \} |
469 | |
470 | //! \name Create Functionality |
471 | //! \{ |
472 | |
473 | //! Creates a new `BLFontFace` from a file specified by `fileName`. |
474 | //! |
475 | //! This is a utility function that first creates a `BLFontLoader` and then |
476 | //! calls `createFromLoader(loader, 0)`. See `BLFontLoader::createFromFile()` |
477 | //! for more details, especially the use of `readFlags` is important for system |
478 | //! fonts. |
479 | //! |
480 | //! \note This function offers a simplified creation of `BLFontFace` directly |
481 | //! from a file, but doesn't provide as much flexibility as `createFromLoader()` |
482 | //! as it allows to specify a `faceIndex`, which can be used to load multiple |
483 | //! font faces from a TrueType/OpenType collection. The use of `createFromLoader()` |
484 | //! is recommended for any serious font handling. |
485 | BL_INLINE BLResult createFromFile(const char* fileName, uint32_t readFlags = 0) noexcept { |
486 | return blFontFaceCreateFromFile(this, fileName, readFlags); |
487 | } |
488 | |
489 | //! Creates a new `BLFontFace` from `BLFontLoader`. |
490 | //! |
491 | //! On success the existing `BLFontFace` is completely replaced by a new one, |
492 | //! on failure a `BLResult` is returned and the existing `BLFontFace` is kept |
493 | //! as is. In other words, it either succeeds and replaces the `BLFontFaceImpl` |
494 | //! or returns an error without touching the existing one. |
495 | BL_INLINE BLResult createFromLoader(const BLFontLoader& loader, uint32_t faceIndex) noexcept { |
496 | return blFontFaceCreateFromLoader(this, &loader, faceIndex); |
497 | } |
498 | |
499 | //! \} |
500 | |
501 | //! \name Font Data & Loader |
502 | //! \{ |
503 | |
504 | //! Returns `BLFontData` associated with this font-face. |
505 | BL_INLINE const BLFontData& data() const noexcept { return impl->data; } |
506 | //! Returns `BLFontLoader` associated with this font-face. |
507 | BL_INLINE const BLFontLoader& loader() const noexcept { return impl->loader; } |
508 | |
509 | //! \} |
510 | |
511 | //! \name Properties |
512 | //! \{ |
513 | |
514 | //! Returns font weight (returns default weight in case this is a variable font). |
515 | BL_INLINE uint32_t weight() const noexcept { return impl->weight; } |
516 | //! Returns font stretch (returns default weight in case this is a variable font). |
517 | BL_INLINE uint32_t stretch() const noexcept { return impl->stretch; } |
518 | //! Returns font style. |
519 | BL_INLINE uint32_t style() const noexcept { return impl->style; } |
520 | |
521 | //! Returns font-face information as `BLFontFaceInfo`. |
522 | BL_INLINE const BLFontFaceInfo& faceInfo() const noexcept { return impl->faceInfo; } |
523 | |
524 | //! Returns the font-face type, see `BLFontFaceType`. |
525 | BL_INLINE uint32_t faceType() const noexcept { return impl->faceInfo.faceType; } |
526 | //! Returns the font-face type, see `BLFontOutlineType`. |
527 | BL_INLINE uint32_t outlineType() const noexcept { return impl->faceInfo.outlineType; } |
528 | //! Returns the number of glyphs of this font-face. |
529 | BL_INLINE uint32_t glyphCount() const noexcept { return impl->faceInfo.glyphCount; } |
530 | |
531 | //! Returns a zero-based index of this font-face. |
532 | //! |
533 | //! \note Face index does only make sense if this face is part of a TrueType |
534 | //! or OpenType font collection. In that case the returned value would be |
535 | //! the index of this face in that collection. If the face is not part of a |
536 | //! collection then the returned value would always be zero. |
537 | BL_INLINE uint32_t faceIndex() const noexcept { return impl->faceInfo.faceIndex; } |
538 | //! Returns font-face flags, see `BLFontFaceFlags`. |
539 | BL_INLINE uint32_t faceFlags() const noexcept { return impl->faceInfo.faceFlags; } |
540 | //! Returns font-face diagnostics flags, see `BLFontFaceDiagFlags`. |
541 | BL_INLINE uint32_t diagFlags() const noexcept { return impl->faceInfo.diagFlags; } |
542 | |
543 | //! Returns a unique identifier describing this `BLFontFace`. |
544 | BL_INLINE uint64_t faceUniqueId() const noexcept { return impl->faceUniqueId; } |
545 | |
546 | //! Returns the font full name as UTF-8 null-terminated string. |
547 | BL_INLINE const char* fullName() const noexcept { return impl->fullName.data(); } |
548 | //! Returns the size of the string returned by `fullName()`. |
549 | BL_INLINE size_t fullNameSize() const noexcept { return impl->fullName.size(); } |
550 | //! Returns the font full name as a UTF-8 string view. |
551 | BL_INLINE const BLStringView& fullNameView() const noexcept { return impl->fullName.view(); } |
552 | |
553 | //! Returns the family name as UTF-8 null-terminated string. |
554 | BL_INLINE const char* familyName() const noexcept { return impl->familyName.data(); } |
555 | //! Returns the size of the string returned by `familyName()`. |
556 | BL_INLINE size_t familyNameSize() const noexcept { return impl->familyName.size(); } |
557 | //! Returns the family-name as a UTF-8 string view. |
558 | BL_INLINE const BLStringView& familyNameView() const noexcept { return impl->familyName.view(); } |
559 | |
560 | //! Returns the font subfamily name as UTF-8 null-terminated string. |
561 | BL_INLINE const char* subfamilyName() const noexcept { return impl->subfamilyName.data(); } |
562 | //! Returns the size of the string returned by `subfamilyName()`. |
563 | BL_INLINE size_t subfamilyNameSize() const noexcept { return impl->subfamilyName.size(); } |
564 | //! Returns the font subfamily-name as a UTF-8 string view. |
565 | BL_INLINE const BLStringView& subfamilyNameView() const noexcept { return impl->subfamilyName.view(); } |
566 | |
567 | //! Returns the font PostScript name as UTF-8 null-terminated string. |
568 | BL_INLINE const char* postScriptName() const noexcept { return impl->postScriptName.data(); } |
569 | //! Returns the size of the string returned by `postScriptName()`. |
570 | BL_INLINE size_t postScriptNameSize() const noexcept { return impl->postScriptName.size(); } |
571 | //! Returns the font PostScript name as a UTF-8 string view. |
572 | BL_INLINE const BLStringView& postScriptNameView() const noexcept { return impl->postScriptName.view(); } |
573 | |
574 | //! Returns feature-set of this `BLFontFace`. |
575 | // BL_INLINE const FontFeatureSet& featureSet() const noexcept { return impl->featureSet; } |
576 | //! Returns design metrics of this `BLFontFace`. |
577 | BL_INLINE const BLFontDesignMetrics& designMetrics() const noexcept { return impl->designMetrics; } |
578 | //! Returns units per em, which are part of font's design metrics. |
579 | BL_INLINE int unitsPerEm() const noexcept { return impl->designMetrics.unitsPerEm; } |
580 | |
581 | //! Returns PANOSE classification of this `BLFontFace`. |
582 | BL_INLINE const BLFontPanose& panose() const noexcept { return impl->panose; } |
583 | //! Returns unicode coverage of this `BLFontFace`. |
584 | BL_INLINE const BLFontUnicodeCoverage& unicodeCoverage() const noexcept { return impl->unicodeCoverage; } |
585 | |
586 | //! \} |
587 | |
588 | static BL_INLINE const BLFontFace& none() noexcept { return reinterpret_cast<const BLFontFace*>(blNone)[kImplType]; } |
589 | }; |
590 | #endif |
591 | |
592 | // ============================================================================ |
593 | // [BLFont - Core] |
594 | // ============================================================================ |
595 | |
596 | //! Font [C Interface - Impl]. |
597 | struct BLFontImpl { |
598 | //! Font-face used by this font. |
599 | BL_TYPED_MEMBER(BLFontFaceCore, BLFontFace, face); |
600 | //! Font features. |
601 | BL_TYPED_MEMBER(BLArrayCore, BLArray<BLFontFeature>, features); |
602 | //! Font variations. |
603 | BL_TYPED_MEMBER(BLArrayCore, BLArray<BLFontVariation>, variations); |
604 | |
605 | //! Reference count. |
606 | volatile size_t refCount; |
607 | //! Impl type. |
608 | uint8_t implType; |
609 | //! Impl traits. |
610 | uint8_t implTraits; |
611 | //! Memory pool data. |
612 | uint16_t memPoolData; |
613 | |
614 | //! Font width (1..1000) [0 if the font is not initialized]. |
615 | uint16_t weight; |
616 | //! Font stretch (1..9) [0 if the font is not initialized]. |
617 | uint8_t stretch; |
618 | //! Font style. |
619 | uint8_t style; |
620 | |
621 | BLFontMetrics metrics; |
622 | BLFontMatrix matrix; |
623 | |
624 | BL_HAS_TYPED_MEMBERS(BLFontImpl) |
625 | }; |
626 | |
627 | //! Font [C Interface - Core]. |
628 | struct BLFontCore { |
629 | BLFontImpl* impl; |
630 | }; |
631 | |
632 | // ============================================================================ |
633 | // [BLFont - C++] |
634 | // ============================================================================ |
635 | |
636 | #ifdef __cplusplus |
637 | //! Font [C++ API]. |
638 | class BLFont : public BLFontCore { |
639 | public: |
640 | //! \cond INTERNAL |
641 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_FONT; |
642 | //! \endcond |
643 | |
644 | //! \name Construction & Destruction |
645 | //! \{ |
646 | |
647 | BL_INLINE BLFont() noexcept { this->impl = none().impl; } |
648 | BL_INLINE BLFont(BLFont&& other) noexcept { blVariantInitMove(this, &other); } |
649 | BL_INLINE BLFont(const BLFont& other) noexcept { blVariantInitWeak(this, &other); } |
650 | BL_INLINE explicit BLFont(BLFontImpl* impl) noexcept { this->impl = impl; } |
651 | BL_INLINE ~BLFont() noexcept { blFontReset(this); } |
652 | |
653 | //! \} |
654 | |
655 | //! \name Overloaded Operators |
656 | //! \{ |
657 | |
658 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
659 | |
660 | BL_INLINE BLFont& operator=(BLFont&& other) noexcept { blFontAssignMove(this, &other); return *this; } |
661 | BL_INLINE BLFont& operator=(const BLFont& other) noexcept { blFontAssignWeak(this, &other); return *this; } |
662 | |
663 | BL_INLINE bool operator==(const BLFont& other) const noexcept { return equals(other); } |
664 | BL_INLINE bool operator!=(const BLFont& other) const noexcept { return !equals(other); } |
665 | |
666 | //! \} |
667 | |
668 | //! \name Common Functionality |
669 | //! \{ |
670 | |
671 | BL_INLINE BLResult reset() noexcept { return blFontReset(this); } |
672 | BL_INLINE void swap(BLFont& other) noexcept { std::swap(this->impl, other.impl); } |
673 | |
674 | BL_INLINE BLResult assign(BLFont&& other) noexcept { return blFontAssignMove(this, &other); } |
675 | BL_INLINE BLResult assign(const BLFont& other) noexcept { return blFontAssignWeak(this, &other); } |
676 | |
677 | //! Tests whether the font is a built-in null instance. |
678 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
679 | //! Tests whether the font is empty (which the same as `isNone()` in this case). |
680 | BL_INLINE bool empty() const noexcept { return isNone(); } |
681 | |
682 | BL_INLINE bool equals(const BLFont& other) const noexcept { return blFontEquals(this, &other); } |
683 | |
684 | //! \} |
685 | |
686 | //! \name Create Functionality |
687 | //! \{ |
688 | |
689 | BL_INLINE BLResult createFromFace(const BLFontFace& face, float size) noexcept { |
690 | return blFontCreateFromFace(this, &face, size); |
691 | } |
692 | |
693 | //! \} |
694 | |
695 | //! \name Properties |
696 | //! \{ |
697 | |
698 | //! Returns the type of the font's associated font-face, see `BLFontFaceType`. |
699 | BL_INLINE uint32_t faceType() const noexcept { return impl->face.faceType(); } |
700 | //! Returns the flags of the font, see `BLFontFaceFlags`. |
701 | BL_INLINE uint32_t faceFlags() const noexcept { return impl->face.faceFlags(); } |
702 | //! Returns the size of the font (as float). |
703 | BL_INLINE float size() const noexcept { return impl->metrics.size; } |
704 | //! Returns the "units per em" (UPEM) of the font's associated font-face. |
705 | BL_INLINE int unitsPerEm() const noexcept { return face().unitsPerEm(); } |
706 | |
707 | //! Returns the font's associated font-face. |
708 | //! |
709 | //! Returns the same font-face, which was passed to `createFromFace()`. |
710 | BL_INLINE const BLFontFace& face() const noexcept { return impl->face; } |
711 | |
712 | //! Returns the features associated with the font. |
713 | BL_INLINE const BLArray<BLFontFeature>& features() const noexcept { return impl->features; } |
714 | //! Returns the variations associated with the font. |
715 | BL_INLINE const BLArray<BLFontVariation>& variations() const noexcept { return impl->variations; } |
716 | |
717 | //! Returns the weight of the font. |
718 | BL_INLINE uint32_t weight() const noexcept { return impl->weight; } |
719 | //! Returns the stretch of the font. |
720 | BL_INLINE uint32_t stretch() const noexcept { return impl->stretch; } |
721 | //! Returns the style of the font. |
722 | BL_INLINE uint32_t style() const noexcept { return impl->style; } |
723 | |
724 | //! Returns a 2x2 matrix of the font. |
725 | //! |
726 | //! The returned `BLFontMatrix` is used to scale fonts from design units |
727 | //! into user units. The matrix usually has a negative `m11` member as |
728 | //! fonts use a different coordinate system than Blend2D. |
729 | BL_INLINE const BLFontMatrix& matrix() const noexcept { return impl->matrix; } |
730 | |
731 | //! Returns the scaled metrics of the font. |
732 | //! |
733 | //! The returned metrics is a scale of design metrics that match the font size and its options. |
734 | BL_INLINE const BLFontMetrics& metrics() const noexcept { return impl->metrics; } |
735 | |
736 | //! Returns the design metrics of the font. |
737 | //! |
738 | //! The returned metrics is compatible with the metrics of `BLFontFace` associated with this font. |
739 | BL_INLINE const BLFontDesignMetrics& designMetrics() const noexcept { return face().designMetrics(); } |
740 | |
741 | //! \} |
742 | |
743 | //! \name Glyphs & Text |
744 | //! \{ |
745 | |
746 | BL_INLINE BLResult shape(BLGlyphBuffer& gb) const noexcept { |
747 | return blFontShape(this, &gb); |
748 | } |
749 | |
750 | BL_INLINE BLResult mapTextToGlyphs(BLGlyphBuffer& gb) const noexcept { |
751 | return blFontMapTextToGlyphs(this, &gb, nullptr); |
752 | } |
753 | |
754 | BL_INLINE BLResult mapTextToGlyphs(BLGlyphBuffer& gb, BLGlyphMappingState& stateOut) const noexcept { |
755 | return blFontMapTextToGlyphs(this, &gb, &stateOut); |
756 | } |
757 | |
758 | BL_INLINE BLResult positionGlyphs(BLGlyphBuffer& gb, uint32_t positioningFlags = 0xFFFFFFFFu) const noexcept { |
759 | return blFontPositionGlyphs(this, &gb, positioningFlags); |
760 | } |
761 | |
762 | BL_INLINE BLResult applyKerning(BLGlyphBuffer& gb) const noexcept { |
763 | return blFontApplyKerning(this, &gb); |
764 | } |
765 | |
766 | BL_INLINE BLResult applyGSub(BLGlyphBuffer& gb, size_t index, BLBitWord lookups) const noexcept { |
767 | return blFontApplyGSub(this, &gb, index, lookups); |
768 | } |
769 | |
770 | BL_INLINE BLResult applyGPos(BLGlyphBuffer& gb, size_t index, BLBitWord lookups) const noexcept { |
771 | return blFontApplyGPos(this, &gb, index, lookups); |
772 | } |
773 | |
774 | BL_INLINE BLResult getTextMetrics(BLGlyphBuffer& gb, BLTextMetrics& out) const noexcept { |
775 | return blFontGetTextMetrics(this, &gb, &out); |
776 | } |
777 | |
778 | BL_INLINE BLResult getGlyphBounds(const void* glyphIdData, intptr_t glyphIdAdvance, BLBoxI* out, size_t count) const noexcept { |
779 | return blFontGetGlyphBounds(this, glyphIdData, glyphIdAdvance, out, count); |
780 | } |
781 | |
782 | BL_INLINE BLResult getGlyphAdvances(const void* glyphIdData, intptr_t glyphIdAdvance, BLGlyphPlacement* out, size_t count) const noexcept { |
783 | return blFontGetGlyphAdvances(this, glyphIdData, glyphIdAdvance, out, count); |
784 | } |
785 | |
786 | BL_INLINE BLResult getGlyphOutlines(uint32_t glyphId, BLPath& out, BLPathSinkFunc sink = nullptr, void* closure = nullptr) const noexcept { |
787 | return blFontGetGlyphOutlines(this, glyphId, nullptr, &out, sink, closure); |
788 | } |
789 | |
790 | BL_INLINE BLResult getGlyphOutlines(uint32_t glyphId, const BLMatrix2D& userMatrix, BLPath& out, BLPathSinkFunc sink = nullptr, void* closure = nullptr) const noexcept { |
791 | return blFontGetGlyphOutlines(this, glyphId, &userMatrix, &out, sink, closure); |
792 | } |
793 | |
794 | BL_INLINE BLResult getGlyphRunOutlines(const BLGlyphRun& glyphRun, BLPath& out, BLPathSinkFunc sink = nullptr, void* closure = nullptr) const noexcept { |
795 | return blFontGetGlyphRunOutlines(this, &glyphRun, nullptr, &out, sink, closure); |
796 | } |
797 | |
798 | BL_INLINE BLResult getGlyphRunOutlines(const BLGlyphRun& glyphRun, const BLMatrix2D& userMatrix, BLPath& out, BLPathSinkFunc sink = nullptr, void* closure = nullptr) const noexcept { |
799 | return blFontGetGlyphRunOutlines(this, &glyphRun, &userMatrix, &out, sink, closure); |
800 | } |
801 | |
802 | //! \} |
803 | |
804 | static BL_INLINE const BLFont& none() noexcept { return reinterpret_cast<const BLFont*>(blNone)[kImplType]; } |
805 | }; |
806 | #endif |
807 | |
808 | //! \} |
809 | |
810 | #endif // BLEND2D_BLFONT_H |
811 | |