diff options
Diffstat (limited to 'src/fontpack.c')
-rw-r--r-- | src/fontpack.c | 112 |
1 files changed, 84 insertions, 28 deletions
diff --git a/src/fontpack.c b/src/fontpack.c index a1f3b829..3b42e848 100644 --- a/src/fontpack.c +++ b/src/fontpack.c | |||
@@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
32 | 32 | ||
33 | #include "embedded.h" | 33 | #include "embedded.h" |
34 | 34 | ||
35 | /* TODO: Clean up and/or reorder this file, it's a bit unorganized. */ | ||
36 | |||
35 | float scale_FontSize(enum iFontSize size) { | 37 | float scale_FontSize(enum iFontSize size) { |
36 | static const float sizes[max_FontSize] = { | 38 | static const float sizes[max_FontSize] = { |
37 | 1.000, /* UI sizes */ | 39 | 1.000, /* UI sizes */ |
@@ -46,8 +48,7 @@ float scale_FontSize(enum iFontSize size) { | |||
46 | 1.666, | 48 | 1.666, |
47 | 2.000, | 49 | 2.000, |
48 | 0.568, | 50 | 0.568, |
49 | 0.710, | 51 | 0.710, /* calibration: fits the Lagrange title screen with Normal line width */ |
50 | 0.800, | ||
51 | }; | 52 | }; |
52 | if (size < 0 || size >= max_FontSize) { | 53 | if (size < 0 || size >= max_FontSize) { |
53 | return 1.0f; | 54 | return 1.0f; |
@@ -66,9 +67,30 @@ struct Impl_Fonts { | |||
66 | 67 | ||
67 | static iFonts fonts_; | 68 | static iFonts fonts_; |
68 | 69 | ||
70 | static void unloadFiles_Fonts_(iFonts *d) { | ||
71 | /* TODO: Mark all files in font packs as not resident. */ | ||
72 | iForEach(PtrArray, i, &d->files) { | ||
73 | delete_FontFile(i.ptr); | ||
74 | } | ||
75 | clear_PtrArray(&d->files); | ||
76 | } | ||
77 | |||
78 | static iFontFile *findFile_Fonts_(iFonts *d, const iString *id) { | ||
79 | iForEach(PtrArray, i, &d->files) { | ||
80 | iFontFile *ff = i.ptr; | ||
81 | if (equal_String(&ff->id, id)) { | ||
82 | return ff; | ||
83 | } | ||
84 | } | ||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | /*----------------------------------------------------------------------------------------------*/ | ||
89 | |||
69 | iDefineTypeConstruction(FontFile) | 90 | iDefineTypeConstruction(FontFile) |
70 | 91 | ||
71 | void init_FontFile(iFontFile *d) { | 92 | void init_FontFile(iFontFile *d) { |
93 | init_String(&d->id); | ||
72 | d->style = regular_FontStyle; | 94 | d->style = regular_FontStyle; |
73 | init_Block(&d->sourceData, 0); | 95 | init_Block(&d->sourceData, 0); |
74 | iZap(d->stbInfo); | 96 | iZap(d->stbInfo); |
@@ -111,6 +133,7 @@ static void unload_FontFile_(iFontFile *d) { | |||
111 | void deinit_FontFile(iFontFile *d) { | 133 | void deinit_FontFile(iFontFile *d) { |
112 | unload_FontFile_(d); | 134 | unload_FontFile_(d); |
113 | deinit_Block(&d->sourceData); | 135 | deinit_Block(&d->sourceData); |
136 | deinit_String(&d->id); | ||
114 | } | 137 | } |
115 | 138 | ||
116 | float scaleForPixelHeight_FontFile(const iFontFile *d, int pixelHeight) { | 139 | float scaleForPixelHeight_FontFile(const iFontFile *d, int pixelHeight) { |
@@ -140,8 +163,11 @@ void init_FontSpec(iFontSpec *d) { | |||
140 | init_String(&d->name); | 163 | init_String(&d->name); |
141 | d->flags = 0; | 164 | d->flags = 0; |
142 | d->priority = 0; | 165 | d->priority = 0; |
143 | d->scaling = 1.0f; | 166 | for (int i = 0; i < 2; ++i) { |
144 | d->vertOffset = 1.0f; | 167 | d->heightScale[i] = 1.0f; |
168 | d->glyphScale[i] = 1.0f; | ||
169 | d->vertOffsetScale[i] = 1.0f; | ||
170 | } | ||
145 | iZap(d->styles); | 171 | iZap(d->styles); |
146 | } | 172 | } |
147 | 173 | ||
@@ -154,12 +180,12 @@ void deinit_FontSpec(iFontSpec *d) { | |||
154 | 180 | ||
155 | iDeclareType(FontPack) | 181 | iDeclareType(FontPack) |
156 | iDeclareTypeConstruction(FontPack) | 182 | iDeclareTypeConstruction(FontPack) |
157 | 183 | ||
158 | struct Impl_FontPack { | 184 | struct Impl_FontPack { |
159 | const iArchive *archive; /* opened ZIP archive */ | 185 | const iArchive *archive; /* opened ZIP archive */ |
160 | iArray fonts; /* array of FontSpecs */ | 186 | iArray fonts; /* array of FontSpecs */ |
161 | iString * loadPath; | 187 | iString * loadPath; |
162 | iFontSpec *loadSpec; | 188 | iFontSpec * loadSpec; |
163 | }; | 189 | }; |
164 | 190 | ||
165 | void init_FontPack(iFontPack *d) { | 191 | void init_FontPack(iFontPack *d) { |
@@ -238,11 +264,27 @@ void handleIniKeyValue_FontPack_(void *context, const iString *table, const iStr | |||
238 | else if (!cmp_String(key, "priority") && value->type == int64_TomlType) { | 264 | else if (!cmp_String(key, "priority") && value->type == int64_TomlType) { |
239 | d->loadSpec->priority = (int) value->value.int64; | 265 | d->loadSpec->priority = (int) value->value.int64; |
240 | } | 266 | } |
241 | else if (!cmp_String(key, "scaling")) { | 267 | else if (!cmp_String(key, "height")) { |
242 | d->loadSpec->scaling = (float) number_TomlValue(value); | 268 | d->loadSpec->heightScale[0] = d->loadSpec->heightScale[1] = (float) number_TomlValue(value); |
269 | } | ||
270 | else if (!cmp_String(key, "glyphscale")) { | ||
271 | d->loadSpec->glyphScale[0] = d->loadSpec->glyphScale[1] = (float) number_TomlValue(value); | ||
243 | } | 272 | } |
244 | else if (!cmp_String(key, "voffset")) { | 273 | else if (!cmp_String(key, "voffset")) { |
245 | d->loadSpec->vertOffset = (float) number_TomlValue(value); | 274 | d->loadSpec->vertOffsetScale[0] = d->loadSpec->vertOffsetScale[1] = |
275 | (float) number_TomlValue(value); | ||
276 | } | ||
277 | else if (startsWith_String(key, "ui.") || startsWith_String(key, "doc.")) { | ||
278 | const int scope = startsWith_String(key, "ui.") ? 0 : 1; | ||
279 | if (endsWith_String(key, ".height")) { | ||
280 | d->loadSpec->heightScale[scope] = (float) number_TomlValue(value); | ||
281 | } | ||
282 | if (endsWith_String(key, ".glyphscale")) { | ||
283 | d->loadSpec->glyphScale[scope] = (float) number_TomlValue(value); | ||
284 | } | ||
285 | else if (endsWith_String(key, ".voffset")) { | ||
286 | d->loadSpec->vertOffsetScale[scope] = (float) number_TomlValue(value); | ||
287 | } | ||
246 | } | 288 | } |
247 | else if (!cmp_String(key, "override") && value->type == boolean_TomlType) { | 289 | else if (!cmp_String(key, "override") && value->type == boolean_TomlType) { |
248 | iChangeFlags(d->loadSpec->flags, override_FontSpecFlag, value->value.boolean); | 290 | iChangeFlags(d->loadSpec->flags, override_FontSpecFlag, value->value.boolean); |
@@ -265,14 +307,20 @@ void handleIniKeyValue_FontPack_(void *context, const iString *table, const iStr | |||
265 | iForIndices(i, styles) { | 307 | iForIndices(i, styles) { |
266 | if (!cmp_String(key, styles[i]) && !d->loadSpec->styles[i]) { | 308 | if (!cmp_String(key, styles[i]) && !d->loadSpec->styles[i]) { |
267 | iFontFile *ff = NULL; | 309 | iFontFile *ff = NULL; |
268 | iBlock *data = readFile_FontPack_(d, value->value.string); | 310 | iString *fontFileId = concat_Path(d->loadPath, value->value.string); |
269 | if (data) { | 311 | if (!(ff = findFile_Fonts_(&fonts_, fontFileId))) { |
270 | ff = new_FontFile(); | 312 | iBlock *data = readFile_FontPack_(d, value->value.string); |
271 | load_FontFile_(ff, data); | 313 | if (data) { |
272 | pushBack_PtrArray(&fonts_.files, ff); /* centralized ownership */ | 314 | ff = new_FontFile(); |
273 | d->loadSpec->styles[i] = ff; | 315 | set_String(&ff->id, fontFileId); |
274 | delete_Block(data); | 316 | load_FontFile_(ff, data); |
317 | pushBack_PtrArray(&fonts_.files, ff); /* centralized ownership */ | ||
318 | delete_Block(data); | ||
319 | // printf("[FontPack] loaded file: %s\n", cstr_String(fontFileId)); | ||
320 | } | ||
275 | } | 321 | } |
322 | d->loadSpec->styles[i] = ff; | ||
323 | delete_String(fontFileId); | ||
276 | break; | 324 | break; |
277 | } | 325 | } |
278 | } | 326 | } |
@@ -290,7 +338,6 @@ static iBool load_FontPack_(iFontPack *d, const iString *ini) { | |||
290 | setHandlers_TomlParser(toml, handleIniTable_FontPack_, handleIniKeyValue_FontPack_, d); | 338 | setHandlers_TomlParser(toml, handleIniTable_FontPack_, handleIniKeyValue_FontPack_, d); |
291 | if (parse_TomlParser(toml, ini)) { | 339 | if (parse_TomlParser(toml, ini)) { |
292 | ok = iTrue; | 340 | ok = iTrue; |
293 | // fprintf(stderr, "[FontPack] error parsing %s\n", cstr_String(iniPath)); | ||
294 | } | 341 | } |
295 | iAssert(d->loadSpec == NULL); | 342 | iAssert(d->loadSpec == NULL); |
296 | // d->loadPath = NULL; | 343 | // d->loadPath = NULL; |
@@ -331,7 +378,7 @@ iBool loadArchive_FontPack(iFontPack *d, const iArchive *zip) { | |||
331 | initBlock_String(&ini, iniData); | 378 | initBlock_String(&ini, iniData); |
332 | if (load_FontPack_(d, &ini)) { | 379 | if (load_FontPack_(d, &ini)) { |
333 | ok = iTrue; | 380 | ok = iTrue; |
334 | } | 381 | } |
335 | deinit_String(&ini); | 382 | deinit_String(&ini); |
336 | } | 383 | } |
337 | return ok; | 384 | return ok; |
@@ -339,14 +386,6 @@ iBool loadArchive_FontPack(iFontPack *d, const iArchive *zip) { | |||
339 | 386 | ||
340 | /*----------------------------------------------------------------------------------------------*/ | 387 | /*----------------------------------------------------------------------------------------------*/ |
341 | 388 | ||
342 | static void unloadFiles_Fonts_(iFonts *d) { | ||
343 | /* TODO: Mark all files in font packs as not resident. */ | ||
344 | iForEach(PtrArray, i, &d->files) { | ||
345 | delete_FontFile(i.ptr); | ||
346 | } | ||
347 | clear_PtrArray(&d->files); | ||
348 | } | ||
349 | |||
350 | static void unloadFonts_Fonts_(iFonts *d) { | 389 | static void unloadFonts_Fonts_(iFonts *d) { |
351 | iForEach(PtrArray, i, &d->packs) { | 390 | iForEach(PtrArray, i, &d->packs) { |
352 | iFontPack *pack = i.ptr; | 391 | iFontPack *pack = i.ptr; |
@@ -360,6 +399,11 @@ static int cmpPriority_FontSpecPtr_(const void *a, const void *b) { | |||
360 | return -iCmp((*p1)->priority, (*p2)->priority); /* highest priority first */ | 399 | return -iCmp((*p1)->priority, (*p2)->priority); /* highest priority first */ |
361 | } | 400 | } |
362 | 401 | ||
402 | static int cmpName_FontSpecPtr_(const void *a, const void *b) { | ||
403 | const iFontSpec **p1 = (const iFontSpec **) a, **p2 = (const iFontSpec **) b; | ||
404 | return cmpStringCase_String(&(*p1)->name, &(*p2)->name); | ||
405 | } | ||
406 | |||
363 | static void sortSpecs_Fonts_(iFonts *d) { | 407 | static void sortSpecs_Fonts_(iFonts *d) { |
364 | clear_PtrArray(&d->specOrder); | 408 | clear_PtrArray(&d->specOrder); |
365 | iConstForEach(PtrArray, p, &d->packs) { | 409 | iConstForEach(PtrArray, p, &d->packs) { |
@@ -410,6 +454,18 @@ const iFontSpec *findSpec_Fonts(const char *fontId) { | |||
410 | return NULL; | 454 | return NULL; |
411 | } | 455 | } |
412 | 456 | ||
457 | const iPtrArray *listSpecs_Fonts(iBool (*filterFunc)(const iFontSpec *)) { | ||
458 | iFonts *d = &fonts_; | ||
459 | iPtrArray *list = collectNew_PtrArray(); | ||
460 | iConstForEach(PtrArray, i, &d->specOrder) { | ||
461 | if (filterFunc == NULL || filterFunc(i.ptr)) { | ||
462 | pushBack_PtrArray(list, i.ptr); | ||
463 | } | ||
464 | } | ||
465 | sort_Array(list, cmpName_FontSpecPtr_); | ||
466 | return list; | ||
467 | } | ||
468 | |||
413 | const iPtrArray *listSpecsByPriority_Fonts(void) { | 469 | const iPtrArray *listSpecsByPriority_Fonts(void) { |
414 | return &fonts_.specOrder; | 470 | return &fonts_.specOrder; |
415 | } | 471 | } |