source: trunk/poppler/freetype2/src/truetype/ttpload.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

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