1/***************************************************************************/
2/*                                                                         */
3/*  ttobjs.c                                                               */
4/*                                                                         */
5/*    Objects manager (body).                                              */
6/*                                                                         */
7/*  Copyright 1996-2015 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_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        { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
260        { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
261        { 0xA344A1EAUL, 0x000001E1UL }  /* prep */
262      },
263      { /* MingLiU 1996- */
264        { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
265        { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
266        { 0xA344A1EBUL, 0x000001E1UL }  /* prep */
267      },
268      { /* DFKaiShu */
269        { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
270        { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
271        { 0x13A42602UL, 0x0000007EUL }  /* prep */
272      },
273      { /* HuaTianKaiTi */
274        { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
275        { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
276        { 0x70020112UL, 0x00000008UL }  /* prep */
277      },
278      { /* HuaTianSongTi */
279        { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
280        { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
281        { 0x70020112UL, 0x00000008UL }  /* prep */
282      },
283      { /* NEC fadpop7.ttf */
284        { 0x00000000UL, 0x00000000UL }, /* cvt  */
285        { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
286        { 0xA39B58E3UL, 0x0000117CUL }  /* prep */
287      },
288      { /* NEC fadrei5.ttf */
289        { 0x00000000UL, 0x00000000UL }, /* cvt  */
290        { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
291        { 0x26D6C52AUL, 0x00000F6AUL }  /* prep */
292      },
293      { /* NEC fangot7.ttf */
294        { 0x00000000UL, 0x00000000UL }, /* cvt  */
295        { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
296        { 0x6C6E4B03UL, 0x00002492UL }  /* prep */
297      },
298      { /* NEC fangyo5.ttf */
299        { 0x00000000UL, 0x00000000UL }, /* cvt  */
300        { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
301        { 0xDE51FAD0UL, 0x0000117CUL }  /* prep */
302      },
303      { /* NEC fankyo5.ttf */
304        { 0x00000000UL, 0x00000000UL }, /* cvt  */
305        { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
306        { 0xA6C62831UL, 0x00001CAAUL }  /* prep */
307      },
308      { /* NEC fanrgo5.ttf */
309        { 0x00000000UL, 0x00000000UL }, /* cvt  */
310        { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
311        { 0xA0604633UL, 0x00001DE8UL }  /* prep */
312      },
313      { /* NEC fangot5.ttc */
314        { 0x00000000UL, 0x00000000UL }, /* cvt  */
315        { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
316        { 0x9B5CAA96UL, 0x00001F9AUL }  /* prep */
317      },
318      { /* NEC fanmin3.ttc */
319        { 0x00000000UL, 0x00000000UL }, /* cvt  */
320        { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
321        { 0xD4127766UL, 0x00002280UL }  /* prep */
322      },
323      { /* NEC FA-Gothic, 1996 */
324        { 0x00000000UL, 0x00000000UL }, /* cvt  */
325        { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
326        { 0x340D4346UL, 0x00001FCAUL }  /* prep */
327      },
328      { /* NEC FA-Minchou, 1996 */
329        { 0x00000000UL, 0x00000000UL }, /* cvt  */
330        { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
331        { 0x6CF31046UL, 0x000022B0UL }  /* prep */
332      },
333      { /* NEC FA-RoundGothicB, 1996 */
334        { 0x00000000UL, 0x00000000UL }, /* cvt  */
335        { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
336        { 0x40745A5FUL, 0x000022E0UL }  /* prep */
337      },
338      { /* NEC FA-RoundGothicM, 1996 */
339        { 0x00000000UL, 0x00000000UL }, /* cvt  */
340        { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
341        { 0x3900DED3UL, 0x00001E18UL }  /* 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    exec = size->context;
755
756    error = TT_Load_Context( exec, face, size );
757    if ( error )
758      return error;
759
760    exec->callTop = 0;
761    exec->top     = 0;
762
763    exec->period    = 64;
764    exec->phase     = 0;
765    exec->threshold = 0;
766
767    exec->instruction_trap = FALSE;
768    exec->F_dot_P          = 0x4000L;
769
770    exec->pedantic_hinting = pedantic;
771
772    {
773      FT_Size_Metrics*  metrics    = &exec->metrics;
774      TT_Size_Metrics*  tt_metrics = &exec->tt_metrics;
775
776
777      metrics->x_ppem   = 0;
778      metrics->y_ppem   = 0;
779      metrics->x_scale  = 0;
780      metrics->y_scale  = 0;
781
782      tt_metrics->ppem  = 0;
783      tt_metrics->scale = 0;
784      tt_metrics->ratio = 0x10000L;
785    }
786
787    /* allow font program execution */
788    TT_Set_CodeRange( exec,
789                      tt_coderange_font,
790                      face->font_program,
791                      (FT_Long)face->font_program_size );
792
793    /* disable CVT and glyph programs coderange */
794    TT_Clear_CodeRange( exec, tt_coderange_cvt );
795    TT_Clear_CodeRange( exec, tt_coderange_glyph );
796
797    if ( face->font_program_size > 0 )
798    {
799      TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
800
801      FT_TRACE4(( "Executing `fpgm' table.\n" ));
802      error = face->interpreter( exec );
803    }
804    else
805      error = FT_Err_Ok;
806
807    size->bytecode_ready = error;
808
809    if ( !error )
810      TT_Save_Context( exec, size );
811
812    return error;
813  }
814
815
816  /*************************************************************************/
817  /*                                                                       */
818  /* <Function>                                                            */
819  /*    tt_size_run_prep                                                   */
820  /*                                                                       */
821  /* <Description>                                                         */
822  /*    Run the control value program.                                     */
823  /*                                                                       */
824  /* <Input>                                                               */
825  /*    size     :: A handle to the size object.                           */
826  /*                                                                       */
827  /*    pedantic :: Set if bytecode execution should be pedantic.          */
828  /*                                                                       */
829  /* <Return>                                                              */
830  /*    FreeType error code.  0 means success.                             */
831  /*                                                                       */
832  FT_LOCAL_DEF( FT_Error )
833  tt_size_run_prep( TT_Size  size,
834                    FT_Bool  pedantic )
835  {
836    TT_Face         face = (TT_Face)size->root.face;
837    TT_ExecContext  exec;
838    FT_Error        error;
839
840
841    exec = size->context;
842
843    error = TT_Load_Context( exec, face, size );
844    if ( error )
845      return error;
846
847    exec->callTop = 0;
848    exec->top     = 0;
849
850    exec->instruction_trap = FALSE;
851
852    exec->pedantic_hinting = pedantic;
853
854    TT_Set_CodeRange( exec,
855                      tt_coderange_cvt,
856                      face->cvt_program,
857                      (FT_Long)face->cvt_program_size );
858
859    TT_Clear_CodeRange( exec, tt_coderange_glyph );
860
861    if ( face->cvt_program_size > 0 )
862    {
863      TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
864
865      FT_TRACE4(( "Executing `prep' table.\n" ));
866
867      error = face->interpreter( exec );
868    }
869    else
870      error = FT_Err_Ok;
871
872    size->cvt_ready = error;
873
874    /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
875    /* graphics state variables to be modified by the CVT program.  */
876
877    exec->GS.dualVector.x = 0x4000;
878    exec->GS.dualVector.y = 0;
879    exec->GS.projVector.x = 0x4000;
880    exec->GS.projVector.y = 0x0;
881    exec->GS.freeVector.x = 0x4000;
882    exec->GS.freeVector.y = 0x0;
883
884    exec->GS.rp0 = 0;
885    exec->GS.rp1 = 0;
886    exec->GS.rp2 = 0;
887
888    exec->GS.gep0 = 1;
889    exec->GS.gep1 = 1;
890    exec->GS.gep2 = 1;
891
892    exec->GS.loop = 1;
893
894    /* save as default graphics state */
895    size->GS = exec->GS;
896
897    TT_Save_Context( exec, size );
898
899    return error;
900  }
901
902
903  static void
904  tt_size_done_bytecode( FT_Size  ftsize )
905  {
906    TT_Size    size   = (TT_Size)ftsize;
907    TT_Face    face   = (TT_Face)ftsize->face;
908    FT_Memory  memory = face->root.memory;
909
910    if ( size->context )
911    {
912      TT_Done_Context( size->context );
913      size->context = NULL;
914    }
915
916    FT_FREE( size->cvt );
917    size->cvt_size = 0;
918
919    /* free storage area */
920    FT_FREE( size->storage );
921    size->storage_size = 0;
922
923    /* twilight zone */
924    tt_glyphzone_done( &size->twilight );
925
926    FT_FREE( size->function_defs );
927    FT_FREE( size->instruction_defs );
928
929    size->num_function_defs    = 0;
930    size->max_function_defs    = 0;
931    size->num_instruction_defs = 0;
932    size->max_instruction_defs = 0;
933
934    size->max_func = 0;
935    size->max_ins  = 0;
936
937    size->bytecode_ready = -1;
938    size->cvt_ready      = -1;
939  }
940
941
942  /* Initialize bytecode-related fields in the size object.       */
943  /* We do this only if bytecode interpretation is really needed. */
944  static FT_Error
945  tt_size_init_bytecode( FT_Size  ftsize,
946                         FT_Bool  pedantic )
947  {
948    FT_Error   error;
949    TT_Size    size = (TT_Size)ftsize;
950    TT_Face    face = (TT_Face)ftsize->face;
951    FT_Memory  memory = face->root.memory;
952
953    FT_UShort       n_twilight;
954    TT_MaxProfile*  maxp = &face->max_profile;
955
956
957    /* clean up bytecode related data */
958    FT_FREE( size->function_defs );
959    FT_FREE( size->instruction_defs );
960    FT_FREE( size->cvt );
961    FT_FREE( size->storage );
962
963    if ( size->context )
964      TT_Done_Context( size->context );
965    tt_glyphzone_done( &size->twilight );
966
967    size->bytecode_ready = -1;
968    size->cvt_ready      = -1;
969
970    size->context = TT_New_Context( (TT_Driver)face->root.driver );
971
972    size->max_function_defs    = maxp->maxFunctionDefs;
973    size->max_instruction_defs = maxp->maxInstructionDefs;
974
975    size->num_function_defs    = 0;
976    size->num_instruction_defs = 0;
977
978    size->max_func = 0;
979    size->max_ins  = 0;
980
981    size->cvt_size     = face->cvt_size;
982    size->storage_size = maxp->maxStorage;
983
984    /* Set default metrics */
985    {
986      TT_Size_Metrics*  metrics = &size->ttmetrics;
987
988
989      metrics->rotated   = FALSE;
990      metrics->stretched = FALSE;
991
992      /* set default engine compensation */
993      metrics->compensations[0] = 0;   /* gray     */
994      metrics->compensations[1] = 0;   /* black    */
995      metrics->compensations[2] = 0;   /* white    */
996      metrics->compensations[3] = 0;   /* reserved */
997    }
998
999    /* allocate function defs, instruction defs, cvt, and storage area */
1000    if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
1001         FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1002         FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
1003         FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
1004      goto Exit;
1005
1006    /* reserve twilight zone */
1007    n_twilight = maxp->maxTwilightPoints;
1008
1009    /* there are 4 phantom points (do we need this?) */
1010    n_twilight += 4;
1011
1012    error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1013    if ( error )
1014      goto Exit;
1015
1016    size->twilight.n_points = n_twilight;
1017
1018    size->GS = tt_default_graphics_state;
1019
1020    /* set `face->interpreter' according to the debug hook present */
1021    {
1022      FT_Library  library = face->root.driver->root.library;
1023
1024
1025      face->interpreter = (TT_Interpreter)
1026                            library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1027      if ( !face->interpreter )
1028        face->interpreter = (TT_Interpreter)TT_RunIns;
1029    }
1030
1031    /* Fine, now run the font program! */
1032    error = tt_size_run_fpgm( size, pedantic );
1033
1034  Exit:
1035    if ( error )
1036      tt_size_done_bytecode( ftsize );
1037
1038    return error;
1039  }
1040
1041
1042  FT_LOCAL_DEF( FT_Error )
1043  tt_size_ready_bytecode( TT_Size  size,
1044                          FT_Bool  pedantic )
1045  {
1046    FT_Error  error = FT_Err_Ok;
1047
1048
1049    if ( size->bytecode_ready < 0 )
1050      error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1051
1052    if ( error || size->bytecode_ready )
1053      goto Exit;
1054
1055    /* rescale CVT when needed */
1056    if ( size->cvt_ready < 0 )
1057    {
1058      FT_UInt  i;
1059      TT_Face  face = (TT_Face)size->root.face;
1060
1061
1062      /* Scale the cvt values to the new ppem.          */
1063      /* We use by default the y ppem to scale the CVT. */
1064      for ( i = 0; i < size->cvt_size; i++ )
1065        size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1066
1067      /* all twilight points are originally zero */
1068      for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
1069      {
1070        size->twilight.org[i].x = 0;
1071        size->twilight.org[i].y = 0;
1072        size->twilight.cur[i].x = 0;
1073        size->twilight.cur[i].y = 0;
1074      }
1075
1076      /* clear storage area */
1077      for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
1078        size->storage[i] = 0;
1079
1080      size->GS = tt_default_graphics_state;
1081
1082      error = tt_size_run_prep( size, pedantic );
1083    }
1084
1085  Exit:
1086    return error;
1087  }
1088
1089#endif /* TT_USE_BYTECODE_INTERPRETER */
1090
1091
1092  /*************************************************************************/
1093  /*                                                                       */
1094  /* <Function>                                                            */
1095  /*    tt_size_init                                                       */
1096  /*                                                                       */
1097  /* <Description>                                                         */
1098  /*    Initialize a new TrueType size object.                             */
1099  /*                                                                       */
1100  /* <InOut>                                                               */
1101  /*    size :: A handle to the size object.                               */
1102  /*                                                                       */
1103  /* <Return>                                                              */
1104  /*    FreeType error code.  0 means success.                             */
1105  /*                                                                       */
1106  FT_LOCAL_DEF( FT_Error )
1107  tt_size_init( FT_Size  ttsize )           /* TT_Size */
1108  {
1109    TT_Size   size  = (TT_Size)ttsize;
1110    FT_Error  error = FT_Err_Ok;
1111
1112
1113#ifdef TT_USE_BYTECODE_INTERPRETER
1114    size->bytecode_ready = -1;
1115    size->cvt_ready      = -1;
1116#endif
1117
1118    size->ttmetrics.valid = FALSE;
1119    size->strike_index    = 0xFFFFFFFFUL;
1120
1121    return error;
1122  }
1123
1124
1125  /*************************************************************************/
1126  /*                                                                       */
1127  /* <Function>                                                            */
1128  /*    tt_size_done                                                       */
1129  /*                                                                       */
1130  /* <Description>                                                         */
1131  /*    The TrueType size object finalizer.                                */
1132  /*                                                                       */
1133  /* <Input>                                                               */
1134  /*    size :: A handle to the target size object.                        */
1135  /*                                                                       */
1136  FT_LOCAL_DEF( void )
1137  tt_size_done( FT_Size  ttsize )           /* TT_Size */
1138  {
1139    TT_Size  size = (TT_Size)ttsize;
1140
1141
1142#ifdef TT_USE_BYTECODE_INTERPRETER
1143    tt_size_done_bytecode( ttsize );
1144#endif
1145
1146    size->ttmetrics.valid = FALSE;
1147  }
1148
1149
1150  /*************************************************************************/
1151  /*                                                                       */
1152  /* <Function>                                                            */
1153  /*    tt_size_reset                                                      */
1154  /*                                                                       */
1155  /* <Description>                                                         */
1156  /*    Reset a TrueType size when resolutions and character dimensions    */
1157  /*    have been changed.                                                 */
1158  /*                                                                       */
1159  /* <Input>                                                               */
1160  /*    size :: A handle to the target size object.                        */
1161  /*                                                                       */
1162  FT_LOCAL_DEF( FT_Error )
1163  tt_size_reset( TT_Size  size )
1164  {
1165    TT_Face           face;
1166    FT_Error          error = FT_Err_Ok;
1167    FT_Size_Metrics*  metrics;
1168
1169
1170    size->ttmetrics.valid = FALSE;
1171
1172    face = (TT_Face)size->root.face;
1173
1174    metrics = &size->metrics;
1175
1176    /* copy the result from base layer */
1177    *metrics = size->root.metrics;
1178
1179    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
1180      return FT_THROW( Invalid_PPem );
1181
1182    /* This bit flag, if set, indicates that the ppems must be       */
1183    /* rounded to integers.  Nearly all TrueType fonts have this bit */
1184    /* set, as hinting won't work really well otherwise.             */
1185    /*                                                               */
1186    if ( face->header.Flags & 8 )
1187    {
1188      metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1189                                    face->root.units_per_EM );
1190      metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1191                                    face->root.units_per_EM );
1192
1193      metrics->ascender =
1194        FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );
1195      metrics->descender =
1196        FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );
1197      metrics->height =
1198        FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );
1199      metrics->max_advance =
1200        FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,
1201                                 metrics->x_scale ) );
1202    }
1203
1204    /* compute new transformation */
1205    if ( metrics->x_ppem >= metrics->y_ppem )
1206    {
1207      size->ttmetrics.scale   = metrics->x_scale;
1208      size->ttmetrics.ppem    = metrics->x_ppem;
1209      size->ttmetrics.x_ratio = 0x10000L;
1210      size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem,
1211                                           metrics->x_ppem );
1212    }
1213    else
1214    {
1215      size->ttmetrics.scale   = metrics->y_scale;
1216      size->ttmetrics.ppem    = metrics->y_ppem;
1217      size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem,
1218                                           metrics->y_ppem );
1219      size->ttmetrics.y_ratio = 0x10000L;
1220    }
1221
1222#ifdef TT_USE_BYTECODE_INTERPRETER
1223    size->cvt_ready = -1;
1224#endif /* TT_USE_BYTECODE_INTERPRETER */
1225
1226    if ( !error )
1227      size->ttmetrics.valid = TRUE;
1228
1229    return error;
1230  }
1231
1232
1233  /*************************************************************************/
1234  /*                                                                       */
1235  /* <Function>                                                            */
1236  /*    tt_driver_init                                                     */
1237  /*                                                                       */
1238  /* <Description>                                                         */
1239  /*    Initialize a given TrueType driver object.                         */
1240  /*                                                                       */
1241  /* <Input>                                                               */
1242  /*    driver :: A handle to the target driver object.                    */
1243  /*                                                                       */
1244  /* <Return>                                                              */
1245  /*    FreeType error code.  0 means success.                             */
1246  /*                                                                       */
1247  FT_LOCAL_DEF( FT_Error )
1248  tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
1249  {
1250
1251#ifdef TT_USE_BYTECODE_INTERPRETER
1252
1253    TT_Driver  driver = (TT_Driver)ttdriver;
1254
1255#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1256    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1257#else
1258    driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1259#endif
1260
1261#else /* !TT_USE_BYTECODE_INTERPRETER */
1262
1263    FT_UNUSED( ttdriver );
1264
1265#endif /* !TT_USE_BYTECODE_INTERPRETER */
1266
1267    return FT_Err_Ok;
1268  }
1269
1270
1271  /*************************************************************************/
1272  /*                                                                       */
1273  /* <Function>                                                            */
1274  /*    tt_driver_done                                                     */
1275  /*                                                                       */
1276  /* <Description>                                                         */
1277  /*    Finalize a given TrueType driver.                                  */
1278  /*                                                                       */
1279  /* <Input>                                                               */
1280  /*    driver :: A handle to the target TrueType driver.                  */
1281  /*                                                                       */
1282  FT_LOCAL_DEF( void )
1283  tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
1284  {
1285    FT_UNUSED( ttdriver );
1286  }
1287
1288
1289  /*************************************************************************/
1290  /*                                                                       */
1291  /* <Function>                                                            */
1292  /*    tt_slot_init                                                       */
1293  /*                                                                       */
1294  /* <Description>                                                         */
1295  /*    Initialize a new slot object.                                      */
1296  /*                                                                       */
1297  /* <InOut>                                                               */
1298  /*    slot :: A handle to the slot object.                               */
1299  /*                                                                       */
1300  /* <Return>                                                              */
1301  /*    FreeType error code.  0 means success.                             */
1302  /*                                                                       */
1303  FT_LOCAL_DEF( FT_Error )
1304  tt_slot_init( FT_GlyphSlot  slot )
1305  {
1306    return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1307  }
1308
1309
1310/* END */
1311