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 /* Return the horizontal or vertical metrics in font units for a */ 187 /* given glyph. The values are the left side bearing (top side */ 188 /* bearing for vertical metrics) and advance width (advance height */ 189 /* for vertical metrics). */ 190 /* */ 191 /* <Input> */ 192 /* face :: A pointer to the TrueType face structure. */ 193 /* */ 194 /* vertical :: If set to TRUE, get vertical metrics. */ 195 /* */ 196 /* gindex :: The glyph index. */ 197 /* */ 198 /* <Output> */ 199 /* abearing :: The bearing, either left side or top side. */ 200 /* */ 201 /* aadvance :: The advance width or advance height, depending on */ 202 /* the `vertical' flag. */ 203 /* */ 204 FT_LOCAL_DEF( FT_Error ) 205 tt_face_get_metrics( TT_Face face, 206 FT_Bool vertical, 207 FT_UInt gindex, 208 FT_Short *abearing, 209 FT_UShort *aadvance ) 210 { 211 FT_Error error; 212 FT_Stream stream = face->root.stream; 213 TT_HoriHeader* header; 214 FT_ULong table_pos, table_size, table_end; 215 FT_UShort k; 216 217 218 if ( vertical ) 219 { 220 void* v = &face->vertical; 221 222 223 header = (TT_HoriHeader*)v; 224 table_pos = face->vert_metrics_offset; 225 table_size = face->vert_metrics_size; 226 } 227 else 228 { 229 header = &face->horizontal; 230 table_pos = face->horz_metrics_offset; 231 table_size = face->horz_metrics_size; 232 } 233 234 table_end = table_pos + table_size; 235 236 k = header->number_Of_HMetrics; 237 238 if ( k > 0 ) 239 { 240 if ( gindex < (FT_UInt)k ) 241 { 242 table_pos += 4 * gindex; 243 if ( table_pos + 4 > table_end ) 244 goto NoData; 245 246 if ( FT_STREAM_SEEK( table_pos ) || 247 FT_READ_USHORT( *aadvance ) || 248 FT_READ_SHORT( *abearing ) ) 249 goto NoData; 250 } 251 else 252 { 253 table_pos += 4 * ( k - 1 ); 254 if ( table_pos + 4 > table_end ) 255 goto NoData; 256 257 if ( FT_STREAM_SEEK( table_pos ) || 258 FT_READ_USHORT( *aadvance ) ) 259 goto NoData; 260 261 table_pos += 4 + 2 * ( gindex - k ); 262 if ( table_pos + 2 > table_end ) 263 *abearing = 0; 264 else 265 { 266 if ( !FT_STREAM_SEEK( table_pos ) ) 267 (void)FT_READ_SHORT( *abearing ); 268 } 269 } 270 } 271 else 272 { 273 NoData: 274 *abearing = 0; 275 *aadvance = 0; 276 } 277 278 return FT_Err_Ok; 279 } 280 281 282 /* END */ 283