Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttload.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ttload.c */ 00004 /* */ 00005 /* Load the basic TrueType tables, i.e., tables that can be either in */ 00006 /* TTF or OTF fonts (body). */ 00007 /* */ 00008 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ 00009 /* 2010 by */ 00010 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00011 /* */ 00012 /* This file is part of the FreeType project, and may only be used, */ 00013 /* modified, and distributed under the terms of the FreeType project */ 00014 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00015 /* this file you indicate that you have read the license and */ 00016 /* understand and accept it fully. */ 00017 /* */ 00018 /***************************************************************************/ 00019 00020 00021 #include <ft2build.h> 00022 #include FT_INTERNAL_DEBUG_H 00023 #include FT_INTERNAL_STREAM_H 00024 #include FT_TRUETYPE_TAGS_H 00025 #include "ttload.h" 00026 00027 #include "sferrors.h" 00028 00029 00030 /*************************************************************************/ 00031 /* */ 00032 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00033 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00034 /* messages during execution. */ 00035 /* */ 00036 #undef FT_COMPONENT 00037 #define FT_COMPONENT trace_ttload 00038 00039 00040 /*************************************************************************/ 00041 /* */ 00042 /* <Function> */ 00043 /* tt_face_lookup_table */ 00044 /* */ 00045 /* <Description> */ 00046 /* Looks for a TrueType table by name. */ 00047 /* */ 00048 /* <Input> */ 00049 /* face :: A face object handle. */ 00050 /* */ 00051 /* tag :: The searched tag. */ 00052 /* */ 00053 /* <Return> */ 00054 /* A pointer to the table directory entry. 0 if not found. */ 00055 /* */ 00056 FT_LOCAL_DEF( TT_Table ) 00057 tt_face_lookup_table( TT_Face face, 00058 FT_ULong tag ) 00059 { 00060 TT_Table entry; 00061 TT_Table limit; 00062 #ifdef FT_DEBUG_LEVEL_TRACE 00063 FT_Bool zero_length = FALSE; 00064 #endif 00065 00066 00067 FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", 00068 face, 00069 (FT_Char)( tag >> 24 ), 00070 (FT_Char)( tag >> 16 ), 00071 (FT_Char)( tag >> 8 ), 00072 (FT_Char)( tag ) )); 00073 00074 entry = face->dir_tables; 00075 limit = entry + face->num_tables; 00076 00077 for ( ; entry < limit; entry++ ) 00078 { 00079 /* For compatibility with Windows, we consider */ 00080 /* zero-length tables the same as missing tables. */ 00081 if ( entry->Tag == tag ) 00082 { 00083 if ( entry->Length != 0 ) 00084 { 00085 FT_TRACE4(( "found table.\n" )); 00086 return entry; 00087 } 00088 #ifdef FT_DEBUG_LEVEL_TRACE 00089 zero_length = TRUE; 00090 #endif 00091 } 00092 } 00093 00094 #ifdef FT_DEBUG_LEVEL_TRACE 00095 if ( zero_length ) 00096 FT_TRACE4(( "ignoring empty table\n" )); 00097 else 00098 FT_TRACE4(( "could not find table\n" )); 00099 #endif 00100 00101 return NULL; 00102 } 00103 00104 00105 /*************************************************************************/ 00106 /* */ 00107 /* <Function> */ 00108 /* tt_face_goto_table */ 00109 /* */ 00110 /* <Description> */ 00111 /* Looks for a TrueType table by name, then seek a stream to it. */ 00112 /* */ 00113 /* <Input> */ 00114 /* face :: A face object handle. */ 00115 /* */ 00116 /* tag :: The searched tag. */ 00117 /* */ 00118 /* stream :: The stream to seek when the table is found. */ 00119 /* */ 00120 /* <Output> */ 00121 /* length :: The length of the table if found, undefined otherwise. */ 00122 /* */ 00123 /* <Return> */ 00124 /* FreeType error code. 0 means success. */ 00125 /* */ 00126 FT_LOCAL_DEF( FT_Error ) 00127 tt_face_goto_table( TT_Face face, 00128 FT_ULong tag, 00129 FT_Stream stream, 00130 FT_ULong* length ) 00131 { 00132 TT_Table table; 00133 FT_Error error; 00134 00135 00136 table = tt_face_lookup_table( face, tag ); 00137 if ( table ) 00138 { 00139 if ( length ) 00140 *length = table->Length; 00141 00142 if ( FT_STREAM_SEEK( table->Offset ) ) 00143 goto Exit; 00144 } 00145 else 00146 error = SFNT_Err_Table_Missing; 00147 00148 Exit: 00149 return error; 00150 } 00151 00152 00153 /* Here, we */ 00154 /* */ 00155 /* - check that `num_tables' is valid (and adjust it if necessary) */ 00156 /* */ 00157 /* - look for a `head' table, check its size, and parse it to check */ 00158 /* whether its `magic' field is correctly set */ 00159 /* */ 00160 /* - errors (except errors returned by stream handling) */ 00161 /* */ 00162 /* SFNT_Err_Unknown_File_Format: */ 00163 /* no table is defined in directory, it is not sfnt-wrapped */ 00164 /* data */ 00165 /* SFNT_Err_Table_Missing: */ 00166 /* table directory is valid, but essential tables */ 00167 /* (head/bhed/SING) are missing */ 00168 /* */ 00169 static FT_Error 00170 check_table_dir( SFNT_Header sfnt, 00171 FT_Stream stream ) 00172 { 00173 FT_Error error; 00174 FT_UShort nn, valid_entries = 0; 00175 FT_UInt has_head = 0, has_sing = 0, has_meta = 0; 00176 FT_ULong offset = sfnt->offset + 12; 00177 00178 static const FT_Frame_Field table_dir_entry_fields[] = 00179 { 00180 #undef FT_STRUCTURE 00181 #define FT_STRUCTURE TT_TableRec 00182 00183 FT_FRAME_START( 16 ), 00184 FT_FRAME_ULONG( Tag ), 00185 FT_FRAME_ULONG( CheckSum ), 00186 FT_FRAME_ULONG( Offset ), 00187 FT_FRAME_ULONG( Length ), 00188 FT_FRAME_END 00189 }; 00190 00191 00192 if ( FT_STREAM_SEEK( offset ) ) 00193 goto Exit; 00194 00195 for ( nn = 0; nn < sfnt->num_tables; nn++ ) 00196 { 00197 TT_TableRec table; 00198 00199 00200 if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) 00201 { 00202 nn--; 00203 FT_TRACE2(( "check_table_dir:" 00204 " can read only %d table%s in font (instead of %d)\n", 00205 nn, nn == 1 ? "" : "s", sfnt->num_tables )); 00206 sfnt->num_tables = nn; 00207 break; 00208 } 00209 00210 /* we ignore invalid tables */ 00211 if ( table.Offset + table.Length > stream->size ) 00212 { 00213 FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); 00214 continue; 00215 } 00216 else 00217 valid_entries++; 00218 00219 if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) 00220 { 00221 FT_UInt32 magic; 00222 00223 00224 #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00225 if ( table.Tag == TTAG_head ) 00226 #endif 00227 has_head = 1; 00228 00229 /* 00230 * The table length should be 0x36, but certain font tools make it 00231 * 0x38, so we will just check that it is greater. 00232 * 00233 * Note that according to the specification, the table must be 00234 * padded to 32-bit lengths, but this doesn't apply to the value of 00235 * its `Length' field! 00236 * 00237 */ 00238 if ( table.Length < 0x36 ) 00239 { 00240 FT_TRACE2(( "check_table_dir: `head' table too small\n" )); 00241 error = SFNT_Err_Table_Missing; 00242 goto Exit; 00243 } 00244 00245 if ( FT_STREAM_SEEK( table.Offset + 12 ) || 00246 FT_READ_ULONG( magic ) ) 00247 goto Exit; 00248 00249 if ( magic != 0x5F0F3CF5UL ) 00250 { 00251 FT_TRACE2(( "check_table_dir:" 00252 " no magic number found in `head' table\n")); 00253 error = SFNT_Err_Table_Missing; 00254 goto Exit; 00255 } 00256 00257 if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) 00258 goto Exit; 00259 } 00260 else if ( table.Tag == TTAG_SING ) 00261 has_sing = 1; 00262 else if ( table.Tag == TTAG_META ) 00263 has_meta = 1; 00264 } 00265 00266 sfnt->num_tables = valid_entries; 00267 00268 if ( sfnt->num_tables == 0 ) 00269 { 00270 FT_TRACE2(( "check_table_dir: no tables found\n" )); 00271 error = SFNT_Err_Unknown_File_Format; 00272 goto Exit; 00273 } 00274 00275 /* if `sing' and `meta' tables are present, there is no `head' table */ 00276 if ( has_head || ( has_sing && has_meta ) ) 00277 { 00278 error = SFNT_Err_Ok; 00279 goto Exit; 00280 } 00281 else 00282 { 00283 FT_TRACE2(( "check_table_dir:" )); 00284 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00285 FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" )); 00286 #else 00287 FT_TRACE2(( " neither `head' nor `sing' table found\n" )); 00288 #endif 00289 error = SFNT_Err_Table_Missing; 00290 } 00291 00292 Exit: 00293 return error; 00294 } 00295 00296 00297 /*************************************************************************/ 00298 /* */ 00299 /* <Function> */ 00300 /* tt_face_load_font_dir */ 00301 /* */ 00302 /* <Description> */ 00303 /* Loads the header of a SFNT font file. */ 00304 /* */ 00305 /* <Input> */ 00306 /* face :: A handle to the target face object. */ 00307 /* */ 00308 /* stream :: The input stream. */ 00309 /* */ 00310 /* <Output> */ 00311 /* sfnt :: The SFNT header. */ 00312 /* */ 00313 /* <Return> */ 00314 /* FreeType error code. 0 means success. */ 00315 /* */ 00316 /* <Note> */ 00317 /* The stream cursor must be at the beginning of the font directory. */ 00318 /* */ 00319 FT_LOCAL_DEF( FT_Error ) 00320 tt_face_load_font_dir( TT_Face face, 00321 FT_Stream stream ) 00322 { 00323 SFNT_HeaderRec sfnt; 00324 FT_Error error; 00325 FT_Memory memory = stream->memory; 00326 TT_TableRec* entry; 00327 FT_Int nn; 00328 00329 static const FT_Frame_Field offset_table_fields[] = 00330 { 00331 #undef FT_STRUCTURE 00332 #define FT_STRUCTURE SFNT_HeaderRec 00333 00334 FT_FRAME_START( 8 ), 00335 FT_FRAME_USHORT( num_tables ), 00336 FT_FRAME_USHORT( search_range ), 00337 FT_FRAME_USHORT( entry_selector ), 00338 FT_FRAME_USHORT( range_shift ), 00339 FT_FRAME_END 00340 }; 00341 00342 00343 FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face )); 00344 00345 /* read the offset table */ 00346 00347 sfnt.offset = FT_STREAM_POS(); 00348 00349 if ( FT_READ_ULONG( sfnt.format_tag ) || 00350 FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) 00351 goto Exit; 00352 00353 /* many fonts don't have these fields set correctly */ 00354 #if 0 00355 if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) || 00356 sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 ) 00357 return SFNT_Err_Unknown_File_Format; 00358 #endif 00359 00360 /* load the table directory */ 00361 00362 FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables )); 00363 FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag )); 00364 00365 /* check first */ 00366 error = check_table_dir( &sfnt, stream ); 00367 if ( error ) 00368 { 00369 FT_TRACE2(( "tt_face_load_font_dir:" 00370 " invalid table directory for TrueType\n" )); 00371 00372 goto Exit; 00373 } 00374 00375 face->num_tables = sfnt.num_tables; 00376 face->format_tag = sfnt.format_tag; 00377 00378 if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) 00379 goto Exit; 00380 00381 if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || 00382 FT_FRAME_ENTER( face->num_tables * 16L ) ) 00383 goto Exit; 00384 00385 entry = face->dir_tables; 00386 00387 FT_TRACE2(( "\n" 00388 " tag offset length checksum\n" 00389 " ----------------------------------\n" )); 00390 00391 for ( nn = 0; nn < sfnt.num_tables; nn++ ) 00392 { 00393 entry->Tag = FT_GET_TAG4(); 00394 entry->CheckSum = FT_GET_ULONG(); 00395 entry->Offset = FT_GET_LONG(); 00396 entry->Length = FT_GET_LONG(); 00397 00398 /* ignore invalid tables */ 00399 if ( entry->Offset + entry->Length > stream->size ) 00400 continue; 00401 else 00402 { 00403 FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx\n", 00404 (FT_Char)( entry->Tag >> 24 ), 00405 (FT_Char)( entry->Tag >> 16 ), 00406 (FT_Char)( entry->Tag >> 8 ), 00407 (FT_Char)( entry->Tag ), 00408 entry->Offset, 00409 entry->Length, 00410 entry->CheckSum )); 00411 entry++; 00412 } 00413 } 00414 00415 FT_FRAME_EXIT(); 00416 00417 FT_TRACE2(( "table directory loaded\n\n" )); 00418 00419 Exit: 00420 return error; 00421 } 00422 00423 00424 /*************************************************************************/ 00425 /* */ 00426 /* <Function> */ 00427 /* tt_face_load_any */ 00428 /* */ 00429 /* <Description> */ 00430 /* Loads any font table into client memory. */ 00431 /* */ 00432 /* <Input> */ 00433 /* face :: The face object to look for. */ 00434 /* */ 00435 /* tag :: The tag of table to load. Use the value 0 if you want */ 00436 /* to access the whole font file, else set this parameter */ 00437 /* to a valid TrueType table tag that you can forge with */ 00438 /* the MAKE_TT_TAG macro. */ 00439 /* */ 00440 /* offset :: The starting offset in the table (or the file if */ 00441 /* tag == 0). */ 00442 /* */ 00443 /* length :: The address of the decision variable: */ 00444 /* */ 00445 /* If length == NULL: */ 00446 /* Loads the whole table. Returns an error if */ 00447 /* `offset' == 0! */ 00448 /* */ 00449 /* If *length == 0: */ 00450 /* Exits immediately; returning the length of the given */ 00451 /* table or of the font file, depending on the value of */ 00452 /* `tag'. */ 00453 /* */ 00454 /* If *length != 0: */ 00455 /* Loads the next `length' bytes of table or font, */ 00456 /* starting at offset `offset' (in table or font too). */ 00457 /* */ 00458 /* <Output> */ 00459 /* buffer :: The address of target buffer. */ 00460 /* */ 00461 /* <Return> */ 00462 /* FreeType error code. 0 means success. */ 00463 /* */ 00464 FT_LOCAL_DEF( FT_Error ) 00465 tt_face_load_any( TT_Face face, 00466 FT_ULong tag, 00467 FT_Long offset, 00468 FT_Byte* buffer, 00469 FT_ULong* length ) 00470 { 00471 FT_Error error; 00472 FT_Stream stream; 00473 TT_Table table; 00474 FT_ULong size; 00475 00476 00477 if ( tag != 0 ) 00478 { 00479 /* look for tag in font directory */ 00480 table = tt_face_lookup_table( face, tag ); 00481 if ( !table ) 00482 { 00483 error = SFNT_Err_Table_Missing; 00484 goto Exit; 00485 } 00486 00487 offset += table->Offset; 00488 size = table->Length; 00489 } 00490 else 00491 /* tag == 0 -- the user wants to access the font file directly */ 00492 size = face->root.stream->size; 00493 00494 if ( length && *length == 0 ) 00495 { 00496 *length = size; 00497 00498 return SFNT_Err_Ok; 00499 } 00500 00501 if ( length ) 00502 size = *length; 00503 00504 stream = face->root.stream; 00505 /* the `if' is syntactic sugar for picky compilers */ 00506 if ( FT_STREAM_READ_AT( offset, buffer, size ) ) 00507 goto Exit; 00508 00509 Exit: 00510 return error; 00511 } 00512 00513 00514 /*************************************************************************/ 00515 /* */ 00516 /* <Function> */ 00517 /* tt_face_load_generic_header */ 00518 /* */ 00519 /* <Description> */ 00520 /* Loads the TrueType table `head' or `bhed'. */ 00521 /* */ 00522 /* <Input> */ 00523 /* face :: A handle to the target face object. */ 00524 /* */ 00525 /* stream :: The input stream. */ 00526 /* */ 00527 /* <Return> */ 00528 /* FreeType error code. 0 means success. */ 00529 /* */ 00530 static FT_Error 00531 tt_face_load_generic_header( TT_Face face, 00532 FT_Stream stream, 00533 FT_ULong tag ) 00534 { 00535 FT_Error error; 00536 TT_Header* header; 00537 00538 static const FT_Frame_Field header_fields[] = 00539 { 00540 #undef FT_STRUCTURE 00541 #define FT_STRUCTURE TT_Header 00542 00543 FT_FRAME_START( 54 ), 00544 FT_FRAME_ULONG ( Table_Version ), 00545 FT_FRAME_ULONG ( Font_Revision ), 00546 FT_FRAME_LONG ( CheckSum_Adjust ), 00547 FT_FRAME_LONG ( Magic_Number ), 00548 FT_FRAME_USHORT( Flags ), 00549 FT_FRAME_USHORT( Units_Per_EM ), 00550 FT_FRAME_LONG ( Created[0] ), 00551 FT_FRAME_LONG ( Created[1] ), 00552 FT_FRAME_LONG ( Modified[0] ), 00553 FT_FRAME_LONG ( Modified[1] ), 00554 FT_FRAME_SHORT ( xMin ), 00555 FT_FRAME_SHORT ( yMin ), 00556 FT_FRAME_SHORT ( xMax ), 00557 FT_FRAME_SHORT ( yMax ), 00558 FT_FRAME_USHORT( Mac_Style ), 00559 FT_FRAME_USHORT( Lowest_Rec_PPEM ), 00560 FT_FRAME_SHORT ( Font_Direction ), 00561 FT_FRAME_SHORT ( Index_To_Loc_Format ), 00562 FT_FRAME_SHORT ( Glyph_Data_Format ), 00563 FT_FRAME_END 00564 }; 00565 00566 00567 error = face->goto_table( face, tag, stream, 0 ); 00568 if ( error ) 00569 goto Exit; 00570 00571 header = &face->header; 00572 00573 if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) 00574 goto Exit; 00575 00576 FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM )); 00577 FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format )); 00578 00579 Exit: 00580 return error; 00581 } 00582 00583 00584 FT_LOCAL_DEF( FT_Error ) 00585 tt_face_load_head( TT_Face face, 00586 FT_Stream stream ) 00587 { 00588 return tt_face_load_generic_header( face, stream, TTAG_head ); 00589 } 00590 00591 00592 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00593 00594 FT_LOCAL_DEF( FT_Error ) 00595 tt_face_load_bhed( TT_Face face, 00596 FT_Stream stream ) 00597 { 00598 return tt_face_load_generic_header( face, stream, TTAG_bhed ); 00599 } 00600 00601 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 00602 00603 00604 /*************************************************************************/ 00605 /* */ 00606 /* <Function> */ 00607 /* tt_face_load_max_profile */ 00608 /* */ 00609 /* <Description> */ 00610 /* Loads the maximum profile into a face object. */ 00611 /* */ 00612 /* <Input> */ 00613 /* face :: A handle to the target face object. */ 00614 /* */ 00615 /* stream :: The input stream. */ 00616 /* */ 00617 /* <Return> */ 00618 /* FreeType error code. 0 means success. */ 00619 /* */ 00620 FT_LOCAL_DEF( FT_Error ) 00621 tt_face_load_maxp( TT_Face face, 00622 FT_Stream stream ) 00623 { 00624 FT_Error error; 00625 TT_MaxProfile* maxProfile = &face->max_profile; 00626 00627 const FT_Frame_Field maxp_fields[] = 00628 { 00629 #undef FT_STRUCTURE 00630 #define FT_STRUCTURE TT_MaxProfile 00631 00632 FT_FRAME_START( 6 ), 00633 FT_FRAME_LONG ( version ), 00634 FT_FRAME_USHORT( numGlyphs ), 00635 FT_FRAME_END 00636 }; 00637 00638 const FT_Frame_Field maxp_fields_extra[] = 00639 { 00640 FT_FRAME_START( 26 ), 00641 FT_FRAME_USHORT( maxPoints ), 00642 FT_FRAME_USHORT( maxContours ), 00643 FT_FRAME_USHORT( maxCompositePoints ), 00644 FT_FRAME_USHORT( maxCompositeContours ), 00645 FT_FRAME_USHORT( maxZones ), 00646 FT_FRAME_USHORT( maxTwilightPoints ), 00647 FT_FRAME_USHORT( maxStorage ), 00648 FT_FRAME_USHORT( maxFunctionDefs ), 00649 FT_FRAME_USHORT( maxInstructionDefs ), 00650 FT_FRAME_USHORT( maxStackElements ), 00651 FT_FRAME_USHORT( maxSizeOfInstructions ), 00652 FT_FRAME_USHORT( maxComponentElements ), 00653 FT_FRAME_USHORT( maxComponentDepth ), 00654 FT_FRAME_END 00655 }; 00656 00657 00658 error = face->goto_table( face, TTAG_maxp, stream, 0 ); 00659 if ( error ) 00660 goto Exit; 00661 00662 if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) ) 00663 goto Exit; 00664 00665 maxProfile->maxPoints = 0; 00666 maxProfile->maxContours = 0; 00667 maxProfile->maxCompositePoints = 0; 00668 maxProfile->maxCompositeContours = 0; 00669 maxProfile->maxZones = 0; 00670 maxProfile->maxTwilightPoints = 0; 00671 maxProfile->maxStorage = 0; 00672 maxProfile->maxFunctionDefs = 0; 00673 maxProfile->maxInstructionDefs = 0; 00674 maxProfile->maxStackElements = 0; 00675 maxProfile->maxSizeOfInstructions = 0; 00676 maxProfile->maxComponentElements = 0; 00677 maxProfile->maxComponentDepth = 0; 00678 00679 if ( maxProfile->version >= 0x10000L ) 00680 { 00681 if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) ) 00682 goto Exit; 00683 00684 /* XXX: an adjustment that is necessary to load certain */ 00685 /* broken fonts like `Keystrokes MT' :-( */ 00686 /* */ 00687 /* We allocate 64 function entries by default when */ 00688 /* the maxFunctionDefs value is smaller. */ 00689 00690 if ( maxProfile->maxFunctionDefs < 64 ) 00691 maxProfile->maxFunctionDefs = 64; 00692 00693 /* we add 4 phantom points later */ 00694 if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) ) 00695 { 00696 FT_TRACE0(( "tt_face_load_maxp:" 00697 " too much twilight points in `maxp' table;\n" 00698 " " 00699 " some glyphs might be rendered incorrectly\n" )); 00700 00701 maxProfile->maxTwilightPoints = 0xFFFFU - 4; 00702 } 00703 00704 /* we arbitrarily limit recursion to avoid stack exhaustion */ 00705 if ( maxProfile->maxComponentDepth > 100 ) 00706 { 00707 FT_TRACE0(( "tt_face_load_maxp:" 00708 " abnormally large component depth (%d) set to 100\n", 00709 maxProfile->maxComponentDepth )); 00710 maxProfile->maxComponentDepth = 100; 00711 } 00712 } 00713 00714 FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); 00715 00716 Exit: 00717 return error; 00718 } 00719 00720 00721 /*************************************************************************/ 00722 /* */ 00723 /* <Function> */ 00724 /* tt_face_load_names */ 00725 /* */ 00726 /* <Description> */ 00727 /* Loads the name records. */ 00728 /* */ 00729 /* <Input> */ 00730 /* face :: A handle to the target face object. */ 00731 /* */ 00732 /* stream :: The input stream. */ 00733 /* */ 00734 /* <Return> */ 00735 /* FreeType error code. 0 means success. */ 00736 /* */ 00737 FT_LOCAL_DEF( FT_Error ) 00738 tt_face_load_name( TT_Face face, 00739 FT_Stream stream ) 00740 { 00741 FT_Error error; 00742 FT_Memory memory = stream->memory; 00743 FT_ULong table_pos, table_len; 00744 FT_ULong storage_start, storage_limit; 00745 FT_UInt count; 00746 TT_NameTable table; 00747 00748 static const FT_Frame_Field name_table_fields[] = 00749 { 00750 #undef FT_STRUCTURE 00751 #define FT_STRUCTURE TT_NameTableRec 00752 00753 FT_FRAME_START( 6 ), 00754 FT_FRAME_USHORT( format ), 00755 FT_FRAME_USHORT( numNameRecords ), 00756 FT_FRAME_USHORT( storageOffset ), 00757 FT_FRAME_END 00758 }; 00759 00760 static const FT_Frame_Field name_record_fields[] = 00761 { 00762 #undef FT_STRUCTURE 00763 #define FT_STRUCTURE TT_NameEntryRec 00764 00765 /* no FT_FRAME_START */ 00766 FT_FRAME_USHORT( platformID ), 00767 FT_FRAME_USHORT( encodingID ), 00768 FT_FRAME_USHORT( languageID ), 00769 FT_FRAME_USHORT( nameID ), 00770 FT_FRAME_USHORT( stringLength ), 00771 FT_FRAME_USHORT( stringOffset ), 00772 FT_FRAME_END 00773 }; 00774 00775 00776 table = &face->name_table; 00777 table->stream = stream; 00778 00779 error = face->goto_table( face, TTAG_name, stream, &table_len ); 00780 if ( error ) 00781 goto Exit; 00782 00783 table_pos = FT_STREAM_POS(); 00784 00785 00786 if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) 00787 goto Exit; 00788 00789 /* Some popular Asian fonts have an invalid `storageOffset' value */ 00790 /* (it should be at least "6 + 12*num_names"). However, the string */ 00791 /* offsets, computed as "storageOffset + entry->stringOffset", are */ 00792 /* valid pointers within the name table... */ 00793 /* */ 00794 /* We thus can't check `storageOffset' right now. */ 00795 /* */ 00796 storage_start = table_pos + 6 + 12*table->numNameRecords; 00797 storage_limit = table_pos + table_len; 00798 00799 if ( storage_start > storage_limit ) 00800 { 00801 FT_ERROR(( "tt_face_load_name: invalid `name' table\n" )); 00802 error = SFNT_Err_Name_Table_Missing; 00803 goto Exit; 00804 } 00805 00806 /* Allocate the array of name records. */ 00807 count = table->numNameRecords; 00808 table->numNameRecords = 0; 00809 00810 if ( FT_NEW_ARRAY( table->names, count ) || 00811 FT_FRAME_ENTER( count * 12 ) ) 00812 goto Exit; 00813 00814 /* Load the name records and determine how much storage is needed */ 00815 /* to hold the strings themselves. */ 00816 { 00817 TT_NameEntryRec* entry = table->names; 00818 00819 00820 for ( ; count > 0; count-- ) 00821 { 00822 if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) ) 00823 continue; 00824 00825 /* check that the name is not empty */ 00826 if ( entry->stringLength == 0 ) 00827 continue; 00828 00829 /* check that the name string is within the table */ 00830 entry->stringOffset += table_pos + table->storageOffset; 00831 if ( entry->stringOffset < storage_start || 00832 entry->stringOffset + entry->stringLength > storage_limit ) 00833 { 00834 /* invalid entry - ignore it */ 00835 entry->stringOffset = 0; 00836 entry->stringLength = 0; 00837 continue; 00838 } 00839 00840 entry++; 00841 } 00842 00843 table->numNameRecords = (FT_UInt)( entry - table->names ); 00844 } 00845 00846 FT_FRAME_EXIT(); 00847 00848 /* everything went well, update face->num_names */ 00849 face->num_names = (FT_UShort) table->numNameRecords; 00850 00851 Exit: 00852 return error; 00853 } 00854 00855 00856 /*************************************************************************/ 00857 /* */ 00858 /* <Function> */ 00859 /* tt_face_free_names */ 00860 /* */ 00861 /* <Description> */ 00862 /* Frees the name records. */ 00863 /* */ 00864 /* <Input> */ 00865 /* face :: A handle to the target face object. */ 00866 /* */ 00867 FT_LOCAL_DEF( void ) 00868 tt_face_free_name( TT_Face face ) 00869 { 00870 FT_Memory memory = face->root.driver->root.memory; 00871 TT_NameTable table = &face->name_table; 00872 TT_NameEntry entry = table->names; 00873 FT_UInt count = table->numNameRecords; 00874 00875 00876 if ( table->names ) 00877 { 00878 for ( ; count > 0; count--, entry++ ) 00879 { 00880 FT_FREE( entry->string ); 00881 entry->stringLength = 0; 00882 } 00883 00884 /* free strings table */ 00885 FT_FREE( table->names ); 00886 } 00887 00888 table->numNameRecords = 0; 00889 table->format = 0; 00890 table->storageOffset = 0; 00891 } 00892 00893 00894 /*************************************************************************/ 00895 /* */ 00896 /* <Function> */ 00897 /* tt_face_load_cmap */ 00898 /* */ 00899 /* <Description> */ 00900 /* Loads the cmap directory in a face object. The cmaps themselves */ 00901 /* are loaded on demand in the `ttcmap.c' module. */ 00902 /* */ 00903 /* <Input> */ 00904 /* face :: A handle to the target face object. */ 00905 /* */ 00906 /* stream :: A handle to the input stream. */ 00907 /* */ 00908 /* <Return> */ 00909 /* FreeType error code. 0 means success. */ 00910 /* */ 00911 00912 FT_LOCAL_DEF( FT_Error ) 00913 tt_face_load_cmap( TT_Face face, 00914 FT_Stream stream ) 00915 { 00916 FT_Error error; 00917 00918 00919 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); 00920 if ( error ) 00921 goto Exit; 00922 00923 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) 00924 face->cmap_size = 0; 00925 00926 Exit: 00927 return error; 00928 } 00929 00930 00931 00932 /*************************************************************************/ 00933 /* */ 00934 /* <Function> */ 00935 /* tt_face_load_os2 */ 00936 /* */ 00937 /* <Description> */ 00938 /* Loads the OS2 table. */ 00939 /* */ 00940 /* <Input> */ 00941 /* face :: A handle to the target face object. */ 00942 /* */ 00943 /* stream :: A handle to the input stream. */ 00944 /* */ 00945 /* <Return> */ 00946 /* FreeType error code. 0 means success. */ 00947 /* */ 00948 FT_LOCAL_DEF( FT_Error ) 00949 tt_face_load_os2( TT_Face face, 00950 FT_Stream stream ) 00951 { 00952 FT_Error error; 00953 TT_OS2* os2; 00954 00955 const FT_Frame_Field os2_fields[] = 00956 { 00957 #undef FT_STRUCTURE 00958 #define FT_STRUCTURE TT_OS2 00959 00960 FT_FRAME_START( 78 ), 00961 FT_FRAME_USHORT( version ), 00962 FT_FRAME_SHORT ( xAvgCharWidth ), 00963 FT_FRAME_USHORT( usWeightClass ), 00964 FT_FRAME_USHORT( usWidthClass ), 00965 FT_FRAME_SHORT ( fsType ), 00966 FT_FRAME_SHORT ( ySubscriptXSize ), 00967 FT_FRAME_SHORT ( ySubscriptYSize ), 00968 FT_FRAME_SHORT ( ySubscriptXOffset ), 00969 FT_FRAME_SHORT ( ySubscriptYOffset ), 00970 FT_FRAME_SHORT ( ySuperscriptXSize ), 00971 FT_FRAME_SHORT ( ySuperscriptYSize ), 00972 FT_FRAME_SHORT ( ySuperscriptXOffset ), 00973 FT_FRAME_SHORT ( ySuperscriptYOffset ), 00974 FT_FRAME_SHORT ( yStrikeoutSize ), 00975 FT_FRAME_SHORT ( yStrikeoutPosition ), 00976 FT_FRAME_SHORT ( sFamilyClass ), 00977 FT_FRAME_BYTE ( panose[0] ), 00978 FT_FRAME_BYTE ( panose[1] ), 00979 FT_FRAME_BYTE ( panose[2] ), 00980 FT_FRAME_BYTE ( panose[3] ), 00981 FT_FRAME_BYTE ( panose[4] ), 00982 FT_FRAME_BYTE ( panose[5] ), 00983 FT_FRAME_BYTE ( panose[6] ), 00984 FT_FRAME_BYTE ( panose[7] ), 00985 FT_FRAME_BYTE ( panose[8] ), 00986 FT_FRAME_BYTE ( panose[9] ), 00987 FT_FRAME_ULONG ( ulUnicodeRange1 ), 00988 FT_FRAME_ULONG ( ulUnicodeRange2 ), 00989 FT_FRAME_ULONG ( ulUnicodeRange3 ), 00990 FT_FRAME_ULONG ( ulUnicodeRange4 ), 00991 FT_FRAME_BYTE ( achVendID[0] ), 00992 FT_FRAME_BYTE ( achVendID[1] ), 00993 FT_FRAME_BYTE ( achVendID[2] ), 00994 FT_FRAME_BYTE ( achVendID[3] ), 00995 00996 FT_FRAME_USHORT( fsSelection ), 00997 FT_FRAME_USHORT( usFirstCharIndex ), 00998 FT_FRAME_USHORT( usLastCharIndex ), 00999 FT_FRAME_SHORT ( sTypoAscender ), 01000 FT_FRAME_SHORT ( sTypoDescender ), 01001 FT_FRAME_SHORT ( sTypoLineGap ), 01002 FT_FRAME_USHORT( usWinAscent ), 01003 FT_FRAME_USHORT( usWinDescent ), 01004 FT_FRAME_END 01005 }; 01006 01007 const FT_Frame_Field os2_fields_extra[] = 01008 { 01009 FT_FRAME_START( 8 ), 01010 FT_FRAME_ULONG( ulCodePageRange1 ), 01011 FT_FRAME_ULONG( ulCodePageRange2 ), 01012 FT_FRAME_END 01013 }; 01014 01015 const FT_Frame_Field os2_fields_extra2[] = 01016 { 01017 FT_FRAME_START( 10 ), 01018 FT_FRAME_SHORT ( sxHeight ), 01019 FT_FRAME_SHORT ( sCapHeight ), 01020 FT_FRAME_USHORT( usDefaultChar ), 01021 FT_FRAME_USHORT( usBreakChar ), 01022 FT_FRAME_USHORT( usMaxContext ), 01023 FT_FRAME_END 01024 }; 01025 01026 01027 /* We now support old Mac fonts where the OS/2 table doesn't */ 01028 /* exist. Simply put, we set the `version' field to 0xFFFF */ 01029 /* and test this value each time we need to access the table. */ 01030 error = face->goto_table( face, TTAG_OS2, stream, 0 ); 01031 if ( error ) 01032 goto Exit; 01033 01034 os2 = &face->os2; 01035 01036 if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) ) 01037 goto Exit; 01038 01039 os2->ulCodePageRange1 = 0; 01040 os2->ulCodePageRange2 = 0; 01041 os2->sxHeight = 0; 01042 os2->sCapHeight = 0; 01043 os2->usDefaultChar = 0; 01044 os2->usBreakChar = 0; 01045 os2->usMaxContext = 0; 01046 01047 if ( os2->version >= 0x0001 ) 01048 { 01049 /* only version 1 tables */ 01050 if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) ) 01051 goto Exit; 01052 01053 if ( os2->version >= 0x0002 ) 01054 { 01055 /* only version 2 tables */ 01056 if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) ) 01057 goto Exit; 01058 } 01059 } 01060 01061 FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); 01062 FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); 01063 FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); 01064 FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); 01065 FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); 01066 01067 Exit: 01068 return error; 01069 } 01070 01071 01072 /*************************************************************************/ 01073 /* */ 01074 /* <Function> */ 01075 /* tt_face_load_postscript */ 01076 /* */ 01077 /* <Description> */ 01078 /* Loads the Postscript table. */ 01079 /* */ 01080 /* <Input> */ 01081 /* face :: A handle to the target face object. */ 01082 /* */ 01083 /* stream :: A handle to the input stream. */ 01084 /* */ 01085 /* <Return> */ 01086 /* FreeType error code. 0 means success. */ 01087 /* */ 01088 FT_LOCAL_DEF( FT_Error ) 01089 tt_face_load_post( TT_Face face, 01090 FT_Stream stream ) 01091 { 01092 FT_Error error; 01093 TT_Postscript* post = &face->postscript; 01094 01095 static const FT_Frame_Field post_fields[] = 01096 { 01097 #undef FT_STRUCTURE 01098 #define FT_STRUCTURE TT_Postscript 01099 01100 FT_FRAME_START( 32 ), 01101 FT_FRAME_ULONG( FormatType ), 01102 FT_FRAME_ULONG( italicAngle ), 01103 FT_FRAME_SHORT( underlinePosition ), 01104 FT_FRAME_SHORT( underlineThickness ), 01105 FT_FRAME_ULONG( isFixedPitch ), 01106 FT_FRAME_ULONG( minMemType42 ), 01107 FT_FRAME_ULONG( maxMemType42 ), 01108 FT_FRAME_ULONG( minMemType1 ), 01109 FT_FRAME_ULONG( maxMemType1 ), 01110 FT_FRAME_END 01111 }; 01112 01113 01114 error = face->goto_table( face, TTAG_post, stream, 0 ); 01115 if ( error ) 01116 return error; 01117 01118 if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) 01119 return error; 01120 01121 /* we don't load the glyph names, we do that in another */ 01122 /* module (ttpost). */ 01123 01124 FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType )); 01125 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch 01126 ? " yes" : " no" )); 01127 01128 return SFNT_Err_Ok; 01129 } 01130 01131 01132 /*************************************************************************/ 01133 /* */ 01134 /* <Function> */ 01135 /* tt_face_load_pclt */ 01136 /* */ 01137 /* <Description> */ 01138 /* Loads the PCL 5 Table. */ 01139 /* */ 01140 /* <Input> */ 01141 /* face :: A handle to the target face object. */ 01142 /* */ 01143 /* stream :: A handle to the input stream. */ 01144 /* */ 01145 /* <Return> */ 01146 /* FreeType error code. 0 means success. */ 01147 /* */ 01148 FT_LOCAL_DEF( FT_Error ) 01149 tt_face_load_pclt( TT_Face face, 01150 FT_Stream stream ) 01151 { 01152 static const FT_Frame_Field pclt_fields[] = 01153 { 01154 #undef FT_STRUCTURE 01155 #define FT_STRUCTURE TT_PCLT 01156 01157 FT_FRAME_START( 54 ), 01158 FT_FRAME_ULONG ( Version ), 01159 FT_FRAME_ULONG ( FontNumber ), 01160 FT_FRAME_USHORT( Pitch ), 01161 FT_FRAME_USHORT( xHeight ), 01162 FT_FRAME_USHORT( Style ), 01163 FT_FRAME_USHORT( TypeFamily ), 01164 FT_FRAME_USHORT( CapHeight ), 01165 FT_FRAME_BYTES ( TypeFace, 16 ), 01166 FT_FRAME_BYTES ( CharacterComplement, 8 ), 01167 FT_FRAME_BYTES ( FileName, 6 ), 01168 FT_FRAME_CHAR ( StrokeWeight ), 01169 FT_FRAME_CHAR ( WidthType ), 01170 FT_FRAME_BYTE ( SerifStyle ), 01171 FT_FRAME_BYTE ( Reserved ), 01172 FT_FRAME_END 01173 }; 01174 01175 FT_Error error; 01176 TT_PCLT* pclt = &face->pclt; 01177 01178 01179 /* optional table */ 01180 error = face->goto_table( face, TTAG_PCLT, stream, 0 ); 01181 if ( error ) 01182 goto Exit; 01183 01184 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) 01185 goto Exit; 01186 01187 Exit: 01188 return error; 01189 } 01190 01191 01192 /*************************************************************************/ 01193 /* */ 01194 /* <Function> */ 01195 /* tt_face_load_gasp */ 01196 /* */ 01197 /* <Description> */ 01198 /* Loads the `gasp' table into a face object. */ 01199 /* */ 01200 /* <Input> */ 01201 /* face :: A handle to the target face object. */ 01202 /* */ 01203 /* stream :: The input stream. */ 01204 /* */ 01205 /* <Return> */ 01206 /* FreeType error code. 0 means success. */ 01207 /* */ 01208 FT_LOCAL_DEF( FT_Error ) 01209 tt_face_load_gasp( TT_Face face, 01210 FT_Stream stream ) 01211 { 01212 FT_Error error; 01213 FT_Memory memory = stream->memory; 01214 01215 FT_UInt j,num_ranges; 01216 TT_GaspRange gaspranges; 01217 01218 01219 /* the gasp table is optional */ 01220 error = face->goto_table( face, TTAG_gasp, stream, 0 ); 01221 if ( error ) 01222 goto Exit; 01223 01224 if ( FT_FRAME_ENTER( 4L ) ) 01225 goto Exit; 01226 01227 face->gasp.version = FT_GET_USHORT(); 01228 face->gasp.numRanges = FT_GET_USHORT(); 01229 01230 FT_FRAME_EXIT(); 01231 01232 /* only support versions 0 and 1 of the table */ 01233 if ( face->gasp.version >= 2 ) 01234 { 01235 face->gasp.numRanges = 0; 01236 error = SFNT_Err_Invalid_Table; 01237 goto Exit; 01238 } 01239 01240 num_ranges = face->gasp.numRanges; 01241 FT_TRACE3(( "numRanges: %u\n", num_ranges )); 01242 01243 if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) || 01244 FT_FRAME_ENTER( num_ranges * 4L ) ) 01245 goto Exit; 01246 01247 face->gasp.gaspRanges = gaspranges; 01248 01249 for ( j = 0; j < num_ranges; j++ ) 01250 { 01251 gaspranges[j].maxPPEM = FT_GET_USHORT(); 01252 gaspranges[j].gaspFlag = FT_GET_USHORT(); 01253 01254 FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n", 01255 j, 01256 gaspranges[j].maxPPEM, 01257 gaspranges[j].gaspFlag )); 01258 } 01259 01260 FT_FRAME_EXIT(); 01261 01262 Exit: 01263 return error; 01264 } 01265 01266 01267 /* END */ Generated on Sat May 26 2012 04:32:56 for ReactOS by
1.7.6.1
|