summaryrefslogtreecommitdiff
path: root/src/fontpack.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-10-05 06:55:51 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-10-05 06:55:51 +0300
commit827951d2807b031d131b7fc05b1596550d258676 (patch)
tree836a6a1ceb07cfbc1867ef65fcc30331b0ad33ba /src/fontpack.c
parent88993e95e5ff9fecc5980b25e1778053ca23afe0 (diff)
Started working on font packs
Diffstat (limited to 'src/fontpack.c')
-rw-r--r--src/fontpack.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/fontpack.c b/src/fontpack.c
new file mode 100644
index 00000000..af341363
--- /dev/null
+++ b/src/fontpack.c
@@ -0,0 +1,226 @@
1/* Copyright 2021 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#include "fontpack.h"
24
25#include <the_Foundation/archive.h>
26#include <the_Foundation/array.h>
27#include <the_Foundation/file.h>
28#include <the_Foundation/path.h>
29#include <the_Foundation/ptrarray.h>
30#include <the_Foundation/string.h>
31#include <the_Foundation/toml.h>
32
33iDeclareType(Fonts)
34
35struct Impl_Fonts {
36 iString userDir;
37 iPtrArray files;
38};
39
40static iFonts fonts_;
41
42iDefineTypeConstruction(FontFile)
43
44void init_FontFile(iFontFile *d) {
45 d->style = regular_FontStyle;
46 init_Block(&d->sourceData, 0);
47 iZap(d->stbInfo);
48#if defined (LAGRANGE_ENABLE_HARFBUZZ)
49 d->hbBlob = NULL;
50 d->hbFace = NULL;
51 d->hbFont = NULL;
52#endif
53}
54
55static void load_FontFile_(iFontFile *d, const iBlock *data) {
56 set_Block(&d->sourceData, data);
57 stbtt_InitFont(&d->stbInfo, constData_Block(&d->sourceData), 0);
58#if defined(LAGRANGE_ENABLE_HARFBUZZ)
59 /* HarfBuzz will read the font data. */
60 d->hbBlob = hb_blob_create(constData_Block(&d->sourceData), size_Block(&d->sourceData),
61 HB_MEMORY_MODE_READONLY, NULL, NULL);
62 d->hbFace = hb_face_create(d->hbBlob, 0);
63 d->hbFont = hb_font_create(d->hbFace);
64#endif
65}
66
67static void unload_FontFile_(iFontFile *d) {
68#if defined(LAGRANGE_ENABLE_HARFBUZZ)
69 /* HarfBuzz objects. */
70 hb_font_destroy(d->hbFont);
71 hb_face_destroy(d->hbFace);
72 hb_blob_destroy(d->hbBlob);
73 d->hbFont = NULL;
74 d->hbFace = NULL;
75 d->hbBlob = NULL;
76#endif
77 clear_Block(&d->sourceData);
78 iZap(d->stbInfo);
79}
80
81void deinit_FontFile(iFontFile *d) {
82 unload_FontFile_(d);
83 deinit_Block(&d->sourceData);
84}
85
86/*----------------------------------------------------------------------------------------------*/
87
88
89iDefineTypeConstruction(FontSpec)
90
91void init_FontSpec(iFontSpec *d) {
92 init_String(&d->id);
93 init_String(&d->name);
94}
95
96void deinit_FontSpec(iFontSpec *d) {
97 deinit_String(&d->name);
98 deinit_String(&d->id);
99}
100
101/*----------------------------------------------------------------------------------------------*/
102
103iDeclareType(FontPack)
104iDeclareTypeConstruction(FontPack)
105
106struct Impl_FontPack {
107 iArchive * archive; /* opened ZIP archive */
108 iArray fonts; /* array of FontSpecs */
109 iString * loadPath;
110 iFontSpec *loadSpec;
111};
112
113void init_FontPack(iFontPack *d) {
114 d->archive = NULL;
115 init_Array(&d->fonts, sizeof(iFontSpec));
116 d->loadSpec = NULL;
117 d->loadPath = NULL;
118}
119
120void deinit_FontPack(iFontPack *d) {
121 iForEach(Array, i, &d->fonts) {
122 deinit_FontSpec(i.value);
123 }
124 deinit_Array(&d->fonts);
125}
126
127void handleIniTable_FontPack_(void *context, const iString *table, iBool isStart) {
128 iFontPack *d = context;
129 if (isStart) {
130 iAssert(!d->loadSpec);
131 d->loadSpec = new_FontSpec();
132 set_String(&d->loadSpec->id, table);
133 }
134 else {
135 pushBack_Array(&d->fonts, d->loadSpec);
136 d->loadSpec = NULL;
137 }
138}
139
140void handleIniKeyValue_FontPack_(void *context, const iString *table, const iString *key,
141 const iTomlValue *value) {
142 iFontPack *d = context;
143 if (!d->loadSpec) return;
144 iUnused(table);
145 if (!cmp_String(key, "name") && value->type == string_TomlType) {
146 set_String(&d->loadSpec->name, value->value.string);
147 }
148 else if (!cmp_String(key, "priority") && value->type == int64_TomlType) {
149 d->loadSpec->priority = (int) value->value.int64;
150 }
151 else if (!cmp_String(key, "scaling")) {
152 d->loadSpec->scaling = (float) number_TomlValue(value);
153 }
154 else if (!cmp_String(key, "monospace") && value->type == boolean_TomlType) {
155 iChangeFlags(d->loadSpec->flags, monospace_FontSpecFlag, value->value.boolean);
156 }
157 else if (!cmp_String(key, "auxiliary") && value->type == boolean_TomlType) {
158 iChangeFlags(d->loadSpec->flags, auxiliary_FontSpecFlag, value->value.boolean);
159 }
160 else if (!cmp_String(key, "arabic") && value->type == boolean_TomlType) {
161 iChangeFlags(d->loadSpec->flags, arabic_FontSpecFlag, value->value.boolean);
162 }
163 else if (value->type == string_TomlType) {
164 const char *styles[max_FontStyle] = { "regular", "italic", "light", "semibold", "bold" };
165 iForIndices(i, styles) {
166 if (!cmp_String(key, styles[i]) && !d->loadSpec->styles[i]) {
167 iFontFile *ff = NULL;
168 /* Loading from a regular file. */
169 iFile *srcFile = new_File(collect_String(concat_Path(d->loadPath,
170 value->value.string)));
171 if (open_File(srcFile, readOnly_FileMode)) {
172 ff = new_FontFile();
173 iBlock *data = readAll_File(srcFile);
174 load_FontFile_(ff, data);
175 delete_Block(data);
176 pushBack_PtrArray(&fonts_.files, ff); /* centralized ownership */
177 d->loadSpec->styles[i] = ff;
178 }
179 iRelease(srcFile);
180 break;
181 }
182 }
183 }
184}
185
186iBool loadIniFile_FontPack(iFontPack *d, const iString *iniPath) {
187 iBeginCollect();
188 iBool ok = iFalse;
189 iFile *f = iClob(new_File(iniPath));
190 if (open_File(f, text_FileMode | readOnly_FileMode)) {
191 d->loadPath = collect_String(newRange_String(dirName_Path(iniPath)));
192 iString *src = collect_String(readString_File(f));
193 iTomlParser *ini = collect_TomlParser(new_TomlParser());
194 setHandlers_TomlParser(ini, 0, 0, d);
195 parse_TomlParser(ini, src);
196 iAssert(d->loadSpec == NULL);
197 d->loadPath = NULL;
198 ok = iTrue;
199 }
200 iEndCollect();
201 return ok;
202}
203
204/*----------------------------------------------------------------------------------------------*/
205
206static void unloadFiles_Fonts_(iFonts *d) {
207 iForEach(PtrArray, i, &d->files) {
208 delete_FontFile(i.ptr);
209 }
210 clear_PtrArray(&d->files);
211}
212
213void init_Fonts(const char *userDir) {
214 iFonts *d = &fonts_;
215 initCStr_String(&d->userDir, userDir);
216 init_PtrArray(&d->files);
217 /* Load the required fonts. */
218
219}
220
221void deinit_Fonts(void) {
222 iFonts *d = &fonts_;
223 unloadFiles_Fonts_(d);
224 deinit_PtrArray(&d->files);
225 deinit_String(&d->userDir);
226}