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 "../../include/ft2build.h" 20#include "../../include/freetype/internal/ftdebug.h" 21#include "../../include/freetype/internal/ftstream.h" 22#include "../../include/freetype/tttags.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 0 82 if ( error ) 83 goto Fail; 84 85 *ptable_size = table_size; 86 *ptable_offset = FT_STREAM_POS(); 87 88 Fail: 89 return error; 90#else 91 *ptable_size = error ? 0 : table_size; 92 *ptable_offset = FT_STREAM_POS(); 93 94 return 0; 95#endif 96 } 97 98 99 /*************************************************************************/ 100 /* */ 101 /* <Function> */ 102 /* tt_face_load_hhea */ 103 /* */ 104 /* <Description> */ 105 /* Load the `hhea' or 'vhea' table into a face object. */ 106 /* */ 107 /* <Input> */ 108 /* face :: A handle to the target face object. */ 109 /* */ 110 /* stream :: The input stream. */ 111 /* */ 112 /* vertical :: A boolean flag. If set, load `vhea'. */ 113 /* */ 114 /* <Return> */ 115 /* FreeType error code. 0 means success. */ 116 /* */ 117 FT_LOCAL_DEF( FT_Error ) 118 tt_face_load_hhea( TT_Face face, 119 FT_Stream stream, 120 FT_Bool vertical ) 121 { 122 FT_Error error; 123 TT_HoriHeader* header; 124 125 static const FT_Frame_Field metrics_header_fields[] = 126 { 127#undef FT_STRUCTURE 128#define FT_STRUCTURE TT_HoriHeader 129 130 FT_FRAME_START( 36 ), 131 FT_FRAME_ULONG ( Version ), 132 FT_FRAME_SHORT ( Ascender ), 133 FT_FRAME_SHORT ( Descender ), 134 FT_FRAME_SHORT ( Line_Gap ), 135 FT_FRAME_USHORT( advance_Width_Max ), 136 FT_FRAME_SHORT ( min_Left_Side_Bearing ), 137 FT_FRAME_SHORT ( min_Right_Side_Bearing ), 138 FT_FRAME_SHORT ( xMax_Extent ), 139 FT_FRAME_SHORT ( caret_Slope_Rise ), 140 FT_FRAME_SHORT ( caret_Slope_Run ), 141 FT_FRAME_SHORT ( caret_Offset ), 142 FT_FRAME_SHORT ( Reserved[0] ), 143 FT_FRAME_SHORT ( Reserved[1] ), 144 FT_FRAME_SHORT ( Reserved[2] ), 145 FT_FRAME_SHORT ( Reserved[3] ), 146 FT_FRAME_SHORT ( metric_Data_Format ), 147 FT_FRAME_USHORT( number_Of_HMetrics ), 148 FT_FRAME_END 149 }; 150 151 152 if ( vertical ) 153 { 154 void *v = &face->vertical; 155 156 157 error = face->goto_table( face, TTAG_vhea, stream, 0 ); 158 if ( error ) 159 goto Fail; 160 161 header = (TT_HoriHeader*)v; 162 } 163 else 164 { 165 error = face->goto_table( face, TTAG_hhea, stream, 0 ); 166 if ( error ) 167 goto Fail; 168 169 header = &face->horizontal; 170 } 171 172 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) 173 goto Fail; 174 175 FT_TRACE3(( "Ascender: %5d\n", header->Ascender )); 176 FT_TRACE3(( "Descender: %5d\n", header->Descender )); 177 FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics )); 178 179 header->long_metrics = NULL; 180 header->short_metrics = NULL; 181 182 Fail: 183 return error; 184 } 185 186 187 /*************************************************************************/ 188 /* */ 189 /* <Function> */ 190 /* tt_face_get_metrics */ 191 /* */ 192 /* <Description> */ 193 /* Returns the horizontal or vertical metrics in font units for a */ 194 /* given glyph. The metrics are the left side bearing (resp. top */ 195 /* side bearing) and advance width (resp. advance height). */ 196 /* */ 197 /* <Input> */ 198 /* header :: A pointer to either the horizontal or vertical metrics */ 199 /* structure. */ 200 /* */ 201 /* idx :: The glyph index. */ 202 /* */ 203 /* <Output> */ 204 /* bearing :: The bearing, either left side or top side. */ 205 /* */ 206 /* advance :: The advance width resp. advance height. */ 207 /* */ 208 FT_LOCAL_DEF( FT_Error ) 209 tt_face_get_metrics( TT_Face face, 210 FT_Bool vertical, 211 FT_UInt gindex, 212 FT_Short *abearing, 213 FT_UShort *aadvance ) 214 { 215 FT_Error error; 216 FT_Stream stream = face->root.stream; 217 TT_HoriHeader* header; 218 FT_ULong table_pos, table_size, table_end; 219 FT_UShort k; 220 221 222 if ( vertical ) 223 { 224 void* v = &face->vertical; 225 226 227 header = (TT_HoriHeader*)v; 228 table_pos = face->vert_metrics_offset; 229 table_size = face->vert_metrics_size; 230 } 231 else 232 { 233 header = &face->horizontal; 234 table_pos = face->horz_metrics_offset; 235 table_size = face->horz_metrics_size; 236 } 237 238 table_end = table_pos + table_size; 239 240 k = header->number_Of_HMetrics; 241 242 if ( k > 0 ) 243 { 244 if ( gindex < (FT_UInt)k ) 245 { 246 table_pos += 4 * gindex; 247 if ( table_pos + 4 > table_end ) 248 goto NoData; 249 250 if ( FT_STREAM_SEEK( table_pos ) || 251 FT_READ_USHORT( *aadvance ) || 252 FT_READ_SHORT( *abearing ) ) 253 goto NoData; 254 } 255 else 256 { 257 table_pos += 4 * ( k - 1 ); 258 if ( table_pos + 4 > table_end ) 259 goto NoData; 260 261 if ( FT_STREAM_SEEK( table_pos ) || 262 FT_READ_USHORT( *aadvance ) ) 263 goto NoData; 264 265 table_pos += 4 + 2 * ( gindex - k ); 266 if ( table_pos + 2 > table_end ) 267 *abearing = 0; 268 else 269 { 270 if ( !FT_STREAM_SEEK( table_pos ) ) 271 (void)FT_READ_SHORT( *abearing ); 272 } 273 } 274 } 275 else 276 { 277 NoData: 278 *abearing = 0; 279 *aadvance = 0; 280 } 281 282 return FT_Err_Ok; 283 } 284 285 286/* END */ 287