1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ttload.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* Load the basic TrueType tables, i.e., tables that can be either in */ 6*37da2899SCharles.Forsyth /* TTF or OTF fonts (body). */ 7*37da2899SCharles.Forsyth /* */ 8*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 9*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 10*37da2899SCharles.Forsyth /* */ 11*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 12*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 13*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 14*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 15*37da2899SCharles.Forsyth /* understand and accept it fully. */ 16*37da2899SCharles.Forsyth /* */ 17*37da2899SCharles.Forsyth /***************************************************************************/ 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsyth #include <ft2build.h> 21*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 23*37da2899SCharles.Forsyth #include FT_TRUETYPE_TAGS_H 24*37da2899SCharles.Forsyth #include "ttload.h" 25*37da2899SCharles.Forsyth #include "ttcmap.h" 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth #include "sferrors.h" 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth /*************************************************************************/ 31*37da2899SCharles.Forsyth /* */ 32*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 33*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 34*37da2899SCharles.Forsyth /* messages during execution. */ 35*37da2899SCharles.Forsyth /* */ 36*37da2899SCharles.Forsyth #undef FT_COMPONENT 37*37da2899SCharles.Forsyth #define FT_COMPONENT trace_ttload 38*37da2899SCharles.Forsyth 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth /*************************************************************************/ 41*37da2899SCharles.Forsyth /* */ 42*37da2899SCharles.Forsyth /* <Function> */ 43*37da2899SCharles.Forsyth /* tt_face_lookup_table */ 44*37da2899SCharles.Forsyth /* */ 45*37da2899SCharles.Forsyth /* <Description> */ 46*37da2899SCharles.Forsyth /* Looks for a TrueType table by name. */ 47*37da2899SCharles.Forsyth /* */ 48*37da2899SCharles.Forsyth /* <Input> */ 49*37da2899SCharles.Forsyth /* face :: A face object handle. */ 50*37da2899SCharles.Forsyth /* */ 51*37da2899SCharles.Forsyth /* tag :: The searched tag. */ 52*37da2899SCharles.Forsyth /* */ 53*37da2899SCharles.Forsyth /* <Return> */ 54*37da2899SCharles.Forsyth /* A pointer to the table directory entry. 0 if not found. */ 55*37da2899SCharles.Forsyth /* */ 56*37da2899SCharles.Forsyth FT_LOCAL_DEF( TT_Table ) tt_face_lookup_table(TT_Face face,FT_ULong tag)57*37da2899SCharles.Forsyth tt_face_lookup_table( TT_Face face, 58*37da2899SCharles.Forsyth FT_ULong tag ) 59*37da2899SCharles.Forsyth { 60*37da2899SCharles.Forsyth TT_Table entry; 61*37da2899SCharles.Forsyth TT_Table limit; 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", 65*37da2899SCharles.Forsyth face, 66*37da2899SCharles.Forsyth (FT_Char)( tag >> 24 ), 67*37da2899SCharles.Forsyth (FT_Char)( tag >> 16 ), 68*37da2899SCharles.Forsyth (FT_Char)( tag >> 8 ), 69*37da2899SCharles.Forsyth (FT_Char)( tag ) )); 70*37da2899SCharles.Forsyth 71*37da2899SCharles.Forsyth entry = face->dir_tables; 72*37da2899SCharles.Forsyth limit = entry + face->num_tables; 73*37da2899SCharles.Forsyth 74*37da2899SCharles.Forsyth for ( ; entry < limit; entry++ ) 75*37da2899SCharles.Forsyth { 76*37da2899SCharles.Forsyth /* For compatibility with Windows, we consider 0-length */ 77*37da2899SCharles.Forsyth /* tables the same as missing tables. */ 78*37da2899SCharles.Forsyth if ( entry->Tag == tag && entry->Length != 0 ) 79*37da2899SCharles.Forsyth { 80*37da2899SCharles.Forsyth FT_TRACE3(( "found table.\n" )); 81*37da2899SCharles.Forsyth return entry; 82*37da2899SCharles.Forsyth } 83*37da2899SCharles.Forsyth } 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth FT_TRACE3(( "could not find table!\n" )); 86*37da2899SCharles.Forsyth return 0; 87*37da2899SCharles.Forsyth } 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth /*************************************************************************/ 91*37da2899SCharles.Forsyth /* */ 92*37da2899SCharles.Forsyth /* <Function> */ 93*37da2899SCharles.Forsyth /* tt_face_goto_table */ 94*37da2899SCharles.Forsyth /* */ 95*37da2899SCharles.Forsyth /* <Description> */ 96*37da2899SCharles.Forsyth /* Looks for a TrueType table by name, then seek a stream to it. */ 97*37da2899SCharles.Forsyth /* */ 98*37da2899SCharles.Forsyth /* <Input> */ 99*37da2899SCharles.Forsyth /* face :: A face object handle. */ 100*37da2899SCharles.Forsyth /* */ 101*37da2899SCharles.Forsyth /* tag :: The searched tag. */ 102*37da2899SCharles.Forsyth /* */ 103*37da2899SCharles.Forsyth /* stream :: The stream to seek when the table is found. */ 104*37da2899SCharles.Forsyth /* */ 105*37da2899SCharles.Forsyth /* <Output> */ 106*37da2899SCharles.Forsyth /* length :: The length of the table if found, undefined otherwise. */ 107*37da2899SCharles.Forsyth /* */ 108*37da2899SCharles.Forsyth /* <Return> */ 109*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 110*37da2899SCharles.Forsyth /* */ 111*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_goto_table(TT_Face face,FT_ULong tag,FT_Stream stream,FT_ULong * length)112*37da2899SCharles.Forsyth tt_face_goto_table( TT_Face face, 113*37da2899SCharles.Forsyth FT_ULong tag, 114*37da2899SCharles.Forsyth FT_Stream stream, 115*37da2899SCharles.Forsyth FT_ULong* length ) 116*37da2899SCharles.Forsyth { 117*37da2899SCharles.Forsyth TT_Table table; 118*37da2899SCharles.Forsyth FT_Error error; 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth 121*37da2899SCharles.Forsyth table = tt_face_lookup_table( face, tag ); 122*37da2899SCharles.Forsyth if ( table ) 123*37da2899SCharles.Forsyth { 124*37da2899SCharles.Forsyth if ( length ) 125*37da2899SCharles.Forsyth *length = table->Length; 126*37da2899SCharles.Forsyth 127*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( table->Offset ) ) 128*37da2899SCharles.Forsyth goto Exit; 129*37da2899SCharles.Forsyth } 130*37da2899SCharles.Forsyth else 131*37da2899SCharles.Forsyth error = SFNT_Err_Table_Missing; 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsyth Exit: 134*37da2899SCharles.Forsyth return error; 135*37da2899SCharles.Forsyth } 136*37da2899SCharles.Forsyth 137*37da2899SCharles.Forsyth 138*37da2899SCharles.Forsyth /* In theory, we should check the values of `search_range', */ 139*37da2899SCharles.Forsyth /* `entry_selector', and `range_shift' to detect non-SFNT based files */ 140*37da2899SCharles.Forsyth /* whose header might also start with 0x100000L (yes, these exist). */ 141*37da2899SCharles.Forsyth /* */ 142*37da2899SCharles.Forsyth /* Very unfortunately, many TrueType fonts don't have these fields */ 143*37da2899SCharles.Forsyth /* set correctly and we must ignore them to support them. An alternative */ 144*37da2899SCharles.Forsyth /* way to check the font file is thus to: */ 145*37da2899SCharles.Forsyth /* */ 146*37da2899SCharles.Forsyth /* - check that `num_tables' is valid */ 147*37da2899SCharles.Forsyth /* - look for a "head" table, check its size, and parse it to */ 148*37da2899SCharles.Forsyth /* see if its "magic" field is correctly set */ 149*37da2899SCharles.Forsyth /* */ 150*37da2899SCharles.Forsyth /* When checking directory entries, ignore the tables `glyx' and `locx' */ 151*37da2899SCharles.Forsyth /* which are hacked-out versions of `glyf' and `loca' in some PostScript */ 152*37da2899SCharles.Forsyth /* Type 42 fonts, and will generally be invalid. */ 153*37da2899SCharles.Forsyth /* */ 154*37da2899SCharles.Forsyth static FT_Error sfnt_dir_check(FT_Stream stream,FT_ULong offset,FT_UInt num_tables)155*37da2899SCharles.Forsyth sfnt_dir_check( FT_Stream stream, 156*37da2899SCharles.Forsyth FT_ULong offset, 157*37da2899SCharles.Forsyth FT_UInt num_tables ) 158*37da2899SCharles.Forsyth { 159*37da2899SCharles.Forsyth FT_Error error; 160*37da2899SCharles.Forsyth FT_UInt nn, has_head = 0; 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); 163*37da2899SCharles.Forsyth const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth static const FT_Frame_Field sfnt_dir_entry_fields[] = 166*37da2899SCharles.Forsyth { 167*37da2899SCharles.Forsyth #undef FT_STRUCTURE 168*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_TableRec 169*37da2899SCharles.Forsyth 170*37da2899SCharles.Forsyth FT_FRAME_START( 16 ), 171*37da2899SCharles.Forsyth FT_FRAME_ULONG( Tag ), 172*37da2899SCharles.Forsyth FT_FRAME_ULONG( CheckSum ), 173*37da2899SCharles.Forsyth FT_FRAME_ULONG( Offset ), 174*37da2899SCharles.Forsyth FT_FRAME_ULONG( Length ), 175*37da2899SCharles.Forsyth FT_FRAME_END 176*37da2899SCharles.Forsyth }; 177*37da2899SCharles.Forsyth 178*37da2899SCharles.Forsyth 179*37da2899SCharles.Forsyth /* if 'num_tables' is 0, read the table count from the file */ 180*37da2899SCharles.Forsyth if ( num_tables == 0 ) 181*37da2899SCharles.Forsyth { 182*37da2899SCharles.Forsyth FT_ULong format_tag; 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( offset ) || 186*37da2899SCharles.Forsyth FT_READ_ULONG ( format_tag ) || 187*37da2899SCharles.Forsyth FT_READ_USHORT( num_tables ) || 188*37da2899SCharles.Forsyth FT_STREAM_SKIP( 6 ) ) 189*37da2899SCharles.Forsyth goto Bad_Format; 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth if ( offset + 12 + num_tables*16 > stream->size ) 192*37da2899SCharles.Forsyth goto Bad_Format; 193*37da2899SCharles.Forsyth } 194*37da2899SCharles.Forsyth else if ( FT_STREAM_SEEK( offset + 12 ) ) 195*37da2899SCharles.Forsyth goto Bad_Format; 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth for ( nn = 0; nn < num_tables; nn++ ) 198*37da2899SCharles.Forsyth { 199*37da2899SCharles.Forsyth TT_TableRec table; 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) ) 203*37da2899SCharles.Forsyth goto Bad_Format; 204*37da2899SCharles.Forsyth 205*37da2899SCharles.Forsyth if ( table.Offset + table.Length > stream->size && 206*37da2899SCharles.Forsyth table.Tag != glyx_tag && table.Tag != locx_tag ) 207*37da2899SCharles.Forsyth goto Bad_Format; 208*37da2899SCharles.Forsyth 209*37da2899SCharles.Forsyth if ( table.Tag == TTAG_head ) 210*37da2899SCharles.Forsyth { 211*37da2899SCharles.Forsyth FT_UInt32 magic; 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth has_head = 1; 215*37da2899SCharles.Forsyth 216*37da2899SCharles.Forsyth if ( table.Length != 0x36 || 217*37da2899SCharles.Forsyth FT_STREAM_SEEK( table.Offset + 12 ) || 218*37da2899SCharles.Forsyth FT_READ_ULONG( magic ) || 219*37da2899SCharles.Forsyth magic != 0x5F0F3CF5UL ) 220*37da2899SCharles.Forsyth goto Bad_Format; 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) ) 223*37da2899SCharles.Forsyth goto Bad_Format; 224*37da2899SCharles.Forsyth } 225*37da2899SCharles.Forsyth } 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth if ( has_head == 0 ) 228*37da2899SCharles.Forsyth goto Bad_Format; 229*37da2899SCharles.Forsyth 230*37da2899SCharles.Forsyth Exit: 231*37da2899SCharles.Forsyth return error; 232*37da2899SCharles.Forsyth 233*37da2899SCharles.Forsyth Bad_Format: 234*37da2899SCharles.Forsyth error = FT_Err_Unknown_File_Format; 235*37da2899SCharles.Forsyth goto Exit; 236*37da2899SCharles.Forsyth } 237*37da2899SCharles.Forsyth 238*37da2899SCharles.Forsyth 239*37da2899SCharles.Forsyth /*************************************************************************/ 240*37da2899SCharles.Forsyth /* */ 241*37da2899SCharles.Forsyth /* <Function> */ 242*37da2899SCharles.Forsyth /* tt_face_load_sfnt_header */ 243*37da2899SCharles.Forsyth /* */ 244*37da2899SCharles.Forsyth /* <Description> */ 245*37da2899SCharles.Forsyth /* Loads the header of a SFNT font file. Supports collections. */ 246*37da2899SCharles.Forsyth /* */ 247*37da2899SCharles.Forsyth /* <Input> */ 248*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 249*37da2899SCharles.Forsyth /* */ 250*37da2899SCharles.Forsyth /* stream :: The input stream. */ 251*37da2899SCharles.Forsyth /* */ 252*37da2899SCharles.Forsyth /* face_index :: If the font is a collection, the number of the font */ 253*37da2899SCharles.Forsyth /* in the collection, ignored otherwise. */ 254*37da2899SCharles.Forsyth /* */ 255*37da2899SCharles.Forsyth /* <Output> */ 256*37da2899SCharles.Forsyth /* sfnt :: The SFNT header. */ 257*37da2899SCharles.Forsyth /* */ 258*37da2899SCharles.Forsyth /* <Return> */ 259*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 260*37da2899SCharles.Forsyth /* */ 261*37da2899SCharles.Forsyth /* <Note> */ 262*37da2899SCharles.Forsyth /* The stream cursor must be at the font file's origin. */ 263*37da2899SCharles.Forsyth /* */ 264*37da2899SCharles.Forsyth /* This function recognizes fonts embedded in a `TrueType collection' */ 265*37da2899SCharles.Forsyth /* */ 266*37da2899SCharles.Forsyth /* The header will be checked whether it is valid by looking at the */ 267*37da2899SCharles.Forsyth /* values of `search_range', `entry_selector', and `range_shift'. */ 268*37da2899SCharles.Forsyth /* */ 269*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_sfnt_header(TT_Face face,FT_Stream stream,FT_Long face_index,SFNT_Header sfnt)270*37da2899SCharles.Forsyth tt_face_load_sfnt_header( TT_Face face, 271*37da2899SCharles.Forsyth FT_Stream stream, 272*37da2899SCharles.Forsyth FT_Long face_index, 273*37da2899SCharles.Forsyth SFNT_Header sfnt ) 274*37da2899SCharles.Forsyth { 275*37da2899SCharles.Forsyth FT_Error error; 276*37da2899SCharles.Forsyth FT_ULong format_tag, offset; 277*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 278*37da2899SCharles.Forsyth 279*37da2899SCharles.Forsyth static const FT_Frame_Field sfnt_header_fields[] = 280*37da2899SCharles.Forsyth { 281*37da2899SCharles.Forsyth #undef FT_STRUCTURE 282*37da2899SCharles.Forsyth #define FT_STRUCTURE SFNT_HeaderRec 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsyth FT_FRAME_START( 8 ), 285*37da2899SCharles.Forsyth FT_FRAME_USHORT( num_tables ), 286*37da2899SCharles.Forsyth FT_FRAME_USHORT( search_range ), 287*37da2899SCharles.Forsyth FT_FRAME_USHORT( entry_selector ), 288*37da2899SCharles.Forsyth FT_FRAME_USHORT( range_shift ), 289*37da2899SCharles.Forsyth FT_FRAME_END 290*37da2899SCharles.Forsyth }; 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth static const FT_Frame_Field ttc_header_fields[] = 293*37da2899SCharles.Forsyth { 294*37da2899SCharles.Forsyth #undef FT_STRUCTURE 295*37da2899SCharles.Forsyth #define FT_STRUCTURE TTC_HeaderRec 296*37da2899SCharles.Forsyth 297*37da2899SCharles.Forsyth FT_FRAME_START( 8 ), 298*37da2899SCharles.Forsyth FT_FRAME_LONG( version ), 299*37da2899SCharles.Forsyth FT_FRAME_LONG( count ), 300*37da2899SCharles.Forsyth FT_FRAME_END 301*37da2899SCharles.Forsyth }; 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth 304*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n", 305*37da2899SCharles.Forsyth face, face_index )); 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth face->ttc_header.tag = 0; 308*37da2899SCharles.Forsyth face->ttc_header.version = 0; 309*37da2899SCharles.Forsyth face->ttc_header.count = 0; 310*37da2899SCharles.Forsyth 311*37da2899SCharles.Forsyth face->num_tables = 0; 312*37da2899SCharles.Forsyth 313*37da2899SCharles.Forsyth /* first of all, read the first 4 bytes. If it is `ttcf', then the */ 314*37da2899SCharles.Forsyth /* file is a TrueType collection, otherwise it can be any other */ 315*37da2899SCharles.Forsyth /* kind of font. */ 316*37da2899SCharles.Forsyth /* */ 317*37da2899SCharles.Forsyth offset = FT_STREAM_POS(); 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth if ( FT_READ_ULONG( format_tag ) ) 320*37da2899SCharles.Forsyth goto Exit; 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsyth if ( format_tag == TTAG_ttcf ) 323*37da2899SCharles.Forsyth { 324*37da2899SCharles.Forsyth FT_Int n; 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" )); 328*37da2899SCharles.Forsyth 329*37da2899SCharles.Forsyth /* It is a TrueType collection, i.e. a file containing several */ 330*37da2899SCharles.Forsyth /* font files. Read the font directory now */ 331*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) 332*37da2899SCharles.Forsyth goto Exit; 333*37da2899SCharles.Forsyth 334*37da2899SCharles.Forsyth /* now read the offsets of each font in the file */ 335*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) || 336*37da2899SCharles.Forsyth FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) 337*37da2899SCharles.Forsyth goto Exit; 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsyth for ( n = 0; n < face->ttc_header.count; n++ ) 340*37da2899SCharles.Forsyth face->ttc_header.offsets[n] = FT_GET_ULONG(); 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 343*37da2899SCharles.Forsyth 344*37da2899SCharles.Forsyth /* check face index */ 345*37da2899SCharles.Forsyth if ( face_index >= face->ttc_header.count ) 346*37da2899SCharles.Forsyth { 347*37da2899SCharles.Forsyth error = SFNT_Err_Bad_Argument; 348*37da2899SCharles.Forsyth goto Exit; 349*37da2899SCharles.Forsyth } 350*37da2899SCharles.Forsyth 351*37da2899SCharles.Forsyth /* seek to the appropriate TrueType file, then read tag */ 352*37da2899SCharles.Forsyth offset = face->ttc_header.offsets[face_index]; 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( offset ) || 355*37da2899SCharles.Forsyth FT_READ_LONG( format_tag ) ) 356*37da2899SCharles.Forsyth goto Exit; 357*37da2899SCharles.Forsyth } 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth /* the format tag was read, now check the rest of the header */ 360*37da2899SCharles.Forsyth sfnt->format_tag = format_tag; 361*37da2899SCharles.Forsyth sfnt->offset = offset; 362*37da2899SCharles.Forsyth 363*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) ) 364*37da2899SCharles.Forsyth goto Exit; 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth /* now check the sfnt directory */ 367*37da2899SCharles.Forsyth error = sfnt_dir_check( stream, offset, sfnt->num_tables ); 368*37da2899SCharles.Forsyth if ( error ) 369*37da2899SCharles.Forsyth { 370*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" )); 371*37da2899SCharles.Forsyth error = SFNT_Err_Unknown_File_Format; 372*37da2899SCharles.Forsyth } 373*37da2899SCharles.Forsyth 374*37da2899SCharles.Forsyth Exit: 375*37da2899SCharles.Forsyth return error; 376*37da2899SCharles.Forsyth } 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth 379*37da2899SCharles.Forsyth /*************************************************************************/ 380*37da2899SCharles.Forsyth /* */ 381*37da2899SCharles.Forsyth /* <Function> */ 382*37da2899SCharles.Forsyth /* tt_face_load_directory */ 383*37da2899SCharles.Forsyth /* */ 384*37da2899SCharles.Forsyth /* <Description> */ 385*37da2899SCharles.Forsyth /* Loads the table directory into a face object. */ 386*37da2899SCharles.Forsyth /* */ 387*37da2899SCharles.Forsyth /* <InOut> */ 388*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 389*37da2899SCharles.Forsyth /* */ 390*37da2899SCharles.Forsyth /* <Input> */ 391*37da2899SCharles.Forsyth /* stream :: The input stream. */ 392*37da2899SCharles.Forsyth /* */ 393*37da2899SCharles.Forsyth /* sfnt :: The SFNT directory header. */ 394*37da2899SCharles.Forsyth /* */ 395*37da2899SCharles.Forsyth /* <Return> */ 396*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 397*37da2899SCharles.Forsyth /* */ 398*37da2899SCharles.Forsyth /* <Note> */ 399*37da2899SCharles.Forsyth /* The stream cursor must be at the font file's origin. */ 400*37da2899SCharles.Forsyth /* */ 401*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_directory(TT_Face face,FT_Stream stream,SFNT_Header sfnt)402*37da2899SCharles.Forsyth tt_face_load_directory( TT_Face face, 403*37da2899SCharles.Forsyth FT_Stream stream, 404*37da2899SCharles.Forsyth SFNT_Header sfnt ) 405*37da2899SCharles.Forsyth { 406*37da2899SCharles.Forsyth FT_Error error; 407*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 408*37da2899SCharles.Forsyth 409*37da2899SCharles.Forsyth TT_TableRec *entry, *limit; 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_directory: %08p\n", face )); 413*37da2899SCharles.Forsyth 414*37da2899SCharles.Forsyth FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables )); 415*37da2899SCharles.Forsyth FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag )); 416*37da2899SCharles.Forsyth 417*37da2899SCharles.Forsyth face->num_tables = sfnt->num_tables; 418*37da2899SCharles.Forsyth 419*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) ) 420*37da2899SCharles.Forsyth goto Exit; 421*37da2899SCharles.Forsyth 422*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( sfnt->offset + 12 ) || 423*37da2899SCharles.Forsyth FT_FRAME_ENTER( face->num_tables * 16L ) ) 424*37da2899SCharles.Forsyth goto Exit; 425*37da2899SCharles.Forsyth 426*37da2899SCharles.Forsyth entry = face->dir_tables; 427*37da2899SCharles.Forsyth limit = entry + face->num_tables; 428*37da2899SCharles.Forsyth 429*37da2899SCharles.Forsyth for ( ; entry < limit; entry++ ) 430*37da2899SCharles.Forsyth { /* loop through the tables and get all entries */ 431*37da2899SCharles.Forsyth entry->Tag = FT_GET_TAG4(); 432*37da2899SCharles.Forsyth entry->CheckSum = FT_GET_ULONG(); 433*37da2899SCharles.Forsyth entry->Offset = FT_GET_LONG(); 434*37da2899SCharles.Forsyth entry->Length = FT_GET_LONG(); 435*37da2899SCharles.Forsyth 436*37da2899SCharles.Forsyth FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", 437*37da2899SCharles.Forsyth (FT_Char)( entry->Tag >> 24 ), 438*37da2899SCharles.Forsyth (FT_Char)( entry->Tag >> 16 ), 439*37da2899SCharles.Forsyth (FT_Char)( entry->Tag >> 8 ), 440*37da2899SCharles.Forsyth (FT_Char)( entry->Tag ), 441*37da2899SCharles.Forsyth entry->Offset, 442*37da2899SCharles.Forsyth entry->Length )); 443*37da2899SCharles.Forsyth } 444*37da2899SCharles.Forsyth 445*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth FT_TRACE2(( "Directory loaded\n\n" )); 448*37da2899SCharles.Forsyth 449*37da2899SCharles.Forsyth Exit: 450*37da2899SCharles.Forsyth return error; 451*37da2899SCharles.Forsyth } 452*37da2899SCharles.Forsyth 453*37da2899SCharles.Forsyth 454*37da2899SCharles.Forsyth /*************************************************************************/ 455*37da2899SCharles.Forsyth /* */ 456*37da2899SCharles.Forsyth /* <Function> */ 457*37da2899SCharles.Forsyth /* tt_face_load_any */ 458*37da2899SCharles.Forsyth /* */ 459*37da2899SCharles.Forsyth /* <Description> */ 460*37da2899SCharles.Forsyth /* Loads any font table into client memory. */ 461*37da2899SCharles.Forsyth /* */ 462*37da2899SCharles.Forsyth /* <Input> */ 463*37da2899SCharles.Forsyth /* face :: The face object to look for. */ 464*37da2899SCharles.Forsyth /* */ 465*37da2899SCharles.Forsyth /* tag :: The tag of table to load. Use the value 0 if you want */ 466*37da2899SCharles.Forsyth /* to access the whole font file, else set this parameter */ 467*37da2899SCharles.Forsyth /* to a valid TrueType table tag that you can forge with */ 468*37da2899SCharles.Forsyth /* the MAKE_TT_TAG macro. */ 469*37da2899SCharles.Forsyth /* */ 470*37da2899SCharles.Forsyth /* offset :: The starting offset in the table (or the file if */ 471*37da2899SCharles.Forsyth /* tag == 0). */ 472*37da2899SCharles.Forsyth /* */ 473*37da2899SCharles.Forsyth /* length :: The address of the decision variable: */ 474*37da2899SCharles.Forsyth /* */ 475*37da2899SCharles.Forsyth /* If length == NULL: */ 476*37da2899SCharles.Forsyth /* Loads the whole table. Returns an error if */ 477*37da2899SCharles.Forsyth /* `offset' == 0! */ 478*37da2899SCharles.Forsyth /* */ 479*37da2899SCharles.Forsyth /* If *length == 0: */ 480*37da2899SCharles.Forsyth /* Exits immediately; returning the length of the given */ 481*37da2899SCharles.Forsyth /* table or of the font file, depending on the value of */ 482*37da2899SCharles.Forsyth /* `tag'. */ 483*37da2899SCharles.Forsyth /* */ 484*37da2899SCharles.Forsyth /* If *length != 0: */ 485*37da2899SCharles.Forsyth /* Loads the next `length' bytes of table or font, */ 486*37da2899SCharles.Forsyth /* starting at offset `offset' (in table or font too). */ 487*37da2899SCharles.Forsyth /* */ 488*37da2899SCharles.Forsyth /* <Output> */ 489*37da2899SCharles.Forsyth /* buffer :: The address of target buffer. */ 490*37da2899SCharles.Forsyth /* */ 491*37da2899SCharles.Forsyth /* <Return> */ 492*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 493*37da2899SCharles.Forsyth /* */ 494*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_any(TT_Face face,FT_ULong tag,FT_Long offset,FT_Byte * buffer,FT_ULong * length)495*37da2899SCharles.Forsyth tt_face_load_any( TT_Face face, 496*37da2899SCharles.Forsyth FT_ULong tag, 497*37da2899SCharles.Forsyth FT_Long offset, 498*37da2899SCharles.Forsyth FT_Byte* buffer, 499*37da2899SCharles.Forsyth FT_ULong* length ) 500*37da2899SCharles.Forsyth { 501*37da2899SCharles.Forsyth FT_Error error; 502*37da2899SCharles.Forsyth FT_Stream stream; 503*37da2899SCharles.Forsyth TT_Table table; 504*37da2899SCharles.Forsyth FT_ULong size; 505*37da2899SCharles.Forsyth 506*37da2899SCharles.Forsyth 507*37da2899SCharles.Forsyth if ( tag != 0 ) 508*37da2899SCharles.Forsyth { 509*37da2899SCharles.Forsyth /* look for tag in font directory */ 510*37da2899SCharles.Forsyth table = tt_face_lookup_table( face, tag ); 511*37da2899SCharles.Forsyth if ( !table ) 512*37da2899SCharles.Forsyth { 513*37da2899SCharles.Forsyth error = SFNT_Err_Table_Missing; 514*37da2899SCharles.Forsyth goto Exit; 515*37da2899SCharles.Forsyth } 516*37da2899SCharles.Forsyth 517*37da2899SCharles.Forsyth offset += table->Offset; 518*37da2899SCharles.Forsyth size = table->Length; 519*37da2899SCharles.Forsyth } 520*37da2899SCharles.Forsyth else 521*37da2899SCharles.Forsyth /* tag == 0 -- the user wants to access the font file directly */ 522*37da2899SCharles.Forsyth size = face->root.stream->size; 523*37da2899SCharles.Forsyth 524*37da2899SCharles.Forsyth if ( length && *length == 0 ) 525*37da2899SCharles.Forsyth { 526*37da2899SCharles.Forsyth *length = size; 527*37da2899SCharles.Forsyth 528*37da2899SCharles.Forsyth return SFNT_Err_Ok; 529*37da2899SCharles.Forsyth } 530*37da2899SCharles.Forsyth 531*37da2899SCharles.Forsyth if ( length ) 532*37da2899SCharles.Forsyth size = *length; 533*37da2899SCharles.Forsyth 534*37da2899SCharles.Forsyth stream = face->root.stream; 535*37da2899SCharles.Forsyth /* the `if' is syntactic sugar for picky compilers */ 536*37da2899SCharles.Forsyth if ( FT_STREAM_READ_AT( offset, buffer, size ) ) 537*37da2899SCharles.Forsyth goto Exit; 538*37da2899SCharles.Forsyth 539*37da2899SCharles.Forsyth Exit: 540*37da2899SCharles.Forsyth return error; 541*37da2899SCharles.Forsyth } 542*37da2899SCharles.Forsyth 543*37da2899SCharles.Forsyth 544*37da2899SCharles.Forsyth /*************************************************************************/ 545*37da2899SCharles.Forsyth /* */ 546*37da2899SCharles.Forsyth /* <Function> */ 547*37da2899SCharles.Forsyth /* tt_face_load_generic_header */ 548*37da2899SCharles.Forsyth /* */ 549*37da2899SCharles.Forsyth /* <Description> */ 550*37da2899SCharles.Forsyth /* Loads the TrueType table `head' or `bhed'. */ 551*37da2899SCharles.Forsyth /* */ 552*37da2899SCharles.Forsyth /* <Input> */ 553*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 554*37da2899SCharles.Forsyth /* */ 555*37da2899SCharles.Forsyth /* stream :: The input stream. */ 556*37da2899SCharles.Forsyth /* */ 557*37da2899SCharles.Forsyth /* <Return> */ 558*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 559*37da2899SCharles.Forsyth /* */ 560*37da2899SCharles.Forsyth static FT_Error tt_face_load_generic_header(TT_Face face,FT_Stream stream,FT_ULong tag)561*37da2899SCharles.Forsyth tt_face_load_generic_header( TT_Face face, 562*37da2899SCharles.Forsyth FT_Stream stream, 563*37da2899SCharles.Forsyth FT_ULong tag ) 564*37da2899SCharles.Forsyth { 565*37da2899SCharles.Forsyth FT_Error error; 566*37da2899SCharles.Forsyth TT_Header* header; 567*37da2899SCharles.Forsyth 568*37da2899SCharles.Forsyth static const FT_Frame_Field header_fields[] = 569*37da2899SCharles.Forsyth { 570*37da2899SCharles.Forsyth #undef FT_STRUCTURE 571*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_Header 572*37da2899SCharles.Forsyth 573*37da2899SCharles.Forsyth FT_FRAME_START( 54 ), 574*37da2899SCharles.Forsyth FT_FRAME_ULONG ( Table_Version ), 575*37da2899SCharles.Forsyth FT_FRAME_ULONG ( Font_Revision ), 576*37da2899SCharles.Forsyth FT_FRAME_LONG ( CheckSum_Adjust ), 577*37da2899SCharles.Forsyth FT_FRAME_LONG ( Magic_Number ), 578*37da2899SCharles.Forsyth FT_FRAME_USHORT( Flags ), 579*37da2899SCharles.Forsyth FT_FRAME_USHORT( Units_Per_EM ), 580*37da2899SCharles.Forsyth FT_FRAME_LONG ( Created[0] ), 581*37da2899SCharles.Forsyth FT_FRAME_LONG ( Created[1] ), 582*37da2899SCharles.Forsyth FT_FRAME_LONG ( Modified[0] ), 583*37da2899SCharles.Forsyth FT_FRAME_LONG ( Modified[1] ), 584*37da2899SCharles.Forsyth FT_FRAME_SHORT ( xMin ), 585*37da2899SCharles.Forsyth FT_FRAME_SHORT ( yMin ), 586*37da2899SCharles.Forsyth FT_FRAME_SHORT ( xMax ), 587*37da2899SCharles.Forsyth FT_FRAME_SHORT ( yMax ), 588*37da2899SCharles.Forsyth FT_FRAME_USHORT( Mac_Style ), 589*37da2899SCharles.Forsyth FT_FRAME_USHORT( Lowest_Rec_PPEM ), 590*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Font_Direction ), 591*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Index_To_Loc_Format ), 592*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Glyph_Data_Format ), 593*37da2899SCharles.Forsyth FT_FRAME_END 594*37da2899SCharles.Forsyth }; 595*37da2899SCharles.Forsyth 596*37da2899SCharles.Forsyth 597*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_generic_header: " 598*37da2899SCharles.Forsyth "%08p, looking up font table `%c%c%c%c'.\n", 599*37da2899SCharles.Forsyth face, 600*37da2899SCharles.Forsyth (FT_Char)( tag >> 24 ), 601*37da2899SCharles.Forsyth (FT_Char)( tag >> 16 ), 602*37da2899SCharles.Forsyth (FT_Char)( tag >> 8 ), 603*37da2899SCharles.Forsyth (FT_Char)( tag ) )); 604*37da2899SCharles.Forsyth 605*37da2899SCharles.Forsyth error = face->goto_table( face, tag, stream, 0 ); 606*37da2899SCharles.Forsyth if ( error ) 607*37da2899SCharles.Forsyth { 608*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" )); 609*37da2899SCharles.Forsyth goto Exit; 610*37da2899SCharles.Forsyth } 611*37da2899SCharles.Forsyth 612*37da2899SCharles.Forsyth header = &face->header; 613*37da2899SCharles.Forsyth 614*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) 615*37da2899SCharles.Forsyth goto Exit; 616*37da2899SCharles.Forsyth 617*37da2899SCharles.Forsyth FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM )); 618*37da2899SCharles.Forsyth FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format )); 619*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" )); 620*37da2899SCharles.Forsyth 621*37da2899SCharles.Forsyth Exit: 622*37da2899SCharles.Forsyth return error; 623*37da2899SCharles.Forsyth } 624*37da2899SCharles.Forsyth 625*37da2899SCharles.Forsyth 626*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_header(TT_Face face,FT_Stream stream)627*37da2899SCharles.Forsyth tt_face_load_header( TT_Face face, 628*37da2899SCharles.Forsyth FT_Stream stream ) 629*37da2899SCharles.Forsyth { 630*37da2899SCharles.Forsyth return tt_face_load_generic_header( face, stream, TTAG_head ); 631*37da2899SCharles.Forsyth } 632*37da2899SCharles.Forsyth 633*37da2899SCharles.Forsyth 634*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_bitmap_header(TT_Face face,FT_Stream stream)637*37da2899SCharles.Forsyth tt_face_load_bitmap_header( TT_Face face, 638*37da2899SCharles.Forsyth FT_Stream stream ) 639*37da2899SCharles.Forsyth { 640*37da2899SCharles.Forsyth return tt_face_load_generic_header( face, stream, TTAG_bhed ); 641*37da2899SCharles.Forsyth } 642*37da2899SCharles.Forsyth 643*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 644*37da2899SCharles.Forsyth 645*37da2899SCharles.Forsyth 646*37da2899SCharles.Forsyth /*************************************************************************/ 647*37da2899SCharles.Forsyth /* */ 648*37da2899SCharles.Forsyth /* <Function> */ 649*37da2899SCharles.Forsyth /* tt_face_load_max_profile */ 650*37da2899SCharles.Forsyth /* */ 651*37da2899SCharles.Forsyth /* <Description> */ 652*37da2899SCharles.Forsyth /* Loads the maximum profile into a face object. */ 653*37da2899SCharles.Forsyth /* */ 654*37da2899SCharles.Forsyth /* <Input> */ 655*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 656*37da2899SCharles.Forsyth /* */ 657*37da2899SCharles.Forsyth /* stream :: The input stream. */ 658*37da2899SCharles.Forsyth /* */ 659*37da2899SCharles.Forsyth /* <Return> */ 660*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 661*37da2899SCharles.Forsyth /* */ 662*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_max_profile(TT_Face face,FT_Stream stream)663*37da2899SCharles.Forsyth tt_face_load_max_profile( TT_Face face, 664*37da2899SCharles.Forsyth FT_Stream stream ) 665*37da2899SCharles.Forsyth { 666*37da2899SCharles.Forsyth FT_Error error; 667*37da2899SCharles.Forsyth TT_MaxProfile* maxProfile = &face->max_profile; 668*37da2899SCharles.Forsyth 669*37da2899SCharles.Forsyth const FT_Frame_Field maxp_fields[] = 670*37da2899SCharles.Forsyth { 671*37da2899SCharles.Forsyth #undef FT_STRUCTURE 672*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_MaxProfile 673*37da2899SCharles.Forsyth 674*37da2899SCharles.Forsyth FT_FRAME_START( 6 ), 675*37da2899SCharles.Forsyth FT_FRAME_LONG ( version ), 676*37da2899SCharles.Forsyth FT_FRAME_USHORT( numGlyphs ), 677*37da2899SCharles.Forsyth FT_FRAME_END 678*37da2899SCharles.Forsyth }; 679*37da2899SCharles.Forsyth 680*37da2899SCharles.Forsyth const FT_Frame_Field maxp_fields_extra[] = 681*37da2899SCharles.Forsyth { 682*37da2899SCharles.Forsyth FT_FRAME_START( 26 ), 683*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxPoints ), 684*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxContours ), 685*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxCompositePoints ), 686*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxCompositeContours ), 687*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxZones ), 688*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxTwilightPoints ), 689*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxStorage ), 690*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxFunctionDefs ), 691*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxInstructionDefs ), 692*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxStackElements ), 693*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxSizeOfInstructions ), 694*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxComponentElements ), 695*37da2899SCharles.Forsyth FT_FRAME_USHORT( maxComponentDepth ), 696*37da2899SCharles.Forsyth FT_FRAME_END 697*37da2899SCharles.Forsyth }; 698*37da2899SCharles.Forsyth 699*37da2899SCharles.Forsyth 700*37da2899SCharles.Forsyth FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face )); 701*37da2899SCharles.Forsyth 702*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_maxp, stream, 0 ); 703*37da2899SCharles.Forsyth if ( error ) 704*37da2899SCharles.Forsyth goto Exit; 705*37da2899SCharles.Forsyth 706*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) ) 707*37da2899SCharles.Forsyth goto Exit; 708*37da2899SCharles.Forsyth 709*37da2899SCharles.Forsyth maxProfile->maxPoints = 0; 710*37da2899SCharles.Forsyth maxProfile->maxContours = 0; 711*37da2899SCharles.Forsyth maxProfile->maxCompositePoints = 0; 712*37da2899SCharles.Forsyth maxProfile->maxCompositeContours = 0; 713*37da2899SCharles.Forsyth maxProfile->maxZones = 0; 714*37da2899SCharles.Forsyth maxProfile->maxTwilightPoints = 0; 715*37da2899SCharles.Forsyth maxProfile->maxStorage = 0; 716*37da2899SCharles.Forsyth maxProfile->maxFunctionDefs = 0; 717*37da2899SCharles.Forsyth maxProfile->maxInstructionDefs = 0; 718*37da2899SCharles.Forsyth maxProfile->maxStackElements = 0; 719*37da2899SCharles.Forsyth maxProfile->maxSizeOfInstructions = 0; 720*37da2899SCharles.Forsyth maxProfile->maxComponentElements = 0; 721*37da2899SCharles.Forsyth maxProfile->maxComponentDepth = 0; 722*37da2899SCharles.Forsyth 723*37da2899SCharles.Forsyth if ( maxProfile->version >= 0x10000L ) 724*37da2899SCharles.Forsyth { 725*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) ) 726*37da2899SCharles.Forsyth goto Exit; 727*37da2899SCharles.Forsyth 728*37da2899SCharles.Forsyth /* XXX: an adjustment that is necessary to load certain */ 729*37da2899SCharles.Forsyth /* broken fonts like `Keystrokes MT' :-( */ 730*37da2899SCharles.Forsyth /* */ 731*37da2899SCharles.Forsyth /* We allocate 64 function entries by default when */ 732*37da2899SCharles.Forsyth /* the maxFunctionDefs field is null. */ 733*37da2899SCharles.Forsyth 734*37da2899SCharles.Forsyth if ( maxProfile->maxFunctionDefs == 0 ) 735*37da2899SCharles.Forsyth maxProfile->maxFunctionDefs = 64; 736*37da2899SCharles.Forsyth 737*37da2899SCharles.Forsyth face->root.num_glyphs = maxProfile->numGlyphs; 738*37da2899SCharles.Forsyth 739*37da2899SCharles.Forsyth face->root.internal->max_points = 740*37da2899SCharles.Forsyth (FT_UShort)MAX( maxProfile->maxCompositePoints, 741*37da2899SCharles.Forsyth maxProfile->maxPoints ); 742*37da2899SCharles.Forsyth 743*37da2899SCharles.Forsyth face->root.internal->max_contours = 744*37da2899SCharles.Forsyth (FT_Short)MAX( maxProfile->maxCompositeContours, 745*37da2899SCharles.Forsyth maxProfile->maxContours ); 746*37da2899SCharles.Forsyth 747*37da2899SCharles.Forsyth face->max_components = (FT_ULong)maxProfile->maxComponentElements + 748*37da2899SCharles.Forsyth maxProfile->maxComponentDepth; 749*37da2899SCharles.Forsyth 750*37da2899SCharles.Forsyth /* XXX: some fonts have maxComponents set to 0; we will */ 751*37da2899SCharles.Forsyth /* then use 16 of them by default. */ 752*37da2899SCharles.Forsyth if ( face->max_components == 0 ) 753*37da2899SCharles.Forsyth face->max_components = 16; 754*37da2899SCharles.Forsyth 755*37da2899SCharles.Forsyth /* We also increase maxPoints and maxContours in order to support */ 756*37da2899SCharles.Forsyth /* some broken fonts. */ 757*37da2899SCharles.Forsyth face->root.internal->max_points += (FT_UShort)8; 758*37da2899SCharles.Forsyth face->root.internal->max_contours += (FT_Short) 4; 759*37da2899SCharles.Forsyth } 760*37da2899SCharles.Forsyth 761*37da2899SCharles.Forsyth FT_TRACE2(( "MAXP loaded.\n" )); 762*37da2899SCharles.Forsyth 763*37da2899SCharles.Forsyth Exit: 764*37da2899SCharles.Forsyth return error; 765*37da2899SCharles.Forsyth } 766*37da2899SCharles.Forsyth 767*37da2899SCharles.Forsyth 768*37da2899SCharles.Forsyth /*************************************************************************/ 769*37da2899SCharles.Forsyth /* */ 770*37da2899SCharles.Forsyth /* <Function> */ 771*37da2899SCharles.Forsyth /* tt_face_load_metrics */ 772*37da2899SCharles.Forsyth /* */ 773*37da2899SCharles.Forsyth /* <Description> */ 774*37da2899SCharles.Forsyth /* Loads the horizontal or vertical metrics table into a face object. */ 775*37da2899SCharles.Forsyth /* */ 776*37da2899SCharles.Forsyth /* <Input> */ 777*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 778*37da2899SCharles.Forsyth /* */ 779*37da2899SCharles.Forsyth /* stream :: The input stream. */ 780*37da2899SCharles.Forsyth /* */ 781*37da2899SCharles.Forsyth /* vertical :: A boolean flag. If set, load vertical metrics. */ 782*37da2899SCharles.Forsyth /* */ 783*37da2899SCharles.Forsyth /* <Return> */ 784*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 785*37da2899SCharles.Forsyth /* */ 786*37da2899SCharles.Forsyth static FT_Error tt_face_load_metrics(TT_Face face,FT_Stream stream,FT_Bool vertical)787*37da2899SCharles.Forsyth tt_face_load_metrics( TT_Face face, 788*37da2899SCharles.Forsyth FT_Stream stream, 789*37da2899SCharles.Forsyth FT_Bool vertical ) 790*37da2899SCharles.Forsyth { 791*37da2899SCharles.Forsyth FT_Error error; 792*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 793*37da2899SCharles.Forsyth 794*37da2899SCharles.Forsyth FT_ULong table_len; 795*37da2899SCharles.Forsyth FT_Long num_shorts, num_longs, num_shorts_checked; 796*37da2899SCharles.Forsyth 797*37da2899SCharles.Forsyth TT_LongMetrics * longs; 798*37da2899SCharles.Forsyth TT_ShortMetrics** shorts; 799*37da2899SCharles.Forsyth 800*37da2899SCharles.Forsyth 801*37da2899SCharles.Forsyth FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" 802*37da2899SCharles.Forsyth : "Horizontal", 803*37da2899SCharles.Forsyth face )); 804*37da2899SCharles.Forsyth 805*37da2899SCharles.Forsyth if ( vertical ) 806*37da2899SCharles.Forsyth { 807*37da2899SCharles.Forsyth /* The table is optional, quit silently if it wasn't found */ 808*37da2899SCharles.Forsyth /* */ 809*37da2899SCharles.Forsyth /* XXX: Some fonts have a valid vertical header with a non-null */ 810*37da2899SCharles.Forsyth /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ 811*37da2899SCharles.Forsyth /* table to get the metrics from (e.g. mingliu). */ 812*37da2899SCharles.Forsyth /* */ 813*37da2899SCharles.Forsyth /* For safety, we set the field to 0! */ 814*37da2899SCharles.Forsyth /* */ 815*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); 816*37da2899SCharles.Forsyth if ( error ) 817*37da2899SCharles.Forsyth { 818*37da2899SCharles.Forsyth /* Set number_Of_VMetrics to 0! */ 819*37da2899SCharles.Forsyth FT_TRACE2(( " no vertical header in file.\n" )); 820*37da2899SCharles.Forsyth face->vertical.number_Of_VMetrics = 0; 821*37da2899SCharles.Forsyth error = SFNT_Err_Ok; 822*37da2899SCharles.Forsyth goto Exit; 823*37da2899SCharles.Forsyth } 824*37da2899SCharles.Forsyth 825*37da2899SCharles.Forsyth num_longs = face->vertical.number_Of_VMetrics; 826*37da2899SCharles.Forsyth longs = (TT_LongMetrics *)&face->vertical.long_metrics; 827*37da2899SCharles.Forsyth shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; 828*37da2899SCharles.Forsyth } 829*37da2899SCharles.Forsyth else 830*37da2899SCharles.Forsyth { 831*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); 832*37da2899SCharles.Forsyth if ( error ) 833*37da2899SCharles.Forsyth { 834*37da2899SCharles.Forsyth FT_ERROR(( " no horizontal metrics in file!\n" )); 835*37da2899SCharles.Forsyth error = SFNT_Err_Hmtx_Table_Missing; 836*37da2899SCharles.Forsyth goto Exit; 837*37da2899SCharles.Forsyth } 838*37da2899SCharles.Forsyth 839*37da2899SCharles.Forsyth num_longs = face->horizontal.number_Of_HMetrics; 840*37da2899SCharles.Forsyth longs = (TT_LongMetrics *)&face->horizontal.long_metrics; 841*37da2899SCharles.Forsyth shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; 842*37da2899SCharles.Forsyth } 843*37da2899SCharles.Forsyth 844*37da2899SCharles.Forsyth /* never trust derived values */ 845*37da2899SCharles.Forsyth 846*37da2899SCharles.Forsyth num_shorts = face->max_profile.numGlyphs - num_longs; 847*37da2899SCharles.Forsyth num_shorts_checked = ( table_len - num_longs * 4L ) / 2; 848*37da2899SCharles.Forsyth 849*37da2899SCharles.Forsyth if ( num_shorts < 0 ) 850*37da2899SCharles.Forsyth { 851*37da2899SCharles.Forsyth FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", 852*37da2899SCharles.Forsyth vertical ? "Vertical" 853*37da2899SCharles.Forsyth : "Horizontal" )); 854*37da2899SCharles.Forsyth 855*37da2899SCharles.Forsyth error = vertical ? SFNT_Err_Invalid_Vert_Metrics 856*37da2899SCharles.Forsyth : SFNT_Err_Invalid_Horiz_Metrics; 857*37da2899SCharles.Forsyth goto Exit; 858*37da2899SCharles.Forsyth } 859*37da2899SCharles.Forsyth 860*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( *longs, num_longs ) || 861*37da2899SCharles.Forsyth FT_NEW_ARRAY( *shorts, num_shorts ) ) 862*37da2899SCharles.Forsyth goto Exit; 863*37da2899SCharles.Forsyth 864*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( table_len ) ) 865*37da2899SCharles.Forsyth goto Exit; 866*37da2899SCharles.Forsyth 867*37da2899SCharles.Forsyth { 868*37da2899SCharles.Forsyth TT_LongMetrics cur = *longs; 869*37da2899SCharles.Forsyth TT_LongMetrics limit = cur + num_longs; 870*37da2899SCharles.Forsyth 871*37da2899SCharles.Forsyth 872*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 873*37da2899SCharles.Forsyth { 874*37da2899SCharles.Forsyth cur->advance = FT_GET_USHORT(); 875*37da2899SCharles.Forsyth cur->bearing = FT_GET_SHORT(); 876*37da2899SCharles.Forsyth } 877*37da2899SCharles.Forsyth } 878*37da2899SCharles.Forsyth 879*37da2899SCharles.Forsyth /* do we have an inconsistent number of metric values? */ 880*37da2899SCharles.Forsyth { 881*37da2899SCharles.Forsyth TT_ShortMetrics* cur = *shorts; 882*37da2899SCharles.Forsyth TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked ); 883*37da2899SCharles.Forsyth 884*37da2899SCharles.Forsyth 885*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 886*37da2899SCharles.Forsyth *cur = FT_GET_SHORT(); 887*37da2899SCharles.Forsyth 888*37da2899SCharles.Forsyth /* we fill up the missing left side bearings with the */ 889*37da2899SCharles.Forsyth /* last valid value. Since this will occur for buggy CJK */ 890*37da2899SCharles.Forsyth /* fonts usually only, nothing serious will happen */ 891*37da2899SCharles.Forsyth if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) 892*37da2899SCharles.Forsyth { 893*37da2899SCharles.Forsyth FT_Short val = (*shorts)[num_shorts_checked - 1]; 894*37da2899SCharles.Forsyth 895*37da2899SCharles.Forsyth 896*37da2899SCharles.Forsyth limit = *shorts + num_shorts; 897*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 898*37da2899SCharles.Forsyth *cur = val; 899*37da2899SCharles.Forsyth } 900*37da2899SCharles.Forsyth } 901*37da2899SCharles.Forsyth 902*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 903*37da2899SCharles.Forsyth 904*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 905*37da2899SCharles.Forsyth 906*37da2899SCharles.Forsyth Exit: 907*37da2899SCharles.Forsyth return error; 908*37da2899SCharles.Forsyth } 909*37da2899SCharles.Forsyth 910*37da2899SCharles.Forsyth 911*37da2899SCharles.Forsyth /*************************************************************************/ 912*37da2899SCharles.Forsyth /* */ 913*37da2899SCharles.Forsyth /* <Function> */ 914*37da2899SCharles.Forsyth /* tt_face_load_metrics_header */ 915*37da2899SCharles.Forsyth /* */ 916*37da2899SCharles.Forsyth /* <Description> */ 917*37da2899SCharles.Forsyth /* Loads the horizontal or vertical header in a face object. */ 918*37da2899SCharles.Forsyth /* */ 919*37da2899SCharles.Forsyth /* <Input> */ 920*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 921*37da2899SCharles.Forsyth /* */ 922*37da2899SCharles.Forsyth /* stream :: The input stream. */ 923*37da2899SCharles.Forsyth /* */ 924*37da2899SCharles.Forsyth /* vertical :: A boolean flag. If set, load vertical metrics. */ 925*37da2899SCharles.Forsyth /* */ 926*37da2899SCharles.Forsyth /* <Return> */ 927*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 928*37da2899SCharles.Forsyth /* */ 929*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_metrics_header(TT_Face face,FT_Stream stream,FT_Bool vertical)930*37da2899SCharles.Forsyth tt_face_load_metrics_header( TT_Face face, 931*37da2899SCharles.Forsyth FT_Stream stream, 932*37da2899SCharles.Forsyth FT_Bool vertical ) 933*37da2899SCharles.Forsyth { 934*37da2899SCharles.Forsyth FT_Error error; 935*37da2899SCharles.Forsyth TT_HoriHeader* header; 936*37da2899SCharles.Forsyth 937*37da2899SCharles.Forsyth const FT_Frame_Field metrics_header_fields[] = 938*37da2899SCharles.Forsyth { 939*37da2899SCharles.Forsyth #undef FT_STRUCTURE 940*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_HoriHeader 941*37da2899SCharles.Forsyth 942*37da2899SCharles.Forsyth FT_FRAME_START( 36 ), 943*37da2899SCharles.Forsyth FT_FRAME_ULONG ( Version ), 944*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Ascender ), 945*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Descender ), 946*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Line_Gap ), 947*37da2899SCharles.Forsyth FT_FRAME_USHORT( advance_Width_Max ), 948*37da2899SCharles.Forsyth FT_FRAME_SHORT ( min_Left_Side_Bearing ), 949*37da2899SCharles.Forsyth FT_FRAME_SHORT ( min_Right_Side_Bearing ), 950*37da2899SCharles.Forsyth FT_FRAME_SHORT ( xMax_Extent ), 951*37da2899SCharles.Forsyth FT_FRAME_SHORT ( caret_Slope_Rise ), 952*37da2899SCharles.Forsyth FT_FRAME_SHORT ( caret_Slope_Run ), 953*37da2899SCharles.Forsyth FT_FRAME_SHORT ( caret_Offset ), 954*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Reserved[0] ), 955*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Reserved[1] ), 956*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Reserved[2] ), 957*37da2899SCharles.Forsyth FT_FRAME_SHORT ( Reserved[3] ), 958*37da2899SCharles.Forsyth FT_FRAME_SHORT ( metric_Data_Format ), 959*37da2899SCharles.Forsyth FT_FRAME_USHORT( number_Of_HMetrics ), 960*37da2899SCharles.Forsyth FT_FRAME_END 961*37da2899SCharles.Forsyth }; 962*37da2899SCharles.Forsyth 963*37da2899SCharles.Forsyth 964*37da2899SCharles.Forsyth FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); 965*37da2899SCharles.Forsyth 966*37da2899SCharles.Forsyth if ( vertical ) 967*37da2899SCharles.Forsyth { 968*37da2899SCharles.Forsyth face->vertical_info = 0; 969*37da2899SCharles.Forsyth 970*37da2899SCharles.Forsyth /* The vertical header table is optional, so return quietly if */ 971*37da2899SCharles.Forsyth /* we don't find it. */ 972*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_vhea, stream, 0 ); 973*37da2899SCharles.Forsyth if ( error ) 974*37da2899SCharles.Forsyth { 975*37da2899SCharles.Forsyth error = SFNT_Err_Ok; 976*37da2899SCharles.Forsyth goto Exit; 977*37da2899SCharles.Forsyth } 978*37da2899SCharles.Forsyth 979*37da2899SCharles.Forsyth face->vertical_info = 1; 980*37da2899SCharles.Forsyth header = (TT_HoriHeader*)&face->vertical; 981*37da2899SCharles.Forsyth } 982*37da2899SCharles.Forsyth else 983*37da2899SCharles.Forsyth { 984*37da2899SCharles.Forsyth /* The horizontal header is mandatory; return an error if we */ 985*37da2899SCharles.Forsyth /* don't find it. */ 986*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_hhea, stream, 0 ); 987*37da2899SCharles.Forsyth if ( error ) 988*37da2899SCharles.Forsyth { 989*37da2899SCharles.Forsyth error = SFNT_Err_Horiz_Header_Missing; 990*37da2899SCharles.Forsyth goto Exit; 991*37da2899SCharles.Forsyth } 992*37da2899SCharles.Forsyth 993*37da2899SCharles.Forsyth header = &face->horizontal; 994*37da2899SCharles.Forsyth } 995*37da2899SCharles.Forsyth 996*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) 997*37da2899SCharles.Forsyth goto Exit; 998*37da2899SCharles.Forsyth 999*37da2899SCharles.Forsyth header->long_metrics = NULL; 1000*37da2899SCharles.Forsyth header->short_metrics = NULL; 1001*37da2899SCharles.Forsyth 1002*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 1003*37da2899SCharles.Forsyth 1004*37da2899SCharles.Forsyth /* Now try to load the corresponding metrics */ 1005*37da2899SCharles.Forsyth 1006*37da2899SCharles.Forsyth error = tt_face_load_metrics( face, stream, vertical ); 1007*37da2899SCharles.Forsyth 1008*37da2899SCharles.Forsyth Exit: 1009*37da2899SCharles.Forsyth return error; 1010*37da2899SCharles.Forsyth } 1011*37da2899SCharles.Forsyth 1012*37da2899SCharles.Forsyth 1013*37da2899SCharles.Forsyth /*************************************************************************/ 1014*37da2899SCharles.Forsyth /* */ 1015*37da2899SCharles.Forsyth /* <Function> */ 1016*37da2899SCharles.Forsyth /* tt_face_load_names */ 1017*37da2899SCharles.Forsyth /* */ 1018*37da2899SCharles.Forsyth /* <Description> */ 1019*37da2899SCharles.Forsyth /* Loads the name records. */ 1020*37da2899SCharles.Forsyth /* */ 1021*37da2899SCharles.Forsyth /* <Input> */ 1022*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1023*37da2899SCharles.Forsyth /* */ 1024*37da2899SCharles.Forsyth /* stream :: The input stream. */ 1025*37da2899SCharles.Forsyth /* */ 1026*37da2899SCharles.Forsyth /* <Return> */ 1027*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1028*37da2899SCharles.Forsyth /* */ 1029*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_names(TT_Face face,FT_Stream stream)1030*37da2899SCharles.Forsyth tt_face_load_names( TT_Face face, 1031*37da2899SCharles.Forsyth FT_Stream stream ) 1032*37da2899SCharles.Forsyth { 1033*37da2899SCharles.Forsyth FT_Error error; 1034*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1035*37da2899SCharles.Forsyth FT_ULong table_pos, table_len; 1036*37da2899SCharles.Forsyth FT_ULong storage_start, storage_limit; 1037*37da2899SCharles.Forsyth FT_UInt count; 1038*37da2899SCharles.Forsyth TT_NameTable table; 1039*37da2899SCharles.Forsyth 1040*37da2899SCharles.Forsyth static const FT_Frame_Field name_table_fields[] = 1041*37da2899SCharles.Forsyth { 1042*37da2899SCharles.Forsyth #undef FT_STRUCTURE 1043*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_NameTableRec 1044*37da2899SCharles.Forsyth 1045*37da2899SCharles.Forsyth FT_FRAME_START( 6 ), 1046*37da2899SCharles.Forsyth FT_FRAME_USHORT( format ), 1047*37da2899SCharles.Forsyth FT_FRAME_USHORT( numNameRecords ), 1048*37da2899SCharles.Forsyth FT_FRAME_USHORT( storageOffset ), 1049*37da2899SCharles.Forsyth FT_FRAME_END 1050*37da2899SCharles.Forsyth }; 1051*37da2899SCharles.Forsyth 1052*37da2899SCharles.Forsyth static const FT_Frame_Field name_record_fields[] = 1053*37da2899SCharles.Forsyth { 1054*37da2899SCharles.Forsyth #undef FT_STRUCTURE 1055*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_NameEntryRec 1056*37da2899SCharles.Forsyth 1057*37da2899SCharles.Forsyth /* no FT_FRAME_START */ 1058*37da2899SCharles.Forsyth FT_FRAME_USHORT( platformID ), 1059*37da2899SCharles.Forsyth FT_FRAME_USHORT( encodingID ), 1060*37da2899SCharles.Forsyth FT_FRAME_USHORT( languageID ), 1061*37da2899SCharles.Forsyth FT_FRAME_USHORT( nameID ), 1062*37da2899SCharles.Forsyth FT_FRAME_USHORT( stringLength ), 1063*37da2899SCharles.Forsyth FT_FRAME_USHORT( stringOffset ), 1064*37da2899SCharles.Forsyth FT_FRAME_END 1065*37da2899SCharles.Forsyth }; 1066*37da2899SCharles.Forsyth 1067*37da2899SCharles.Forsyth 1068*37da2899SCharles.Forsyth table = &face->name_table; 1069*37da2899SCharles.Forsyth table->stream = stream; 1070*37da2899SCharles.Forsyth 1071*37da2899SCharles.Forsyth FT_TRACE2(( "Names " )); 1072*37da2899SCharles.Forsyth 1073*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_name, stream, &table_len ); 1074*37da2899SCharles.Forsyth if ( error ) 1075*37da2899SCharles.Forsyth { 1076*37da2899SCharles.Forsyth /* The name table is required so indicate failure. */ 1077*37da2899SCharles.Forsyth FT_TRACE2(( "is missing!\n" )); 1078*37da2899SCharles.Forsyth error = SFNT_Err_Name_Table_Missing; 1079*37da2899SCharles.Forsyth goto Exit; 1080*37da2899SCharles.Forsyth } 1081*37da2899SCharles.Forsyth 1082*37da2899SCharles.Forsyth table_pos = FT_STREAM_POS(); 1083*37da2899SCharles.Forsyth 1084*37da2899SCharles.Forsyth 1085*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) 1086*37da2899SCharles.Forsyth goto Exit; 1087*37da2899SCharles.Forsyth 1088*37da2899SCharles.Forsyth /* Some popular asian fonts have an invalid `storageOffset' value */ 1089*37da2899SCharles.Forsyth /* (it should be at least "6 + 12*num_names"). However, the string */ 1090*37da2899SCharles.Forsyth /* offsets, computed as "storageOffset + entry->stringOffset", are */ 1091*37da2899SCharles.Forsyth /* valid pointers within the name table... */ 1092*37da2899SCharles.Forsyth /* */ 1093*37da2899SCharles.Forsyth /* We thus can't check `storageOffset' right now. */ 1094*37da2899SCharles.Forsyth /* */ 1095*37da2899SCharles.Forsyth storage_start = table_pos + 6 + 12*table->numNameRecords; 1096*37da2899SCharles.Forsyth storage_limit = table_pos + table_len; 1097*37da2899SCharles.Forsyth 1098*37da2899SCharles.Forsyth if ( storage_start > storage_limit ) 1099*37da2899SCharles.Forsyth { 1100*37da2899SCharles.Forsyth FT_ERROR(( "tt_face_load_names: invalid `name' table\n" )); 1101*37da2899SCharles.Forsyth error = SFNT_Err_Name_Table_Missing; 1102*37da2899SCharles.Forsyth goto Exit; 1103*37da2899SCharles.Forsyth } 1104*37da2899SCharles.Forsyth 1105*37da2899SCharles.Forsyth /* Allocate the array of name records. */ 1106*37da2899SCharles.Forsyth count = table->numNameRecords; 1107*37da2899SCharles.Forsyth table->numNameRecords = 0; 1108*37da2899SCharles.Forsyth 1109*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( table->names, count ) || 1110*37da2899SCharles.Forsyth FT_FRAME_ENTER( count * 12 ) ) 1111*37da2899SCharles.Forsyth goto Exit; 1112*37da2899SCharles.Forsyth 1113*37da2899SCharles.Forsyth /* Load the name records and determine how much storage is needed */ 1114*37da2899SCharles.Forsyth /* to hold the strings themselves. */ 1115*37da2899SCharles.Forsyth { 1116*37da2899SCharles.Forsyth TT_NameEntryRec* entry = table->names; 1117*37da2899SCharles.Forsyth 1118*37da2899SCharles.Forsyth 1119*37da2899SCharles.Forsyth for ( ; count > 0; count-- ) 1120*37da2899SCharles.Forsyth { 1121*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) ) 1122*37da2899SCharles.Forsyth continue; 1123*37da2899SCharles.Forsyth 1124*37da2899SCharles.Forsyth /* check that the name is not empty */ 1125*37da2899SCharles.Forsyth if ( entry->stringLength == 0 ) 1126*37da2899SCharles.Forsyth continue; 1127*37da2899SCharles.Forsyth 1128*37da2899SCharles.Forsyth /* check that the name string is within the table */ 1129*37da2899SCharles.Forsyth entry->stringOffset += table_pos + table->storageOffset; 1130*37da2899SCharles.Forsyth if ( entry->stringOffset < storage_start || 1131*37da2899SCharles.Forsyth entry->stringOffset + entry->stringLength > storage_limit ) 1132*37da2899SCharles.Forsyth { 1133*37da2899SCharles.Forsyth /* invalid entry - ignore it */ 1134*37da2899SCharles.Forsyth entry->stringOffset = 0; 1135*37da2899SCharles.Forsyth entry->stringLength = 0; 1136*37da2899SCharles.Forsyth continue; 1137*37da2899SCharles.Forsyth } 1138*37da2899SCharles.Forsyth 1139*37da2899SCharles.Forsyth entry++; 1140*37da2899SCharles.Forsyth } 1141*37da2899SCharles.Forsyth 1142*37da2899SCharles.Forsyth table->numNameRecords = (FT_UInt)( entry - table->names ); 1143*37da2899SCharles.Forsyth } 1144*37da2899SCharles.Forsyth 1145*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1146*37da2899SCharles.Forsyth 1147*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 1148*37da2899SCharles.Forsyth 1149*37da2899SCharles.Forsyth /* everything went well, update face->num_names */ 1150*37da2899SCharles.Forsyth face->num_names = (FT_UShort) table->numNameRecords; 1151*37da2899SCharles.Forsyth 1152*37da2899SCharles.Forsyth Exit: 1153*37da2899SCharles.Forsyth return error; 1154*37da2899SCharles.Forsyth } 1155*37da2899SCharles.Forsyth 1156*37da2899SCharles.Forsyth 1157*37da2899SCharles.Forsyth /*************************************************************************/ 1158*37da2899SCharles.Forsyth /* */ 1159*37da2899SCharles.Forsyth /* <Function> */ 1160*37da2899SCharles.Forsyth /* tt_face_free_names */ 1161*37da2899SCharles.Forsyth /* */ 1162*37da2899SCharles.Forsyth /* <Description> */ 1163*37da2899SCharles.Forsyth /* Frees the name records. */ 1164*37da2899SCharles.Forsyth /* */ 1165*37da2899SCharles.Forsyth /* <Input> */ 1166*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1167*37da2899SCharles.Forsyth /* */ 1168*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) tt_face_free_names(TT_Face face)1169*37da2899SCharles.Forsyth tt_face_free_names( TT_Face face ) 1170*37da2899SCharles.Forsyth { 1171*37da2899SCharles.Forsyth FT_Memory memory = face->root.driver->root.memory; 1172*37da2899SCharles.Forsyth TT_NameTable table = &face->name_table; 1173*37da2899SCharles.Forsyth TT_NameEntry entry = table->names; 1174*37da2899SCharles.Forsyth FT_UInt count = table->numNameRecords; 1175*37da2899SCharles.Forsyth 1176*37da2899SCharles.Forsyth 1177*37da2899SCharles.Forsyth for ( ; count > 0; count--, entry++ ) 1178*37da2899SCharles.Forsyth { 1179*37da2899SCharles.Forsyth FT_FREE( entry->string ); 1180*37da2899SCharles.Forsyth entry->stringLength = 0; 1181*37da2899SCharles.Forsyth } 1182*37da2899SCharles.Forsyth 1183*37da2899SCharles.Forsyth /* free strings table */ 1184*37da2899SCharles.Forsyth FT_FREE( table->names ); 1185*37da2899SCharles.Forsyth 1186*37da2899SCharles.Forsyth table->numNameRecords = 0; 1187*37da2899SCharles.Forsyth table->format = 0; 1188*37da2899SCharles.Forsyth table->storageOffset = 0; 1189*37da2899SCharles.Forsyth } 1190*37da2899SCharles.Forsyth 1191*37da2899SCharles.Forsyth 1192*37da2899SCharles.Forsyth /*************************************************************************/ 1193*37da2899SCharles.Forsyth /* */ 1194*37da2899SCharles.Forsyth /* <Function> */ 1195*37da2899SCharles.Forsyth /* tt_face_load_cmap */ 1196*37da2899SCharles.Forsyth /* */ 1197*37da2899SCharles.Forsyth /* <Description> */ 1198*37da2899SCharles.Forsyth /* Loads the cmap directory in a face object. The cmaps itselves are */ 1199*37da2899SCharles.Forsyth /* loaded on demand in the `ttcmap.c' module. */ 1200*37da2899SCharles.Forsyth /* */ 1201*37da2899SCharles.Forsyth /* <Input> */ 1202*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1203*37da2899SCharles.Forsyth /* */ 1204*37da2899SCharles.Forsyth /* stream :: A handle to the input stream. */ 1205*37da2899SCharles.Forsyth /* */ 1206*37da2899SCharles.Forsyth /* <Return> */ 1207*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1208*37da2899SCharles.Forsyth /* */ 1209*37da2899SCharles.Forsyth 1210*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_cmap(TT_Face face,FT_Stream stream)1211*37da2899SCharles.Forsyth tt_face_load_cmap( TT_Face face, 1212*37da2899SCharles.Forsyth FT_Stream stream ) 1213*37da2899SCharles.Forsyth { 1214*37da2899SCharles.Forsyth FT_Error error; 1215*37da2899SCharles.Forsyth 1216*37da2899SCharles.Forsyth 1217*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); 1218*37da2899SCharles.Forsyth if ( error ) 1219*37da2899SCharles.Forsyth { 1220*37da2899SCharles.Forsyth FT_TRACE2(( "No `cmap' table in font !\n" )); 1221*37da2899SCharles.Forsyth error = SFNT_Err_CMap_Table_Missing; 1222*37da2899SCharles.Forsyth goto Exit; 1223*37da2899SCharles.Forsyth } 1224*37da2899SCharles.Forsyth 1225*37da2899SCharles.Forsyth if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) 1226*37da2899SCharles.Forsyth FT_TRACE2(( "`cmap' table loaded\n" )); 1227*37da2899SCharles.Forsyth else 1228*37da2899SCharles.Forsyth { 1229*37da2899SCharles.Forsyth FT_ERROR(( "`cmap' table is too short!\n" )); 1230*37da2899SCharles.Forsyth face->cmap_size = 0; 1231*37da2899SCharles.Forsyth } 1232*37da2899SCharles.Forsyth 1233*37da2899SCharles.Forsyth Exit: 1234*37da2899SCharles.Forsyth return error; 1235*37da2899SCharles.Forsyth } 1236*37da2899SCharles.Forsyth 1237*37da2899SCharles.Forsyth 1238*37da2899SCharles.Forsyth 1239*37da2899SCharles.Forsyth /*************************************************************************/ 1240*37da2899SCharles.Forsyth /* */ 1241*37da2899SCharles.Forsyth /* <Function> */ 1242*37da2899SCharles.Forsyth /* tt_face_load_os2 */ 1243*37da2899SCharles.Forsyth /* */ 1244*37da2899SCharles.Forsyth /* <Description> */ 1245*37da2899SCharles.Forsyth /* Loads the OS2 table. */ 1246*37da2899SCharles.Forsyth /* */ 1247*37da2899SCharles.Forsyth /* <Input> */ 1248*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1249*37da2899SCharles.Forsyth /* */ 1250*37da2899SCharles.Forsyth /* stream :: A handle to the input stream. */ 1251*37da2899SCharles.Forsyth /* */ 1252*37da2899SCharles.Forsyth /* <Return> */ 1253*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1254*37da2899SCharles.Forsyth /* */ 1255*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_os2(TT_Face face,FT_Stream stream)1256*37da2899SCharles.Forsyth tt_face_load_os2( TT_Face face, 1257*37da2899SCharles.Forsyth FT_Stream stream ) 1258*37da2899SCharles.Forsyth { 1259*37da2899SCharles.Forsyth FT_Error error; 1260*37da2899SCharles.Forsyth TT_OS2* os2; 1261*37da2899SCharles.Forsyth 1262*37da2899SCharles.Forsyth const FT_Frame_Field os2_fields[] = 1263*37da2899SCharles.Forsyth { 1264*37da2899SCharles.Forsyth #undef FT_STRUCTURE 1265*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_OS2 1266*37da2899SCharles.Forsyth 1267*37da2899SCharles.Forsyth FT_FRAME_START( 78 ), 1268*37da2899SCharles.Forsyth FT_FRAME_USHORT( version ), 1269*37da2899SCharles.Forsyth FT_FRAME_SHORT ( xAvgCharWidth ), 1270*37da2899SCharles.Forsyth FT_FRAME_USHORT( usWeightClass ), 1271*37da2899SCharles.Forsyth FT_FRAME_USHORT( usWidthClass ), 1272*37da2899SCharles.Forsyth FT_FRAME_SHORT ( fsType ), 1273*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySubscriptXSize ), 1274*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySubscriptYSize ), 1275*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySubscriptXOffset ), 1276*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySubscriptYOffset ), 1277*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySuperscriptXSize ), 1278*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySuperscriptYSize ), 1279*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySuperscriptXOffset ), 1280*37da2899SCharles.Forsyth FT_FRAME_SHORT ( ySuperscriptYOffset ), 1281*37da2899SCharles.Forsyth FT_FRAME_SHORT ( yStrikeoutSize ), 1282*37da2899SCharles.Forsyth FT_FRAME_SHORT ( yStrikeoutPosition ), 1283*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sFamilyClass ), 1284*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[0] ), 1285*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[1] ), 1286*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[2] ), 1287*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[3] ), 1288*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[4] ), 1289*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[5] ), 1290*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[6] ), 1291*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[7] ), 1292*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[8] ), 1293*37da2899SCharles.Forsyth FT_FRAME_BYTE ( panose[9] ), 1294*37da2899SCharles.Forsyth FT_FRAME_ULONG ( ulUnicodeRange1 ), 1295*37da2899SCharles.Forsyth FT_FRAME_ULONG ( ulUnicodeRange2 ), 1296*37da2899SCharles.Forsyth FT_FRAME_ULONG ( ulUnicodeRange3 ), 1297*37da2899SCharles.Forsyth FT_FRAME_ULONG ( ulUnicodeRange4 ), 1298*37da2899SCharles.Forsyth FT_FRAME_BYTE ( achVendID[0] ), 1299*37da2899SCharles.Forsyth FT_FRAME_BYTE ( achVendID[1] ), 1300*37da2899SCharles.Forsyth FT_FRAME_BYTE ( achVendID[2] ), 1301*37da2899SCharles.Forsyth FT_FRAME_BYTE ( achVendID[3] ), 1302*37da2899SCharles.Forsyth 1303*37da2899SCharles.Forsyth FT_FRAME_USHORT( fsSelection ), 1304*37da2899SCharles.Forsyth FT_FRAME_USHORT( usFirstCharIndex ), 1305*37da2899SCharles.Forsyth FT_FRAME_USHORT( usLastCharIndex ), 1306*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sTypoAscender ), 1307*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sTypoDescender ), 1308*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sTypoLineGap ), 1309*37da2899SCharles.Forsyth FT_FRAME_USHORT( usWinAscent ), 1310*37da2899SCharles.Forsyth FT_FRAME_USHORT( usWinDescent ), 1311*37da2899SCharles.Forsyth FT_FRAME_END 1312*37da2899SCharles.Forsyth }; 1313*37da2899SCharles.Forsyth 1314*37da2899SCharles.Forsyth const FT_Frame_Field os2_fields_extra[] = 1315*37da2899SCharles.Forsyth { 1316*37da2899SCharles.Forsyth FT_FRAME_START( 8 ), 1317*37da2899SCharles.Forsyth FT_FRAME_ULONG( ulCodePageRange1 ), 1318*37da2899SCharles.Forsyth FT_FRAME_ULONG( ulCodePageRange2 ), 1319*37da2899SCharles.Forsyth FT_FRAME_END 1320*37da2899SCharles.Forsyth }; 1321*37da2899SCharles.Forsyth 1322*37da2899SCharles.Forsyth const FT_Frame_Field os2_fields_extra2[] = 1323*37da2899SCharles.Forsyth { 1324*37da2899SCharles.Forsyth FT_FRAME_START( 10 ), 1325*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sxHeight ), 1326*37da2899SCharles.Forsyth FT_FRAME_SHORT ( sCapHeight ), 1327*37da2899SCharles.Forsyth FT_FRAME_USHORT( usDefaultChar ), 1328*37da2899SCharles.Forsyth FT_FRAME_USHORT( usBreakChar ), 1329*37da2899SCharles.Forsyth FT_FRAME_USHORT( usMaxContext ), 1330*37da2899SCharles.Forsyth FT_FRAME_END 1331*37da2899SCharles.Forsyth }; 1332*37da2899SCharles.Forsyth 1333*37da2899SCharles.Forsyth 1334*37da2899SCharles.Forsyth FT_TRACE2(( "OS/2 Table " )); 1335*37da2899SCharles.Forsyth 1336*37da2899SCharles.Forsyth /* We now support old Mac fonts where the OS/2 table doesn't */ 1337*37da2899SCharles.Forsyth /* exist. Simply put, we set the `version' field to 0xFFFF */ 1338*37da2899SCharles.Forsyth /* and test this value each time we need to access the table. */ 1339*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_OS2, stream, 0 ); 1340*37da2899SCharles.Forsyth if ( error ) 1341*37da2899SCharles.Forsyth { 1342*37da2899SCharles.Forsyth FT_TRACE2(( "is missing!\n" )); 1343*37da2899SCharles.Forsyth face->os2.version = 0xFFFFU; 1344*37da2899SCharles.Forsyth error = SFNT_Err_Ok; 1345*37da2899SCharles.Forsyth goto Exit; 1346*37da2899SCharles.Forsyth } 1347*37da2899SCharles.Forsyth 1348*37da2899SCharles.Forsyth os2 = &face->os2; 1349*37da2899SCharles.Forsyth 1350*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) ) 1351*37da2899SCharles.Forsyth goto Exit; 1352*37da2899SCharles.Forsyth 1353*37da2899SCharles.Forsyth os2->ulCodePageRange1 = 0; 1354*37da2899SCharles.Forsyth os2->ulCodePageRange2 = 0; 1355*37da2899SCharles.Forsyth os2->sxHeight = 0; 1356*37da2899SCharles.Forsyth os2->sCapHeight = 0; 1357*37da2899SCharles.Forsyth os2->usDefaultChar = 0; 1358*37da2899SCharles.Forsyth os2->usBreakChar = 0; 1359*37da2899SCharles.Forsyth os2->usMaxContext = 0; 1360*37da2899SCharles.Forsyth 1361*37da2899SCharles.Forsyth if ( os2->version >= 0x0001 ) 1362*37da2899SCharles.Forsyth { 1363*37da2899SCharles.Forsyth /* only version 1 tables */ 1364*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) ) 1365*37da2899SCharles.Forsyth goto Exit; 1366*37da2899SCharles.Forsyth 1367*37da2899SCharles.Forsyth if ( os2->version >= 0x0002 ) 1368*37da2899SCharles.Forsyth { 1369*37da2899SCharles.Forsyth /* only version 2 tables */ 1370*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) ) 1371*37da2899SCharles.Forsyth goto Exit; 1372*37da2899SCharles.Forsyth } 1373*37da2899SCharles.Forsyth } 1374*37da2899SCharles.Forsyth 1375*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 1376*37da2899SCharles.Forsyth 1377*37da2899SCharles.Forsyth Exit: 1378*37da2899SCharles.Forsyth return error; 1379*37da2899SCharles.Forsyth } 1380*37da2899SCharles.Forsyth 1381*37da2899SCharles.Forsyth 1382*37da2899SCharles.Forsyth /*************************************************************************/ 1383*37da2899SCharles.Forsyth /* */ 1384*37da2899SCharles.Forsyth /* <Function> */ 1385*37da2899SCharles.Forsyth /* tt_face_load_postscript */ 1386*37da2899SCharles.Forsyth /* */ 1387*37da2899SCharles.Forsyth /* <Description> */ 1388*37da2899SCharles.Forsyth /* Loads the Postscript table. */ 1389*37da2899SCharles.Forsyth /* */ 1390*37da2899SCharles.Forsyth /* <Input> */ 1391*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1392*37da2899SCharles.Forsyth /* */ 1393*37da2899SCharles.Forsyth /* stream :: A handle to the input stream. */ 1394*37da2899SCharles.Forsyth /* */ 1395*37da2899SCharles.Forsyth /* <Return> */ 1396*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1397*37da2899SCharles.Forsyth /* */ 1398*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_postscript(TT_Face face,FT_Stream stream)1399*37da2899SCharles.Forsyth tt_face_load_postscript( TT_Face face, 1400*37da2899SCharles.Forsyth FT_Stream stream ) 1401*37da2899SCharles.Forsyth { 1402*37da2899SCharles.Forsyth FT_Error error; 1403*37da2899SCharles.Forsyth TT_Postscript* post = &face->postscript; 1404*37da2899SCharles.Forsyth 1405*37da2899SCharles.Forsyth static const FT_Frame_Field post_fields[] = 1406*37da2899SCharles.Forsyth { 1407*37da2899SCharles.Forsyth #undef FT_STRUCTURE 1408*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_Postscript 1409*37da2899SCharles.Forsyth 1410*37da2899SCharles.Forsyth FT_FRAME_START( 32 ), 1411*37da2899SCharles.Forsyth FT_FRAME_ULONG( FormatType ), 1412*37da2899SCharles.Forsyth FT_FRAME_ULONG( italicAngle ), 1413*37da2899SCharles.Forsyth FT_FRAME_SHORT( underlinePosition ), 1414*37da2899SCharles.Forsyth FT_FRAME_SHORT( underlineThickness ), 1415*37da2899SCharles.Forsyth FT_FRAME_ULONG( isFixedPitch ), 1416*37da2899SCharles.Forsyth FT_FRAME_ULONG( minMemType42 ), 1417*37da2899SCharles.Forsyth FT_FRAME_ULONG( maxMemType42 ), 1418*37da2899SCharles.Forsyth FT_FRAME_ULONG( minMemType1 ), 1419*37da2899SCharles.Forsyth FT_FRAME_ULONG( maxMemType1 ), 1420*37da2899SCharles.Forsyth FT_FRAME_END 1421*37da2899SCharles.Forsyth }; 1422*37da2899SCharles.Forsyth 1423*37da2899SCharles.Forsyth 1424*37da2899SCharles.Forsyth FT_TRACE2(( "PostScript " )); 1425*37da2899SCharles.Forsyth 1426*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_post, stream, 0 ); 1427*37da2899SCharles.Forsyth if ( error ) 1428*37da2899SCharles.Forsyth return SFNT_Err_Post_Table_Missing; 1429*37da2899SCharles.Forsyth 1430*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) 1431*37da2899SCharles.Forsyth return error; 1432*37da2899SCharles.Forsyth 1433*37da2899SCharles.Forsyth /* we don't load the glyph names, we do that in another */ 1434*37da2899SCharles.Forsyth /* module (ttpost). */ 1435*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 1436*37da2899SCharles.Forsyth 1437*37da2899SCharles.Forsyth return SFNT_Err_Ok; 1438*37da2899SCharles.Forsyth } 1439*37da2899SCharles.Forsyth 1440*37da2899SCharles.Forsyth 1441*37da2899SCharles.Forsyth /*************************************************************************/ 1442*37da2899SCharles.Forsyth /* */ 1443*37da2899SCharles.Forsyth /* <Function> */ 1444*37da2899SCharles.Forsyth /* tt_face_load_pclt */ 1445*37da2899SCharles.Forsyth /* */ 1446*37da2899SCharles.Forsyth /* <Description> */ 1447*37da2899SCharles.Forsyth /* Loads the PCL 5 Table. */ 1448*37da2899SCharles.Forsyth /* */ 1449*37da2899SCharles.Forsyth /* <Input> */ 1450*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1451*37da2899SCharles.Forsyth /* */ 1452*37da2899SCharles.Forsyth /* stream :: A handle to the input stream. */ 1453*37da2899SCharles.Forsyth /* */ 1454*37da2899SCharles.Forsyth /* <Return> */ 1455*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1456*37da2899SCharles.Forsyth /* */ 1457*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_pclt(TT_Face face,FT_Stream stream)1458*37da2899SCharles.Forsyth tt_face_load_pclt( TT_Face face, 1459*37da2899SCharles.Forsyth FT_Stream stream ) 1460*37da2899SCharles.Forsyth { 1461*37da2899SCharles.Forsyth static const FT_Frame_Field pclt_fields[] = 1462*37da2899SCharles.Forsyth { 1463*37da2899SCharles.Forsyth #undef FT_STRUCTURE 1464*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_PCLT 1465*37da2899SCharles.Forsyth 1466*37da2899SCharles.Forsyth FT_FRAME_START( 54 ), 1467*37da2899SCharles.Forsyth FT_FRAME_ULONG ( Version ), 1468*37da2899SCharles.Forsyth FT_FRAME_ULONG ( FontNumber ), 1469*37da2899SCharles.Forsyth FT_FRAME_USHORT( Pitch ), 1470*37da2899SCharles.Forsyth FT_FRAME_USHORT( xHeight ), 1471*37da2899SCharles.Forsyth FT_FRAME_USHORT( Style ), 1472*37da2899SCharles.Forsyth FT_FRAME_USHORT( TypeFamily ), 1473*37da2899SCharles.Forsyth FT_FRAME_USHORT( CapHeight ), 1474*37da2899SCharles.Forsyth FT_FRAME_BYTES ( TypeFace, 16 ), 1475*37da2899SCharles.Forsyth FT_FRAME_BYTES ( CharacterComplement, 8 ), 1476*37da2899SCharles.Forsyth FT_FRAME_BYTES ( FileName, 6 ), 1477*37da2899SCharles.Forsyth FT_FRAME_CHAR ( StrokeWeight ), 1478*37da2899SCharles.Forsyth FT_FRAME_CHAR ( WidthType ), 1479*37da2899SCharles.Forsyth FT_FRAME_BYTE ( SerifStyle ), 1480*37da2899SCharles.Forsyth FT_FRAME_BYTE ( Reserved ), 1481*37da2899SCharles.Forsyth FT_FRAME_END 1482*37da2899SCharles.Forsyth }; 1483*37da2899SCharles.Forsyth 1484*37da2899SCharles.Forsyth FT_Error error; 1485*37da2899SCharles.Forsyth TT_PCLT* pclt = &face->pclt; 1486*37da2899SCharles.Forsyth 1487*37da2899SCharles.Forsyth 1488*37da2899SCharles.Forsyth FT_TRACE2(( "PCLT " )); 1489*37da2899SCharles.Forsyth 1490*37da2899SCharles.Forsyth /* optional table */ 1491*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_PCLT, stream, 0 ); 1492*37da2899SCharles.Forsyth if ( error ) 1493*37da2899SCharles.Forsyth { 1494*37da2899SCharles.Forsyth FT_TRACE2(( "missing (optional)\n" )); 1495*37da2899SCharles.Forsyth pclt->Version = 0; 1496*37da2899SCharles.Forsyth return SFNT_Err_Ok; 1497*37da2899SCharles.Forsyth } 1498*37da2899SCharles.Forsyth 1499*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) 1500*37da2899SCharles.Forsyth goto Exit; 1501*37da2899SCharles.Forsyth 1502*37da2899SCharles.Forsyth FT_TRACE2(( "loaded\n" )); 1503*37da2899SCharles.Forsyth 1504*37da2899SCharles.Forsyth Exit: 1505*37da2899SCharles.Forsyth return error; 1506*37da2899SCharles.Forsyth } 1507*37da2899SCharles.Forsyth 1508*37da2899SCharles.Forsyth 1509*37da2899SCharles.Forsyth /*************************************************************************/ 1510*37da2899SCharles.Forsyth /* */ 1511*37da2899SCharles.Forsyth /* <Function> */ 1512*37da2899SCharles.Forsyth /* tt_face_load_gasp */ 1513*37da2899SCharles.Forsyth /* */ 1514*37da2899SCharles.Forsyth /* <Description> */ 1515*37da2899SCharles.Forsyth /* Loads the `gasp' table into a face object. */ 1516*37da2899SCharles.Forsyth /* */ 1517*37da2899SCharles.Forsyth /* <Input> */ 1518*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1519*37da2899SCharles.Forsyth /* */ 1520*37da2899SCharles.Forsyth /* stream :: The input stream. */ 1521*37da2899SCharles.Forsyth /* */ 1522*37da2899SCharles.Forsyth /* <Return> */ 1523*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1524*37da2899SCharles.Forsyth /* */ 1525*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_gasp(TT_Face face,FT_Stream stream)1526*37da2899SCharles.Forsyth tt_face_load_gasp( TT_Face face, 1527*37da2899SCharles.Forsyth FT_Stream stream ) 1528*37da2899SCharles.Forsyth { 1529*37da2899SCharles.Forsyth FT_Error error; 1530*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1531*37da2899SCharles.Forsyth 1532*37da2899SCharles.Forsyth FT_UInt j,num_ranges; 1533*37da2899SCharles.Forsyth TT_GaspRange gaspranges; 1534*37da2899SCharles.Forsyth 1535*37da2899SCharles.Forsyth 1536*37da2899SCharles.Forsyth FT_TRACE2(( "tt_face_load_gasp: %08p\n", face )); 1537*37da2899SCharles.Forsyth 1538*37da2899SCharles.Forsyth /* the gasp table is optional */ 1539*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_gasp, stream, 0 ); 1540*37da2899SCharles.Forsyth if ( error ) 1541*37da2899SCharles.Forsyth return SFNT_Err_Ok; 1542*37da2899SCharles.Forsyth 1543*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 4L ) ) 1544*37da2899SCharles.Forsyth goto Exit; 1545*37da2899SCharles.Forsyth 1546*37da2899SCharles.Forsyth face->gasp.version = FT_GET_USHORT(); 1547*37da2899SCharles.Forsyth face->gasp.numRanges = FT_GET_USHORT(); 1548*37da2899SCharles.Forsyth 1549*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1550*37da2899SCharles.Forsyth 1551*37da2899SCharles.Forsyth num_ranges = face->gasp.numRanges; 1552*37da2899SCharles.Forsyth FT_TRACE3(( "number of ranges = %d\n", num_ranges )); 1553*37da2899SCharles.Forsyth 1554*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( gaspranges, num_ranges ) || 1555*37da2899SCharles.Forsyth FT_FRAME_ENTER( num_ranges * 4L ) ) 1556*37da2899SCharles.Forsyth goto Exit; 1557*37da2899SCharles.Forsyth 1558*37da2899SCharles.Forsyth face->gasp.gaspRanges = gaspranges; 1559*37da2899SCharles.Forsyth 1560*37da2899SCharles.Forsyth for ( j = 0; j < num_ranges; j++ ) 1561*37da2899SCharles.Forsyth { 1562*37da2899SCharles.Forsyth gaspranges[j].maxPPEM = FT_GET_USHORT(); 1563*37da2899SCharles.Forsyth gaspranges[j].gaspFlag = FT_GET_USHORT(); 1564*37da2899SCharles.Forsyth 1565*37da2899SCharles.Forsyth FT_TRACE3(( " [max:%d flag:%d]", 1566*37da2899SCharles.Forsyth gaspranges[j].maxPPEM, 1567*37da2899SCharles.Forsyth gaspranges[j].gaspFlag )); 1568*37da2899SCharles.Forsyth } 1569*37da2899SCharles.Forsyth FT_TRACE3(( "\n" )); 1570*37da2899SCharles.Forsyth 1571*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1572*37da2899SCharles.Forsyth FT_TRACE2(( "GASP loaded\n" )); 1573*37da2899SCharles.Forsyth 1574*37da2899SCharles.Forsyth Exit: 1575*37da2899SCharles.Forsyth return error; 1576*37da2899SCharles.Forsyth } 1577*37da2899SCharles.Forsyth 1578*37da2899SCharles.Forsyth 1579*37da2899SCharles.Forsyth FT_CALLBACK_DEF( int ) 1580*37da2899SCharles.Forsyth tt_kern_pair_compare( const void* a, 1581*37da2899SCharles.Forsyth const void* b ); 1582*37da2899SCharles.Forsyth 1583*37da2899SCharles.Forsyth 1584*37da2899SCharles.Forsyth /*************************************************************************/ 1585*37da2899SCharles.Forsyth /* */ 1586*37da2899SCharles.Forsyth /* <Function> */ 1587*37da2899SCharles.Forsyth /* tt_face_load_kern */ 1588*37da2899SCharles.Forsyth /* */ 1589*37da2899SCharles.Forsyth /* <Description> */ 1590*37da2899SCharles.Forsyth /* Loads the first kerning table with format 0 in the font. Only */ 1591*37da2899SCharles.Forsyth /* accepts the first horizontal kerning table. Developers should use */ 1592*37da2899SCharles.Forsyth /* the `ftxkern' extension to access other kerning tables in the font */ 1593*37da2899SCharles.Forsyth /* file, if they really want to. */ 1594*37da2899SCharles.Forsyth /* */ 1595*37da2899SCharles.Forsyth /* <Input> */ 1596*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1597*37da2899SCharles.Forsyth /* */ 1598*37da2899SCharles.Forsyth /* stream :: The input stream. */ 1599*37da2899SCharles.Forsyth /* */ 1600*37da2899SCharles.Forsyth /* <Return> */ 1601*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1602*37da2899SCharles.Forsyth /* */ 1603*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_kern(TT_Face face,FT_Stream stream)1604*37da2899SCharles.Forsyth tt_face_load_kern( TT_Face face, 1605*37da2899SCharles.Forsyth FT_Stream stream ) 1606*37da2899SCharles.Forsyth { 1607*37da2899SCharles.Forsyth FT_Error error; 1608*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1609*37da2899SCharles.Forsyth 1610*37da2899SCharles.Forsyth FT_UInt n, num_tables; 1611*37da2899SCharles.Forsyth 1612*37da2899SCharles.Forsyth 1613*37da2899SCharles.Forsyth /* the kern table is optional; exit silently if it is missing */ 1614*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_kern, stream, 0 ); 1615*37da2899SCharles.Forsyth if ( error ) 1616*37da2899SCharles.Forsyth return SFNT_Err_Ok; 1617*37da2899SCharles.Forsyth 1618*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 4L ) ) 1619*37da2899SCharles.Forsyth goto Exit; 1620*37da2899SCharles.Forsyth 1621*37da2899SCharles.Forsyth (void)FT_GET_USHORT(); /* version */ 1622*37da2899SCharles.Forsyth num_tables = FT_GET_USHORT(); 1623*37da2899SCharles.Forsyth 1624*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1625*37da2899SCharles.Forsyth 1626*37da2899SCharles.Forsyth for ( n = 0; n < num_tables; n++ ) 1627*37da2899SCharles.Forsyth { 1628*37da2899SCharles.Forsyth FT_UInt coverage; 1629*37da2899SCharles.Forsyth FT_UInt length; 1630*37da2899SCharles.Forsyth 1631*37da2899SCharles.Forsyth 1632*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 6L ) ) 1633*37da2899SCharles.Forsyth goto Exit; 1634*37da2899SCharles.Forsyth 1635*37da2899SCharles.Forsyth (void)FT_GET_USHORT(); /* version */ 1636*37da2899SCharles.Forsyth length = FT_GET_USHORT() - 6; /* substract header length */ 1637*37da2899SCharles.Forsyth coverage = FT_GET_USHORT(); 1638*37da2899SCharles.Forsyth 1639*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1640*37da2899SCharles.Forsyth 1641*37da2899SCharles.Forsyth if ( coverage == 0x0001 ) 1642*37da2899SCharles.Forsyth { 1643*37da2899SCharles.Forsyth FT_UInt num_pairs; 1644*37da2899SCharles.Forsyth TT_Kern0_Pair pair; 1645*37da2899SCharles.Forsyth TT_Kern0_Pair limit; 1646*37da2899SCharles.Forsyth 1647*37da2899SCharles.Forsyth 1648*37da2899SCharles.Forsyth /* found a horizontal format 0 kerning table! */ 1649*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 8L ) ) 1650*37da2899SCharles.Forsyth goto Exit; 1651*37da2899SCharles.Forsyth 1652*37da2899SCharles.Forsyth num_pairs = FT_GET_USHORT(); 1653*37da2899SCharles.Forsyth 1654*37da2899SCharles.Forsyth /* skip the rest */ 1655*37da2899SCharles.Forsyth 1656*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1657*37da2899SCharles.Forsyth 1658*37da2899SCharles.Forsyth /* allocate array of kerning pairs */ 1659*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( face->kern_pairs, num_pairs ) || 1660*37da2899SCharles.Forsyth FT_FRAME_ENTER( 6L * num_pairs ) ) 1661*37da2899SCharles.Forsyth goto Exit; 1662*37da2899SCharles.Forsyth 1663*37da2899SCharles.Forsyth pair = face->kern_pairs; 1664*37da2899SCharles.Forsyth limit = pair + num_pairs; 1665*37da2899SCharles.Forsyth for ( ; pair < limit; pair++ ) 1666*37da2899SCharles.Forsyth { 1667*37da2899SCharles.Forsyth pair->left = FT_GET_USHORT(); 1668*37da2899SCharles.Forsyth pair->right = FT_GET_USHORT(); 1669*37da2899SCharles.Forsyth pair->value = FT_GET_USHORT(); 1670*37da2899SCharles.Forsyth } 1671*37da2899SCharles.Forsyth 1672*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1673*37da2899SCharles.Forsyth 1674*37da2899SCharles.Forsyth face->num_kern_pairs = num_pairs; 1675*37da2899SCharles.Forsyth face->kern_table_index = n; 1676*37da2899SCharles.Forsyth 1677*37da2899SCharles.Forsyth /* ensure that the kerning pair table is sorted (yes, some */ 1678*37da2899SCharles.Forsyth /* fonts have unsorted tables!) */ 1679*37da2899SCharles.Forsyth { 1680*37da2899SCharles.Forsyth FT_UInt i; 1681*37da2899SCharles.Forsyth TT_Kern0_Pair pair0; 1682*37da2899SCharles.Forsyth 1683*37da2899SCharles.Forsyth 1684*37da2899SCharles.Forsyth pair0 = face->kern_pairs; 1685*37da2899SCharles.Forsyth 1686*37da2899SCharles.Forsyth for ( i = 1; i < num_pairs; i++, pair0++ ) 1687*37da2899SCharles.Forsyth { 1688*37da2899SCharles.Forsyth if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 ) 1689*37da2899SCharles.Forsyth { 1690*37da2899SCharles.Forsyth ft_qsort( (void*)face->kern_pairs, (int)num_pairs, 1691*37da2899SCharles.Forsyth sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare ); 1692*37da2899SCharles.Forsyth break; 1693*37da2899SCharles.Forsyth } 1694*37da2899SCharles.Forsyth } 1695*37da2899SCharles.Forsyth } 1696*37da2899SCharles.Forsyth 1697*37da2899SCharles.Forsyth goto Exit; 1698*37da2899SCharles.Forsyth } 1699*37da2899SCharles.Forsyth 1700*37da2899SCharles.Forsyth if ( FT_STREAM_SKIP( length ) ) 1701*37da2899SCharles.Forsyth goto Exit; 1702*37da2899SCharles.Forsyth } 1703*37da2899SCharles.Forsyth 1704*37da2899SCharles.Forsyth /* no kern table found -- doesn't matter */ 1705*37da2899SCharles.Forsyth face->kern_table_index = -1; 1706*37da2899SCharles.Forsyth face->num_kern_pairs = 0; 1707*37da2899SCharles.Forsyth face->kern_pairs = NULL; 1708*37da2899SCharles.Forsyth 1709*37da2899SCharles.Forsyth Exit: 1710*37da2899SCharles.Forsyth return error; 1711*37da2899SCharles.Forsyth } 1712*37da2899SCharles.Forsyth 1713*37da2899SCharles.Forsyth 1714*37da2899SCharles.Forsyth #undef TT_KERN_INDEX 1715*37da2899SCharles.Forsyth #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) 1716*37da2899SCharles.Forsyth 1717*37da2899SCharles.Forsyth 1718*37da2899SCharles.Forsyth FT_CALLBACK_DEF( int ) tt_kern_pair_compare(const void * a,const void * b)1719*37da2899SCharles.Forsyth tt_kern_pair_compare( const void* a, 1720*37da2899SCharles.Forsyth const void* b ) 1721*37da2899SCharles.Forsyth { 1722*37da2899SCharles.Forsyth TT_Kern0_Pair pair1 = (TT_Kern0_Pair)a; 1723*37da2899SCharles.Forsyth TT_Kern0_Pair pair2 = (TT_Kern0_Pair)b; 1724*37da2899SCharles.Forsyth 1725*37da2899SCharles.Forsyth FT_ULong index1 = TT_KERN_INDEX( pair1->left, pair1->right ); 1726*37da2899SCharles.Forsyth FT_ULong index2 = TT_KERN_INDEX( pair2->left, pair2->right ); 1727*37da2899SCharles.Forsyth 1728*37da2899SCharles.Forsyth 1729*37da2899SCharles.Forsyth return ( index1 < index2 ? -1 : 1730*37da2899SCharles.Forsyth ( index1 > index2 ? 1 : 0 )); 1731*37da2899SCharles.Forsyth } 1732*37da2899SCharles.Forsyth 1733*37da2899SCharles.Forsyth 1734*37da2899SCharles.Forsyth #undef TT_KERN_INDEX 1735*37da2899SCharles.Forsyth 1736*37da2899SCharles.Forsyth 1737*37da2899SCharles.Forsyth /*************************************************************************/ 1738*37da2899SCharles.Forsyth /* */ 1739*37da2899SCharles.Forsyth /* <Function> */ 1740*37da2899SCharles.Forsyth /* tt_face_load_hdmx */ 1741*37da2899SCharles.Forsyth /* */ 1742*37da2899SCharles.Forsyth /* <Description> */ 1743*37da2899SCharles.Forsyth /* Loads the horizontal device metrics table. */ 1744*37da2899SCharles.Forsyth /* */ 1745*37da2899SCharles.Forsyth /* <Input> */ 1746*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1747*37da2899SCharles.Forsyth /* */ 1748*37da2899SCharles.Forsyth /* stream :: A handle to the input stream. */ 1749*37da2899SCharles.Forsyth /* */ 1750*37da2899SCharles.Forsyth /* <Return> */ 1751*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 1752*37da2899SCharles.Forsyth /* */ 1753*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_hdmx(TT_Face face,FT_Stream stream)1754*37da2899SCharles.Forsyth tt_face_load_hdmx( TT_Face face, 1755*37da2899SCharles.Forsyth FT_Stream stream ) 1756*37da2899SCharles.Forsyth { 1757*37da2899SCharles.Forsyth FT_Error error; 1758*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1759*37da2899SCharles.Forsyth 1760*37da2899SCharles.Forsyth TT_Hdmx hdmx = &face->hdmx; 1761*37da2899SCharles.Forsyth FT_Long num_glyphs; 1762*37da2899SCharles.Forsyth FT_Long record_size; 1763*37da2899SCharles.Forsyth 1764*37da2899SCharles.Forsyth 1765*37da2899SCharles.Forsyth hdmx->version = 0; 1766*37da2899SCharles.Forsyth hdmx->num_records = 0; 1767*37da2899SCharles.Forsyth hdmx->records = 0; 1768*37da2899SCharles.Forsyth 1769*37da2899SCharles.Forsyth /* this table is optional */ 1770*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_hdmx, stream, 0 ); 1771*37da2899SCharles.Forsyth if ( error ) 1772*37da2899SCharles.Forsyth return SFNT_Err_Ok; 1773*37da2899SCharles.Forsyth 1774*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 8L ) ) 1775*37da2899SCharles.Forsyth goto Exit; 1776*37da2899SCharles.Forsyth 1777*37da2899SCharles.Forsyth hdmx->version = FT_GET_USHORT(); 1778*37da2899SCharles.Forsyth hdmx->num_records = FT_GET_SHORT(); 1779*37da2899SCharles.Forsyth record_size = FT_GET_LONG(); 1780*37da2899SCharles.Forsyth 1781*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1782*37da2899SCharles.Forsyth 1783*37da2899SCharles.Forsyth /* Only recognize format 0 */ 1784*37da2899SCharles.Forsyth if ( hdmx->version != 0 ) 1785*37da2899SCharles.Forsyth goto Exit; 1786*37da2899SCharles.Forsyth 1787*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( hdmx->records, hdmx->num_records ) ) 1788*37da2899SCharles.Forsyth goto Exit; 1789*37da2899SCharles.Forsyth 1790*37da2899SCharles.Forsyth num_glyphs = face->root.num_glyphs; 1791*37da2899SCharles.Forsyth record_size -= num_glyphs + 2; 1792*37da2899SCharles.Forsyth 1793*37da2899SCharles.Forsyth { 1794*37da2899SCharles.Forsyth TT_HdmxEntry cur = hdmx->records; 1795*37da2899SCharles.Forsyth TT_HdmxEntry limit = cur + hdmx->num_records; 1796*37da2899SCharles.Forsyth 1797*37da2899SCharles.Forsyth 1798*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 1799*37da2899SCharles.Forsyth { 1800*37da2899SCharles.Forsyth /* read record */ 1801*37da2899SCharles.Forsyth if ( FT_READ_BYTE( cur->ppem ) || 1802*37da2899SCharles.Forsyth FT_READ_BYTE( cur->max_width ) ) 1803*37da2899SCharles.Forsyth goto Exit; 1804*37da2899SCharles.Forsyth 1805*37da2899SCharles.Forsyth if ( FT_ALLOC( cur->widths, num_glyphs ) || 1806*37da2899SCharles.Forsyth FT_STREAM_READ( cur->widths, num_glyphs ) ) 1807*37da2899SCharles.Forsyth goto Exit; 1808*37da2899SCharles.Forsyth 1809*37da2899SCharles.Forsyth /* skip padding bytes */ 1810*37da2899SCharles.Forsyth if ( record_size > 0 && FT_STREAM_SKIP( record_size ) ) 1811*37da2899SCharles.Forsyth goto Exit; 1812*37da2899SCharles.Forsyth } 1813*37da2899SCharles.Forsyth } 1814*37da2899SCharles.Forsyth 1815*37da2899SCharles.Forsyth Exit: 1816*37da2899SCharles.Forsyth return error; 1817*37da2899SCharles.Forsyth } 1818*37da2899SCharles.Forsyth 1819*37da2899SCharles.Forsyth 1820*37da2899SCharles.Forsyth /*************************************************************************/ 1821*37da2899SCharles.Forsyth /* */ 1822*37da2899SCharles.Forsyth /* <Function> */ 1823*37da2899SCharles.Forsyth /* tt_face_free_hdmx */ 1824*37da2899SCharles.Forsyth /* */ 1825*37da2899SCharles.Forsyth /* <Description> */ 1826*37da2899SCharles.Forsyth /* Frees the horizontal device metrics table. */ 1827*37da2899SCharles.Forsyth /* */ 1828*37da2899SCharles.Forsyth /* <Input> */ 1829*37da2899SCharles.Forsyth /* face :: A handle to the target face object. */ 1830*37da2899SCharles.Forsyth /* */ 1831*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) tt_face_free_hdmx(TT_Face face)1832*37da2899SCharles.Forsyth tt_face_free_hdmx( TT_Face face ) 1833*37da2899SCharles.Forsyth { 1834*37da2899SCharles.Forsyth if ( face ) 1835*37da2899SCharles.Forsyth { 1836*37da2899SCharles.Forsyth FT_Int n; 1837*37da2899SCharles.Forsyth FT_Memory memory = face->root.driver->root.memory; 1838*37da2899SCharles.Forsyth 1839*37da2899SCharles.Forsyth 1840*37da2899SCharles.Forsyth for ( n = 0; n < face->hdmx.num_records; n++ ) 1841*37da2899SCharles.Forsyth FT_FREE( face->hdmx.records[n].widths ); 1842*37da2899SCharles.Forsyth 1843*37da2899SCharles.Forsyth FT_FREE( face->hdmx.records ); 1844*37da2899SCharles.Forsyth face->hdmx.num_records = 0; 1845*37da2899SCharles.Forsyth } 1846*37da2899SCharles.Forsyth } 1847*37da2899SCharles.Forsyth 1848*37da2899SCharles.Forsyth 1849*37da2899SCharles.Forsyth /* END */ 1850