1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* sfobjs.c */ |
|
4 /* */ |
|
5 /* SFNT object management (base). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2008, 2010-2011 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 <ft2build.h> |
|
20 #include "sfobjs.h" |
|
21 #include "ttload.h" |
|
22 #include "ttcmap.h" |
|
23 #include "ttkern.h" |
|
24 #include FT_INTERNAL_SFNT_H |
|
25 #include FT_INTERNAL_DEBUG_H |
|
26 #include FT_TRUETYPE_IDS_H |
|
27 #include FT_TRUETYPE_TAGS_H |
|
28 #include FT_SERVICE_POSTSCRIPT_CMAPS_H |
|
29 #include FT_SFNT_NAMES_H |
|
30 #include "sferrors.h" |
|
31 |
|
32 #ifdef TT_CONFIG_OPTION_BDF |
|
33 #include "ttbdf.h" |
|
34 #endif |
|
35 |
|
36 |
|
37 /*************************************************************************/ |
|
38 /* */ |
|
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
41 /* messages during execution. */ |
|
42 /* */ |
|
43 #undef FT_COMPONENT |
|
44 #define FT_COMPONENT trace_sfobjs |
|
45 |
|
46 |
|
47 |
|
48 /* convert a UTF-16 name entry to ASCII */ |
|
49 static FT_String* |
|
50 tt_name_entry_ascii_from_utf16( TT_NameEntry entry, |
|
51 FT_Memory memory ) |
|
52 { |
|
53 FT_String* string = NULL; |
|
54 FT_UInt len, code, n; |
|
55 FT_Byte* read = (FT_Byte*)entry->string; |
|
56 FT_Error error; |
|
57 |
|
58 |
|
59 len = (FT_UInt)entry->stringLength / 2; |
|
60 |
|
61 if ( FT_NEW_ARRAY( string, len + 1 ) ) |
|
62 return NULL; |
|
63 |
|
64 for ( n = 0; n < len; n++ ) |
|
65 { |
|
66 code = FT_NEXT_USHORT( read ); |
|
67 if ( code < 32 || code > 127 ) |
|
68 code = '?'; |
|
69 |
|
70 string[n] = (char)code; |
|
71 } |
|
72 |
|
73 string[len] = 0; |
|
74 |
|
75 return string; |
|
76 } |
|
77 |
|
78 |
|
79 /* convert an Apple Roman or symbol name entry to ASCII */ |
|
80 static FT_String* |
|
81 tt_name_entry_ascii_from_other( TT_NameEntry entry, |
|
82 FT_Memory memory ) |
|
83 { |
|
84 FT_String* string = NULL; |
|
85 FT_UInt len, code, n; |
|
86 FT_Byte* read = (FT_Byte*)entry->string; |
|
87 FT_Error error; |
|
88 |
|
89 |
|
90 len = (FT_UInt)entry->stringLength; |
|
91 |
|
92 if ( FT_NEW_ARRAY( string, len + 1 ) ) |
|
93 return NULL; |
|
94 |
|
95 for ( n = 0; n < len; n++ ) |
|
96 { |
|
97 code = *read++; |
|
98 if ( code < 32 || code > 127 ) |
|
99 code = '?'; |
|
100 |
|
101 string[n] = (char)code; |
|
102 } |
|
103 |
|
104 string[len] = 0; |
|
105 |
|
106 return string; |
|
107 } |
|
108 |
|
109 |
|
110 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, |
|
111 FT_Memory memory ); |
|
112 |
|
113 |
|
114 /*************************************************************************/ |
|
115 /* */ |
|
116 /* <Function> */ |
|
117 /* tt_face_get_name */ |
|
118 /* */ |
|
119 /* <Description> */ |
|
120 /* Returns a given ENGLISH name record in ASCII. */ |
|
121 /* */ |
|
122 /* <Input> */ |
|
123 /* face :: A handle to the source face object. */ |
|
124 /* */ |
|
125 /* nameid :: The name id of the name record to return. */ |
|
126 /* */ |
|
127 /* <InOut> */ |
|
128 /* name :: The address of a string pointer. NULL if no name is */ |
|
129 /* present. */ |
|
130 /* */ |
|
131 /* <Return> */ |
|
132 /* FreeType error code. 0 means success. */ |
|
133 /* */ |
|
134 static FT_Error |
|
135 tt_face_get_name( TT_Face face, |
|
136 FT_UShort nameid, |
|
137 FT_String** name ) |
|
138 { |
|
139 FT_Memory memory = face->root.memory; |
|
140 FT_Error error = SFNT_Err_Ok; |
|
141 FT_String* result = NULL; |
|
142 FT_UShort n; |
|
143 TT_NameEntryRec* rec; |
|
144 FT_Int found_apple = -1; |
|
145 FT_Int found_apple_roman = -1; |
|
146 FT_Int found_apple_english = -1; |
|
147 FT_Int found_win = -1; |
|
148 FT_Int found_unicode = -1; |
|
149 |
|
150 FT_Bool is_english = 0; |
|
151 |
|
152 TT_NameEntry_ConvertFunc convert; |
|
153 |
|
154 |
|
155 FT_ASSERT( name ); |
|
156 |
|
157 rec = face->name_table.names; |
|
158 for ( n = 0; n < face->num_names; n++, rec++ ) |
|
159 { |
|
160 /* According to the OpenType 1.3 specification, only Microsoft or */ |
|
161 /* Apple platform IDs might be used in the `name' table. The */ |
|
162 /* `Unicode' platform is reserved for the `cmap' table, and the */ |
|
163 /* `ISO' one is deprecated. */ |
|
164 /* */ |
|
165 /* However, the Apple TrueType specification doesn't say the same */ |
|
166 /* thing and goes to suggest that all Unicode `name' table entries */ |
|
167 /* should be coded in UTF-16 (in big-endian format I suppose). */ |
|
168 /* */ |
|
169 if ( rec->nameID == nameid && rec->stringLength > 0 ) |
|
170 { |
|
171 switch ( rec->platformID ) |
|
172 { |
|
173 case TT_PLATFORM_APPLE_UNICODE: |
|
174 case TT_PLATFORM_ISO: |
|
175 /* there is `languageID' to check there. We should use this */ |
|
176 /* field only as a last solution when nothing else is */ |
|
177 /* available. */ |
|
178 /* */ |
|
179 found_unicode = n; |
|
180 break; |
|
181 |
|
182 case TT_PLATFORM_MACINTOSH: |
|
183 /* This is a bit special because some fonts will use either */ |
|
184 /* an English language id, or a Roman encoding id, to indicate */ |
|
185 /* the English version of its font name. */ |
|
186 /* */ |
|
187 if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) |
|
188 found_apple_english = n; |
|
189 else if ( rec->encodingID == TT_MAC_ID_ROMAN ) |
|
190 found_apple_roman = n; |
|
191 break; |
|
192 |
|
193 case TT_PLATFORM_MICROSOFT: |
|
194 /* we only take a non-English name when there is nothing */ |
|
195 /* else available in the font */ |
|
196 /* */ |
|
197 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) |
|
198 { |
|
199 switch ( rec->encodingID ) |
|
200 { |
|
201 case TT_MS_ID_SYMBOL_CS: |
|
202 case TT_MS_ID_UNICODE_CS: |
|
203 case TT_MS_ID_UCS_4: |
|
204 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); |
|
205 found_win = n; |
|
206 break; |
|
207 |
|
208 default: |
|
209 ; |
|
210 } |
|
211 } |
|
212 break; |
|
213 |
|
214 default: |
|
215 ; |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 found_apple = found_apple_roman; |
|
221 if ( found_apple_english >= 0 ) |
|
222 found_apple = found_apple_english; |
|
223 |
|
224 /* some fonts contain invalid Unicode or Macintosh formatted entries; */ |
|
225 /* we will thus favor names encoded in Windows formats if available */ |
|
226 /* (provided it is an English name) */ |
|
227 /* */ |
|
228 convert = NULL; |
|
229 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) |
|
230 { |
|
231 rec = face->name_table.names + found_win; |
|
232 switch ( rec->encodingID ) |
|
233 { |
|
234 /* all Unicode strings are encoded using UTF-16BE */ |
|
235 case TT_MS_ID_UNICODE_CS: |
|
236 case TT_MS_ID_SYMBOL_CS: |
|
237 convert = tt_name_entry_ascii_from_utf16; |
|
238 break; |
|
239 |
|
240 case TT_MS_ID_UCS_4: |
|
241 /* Apparently, if this value is found in a name table entry, it is */ |
|
242 /* documented as `full Unicode repertoire'. Experience with the */ |
|
243 /* MsGothic font shipped with Windows Vista shows that this really */ |
|
244 /* means UTF-16 encoded names (UCS-4 values are only used within */ |
|
245 /* charmaps). */ |
|
246 convert = tt_name_entry_ascii_from_utf16; |
|
247 break; |
|
248 |
|
249 default: |
|
250 ; |
|
251 } |
|
252 } |
|
253 else if ( found_apple >= 0 ) |
|
254 { |
|
255 rec = face->name_table.names + found_apple; |
|
256 convert = tt_name_entry_ascii_from_other; |
|
257 } |
|
258 else if ( found_unicode >= 0 ) |
|
259 { |
|
260 rec = face->name_table.names + found_unicode; |
|
261 convert = tt_name_entry_ascii_from_utf16; |
|
262 } |
|
263 |
|
264 if ( rec && convert ) |
|
265 { |
|
266 if ( rec->string == NULL ) |
|
267 { |
|
268 FT_Stream stream = face->name_table.stream; |
|
269 |
|
270 |
|
271 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || |
|
272 FT_STREAM_SEEK( rec->stringOffset ) || |
|
273 FT_STREAM_READ( rec->string, rec->stringLength ) ) |
|
274 { |
|
275 FT_FREE( rec->string ); |
|
276 rec->stringLength = 0; |
|
277 result = NULL; |
|
278 goto Exit; |
|
279 } |
|
280 } |
|
281 |
|
282 result = convert( rec, memory ); |
|
283 } |
|
284 |
|
285 Exit: |
|
286 *name = result; |
|
287 return error; |
|
288 } |
|
289 |
|
290 |
|
291 static FT_Encoding |
|
292 sfnt_find_encoding( int platform_id, |
|
293 int encoding_id ) |
|
294 { |
|
295 typedef struct TEncoding_ |
|
296 { |
|
297 int platform_id; |
|
298 int encoding_id; |
|
299 FT_Encoding encoding; |
|
300 |
|
301 } TEncoding; |
|
302 |
|
303 static |
|
304 const TEncoding tt_encodings[] = |
|
305 { |
|
306 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, |
|
307 |
|
308 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, |
|
309 |
|
310 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, |
|
311 |
|
312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, |
|
313 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, |
|
314 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, |
|
315 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, |
|
316 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, |
|
317 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, |
|
318 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, |
|
319 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } |
|
320 }; |
|
321 |
|
322 const TEncoding *cur, *limit; |
|
323 |
|
324 |
|
325 cur = tt_encodings; |
|
326 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); |
|
327 |
|
328 for ( ; cur < limit; cur++ ) |
|
329 { |
|
330 if ( cur->platform_id == platform_id ) |
|
331 { |
|
332 if ( cur->encoding_id == encoding_id || |
|
333 cur->encoding_id == -1 ) |
|
334 return cur->encoding; |
|
335 } |
|
336 } |
|
337 |
|
338 return FT_ENCODING_NONE; |
|
339 } |
|
340 |
|
341 |
|
342 /* Fill in face->ttc_header. If the font is not a TTC, it is */ |
|
343 /* synthesized into a TTC with one offset table. */ |
|
344 static FT_Error |
|
345 sfnt_open_font( FT_Stream stream, |
|
346 TT_Face face ) |
|
347 { |
|
348 FT_Memory memory = stream->memory; |
|
349 FT_Error error; |
|
350 FT_ULong tag, offset; |
|
351 |
|
352 static const FT_Frame_Field ttc_header_fields[] = |
|
353 { |
|
354 #undef FT_STRUCTURE |
|
355 #define FT_STRUCTURE TTC_HeaderRec |
|
356 |
|
357 FT_FRAME_START( 8 ), |
|
358 FT_FRAME_LONG( version ), |
|
359 FT_FRAME_LONG( count ), /* this is ULong in the specs */ |
|
360 FT_FRAME_END |
|
361 }; |
|
362 |
|
363 |
|
364 face->ttc_header.tag = 0; |
|
365 face->ttc_header.version = 0; |
|
366 face->ttc_header.count = 0; |
|
367 |
|
368 offset = FT_STREAM_POS(); |
|
369 |
|
370 if ( FT_READ_ULONG( tag ) ) |
|
371 return error; |
|
372 |
|
373 if ( tag != 0x00010000UL && |
|
374 tag != TTAG_ttcf && |
|
375 tag != TTAG_OTTO && |
|
376 tag != TTAG_true && |
|
377 tag != TTAG_typ1 && |
|
378 tag != 0x00020000UL ) |
|
379 return SFNT_Err_Unknown_File_Format; |
|
380 |
|
381 face->ttc_header.tag = TTAG_ttcf; |
|
382 |
|
383 if ( tag == TTAG_ttcf ) |
|
384 { |
|
385 FT_Int n; |
|
386 |
|
387 |
|
388 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); |
|
389 |
|
390 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) |
|
391 return error; |
|
392 |
|
393 if ( face->ttc_header.count == 0 ) |
|
394 return SFNT_Err_Invalid_Table; |
|
395 |
|
396 /* a rough size estimate: let's conservatively assume that there */ |
|
397 /* is just a single table info in each subfont header (12 + 16*1 = */ |
|
398 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ |
|
399 /* size of the TTC header plus `28*count' bytes for all subfont */ |
|
400 /* headers */ |
|
401 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) |
|
402 return SFNT_Err_Array_Too_Large; |
|
403 |
|
404 /* now read the offsets of each font in the file */ |
|
405 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) |
|
406 return error; |
|
407 |
|
408 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) |
|
409 return error; |
|
410 |
|
411 for ( n = 0; n < face->ttc_header.count; n++ ) |
|
412 face->ttc_header.offsets[n] = FT_GET_ULONG(); |
|
413 |
|
414 FT_FRAME_EXIT(); |
|
415 } |
|
416 else |
|
417 { |
|
418 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); |
|
419 |
|
420 face->ttc_header.version = 1 << 16; |
|
421 face->ttc_header.count = 1; |
|
422 |
|
423 if ( FT_NEW( face->ttc_header.offsets ) ) |
|
424 return error; |
|
425 |
|
426 face->ttc_header.offsets[0] = offset; |
|
427 } |
|
428 |
|
429 return error; |
|
430 } |
|
431 |
|
432 |
|
433 FT_LOCAL_DEF( FT_Error ) |
|
434 sfnt_init_face( FT_Stream stream, |
|
435 TT_Face face, |
|
436 FT_Int face_index, |
|
437 FT_Int num_params, |
|
438 FT_Parameter* params ) |
|
439 { |
|
440 FT_Error error; |
|
441 FT_Library library = face->root.driver->root.library; |
|
442 SFNT_Service sfnt; |
|
443 |
|
444 |
|
445 /* for now, parameters are unused */ |
|
446 FT_UNUSED( num_params ); |
|
447 FT_UNUSED( params ); |
|
448 |
|
449 |
|
450 sfnt = (SFNT_Service)face->sfnt; |
|
451 if ( !sfnt ) |
|
452 { |
|
453 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); |
|
454 if ( !sfnt ) |
|
455 return SFNT_Err_Invalid_File_Format; |
|
456 |
|
457 face->sfnt = sfnt; |
|
458 face->goto_table = sfnt->goto_table; |
|
459 } |
|
460 |
|
461 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); |
|
462 |
|
463 error = sfnt_open_font( stream, face ); |
|
464 if ( error ) |
|
465 return error; |
|
466 |
|
467 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); |
|
468 |
|
469 if ( face_index < 0 ) |
|
470 face_index = 0; |
|
471 |
|
472 if ( face_index >= face->ttc_header.count ) |
|
473 return SFNT_Err_Invalid_Argument; |
|
474 |
|
475 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) |
|
476 return error; |
|
477 |
|
478 /* check that we have a valid TrueType file */ |
|
479 error = sfnt->load_font_dir( face, stream ); |
|
480 if ( error ) |
|
481 return error; |
|
482 |
|
483 face->root.num_faces = face->ttc_header.count; |
|
484 face->root.face_index = face_index; |
|
485 |
|
486 return error; |
|
487 } |
|
488 |
|
489 |
|
490 #define LOAD_( x ) \ |
|
491 do { \ |
|
492 FT_TRACE2(( "`" #x "' " )); \ |
|
493 FT_TRACE3(( "-->\n" )); \ |
|
494 \ |
|
495 error = sfnt->load_##x( face, stream ); \ |
|
496 \ |
|
497 FT_TRACE2(( "%s\n", ( !error ) \ |
|
498 ? "loaded" \ |
|
499 : ( error == SFNT_Err_Table_Missing ) \ |
|
500 ? "missing" \ |
|
501 : "failed to load" )); \ |
|
502 FT_TRACE3(( "\n" )); \ |
|
503 } while ( 0 ) |
|
504 |
|
505 #define LOADM_( x, vertical ) \ |
|
506 do { \ |
|
507 FT_TRACE2(( "`%s" #x "' ", \ |
|
508 vertical ? "vertical " : "" )); \ |
|
509 FT_TRACE3(( "-->\n" )); \ |
|
510 \ |
|
511 error = sfnt->load_##x( face, stream, vertical ); \ |
|
512 \ |
|
513 FT_TRACE2(( "%s\n", ( !error ) \ |
|
514 ? "loaded" \ |
|
515 : ( error == SFNT_Err_Table_Missing ) \ |
|
516 ? "missing" \ |
|
517 : "failed to load" )); \ |
|
518 FT_TRACE3(( "\n" )); \ |
|
519 } while ( 0 ) |
|
520 |
|
521 #define GET_NAME( id, field ) \ |
|
522 do { \ |
|
523 error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \ |
|
524 if ( error ) \ |
|
525 goto Exit; \ |
|
526 } while ( 0 ) |
|
527 |
|
528 |
|
529 FT_LOCAL_DEF( FT_Error ) |
|
530 sfnt_load_face( FT_Stream stream, |
|
531 TT_Face face, |
|
532 FT_Int face_index, |
|
533 FT_Int num_params, |
|
534 FT_Parameter* params ) |
|
535 { |
|
536 FT_Error error; |
|
537 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
|
538 FT_Error psnames_error; |
|
539 #endif |
|
540 FT_Bool has_outline; |
|
541 FT_Bool is_apple_sbit; |
|
542 FT_Bool ignore_preferred_family = FALSE; |
|
543 FT_Bool ignore_preferred_subfamily = FALSE; |
|
544 |
|
545 SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
|
546 |
|
547 FT_UNUSED( face_index ); |
|
548 |
|
549 /* Check parameters */ |
|
550 |
|
551 { |
|
552 FT_Int i; |
|
553 |
|
554 |
|
555 for ( i = 0; i < num_params; i++ ) |
|
556 { |
|
557 if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) |
|
558 ignore_preferred_family = TRUE; |
|
559 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) |
|
560 ignore_preferred_subfamily = TRUE; |
|
561 } |
|
562 } |
|
563 |
|
564 /* Load tables */ |
|
565 |
|
566 /* We now support two SFNT-based bitmapped font formats. They */ |
|
567 /* are recognized easily as they do not include a `glyf' */ |
|
568 /* table. */ |
|
569 /* */ |
|
570 /* The first format comes from Apple, and uses a table named */ |
|
571 /* `bhed' instead of `head' to store the font header (using */ |
|
572 /* the same format). It also doesn't include horizontal and */ |
|
573 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ |
|
574 /* missing). */ |
|
575 /* */ |
|
576 /* The other format comes from Microsoft, and is used with */ |
|
577 /* WinCE/PocketPC. It looks like a standard TTF, except that */ |
|
578 /* it doesn't contain outlines. */ |
|
579 /* */ |
|
580 |
|
581 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); |
|
582 |
|
583 /* do we have outlines in there? */ |
|
584 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
585 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || |
|
586 tt_face_lookup_table( face, TTAG_glyf ) != 0 || |
|
587 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); |
|
588 #else |
|
589 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || |
|
590 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); |
|
591 #endif |
|
592 |
|
593 is_apple_sbit = 0; |
|
594 |
|
595 /* if this font doesn't contain outlines, we try to load */ |
|
596 /* a `bhed' table */ |
|
597 if ( !has_outline && sfnt->load_bhed ) |
|
598 { |
|
599 LOAD_( bhed ); |
|
600 is_apple_sbit = FT_BOOL( !error ); |
|
601 } |
|
602 |
|
603 /* load the font header (`head' table) if this isn't an Apple */ |
|
604 /* sbit font file */ |
|
605 if ( !is_apple_sbit ) |
|
606 { |
|
607 LOAD_( head ); |
|
608 if ( error ) |
|
609 goto Exit; |
|
610 } |
|
611 |
|
612 if ( face->header.Units_Per_EM == 0 ) |
|
613 { |
|
614 error = SFNT_Err_Invalid_Table; |
|
615 |
|
616 goto Exit; |
|
617 } |
|
618 |
|
619 /* the following tables are often not present in embedded TrueType */ |
|
620 /* fonts within PDF documents, so don't check for them. */ |
|
621 LOAD_( maxp ); |
|
622 LOAD_( cmap ); |
|
623 |
|
624 /* the following tables are optional in PCL fonts -- */ |
|
625 /* don't check for errors */ |
|
626 LOAD_( name ); |
|
627 LOAD_( post ); |
|
628 |
|
629 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
|
630 psnames_error = error; |
|
631 #endif |
|
632 |
|
633 /* do not load the metrics headers and tables if this is an Apple */ |
|
634 /* sbit font file */ |
|
635 if ( !is_apple_sbit ) |
|
636 { |
|
637 /* load the `hhea' and `hmtx' tables */ |
|
638 LOADM_( hhea, 0 ); |
|
639 if ( !error ) |
|
640 { |
|
641 LOADM_( hmtx, 0 ); |
|
642 if ( error == SFNT_Err_Table_Missing ) |
|
643 { |
|
644 error = SFNT_Err_Hmtx_Table_Missing; |
|
645 |
|
646 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
647 /* If this is an incrementally loaded font and there are */ |
|
648 /* overriding metrics, tolerate a missing `hmtx' table. */ |
|
649 if ( face->root.internal->incremental_interface && |
|
650 face->root.internal->incremental_interface->funcs-> |
|
651 get_glyph_metrics ) |
|
652 { |
|
653 face->horizontal.number_Of_HMetrics = 0; |
|
654 error = SFNT_Err_Ok; |
|
655 } |
|
656 #endif |
|
657 } |
|
658 } |
|
659 else if ( error == SFNT_Err_Table_Missing ) |
|
660 { |
|
661 /* No `hhea' table necessary for SFNT Mac fonts. */ |
|
662 if ( face->format_tag == TTAG_true ) |
|
663 { |
|
664 FT_TRACE2(( "This is an SFNT Mac font.\n" )); |
|
665 has_outline = 0; |
|
666 error = SFNT_Err_Ok; |
|
667 } |
|
668 else |
|
669 { |
|
670 error = SFNT_Err_Horiz_Header_Missing; |
|
671 |
|
672 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
673 /* If this is an incrementally loaded font and there are */ |
|
674 /* overriding metrics, tolerate a missing `hhea' table. */ |
|
675 if ( face->root.internal->incremental_interface && |
|
676 face->root.internal->incremental_interface->funcs-> |
|
677 get_glyph_metrics ) |
|
678 { |
|
679 face->horizontal.number_Of_HMetrics = 0; |
|
680 error = SFNT_Err_Ok; |
|
681 } |
|
682 #endif |
|
683 |
|
684 } |
|
685 } |
|
686 |
|
687 if ( error ) |
|
688 goto Exit; |
|
689 |
|
690 /* try to load the `vhea' and `vmtx' tables */ |
|
691 LOADM_( hhea, 1 ); |
|
692 if ( !error ) |
|
693 { |
|
694 LOADM_( hmtx, 1 ); |
|
695 if ( !error ) |
|
696 face->vertical_info = 1; |
|
697 } |
|
698 |
|
699 if ( error && error != SFNT_Err_Table_Missing ) |
|
700 goto Exit; |
|
701 |
|
702 LOAD_( os2 ); |
|
703 if ( error ) |
|
704 { |
|
705 /* we treat the table as missing if there are any errors */ |
|
706 face->os2.version = 0xFFFFU; |
|
707 } |
|
708 } |
|
709 |
|
710 /* the optional tables */ |
|
711 |
|
712 /* embedded bitmap support */ |
|
713 if ( sfnt->load_eblc ) |
|
714 { |
|
715 LOAD_( eblc ); |
|
716 if ( error ) |
|
717 { |
|
718 /* a font which contains neither bitmaps nor outlines is */ |
|
719 /* still valid (although rather useless in most cases); */ |
|
720 /* however, you can find such stripped fonts in PDFs */ |
|
721 if ( error == SFNT_Err_Table_Missing ) |
|
722 error = SFNT_Err_Ok; |
|
723 else |
|
724 goto Exit; |
|
725 } |
|
726 } |
|
727 |
|
728 LOAD_( pclt ); |
|
729 if ( error ) |
|
730 { |
|
731 if ( error != SFNT_Err_Table_Missing ) |
|
732 goto Exit; |
|
733 |
|
734 face->pclt.Version = 0; |
|
735 } |
|
736 |
|
737 /* consider the kerning and gasp tables as optional */ |
|
738 LOAD_( gasp ); |
|
739 LOAD_( kern ); |
|
740 |
|
741 face->root.num_glyphs = face->max_profile.numGlyphs; |
|
742 |
|
743 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ |
|
744 /* a WWS-only font face. `WWS' stands for `weight', width', and */ |
|
745 /* `slope', a term used by Microsoft's Windows Presentation */ |
|
746 /* Foundation (WPF). This flag has been introduced in version */ |
|
747 /* 1.5 of the OpenType specification (May 2008). */ |
|
748 |
|
749 face->root.family_name = NULL; |
|
750 face->root.style_name = NULL; |
|
751 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) |
|
752 { |
|
753 if ( !ignore_preferred_family ) |
|
754 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); |
|
755 if ( !face->root.family_name ) |
|
756 GET_NAME( FONT_FAMILY, &face->root.family_name ); |
|
757 |
|
758 if ( !ignore_preferred_subfamily ) |
|
759 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); |
|
760 if ( !face->root.style_name ) |
|
761 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); |
|
762 } |
|
763 else |
|
764 { |
|
765 GET_NAME( WWS_FAMILY, &face->root.family_name ); |
|
766 if ( !face->root.family_name && !ignore_preferred_family ) |
|
767 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); |
|
768 if ( !face->root.family_name ) |
|
769 GET_NAME( FONT_FAMILY, &face->root.family_name ); |
|
770 |
|
771 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); |
|
772 if ( !face->root.style_name && !ignore_preferred_subfamily ) |
|
773 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); |
|
774 if ( !face->root.style_name ) |
|
775 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); |
|
776 } |
|
777 |
|
778 /* now set up root fields */ |
|
779 { |
|
780 FT_Face root = &face->root; |
|
781 FT_Long flags = root->face_flags; |
|
782 |
|
783 |
|
784 /*********************************************************************/ |
|
785 /* */ |
|
786 /* Compute face flags. */ |
|
787 /* */ |
|
788 if ( has_outline == TRUE ) |
|
789 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ |
|
790 |
|
791 /* The sfnt driver only supports bitmap fonts natively, thus we */ |
|
792 /* don't set FT_FACE_FLAG_HINTER. */ |
|
793 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ |
|
794 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ |
|
795 |
|
796 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
|
797 if ( psnames_error == SFNT_Err_Ok && |
|
798 face->postscript.FormatType != 0x00030000L ) |
|
799 flags |= FT_FACE_FLAG_GLYPH_NAMES; |
|
800 #endif |
|
801 |
|
802 /* fixed width font? */ |
|
803 if ( face->postscript.isFixedPitch ) |
|
804 flags |= FT_FACE_FLAG_FIXED_WIDTH; |
|
805 |
|
806 /* vertical information? */ |
|
807 if ( face->vertical_info ) |
|
808 flags |= FT_FACE_FLAG_VERTICAL; |
|
809 |
|
810 /* kerning available ? */ |
|
811 if ( TT_FACE_HAS_KERNING( face ) ) |
|
812 flags |= FT_FACE_FLAG_KERNING; |
|
813 |
|
814 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
815 /* Don't bother to load the tables unless somebody asks for them. */ |
|
816 /* No need to do work which will (probably) not be used. */ |
|
817 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && |
|
818 tt_face_lookup_table( face, TTAG_fvar ) != 0 && |
|
819 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) |
|
820 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; |
|
821 #endif |
|
822 |
|
823 root->face_flags = flags; |
|
824 |
|
825 /*********************************************************************/ |
|
826 /* */ |
|
827 /* Compute style flags. */ |
|
828 /* */ |
|
829 |
|
830 flags = 0; |
|
831 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) |
|
832 { |
|
833 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ |
|
834 /* indicates an oblique font face. This flag has been */ |
|
835 /* introduced in version 1.5 of the OpenType specification. */ |
|
836 |
|
837 if ( face->os2.fsSelection & 512 ) /* bit 9 */ |
|
838 flags |= FT_STYLE_FLAG_ITALIC; |
|
839 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ |
|
840 flags |= FT_STYLE_FLAG_ITALIC; |
|
841 |
|
842 if ( face->os2.fsSelection & 32 ) /* bit 5 */ |
|
843 flags |= FT_STYLE_FLAG_BOLD; |
|
844 } |
|
845 else |
|
846 { |
|
847 /* this is an old Mac font, use the header field */ |
|
848 |
|
849 if ( face->header.Mac_Style & 1 ) |
|
850 flags |= FT_STYLE_FLAG_BOLD; |
|
851 |
|
852 if ( face->header.Mac_Style & 2 ) |
|
853 flags |= FT_STYLE_FLAG_ITALIC; |
|
854 } |
|
855 |
|
856 root->style_flags = flags; |
|
857 |
|
858 /*********************************************************************/ |
|
859 /* */ |
|
860 /* Polish the charmaps. */ |
|
861 /* */ |
|
862 /* Try to set the charmap encoding according to the platform & */ |
|
863 /* encoding ID of each charmap. */ |
|
864 /* */ |
|
865 |
|
866 tt_face_build_cmaps( face ); /* ignore errors */ |
|
867 |
|
868 |
|
869 /* set the encoding fields */ |
|
870 { |
|
871 FT_Int m; |
|
872 |
|
873 |
|
874 for ( m = 0; m < root->num_charmaps; m++ ) |
|
875 { |
|
876 FT_CharMap charmap = root->charmaps[m]; |
|
877 |
|
878 |
|
879 charmap->encoding = sfnt_find_encoding( charmap->platform_id, |
|
880 charmap->encoding_id ); |
|
881 |
|
882 #if 0 |
|
883 if ( root->charmap == NULL && |
|
884 charmap->encoding == FT_ENCODING_UNICODE ) |
|
885 { |
|
886 /* set 'root->charmap' to the first Unicode encoding we find */ |
|
887 root->charmap = charmap; |
|
888 } |
|
889 #endif |
|
890 } |
|
891 } |
|
892 |
|
893 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
|
894 |
|
895 /* |
|
896 * Now allocate the root array of FT_Bitmap_Size records and |
|
897 * populate them. Unfortunately, it isn't possible to indicate bit |
|
898 * depths in the FT_Bitmap_Size record. This is a design error. |
|
899 */ |
|
900 { |
|
901 FT_UInt i, count; |
|
902 |
|
903 |
|
904 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS |
|
905 count = face->sbit_num_strikes; |
|
906 #else |
|
907 count = (FT_UInt)face->num_sbit_strikes; |
|
908 #endif |
|
909 |
|
910 if ( count > 0 ) |
|
911 { |
|
912 FT_Memory memory = face->root.stream->memory; |
|
913 FT_UShort em_size = face->header.Units_Per_EM; |
|
914 FT_Short avgwidth = face->os2.xAvgCharWidth; |
|
915 FT_Size_Metrics metrics; |
|
916 |
|
917 |
|
918 if ( em_size == 0 || face->os2.version == 0xFFFFU ) |
|
919 { |
|
920 avgwidth = 0; |
|
921 em_size = 1; |
|
922 } |
|
923 |
|
924 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) |
|
925 goto Exit; |
|
926 |
|
927 for ( i = 0; i < count; i++ ) |
|
928 { |
|
929 FT_Bitmap_Size* bsize = root->available_sizes + i; |
|
930 |
|
931 |
|
932 error = sfnt->load_strike_metrics( face, i, &metrics ); |
|
933 if ( error ) |
|
934 goto Exit; |
|
935 |
|
936 bsize->height = (FT_Short)( metrics.height >> 6 ); |
|
937 bsize->width = (FT_Short)( |
|
938 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); |
|
939 |
|
940 bsize->x_ppem = metrics.x_ppem << 6; |
|
941 bsize->y_ppem = metrics.y_ppem << 6; |
|
942 |
|
943 /* assume 72dpi */ |
|
944 bsize->size = metrics.y_ppem << 6; |
|
945 } |
|
946 |
|
947 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; |
|
948 root->num_fixed_sizes = (FT_Int)count; |
|
949 } |
|
950 } |
|
951 |
|
952 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
|
953 |
|
954 /* a font with no bitmaps and no outlines is scalable; */ |
|
955 /* it has only empty glyphs then */ |
|
956 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) |
|
957 root->face_flags |= FT_FACE_FLAG_SCALABLE; |
|
958 |
|
959 |
|
960 /*********************************************************************/ |
|
961 /* */ |
|
962 /* Set up metrics. */ |
|
963 /* */ |
|
964 if ( FT_IS_SCALABLE( root ) ) |
|
965 { |
|
966 /* XXX What about if outline header is missing */ |
|
967 /* (e.g. sfnt wrapped bitmap)? */ |
|
968 root->bbox.xMin = face->header.xMin; |
|
969 root->bbox.yMin = face->header.yMin; |
|
970 root->bbox.xMax = face->header.xMax; |
|
971 root->bbox.yMax = face->header.yMax; |
|
972 root->units_per_EM = face->header.Units_Per_EM; |
|
973 |
|
974 |
|
975 /* XXX: Computing the ascender/descender/height is very different */ |
|
976 /* from what the specification tells you. Apparently, we */ |
|
977 /* must be careful because */ |
|
978 /* */ |
|
979 /* - not all fonts have an OS/2 table; in this case, we take */ |
|
980 /* the values in the horizontal header. However, these */ |
|
981 /* values very often are not reliable. */ |
|
982 /* */ |
|
983 /* - otherwise, the correct typographic values are in the */ |
|
984 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ |
|
985 /* */ |
|
986 /* However, certain fonts have these fields set to 0. */ |
|
987 /* Rather, they have usWinAscent & usWinDescent correctly */ |
|
988 /* set (but with different values). */ |
|
989 /* */ |
|
990 /* As an example, Arial Narrow is implemented through four */ |
|
991 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ |
|
992 /* */ |
|
993 /* Strangely, all fonts have the same values in their */ |
|
994 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ |
|
995 /* */ |
|
996 /* On the other hand, they all have different */ |
|
997 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ |
|
998 /* table cannot be used to compute the text height reliably! */ |
|
999 /* */ |
|
1000 |
|
1001 /* The ascender/descender/height are computed from the OS/2 table */ |
|
1002 /* when found. Otherwise, they're taken from the horizontal */ |
|
1003 /* header. */ |
|
1004 /* */ |
|
1005 |
|
1006 root->ascender = face->horizontal.Ascender; |
|
1007 root->descender = face->horizontal.Descender; |
|
1008 |
|
1009 root->height = (FT_Short)( root->ascender - root->descender + |
|
1010 face->horizontal.Line_Gap ); |
|
1011 |
|
1012 #if 0 |
|
1013 /* if the line_gap is 0, we add an extra 15% to the text height -- */ |
|
1014 /* this computation is based on various versions of Times New Roman */ |
|
1015 if ( face->horizontal.Line_Gap == 0 ) |
|
1016 root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 ); |
|
1017 #endif /* 0 */ |
|
1018 |
|
1019 #if 0 |
|
1020 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ |
|
1021 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ |
|
1022 if ( face->os2.version != 0xFFFFU && root->ascender ) |
|
1023 { |
|
1024 FT_Int height; |
|
1025 |
|
1026 |
|
1027 root->ascender = face->os2.sTypoAscender; |
|
1028 root->descender = -face->os2.sTypoDescender; |
|
1029 |
|
1030 height = root->ascender + root->descender + face->os2.sTypoLineGap; |
|
1031 if ( height > root->height ) |
|
1032 root->height = height; |
|
1033 } |
|
1034 #endif /* 0 */ |
|
1035 |
|
1036 root->max_advance_width = face->horizontal.advance_Width_Max; |
|
1037 root->max_advance_height = (FT_Short)( face->vertical_info |
|
1038 ? face->vertical.advance_Height_Max |
|
1039 : root->height ); |
|
1040 |
|
1041 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ |
|
1042 /* Adjust underline position from top edge to centre of */ |
|
1043 /* stroke to convert TrueType meaning to FreeType meaning. */ |
|
1044 root->underline_position = face->postscript.underlinePosition - |
|
1045 face->postscript.underlineThickness / 2; |
|
1046 root->underline_thickness = face->postscript.underlineThickness; |
|
1047 } |
|
1048 |
|
1049 } |
|
1050 |
|
1051 Exit: |
|
1052 FT_TRACE2(( "sfnt_load_face: done\n" )); |
|
1053 |
|
1054 return error; |
|
1055 } |
|
1056 |
|
1057 |
|
1058 #undef LOAD_ |
|
1059 #undef LOADM_ |
|
1060 #undef GET_NAME |
|
1061 |
|
1062 |
|
1063 FT_LOCAL_DEF( void ) |
|
1064 sfnt_done_face( TT_Face face ) |
|
1065 { |
|
1066 FT_Memory memory; |
|
1067 SFNT_Service sfnt; |
|
1068 |
|
1069 |
|
1070 if ( !face ) |
|
1071 return; |
|
1072 |
|
1073 memory = face->root.memory; |
|
1074 sfnt = (SFNT_Service)face->sfnt; |
|
1075 |
|
1076 if ( sfnt ) |
|
1077 { |
|
1078 /* destroy the postscript names table if it is loaded */ |
|
1079 if ( sfnt->free_psnames ) |
|
1080 sfnt->free_psnames( face ); |
|
1081 |
|
1082 /* destroy the embedded bitmaps table if it is loaded */ |
|
1083 if ( sfnt->free_eblc ) |
|
1084 sfnt->free_eblc( face ); |
|
1085 } |
|
1086 |
|
1087 #ifdef TT_CONFIG_OPTION_BDF |
|
1088 /* freeing the embedded BDF properties */ |
|
1089 tt_face_free_bdf_props( face ); |
|
1090 #endif |
|
1091 |
|
1092 /* freeing the kerning table */ |
|
1093 tt_face_done_kern( face ); |
|
1094 |
|
1095 /* freeing the collection table */ |
|
1096 FT_FREE( face->ttc_header.offsets ); |
|
1097 face->ttc_header.count = 0; |
|
1098 |
|
1099 /* freeing table directory */ |
|
1100 FT_FREE( face->dir_tables ); |
|
1101 face->num_tables = 0; |
|
1102 |
|
1103 { |
|
1104 FT_Stream stream = FT_FACE_STREAM( face ); |
|
1105 |
|
1106 |
|
1107 /* simply release the 'cmap' table frame */ |
|
1108 FT_FRAME_RELEASE( face->cmap_table ); |
|
1109 face->cmap_size = 0; |
|
1110 } |
|
1111 |
|
1112 /* freeing the horizontal metrics */ |
|
1113 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS |
|
1114 { |
|
1115 FT_Stream stream = FT_FACE_STREAM( face ); |
|
1116 |
|
1117 |
|
1118 FT_FRAME_RELEASE( face->horz_metrics ); |
|
1119 FT_FRAME_RELEASE( face->vert_metrics ); |
|
1120 face->horz_metrics_size = 0; |
|
1121 face->vert_metrics_size = 0; |
|
1122 } |
|
1123 #else |
|
1124 FT_FREE( face->horizontal.long_metrics ); |
|
1125 FT_FREE( face->horizontal.short_metrics ); |
|
1126 #endif |
|
1127 |
|
1128 /* freeing the vertical ones, if any */ |
|
1129 if ( face->vertical_info ) |
|
1130 { |
|
1131 FT_FREE( face->vertical.long_metrics ); |
|
1132 FT_FREE( face->vertical.short_metrics ); |
|
1133 face->vertical_info = 0; |
|
1134 } |
|
1135 |
|
1136 /* freeing the gasp table */ |
|
1137 FT_FREE( face->gasp.gaspRanges ); |
|
1138 face->gasp.numRanges = 0; |
|
1139 |
|
1140 /* freeing the name table */ |
|
1141 if ( sfnt ) |
|
1142 sfnt->free_name( face ); |
|
1143 |
|
1144 /* freeing family and style name */ |
|
1145 FT_FREE( face->root.family_name ); |
|
1146 FT_FREE( face->root.style_name ); |
|
1147 |
|
1148 /* freeing sbit size table */ |
|
1149 FT_FREE( face->root.available_sizes ); |
|
1150 face->root.num_fixed_sizes = 0; |
|
1151 |
|
1152 FT_FREE( face->postscript_name ); |
|
1153 |
|
1154 face->sfnt = 0; |
|
1155 } |
|
1156 |
|
1157 |
|
1158 /* END */ |
|