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].
26struct 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].
33struct 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].
54struct BLFontDataCore {
55 BLFontDataImpl* impl;
56};
57
58// ============================================================================
59// [BLFontData - C++]
60// ============================================================================
61
62#ifdef __cplusplus
63//! Font data [C++ API].
64class BLFontData : public BLFontDataCore {
65public:
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].
161struct 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].
167struct 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].
190struct BLFontLoaderCore {
191 BLFontLoaderImpl* impl;
192};
193
194// ============================================================================
195// [BLFontLoader - C++]
196// ============================================================================
197
198#ifdef __cplusplus
199//! Font loader [C++ API].
200class BLFontLoader : public BLFontLoaderCore {
201public:
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
341BL_INLINE BLFontData::BLFontData(const BLFontLoader& loader, uint32_t faceIndex) noexcept {
342 blFontDataInitFromLoader(this, &loader, faceIndex);
343}
344
345BL_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].
357struct BLFontFaceVirt {
358 BLResult (BL_CDECL* destroy)(BLFontFaceImpl* impl) BL_NOEXCEPT;
359};
360
361//! Font face [C Interface - Impl].
362struct 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].
412struct BLFontFaceCore {
413 BLFontFaceImpl* impl;
414};
415
416// ============================================================================
417// [BLFontFace - C++]
418// ============================================================================
419
420#ifdef __cplusplus
421//! Font face [C++ API].
422class BLFontFace : public BLFontFaceCore {
423public:
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].
597struct 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].
628struct BLFontCore {
629 BLFontImpl* impl;
630};
631
632// ============================================================================
633// [BLFont - C++]
634// ============================================================================
635
636#ifdef __cplusplus
637//! Font [C++ API].
638class BLFont : public BLFontCore {
639public:
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