1 /***************************************************************************/ 2 /* */ 3 /* ttpload.c */ 4 /* */ 5 /* TrueType-specific tables loader (body). */ 6 /* */ 7 /* Copyright 1996-2002, 2004-2013 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include "../../include/ft2build.h" 20 #include "../../include/freetype/internal/ftdebug.h" 21 #include "../../include/freetype/internal/ftobjs.h" 22 #include "../../include/freetype/internal/ftstream.h" 23 #include "../../include/freetype/tttags.h" 24 25 #include "ttpload.h" 26 27 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 28 #include "ttgxvar.h" 29 #endif 30 31 #include "tterrors.h" 32 33 34 /*************************************************************************/ 35 /* */ 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 38 /* messages during execution. */ 39 /* */ 40 #undef FT_COMPONENT 41 #define FT_COMPONENT trace_ttpload 42 43 44 /*************************************************************************/ 45 /* */ 46 /* <Function> */ 47 /* tt_face_load_loca */ 48 /* */ 49 /* <Description> */ 50 /* Load the locations table. */ 51 /* */ 52 /* <InOut> */ 53 /* face :: A handle to the target face object. */ 54 /* */ 55 /* <Input> */ 56 /* stream :: The input stream. */ 57 /* */ 58 /* <Return> */ 59 /* FreeType error code. 0 means success. */ 60 /* */ 61 FT_LOCAL_DEF( FT_Error ) 62 tt_face_load_loca( TT_Face face, 63 FT_Stream stream ) 64 { 65 FT_Error error; 66 FT_ULong table_len; 67 FT_Int shift; 68 69 70 /* we need the size of the `glyf' table for malformed `loca' tables */ 71 error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len ); 72 73 /* it is possible that a font doesn't have a glyf table at all */ 74 /* or its size is zero */ 75 if ( FT_ERR_EQ( error, Table_Missing ) ) 76 face->glyf_len = 0; 77 else if ( error ) 78 goto Exit; 79 80 FT_TRACE2(( "Locations " )); 81 error = face->goto_table( face, TTAG_loca, stream, &table_len ); 82 if ( error ) 83 { 84 error = FT_THROW( Locations_Missing ); 85 goto Exit; 86 } 87 88 if ( face->header.Index_To_Loc_Format != 0 ) 89 { 90 shift = 2; 91 92 if ( table_len >= 0x40000L ) 93 { 94 FT_TRACE2(( "table too large\n" )); 95 error = FT_THROW( Invalid_Table ); 96 goto Exit; 97 } 98 face->num_locations = table_len >> shift; 99 } 100 else 101 { 102 shift = 1; 103 104 if ( table_len >= 0x20000L ) 105 { 106 FT_TRACE2(( "table too large\n" )); 107 error = FT_THROW( Invalid_Table ); 108 goto Exit; 109 } 110 face->num_locations = table_len >> shift; 111 } 112 /* Sunliang.Liu 20101013, We ignore the 242 new added code which cause some font load failed. 113 TESTDOC: Bug #4502 - PM2-beheerdershandleiding.pdf*/ 114 /*if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 ) 115 { 116 FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n", 117 face->num_locations - 1, face->root.num_glyphs )); 118 119 // we only handle the case where `maxp' gives a larger value 120 if ( face->num_locations <= (FT_ULong)face->root.num_glyphs ) 121 { 122 FT_Long new_loca_len = 123 ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift; 124 125 TT_Table entry = face->dir_tables; 126 TT_Table limit = entry + face->num_tables; 127 128 FT_Long pos = FT_Stream_Pos( stream ); 129 FT_Long dist = 0x7FFFFFFFL; 130 131 132 // compute the distance to next table in font file 133 for ( ; entry < limit; entry++ ) 134 { 135 FT_Long diff = entry->Offset - pos; 136 137 138 if ( diff > 0 && diff < dist ) 139 dist = diff; 140 } 141 142 if ( entry == limit ) 143 { 144 // `loca' is the last table 145 dist = stream->size - pos; 146 } 147 148 if ( new_loca_len <= dist ) 149 { 150 face->num_locations = face->root.num_glyphs + 1; 151 table_len = new_loca_len; 152 153 FT_TRACE2(( "adjusting num_locations to %d\n", 154 face->num_locations )); 155 } 156 } 157 }*/ 158 159 /* 160 * Extract the frame. We don't need to decompress it since 161 * we are able to parse it directly. 162 */ 163 if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) ) 164 goto Exit; 165 166 FT_TRACE2(( "loaded\n" )); 167 168 Exit: 169 return error; 170 } 171 172 173 FT_LOCAL_DEF( FT_ULong ) 174 tt_face_get_location( TT_Face face, 175 FT_UInt gindex, 176 FT_UInt *asize ) 177 { 178 FT_ULong pos1, pos2; 179 FT_Byte* p; 180 FT_Byte* p_limit; 181 182 183 pos1 = pos2 = 0; 184 185 186 if (gindex < face->num_locations)/* gindex < face->num_locations */ /* XYQ 2008-11-03 Some ill TT has wrong glyf table size. It seems Adobe ignore the limit. TESTDOC: Bug #6248 - F-2008-18.pdf */ 187 { 188 if ( face->header.Index_To_Loc_Format != 0 ) 189 { 190 p = face->glyph_locations + gindex * 4; 191 p_limit = face->glyph_locations + face->num_locations * 4; 192 193 pos1 = FT_NEXT_ULONG( p ); 194 pos2 = pos1; 195 196 if (1)/* p + 4 <= p_limit ) */ 197 pos2 = FT_NEXT_ULONG( p ); 198 } 199 else 200 { 201 p = face->glyph_locations + gindex * 2; 202 p_limit = face->glyph_locations + face->num_locations * 2; 203 204 pos1 = FT_NEXT_USHORT( p ); 205 pos2 = pos1; 206 207 if (1) /* p + 2 <= p_limit ) */ 208 pos2 = FT_NEXT_USHORT( p ); 209 210 pos1 <<= 1; 211 pos2 <<= 1; 212 } 213 } 214 215 /* Check broken location data */ 216 if ( pos1 > face->glyf_len ) 217 { 218 FT_TRACE1(( "tt_face_get_location:" 219 " too large offset=0x%08lx found for gid=0x%04lx," 220 " exceeding the end of glyf table (0x%08lx)\n", 221 pos1, gindex, face->glyf_len )); 222 *asize = 0; 223 return 0; 224 } 225 226 if ( pos2 > face->glyf_len ) 227 { 228 FT_TRACE1(( "tt_face_get_location:" 229 " too large offset=0x%08lx found for gid=0x%04lx," 230 " truncate at the end of glyf table (0x%08lx)\n", 231 pos2, gindex + 1, face->glyf_len )); 232 pos2 = face->glyf_len; 233 } 234 235 /* The `loca' table must be ordered; it refers to the length of */ 236 /* an entry as the difference between the current and the next */ 237 /* position. However, there do exist (malformed) fonts which */ 238 /* don't obey this rule, so we are only able to provide an */ 239 /* upper bound for the size. */ 240 /* */ 241 /* We get (intentionally) a wrong, non-zero result in case the */ 242 /* `glyf' table is missing. */ 243 if ( pos2 >= pos1 ) 244 *asize = (FT_UInt)( pos2 - pos1 ); 245 else 246 *asize = (FT_UInt)( face->glyf_len - pos1 ); 247 248 return pos1; 249 } 250 251 252 FT_LOCAL_DEF( void ) 253 tt_face_done_loca( TT_Face face ) 254 { 255 FT_Stream stream = face->root.stream; 256 257 258 FT_FRAME_RELEASE( face->glyph_locations ); 259 face->num_locations = 0; 260 } 261 262 263 264 /*************************************************************************/ 265 /* */ 266 /* <Function> */ 267 /* tt_face_load_cvt */ 268 /* */ 269 /* <Description> */ 270 /* Load the control value table into a face object. */ 271 /* */ 272 /* <InOut> */ 273 /* face :: A handle to the target face object. */ 274 /* */ 275 /* <Input> */ 276 /* stream :: A handle to the input stream. */ 277 /* */ 278 /* <Return> */ 279 /* FreeType error code. 0 means success. */ 280 /* */ 281 FT_LOCAL_DEF( FT_Error ) 282 tt_face_load_cvt( TT_Face face, 283 FT_Stream stream ) 284 { 285 #ifdef TT_USE_BYTECODE_INTERPRETER 286 287 FT_Error error; 288 FT_Memory memory = stream->memory; 289 FT_ULong table_len; 290 291 292 FT_TRACE2(( "CVT " )); 293 294 error = face->goto_table( face, TTAG_cvt, stream, &table_len ); 295 if ( error ) 296 { 297 FT_TRACE2(( "is missing\n" )); 298 299 face->cvt_size = 0; 300 face->cvt = NULL; 301 error = FT_Err_Ok; 302 303 goto Exit; 304 } 305 306 face->cvt_size = table_len / 2; 307 308 if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) ) 309 goto Exit; 310 311 if ( FT_FRAME_ENTER( face->cvt_size * 2L ) ) 312 goto Exit; 313 314 { 315 FT_Short* cur = face->cvt; 316 FT_Short* limit = cur + face->cvt_size; 317 318 319 for ( ; cur < limit; cur++ ) 320 *cur = FT_GET_SHORT(); 321 } 322 323 FT_FRAME_EXIT(); 324 FT_TRACE2(( "loaded\n" )); 325 326 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 327 if ( face->doblend ) 328 error = tt_face_vary_cvt( face, stream ); 329 #endif 330 331 Exit: 332 return error; 333 334 #else /* !TT_USE_BYTECODE_INTERPRETER */ 335 336 FT_UNUSED( face ); 337 FT_UNUSED( stream ); 338 339 return FT_Err_Ok; 340 341 #endif 342 } 343 344 345 /*************************************************************************/ 346 /* */ 347 /* <Function> */ 348 /* tt_face_load_fpgm */ 349 /* */ 350 /* <Description> */ 351 /* Load the font program. */ 352 /* */ 353 /* <InOut> */ 354 /* face :: A handle to the target face object. */ 355 /* */ 356 /* <Input> */ 357 /* stream :: A handle to the input stream. */ 358 /* */ 359 /* <Return> */ 360 /* FreeType error code. 0 means success. */ 361 /* */ 362 FT_LOCAL_DEF( FT_Error ) 363 tt_face_load_fpgm( TT_Face face, 364 FT_Stream stream ) 365 { 366 #ifdef TT_USE_BYTECODE_INTERPRETER 367 368 FT_Error error; 369 FT_ULong table_len; 370 371 372 FT_TRACE2(( "Font program " )); 373 374 /* The font program is optional */ 375 error = face->goto_table( face, TTAG_fpgm, stream, &table_len ); 376 if ( error ) 377 { 378 face->font_program = NULL; 379 face->font_program_size = 0; 380 error = FT_Err_Ok; 381 382 FT_TRACE2(( "is missing\n" )); 383 } 384 else 385 { 386 face->font_program_size = table_len; 387 if ( FT_FRAME_EXTRACT( table_len, face->font_program ) ) 388 goto Exit; 389 390 FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); 391 } 392 393 Exit: 394 return error; 395 396 #else /* !TT_USE_BYTECODE_INTERPRETER */ 397 398 FT_UNUSED( face ); 399 FT_UNUSED( stream ); 400 401 return FT_Err_Ok; 402 403 #endif 404 } 405 406 407 /*************************************************************************/ 408 /* */ 409 /* <Function> */ 410 /* tt_face_load_prep */ 411 /* */ 412 /* <Description> */ 413 /* Load the cvt program. */ 414 /* */ 415 /* <InOut> */ 416 /* face :: A handle to the target face object. */ 417 /* */ 418 /* <Input> */ 419 /* stream :: A handle to the input stream. */ 420 /* */ 421 /* <Return> */ 422 /* FreeType error code. 0 means success. */ 423 /* */ 424 FT_LOCAL_DEF( FT_Error ) 425 tt_face_load_prep( TT_Face face, 426 FT_Stream stream ) 427 { 428 #ifdef TT_USE_BYTECODE_INTERPRETER 429 430 FT_Error error; 431 FT_ULong table_len; 432 433 434 FT_TRACE2(( "Prep program " )); 435 436 error = face->goto_table( face, TTAG_prep, stream, &table_len ); 437 if ( error ) 438 { 439 face->cvt_program = NULL; 440 face->cvt_program_size = 0; 441 error = FT_Err_Ok; 442 443 FT_TRACE2(( "is missing\n" )); 444 } 445 else 446 { 447 face->cvt_program_size = table_len; 448 if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) ) 449 goto Exit; 450 451 FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); 452 } 453 454 Exit: 455 return error; 456 457 #else /* !TT_USE_BYTECODE_INTERPRETER */ 458 459 FT_UNUSED( face ); 460 FT_UNUSED( stream ); 461 462 return FT_Err_Ok; 463 464 #endif 465 } 466 467 468 /*************************************************************************/ 469 /* */ 470 /* <Function> */ 471 /* tt_face_load_hdmx */ 472 /* */ 473 /* <Description> */ 474 /* Load the `hdmx' table into the face object. */ 475 /* */ 476 /* <Input> */ 477 /* face :: A handle to the target face object. */ 478 /* */ 479 /* stream :: A handle to the input stream. */ 480 /* */ 481 /* <Return> */ 482 /* FreeType error code. 0 means success. */ 483 /* */ 484 485 FT_LOCAL_DEF( FT_Error ) 486 tt_face_load_hdmx( TT_Face face, 487 FT_Stream stream ) 488 { 489 FT_Error error; 490 FT_Memory memory = stream->memory; 491 FT_UInt version, nn, num_records; 492 FT_ULong table_size, record_size; 493 FT_Byte* p; 494 FT_Byte* limit; 495 496 497 /* this table is optional */ 498 error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); 499 if ( error || table_size < 8 ) 500 return FT_Err_Ok; 501 502 if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) 503 goto Exit; 504 505 p = face->hdmx_table; 506 limit = p + table_size; 507 508 version = FT_NEXT_USHORT( p ); 509 num_records = FT_NEXT_USHORT( p ); 510 record_size = FT_NEXT_ULONG( p ); 511 512 /* The maximum number of bytes in an hdmx device record is the */ 513 /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */ 514 /* the reason why `record_size' is a long (which we read as */ 515 /* unsigned long for convenience). In practice, two bytes */ 516 /* sufficient to hold the size value. */ 517 /* */ 518 /* There are at least two fonts, HANNOM-A and HANNOM-B version */ 519 /* 2.0 (2005), which get this wrong: The upper two bytes of */ 520 /* the size value are set to 0xFF instead of 0x00. We catch */ 521 /* and fix this. */ 522 523 if ( record_size >= 0xFFFF0000UL ) 524 record_size &= 0xFFFFU; 525 526 /* The limit for `num_records' is a heuristic value. */ 527 528 if ( version != 0 || num_records > 255 || record_size > 0x10001L ) 529 { 530 error = FT_THROW( Invalid_File_Format ); 531 goto Fail; 532 } 533 534 if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) 535 goto Fail; 536 537 for ( nn = 0; nn < num_records; nn++ ) 538 { 539 if ( p + record_size > limit ) 540 break; 541 542 face->hdmx_record_sizes[nn] = p[0]; 543 p += record_size; 544 } 545 546 face->hdmx_record_count = nn; 547 face->hdmx_table_size = table_size; 548 face->hdmx_record_size = record_size; 549 550 Exit: 551 return error; 552 553 Fail: 554 FT_FRAME_RELEASE( face->hdmx_table ); 555 face->hdmx_table_size = 0; 556 goto Exit; 557 } 558 559 560 FT_LOCAL_DEF( void ) 561 tt_face_free_hdmx( TT_Face face ) 562 { 563 FT_Stream stream = face->root.stream; 564 FT_Memory memory = stream->memory; 565 566 567 FT_FREE( face->hdmx_record_sizes ); 568 FT_FRAME_RELEASE( face->hdmx_table ); 569 } 570 571 572 /*************************************************************************/ 573 /* */ 574 /* Return the advance width table for a given pixel size if it is found */ 575 /* in the font's `hdmx' table (if any). */ 576 /* */ 577 FT_LOCAL_DEF( FT_Byte* ) 578 tt_face_get_device_metrics( TT_Face face, 579 FT_UInt ppem, 580 FT_UInt gindex ) 581 { 582 FT_UInt nn; 583 FT_Byte* result = NULL; 584 FT_ULong record_size = face->hdmx_record_size; 585 FT_Byte* record = face->hdmx_table + 8; 586 587 588 for ( nn = 0; nn < face->hdmx_record_count; nn++ ) 589 if ( face->hdmx_record_sizes[nn] == ppem ) 590 { 591 gindex += 2; 592 if ( gindex < record_size ) 593 result = record + nn * record_size + gindex; 594 break; 595 } 596 597 return result; 598 } 599 600 601 /* END */ 602