• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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