~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/truetype/ttpload.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

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