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