diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-29 14:00:41 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-29 14:00:41 +0300 |
commit | d98604ca3bd3f3986a42c4e9e1c4228089e39024 (patch) | |
tree | 9d3fdd5115d86300027476882417fb5127278963 /src/fontpack.c | |
parent | b99c6e693b8ade1fa117f4cb54105366a7768da0 (diff) |
FontPack: Loading fonts from TTC files
Diffstat (limited to 'src/fontpack.c')
-rw-r--r-- | src/fontpack.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/src/fontpack.c b/src/fontpack.c index 96d973f7..ec62702f 100644 --- a/src/fontpack.c +++ b/src/fontpack.c | |||
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
31 | #include <the_Foundation/fileinfo.h> | 31 | #include <the_Foundation/fileinfo.h> |
32 | #include <the_Foundation/path.h> | 32 | #include <the_Foundation/path.h> |
33 | #include <the_Foundation/ptrarray.h> | 33 | #include <the_Foundation/ptrarray.h> |
34 | #include <the_Foundation/regexp.h> | ||
34 | #include <the_Foundation/string.h> | 35 | #include <the_Foundation/string.h> |
35 | #include <the_Foundation/stringlist.h> | 36 | #include <the_Foundation/stringlist.h> |
36 | #include <the_Foundation/toml.h> | 37 | #include <the_Foundation/toml.h> |
@@ -65,6 +66,7 @@ iDefineObjectConstruction(FontFile) | |||
65 | 66 | ||
66 | void init_FontFile(iFontFile *d) { | 67 | void init_FontFile(iFontFile *d) { |
67 | init_String(&d->id); | 68 | init_String(&d->id); |
69 | d->colIndex = 0; | ||
68 | d->style = regular_FontStyle; | 70 | d->style = regular_FontStyle; |
69 | init_Block(&d->sourceData, 0); | 71 | init_Block(&d->sourceData, 0); |
70 | iZap(d->stbInfo); | 72 | iZap(d->stbInfo); |
@@ -77,15 +79,17 @@ void init_FontFile(iFontFile *d) { | |||
77 | 79 | ||
78 | static void load_FontFile_(iFontFile *d, const iBlock *data) { | 80 | static void load_FontFile_(iFontFile *d, const iBlock *data) { |
79 | set_Block(&d->sourceData, data); | 81 | set_Block(&d->sourceData, data); |
80 | stbtt_InitFont(&d->stbInfo, constData_Block(&d->sourceData), 0); | 82 | const size_t offset = stbtt_GetFontOffsetForIndex(constData_Block(&d->sourceData), |
83 | d->colIndex); | ||
84 | stbtt_InitFont(&d->stbInfo, constData_Block(data), offset); | ||
81 | /* Basic metrics. */ | 85 | /* Basic metrics. */ |
82 | stbtt_GetFontVMetrics(&d->stbInfo, &d->ascent, &d->descent, NULL); | 86 | stbtt_GetFontVMetrics(&d->stbInfo, &d->ascent, &d->descent, NULL); |
83 | stbtt_GetCodepointHMetrics(&d->stbInfo, 'M', &d->emAdvance, NULL); | 87 | stbtt_GetCodepointHMetrics(&d->stbInfo, 'M', &d->emAdvance, NULL); |
84 | #if defined(LAGRANGE_ENABLE_HARFBUZZ) | 88 | #if defined(LAGRANGE_ENABLE_HARFBUZZ) |
85 | /* HarfBuzz will read the font data. */ | 89 | /* HarfBuzz will read the font data. */ |
86 | d->hbBlob = hb_blob_create(constData_Block(&d->sourceData), size_Block(&d->sourceData), | 90 | d->hbBlob = hb_blob_create(constData_Block(data), size_Block(&d->sourceData), |
87 | HB_MEMORY_MODE_READONLY, NULL, NULL); | 91 | HB_MEMORY_MODE_READONLY, NULL, NULL); |
88 | d->hbFace = hb_face_create(d->hbBlob, 0); | 92 | d->hbFace = hb_face_create(d->hbBlob, d->colIndex); |
89 | d->hbFont = hb_font_create(d->hbFace); | 93 | d->hbFont = hb_font_create(d->hbFace); |
90 | #endif | 94 | #endif |
91 | } | 95 | } |
@@ -173,6 +177,7 @@ struct Impl_Fonts { | |||
173 | iPtrArray packs; | 177 | iPtrArray packs; |
174 | iObjectList *files; | 178 | iObjectList *files; |
175 | iPtrArray specOrder; /* specs sorted by priority */ | 179 | iPtrArray specOrder; /* specs sorted by priority */ |
180 | iRegExp *indexPattern; /* collection index filename suffix */ | ||
176 | }; | 181 | }; |
177 | 182 | ||
178 | static iFonts fonts_; | 183 | static iFonts fonts_; |
@@ -371,22 +376,40 @@ void handleIniKeyValue_FontPack_(void *context, const iString *table, const iStr | |||
371 | else if (value->type == string_TomlType) { | 376 | else if (value->type == string_TomlType) { |
372 | iForIndices(i, styles_) { | 377 | iForIndices(i, styles_) { |
373 | if (!cmp_String(key, styles_[i]) && !d->loadSpec->styles[i]) { | 378 | if (!cmp_String(key, styles_[i]) && !d->loadSpec->styles[i]) { |
379 | iBeginCollect(); | ||
374 | iFontFile *ff = NULL; | 380 | iFontFile *ff = NULL; |
375 | iString *fontFileId = concat_Path(d->loadPath, value->value.string); | 381 | iString *cleanPath = collect_String(copy_String(value->value.string)); |
376 | if (!(ff = findFile_Fonts_(&fonts_, fontFileId))) { | 382 | int colIndex = 0; |
377 | iBlock *data = readFile_FontPack_(d, value->value.string); | 383 | /* Remove the collection index from the path. */ { |
378 | if (data) { | 384 | iRegExpMatch m; |
379 | ff = new_FontFile(); | 385 | init_RegExpMatch(&m); |
380 | set_String(&ff->id, fontFileId); | 386 | if (matchString_RegExp(fonts_.indexPattern, cleanPath, &m)) { |
381 | load_FontFile_(ff, data); | 387 | colIndex = toInt_String(collect_String(captured_RegExpMatch(&m, 1))); |
382 | pushBack_ObjectList(fonts_.files, ff); /* centralized ownership */ | 388 | removeEnd_String(cleanPath, size_Range(&m.range)); |
383 | iRelease(ff); | ||
384 | delete_Block(data); | ||
385 | // printf("[FontPack] loaded file: %s\n", cstr_String(fontFileId)); | ||
386 | } | 389 | } |
387 | } | 390 | } |
391 | iString *fontFileId = concat_Path(d->loadPath, cleanPath); | ||
392 | /* FontFiles share source data blocks. The entire FontFiles can be reused, too, | ||
393 | if have the same collection index is in use. */ | ||
394 | iBlock *data = NULL; | ||
395 | ff = findFile_Fonts_(&fonts_, fontFileId); | ||
396 | if (ff) { | ||
397 | data = &ff->sourceData; | ||
398 | } | ||
399 | if (!ff || ff->colIndex != colIndex) { | ||
400 | if (!data) { | ||
401 | data = collect_Block(readFile_FontPack_(d, cleanPath)); | ||
402 | } | ||
403 | ff = new_FontFile(); | ||
404 | set_String(&ff->id, fontFileId); | ||
405 | ff->colIndex = colIndex; | ||
406 | load_FontFile_(ff, data); | ||
407 | pushBack_ObjectList(fonts_.files, ff); /* centralized ownership */ | ||
408 | iRelease(ff); | ||
409 | } | ||
388 | d->loadSpec->styles[i] = ref_Object(ff); | 410 | d->loadSpec->styles[i] = ref_Object(ff); |
389 | delete_String(fontFileId); | 411 | delete_String(fontFileId); |
412 | iEndCollect(); | ||
390 | break; | 413 | break; |
391 | } | 414 | } |
392 | } | 415 | } |
@@ -528,6 +551,7 @@ static const iString *userFontsDirectory_Fonts_(const iFonts *d) { | |||
528 | 551 | ||
529 | void init_Fonts(const char *userDir) { | 552 | void init_Fonts(const char *userDir) { |
530 | iFonts *d = &fonts_; | 553 | iFonts *d = &fonts_; |
554 | d->indexPattern = new_RegExp(":([0-9]+)$", 0); | ||
531 | initCStr_String(&d->userDir, userDir); | 555 | initCStr_String(&d->userDir, userDir); |
532 | const iString *userFontsDir = userFontsDirectory_Fonts_(d); | 556 | const iString *userFontsDir = userFontsDirectory_Fonts_(d); |
533 | makeDirs_Path(userFontsDir); | 557 | makeDirs_Path(userFontsDir); |
@@ -659,6 +683,7 @@ void deinit_Fonts(void) { | |||
659 | deinit_PtrArray(&d->specOrder); | 683 | deinit_PtrArray(&d->specOrder); |
660 | deinit_PtrArray(&d->packs); | 684 | deinit_PtrArray(&d->packs); |
661 | iRelease(d->files); | 685 | iRelease(d->files); |
686 | iRelease(d->indexPattern); | ||
662 | deinit_String(&d->userDir); | 687 | deinit_String(&d->userDir); |
663 | } | 688 | } |
664 | 689 | ||
@@ -706,18 +731,27 @@ iString *infoText_FontPack(const iFontPack *d) { | |||
706 | const iFontSpec *spec = i.ptr; | 731 | const iFontSpec *spec = i.ptr; |
707 | pushBack_StringList(names, &spec->name); | 732 | pushBack_StringList(names, &spec->name); |
708 | iForIndices(j, spec->styles) { | 733 | iForIndices(j, spec->styles) { |
709 | insert_PtrSet(uniqueFiles, spec->styles[j]); | 734 | insert_PtrSet(uniqueFiles, spec->styles[j]->sourceData.i); |
710 | } | 735 | } |
711 | } | 736 | } |
712 | iConstForEach(PtrSet, j, uniqueFiles) { | 737 | iConstForEach(PtrSet, j, uniqueFiles) { |
713 | sizeInBytes += size_Block(&((const iFontFile *) *j.value)->sourceData); | 738 | sizeInBytes += ((const iBlockData *) *j.value)->size; |
714 | } | 739 | } |
715 | appendFormat_String(str, "%.1f ${mb} (%s) \u2014 %s\n", | 740 | appendFormat_String(str, "%.1f ${mb} ", sizeInBytes / 1.0e6); |
716 | sizeInBytes / 1.0e6, | 741 | if (size_PtrSet(uniqueFiles) > 1 || size_StringList(names) > 1) { |
717 | formatCStrs_Lang("num.files.n", size_PtrSet(uniqueFiles)), | 742 | appendFormat_String(str, "("); |
718 | // formatCStrs_Lang("num.fonts.n", size_StringList(names)), | 743 | if (size_PtrSet(uniqueFiles) > 1) { |
719 | cstrCollect_String(joinCStr_StringList(names, ", ")), | 744 | appendCStr_String(str, formatCStrs_Lang("num.files.n", size_PtrSet(uniqueFiles))); |
720 | d->version); | 745 | } |
746 | if (size_StringList(names) > 1) { | ||
747 | if (!endsWith_String(str, "(")) { | ||
748 | appendCStr_String(str, ", "); | ||
749 | } | ||
750 | appendCStr_String(str, formatCStrs_Lang("num.fonts.n", size_StringList(names))); | ||
751 | } | ||
752 | appendFormat_String(str, ")"); | ||
753 | } | ||
754 | appendFormat_String(str, " \u2014 %s\n", cstrCollect_String(joinCStr_StringList(names, ", "))); | ||
721 | if (isInstalled && installedVersion != d->version) { | 755 | if (isInstalled && installedVersion != d->version) { |
722 | appendCStr_String(str, format_Lang("${fontpack.meta.version}\n", d->version)); | 756 | appendCStr_String(str, format_Lang("${fontpack.meta.version}\n", d->version)); |
723 | } | 757 | } |