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_STREAM_H
00022 #include FT_TRUETYPE_TAGS_H
00023 #include "ttmtx.h"
00024
00025 #include "sferrors.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034 #undef FT_COMPONENT
00035 #define FT_COMPONENT trace_ttmtx
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
00064
00065 FT_LOCAL_DEF( FT_Error )
00066 tt_face_load_hmtx( TT_Face face,
00067 FT_Stream stream,
00068 FT_Bool vertical )
00069 {
00070 FT_Error error;
00071 FT_ULong tag, table_size;
00072 FT_ULong* ptable_offset;
00073 FT_ULong* ptable_size;
00074
00075
00076 if ( vertical )
00077 {
00078 tag = TTAG_vmtx;
00079 ptable_offset = &face->vert_metrics_offset;
00080 ptable_size = &face->vert_metrics_size;
00081 }
00082 else
00083 {
00084 tag = TTAG_hmtx;
00085 ptable_offset = &face->horz_metrics_offset;
00086 ptable_size = &face->horz_metrics_size;
00087 }
00088
00089 error = face->goto_table( face, tag, stream, &table_size );
00090 if ( error )
00091 goto Fail;
00092
00093 *ptable_size = table_size;
00094 *ptable_offset = FT_STREAM_POS();
00095
00096 Fail:
00097 return error;
00098 }
00099
00100 #else
00101
00102 FT_LOCAL_DEF( FT_Error )
00103 tt_face_load_hmtx( TT_Face face,
00104 FT_Stream stream,
00105 FT_Bool vertical )
00106 {
00107 FT_Error error;
00108 FT_Memory memory = stream->memory;
00109
00110 FT_ULong table_len;
00111 FT_Long num_shorts, num_longs, num_shorts_checked;
00112
00113 TT_LongMetrics* longs;
00114 TT_ShortMetrics** shorts;
00115 FT_Byte* p;
00116
00117
00118 if ( vertical )
00119 {
00120 void* lm = &face->vertical.long_metrics;
00121 void** sm = &face->vertical.short_metrics;
00122
00123
00124 error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
00125 if ( error )
00126 goto Fail;
00127
00128 num_longs = face->vertical.number_Of_VMetrics;
00129 if ( (FT_ULong)num_longs > table_len / 4 )
00130 num_longs = (FT_Long)( table_len / 4 );
00131
00132 face->vertical.number_Of_VMetrics = 0;
00133
00134 longs = (TT_LongMetrics*)lm;
00135 shorts = (TT_ShortMetrics**)sm;
00136 }
00137 else
00138 {
00139 void* lm = &face->horizontal.long_metrics;
00140 void** sm = &face->horizontal.short_metrics;
00141
00142
00143 error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
00144 if ( error )
00145 goto Fail;
00146
00147 num_longs = face->horizontal.number_Of_HMetrics;
00148 if ( (FT_ULong)num_longs > table_len / 4 )
00149 num_longs = (FT_Long)( table_len / 4 );
00150
00151 face->horizontal.number_Of_HMetrics = 0;
00152
00153 longs = (TT_LongMetrics*)lm;
00154 shorts = (TT_ShortMetrics**)sm;
00155 }
00156
00157
00158
00159 num_shorts = face->max_profile.numGlyphs - num_longs;
00160 num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
00161
00162 if ( num_shorts < 0 )
00163 {
00164 FT_TRACE0(( "tt_face_load_hmtx:"
00165 " %cmtx has more metrics than glyphs.\n",
00166 vertical ? "v" : "h" ));
00167
00168
00169 #if 0
00170 error = vertical ? SFNT_Err_Invalid_Vert_Metrics
00171 : SFNT_Err_Invalid_Horiz_Metrics;
00172 goto Exit;
00173 #else
00174 num_shorts = 0;
00175 #endif
00176 }
00177
00178 if ( FT_QNEW_ARRAY( *longs, num_longs ) ||
00179 FT_QNEW_ARRAY( *shorts, num_shorts ) )
00180 goto Fail;
00181
00182 if ( FT_FRAME_ENTER( table_len ) )
00183 goto Fail;
00184
00185 p = stream->cursor;
00186
00187 {
00188 TT_LongMetrics cur = *longs;
00189 TT_LongMetrics limit = cur + num_longs;
00190
00191
00192 for ( ; cur < limit; cur++ )
00193 {
00194 cur->advance = FT_NEXT_USHORT( p );
00195 cur->bearing = FT_NEXT_SHORT( p );
00196 }
00197 }
00198
00199
00200 {
00201 TT_ShortMetrics* cur = *shorts;
00202 TT_ShortMetrics* limit = cur +
00203 FT_MIN( num_shorts, num_shorts_checked );
00204
00205
00206 for ( ; cur < limit; cur++ )
00207 *cur = FT_NEXT_SHORT( p );
00208
00209
00210
00211
00212 if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
00213 {
00214 FT_Short val = (*shorts)[num_shorts_checked - 1];
00215
00216
00217 limit = *shorts + num_shorts;
00218 for ( ; cur < limit; cur++ )
00219 *cur = val;
00220 }
00221 }
00222
00223 FT_FRAME_EXIT();
00224
00225 if ( vertical )
00226 face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
00227 else
00228 face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
00229
00230 Fail:
00231 return error;
00232 }
00233
00234 #endif
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 FT_LOCAL_DEF( FT_Error )
00256 tt_face_load_hhea( TT_Face face,
00257 FT_Stream stream,
00258 FT_Bool vertical )
00259 {
00260 FT_Error error;
00261 TT_HoriHeader* header;
00262
00263 const FT_Frame_Field metrics_header_fields[] =
00264 {
00265 #undef FT_STRUCTURE
00266 #define FT_STRUCTURE TT_HoriHeader
00267
00268 FT_FRAME_START( 36 ),
00269 FT_FRAME_ULONG ( Version ),
00270 FT_FRAME_SHORT ( Ascender ),
00271 FT_FRAME_SHORT ( Descender ),
00272 FT_FRAME_SHORT ( Line_Gap ),
00273 FT_FRAME_USHORT( advance_Width_Max ),
00274 FT_FRAME_SHORT ( min_Left_Side_Bearing ),
00275 FT_FRAME_SHORT ( min_Right_Side_Bearing ),
00276 FT_FRAME_SHORT ( xMax_Extent ),
00277 FT_FRAME_SHORT ( caret_Slope_Rise ),
00278 FT_FRAME_SHORT ( caret_Slope_Run ),
00279 FT_FRAME_SHORT ( caret_Offset ),
00280 FT_FRAME_SHORT ( Reserved[0] ),
00281 FT_FRAME_SHORT ( Reserved[1] ),
00282 FT_FRAME_SHORT ( Reserved[2] ),
00283 FT_FRAME_SHORT ( Reserved[3] ),
00284 FT_FRAME_SHORT ( metric_Data_Format ),
00285 FT_FRAME_USHORT( number_Of_HMetrics ),
00286 FT_FRAME_END
00287 };
00288
00289
00290 if ( vertical )
00291 {
00292 void *v = &face->vertical;
00293
00294
00295 error = face->goto_table( face, TTAG_vhea, stream, 0 );
00296 if ( error )
00297 goto Fail;
00298
00299 header = (TT_HoriHeader*)v;
00300 }
00301 else
00302 {
00303 error = face->goto_table( face, TTAG_hhea, stream, 0 );
00304 if ( error )
00305 goto Fail;
00306
00307 header = &face->horizontal;
00308 }
00309
00310 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
00311 goto Fail;
00312
00313 FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
00314 FT_TRACE3(( "Descender: %5d\n", header->Descender ));
00315 FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
00316
00317 header->long_metrics = NULL;
00318 header->short_metrics = NULL;
00319
00320 Fail:
00321 return error;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
00347
00348 FT_LOCAL_DEF( FT_Error )
00349 tt_face_get_metrics( TT_Face face,
00350 FT_Bool vertical,
00351 FT_UInt gindex,
00352 FT_Short *abearing,
00353 FT_UShort *aadvance )
00354 {
00355 FT_Error error;
00356 FT_Stream stream = face->root.stream;
00357 TT_HoriHeader* header;
00358 FT_ULong table_pos, table_size, table_end;
00359 FT_UShort k;
00360
00361
00362 if ( vertical )
00363 {
00364 void* v = &face->vertical;
00365
00366
00367 header = (TT_HoriHeader*)v;
00368 table_pos = face->vert_metrics_offset;
00369 table_size = face->vert_metrics_size;
00370 }
00371 else
00372 {
00373 header = &face->horizontal;
00374 table_pos = face->horz_metrics_offset;
00375 table_size = face->horz_metrics_size;
00376 }
00377
00378 table_end = table_pos + table_size;
00379
00380 k = header->number_Of_HMetrics;
00381
00382 if ( k > 0 )
00383 {
00384 if ( gindex < (FT_UInt)k )
00385 {
00386 table_pos += 4 * gindex;
00387 if ( table_pos + 4 > table_end )
00388 goto NoData;
00389
00390 if ( FT_STREAM_SEEK( table_pos ) ||
00391 FT_READ_USHORT( *aadvance ) ||
00392 FT_READ_SHORT( *abearing ) )
00393 goto NoData;
00394 }
00395 else
00396 {
00397 table_pos += 4 * ( k - 1 );
00398 if ( table_pos + 4 > table_end )
00399 goto NoData;
00400
00401 if ( FT_STREAM_SEEK( table_pos ) ||
00402 FT_READ_USHORT( *aadvance ) )
00403 goto NoData;
00404
00405 table_pos += 4 + 2 * ( gindex - k );
00406 if ( table_pos + 2 > table_end )
00407 *abearing = 0;
00408 else
00409 {
00410 if ( !FT_STREAM_SEEK( table_pos ) )
00411 (void)FT_READ_SHORT( *abearing );
00412 }
00413 }
00414 }
00415 else
00416 {
00417 NoData:
00418 *abearing = 0;
00419 *aadvance = 0;
00420 }
00421
00422 return SFNT_Err_Ok;
00423 }
00424
00425 #else
00426
00427 FT_LOCAL_DEF( FT_Error )
00428 tt_face_get_metrics( TT_Face face,
00429 FT_Bool vertical,
00430 FT_UInt gindex,
00431 FT_Short* abearing,
00432 FT_UShort* aadvance )
00433 {
00434 void* v = &face->vertical;
00435 void* h = &face->horizontal;
00436 TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v
00437 : (TT_HoriHeader*)h;
00438 TT_LongMetrics longs_m;
00439 FT_UShort k = header->number_Of_HMetrics;
00440
00441
00442 if ( k == 0 ||
00443 !header->long_metrics ||
00444 gindex >= (FT_UInt)face->max_profile.numGlyphs )
00445 {
00446 *abearing = *aadvance = 0;
00447 return SFNT_Err_Ok;
00448 }
00449
00450 if ( gindex < (FT_UInt)k )
00451 {
00452 longs_m = (TT_LongMetrics)header->long_metrics + gindex;
00453 *abearing = longs_m->bearing;
00454 *aadvance = longs_m->advance;
00455 }
00456 else
00457 {
00458 *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
00459 *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
00460 }
00461
00462 return SFNT_Err_Ok;
00463 }
00464
00465 #endif
00466
00467
00468