Sync with trunk head (part 1 of x)
[reactos.git] / lib / 3rdparty / freetype / src / sfnt / ttload.c
1 /***************************************************************************/
2 /* */
3 /* ttload.c */
4 /* */
5 /* Load the basic TrueType tables, i.e., tables that can be either in */
6 /* TTF or OTF fonts (body). */
7 /* */
8 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
16 /* */
17 /***************************************************************************/
18
19
20 #include <ft2build.h>
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_TAGS_H
24 #include "ttload.h"
25
26 #include "sferrors.h"
27
28
29 /*************************************************************************/
30 /* */
31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
33 /* messages during execution. */
34 /* */
35 #undef FT_COMPONENT
36 #define FT_COMPONENT trace_ttload
37
38
39 /*************************************************************************/
40 /* */
41 /* <Function> */
42 /* tt_face_lookup_table */
43 /* */
44 /* <Description> */
45 /* Looks for a TrueType table by name. */
46 /* */
47 /* <Input> */
48 /* face :: A face object handle. */
49 /* */
50 /* tag :: The searched tag. */
51 /* */
52 /* <Return> */
53 /* A pointer to the table directory entry. 0 if not found. */
54 /* */
55 FT_LOCAL_DEF( TT_Table )
56 tt_face_lookup_table( TT_Face face,
57 FT_ULong tag )
58 {
59 TT_Table entry;
60 TT_Table limit;
61
62
63 FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
64 face,
65 (FT_Char)( tag >> 24 ),
66 (FT_Char)( tag >> 16 ),
67 (FT_Char)( tag >> 8 ),
68 (FT_Char)( tag ) ));
69
70 entry = face->dir_tables;
71 limit = entry + face->num_tables;
72
73 for ( ; entry < limit; entry++ )
74 {
75 /* For compatibility with Windows, we consider 0-length */
76 /* tables the same as missing tables. */
77 if ( entry->Tag == tag && entry->Length != 0 )
78 {
79 FT_TRACE4(( "found table.\n" ));
80 return entry;
81 }
82 }
83
84 FT_TRACE4(( "could not find table!\n" ));
85 return 0;
86 }
87
88
89 /*************************************************************************/
90 /* */
91 /* <Function> */
92 /* tt_face_goto_table */
93 /* */
94 /* <Description> */
95 /* Looks for a TrueType table by name, then seek a stream to it. */
96 /* */
97 /* <Input> */
98 /* face :: A face object handle. */
99 /* */
100 /* tag :: The searched tag. */
101 /* */
102 /* stream :: The stream to seek when the table is found. */
103 /* */
104 /* <Output> */
105 /* length :: The length of the table if found, undefined otherwise. */
106 /* */
107 /* <Return> */
108 /* FreeType error code. 0 means success. */
109 /* */
110 FT_LOCAL_DEF( FT_Error )
111 tt_face_goto_table( TT_Face face,
112 FT_ULong tag,
113 FT_Stream stream,
114 FT_ULong* length )
115 {
116 TT_Table table;
117 FT_Error error;
118
119
120 table = tt_face_lookup_table( face, tag );
121 if ( table )
122 {
123 if ( length )
124 *length = table->Length;
125
126 if ( FT_STREAM_SEEK( table->Offset ) )
127 goto Exit;
128 }
129 else
130 error = SFNT_Err_Table_Missing;
131
132 Exit:
133 return error;
134 }
135
136
137 /* Here, we */
138 /* */
139 /* - check that `num_tables' is valid */
140 /* - look for a `head' table, check its size, and parse it to check */
141 /* whether its `magic' field is correctly set */
142 /* */
143 /* When checking directory entries, ignore the tables `glyx' and `locx' */
144 /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
145 /* Type 42 fonts, and which are generally invalid. */
146 /* */
147 static FT_Error
148 check_table_dir( SFNT_Header sfnt,
149 FT_Stream stream )
150 {
151 FT_Error error;
152 FT_UInt nn;
153 FT_UInt has_head = 0, has_sing = 0, has_meta = 0;
154 FT_ULong offset = sfnt->offset + 12;
155
156 const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
157 const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
158
159 static const FT_Frame_Field table_dir_entry_fields[] =
160 {
161 #undef FT_STRUCTURE
162 #define FT_STRUCTURE TT_TableRec
163
164 FT_FRAME_START( 16 ),
165 FT_FRAME_ULONG( Tag ),
166 FT_FRAME_ULONG( CheckSum ),
167 FT_FRAME_ULONG( Offset ),
168 FT_FRAME_ULONG( Length ),
169 FT_FRAME_END
170 };
171
172
173 if ( sfnt->num_tables == 0 ||
174 offset + sfnt->num_tables * 16 > stream->size )
175 return SFNT_Err_Unknown_File_Format;
176
177 if ( FT_STREAM_SEEK( offset ) )
178 return error;
179
180 for ( nn = 0; nn < sfnt->num_tables; nn++ )
181 {
182 TT_TableRec table;
183
184
185 if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
186 return error;
187
188 if ( table.Offset + table.Length > stream->size &&
189 table.Tag != glyx_tag &&
190 table.Tag != locx_tag )
191 return SFNT_Err_Unknown_File_Format;
192
193 if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
194 {
195 FT_UInt32 magic;
196
197
198 #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
199 if ( table.Tag == TTAG_head )
200 #endif
201 has_head = 1;
202
203 /*
204 * The table length should be 0x36, but certain font tools make it
205 * 0x38, so we will just check that it is greater.
206 *
207 * Note that according to the specification, the table must be
208 * padded to 32-bit lengths, but this doesn't apply to the value of
209 * its `Length' field!
210 *
211 */
212 if ( table.Length < 0x36 )
213 return SFNT_Err_Unknown_File_Format;
214
215 if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
216 FT_READ_ULONG( magic ) )
217 return error;
218
219 if ( magic != 0x5F0F3CF5UL )
220 return SFNT_Err_Unknown_File_Format;
221
222 if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
223 return error;
224 }
225 else if ( table.Tag == TTAG_SING )
226 has_sing = 1;
227 else if ( table.Tag == TTAG_META )
228 has_meta = 1;
229 }
230
231 /* if `sing' and `meta' tables are present, there is no `head' table */
232 if ( has_head || ( has_sing && has_meta ) )
233 return SFNT_Err_Ok;
234 else
235 return SFNT_Err_Unknown_File_Format;
236 }
237
238
239 /*************************************************************************/
240 /* */
241 /* <Function> */
242 /* tt_face_load_font_dir */
243 /* */
244 /* <Description> */
245 /* Loads the header of a SFNT font file. */
246 /* */
247 /* <Input> */
248 /* face :: A handle to the target face object. */
249 /* */
250 /* stream :: The input stream. */
251 /* */
252 /* <Output> */
253 /* sfnt :: The SFNT header. */
254 /* */
255 /* <Return> */
256 /* FreeType error code. 0 means success. */
257 /* */
258 /* <Note> */
259 /* The stream cursor must be at the beginning of the font directory. */
260 /* */
261 FT_LOCAL_DEF( FT_Error )
262 tt_face_load_font_dir( TT_Face face,
263 FT_Stream stream )
264 {
265 SFNT_HeaderRec sfnt;
266 FT_Error error;
267 FT_Memory memory = stream->memory;
268 TT_TableRec* entry;
269 TT_TableRec* limit;
270
271 static const FT_Frame_Field offset_table_fields[] =
272 {
273 #undef FT_STRUCTURE
274 #define FT_STRUCTURE SFNT_HeaderRec
275
276 FT_FRAME_START( 8 ),
277 FT_FRAME_USHORT( num_tables ),
278 FT_FRAME_USHORT( search_range ),
279 FT_FRAME_USHORT( entry_selector ),
280 FT_FRAME_USHORT( range_shift ),
281 FT_FRAME_END
282 };
283
284
285 FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
286
287 /* read the offset table */
288
289 sfnt.offset = FT_STREAM_POS();
290
291 if ( FT_READ_ULONG( sfnt.format_tag ) ||
292 FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
293 return error;
294
295 /* many fonts don't have these fields set correctly */
296 #if 0
297 if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) ||
298 sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
299 return SFNT_Err_Unknown_File_Format;
300 #endif
301
302 /* load the table directory */
303
304 FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables ));
305 FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag ));
306
307 /* check first */
308 error = check_table_dir( &sfnt, stream );
309 if ( error )
310 {
311 FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" ));
312
313 return error;
314 }
315
316 face->num_tables = sfnt.num_tables;
317 face->format_tag = sfnt.format_tag;
318
319 if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
320 return error;
321
322 if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
323 FT_FRAME_ENTER( face->num_tables * 16L ) )
324 return error;
325
326 entry = face->dir_tables;
327 limit = entry + face->num_tables;
328
329 for ( ; entry < limit; entry++ )
330 {
331 entry->Tag = FT_GET_TAG4();
332 entry->CheckSum = FT_GET_ULONG();
333 entry->Offset = FT_GET_LONG();
334 entry->Length = FT_GET_LONG();
335
336 FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
337 (FT_Char)( entry->Tag >> 24 ),
338 (FT_Char)( entry->Tag >> 16 ),
339 (FT_Char)( entry->Tag >> 8 ),
340 (FT_Char)( entry->Tag ),
341 entry->Offset,
342 entry->Length ));
343 }
344
345 FT_FRAME_EXIT();
346
347 FT_TRACE2(( "table directory loaded\n\n" ));
348
349 return error;
350 }
351
352
353 /*************************************************************************/
354 /* */
355 /* <Function> */
356 /* tt_face_load_any */
357 /* */
358 /* <Description> */
359 /* Loads any font table into client memory. */
360 /* */
361 /* <Input> */
362 /* face :: The face object to look for. */
363 /* */
364 /* tag :: The tag of table to load. Use the value 0 if you want */
365 /* to access the whole font file, else set this parameter */
366 /* to a valid TrueType table tag that you can forge with */
367 /* the MAKE_TT_TAG macro. */
368 /* */
369 /* offset :: The starting offset in the table (or the file if */
370 /* tag == 0). */
371 /* */
372 /* length :: The address of the decision variable: */
373 /* */
374 /* If length == NULL: */
375 /* Loads the whole table. Returns an error if */
376 /* `offset' == 0! */
377 /* */
378 /* If *length == 0: */
379 /* Exits immediately; returning the length of the given */
380 /* table or of the font file, depending on the value of */
381 /* `tag'. */
382 /* */
383 /* If *length != 0: */
384 /* Loads the next `length' bytes of table or font, */
385 /* starting at offset `offset' (in table or font too). */
386 /* */
387 /* <Output> */
388 /* buffer :: The address of target buffer. */
389 /* */
390 /* <Return> */
391 /* FreeType error code. 0 means success. */
392 /* */
393 FT_LOCAL_DEF( FT_Error )
394 tt_face_load_any( TT_Face face,
395 FT_ULong tag,
396 FT_Long offset,
397 FT_Byte* buffer,
398 FT_ULong* length )
399 {
400 FT_Error error;
401 FT_Stream stream;
402 TT_Table table;
403 FT_ULong size;
404
405
406 if ( tag != 0 )
407 {
408 /* look for tag in font directory */
409 table = tt_face_lookup_table( face, tag );
410 if ( !table )
411 {
412 error = SFNT_Err_Table_Missing;
413 goto Exit;
414 }
415
416 offset += table->Offset;
417 size = table->Length;
418 }
419 else
420 /* tag == 0 -- the user wants to access the font file directly */
421 size = face->root.stream->size;
422
423 if ( length && *length == 0 )
424 {
425 *length = size;
426
427 return SFNT_Err_Ok;
428 }
429
430 if ( length )
431 size = *length;
432
433 stream = face->root.stream;
434 /* the `if' is syntactic sugar for picky compilers */
435 if ( FT_STREAM_READ_AT( offset, buffer, size ) )
436 goto Exit;
437
438 Exit:
439 return error;
440 }
441
442
443 /*************************************************************************/
444 /* */
445 /* <Function> */
446 /* tt_face_load_generic_header */
447 /* */
448 /* <Description> */
449 /* Loads the TrueType table `head' or `bhed'. */
450 /* */
451 /* <Input> */
452 /* face :: A handle to the target face object. */
453 /* */
454 /* stream :: The input stream. */
455 /* */
456 /* <Return> */
457 /* FreeType error code. 0 means success. */
458 /* */
459 static FT_Error
460 tt_face_load_generic_header( TT_Face face,
461 FT_Stream stream,
462 FT_ULong tag )
463 {
464 FT_Error error;
465 TT_Header* header;
466
467 static const FT_Frame_Field header_fields[] =
468 {
469 #undef FT_STRUCTURE
470 #define FT_STRUCTURE TT_Header
471
472 FT_FRAME_START( 54 ),
473 FT_FRAME_ULONG ( Table_Version ),
474 FT_FRAME_ULONG ( Font_Revision ),
475 FT_FRAME_LONG ( CheckSum_Adjust ),
476 FT_FRAME_LONG ( Magic_Number ),
477 FT_FRAME_USHORT( Flags ),
478 FT_FRAME_USHORT( Units_Per_EM ),
479 FT_FRAME_LONG ( Created[0] ),
480 FT_FRAME_LONG ( Created[1] ),
481 FT_FRAME_LONG ( Modified[0] ),
482 FT_FRAME_LONG ( Modified[1] ),
483 FT_FRAME_SHORT ( xMin ),
484 FT_FRAME_SHORT ( yMin ),
485 FT_FRAME_SHORT ( xMax ),
486 FT_FRAME_SHORT ( yMax ),
487 FT_FRAME_USHORT( Mac_Style ),
488 FT_FRAME_USHORT( Lowest_Rec_PPEM ),
489 FT_FRAME_SHORT ( Font_Direction ),
490 FT_FRAME_SHORT ( Index_To_Loc_Format ),
491 FT_FRAME_SHORT ( Glyph_Data_Format ),
492 FT_FRAME_END
493 };
494
495
496 error = face->goto_table( face, tag, stream, 0 );
497 if ( error )
498 goto Exit;
499
500 header = &face->header;
501
502 if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
503 goto Exit;
504
505 FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
506 FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format ));
507
508 Exit:
509 return error;
510 }
511
512
513 FT_LOCAL_DEF( FT_Error )
514 tt_face_load_head( TT_Face face,
515 FT_Stream stream )
516 {
517 return tt_face_load_generic_header( face, stream, TTAG_head );
518 }
519
520
521 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
522
523 FT_LOCAL_DEF( FT_Error )
524 tt_face_load_bhed( TT_Face face,
525 FT_Stream stream )
526 {
527 return tt_face_load_generic_header( face, stream, TTAG_bhed );
528 }
529
530 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
531
532
533 /*************************************************************************/
534 /* */
535 /* <Function> */
536 /* tt_face_load_max_profile */
537 /* */
538 /* <Description> */
539 /* Loads the maximum profile into a face object. */
540 /* */
541 /* <Input> */
542 /* face :: A handle to the target face object. */
543 /* */
544 /* stream :: The input stream. */
545 /* */
546 /* <Return> */
547 /* FreeType error code. 0 means success. */
548 /* */
549 FT_LOCAL_DEF( FT_Error )
550 tt_face_load_maxp( TT_Face face,
551 FT_Stream stream )
552 {
553 FT_Error error;
554 TT_MaxProfile* maxProfile = &face->max_profile;
555
556 const FT_Frame_Field maxp_fields[] =
557 {
558 #undef FT_STRUCTURE
559 #define FT_STRUCTURE TT_MaxProfile
560
561 FT_FRAME_START( 6 ),
562 FT_FRAME_LONG ( version ),
563 FT_FRAME_USHORT( numGlyphs ),
564 FT_FRAME_END
565 };
566
567 const FT_Frame_Field maxp_fields_extra[] =
568 {
569 FT_FRAME_START( 26 ),
570 FT_FRAME_USHORT( maxPoints ),
571 FT_FRAME_USHORT( maxContours ),
572 FT_FRAME_USHORT( maxCompositePoints ),
573 FT_FRAME_USHORT( maxCompositeContours ),
574 FT_FRAME_USHORT( maxZones ),
575 FT_FRAME_USHORT( maxTwilightPoints ),
576 FT_FRAME_USHORT( maxStorage ),
577 FT_FRAME_USHORT( maxFunctionDefs ),
578 FT_FRAME_USHORT( maxInstructionDefs ),
579 FT_FRAME_USHORT( maxStackElements ),
580 FT_FRAME_USHORT( maxSizeOfInstructions ),
581 FT_FRAME_USHORT( maxComponentElements ),
582 FT_FRAME_USHORT( maxComponentDepth ),
583 FT_FRAME_END
584 };
585
586
587 error = face->goto_table( face, TTAG_maxp, stream, 0 );
588 if ( error )
589 goto Exit;
590
591 if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
592 goto Exit;
593
594 maxProfile->maxPoints = 0;
595 maxProfile->maxContours = 0;
596 maxProfile->maxCompositePoints = 0;
597 maxProfile->maxCompositeContours = 0;
598 maxProfile->maxZones = 0;
599 maxProfile->maxTwilightPoints = 0;
600 maxProfile->maxStorage = 0;
601 maxProfile->maxFunctionDefs = 0;
602 maxProfile->maxInstructionDefs = 0;
603 maxProfile->maxStackElements = 0;
604 maxProfile->maxSizeOfInstructions = 0;
605 maxProfile->maxComponentElements = 0;
606 maxProfile->maxComponentDepth = 0;
607
608 if ( maxProfile->version >= 0x10000L )
609 {
610 if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
611 goto Exit;
612
613 /* XXX: an adjustment that is necessary to load certain */
614 /* broken fonts like `Keystrokes MT' :-( */
615 /* */
616 /* We allocate 64 function entries by default when */
617 /* the maxFunctionDefs field is null. */
618
619 if ( maxProfile->maxFunctionDefs == 0 )
620 maxProfile->maxFunctionDefs = 64;
621 }
622
623 FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
624
625 Exit:
626 return error;
627 }
628
629
630 /*************************************************************************/
631 /* */
632 /* <Function> */
633 /* tt_face_load_names */
634 /* */
635 /* <Description> */
636 /* Loads the name records. */
637 /* */
638 /* <Input> */
639 /* face :: A handle to the target face object. */
640 /* */
641 /* stream :: The input stream. */
642 /* */
643 /* <Return> */
644 /* FreeType error code. 0 means success. */
645 /* */
646 FT_LOCAL_DEF( FT_Error )
647 tt_face_load_name( TT_Face face,
648 FT_Stream stream )
649 {
650 FT_Error error;
651 FT_Memory memory = stream->memory;
652 FT_ULong table_pos, table_len;
653 FT_ULong storage_start, storage_limit;
654 FT_UInt count;
655 TT_NameTable table;
656
657 static const FT_Frame_Field name_table_fields[] =
658 {
659 #undef FT_STRUCTURE
660 #define FT_STRUCTURE TT_NameTableRec
661
662 FT_FRAME_START( 6 ),
663 FT_FRAME_USHORT( format ),
664 FT_FRAME_USHORT( numNameRecords ),
665 FT_FRAME_USHORT( storageOffset ),
666 FT_FRAME_END
667 };
668
669 static const FT_Frame_Field name_record_fields[] =
670 {
671 #undef FT_STRUCTURE
672 #define FT_STRUCTURE TT_NameEntryRec
673
674 /* no FT_FRAME_START */
675 FT_FRAME_USHORT( platformID ),
676 FT_FRAME_USHORT( encodingID ),
677 FT_FRAME_USHORT( languageID ),
678 FT_FRAME_USHORT( nameID ),
679 FT_FRAME_USHORT( stringLength ),
680 FT_FRAME_USHORT( stringOffset ),
681 FT_FRAME_END
682 };
683
684
685 table = &face->name_table;
686 table->stream = stream;
687
688 error = face->goto_table( face, TTAG_name, stream, &table_len );
689 if ( error )
690 goto Exit;
691
692 table_pos = FT_STREAM_POS();
693
694
695 if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
696 goto Exit;
697
698 /* Some popular Asian fonts have an invalid `storageOffset' value */
699 /* (it should be at least "6 + 12*num_names"). However, the string */
700 /* offsets, computed as "storageOffset + entry->stringOffset", are */
701 /* valid pointers within the name table... */
702 /* */
703 /* We thus can't check `storageOffset' right now. */
704 /* */
705 storage_start = table_pos + 6 + 12*table->numNameRecords;
706 storage_limit = table_pos + table_len;
707
708 if ( storage_start > storage_limit )
709 {
710 FT_ERROR(( "invalid `name' table\n" ));
711 error = SFNT_Err_Name_Table_Missing;
712 goto Exit;
713 }
714
715 /* Allocate the array of name records. */
716 count = table->numNameRecords;
717 table->numNameRecords = 0;
718
719 if ( FT_NEW_ARRAY( table->names, count ) ||
720 FT_FRAME_ENTER( count * 12 ) )
721 goto Exit;
722
723 /* Load the name records and determine how much storage is needed */
724 /* to hold the strings themselves. */
725 {
726 TT_NameEntryRec* entry = table->names;
727
728
729 for ( ; count > 0; count-- )
730 {
731 if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
732 continue;
733
734 /* check that the name is not empty */
735 if ( entry->stringLength == 0 )
736 continue;
737
738 /* check that the name string is within the table */
739 entry->stringOffset += table_pos + table->storageOffset;
740 if ( entry->stringOffset < storage_start ||
741 entry->stringOffset + entry->stringLength > storage_limit )
742 {
743 /* invalid entry - ignore it */
744 entry->stringOffset = 0;
745 entry->stringLength = 0;
746 continue;
747 }
748
749 entry++;
750 }
751
752 table->numNameRecords = (FT_UInt)( entry - table->names );
753 }
754
755 FT_FRAME_EXIT();
756
757 /* everything went well, update face->num_names */
758 face->num_names = (FT_UShort) table->numNameRecords;
759
760 Exit:
761 return error;
762 }
763
764
765 /*************************************************************************/
766 /* */
767 /* <Function> */
768 /* tt_face_free_names */
769 /* */
770 /* <Description> */
771 /* Frees the name records. */
772 /* */
773 /* <Input> */
774 /* face :: A handle to the target face object. */
775 /* */
776 FT_LOCAL_DEF( void )
777 tt_face_free_name( TT_Face face )
778 {
779 FT_Memory memory = face->root.driver->root.memory;
780 TT_NameTable table = &face->name_table;
781 TT_NameEntry entry = table->names;
782 FT_UInt count = table->numNameRecords;
783
784
785 if ( table->names )
786 {
787 for ( ; count > 0; count--, entry++ )
788 {
789 FT_FREE( entry->string );
790 entry->stringLength = 0;
791 }
792
793 /* free strings table */
794 FT_FREE( table->names );
795 }
796
797 table->numNameRecords = 0;
798 table->format = 0;
799 table->storageOffset = 0;
800 }
801
802
803 /*************************************************************************/
804 /* */
805 /* <Function> */
806 /* tt_face_load_cmap */
807 /* */
808 /* <Description> */
809 /* Loads the cmap directory in a face object. The cmaps themselves */
810 /* are loaded on demand in the `ttcmap.c' module. */
811 /* */
812 /* <Input> */
813 /* face :: A handle to the target face object. */
814 /* */
815 /* stream :: A handle to the input stream. */
816 /* */
817 /* <Return> */
818 /* FreeType error code. 0 means success. */
819 /* */
820
821 FT_LOCAL_DEF( FT_Error )
822 tt_face_load_cmap( TT_Face face,
823 FT_Stream stream )
824 {
825 FT_Error error;
826
827
828 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
829 if ( error )
830 goto Exit;
831
832 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
833 face->cmap_size = 0;
834
835 Exit:
836 return error;
837 }
838
839
840
841 /*************************************************************************/
842 /* */
843 /* <Function> */
844 /* tt_face_load_os2 */
845 /* */
846 /* <Description> */
847 /* Loads the OS2 table. */
848 /* */
849 /* <Input> */
850 /* face :: A handle to the target face object. */
851 /* */
852 /* stream :: A handle to the input stream. */
853 /* */
854 /* <Return> */
855 /* FreeType error code. 0 means success. */
856 /* */
857 FT_LOCAL_DEF( FT_Error )
858 tt_face_load_os2( TT_Face face,
859 FT_Stream stream )
860 {
861 FT_Error error;
862 TT_OS2* os2;
863
864 const FT_Frame_Field os2_fields[] =
865 {
866 #undef FT_STRUCTURE
867 #define FT_STRUCTURE TT_OS2
868
869 FT_FRAME_START( 78 ),
870 FT_FRAME_USHORT( version ),
871 FT_FRAME_SHORT ( xAvgCharWidth ),
872 FT_FRAME_USHORT( usWeightClass ),
873 FT_FRAME_USHORT( usWidthClass ),
874 FT_FRAME_SHORT ( fsType ),
875 FT_FRAME_SHORT ( ySubscriptXSize ),
876 FT_FRAME_SHORT ( ySubscriptYSize ),
877 FT_FRAME_SHORT ( ySubscriptXOffset ),
878 FT_FRAME_SHORT ( ySubscriptYOffset ),
879 FT_FRAME_SHORT ( ySuperscriptXSize ),
880 FT_FRAME_SHORT ( ySuperscriptYSize ),
881 FT_FRAME_SHORT ( ySuperscriptXOffset ),
882 FT_FRAME_SHORT ( ySuperscriptYOffset ),
883 FT_FRAME_SHORT ( yStrikeoutSize ),
884 FT_FRAME_SHORT ( yStrikeoutPosition ),
885 FT_FRAME_SHORT ( sFamilyClass ),
886 FT_FRAME_BYTE ( panose[0] ),
887 FT_FRAME_BYTE ( panose[1] ),
888 FT_FRAME_BYTE ( panose[2] ),
889 FT_FRAME_BYTE ( panose[3] ),
890 FT_FRAME_BYTE ( panose[4] ),
891 FT_FRAME_BYTE ( panose[5] ),
892 FT_FRAME_BYTE ( panose[6] ),
893 FT_FRAME_BYTE ( panose[7] ),
894 FT_FRAME_BYTE ( panose[8] ),
895 FT_FRAME_BYTE ( panose[9] ),
896 FT_FRAME_ULONG ( ulUnicodeRange1 ),
897 FT_FRAME_ULONG ( ulUnicodeRange2 ),
898 FT_FRAME_ULONG ( ulUnicodeRange3 ),
899 FT_FRAME_ULONG ( ulUnicodeRange4 ),
900 FT_FRAME_BYTE ( achVendID[0] ),
901 FT_FRAME_BYTE ( achVendID[1] ),
902 FT_FRAME_BYTE ( achVendID[2] ),
903 FT_FRAME_BYTE ( achVendID[3] ),
904
905 FT_FRAME_USHORT( fsSelection ),
906 FT_FRAME_USHORT( usFirstCharIndex ),
907 FT_FRAME_USHORT( usLastCharIndex ),
908 FT_FRAME_SHORT ( sTypoAscender ),
909 FT_FRAME_SHORT ( sTypoDescender ),
910 FT_FRAME_SHORT ( sTypoLineGap ),
911 FT_FRAME_USHORT( usWinAscent ),
912 FT_FRAME_USHORT( usWinDescent ),
913 FT_FRAME_END
914 };
915
916 const FT_Frame_Field os2_fields_extra[] =
917 {
918 FT_FRAME_START( 8 ),
919 FT_FRAME_ULONG( ulCodePageRange1 ),
920 FT_FRAME_ULONG( ulCodePageRange2 ),
921 FT_FRAME_END
922 };
923
924 const FT_Frame_Field os2_fields_extra2[] =
925 {
926 FT_FRAME_START( 10 ),
927 FT_FRAME_SHORT ( sxHeight ),
928 FT_FRAME_SHORT ( sCapHeight ),
929 FT_FRAME_USHORT( usDefaultChar ),
930 FT_FRAME_USHORT( usBreakChar ),
931 FT_FRAME_USHORT( usMaxContext ),
932 FT_FRAME_END
933 };
934
935
936 /* We now support old Mac fonts where the OS/2 table doesn't */
937 /* exist. Simply put, we set the `version' field to 0xFFFF */
938 /* and test this value each time we need to access the table. */
939 error = face->goto_table( face, TTAG_OS2, stream, 0 );
940 if ( error )
941 goto Exit;
942
943 os2 = &face->os2;
944
945 if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
946 goto Exit;
947
948 os2->ulCodePageRange1 = 0;
949 os2->ulCodePageRange2 = 0;
950 os2->sxHeight = 0;
951 os2->sCapHeight = 0;
952 os2->usDefaultChar = 0;
953 os2->usBreakChar = 0;
954 os2->usMaxContext = 0;
955
956 if ( os2->version >= 0x0001 )
957 {
958 /* only version 1 tables */
959 if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
960 goto Exit;
961
962 if ( os2->version >= 0x0002 )
963 {
964 /* only version 2 tables */
965 if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
966 goto Exit;
967 }
968 }
969
970 FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender ));
971 FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender ));
972 FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent ));
973 FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent ));
974 FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection ));
975
976 Exit:
977 return error;
978 }
979
980
981 /*************************************************************************/
982 /* */
983 /* <Function> */
984 /* tt_face_load_postscript */
985 /* */
986 /* <Description> */
987 /* Loads the Postscript table. */
988 /* */
989 /* <Input> */
990 /* face :: A handle to the target face object. */
991 /* */
992 /* stream :: A handle to the input stream. */
993 /* */
994 /* <Return> */
995 /* FreeType error code. 0 means success. */
996 /* */
997 FT_LOCAL_DEF( FT_Error )
998 tt_face_load_post( TT_Face face,
999 FT_Stream stream )
1000 {
1001 FT_Error error;
1002 TT_Postscript* post = &face->postscript;
1003
1004 static const FT_Frame_Field post_fields[] =
1005 {
1006 #undef FT_STRUCTURE
1007 #define FT_STRUCTURE TT_Postscript
1008
1009 FT_FRAME_START( 32 ),
1010 FT_FRAME_ULONG( FormatType ),
1011 FT_FRAME_ULONG( italicAngle ),
1012 FT_FRAME_SHORT( underlinePosition ),
1013 FT_FRAME_SHORT( underlineThickness ),
1014 FT_FRAME_ULONG( isFixedPitch ),
1015 FT_FRAME_ULONG( minMemType42 ),
1016 FT_FRAME_ULONG( maxMemType42 ),
1017 FT_FRAME_ULONG( minMemType1 ),
1018 FT_FRAME_ULONG( maxMemType1 ),
1019 FT_FRAME_END
1020 };
1021
1022
1023 error = face->goto_table( face, TTAG_post, stream, 0 );
1024 if ( error )
1025 return error;
1026
1027 if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
1028 return error;
1029
1030 /* we don't load the glyph names, we do that in another */
1031 /* module (ttpost). */
1032
1033 FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType ));
1034 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch
1035 ? " yes" : " no" ));
1036
1037 return SFNT_Err_Ok;
1038 }
1039
1040
1041 /*************************************************************************/
1042 /* */
1043 /* <Function> */
1044 /* tt_face_load_pclt */
1045 /* */
1046 /* <Description> */
1047 /* Loads the PCL 5 Table. */
1048 /* */
1049 /* <Input> */
1050 /* face :: A handle to the target face object. */
1051 /* */
1052 /* stream :: A handle to the input stream. */
1053 /* */
1054 /* <Return> */
1055 /* FreeType error code. 0 means success. */
1056 /* */
1057 FT_LOCAL_DEF( FT_Error )
1058 tt_face_load_pclt( TT_Face face,
1059 FT_Stream stream )
1060 {
1061 static const FT_Frame_Field pclt_fields[] =
1062 {
1063 #undef FT_STRUCTURE
1064 #define FT_STRUCTURE TT_PCLT
1065
1066 FT_FRAME_START( 54 ),
1067 FT_FRAME_ULONG ( Version ),
1068 FT_FRAME_ULONG ( FontNumber ),
1069 FT_FRAME_USHORT( Pitch ),
1070 FT_FRAME_USHORT( xHeight ),
1071 FT_FRAME_USHORT( Style ),
1072 FT_FRAME_USHORT( TypeFamily ),
1073 FT_FRAME_USHORT( CapHeight ),
1074 FT_FRAME_BYTES ( TypeFace, 16 ),
1075 FT_FRAME_BYTES ( CharacterComplement, 8 ),
1076 FT_FRAME_BYTES ( FileName, 6 ),
1077 FT_FRAME_CHAR ( StrokeWeight ),
1078 FT_FRAME_CHAR ( WidthType ),
1079 FT_FRAME_BYTE ( SerifStyle ),
1080 FT_FRAME_BYTE ( Reserved ),
1081 FT_FRAME_END
1082 };
1083
1084 FT_Error error;
1085 TT_PCLT* pclt = &face->pclt;
1086
1087
1088 /* optional table */
1089 error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1090 if ( error )
1091 goto Exit;
1092
1093 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
1094 goto Exit;
1095
1096 Exit:
1097 return error;
1098 }
1099
1100
1101 /*************************************************************************/
1102 /* */
1103 /* <Function> */
1104 /* tt_face_load_gasp */
1105 /* */
1106 /* <Description> */
1107 /* Loads the `gasp' table into a face object. */
1108 /* */
1109 /* <Input> */
1110 /* face :: A handle to the target face object. */
1111 /* */
1112 /* stream :: The input stream. */
1113 /* */
1114 /* <Return> */
1115 /* FreeType error code. 0 means success. */
1116 /* */
1117 FT_LOCAL_DEF( FT_Error )
1118 tt_face_load_gasp( TT_Face face,
1119 FT_Stream stream )
1120 {
1121 FT_Error error;
1122 FT_Memory memory = stream->memory;
1123
1124 FT_UInt j,num_ranges;
1125 TT_GaspRange gaspranges;
1126
1127
1128 /* the gasp table is optional */
1129 error = face->goto_table( face, TTAG_gasp, stream, 0 );
1130 if ( error )
1131 goto Exit;
1132
1133 if ( FT_FRAME_ENTER( 4L ) )
1134 goto Exit;
1135
1136 face->gasp.version = FT_GET_USHORT();
1137 face->gasp.numRanges = FT_GET_USHORT();
1138
1139 FT_FRAME_EXIT();
1140
1141 /* only support versions 0 and 1 of the table */
1142 if ( face->gasp.version >= 2 )
1143 {
1144 face->gasp.numRanges = 0;
1145 error = SFNT_Err_Invalid_Table;
1146 goto Exit;
1147 }
1148
1149 num_ranges = face->gasp.numRanges;
1150 FT_TRACE3(( "numRanges: %u\n", num_ranges ));
1151
1152 if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
1153 FT_FRAME_ENTER( num_ranges * 4L ) )
1154 goto Exit;
1155
1156 face->gasp.gaspRanges = gaspranges;
1157
1158 for ( j = 0; j < num_ranges; j++ )
1159 {
1160 gaspranges[j].maxPPEM = FT_GET_USHORT();
1161 gaspranges[j].gaspFlag = FT_GET_USHORT();
1162
1163 FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
1164 j,
1165 gaspranges[j].maxPPEM,
1166 gaspranges[j].gaspFlag ));
1167 }
1168
1169 FT_FRAME_EXIT();
1170
1171 Exit:
1172 return error;
1173 }
1174
1175
1176 /* END */