1 /***************************************************************************/ 2 /* */ 3 /* ttmtx.c */ 4 /* */ 5 /* Load the metrics tables common to TTF and OTF fonts (body). */ 6 /* */ 7 /* Copyright 2006-2017 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_STREAM_H 22 #include FT_TRUETYPE_TAGS_H 23 24 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 25 #include FT_SERVICE_METRICS_VARIATIONS_H 26 #endif 27 28 #include "ttmtx.h" 29 30 #include "sferrors.h" 31 32 33 /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ 34 /* be identical except for the names of their fields, */ 35 /* which are different. */ 36 /* */ 37 /* This ensures that `tt_face_load_hmtx' is able to read */ 38 /* both the horizontal and vertical headers. */ 39 40 41 /*************************************************************************/ 42 /* */ 43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 45 /* messages during execution. */ 46 /* */ 47 #undef FT_COMPONENT 48 #define FT_COMPONENT trace_ttmtx 49 50 51 /*************************************************************************/ 52 /* */ 53 /* <Function> */ 54 /* tt_face_load_hmtx */ 55 /* */ 56 /* <Description> */ 57 /* Load the `hmtx' or `vmtx' table into a face object. */ 58 /* */ 59 /* <Input> */ 60 /* face :: A handle to the target face object. */ 61 /* */ 62 /* stream :: The input stream. */ 63 /* */ 64 /* vertical :: A boolean flag. If set, load `vmtx'. */ 65 /* */ 66 /* <Return> */ 67 /* FreeType error code. 0 means success. */ 68 /* */ 69 FT_LOCAL_DEF( FT_Error ) tt_face_load_hmtx(TT_Face face,FT_Stream stream,FT_Bool vertical)70 tt_face_load_hmtx( TT_Face face, 71 FT_Stream stream, 72 FT_Bool vertical ) 73 { 74 FT_Error error; 75 FT_ULong tag, table_size; 76 FT_ULong* ptable_offset; 77 FT_ULong* ptable_size; 78 79 80 if ( vertical ) 81 { 82 tag = TTAG_vmtx; 83 ptable_offset = &face->vert_metrics_offset; 84 ptable_size = &face->vert_metrics_size; 85 } 86 else 87 { 88 tag = TTAG_hmtx; 89 ptable_offset = &face->horz_metrics_offset; 90 ptable_size = &face->horz_metrics_size; 91 } 92 93 error = face->goto_table( face, tag, stream, &table_size ); 94 if ( error ) 95 goto Fail; 96 97 *ptable_size = table_size; 98 *ptable_offset = FT_STREAM_POS(); 99 100 Fail: 101 return error; 102 } 103 104 105 /*************************************************************************/ 106 /* */ 107 /* <Function> */ 108 /* tt_face_load_hhea */ 109 /* */ 110 /* <Description> */ 111 /* Load the `hhea' or 'vhea' table into a face object. */ 112 /* */ 113 /* <Input> */ 114 /* face :: A handle to the target face object. */ 115 /* */ 116 /* stream :: The input stream. */ 117 /* */ 118 /* vertical :: A boolean flag. If set, load `vhea'. */ 119 /* */ 120 /* <Return> */ 121 /* FreeType error code. 0 means success. */ 122 /* */ 123 FT_LOCAL_DEF( FT_Error ) tt_face_load_hhea(TT_Face face,FT_Stream stream,FT_Bool vertical)124 tt_face_load_hhea( TT_Face face, 125 FT_Stream stream, 126 FT_Bool vertical ) 127 { 128 FT_Error error; 129 TT_HoriHeader* header; 130 131 static const FT_Frame_Field metrics_header_fields[] = 132 { 133 #undef FT_STRUCTURE 134 #define FT_STRUCTURE TT_HoriHeader 135 136 FT_FRAME_START( 36 ), 137 FT_FRAME_ULONG ( Version ), 138 FT_FRAME_SHORT ( Ascender ), 139 FT_FRAME_SHORT ( Descender ), 140 FT_FRAME_SHORT ( Line_Gap ), 141 FT_FRAME_USHORT( advance_Width_Max ), 142 FT_FRAME_SHORT ( min_Left_Side_Bearing ), 143 FT_FRAME_SHORT ( min_Right_Side_Bearing ), 144 FT_FRAME_SHORT ( xMax_Extent ), 145 FT_FRAME_SHORT ( caret_Slope_Rise ), 146 FT_FRAME_SHORT ( caret_Slope_Run ), 147 FT_FRAME_SHORT ( caret_Offset ), 148 FT_FRAME_SHORT ( Reserved[0] ), 149 FT_FRAME_SHORT ( Reserved[1] ), 150 FT_FRAME_SHORT ( Reserved[2] ), 151 FT_FRAME_SHORT ( Reserved[3] ), 152 FT_FRAME_SHORT ( metric_Data_Format ), 153 FT_FRAME_USHORT( number_Of_HMetrics ), 154 FT_FRAME_END 155 }; 156 157 158 if ( vertical ) 159 { 160 void *v = &face->vertical; 161 162 163 error = face->goto_table( face, TTAG_vhea, stream, 0 ); 164 if ( error ) 165 goto Fail; 166 167 header = (TT_HoriHeader*)v; 168 } 169 else 170 { 171 error = face->goto_table( face, TTAG_hhea, stream, 0 ); 172 if ( error ) 173 goto Fail; 174 175 header = &face->horizontal; 176 } 177 178 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) 179 goto Fail; 180 181 FT_TRACE3(( "Ascender: %5d\n", header->Ascender )); 182 FT_TRACE3(( "Descender: %5d\n", header->Descender )); 183 FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics )); 184 185 header->long_metrics = NULL; 186 header->short_metrics = NULL; 187 188 Fail: 189 return error; 190 } 191 192 193 /*************************************************************************/ 194 /* */ 195 /* <Function> */ 196 /* tt_face_get_metrics */ 197 /* */ 198 /* <Description> */ 199 /* Return the horizontal or vertical metrics in font units for a */ 200 /* given glyph. The values are the left side bearing (top side */ 201 /* bearing for vertical metrics) and advance width (advance height */ 202 /* for vertical metrics). */ 203 /* */ 204 /* <Input> */ 205 /* face :: A pointer to the TrueType face structure. */ 206 /* */ 207 /* vertical :: If set to TRUE, get vertical metrics. */ 208 /* */ 209 /* gindex :: The glyph index. */ 210 /* */ 211 /* <Output> */ 212 /* abearing :: The bearing, either left side or top side. */ 213 /* */ 214 /* aadvance :: The advance width or advance height, depending on */ 215 /* the `vertical' flag. */ 216 /* */ 217 FT_LOCAL_DEF( void ) tt_face_get_metrics(TT_Face face,FT_Bool vertical,FT_UInt gindex,FT_Short * abearing,FT_UShort * aadvance)218 tt_face_get_metrics( TT_Face face, 219 FT_Bool vertical, 220 FT_UInt gindex, 221 FT_Short *abearing, 222 FT_UShort *aadvance ) 223 { 224 FT_Error error; 225 FT_Stream stream = face->root.stream; 226 TT_HoriHeader* header; 227 FT_ULong table_pos, table_size, table_end; 228 FT_UShort k; 229 230 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 231 FT_Service_MetricsVariations var = 232 (FT_Service_MetricsVariations)face->var; 233 #endif 234 235 236 if ( vertical ) 237 { 238 void* v = &face->vertical; 239 240 241 header = (TT_HoriHeader*)v; 242 table_pos = face->vert_metrics_offset; 243 table_size = face->vert_metrics_size; 244 } 245 else 246 { 247 header = &face->horizontal; 248 table_pos = face->horz_metrics_offset; 249 table_size = face->horz_metrics_size; 250 } 251 252 table_end = table_pos + table_size; 253 254 k = header->number_Of_HMetrics; 255 256 if ( k > 0 ) 257 { 258 if ( gindex < (FT_UInt)k ) 259 { 260 table_pos += 4 * gindex; 261 if ( table_pos + 4 > table_end ) 262 goto NoData; 263 264 if ( FT_STREAM_SEEK( table_pos ) || 265 FT_READ_USHORT( *aadvance ) || 266 FT_READ_SHORT( *abearing ) ) 267 goto NoData; 268 } 269 else 270 { 271 table_pos += 4 * ( k - 1 ); 272 if ( table_pos + 4 > table_end ) 273 goto NoData; 274 275 if ( FT_STREAM_SEEK( table_pos ) || 276 FT_READ_USHORT( *aadvance ) ) 277 goto NoData; 278 279 table_pos += 4 + 2 * ( gindex - k ); 280 if ( table_pos + 2 > table_end ) 281 *abearing = 0; 282 else 283 { 284 if ( !FT_STREAM_SEEK( table_pos ) ) 285 (void)FT_READ_SHORT( *abearing ); 286 } 287 } 288 } 289 else 290 { 291 NoData: 292 *abearing = 0; 293 *aadvance = 0; 294 } 295 296 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 297 if ( var ) 298 { 299 FT_Face f = FT_FACE( face ); 300 FT_Int a = (FT_Int)*aadvance; 301 FT_Int b = (FT_Int)*abearing; 302 303 304 if ( vertical ) 305 { 306 if ( var->vadvance_adjust ) 307 var->vadvance_adjust( f, gindex, &a ); 308 if ( var->tsb_adjust ) 309 var->tsb_adjust( f, gindex, &b ); 310 } 311 else 312 { 313 if ( var->hadvance_adjust ) 314 var->hadvance_adjust( f, gindex, &a ); 315 if ( var->lsb_adjust ) 316 var->lsb_adjust( f, gindex, &b ); 317 } 318 319 *aadvance = (FT_UShort)a; 320 *abearing = (FT_Short)b; 321 } 322 #endif 323 } 324 325 326 /* END */ 327