Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttmtx.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ttmtx.c */ 00004 /* */ 00005 /* Load the metrics tables common to TTF and OTF fonts (body). */ 00006 /* */ 00007 /* Copyright 2006, 2007, 2008, 2009 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 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 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00031 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00032 /* messages during execution. */ 00033 /* */ 00034 #undef FT_COMPONENT 00035 #define FT_COMPONENT trace_ttmtx 00036 00037 00038 /* 00039 * Unfortunately, we can't enable our memory optimizations if 00040 * FT_CONFIG_OPTION_OLD_INTERNALS is defined. This is because at least 00041 * one rogue client (libXfont in the X.Org XServer) is directly accessing 00042 * the metrics. 00043 */ 00044 00045 /*************************************************************************/ 00046 /* */ 00047 /* <Function> */ 00048 /* tt_face_load_hmtx */ 00049 /* */ 00050 /* <Description> */ 00051 /* Load the `hmtx' or `vmtx' table into a face object. */ 00052 /* */ 00053 /* <Input> */ 00054 /* face :: A handle to the target face object. */ 00055 /* */ 00056 /* stream :: The input stream. */ 00057 /* */ 00058 /* vertical :: A boolean flag. If set, load `vmtx'. */ 00059 /* */ 00060 /* <Return> */ 00061 /* FreeType error code. 0 means success. */ 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 /* !FT_CONFIG_OPTION_OLD_INTERNALS */ 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 /* never trust derived values */ 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 /* Adobe simply ignores this problem. So we shall do the same. */ 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 /* do we have an inconsistent number of metric values? */ 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 /* We fill up the missing left side bearings with the */ 00210 /* last valid value. Since this will occur for buggy CJK */ 00211 /* fonts usually only, nothing serious will happen. */ 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 /* !FT_CONFIG_OPTION_OLD_INTERNALS */ 00235 00236 00237 /*************************************************************************/ 00238 /* */ 00239 /* <Function> */ 00240 /* tt_face_load_hhea */ 00241 /* */ 00242 /* <Description> */ 00243 /* Load the `hhea' or 'vhea' table into a face object. */ 00244 /* */ 00245 /* <Input> */ 00246 /* face :: A handle to the target face object. */ 00247 /* */ 00248 /* stream :: The input stream. */ 00249 /* */ 00250 /* vertical :: A boolean flag. If set, load `vhea'. */ 00251 /* */ 00252 /* <Return> */ 00253 /* FreeType error code. 0 means success. */ 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 /* <Function> */ 00328 /* tt_face_get_metrics */ 00329 /* */ 00330 /* <Description> */ 00331 /* Returns the horizontal or vertical metrics in font units for a */ 00332 /* given glyph. The metrics are the left side bearing (resp. top */ 00333 /* side bearing) and advance width (resp. advance height). */ 00334 /* */ 00335 /* <Input> */ 00336 /* header :: A pointer to either the horizontal or vertical metrics */ 00337 /* structure. */ 00338 /* */ 00339 /* idx :: The glyph index. */ 00340 /* */ 00341 /* <Output> */ 00342 /* bearing :: The bearing, either left side or top side. */ 00343 /* */ 00344 /* advance :: The advance width resp. advance height. */ 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 /* !FT_CONFIG_OPTION_OLD_INTERNALS */ 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 /* !FT_CONFIG_OPTION_OLD_INTERNALS */ 00466 00467 00468 /* END */ Generated on Fri May 25 2012 04:32:32 for ReactOS by
1.7.6.1
|