summaryrefslogtreecommitdiff
path: root/src/fontpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fontpack.c')
-rw-r--r--src/fontpack.c112
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
35float scale_FontSize(enum iFontSize size) { 37float 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
67static iFonts fonts_; 68static iFonts fonts_;
68 69
70static 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
78static 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
69iDefineTypeConstruction(FontFile) 90iDefineTypeConstruction(FontFile)
70 91
71void init_FontFile(iFontFile *d) { 92void 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) {
111void deinit_FontFile(iFontFile *d) { 133void 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
116float scaleForPixelHeight_FontFile(const iFontFile *d, int pixelHeight) { 139float 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
155iDeclareType(FontPack) 181iDeclareType(FontPack)
156iDeclareTypeConstruction(FontPack) 182iDeclareTypeConstruction(FontPack)
157 183
158struct Impl_FontPack { 184struct 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
165void init_FontPack(iFontPack *d) { 191void 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
342static 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
350static void unloadFonts_Fonts_(iFonts *d) { 389static 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
402static 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
363static void sortSpecs_Fonts_(iFonts *d) { 407static 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
457const 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
413const iPtrArray *listSpecsByPriority_Fonts(void) { 469const iPtrArray *listSpecsByPriority_Fonts(void) {
414 return &fonts_.specOrder; 470 return &fonts_.specOrder;
415} 471}