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