PageRenderTime 112ms CodeModel.GetById 9ms app.highlight 86ms RepoModel.GetById 1ms app.codeStats 1ms

/src/compiler/android-ndk/jni/freetype/src/base/ftobjs.c

http://ftk.googlecode.com/
C | 2205 lines | 1429 code | 471 blank | 305 comment | 273 complexity | 7d02caf4d5d1a519f902fcc28bfc1bea MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/***************************************************************************/
   2/*                                                                         */
   3/*  ftobjs.c                                                               */
   4/*                                                                         */
   5/*    The FreeType private base classes (body).                            */
   6/*                                                                         */
   7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
   8/*            2010 by                                                      */
   9/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  10/*                                                                         */
  11/*  This file is part of the FreeType project, and may only be used,       */
  12/*  modified, and distributed under the terms of the FreeType project      */
  13/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  14/*  this file you indicate that you have read the license and              */
  15/*  understand and accept it fully.                                        */
  16/*                                                                         */
  17/***************************************************************************/
  18
  19
  20#include <ft2build.h>
  21#include FT_LIST_H
  22#include FT_OUTLINE_H
  23#include FT_INTERNAL_VALIDATE_H
  24#include FT_INTERNAL_OBJECTS_H
  25#include FT_INTERNAL_DEBUG_H
  26#include FT_INTERNAL_RFORK_H
  27#include FT_INTERNAL_STREAM_H
  28#include FT_INTERNAL_SFNT_H    /* for SFNT_Load_Table_Func */
  29#include FT_TRUETYPE_TABLES_H
  30#include FT_TRUETYPE_TAGS_H
  31#include FT_TRUETYPE_IDS_H
  32#include FT_OUTLINE_H
  33
  34#include FT_SERVICE_SFNT_H
  35#include FT_SERVICE_POSTSCRIPT_NAME_H
  36#include FT_SERVICE_GLYPH_DICT_H
  37#include FT_SERVICE_TT_CMAP_H
  38#include FT_SERVICE_KERNING_H
  39#include FT_SERVICE_TRUETYPE_ENGINE_H
  40
  41#ifdef FT_CONFIG_OPTION_MAC_FONTS
  42#include "ftbase.h"
  43#endif
  44
  45#define GRID_FIT_METRICS
  46
  47
  48  FT_BASE_DEF( FT_Pointer )
  49  ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
  50                          const char*     service_id )
  51  {
  52    FT_Pointer      result = NULL;
  53    FT_ServiceDesc  desc   = service_descriptors;
  54
  55
  56    if ( desc && service_id )
  57    {
  58      for ( ; desc->serv_id != NULL; desc++ )
  59      {
  60        if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
  61        {
  62          result = (FT_Pointer)desc->serv_data;
  63          break;
  64        }
  65      }
  66    }
  67
  68    return result;
  69  }
  70
  71
  72  FT_BASE_DEF( void )
  73  ft_validator_init( FT_Validator        valid,
  74                     const FT_Byte*      base,
  75                     const FT_Byte*      limit,
  76                     FT_ValidationLevel  level )
  77  {
  78    valid->base  = base;
  79    valid->limit = limit;
  80    valid->level = level;
  81    valid->error = FT_Err_Ok;
  82  }
  83
  84
  85  FT_BASE_DEF( FT_Int )
  86  ft_validator_run( FT_Validator  valid )
  87  {
  88    /* This function doesn't work!  None should call it. */
  89    FT_UNUSED( valid );
  90
  91    return -1;
  92  }
  93
  94
  95  FT_BASE_DEF( void )
  96  ft_validator_error( FT_Validator  valid,
  97                      FT_Error      error )
  98  {
  99    /* since the cast below also disables the compiler's */
 100    /* type check, we introduce a dummy variable, which  */
 101    /* will be optimized away                            */
 102    volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
 103
 104
 105    valid->error = error;
 106
 107    /* throw away volatileness; use `jump_buffer' or the  */
 108    /* compiler may warn about an unused local variable   */
 109    ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
 110  }
 111
 112
 113  /*************************************************************************/
 114  /*************************************************************************/
 115  /*************************************************************************/
 116  /****                                                                 ****/
 117  /****                                                                 ****/
 118  /****                           S T R E A M                           ****/
 119  /****                                                                 ****/
 120  /****                                                                 ****/
 121  /*************************************************************************/
 122  /*************************************************************************/
 123  /*************************************************************************/
 124
 125
 126  /* create a new input stream from an FT_Open_Args structure */
 127  /*                                                          */
 128  FT_BASE_DEF( FT_Error )
 129  FT_Stream_New( FT_Library           library,
 130                 const FT_Open_Args*  args,
 131                 FT_Stream           *astream )
 132  {
 133    FT_Error   error;
 134    FT_Memory  memory;
 135    FT_Stream  stream;
 136
 137
 138    *astream = 0;
 139
 140    if ( !library )
 141      return FT_Err_Invalid_Library_Handle;
 142
 143    if ( !args )
 144      return FT_Err_Invalid_Argument;
 145
 146    memory   = library->memory;
 147
 148    if ( FT_NEW( stream ) )
 149      goto Exit;
 150
 151    stream->memory = memory;
 152
 153    if ( args->flags & FT_OPEN_MEMORY )
 154    {
 155      /* create a memory-based stream */
 156      FT_Stream_OpenMemory( stream,
 157                            (const FT_Byte*)args->memory_base,
 158                            args->memory_size );
 159    }
 160    else if ( args->flags & FT_OPEN_PATHNAME )
 161    {
 162      /* create a normal system stream */
 163      error = FT_Stream_Open( stream, args->pathname );
 164      stream->pathname.pointer = args->pathname;
 165    }
 166    else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
 167    {
 168      /* use an existing, user-provided stream */
 169
 170      /* in this case, we do not need to allocate a new stream object */
 171      /* since the caller is responsible for closing it himself       */
 172      FT_FREE( stream );
 173      stream = args->stream;
 174    }
 175    else
 176      error = FT_Err_Invalid_Argument;
 177
 178    if ( error )
 179      FT_FREE( stream );
 180    else
 181      stream->memory = memory;  /* just to be certain */
 182
 183    *astream = stream;
 184
 185  Exit:
 186    return error;
 187  }
 188
 189
 190  FT_BASE_DEF( void )
 191  FT_Stream_Free( FT_Stream  stream,
 192                  FT_Int     external )
 193  {
 194    if ( stream )
 195    {
 196      FT_Memory  memory = stream->memory;
 197
 198
 199      FT_Stream_Close( stream );
 200
 201      if ( !external )
 202        FT_FREE( stream );
 203    }
 204  }
 205
 206
 207  /*************************************************************************/
 208  /*                                                                       */
 209  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 210  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 211  /* messages during execution.                                            */
 212  /*                                                                       */
 213#undef  FT_COMPONENT
 214#define FT_COMPONENT  trace_objs
 215
 216
 217  /*************************************************************************/
 218  /*************************************************************************/
 219  /*************************************************************************/
 220  /****                                                                 ****/
 221  /****                                                                 ****/
 222  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
 223  /****                                                                 ****/
 224  /****                                                                 ****/
 225  /*************************************************************************/
 226  /*************************************************************************/
 227  /*************************************************************************/
 228
 229
 230  static FT_Error
 231  ft_glyphslot_init( FT_GlyphSlot  slot )
 232  {
 233    FT_Driver         driver = slot->face->driver;
 234    FT_Driver_Class   clazz  = driver->clazz;
 235    FT_Memory         memory = driver->root.memory;
 236    FT_Error          error  = FT_Err_Ok;
 237    FT_Slot_Internal  internal;
 238
 239
 240    slot->library = driver->root.library;
 241
 242    if ( FT_NEW( internal ) )
 243      goto Exit;
 244
 245    slot->internal = internal;
 246
 247    if ( FT_DRIVER_USES_OUTLINES( driver ) )
 248      error = FT_GlyphLoader_New( memory, &internal->loader );
 249
 250    if ( !error && clazz->init_slot )
 251      error = clazz->init_slot( slot );
 252
 253  Exit:
 254    return error;
 255  }
 256
 257
 258  FT_BASE_DEF( void )
 259  ft_glyphslot_free_bitmap( FT_GlyphSlot  slot )
 260  {
 261    if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
 262    {
 263      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
 264
 265
 266      FT_FREE( slot->bitmap.buffer );
 267      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
 268    }
 269    else
 270    {
 271      /* assume that the bitmap buffer was stolen or not */
 272      /* allocated from the heap                         */
 273      slot->bitmap.buffer = NULL;
 274    }
 275  }
 276
 277
 278  FT_BASE_DEF( void )
 279  ft_glyphslot_set_bitmap( FT_GlyphSlot  slot,
 280                           FT_Byte*      buffer )
 281  {
 282    ft_glyphslot_free_bitmap( slot );
 283
 284    slot->bitmap.buffer = buffer;
 285
 286    FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
 287  }
 288
 289
 290  FT_BASE_DEF( FT_Error )
 291  ft_glyphslot_alloc_bitmap( FT_GlyphSlot  slot,
 292                             FT_ULong      size )
 293  {
 294    FT_Memory  memory = FT_FACE_MEMORY( slot->face );
 295    FT_Error   error;
 296
 297
 298    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
 299      FT_FREE( slot->bitmap.buffer );
 300    else
 301      slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 302
 303    (void)FT_ALLOC( slot->bitmap.buffer, size );
 304    return error;
 305  }
 306
 307
 308  static void
 309  ft_glyphslot_clear( FT_GlyphSlot  slot )
 310  {
 311    /* free bitmap if needed */
 312    ft_glyphslot_free_bitmap( slot );
 313
 314    /* clear all public fields in the glyph slot */
 315    FT_ZERO( &slot->metrics );
 316    FT_ZERO( &slot->outline );
 317
 318    slot->bitmap.width      = 0;
 319    slot->bitmap.rows       = 0;
 320    slot->bitmap.pitch      = 0;
 321    slot->bitmap.pixel_mode = 0;
 322    /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
 323
 324    slot->bitmap_left   = 0;
 325    slot->bitmap_top    = 0;
 326    slot->num_subglyphs = 0;
 327    slot->subglyphs     = 0;
 328    slot->control_data  = 0;
 329    slot->control_len   = 0;
 330    slot->other         = 0;
 331    slot->format        = FT_GLYPH_FORMAT_NONE;
 332
 333    slot->linearHoriAdvance = 0;
 334    slot->linearVertAdvance = 0;
 335    slot->lsb_delta         = 0;
 336    slot->rsb_delta         = 0;
 337  }
 338
 339
 340  static void
 341  ft_glyphslot_done( FT_GlyphSlot  slot )
 342  {
 343    FT_Driver        driver = slot->face->driver;
 344    FT_Driver_Class  clazz  = driver->clazz;
 345    FT_Memory        memory = driver->root.memory;
 346
 347
 348    if ( clazz->done_slot )
 349      clazz->done_slot( slot );
 350
 351    /* free bitmap buffer if needed */
 352    ft_glyphslot_free_bitmap( slot );
 353
 354    /* slot->internal might be NULL in out-of-memory situations */
 355    if ( slot->internal )
 356    {
 357    /* free glyph loader */
 358    if ( FT_DRIVER_USES_OUTLINES( driver ) )
 359    {
 360      FT_GlyphLoader_Done( slot->internal->loader );
 361      slot->internal->loader = 0;
 362    }
 363
 364    FT_FREE( slot->internal );
 365    }
 366  }
 367
 368
 369  /* documentation is in ftobjs.h */
 370
 371  FT_BASE_DEF( FT_Error )
 372  FT_New_GlyphSlot( FT_Face        face,
 373                    FT_GlyphSlot  *aslot )
 374  {
 375    FT_Error         error;
 376    FT_Driver        driver;
 377    FT_Driver_Class  clazz;
 378    FT_Memory        memory;
 379    FT_GlyphSlot     slot;
 380
 381
 382    if ( !face || !face->driver )
 383      return FT_Err_Invalid_Argument;
 384
 385    driver = face->driver;
 386    clazz  = driver->clazz;
 387    memory = driver->root.memory;
 388
 389    FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
 390    if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
 391    {
 392      slot->face = face;
 393
 394      error = ft_glyphslot_init( slot );
 395      if ( error )
 396      {
 397        ft_glyphslot_done( slot );
 398        FT_FREE( slot );
 399        goto Exit;
 400      }
 401
 402      slot->next  = face->glyph;
 403      face->glyph = slot;
 404
 405      if ( aslot )
 406        *aslot = slot;
 407    }
 408    else if ( aslot )
 409      *aslot = 0;
 410
 411
 412  Exit:
 413    FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
 414    return error;
 415  }
 416
 417
 418  /* documentation is in ftobjs.h */
 419
 420  FT_BASE_DEF( void )
 421  FT_Done_GlyphSlot( FT_GlyphSlot  slot )
 422  {
 423    if ( slot )
 424    {
 425      FT_Driver     driver = slot->face->driver;
 426      FT_Memory     memory = driver->root.memory;
 427      FT_GlyphSlot  prev;
 428      FT_GlyphSlot  cur;
 429
 430
 431      /* Remove slot from its parent face's list */
 432      prev = NULL;
 433      cur  = slot->face->glyph;
 434
 435      while ( cur )
 436      {
 437        if ( cur == slot )
 438        {
 439          if ( !prev )
 440            slot->face->glyph = cur->next;
 441          else
 442            prev->next = cur->next;
 443
 444          ft_glyphslot_done( slot );
 445          FT_FREE( slot );
 446          break;
 447        }
 448        prev = cur;
 449        cur  = cur->next;
 450      }
 451    }
 452  }
 453
 454
 455  /* documentation is in freetype.h */
 456
 457  FT_EXPORT_DEF( void )
 458  FT_Set_Transform( FT_Face     face,
 459                    FT_Matrix*  matrix,
 460                    FT_Vector*  delta )
 461  {
 462    FT_Face_Internal  internal;
 463
 464
 465    if ( !face )
 466      return;
 467
 468    internal = face->internal;
 469
 470    internal->transform_flags = 0;
 471
 472    if ( !matrix )
 473    {
 474      internal->transform_matrix.xx = 0x10000L;
 475      internal->transform_matrix.xy = 0;
 476      internal->transform_matrix.yx = 0;
 477      internal->transform_matrix.yy = 0x10000L;
 478      matrix = &internal->transform_matrix;
 479    }
 480    else
 481      internal->transform_matrix = *matrix;
 482
 483    /* set transform_flags bit flag 0 if `matrix' isn't the identity */
 484    if ( ( matrix->xy | matrix->yx ) ||
 485         matrix->xx != 0x10000L      ||
 486         matrix->yy != 0x10000L      )
 487      internal->transform_flags |= 1;
 488
 489    if ( !delta )
 490    {
 491      internal->transform_delta.x = 0;
 492      internal->transform_delta.y = 0;
 493      delta = &internal->transform_delta;
 494    }
 495    else
 496      internal->transform_delta = *delta;
 497
 498    /* set transform_flags bit flag 1 if `delta' isn't the null vector */
 499    if ( delta->x | delta->y )
 500      internal->transform_flags |= 2;
 501  }
 502
 503
 504  static FT_Renderer
 505  ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
 506
 507
 508#ifdef GRID_FIT_METRICS
 509  static void
 510  ft_glyphslot_grid_fit_metrics( FT_GlyphSlot  slot,
 511                                 FT_Bool       vertical )
 512  {
 513    FT_Glyph_Metrics*  metrics = &slot->metrics;
 514    FT_Pos             right, bottom;
 515
 516
 517    if ( vertical )
 518    {
 519      metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
 520      metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 521
 522      right  = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
 523      bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
 524
 525      metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
 526      metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 527
 528      metrics->width  = right - metrics->vertBearingX;
 529      metrics->height = bottom - metrics->vertBearingY;
 530    }
 531    else
 532    {
 533      metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
 534      metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 535
 536      right  = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
 537      bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
 538
 539      metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
 540      metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 541
 542      metrics->width  = right - metrics->horiBearingX;
 543      metrics->height = metrics->horiBearingY - bottom;
 544    }
 545
 546    metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
 547    metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
 548  }
 549#endif /* GRID_FIT_METRICS */
 550
 551
 552  /* documentation is in freetype.h */
 553
 554  FT_EXPORT_DEF( FT_Error )
 555  FT_Load_Glyph( FT_Face   face,
 556                 FT_UInt   glyph_index,
 557                 FT_Int32  load_flags )
 558  {
 559    FT_Error      error;
 560    FT_Driver     driver;
 561    FT_GlyphSlot  slot;
 562    FT_Library    library;
 563    FT_Bool       autohint = FALSE;
 564    FT_Module     hinter;
 565
 566
 567    if ( !face || !face->size || !face->glyph )
 568      return FT_Err_Invalid_Face_Handle;
 569
 570    /* The validity test for `glyph_index' is performed by the */
 571    /* font drivers.                                           */
 572
 573    slot = face->glyph;
 574    ft_glyphslot_clear( slot );
 575
 576    driver  = face->driver;
 577    library = driver->root.library;
 578    hinter  = library->auto_hinter;
 579
 580    /* resolve load flags dependencies */
 581
 582    if ( load_flags & FT_LOAD_NO_RECURSE )
 583      load_flags |= FT_LOAD_NO_SCALE         |
 584                    FT_LOAD_IGNORE_TRANSFORM;
 585
 586    if ( load_flags & FT_LOAD_NO_SCALE )
 587    {
 588      load_flags |= FT_LOAD_NO_HINTING |
 589                    FT_LOAD_NO_BITMAP;
 590
 591      load_flags &= ~FT_LOAD_RENDER;
 592    }
 593
 594    /*
 595     * Determine whether we need to auto-hint or not.
 596     * The general rules are:
 597     *
 598     * - Do only auto-hinting if we have a hinter module, a scalable font
 599     *   format dealing with outlines, and no transforms except simple
 600     *   slants and/or rotations by integer multiples of 90 degrees.
 601     *
 602     * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
 603     *   have a native font hinter.
 604     *
 605     * - Otherwise, auto-hint for LIGHT hinting mode.
 606     *
 607     * - Exception: The font is `tricky' and requires the native hinter to
 608     *   load properly.
 609     */
 610
 611    if ( hinter                                   &&
 612         !( load_flags & FT_LOAD_NO_HINTING )     &&
 613         !( load_flags & FT_LOAD_NO_AUTOHINT )    &&
 614         FT_DRIVER_IS_SCALABLE( driver )          &&
 615         FT_DRIVER_USES_OUTLINES( driver )        &&
 616         !FT_IS_TRICKY( face )                    &&
 617         ( ( face->internal->transform_matrix.yx == 0 &&
 618             face->internal->transform_matrix.xx != 0 ) ||
 619           ( face->internal->transform_matrix.xx == 0 &&
 620             face->internal->transform_matrix.yx != 0 ) ) )
 621    {
 622      if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
 623           !FT_DRIVER_HAS_HINTER( driver )         )
 624        autohint = TRUE;
 625      else
 626      {
 627        FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
 628
 629
 630        if ( mode == FT_RENDER_MODE_LIGHT             ||
 631             face->internal->ignore_unpatented_hinter )
 632          autohint = TRUE;
 633      }
 634    }
 635
 636    if ( autohint )
 637    {
 638      FT_AutoHinter_Service  hinting;
 639
 640
 641      /* try to load embedded bitmaps first if available            */
 642      /*                                                            */
 643      /* XXX: This is really a temporary hack that should disappear */
 644      /*      promptly with FreeType 2.1!                           */
 645      /*                                                            */
 646      if ( FT_HAS_FIXED_SIZES( face )             &&
 647          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
 648      {
 649        error = driver->clazz->load_glyph( slot, face->size,
 650                                           glyph_index,
 651                                           load_flags | FT_LOAD_SBITS_ONLY );
 652
 653        if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
 654          goto Load_Ok;
 655      }
 656
 657      {
 658        FT_Face_Internal  internal        = face->internal;
 659        FT_Int            transform_flags = internal->transform_flags;
 660
 661
 662        /* since the auto-hinter calls FT_Load_Glyph by itself, */
 663        /* make sure that glyphs aren't transformed             */
 664        internal->transform_flags = 0;
 665
 666        /* load auto-hinted outline */
 667        hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
 668
 669        error   = hinting->load_glyph( (FT_AutoHinter)hinter,
 670                                       slot, face->size,
 671                                       glyph_index, load_flags );
 672
 673        internal->transform_flags = transform_flags;
 674      }
 675    }
 676    else
 677    {
 678      error = driver->clazz->load_glyph( slot,
 679                                         face->size,
 680                                         glyph_index,
 681                                         load_flags );
 682      if ( error )
 683        goto Exit;
 684
 685      if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
 686      {
 687        /* check that the loaded outline is correct */
 688        error = FT_Outline_Check( &slot->outline );
 689        if ( error )
 690          goto Exit;
 691
 692#ifdef GRID_FIT_METRICS
 693        if ( !( load_flags & FT_LOAD_NO_HINTING ) )
 694          ft_glyphslot_grid_fit_metrics( slot,
 695              FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
 696#endif
 697      }
 698    }
 699
 700  Load_Ok:
 701    /* compute the advance */
 702    if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
 703    {
 704      slot->advance.x = 0;
 705      slot->advance.y = slot->metrics.vertAdvance;
 706    }
 707    else
 708    {
 709      slot->advance.x = slot->metrics.horiAdvance;
 710      slot->advance.y = 0;
 711    }
 712
 713    /* compute the linear advance in 16.16 pixels */
 714    if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0  &&
 715         ( FT_IS_SCALABLE( face ) )                   )
 716    {
 717      FT_Size_Metrics*  metrics = &face->size->metrics;
 718
 719
 720      /* it's tricky! */
 721      slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
 722                                           metrics->x_scale, 64 );
 723
 724      slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
 725                                           metrics->y_scale, 64 );
 726    }
 727
 728    if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
 729    {
 730      FT_Face_Internal  internal = face->internal;
 731
 732
 733      /* now, transform the glyph image if needed */
 734      if ( internal->transform_flags )
 735      {
 736        /* get renderer */
 737        FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
 738
 739
 740        if ( renderer )
 741          error = renderer->clazz->transform_glyph(
 742                                     renderer, slot,
 743                                     &internal->transform_matrix,
 744                                     &internal->transform_delta );
 745        else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
 746        {
 747          /* apply `standard' transformation if no renderer is available */
 748          if ( &internal->transform_matrix )
 749            FT_Outline_Transform( &slot->outline,
 750                                  &internal->transform_matrix );
 751
 752          if ( &internal->transform_delta )
 753            FT_Outline_Translate( &slot->outline,
 754                                  internal->transform_delta.x,
 755                                  internal->transform_delta.y );
 756        }
 757
 758        /* transform advance */
 759        FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
 760      }
 761    }
 762
 763    FT_TRACE5(( "  x advance: %d\n" , slot->advance.x ));
 764    FT_TRACE5(( "  y advance: %d\n" , slot->advance.y ));
 765
 766    FT_TRACE5(( "  linear x advance: %d\n" , slot->linearHoriAdvance ));
 767    FT_TRACE5(( "  linear y advance: %d\n" , slot->linearVertAdvance ));
 768
 769    /* do we need to render the image now? */
 770    if ( !error                                    &&
 771         slot->format != FT_GLYPH_FORMAT_BITMAP    &&
 772         slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
 773         load_flags & FT_LOAD_RENDER )
 774    {
 775      FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
 776
 777
 778      if ( mode == FT_RENDER_MODE_NORMAL      &&
 779           (load_flags & FT_LOAD_MONOCHROME ) )
 780        mode = FT_RENDER_MODE_MONO;
 781
 782      error = FT_Render_Glyph( slot, mode );
 783    }
 784
 785  Exit:
 786    return error;
 787  }
 788
 789
 790  /* documentation is in freetype.h */
 791
 792  FT_EXPORT_DEF( FT_Error )
 793  FT_Load_Char( FT_Face   face,
 794                FT_ULong  char_code,
 795                FT_Int32  load_flags )
 796  {
 797    FT_UInt  glyph_index;
 798
 799
 800    if ( !face )
 801      return FT_Err_Invalid_Face_Handle;
 802
 803    glyph_index = (FT_UInt)char_code;
 804    if ( face->charmap )
 805      glyph_index = FT_Get_Char_Index( face, char_code );
 806
 807    return FT_Load_Glyph( face, glyph_index, load_flags );
 808  }
 809
 810
 811  /* destructor for sizes list */
 812  static void
 813  destroy_size( FT_Memory  memory,
 814                FT_Size    size,
 815                FT_Driver  driver )
 816  {
 817    /* finalize client-specific data */
 818    if ( size->generic.finalizer )
 819      size->generic.finalizer( size );
 820
 821    /* finalize format-specific stuff */
 822    if ( driver->clazz->done_size )
 823      driver->clazz->done_size( size );
 824
 825    FT_FREE( size->internal );
 826    FT_FREE( size );
 827  }
 828
 829
 830  static void
 831  ft_cmap_done_internal( FT_CMap  cmap );
 832
 833
 834  static void
 835  destroy_charmaps( FT_Face    face,
 836                    FT_Memory  memory )
 837  {
 838    FT_Int  n;
 839
 840
 841    if ( !face )
 842      return;
 843
 844    for ( n = 0; n < face->num_charmaps; n++ )
 845    {
 846      FT_CMap  cmap = FT_CMAP( face->charmaps[n] );
 847
 848
 849      ft_cmap_done_internal( cmap );
 850
 851      face->charmaps[n] = NULL;
 852    }
 853
 854    FT_FREE( face->charmaps );
 855    face->num_charmaps = 0;
 856  }
 857
 858
 859  /* destructor for faces list */
 860  static void
 861  destroy_face( FT_Memory  memory,
 862                FT_Face    face,
 863                FT_Driver  driver )
 864  {
 865    FT_Driver_Class  clazz = driver->clazz;
 866
 867
 868    /* discard auto-hinting data */
 869    if ( face->autohint.finalizer )
 870      face->autohint.finalizer( face->autohint.data );
 871
 872    /* Discard glyph slots for this face.                           */
 873    /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
 874    while ( face->glyph )
 875      FT_Done_GlyphSlot( face->glyph );
 876
 877    /* discard all sizes for this face */
 878    FT_List_Finalize( &face->sizes_list,
 879                      (FT_List_Destructor)destroy_size,
 880                      memory,
 881                      driver );
 882    face->size = 0;
 883
 884    /* now discard client data */
 885    if ( face->generic.finalizer )
 886      face->generic.finalizer( face );
 887
 888    /* discard charmaps */
 889    destroy_charmaps( face, memory );
 890
 891    /* finalize format-specific stuff */
 892    if ( clazz->done_face )
 893      clazz->done_face( face );
 894
 895    /* close the stream for this face if needed */
 896    FT_Stream_Free(
 897      face->stream,
 898      ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
 899
 900    face->stream = 0;
 901
 902    /* get rid of it */
 903    if ( face->internal )
 904    {
 905      FT_FREE( face->internal );
 906    }
 907    FT_FREE( face );
 908  }
 909
 910
 911  static void
 912  Destroy_Driver( FT_Driver  driver )
 913  {
 914    FT_List_Finalize( &driver->faces_list,
 915                      (FT_List_Destructor)destroy_face,
 916                      driver->root.memory,
 917                      driver );
 918
 919    /* check whether we need to drop the driver's glyph loader */
 920    if ( FT_DRIVER_USES_OUTLINES( driver ) )
 921      FT_GlyphLoader_Done( driver->glyph_loader );
 922  }
 923
 924
 925  /*************************************************************************/
 926  /*                                                                       */
 927  /* <Function>                                                            */
 928  /*    find_unicode_charmap                                               */
 929  /*                                                                       */
 930  /* <Description>                                                         */
 931  /*    This function finds a Unicode charmap, if there is one.            */
 932  /*    And if there is more than one, it tries to favour the more         */
 933  /*    extensive one, i.e., one that supports UCS-4 against those which   */
 934  /*    are limited to the BMP (said UCS-2 encoding.)                      */
 935  /*                                                                       */
 936  /*    This function is called from open_face() (just below), and also    */
 937  /*    from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ).                */
 938  /*                                                                       */
 939  static FT_Error
 940  find_unicode_charmap( FT_Face  face )
 941  {
 942    FT_CharMap*  first;
 943    FT_CharMap*  cur;
 944
 945
 946    /* caller should have already checked that `face' is valid */
 947    FT_ASSERT( face );
 948
 949    first = face->charmaps;
 950
 951    if ( !first )
 952      return FT_Err_Invalid_CharMap_Handle;
 953
 954    /*
 955     *  The original TrueType specification(s) only specified charmap
 956     *  formats that are capable of mapping 8 or 16 bit character codes to
 957     *  glyph indices.
 958     *
 959     *  However, recent updates to the Apple and OpenType specifications
 960     *  introduced new formats that are capable of mapping 32-bit character
 961     *  codes as well.  And these are already used on some fonts, mainly to
 962     *  map non-BMP Asian ideographs as defined in Unicode.
 963     *
 964     *  For compatibility purposes, these fonts generally come with
 965     *  *several* Unicode charmaps:
 966     *
 967     *   - One of them in the "old" 16-bit format, that cannot access
 968     *     all glyphs in the font.
 969     *
 970     *   - Another one in the "new" 32-bit format, that can access all
 971     *     the glyphs.
 972     *
 973     *  This function has been written to always favor a 32-bit charmap
 974     *  when found.  Otherwise, a 16-bit one is returned when found.
 975     */
 976
 977    /* Since the `interesting' table, with IDs (3,10), is normally the */
 978    /* last one, we loop backwards.  This loses with type1 fonts with  */
 979    /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP  */
 980    /* chars (.01% ?), and this is the same about 99.99% of the time!  */
 981
 982    cur = first + face->num_charmaps;  /* points after the last one */
 983
 984    for ( ; --cur >= first; )
 985    {
 986      if ( cur[0]->encoding == FT_ENCODING_UNICODE )
 987      {
 988        /* XXX If some new encodings to represent UCS-4 are added, */
 989        /*     they should be added here.                          */
 990        if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
 991               cur[0]->encoding_id == TT_MS_ID_UCS_4        )     ||
 992             ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
 993               cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32    ) )
 994        {
 995          face->charmap = cur[0];
 996          return FT_Err_Ok;
 997        }
 998      }
 999    }
