source: trunk/poppler/freetype2/src/sfnt/ttmtx.c @ 182

Last change on this file since 182 was 182, checked in by Eugene Romanenko, 15 years ago

freetype update to version 2.3.0

File size: 15.7 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ttmtx.c                                                                */
4/*                                                                         */
5/*    Load the metrics tables common to TTF and OTF fonts (body).          */
6/*                                                                         */
7/*  Copyright 2006, 2007 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   *  Unfortunately, we can't enable our memory optimizations if
40   *  FT_CONFIG_OPTION_OLD_INTERNALS is defined.  This is because at least
41   *  one rogue client (libXfont in the X.Org XServer) is directly accessing
42   *  the metrics.
43   */
44
45  /*************************************************************************/
46  /*                                                                       */
47  /* <Function>                                                            */
48  /*    tt_face_load_hmtx                                                  */
49  /*                                                                       */
50  /* <Description>                                                         */
51  /*    Load the `hmtx' or `vmtx' table into a face object.                */
52  /*                                                                       */
53  /* <Input>                                                               */
54  /*    face     :: A handle to the target face object.                    */
55  /*                                                                       */
56  /*    stream   :: The input stream.                                      */
57  /*                                                                       */
58  /*    vertical :: A boolean flag.  If set, load `vmtx'.                  */
59  /*                                                                       */
60  /* <Return>                                                              */
61  /*    FreeType error code.  0 means success.                             */
62  /*                                                                       */
63#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
64
65  FT_LOCAL_DEF( FT_Error )
66  tt_face_load_hmtx( TT_Face    face,
67                     FT_Stream  stream,
68                     FT_Bool    vertical )
69  {
70    FT_Error   error;
71    FT_ULong   tag, table_size;
72    FT_ULong*  ptable_offset;
73    FT_ULong*  ptable_size;
74
75
76    if ( vertical )
77    {
78      tag           = TTAG_vmtx;
79      ptable_offset = &face->vert_metrics_offset;
80      ptable_size   = &face->vert_metrics_size;
81    }
82    else
83    {
84      tag           = TTAG_hmtx;
85      ptable_offset = &face->horz_metrics_offset;
86      ptable_size   = &face->horz_metrics_size;
87    }
88
89    error = face->goto_table( face, tag, stream, &table_size );
90    if ( error )
91      goto Fail;
92
93    *ptable_size   = table_size;
94    *ptable_offset = FT_STREAM_POS();
95
96  Fail:
97    return error;
98  }
99
100#else /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
101
102  FT_LOCAL_DEF( FT_Error )
103  tt_face_load_hmtx( TT_Face    face,
104                     FT_Stream  stream,
105                     FT_Bool    vertical )
106  {
107    FT_Error   error;
108    FT_Memory  memory = stream->memory;
109
110    FT_ULong   table_len;
111    FT_Long    num_shorts, num_longs, num_shorts_checked;
112
113    TT_LongMetrics *   longs;
114    TT_ShortMetrics**  shorts;
115    FT_Byte*           p;
116
117
118    if ( vertical )
119    {
120      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
121      if ( error )
122        goto Fail;
123
124      num_longs = face->vertical.number_Of_VMetrics;
125      if ( (FT_ULong)num_longs > table_len / 4 )
126        num_longs = (FT_Long)(table_len / 4);
127
128      face->vertical.number_Of_VMetrics = 0;
129
130      longs  = (TT_LongMetrics *)&face->vertical.long_metrics;
131      shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
132    }
133    else
134    {
135      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
136      if ( error )
137        goto Fail;
138
139      num_longs = face->horizontal.number_Of_HMetrics;
140      if ( (FT_ULong)num_longs > table_len / 4 )
141        num_longs = (FT_Long)(table_len / 4);
142
143      face->horizontal.number_Of_HMetrics = 0;
144
145      longs  = (TT_LongMetrics *)&face->horizontal.long_metrics;
146      shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
147    }
148
149    /* never trust derived values */
150
151    num_shorts         = face->max_profile.numGlyphs - num_longs;
152    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
153
154    if ( num_shorts < 0 )
155    {
156      FT_ERROR(( "%cmtx has more metrics than glyphs.\n" ));
157
158      /* Adobe simply ignores this problem.  So we shall do the same. */
159#if 0
160      error = vertical ? SFNT_Err_Invalid_Vert_Metrics
161                       : SFNT_Err_Invalid_Horiz_Metrics;
162      goto Exit;
163#else
164      num_shorts = 0;
165#endif
166    }
167
168    if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
169         FT_QNEW_ARRAY( *shorts, num_shorts ) )
170      goto Fail;
171
172    if ( FT_FRAME_ENTER( table_len ) )
173      goto Fail;
174
175    p = stream->cursor;
176
177    {
178      TT_LongMetrics  cur   = *longs;
179      TT_LongMetrics  limit = cur + num_longs;
180
181
182      for ( ; cur < limit; cur++ )
183      {
184        cur->advance = FT_NEXT_USHORT( p );
185        cur->bearing = FT_NEXT_SHORT( p );
186      }
187    }
188
189    /* do we have an inconsistent number of metric values? */
190    {
191      TT_ShortMetrics*  cur   = *shorts;
192      TT_ShortMetrics*  limit = cur +
193                                FT_MIN( num_shorts, num_shorts_checked );
194
195
196      for ( ; cur < limit; cur++ )
197        *cur = FT_NEXT_SHORT( p );
198
199      /* We fill up the missing left side bearings with the     */
200      /* last valid value.  Since this will occur for buggy CJK */
201      /* fonts usually only, nothing serious will happen.       */
202      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
203      {
204        FT_Short  val = (*shorts)[num_shorts_checked - 1];
205
206
207        limit = *shorts + num_shorts;
208        for ( ; cur < limit; cur++ )
209          *cur = val;
210      }
211    }
212
213    FT_FRAME_EXIT();
214
215    if ( vertical )
216      face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
217    else
218      face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
219
220  Fail:
221    return error;
222  }
223
224#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
225
226
227  /*************************************************************************/
228  /*                                                                       */
229  /* <Function>                                                            */
230  /*    tt_face_load_hhea                                                  */
231  /*                                                                       */
232  /* <Description>                                                         */
233  /*    Load the `hhea' or 'vhea' table into a face object.                */
234  /*                                                                       */
235  /* <Input>                                                               */
236  /*    face     :: A handle to the target face object.                    */
237  /*                                                                       */
238  /*    stream   :: The input stream.                                      */
239  /*                                                                       */
240  /*    vertical :: A boolean flag.  If set, load `vhea'.                  */
241  /*                                                                       */
242  /* <Return>                                                              */
243  /*    FreeType error code.  0 means success.                             */
244  /*                                                                       */
245  FT_LOCAL_DEF( FT_Error )
246  tt_face_load_hhea( TT_Face    face,
247                     FT_Stream  stream,
248                     FT_Bool    vertical )
249  {
250    FT_Error        error;
251    TT_HoriHeader*  header;
252
253    const FT_Frame_Field  metrics_header_fields[] =
254    {
255#undef  FT_STRUCTURE
256#define FT_STRUCTURE  TT_HoriHeader
257
258      FT_FRAME_START( 36 ),
259        FT_FRAME_ULONG ( Version ),
260        FT_FRAME_SHORT ( Ascender ),
261        FT_FRAME_SHORT ( Descender ),
262        FT_FRAME_SHORT ( Line_Gap ),
263        FT_FRAME_USHORT( advance_Width_Max ),
264        FT_FRAME_SHORT ( min_Left_Side_Bearing ),
265        FT_FRAME_SHORT ( min_Right_Side_Bearing ),
266        FT_FRAME_SHORT ( xMax_Extent ),
267        FT_FRAME_SHORT ( caret_Slope_Rise ),
268        FT_FRAME_SHORT ( caret_Slope_Run ),
269        FT_FRAME_SHORT ( caret_Offset ),
270        FT_FRAME_SHORT ( Reserved[0] ),
271        FT_FRAME_SHORT ( Reserved[1] ),
272        FT_FRAME_SHORT ( Reserved[2] ),
273        FT_FRAME_SHORT ( Reserved[3] ),
274        FT_FRAME_SHORT ( metric_Data_Format ),
275        FT_FRAME_USHORT( number_Of_HMetrics ),
276      FT_FRAME_END
277    };
278
279
280    if ( vertical )
281    {
282      error = face->goto_table( face, TTAG_vhea, stream, 0 );
283      if ( error )
284        goto Fail;
285
286      header = (TT_HoriHeader*)&face->vertical;
287    }
288    else
289    {
290      error = face->goto_table( face, TTAG_hhea, stream, 0 );
291      if ( error )
292        goto Fail;
293
294      header = &face->horizontal;
295    }
296
297    if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
298      goto Fail;
299
300    FT_TRACE3(( "Ascender:          %5d\n", header->Ascender ));
301    FT_TRACE3(( "Descender:         %5d\n", header->Descender ));
302    FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
303
304    header->long_metrics  = NULL;
305    header->short_metrics = NULL;
306
307  Fail:
308    return error;
309  }
310
311
312  /*************************************************************************/
313  /*                                                                       */
314  /* <Function>                                                            */
315  /*    tt_face_get_metrics                                                */
316  /*                                                                       */
317  /* <Description>                                                         */
318  /*    Returns the horizontal or vertical metrics in font units for a     */
319  /*    given glyph.  The metrics are the left side bearing (resp. top     */
320  /*    side bearing) and advance width (resp. advance height).            */
321  /*                                                                       */
322  /* <Input>                                                               */
323  /*    header  :: A pointer to either the horizontal or vertical metrics  */
324  /*               structure.                                              */
325  /*                                                                       */
326  /*    idx     :: The glyph index.                                        */
327  /*                                                                       */
328  /* <Output>                                                              */
329  /*    bearing :: The bearing, either left side or top side.              */
330  /*                                                                       */
331  /*    advance :: The advance width resp. advance height.                 */
332  /*                                                                       */
333#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
334
335  FT_LOCAL_DEF( FT_Error )
336  tt_face_get_metrics( TT_Face     face,
337                       FT_Bool     vertical,
338                       FT_UInt     gindex,
339                       FT_Short   *abearing,
340                       FT_UShort  *aadvance )
341  {
342    FT_Error        error;
343    FT_Stream       stream = face->root.stream;
344    TT_HoriHeader*  header;
345    FT_ULong        table_pos, table_size, table_end;
346    FT_UShort       k;
347
348
349    if ( vertical )
350    {
351      header     = (TT_HoriHeader*)&face->vertical;
352      table_pos  = face->vert_metrics_offset;
353      table_size = face->vert_metrics_size;
354    }
355    else
356    {
357      header     = &face->horizontal;
358      table_pos  = face->horz_metrics_offset;
359      table_size = face->horz_metrics_size;
360    }
361
362    table_end = table_pos + table_size;
363
364    k = header->number_Of_HMetrics;
365
366    if ( k > 0 )
367    {
368      if ( gindex < (FT_UInt)k )
369      {
370        table_pos += 4 * gindex;
371        if ( table_pos + 6 > table_end )
372          goto NoData;
373
374        if ( FT_STREAM_SEEK( table_pos ) ||
375             FT_READ_USHORT( *aadvance)  ||
376             FT_READ_SHORT( *abearing )  )
377          goto NoData;
378      }
379      else
380      {
381        table_pos += 4 * ( k - 1 );
382        if ( table_pos + 4 > table_end )
383          goto NoData;
384
385        if ( FT_STREAM_SEEK( table_pos ) ||
386             FT_READ_USHORT( *aadvance ) )
387          goto NoData;
388
389        table_pos += 4 + 2 * ( gindex - k );
390        if ( table_pos + 2 > table_end )
391          *abearing = 0;
392        else
393        {
394          if ( !FT_STREAM_SEEK( table_pos ) )
395            (void)FT_READ_SHORT( *abearing );
396        }
397      }
398    }
399    else
400    {
401    NoData:
402      *abearing = 0;
403      *aadvance = 0;
404    }
405
406    return SFNT_Err_Ok;
407  }
408
409#else /* OLD_INTERNALS */
410
411  FT_LOCAL_DEF( FT_Error )
412  tt_face_get_metrics( TT_Face     face,
413                       FT_Bool     vertical,
414                       FT_UInt     gindex,
415                       FT_Short*   abearing,
416                       FT_UShort*  aadvance )
417  {
418    TT_HoriHeader*  header = vertical ? (TT_HoriHeader*)&face->vertical
419                                      :                 &face->horizontal;
420    TT_LongMetrics  longs_m;
421    FT_UShort       k = header->number_Of_HMetrics;
422
423
424    if ( k == 0                                         ||
425         !header->long_metrics                          ||
426         gindex >= (FT_UInt)face->max_profile.numGlyphs )
427    {
428      *abearing = *aadvance = 0;
429      return SFNT_Err_Ok;
430    }
431
432    if ( gindex < (FT_UInt)k )
433    {
434      longs_m   = (TT_LongMetrics)header->long_metrics + gindex;
435      *abearing = longs_m->bearing;
436      *aadvance = longs_m->advance;
437    }
438    else
439    {
440      *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
441      *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
442    }
443
444    return SFNT_Err_Ok;
445  }
446
447#endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
448
449
450/* END */
Note: See TracBrowser for help on using the repository browser.