/src/skia/third_party/externals/freetype/src/sfnt/sfobjs.c
Line | Count | Source (jump to first uncovered line) |
1 | | /**************************************************************************** |
2 | | * |
3 | | * sfobjs.c |
4 | | * |
5 | | * SFNT object management (base). |
6 | | * |
7 | | * Copyright (C) 1996-2021 by |
8 | | * David Turner, Robert Wilhelm, and Werner Lemberg. |
9 | | * |
10 | | * This file is part of the FreeType project, and may only be used, |
11 | | * modified, and distributed under the terms of the FreeType project |
12 | | * license, LICENSE.TXT. By continuing to use, modify, or distribute |
13 | | * this file you indicate that you have read the license and |
14 | | * understand and accept it fully. |
15 | | * |
16 | | */ |
17 | | |
18 | | |
19 | | #include "sfobjs.h" |
20 | | #include "ttload.h" |
21 | | #include "ttcmap.h" |
22 | | #include "ttkern.h" |
23 | | #include "sfwoff.h" |
24 | | #include "sfwoff2.h" |
25 | | #include <freetype/internal/sfnt.h> |
26 | | #include <freetype/internal/ftdebug.h> |
27 | | #include <freetype/ttnameid.h> |
28 | | #include <freetype/tttags.h> |
29 | | #include <freetype/internal/services/svpscmap.h> |
30 | | #include <freetype/ftsnames.h> |
31 | | |
32 | | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
33 | | #include <freetype/internal/services/svmm.h> |
34 | | #include <freetype/internal/services/svmetric.h> |
35 | | #endif |
36 | | |
37 | | #include "sferrors.h" |
38 | | |
39 | | #ifdef TT_CONFIG_OPTION_BDF |
40 | | #include "ttbdf.h" |
41 | | #endif |
42 | | |
43 | | |
44 | | /************************************************************************** |
45 | | * |
46 | | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
47 | | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
48 | | * messages during execution. |
49 | | */ |
50 | | #undef FT_COMPONENT |
51 | | #define FT_COMPONENT sfobjs |
52 | | |
53 | | |
54 | | |
55 | | /* convert a UTF-16 name entry to ASCII */ |
56 | | static FT_String* |
57 | | tt_name_ascii_from_utf16( TT_Name entry, |
58 | | FT_Memory memory ) |
59 | 0 | { |
60 | 0 | FT_String* string = NULL; |
61 | 0 | FT_UInt len, code, n; |
62 | 0 | FT_Byte* read = (FT_Byte*)entry->string; |
63 | 0 | FT_Error error; |
64 | | |
65 | |
|
66 | 0 | len = (FT_UInt)entry->stringLength / 2; |
67 | |
|
68 | 0 | if ( FT_QNEW_ARRAY( string, len + 1 ) ) |
69 | 0 | return NULL; |
70 | | |
71 | 0 | for ( n = 0; n < len; n++ ) |
72 | 0 | { |
73 | 0 | code = FT_NEXT_USHORT( read ); |
74 | |
|
75 | 0 | if ( code == 0 ) |
76 | 0 | break; |
77 | | |
78 | 0 | if ( code < 32 || code > 127 ) |
79 | 0 | code = '?'; |
80 | |
|
81 | 0 | string[n] = (char)code; |
82 | 0 | } |
83 | |
|
84 | 0 | string[n] = 0; |
85 | |
|
86 | 0 | return string; |
87 | 0 | } |
88 | | |
89 | | |
90 | | /* convert an Apple Roman or symbol name entry to ASCII */ |
91 | | static FT_String* |
92 | | tt_name_ascii_from_other( TT_Name entry, |
93 | | FT_Memory memory ) |
94 | 0 | { |
95 | 0 | FT_String* string = NULL; |
96 | 0 | FT_UInt len, code, n; |
97 | 0 | FT_Byte* read = (FT_Byte*)entry->string; |
98 | 0 | FT_Error error; |
99 | | |
100 | |
|
101 | 0 | len = (FT_UInt)entry->stringLength; |
102 | |
|
103 | 0 | if ( FT_QNEW_ARRAY( string, len + 1 ) ) |
104 | 0 | return NULL; |
105 | | |
106 | 0 | for ( n = 0; n < len; n++ ) |
107 | 0 | { |
108 | 0 | code = *read++; |
109 | |
|
110 | 0 | if ( code == 0 ) |
111 | 0 | break; |
112 | | |
113 | 0 | if ( code < 32 || code > 127 ) |
114 | 0 | code = '?'; |
115 | |
|
116 | 0 | string[n] = (char)code; |
117 | 0 | } |
118 | |
|
119 | 0 | string[n] = 0; |
120 | |
|
121 | 0 | return string; |
122 | 0 | } |
123 | | |
124 | | |
125 | | typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry, |
126 | | FT_Memory memory ); |
127 | | |
128 | | |
129 | | /* documentation is in sfnt.h */ |
130 | | |
131 | | FT_LOCAL_DEF( FT_Error ) |
132 | | tt_face_get_name( TT_Face face, |
133 | | FT_UShort nameid, |
134 | | FT_String** name ) |
135 | 14.8k | { |
136 | 14.8k | FT_Memory memory = face->root.memory; |
137 | 14.8k | FT_Error error = FT_Err_Ok; |
138 | 14.8k | FT_String* result = NULL; |
139 | 14.8k | FT_UShort n; |
140 | 14.8k | TT_Name rec; |
141 | | |
142 | 14.8k | FT_Int found_apple = -1; |
143 | 14.8k | FT_Int found_apple_roman = -1; |
144 | 14.8k | FT_Int found_apple_english = -1; |
145 | 14.8k | FT_Int found_win = -1; |
146 | 14.8k | FT_Int found_unicode = -1; |
147 | | |
148 | 14.8k | FT_Bool is_english = 0; |
149 | | |
150 | 14.8k | TT_Name_ConvertFunc convert; |
151 | | |
152 | | |
153 | 14.8k | FT_ASSERT( name ); |
154 | | |
155 | 14.8k | rec = face->name_table.names; |
156 | 14.9k | for ( n = 0; n < face->num_names; n++, rec++ ) |
157 | 194 | { |
158 | | /* According to the OpenType 1.3 specification, only Microsoft or */ |
159 | | /* Apple platform IDs might be used in the `name' table. The */ |
160 | | /* `Unicode' platform is reserved for the `cmap' table, and the */ |
161 | | /* `ISO' one is deprecated. */ |
162 | | /* */ |
163 | | /* However, the Apple TrueType specification doesn't say the same */ |
164 | | /* thing and goes to suggest that all Unicode `name' table entries */ |
165 | | /* should be coded in UTF-16 (in big-endian format I suppose). */ |
166 | | /* */ |
167 | 194 | if ( rec->nameID == nameid && rec->stringLength > 0 ) |
168 | 0 | { |
169 | 0 | switch ( rec->platformID ) |
170 | 0 | { |
171 | 0 | case TT_PLATFORM_APPLE_UNICODE: |
172 | 0 | case TT_PLATFORM_ISO: |
173 | | /* there is `languageID' to check there. We should use this */ |
174 | | /* field only as a last solution when nothing else is */ |
175 | | /* available. */ |
176 | | /* */ |
177 | 0 | found_unicode = n; |
178 | 0 | break; |
179 | |
|
180 | 0 | case TT_PLATFORM_MACINTOSH: |
181 | | /* This is a bit special because some fonts will use either */ |
182 | | /* an English language id, or a Roman encoding id, to indicate */ |
183 | | /* the English version of its font name. */ |
184 | | /* */ |
185 | 0 | if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) |
186 | 0 | found_apple_english = n; |
187 | 0 | else if ( rec->encodingID == TT_MAC_ID_ROMAN ) |
188 | 0 | found_apple_roman = n; |
189 | 0 | break; |
190 | |
|
191 | 0 | case TT_PLATFORM_MICROSOFT: |
192 | | /* we only take a non-English name when there is nothing */ |
193 | | /* else available in the font */ |
194 | | /* */ |
195 | 0 | if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) |
196 | 0 | { |
197 | 0 | switch ( rec->encodingID ) |
198 | 0 | { |
199 | 0 | case TT_MS_ID_SYMBOL_CS: |
200 | 0 | case TT_MS_ID_UNICODE_CS: |
201 | 0 | case TT_MS_ID_UCS_4: |
202 | 0 | is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); |
203 | 0 | found_win = n; |
204 | 0 | break; |
205 | |
|
206 | 0 | default: |
207 | 0 | ; |
208 | 0 | } |
209 | 0 | } |
210 | 0 | break; |
211 | |
|
212 | 0 | default: |
213 | 0 | ; |
214 | 0 | } |
215 | 0 | } |
216 | 194 | } |
217 | | |
218 | 14.8k | found_apple = found_apple_roman; |
219 | 14.8k | if ( found_apple_english >= 0 ) |
220 | 0 | found_apple = found_apple_english; |
221 | | |
222 | | /* some fonts contain invalid Unicode or Macintosh formatted entries; */ |
223 | | /* we will thus favor names encoded in Windows formats if available */ |
224 | | /* (provided it is an English name) */ |
225 | | /* */ |
226 | 14.8k | convert = NULL; |
227 | 14.8k | if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) |
228 | 0 | { |
229 | 0 | rec = face->name_table.names + found_win; |
230 | 0 | switch ( rec->encodingID ) |
231 | 0 | { |
232 | | /* all Unicode strings are encoded using UTF-16BE */ |
233 | 0 | case TT_MS_ID_UNICODE_CS: |
234 | 0 | case TT_MS_ID_SYMBOL_CS: |
235 | 0 | convert = tt_name_ascii_from_utf16; |
236 | 0 | break; |
237 | |
|
238 | 0 | case TT_MS_ID_UCS_4: |
239 | | /* Apparently, if this value is found in a name table entry, it is */ |
240 | | /* documented as `full Unicode repertoire'. Experience with the */ |
241 | | /* MsGothic font shipped with Windows Vista shows that this really */ |
242 | | /* means UTF-16 encoded names (UCS-4 values are only used within */ |
243 | | /* charmaps). */ |
244 | 0 | convert = tt_name_ascii_from_utf16; |
245 | 0 | break; |
246 | |
|
247 | 0 | default: |
248 | 0 | ; |
249 | 0 | } |
250 | 0 | } |
251 | 14.8k | else if ( found_apple >= 0 ) |
252 | 0 | { |
253 | 0 | rec = face->name_table.names + found_apple; |
254 | 0 | convert = tt_name_ascii_from_other; |
255 | 0 | } |
256 | 14.8k | else if ( found_unicode >= 0 ) |
257 | 0 | { |
258 | 0 | rec = face->name_table.names + found_unicode; |
259 | 0 | convert = tt_name_ascii_from_utf16; |
260 | 0 | } |
261 | | |
262 | 14.8k | if ( rec && convert ) |
263 | 0 | { |
264 | 0 | if ( !rec->string ) |
265 | 0 | { |
266 | 0 | FT_Stream stream = face->name_table.stream; |
267 | | |
268 | |
|
269 | 0 | if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || |
270 | 0 | FT_STREAM_SEEK( rec->stringOffset ) || |
271 | 0 | FT_STREAM_READ( rec->string, rec->stringLength ) ) |
272 | 0 | { |
273 | 0 | FT_FREE( rec->string ); |
274 | 0 | rec->stringLength = 0; |
275 | 0 | result = NULL; |
276 | 0 | goto Exit; |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | 0 | result = convert( rec, memory ); |
281 | 0 | } |
282 | | |
283 | 14.8k | Exit: |
284 | 14.8k | *name = result; |
285 | 14.8k | return error; |
286 | 14.8k | } |
287 | | |
288 | | |
289 | | static FT_Encoding |
290 | | sfnt_find_encoding( int platform_id, |
291 | | int encoding_id ) |
292 | 320 | { |
293 | 320 | typedef struct TEncoding_ |
294 | 320 | { |
295 | 320 | int platform_id; |
296 | 320 | int encoding_id; |
297 | 320 | FT_Encoding encoding; |
298 | | |
299 | 320 | } TEncoding; |
300 | | |
301 | 320 | static |
302 | 320 | const TEncoding tt_encodings[] = |
303 | 320 | { |
304 | 320 | { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, |
305 | | |
306 | 320 | { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, |
307 | | |
308 | 320 | { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, |
309 | | |
310 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, |
311 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, |
312 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, |
313 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, |
314 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC }, |
315 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, |
316 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, |
317 | 320 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } |
318 | 320 | }; |
319 | | |
320 | 320 | const TEncoding *cur, *limit; |
321 | | |
322 | | |
323 | 320 | cur = tt_encodings; |
324 | 320 | limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); |
325 | | |
326 | 1.68k | for ( ; cur < limit; cur++ ) |
327 | 1.58k | { |
328 | 1.58k | if ( cur->platform_id == platform_id ) |
329 | 215 | { |
330 | 215 | if ( cur->encoding_id == encoding_id || |
331 | 215 | cur->encoding_id == -1 ) |
332 | 215 | return cur->encoding; |
333 | 215 | } |
334 | 1.58k | } |
335 | | |
336 | 105 | return FT_ENCODING_NONE; |
337 | 320 | } |
338 | | |
339 | | |
340 | | /* Fill in face->ttc_header. If the font is not a TTC, it is */ |
341 | | /* synthesized into a TTC with one offset table. */ |
342 | | static FT_Error |
343 | | sfnt_open_font( FT_Stream stream, |
344 | | TT_Face face, |
345 | | FT_Int* face_instance_index, |
346 | | FT_Long* woff2_num_faces ) |
347 | 12.5k | { |
348 | 12.5k | FT_Memory memory = stream->memory; |
349 | 12.5k | FT_Error error; |
350 | 12.5k | FT_ULong tag, offset; |
351 | | |
352 | 12.5k | static const FT_Frame_Field ttc_header_fields[] = |
353 | 12.5k | { |
354 | 12.5k | #undef FT_STRUCTURE |
355 | 12.5k | #define FT_STRUCTURE TTC_HeaderRec |
356 | | |
357 | 12.5k | FT_FRAME_START( 8 ), |
358 | 12.5k | FT_FRAME_LONG( version ), |
359 | 12.5k | FT_FRAME_LONG( count ), /* this is ULong in the specs */ |
360 | 12.5k | FT_FRAME_END |
361 | 12.5k | }; |
362 | | |
363 | | |
364 | 12.5k | face->ttc_header.tag = 0; |
365 | 12.5k | face->ttc_header.version = 0; |
366 | 12.5k | face->ttc_header.count = 0; |
367 | | |
368 | 12.5k | retry: |
369 | 12.5k | offset = FT_STREAM_POS(); |
370 | | |
371 | 12.5k | if ( FT_READ_ULONG( tag ) ) |
372 | 3 | return error; |
373 | | |
374 | 12.5k | if ( tag == TTAG_wOFF ) |
375 | 0 | { |
376 | 0 | FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); |
377 | |
|
378 | 0 | if ( FT_STREAM_SEEK( offset ) ) |
379 | 0 | return error; |
380 | | |
381 | 0 | error = woff_open_font( stream, face ); |
382 | 0 | if ( error ) |
383 | 0 | return error; |
384 | | |
385 | | /* Swap out stream and retry! */ |
386 | 0 | stream = face->root.stream; |
387 | 0 | goto retry; |
388 | 0 | } |
389 | | |
390 | 12.5k | if ( tag == TTAG_wOF2 ) |
391 | 0 | { |
392 | 0 | FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" )); |
393 | |
|
394 | 0 | if ( FT_STREAM_SEEK( offset ) ) |
395 | 0 | return error; |
396 | | |
397 | 0 | error = woff2_open_font( stream, |
398 | 0 | face, |
399 | 0 | face_instance_index, |
400 | 0 | woff2_num_faces ); |
401 | 0 | if ( error ) |
402 | 0 | return error; |
403 | | |
404 | | /* Swap out stream and retry! */ |
405 | 0 | stream = face->root.stream; |
406 | 0 | goto retry; |
407 | 0 | } |
408 | | |
409 | 12.5k | if ( tag != 0x00010000UL && |
410 | 12.0k | tag != TTAG_ttcf && |
411 | 12.0k | tag != TTAG_OTTO && |
412 | 4.24k | tag != TTAG_true && |
413 | 4.24k | tag != TTAG_typ1 && |
414 | 4.24k | tag != TTAG_0xA5kbd && |
415 | 4.24k | tag != TTAG_0xA5lst && |
416 | 4.24k | tag != 0x00020000UL ) |
417 | 4.24k | { |
418 | 4.24k | FT_TRACE2(( " not a font using the SFNT container format\n" )); |
419 | 4.24k | return FT_THROW( Unknown_File_Format ); |
420 | 4.24k | } |
421 | | |
422 | 8.27k | face->ttc_header.tag = TTAG_ttcf; |
423 | | |
424 | 8.27k | if ( tag == TTAG_ttcf ) |
425 | 0 | { |
426 | 0 | FT_Int n; |
427 | | |
428 | |
|
429 | 0 | FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); |
430 | |
|
431 | 0 | if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) |
432 | 0 | return error; |
433 | | |
434 | 0 | FT_TRACE3(( " with %ld subfonts\n", |
435 | 0 | face->ttc_header.count )); |
436 | |
|
437 | 0 | if ( face->ttc_header.count == 0 ) |
438 | 0 | return FT_THROW( Invalid_Table ); |
439 | | |
440 | | /* a rough size estimate: let's conservatively assume that there */ |
441 | | /* is just a single table info in each subfont header (12 + 16*1 = */ |
442 | | /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ |
443 | | /* size of the TTC header plus `28*count' bytes for all subfont */ |
444 | | /* headers */ |
445 | 0 | if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) |
446 | 0 | return FT_THROW( Array_Too_Large ); |
447 | | |
448 | | /* now read the offsets of each font in the file */ |
449 | 0 | if ( FT_QNEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) |
450 | 0 | return error; |
451 | | |
452 | 0 | if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) |
453 | 0 | return error; |
454 | | |
455 | 0 | for ( n = 0; n < face->ttc_header.count; n++ ) |
456 | 0 | face->ttc_header.offsets[n] = FT_GET_ULONG(); |
457 | |
|
458 | 0 | FT_FRAME_EXIT(); |
459 | 0 | } |
460 | 8.27k | else |
461 | 8.27k | { |
462 | 8.27k | FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); |
463 | | |
464 | 8.27k | face->ttc_header.version = 1 << 16; |
465 | 8.27k | face->ttc_header.count = 1; |
466 | | |
467 | 8.27k | if ( FT_QNEW( face->ttc_header.offsets ) ) |
468 | 0 | return error; |
469 | | |
470 | 8.27k | face->ttc_header.offsets[0] = offset; |
471 | 8.27k | } |
472 | | |
473 | 8.27k | return error; |
474 | 8.27k | } |
475 | | |
476 | | |
477 | | FT_LOCAL_DEF( FT_Error ) |
478 | | sfnt_init_face( FT_Stream stream, |
479 | | TT_Face face, |
480 | | FT_Int face_instance_index, |
481 | | FT_Int num_params, |
482 | | FT_Parameter* params ) |
483 | 12.5k | { |
484 | 12.5k | FT_Error error; |
485 | 12.5k | FT_Library library = face->root.driver->root.library; |
486 | 12.5k | SFNT_Service sfnt; |
487 | 12.5k | FT_Int face_index; |
488 | 12.5k | FT_Long woff2_num_faces = 0; |
489 | | |
490 | | |
491 | | /* for now, parameters are unused */ |
492 | 12.5k | FT_UNUSED( num_params ); |
493 | 12.5k | FT_UNUSED( params ); |
494 | | |
495 | | |
496 | 12.5k | sfnt = (SFNT_Service)face->sfnt; |
497 | 12.5k | if ( !sfnt ) |
498 | 12.5k | { |
499 | 12.5k | sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); |
500 | 12.5k | if ( !sfnt ) |
501 | 0 | { |
502 | 0 | FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); |
503 | 0 | return FT_THROW( Missing_Module ); |
504 | 0 | } |
505 | | |
506 | 12.5k | face->sfnt = sfnt; |
507 | 12.5k | face->goto_table = sfnt->goto_table; |
508 | 12.5k | } |
509 | | |
510 | 12.5k | FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); |
511 | | |
512 | 12.5k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
513 | 12.5k | if ( !face->mm ) |
514 | 12.5k | { |
515 | | /* we want the MM interface from the `truetype' module only */ |
516 | 12.5k | FT_Module tt_module = FT_Get_Module( library, "truetype" ); |
517 | | |
518 | | |
519 | 12.5k | face->mm = ft_module_get_service( tt_module, |
520 | 12.5k | FT_SERVICE_ID_MULTI_MASTERS, |
521 | 12.5k | 0 ); |
522 | 12.5k | } |
523 | | |
524 | 12.5k | if ( !face->var ) |
525 | 12.5k | { |
526 | | /* we want the metrics variations interface */ |
527 | | /* from the `truetype' module only */ |
528 | 12.5k | FT_Module tt_module = FT_Get_Module( library, "truetype" ); |
529 | | |
530 | | |
531 | 12.5k | face->var = ft_module_get_service( tt_module, |
532 | 12.5k | FT_SERVICE_ID_METRICS_VARIATIONS, |
533 | 12.5k | 0 ); |
534 | 12.5k | } |
535 | 12.5k | #endif |
536 | | |
537 | 12.5k | FT_TRACE2(( "SFNT driver\n" )); |
538 | | |
539 | 12.5k | error = sfnt_open_font( stream, |
540 | 12.5k | face, |
541 | 12.5k | &face_instance_index, |
542 | 12.5k | &woff2_num_faces ); |
543 | 12.5k | if ( error ) |
544 | 4.24k | return error; |
545 | | |
546 | | /* Stream may have changed in sfnt_open_font. */ |
547 | 8.27k | stream = face->root.stream; |
548 | | |
549 | 8.27k | FT_TRACE2(( "sfnt_init_face: %p (index %d)\n", |
550 | 8.27k | (void *)face, |
551 | 8.27k | face_instance_index )); |
552 | | |
553 | 8.27k | face_index = FT_ABS( face_instance_index ) & 0xFFFF; |
554 | | |
555 | | /* value -(N+1) requests information on index N */ |
556 | 8.27k | if ( face_instance_index < 0 ) |
557 | 0 | face_index--; |
558 | | |
559 | 8.27k | if ( face_index >= face->ttc_header.count ) |
560 | 0 | { |
561 | 0 | if ( face_instance_index >= 0 ) |
562 | 0 | return FT_THROW( Invalid_Argument ); |
563 | 0 | else |
564 | 0 | face_index = 0; |
565 | 0 | } |
566 | | |
567 | 8.27k | if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) |
568 | 0 | return error; |
569 | | |
570 | | /* check whether we have a valid TrueType file */ |
571 | 8.27k | error = sfnt->load_font_dir( face, stream ); |
572 | 8.27k | if ( error ) |
573 | 234 | return error; |
574 | | |
575 | 8.03k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
576 | 8.03k | { |
577 | 8.03k | FT_Memory memory = face->root.memory; |
578 | | |
579 | 8.03k | FT_ULong fvar_len; |
580 | | |
581 | 8.03k | FT_ULong version; |
582 | 8.03k | FT_ULong offset; |
583 | | |
584 | 8.03k | FT_UShort num_axes; |
585 | 8.03k | FT_UShort axis_size; |
586 | 8.03k | FT_UShort num_instances; |
587 | 8.03k | FT_UShort instance_size; |
588 | | |
589 | 8.03k | FT_Int instance_index; |
590 | | |
591 | 8.03k | FT_Byte* default_values = NULL; |
592 | 8.03k | FT_Byte* instance_values = NULL; |
593 | | |
594 | | |
595 | 8.03k | instance_index = FT_ABS( face_instance_index ) >> 16; |
596 | | |
597 | | /* test whether current face is a GX font with named instances */ |
598 | 8.03k | if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || |
599 | 0 | fvar_len < 20 || |
600 | 8.03k | FT_READ_ULONG( version ) || |
601 | 8.03k | FT_READ_USHORT( offset ) || |
602 | 8.03k | FT_STREAM_SKIP( 2 ) /* reserved */ || |
603 | 8.03k | FT_READ_USHORT( num_axes ) || |
604 | 8.03k | FT_READ_USHORT( axis_size ) || |
605 | 8.03k | FT_READ_USHORT( num_instances ) || |
606 | 8.03k | FT_READ_USHORT( instance_size ) ) |
607 | 8.03k | { |
608 | 8.03k | version = 0; |
609 | 8.03k | offset = 0; |
610 | 8.03k | num_axes = 0; |
611 | 8.03k | axis_size = 0; |
612 | 8.03k | num_instances = 0; |
613 | 8.03k | instance_size = 0; |
614 | 8.03k | } |
615 | | |
616 | | /* check that the data is bound by the table length */ |
617 | 8.03k | if ( version != 0x00010000UL || |
618 | 0 | axis_size != 20 || |
619 | 0 | num_axes == 0 || |
620 | | /* `num_axes' limit implied by 16-bit `instance_size' */ |
621 | 0 | num_axes > 0x3FFE || |
622 | 0 | !( instance_size == 4 + 4 * num_axes || |
623 | 0 | instance_size == 6 + 4 * num_axes ) || |
624 | | /* `num_instances' limit implied by limited range of name IDs */ |
625 | 0 | num_instances > 0x7EFF || |
626 | 0 | offset + |
627 | 0 | axis_size * num_axes + |
628 | 0 | instance_size * num_instances > fvar_len ) |
629 | 8.03k | num_instances = 0; |
630 | 0 | else |
631 | 0 | face->variation_support |= TT_FACE_FLAG_VAR_FVAR; |
632 | | |
633 | | /* |
634 | | * As documented in the OpenType specification, an entry for the |
635 | | * default instance may be omitted in the named instance table. In |
636 | | * particular this means that even if there is no named instance |
637 | | * table in the font we actually do have a named instance, namely the |
638 | | * default instance. |
639 | | * |
640 | | * For consistency, we always want the default instance in our list |
641 | | * of named instances. If it is missing, we try to synthesize it |
642 | | * later on. Here, we have to adjust `num_instances' accordingly. |
643 | | */ |
644 | | |
645 | 8.03k | if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && |
646 | 0 | !( FT_QALLOC( default_values, num_axes * 4 ) || |
647 | 0 | FT_QALLOC( instance_values, num_axes * 4 ) ) ) |
648 | 0 | { |
649 | | /* the current stream position is 16 bytes after the table start */ |
650 | 0 | FT_ULong array_start = FT_STREAM_POS() - 16 + offset; |
651 | 0 | FT_ULong default_value_offset, instance_offset; |
652 | |
|
653 | 0 | FT_Byte* p; |
654 | 0 | FT_UInt i; |
655 | | |
656 | |
|
657 | 0 | default_value_offset = array_start + 8; |
658 | 0 | p = default_values; |
659 | |
|
660 | 0 | for ( i = 0; i < num_axes; i++ ) |
661 | 0 | { |
662 | 0 | (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); |
663 | |
|
664 | 0 | default_value_offset += axis_size; |
665 | 0 | p += 4; |
666 | 0 | } |
667 | |
|
668 | 0 | instance_offset = array_start + axis_size * num_axes + 4; |
669 | |
|
670 | 0 | for ( i = 0; i < num_instances; i++ ) |
671 | 0 | { |
672 | 0 | (void)FT_STREAM_READ_AT( instance_offset, |
673 | 0 | instance_values, |
674 | 0 | num_axes * 4 ); |
675 | |
|
676 | 0 | if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) |
677 | 0 | break; |
678 | | |
679 | 0 | instance_offset += instance_size; |
680 | 0 | } |
681 | |
|
682 | 0 | if ( i == num_instances ) |
683 | 0 | { |
684 | | /* no default instance in named instance table; */ |
685 | | /* we thus have to synthesize it */ |
686 | 0 | num_instances++; |
687 | 0 | } |
688 | 0 | } |
689 | | |
690 | 8.03k | FT_FREE( default_values ); |
691 | 8.03k | FT_FREE( instance_values ); |
692 | | |
693 | | /* we don't support Multiple Master CFFs yet; */ |
694 | | /* note that `glyf' or `CFF2' have precedence */ |
695 | 8.03k | if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && |
696 | 7.74k | face->goto_table( face, TTAG_CFF2, stream, 0 ) && |
697 | 7.74k | !face->goto_table( face, TTAG_CFF, stream, 0 ) ) |
698 | 7.50k | num_instances = 0; |
699 | | |
700 | | /* instance indices in `face_instance_index' start with index 1, */ |
701 | | /* thus `>' and not `>=' */ |
702 | 8.03k | if ( instance_index > num_instances ) |
703 | 0 | { |
704 | 0 | if ( face_instance_index >= 0 ) |
705 | 0 | return FT_THROW( Invalid_Argument ); |
706 | 0 | else |
707 | 0 | num_instances = 0; |
708 | 0 | } |
709 | | |
710 | 8.03k | face->root.style_flags = (FT_Long)num_instances << 16; |
711 | 8.03k | } |
712 | 8.03k | #endif |
713 | | |
714 | 8.03k | face->root.num_faces = face->ttc_header.count; |
715 | 8.03k | face->root.face_index = face_instance_index; |
716 | | |
717 | | /* `num_faces' for a WOFF2 needs to be handled separately. */ |
718 | 8.03k | if ( woff2_num_faces ) |
719 | 0 | face->root.num_faces = woff2_num_faces; |
720 | | |
721 | 8.03k | return error; |
722 | 8.03k | } |
723 | | |
724 | | |
725 | | #define LOAD_( x ) \ |
726 | 40.1k | do \ |
727 | 34.4k | { \ |
728 | 34.4k | FT_TRACE2(( "`" #x "' " )); \ |
729 | 34.4k | FT_TRACE3(( "-->\n" )); \ |
730 | 34.4k | \ |
731 | 34.4k | error = sfnt->load_ ## x( face, stream ); \ |
732 | 34.4k | \ |
733 | 34.4k | FT_TRACE2(( "%s\n", ( !error ) \ |
734 | 34.4k | ? "loaded" \ |
735 | 34.4k | : FT_ERR_EQ( error, Table_Missing ) \ |
736 | 34.4k | ? "missing" \ |
737 | 34.4k | : "failed to load" )); \ |
738 | 34.4k | FT_TRACE3(( "\n" )); \ |
739 | 34.4k | } while ( 0 ) |
740 | | |
741 | | #define LOADM_( x, vertical ) \ |
742 | 11.1k | do \ |
743 | 8.41k | { \ |
744 | 8.41k | FT_TRACE2(( "`%s" #x "' ", \ |
745 | 8.41k | vertical ? "vertical " : "" )); \ |
746 | 8.41k | FT_TRACE3(( "-->\n" )); \ |
747 | 8.41k | \ |
748 | 8.41k | error = sfnt->load_ ## x( face, stream, vertical ); \ |
749 | 8.41k | \ |
750 | 8.41k | FT_TRACE2(( "%s\n", ( !error ) \ |
751 | 8.41k | ? "loaded" \ |
752 | 8.41k | : FT_ERR_EQ( error, Table_Missing ) \ |
753 | 8.41k | ? "missing" \ |
754 | 8.41k | : "failed to load" )); \ |
755 | 8.41k | FT_TRACE3(( "\n" )); \ |
756 | 8.41k | } while ( 0 ) |
757 | | |
758 | | #define GET_NAME( id, field ) \ |
759 | 14.8k | do \ |
760 | 14.8k | { \ |
761 | 14.8k | error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ |
762 | 14.8k | if ( error ) \ |
763 | 0 | goto Exit; \ |
764 | 14.8k | } while ( 0 ) |
765 | | |
766 | | |
767 | | FT_LOCAL_DEF( FT_Error ) |
768 | | sfnt_load_face( FT_Stream stream, |
769 | | TT_Face face, |
770 | | FT_Int face_instance_index, |
771 | | FT_Int num_params, |
772 | | FT_Parameter* params ) |
773 | 3.67k | { |
774 | 3.67k | FT_Error error; |
775 | 3.67k | #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
776 | 3.67k | FT_Error psnames_error; |
777 | 3.67k | #endif |
778 | 3.67k | FT_Bool has_outline; |
779 | 3.67k | FT_Bool is_apple_sbit; |
780 | 3.67k | FT_Bool is_apple_sbix; |
781 | 3.67k | FT_Bool has_CBLC; |
782 | 3.67k | FT_Bool has_CBDT; |
783 | 3.67k | FT_Bool ignore_typographic_family = FALSE; |
784 | 3.67k | FT_Bool ignore_typographic_subfamily = FALSE; |
785 | | |
786 | 3.67k | SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
787 | | |
788 | 3.67k | FT_UNUSED( face_instance_index ); |
789 | | |
790 | | |
791 | | /* Check parameters */ |
792 | | |
793 | 3.67k | { |
794 | 3.67k | FT_Int i; |
795 | | |
796 | | |
797 | 3.67k | for ( i = 0; i < num_params; i++ ) |
798 | 0 | { |
799 | 0 | if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) |
800 | 0 | ignore_typographic_family = TRUE; |
801 | 0 | else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) |
802 | 0 | ignore_typographic_subfamily = TRUE; |
803 | 0 | } |
804 | 3.67k | } |
805 | | |
806 | | /* Load tables */ |
807 | | |
808 | | /* We now support two SFNT-based bitmapped font formats. They */ |
809 | | /* are recognized easily as they do not include a `glyf' */ |
810 | | /* table. */ |
811 | | /* */ |
812 | | /* The first format comes from Apple, and uses a table named */ |
813 | | /* `bhed' instead of `head' to store the font header (using */ |
814 | | /* the same format). It also doesn't include horizontal and */ |
815 | | /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ |
816 | | /* missing). */ |
817 | | /* */ |
818 | | /* The other format comes from Microsoft, and is used with */ |
819 | | /* WinCE/PocketPC. It looks like a standard TTF, except that */ |
820 | | /* it doesn't contain outlines. */ |
821 | | /* */ |
822 | | |
823 | 3.67k | FT_TRACE2(( "sfnt_load_face: %p\n", (void *)face )); |
824 | 3.67k | FT_TRACE2(( "\n" )); |
825 | | |
826 | | /* do we have outlines in there? */ |
827 | 3.67k | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
828 | 3.67k | has_outline = FT_BOOL( face->root.internal->incremental_interface || |
829 | 3.67k | tt_face_lookup_table( face, TTAG_glyf ) || |
830 | 3.67k | tt_face_lookup_table( face, TTAG_CFF ) || |
831 | 3.67k | tt_face_lookup_table( face, TTAG_CFF2 ) ); |
832 | | #else |
833 | | has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) || |
834 | | tt_face_lookup_table( face, TTAG_CFF ) || |
835 | | tt_face_lookup_table( face, TTAG_CFF2 ) ); |
836 | | #endif |
837 | | |
838 | 3.67k | is_apple_sbit = 0; |
839 | 3.67k | is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); |
840 | | |
841 | | /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' |
842 | | * outline rendered on top. We don't support that yet, so just ignore |
843 | | * the 'glyf' outline and advertise it as a bitmap-only font. */ |
844 | 3.67k | if ( is_apple_sbix ) |
845 | 0 | has_outline = FALSE; |
846 | | |
847 | | /* if this font doesn't contain outlines, we try to load */ |
848 | | /* a `bhed' table */ |
849 | 3.67k | if ( !has_outline && sfnt->load_bhed ) |
850 | 36 | { |
851 | 36 | LOAD_( bhed ); |
852 | 36 | is_apple_sbit = FT_BOOL( !error ); |
853 | 36 | } |
854 | | |
855 | | /* load the font header (`head' table) if this isn't an Apple */ |
856 | | /* sbit font file */ |
857 | 3.67k | if ( !is_apple_sbit || is_apple_sbix ) |
858 | 3.67k | { |
859 | 3.67k | LOAD_( head ); |
860 | 3.67k | if ( error ) |
861 | 0 | goto Exit; |
862 | 3.67k | } |
863 | | |
864 | 3.67k | has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); |
865 | 3.67k | has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); |
866 | | |
867 | | /* Ignore outlines for CBLC/CBDT fonts. */ |
868 | 3.67k | if ( has_CBLC || has_CBDT ) |
869 | 0 | has_outline = FALSE; |
870 | | |
871 | | /* OpenType 1.8.2 introduced limits to this value; */ |
872 | | /* however, they make sense for older SFNT fonts also */ |
873 | 3.67k | if ( face->header.Units_Per_EM < 16 || |
874 | 3.33k | face->header.Units_Per_EM > 16384 ) |
875 | 820 | { |
876 | 820 | error = FT_THROW( Invalid_Table ); |
877 | | |
878 | 820 | goto Exit; |
879 | 820 | } |
880 | | |
881 | | /* the following tables are often not present in embedded TrueType */ |
882 | | /* fonts within PDF documents, so don't check for them. */ |
883 | 2.85k | LOAD_( maxp ); |
884 | 2.85k | LOAD_( cmap ); |
885 | | |
886 | | /* the following tables are optional in PCL fonts -- */ |
887 | | /* don't check for errors */ |
888 | 2.85k | LOAD_( name ); |
889 | 2.85k | LOAD_( post ); |
890 | | |
891 | 2.85k | #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
892 | 2.85k | psnames_error = error; |
893 | 2.85k | #endif |
894 | | |
895 | | /* do not load the metrics headers and tables if this is an Apple */ |
896 | | /* sbit font file */ |
897 | 2.85k | if ( !is_apple_sbit ) |
898 | 2.85k | { |
899 | | /* load the `hhea' and `hmtx' tables */ |
900 | 2.85k | LOADM_( hhea, 0 ); |
901 | 2.85k | if ( !error ) |
902 | 2.79k | { |
903 | 2.79k | LOADM_( hmtx, 0 ); |
904 | 2.79k | if ( FT_ERR_EQ( error, Table_Missing ) ) |
905 | 26 | { |
906 | 26 | error = FT_THROW( Hmtx_Table_Missing ); |
907 | | |
908 | 26 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
909 | | /* If this is an incrementally loaded font and there are */ |
910 | | /* overriding metrics, tolerate a missing `hmtx' table. */ |
911 | 26 | if ( face->root.internal->incremental_interface && |
912 | 0 | face->root.internal->incremental_interface->funcs-> |
913 | 0 | get_glyph_metrics ) |
914 | 0 | { |
915 | 0 | face->horizontal.number_Of_HMetrics = 0; |
916 | 0 | error = FT_Err_Ok; |
917 | 0 | } |
918 | 26 | #endif |
919 | 26 | } |
920 | 2.79k | } |
921 | 56 | else if ( FT_ERR_EQ( error, Table_Missing ) ) |
922 | 56 | { |
923 | | /* No `hhea' table necessary for SFNT Mac fonts. */ |
924 | 56 | if ( face->format_tag == TTAG_true ) |
925 | 0 | { |
926 | 0 | FT_TRACE2(( "This is an SFNT Mac font.\n" )); |
927 | |
|
928 | 0 | has_outline = 0; |
929 | 0 | error = FT_Err_Ok; |
930 | 0 | } |
931 | 56 | else |
932 | 56 | { |
933 | 56 | error = FT_THROW( Horiz_Header_Missing ); |
934 | | |
935 | 56 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
936 | | /* If this is an incrementally loaded font and there are */ |
937 | | /* overriding metrics, tolerate a missing `hhea' table. */ |
938 | 56 | if ( face->root.internal->incremental_interface && |
939 | 0 | face->root.internal->incremental_interface->funcs-> |
940 | 0 | get_glyph_metrics ) |
941 | 0 | { |
942 | 0 | face->horizontal.number_Of_HMetrics = 0; |
943 | 0 | error = FT_Err_Ok; |
944 | 0 | } |
945 | 56 | #endif |
946 | | |
947 | 56 | } |
948 | 56 | } |
949 | | |
950 | 2.85k | if ( error ) |
951 | 82 | goto Exit; |
952 | | |
953 | | /* try to load the `vhea' and `vmtx' tables */ |
954 | 2.76k | LOADM_( hhea, 1 ); |
955 | 2.76k | if ( !error ) |
956 | 0 | { |
957 | 0 | LOADM_( hmtx, 1 ); |
958 | 0 | if ( !error ) |
959 | 0 | face->vertical_info = 1; |
960 | 0 | } |
961 | | |
962 | 2.76k | if ( error && FT_ERR_NEQ( error, Table_Missing ) ) |
963 | 0 | goto Exit; |
964 | | |
965 | 2.76k | LOAD_( os2 ); |
966 | 2.76k | if ( error ) |
967 | 178 | { |
968 | | /* we treat the table as missing if there are any errors */ |
969 | 178 | face->os2.version = 0xFFFFU; |
970 | 178 | } |
971 | 2.76k | } |
972 | | |
973 | | /* the optional tables */ |
974 | | |
975 | | /* embedded bitmap support */ |
976 | 2.76k | if ( sfnt->load_eblc ) |
977 | 2.76k | LOAD_( eblc ); |
978 | | |
979 | | /* colored glyph support */ |
980 | 2.76k | if ( sfnt->load_cpal ) |
981 | 2.76k | { |
982 | 2.76k | LOAD_( cpal ); |
983 | 2.76k | LOAD_( colr ); |
984 | 2.76k | } |
985 | | |
986 | | /* consider the pclt, kerning, and gasp tables as optional */ |
987 | 2.76k | LOAD_( pclt ); |
988 | 2.76k | LOAD_( gasp ); |
989 | 2.76k | LOAD_( kern ); |
990 | | |
991 | 2.76k | face->root.num_glyphs = face->max_profile.numGlyphs; |
992 | | |
993 | | /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ |
994 | | /* a WWS-only font face. `WWS' stands for `weight', width', and */ |
995 | | /* `slope', a term used by Microsoft's Windows Presentation */ |
996 | | /* Foundation (WPF). This flag has been introduced in version */ |
997 | | /* 1.5 of the OpenType specification (May 2008). */ |
998 | | |
999 | 2.76k | face->root.family_name = NULL; |
1000 | 2.76k | face->root.style_name = NULL; |
1001 | 2.76k | if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) |
1002 | 903 | { |
1003 | 903 | if ( !ignore_typographic_family ) |
1004 | 903 | GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); |
1005 | 903 | if ( !face->root.family_name ) |
1006 | 903 | GET_NAME( FONT_FAMILY, &face->root.family_name ); |
1007 | | |
1008 | 903 | if ( !ignore_typographic_subfamily ) |
1009 | 903 | GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); |
1010 | 903 | if ( !face->root.style_name ) |
1011 | 903 | GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); |
1012 | 903 | } |
1013 | 1.86k | else |
1014 | 1.86k | { |
1015 | 1.86k | GET_NAME( WWS_FAMILY, &face->root.family_name ); |
1016 | 1.86k | if ( !face->root.family_name && !ignore_typographic_family ) |
1017 | 1.86k | GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); |
1018 | 1.86k | if ( !face->root.family_name ) |
1019 | 1.86k | GET_NAME( FONT_FAMILY, &face->root.family_name ); |
1020 | | |
1021 | 1.86k | GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); |
1022 | 1.86k | if ( !face->root.style_name && !ignore_typographic_subfamily ) |
1023 | 1.86k | GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); |
1024 | 1.86k | if ( !face->root.style_name ) |
1025 | 1.86k | GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); |
1026 | 1.86k | } |
1027 | | |
1028 | | /* now set up root fields */ |
1029 | 2.76k | { |
1030 | 2.76k | FT_Face root = &face->root; |
1031 | 2.76k | FT_Long flags = root->face_flags; |
1032 | | |
1033 | | |
1034 | | /********************************************************************** |
1035 | | * |
1036 | | * Compute face flags. |
1037 | | */ |
1038 | 2.76k | if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || |
1039 | 2.76k | face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || |
1040 | 2.76k | face->colr ) |
1041 | 0 | flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ |
1042 | | |
1043 | 2.76k | if ( has_outline == TRUE ) |
1044 | 2.74k | flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ |
1045 | | |
1046 | | /* The sfnt driver only supports bitmap fonts natively, thus we */ |
1047 | | /* don't set FT_FACE_FLAG_HINTER. */ |
1048 | 2.76k | flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ |
1049 | 2.76k | FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ |
1050 | | |
1051 | 2.76k | #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
1052 | 2.76k | if ( !psnames_error && |
1053 | 52 | face->postscript.FormatType != 0x00030000L ) |
1054 | 49 | flags |= FT_FACE_FLAG_GLYPH_NAMES; |
1055 | 2.76k | #endif |
1056 | | |
1057 | | /* fixed width font? */ |
1058 | 2.76k | if ( face->postscript.isFixedPitch ) |
1059 | 2.33k | flags |= FT_FACE_FLAG_FIXED_WIDTH; |
1060 | | |
1061 | | /* vertical information? */ |
1062 | 2.76k | if ( face->vertical_info ) |
1063 | 0 | flags |= FT_FACE_FLAG_VERTICAL; |
1064 | | |
1065 | | /* kerning available ? */ |
1066 | 2.76k | if ( TT_FACE_HAS_KERNING( face ) ) |
1067 | 0 | flags |= FT_FACE_FLAG_KERNING; |
1068 | | |
1069 | 2.76k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
1070 | | /* Don't bother to load the tables unless somebody asks for them. */ |
1071 | | /* No need to do work which will (probably) not be used. */ |
1072 | 2.76k | if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) |
1073 | 0 | { |
1074 | 0 | if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && |
1075 | 0 | tt_face_lookup_table( face, TTAG_gvar ) != 0 ) |
1076 | 0 | flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; |
1077 | 0 | if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) |
1078 | 0 | flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; |
1079 | 0 | } |
1080 | 2.76k | #endif |
1081 | | |
1082 | 2.76k | root->face_flags = flags; |
1083 | | |
1084 | | /********************************************************************** |
1085 | | * |
1086 | | * Compute style flags. |
1087 | | */ |
1088 | | |
1089 | 2.76k | flags = 0; |
1090 | 2.76k | if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) |
1091 | 2.56k | { |
1092 | | /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ |
1093 | | /* indicates an oblique font face. This flag has been */ |
1094 | | /* introduced in version 1.5 of the OpenType specification. */ |
1095 | | |
1096 | 2.56k | if ( face->os2.fsSelection & 512 ) /* bit 9 */ |
1097 | 652 | flags |= FT_STYLE_FLAG_ITALIC; |
1098 | 1.91k | else if ( face->os2.fsSelection & 1 ) /* bit 0 */ |
1099 | 556 | flags |= FT_STYLE_FLAG_ITALIC; |
1100 | | |
1101 | 2.56k | if ( face->os2.fsSelection & 32 ) /* bit 5 */ |
1102 | 824 | flags |= FT_STYLE_FLAG_BOLD; |
1103 | 2.56k | } |
1104 | 199 | else |
1105 | 199 | { |
1106 | | /* this is an old Mac font, use the header field */ |
1107 | | |
1108 | 199 | if ( face->header.Mac_Style & 1 ) |
1109 | 87 | flags |= FT_STYLE_FLAG_BOLD; |
1110 | | |
1111 | 199 | if ( face->header.Mac_Style & 2 ) |
1112 | 75 | flags |= FT_STYLE_FLAG_ITALIC; |
1113 | 199 | } |
1114 | | |
1115 | 2.76k | root->style_flags |= flags; |
1116 | | |
1117 | | /********************************************************************** |
1118 | | * |
1119 | | * Polish the charmaps. |
1120 | | * |
1121 | | * Try to set the charmap encoding according to the platform & |
1122 | | * encoding ID of each charmap. Emulate Unicode charmap if one |
1123 | | * is missing. |
1124 | | */ |
1125 | | |
1126 | 2.76k | tt_face_build_cmaps( face ); /* ignore errors */ |
1127 | | |
1128 | | |
1129 | | /* set the encoding fields */ |
1130 | 2.76k | { |
1131 | 2.76k | FT_Int m; |
1132 | 2.76k | #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES |
1133 | 2.76k | FT_Bool has_unicode = FALSE; |
1134 | 2.76k | #endif |
1135 | | |
1136 | | |
1137 | 3.08k | for ( m = 0; m < root->num_charmaps; m++ ) |
1138 | 320 | { |
1139 | 320 | FT_CharMap charmap = root->charmaps[m]; |
1140 | | |
1141 | | |
1142 | 320 | charmap->encoding = sfnt_find_encoding( charmap->platform_id, |
1143 | 320 | charmap->encoding_id ); |
1144 | | |
1145 | 320 | #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES |
1146 | | |
1147 | 320 | if ( charmap->encoding == FT_ENCODING_UNICODE || |
1148 | 105 | charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ |
1149 | 215 | has_unicode = TRUE; |
1150 | 320 | } |
1151 | | |
1152 | | /* synthesize Unicode charmap if one is missing */ |
1153 | 2.76k | if ( !has_unicode && |
1154 | 2.69k | root->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) |
1155 | 47 | { |
1156 | 47 | FT_CharMapRec cmaprec; |
1157 | | |
1158 | | |
1159 | 47 | cmaprec.face = root; |
1160 | 47 | cmaprec.platform_id = TT_PLATFORM_MICROSOFT; |
1161 | 47 | cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; |
1162 | 47 | cmaprec.encoding = FT_ENCODING_UNICODE; |
1163 | | |
1164 | | |
1165 | 47 | error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, |
1166 | 47 | NULL, &cmaprec, NULL ); |
1167 | 47 | if ( error && |
1168 | 47 | FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) && |
1169 | 47 | FT_ERR_NEQ( error, Unimplemented_Feature ) ) |
1170 | 0 | goto Exit; |
1171 | 47 | error = FT_Err_Ok; |
1172 | | |
1173 | 47 | #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ |
1174 | | |
1175 | 47 | } |
1176 | 2.76k | } |
1177 | | |
1178 | 2.76k | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
1179 | | |
1180 | | /* |
1181 | | * Now allocate the root array of FT_Bitmap_Size records and |
1182 | | * populate them. Unfortunately, it isn't possible to indicate bit |
1183 | | * depths in the FT_Bitmap_Size record. This is a design error. |
1184 | | */ |
1185 | 2.76k | { |
1186 | 2.76k | FT_UInt count; |
1187 | | |
1188 | | |
1189 | 2.76k | count = face->sbit_num_strikes; |
1190 | | |
1191 | 2.76k | if ( count > 0 ) |
1192 | 0 | { |
1193 | 0 | FT_Memory memory = face->root.stream->memory; |
1194 | 0 | FT_UShort em_size = face->header.Units_Per_EM; |
1195 | 0 | FT_Short avgwidth = face->os2.xAvgCharWidth; |
1196 | 0 | FT_Size_Metrics metrics; |
1197 | |
|
1198 | 0 | FT_UInt* sbit_strike_map = NULL; |
1199 | 0 | FT_UInt strike_idx, bsize_idx; |
1200 | | |
1201 | |
|
1202 | 0 | if ( em_size == 0 || face->os2.version == 0xFFFFU ) |
1203 | 0 | { |
1204 | 0 | avgwidth = 1; |
1205 | 0 | em_size = 1; |
1206 | 0 | } |
1207 | | |
1208 | | /* to avoid invalid strike data in the `available_sizes' field */ |
1209 | | /* of `FT_Face', we map `available_sizes' indices to strike */ |
1210 | | /* indices */ |
1211 | 0 | if ( FT_NEW_ARRAY( root->available_sizes, count ) || |
1212 | 0 | FT_NEW_ARRAY( sbit_strike_map, count ) ) |
1213 | 0 | goto Exit; |
1214 | | |
1215 | 0 | bsize_idx = 0; |
1216 | 0 | for ( strike_idx = 0; strike_idx < count; strike_idx++ ) |
1217 | 0 | { |
1218 | 0 | FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx; |
1219 | | |
1220 | |
|
1221 | 0 | error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); |
1222 | 0 | if ( error ) |
1223 | 0 | continue; |
1224 | | |
1225 | 0 | bsize->height = (FT_Short)( metrics.height >> 6 ); |
1226 | 0 | bsize->width = (FT_Short)( |
1227 | 0 | ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); |
1228 | |
|
1229 | 0 | bsize->x_ppem = metrics.x_ppem << 6; |
1230 | 0 | bsize->y_ppem = metrics.y_ppem << 6; |
1231 | | |
1232 | | /* assume 72dpi */ |
1233 | 0 | bsize->size = metrics.y_ppem << 6; |
1234 | | |
1235 | | /* only use strikes with valid PPEM values */ |
1236 | 0 | if ( bsize->x_ppem && bsize->y_ppem ) |
1237 | 0 | sbit_strike_map[bsize_idx++] = strike_idx; |
1238 | 0 | } |
1239 | | |
1240 | | /* reduce array size to the actually used elements */ |
1241 | 0 | (void)FT_QRENEW_ARRAY( sbit_strike_map, count, bsize_idx ); |
1242 | | |
1243 | | /* from now on, all strike indices are mapped */ |
1244 | | /* using `sbit_strike_map' */ |
1245 | 0 | if ( bsize_idx ) |
1246 | 0 | { |
1247 | 0 | face->sbit_strike_map = sbit_strike_map; |
1248 | |
|
1249 | 0 | root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; |
1250 | 0 | root->num_fixed_sizes = (FT_Int)bsize_idx; |
1251 | 0 | } |
1252 | 0 | } |
1253 | 2.76k | } |
1254 | | |
1255 | 2.76k | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
1256 | | |
1257 | | /* a font with no bitmaps and no outlines is scalable; */ |
1258 | | /* it has only empty glyphs then */ |
1259 | 2.76k | if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) |
1260 | 19 | root->face_flags |= FT_FACE_FLAG_SCALABLE; |
1261 | | |
1262 | | |
1263 | | /********************************************************************** |
1264 | | * |
1265 | | * Set up metrics. |
1266 | | */ |
1267 | 2.76k | if ( FT_IS_SCALABLE( root ) ) |
1268 | 2.76k | { |
1269 | | /* XXX What about if outline header is missing */ |
1270 | | /* (e.g. sfnt wrapped bitmap)? */ |
1271 | 2.76k | root->bbox.xMin = face->header.xMin; |
1272 | 2.76k | root->bbox.yMin = face->header.yMin; |
1273 | 2.76k | root->bbox.xMax = face->header.xMax; |
1274 | 2.76k | root->bbox.yMax = face->header.yMax; |
1275 | 2.76k | root->units_per_EM = face->header.Units_Per_EM; |
1276 | | |
1277 | | |
1278 | | /* |
1279 | | * Computing the ascender/descender/height is tricky. |
1280 | | * |
1281 | | * The OpenType specification v1.8.3 says: |
1282 | | * |
1283 | | * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields |
1284 | | * are intended to allow applications to lay out documents in a |
1285 | | * typographically-correct and portable fashion. |
1286 | | * |
1287 | | * This is somewhat at odds with the decades of backwards |
1288 | | * compatibility, operating systems and applications doing whatever |
1289 | | * they want, not to mention broken fonts. |
1290 | | * |
1291 | | * Not all fonts have an OS/2 table; in this case, we take the values |
1292 | | * in the horizontal header, although there is nothing stopping the |
1293 | | * values from being unreliable. Even with a OS/2 table, certain fonts |
1294 | | * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0 |
1295 | | * and instead correctly set usWinAscent and usWinDescent. |
1296 | | * |
1297 | | * As an example, Arial Narrow is shipped as four files ARIALN.TTF, |
1298 | | * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have |
1299 | | * the same values in their sTypo* fields, except ARIALNB.ttf which |
1300 | | * sets them to 0. All of them have different usWinAscent/Descent |
1301 | | * values. The OS/2 table therefore cannot be trusted for computing the |
1302 | | * text height reliably. |
1303 | | * |
1304 | | * As a compromise, do the following: |
1305 | | * |
1306 | | * 1. If the OS/2 table exists and the fsSelection bit 7 is set |
1307 | | * (USE_TYPO_METRICS), trust the font and use the sTypo* metrics. |
1308 | | * 2. Otherwise, use the `hhea' table's metrics. |
1309 | | * 3. If they are zero and the OS/2 table exists, |
1310 | | * 1. use the OS/2 table's sTypo* metrics if they are non-zero. |
1311 | | * 2. Otherwise, use the OS/2 table's usWin* metrics. |
1312 | | */ |
1313 | | |
1314 | 2.76k | if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 ) |
1315 | 406 | { |
1316 | 406 | root->ascender = face->os2.sTypoAscender; |
1317 | 406 | root->descender = face->os2.sTypoDescender; |
1318 | 406 | root->height = root->ascender - root->descender + |
1319 | 406 | face->os2.sTypoLineGap; |
1320 | 406 | } |
1321 | 2.36k | else |
1322 | 2.36k | { |
1323 | 2.36k | root->ascender = face->horizontal.Ascender; |
1324 | 2.36k | root->descender = face->horizontal.Descender; |
1325 | 2.36k | root->height = root->ascender - root->descender + |
1326 | 2.36k | face->horizontal.Line_Gap; |
1327 | | |
1328 | 2.36k | if ( !( root->ascender || root->descender ) ) |
1329 | 181 | { |
1330 | 181 | if ( face->os2.version != 0xFFFFU ) |
1331 | 151 | { |
1332 | 151 | if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) |
1333 | 126 | { |
1334 | 126 | root->ascender = face->os2.sTypoAscender; |
1335 | 126 | root->descender = face->os2.sTypoDescender; |
1336 | 126 | root->height = root->ascender - root->descender + |
1337 | 126 | face->os2.sTypoLineGap; |
1338 | 126 | } |
1339 | 25 | else |
1340 | 25 | { |
1341 | 25 | root->ascender = (FT_Short)face->os2.usWinAscent; |
1342 | 25 | root->descender = -(FT_Short)face->os2.usWinDescent; |
1343 | 25 | root->height = root->ascender - root->descender; |
1344 | 25 | } |
1345 | 151 | } |
1346 | 181 | } |
1347 | 2.36k | } |
1348 | | |
1349 | 2.76k | root->max_advance_width = |
1350 | 2.76k | (FT_Short)face->horizontal.advance_Width_Max; |
1351 | 2.76k | root->max_advance_height = |
1352 | 0 | (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max |
1353 | 2.76k | : root->height ); |
1354 | | |
1355 | | /* See https://www.microsoft.com/typography/otspec/post.htm -- */ |
1356 | | /* Adjust underline position from top edge to centre of */ |
1357 | | /* stroke to convert TrueType meaning to FreeType meaning. */ |
1358 | 2.76k | root->underline_position = face->postscript.underlinePosition - |
1359 | 2.76k | face->postscript.underlineThickness / 2; |
1360 | 2.76k | root->underline_thickness = face->postscript.underlineThickness; |
1361 | 2.76k | } |
1362 | | |
1363 | 2.76k | } |
1364 | | |
1365 | 3.67k | Exit: |
1366 | 3.67k | FT_TRACE2(( "sfnt_load_face: done\n" )); |
1367 | | |
1368 | 3.67k | return error; |
1369 | 2.76k | } |
1370 | | |
1371 | | |
1372 | | #undef LOAD_ |
1373 | | #undef LOADM_ |
1374 | | #undef GET_NAME |
1375 | | |
1376 | | |
1377 | | FT_LOCAL_DEF( void ) |
1378 | | sfnt_done_face( TT_Face face ) |
1379 | 12.5k | { |
1380 | 12.5k | FT_Memory memory; |
1381 | 12.5k | SFNT_Service sfnt; |
1382 | | |
1383 | | |
1384 | 12.5k | if ( !face ) |
1385 | 0 | return; |
1386 | | |
1387 | 12.5k | memory = face->root.memory; |
1388 | 12.5k | sfnt = (SFNT_Service)face->sfnt; |
1389 | | |
1390 | 12.5k | if ( sfnt ) |
1391 | 12.5k | { |
1392 | | /* destroy the postscript names table if it is loaded */ |
1393 | 12.5k | if ( sfnt->free_psnames ) |
1394 | 12.5k | sfnt->free_psnames( face ); |
1395 | | |
1396 | | /* destroy the embedded bitmaps table if it is loaded */ |
1397 | 12.5k | if ( sfnt->free_eblc ) |
1398 | 12.5k | sfnt->free_eblc( face ); |
1399 | | |
1400 | | /* destroy color table data if it is loaded */ |
1401 | 12.5k | if ( sfnt->free_cpal ) |
1402 | 12.5k | { |
1403 | 12.5k | sfnt->free_cpal( face ); |
1404 | 12.5k | sfnt->free_colr( face ); |
1405 | 12.5k | } |
1406 | 12.5k | } |
1407 | | |
1408 | 12.5k | #ifdef TT_CONFIG_OPTION_BDF |
1409 | | /* freeing the embedded BDF properties */ |
1410 | 12.5k | tt_face_free_bdf_props( face ); |
1411 | 12.5k | #endif |
1412 | | |
1413 | | /* freeing the kerning table */ |
1414 | 12.5k | tt_face_done_kern( face ); |
1415 | | |
1416 | | /* freeing the collection table */ |
1417 | 12.5k | FT_FREE( face->ttc_header.offsets ); |
1418 | 12.5k | face->ttc_header.count = 0; |
1419 | | |
1420 | | /* freeing table directory */ |
1421 | 12.5k | FT_FREE( face->dir_tables ); |
1422 | 12.5k | face->num_tables = 0; |
1423 | | |
1424 | 12.5k | { |
1425 | 12.5k | FT_Stream stream = FT_FACE_STREAM( face ); |
1426 | | |
1427 | | |
1428 | | /* simply release the 'cmap' table frame */ |
1429 | 12.5k | FT_FRAME_RELEASE( face->cmap_table ); |
1430 | 12.5k | face->cmap_size = 0; |
1431 | 12.5k | } |
1432 | | |
1433 | 12.5k | face->horz_metrics_size = 0; |
1434 | 12.5k | face->vert_metrics_size = 0; |
1435 | | |
1436 | | /* freeing vertical metrics, if any */ |
1437 | 12.5k | if ( face->vertical_info ) |
1438 | 0 | { |
1439 | 0 | FT_FREE( face->vertical.long_metrics ); |
1440 | 0 | FT_FREE( face->vertical.short_metrics ); |
1441 | 0 | face->vertical_info = 0; |
1442 | 0 | } |
1443 | | |
1444 | | /* freeing the gasp table */ |
1445 | 12.5k | FT_FREE( face->gasp.gaspRanges ); |
1446 | 12.5k | face->gasp.numRanges = 0; |
1447 | | |
1448 | | /* freeing the name table */ |
1449 | 12.5k | if ( sfnt ) |
1450 | 12.5k | sfnt->free_name( face ); |
1451 | | |
1452 | | /* freeing family and style name */ |
1453 | 12.5k | FT_FREE( face->root.family_name ); |
1454 | 12.5k | FT_FREE( face->root.style_name ); |
1455 | | |
1456 | | /* freeing sbit size table */ |
1457 | 12.5k | FT_FREE( face->root.available_sizes ); |
1458 | 12.5k | FT_FREE( face->sbit_strike_map ); |
1459 | 12.5k | face->root.num_fixed_sizes = 0; |
1460 | | |
1461 | 12.5k | FT_FREE( face->postscript_name ); |
1462 | | |
1463 | 12.5k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
1464 | 12.5k | FT_FREE( face->var_postscript_prefix ); |
1465 | 12.5k | #endif |
1466 | | |
1467 | | /* freeing glyph color palette data */ |
1468 | 12.5k | FT_FREE( face->palette_data.palette_name_ids ); |
1469 | 12.5k | FT_FREE( face->palette_data.palette_flags ); |
1470 | 12.5k | FT_FREE( face->palette_data.palette_entry_name_ids ); |
1471 | 12.5k | FT_FREE( face->palette ); |
1472 | | |
1473 | 12.5k | face->sfnt = NULL; |
1474 | 12.5k | } |
1475 | | |
1476 | | |
1477 | | /* END */ |