1000
1001    /* We do not have any UCS-4 charmap.                */
1002    /* Do the loop again and search for UCS-2 charmaps. */
1003    cur = first + face->num_charmaps;
1004
1005    for ( ; --cur >= first; )
1006    {
1007      if ( cur[0]->encoding == FT_ENCODING_UNICODE )
1008      {
1009        face->charmap = cur[0];
1010        return FT_Err_Ok;
1011      }
1012    }
1013
1014    return FT_Err_Invalid_CharMap_Handle;
1015  }
1016
1017
1018  /*************************************************************************/
1019  /*                                                                       */
1020  /* <Function>                                                            */
1021  /*    find_variant_selector_charmap                                      */
1022  /*                                                                       */
1023  /* <Description>                                                         */
1024  /*    This function finds the variant selector charmap, if there is one. */
1025  /*    There can only be one (platform=0, specific=5, format=14).         */
1026  /*                                                                       */
1027  static FT_CharMap
1028  find_variant_selector_charmap( FT_Face  face )
1029  {
1030    FT_CharMap*  first;
1031    FT_CharMap*  end;
1032    FT_CharMap*  cur;
1033
1034
1035    /* caller should have already checked that `face' is valid */
1036    FT_ASSERT( face );
1037
1038    first = face->charmaps;
1039
1040    if ( !first )
1041      return NULL;
1042
1043    end = first + face->num_charmaps;  /* points after the last one */
1044
1045    for ( cur = first; cur < end; ++cur )
1046    {
1047      if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
1048           cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
1049           FT_Get_CMap_Format( cur[0] ) == 14                  )
1050        return cur[0];
1051    }
1052
1053    return NULL;
1054  }
1055
1056
1057  /*************************************************************************/
1058  /*                                                                       */
1059  /* <Function>                                                            */
1060  /*    open_face                                                          */
1061  /*                                                                       */
1062  /* <Description>                                                         */
1063  /*    This function does some work for FT_Open_Face().                   */
1064  /*                                                                       */
1065  static FT_Error
1066  open_face( FT_Driver      driver,
1067             FT_Stream      stream,
1068             FT_Long        face_index,
1069             FT_Int         num_params,
1070             FT_Parameter*  params,
1071             FT_Face       *aface )
1072  {
1073    FT_Memory         memory;
1074    FT_Driver_Class   clazz;
1075    FT_Face           face = 0;
1076    FT_Error          error, error2;
1077    FT_Face_Internal  internal = NULL;
1078
1079
1080    clazz  = driver->clazz;
1081    memory = driver->root.memory;
1082
1083    /* allocate the face object and perform basic initialization */
1084    if ( FT_ALLOC( face, clazz->face_object_size ) )
1085      goto Fail;
1086
1087    if ( FT_NEW( internal ) )
1088      goto Fail;
1089
1090    face->internal = internal;
1091
1092    face->driver   = driver;
1093    face->memory   = memory;
1094    face->stream   = stream;
1095
1096#ifdef FT_CONFIG_OPTION_INCREMENTAL
1097    {
1098      int  i;
1099
1100
1101      face->internal->incremental_interface = 0;
1102      for ( i = 0; i < num_params && !face->internal->incremental_interface;
1103            i++ )
1104        if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
1105          face->internal->incremental_interface =
1106            (FT_Incremental_Interface)params[i].data;
1107    }
1108#endif
1109
1110    if ( clazz->init_face )
1111      error = clazz->init_face( stream,
1112                                face,
1113                                (FT_Int)face_index,
1114                                num_params,
1115                                params );
1116    if ( error )
1117      goto Fail;
1118
1119    /* select Unicode charmap by default */
1120    error2 = find_unicode_charmap( face );
1121
1122    /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1123    /* is returned.                                                      */
1124
1125    /* no error should happen, but we want to play safe */
1126    if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
1127    {
1128      error = error2;
1129      goto Fail;
1130    }
1131
1132    *aface = face;
1133
1134  Fail:
1135    if ( error )
1136    {
1137      destroy_charmaps( face, memory );
1138      if ( clazz->done_face )
1139        clazz->done_face( face );
1140      FT_FREE( internal );
1141      FT_FREE( face );
1142      *aface = 0;
1143    }
1144
1145    return error;
1146  }
1147
1148
1149  /* there's a Mac-specific extended implementation of FT_New_Face() */
1150  /* in src/base/ftmac.c                                             */
1151
1152#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
1153
1154  /* documentation is in freetype.h */
1155
1156  FT_EXPORT_DEF( FT_Error )
1157  FT_New_Face( FT_Library   library,
1158               const char*  pathname,
1159               FT_Long      face_index,
1160               FT_Face     *aface )
1161  {
1162    FT_Open_Args  args;
1163
1164
1165    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1166    if ( !pathname )
1167      return FT_Err_Invalid_Argument;
1168
1169    args.flags    = FT_OPEN_PATHNAME;
1170    args.pathname = (char*)pathname;
1171    args.stream   = NULL;
1172
1173    return FT_Open_Face( library, &args, face_index, aface );
1174  }
1175
1176#endif  /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
1177
1178
1179  /* documentation is in freetype.h */
1180
1181  FT_EXPORT_DEF( FT_Error )
1182  FT_New_Memory_Face( FT_Library      library,
1183                      const FT_Byte*  file_base,
1184                      FT_Long         file_size,
1185                      FT_Long         face_index,
1186                      FT_Face        *aface )
1187  {
1188    FT_Open_Args  args;
1189
1190
1191    /* test for valid `library' and `face' delayed to FT_Open_Face() */
1192    if ( !file_base )
1193      return FT_Err_Invalid_Argument;
1194
1195    args.flags       = FT_OPEN_MEMORY;
1196    args.memory_base = file_base;
1197    args.memory_size = file_size;
1198    args.stream      = NULL;
1199
1200    return FT_Open_Face( library, &args, face_index, aface );
1201  }
1202
1203
1204#ifdef FT_CONFIG_OPTION_MAC_FONTS
1205
1206  /* The behavior here is very similar to that in base/ftmac.c, but it     */
1207  /* is designed to work on non-mac systems, so no mac specific calls.     */
1208  /*                                                                       */
1209  /* We look at the file and determine if it is a mac dfont file or a mac  */
1210  /* resource file, or a macbinary file containing a mac resource file.    */
1211  /*                                                                       */
1212  /* Unlike ftmac I'm not going to look at a `FOND'.  I don't really see   */
1213  /* the point, especially since there may be multiple `FOND' resources.   */
1214  /* Instead I'll just look for `sfnt' and `POST' resources, ordered as    */
1215  /* they occur in the file.                                               */
1216  /*                                                                       */
1217  /* Note that multiple `POST' resources do not mean multiple postscript   */
1218  /* fonts; they all get jammed together to make what is essentially a     */
1219  /* pfb file.                                                             */
1220  /*                                                                       */
1221  /* We aren't interested in `NFNT' or `FONT' bitmap resources.            */
1222  /*                                                                       */
1223  /* As soon as we get an `sfnt' load it into memory and pass it off to    */
1224  /* FT_Open_Face.                                                         */
1225  /*                                                                       */
1226  /* If we have a (set of) `POST' resources, massage them into a (memory)  */
1227  /* pfb file and pass that to FT_Open_Face.  (As with ftmac.c I'm not     */
1228  /* going to try to save the kerning info.  After all that lives in the   */
1229  /* `FOND' which isn't in the file containing the `POST' resources so     */
1230  /* we don't really have access to it.                                    */
1231
1232
1233  /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
1234  /* It frees the memory it uses.                                  */
1235  /* From ftmac.c.                                                 */
1236  static void
1237  memory_stream_close( FT_Stream  stream )
1238  {
1239    FT_Memory  memory = stream->memory;
1240
1241
1242    FT_FREE( stream->base );
1243
1244    stream->size  = 0;
1245    stream->base  = 0;
1246    stream->close = 0;
1247  }
1248
1249
1250  /* Create a new memory stream from a buffer and a size. */
1251  /* From ftmac.c.                                        */
1252  static FT_Error
1253  new_memory_stream( FT_Library           library,
1254                     FT_Byte*             base,
1255                     FT_ULong             size,
1256                     FT_Stream_CloseFunc  close,
1257                     FT_Stream           *astream )
1258  {
1259    FT_Error   error;
1260    FT_Memory  memory;
1261    FT_Stream  stream;
1262
1263
1264    if ( !library )
1265      return FT_Err_Invalid_Library_Handle;
1266
1267    if ( !base )
1268      return FT_Err_Invalid_Argument;
1269
1270    *astream = 0;
1271    memory = library->memory;
1272    if ( FT_NEW( stream ) )
1273      goto Exit;
1274
1275    FT_Stream_OpenMemory( stream, base, size );
1276
1277    stream->close = close;
1278
1279    *astream = stream;
1280
1281  Exit:
1282    return error;
1283  }
1284
1285
1286  /* Create a new FT_Face given a buffer and a driver name. */
1287  /* from ftmac.c */
1288  FT_LOCAL_DEF( FT_Error )
1289  open_face_from_buffer( FT_Library   library,
1290                         FT_Byte*     base,
1291                         FT_ULong     size,
1292                         FT_Long      face_index,
1293                         const char*  driver_name,
1294                         FT_Face     *aface )
1295  {
1296    FT_Open_Args  args;
1297    FT_Error      error;
1298    FT_Stream     stream = NULL;
1299    FT_Memory     memory = library->memory;
1300
1301
1302    error = new_memory_stream( library,
1303                               base,
1304                               size,
1305                               memory_stream_close,
1306                               &stream );
1307    if ( error )
1308    {
1309      FT_FREE( base );
1310      return error;
1311    }
1312
1313    args.flags = FT_OPEN_STREAM;
1314    args.stream = stream;
1315    if ( driver_name )
1316    {
1317      args.flags = args.flags | FT_OPEN_DRIVER;
1318      args.driver = FT_Get_Module( library, driver_name );
1319    }
1320
1321#ifdef FT_MACINTOSH
1322    /* At this point, face_index has served its purpose;      */
1323    /* whoever calls this function has already used it to     */
1324    /* locate the correct font data.  We should not propagate */
1325    /* this index to FT_Open_Face() (unless it is negative).  */
1326
1327    if ( face_index > 0 )
1328      face_index = 0;
1329#endif
1330
1331    error = FT_Open_Face( library, &args, face_index, aface );
1332
1333    if ( error == FT_Err_Ok )
1334      (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
1335    else
1336#ifdef FT_MACINTOSH
1337      FT_Stream_Free( stream, 0 );
1338#else
1339    {
1340      FT_Stream_Close( stream );
1341      FT_FREE( stream );
1342    }
1343#endif
1344
1345    return error;
1346  }
1347
1348
1349  /* Look up `TYP1' or `CID ' table from sfnt table directory.       */
1350  /* `offset' and `length' must exclude the binary header in tables. */
1351
1352  /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
1353  /* format too.  Here, since we can't expect that the TrueType font */
1354  /* driver is loaded unconditially, we must parse the font by       */
1355  /* ourselves.  We are only interested in the name of the table and */
1356  /* the offset.                                                     */
1357
1358  static FT_Error
1359  ft_lookup_PS_in_sfnt_stream( FT_Stream  stream,
1360                               FT_Long    face_index,
1361                               FT_ULong*  offset,
1362                               FT_ULong*  length,
1363                               FT_Bool*   is_sfnt_cid )
1364  {
1365    FT_Error   error;
1366    FT_UShort  numTables;
1367    FT_Long    pstable_index;
1368    FT_ULong   tag;
1369    int        i;
1370
1371
1372    *offset = 0;
1373    *length = 0;
1374    *is_sfnt_cid = FALSE;
1375
1376    /* TODO: support for sfnt-wrapped PS/CID in TTC format */
1377
1378    /* version check for 'typ1' (should be ignored?) */
1379    if ( FT_READ_ULONG( tag ) )
1380      return error;
1381    if ( tag != TTAG_typ1 )
1382      return FT_Err_Unknown_File_Format;
1383
1384    if ( FT_READ_USHORT( numTables ) )
1385      return error;
1386    if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
1387      return error;
1388
1389    pstable_index = -1;
1390    *is_sfnt_cid  = FALSE;
1391
1392    for ( i = 0; i < numTables; i++ )
1393    {
1394      if ( FT_READ_ULONG( tag )     || FT_STREAM_SKIP( 4 )      ||
1395           FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
1396        return error;
1397
1398      if ( tag == TTAG_CID )
1399      {
1400        pstable_index++;
1401        *offset += 22;
1402        *length -= 22;
1403        *is_sfnt_cid = TRUE;
1404        if ( face_index < 0 )
1405          return FT_Err_Ok;
1406      }
1407      else if ( tag == TTAG_TYP1 )
1408      {
1409        pstable_index++;
1410        *offset += 24;
1411        *length -= 24;
1412        *is_sfnt_cid = FALSE;
1413        if ( face_index < 0 )
1414          return FT_Err_Ok;
1415      }
1416      if ( face_index >= 0 && pstable_index == face_index )
1417        return FT_Err_Ok;
1418    }
1419    return FT_Err_Table_Missing;
1420  }
1421
1422
1423  FT_LOCAL_DEF( FT_Error )
1424  open_face_PS_from_sfnt_stream( FT_Library     library,
1425                                 FT_Stream      stream,
1426                                 FT_Long        face_index,
1427                                 FT_Int         num_params,
1428                                 FT_Parameter  *params,
1429                                 FT_Face       *aface )
1430  {
1431    FT_Error   error;
1432    FT_Memory  memory = library->memory;
1433    FT_ULong   offset, length;
1434    FT_Long    pos;
1435    FT_Bool    is_sfnt_cid;
1436    FT_Byte*   sfnt_ps;
1437
1438    FT_UNUSED( num_params );
1439    FT_UNUSED( params );
1440
1441
1442    pos = FT_Stream_Pos( stream );
1443
1444    error = ft_lookup_PS_in_sfnt_stream( stream,
1445                                         face_index,
1446                                         &offset,
1447                                         &length,
1448                                         &is_sfnt_cid );
1449    if ( error )
1450      goto Exit;
1451
1452    if ( FT_Stream_Seek( stream, pos + offset ) )
1453      goto Exit;
1454
1455    if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
1456      goto Exit;
1457
1458    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
1459    if ( error )
1460      goto Exit;
1461
1462    error = open_face_from_buffer( library,
1463                                   sfnt_ps,
1464                                   length,
1465                                   face_index < 0 ? face_index : 0,
1466                                   is_sfnt_cid ? "cid" : "type1",
1467                                   aface );
1468  Exit:
1469    {
1470      FT_Error  error1;
1471
1472
1473      if ( error == FT_Err_Unknown_File_Format )
1474      {
1475        error1 = FT_Stream_Seek( stream, pos );
1476        if ( error1 )
1477          return error1;
1478      }
1479
1480      return error;
1481    }
1482  }
1483
1484
1485#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
1486
1487  /* The resource header says we've got resource_cnt `POST' (type1) */
1488  /* resources in this file.  They all need to be coalesced into    */
1489  /* one lump which gets passed on to the type1 driver.             */
1490  /* Here can be only one PostScript font in a file so face_index   */
1491  /* must be 0 (or -1).                                             */
1492  /*                                                                */
1493  static FT_Error
1494  Mac_Read_POST_Resource( FT_Library  library,
1495                          FT_Stream   stream,
1496                          FT_Long    *offsets,
1497                          FT_Long     resource_cnt,
1498                          FT_Long     face_index,
1499                          FT_Face    *aface )
1500  {
1501    FT_Error   error  = FT_Err_Cannot_Open_Resource;
1502    FT_Memory  memory = library->memory;
1503    FT_Byte*   pfb_data;
1504    int        i, type, flags;
1505    FT_Long    len;
1506    FT_Long    pfb_len, pfb_pos, pfb_lenpos;
1507    FT_Long    rlen, temp;
1508
1509
1510    if ( face_index == -1 )
1511      face_index = 0;
1512    if ( face_index != 0 )
1513      return error;
1514
1515    /* Find the length of all the POST resources, concatenated.  Assume */
1516    /* worst case (each resource in its own section).                   */
1517    pfb_len = 0;
1518    for ( i = 0; i < resource_cnt; ++i )
1519    {
1520      error = FT_Stream_Seek( stream, offsets[i] );
1521      if ( error )
1522        goto Exit;
1523      if ( FT_READ_LONG( temp ) )
1524        goto Exit;
1525      pfb_len += temp + 6;
1526    }
1527
1528    if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
1529      goto Exit;
1530
1531    pfb_data[0] = 0x80;
1532    pfb_data[1] = 1;            /* Ascii section */
1533    pfb_data[2] = 0;            /* 4-byte length, fill in later */
1534    pfb_data[3] = 0;
1535    pfb_data[4] = 0;
1536    pfb_data[5] = 0;
1537    pfb_pos     = 6;
1538    pfb_lenpos  = 2;
1539
1540    len = 0;
1541    type = 1;
1542    for ( i = 0; i < resource_cnt; ++i )
1543    {
1544      error = FT_Stream_Seek( stream, offsets[i] );
1545      if ( error )
1546        goto Exit2;
1547      if ( FT_READ_LONG( rlen ) )
1548        goto Exit;
1549      if ( FT_READ_USHORT( flags ) )
1550        goto Exit;
1551      rlen -= 2;                    /* the flags are part of the resource */
1552      if ( ( flags >> 8 ) == type )
1553        len += rlen;
1554      else
1555      {
1556        pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
1557        pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1558        pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1559        pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
1560
1561        if ( ( flags >> 8 ) == 5 )      /* End of font mark */
1562          break;
1563
1564        pfb_data[pfb_pos++] = 0x80;
1565
1566        type = flags >> 8;
1567        len = rlen;
1568
1569        pfb_data[pfb_pos++] = (FT_Byte)type;
1570        pfb_lenpos          = pfb_pos;
1571        pfb_data[pfb_pos++] = 0;        /* 4-byte length, fill in later */
1572        pfb_data[pfb_pos++] = 0;
1573        pfb_data[pfb_pos++] = 0;
1574        pfb_data[pfb_pos++] = 0;
1575      }
1576
1577      error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
1578      pfb_pos += rlen;
1579    }
1580
1581    pfb_data[pfb_pos++] = 0x80;
1582    pfb_data[pfb_pos++] = 3;
1583
1584    pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
1585    pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
1586    pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
1587    pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
1588
1589    return open_face_from_buffer( library,
1590                                  pfb_data,
1591                                  pfb_pos,
1592                                  face_index,
1593                                  "type1",
1594                                  aface );
1595
1596  Exit2:
1597    FT_FREE( pfb_data );
1598
1599  Exit:
1600    return error;
1601  }
1602
1603
1604  /* The resource header says we've got resource_cnt `sfnt'      */
1605  /* (TrueType/OpenType) resources in this file.  Look through   */
1606  /* them for the one indicated by face_index, load it into mem, */
1607  /* pass it on the the truetype driver and return it.           */
1608  /*                                                             */
1609  static FT_Error
1610  Mac_Read_sfnt_Resource( FT_Library  library,
1611                          FT_Stream   stream,
1612                          FT_Long    *offsets,
1613                          FT_Long     resource_cnt,
1614                          FT_Long     face_index,
1615                          FT_Face    *aface )
1616  {
1617    FT_Memory  memory = library->memory;
1618    FT_Byte*   sfnt_data;
1619    FT_Error   error;
1620    FT_Long    flag_offset;
1621    FT_Long    rlen;
1622    int        is_cff;
1623    FT_Long    face_index_in_resource = 0;
1624
1625
1626    if ( face_index == -1 )
1627      face_index = 0;
1628    if ( face_index >= resource_cnt )
1629      return FT_Err_Cannot_Open_Resource;
1630
1631    flag_offset = offsets[face_index];
1632    error = FT_Stream_Seek( stream, flag_offset );
1633    if ( error )
1634      goto Exit;
1635
1636    if ( FT_READ_LONG( rlen ) )
1637      goto Exit;
1638    if ( rlen == -1 )
1639      return FT_Err_Cannot_Open_Resource;
1640
1641    error = open_face_PS_from_sfnt_stream( library,
1642                                           stream,
1643                                           face_index,
1644                                           0, NULL,
1645                                           aface );
1646    if ( !error )
1647      goto Exit;
1648
1649    /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
1650    if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
1651      goto Exit;
1652
1653    if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
1654      return error;
1655    error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
1656    if ( error )
1657      goto Exit;
1658
1659    is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
1660    error = open_face_from_buffer( library,
1661                                   sfnt_data,
1662    

Large files files are truncated, but you can click here to view the full file