Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ttmtx.c
Go to the documentation of this file.
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  * 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 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
64 
68  FT_Bool vertical )
69  {
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 /* !FT_CONFIG_OPTION_OLD_INTERNALS */
101 
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  void* lm = &face->vertical.long_metrics;
121  void** sm = &face->vertical.short_metrics;
122 
123 
124  error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
125  if ( error )
126  goto Fail;
127 
128  num_longs = face->vertical.number_Of_VMetrics;
129  if ( (FT_ULong)num_longs > table_len / 4 )
130  num_longs = (FT_Long)( table_len / 4 );
131 
132  face->vertical.number_Of_VMetrics = 0;
133 
134  longs = (TT_LongMetrics*)lm;
135  shorts = (TT_ShortMetrics**)sm;
136  }
137  else
138  {
139  void* lm = &face->horizontal.long_metrics;
140  void** sm = &face->horizontal.short_metrics;
141 
142 
143  error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
144  if ( error )
145  goto Fail;
146 
147  num_longs = face->horizontal.number_Of_HMetrics;
148  if ( (FT_ULong)num_longs > table_len / 4 )
149  num_longs = (FT_Long)( table_len / 4 );
150 
151  face->horizontal.number_Of_HMetrics = 0;
152 
153  longs = (TT_LongMetrics*)lm;
154  shorts = (TT_ShortMetrics**)sm;
155  }
156 
157  /* never trust derived values */
158 
159  num_shorts = face->max_profile.numGlyphs - num_longs;
160  num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
161 
162  if ( num_shorts < 0 )
163  {
164  FT_TRACE0(( "tt_face_load_hmtx:"
165  " %cmtx has more metrics than glyphs.\n",
166  vertical ? 'v' : 'h' ));
167 
168  /* Adobe simply ignores this problem. So we shall do the same. */
169 #if 0
170  error = vertical ? FT_THROW( Invalid_Vert_Metrics )
171  : FT_THROW( Invalid_Horiz_Metrics );
172  goto Exit;
173 #else
174  num_shorts = 0;
175 #endif
176  }
177 
178  if ( FT_QNEW_ARRAY( *longs, num_longs ) ||
179  FT_QNEW_ARRAY( *shorts, num_shorts ) )
180  goto Fail;
181 
182  if ( FT_FRAME_ENTER( table_len ) )
183  goto Fail;
184 
185  p = stream->cursor;
186 
187  {
188  TT_LongMetrics cur = *longs;
189  TT_LongMetrics limit = cur + num_longs;
190 
191 
192  for ( ; cur < limit; cur++ )
193  {
194  cur->advance = FT_NEXT_USHORT( p );
195  cur->bearing = FT_NEXT_SHORT( p );
196  }
197  }
198 
199  /* do we have an inconsistent number of metric values? */
200  {
201  TT_ShortMetrics* cur = *shorts;
202  TT_ShortMetrics* limit = cur +
203  FT_MIN( num_shorts, num_shorts_checked );
204 
205 
206  for ( ; cur < limit; cur++ )
207  *cur = FT_NEXT_SHORT( p );
208 
209  /* We fill up the missing left side bearings with the */
210  /* last valid value. Since this will occur for buggy CJK */
211  /* fonts usually only, nothing serious will happen. */
212  if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
213  {
214  FT_Short val = (*shorts)[num_shorts_checked - 1];
215 
216 
217  limit = *shorts + num_shorts;
218  for ( ; cur < limit; cur++ )
219  *cur = val;
220  }
221  }
222 
223  FT_FRAME_EXIT();
224 
225  if ( vertical )
226  face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
227  else
228  face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
229 
230  Fail:
231  return error;
232  }
233 
234 #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
235 
236 
237  /*************************************************************************/
238  /* */
239  /* <Function> */
240  /* tt_face_load_hhea */
241  /* */
242  /* <Description> */
243  /* Load the `hhea' or 'vhea' table into a face object. */
244  /* */
245  /* <Input> */
246  /* face :: A handle to the target face object. */
247  /* */
248  /* stream :: The input stream. */
249  /* */
250  /* vertical :: A boolean flag. If set, load `vhea'. */
251  /* */
252  /* <Return> */
253  /* FreeType error code. 0 means success. */
254  /* */
257  FT_Stream stream,
258  FT_Bool vertical )
259  {
260  FT_Error error;
261  TT_HoriHeader* header;
262 
263  static const FT_Frame_Field metrics_header_fields[] =
264  {
265 #undef FT_STRUCTURE
266 #define FT_STRUCTURE TT_HoriHeader
267 
268  FT_FRAME_START( 36 ),
269  FT_FRAME_ULONG ( Version ),
270  FT_FRAME_SHORT ( Ascender ),
271  FT_FRAME_SHORT ( Descender ),
272  FT_FRAME_SHORT ( Line_Gap ),
273  FT_FRAME_USHORT( advance_Width_Max ),
274  FT_FRAME_SHORT ( min_Left_Side_Bearing ),
275  FT_FRAME_SHORT ( min_Right_Side_Bearing ),
276  FT_FRAME_SHORT ( xMax_Extent ),
277  FT_FRAME_SHORT ( caret_Slope_Rise ),
278  FT_FRAME_SHORT ( caret_Slope_Run ),
279  FT_FRAME_SHORT ( caret_Offset ),
280  FT_FRAME_SHORT ( Reserved[0] ),
281  FT_FRAME_SHORT ( Reserved[1] ),
282  FT_FRAME_SHORT ( Reserved[2] ),
283  FT_FRAME_SHORT ( Reserved[3] ),
284  FT_FRAME_SHORT ( metric_Data_Format ),
285  FT_FRAME_USHORT( number_Of_HMetrics ),
287  };
288 
289 
290  if ( vertical )
291  {
292  void *v = &face->vertical;
293 
294 
295  error = face->goto_table( face, TTAG_vhea, stream, 0 );
296  if ( error )
297  goto Fail;
298 
299  header = (TT_HoriHeader*)v;
300  }
301  else
302  {
303  error = face->goto_table( face, TTAG_hhea, stream, 0 );
304  if ( error )
305  goto Fail;
306 
307  header = &face->horizontal;
308  }
309 
310  if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
311  goto Fail;
312 
313  FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
314  FT_TRACE3(( "Descender: %5d\n", header->Descender ));
315  FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
316 
317  header->long_metrics = NULL;
318  header->short_metrics = NULL;
319 
320  Fail:
321  return error;
322  }
323 
324 
325  /*************************************************************************/
326  /* */
327  /* <Function> */
328  /* tt_face_get_metrics */
329  /* */
330  /* <Description> */
331  /* Returns the horizontal or vertical metrics in font units for a */
332  /* given glyph. The metrics are the left side bearing (resp. top */
333  /* side bearing) and advance width (resp. advance height). */
334  /* */
335  /* <Input> */
336  /* header :: A pointer to either the horizontal or vertical metrics */
337  /* structure. */
338  /* */
339  /* idx :: The glyph index. */
340  /* */
341  /* <Output> */
342  /* bearing :: The bearing, either left side or top side. */
343  /* */
344  /* advance :: The advance width resp. advance height. */
345  /* */
346 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
347 
350  FT_Bool vertical,
351  FT_UInt gindex,
352  FT_Short *abearing,
353  FT_UShort *aadvance )
354  {
355  FT_Error error;
356  FT_Stream stream = face->root.stream;
357  TT_HoriHeader* header;
358  FT_ULong table_pos, table_size, table_end;
359  FT_UShort k;
360 
361 
362  if ( vertical )
363  {
364  void* v = &face->vertical;
365 
366 
367  header = (TT_HoriHeader*)v;
368  table_pos = face->vert_metrics_offset;
369  table_size = face->vert_metrics_size;
370  }
371  else
372  {
373  header = &face->horizontal;
374  table_pos = face->horz_metrics_offset;
375  table_size = face->horz_metrics_size;
376  }
377 
378  table_end = table_pos + table_size;
379 
380  k = header->number_Of_HMetrics;
381 
382  if ( k > 0 )
383  {
384  if ( gindex < (FT_UInt)k )
385  {
386  table_pos += 4 * gindex;
387  if ( table_pos + 4 > table_end )
388  goto NoData;
389 
390  if ( FT_STREAM_SEEK( table_pos ) ||
391  FT_READ_USHORT( *aadvance ) ||
392  FT_READ_SHORT( *abearing ) )
393  goto NoData;
394  }
395  else
396  {
397  table_pos += 4 * ( k - 1 );
398  if ( table_pos + 4 > table_end )
399  goto NoData;
400 
401  if ( FT_STREAM_SEEK( table_pos ) ||
402  FT_READ_USHORT( *aadvance ) )
403  goto NoData;
404 
405  table_pos += 4 + 2 * ( gindex - k );
406  if ( table_pos + 2 > table_end )
407  *abearing = 0;
408  else
409  {
410  if ( !FT_STREAM_SEEK( table_pos ) )
411  (void)FT_READ_SHORT( *abearing );
412  }
413  }
414  }
415  else
416  {
417  NoData:
418  *abearing = 0;
419  *aadvance = 0;
420  }
421 
422  return FT_Err_Ok;
423  }
424 
425 #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
426 
429  FT_Bool vertical,
430  FT_UInt gindex,
431  FT_Short* abearing,
432  FT_UShort* aadvance )
433  {
434  void* v = &face->vertical;
435  void* h = &face->horizontal;
436  TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v
437  : (TT_HoriHeader*)h;
438  TT_LongMetrics longs_m;
439  FT_UShort k = header->number_Of_HMetrics;
440 
441 
442  if ( k == 0 ||
443  !header->long_metrics ||
444  gindex >= (FT_UInt)face->max_profile.numGlyphs )
445  {
446  *abearing = *aadvance = 0;
447  return FT_Err_Ok;
448  }
449 
450  if ( gindex < (FT_UInt)k )
451  {
452  longs_m = (TT_LongMetrics)header->long_metrics + gindex;
453  *abearing = longs_m->bearing;
454  *aadvance = longs_m->advance;
455  }
456  else
457  {
458  *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
459  *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
460  }
461 
462  return FT_Err_Ok;
463  }
464 
465 #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
466 
467 
468 /* END */
int FT_Error
Definition: fttypes.h:296
GLuint GLuint stream
signed long FT_Long
Definition: fttypes.h:238
unsigned long FT_ULong
Definition: fttypes.h:249
GLfloat GLfloat p
tt_face_load_hhea(TT_Face face, FT_Stream stream, FT_Bool vertical)
Definition: ttmtx.c:256
#define NULL
Definition: ftobjs.h:61
unsigned char * cursor
Definition: ftsystem.h:333
FT_UShort number_Of_HMetrics
Definition: tttables.h:199
GLfloat GLfloat GLfloat GLfloat h
return FT_THROW(Missing_Property)
#define TTAG_vhea
Definition: tttags.h:98
#define FT_MIN(a, b)
Definition: ftobjs.h:70
tt_face_get_metrics(TT_Face face, FT_Bool vertical, FT_UInt gindex, FT_Short *abearing, FT_UShort *aadvance)
Definition: ttmtx.c:349
#define FT_QNEW_ARRAY(ptr, count)
Definition: ftmemory.h:299
FT_UShort advance
Definition: tttypes.h:156
return FT_Err_Ok
Definition: ftbbox.c:645
#define FT_READ_USHORT(var)
Definition: ftstream.h:309
FT_ULong horz_metrics_size
Definition: tttypes.h:1399
FT_UShort numGlyphs
Definition: tttables.h:531
TT_Loader_GotoTableFunc goto_table
Definition: tttypes.h:1288
FT_ULong vert_metrics_offset
Definition: tttypes.h:1429
#define TTAG_hmtx
Definition: tttags.h:65
void * short_metrics
Definition: tttables.h:206
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
GLenum GLuint GLint GLenum face
FT_Short TT_ShortMetrics
Definition: tttypes.h:171
unsigned char FT_Byte
Definition: fttypes.h:150
#define TTAG_hhea
Definition: tttags.h:64
FT_Short Descender
Definition: tttables.h:184
#define FT_STREAM_READ_FIELDS(fields, object)
Definition: ftstream.h:506
FT_Short bearing
Definition: tttypes.h:157
FT_Memory memory
Definition: ftsystem.h:332
FT_Short Ascender
Definition: tttables.h:183
#define FT_FRAME_END
Definition: ftstream.h:118
#define FT_FRAME_USHORT(f)
Definition: ftstream.h:123
TT_MaxProfile max_profile
Definition: tttypes.h:1271
FT_Error error
Definition: cffdrivr.c:411
const GLdouble * v
FT_UShort number_Of_VMetrics
Definition: tttables.h:325
GLuint GLfloat * val
TT_VertHeader vertical
Definition: tttypes.h:1277
signed short FT_Short
Definition: fttypes.h:194
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_FaceRec root
Definition: tttypes.h:1260
#define FT_FRAME_EXIT()
Definition: ftstream.h:514
TT_HoriHeader horizontal
Definition: tttypes.h:1269
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
#define FT_NEXT_USHORT(buffer)
Definition: ftstream.h:226
#define TTAG_vmtx
Definition: tttags.h:99
#define FT_TRACE3(varformat)
Definition: ftdebug.h:160
#define FT_STREAM_POS()
Definition: ftstream.h:486
#define FT_FRAME_ULONG(f)
Definition: ftstream.h:121
FT_ULong horz_metrics_offset
Definition: tttypes.h:1428
unsigned int FT_UInt
Definition: fttypes.h:227
FT_ULong vert_metrics_size
Definition: tttypes.h:1402
tt_face_load_hmtx(TT_Face face, FT_Stream stream, FT_Bool vertical)
Definition: ttmtx.c:66
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:510
void * short_metrics
Definition: tttables.h:332
FT_TRACE0(("cff_property_set: missing property `%s'\, property_name))
#define FT_NEXT_SHORT(buffer)
Definition: ftstream.h:223
#define FT_READ_SHORT(var)
Definition: ftstream.h:308
void * long_metrics
Definition: tttables.h:205
unsigned short FT_UShort
Definition: fttypes.h:205
FT_Stream stream
Definition: freetype.h:964
#define FT_FRAME_SHORT(f)
Definition: ftstream.h:122
#define FT_FRAME_START(size)
Definition: ftstream.h:117
GLint limit
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
void * long_metrics
Definition: tttables.h:331
struct TT_LongMetricsRec_ * TT_LongMetrics