00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_TRUETYPE_TAGS_H
00024
00025 #include "ttpload.h"
00026
00027 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00028 #include "ttgxvar.h"
00029 #endif
00030
00031 #include "tterrors.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040 #undef FT_COMPONENT
00041 #define FT_COMPONENT trace_ttpload
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 FT_LOCAL_DEF( FT_Error )
00062 tt_face_load_loca( TT_Face face,
00063 FT_Stream stream )
00064 {
00065 FT_Error error;
00066 FT_ULong table_len;
00067 FT_Int shift;
00068
00069
00070
00071 error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
00072
00073
00074
00075 if ( error == TT_Err_Table_Missing )
00076 face->glyf_len = 0;
00077 else if ( error )
00078 goto Exit;
00079
00080 FT_TRACE2(( "Locations " ));
00081 error = face->goto_table( face, TTAG_loca, stream, &table_len );
00082 if ( error )
00083 {
00084 error = TT_Err_Locations_Missing;
00085 goto Exit;
00086 }
00087
00088 if ( face->header.Index_To_Loc_Format != 0 )
00089 {
00090 shift = 2;
00091
00092 if ( table_len >= 0x40000L )
00093 {
00094 FT_TRACE2(( "table too large\n" ));
00095 error = TT_Err_Invalid_Table;
00096 goto Exit;
00097 }
00098 face->num_locations = table_len >> shift;
00099 }
00100 else
00101 {
00102 shift = 1;
00103
00104 if ( table_len >= 0x20000L )
00105 {
00106 FT_TRACE2(( "table too large\n" ));
00107 error = TT_Err_Invalid_Table;
00108 goto Exit;
00109 }
00110 face->num_locations = table_len >> shift;
00111 }
00112
00113 if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
00114 {
00115 FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
00116 face->num_locations, face->root.num_glyphs ));
00117
00118
00119 if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
00120 {
00121 FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
00122
00123 TT_Table entry = face->dir_tables;
00124 TT_Table limit = entry + face->num_tables;
00125
00126 FT_Long pos = FT_Stream_Pos( stream );
00127 FT_Long dist = 0x7FFFFFFFL;
00128
00129
00130
00131 for ( ; entry < limit; entry++ )
00132 {
00133 FT_Long diff = entry->Offset - pos;
00134
00135
00136 if ( diff > 0 && diff < dist )
00137 dist = diff;
00138 }
00139
00140 if ( new_loca_len <= dist )
00141 {
00142 face->num_locations = face->root.num_glyphs;
00143 table_len = new_loca_len;
00144
00145 FT_TRACE2(( "adjusting num_locations to %d\n",
00146 face->num_locations ));
00147 }
00148 }
00149 }
00150
00151
00152
00153
00154
00155 if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
00156 goto Exit;
00157
00158 FT_TRACE2(( "loaded\n" ));
00159
00160 Exit:
00161 return error;
00162 }
00163
00164
00165 FT_LOCAL_DEF( FT_ULong )
00166 tt_face_get_location( TT_Face face,
00167 FT_UInt gindex,
00168 FT_UInt *asize )
00169 {
00170 FT_ULong pos1, pos2;
00171 FT_Byte* p;
00172 FT_Byte* p_limit;
00173
00174
00175 pos1 = pos2 = 0;
00176
00177 if ( gindex < face->num_locations )
00178 {
00179 if ( face->header.Index_To_Loc_Format != 0 )
00180 {
00181 p = face->glyph_locations + gindex * 4;
00182 p_limit = face->glyph_locations + face->num_locations * 4;
00183
00184 pos1 = FT_NEXT_ULONG( p );
00185 pos2 = pos1;
00186
00187 if ( p + 4 <= p_limit )
00188 pos2 = FT_NEXT_ULONG( p );
00189 }
00190 else
00191 {
00192 p = face->glyph_locations + gindex * 2;
00193 p_limit = face->glyph_locations + face->num_locations * 2;
00194
00195 pos1 = FT_NEXT_USHORT( p );
00196 pos2 = pos1;
00197
00198 if ( p + 2 <= p_limit )
00199 pos2 = FT_NEXT_USHORT( p );
00200
00201 pos1 <<= 1;
00202 pos2 <<= 1;
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 if ( pos2 >= pos1 )
00215 *asize = (FT_UInt)( pos2 - pos1 );
00216 else
00217 *asize = (FT_UInt)( face->glyf_len - pos1 );
00218
00219 return pos1;
00220 }
00221
00222
00223 FT_LOCAL_DEF( void )
00224 tt_face_done_loca( TT_Face face )
00225 {
00226 FT_Stream stream = face->root.stream;
00227
00228
00229 FT_FRAME_RELEASE( face->glyph_locations );
00230 face->num_locations = 0;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 FT_LOCAL_DEF( FT_Error )
00253 tt_face_load_cvt( TT_Face face,
00254 FT_Stream stream )
00255 {
00256 #ifdef TT_USE_BYTECODE_INTERPRETER
00257
00258 FT_Error error;
00259 FT_Memory memory = stream->memory;
00260 FT_ULong table_len;
00261
00262
00263 FT_TRACE2(( "CVT " ));
00264
00265 error = face->goto_table( face, TTAG_cvt, stream, &table_len );
00266 if ( error )
00267 {
00268 FT_TRACE2(( "is missing\n" ));
00269
00270 face->cvt_size = 0;
00271 face->cvt = NULL;
00272 error = TT_Err_Ok;
00273
00274 goto Exit;
00275 }
00276
00277 face->cvt_size = table_len / 2;
00278
00279 if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
00280 goto Exit;
00281
00282 if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
00283 goto Exit;
00284
00285 {
00286 FT_Short* cur = face->cvt;
00287 FT_Short* limit = cur + face->cvt_size;
00288
00289
00290 for ( ; cur < limit; cur++ )
00291 *cur = FT_GET_SHORT();
00292 }
00293
00294 FT_FRAME_EXIT();
00295 FT_TRACE2(( "loaded\n" ));
00296
00297 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
00298 if ( face->doblend )
00299 error = tt_face_vary_cvt( face, stream );
00300 #endif
00301
00302 Exit:
00303 return error;
00304
00305 #else
00306
00307 FT_UNUSED( face );
00308 FT_UNUSED( stream );
00309
00310 return TT_Err_Ok;
00311
00312 #endif
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 FT_LOCAL_DEF( FT_Error )
00334 tt_face_load_fpgm( TT_Face face,
00335 FT_Stream stream )
00336 {
00337 #ifdef TT_USE_BYTECODE_INTERPRETER
00338
00339 FT_Error error;
00340 FT_ULong table_len;
00341
00342
00343 FT_TRACE2(( "Font program " ));
00344
00345
00346 error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
00347 if ( error )
00348 {
00349 face->font_program = NULL;
00350 face->font_program_size = 0;
00351 error = TT_Err_Ok;
00352
00353 FT_TRACE2(( "is missing\n" ));
00354 }
00355 else
00356 {
00357 face->font_program_size = table_len;
00358 if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
00359 goto Exit;
00360
00361 FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
00362 }
00363
00364 Exit:
00365 return error;
00366
00367 #else
00368
00369 FT_UNUSED( face );
00370 FT_UNUSED( stream );
00371
00372 return TT_Err_Ok;
00373
00374 #endif
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 FT_LOCAL_DEF( FT_Error )
00396 tt_face_load_prep( TT_Face face,
00397 FT_Stream stream )
00398 {
00399 #ifdef TT_USE_BYTECODE_INTERPRETER
00400
00401 FT_Error error;
00402 FT_ULong table_len;
00403
00404
00405 FT_TRACE2(( "Prep program " ));
00406
00407 error = face->goto_table( face, TTAG_prep, stream, &table_len );
00408 if ( error )
00409 {
00410 face->cvt_program = NULL;
00411 face->cvt_program_size = 0;
00412 error = TT_Err_Ok;
00413
00414 FT_TRACE2(( "is missing\n" ));
00415 }
00416 else
00417 {
00418 face->cvt_program_size = table_len;
00419 if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
00420 goto Exit;
00421
00422 FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
00423 }
00424
00425 Exit:
00426 return error;
00427
00428 #else
00429
00430 FT_UNUSED( face );
00431 FT_UNUSED( stream );
00432
00433 return TT_Err_Ok;
00434
00435 #endif
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 FT_LOCAL_DEF( FT_Error )
00457 tt_face_load_hdmx( TT_Face face,
00458 FT_Stream stream )
00459 {
00460 FT_Error error;
00461 FT_Memory memory = stream->memory;
00462 FT_UInt version, nn, num_records;
00463 FT_ULong table_size, record_size;
00464 FT_Byte* p;
00465 FT_Byte* limit;
00466
00467
00468
00469 error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
00470 if ( error || table_size < 8 )
00471 return TT_Err_Ok;
00472
00473 if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
00474 goto Exit;
00475
00476 p = face->hdmx_table;
00477 limit = p + table_size;
00478
00479 version = FT_NEXT_USHORT( p );
00480 num_records = FT_NEXT_USHORT( p );
00481 record_size = FT_NEXT_ULONG( p );
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 if ( record_size >= 0xFFFF0000UL )
00495 record_size &= 0xFFFFU;
00496
00497
00498
00499 if ( version != 0 || num_records > 255 || record_size > 0x10001L )
00500 {
00501 error = TT_Err_Invalid_File_Format;
00502 goto Fail;
00503 }
00504
00505 if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
00506 goto Fail;
00507
00508 for ( nn = 0; nn < num_records; nn++ )
00509 {
00510 if ( p + record_size > limit )
00511 break;
00512
00513 face->hdmx_record_sizes[nn] = p[0];
00514 p += record_size;
00515 }
00516
00517 face->hdmx_record_count = nn;
00518 face->hdmx_table_size = table_size;
00519 face->hdmx_record_size = record_size;
00520
00521 Exit:
00522 return error;
00523
00524 Fail:
00525 FT_FRAME_RELEASE( face->hdmx_table );
00526 face->hdmx_table_size = 0;
00527 goto Exit;
00528 }
00529
00530
00531 FT_LOCAL_DEF( void )
00532 tt_face_free_hdmx( TT_Face face )
00533 {
00534 FT_Stream stream = face->root.stream;
00535 FT_Memory memory = stream->memory;
00536
00537
00538 FT_FREE( face->hdmx_record_sizes );
00539 FT_FRAME_RELEASE( face->hdmx_table );
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 FT_LOCAL_DEF( FT_Byte* )
00549 tt_face_get_device_metrics( TT_Face face,
00550 FT_UInt ppem,
00551 FT_UInt gindex )
00552 {
00553 FT_UInt nn;
00554 FT_Byte* result = NULL;
00555 FT_ULong record_size = face->hdmx_record_size;
00556 FT_Byte* record = face->hdmx_table + 8;
00557
00558
00559 for ( nn = 0; nn < face->hdmx_record_count; nn++ )
00560 if ( face->hdmx_record_sizes[nn] == ppem )
00561 {
00562 gindex += 2;
00563 if ( gindex < record_size )
00564 result = record + nn * record_size + gindex;
00565 break;
00566 }
00567
00568 return result;
00569 }
00570
00571
00572