1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849 |
- /***************************************************************************/
- /* */
- /* ttload.c */
- /* */
- /* Load the basic TrueType tables, i.e., tables that can be either in */
- /* TTF or OTF fonts (body). */
- /* */
- /* Copyright 1996-2001, 2002 by */
- /* David Turner, Robert Wilhelm, and Werner Lemberg. */
- /* */
- /* This file is part of the FreeType project, and may only be used, */
- /* modified, and distributed under the terms of the FreeType project */
- /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
- /* this file you indicate that you have read the license and */
- /* understand and accept it fully. */
- /* */
- /***************************************************************************/
- #include <ft2build.h>
- #include FT_INTERNAL_DEBUG_H
- #include FT_INTERNAL_STREAM_H
- #include FT_TRUETYPE_TAGS_H
- #include "ttload.h"
- #include "ttcmap.h"
- #include "sferrors.h"
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
- #undef FT_COMPONENT
- #define FT_COMPONENT trace_ttload
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_lookup_table */
- /* */
- /* <Description> */
- /* Looks for a TrueType table by name. */
- /* */
- /* <Input> */
- /* face :: A face object handle. */
- /* */
- /* tag :: The searched tag. */
- /* */
- /* <Return> */
- /* A pointer to the table directory entry. 0 if not found. */
- /* */
- FT_LOCAL_DEF( TT_Table )
- tt_face_lookup_table( TT_Face face,
- FT_ULong tag )
- {
- TT_Table entry;
- TT_Table limit;
- FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
- face,
- (FT_Char)( tag >> 24 ),
- (FT_Char)( tag >> 16 ),
- (FT_Char)( tag >> 8 ),
- (FT_Char)( tag ) ));
- entry = face->dir_tables;
- limit = entry + face->num_tables;
- for ( ; entry < limit; entry++ )
- {
- /* For compatibility with Windows, we consider 0-length */
- /* tables the same as missing tables. */
- if ( entry->Tag == tag && entry->Length != 0 )
- {
- FT_TRACE3(( "found table.\n" ));
- return entry;
- }
- }
- FT_TRACE3(( "could not find table!\n" ));
- return 0;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_goto_table */
- /* */
- /* <Description> */
- /* Looks for a TrueType table by name, then seek a stream to it. */
- /* */
- /* <Input> */
- /* face :: A face object handle. */
- /* */
- /* tag :: The searched tag. */
- /* */
- /* stream :: The stream to seek when the table is found. */
- /* */
- /* <Output> */
- /* length :: The length of the table if found, undefined otherwise. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_goto_table( TT_Face face,
- FT_ULong tag,
- FT_Stream stream,
- FT_ULong* length )
- {
- TT_Table table;
- FT_Error error;
- table = tt_face_lookup_table( face, tag );
- if ( table )
- {
- if ( length )
- *length = table->Length;
- if ( FT_STREAM_SEEK( table->Offset ) )
- goto Exit;
- }
- else
- error = SFNT_Err_Table_Missing;
- Exit:
- return error;
- }
- /* In theory, we should check the values of `search_range', */
- /* `entry_selector', and `range_shift' to detect non-SFNT based files */
- /* whose header might also start with 0x100000L (yes, these exist). */
- /* */
- /* Very unfortunately, many TrueType fonts don't have these fields */
- /* set correctly and we must ignore them to support them. An alternative */
- /* way to check the font file is thus to: */
- /* */
- /* - check that `num_tables' is valid */
- /* - look for a "head" table, check its size, and parse it to */
- /* see if its "magic" field is correctly set */
- /* */
- /* When checking directory entries, ignore the tables `glyx' and `locx' */
- /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
- /* Type 42 fonts, and will generally be invalid. */
- /* */
- static FT_Error
- sfnt_dir_check( FT_Stream stream,
- FT_ULong offset,
- FT_UInt num_tables )
- {
- FT_Error error;
- FT_UInt nn, has_head = 0;
- const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
- const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
- static const FT_Frame_Field sfnt_dir_entry_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_TableRec
- FT_FRAME_START( 16 ),
- FT_FRAME_ULONG( Tag ),
- FT_FRAME_ULONG( CheckSum ),
- FT_FRAME_ULONG( Offset ),
- FT_FRAME_ULONG( Length ),
- FT_FRAME_END
- };
- /* if 'num_tables' is 0, read the table count from the file */
- if ( num_tables == 0 )
- {
- FT_ULong format_tag;
- if ( FT_STREAM_SEEK( offset ) ||
- FT_READ_ULONG ( format_tag ) ||
- FT_READ_USHORT( num_tables ) ||
- FT_STREAM_SKIP( 6 ) )
- goto Bad_Format;
- if ( offset + 12 + num_tables*16 > stream->size )
- goto Bad_Format;
- }
- else if ( FT_STREAM_SEEK( offset + 12 ) )
- goto Bad_Format;
- for ( nn = 0; nn < num_tables; nn++ )
- {
- TT_TableRec table;
- if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
- goto Bad_Format;
- if ( table.Offset + table.Length > stream->size &&
- table.Tag != glyx_tag && table.Tag != locx_tag )
- goto Bad_Format;
- if ( table.Tag == TTAG_head )
- {
- FT_UInt32 magic;
- has_head = 1;
- if ( table.Length != 0x36 ||
- FT_STREAM_SEEK( table.Offset + 12 ) ||
- FT_READ_ULONG( magic ) ||
- magic != 0x5F0F3CF5UL )
- goto Bad_Format;
- if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
- goto Bad_Format;
- }
- }
- if ( has_head == 0 )
- goto Bad_Format;
- Exit:
- return error;
- Bad_Format:
- error = FT_Err_Unknown_File_Format;
- goto Exit;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_sfnt_header */
- /* */
- /* <Description> */
- /* Loads the header of a SFNT font file. Supports collections. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* face_index :: If the font is a collection, the number of the font */
- /* in the collection, ignored otherwise. */
- /* */
- /* <Output> */
- /* sfnt :: The SFNT header. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be at the font file's origin. */
- /* */
- /* This function recognizes fonts embedded in a `TrueType collection' */
- /* */
- /* The header will be checked whether it is valid by looking at the */
- /* values of `search_range', `entry_selector', and `range_shift'. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_sfnt_header( TT_Face face,
- FT_Stream stream,
- FT_Long face_index,
- SFNT_Header sfnt )
- {
- FT_Error error;
- FT_ULong format_tag, offset;
- FT_Memory memory = stream->memory;
- static const FT_Frame_Field sfnt_header_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE SFNT_HeaderRec
- FT_FRAME_START( 8 ),
- FT_FRAME_USHORT( num_tables ),
- FT_FRAME_USHORT( search_range ),
- FT_FRAME_USHORT( entry_selector ),
- FT_FRAME_USHORT( range_shift ),
- FT_FRAME_END
- };
- static const FT_Frame_Field ttc_header_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TTC_HeaderRec
- FT_FRAME_START( 8 ),
- FT_FRAME_LONG( version ),
- FT_FRAME_LONG( count ),
- FT_FRAME_END
- };
- FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
- face, face_index ));
- face->ttc_header.tag = 0;
- face->ttc_header.version = 0;
- face->ttc_header.count = 0;
- face->num_tables = 0;
- /* first of all, read the first 4 bytes. If it is `ttcf', then the */
- /* file is a TrueType collection, otherwise it can be any other */
- /* kind of font. */
- /* */
- offset = FT_STREAM_POS();
- if ( FT_READ_ULONG( format_tag ) )
- goto Exit;
- if ( format_tag == TTAG_ttcf )
- {
- FT_Int n;
- FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" ));
- /* It is a TrueType collection, i.e. a file containing several */
- /* font files. Read the font directory now */
- if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
- goto Exit;
- /* now read the offsets of each font in the file */
- if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ||
- FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
- goto Exit;
- for ( n = 0; n < face->ttc_header.count; n++ )
- face->ttc_header.offsets[n] = FT_GET_ULONG();
- FT_FRAME_EXIT();
- /* check face index */
- if ( face_index >= face->ttc_header.count )
- {
- error = SFNT_Err_Bad_Argument;
- goto Exit;
- }
- /* seek to the appropriate TrueType file, then read tag */
- offset = face->ttc_header.offsets[face_index];
- if ( FT_STREAM_SEEK( offset ) ||
- FT_READ_LONG( format_tag ) )
- goto Exit;
- }
- /* the format tag was read, now check the rest of the header */
- sfnt->format_tag = format_tag;
- sfnt->offset = offset;
- if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
- goto Exit;
- /* now check the sfnt directory */
- error = sfnt_dir_check( stream, offset, sfnt->num_tables );
- if ( error )
- {
- FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" ));
- error = SFNT_Err_Unknown_File_Format;
- }
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_directory */
- /* */
- /* <Description> */
- /* Loads the table directory into a face object. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* sfnt :: The SFNT directory header. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The stream cursor must be at the font file's origin. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_directory( TT_Face face,
- FT_Stream stream,
- SFNT_Header sfnt )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- TT_TableRec *entry, *limit;
- FT_TRACE2(( "tt_face_load_directory: %08p\n", face ));
- FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables ));
- FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
- face->num_tables = sfnt->num_tables;
- if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
- goto Exit;
- if ( FT_STREAM_SEEK( sfnt->offset + 12 ) ||
- FT_FRAME_ENTER( face->num_tables * 16L ) )
- goto Exit;
- entry = face->dir_tables;
- limit = entry + face->num_tables;
- for ( ; entry < limit; entry++ )
- { /* loop through the tables and get all entries */
- entry->Tag = FT_GET_TAG4();
- entry->CheckSum = FT_GET_ULONG();
- entry->Offset = FT_GET_LONG();
- entry->Length = FT_GET_LONG();
- FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
- (FT_Char)( entry->Tag >> 24 ),
- (FT_Char)( entry->Tag >> 16 ),
- (FT_Char)( entry->Tag >> 8 ),
- (FT_Char)( entry->Tag ),
- entry->Offset,
- entry->Length ));
- }
- FT_FRAME_EXIT();
- FT_TRACE2(( "Directory loaded\n\n" ));
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_any */
- /* */
- /* <Description> */
- /* Loads any font table into client memory. */
- /* */
- /* <Input> */
- /* face :: The face object to look for. */
- /* */
- /* tag :: The tag of table to load. Use the value 0 if you want */
- /* to access the whole font file, else set this parameter */
- /* to a valid TrueType table tag that you can forge with */
- /* the MAKE_TT_TAG macro. */
- /* */
- /* offset :: The starting offset in the table (or the file if */
- /* tag == 0). */
- /* */
- /* length :: The address of the decision variable: */
- /* */
- /* If length == NULL: */
- /* Loads the whole table. Returns an error if */
- /* `offset' == 0! */
- /* */
- /* If *length == 0: */
- /* Exits immediately; returning the length of the given */
- /* table or of the font file, depending on the value of */
- /* `tag'. */
- /* */
- /* If *length != 0: */
- /* Loads the next `length' bytes of table or font, */
- /* starting at offset `offset' (in table or font too). */
- /* */
- /* <Output> */
- /* buffer :: The address of target buffer. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_any( TT_Face face,
- FT_ULong tag,
- FT_Long offset,
- FT_Byte* buffer,
- FT_ULong* length )
- {
- FT_Error error;
- FT_Stream stream;
- TT_Table table;
- FT_ULong size;
- if ( tag != 0 )
- {
- /* look for tag in font directory */
- table = tt_face_lookup_table( face, tag );
- if ( !table )
- {
- error = SFNT_Err_Table_Missing;
- goto Exit;
- }
- offset += table->Offset;
- size = table->Length;
- }
- else
- /* tag == 0 -- the user wants to access the font file directly */
- size = face->root.stream->size;
- if ( length && *length == 0 )
- {
- *length = size;
- return SFNT_Err_Ok;
- }
- if ( length )
- size = *length;
- stream = face->root.stream;
- /* the `if' is syntactic sugar for picky compilers */
- if ( FT_STREAM_READ_AT( offset, buffer, size ) )
- goto Exit;
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_generic_header */
- /* */
- /* <Description> */
- /* Loads the TrueType table `head' or `bhed'. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
- tt_face_load_generic_header( TT_Face face,
- FT_Stream stream,
- FT_ULong tag )
- {
- FT_Error error;
- TT_Header* header;
- static const FT_Frame_Field header_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_Header
- FT_FRAME_START( 54 ),
- FT_FRAME_ULONG ( Table_Version ),
- FT_FRAME_ULONG ( Font_Revision ),
- FT_FRAME_LONG ( CheckSum_Adjust ),
- FT_FRAME_LONG ( Magic_Number ),
- FT_FRAME_USHORT( Flags ),
- FT_FRAME_USHORT( Units_Per_EM ),
- FT_FRAME_LONG ( Created[0] ),
- FT_FRAME_LONG ( Created[1] ),
- FT_FRAME_LONG ( Modified[0] ),
- FT_FRAME_LONG ( Modified[1] ),
- FT_FRAME_SHORT ( xMin ),
- FT_FRAME_SHORT ( yMin ),
- FT_FRAME_SHORT ( xMax ),
- FT_FRAME_SHORT ( yMax ),
- FT_FRAME_USHORT( Mac_Style ),
- FT_FRAME_USHORT( Lowest_Rec_PPEM ),
- FT_FRAME_SHORT ( Font_Direction ),
- FT_FRAME_SHORT ( Index_To_Loc_Format ),
- FT_FRAME_SHORT ( Glyph_Data_Format ),
- FT_FRAME_END
- };
- FT_TRACE2(( "tt_face_load_generic_header: "
- "%08p, looking up font table `%c%c%c%c'.\n",
- face,
- (FT_Char)( tag >> 24 ),
- (FT_Char)( tag >> 16 ),
- (FT_Char)( tag >> 8 ),
- (FT_Char)( tag ) ));
- error = face->goto_table( face, tag, stream, 0 );
- if ( error )
- {
- FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" ));
- goto Exit;
- }
- header = &face->header;
- if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
- goto Exit;
- FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM ));
- FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format ));
- FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" ));
- Exit:
- return error;
- }
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_header( TT_Face face,
- FT_Stream stream )
- {
- return tt_face_load_generic_header( face, stream, TTAG_head );
- }
- #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_bitmap_header( TT_Face face,
- FT_Stream stream )
- {
- return tt_face_load_generic_header( face, stream, TTAG_bhed );
- }
- #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_max_profile */
- /* */
- /* <Description> */
- /* Loads the maximum profile into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_max_profile( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- TT_MaxProfile* maxProfile = &face->max_profile;
- const FT_Frame_Field maxp_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_MaxProfile
- FT_FRAME_START( 6 ),
- FT_FRAME_LONG ( version ),
- FT_FRAME_USHORT( numGlyphs ),
- FT_FRAME_END
- };
- const FT_Frame_Field maxp_fields_extra[] =
- {
- FT_FRAME_START( 26 ),
- FT_FRAME_USHORT( maxPoints ),
- FT_FRAME_USHORT( maxContours ),
- FT_FRAME_USHORT( maxCompositePoints ),
- FT_FRAME_USHORT( maxCompositeContours ),
- FT_FRAME_USHORT( maxZones ),
- FT_FRAME_USHORT( maxTwilightPoints ),
- FT_FRAME_USHORT( maxStorage ),
- FT_FRAME_USHORT( maxFunctionDefs ),
- FT_FRAME_USHORT( maxInstructionDefs ),
- FT_FRAME_USHORT( maxStackElements ),
- FT_FRAME_USHORT( maxSizeOfInstructions ),
- FT_FRAME_USHORT( maxComponentElements ),
- FT_FRAME_USHORT( maxComponentDepth ),
- FT_FRAME_END
- };
- FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
- error = face->goto_table( face, TTAG_maxp, stream, 0 );
- if ( error )
- goto Exit;
- if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
- goto Exit;
- maxProfile->maxPoints = 0;
- maxProfile->maxContours = 0;
- maxProfile->maxCompositePoints = 0;
- maxProfile->maxCompositeContours = 0;
- maxProfile->maxZones = 0;
- maxProfile->maxTwilightPoints = 0;
- maxProfile->maxStorage = 0;
- maxProfile->maxFunctionDefs = 0;
- maxProfile->maxInstructionDefs = 0;
- maxProfile->maxStackElements = 0;
- maxProfile->maxSizeOfInstructions = 0;
- maxProfile->maxComponentElements = 0;
- maxProfile->maxComponentDepth = 0;
- if ( maxProfile->version >= 0x10000L )
- {
- if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
- goto Exit;
- /* XXX: an adjustment that is necessary to load certain */
- /* broken fonts like `Keystrokes MT' :-( */
- /* */
- /* We allocate 64 function entries by default when */
- /* the maxFunctionDefs field is null. */
- if ( maxProfile->maxFunctionDefs == 0 )
- maxProfile->maxFunctionDefs = 64;
- face->root.num_glyphs = maxProfile->numGlyphs;
- face->root.internal->max_points =
- (FT_UShort)MAX( maxProfile->maxCompositePoints,
- maxProfile->maxPoints );
- face->root.internal->max_contours =
- (FT_Short)MAX( maxProfile->maxCompositeContours,
- maxProfile->maxContours );
- face->max_components = (FT_ULong)maxProfile->maxComponentElements +
- maxProfile->maxComponentDepth;
- /* XXX: some fonts have maxComponents set to 0; we will */
- /* then use 16 of them by default. */
- if ( face->max_components == 0 )
- face->max_components = 16;
- /* We also increase maxPoints and maxContours in order to support */
- /* some broken fonts. */
- face->root.internal->max_points += (FT_UShort)8;
- face->root.internal->max_contours += (FT_Short) 4;
- }
- FT_TRACE2(( "MAXP loaded.\n" ));
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_metrics */
- /* */
- /* <Description> */
- /* Loads the horizontal or vertical metrics table into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* vertical :: A boolean flag. If set, load vertical metrics. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
- tt_face_load_metrics( TT_Face face,
- FT_Stream stream,
- FT_Bool vertical )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_ULong table_len;
- FT_Long num_shorts, num_longs, num_shorts_checked;
- TT_LongMetrics * longs;
- TT_ShortMetrics** shorts;
- FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
- : "Horizontal",
- face ));
- if ( vertical )
- {
- /* The table is optional, quit silently if it wasn't found */
- /* */
- /* XXX: Some fonts have a valid vertical header with a non-null */
- /* `number_of_VMetrics' fields, but no corresponding `vmtx' */
- /* table to get the metrics from (e.g. mingliu). */
- /* */
- /* For safety, we set the field to 0! */
- /* */
- error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
- if ( error )
- {
- /* Set number_Of_VMetrics to 0! */
- FT_TRACE2(( " no vertical header in file.\n" ));
- face->vertical.number_Of_VMetrics = 0;
- error = SFNT_Err_Ok;
- goto Exit;
- }
- num_longs = face->vertical.number_Of_VMetrics;
- longs = (TT_LongMetrics *)&face->vertical.long_metrics;
- shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
- }
- else
- {
- error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
- if ( error )
- {
- FT_ERROR(( " no horizontal metrics in file!\n" ));
- error = SFNT_Err_Hmtx_Table_Missing;
- goto Exit;
- }
- num_longs = face->horizontal.number_Of_HMetrics;
- longs = (TT_LongMetrics *)&face->horizontal.long_metrics;
- shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
- }
- /* never trust derived values */
- num_shorts = face->max_profile.numGlyphs - num_longs;
- num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
- if ( num_shorts < 0 )
- {
- FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
- vertical ? "Vertical"
- : "Horizontal" ));
- error = vertical ? SFNT_Err_Invalid_Vert_Metrics
- : SFNT_Err_Invalid_Horiz_Metrics;
- goto Exit;
- }
- if ( FT_NEW_ARRAY( *longs, num_longs ) ||
- FT_NEW_ARRAY( *shorts, num_shorts ) )
- goto Exit;
- if ( FT_FRAME_ENTER( table_len ) )
- goto Exit;
- {
- TT_LongMetrics cur = *longs;
- TT_LongMetrics limit = cur + num_longs;
- for ( ; cur < limit; cur++ )
- {
- cur->advance = FT_GET_USHORT();
- cur->bearing = FT_GET_SHORT();
- }
- }
- /* do we have an inconsistent number of metric values? */
- {
- TT_ShortMetrics* cur = *shorts;
- TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked );
- for ( ; cur < limit; cur++ )
- *cur = FT_GET_SHORT();
- /* we fill up the missing left side bearings with the */
- /* last valid value. Since this will occur for buggy CJK */
- /* fonts usually only, nothing serious will happen */
- if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
- {
- FT_Short val = (*shorts)[num_shorts_checked - 1];
- limit = *shorts + num_shorts;
- for ( ; cur < limit; cur++ )
- *cur = val;
- }
- }
- FT_FRAME_EXIT();
- FT_TRACE2(( "loaded\n" ));
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_metrics_header */
- /* */
- /* <Description> */
- /* Loads the horizontal or vertical header in a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* vertical :: A boolean flag. If set, load vertical metrics. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_metrics_header( TT_Face face,
- FT_Stream stream,
- FT_Bool vertical )
- {
- FT_Error error;
- TT_HoriHeader* header;
- const FT_Frame_Field metrics_header_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_HoriHeader
- FT_FRAME_START( 36 ),
- FT_FRAME_ULONG ( Version ),
- FT_FRAME_SHORT ( Ascender ),
- FT_FRAME_SHORT ( Descender ),
- FT_FRAME_SHORT ( Line_Gap ),
- FT_FRAME_USHORT( advance_Width_Max ),
- FT_FRAME_SHORT ( min_Left_Side_Bearing ),
- FT_FRAME_SHORT ( min_Right_Side_Bearing ),
- FT_FRAME_SHORT ( xMax_Extent ),
- FT_FRAME_SHORT ( caret_Slope_Rise ),
- FT_FRAME_SHORT ( caret_Slope_Run ),
- FT_FRAME_SHORT ( caret_Offset ),
- FT_FRAME_SHORT ( Reserved[0] ),
- FT_FRAME_SHORT ( Reserved[1] ),
- FT_FRAME_SHORT ( Reserved[2] ),
- FT_FRAME_SHORT ( Reserved[3] ),
- FT_FRAME_SHORT ( metric_Data_Format ),
- FT_FRAME_USHORT( number_Of_HMetrics ),
- FT_FRAME_END
- };
- FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
- if ( vertical )
- {
- face->vertical_info = 0;
- /* The vertical header table is optional, so return quietly if */
- /* we don't find it. */
- error = face->goto_table( face, TTAG_vhea, stream, 0 );
- if ( error )
- {
- error = SFNT_Err_Ok;
- goto Exit;
- }
- face->vertical_info = 1;
- header = (TT_HoriHeader*)&face->vertical;
- }
- else
- {
- /* The horizontal header is mandatory; return an error if we */
- /* don't find it. */
- error = face->goto_table( face, TTAG_hhea, stream, 0 );
- if ( error )
- {
- error = SFNT_Err_Horiz_Header_Missing;
- goto Exit;
- }
- header = &face->horizontal;
- }
- if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
- goto Exit;
- header->long_metrics = NULL;
- header->short_metrics = NULL;
- FT_TRACE2(( "loaded\n" ));
- /* Now try to load the corresponding metrics */
- error = tt_face_load_metrics( face, stream, vertical );
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_names */
- /* */
- /* <Description> */
- /* Loads the name records. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_names( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_ULong table_pos, table_len;
- FT_ULong storage_start, storage_limit;
- FT_UInt count;
- TT_NameTable table;
- static const FT_Frame_Field name_table_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_NameTableRec
- FT_FRAME_START( 6 ),
- FT_FRAME_USHORT( format ),
- FT_FRAME_USHORT( numNameRecords ),
- FT_FRAME_USHORT( storageOffset ),
- FT_FRAME_END
- };
- static const FT_Frame_Field name_record_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_NameEntryRec
- /* no FT_FRAME_START */
- FT_FRAME_USHORT( platformID ),
- FT_FRAME_USHORT( encodingID ),
- FT_FRAME_USHORT( languageID ),
- FT_FRAME_USHORT( nameID ),
- FT_FRAME_USHORT( stringLength ),
- FT_FRAME_USHORT( stringOffset ),
- FT_FRAME_END
- };
- table = &face->name_table;
- table->stream = stream;
- FT_TRACE2(( "Names " ));
- error = face->goto_table( face, TTAG_name, stream, &table_len );
- if ( error )
- {
- /* The name table is required so indicate failure. */
- FT_TRACE2(( "is missing!\n" ));
- error = SFNT_Err_Name_Table_Missing;
- goto Exit;
- }
- table_pos = FT_STREAM_POS();
- if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
- goto Exit;
- /* Some popular asian fonts have an invalid `storageOffset' value */
- /* (it should be at least "6 + 12*num_names"). However, the string */
- /* offsets, computed as "storageOffset + entry->stringOffset", are */
- /* valid pointers within the name table... */
- /* */
- /* We thus can't check `storageOffset' right now. */
- /* */
- storage_start = table_pos + 6 + 12*table->numNameRecords;
- storage_limit = table_pos + table_len;
- if ( storage_start > storage_limit )
- {
- FT_ERROR(( "tt_face_load_names: invalid `name' table\n" ));
- error = SFNT_Err_Name_Table_Missing;
- goto Exit;
- }
- /* Allocate the array of name records. */
- count = table->numNameRecords;
- table->numNameRecords = 0;
- if ( FT_NEW_ARRAY( table->names, count ) ||
- FT_FRAME_ENTER( count * 12 ) )
- goto Exit;
- /* Load the name records and determine how much storage is needed */
- /* to hold the strings themselves. */
- {
- TT_NameEntryRec* entry = table->names;
- for ( ; count > 0; count-- )
- {
- if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
- continue;
- /* check that the name is not empty */
- if ( entry->stringLength == 0 )
- continue;
- /* check that the name string is within the table */
- entry->stringOffset += table_pos + table->storageOffset;
- if ( entry->stringOffset < storage_start ||
- entry->stringOffset + entry->stringLength > storage_limit )
- {
- /* invalid entry - ignore it */
- entry->stringOffset = 0;
- entry->stringLength = 0;
- continue;
- }
- entry++;
- }
- table->numNameRecords = (FT_UInt)( entry - table->names );
- }
- FT_FRAME_EXIT();
- FT_TRACE2(( "loaded\n" ));
- /* everything went well, update face->num_names */
- face->num_names = (FT_UShort) table->numNameRecords;
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_free_names */
- /* */
- /* <Description> */
- /* Frees the name records. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- FT_LOCAL_DEF( void )
- tt_face_free_names( TT_Face face )
- {
- FT_Memory memory = face->root.driver->root.memory;
- TT_NameTable table = &face->name_table;
- TT_NameEntry entry = table->names;
- FT_UInt count = table->numNameRecords;
- for ( ; count > 0; count--, entry++ )
- {
- FT_FREE( entry->string );
- entry->stringLength = 0;
- }
- /* free strings table */
- FT_FREE( table->names );
- table->numNameRecords = 0;
- table->format = 0;
- table->storageOffset = 0;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_cmap */
- /* */
- /* <Description> */
- /* Loads the cmap directory in a face object. The cmaps itselves are */
- /* loaded on demand in the `ttcmap.c' module. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_cmap( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
- if ( error )
- {
- FT_TRACE2(( "No `cmap' table in font !\n" ));
- error = SFNT_Err_CMap_Table_Missing;
- goto Exit;
- }
- if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
- FT_TRACE2(( "`cmap' table loaded\n" ));
- else
- {
- FT_ERROR(( "`cmap' table is too short!\n" ));
- face->cmap_size = 0;
- }
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_os2 */
- /* */
- /* <Description> */
- /* Loads the OS2 table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_os2( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- TT_OS2* os2;
- const FT_Frame_Field os2_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_OS2
- FT_FRAME_START( 78 ),
- FT_FRAME_USHORT( version ),
- FT_FRAME_SHORT ( xAvgCharWidth ),
- FT_FRAME_USHORT( usWeightClass ),
- FT_FRAME_USHORT( usWidthClass ),
- FT_FRAME_SHORT ( fsType ),
- FT_FRAME_SHORT ( ySubscriptXSize ),
- FT_FRAME_SHORT ( ySubscriptYSize ),
- FT_FRAME_SHORT ( ySubscriptXOffset ),
- FT_FRAME_SHORT ( ySubscriptYOffset ),
- FT_FRAME_SHORT ( ySuperscriptXSize ),
- FT_FRAME_SHORT ( ySuperscriptYSize ),
- FT_FRAME_SHORT ( ySuperscriptXOffset ),
- FT_FRAME_SHORT ( ySuperscriptYOffset ),
- FT_FRAME_SHORT ( yStrikeoutSize ),
- FT_FRAME_SHORT ( yStrikeoutPosition ),
- FT_FRAME_SHORT ( sFamilyClass ),
- FT_FRAME_BYTE ( panose[0] ),
- FT_FRAME_BYTE ( panose[1] ),
- FT_FRAME_BYTE ( panose[2] ),
- FT_FRAME_BYTE ( panose[3] ),
- FT_FRAME_BYTE ( panose[4] ),
- FT_FRAME_BYTE ( panose[5] ),
- FT_FRAME_BYTE ( panose[6] ),
- FT_FRAME_BYTE ( panose[7] ),
- FT_FRAME_BYTE ( panose[8] ),
- FT_FRAME_BYTE ( panose[9] ),
- FT_FRAME_ULONG ( ulUnicodeRange1 ),
- FT_FRAME_ULONG ( ulUnicodeRange2 ),
- FT_FRAME_ULONG ( ulUnicodeRange3 ),
- FT_FRAME_ULONG ( ulUnicodeRange4 ),
- FT_FRAME_BYTE ( achVendID[0] ),
- FT_FRAME_BYTE ( achVendID[1] ),
- FT_FRAME_BYTE ( achVendID[2] ),
- FT_FRAME_BYTE ( achVendID[3] ),
- FT_FRAME_USHORT( fsSelection ),
- FT_FRAME_USHORT( usFirstCharIndex ),
- FT_FRAME_USHORT( usLastCharIndex ),
- FT_FRAME_SHORT ( sTypoAscender ),
- FT_FRAME_SHORT ( sTypoDescender ),
- FT_FRAME_SHORT ( sTypoLineGap ),
- FT_FRAME_USHORT( usWinAscent ),
- FT_FRAME_USHORT( usWinDescent ),
- FT_FRAME_END
- };
- const FT_Frame_Field os2_fields_extra[] =
- {
- FT_FRAME_START( 8 ),
- FT_FRAME_ULONG( ulCodePageRange1 ),
- FT_FRAME_ULONG( ulCodePageRange2 ),
- FT_FRAME_END
- };
- const FT_Frame_Field os2_fields_extra2[] =
- {
- FT_FRAME_START( 10 ),
- FT_FRAME_SHORT ( sxHeight ),
- FT_FRAME_SHORT ( sCapHeight ),
- FT_FRAME_USHORT( usDefaultChar ),
- FT_FRAME_USHORT( usBreakChar ),
- FT_FRAME_USHORT( usMaxContext ),
- FT_FRAME_END
- };
- FT_TRACE2(( "OS/2 Table " ));
- /* We now support old Mac fonts where the OS/2 table doesn't */
- /* exist. Simply put, we set the `version' field to 0xFFFF */
- /* and test this value each time we need to access the table. */
- error = face->goto_table( face, TTAG_OS2, stream, 0 );
- if ( error )
- {
- FT_TRACE2(( "is missing!\n" ));
- face->os2.version = 0xFFFFU;
- error = SFNT_Err_Ok;
- goto Exit;
- }
- os2 = &face->os2;
- if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
- goto Exit;
- os2->ulCodePageRange1 = 0;
- os2->ulCodePageRange2 = 0;
- os2->sxHeight = 0;
- os2->sCapHeight = 0;
- os2->usDefaultChar = 0;
- os2->usBreakChar = 0;
- os2->usMaxContext = 0;
- if ( os2->version >= 0x0001 )
- {
- /* only version 1 tables */
- if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
- goto Exit;
- if ( os2->version >= 0x0002 )
- {
- /* only version 2 tables */
- if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
- goto Exit;
- }
- }
- FT_TRACE2(( "loaded\n" ));
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_postscript */
- /* */
- /* <Description> */
- /* Loads the Postscript table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_postscript( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- TT_Postscript* post = &face->postscript;
- static const FT_Frame_Field post_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_Postscript
- FT_FRAME_START( 32 ),
- FT_FRAME_ULONG( FormatType ),
- FT_FRAME_ULONG( italicAngle ),
- FT_FRAME_SHORT( underlinePosition ),
- FT_FRAME_SHORT( underlineThickness ),
- FT_FRAME_ULONG( isFixedPitch ),
- FT_FRAME_ULONG( minMemType42 ),
- FT_FRAME_ULONG( maxMemType42 ),
- FT_FRAME_ULONG( minMemType1 ),
- FT_FRAME_ULONG( maxMemType1 ),
- FT_FRAME_END
- };
- FT_TRACE2(( "PostScript " ));
- error = face->goto_table( face, TTAG_post, stream, 0 );
- if ( error )
- return SFNT_Err_Post_Table_Missing;
- if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
- return error;
- /* we don't load the glyph names, we do that in another */
- /* module (ttpost). */
- FT_TRACE2(( "loaded\n" ));
- return SFNT_Err_Ok;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_pclt */
- /* */
- /* <Description> */
- /* Loads the PCL 5 Table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_pclt( TT_Face face,
- FT_Stream stream )
- {
- static const FT_Frame_Field pclt_fields[] =
- {
- #undef FT_STRUCTURE
- #define FT_STRUCTURE TT_PCLT
- FT_FRAME_START( 54 ),
- FT_FRAME_ULONG ( Version ),
- FT_FRAME_ULONG ( FontNumber ),
- FT_FRAME_USHORT( Pitch ),
- FT_FRAME_USHORT( xHeight ),
- FT_FRAME_USHORT( Style ),
- FT_FRAME_USHORT( TypeFamily ),
- FT_FRAME_USHORT( CapHeight ),
- FT_FRAME_BYTES ( TypeFace, 16 ),
- FT_FRAME_BYTES ( CharacterComplement, 8 ),
- FT_FRAME_BYTES ( FileName, 6 ),
- FT_FRAME_CHAR ( StrokeWeight ),
- FT_FRAME_CHAR ( WidthType ),
- FT_FRAME_BYTE ( SerifStyle ),
- FT_FRAME_BYTE ( Reserved ),
- FT_FRAME_END
- };
- FT_Error error;
- TT_PCLT* pclt = &face->pclt;
- FT_TRACE2(( "PCLT " ));
- /* optional table */
- error = face->goto_table( face, TTAG_PCLT, stream, 0 );
- if ( error )
- {
- FT_TRACE2(( "missing (optional)\n" ));
- pclt->Version = 0;
- return SFNT_Err_Ok;
- }
- if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
- goto Exit;
- FT_TRACE2(( "loaded\n" ));
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_gasp */
- /* */
- /* <Description> */
- /* Loads the `gasp' table into a face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_gasp( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UInt j,num_ranges;
- TT_GaspRange gaspranges;
- FT_TRACE2(( "tt_face_load_gasp: %08p\n", face ));
- /* the gasp table is optional */
- error = face->goto_table( face, TTAG_gasp, stream, 0 );
- if ( error )
- return SFNT_Err_Ok;
- if ( FT_FRAME_ENTER( 4L ) )
- goto Exit;
- face->gasp.version = FT_GET_USHORT();
- face->gasp.numRanges = FT_GET_USHORT();
- FT_FRAME_EXIT();
- num_ranges = face->gasp.numRanges;
- FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
- if ( FT_NEW_ARRAY( gaspranges, num_ranges ) ||
- FT_FRAME_ENTER( num_ranges * 4L ) )
- goto Exit;
- face->gasp.gaspRanges = gaspranges;
- for ( j = 0; j < num_ranges; j++ )
- {
- gaspranges[j].maxPPEM = FT_GET_USHORT();
- gaspranges[j].gaspFlag = FT_GET_USHORT();
- FT_TRACE3(( " [max:%d flag:%d]",
- gaspranges[j].maxPPEM,
- gaspranges[j].gaspFlag ));
- }
- FT_TRACE3(( "\n" ));
- FT_FRAME_EXIT();
- FT_TRACE2(( "GASP loaded\n" ));
- Exit:
- return error;
- }
- FT_CALLBACK_DEF( int )
- tt_kern_pair_compare( const void* a,
- const void* b );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_kern */
- /* */
- /* <Description> */
- /* Loads the first kerning table with format 0 in the font. Only */
- /* accepts the first horizontal kerning table. Developers should use */
- /* the `ftxkern' extension to access other kerning tables in the font */
- /* file, if they really want to. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_kern( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UInt n, num_tables;
- /* the kern table is optional; exit silently if it is missing */
- error = face->goto_table( face, TTAG_kern, stream, 0 );
- if ( error )
- return SFNT_Err_Ok;
- if ( FT_FRAME_ENTER( 4L ) )
- goto Exit;
- (void)FT_GET_USHORT(); /* version */
- num_tables = FT_GET_USHORT();
- FT_FRAME_EXIT();
- for ( n = 0; n < num_tables; n++ )
- {
- FT_UInt coverage;
- FT_UInt length;
- if ( FT_FRAME_ENTER( 6L ) )
- goto Exit;
- (void)FT_GET_USHORT(); /* version */
- length = FT_GET_USHORT() - 6; /* substract header length */
- coverage = FT_GET_USHORT();
- FT_FRAME_EXIT();
- if ( coverage == 0x0001 )
- {
- FT_UInt num_pairs;
- TT_Kern0_Pair pair;
- TT_Kern0_Pair limit;
- /* found a horizontal format 0 kerning table! */
- if ( FT_FRAME_ENTER( 8L ) )
- goto Exit;
- num_pairs = FT_GET_USHORT();
- /* skip the rest */
- FT_FRAME_EXIT();
- /* allocate array of kerning pairs */
- if ( FT_NEW_ARRAY( face->kern_pairs, num_pairs ) ||
- FT_FRAME_ENTER( 6L * num_pairs ) )
- goto Exit;
- pair = face->kern_pairs;
- limit = pair + num_pairs;
- for ( ; pair < limit; pair++ )
- {
- pair->left = FT_GET_USHORT();
- pair->right = FT_GET_USHORT();
- pair->value = FT_GET_USHORT();
- }
- FT_FRAME_EXIT();
- face->num_kern_pairs = num_pairs;
- face->kern_table_index = n;
- /* ensure that the kerning pair table is sorted (yes, some */
- /* fonts have unsorted tables!) */
- {
- FT_UInt i;
- TT_Kern0_Pair pair0;
- pair0 = face->kern_pairs;
- for ( i = 1; i < num_pairs; i++, pair0++ )
- {
- if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 )
- {
- ft_qsort( (void*)face->kern_pairs, (int)num_pairs,
- sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare );
- break;
- }
- }
- }
- goto Exit;
- }
- if ( FT_STREAM_SKIP( length ) )
- goto Exit;
- }
- /* no kern table found -- doesn't matter */
- face->kern_table_index = -1;
- face->num_kern_pairs = 0;
- face->kern_pairs = NULL;
- Exit:
- return error;
- }
- #undef TT_KERN_INDEX
- #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
- FT_CALLBACK_DEF( int )
- tt_kern_pair_compare( const void* a,
- const void* b )
- {
- TT_Kern0_Pair pair1 = (TT_Kern0_Pair)a;
- TT_Kern0_Pair pair2 = (TT_Kern0_Pair)b;
- FT_ULong index1 = TT_KERN_INDEX( pair1->left, pair1->right );
- FT_ULong index2 = TT_KERN_INDEX( pair2->left, pair2->right );
- return ( index1 < index2 ? -1 :
- ( index1 > index2 ? 1 : 0 ));
- }
- #undef TT_KERN_INDEX
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_hdmx */
- /* */
- /* <Description> */
- /* Loads the horizontal device metrics table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_hdmx( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- TT_Hdmx hdmx = &face->hdmx;
- FT_Long num_glyphs;
- FT_Long record_size;
- hdmx->version = 0;
- hdmx->num_records = 0;
- hdmx->records = 0;
- /* this table is optional */
- error = face->goto_table( face, TTAG_hdmx, stream, 0 );
- if ( error )
- return SFNT_Err_Ok;
- if ( FT_FRAME_ENTER( 8L ) )
- goto Exit;
- hdmx->version = FT_GET_USHORT();
- hdmx->num_records = FT_GET_SHORT();
- record_size = FT_GET_LONG();
- FT_FRAME_EXIT();
- /* Only recognize format 0 */
- if ( hdmx->version != 0 )
- goto Exit;
- if ( FT_NEW_ARRAY( hdmx->records, hdmx->num_records ) )
- goto Exit;
- num_glyphs = face->root.num_glyphs;
- record_size -= num_glyphs + 2;
- {
- TT_HdmxEntry cur = hdmx->records;
- TT_HdmxEntry limit = cur + hdmx->num_records;
- for ( ; cur < limit; cur++ )
- {
- /* read record */
- if ( FT_READ_BYTE( cur->ppem ) ||
- FT_READ_BYTE( cur->max_width ) )
- goto Exit;
- if ( FT_ALLOC( cur->widths, num_glyphs ) ||
- FT_STREAM_READ( cur->widths, num_glyphs ) )
- goto Exit;
- /* skip padding bytes */
- if ( record_size > 0 && FT_STREAM_SKIP( record_size ) )
- goto Exit;
- }
- }
- Exit:
- return error;
- }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_free_hdmx */
- /* */
- /* <Description> */
- /* Frees the horizontal device metrics table. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- FT_LOCAL_DEF( void )
- tt_face_free_hdmx( TT_Face face )
- {
- if ( face )
- {
- FT_Int n;
- FT_Memory memory = face->root.driver->root.memory;
- for ( n = 0; n < face->hdmx.num_records; n++ )
- FT_FREE( face->hdmx.records[n].widths );
- FT_FREE( face->hdmx.records );
- face->hdmx.num_records = 0;
- }
- }
- /* END */
|