source: trunk/poppler/freetype2/src/truetype/ttpload.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: 18.1 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ttpload.c                                                              */
4/*                                                                         */
5/*    TrueType-specific tables loader (body).                              */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2004, 2005, 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_OBJECTS_H
22#include FT_INTERNAL_STREAM_H
23#include FT_TRUETYPE_TAGS_H
24
25#include "ttpload.h"
26
27#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
28#include "ttgxvar.h"
29#endif
30
31#include "tterrors.h"
32
33
34  /*************************************************************************/
35  /*                                                                       */
36  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
37  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
38  /* messages during execution.                                            */
39  /*                                                                       */
40#undef  FT_COMPONENT
41#define FT_COMPONENT  trace_ttpload
42
43
44  /*************************************************************************/
45  /*                                                                       */
46  /* <Function>                                                            */
47  /*    tt_face_load_loca                                                  */
48  /*                                                                       */
49  /* <Description>                                                         */
50  /*    Load the locations table.                                          */
51  /*                                                                       */
52  /* <InOut>                                                               */
53  /*    face   :: A handle to the target face object.                      */
54  /*                                                                       */
55  /* <Input>                                                               */
56  /*    stream :: The input stream.                                        */
57  /*                                                                       */
58  /* <Return>                                                              */
59  /*    FreeType error code.  0 means success.                             */
60  /*                                                                       */
61
62  FT_LOCAL_DEF( FT_Error )
63  tt_face_load_loca( TT_Face    face,
64                     FT_Stream  stream )
65  {
66    FT_Error  error;
67    FT_ULong  table_len;
68
69
70    /* we need the size of the `glyf' table for malformed `loca' tables */
71    error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
72    if ( error )
73      goto Exit;
74
75    FT_TRACE2(( "Locations " ));
76    error = face->goto_table( face, TTAG_loca, stream, &table_len );
77    if ( error )
78    {
79      error = TT_Err_Locations_Missing;
80      goto Exit;
81    }
82
83    if ( face->header.Index_To_Loc_Format != 0 )
84    {
85      if ( table_len >= 0x40000L )
86      {
87        FT_TRACE2(( "table too large!\n" ));
88        error = TT_Err_Invalid_Table;
89        goto Exit;
90      }
91      face->num_locations = (FT_UInt)( table_len >> 2 );
92    }
93    else
94    {
95      if ( table_len >= 0x20000L )
96      {
97        FT_TRACE2(( "table too large!\n" ));
98        error = TT_Err_Invalid_Table;
99        goto Exit;
100      }
101      face->num_locations = (FT_UInt)( table_len >> 1 );
102    }
103
104    /*
105     * Extract the frame.  We don't need to decompress it since
106     * we are able to parse it directly.
107     */
108    if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
109      goto Exit;
110
111    FT_TRACE2(( "loaded\n" ));
112
113  Exit:
114    return error;
115  }
116
117
118  FT_LOCAL_DEF( FT_ULong )
119  tt_face_get_location( TT_Face   face,
120                        FT_UInt   gindex,
121                        FT_UInt  *asize )
122  {
123    FT_ULong  pos1, pos2;
124    FT_Byte*  p;
125    FT_Byte*  p_limit;
126
127
128    pos1 = pos2 = 0;
129
130    if ( gindex < face->num_locations )
131    {
132      if ( face->header.Index_To_Loc_Format != 0 )
133      {
134        p       = face->glyph_locations + gindex * 4;
135        p_limit = face->glyph_locations + face->num_locations * 4;
136
137        pos1 = FT_NEXT_ULONG( p );
138        pos2 = pos1;
139
140        if ( p + 4 <= p_limit )
141          pos2 = FT_NEXT_ULONG( p );
142      }
143      else
144      {
145        p       = face->glyph_locations + gindex * 2;
146        p_limit = face->glyph_locations + face->num_locations * 2;
147
148        pos1 = FT_NEXT_USHORT( p );
149        pos2 = pos1;
150
151        if ( p + 2 <= p_limit )
152          pos2 = FT_NEXT_USHORT( p );
153
154        pos1 <<= 1;
155        pos2 <<= 1;
156      }
157    }
158
159    /* It isn't mentioned explicitly that the `loca' table must be  */
160    /* ordered, but implicitly it refers to the length of an entry  */
161    /* as the difference between the current and the next position. */
162    /* Anyway, there do exist (malformed) fonts which don't obey    */
163    /* this rule, so we are only able to provide an upper bound for */
164    /* the size.                                                    */
165    if ( pos2 >= pos1 )
166      *asize = (FT_UInt)( pos2 - pos1 );
167    else
168      *asize = (FT_UInt)( face->glyf_len - pos1 );
169
170    return pos1;
171  }
172
173
174  FT_LOCAL_DEF( void )
175  tt_face_done_loca( TT_Face  face )
176  {
177    FT_Stream  stream = face->root.stream;
178
179
180    FT_FRAME_RELEASE( face->glyph_locations );
181    face->num_locations = 0;
182  }
183
184
185
186  /*************************************************************************/
187  /*                                                                       */
188  /* <Function>                                                            */
189  /*    tt_face_load_cvt                                                   */
190  /*                                                                       */
191  /* <Description>                                                         */
192  /*    Load the control value table into a face object.                   */
193  /*                                                                       */
194  /* <InOut>                                                               */
195  /*    face   :: A handle to the target face object.                      */
196  /*                                                                       */
197  /* <Input>                                                               */
198  /*    stream :: A handle to the input stream.                            */
199  /*                                                                       */
200  /* <Return>                                                              */
201  /*    FreeType error code.  0 means success.                             */
202  /*                                                                       */
203  FT_LOCAL_DEF( FT_Error )
204  tt_face_load_cvt( TT_Face    face,
205                    FT_Stream  stream )
206  {
207#ifdef TT_USE_BYTECODE_INTERPRETER
208
209    FT_Error   error;
210    FT_Memory  memory = stream->memory;
211    FT_ULong   table_len;
212
213
214    FT_TRACE2(( "CVT " ));
215
216    error = face->goto_table( face, TTAG_cvt, stream, &table_len );
217    if ( error )
218    {
219      FT_TRACE2(( "is missing!\n" ));
220
221      face->cvt_size = 0;
222      face->cvt      = NULL;
223      error          = TT_Err_Ok;
224
225      goto Exit;
226    }
227
228    face->cvt_size = table_len / 2;
229
230    if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
231      goto Exit;
232
233    if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
234      goto Exit;
235
236    {
237      FT_Short*  cur   = face->cvt;
238      FT_Short*  limit = cur + face->cvt_size;
239
240
241      for ( ; cur <  limit; cur++ )
242        *cur = FT_GET_SHORT();
243    }
244
245    FT_FRAME_EXIT();
246    FT_TRACE2(( "loaded\n" ));
247
248#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
249    if ( face->doblend )
250      error = tt_face_vary_cvt( face, stream );
251#endif
252
253  Exit:
254    return error;
255
256#else /* !TT_USE_BYTECODE_INTERPRETER */
257
258    FT_UNUSED( face   );
259    FT_UNUSED( stream );
260
261    return TT_Err_Ok;
262
263#endif
264  }
265
266
267  /*************************************************************************/
268  /*                                                                       */
269  /* <Function>                                                            */
270  /*    tt_face_load_fpgm                                                  */
271  /*                                                                       */
272  /* <Description>                                                         */
273  /*    Load the font program.                                             */
274  /*                                                                       */
275  /* <InOut>                                                               */
276  /*    face   :: A handle to the target face object.                      */
277  /*                                                                       */
278  /* <Input>                                                               */
279  /*    stream :: A handle to the input stream.                            */
280  /*                                                                       */
281  /* <Return>                                                              */
282  /*    FreeType error code.  0 means success.                             */
283  /*                                                                       */
284  FT_LOCAL_DEF( FT_Error )
285  tt_face_load_fpgm( TT_Face    face,
286                     FT_Stream  stream )
287  {
288#ifdef TT_USE_BYTECODE_INTERPRETER
289
290    FT_Error  error;
291    FT_ULong  table_len;
292
293
294    FT_TRACE2(( "Font program " ));
295
296    /* The font program is optional */
297    error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
298    if ( error )
299    {
300      face->font_program      = NULL;
301      face->font_program_size = 0;
302      error                   = TT_Err_Ok;
303
304      FT_TRACE2(( "is missing!\n" ));
305    }
306    else
307    {
308      face->font_program_size = table_len;
309      if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
310        goto Exit;
311
312      FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
313    }
314
315  Exit:
316    return error;
317
318#else /* !TT_USE_BYTECODE_INTERPRETER */
319
320    FT_UNUSED( face   );
321    FT_UNUSED( stream );
322
323    return TT_Err_Ok;
324
325#endif
326  }
327
328
329  /*************************************************************************/
330  /*                                                                       */
331  /* <Function>                                                            */
332  /*    tt_face_load_prep                                                  */
333  /*                                                                       */
334  /* <Description>                                                         */
335  /*    Load the cvt program.                                              */
336  /*                                                                       */
337  /* <InOut>                                                               */
338  /*    face   :: A handle to the target face object.                      */
339  /*                                                                       */
340  /* <Input>                                                               */
341  /*    stream :: A handle to the input stream.                            */
342  /*                                                                       */
343  /* <Return>                                                              */
344  /*    FreeType error code.  0 means success.                             */
345  /*                                                                       */
346  FT_LOCAL_DEF( FT_Error )
347  tt_face_load_prep( TT_Face    face,
348                     FT_Stream  stream )
349  {
350#ifdef TT_USE_BYTECODE_INTERPRETER
351
352    FT_Error  error;
353    FT_ULong  table_len;
354
355
356    FT_TRACE2(( "Prep program " ));
357
358    error = face->goto_table( face, TTAG_prep, stream, &table_len );
359    if ( error )
360    {
361      face->cvt_program      = NULL;
362      face->cvt_program_size = 0;
363      error                  = TT_Err_Ok;
364
365      FT_TRACE2(( "is missing!\n" ));
366    }
367    else
368    {
369      face->cvt_program_size = table_len;
370      if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
371        goto Exit;
372
373      FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
374    }
375
376  Exit:
377    return error;
378
379#else /* !TT_USE_BYTECODE_INTERPRETER */
380
381    FT_UNUSED( face   );
382    FT_UNUSED( stream );
383
384    return TT_Err_Ok;
385
386#endif
387  }
388
389
390  /*************************************************************************/
391  /*                                                                       */
392  /* <Function>                                                            */
393  /*    tt_face_load_hdmx                                                  */
394  /*                                                                       */
395  /* <Description>                                                         */
396  /*    Load the `hdmx' table into the face object.                        */
397  /*                                                                       */
398  /* <Input>                                                               */
399  /*    face   :: A handle to the target face object.                      */
400  /*                                                                       */
401  /*    stream :: A handle to the input stream.                            */
402  /*                                                                       */
403  /* <Return>                                                              */
404  /*    FreeType error code.  0 means success.                             */
405  /*                                                                       */
406
407  FT_LOCAL_DEF( FT_Error )
408  tt_face_load_hdmx( TT_Face    face,
409                     FT_Stream  stream )
410  {
411    FT_Error   error;
412    FT_Memory  memory = stream->memory;
413    FT_UInt    version, nn, num_records;
414    FT_ULong   table_size, record_size;
415    FT_Byte*   p;
416    FT_Byte*   limit;
417
418
419    /* this table is optional */
420    error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
421    if ( error || table_size < 8 )
422      return TT_Err_Ok;
423
424    if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
425      goto Exit;
426
427    p     = face->hdmx_table;
428    limit = p + table_size;
429
430    version     = FT_NEXT_USHORT( p );
431    num_records = FT_NEXT_USHORT( p );
432    record_size = FT_NEXT_ULONG( p );
433
434    /* The maximum number of bytes in an hdmx device record is the */
435    /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
436    /* the reason why `record_size' is a long (which we read as    */
437    /* unsigned long for convenience).  In practice, two bytes     */
438    /* sufficient to hold the size value.                          */
439    /*                                                             */
440    /* There are at least two fonts, HANNOM-A and HANNOM-B version */
441    /* 2.0 (2005), which get this wrong: The upper two bytes of    */
442    /* the size value are set to 0xFF instead of 0x00.  We catch   */
443    /* and fix this.                                               */
444
445    if ( record_size >= 0xFFFF0000UL )
446      record_size &= 0xFFFFU;
447
448    /* The limit for `num_records' is a heuristic value. */
449
450    if ( version != 0 || num_records > 255 || record_size > 0x10001L )
451    {
452      error = TT_Err_Invalid_File_Format;
453      goto Fail;
454    }
455
456    if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
457      goto Fail;
458
459    for ( nn = 0; nn < num_records; nn++ )
460    {
461      if ( p + record_size > limit )
462        break;
463
464      face->hdmx_record_sizes[nn] = p[0];
465      p                          += record_size;
466    }
467
468    face->hdmx_record_count = nn;
469    face->hdmx_table_size   = table_size;
470    face->hdmx_record_size  = record_size;
471
472  Exit:
473    return error;
474
475  Fail:
476    FT_FRAME_RELEASE( face->hdmx_table );
477    face->hdmx_table_size = 0;
478    goto Exit;
479  }
480
481
482  FT_LOCAL_DEF( void )
483  tt_face_free_hdmx( TT_Face  face )
484  {
485    FT_Stream  stream = face->root.stream;
486    FT_Memory  memory = stream->memory;
487
488
489    FT_FREE( face->hdmx_record_sizes );
490    FT_FRAME_RELEASE( face->hdmx_table );
491  }
492
493
494  /*************************************************************************/
495  /*                                                                       */
496  /* Return the advance width table for a given pixel size if it is found  */
497  /* in the font's `hdmx' table (if any).                                  */
498  /*                                                                       */
499  FT_LOCAL_DEF( FT_Byte* )
500  tt_face_get_device_metrics( TT_Face  face,
501                              FT_UInt  ppem,
502                              FT_UInt  gindex )
503  {
504    FT_UInt   nn;
505    FT_Byte*  result      = NULL;
506    FT_ULong  record_size = face->hdmx_record_size;
507    FT_Byte*  record      = face->hdmx_table + 8;
508
509
510    for ( nn = 0; nn < face->hdmx_record_count; nn++ )
511      if ( face->hdmx_record_sizes[nn] == ppem )
512      {
513        gindex += 2;
514        if ( gindex < record_size )
515          result = record + nn * record_size + gindex;
516        break;
517      }
518
519    return result;
520  }
521
522
523/* END */
Note: See TracBrowser for help on using the repository browser.