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