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