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