1 /***************************************************************************/ 2 /* */ 3 /* ttpload.c */ 4 /* */ 5 /* TrueType-specific tables loader (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_OBJECTS_H 22 #include FT_INTERNAL_STREAM_H 23 #include FT_TRUETYPE_TAGS_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 ) tt_face_load_loca(TT_Face face,FT_Stream stream)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 ( error == TT_Err_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 = TT_Err_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 = TT_Err_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 = TT_Err_Invalid_Table; 108 goto Exit; 109 } 110 face->num_locations = table_len >> shift; 111 } 112 113 if ( face->num_locations != (FT_ULong)face->root.num_glyphs ) 114 { 115 FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n", 116 face->num_locations, face->root.num_glyphs )); 117 118 /* we only handle the case where `maxp' gives a larger value */ 119 if ( face->num_locations < (FT_ULong)face->root.num_glyphs ) 120 { 121 FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift; 122 123 TT_Table entry = face->dir_tables; 124 TT_Table limit = entry + face->num_tables; 125 126 FT_Long pos = FT_Stream_Pos( stream ); 127 FT_Long dist = 0x7FFFFFFFL; 128 129 130 /* compute the distance to next table in font file */ 131 for ( ; entry < limit; entry++ ) 132 { 133 FT_Long diff = entry->Offset - pos; 134 135 136 if ( diff > 0 && diff < dist ) 137 dist = diff; 138 } 139 140 if ( new_loca_len <= dist ) 141 { 142 face->num_locations = face->root.num_glyphs; 143 table_len = new_loca_len; 144 145 FT_TRACE2(( "adjusting num_locations to %d\n", 146 face->num_locations )); 147 } 148 } 149 } 150 151 /* 152 * Extract the frame. We don't need to decompress it since 153 * we are able to parse it directly. 154 */ 155 if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) ) 156 goto Exit; 157 158 FT_TRACE2(( "loaded\n" )); 159 160 Exit: 161 return error; 162 } 163 164 165 FT_LOCAL_DEF( FT_ULong ) tt_face_get_location(TT_Face face,FT_UInt gindex,FT_UInt * asize)166 tt_face_get_location( TT_Face face, 167 FT_UInt gindex, 168 FT_UInt *asize ) 169 { 170 FT_ULong pos1, pos2; 171 FT_Byte* p; 172 FT_Byte* p_limit; 173 174 175 pos1 = pos2 = 0; 176 177 if ( gindex < face->num_locations ) 178 { 179 if ( face->header.Index_To_Loc_Format != 0 ) 180 { 181 p = face->glyph_locations + gindex * 4; 182 p_limit = face->glyph_locations + face->num_locations * 4; 183 184 pos1 = FT_NEXT_ULONG( p ); 185 pos2 = pos1; 186 187 if ( p + 4 <= p_limit ) 188 pos2 = FT_NEXT_ULONG( p ); 189 } 190 else 191 { 192 p = face->glyph_locations + gindex * 2; 193 p_limit = face->glyph_locations + face->num_locations * 2; 194 195 pos1 = FT_NEXT_USHORT( p ); 196 pos2 = pos1; 197 198 if ( p + 2 <= p_limit ) 199 pos2 = FT_NEXT_USHORT( p ); 200 201 pos1 <<= 1; 202 pos2 <<= 1; 203 } 204 } 205 206 /* The `loca' table must be ordered; it refers to the length of */ 207 /* an entry as the difference between the current and the next */ 208 /* position. However, there do exist (malformed) fonts which */ 209 /* don't obey this rule, so we are only able to provide an */ 210 /* upper bound for the size. */ 211 /* */ 212 /* We get (intentionally) a wrong, non-zero result in case the */ 213 /* `glyf' table is missing. */ 214 if ( pos2 >= pos1 ) 215 *asize = (FT_UInt)( pos2 - pos1 ); 216 else 217 *asize = (FT_UInt)( face->glyf_len - pos1 ); 218 219 return pos1; 220 } 221 222 223 FT_LOCAL_DEF( void ) tt_face_done_loca(TT_Face face)224 tt_face_done_loca( TT_Face face ) 225 { 226 FT_Stream stream = face->root.stream; 227 228 229 FT_FRAME_RELEASE( face->glyph_locations ); 230 face->num_locations = 0; 231 } 232 233 234 235 /*************************************************************************/ 236 /* */ 237 /* <Function> */ 238 /* tt_face_load_cvt */ 239 /* */ 240 /* <Description> */ 241 /* Load the control value table into a face object. */ 242 /* */ 243 /* <InOut> */ 244 /* face :: A handle to the target face object. */ 245 /* */ 246 /* <Input> */ 247 /* stream :: A handle to the input stream. */ 248 /* */ 249 /* <Return> */ 250 /* FreeType error code. 0 means success. */ 251 /* */ 252 FT_LOCAL_DEF( FT_Error ) tt_face_load_cvt(TT_Face face,FT_Stream stream)253 tt_face_load_cvt( TT_Face face, 254 FT_Stream stream ) 255 { 256 #ifdef TT_USE_BYTECODE_INTERPRETER 257 258 FT_Error error; 259 FT_Memory memory = stream->memory; 260 FT_ULong table_len; 261 262 263 FT_TRACE2(( "CVT " )); 264 265 error = face->goto_table( face, TTAG_cvt, stream, &table_len ); 266 if ( error ) 267 { 268 FT_TRACE2(( "is missing\n" )); 269 270 face->cvt_size = 0; 271 face->cvt = NULL; 272 error = TT_Err_Ok; 273 274 goto Exit; 275 } 276 277 face->cvt_size = table_len / 2; 278 279 if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) ) 280 goto Exit; 281 282 if ( FT_FRAME_ENTER( face->cvt_size * 2L ) ) 283 goto Exit; 284 285 { 286 FT_Short* cur = face->cvt; 287 FT_Short* limit = cur + face->cvt_size; 288 289 290 for ( ; cur < limit; cur++ ) 291 *cur = FT_GET_SHORT(); 292 } 293 294 FT_FRAME_EXIT(); 295 FT_TRACE2(( "loaded\n" )); 296 297 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 298 if ( face->doblend ) 299 error = tt_face_vary_cvt( face, stream ); 300 #endif 301 302 Exit: 303 return error; 304 305 #else /* !TT_USE_BYTECODE_INTERPRETER */ 306 307 FT_UNUSED( face ); 308 FT_UNUSED( stream ); 309 310 return TT_Err_Ok; 311 312 #endif 313 } 314 315 316 /*************************************************************************/ 317 /* */ 318 /* <Function> */ 319 /* tt_face_load_fpgm */ 320 /* */ 321 /* <Description> */ 322 /* Load the font program. */ 323 /* */ 324 /* <InOut> */ 325 /* face :: A handle to the target face object. */ 326 /* */ 327 /* <Input> */ 328 /* stream :: A handle to the input stream. */ 329 /* */ 330 /* <Return> */ 331 /* FreeType error code. 0 means success. */ 332 /* */ 333 FT_LOCAL_DEF( FT_Error ) tt_face_load_fpgm(TT_Face face,FT_Stream stream)334 tt_face_load_fpgm( TT_Face face, 335 FT_Stream stream ) 336 { 337 #ifdef TT_USE_BYTECODE_INTERPRETER 338 339 FT_Error error; 340 FT_ULong table_len; 341 342 343 FT_TRACE2(( "Font program " )); 344 345 /* The font program is optional */ 346 error = face->goto_table( face, TTAG_fpgm, stream, &table_len ); 347 if ( error ) 348 { 349 face->font_program = NULL; 350 face->font_program_size = 0; 351 error = TT_Err_Ok; 352 353 FT_TRACE2(( "is missing\n" )); 354 } 355 else 356 { 357 face->font_program_size = table_len; 358 if ( FT_FRAME_EXTRACT( table_len, face->font_program ) ) 359 goto Exit; 360 361 FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); 362 } 363 364 Exit: 365 return error; 366 367 #else /* !TT_USE_BYTECODE_INTERPRETER */ 368 369 FT_UNUSED( face ); 370 FT_UNUSED( stream ); 371 372 return TT_Err_Ok; 373 374 #endif 375 } 376 377 378 /*************************************************************************/ 379 /* */ 380 /* <Function> */ 381 /* tt_face_load_prep */ 382 /* */ 383 /* <Description> */ 384 /* Load the cvt program. */ 385 /* */ 386 /* <InOut> */ 387 /* face :: A handle to the target face object. */ 388 /* */ 389 /* <Input> */ 390 /* stream :: A handle to the input stream. */ 391 /* */ 392 /* <Return> */ 393 /* FreeType error code. 0 means success. */ 394 /* */ 395 FT_LOCAL_DEF( FT_Error ) tt_face_load_prep(TT_Face face,FT_Stream stream)396 tt_face_load_prep( TT_Face face, 397 FT_Stream stream ) 398 { 399 #ifdef TT_USE_BYTECODE_INTERPRETER 400 401 FT_Error error; 402 FT_ULong table_len; 403 404 405 FT_TRACE2(( "Prep program " )); 406 407 error = face->goto_table( face, TTAG_prep, stream, &table_len ); 408 if ( error ) 409 { 410 face->cvt_program = NULL; 411 face->cvt_program_size = 0; 412 error = TT_Err_Ok; 413 414 FT_TRACE2(( "is missing\n" )); 415 } 416 else 417 { 418 face->cvt_program_size = table_len; 419 if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) ) 420 goto Exit; 421 422 FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); 423 } 424 425 Exit: 426 return error; 427 428 #else /* !TT_USE_BYTECODE_INTERPRETER */ 429 430 FT_UNUSED( face ); 431 FT_UNUSED( stream ); 432 433 return TT_Err_Ok; 434 435 #endif 436 } 437 438 439 /*************************************************************************/ 440 /* */ 441 /* <Function> */ 442 /* tt_face_load_hdmx */ 443 /* */ 444 /* <Description> */ 445 /* Load the `hdmx' table into the face object. */ 446 /* */ 447 /* <Input> */ 448 /* face :: A handle to the target face object. */ 449 /* */ 450 /* stream :: A handle to the input stream. */ 451 /* */ 452 /* <Return> */ 453 /* FreeType error code. 0 means success. */ 454 /* */ 455 456 FT_LOCAL_DEF( FT_Error ) tt_face_load_hdmx(TT_Face face,FT_Stream stream)457 tt_face_load_hdmx( TT_Face face, 458 FT_Stream stream ) 459 { 460 FT_Error error; 461 FT_Memory memory = stream->memory; 462 FT_UInt version, nn, num_records; 463 FT_ULong table_size, record_size; 464 FT_Byte* p; 465 FT_Byte* limit; 466 467 468 /* this table is optional */ 469 error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); 470 if ( error || table_size < 8 ) 471 return TT_Err_Ok; 472 473 if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) 474 goto Exit; 475 476 p = face->hdmx_table; 477 limit = p + table_size; 478 479 version = FT_NEXT_USHORT( p ); 480 num_records = FT_NEXT_USHORT( p ); 481 record_size = FT_NEXT_ULONG( p ); 482 483 /* The maximum number of bytes in an hdmx device record is the */ 484 /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */ 485 /* the reason why `record_size' is a long (which we read as */ 486 /* unsigned long for convenience). In practice, two bytes */ 487 /* sufficient to hold the size value. */ 488 /* */ 489 /* There are at least two fonts, HANNOM-A and HANNOM-B version */ 490 /* 2.0 (2005), which get this wrong: The upper two bytes of */ 491 /* the size value are set to 0xFF instead of 0x00. We catch */ 492 /* and fix this. */ 493 494 if ( record_size >= 0xFFFF0000UL ) 495 record_size &= 0xFFFFU; 496 497 /* The limit for `num_records' is a heuristic value. */ 498 499 if ( version != 0 || num_records > 255 || record_size > 0x10001L ) 500 { 501 error = TT_Err_Invalid_File_Format; 502 goto Fail; 503 } 504 505 if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) 506 goto Fail; 507 508 for ( nn = 0; nn < num_records; nn++ ) 509 { 510 if ( p + record_size > limit ) 511 break; 512 513 face->hdmx_record_sizes[nn] = p[0]; 514 p += record_size; 515 } 516 517 face->hdmx_record_count = nn; 518 face->hdmx_table_size = table_size; 519 face->hdmx_record_size = record_size; 520 521 Exit: 522 return error; 523 524 Fail: 525 FT_FRAME_RELEASE( face->hdmx_table ); 526 face->hdmx_table_size = 0; 527 goto Exit; 528 } 529 530 531 FT_LOCAL_DEF( void ) tt_face_free_hdmx(TT_Face face)532 tt_face_free_hdmx( TT_Face face ) 533 { 534 FT_Stream stream = face->root.stream; 535 FT_Memory memory = stream->memory; 536 537 538 FT_FREE( face->hdmx_record_sizes ); 539 FT_FRAME_RELEASE( face->hdmx_table ); 540 } 541 542 543 /*************************************************************************/ 544 /* */ 545 /* Return the advance width table for a given pixel size if it is found */ 546 /* in the font's `hdmx' table (if any). */ 547 /* */ 548 FT_LOCAL_DEF( FT_Byte* ) tt_face_get_device_metrics(TT_Face face,FT_UInt ppem,FT_UInt gindex)549 tt_face_get_device_metrics( TT_Face face, 550 FT_UInt ppem, 551 FT_UInt gindex ) 552 { 553 FT_UInt nn; 554 FT_Byte* result = NULL; 555 FT_ULong record_size = face->hdmx_record_size; 556 FT_Byte* record = face->hdmx_table + 8; 557 558 559 for ( nn = 0; nn < face->hdmx_record_count; nn++ ) 560 if ( face->hdmx_record_sizes[nn] == ppem ) 561 { 562 gindex += 2; 563 if ( gindex < record_size ) 564 result = record + nn * record_size + gindex; 565 break; 566 } 567 568 return result; 569 } 570 571 572 /* END */ 573