| 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
|
|
|
|
|
|
|
|