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