File Coverage

third_party/modest/source/myfont/myfont.c
Criterion Covered Total %
statement 0 242 0.0
branch 0 128 0.0
condition n/a
subroutine n/a
pod n/a
total 0 370 0.0


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2016-2017 Alexander Borisov
3            
4             This library is free software; you can redistribute it and/or
5             modify it under the terms of the GNU Lesser General Public
6             License as published by the Free Software Foundation; either
7             version 2.1 of the License, or (at your option) any later version.
8            
9             This library is distributed in the hope that it will be useful,
10             but WITHOUT ANY WARRANTY; without even the implied warranty of
11             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12             Lesser General Public License for more details.
13            
14             You should have received a copy of the GNU Lesser General Public
15             License along with this library; if not, write to the Free Software
16             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17            
18             Author: lex.borisov@gmail.com (Alexander Borisov)
19             */
20              
21             #include "myfont/myfont.h"
22              
23             const char myfont_table_name[][5] = {
24             "cmap", "head", "hhea", "hmtx", "maxp", "name",
25             "OS/2", "post", "cvt" , "fpgm", "glyf", "loca",
26             "prep", "gasp", "CFF" , "VORG", "SVG" , "EBDT",
27             "EBLC", "EBSC", "CBDT", "CBLC", "BASE", "GDEF",
28             "GPOS", "GSUB", "JSTF", "MATH", "DSIG", "hdmx",
29             "kern", "LTSH", "PCLT", "VDMX", "vhea", "vmtx",
30             "COLR", "CPAL"
31             };
32              
33 0           myfont_font_t * myfont_create(void)
34             {
35 0           return (myfont_font_t *)mycore_calloc(1, sizeof(myfont_font_t));
36             }
37              
38 0           mystatus_t myfont_init(myfont_font_t *mf)
39             {
40             mystatus_t status;
41            
42 0           mf->mchar = mchar_async_create();
43 0 0         if(mf->mchar == NULL)
44 0           return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION;
45            
46 0 0         if((status = mchar_async_init(mf->mchar, 64, (4096 * 2))))
47 0           return status;
48            
49 0           mf->mchar_node_id = mchar_async_node_add(mf->mchar, &status);
50            
51 0 0         if(status)
52 0           return status;
53            
54 0           memset(mf->cache.tables_offset, 0, sizeof(uint32_t) * MyFONT_TKEY_LAST_KEY);
55 0           memset(&mf->header, 0, sizeof(myfont_header_t));
56            
57 0           return MyFONT_STATUS_OK;
58             }
59              
60 0           void myfont_clean(myfont_font_t *mf)
61             {
62 0           mchar_async_node_clean(mf->mchar, mf->mchar_node_id);
63            
64 0           memset(mf->cache.tables_offset, 0, sizeof(uint32_t) * MyFONT_TKEY_LAST_KEY);
65 0           memset(&mf->header, 0, sizeof(myfont_header_t));
66 0           memset(mf, 0, sizeof(myfont_font_t));
67 0           }
68              
69 0           myfont_font_t * myfont_destroy(myfont_font_t *mf, bool self_destroy)
70             {
71 0 0         if(mf == NULL)
72 0           return NULL;
73            
74 0           mf->mchar = mchar_async_destroy(mf->mchar, 1);
75            
76 0 0         if(self_destroy) {
77 0           mycore_free(mf);
78 0           return NULL;
79             }
80            
81 0           return mf;
82             }
83              
84 0           void * myfont_malloc(myfont_font_t* mf, size_t size)
85             {
86 0           return (void*)mchar_async_malloc(mf->mchar, mf->mchar_node_id, size);
87             }
88              
89 0           void * myfont_calloc(myfont_font_t* mf, size_t count, size_t size)
90             {
91 0           void *data = (void*)mchar_async_malloc(mf->mchar, mf->mchar_node_id, (size * count));
92 0           memset(data, 0, (size * count));
93            
94 0           return data;
95             }
96              
97 0           void myfont_free(myfont_font_t *mf, void* data)
98             {
99 0           mchar_async_free(mf->mchar, mf->mchar_node_id, data);
100 0           }
101              
102 0           mystatus_t myfont_load_from_file(myfont_font_t *mf, const char *filepath, uint8_t** return_data, size_t* data_size)
103             {
104 0 0         if(return_data)
105 0           *return_data = NULL;
106            
107 0 0         if(data_size)
108 0           *data_size = 0;
109            
110             size_t file_data_size;
111            
112 0           FILE *fh = mycore_fopen(filepath, "rb");
113 0 0         if(fh == NULL)
114 0           return MyFONT_STATUS_ERROR_FILE_OPEN;
115            
116 0 0         if(mycore_fseek(fh, 0L, SEEK_END)) {
117 0           mycore_fclose(fh);
118 0           return MyFONT_STATUS_ERROR_FILE_SEEK;
119             }
120            
121 0           long file_size = mycore_ftell(fh);
122 0 0         if(file_size == -1) {
123 0           mycore_fclose(fh);
124 0           return MyFONT_STATUS_ERROR_FILE_TELL;
125             }
126            
127 0 0         if(mycore_fseek(fh, 0L, SEEK_SET)) {
128 0           mycore_fclose(fh);
129 0           return MyFONT_STATUS_ERROR_FILE_SEEK;
130             }
131            
132 0 0         if(file_size > 0)
133 0           file_data_size = (size_t)file_size;
134             else {
135 0           mycore_fclose(fh);
136 0           return MyFONT_STATUS_ERROR_FILE_TOO_SMALL;
137             }
138            
139 0           uint8_t* data = (uint8_t*)mycore_malloc(file_size);
140            
141 0 0         if(data == NULL) {
142 0           mycore_fclose(fh);
143 0           return MyFONT_STATUS_ERROR_MEMORY_ALLOCATION;
144             }
145            
146 0 0         if(mycore_fread(data, 1, file_size, fh) != file_size) {
147 0           mycore_fclose(fh);
148 0           return MyFONT_STATUS_ERROR_FILE_READ;
149             }
150            
151 0           mycore_fclose(fh);
152            
153 0 0         if(return_data)
154 0           *return_data = data;
155            
156 0 0         if(data_size)
157 0           *data_size = file_data_size;
158            
159 0           return myfont_load(mf, data, file_data_size);
160             }
161              
162 0           void * myfont_destroy_font_data(myfont_font_t *mf, uint8_t* return_data)
163             {
164 0 0         if(return_data)
165 0           return mycore_free(return_data);
166            
167 0           return NULL;
168             }
169              
170 0           mystatus_t myfont_load(myfont_font_t *mf, uint8_t* font_data, size_t data_size)
171             {
172 0 0         if(data_size < 12)
173 0           return MyFONT_STATUS_ERROR_TABLE_UNEXPECTED_ENDING;
174            
175 0           uint8_t* data = font_data;
176            
177 0           mf->header.version_major = myfont_read_u16(&data);
178 0           mf->header.version_minor = myfont_read_u16(&data);
179 0           mf->header.numTables = myfont_read_u16(&data);
180 0           mf->header.searchRange = myfont_read_u16(&data);
181 0           mf->header.entrySelector = myfont_read_u16(&data);
182 0           mf->header.rangeShift = myfont_read_u16(&data);
183            
184 0 0         if(data_size < (12 + (mf->header.numTables * 16)))
185 0           return MyFONT_STATUS_ERROR_TABLE_UNEXPECTED_ENDING;
186            
187 0 0         for(uint16_t i = 0; i < mf->header.numTables; i++)
188             {
189             myfont_table_t table;
190 0           table.tag = myfont_read_u32_as_net(&data);
191 0           table.checkSum = myfont_read_u32(&data);
192 0           table.offset = myfont_read_u32(&data);
193 0           table.length = myfont_read_u32(&data);
194            
195 0           switch(table.tag) {
196 0           case MyFONT_TABLE_TYPE_cmap: mf->cache.tables_offset[ MyFONT_TKEY_cmap ] = table.offset; break;
197 0           case MyFONT_TABLE_TYPE_head: mf->cache.tables_offset[ MyFONT_TKEY_head ] = table.offset; break;
198 0           case MyFONT_TABLE_TYPE_hhea: mf->cache.tables_offset[ MyFONT_TKEY_hhea ] = table.offset; break;
199 0           case MyFONT_TABLE_TYPE_hmtx: mf->cache.tables_offset[ MyFONT_TKEY_hmtx ] = table.offset; break;
200 0           case MyFONT_TABLE_TYPE_maxp: mf->cache.tables_offset[ MyFONT_TKEY_maxp ] = table.offset; break;
201 0           case MyFONT_TABLE_TYPE_name: mf->cache.tables_offset[ MyFONT_TKEY_name ] = table.offset; break;
202 0           case MyFONT_TABLE_TYPE_OS_2: mf->cache.tables_offset[ MyFONT_TKEY_OS_2 ] = table.offset; break;
203 0           case MyFONT_TABLE_TYPE_post: mf->cache.tables_offset[ MyFONT_TKEY_post ] = table.offset; break;
204 0           case MyFONT_TABLE_TYPE_cvt: mf->cache.tables_offset[ MyFONT_TKEY_cvt ] = table.offset; break;
205 0           case MyFONT_TABLE_TYPE_fpgm: mf->cache.tables_offset[ MyFONT_TKEY_fpgm ] = table.offset; break;
206 0           case MyFONT_TABLE_TYPE_glyf: mf->cache.tables_offset[ MyFONT_TKEY_glyf ] = table.offset; break;
207 0           case MyFONT_TABLE_TYPE_loca: mf->cache.tables_offset[ MyFONT_TKEY_loca ] = table.offset; break;
208 0           case MyFONT_TABLE_TYPE_prep: mf->cache.tables_offset[ MyFONT_TKEY_prep ] = table.offset; break;
209 0           case MyFONT_TABLE_TYPE_gasp: mf->cache.tables_offset[ MyFONT_TKEY_gasp ] = table.offset; break;
210 0           case MyFONT_TABLE_TYPE_CFF: mf->cache.tables_offset[ MyFONT_TKEY_CFF ] = table.offset; break;
211 0           case MyFONT_TABLE_TYPE_VORG: mf->cache.tables_offset[ MyFONT_TKEY_VORG ] = table.offset; break;
212 0           case MyFONT_TABLE_TYPE_SVG: mf->cache.tables_offset[ MyFONT_TKEY_SVG ] = table.offset; break;
213 0           case MyFONT_TABLE_TYPE_EBDT: mf->cache.tables_offset[ MyFONT_TKEY_EBDT ] = table.offset; break;
214 0           case MyFONT_TABLE_TYPE_EBLC: mf->cache.tables_offset[ MyFONT_TKEY_EBLC ] = table.offset; break;
215 0           case MyFONT_TABLE_TYPE_EBSC: mf->cache.tables_offset[ MyFONT_TKEY_EBSC ] = table.offset; break;
216 0           case MyFONT_TABLE_TYPE_CBDT: mf->cache.tables_offset[ MyFONT_TKEY_CBDT ] = table.offset; break;
217 0           case MyFONT_TABLE_TYPE_CBLC: mf->cache.tables_offset[ MyFONT_TKEY_CBLC ] = table.offset; break;
218 0           case MyFONT_TABLE_TYPE_BASE: mf->cache.tables_offset[ MyFONT_TKEY_BASE ] = table.offset; break;
219 0           case MyFONT_TABLE_TYPE_GDEF: mf->cache.tables_offset[ MyFONT_TKEY_GDEF ] = table.offset; break;
220 0           case MyFONT_TABLE_TYPE_GPOS: mf->cache.tables_offset[ MyFONT_TKEY_GPOS ] = table.offset; break;
221 0           case MyFONT_TABLE_TYPE_GSUB: mf->cache.tables_offset[ MyFONT_TKEY_GSUB ] = table.offset; break;
222 0           case MyFONT_TABLE_TYPE_JSTF: mf->cache.tables_offset[ MyFONT_TKEY_JSTF ] = table.offset; break;
223 0           case MyFONT_TABLE_TYPE_MATH: mf->cache.tables_offset[ MyFONT_TKEY_MATH ] = table.offset; break;
224 0           case MyFONT_TABLE_TYPE_DSIG: mf->cache.tables_offset[ MyFONT_TKEY_DSIG ] = table.offset; break;
225 0           case MyFONT_TABLE_TYPE_hdmx: mf->cache.tables_offset[ MyFONT_TKEY_hdmx ] = table.offset; break;
226 0           case MyFONT_TABLE_TYPE_kern: mf->cache.tables_offset[ MyFONT_TKEY_kern ] = table.offset; break;
227 0           case MyFONT_TABLE_TYPE_LTSH: mf->cache.tables_offset[ MyFONT_TKEY_LTSH ] = table.offset; break;
228 0           case MyFONT_TABLE_TYPE_PCLT: mf->cache.tables_offset[ MyFONT_TKEY_PCLT ] = table.offset; break;
229 0           case MyFONT_TABLE_TYPE_VDMX: mf->cache.tables_offset[ MyFONT_TKEY_VDMX ] = table.offset; break;
230 0           case MyFONT_TABLE_TYPE_vhea: mf->cache.tables_offset[ MyFONT_TKEY_vhea ] = table.offset; break;
231 0           case MyFONT_TABLE_TYPE_vmtx: mf->cache.tables_offset[ MyFONT_TKEY_vmtx ] = table.offset; break;
232 0           case MyFONT_TABLE_TYPE_COLR: mf->cache.tables_offset[ MyFONT_TKEY_COLR ] = table.offset; break;
233 0           case MyFONT_TABLE_TYPE_CPAL: mf->cache.tables_offset[ MyFONT_TKEY_CPAL ] = table.offset; break;
234             default:
235 0           break;
236             };
237             }
238            
239 0 0         if(myfont_check_required_tables(mf))
240 0           return MyFONT_STATUS_ERROR_TABLE_LACKS_REQUIRED;
241            
242             mystatus_t status;
243            
244 0 0         if((status = myfont_load_table_cmap(mf, font_data, data_size)))
245 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_CMAP;
246            
247 0 0         if((status = myfont_load_table_head(mf, font_data, data_size)))
248 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_HEAD;
249            
250 0 0         if((status = myfont_load_table_name(mf, font_data, data_size)))
251 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_NAME;
252            
253 0 0         if((status = myfont_load_table_os_2(mf, font_data, data_size)))
254 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_OS_2;
255            
256 0 0         if((status = myfont_load_table_maxp(mf, font_data, data_size)))
257 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_MAXP;
258            
259 0 0         if((status = myfont_load_table_hhea(mf, font_data, data_size)))
260 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_HHEA;
261            
262 0 0         if((status = myfont_load_table_hmtx(mf, font_data, data_size)))
263 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_HMTX;
264            
265 0 0         if((status = myfont_load_table_loca(mf, font_data, data_size)))
266 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_LOCA;
267            
268 0 0         if((status = myfont_load_table_glyf(mf, font_data, data_size)))
269 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_GLYF;
270            
271 0 0         if((status = myfont_load_table_vhea(mf, font_data, data_size)))
272 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_VHEA;
273            
274 0 0         if((status = myfont_load_table_vmtx(mf, font_data, data_size)))
275 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_VMTX;
276            
277 0 0         if((status = myfont_load_table_pclt(mf, font_data, data_size)))
278 0           return MyFONT_STATUS_ERROR_TABLE_LOAD_PCLT;
279            
280 0           return MyFONT_STATUS_OK;
281             }
282              
283 0           mystatus_t myfont_check_required_tables(myfont_font_t *mf)
284             {
285 0 0         if(mf->cache.tables_offset[ MyFONT_TKEY_cmap ] == 0 ||
    0          
286 0 0         mf->cache.tables_offset[ MyFONT_TKEY_glyf ] == 0 ||
287 0 0         mf->cache.tables_offset[ MyFONT_TKEY_head ] == 0 ||
288 0 0         mf->cache.tables_offset[ MyFONT_TKEY_hhea ] == 0 ||
289 0 0         mf->cache.tables_offset[ MyFONT_TKEY_hmtx ] == 0 ||
290 0 0         mf->cache.tables_offset[ MyFONT_TKEY_loca ] == 0 ||
291 0 0         mf->cache.tables_offset[ MyFONT_TKEY_maxp ] == 0 ||
292 0 0         mf->cache.tables_offset[ MyFONT_TKEY_name ] == 0 ||
293 0           mf->cache.tables_offset[ MyFONT_TKEY_post ] == 0)
294 0           return MyFONT_STATUS_ERROR_TABLE_LACKS_REQUIRED;
295            
296 0           return MyFONT_STATUS_OK;
297             }
298              
299             // metrics
300 0           float myfont_metrics_baseline(myfont_font_t *mf, float font_size)
301             {
302 0           return (float)(mf->table_hhea.Ascender) * font_size / ((float)(mf->table_head.unitsPerEm));
303             }
304              
305 0           float myfont_metrics_ascender(myfont_font_t *mf, float font_size)
306             {
307 0           return 0.0f;
308             }
309              
310 0           float myfont_metrics_descender(myfont_font_t *mf, float font_size)
311             {
312 0           return (float)(mf->table_hhea.Ascender - mf->table_hhea.Descender) * font_size / ((float)(mf->table_head.unitsPerEm));
313             }
314              
315 0           float myfont_metrics_line_gap(myfont_font_t *mf, float font_size)
316             {
317 0           return (float)(mf->table_hhea.LineGap) * font_size / ((float)(mf->table_head.unitsPerEm));
318             }
319              
320 0           float myfont_metrics_x_height(myfont_font_t *mf, float font_size)
321             {
322 0           int16_t xheight = 0;
323            
324 0 0         if(mf->table_os_2.version > 1)
325             {
326 0 0         if(mf->table_os_2.sxHeight)
327 0           xheight = mf->table_os_2.sxHeight;
328             }
329            
330 0 0         if(xheight == 0 && mf->table_pclt.xHeight)
    0          
331 0           xheight = (int16_t)mf->table_pclt.xHeight;
332            
333 0 0         if(xheight == 0)
334             {
335             mystatus_t mf_status;
336 0           uint16_t glyph_index = myfont_glyph_index_by_codepoint(mf, (unsigned long)('x'), &mf_status);
337            
338 0 0         if(mf_status == MyFONT_STATUS_OK) {
339 0           myfont_table_glyph_t *glyph = &mf->table_glyf.cache[glyph_index];
340 0           xheight = glyph->head.yMax;
341             }
342             }
343            
344 0           return (float)((mf->table_hhea.Ascender) - xheight) * font_size / (float)(mf->table_head.unitsPerEm);
345             }
346              
347 0           float myfont_metrics_cap_height(myfont_font_t *mf, float font_size)
348             {
349 0           int16_t cap_height = 0;
350            
351 0 0         if(mf->table_os_2.version > 1) {
352 0 0         if(mf->table_os_2.sCapHeight)
353 0           cap_height = mf->table_os_2.sCapHeight;
354             }
355            
356 0 0         if(cap_height == 0 && mf->table_pclt.capHeight)
    0          
357 0           cap_height = (int16_t)mf->table_pclt.capHeight;
358            
359 0 0         if(cap_height == 0)
360             {
361             mystatus_t mf_status;
362 0           uint16_t glyph_index = myfont_glyph_index_by_codepoint(mf, (unsigned long)('H'), &mf_status);
363            
364 0 0         if(mf_status == MyFONT_STATUS_OK) {
365 0           myfont_table_glyph_t *glyph = &mf->table_glyf.cache[glyph_index];
366 0           cap_height = glyph->head.yMax;
367             }
368             }
369            
370 0           return(float)((mf->table_hhea.Ascender) - cap_height) * font_size / (float)(mf->table_head.unitsPerEm);
371             }
372              
373 0           float myfont_metrics_font_height(myfont_font_t *mf, float font_size)
374             {
375 0           return (float)(mf->table_hhea.Ascender - mf->table_hhea.Descender) * font_size / (float)mf->table_head.unitsPerEm;
376             }
377              
378             // width, height and ...
379 0           float myfont_metrics_width(myfont_font_t *mf, unsigned long codepoint, float font_size, mystatus_t* status)
380             {
381 0 0         if(mf->table_hhea.numberOfHMetrics == 0 || mf->table_hmtx.hMetrics == NULL)
    0          
382 0           return 0.0f;
383            
384             mystatus_t mf_status;
385            
386 0           uint16_t glyph_index = myfont_glyph_index_by_codepoint(mf, codepoint, &mf_status);
387            
388 0 0         if(mf_status) {
389 0 0         if(status)
390 0           *status = mf_status;
391            
392 0           return 0.0f;
393             }
394            
395 0           return (float)(mf->table_hmtx.hMetrics[glyph_index].advanceWidth) * font_size / (float)(mf->table_head.unitsPerEm);
396             }
397              
398 0           float myfont_metrics_height(myfont_font_t *mf, unsigned long codepoint, float font_size, mystatus_t* status)
399             {
400 0 0         if(mf->table_vhea.numOfLongVerMetrics == 0 || mf->table_vmtx.vMetrics == NULL)
    0          
401 0           return myfont_metrics_font_height(mf, font_size);
402            
403             mystatus_t mf_status;
404            
405 0           uint16_t glyph_index = myfont_glyph_index_by_codepoint(mf, codepoint, &mf_status);
406            
407 0 0         if(mf_status) {
408 0 0         if(status)
409 0           *status = mf_status;
410            
411 0           return 0.0f;
412             }
413            
414 0           return (float)(mf->table_vmtx.vMetrics[glyph_index].advanceHeight) * font_size / (float)(mf->table_head.unitsPerEm);
415             }
416              
417 0           float myfont_metrics_glyph_offset_y(myfont_font_t *mf, unsigned long codepoint, float font_size, mystatus_t* status)
418             {
419             mystatus_t mf_status;
420            
421 0           uint16_t glyph_index = myfont_glyph_index_by_codepoint(mf, codepoint, &mf_status);
422            
423 0 0         if(mf_status) {
424 0 0         if(status)
425 0           *status = mf_status;
426            
427 0           return 0.0f;
428             }
429            
430 0           return (float)((mf->table_hhea.Ascender - mf->table_glyf.cache[glyph_index].head.yMax)) * font_size / ((float)mf->table_head.unitsPerEm);
431             }
432              
433 0           int16_t myfont_table_version_major(uint32_t version)
434             {
435 0           version = myfont_htonl(version);
436 0           version >>= 16;
437 0           return (int16_t)version;
438             }
439              
440 0           int16_t myfont_table_version_minor(uint32_t version)
441             {
442 0           version = myfont_htonl(version);
443 0           version <<= 16;
444 0           version >>= 16;
445 0           return (int16_t)version;
446             }
447