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