1/***************************************************************************/
2/*                                                                         */
3/*  ttobjs.c                                                               */
4/*                                                                         */
5/*    Objects manager (body).                                              */
6/*                                                                         */
7/*  Copyright 1996-2013                                                    */
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_STREAM_H
22#include FT_TRUETYPE_TAGS_H
23#include FT_INTERNAL_SFNT_H
24#include FT_TRUETYPE_DRIVER_H
25
26#include "ttgload.h"
27#include "ttpload.h"
28
29#include "tterrors.h"
30
31#ifdef TT_USE_BYTECODE_INTERPRETER
32#include "ttinterp.h"
33#endif
34
35#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
36#include FT_TRUETYPE_UNPATENTED_H
37#endif
38
39#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
40#include "ttgxvar.h"
41#endif
42
43  /*************************************************************************/
44  /*                                                                       */
45  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
46  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
47  /* messages during execution.                                            */
48  /*                                                                       */
49#undef  FT_COMPONENT
50#define FT_COMPONENT  trace_ttobjs
51
52
53#ifdef TT_USE_BYTECODE_INTERPRETER
54
55  /*************************************************************************/
56  /*                                                                       */
57  /*                       GLYPH ZONE FUNCTIONS                            */
58  /*                                                                       */
59  /*************************************************************************/
60
61
62  /*************************************************************************/
63  /*                                                                       */
64  /* <Function>                                                            */
65  /*    tt_glyphzone_done                                                  */
66  /*                                                                       */
67  /* <Description>                                                         */
68  /*    Deallocate a glyph zone.                                           */
69  /*                                                                       */
70  /* <Input>                                                               */
71  /*    zone :: A pointer to the target glyph zone.                        */
72  /*                                                                       */
73  FT_LOCAL_DEF( void )
74  tt_glyphzone_done( TT_GlyphZone  zone )
75  {
76    FT_Memory  memory = zone->memory;
77
78
79    if ( memory )
80    {
81      FT_FREE( zone->contours );
82      FT_FREE( zone->tags );
83      FT_FREE( zone->cur );
84      FT_FREE( zone->org );
85      FT_FREE( zone->orus );
86
87      zone->max_points   = zone->n_points   = 0;
88      zone->max_contours = zone->n_contours = 0;
89      zone->memory       = NULL;
90    }
91  }
92
93
94  /*************************************************************************/
95  /*                                                                       */
96  /* <Function>                                                            */
97  /*    tt_glyphzone_new                                                   */
98  /*                                                                       */
99  /* <Description>                                                         */
100  /*    Allocate a new glyph zone.                                         */
101  /*                                                                       */
102  /* <Input>                                                               */
103  /*    memory      :: A handle to the current memory object.              */
104  /*                                                                       */
105  /*    maxPoints   :: The capacity of glyph zone in points.               */
106  /*                                                                       */
107  /*    maxContours :: The capacity of glyph zone in contours.             */
108  /*                                                                       */
109  /* <Output>                                                              */
110  /*    zone        :: A pointer to the target glyph zone record.          */
111  /*                                                                       */
112  /* <Return>                                                              */
113  /*    FreeType error code.  0 means success.                             */
114  /*                                                                       */
115  FT_LOCAL_DEF( FT_Error )
116  tt_glyphzone_new( FT_Memory     memory,
117                    FT_UShort     maxPoints,
118                    FT_Short      maxContours,
119                    TT_GlyphZone  zone )
120  {
121    FT_Error  error;
122
123
124    FT_MEM_ZERO( zone, sizeof ( *zone ) );
125    zone->memory = memory;
126
127    if ( FT_NEW_ARRAY( zone->org,      maxPoints   ) ||
128         FT_NEW_ARRAY( zone->cur,      maxPoints   ) ||
129         FT_NEW_ARRAY( zone->orus,     maxPoints   ) ||
130         FT_NEW_ARRAY( zone->tags,     maxPoints   ) ||
131         FT_NEW_ARRAY( zone->contours, maxContours ) )
132    {
133      tt_glyphzone_done( zone );
134    }
135    else
136    {
137      zone->max_points   = maxPoints;
138      zone->max_contours = maxContours;
139    }
140
141    return error;
142  }
143#endif /* TT_USE_BYTECODE_INTERPRETER */
144
145
146  /* Compare the face with a list of well-known `tricky' fonts. */
147  /* This list shall be expanded as we find more of them.       */
148
149  static FT_Bool
150  tt_check_trickyness_family( FT_String*  name )
151  {
152
153#define TRICK_NAMES_MAX_CHARACTERS  19
154#define TRICK_NAMES_COUNT            9
155
156    static const char trick_names[TRICK_NAMES_COUNT]
157                                 [TRICK_NAMES_MAX_CHARACTERS + 1] =
158    {
159      "DFKaiSho-SB",        /* dfkaisb.ttf */
160      "DFKaiShu",
161      "DFKai-SB",           /* kaiu.ttf */
162      "HuaTianKaiTi?",      /* htkt2.ttf */
163      "HuaTianSongTi?",     /* htst3.ttf */
164      "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */
165      "MingLiU",            /* mingliu.ttf & mingliu.ttc */
166      "PMingLiU",           /* mingliu.ttc */
167      "MingLi43",           /* mingli.ttf */
168    };
169
170    int  nn;
171
172
173    for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
174      if ( ft_strstr( name, trick_names[nn] ) )
175        return TRUE;
176
177    return FALSE;
178  }
179
180
181  /* XXX: This function should be in the `sfnt' module. */
182
183  /* Some PDF generators clear the checksums in the TrueType header table. */
184  /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF     */
185  /* Printer clears the entries for subsetted subtables.  We thus have to  */
186  /* recalculate the checksums  where necessary.                           */
187
188  static FT_UInt32
189  tt_synth_sfnt_checksum( FT_Stream  stream,
190                          FT_ULong   length )
191  {
192    FT_Error   error;
193    FT_UInt32  checksum = 0;
194    int        i;
195
196
197    if ( FT_FRAME_ENTER( length ) )
198      return 0;
199
200    for ( ; length > 3; length -= 4 )
201      checksum += (FT_UInt32)FT_GET_ULONG();
202
203    for ( i = 3; length > 0; length --, i-- )
204      checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
205
206    FT_FRAME_EXIT();
207
208    return checksum;
209  }
210
211
212  /* XXX: This function should be in the `sfnt' module. */
213
214  static FT_ULong
215  tt_get_sfnt_checksum( TT_Face    face,
216                        FT_UShort  i )
217  {
218#if 0 /* if we believe the written value, use following part. */
219    if ( face->dir_tables[i].CheckSum )
220      return face->dir_tables[i].CheckSum;
221#endif
222
223    if ( !face->goto_table )
224      return 0;
225
226    if ( face->goto_table( face,
227                           face->dir_tables[i].Tag,
228                           face->root.stream,
229                           NULL ) )
230      return 0;
231
232    return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
233                                             face->dir_tables[i].Length );
234  }
235
236
237  typedef struct tt_sfnt_id_rec_
238  {
239    FT_ULong  CheckSum;
240    FT_ULong  Length;
241
242  } tt_sfnt_id_rec;
243
244
245  static FT_Bool
246  tt_check_trickyness_sfnt_ids( TT_Face  face )
247  {
248#define TRICK_SFNT_IDS_PER_FACE   3
249#define TRICK_SFNT_IDS_NUM_FACES  17
250
251    static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
252                                       [TRICK_SFNT_IDS_PER_FACE] = {
253
254#define TRICK_SFNT_ID_cvt   0
255#define TRICK_SFNT_ID_fpgm  1
256#define TRICK_SFNT_ID_prep  2
257
258      { /* MingLiU 1995 */
259        { 0x05bcf058, 0x000002e4 }, /* cvt  */
260        { 0x28233bf1, 0x000087c4 }, /* fpgm */
261        { 0xa344a1ea, 0x000001e1 }  /* prep */
262      },
263      { /* MingLiU 1996- */
264        { 0x05bcf058, 0x000002e4 }, /* cvt  */
265        { 0x28233bf1, 0x000087c4 }, /* fpgm */
266        { 0xa344a1eb, 0x000001e1 }  /* prep */
267      },
268      { /* DFKaiShu */
269        { 0x11e5ead4, 0x00000350 }, /* cvt  */
270        { 0x5a30ca3b, 0x00009063 }, /* fpgm */
271        { 0x13a42602, 0x0000007e }  /* prep */
272      },
273      { /* HuaTianKaiTi */
274        { 0xfffbfffc, 0x00000008 }, /* cvt  */
275        { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
276        { 0x70020112, 0x00000008 }  /* prep */
277      },
278      { /* HuaTianSongTi */
279        { 0xfffbfffc, 0x00000008 }, /* cvt  */
280        { 0x0a5a0483, 0x00017c39 }, /* fpgm */
281        { 0x70020112, 0x00000008 }  /* prep */
282      },
283      { /* NEC fadpop7.ttf */
284        { 0x00000000, 0x00000000 }, /* cvt  */
285        { 0x40c92555, 0x000000e5 }, /* fpgm */
286        { 0xa39b58e3, 0x0000117c }  /* prep */
287      },
288      { /* NEC fadrei5.ttf */
289        { 0x00000000, 0x00000000 }, /* cvt  */
290        { 0x33c41652, 0x000000e5 }, /* fpgm */
291        { 0x26d6c52a, 0x00000f6a }  /* prep */
292      },
293      { /* NEC fangot7.ttf */
294        { 0x00000000, 0x00000000 }, /* cvt  */
295        { 0x6db1651d, 0x0000019d }, /* fpgm */
296        { 0x6c6e4b03, 0x00002492 }  /* prep */
297      },
298      { /* NEC fangyo5.ttf */
299        { 0x00000000, 0x00000000 }, /* cvt  */
300        { 0x40c92555, 0x000000e5 }, /* fpgm */
301        { 0xde51fad0, 0x0000117c }  /* prep */
302      },
303      { /* NEC fankyo5.ttf */
304        { 0x00000000, 0x00000000 }, /* cvt  */
305        { 0x85e47664, 0x000000e5 }, /* fpgm */
306        { 0xa6c62831, 0x00001caa }  /* prep */
307      },
308      { /* NEC fanrgo5.ttf */
309        { 0x00000000, 0x00000000 }, /* cvt  */
310        { 0x2d891cfd, 0x0000019d }, /* fpgm */
311        { 0xa0604633, 0x00001de8 }  /* prep */
312      },
313      { /* NEC fangot5.ttc */
314        { 0x00000000, 0x00000000 }, /* cvt  */
315        { 0x40aa774c, 0x000001cb }, /* fpgm */
316        { 0x9b5caa96, 0x00001f9a }  /* prep */
317      },
318      { /* NEC fanmin3.ttc */
319        { 0x00000000, 0x00000000 }, /* cvt  */
320        { 0x0d3de9cb, 0x00000141 }, /* fpgm */
321        { 0xd4127766, 0x00002280 }  /* prep */
322      },
323      { /* NEC FA-Gothic, 1996 */
324        { 0x00000000, 0x00000000 }, /* cvt  */
325        { 0x4a692698, 0x000001f0 }, /* fpgm */
326        { 0x340d4346, 0x00001fca }  /* prep */
327      },
328      { /* NEC FA-Minchou, 1996 */
329        { 0x00000000, 0x00000000 }, /* cvt  */
330        { 0xcd34c604, 0x00000166 }, /* fpgm */
331        { 0x6cf31046, 0x000022b0 }  /* prep */
332      },
333      { /* NEC FA-RoundGothicB, 1996 */
334        { 0x00000000, 0x00000000 }, /* cvt  */
335        { 0x5da75315, 0x0000019d }, /* fpgm */
336        { 0x40745a5f, 0x000022e0 }  /* prep */
337      },
338      { /* NEC FA-RoundGothicM, 1996 */
339        { 0x00000000, 0x00000000 }, /* cvt  */
340        { 0xf055fc48, 0x000001c2 }, /* fpgm */
341        { 0x3900ded3, 0x00001e18 }  /* prep */
342      }
343    };
344
345    FT_ULong   checksum;
346    int        num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
347    FT_Bool    has_cvt, has_fpgm, has_prep;
348    FT_UShort  i;
349    int        j, k;
350
351
352    FT_MEM_SET( num_matched_ids, 0,
353                sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES );
354    has_cvt  = FALSE;
355    has_fpgm = FALSE;
356    has_prep = FALSE;
357
358    for ( i = 0; i < face->num_tables; i++ )
359    {
360      checksum = 0;
361
362      switch( face->dir_tables[i].Tag )
363      {
364      case TTAG_cvt:
365        k = TRICK_SFNT_ID_cvt;
366        has_cvt  = TRUE;
367        break;
368
369      case TTAG_fpgm:
370        k = TRICK_SFNT_ID_fpgm;
371        has_fpgm = TRUE;
372        break;
373
374      case TTAG_prep:
375        k = TRICK_SFNT_ID_prep;
376        has_prep = TRUE;
377        break;
378
379      default:
380        continue;
381      }
382
383      for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
384        if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
385        {
386          if ( !checksum )
387            checksum = tt_get_sfnt_checksum( face, i );
388
389          if ( sfnt_id[j][k].CheckSum == checksum )
390            num_matched_ids[j]++;
391
392          if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
393            return TRUE;
394        }
395    }
396
397    for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
398    {
399      if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
400        num_matched_ids[j] ++;
401      if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
402        num_matched_ids[j] ++;
403      if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
404        num_matched_ids[j] ++;
405      if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
406        return TRUE;
407    }
408
409    return FALSE;
410  }
411
412
413  static FT_Bool
414  tt_check_trickyness( FT_Face  face )
415  {
416    if ( !face )
417      return FALSE;
418
419    /* For first, check the face name for quick check. */
420    if ( face->family_name                               &&
421         tt_check_trickyness_family( face->family_name ) )
422      return TRUE;
423
424    /* Type42 fonts may lack `name' tables, we thus try to identify */
425    /* tricky fonts by checking the checksums of Type42-persistent  */
426    /* sfnt tables (`cvt', `fpgm', and `prep').                     */
427    if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
428      return TRUE;
429
430    return FALSE;
431  }
432
433
434  /* Check whether `.notdef' is the only glyph in the `loca' table. */
435  static FT_Bool
436  tt_check_single_notdef( FT_Face  ttface )
437  {
438    FT_Bool   result = FALSE;
439
440    TT_Face   face = (TT_Face)ttface;
441    FT_UInt   asize;
442    FT_ULong  i;
443    FT_ULong  glyph_index = 0;
444    FT_UInt   count       = 0;
445
446
447    for( i = 0; i < face->num_locations; i++ )
448    {
449      tt_face_get_location( face, i, &asize );
450      if ( asize > 0 )
451      {
452        count += 1;
453        if ( count > 1 )
454          break;
455        glyph_index = i;
456      }
457    }
458
459    /* Only have a single outline. */
460    if ( count == 1 )
461    {
462      if ( glyph_index == 0 )
463        result = TRUE;
464      else
465      {
466        /* FIXME: Need to test glyphname == .notdef ? */
467        FT_Error error;
468        char buf[8];
469
470
471        error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
472        if ( !error                                            &&
473             buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
474          result = TRUE;
475      }
476    }
477
478    return result;
479  }
480
481
482  /*************************************************************************/
483  /*                                                                       */
484  /* <Function>                                                            */
485  /*    tt_face_init                                                       */
486  /*                                                                       */
487  /* <Description>                                                         */
488  /*    Initialize a given TrueType face object.                           */
489  /*                                                                       */
490  /* <Input>                                                               */
491  /*    stream     :: The source font stream.                              */
492  /*                                                                       */
493  /*    face_index :: The index of the font face in the resource.          */
494  /*                                                                       */
495  /*    num_params :: Number of additional generic parameters.  Ignored.   */
496  /*                                                                       */
497  /*    params     :: Additional generic parameters.  Ignored.             */
498  /*                                                                       */
499  /* <InOut>                                                               */
500  /*    face       :: The newly built face object.                         */
501  /*                                                                       */
502  /* <Return>                                                              */
503  /*    FreeType error code.  0 means success.                             */
504  /*                                                                       */
505  FT_LOCAL_DEF( FT_Error )
506  tt_face_init( FT_Stream      stream,
507                FT_Face        ttface,      /* TT_Face */
508                FT_Int         face_index,
509                FT_Int         num_params,
510                FT_Parameter*  params )
511  {
512    FT_Error      error;
513    FT_Library    library;
514    SFNT_Service  sfnt;
515    TT_Face       face = (TT_Face)ttface;
516
517
518    FT_TRACE2(( "TTF driver\n" ));
519
520    library = ttface->driver->root.library;
521
522    sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
523    if ( !sfnt )
524    {
525      FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
526      error = FT_THROW( Missing_Module );
527      goto Exit;
528    }
529
530    /* create input stream from resource */
531    if ( FT_STREAM_SEEK( 0 ) )
532      goto Exit;
533
534    /* check that we have a valid TrueType file */
535    error = sfnt->init_face( stream, face, face_index, num_params, params );
536
537    /* Stream may have changed. */
538    stream = face->root.stream;
539
540    if ( error )
541      goto Exit;
542
543    /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
544    /* The 0x00020000 tag is completely undocumented; some fonts from   */
545    /* Arphic made for Chinese Windows 3.1 have this.                   */
546    if ( face->format_tag != 0x00010000L &&    /* MS fonts  */
547         face->format_tag != 0x00020000L &&    /* CJK fonts for Win 3.1 */
548         face->format_tag != TTAG_true   )     /* Mac fonts */
549    {
550      FT_TRACE2(( "  not a TTF font\n" ));
551      goto Bad_Format;
552    }
553
554#ifdef TT_USE_BYTECODE_INTERPRETER
555    ttface->face_flags |= FT_FACE_FLAG_HINTER;
556#endif
557
558    /* If we are performing a simple font format check, exit immediately. */
559    if ( face_index < 0 )
560      return FT_Err_Ok;
561
562    /* Load font directory */
563    error = sfnt->load_face( stream, face, face_index, num_params, params );
564    if ( error )
565      goto Exit;
566
567    if ( tt_check_trickyness( ttface ) )
568      ttface->face_flags |= FT_FACE_FLAG_TRICKY;
569
570    error = tt_face_load_hdmx( face, stream );
571    if ( error )
572      goto Exit;
573
574    if ( FT_IS_SCALABLE( ttface ) )
575    {
576
577#ifdef FT_CONFIG_OPTION_INCREMENTAL
578
579      if ( !ttface->internal->incremental_interface )
580        error = tt_face_load_loca( face, stream );
581      if ( !error )
582        error = tt_face_load_cvt( face, stream );
583      if ( !error )
584        error = tt_face_load_fpgm( face, stream );
585      if ( !error )
586        error = tt_face_load_prep( face, stream );
587
588      /* Check the scalable flag based on `loca'. */
589      if ( !ttface->internal->incremental_interface &&
590           ttface->num_fixed_sizes                  &&
591           face->glyph_locations                    &&
592           tt_check_single_notdef( ttface )         )
593      {
594        FT_TRACE5(( "tt_face_init:"
595                    " Only the `.notdef' glyph has an outline.\n"
596                    "             "
597                    " Resetting scalable flag to FALSE.\n" ));
598
599        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
600      }
601
602#else
603
604      if ( !error )
605        error = tt_face_load_loca( face, stream );
606      if ( !error )
607        error = tt_face_load_cvt( face, stream );
608      if ( !error )
609        error = tt_face_load_fpgm( face, stream );
610      if ( !error )
611        error = tt_face_load_prep( face, stream );
612
613      /* Check the scalable flag based on `loca'. */
614      if ( ttface->num_fixed_sizes          &&
615           face->glyph_locations            &&
616           tt_check_single_notdef( ttface ) )
617      {
618        FT_TRACE5(( "tt_face_init:"
619                    " Only the `.notdef' glyph has an outline.\n"
620                    "             "
621                    " Resetting scalable flag to FALSE.\n" ));
622
623        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
624      }
625
626#endif
627
628    }
629
630#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING    ) && \
631    !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
632
633    {
634      FT_Bool  unpatented_hinting;
635      int      i;
636
637
638      /* Determine whether unpatented hinting is to be used for this face. */
639      unpatented_hinting = FT_BOOL
640        ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL );
641
642      for ( i = 0; i < num_params && !face->unpatented_hinting; i++ )
643        if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )
644          unpatented_hinting = TRUE;
645
646      if ( !unpatented_hinting )
647        ttface->internal->ignore_unpatented_hinter = TRUE;
648    }
649
650#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
651          !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
652
653    /* initialize standard glyph loading routines */
654    TT_Init_Glyph_Loading( face );
655
656  Exit:
657    return error;
658
659  Bad_Format:
660    error = FT_THROW( Unknown_File_Format );
661    goto Exit;
662  }
663
664
665  /*************************************************************************/
666  /*                                                                       */
667  /* <Function>                                                            */
668  /*    tt_face_done                                                       */
669  /*                                                                       */
670  /* <Description>                                                         */
671  /*    Finalize a given face object.                                      */
672  /*                                                                       */
673  /* <Input>                                                               */
674  /*    face :: A pointer to the face object to destroy.                   */
675  /*                                                                       */
676  FT_LOCAL_DEF( void )
677  tt_face_done( FT_Face  ttface )           /* TT_Face */
678  {
679    TT_Face       face = (TT_Face)ttface;
680    FT_Memory     memory;
681    FT_Stream     stream;
682    SFNT_Service  sfnt;
683
684
685    if ( !face )
686      return;
687
688    memory = ttface->memory;
689    stream = ttface->stream;
690    sfnt   = (SFNT_Service)face->sfnt;
691
692    /* for `extended TrueType formats' (i.e. compressed versions) */
693    if ( face->extra.finalizer )
694      face->extra.finalizer( face->extra.data );
695
696    if ( sfnt )
697      sfnt->done_face( face );
698
699    /* freeing the locations table */
700    tt_face_done_loca( face );
701
702    tt_face_free_hdmx( face );
703
704    /* freeing the CVT */
705    FT_FREE( face->cvt );
706    face->cvt_size = 0;
707
708    /* freeing the programs */
709    FT_FRAME_RELEASE( face->font_program );
710    FT_FRAME_RELEASE( face->cvt_program );
711    face->font_program_size = 0;
712    face->cvt_program_size  = 0;
713
714#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
715    tt_done_blend( memory, face->blend );
716    face->blend = NULL;
717#endif
718  }
719
720
721  /*************************************************************************/
722  /*                                                                       */
723  /*                           SIZE  FUNCTIONS                             */
724  /*                                                                       */
725  /*************************************************************************/
726
727#ifdef TT_USE_BYTECODE_INTERPRETER
728
729  /*************************************************************************/
730  /*                                                                       */
731  /* <Function>                                                            */
732  /*    tt_size_run_fpgm                                                   */
733  /*                                                                       */
734  /* <Description>                                                         */
735  /*    Run the font program.                                              */
736  /*                                                                       */
737  /* <Input>                                                               */
738  /*    size     :: A handle to the size object.                           */
739  /*                                                                       */
740  /*    pedantic :: Set if bytecode execution should be pedantic.          */
741  /*                                                                       */
742  /* <Return>                                                              */
743  /*    FreeType error code.  0 means success.                             */
744  /*                                                                       */
745  FT_LOCAL_DEF( FT_Error )
746  tt_size_run_fpgm( TT_Size  size,
747                    FT_Bool  pedantic )
748  {
749    TT_Face         face = (TT_Face)size->root.face;
750    TT_ExecContext  exec;
751    FT_Error        error;
752
753
754    /* debugging instances have their own context */
755    if ( size->debug )
756      exec = size->context;
757    else
758      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
759
760    if ( !exec )
761      return FT_THROW( Could_Not_Find_Context );
762
763    TT_Load_Context( exec, face, size );
764
765    exec->callTop = 0;
766    exec->top     = 0;
767
768    exec->period    = 64;
769    exec->phase     = 0;
770    exec->threshold = 0;
771
772    exec->instruction_trap = FALSE;
773    exec->F_dot_P          = 0x4000L;
774
775    exec->pedantic_hinting = pedantic;
776
777    {
778      FT_Size_Metrics*  metrics    = &exec->metrics;
779      TT_Size_Metrics*  tt_metrics = &exec->tt_metrics;
780
781
782      metrics->x_ppem   = 0;
783      metrics->y_ppem   = 0;
784      metrics->x_scale  = 0;
785      metrics->y_scale  = 0;
786
787      tt_metrics->ppem  = 0;
788      tt_metrics->scale = 0;
789      tt_metrics->ratio = 0x10000L;
790    }
791
792    /* allow font program execution */
793    TT_Set_CodeRange( exec,
794                      tt_coderange_font,
795                      face->font_program,
796                      face->font_program_size );
797
798    /* disable CVT and glyph programs coderange */
799    TT_Clear_CodeRange( exec, tt_coderange_cvt );
800    TT_Clear_CodeRange( exec, tt_coderange_glyph );
801
802    if ( face->font_program_size > 0 )
803    {
804      error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
805
806      if ( !error )
807      {
808        FT_TRACE4(( "Executing `fpgm' table.\n" ));
809
810        error = face->interpreter( exec );
811      }
812    }
813    else
814      error = FT_Err_Ok;
815
816    size->bytecode_ready = error;
817
818    if ( !error )
819      TT_Save_Context( exec, size );
820
821    return error;
822  }
823
824
825  /*************************************************************************/
826  /*                                                                       */
827  /* <Function>                                                            */
828  /*    tt_size_run_prep                                                   */
829  /*                                                                       */
830  /* <Description>                                                         */
831  /*    Run the control value program.                                     */
832  /*                                                                       */
833  /* <Input>                                                               */
834  /*    size     :: A handle to the size object.                           */
835  /*                                                                       */
836  /*    pedantic :: Set if bytecode execution should be pedantic.          */
837  /*                                                                       */
838  /* <Return>                                                              */
839  /*    FreeType error code.  0 means success.                             */
840  /*                                                                       */
841  FT_LOCAL_DEF( FT_Error )
842  tt_size_run_prep( TT_Size  size,
843                    FT_Bool  pedantic )
844  {
845    TT_Face         face = (TT_Face)size->root.face;
846    TT_ExecContext  exec;
847    FT_Error        error;
848
849
850    /* debugging instances have their own context */
851    if ( size->debug )
852      exec = size->context;
853    else
854      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
855
856    if ( !exec )
857      return FT_THROW( Could_Not_Find_Context );
858
859    TT_Load_Context( exec, face, size );
860
861    exec->callTop = 0;
862    exec->top     = 0;
863
864    exec->instruction_trap = FALSE;
865
866    exec->pedantic_hinting = pedantic;
867
868    TT_Set_CodeRange( exec,
869                      tt_coderange_cvt,
870                      face->cvt_program,
871                      face->cvt_program_size );
872
873    TT_Clear_CodeRange( exec, tt_coderange_glyph );
874
875    if ( face->cvt_program_size > 0 )
876    {
877      error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
878
879      if ( !error && !size->debug )
880      {
881        FT_TRACE4(( "Executing `prep' table.\n" ));
882
883        error = face->interpreter( exec );
884      }
885    }
886    else
887      error = FT_Err_Ok;
888
889    size->cvt_ready = error;
890
891    /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
892    /* graphics state variables to be modified by the CVT program.  */
893
894    exec->GS.dualVector.x = 0x4000;
895    exec->GS.dualVector.y = 0;
896    exec->GS.projVector.x = 0x4000;
897    exec->GS.projVector.y = 0x0;
898    exec->GS.freeVector.x = 0x4000;
899    exec->GS.freeVector.y = 0x0;
900
901    exec->GS.rp0 = 0;
902    exec->GS.rp1 = 0;
903    exec->GS.rp2 = 0;
904
905    exec->GS.gep0 = 1;
906    exec->GS.gep1 = 1;
907    exec->GS.gep2 = 1;
908
909    exec->GS.loop = 1;
910
911    /* save as default graphics state */
912    size->GS = exec->GS;
913
914    TT_Save_Context( exec, size );
915
916    return error;
917  }
918
919
920  static void
921  tt_size_done_bytecode( FT_Size  ftsize )
922  {
923    TT_Size    size   = (TT_Size)ftsize;
924    TT_Face    face   = (TT_Face)ftsize->face;
925    FT_Memory  memory = face->root.memory;
926
927
928    if ( size->debug )
929    {
930      /* the debug context must be deleted by the debugger itself */
931      size->context = NULL;
932      size->debug   = FALSE;
933    }
934
935    FT_FREE( size->cvt );
936    size->cvt_size = 0;
937
938    /* free storage area */
939    FT_FREE( size->storage );
940    size->storage_size = 0;
941
942    /* twilight zone */
943    tt_glyphzone_done( &size->twilight );
944
945    FT_FREE( size->function_defs );
946    FT_FREE( size->instruction_defs );
947
948    size->num_function_defs    = 0;
949    size->max_function_defs    = 0;
950    size->num_instruction_defs = 0;
951    size->max_instruction_defs = 0;
952
953    size->max_func = 0;
954    size->max_ins  = 0;
955
956    size->bytecode_ready = -1;
957    size->cvt_ready      = -1;
958  }
959
960
961  /* Initialize bytecode-related fields in the size object.       */
962  /* We do this only if bytecode interpretation is really needed. */
963  static FT_Error
964  tt_size_init_bytecode( FT_Size  ftsize,
965                         FT_Bool  pedantic )
966  {
967    FT_Error   error;
968    TT_Size    size = (TT_Size)ftsize;
969    TT_Face    face = (TT_Face)ftsize->face;
970    FT_Memory  memory = face->root.memory;
971    FT_Int     i;
972
973    FT_UShort       n_twilight;
974    TT_MaxProfile*  maxp = &face->max_profile;
975
976
977    size->bytecode_ready = -1;
978    size->cvt_ready      = -1;
979
980    size->max_function_defs    = maxp->maxFunctionDefs;
981    size->max_instruction_defs = maxp->maxInstructionDefs;
982
983    size->num_function_defs    = 0;
984    size->num_instruction_defs = 0;
985
986    size->max_func = 0;
987    size->max_ins  = 0;
988
989    size->cvt_size     = face->cvt_size;
990    size->storage_size = maxp->maxStorage;
991
992    /* Set default metrics */
993    {
994      TT_Size_Metrics*  metrics = &size->ttmetrics;
995
996
997      metrics->rotated   = FALSE;
998      metrics->stretched = FALSE;
999
1000      /* set default compensation (all 0) */
1001      for ( i = 0; i < 4; i++ )
1002        metrics->compensations[i] = 0;
1003    }
1004
1005    /* allocate function defs, instruction defs, cvt, and storage area */
1006    if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
1007         FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1008         FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
1009         FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
1010      goto Exit;
1011
1012    /* reserve twilight zone */
1013    n_twilight = maxp->maxTwilightPoints;
1014
1015    /* there are 4 phantom points (do we need this?) */
1016    n_twilight += 4;
1017
1018    error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1019    if ( error )
1020      goto Exit;
1021
1022    size->twilight.n_points = n_twilight;
1023
1024    size->GS = tt_default_graphics_state;
1025
1026    /* set `face->interpreter' according to the debug hook present */
1027    {
1028      FT_Library  library = face->root.driver->root.library;
1029
1030
1031      face->interpreter = (TT_Interpreter)
1032                            library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1033      if ( !face->interpreter )
1034        face->interpreter = (TT_Interpreter)TT_RunIns;
1035    }
1036
1037    /* Fine, now run the font program! */
1038    error = tt_size_run_fpgm( size, pedantic );
1039
1040  Exit:
1041    if ( error )
1042      tt_size_done_bytecode( ftsize );
1043
1044    return error;
1045  }
1046
1047
1048  FT_LOCAL_DEF( FT_Error )
1049  tt_size_ready_bytecode( TT_Size  size,
1050                          FT_Bool  pedantic )
1051  {
1052    FT_Error  error = FT_Err_Ok;
1053
1054
1055    if ( size->bytecode_ready < 0 )
1056      error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1057
1058    if ( error || size->bytecode_ready )
1059      goto Exit;
1060
1061    /* rescale CVT when needed */
1062    if ( size->cvt_ready < 0 )
1063    {
1064      FT_UInt  i;
1065      TT_Face  face = (TT_Face)size->root.face;
1066
1067
1068      /* Scale the cvt values to the new ppem.          */
1069      /* We use by default the y ppem to scale the CVT. */
1070      for ( i = 0; i < size->cvt_size; i++ )
1071        size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1072
1073      /* all twilight points are originally zero */
1074      for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
1075      {
1076        size->twilight.org[i].x = 0;
1077        size->twilight.org[i].y = 0;
1078        size->twilight.cur[i].x = 0;
1079        size->twilight.cur[i].y = 0;
1080      }
1081
1082      /* clear storage area */
1083      for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
1084        size->storage[i] = 0;
1085
1086      size->GS = tt_default_graphics_state;
1087
1088      error = tt_size_run_prep( size, pedantic );
1089    }
1090
1091  Exit:
1092    return error;
1093  }
1094
1095#endif /* TT_USE_BYTECODE_INTERPRETER */
1096
1097
1098  /*************************************************************************/
1099  /*                                                                       */
1100  /* <Function>                                                            */
1101  /*    tt_size_init                                                       */
1102  /*                                                                       */
1103  /* <Description>                                                         */
1104  /*    Initialize a new TrueType size object.                             */
1105  /*                                                                       */
1106  /* <InOut>                                                               */
1107  /*    size :: A handle to the size object.                               */
1108  /*                                                                       */
1109  /* <Return>                                                              */
1110  /*    FreeType error code.  0 means success.                             */
1111  /*                                                                       */
1112  FT_LOCAL_DEF( FT_Error )
1113  tt_size_init( FT_Size  ttsize )           /* TT_Size */
1114  {
1115    TT_Size   size  = (TT_Size)ttsize;
1116    FT_Error  error = FT_Err_Ok;
1117
1118#ifdef TT_USE_BYTECODE_INTERPRETER
1119    size->bytecode_ready = -1;
1120    size->cvt_ready      = -1;
1121#endif
1122
1123    size->ttmetrics.valid = FALSE;
1124    size->strike_index    = 0xFFFFFFFFUL;
1125
1126    return error;
1127  }
1128
1129
1130  /*************************************************************************/
1131  /*                                                                       */
1132  /* <Function>                                                            */
1133  /*    tt_size_done                                                       */
1134  /*                                                                       */
1135  /* <Description>                                                         */
1136  /*    The TrueType size object finalizer.                                */
1137  /*                                                                       */
1138  /* <Input>                                                               */
1139  /*    size :: A handle to the target size object.                        */
1140  /*                                                                       */
1141  FT_LOCAL_DEF( void )
1142  tt_size_done( FT_Size  ttsize )           /* TT_Size */
1143  {
1144    TT_Size  size = (TT_Size)ttsize;
1145
1146
1147#ifdef TT_USE_BYTECODE_INTERPRETER
1148    if ( size->bytecode_ready >= 0 )
1149      tt_size_done_bytecode( ttsize );
1150#endif
1151
1152    size->ttmetrics.valid = FALSE;
1153  }
1154
1155
1156  /*************************************************************************/
1157  /*                                                                       */
1158  /* <Function>                                                            */
1159  /*    tt_size_reset                                                      */
1160  /*                                                                       */
1161  /* <Description>                                                         */
1162  /*    Reset a TrueType size when resolutions and character dimensions    */
1163  /*    have been changed.                                                 */
1164  /*                                                                       */
1165  /* <Input>                                                               */
1166  /*    size :: A handle to the target size object.                        */
1167  /*                                                                       */
1168  FT_LOCAL_DEF( FT_Error )
1169  tt_size_reset( TT_Size  size )
1170  {
1171    TT_Face           face;
1172    FT_Error          error = FT_Err_Ok;
1173    FT_Size_Metrics*  metrics;
1174
1175
1176    size->ttmetrics.valid = FALSE;
1177
1178    face = (TT_Face)size->root.face;
1179
1180    metrics = &size->metrics;
1181
1182    /* copy the result from base layer */
1183    *metrics = size->root.metrics;
1184
1185    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
1186      return FT_THROW( Invalid_PPem );
1187
1188    /* This bit flag, if set, indicates that the ppems must be       */
1189    /* rounded to integers.  Nearly all TrueType fonts have this bit */
1190    /* set, as hinting won't work really well otherwise.             */
1191    /*                                                               */
1192    if ( face->header.Flags & 8 )
1193    {
1194      metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1195                                    face->root.units_per_EM );
1196      metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1197                                    face->root.units_per_EM );
1198
1199      metrics->ascender =
1200        FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );
1201      metrics->descender =
1202        FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );
1203      metrics->height =
1204        FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );
1205      metrics->max_advance =
1206        FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,
1207                                 metrics->x_scale ) );
1208    }
1209
1210    /* compute new transformation */
1211    if ( metrics->x_ppem >= metrics->y_ppem )
1212    {
1213      size->ttmetrics.scale   = metrics->x_scale;
1214      size->ttmetrics.ppem    = metrics->x_ppem;
1215      size->ttmetrics.x_ratio = 0x10000L;
1216      size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem,
1217                                           metrics->x_ppem );
1218    }
1219    else
1220    {
1221      size->ttmetrics.scale   = metrics->y_scale;
1222      size->ttmetrics.ppem    = metrics->y_ppem;
1223      size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem,
1224                                           metrics->y_ppem );
1225      size->ttmetrics.y_ratio = 0x10000L;
1226    }
1227
1228#ifdef TT_USE_BYTECODE_INTERPRETER
1229    size->cvt_ready = -1;
1230#endif /* TT_USE_BYTECODE_INTERPRETER */
1231
1232    if ( !error )
1233      size->ttmetrics.valid = TRUE;
1234
1235    return error;
1236  }
1237
1238
1239  /*************************************************************************/
1240  /*                                                                       */
1241  /* <Function>                                                            */
1242  /*    tt_driver_init                                                     */
1243  /*                                                                       */
1244  /* <Description>                                                         */
1245  /*    Initialize a given TrueType driver object.                         */
1246  /*                                                                       */
1247  /* <Input>                                                               */
1248  /*    driver :: A handle to the target driver object.                    */
1249  /*                                                                       */
1250  /* <Return>                                                              */
1251  /*    FreeType error code.  0 means success.                             */
1252  /*                                                                       */
1253  FT_LOCAL_DEF( FT_Error )
1254  tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
1255  {
1256
1257#ifdef TT_USE_BYTECODE_INTERPRETER
1258
1259    TT_Driver  driver = (TT_Driver)ttdriver;
1260
1261
1262    if ( !TT_New_Context( driver ) )
1263      return FT_THROW( Could_Not_Find_Context );
1264
1265#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1266    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1267#else
1268    driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1269#endif
1270
1271#else /* !TT_USE_BYTECODE_INTERPRETER */
1272
1273    FT_UNUSED( ttdriver );
1274
1275#endif /* !TT_USE_BYTECODE_INTERPRETER */
1276
1277    return FT_Err_Ok;
1278  }
1279
1280
1281  /*************************************************************************/
1282  /*                                                                       */
1283  /* <Function>                                                            */
1284  /*    tt_driver_done                                                     */
1285  /*                                                                       */
1286  /* <Description>                                                         */
1287  /*    Finalize a given TrueType driver.                                  */
1288  /*                                                                       */
1289  /* <Input>                                                               */
1290  /*    driver :: A handle to the target TrueType driver.                  */
1291  /*                                                                       */
1292  FT_LOCAL_DEF( void )
1293  tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
1294  {
1295#ifdef TT_USE_BYTECODE_INTERPRETER
1296    TT_Driver  driver = (TT_Driver)ttdriver;
1297
1298
1299    /* destroy the execution context */
1300    if ( driver->context )
1301    {
1302      TT_Done_Context( driver->context );
1303      driver->context = NULL;
1304    }
1305#else
1306    FT_UNUSED( ttdriver );
1307#endif
1308
1309  }
1310
1311
1312  /*************************************************************************/
1313  /*                                                                       */
1314  /* <Function>                                                            */
1315  /*    tt_slot_init                                                       */
1316  /*                                                                       */
1317  /* <Description>                                                         */
1318  /*    Initialize a new slot object.                                      */
1319  /*                                                                       */
1320  /* <InOut>                                                               */
1321  /*    slot :: A handle to the slot object.                               */
1322  /*                                                                       */
1323  /* <Return>                                                              */
1324  /*    FreeType error code.  0 means success.                             */
1325  /*                                                                       */
1326  FT_LOCAL_DEF( FT_Error )
1327  tt_slot_init( FT_GlyphSlot  slot )
1328  {
1329    return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1330  }
1331
1332
1333/* END */
1334