PageRenderTime 60ms CodeModel.GetById 2ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/src/freetype/src/truetype/ttobjs.c

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