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