📄 ttload.c
字号:
if ( n < 0 ) { /* Set the number_Of_VMetrics to 0! */ PTRACE2(( " no vertical header in file.\n" )); face->verticalHeader.number_Of_VMetrics = 0; return TT_Err_Ok; } num_longs = face->verticalHeader.number_Of_VMetrics; longs = (PLongMetrics*)&face->verticalHeader.long_metrics; shorts = (PShortMetrics*)&face->verticalHeader.short_metrics; } else { if ( ( n = TT_LookUp_Table( face, TTAG_hmtx ) ) < 0 ) { PERROR(( "!! No Horizontal metrics in file !!\n" )); return TT_Err_Hmtx_Table_Missing; } num_longs = face->horizontalHeader.number_Of_HMetrics; longs = (PLongMetrics*)&face->horizontalHeader.long_metrics; shorts = (PShortMetrics*)&face->horizontalHeader.short_metrics; } /* never trust derived values! */ num_shorts = face->maxProfile.numGlyphs - num_longs; num_shorts_checked = ( face->dirTables[n].Length - num_longs * 4 ) / 2; if ( num_shorts < 0 ) /* sanity check */ { PERROR(( "!! more metrics than glyphs!\n" )); if ( vertical ) return TT_Err_Invalid_Vert_Metrics; else return TT_Err_Invalid_Horiz_Metrics; } if ( ALLOC_ARRAY( *longs, num_longs, TLongMetrics ) || ALLOC_ARRAY( *shorts, num_shorts, TShortMetrics ) ) return error; if ( FILE_Seek( face->dirTables[n].Offset ) || ACCESS_Frame( face->dirTables[n].Length ) ) return error; long_metric = *longs; for ( n = 0; n < num_longs; n++ ) { long_metric->advance = GET_UShort(); long_metric->bearing = GET_Short(); long_metric++; } /* do we have an inconsistent number of metric values? */ if ( num_shorts > num_shorts_checked ) { for ( n = 0; n < num_shorts_checked; n++ ) (*shorts)[n] = GET_Short(); /* we fill up the missing left side bearings with the */ /* last valid value. Since this will occur for buggy CJK */ /* fonts usually, nothing serious will happen. */ for ( n = num_shorts_checked; n < num_shorts; n++ ) (*shorts)[n] = (*shorts)[num_shorts_checked - 1]; } else { for ( n = 0; n < num_shorts; n++ ) (*shorts)[n] = GET_Short(); } FORGET_Frame(); PTRACE2(( "loaded\n" )); return TT_Err_Ok; }/******************************************************************* * * Function : Load_TrueType_Metrics_Header * * Description : Loads either the "hhea" or "vhea" table in memory * * Input : face face table to look for * vertical a boolean. When set, queries the optional * "vhea" table. Otherwise, load the mandatory * "hhea" horizontal header. * * Output : Error code. * * Note : This function now loads the corresponding metrics table * (either hmtx or vmtx) and attaches it to the header. * ******************************************************************/ LOCAL_FUNC TT_Error Load_TrueType_Metrics_Header( PFace face, Bool vertical ) { DEFINE_LOCALS; Long i; TT_Horizontal_Header* header; PTRACE2(( vertical ? "Vertical header" : "Horizontal header " )); if ( vertical ) { face->verticalInfo = 0; /* The vertical header table is optional, so return quietly if */ /* we don't find it.. */ if ( ( i = TT_LookUp_Table( face, TTAG_vhea ) ) < 0 ) return TT_Err_Ok; face->verticalInfo = 1; header = (TT_Horizontal_Header*)&face->verticalHeader; } else { /* The orizontal header is mandatory, return an error if we */ /* don't find it. */ if ( ( i = TT_LookUp_Table( face, TTAG_hhea ) ) < 0 ) return TT_Err_Horiz_Header_Missing; header = &face->horizontalHeader; } if ( FILE_Seek( face->dirTables[i].Offset ) || ACCESS_Frame( 36L ) ) return error; header->Version = GET_ULong(); header->Ascender = GET_Short(); header->Descender = GET_Short(); header->Line_Gap = GET_Short(); header->advance_Width_Max = GET_UShort(); header->min_Left_Side_Bearing = GET_Short(); header->min_Right_Side_Bearing = GET_Short(); header->xMax_Extent = GET_Short(); header->caret_Slope_Rise = GET_Short(); header->caret_Slope_Run = GET_Short(); header->Reserved0 = GET_Short(); /* this is caret_Offset for vertical headers */ header->Reserved1 = GET_Short(); header->Reserved2 = GET_Short(); header->Reserved3 = GET_Short(); header->Reserved4 = GET_Short(); header->metric_Data_Format = GET_Short(); header->number_Of_HMetrics = GET_UShort(); FORGET_Frame(); header->long_metrics = NULL; header->short_metrics = NULL; PTRACE2(( "loaded\n" )); /* Now try to load the corresponding metrics */ return Load_TrueType_Metrics( face, vertical ); }/******************************************************************* * * Function : Load_TrueType_Locations * * Description : Loads the location table into face table. * * Input : face face table to look for * * Output : Error code. * * NOTE: * The Font Header *must* be loaded in the leading segment * calling this function. * ******************************************************************/ LOCAL_FUNC TT_Error Load_TrueType_Locations( PFace face ) { DEFINE_LOCALS; Long n, limit; Short LongOffsets; PTRACE2(( "Locations " )); LongOffsets = face->fontHeader.Index_To_Loc_Format; if ( ( n = TT_LookUp_Table( face, TTAG_loca ) ) < 0 ) return TT_Err_Locations_Missing; if ( FILE_Seek( face->dirTables[n].Offset ) ) return error; if ( LongOffsets != 0 ) { face->numLocations = face->dirTables[n].Length >> 2; PTRACE2(( "(32 bit offsets): %12lu ", face->numLocations )); if ( ALLOC_ARRAY( face->glyphLocations, face->numLocations, Long ) ) return error; if ( ACCESS_Frame( face->numLocations * 4L ) ) return error; limit = face->numLocations; for ( n = 0; n < limit; n++ ) face->glyphLocations[n] = GET_Long(); FORGET_Frame(); } else { face->numLocations = face->dirTables[n].Length >> 1; PTRACE2(( "(16 bit offsets): %12lu ", face->numLocations )); if ( ALLOC_ARRAY( face->glyphLocations, face->numLocations, Long ) ) return error; if ( ACCESS_Frame( face->numLocations * 2L ) ) return error; limit = face->numLocations; for ( n = 0; n < limit; n++ ) face->glyphLocations[n] = (Long)((ULong)GET_UShort() * 2); FORGET_Frame(); } PTRACE2(( "loaded\n" )); return TT_Err_Ok; }/******************************************************************* * * Function : Load_TrueType_Names * * Description : Loads the name table into face table. * * Input : face face table to look for * * Output : Error code. * ******************************************************************/ LOCAL_FUNC TT_Error Load_TrueType_Names( PFace face ) { DEFINE_LOCALS; UShort i, bytes; Long n; PByte storage; TName_Table* names; TNameRec* namerec; PTRACE2(( "Names " )); if ( ( n = TT_LookUp_Table( face, TTAG_name ) ) < 0 ) { /* The name table is required so indicate failure. */ PTRACE2(( "is missing!\n" )); return TT_Err_Name_Table_Missing; } /* Seek to the beginning of the table and check the frame access. */ /* The names table has a 6 byte header. */ if ( FILE_Seek( face->dirTables[n].Offset ) || ACCESS_Frame( 6L ) ) return error; names = &face->nameTable; /* Load the initial names data. */ names->format = GET_UShort(); names->numNameRecords = GET_UShort(); names->storageOffset = GET_UShort(); FORGET_Frame(); /* Allocate the array of name records. */ if ( ALLOC_ARRAY( names->names, names->numNameRecords, TNameRec ) || ACCESS_Frame( names->numNameRecords * 12L ) ) { names->numNameRecords = 0; goto Fail; } /* Load the name records and determine how much storage is needed */ /* to hold the strings themselves. */ for ( i = bytes = 0; i < names->numNameRecords; i++ ) { namerec = names->names + i; namerec->platformID = GET_UShort(); namerec->encodingID = GET_UShort(); namerec->languageID = GET_UShort(); namerec->nameID = GET_UShort(); namerec->stringLength = GET_UShort(); namerec->stringOffset = GET_UShort();#if 0 /* check the ids */ if ( namerec->platformID <= 3 ) {#endif /* this test takes care of 'holes' in the names tables, as */ /* reported by Erwin */ if ( (namerec->stringOffset + namerec->stringLength) > bytes ) bytes = namerec->stringOffset + namerec->stringLength;#if 0 }#endif } FORGET_Frame(); /* Allocate storage for the strings if they exist. */ names->storage = NULL; if ( bytes > 0 ) { if ( ALLOC( storage, bytes ) || FILE_Read_At( face->dirTables[n].Offset + names->storageOffset, (void*)storage, bytes ) ) goto Fail_Storage; names->storage = storage; /* Go through and assign the string pointers to the name records. */ for ( i = 0; i < names->numNameRecords; i++ ) { namerec = names->names + i; namerec->string = storage + names->names[i].stringOffset;/* It is possible (but rather unlikely) that a new platform ID will be *//* added by Apple, so we can't rule out IDs > 3. */#if 0 if ( namerec->platformID <= 3 ) namerec->string = storage + names->names[i].stringOffset; else { namerec->string = NULL; namerec->stringLength = 0; }#endif } }#ifdef DEBUG_LEVEL_TRACE for ( i = 0; i < names->numNameRecords; i++ ) { int j; PTRACE2(( "%d %d %x %d ", names->names[i].platformID, names->names[i].encodingID, names->names[i].languageID, names->names[i].nameID )); /* I know that M$ encoded strings are Unicode, */ /* but this works reasonable well for debugging purposes. */ for ( j = 0; j < names->names[i].stringLength; j++ ) { if (names->names[i].string) { Char c = *(names->names[i].string + j); if ( (Byte)c < 128 ) PTRACE2(( "%c", c )); } } PTRACE2(( "\n" )); }#endif /* DEBUG_LEVEL_TRACE */ PTRACE2(( "loaded\n" )); return TT_Err_Ok; Fail_Storage: FREE( storage ); Fail: Free_TrueType_Names( face ); return error; }/******************************************************************* * * Function : Free_TrueType_Names * * Description : Frees a name table. * * Input : face face table to look for * * Output : TT_Err_Ok. * ******************************************************************/ LOCAL_FUNC TT_Error Free_TrueType_Names( PFace face ) { TName_Table* names = &face->nameTable; /* free strings table */ FREE( names->names ); /* free strings storage */ FREE( names->storage ); names->numNameRecords = 0; names->format = 0; names->storageOffset = 0; return TT_Err_Ok; }/******************************************************************* * * Function : Load_TrueType_CVT * * Description : Loads cvt table into resident table. * * Input : face face table to look for * * Output : Error code. * ******************************************************************/ LOCAL_FUNC TT_Error Load_TrueType_CVT( PFace face ) { DEFINE_LOCALS; Long n, limit; PTRACE2(( "CVT " )); if ( ( n = TT_LookUp_Table( face, TTAG_cvt ) ) < 0 ) { PTRACE2(( "is missing!\n" )); face->cvtSize = 0; face->cvt = NULL; return TT_Err_Ok; } face->cvtSize = face->dirTables[n].Length / 2; if ( ALLOC_ARRAY( face->cvt, face->cvtSize, Short ) ) return error; if ( FILE_Seek( face->dirTables[n].Offset ) || ACCESS_Frame( face->cvtSize * 2L ) ) return error; limit = face->cvtSize; for ( n = 0; n < limit; n++ ) face->cvt[n] = GET_Short(); FORGET_Frame(); PTRACE2(( "loaded\n" )); return TT_Err_Ok; }/******************************************************************* * * Function : Load_TrueType_CMap * * Description : Loads the cmap directory in memory. * The cmaps themselves are loaded in ttcmap.c . *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -