summaryrefslogtreecommitdiff
path: root/src/fontpack.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-10-29 14:00:41 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-10-29 14:00:41 +0300
commitd98604ca3bd3f3986a42c4e9e1c4228089e39024 (patch)
tree9d3fdd5115d86300027476882417fb5127278963 /src/fontpack.c
parentb99c6e693b8ade1fa117f4cb54105366a7768da0 (diff)
FontPack: Loading fonts from TTC files
Diffstat (limited to 'src/fontpack.c')
-rw-r--r--src/fontpack.c80
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
66void init_FontFile(iFontFile *d) { 67void 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
78static void load_FontFile_(iFontFile *d, const iBlock *data) { 80static 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
178static iFonts fonts_; 183static 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
529void init_Fonts(const char *userDir) { 552void 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 }