misc/libfreetype/src/base/ftobjs.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftobjs.c                                                               */
       
     4 /*                                                                         */
       
     5 /*    The FreeType private base classes (body).                            */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2011 by                                                 */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    10 /*  This file is part of the FreeType project, and may only be used,       */
       
    11 /*  modified, and distributed under the terms of the FreeType project      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19 #include <ft2build.h>
       
    20 #include FT_LIST_H
       
    21 #include FT_OUTLINE_H
       
    22 #include FT_INTERNAL_VALIDATE_H
       
    23 #include FT_INTERNAL_OBJECTS_H
       
    24 #include FT_INTERNAL_DEBUG_H
       
    25 #include FT_INTERNAL_RFORK_H
       
    26 #include FT_INTERNAL_STREAM_H
       
    27 #include FT_INTERNAL_SFNT_H    /* for SFNT_Load_Table_Func */
       
    28 #include FT_TRUETYPE_TABLES_H
       
    29 #include FT_TRUETYPE_TAGS_H
       
    30 #include FT_TRUETYPE_IDS_H
       
    31 
       
    32 #include FT_SERVICE_SFNT_H
       
    33 #include FT_SERVICE_POSTSCRIPT_NAME_H
       
    34 #include FT_SERVICE_GLYPH_DICT_H
       
    35 #include FT_SERVICE_TT_CMAP_H
       
    36 #include FT_SERVICE_KERNING_H
       
    37 #include FT_SERVICE_TRUETYPE_ENGINE_H
       
    38 
       
    39 #ifdef FT_CONFIG_OPTION_MAC_FONTS
       
    40 #include "ftbase.h"
       
    41 #endif
       
    42 
       
    43 #define GRID_FIT_METRICS
       
    44 
       
    45 
       
    46   FT_BASE_DEF( FT_Pointer )
       
    47   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
       
    48                           const char*     service_id )
       
    49   {
       
    50     FT_Pointer      result = NULL;
       
    51     FT_ServiceDesc  desc   = service_descriptors;
       
    52 
       
    53 
       
    54     if ( desc && service_id )
       
    55     {
       
    56       for ( ; desc->serv_id != NULL; desc++ )
       
    57       {
       
    58         if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
       
    59         {
       
    60           result = (FT_Pointer)desc->serv_data;
       
    61           break;
       
    62         }
       
    63       }
       
    64     }
       
    65 
       
    66     return result;
       
    67   }
       
    68 
       
    69 
       
    70   FT_BASE_DEF( void )
       
    71   ft_validator_init( FT_Validator        valid,
       
    72                      const FT_Byte*      base,
       
    73                      const FT_Byte*      limit,
       
    74                      FT_ValidationLevel  level )
       
    75   {
       
    76     valid->base  = base;
       
    77     valid->limit = limit;
       
    78     valid->level = level;
       
    79     valid->error = FT_Err_Ok;
       
    80   }
       
    81 
       
    82 
       
    83   FT_BASE_DEF( FT_Int )
       
    84   ft_validator_run( FT_Validator  valid )
       
    85   {
       
    86     /* This function doesn't work!  None should call it. */
       
    87     FT_UNUSED( valid );
       
    88 
       
    89     return -1;
       
    90   }
       
    91 
       
    92 
       
    93   FT_BASE_DEF( void )
       
    94   ft_validator_error( FT_Validator  valid,
       
    95                       FT_Error      error )
       
    96   {
       
    97     /* since the cast below also disables the compiler's */
       
    98     /* type check, we introduce a dummy variable, which  */
       
    99     /* will be optimized away                            */
       
   100     volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
       
   101 
       
   102 
       
   103     valid->error = error;
       
   104 
       
   105     /* throw away volatileness; use `jump_buffer' or the  */
       
   106     /* compiler may warn about an unused local variable   */
       
   107     ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
       
   108   }
       
   109 
       
   110 
       
   111   /*************************************************************************/
       
   112   /*************************************************************************/
       
   113   /*************************************************************************/
       
   114   /****                                                                 ****/
       
   115   /****                                                                 ****/
       
   116   /****                           S T R E A M                           ****/
       
   117   /****                                                                 ****/
       
   118   /****                                                                 ****/
       
   119   /*************************************************************************/
       
   120   /*************************************************************************/
       
   121   /*************************************************************************/
       
   122 
       
   123 
       
   124   /* create a new input stream from an FT_Open_Args structure */
       
   125   /*                                                          */
       
   126   FT_BASE_DEF( FT_Error )
       
   127   FT_Stream_New( FT_Library           library,
       
   128                  const FT_Open_Args*  args,
       
   129                  FT_Stream           *astream )
       
   130   {
       
   131     FT_Error   error;
       
   132     FT_Memory  memory;
       
   133     FT_Stream  stream;
       
   134 
       
   135 
       
   136     *astream = 0;
       
   137 
       
   138     if ( !library )
       
   139       return FT_Err_Invalid_Library_Handle;
       
   140 
       
   141     if ( !args )
       
   142       return FT_Err_Invalid_Argument;
       
   143 
       
   144     memory = library->memory;
       
   145 
       
   146     if ( FT_NEW( stream ) )
       
   147       goto Exit;
       
   148 
       
   149     stream->memory = memory;
       
   150 
       
   151     if ( args->flags & FT_OPEN_MEMORY )
       
   152     {
       
   153       /* create a memory-based stream */
       
   154       FT_Stream_OpenMemory( stream,
       
   155                             (const FT_Byte*)args->memory_base,
       
   156                             args->memory_size );
       
   157     }
       
   158     else if ( args->flags & FT_OPEN_PATHNAME )
       
   159     {
       
   160       /* create a normal system stream */
       
   161       error = FT_Stream_Open( stream, args->pathname );
       
   162       stream->pathname.pointer = args->pathname;
       
   163     }
       
   164     else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
       
   165     {
       
   166       /* use an existing, user-provided stream */
       
   167 
       
   168       /* in this case, we do not need to allocate a new stream object */
       
   169       /* since the caller is responsible for closing it himself       */
       
   170       FT_FREE( stream );
       
   171       stream = args->stream;
       
   172     }
       
   173     else
       
   174       error = FT_Err_Invalid_Argument;
       
   175 
       
   176     if ( error )
       
   177       FT_FREE( stream );
       
   178     else
       
   179       stream->memory = memory;  /* just to be certain */
       
   180 
       
   181     *astream = stream;
       
   182 
       
   183   Exit:
       
   184     return error;
       
   185   }
       
   186 
       
   187 
       
   188   FT_BASE_DEF( void )
       
   189   FT_Stream_Free( FT_Stream  stream,
       
   190                   FT_Int     external )
       
   191   {
       
   192     if ( stream )
       
   193     {
       
   194       FT_Memory  memory = stream->memory;
       
   195 
       
   196 
       
   197       FT_Stream_Close( stream );
       
   198 
       
   199       if ( !external )
       
   200         FT_FREE( stream );
       
   201     }
       
   202   }
       
   203 
       
   204 
       
   205   /*************************************************************************/
       
   206   /*                                                                       */
       
   207   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
   208   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
   209   /* messages during execution.                                            */
       
   210   /*                                                                       */
       
   211 #undef  FT_COMPONENT
       
   212 #define FT_COMPONENT  trace_objs
       
   213 
       
   214 
       
   215   /*************************************************************************/
       
   216   /*************************************************************************/
       
   217   /*************************************************************************/
       
   218   /****                                                                 ****/
       
   219   /****                                                                 ****/
       
   220   /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
       
   221   /****                                                                 ****/
       
   222   /****                                                                 ****/
       
   223   /*************************************************************************/
       
   224   /*************************************************************************/
       
   225   /*************************************************************************/
       
   226 
       
   227 
       
   228   static FT_Error
       
   229   ft_glyphslot_init( FT_GlyphSlot  slot )
       
   230   {
       
   231     FT_Driver         driver   = slot->face->driver;
       
   232     FT_Driver_Class   clazz    = driver->clazz;
       
   233     FT_Memory         memory   = driver->root.memory;
       
   234     FT_Error          error    = FT_Err_Ok;
       
   235     FT_Slot_Internal  internal = NULL;
       
   236 
       
   237 
       
   238     slot->library = driver->root.library;
       
   239 
       
   240     if ( FT_NEW( internal ) )
       
   241       goto Exit;
       
   242 
       
   243     slot->internal = internal;
       
   244 
       
   245     if ( FT_DRIVER_USES_OUTLINES( driver ) )
       
   246       error = FT_GlyphLoader_New( memory, &internal->loader );
       
   247 
       
   248     if ( !error && clazz->init_slot )
       
   249       error = clazz->init_slot( slot );
       
   250 
       
   251   Exit:
       
   252     return error;
       
   253   }
       
   254 
       
   255 
       
   256   FT_BASE_DEF( void )
       
   257   ft_glyphslot_free_bitmap( FT_GlyphSlot  slot )
       
   258   {
       
   259     if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
       
   260     {
       
   261       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
       
   262 
       
   263 
       
   264       FT_FREE( slot->bitmap.buffer );
       
   265       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
       
   266     }
       
   267     else
       
   268     {
       
   269       /* assume that the bitmap buffer was stolen or not */
       
   270       /* allocated from the heap                         */
       
   271       slot->bitmap.buffer = NULL;
       
   272     }
       
   273   }
       
   274 
       
   275 
       
   276   FT_BASE_DEF( void )
       
   277   ft_glyphslot_set_bitmap( FT_GlyphSlot  slot,
       
   278                            FT_Byte*      buffer )
       
   279   {
       
   280     ft_glyphslot_free_bitmap( slot );
       
   281 
       
   282     slot->bitmap.buffer = buffer;
       
   283 
       
   284     FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
       
   285   }
       
   286 
       
   287 
       
   288   FT_BASE_DEF( FT_Error )
       
   289   ft_glyphslot_alloc_bitmap( FT_GlyphSlot  slot,
       
   290                              FT_ULong      size )
       
   291   {
       
   292     FT_Memory  memory = FT_FACE_MEMORY( slot->face );
       
   293     FT_Error   error;
       
   294 
       
   295 
       
   296     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
       
   297       FT_FREE( slot->bitmap.buffer );
       
   298     else
       
   299       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
       
   300 
       
   301     (void)FT_ALLOC( slot->bitmap.buffer, size );
       
   302     return error;
       
   303   }
       
   304 
       
   305 
       
   306   static void
       
   307   ft_glyphslot_clear( FT_GlyphSlot  slot )
       
   308   {
       
   309     /* free bitmap if needed */
       
   310     ft_glyphslot_free_bitmap( slot );
       
   311 
       
   312     /* clear all public fields in the glyph slot */
       
   313     FT_ZERO( &slot->metrics );
       
   314     FT_ZERO( &slot->outline );
       
   315 
       
   316     slot->bitmap.width      = 0;
       
   317     slot->bitmap.rows       = 0;
       
   318     slot->bitmap.pitch      = 0;
       
   319     slot->bitmap.pixel_mode = 0;
       
   320     /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
       
   321 
       
   322     slot->bitmap_left   = 0;
       
   323     slot->bitmap_top    = 0;
       
   324     slot->num_subglyphs = 0;
       
   325     slot->subglyphs     = 0;
       
   326     slot->control_data  = 0;
       
   327     slot->control_len   = 0;
       
   328     slot->other         = 0;
       
   329     slot->format        = FT_GLYPH_FORMAT_NONE;
       
   330 
       
   331     slot->linearHoriAdvance = 0;
       
   332     slot->linearVertAdvance = 0;
       
   333     slot->lsb_delta         = 0;
       
   334     slot->rsb_delta         = 0;
       
   335   }
       
   336 
       
   337 
       
   338   static void
       
   339   ft_glyphslot_done( FT_GlyphSlot  slot )
       
   340   {
       
   341     FT_Driver        driver = slot->face->driver;
       
   342     FT_Driver_Class  clazz  = driver->clazz;
       
   343     FT_Memory        memory = driver->root.memory;
       
   344 
       
   345 
       
   346     if ( clazz->done_slot )
       
   347       clazz->done_slot( slot );
       
   348 
       
   349     /* free bitmap buffer if needed */
       
   350     ft_glyphslot_free_bitmap( slot );
       
   351 
       
   352     /* slot->internal might be NULL in out-of-memory situations */
       
   353     if ( slot->internal )
       
   354     {
       
   355       /* free glyph loader */
       
   356       if ( FT_DRIVER_USES_OUTLINES( driver ) )
       
   357       {
       
   358         FT_GlyphLoader_Done( slot->internal->loader );
       
   359         slot->internal->loader = 0;
       
   360       }
       
   361 
       
   362       FT_FREE( slot->internal );
       
   363     }
       
   364   }
       
   365 
       
   366 
       
   367   /* documentation is in ftobjs.h */
       
   368 
       
   369   FT_BASE_DEF( FT_Error )
       
   370   FT_New_GlyphSlot( FT_Face        face,
       
   371                     FT_GlyphSlot  *aslot )
       
   372   {
       
   373     FT_Error         error;
       
   374     FT_Driver        driver;
       
   375     FT_Driver_Class  clazz;
       
   376     FT_Memory        memory;
       
   377     FT_GlyphSlot     slot;
       
   378 
       
   379 
       
   380     if ( !face || !face->driver )
       
   381       return FT_Err_Invalid_Argument;
       
   382 
       
   383     driver = face->driver;
       
   384     clazz  = driver->clazz;
       
   385     memory = driver->root.memory;
       
   386 
       
   387     FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
       
   388     if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
       
   389     {
       
   390       slot->face = face;
       
   391 
       
   392       error = ft_glyphslot_init( slot );
       
   393       if ( error )
       
   394       {
       
   395         ft_glyphslot_done( slot );
       
   396         FT_FREE( slot );
       
   397         goto Exit;
       
   398       }
       
   399 
       
   400       slot->next  = face->glyph;
       
   401       face->glyph = slot;
       
   402 
       
   403       if ( aslot )
       
   404         *aslot = slot;
       
   405     }
       
   406     else if ( aslot )
       
   407       *aslot = 0;
       
   408 
       
   409 
       
   410   Exit:
       
   411     FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
       
   412     return error;
       
   413   }
       
   414 
       
   415 
       
   416   /* documentation is in ftobjs.h */
       
   417 
       
   418   FT_BASE_DEF( void )
       
   419   FT_Done_GlyphSlot( FT_GlyphSlot  slot )
       
   420   {
       
   421     if ( slot )
       
   422     {
       
   423       FT_Driver     driver = slot->face->driver;
       
   424       FT_Memory     memory = driver->root.memory;
       
   425       FT_GlyphSlot  prev;
       
   426       FT_GlyphSlot  cur;
       
   427 
       
   428 
       
   429       /* Remove slot from its parent face's list */
       
   430       prev = NULL;
       
   431       cur  = slot->face->glyph;
       
   432 
       
   433       while ( cur )
       
   434       {
       
   435         if ( cur == slot )
       
   436         {
       
   437           if ( !prev )
       
   438             slot->face->glyph = cur->next;
       
   439           else
       
   440             prev->next = cur->next;
       
   441 
       
   442           ft_glyphslot_done( slot );
       
   443           FT_FREE( slot );
       
   444           break;
       
   445         }
       
   446         prev = cur;
       
   447         cur  = cur->next;
       
   448       }
       
   449     }
       
   450   }
       
   451 
       
   452 
       
   453   /* documentation is in freetype.h */
       
   454 
       
   455   FT_EXPORT_DEF( void )
       
   456   FT_Set_Transform( FT_Face     face,
       
   457                     FT_Matrix*  matrix,
       
   458                     FT_Vector*  delta )
       
   459   {
       
   460     FT_Face_Internal  internal;
       
   461 
       
   462 
       
   463     if ( !face )
       
   464       return;
       
   465 
       
   466     internal = face->internal;
       
   467 
       
   468     internal->transform_flags = 0;
       
   469 
       
   470     if ( !matrix )
       
   471     {
       
   472       internal->transform_matrix.xx = 0x10000L;
       
   473       internal->transform_matrix.xy = 0;
       
   474       internal->transform_matrix.yx = 0;
       
   475       internal->transform_matrix.yy = 0x10000L;
       
   476       matrix = &internal->transform_matrix;
       
   477     }
       
   478     else
       
   479       internal->transform_matrix = *matrix;
       
   480 
       
   481     /* set transform_flags bit flag 0 if `matrix' isn't the identity */
       
   482     if ( ( matrix->xy | matrix->yx ) ||
       
   483          matrix->xx != 0x10000L      ||
       
   484          matrix->yy != 0x10000L      )
       
   485       internal->transform_flags |= 1;
       
   486 
       
   487     if ( !delta )
       
   488     {
       
   489       internal->transform_delta.x = 0;
       
   490       internal->transform_delta.y = 0;
       
   491       delta = &internal->transform_delta;
       
   492     }
       
   493     else
       
   494       internal->transform_delta = *delta;
       
   495 
       
   496     /* set transform_flags bit flag 1 if `delta' isn't the null vector */
       
   497     if ( delta->x | delta->y )
       
   498       internal->transform_flags |= 2;
       
   499   }
       
   500 
       
   501 
       
   502   static FT_Renderer
       
   503   ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
       
   504 
       
   505 
       
   506 #ifdef GRID_FIT_METRICS
       
   507   static void
       
   508   ft_glyphslot_grid_fit_metrics( FT_GlyphSlot  slot,
       
   509                                  FT_Bool       vertical )
       
   510   {
       
   511     FT_Glyph_Metrics*  metrics = &slot->metrics;
       
   512     FT_Pos             right, bottom;
       
   513 
       
   514 
       
   515     if ( vertical )
       
   516     {
       
   517       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
       
   518       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
       
   519 
       
   520       right  = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
       
   521       bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
       
   522 
       
   523       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
       
   524       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
       
   525 
       
   526       metrics->width  = right - metrics->vertBearingX;
       
   527       metrics->height = bottom - metrics->vertBearingY;
       
   528     }
       
   529     else
       
   530     {
       
   531       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
       
   532       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
       
   533 
       
   534       right  = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
       
   535       bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
       
   536 
       
   537       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
       
   538       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
       
   539 
       
   540       metrics->width  = right - metrics->horiBearingX;
       
   541       metrics->height = metrics->horiBearingY - bottom;
       
   542     }
       
   543 
       
   544     metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
       
   545     metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
       
   546   }
       
   547 #endif /* GRID_FIT_METRICS */
       
   548 
       
   549 
       
   550   /* documentation is in freetype.h */
       
   551 
       
   552   FT_EXPORT_DEF( FT_Error )
       
   553   FT_Load_Glyph( FT_Face   face,
       
   554                  FT_UInt   glyph_index,
       
   555                  FT_Int32  load_flags )
       
   556   {
       
   557     FT_Error      error;
       
   558     FT_Driver     driver;
       
   559     FT_GlyphSlot  slot;
       
   560     FT_Library    library;
       
   561     FT_Bool       autohint = FALSE;
       
   562     FT_Module     hinter;
       
   563     TT_Face       ttface = (TT_Face)face;
       
   564 
       
   565 
       
   566     if ( !face || !face->size || !face->glyph )
       
   567       return FT_Err_Invalid_Face_Handle;
       
   568 
       
   569     /* The validity test for `glyph_index' is performed by the */
       
   570     /* font drivers.                                           */
       
   571 
       
   572     slot = face->glyph;
       
   573     ft_glyphslot_clear( slot );
       
   574 
       
   575     driver  = face->driver;
       
   576     library = driver->root.library;
       
   577     hinter  = library->auto_hinter;
       
   578 
       
   579     /* resolve load flags dependencies */
       
   580 
       
   581     if ( load_flags & FT_LOAD_NO_RECURSE )
       
   582       load_flags |= FT_LOAD_NO_SCALE         |
       
   583                     FT_LOAD_IGNORE_TRANSFORM;
       
   584 
       
   585     if ( load_flags & FT_LOAD_NO_SCALE )
       
   586     {
       
   587       load_flags |= FT_LOAD_NO_HINTING |
       
   588                     FT_LOAD_NO_BITMAP;
       
   589 
       
   590       load_flags &= ~FT_LOAD_RENDER;
       
   591     }
       
   592 
       
   593     /*
       
   594      * Determine whether we need to auto-hint or not.
       
   595      * The general rules are:
       
   596      *
       
   597      * - Do only auto-hinting if we have a hinter module, a scalable font
       
   598      *   format dealing with outlines, and no transforms except simple
       
   599      *   slants and/or rotations by integer multiples of 90 degrees.
       
   600      *
       
   601      * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
       
   602      *   have a native font hinter.
       
   603      *
       
   604      * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
       
   605      *   any hinting bytecode in the TrueType/OpenType font.
       
   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         /* the check for `num_locations' assures that we actually    */
       
   631         /* test for instructions in a TTF and not in a CFF-based OTF */
       
   632         if ( mode == FT_RENDER_MODE_LIGHT                       ||
       
   633              face->internal->ignore_unpatented_hinter           ||
       
   634              ( FT_IS_SFNT( face )                             &&
       
   635                ttface->num_locations                          &&
       
   636                ttface->max_profile.maxSizeOfInstructions == 0 ) )
       
   637           autohint = TRUE;
       
   638       }
       
   639     }
       
   640 
       
   641     if ( autohint )
       
   642     {
       
   643       FT_AutoHinter_Service  hinting;
       
   644 
       
   645 
       
   646       /* try to load embedded bitmaps first if available            */
       
   647       /*                                                            */
       
   648       /* XXX: This is really a temporary hack that should disappear */
       
   649       /*      promptly with FreeType 2.1!                           */
       
   650       /*                                                            */
       
   651       if ( FT_HAS_FIXED_SIZES( face )             &&
       
   652           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
       
   653       {
       
   654         error = driver->clazz->load_glyph( slot, face->size,
       
   655                                            glyph_index,
       
   656                                            load_flags | FT_LOAD_SBITS_ONLY );
       
   657 
       
   658         if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
       
   659           goto Load_Ok;
       
   660       }
       
   661 
       
   662       {
       
   663         FT_Face_Internal  internal        = face->internal;
       
   664         FT_Int            transform_flags = internal->transform_flags;
       
   665 
       
   666 
       
   667         /* since the auto-hinter calls FT_Load_Glyph by itself, */
       
   668         /* make sure that glyphs aren't transformed             */
       
   669         internal->transform_flags = 0;
       
   670 
       
   671         /* load auto-hinted outline */
       
   672         hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
       
   673 
       
   674         error   = hinting->load_glyph( (FT_AutoHinter)hinter,
       
   675                                        slot, face->size,
       
   676                                        glyph_index, load_flags );
       
   677 
       
   678         internal->transform_flags = transform_flags;
       
   679       }
       
   680     }
       
   681     else
       
   682     {
       
   683       error = driver->clazz->load_glyph( slot,
       
   684                                          face->size,
       
   685                                          glyph_index,
       
   686                                          load_flags );
       
   687       if ( error )
       
   688         goto Exit;
       
   689 
       
   690       if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
       
   691       {
       
   692         /* check that the loaded outline is correct */
       
   693         error = FT_Outline_Check( &slot->outline );
       
   694         if ( error )
       
   695           goto Exit;
       
   696 
       
   697 #ifdef GRID_FIT_METRICS
       
   698         if ( !( load_flags & FT_LOAD_NO_HINTING ) )
       
   699           ft_glyphslot_grid_fit_metrics( slot,
       
   700               FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
       
   701 #endif
       
   702       }
       
   703     }
       
   704 
       
   705   Load_Ok:
       
   706     /* compute the advance */
       
   707     if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
       
   708     {
       
   709       slot->advance.x = 0;
       
   710       slot->advance.y = slot->metrics.vertAdvance;
       
   711     }
       
   712     else
       
   713     {
       
   714       slot->advance.x = slot->metrics.horiAdvance;
       
   715       slot->advance.y = 0;
       
   716     }
       
   717 
       
   718     /* compute the linear advance in 16.16 pixels */
       
   719     if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
       
   720          ( FT_IS_SCALABLE( face ) )                  )
       
   721     {
       
   722       FT_Size_Metrics*  metrics = &face->size->metrics;
       
   723 
       
   724 
       
   725       /* it's tricky! */
       
   726       slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
       
   727                                            metrics->x_scale, 64 );
       
   728 
       
   729       slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
       
   730                                            metrics->y_scale, 64 );
       
   731     }
       
   732 
       
   733     if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
       
   734     {
       
   735       FT_Face_Internal  internal = face->internal;
       
   736 
       
   737 
       
   738       /* now, transform the glyph image if needed */
       
   739       if ( internal->transform_flags )
       
   740       {
       
   741         /* get renderer */
       
   742         FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
       
   743 
       
   744 
       
   745         if ( renderer )
       
   746           error = renderer->clazz->transform_glyph(
       
   747                                      renderer, slot,
       
   748                                      &internal->transform_matrix,
       
   749                                      &internal->transform_delta );
       
   750         else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
       
   751         {
       
   752           /* apply `standard' transformation if no renderer is available */
       
   753           if ( &internal->transform_matrix )
       
   754             FT_Outline_Transform( &slot->outline,
       
   755                                   &internal->transform_matrix );
       
   756 
       
   757           if ( &internal->transform_delta )
       
   758             FT_Outline_Translate( &slot->outline,
       
   759                                   internal->transform_delta.x,
       
   760                                   internal->transform_delta.y );
       
   761         }
       
   762 
       
   763         /* transform advance */
       
   764         FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
       
   765       }
       
   766     }
       
   767 
       
   768     FT_TRACE5(( "  x advance: %d\n" , slot->advance.x ));
       
   769     FT_TRACE5(( "  y advance: %d\n" , slot->advance.y ));
       
   770 
       
   771     FT_TRACE5(( "  linear x advance: %d\n" , slot->linearHoriAdvance ));
       
   772     FT_TRACE5(( "  linear y advance: %d\n" , slot->linearVertAdvance ));
       
   773 
       
   774     /* do we need to render the image now? */
       
   775     if ( !error                                    &&
       
   776          slot->format != FT_GLYPH_FORMAT_BITMAP    &&
       
   777          slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
       
   778          load_flags & FT_LOAD_RENDER )
       
   779     {
       
   780       FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
       
   781 
       
   782 
       
   783       if ( mode == FT_RENDER_MODE_NORMAL      &&
       
   784            (load_flags & FT_LOAD_MONOCHROME ) )
       
   785         mode = FT_RENDER_MODE_MONO;
       
   786 
       
   787       error = FT_Render_Glyph( slot, mode );
       
   788     }
       
   789 
       
   790   Exit:
       
   791     return error;
       
   792   }
       
   793 
       
   794 
       
   795   /* documentation is in freetype.h */
       
   796 
       
   797   FT_EXPORT_DEF( FT_Error )
       
   798   FT_Load_Char( FT_Face   face,
       
   799                 FT_ULong  char_code,
       
   800                 FT_Int32  load_flags )
       
   801   {
       
   802     FT_UInt  glyph_index;
       
   803 
       
   804 
       
   805     if ( !face )
       
   806       return FT_Err_Invalid_Face_Handle;
       
   807 
       
   808     glyph_index = (FT_UInt)char_code;
       
   809     if ( face->charmap )
       
   810       glyph_index = FT_Get_Char_Index( face, char_code );
       
   811 
       
   812     return FT_Load_Glyph( face, glyph_index, load_flags );
       
   813   }
       
   814 
       
   815 
       
   816   /* destructor for sizes list */
       
   817   static void
       
   818   destroy_size( FT_Memory  memory,
       
   819                 FT_Size    size,
       
   820                 FT_Driver  driver )
       
   821   {
       
   822     /* finalize client-specific data */
       
   823     if ( size->generic.finalizer )
       
   824       size->generic.finalizer( size );
       
   825 
       
   826     /* finalize format-specific stuff */
       
   827     if ( driver->clazz->done_size )
       
   828       driver->clazz->done_size( size );
       
   829 
       
   830     FT_FREE( size->internal );
       
   831     FT_FREE( size );
       
   832   }
       
   833 
       
   834 
       
   835   static void
       
   836   ft_cmap_done_internal( FT_CMap  cmap );
       
   837 
       
   838 
       
   839   static void
       
   840   destroy_charmaps( FT_Face    face,
       
   841                     FT_Memory  memory )
       
   842   {
       
   843     FT_Int  n;
       
   844 
       
   845 
       
   846     if ( !face )
       
   847       return;
       
   848 
       
   849     for ( n = 0; n < face->num_charmaps; n++ )
       
   850     {
       
   851       FT_CMap  cmap = FT_CMAP( face->charmaps[n] );
       
   852 
       
   853 
       
   854       ft_cmap_done_internal( cmap );
       
   855 
       
   856       face->charmaps[n] = NULL;
       
   857     }
       
   858 
       
   859     FT_FREE( face->charmaps );
       
   860     face->num_charmaps = 0;
       
   861   }
       
   862 
       
   863 
       
   864   /* destructor for faces list */
       
   865   static void
       
   866   destroy_face( FT_Memory  memory,
       
   867                 FT_Face    face,
       
   868                 FT_Driver  driver )
       
   869   {
       
   870     FT_Driver_Class  clazz = driver->clazz;
       
   871 
       
   872 
       
   873     /* discard auto-hinting data */
       
   874     if ( face->autohint.finalizer )
       
   875       face->autohint.finalizer( face->autohint.data );
       
   876 
       
   877     /* Discard glyph slots for this face.                           */
       
   878     /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
       
   879     while ( face->glyph )
       
   880       FT_Done_GlyphSlot( face->glyph );
       
   881 
       
   882     /* discard all sizes for this face */
       
   883     FT_List_Finalize( &face->sizes_list,
       
   884                       (FT_List_Destructor)destroy_size,
       
   885                       memory,
       
   886                       driver );
       
   887     face->size = 0;
       
   888 
       
   889     /* now discard client data */
       
   890     if ( face->generic.finalizer )
       
   891       face->generic.finalizer( face );
       
   892 
       
   893     /* discard charmaps */
       
   894     destroy_charmaps( face, memory );
       
   895 
       
   896     /* finalize format-specific stuff */
       
   897     if ( clazz->done_face )
       
   898       clazz->done_face( face );
       
   899 
       
   900     /* close the stream for this face if needed */
       
   901     FT_Stream_Free(
       
   902       face->stream,
       
   903       ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
       
   904 
       
   905     face->stream = 0;
       
   906 
       
   907     /* get rid of it */
       
   908     if ( face->internal )
       
   909     {
       
   910       FT_FREE( face->internal );
       
   911     }
       
   912     FT_FREE( face );
       
   913   }
       
   914 
       
   915 
       
   916   static void
       
   917   Destroy_Driver( FT_Driver  driver )
       
   918   {
       
   919     FT_List_Finalize( &driver->faces_list,
       
   920                       (FT_List_Destructor)destroy_face,
       
   921                       driver->root.memory,
       
   922                       driver );
       
   923 
       
   924     /* check whether we need to drop the driver's glyph loader */
       
   925     if ( FT_DRIVER_USES_OUTLINES( driver ) )
       
   926       FT_GlyphLoader_Done( driver->glyph_loader );
       
   927   }
       
   928 
       
   929 
       
   930   /*************************************************************************/
       
   931   /*                                                                       */
       
   932   /* <Function>                                                            */
       
   933   /*    find_unicode_charmap                                               */
       
   934   /*                                                                       */
       
   935   /* <Description>                                                         */
       
   936   /*    This function finds a Unicode charmap, if there is one.            */
       
   937   /*    And if there is more than one, it tries to favour the more         */
       
   938   /*    extensive one, i.e., one that supports UCS-4 against those which   */
       
   939   /*    are limited to the BMP (said UCS-2 encoding.)                      */
       
   940   /*                                                                       */
       
   941   /*    This function is called from open_face() (just below), and also    */
       
   942   /*    from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ).                */
       
   943   /*                                                                       */
       
   944   static FT_Error
       
   945   find_unicode_charmap( FT_Face  face )
       
   946   {
       
   947     FT_CharMap*  first;
       
   948     FT_CharMap*  cur;
       
   949 
       
   950 
       
   951     /* caller should have already checked that `face' is valid */
       
   952     FT_ASSERT( face );
       
   953 
       
   954     first = face->charmaps;
       
   955 
       
   956     if ( !first )
       
   957       return FT_Err_Invalid_CharMap_Handle;
       
   958 
       
   959     /*
       
   960      *  The original TrueType specification(s) only specified charmap
       
   961      *  formats that are capable of mapping 8 or 16 bit character codes to
       
   962      *  glyph indices.
       
   963      *
       
   964      *  However, recent updates to the Apple and OpenType specifications
       
   965      *  introduced new formats that are capable of mapping 32-bit character
       
   966      *  codes as well.  And these are already used on some fonts, mainly to
       
   967      *  map non-BMP Asian ideographs as defined in Unicode.
       
   968      *
       
   969      *  For compatibility purposes, these fonts generally come with
       
   970      *  *several* Unicode charmaps:
       
   971      *
       
   972      *   - One of them in the "old" 16-bit format, that cannot access
       
   973      *     all glyphs in the font.
       
   974      *
       
   975      *   - Another one in the "new" 32-bit format, that can access all
       
   976      *     the glyphs.
       
   977      *
       
   978      *  This function has been written to always favor a 32-bit charmap
       
   979      *  when found.  Otherwise, a 16-bit one is returned when found.
       
   980      */
       
   981 
       
   982     /* Since the `interesting' table, with IDs (3,10), is normally the */
       
   983     /* last one, we loop backwards.  This loses with type1 fonts with  */
       
   984     /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP  */
       
   985     /* chars (.01% ?), and this is the same about 99.99% of the time!  */
       
   986 
       
   987     cur = first + face->num_charmaps;  /* points after the last one */
       
   988 
       
   989     for ( ; --cur >= first; )
       
   990     {
       
   991       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
       
   992       {
       
   993         /* XXX If some new encodings to represent UCS-4 are added, */
       
   994         /*     they should be added here.                          */
       
   995         if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
       
   996                cur[0]->encoding_id == TT_MS_ID_UCS_4        )     ||
       
   997              ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
       
   998                cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32    ) )
       
   999         {
       
  1000 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  1001           if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
       
  1002           {
       
  1003             FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
       
  1004                        "at too late position (%d)\n", cur - first ));
       
  1005             continue;
       
  1006           }
       
  1007 #endif
       
  1008           face->charmap = cur[0];
       
  1009           return FT_Err_Ok;
       
  1010         }
       
  1011       }
       
  1012     }
       
  1013 
       
  1014     /* We do not have any UCS-4 charmap.                */
       
  1015     /* Do the loop again and search for UCS-2 charmaps. */
       
  1016     cur = first + face->num_charmaps;
       
  1017 
       
  1018     for ( ; --cur >= first; )
       
  1019     {
       
  1020       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
       
  1021       {
       
  1022 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  1023         if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
       
  1024         {
       
  1025           FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
       
  1026                      "at too late position (%d)\n", cur - first ));
       
  1027           continue;
       
  1028         }
       
  1029 #endif
       
  1030         face->charmap = cur[0];
       
  1031         return FT_Err_Ok;
       
  1032       }
       
  1033     }
       
  1034 
       
  1035     return FT_Err_Invalid_CharMap_Handle;
       
  1036   }
       
  1037 
       
  1038 
       
  1039   /*************************************************************************/
       
  1040   /*                                                                       */
       
  1041   /* <Function>                                                            */
       
  1042   /*    find_variant_selector_charmap                                      */
       
  1043   /*                                                                       */
       
  1044   /* <Description>                                                         */
       
  1045   /*    This function finds the variant selector charmap, if there is one. */
       
  1046   /*    There can only be one (platform=0, specific=5, format=14).         */
       
  1047   /*                                                                       */
       
  1048   static FT_CharMap
       
  1049   find_variant_selector_charmap( FT_Face  face )
       
  1050   {
       
  1051     FT_CharMap*  first;
       
  1052     FT_CharMap*  end;
       
  1053     FT_CharMap*  cur;
       
  1054 
       
  1055 
       
  1056     /* caller should have already checked that `face' is valid */
       
  1057     FT_ASSERT( face );
       
  1058 
       
  1059     first = face->charmaps;
       
  1060 
       
  1061     if ( !first )
       
  1062       return NULL;
       
  1063 
       
  1064     end = first + face->num_charmaps;  /* points after the last one */
       
  1065 
       
  1066     for ( cur = first; cur < end; ++cur )
       
  1067     {
       
  1068       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
       
  1069            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
       
  1070            FT_Get_CMap_Format( cur[0] ) == 14                  )
       
  1071       {
       
  1072 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  1073         if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
       
  1074         {
       
  1075           FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
       
  1076                      "at too late position (%d)\n", cur - first ));
       
  1077           continue;
       
  1078         }
       
  1079 #endif
       
  1080         return cur[0];
       
  1081       }
       
  1082     }
       
  1083 
       
  1084     return NULL;
       
  1085   }
       
  1086 
       
  1087 
       
  1088   /*************************************************************************/
       
  1089   /*                                                                       */
       
  1090   /* <Function>                                                            */
       
  1091   /*    open_face                                                          */
       
  1092   /*                                                                       */
       
  1093   /* <Description>                                                         */
       
  1094   /*    This function does some work for FT_Open_Face().                   */
       
  1095   /*                                                                       */
       
  1096   static FT_Error
       
  1097   open_face( FT_Driver      driver,
       
  1098              FT_Stream      stream,
       
  1099              FT_Long        face_index,
       
  1100              FT_Int         num_params,
       
  1101              FT_Parameter*  params,
       
  1102              FT_Face       *aface )
       
  1103   {
       
  1104     FT_Memory         memory;
       
  1105     FT_Driver_Class   clazz;
       
  1106     FT_Face           face = 0;
       
  1107     FT_Error          error, error2;
       
  1108     FT_Face_Internal  internal = NULL;
       
  1109 
       
  1110 
       
  1111     clazz  = driver->clazz;
       
  1112     memory = driver->root.memory;
       
  1113 
       
  1114     /* allocate the face object and perform basic initialization */
       
  1115     if ( FT_ALLOC( face, clazz->face_object_size ) )
       
  1116       goto Fail;
       
  1117 
       
  1118     if ( FT_NEW( internal ) )
       
  1119       goto Fail;
       
  1120 
       
  1121     face->internal = internal;
       
  1122 
       
  1123     face->driver   = driver;
       
  1124     face->memory   = memory;
       
  1125     face->stream   = stream;
       
  1126 
       
  1127 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
  1128     {
       
  1129       int  i;
       
  1130 
       
  1131 
       
  1132       face->internal->incremental_interface = 0;
       
  1133       for ( i = 0; i < num_params && !face->internal->incremental_interface;
       
  1134             i++ )
       
  1135         if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
       
  1136           face->internal->incremental_interface =
       
  1137             (FT_Incremental_Interface)params[i].data;
       
  1138     }
       
  1139 #endif
       
  1140 
       
  1141     if ( clazz->init_face )
       
  1142       error = clazz->init_face( stream,
       
  1143                                 face,
       
  1144                                 (FT_Int)face_index,
       
  1145                                 num_params,
       
  1146                                 params );
       
  1147     if ( error )
       
  1148       goto Fail;
       
  1149 
       
  1150     /* select Unicode charmap by default */
       
  1151     error2 = find_unicode_charmap( face );
       
  1152 
       
  1153     /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
       
  1154     /* is returned.                                                      */
       
  1155 
       
  1156     /* no error should happen, but we want to play safe */
       
  1157     if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
       
  1158     {
       
  1159       error = error2;
       
  1160       goto Fail;
       
  1161     }
       
  1162 
       
  1163     *aface = face;
       
  1164 
       
  1165   Fail:
       
  1166     if ( error )
       
  1167     {
       
  1168       destroy_charmaps( face, memory );
       
  1169       if ( clazz->done_face )
       
  1170         clazz->done_face( face );
       
  1171       FT_FREE( internal );
       
  1172       FT_FREE( face );
       
  1173       *aface = 0;
       
  1174     }
       
  1175 
       
  1176     return error;
       
  1177   }
       
  1178 
       
  1179 
       
  1180   /* there's a Mac-specific extended implementation of FT_New_Face() */
       
  1181   /* in src/base/ftmac.c                                             */
       
  1182 
       
  1183 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
       
  1184 
       
  1185   /* documentation is in freetype.h */
       
  1186 
       
  1187   FT_EXPORT_DEF( FT_Error )
       
  1188   FT_New_Face( FT_Library   library,
       
  1189                const char*  pathname,
       
  1190                FT_Long      face_index,
       
  1191                FT_Face     *aface )
       
  1192   {
       
  1193     FT_Open_Args  args;
       
  1194 
       
  1195 
       
  1196     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
       
  1197     if ( !pathname )
       
  1198       return FT_Err_Invalid_Argument;
       
  1199 
       
  1200     args.flags    = FT_OPEN_PATHNAME;
       
  1201     args.pathname = (char*)pathname;
       
  1202     args.stream   = NULL;
       
  1203 
       
  1204     return FT_Open_Face( library, &args, face_index, aface );
       
  1205   }
       
  1206 
       
  1207 #endif  /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
       
  1208 
       
  1209 
       
  1210   /* documentation is in freetype.h */
       
  1211 
       
  1212   FT_EXPORT_DEF( FT_Error )
       
  1213   FT_New_Memory_Face( FT_Library      library,
       
  1214                       const FT_Byte*  file_base,
       
  1215                       FT_Long         file_size,
       
  1216                       FT_Long         face_index,
       
  1217                       FT_Face        *aface )
       
  1218   {
       
  1219     FT_Open_Args  args;
       
  1220 
       
  1221 
       
  1222     /* test for valid `library' and `face' delayed to FT_Open_Face() */
       
  1223     if ( !file_base )
       
  1224       return FT_Err_Invalid_Argument;
       
  1225 
       
  1226     args.flags       = FT_OPEN_MEMORY;
       
  1227     args.memory_base = file_base;
       
  1228     args.memory_size = file_size;
       
  1229     args.stream      = NULL;
       
  1230 
       
  1231     return FT_Open_Face( library, &args, face_index, aface );
       
  1232   }
       
  1233 
       
  1234 
       
  1235 #ifdef FT_CONFIG_OPTION_MAC_FONTS
       
  1236 
       
  1237   /* The behavior here is very similar to that in base/ftmac.c, but it     */
       
  1238   /* is designed to work on non-mac systems, so no mac specific calls.     */
       
  1239   /*                                                                       */
       
  1240   /* We look at the file and determine if it is a mac dfont file or a mac  */
       
  1241   /* resource file, or a macbinary file containing a mac resource file.    */
       
  1242   /*                                                                       */
       
  1243   /* Unlike ftmac I'm not going to look at a `FOND'.  I don't really see   */
       
  1244   /* the point, especially since there may be multiple `FOND' resources.   */
       
  1245   /* Instead I'll just look for `sfnt' and `POST' resources, ordered as    */
       
  1246   /* they occur in the file.                                               */
       
  1247   /*                                                                       */
       
  1248   /* Note that multiple `POST' resources do not mean multiple postscript   */
       
  1249   /* fonts; they all get jammed together to make what is essentially a     */
       
  1250   /* pfb file.                                                             */
       
  1251   /*                                                                       */
       
  1252   /* We aren't interested in `NFNT' or `FONT' bitmap resources.            */
       
  1253   /*                                                                       */
       
  1254   /* As soon as we get an `sfnt' load it into memory and pass it off to    */
       
  1255   /* FT_Open_Face.                                                         */
       
  1256   /*                                                                       */
       
  1257   /* If we have a (set of) `POST' resources, massage them into a (memory)  */
       
  1258   /* pfb file and pass that to FT_Open_Face.  (As with ftmac.c I'm not     */
       
  1259   /* going to try to save the kerning info.  After all that lives in the   */
       
  1260   /* `FOND' which isn't in the file containing the `POST' resources so     */
       
  1261   /* we don't really have access to it.                                    */
       
  1262 
       
  1263 
       
  1264   /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
       
  1265   /* It frees the memory it uses.                                  */
       
  1266   /* From ftmac.c.                                                 */
       
  1267   static void
       
  1268   memory_stream_close( FT_Stream  stream )
       
  1269   {
       
  1270     FT_Memory  memory = stream->memory;
       
  1271 
       
  1272 
       
  1273     FT_FREE( stream->base );
       
  1274 
       
  1275     stream->size  = 0;
       
  1276     stream->base  = 0;
       
  1277     stream->close = 0;
       
  1278   }
       
  1279 
       
  1280 
       
  1281   /* Create a new memory stream from a buffer and a size. */
       
  1282   /* From ftmac.c.                                        */
       
  1283   static FT_Error
       
  1284   new_memory_stream( FT_Library           library,
       
  1285                      FT_Byte*             base,
       
  1286                      FT_ULong             size,
       
  1287                      FT_Stream_CloseFunc  close,
       
  1288                      FT_Stream           *astream )
       
  1289   {
       
  1290     FT_Error   error;
       
  1291     FT_Memory  memory;
       
  1292     FT_Stream  stream;
       
  1293 
       
  1294 
       
  1295     if ( !library )
       
  1296       return FT_Err_Invalid_Library_Handle;
       
  1297 
       
  1298     if ( !base )
       
  1299       return FT_Err_Invalid_Argument;
       
  1300 
       
  1301     *astream = 0;
       
  1302     memory = library->memory;
       
  1303     if ( FT_NEW( stream ) )
       
  1304       goto Exit;
       
  1305 
       
  1306     FT_Stream_OpenMemory( stream, base, size );
       
  1307 
       
  1308     stream->close = close;
       
  1309 
       
  1310     *astream = stream;
       
  1311 
       
  1312   Exit:
       
  1313     return error;
       
  1314   }
       
  1315 
       
  1316 
       
  1317   /* Create a new FT_Face given a buffer and a driver name. */
       
  1318   /* from ftmac.c */
       
  1319   FT_LOCAL_DEF( FT_Error )
       
  1320   open_face_from_buffer( FT_Library   library,
       
  1321                          FT_Byte*     base,
       
  1322                          FT_ULong     size,
       
  1323                          FT_Long      face_index,
       
  1324                          const char*  driver_name,
       
  1325                          FT_Face     *aface )
       
  1326   {
       
  1327     FT_Open_Args  args;
       
  1328     FT_Error      error;
       
  1329     FT_Stream     stream = NULL;
       
  1330     FT_Memory     memory = library->memory;
       
  1331 
       
  1332 
       
  1333     error = new_memory_stream( library,
       
  1334                                base,
       
  1335                                size,
       
  1336                                memory_stream_close,
       
  1337                                &stream );
       
  1338     if ( error )
       
  1339     {
       
  1340       FT_FREE( base );
       
  1341       return error;
       
  1342     }
       
  1343 
       
  1344     args.flags = FT_OPEN_STREAM;
       
  1345     args.stream = stream;
       
  1346     if ( driver_name )
       
  1347     {
       
  1348       args.flags = args.flags | FT_OPEN_DRIVER;
       
  1349       args.driver = FT_Get_Module( library, driver_name );
       
  1350     }
       
  1351 
       
  1352 #ifdef FT_MACINTOSH
       
  1353     /* At this point, face_index has served its purpose;      */
       
  1354     /* whoever calls this function has already used it to     */
       
  1355     /* locate the correct font data.  We should not propagate */
       
  1356     /* this index to FT_Open_Face() (unless it is negative).  */
       
  1357 
       
  1358     if ( face_index > 0 )
       
  1359       face_index = 0;
       
  1360 #endif
       
  1361 
       
  1362     error = FT_Open_Face( library, &args, face_index, aface );
       
  1363 
       
  1364     if ( error == FT_Err_Ok )
       
  1365       (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
       
  1366     else
       
  1367 #ifdef FT_MACINTOSH
       
  1368       FT_Stream_Free( stream, 0 );
       
  1369 #else
       
  1370     {
       
  1371       FT_Stream_Close( stream );
       
  1372       FT_FREE( stream );
       
  1373     }
       
  1374 #endif
       
  1375 
       
  1376     return error;
       
  1377   }
       
  1378 
       
  1379 
       
  1380   /* Look up `TYP1' or `CID ' table from sfnt table directory.       */
       
  1381   /* `offset' and `length' must exclude the binary header in tables. */
       
  1382 
       
  1383   /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
       
  1384   /* format too.  Here, since we can't expect that the TrueType font */
       
  1385   /* driver is loaded unconditially, we must parse the font by       */
       
  1386   /* ourselves.  We are only interested in the name of the table and */
       
  1387   /* the offset.                                                     */
       
  1388 
       
  1389   static FT_Error
       
  1390   ft_lookup_PS_in_sfnt_stream( FT_Stream  stream,
       
  1391                                FT_Long    face_index,
       
  1392                                FT_ULong*  offset,
       
  1393                                FT_ULong*  length,
       
  1394                                FT_Bool*   is_sfnt_cid )
       
  1395   {
       
  1396     FT_Error   error;
       
  1397     FT_UShort  numTables;
       
  1398     FT_Long    pstable_index;
       
  1399     FT_ULong   tag;
       
  1400     int        i;
       
  1401 
       
  1402 
       
  1403     *offset = 0;
       
  1404     *length = 0;
       
  1405     *is_sfnt_cid = FALSE;
       
  1406 
       
  1407     /* TODO: support for sfnt-wrapped PS/CID in TTC format */
       
  1408 
       
  1409     /* version check for 'typ1' (should be ignored?) */
       
  1410     if ( FT_READ_ULONG( tag ) )
       
  1411       return error;
       
  1412     if ( tag != TTAG_typ1 )
       
  1413       return FT_Err_Unknown_File_Format;
       
  1414 
       
  1415     if ( FT_READ_USHORT( numTables ) )
       
  1416       return error;
       
  1417     if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
       
  1418       return error;
       
  1419 
       
  1420     pstable_index = -1;
       
  1421     *is_sfnt_cid  = FALSE;
       
  1422 
       
  1423     for ( i = 0; i < numTables; i++ )
       
  1424     {
       
  1425       if ( FT_READ_ULONG( tag )     || FT_STREAM_SKIP( 4 )      ||
       
  1426            FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
       
  1427         return error;
       
  1428 
       
  1429       if ( tag == TTAG_CID )
       
  1430       {
       
  1431         pstable_index++;
       
  1432         *offset += 22;
       
  1433         *length -= 22;
       
  1434         *is_sfnt_cid = TRUE;
       
  1435         if ( face_index < 0 )
       
  1436           return FT_Err_Ok;
       
  1437       }
       
  1438       else if ( tag == TTAG_TYP1 )
       
  1439       {
       
  1440         pstable_index++;
       
  1441         *offset += 24;
       
  1442         *length -= 24;
       
  1443         *is_sfnt_cid = FALSE;
       
  1444         if ( face_index < 0 )
       
  1445           return FT_Err_Ok;
       
  1446       }
       
  1447       if ( face_index >= 0 && pstable_index == face_index )
       
  1448         return FT_Err_Ok;
       
  1449     }
       
  1450     return FT_Err_Table_Missing;
       
  1451   }
       
  1452 
       
  1453 
       
  1454   FT_LOCAL_DEF( FT_Error )
       
  1455   open_face_PS_from_sfnt_stream( FT_Library     library,
       
  1456                                  FT_Stream      stream,
       
  1457                                  FT_Long        face_index,
       
  1458                                  FT_Int         num_params,
       
  1459                                  FT_Parameter  *params,
       
  1460                                  FT_Face       *aface )
       
  1461   {
       
  1462     FT_Error   error;
       
  1463     FT_Memory  memory = library->memory;
       
  1464     FT_ULong   offset, length;
       
  1465     FT_Long    pos;
       
  1466     FT_Bool    is_sfnt_cid;
       
  1467     FT_Byte*   sfnt_ps;
       
  1468 
       
  1469     FT_UNUSED( num_params );
       
  1470     FT_UNUSED( params );
       
  1471 
       
  1472 
       
  1473     pos = FT_Stream_Pos( stream );
       
  1474 
       
  1475     error = ft_lookup_PS_in_sfnt_stream( stream,
       
  1476                                          face_index,
       
  1477                                          &offset,
       
  1478                                          &length,
       
  1479                                          &is_sfnt_cid );
       
  1480     if ( error )
       
  1481       goto Exit;
       
  1482 
       
  1483     if ( FT_Stream_Seek( stream, pos + offset ) )
       
  1484       goto Exit;
       
  1485 
       
  1486     if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
       
  1487       goto Exit;
       
  1488 
       
  1489     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
       
  1490     if ( error )
       
  1491       goto Exit;
       
  1492 
       
  1493     error = open_face_from_buffer( library,
       
  1494                                    sfnt_ps,
       
  1495                                    length,
       
  1496                                    face_index < 0 ? face_index : 0,
       
  1497                                    is_sfnt_cid ? "cid" : "type1",
       
  1498                                    aface );
       
  1499   Exit:
       
  1500     {
       
  1501       FT_Error  error1;
       
  1502 
       
  1503 
       
  1504       if ( error == FT_Err_Unknown_File_Format )
       
  1505       {
       
  1506         error1 = FT_Stream_Seek( stream, pos );
       
  1507         if ( error1 )
       
  1508           return error1;
       
  1509       }
       
  1510 
       
  1511       return error;
       
  1512     }
       
  1513   }
       
  1514 
       
  1515 
       
  1516 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
       
  1517 
       
  1518   /* The resource header says we've got resource_cnt `POST' (type1) */
       
  1519   /* resources in this file.  They all need to be coalesced into    */
       
  1520   /* one lump which gets passed on to the type1 driver.             */
       
  1521   /* Here can be only one PostScript font in a file so face_index   */
       
  1522   /* must be 0 (or -1).                                             */
       
  1523   /*                                                                */
       
  1524   static FT_Error
       
  1525   Mac_Read_POST_Resource( FT_Library  library,
       
  1526                           FT_Stream   stream,
       
  1527                           FT_Long    *offsets,
       
  1528                           FT_Long     resource_cnt,
       
  1529                           FT_Long     face_index,
       
  1530                           FT_Face    *aface )
       
  1531   {
       
  1532     FT_Error   error  = FT_Err_Cannot_Open_Resource;
       
  1533     FT_Memory  memory = library->memory;
       
  1534     FT_Byte*   pfb_data;
       
  1535     int        i, type, flags;
       
  1536     FT_Long    len;
       
  1537     FT_Long    pfb_len, pfb_pos, pfb_lenpos;
       
  1538     FT_Long    rlen, temp;
       
  1539 
       
  1540 
       
  1541     if ( face_index == -1 )
       
  1542       face_index = 0;
       
  1543     if ( face_index != 0 )
       
  1544       return error;
       
  1545 
       
  1546     /* Find the length of all the POST resources, concatenated.  Assume */
       
  1547     /* worst case (each resource in its own section).                   */
       
  1548     pfb_len = 0;
       
  1549     for ( i = 0; i < resource_cnt; ++i )
       
  1550     {
       
  1551       error = FT_Stream_Seek( stream, offsets[i] );
       
  1552       if ( error )
       
  1553         goto Exit;
       
  1554       if ( FT_READ_LONG( temp ) )
       
  1555         goto Exit;
       
  1556       pfb_len += temp + 6;
       
  1557     }
       
  1558 
       
  1559     if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
       
  1560       goto Exit;
       
  1561 
       
  1562     pfb_data[0] = 0x80;
       
  1563     pfb_data[1] = 1;            /* Ascii section */
       
  1564     pfb_data[2] = 0;            /* 4-byte length, fill in later */
       
  1565     pfb_data[3] = 0;
       
  1566     pfb_data[4] = 0;
       
  1567     pfb_data[5] = 0;
       
  1568     pfb_pos     = 6;
       
  1569     pfb_lenpos  = 2;
       
  1570 
       
  1571     len = 0;
       
  1572     type = 1;
       
  1573     for ( i = 0; i < resource_cnt; ++i )
       
  1574     {
       
  1575       error = FT_Stream_Seek( stream, offsets[i] );
       
  1576       if ( error )
       
  1577         goto Exit2;
       
  1578       if ( FT_READ_LONG( rlen ) )
       
  1579         goto Exit;
       
  1580       if ( FT_READ_USHORT( flags ) )
       
  1581         goto Exit;
       
  1582       FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
       
  1583                    i, offsets[i], rlen, flags ));
       
  1584 
       
  1585       /* postpone the check of rlen longer than buffer until FT_Stream_Read() */
       
  1586       if ( ( flags >> 8 ) == 0 )        /* Comment, should not be loaded */
       
  1587         continue;
       
  1588 
       
  1589       /* the flags are part of the resource, so rlen >= 2.  */
       
  1590       /* but some fonts declare rlen = 0 for empty fragment */
       
  1591       if ( rlen > 2 )
       
  1592         rlen -= 2;
       
  1593       else
       
  1594         rlen = 0;
       
  1595 
       
  1596       if ( ( flags >> 8 ) == type )
       
  1597         len += rlen;
       
  1598       else
       
  1599       {
       
  1600         if ( pfb_lenpos + 3 > pfb_len + 2 )
       
  1601           goto Exit2;
       
  1602         pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
       
  1603         pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
       
  1604         pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
       
  1605         pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
       
  1606 
       
  1607         if ( ( flags >> 8 ) == 5 )      /* End of font mark */
       
  1608           break;
       
  1609 
       
  1610         if ( pfb_pos + 6 > pfb_len + 2 )
       
  1611           goto Exit2;
       
  1612         pfb_data[pfb_pos++] = 0x80;
       
  1613 
       
  1614         type = flags >> 8;
       
  1615         len = rlen;
       
  1616 
       
  1617         pfb_data[pfb_pos++] = (FT_Byte)type;
       
  1618         pfb_lenpos          = pfb_pos;
       
  1619         pfb_data[pfb_pos++] = 0;        /* 4-byte length, fill in later */
       
  1620         pfb_data[pfb_pos++] = 0;
       
  1621         pfb_data[pfb_pos++] = 0;
       
  1622         pfb_data[pfb_pos++] = 0;
       
  1623       }
       
  1624 
       
  1625       error = FT_Err_Cannot_Open_Resource;
       
  1626       if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
       
  1627         goto Exit2;
       
  1628 
       
  1629       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
       
  1630       if ( error )
       
  1631         goto Exit2;
       
  1632       pfb_pos += rlen;
       
  1633     }
       
  1634 
       
  1635     if ( pfb_pos + 2 > pfb_len + 2 )
       
  1636       goto Exit2;
       
  1637     pfb_data[pfb_pos++] = 0x80;
       
  1638     pfb_data[pfb_pos++] = 3;
       
  1639 
       
  1640     if ( pfb_lenpos + 3 > pfb_len + 2 )
       
  1641       goto Exit2;
       
  1642     pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
       
  1643     pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
       
  1644     pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
       
  1645     pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
       
  1646 
       
  1647     return open_face_from_buffer( library,
       
  1648                                   pfb_data,
       
  1649                                   pfb_pos,
       
  1650                                   face_index,
       
  1651                                   "type1",
       
  1652                                   aface );
       
  1653 
       
  1654   Exit2:
       
  1655     FT_FREE( pfb_data );
       
  1656 
       
  1657   Exit:
       
  1658     return error;
       
  1659   }
       
  1660 
       
  1661 
       
  1662   /* The resource header says we've got resource_cnt `sfnt'      */
       
  1663   /* (TrueType/OpenType) resources in this file.  Look through   */
       
  1664   /* them for the one indicated by face_index, load it into mem, */
       
  1665   /* pass it on the the truetype driver and return it.           */
       
  1666   /*                                                             */
       
  1667   static FT_Error
       
  1668   Mac_Read_sfnt_Resource( FT_Library  library,
       
  1669                           FT_Stream   stream,
       
  1670                           FT_Long    *offsets,
       
  1671                           FT_Long     resource_cnt,
       
  1672                           FT_Long     face_index,
       
  1673                           FT_Face    *aface )
       
  1674   {
       
  1675     FT_Memory  memory = library->memory;
       
  1676     FT_Byte*   sfnt_data;
       
  1677     FT_Error   error;
       
  1678     FT_Long    flag_offset;
       
  1679     FT_Long    rlen;
       
  1680     int        is_cff;
       
  1681     FT_Long    face_index_in_resource = 0;
       
  1682 
       
  1683 
       
  1684     if ( face_index == -1 )
       
  1685       face_index = 0;
       
  1686     if ( face_index >= resource_cnt )
       
  1687       return FT_Err_Cannot_Open_Resource;
       
  1688 
       
  1689     flag_offset = offsets[face_index];
       
  1690     error = FT_Stream_Seek( stream, flag_offset );
       
  1691     if ( error )
       
  1692       goto Exit;
       
  1693 
       
  1694     if ( FT_READ_LONG( rlen ) )
       
  1695       goto Exit;
       
  1696     if ( rlen == -1 )
       
  1697       return FT_Err_Cannot_Open_Resource;
       
  1698 
       
  1699     error = open_face_PS_from_sfnt_stream( library,
       
  1700                                            stream,
       
  1701                                            face_index,
       
  1702                                            0, NULL,
       
  1703                                            aface );
       
  1704     if ( !error )
       
  1705       goto Exit;
       
  1706 
       
  1707     /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
       
  1708     if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
       
  1709       goto Exit;
       
  1710 
       
  1711     if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
       
  1712       return error;
       
  1713     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
       
  1714     if ( error )
       
  1715       goto Exit;
       
  1716 
       
  1717     is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
       
  1718     error = open_face_from_buffer( library,
       
  1719                                    sfnt_data,
       
  1720                                    rlen,
       
  1721                                    face_index_in_resource,
       
  1722                                    is_cff ? "cff" : "truetype",
       
  1723                                    aface );
       
  1724 
       
  1725   Exit:
       
  1726     return error;
       
  1727   }
       
  1728 
       
  1729 
       
  1730   /* Check for a valid resource fork header, or a valid dfont    */
       
  1731   /* header.  In a resource fork the first 16 bytes are repeated */
       
  1732   /* at the location specified by bytes 4-7.  In a dfont bytes   */
       
  1733   /* 4-7 point to 16 bytes of zeroes instead.                    */
       
  1734   /*                                                             */
       
  1735   static FT_Error
       
  1736   IsMacResource( FT_Library  library,
       
  1737                  FT_Stream   stream,
       
  1738                  FT_Long     resource_offset,
       
  1739                  FT_Long     face_index,
       
  1740                  FT_Face    *aface )
       
  1741   {
       
  1742     FT_Memory  memory = library->memory;
       
  1743     FT_Error   error;
       
  1744     FT_Long    map_offset, rdara_pos;
       
  1745     FT_Long    *data_offsets;
       
  1746     FT_Long    count;
       
  1747 
       
  1748 
       
  1749     error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
       
  1750                                        &map_offset, &rdara_pos );
       
  1751     if ( error )
       
  1752       return error;
       
  1753 
       
  1754     error = FT_Raccess_Get_DataOffsets( library, stream,
       
  1755                                         map_offset, rdara_pos,
       
  1756                                         TTAG_POST,
       
  1757                                         &data_offsets, &count );
       
  1758     if ( !error )
       
  1759     {
       
  1760       error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
       
  1761                                       face_index, aface );
       
  1762       FT_FREE( data_offsets );
       
  1763       /* POST exists in an LWFN providing a single face */
       
  1764       if ( !error )
       
  1765         (*aface)->num_faces = 1;
       
  1766       return error;
       
  1767     }
       
  1768 
       
  1769     error = FT_Raccess_Get_DataOffsets( library, stream,
       
  1770                                         map_offset, rdara_pos,
       
  1771                                         TTAG_sfnt,
       
  1772                                         &data_offsets, &count );
       
  1773     if ( !error )
       
  1774     {
       
  1775       FT_Long  face_index_internal = face_index % count;
       
  1776 
       
  1777 
       
  1778       error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
       
  1779                                       face_index_internal, aface );
       
  1780       FT_FREE( data_offsets );
       
  1781       if ( !error )
       
  1782         (*aface)->num_faces = count;
       
  1783     }
       
  1784 
       
  1785     return error;
       
  1786   }
       
  1787 
       
  1788 
       
  1789   /* Check for a valid macbinary header, and if we find one   */
       
  1790   /* check that the (flattened) resource fork in it is valid. */
       
  1791   /*                                                          */
       
  1792   static FT_Error
       
  1793   IsMacBinary( FT_Library  library,
       
  1794                FT_Stream   stream,
       
  1795                FT_Long     face_index,
       
  1796                FT_Face    *aface )
       
  1797   {
       
  1798     unsigned char  header[128];
       
  1799     FT_Error       error;
       
  1800     FT_Long        dlen, offset;
       
  1801 
       
  1802 
       
  1803     if ( NULL == stream )
       
  1804       return FT_Err_Invalid_Stream_Operation;
       
  1805 
       
  1806     error = FT_Stream_Seek( stream, 0 );
       
  1807     if ( error )
       
  1808       goto Exit;
       
  1809 
       
  1810     error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
       
  1811     if ( error )
       
  1812       goto Exit;
       
  1813 
       
  1814     if (            header[ 0] !=  0 ||
       
  1815                     header[74] !=  0 ||
       
  1816                     header[82] !=  0 ||
       
  1817                     header[ 1] ==  0 ||
       
  1818                     header[ 1] >  33 ||
       
  1819                     header[63] !=  0 ||
       
  1820          header[2 + header[1]] !=  0 )
       
  1821       return FT_Err_Unknown_File_Format;
       
  1822 
       
  1823     dlen = ( header[0x53] << 24 ) |
       
  1824            ( header[0x54] << 16 ) |
       
  1825            ( header[0x55] <<  8 ) |
       
  1826              header[0x56];
       
  1827 #if 0
       
  1828     rlen = ( header[0x57] << 24 ) |
       
  1829            ( header[0x58] << 16 ) |
       
  1830            ( header[0x59] <<  8 ) |
       
  1831              header[0x5a];
       
  1832 #endif /* 0 */
       
  1833     offset = 128 + ( ( dlen + 127 ) & ~127 );
       
  1834 
       
  1835     return IsMacResource( library, stream, offset, face_index, aface );
       
  1836 
       
  1837   Exit:
       
  1838     return error;
       
  1839   }
       
  1840 
       
  1841 
       
  1842   static FT_Error
       
  1843   load_face_in_embedded_rfork( FT_Library           library,
       
  1844                                FT_Stream            stream,
       
  1845                                FT_Long              face_index,
       
  1846                                FT_Face             *aface,
       
  1847                                const FT_Open_Args  *args )
       
  1848   {
       
  1849 
       
  1850 #undef  FT_COMPONENT
       
  1851 #define FT_COMPONENT  trace_raccess
       
  1852 
       
  1853     FT_Memory  memory = library->memory;
       
  1854     FT_Error   error  = FT_Err_Unknown_File_Format;
       
  1855     int        i;
       
  1856 
       
  1857     char *     file_names[FT_RACCESS_N_RULES];
       
  1858     FT_Long    offsets[FT_RACCESS_N_RULES];
       
  1859     FT_Error   errors[FT_RACCESS_N_RULES];
       
  1860     FT_Bool    is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
       
  1861 
       
  1862     FT_Open_Args  args2;
       
  1863     FT_Stream     stream2 = 0;
       
  1864 
       
  1865 
       
  1866     FT_Raccess_Guess( library, stream,
       
  1867                       args->pathname, file_names, offsets, errors );
       
  1868 
       
  1869     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
       
  1870     {
       
  1871       is_darwin_vfs = raccess_rule_by_darwin_vfs( i );
       
  1872       if ( is_darwin_vfs && vfs_rfork_has_no_font )
       
  1873       {
       
  1874         FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"
       
  1875                     " is already checked and"
       
  1876                     " no font is found\n", i ));
       
  1877         continue;
       
  1878       }
       
  1879 
       
  1880       if ( errors[i] )
       
  1881       {
       
  1882         FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
       
  1883         continue;
       
  1884       }
       
  1885 
       
  1886       args2.flags    = FT_OPEN_PATHNAME;
       
  1887       args2.pathname = file_names[i] ? file_names[i] : args->pathname;
       
  1888 
       
  1889       FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
       
  1890                   i, args2.pathname, offsets[i] ));
       
  1891 
       
  1892       error = FT_Stream_New( library, &args2, &stream2 );
       
  1893       if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )
       
  1894         vfs_rfork_has_no_font = TRUE;
       
  1895 
       
  1896       if ( error )
       
  1897       {
       
  1898         FT_TRACE3(( "failed\n" ));
       
  1899         continue;
       
  1900       }
       
  1901 
       
  1902       error = IsMacResource( library, stream2, offsets[i],
       
  1903                              face_index, aface );
       
  1904       FT_Stream_Free( stream2, 0 );
       
  1905 
       
  1906       FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
       
  1907 
       
  1908       if ( !error )
       
  1909           break;
       
  1910       else if ( is_darwin_vfs )
       
  1911           vfs_rfork_has_no_font = TRUE;
       
  1912     }
       
  1913 
       
  1914     for (i = 0; i < FT_RACCESS_N_RULES; i++)
       
  1915     {
       
  1916       if ( file_names[i] )
       
  1917         FT_FREE( file_names[i] );
       
  1918     }
       
  1919 
       
  1920     /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
       
  1921     if ( error )
       
  1922       error = FT_Err_Unknown_File_Format;
       
  1923 
       
  1924     return error;
       
  1925 
       
  1926 #undef  FT_COMPONENT
       
  1927 #define FT_COMPONENT  trace_objs
       
  1928 
       
  1929   }
       
  1930 
       
  1931 
       
  1932   /* Check for some macintosh formats without Carbon framework.    */
       
  1933   /* Is this a macbinary file?  If so look at the resource fork.   */
       
  1934   /* Is this a mac dfont file?                                     */
       
  1935   /* Is this an old style resource fork? (in data)                 */
       
  1936   /* Else call load_face_in_embedded_rfork to try extra rules      */
       
  1937   /* (defined in `ftrfork.c').                                     */
       
  1938   /*                                                               */
       
  1939   static FT_Error
       
  1940   load_mac_face( FT_Library           library,
       
  1941                  FT_Stream            stream,
       
  1942                  FT_Long              face_index,
       
  1943                  FT_Face             *aface,
       
  1944                  const FT_Open_Args  *args )
       
  1945   {
       
  1946     FT_Error error;
       
  1947     FT_UNUSED( args );
       
  1948 
       
  1949 
       
  1950     error = IsMacBinary( library, stream, face_index, aface );
       
  1951     if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
       
  1952     {
       
  1953 
       
  1954 #undef  FT_COMPONENT
       
  1955 #define FT_COMPONENT  trace_raccess
       
  1956 
       
  1957       FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
       
  1958 
       
  1959       error = IsMacResource( library, stream, 0, face_index, aface );
       
  1960 
       
  1961       FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
       
  1962 
       
  1963 #undef  FT_COMPONENT
       
  1964 #define FT_COMPONENT  trace_objs
       
  1965 
       
  1966     }
       
  1967 
       
  1968     if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format      ||
       
  1969            FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
       
  1970          ( args->flags & FT_OPEN_PATHNAME )                            )
       
  1971       error = load_face_in_embedded_rfork( library, stream,
       
  1972                                            face_index, aface, args );
       
  1973     return error;
       
  1974   }
       
  1975 #endif
       
  1976 
       
  1977 #endif  /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
       
  1978 
       
  1979 
       
  1980   /* documentation is in freetype.h */
       
  1981 
       
  1982   FT_EXPORT_DEF( FT_Error )
       
  1983   FT_Open_Face( FT_Library           library,
       
  1984                 const FT_Open_Args*  args,
       
  1985                 FT_Long              face_index,
       
  1986                 FT_Face             *aface )
       
  1987   {
       
  1988     FT_Error     error;
       
  1989     FT_Driver    driver;
       
  1990     FT_Memory    memory;
       
  1991     FT_Stream    stream = NULL;
       
  1992     FT_Face      face   = NULL;
       
  1993     FT_ListNode  node   = NULL;
       
  1994     FT_Bool      external_stream;
       
  1995     FT_Module*   cur;
       
  1996     FT_Module*   limit;
       
  1997 
       
  1998 
       
  1999     /* test for valid `library' delayed to */
       
  2000     /* FT_Stream_New()                     */
       
  2001 
       
  2002     if ( ( !aface && face_index >= 0 ) || !args )
       
  2003       return FT_Err_Invalid_Argument;
       
  2004 
       
  2005     external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
       
  2006                                args->stream                     );
       
  2007 
       
  2008     /* create input stream */
       
  2009     error = FT_Stream_New( library, args, &stream );
       
  2010     if ( error )
       
  2011       goto Fail3;
       
  2012 
       
  2013     memory = library->memory;
       
  2014 
       
  2015     /* If the font driver is specified in the `args' structure, use */
       
  2016     /* it.  Otherwise, we scan the list of registered drivers.      */
       
  2017     if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
       
  2018     {
       
  2019       driver = FT_DRIVER( args->driver );
       
  2020 
       
  2021       /* not all modules are drivers, so check... */
       
  2022       if ( FT_MODULE_IS_DRIVER( driver ) )
       
  2023       {
       
  2024         FT_Int         num_params = 0;
       
  2025         FT_Parameter*  params     = 0;
       
  2026 
       
  2027 
       
  2028         if ( args->flags & FT_OPEN_PARAMS )
       
  2029         {
       
  2030           num_params = args->num_params;
       
  2031           params     = args->params;
       
  2032         }
       
  2033 
       
  2034         error = open_face( driver, stream, face_index,
       
  2035                            num_params, params, &face );
       
  2036         if ( !error )
       
  2037           goto Success;
       
  2038       }
       
  2039       else
       
  2040         error = FT_Err_Invalid_Handle;
       
  2041 
       
  2042       FT_Stream_Free( stream, external_stream );
       
  2043       goto Fail;
       
  2044     }
       
  2045     else
       
  2046     {
       
  2047       /* check each font driver for an appropriate format */
       
  2048       cur   = library->modules;
       
  2049       limit = cur + library->num_modules;
       
  2050 
       
  2051 
       
  2052       for ( ; cur < limit; cur++ )
       
  2053       {
       
  2054         /* not all modules are font drivers, so check... */
       
  2055         if ( FT_MODULE_IS_DRIVER( cur[0] ) )
       
  2056         {
       
  2057           FT_Int         num_params = 0;
       
  2058           FT_Parameter*  params     = 0;
       
  2059 
       
  2060 
       
  2061           driver = FT_DRIVER( cur[0] );
       
  2062 
       
  2063           if ( args->flags & FT_OPEN_PARAMS )
       
  2064           {
       
  2065             num_params = args->num_params;
       
  2066             params     = args->params;
       
  2067           }
       
  2068 
       
  2069           error = open_face( driver, stream, face_index,
       
  2070                              num_params, params, &face );
       
  2071           if ( !error )
       
  2072             goto Success;
       
  2073 
       
  2074 #ifdef FT_CONFIG_OPTION_MAC_FONTS
       
  2075           if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
       
  2076                FT_ERROR_BASE( error ) == FT_Err_Table_Missing           )
       
  2077           {
       
  2078             /* TrueType but essential tables are missing */
       
  2079             if ( FT_Stream_Seek( stream, 0 ) )
       
  2080               break;
       
  2081 
       
  2082             error = open_face_PS_from_sfnt_stream( library,
       
  2083                                                    stream,
       
  2084                                                    face_index,
       
  2085                                                    num_params,
       
  2086                                                    params,
       
  2087                                                    aface );
       
  2088             if ( !error )
       
  2089             {
       
  2090               FT_Stream_Free( stream, external_stream );
       
  2091               return error;
       
  2092             }
       
  2093           }
       
  2094 #endif
       
  2095 
       
  2096           if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
       
  2097             goto Fail3;
       
  2098         }
       
  2099       }
       
  2100 
       
  2101   Fail3:
       
  2102     /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
       
  2103     /* it may be because we have an empty data fork, so we need to check   */
       
  2104     /* the resource fork.                                                  */
       
  2105     if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream       &&
       
  2106          FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format      &&
       
  2107          FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
       
  2108       goto Fail2;
       
  2109 
       
  2110 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
       
  2111     error = load_mac_face( library, stream, face_index, aface, args );
       
  2112     if ( !error )
       
  2113     {
       
  2114       /* We don't want to go to Success here.  We've already done that. */
       
  2115       /* On the other hand, if we succeeded we still need to close this */
       
  2116       /* stream (we opened a different stream which extracted the       */
       
  2117       /* interesting information out of this stream here.  That stream  */
       
  2118       /* will still be open and the face will point to it).             */
       
  2119       FT_Stream_Free( stream, external_stream );
       
  2120       return error;
       
  2121     }
       
  2122 
       
  2123     if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
       
  2124       goto Fail2;
       
  2125 #endif  /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
       
  2126 
       
  2127       /* no driver is able to handle this format */
       
  2128       error = FT_Err_Unknown_File_Format;
       
  2129 
       
  2130   Fail2:
       
  2131       FT_Stream_Free( stream, external_stream );
       
  2132       goto Fail;
       
  2133     }
       
  2134 
       
  2135   Success:
       
  2136     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
       
  2137 
       
  2138     /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
       
  2139     if ( external_stream )
       
  2140       face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
       
  2141 
       
  2142     /* add the face object to its driver's list */
       
  2143     if ( FT_NEW( node ) )
       
  2144       goto Fail;
       
  2145 
       
  2146     node->data = face;
       
  2147     /* don't assume driver is the same as face->driver, so use */
       
  2148     /* face->driver instead.                                   */
       
  2149     FT_List_Add( &face->driver->faces_list, node );
       
  2150 
       
  2151     /* now allocate a glyph slot object for the face */
       
  2152     FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
       
  2153 
       
  2154     if ( face_index >= 0 )
       
  2155     {
       
  2156       error = FT_New_GlyphSlot( face, NULL );
       
  2157       if ( error )
       
  2158         goto Fail;
       
  2159 
       
  2160       /* finally, allocate a size object for the face */
       
  2161       {
       
  2162         FT_Size  size;
       
  2163 
       
  2164 
       
  2165         FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
       
  2166 
       
  2167         error = FT_New_Size( face, &size );
       
  2168         if ( error )
       
  2169           goto Fail;
       
  2170 
       
  2171         face->size = size;
       
  2172       }
       
  2173     }
       
  2174 
       
  2175     /* some checks */
       
  2176 
       
  2177     if ( FT_IS_SCALABLE( face ) )
       
  2178     {
       
  2179       if ( face->height < 0 )
       
  2180         face->height = (FT_Short)-face->height;
       
  2181 
       
  2182       if ( !FT_HAS_VERTICAL( face ) )
       
  2183         face->max_advance_height = (FT_Short)face->height;
       
  2184     }
       
  2185 
       
  2186     if ( FT_HAS_FIXED_SIZES( face ) )
       
  2187     {
       
  2188       FT_Int  i;
       
  2189 
       
  2190 
       
  2191       for ( i = 0; i < face->num_fixed_sizes; i++ )
       
  2192       {
       
  2193         FT_Bitmap_Size*  bsize = face->available_sizes + i;
       
  2194 
       
  2195 
       
  2196         if ( bsize->height < 0 )
       
  2197           bsize->height = (FT_Short)-bsize->height;
       
  2198         if ( bsize->x_ppem < 0 )
       
  2199           bsize->x_ppem = (FT_Short)-bsize->x_ppem;
       
  2200         if ( bsize->y_ppem < 0 )
       
  2201           bsize->y_ppem = -bsize->y_ppem;
       
  2202       }
       
  2203     }
       
  2204 
       
  2205     /* initialize internal face data */
       
  2206     {
       
  2207       FT_Face_Internal  internal = face->internal;
       
  2208 
       
  2209 
       
  2210       internal->transform_matrix.xx = 0x10000L;
       
  2211       internal->transform_matrix.xy = 0;
       
  2212       internal->transform_matrix.yx = 0;
       
  2213       internal->transform_matrix.yy = 0x10000L;
       
  2214 
       
  2215       internal->transform_delta.x = 0;
       
  2216       internal->transform_delta.y = 0;
       
  2217 
       
  2218       internal->refcount = 1;
       
  2219     }
       
  2220 
       
  2221     if ( aface )
       
  2222       *aface = face;
       
  2223     else
       
  2224       FT_Done_Face( face );
       
  2225 
       
  2226     goto Exit;
       
  2227 
       
  2228   Fail:
       
  2229     FT_Done_Face( face );
       
  2230 
       
  2231   Exit:
       
  2232     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
       
  2233 
       
  2234     return error;
       
  2235   }
       
  2236 
       
  2237 
       
  2238   /* documentation is in freetype.h */
       
  2239 
       
  2240   FT_EXPORT_DEF( FT_Error )
       
  2241   FT_Attach_File( FT_Face      face,
       
  2242                   const char*  filepathname )
       
  2243   {
       
  2244     FT_Open_Args  open;
       
  2245 
       
  2246 
       
  2247     /* test for valid `face' delayed to FT_Attach_Stream() */
       
  2248 
       
  2249     if ( !filepathname )
       
  2250       return FT_Err_Invalid_Argument;
       
  2251 
       
  2252     open.stream   = NULL;
       
  2253     open.flags    = FT_OPEN_PATHNAME;
       
  2254     open.pathname = (char*)filepathname;
       
  2255 
       
  2256     return FT_Attach_Stream( face, &open );
       
  2257   }
       
  2258 
       
  2259 
       
  2260   /* documentation is in freetype.h */
       
  2261 
       
  2262   FT_EXPORT_DEF( FT_Error )
       
  2263   FT_Attach_Stream( FT_Face        face,
       
  2264                     FT_Open_Args*  parameters )
       
  2265   {
       
  2266     FT_Stream  stream;
       
  2267     FT_Error   error;
       
  2268     FT_Driver  driver;
       
  2269 
       
  2270     FT_Driver_Class  clazz;
       
  2271 
       
  2272 
       
  2273     /* test for valid `parameters' delayed to FT_Stream_New() */
       
  2274 
       
  2275     if ( !face )
       
  2276       return FT_Err_Invalid_Face_Handle;
       
  2277 
       
  2278     driver = face->driver;
       
  2279     if ( !driver )
       
  2280       return FT_Err_Invalid_Driver_Handle;
       
  2281 
       
  2282     error = FT_Stream_New( driver->root.library, parameters, &stream );
       
  2283     if ( error )
       
  2284       goto Exit;
       
  2285 
       
  2286     /* we implement FT_Attach_Stream in each driver through the */
       
  2287     /* `attach_file' interface                                  */
       
  2288 
       
  2289     error = FT_Err_Unimplemented_Feature;
       
  2290     clazz = driver->clazz;
       
  2291     if ( clazz->attach_file )
       
  2292       error = clazz->attach_file( face, stream );
       
  2293 
       
  2294     /* close the attached stream */
       
  2295     FT_Stream_Free( stream,
       
  2296                     (FT_Bool)( parameters->stream &&
       
  2297                                ( parameters->flags & FT_OPEN_STREAM ) ) );
       
  2298 
       
  2299   Exit:
       
  2300     return error;
       
  2301   }
       
  2302 
       
  2303 
       
  2304   /* documentation is in freetype.h */
       
  2305 
       
  2306   FT_EXPORT_DEF( FT_Error )
       
  2307   FT_Reference_Face( FT_Face  face )
       
  2308   {
       
  2309     face->internal->refcount++;
       
  2310 
       
  2311     return FT_Err_Ok;
       
  2312   }
       
  2313 
       
  2314 
       
  2315   /* documentation is in freetype.h */
       
  2316 
       
  2317   FT_EXPORT_DEF( FT_Error )
       
  2318   FT_Done_Face( FT_Face  face )
       
  2319   {
       
  2320     FT_Error     error;
       
  2321     FT_Driver    driver;
       
  2322     FT_Memory    memory;
       
  2323     FT_ListNode  node;
       
  2324 
       
  2325 
       
  2326     error = FT_Err_Invalid_Face_Handle;
       
  2327     if ( face && face->driver )
       
  2328     {
       
  2329       face->internal->refcount--;
       
  2330       if ( face->internal->refcount > 0 )
       
  2331         error = FT_Err_Ok;
       
  2332       else
       
  2333       {
       
  2334         driver = face->driver;
       
  2335         memory = driver->root.memory;
       
  2336 
       
  2337         /* find face in driver's list */
       
  2338         node = FT_List_Find( &driver->faces_list, face );
       
  2339         if ( node )
       
  2340         {
       
  2341           /* remove face object from the driver's list */
       
  2342           FT_List_Remove( &driver->faces_list, node );
       
  2343           FT_FREE( node );
       
  2344 
       
  2345           /* now destroy the object proper */
       
  2346           destroy_face( memory, face, driver );
       
  2347           error = FT_Err_Ok;
       
  2348         }
       
  2349       }
       
  2350     }
       
  2351 
       
  2352     return error;
       
  2353   }
       
  2354 
       
  2355 
       
  2356   /* documentation is in ftobjs.h */
       
  2357 
       
  2358   FT_EXPORT_DEF( FT_Error )
       
  2359   FT_New_Size( FT_Face   face,
       
  2360                FT_Size  *asize )
       
  2361   {
       
  2362     FT_Error         error;
       
  2363     FT_Memory        memory;
       
  2364     FT_Driver        driver;
       
  2365     FT_Driver_Class  clazz;
       
  2366 
       
  2367     FT_Size          size = 0;
       
  2368     FT_ListNode      node = 0;
       
  2369 
       
  2370 
       
  2371     if ( !face )
       
  2372       return FT_Err_Invalid_Face_Handle;
       
  2373 
       
  2374     if ( !asize )
       
  2375       return FT_Err_Invalid_Size_Handle;
       
  2376 
       
  2377     if ( !face->driver )
       
  2378       return FT_Err_Invalid_Driver_Handle;
       
  2379 
       
  2380     *asize = 0;
       
  2381 
       
  2382     driver = face->driver;
       
  2383     clazz  = driver->clazz;
       
  2384     memory = face->memory;
       
  2385 
       
  2386     /* Allocate new size object and perform basic initialisation */
       
  2387     if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
       
  2388       goto Exit;
       
  2389 
       
  2390     size->face = face;
       
  2391 
       
  2392     /* for now, do not use any internal fields in size objects */
       
  2393     size->internal = 0;
       
  2394 
       
  2395     if ( clazz->init_size )
       
  2396       error = clazz->init_size( size );
       
  2397 
       
  2398     /* in case of success, add to the face's list */
       
  2399     if ( !error )
       
  2400     {
       
  2401       *asize     = size;
       
  2402       node->data = size;
       
  2403       FT_List_Add( &face->sizes_list, node );
       
  2404     }
       
  2405 
       
  2406   Exit:
       
  2407     if ( error )
       
  2408     {
       
  2409       FT_FREE( node );
       
  2410       FT_FREE( size );
       
  2411     }
       
  2412 
       
  2413     return error;
       
  2414   }
       
  2415 
       
  2416 
       
  2417   /* documentation is in ftobjs.h */
       
  2418 
       
  2419   FT_EXPORT_DEF( FT_Error )
       
  2420   FT_Done_Size( FT_Size  size )
       
  2421   {
       
  2422     FT_Error     error;
       
  2423     FT_Driver    driver;
       
  2424     FT_Memory    memory;
       
  2425     FT_Face      face;
       
  2426     FT_ListNode  node;
       
  2427 
       
  2428 
       
  2429     if ( !size )
       
  2430       return FT_Err_Invalid_Size_Handle;
       
  2431 
       
  2432     face = size->face;
       
  2433     if ( !face )
       
  2434       return FT_Err_Invalid_Face_Handle;
       
  2435 
       
  2436     driver = face->driver;
       
  2437     if ( !driver )
       
  2438       return FT_Err_Invalid_Driver_Handle;
       
  2439 
       
  2440     memory = driver->root.memory;
       
  2441 
       
  2442     error = FT_Err_Ok;
       
  2443     node  = FT_List_Find( &face->sizes_list, size );
       
  2444     if ( node )
       
  2445     {
       
  2446       FT_List_Remove( &face->sizes_list, node );
       
  2447       FT_FREE( node );
       
  2448 
       
  2449       if ( face->size == size )
       
  2450       {
       
  2451         face->size = 0;
       
  2452         if ( face->sizes_list.head )
       
  2453           face->size = (FT_Size)(face->sizes_list.head->data);
       
  2454       }
       
  2455 
       
  2456       destroy_size( memory, size, driver );
       
  2457     }
       
  2458     else
       
  2459       error = FT_Err_Invalid_Size_Handle;
       
  2460 
       
  2461     return error;
       
  2462   }
       
  2463 
       
  2464 
       
  2465   /* documentation is in ftobjs.h */
       
  2466 
       
  2467   FT_BASE_DEF( FT_Error )
       
  2468   FT_Match_Size( FT_Face          face,
       
  2469                  FT_Size_Request  req,
       
  2470                  FT_Bool          ignore_width,
       
  2471                  FT_ULong*        size_index )
       
  2472   {
       
  2473     FT_Int   i;
       
  2474     FT_Long  w, h;
       
  2475 
       
  2476 
       
  2477     if ( !FT_HAS_FIXED_SIZES( face ) )
       
  2478       return FT_Err_Invalid_Face_Handle;
       
  2479 
       
  2480     /* FT_Bitmap_Size doesn't provide enough info... */
       
  2481     if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
       
  2482       return FT_Err_Unimplemented_Feature;
       
  2483 
       
  2484     w = FT_REQUEST_WIDTH ( req );
       
  2485     h = FT_REQUEST_HEIGHT( req );
       
  2486 
       
  2487     if ( req->width && !req->height )
       
  2488       h = w;
       
  2489     else if ( !req->width && req->height )
       
  2490       w = h;
       
  2491 
       
  2492     w = FT_PIX_ROUND( w );
       
  2493     h = FT_PIX_ROUND( h );
       
  2494 
       
  2495     for ( i = 0; i < face->num_fixed_sizes; i++ )
       
  2496     {
       
  2497       FT_Bitmap_Size*  bsize = face->available_sizes + i;
       
  2498 
       
  2499 
       
  2500       if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
       
  2501         continue;
       
  2502 
       
  2503       if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
       
  2504       {
       
  2505         if ( size_index )
       
  2506           *size_index = (FT_ULong)i;
       
  2507 
       
  2508         return FT_Err_Ok;
       
  2509       }
       
  2510     }
       
  2511 
       
  2512     return FT_Err_Invalid_Pixel_Size;
       
  2513   }
       
  2514 
       
  2515 
       
  2516   /* documentation is in ftobjs.h */
       
  2517 
       
  2518   FT_BASE_DEF( void )
       
  2519   ft_synthesize_vertical_metrics( FT_Glyph_Metrics*  metrics,
       
  2520                                   FT_Pos             advance )
       
  2521   {
       
  2522     FT_Pos  height = metrics->height;
       
  2523 
       
  2524 
       
  2525     /* compensate for glyph with bbox above/below the baseline */
       
  2526     if ( metrics->horiBearingY < 0 )
       
  2527     {
       
  2528       if ( height < metrics->horiBearingY )
       
  2529         height = metrics->horiBearingY;
       
  2530     }
       
  2531     else if ( metrics->horiBearingY > 0 )
       
  2532       height -= metrics->horiBearingY;
       
  2533 
       
  2534     /* the factor 1.2 is a heuristical value */
       
  2535     if ( !advance )
       
  2536       advance = height * 12 / 10;
       
  2537 
       
  2538     metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
       
  2539     metrics->vertBearingY = ( advance - height ) / 2;
       
  2540     metrics->vertAdvance  = advance;
       
  2541   }
       
  2542 
       
  2543 
       
  2544   static void
       
  2545   ft_recompute_scaled_metrics( FT_Face           face,
       
  2546                                FT_Size_Metrics*  metrics )
       
  2547   {
       
  2548     /* Compute root ascender, descender, test height, and max_advance */
       
  2549 
       
  2550 #ifdef GRID_FIT_METRICS
       
  2551     metrics->ascender    = FT_PIX_CEIL( FT_MulFix( face->ascender,
       
  2552                                                    metrics->y_scale ) );
       
  2553 
       
  2554     metrics->descender   = FT_PIX_FLOOR( FT_MulFix( face->descender,
       
  2555                                                     metrics->y_scale ) );
       
  2556 
       
  2557     metrics->height      = FT_PIX_ROUND( FT_MulFix( face->height,
       
  2558                                                     metrics->y_scale ) );
       
  2559 
       
  2560     metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
       
  2561                                                     metrics->x_scale ) );
       
  2562 #else /* !GRID_FIT_METRICS */
       
  2563     metrics->ascender    = FT_MulFix( face->ascender,
       
  2564                                       metrics->y_scale );
       
  2565 
       
  2566     metrics->descender   = FT_MulFix( face->descender,
       
  2567                                       metrics->y_scale );
       
  2568 
       
  2569     metrics->height      = FT_MulFix( face->height,
       
  2570                                       metrics->y_scale );
       
  2571 
       
  2572     metrics->max_advance = FT_MulFix( face->max_advance_width,
       
  2573                                       metrics->x_scale );
       
  2574 #endif /* !GRID_FIT_METRICS */
       
  2575   }
       
  2576 
       
  2577 
       
  2578   FT_BASE_DEF( void )
       
  2579   FT_Select_Metrics( FT_Face   face,
       
  2580                      FT_ULong  strike_index )
       
  2581   {
       
  2582     FT_Size_Metrics*  metrics;
       
  2583     FT_Bitmap_Size*   bsize;
       
  2584 
       
  2585 
       
  2586     metrics = &face->size->metrics;
       
  2587     bsize   = face->available_sizes + strike_index;
       
  2588 
       
  2589     metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
       
  2590     metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
       
  2591 
       
  2592     if ( FT_IS_SCALABLE( face ) )
       
  2593     {
       
  2594       metrics->x_scale = FT_DivFix( bsize->x_ppem,
       
  2595                                     face->units_per_EM );
       
  2596       metrics->y_scale = FT_DivFix( bsize->y_ppem,
       
  2597                                     face->units_per_EM );
       
  2598 
       
  2599       ft_recompute_scaled_metrics( face, metrics );
       
  2600     }
       
  2601     else
       
  2602     {
       
  2603       metrics->x_scale     = 1L << 16;
       
  2604       metrics->y_scale     = 1L << 16;
       
  2605       metrics->ascender    = bsize->y_ppem;
       
  2606       metrics->descender   = 0;
       
  2607       metrics->height      = bsize->height << 6;
       
  2608       metrics->max_advance = bsize->x_ppem;
       
  2609     }
       
  2610   }
       
  2611 
       
  2612 
       
  2613   FT_BASE_DEF( void )
       
  2614   FT_Request_Metrics( FT_Face          face,
       
  2615                       FT_Size_Request  req )
       
  2616   {
       
  2617     FT_Size_Metrics*  metrics;
       
  2618 
       
  2619 
       
  2620     metrics = &face->size->metrics;
       
  2621 
       
  2622     if ( FT_IS_SCALABLE( face ) )
       
  2623     {
       
  2624       FT_Long  w = 0, h = 0, scaled_w = 0, scaled_h = 0;
       
  2625 
       
  2626 
       
  2627       switch ( req->type )
       
  2628       {
       
  2629       case FT_SIZE_REQUEST_TYPE_NOMINAL:
       
  2630         w = h = face->units_per_EM;
       
  2631         break;
       
  2632 
       
  2633       case FT_SIZE_REQUEST_TYPE_REAL_DIM:
       
  2634         w = h = face->ascender - face->descender;
       
  2635         break;
       
  2636 
       
  2637       case FT_SIZE_REQUEST_TYPE_BBOX:
       
  2638         w = face->bbox.xMax - face->bbox.xMin;
       
  2639         h = face->bbox.yMax - face->bbox.yMin;
       
  2640         break;
       
  2641 
       
  2642       case FT_SIZE_REQUEST_TYPE_CELL:
       
  2643         w = face->max_advance_width;
       
  2644         h = face->ascender - face->descender;
       
  2645         break;
       
  2646 
       
  2647       case FT_SIZE_REQUEST_TYPE_SCALES:
       
  2648         metrics->x_scale = (FT_Fixed)req->width;
       
  2649         metrics->y_scale = (FT_Fixed)req->height;
       
  2650         if ( !metrics->x_scale )
       
  2651           metrics->x_scale = metrics->y_scale;
       
  2652         else if ( !metrics->y_scale )
       
  2653           metrics->y_scale = metrics->x_scale;
       
  2654         goto Calculate_Ppem;
       
  2655 
       
  2656       case FT_SIZE_REQUEST_TYPE_MAX:
       
  2657         break;
       
  2658       }
       
  2659 
       
  2660       /* to be on the safe side */
       
  2661       if ( w < 0 )
       
  2662         w = -w;
       
  2663 
       
  2664       if ( h < 0 )
       
  2665         h = -h;
       
  2666 
       
  2667       scaled_w = FT_REQUEST_WIDTH ( req );
       
  2668       scaled_h = FT_REQUEST_HEIGHT( req );
       
  2669 
       
  2670       /* determine scales */
       
  2671       if ( req->width )
       
  2672       {
       
  2673         metrics->x_scale = FT_DivFix( scaled_w, w );
       
  2674 
       
  2675         if ( req->height )
       
  2676         {
       
  2677           metrics->y_scale = FT_DivFix( scaled_h, h );
       
  2678 
       
  2679           if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
       
  2680           {
       
  2681             if ( metrics->y_scale > metrics->x_scale )
       
  2682               metrics->y_scale = metrics->x_scale;
       
  2683             else
       
  2684               metrics->x_scale = metrics->y_scale;
       
  2685           }
       
  2686         }
       
  2687         else
       
  2688         {
       
  2689           metrics->y_scale = metrics->x_scale;
       
  2690           scaled_h = FT_MulDiv( scaled_w, h, w );
       
  2691         }
       
  2692       }
       
  2693       else
       
  2694       {
       
  2695         metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
       
  2696         scaled_w = FT_MulDiv( scaled_h, w, h );
       
  2697       }
       
  2698 
       
  2699   Calculate_Ppem:
       
  2700       /* calculate the ppems */
       
  2701       if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
       
  2702       {
       
  2703         scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
       
  2704         scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
       
  2705       }
       
  2706 
       
  2707       metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
       
  2708       metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
       
  2709 
       
  2710       ft_recompute_scaled_metrics( face, metrics );
       
  2711     }
       
  2712     else
       
  2713     {
       
  2714       FT_ZERO( metrics );
       
  2715       metrics->x_scale = 1L << 16;
       
  2716       metrics->y_scale = 1L << 16;
       
  2717     }
       
  2718   }
       
  2719 
       
  2720 
       
  2721   /* documentation is in freetype.h */
       
  2722 
       
  2723   FT_EXPORT_DEF( FT_Error )
       
  2724   FT_Select_Size( FT_Face  face,
       
  2725                   FT_Int   strike_index )
       
  2726   {
       
  2727     FT_Driver_Class  clazz;
       
  2728 
       
  2729 
       
  2730     if ( !face || !FT_HAS_FIXED_SIZES( face ) )
       
  2731       return FT_Err_Invalid_Face_Handle;
       
  2732 
       
  2733     if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
       
  2734       return FT_Err_Invalid_Argument;
       
  2735 
       
  2736     clazz = face->driver->clazz;
       
  2737 
       
  2738     if ( clazz->select_size )
       
  2739       return clazz->select_size( face->size, (FT_ULong)strike_index );
       
  2740 
       
  2741     FT_Select_Metrics( face, (FT_ULong)strike_index );
       
  2742 
       
  2743     return FT_Err_Ok;
       
  2744   }
       
  2745 
       
  2746 
       
  2747   /* documentation is in freetype.h */
       
  2748 
       
  2749   FT_EXPORT_DEF( FT_Error )
       
  2750   FT_Request_Size( FT_Face          face,
       
  2751                    FT_Size_Request  req )
       
  2752   {
       
  2753     FT_Driver_Class  clazz;
       
  2754     FT_ULong         strike_index;
       
  2755 
       
  2756 
       
  2757     if ( !face )
       
  2758       return FT_Err_Invalid_Face_Handle;
       
  2759 
       
  2760     if ( !req || req->width < 0 || req->height < 0 ||
       
  2761          req->type >= FT_SIZE_REQUEST_TYPE_MAX )
       
  2762       return FT_Err_Invalid_Argument;
       
  2763 
       
  2764     clazz = face->driver->clazz;
       
  2765 
       
  2766     if ( clazz->request_size )
       
  2767       return clazz->request_size( face->size, req );
       
  2768 
       
  2769     /*
       
  2770      * The reason that a driver doesn't have `request_size' defined is
       
  2771      * either that the scaling here suffices or that the supported formats
       
  2772      * are bitmap-only and size matching is not implemented.
       
  2773      *
       
  2774      * In the latter case, a simple size matching is done.
       
  2775      */
       
  2776     if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
       
  2777     {
       
  2778       FT_Error  error;
       
  2779 
       
  2780 
       
  2781       error = FT_Match_Size( face, req, 0, &strike_index );
       
  2782       if ( error )
       
  2783         return error;
       
  2784 
       
  2785       FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
       
  2786                   strike_index ));
       
  2787 
       
  2788       return FT_Select_Size( face, (FT_Int)strike_index );
       
  2789     }
       
  2790 
       
  2791     FT_Request_Metrics( face, req );
       
  2792 
       
  2793     return FT_Err_Ok;
       
  2794   }
       
  2795 
       
  2796 
       
  2797   /* documentation is in freetype.h */
       
  2798 
       
  2799   FT_EXPORT_DEF( FT_Error )
       
  2800   FT_Set_Char_Size( FT_Face     face,
       
  2801                     FT_F26Dot6  char_width,
       
  2802                     FT_F26Dot6  char_height,
       
  2803                     FT_UInt     horz_resolution,
       
  2804                     FT_UInt     vert_resolution )
       
  2805   {
       
  2806     FT_Size_RequestRec  req;
       
  2807 
       
  2808 
       
  2809     if ( !char_width )
       
  2810       char_width = char_height;
       
  2811     else if ( !char_height )
       
  2812       char_height = char_width;
       
  2813 
       
  2814     if ( !horz_resolution )
       
  2815       horz_resolution = vert_resolution;
       
  2816     else if ( !vert_resolution )
       
  2817       vert_resolution = horz_resolution;
       
  2818 
       
  2819     if ( char_width  < 1 * 64 )
       
  2820       char_width  = 1 * 64;
       
  2821     if ( char_height < 1 * 64 )
       
  2822       char_height = 1 * 64;
       
  2823 
       
  2824     if ( !horz_resolution )
       
  2825       horz_resolution = vert_resolution = 72;
       
  2826 
       
  2827     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
       
  2828     req.width          = char_width;
       
  2829     req.height         = char_height;
       
  2830     req.horiResolution = horz_resolution;
       
  2831     req.vertResolution = vert_resolution;
       
  2832 
       
  2833     return FT_Request_Size( face, &req );
       
  2834   }
       
  2835 
       
  2836 
       
  2837   /* documentation is in freetype.h */
       
  2838 
       
  2839   FT_EXPORT_DEF( FT_Error )
       
  2840   FT_Set_Pixel_Sizes( FT_Face  face,
       
  2841                       FT_UInt  pixel_width,
       
  2842                       FT_UInt  pixel_height )
       
  2843   {
       
  2844     FT_Size_RequestRec  req;
       
  2845 
       
  2846 
       
  2847     if ( pixel_width == 0 )
       
  2848       pixel_width = pixel_height;
       
  2849     else if ( pixel_height == 0 )
       
  2850       pixel_height = pixel_width;
       
  2851 
       
  2852     if ( pixel_width  < 1 )
       
  2853       pixel_width  = 1;
       
  2854     if ( pixel_height < 1 )
       
  2855       pixel_height = 1;
       
  2856 
       
  2857     /* use `>=' to avoid potential compiler warning on 16bit platforms */
       
  2858     if ( pixel_width  >= 0xFFFFU )
       
  2859       pixel_width  = 0xFFFFU;
       
  2860     if ( pixel_height >= 0xFFFFU )
       
  2861       pixel_height = 0xFFFFU;
       
  2862 
       
  2863     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
       
  2864     req.width          = pixel_width << 6;
       
  2865     req.height         = pixel_height << 6;
       
  2866     req.horiResolution = 0;
       
  2867     req.vertResolution = 0;
       
  2868 
       
  2869     return FT_Request_Size( face, &req );
       
  2870   }
       
  2871 
       
  2872 
       
  2873   /* documentation is in freetype.h */
       
  2874 
       
  2875   FT_EXPORT_DEF( FT_Error )
       
  2876   FT_Get_Kerning( FT_Face     face,
       
  2877                   FT_UInt     left_glyph,
       
  2878                   FT_UInt     right_glyph,
       
  2879                   FT_UInt     kern_mode,
       
  2880                   FT_Vector  *akerning )
       
  2881   {
       
  2882     FT_Error   error = FT_Err_Ok;
       
  2883     FT_Driver  driver;
       
  2884 
       
  2885 
       
  2886     if ( !face )
       
  2887       return FT_Err_Invalid_Face_Handle;
       
  2888 
       
  2889     if ( !akerning )
       
  2890       return FT_Err_Invalid_Argument;
       
  2891 
       
  2892     driver = face->driver;
       
  2893 
       
  2894     akerning->x = 0;
       
  2895     akerning->y = 0;
       
  2896 
       
  2897     if ( driver->clazz->get_kerning )
       
  2898     {
       
  2899       error = driver->clazz->get_kerning( face,
       
  2900                                           left_glyph,
       
  2901                                           right_glyph,
       
  2902                                           akerning );
       
  2903       if ( !error )
       
  2904       {
       
  2905         if ( kern_mode != FT_KERNING_UNSCALED )
       
  2906         {
       
  2907           akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
       
  2908           akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
       
  2909 
       
  2910           if ( kern_mode != FT_KERNING_UNFITTED )
       
  2911           {
       
  2912             /* we scale down kerning values for small ppem values */
       
  2913             /* to avoid that rounding makes them too big.         */
       
  2914             /* `25' has been determined heuristically.            */
       
  2915             if ( face->size->metrics.x_ppem < 25 )
       
  2916               akerning->x = FT_MulDiv( akerning->x,
       
  2917                                        face->size->metrics.x_ppem, 25 );
       
  2918             if ( face->size->metrics.y_ppem < 25 )
       
  2919               akerning->y = FT_MulDiv( akerning->y,
       
  2920                                        face->size->metrics.y_ppem, 25 );
       
  2921 
       
  2922             akerning->x = FT_PIX_ROUND( akerning->x );
       
  2923             akerning->y = FT_PIX_ROUND( akerning->y );
       
  2924           }
       
  2925         }
       
  2926       }
       
  2927     }
       
  2928 
       
  2929     return error;
       
  2930   }
       
  2931 
       
  2932 
       
  2933   /* documentation is in freetype.h */
       
  2934 
       
  2935   FT_EXPORT_DEF( FT_Error )
       
  2936   FT_Get_Track_Kerning( FT_Face    face,
       
  2937                         FT_Fixed   point_size,
       
  2938                         FT_Int     degree,
       
  2939                         FT_Fixed*  akerning )
       
  2940   {
       
  2941     FT_Service_Kerning  service;
       
  2942     FT_Error            error = FT_Err_Ok;
       
  2943 
       
  2944 
       
  2945     if ( !face )
       
  2946       return FT_Err_Invalid_Face_Handle;
       
  2947 
       
  2948     if ( !akerning )
       
  2949       return FT_Err_Invalid_Argument;
       
  2950 
       
  2951     FT_FACE_FIND_SERVICE( face, service, KERNING );
       
  2952     if ( !service )
       
  2953       return FT_Err_Unimplemented_Feature;
       
  2954 
       
  2955     error = service->get_track( face,
       
  2956                                 point_size,
       
  2957                                 degree,
       
  2958                                 akerning );
       
  2959 
       
  2960     return error;
       
  2961   }
       
  2962 
       
  2963 
       
  2964   /* documentation is in freetype.h */
       
  2965 
       
  2966   FT_EXPORT_DEF( FT_Error )
       
  2967   FT_Select_Charmap( FT_Face      face,
       
  2968                      FT_Encoding  encoding )
       
  2969   {
       
  2970     FT_CharMap*  cur;
       
  2971     FT_CharMap*  limit;
       
  2972 
       
  2973 
       
  2974     if ( !face )
       
  2975       return FT_Err_Invalid_Face_Handle;
       
  2976 
       
  2977     if ( encoding == FT_ENCODING_NONE )
       
  2978       return FT_Err_Invalid_Argument;
       
  2979 
       
  2980     /* FT_ENCODING_UNICODE is special.  We try to find the `best' Unicode */
       
  2981     /* charmap available, i.e., one with UCS-4 characters, if possible.   */
       
  2982     /*                                                                    */
       
  2983     /* This is done by find_unicode_charmap() above, to share code.       */
       
  2984     if ( encoding == FT_ENCODING_UNICODE )
       
  2985       return find_unicode_charmap( face );
       
  2986 
       
  2987     cur = face->charmaps;
       
  2988     if ( !cur )
       
  2989       return FT_Err_Invalid_CharMap_Handle;
       
  2990 
       
  2991     limit = cur + face->num_charmaps;
       
  2992 
       
  2993     for ( ; cur < limit; cur++ )
       
  2994     {
       
  2995       if ( cur[0]->encoding == encoding )
       
  2996       {
       
  2997 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  2998         if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
       
  2999         {
       
  3000           FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
       
  3001                      "but in too late position to cache\n",
       
  3002                      cur - face->charmaps ));
       
  3003           continue;
       
  3004         }
       
  3005 #endif
       
  3006         face->charmap = cur[0];
       
  3007         return 0;
       
  3008       }
       
  3009     }
       
  3010 
       
  3011     return FT_Err_Invalid_Argument;
       
  3012   }
       
  3013 
       
  3014 
       
  3015   /* documentation is in freetype.h */
       
  3016 
       
  3017   FT_EXPORT_DEF( FT_Error )
       
  3018   FT_Set_Charmap( FT_Face     face,
       
  3019                   FT_CharMap  charmap )
       
  3020   {
       
  3021     FT_CharMap*  cur;
       
  3022     FT_CharMap*  limit;
       
  3023 
       
  3024 
       
  3025     if ( !face )
       
  3026       return FT_Err_Invalid_Face_Handle;
       
  3027 
       
  3028     cur = face->charmaps;
       
  3029     if ( !cur )
       
  3030       return FT_Err_Invalid_CharMap_Handle;
       
  3031     if ( FT_Get_CMap_Format( charmap ) == 14 )
       
  3032       return FT_Err_Invalid_Argument;
       
  3033 
       
  3034     limit = cur + face->num_charmaps;
       
  3035 
       
  3036     for ( ; cur < limit; cur++ )
       
  3037     {
       
  3038       if ( cur[0] == charmap )
       
  3039       {
       
  3040 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  3041         if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
       
  3042         {
       
  3043           FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
       
  3044                      "but in too late position to cache\n",
       
  3045                      cur - face->charmaps ));
       
  3046           continue;
       
  3047         }
       
  3048 #endif
       
  3049         face->charmap = cur[0];
       
  3050         return 0;
       
  3051       }
       
  3052     }
       
  3053     return FT_Err_Invalid_Argument;
       
  3054   }
       
  3055 
       
  3056 
       
  3057   /* documentation is in freetype.h */
       
  3058 
       
  3059   FT_EXPORT_DEF( FT_Int )
       
  3060   FT_Get_Charmap_Index( FT_CharMap  charmap )
       
  3061   {
       
  3062     FT_Int  i;
       
  3063 
       
  3064 
       
  3065     if ( !charmap || !charmap->face )
       
  3066       return -1;
       
  3067 
       
  3068     for ( i = 0; i < charmap->face->num_charmaps; i++ )
       
  3069       if ( charmap->face->charmaps[i] == charmap )
       
  3070         break;
       
  3071 
       
  3072     FT_ASSERT( i < charmap->face->num_charmaps );
       
  3073 
       
  3074 #ifdef FT_MAX_CHARMAP_CACHEABLE
       
  3075     if ( i > FT_MAX_CHARMAP_CACHEABLE )
       
  3076     {
       
  3077       FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
       
  3078                  "but in too late position to cache\n",
       
  3079                  i ));
       
  3080       return -i;
       
  3081     }
       
  3082 #endif
       
  3083     return i;
       
  3084   }
       
  3085 
       
  3086 
       
  3087   static void
       
  3088   ft_cmap_done_internal( FT_CMap  cmap )
       
  3089   {
       
  3090     FT_CMap_Class  clazz  = cmap->clazz;
       
  3091     FT_Face        face   = cmap->charmap.face;
       
  3092     FT_Memory      memory = FT_FACE_MEMORY(face);
       
  3093 
       
  3094 
       
  3095     if ( clazz->done )
       
  3096       clazz->done( cmap );
       
  3097 
       
  3098     FT_FREE( cmap );
       
  3099   }
       
  3100 
       
  3101 
       
  3102   FT_BASE_DEF( void )
       
  3103   FT_CMap_Done( FT_CMap  cmap )
       
  3104   {
       
  3105     if ( cmap )
       
  3106     {
       
  3107       FT_Face    face   = cmap->charmap.face;
       
  3108       FT_Memory  memory = FT_FACE_MEMORY( face );
       
  3109       FT_Error   error;
       
  3110       FT_Int     i, j;
       
  3111 
       
  3112 
       
  3113       for ( i = 0; i < face->num_charmaps; i++ )
       
  3114       {
       
  3115         if ( (FT_CMap)face->charmaps[i] == cmap )
       
  3116         {
       
  3117           FT_CharMap  last_charmap = face->charmaps[face->num_charmaps - 1];
       
  3118 
       
  3119 
       
  3120           if ( FT_RENEW_ARRAY( face->charmaps,
       
  3121                                face->num_charmaps,
       
  3122                                face->num_charmaps - 1 ) )
       
  3123             return;
       
  3124 
       
  3125           /* remove it from our list of charmaps */
       
  3126           for ( j = i + 1; j < face->num_charmaps; j++ )
       
  3127           {
       
  3128             if ( j == face->num_charmaps - 1 )
       
  3129               face->charmaps[j - 1] = last_charmap;
       
  3130             else
       
  3131               face->charmaps[j - 1] = face->charmaps[j];
       
  3132           }
       
  3133 
       
  3134           face->num_charmaps--;
       
  3135 
       
  3136           if ( (FT_CMap)face->charmap == cmap )
       
  3137             face->charmap = NULL;
       
  3138 
       
  3139           ft_cmap_done_internal( cmap );
       
  3140 
       
  3141           break;
       
  3142         }
       
  3143       }
       
  3144     }
       
  3145   }
       
  3146 
       
  3147 
       
  3148   FT_BASE_DEF( FT_Error )
       
  3149   FT_CMap_New( FT_CMap_Class  clazz,
       
  3150                FT_Pointer     init_data,
       
  3151                FT_CharMap     charmap,
       
  3152                FT_CMap       *acmap )
       
  3153   {
       
  3154     FT_Error   error = FT_Err_Ok;
       
  3155     FT_Face    face;
       
  3156     FT_Memory  memory;
       
  3157     FT_CMap    cmap;
       
  3158 
       
  3159 
       
  3160     if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
       
  3161       return FT_Err_Invalid_Argument;
       
  3162 
       
  3163     face   = charmap->face;
       
  3164     memory = FT_FACE_MEMORY( face );
       
  3165 
       
  3166     if ( !FT_ALLOC( cmap, clazz->size ) )
       
  3167     {
       
  3168       cmap->charmap = *charmap;
       
  3169       cmap->clazz   = clazz;
       
  3170 
       
  3171       if ( clazz->init )
       
  3172       {
       
  3173         error = clazz->init( cmap, init_data );
       
  3174         if ( error )
       
  3175           goto Fail;
       
  3176       }
       
  3177 
       
  3178       /* add it to our list of charmaps */
       
  3179       if ( FT_RENEW_ARRAY( face->charmaps,
       
  3180                            face->num_charmaps,
       
  3181                            face->num_charmaps + 1 ) )
       
  3182         goto Fail;
       
  3183 
       
  3184       face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
       
  3185     }
       
  3186 
       
  3187   Exit:
       
  3188     if ( acmap )
       
  3189       *acmap = cmap;
       
  3190 
       
  3191     return error;
       
  3192 
       
  3193   Fail:
       
  3194     ft_cmap_done_internal( cmap );
       
  3195     cmap = NULL;
       
  3196     goto Exit;
       
  3197   }
       
  3198 
       
  3199 
       
  3200   /* documentation is in freetype.h */
       
  3201 
       
  3202   FT_EXPORT_DEF( FT_UInt )
       
  3203   FT_Get_Char_Index( FT_Face   face,
       
  3204                      FT_ULong  charcode )
       
  3205   {
       
  3206     FT_UInt  result = 0;
       
  3207 
       
  3208 
       
  3209     if ( face && face->charmap )
       
  3210     {
       
  3211       FT_CMap  cmap = FT_CMAP( face->charmap );
       
  3212 
       
  3213 
       
  3214       if ( charcode > 0xFFFFFFFFUL )
       
  3215       {
       
  3216         FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
       
  3217         FT_TRACE1(( " 0x%x is truncated\n", charcode ));
       
  3218       }
       
  3219       result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
       
  3220     }
       
  3221     return result;
       
  3222   }
       
  3223 
       
  3224 
       
  3225   /* documentation is in freetype.h */
       
  3226 
       
  3227   FT_EXPORT_DEF( FT_ULong )
       
  3228   FT_Get_First_Char( FT_Face   face,
       
  3229                      FT_UInt  *agindex )
       
  3230   {
       
  3231     FT_ULong  result = 0;
       
  3232     FT_UInt   gindex = 0;
       
  3233 
       
  3234 
       
  3235     if ( face && face->charmap && face->num_glyphs )
       
  3236     {
       
  3237       gindex = FT_Get_Char_Index( face, 0 );
       
  3238       if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
       
  3239         result = FT_Get_Next_Char( face, 0, &gindex );
       
  3240     }
       
  3241 
       
  3242     if ( agindex )
       
  3243       *agindex = gindex;
       
  3244 
       
  3245     return result;
       
  3246   }
       
  3247 
       
  3248 
       
  3249   /* documentation is in freetype.h */
       
  3250 
       
  3251   FT_EXPORT_DEF( FT_ULong )
       
  3252   FT_Get_Next_Char( FT_Face   face,
       
  3253                     FT_ULong  charcode,
       
  3254                     FT_UInt  *agindex )
       
  3255   {
       
  3256     FT_ULong  result = 0;
       
  3257     FT_UInt   gindex = 0;
       
  3258 
       
  3259 
       
  3260     if ( face && face->charmap && face->num_glyphs )
       
  3261     {
       
  3262       FT_UInt32  code = (FT_UInt32)charcode;
       
  3263       FT_CMap    cmap = FT_CMAP( face->charmap );
       
  3264 
       
  3265 
       
  3266       do {
       
  3267         gindex = cmap->clazz->char_next( cmap, &code );
       
  3268       } while ( gindex >= (FT_UInt)face->num_glyphs );
       
  3269 
       
  3270       result = ( gindex == 0 ) ? 0 : code;
       
  3271     }
       
  3272 
       
  3273     if ( agindex )
       
  3274       *agindex = gindex;
       
  3275 
       
  3276     return result;
       
  3277   }
       
  3278 
       
  3279 
       
  3280   /* documentation is in freetype.h */
       
  3281 
       
  3282   FT_EXPORT_DEF( FT_UInt )
       
  3283   FT_Face_GetCharVariantIndex( FT_Face   face,
       
  3284                                FT_ULong  charcode,
       
  3285                                FT_ULong  variantSelector )
       
  3286   {
       
  3287     FT_UInt  result = 0;
       
  3288 
       
  3289 
       
  3290     if ( face && face->charmap &&
       
  3291         face->charmap->encoding == FT_ENCODING_UNICODE )
       
  3292     {
       
  3293       FT_CharMap  charmap = find_variant_selector_charmap( face );
       
  3294       FT_CMap     ucmap = FT_CMAP( face->charmap );
       
  3295 
       
  3296 
       
  3297       if ( charmap != NULL )
       
  3298       {
       
  3299         FT_CMap  vcmap = FT_CMAP( charmap );
       
  3300 
       
  3301 
       
  3302         if ( charcode > 0xFFFFFFFFUL )
       
  3303         {
       
  3304           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
       
  3305           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
       
  3306         }
       
  3307         if ( variantSelector > 0xFFFFFFFFUL )
       
  3308         {
       
  3309           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
       
  3310           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
       
  3311         }
       
  3312 
       
  3313         result = vcmap->clazz->char_var_index( vcmap, ucmap,
       
  3314                                                (FT_UInt32)charcode,
       
  3315                                                (FT_UInt32)variantSelector );
       
  3316       }
       
  3317     }
       
  3318 
       
  3319     return result;
       
  3320   }
       
  3321 
       
  3322 
       
  3323   /* documentation is in freetype.h */
       
  3324 
       
  3325   FT_EXPORT_DEF( FT_Int )
       
  3326   FT_Face_GetCharVariantIsDefault( FT_Face   face,
       
  3327                                    FT_ULong  charcode,
       
  3328                                    FT_ULong  variantSelector )
       
  3329   {
       
  3330     FT_Int  result = -1;
       
  3331 
       
  3332 
       
  3333     if ( face )
       
  3334     {
       
  3335       FT_CharMap  charmap = find_variant_selector_charmap( face );
       
  3336 
       
  3337 
       
  3338       if ( charmap != NULL )
       
  3339       {
       
  3340         FT_CMap  vcmap = FT_CMAP( charmap );
       
  3341 
       
  3342 
       
  3343         if ( charcode > 0xFFFFFFFFUL )
       
  3344         {
       
  3345           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
       
  3346           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
       
  3347         }
       
  3348         if ( variantSelector > 0xFFFFFFFFUL )
       
  3349         {
       
  3350           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
       
  3351           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
       
  3352         }
       
  3353 
       
  3354         result = vcmap->clazz->char_var_default( vcmap,
       
  3355                                                  (FT_UInt32)charcode,
       
  3356                                                  (FT_UInt32)variantSelector );
       
  3357       }
       
  3358     }
       
  3359 
       
  3360     return result;
       
  3361   }
       
  3362 
       
  3363 
       
  3364   /* documentation is in freetype.h */
       
  3365 
       
  3366   FT_EXPORT_DEF( FT_UInt32* )
       
  3367   FT_Face_GetVariantSelectors( FT_Face  face )
       
  3368   {
       
  3369     FT_UInt32  *result = NULL;
       
  3370 
       
  3371 
       
  3372     if ( face )
       
  3373     {
       
  3374       FT_CharMap  charmap = find_variant_selector_charmap( face );
       
  3375 
       
  3376 
       
  3377       if ( charmap != NULL )
       
  3378       {
       
  3379         FT_CMap    vcmap  = FT_CMAP( charmap );
       
  3380         FT_Memory  memory = FT_FACE_MEMORY( face );
       
  3381 
       
  3382 
       
  3383         result = vcmap->clazz->variant_list( vcmap, memory );
       
  3384       }
       
  3385     }
       
  3386 
       
  3387     return result;
       
  3388   }
       
  3389 
       
  3390 
       
  3391   /* documentation is in freetype.h */
       
  3392 
       
  3393   FT_EXPORT_DEF( FT_UInt32* )
       
  3394   FT_Face_GetVariantsOfChar( FT_Face   face,
       
  3395                              FT_ULong  charcode )
       
  3396   {
       
  3397     FT_UInt32  *result = NULL;
       
  3398 
       
  3399 
       
  3400     if ( face )
       
  3401     {
       
  3402       FT_CharMap  charmap = find_variant_selector_charmap( face );
       
  3403 
       
  3404 
       
  3405       if ( charmap != NULL )
       
  3406       {
       
  3407         FT_CMap    vcmap  = FT_CMAP( charmap );
       
  3408         FT_Memory  memory = FT_FACE_MEMORY( face );
       
  3409 
       
  3410 
       
  3411         if ( charcode > 0xFFFFFFFFUL )
       
  3412         {
       
  3413           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
       
  3414           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
       
  3415         }
       
  3416 
       
  3417         result = vcmap->clazz->charvariant_list( vcmap, memory,
       
  3418                                                  (FT_UInt32)charcode );
       
  3419       }
       
  3420     }
       
  3421     return result;
       
  3422   }
       
  3423 
       
  3424 
       
  3425   /* documentation is in freetype.h */
       
  3426 
       
  3427   FT_EXPORT_DEF( FT_UInt32* )
       
  3428   FT_Face_GetCharsOfVariant( FT_Face   face,
       
  3429                              FT_ULong  variantSelector )
       
  3430   {
       
  3431     FT_UInt32  *result = NULL;
       
  3432 
       
  3433 
       
  3434     if ( face )
       
  3435     {
       
  3436       FT_CharMap  charmap = find_variant_selector_charmap( face );
       
  3437 
       
  3438 
       
  3439       if ( charmap != NULL )
       
  3440       {
       
  3441         FT_CMap    vcmap  = FT_CMAP( charmap );
       
  3442         FT_Memory  memory = FT_FACE_MEMORY( face );
       
  3443 
       
  3444 
       
  3445         if ( variantSelector > 0xFFFFFFFFUL )
       
  3446         {
       
  3447           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
       
  3448           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
       
  3449         }
       
  3450 
       
  3451         result = vcmap->clazz->variantchar_list( vcmap, memory,
       
  3452                                                  (FT_UInt32)variantSelector );
       
  3453       }
       
  3454     }
       
  3455 
       
  3456     return result;
       
  3457   }
       
  3458 
       
  3459 
       
  3460   /* documentation is in freetype.h */
       
  3461 
       
  3462   FT_EXPORT_DEF( FT_UInt )
       
  3463   FT_Get_Name_Index( FT_Face     face,
       
  3464                      FT_String*  glyph_name )
       
  3465   {
       
  3466     FT_UInt  result = 0;
       
  3467 
       
  3468 
       
  3469     if ( face && FT_HAS_GLYPH_NAMES( face ) )
       
  3470     {
       
  3471       FT_Service_GlyphDict  service;
       
  3472 
       
  3473 
       
  3474       FT_FACE_LOOKUP_SERVICE( face,
       
  3475                               service,
       
  3476                               GLYPH_DICT );
       
  3477 
       
  3478       if ( service && service->name_index )
       
  3479         result = service->name_index( face, glyph_name );
       
  3480     }
       
  3481 
       
  3482     return result;
       
  3483   }
       
  3484 
       
  3485 
       
  3486   /* documentation is in freetype.h */
       
  3487 
       
  3488   FT_EXPORT_DEF( FT_Error )
       
  3489   FT_Get_Glyph_Name( FT_Face     face,
       
  3490                      FT_UInt     glyph_index,
       
  3491                      FT_Pointer  buffer,
       
  3492                      FT_UInt     buffer_max )
       
  3493   {
       
  3494     FT_Error  error = FT_Err_Invalid_Argument;
       
  3495 
       
  3496 
       
  3497     /* clean up buffer */
       
  3498     if ( buffer && buffer_max > 0 )
       
  3499       ((FT_Byte*)buffer)[0] = 0;
       
  3500 
       
  3501     if ( face                                     &&
       
  3502          (FT_Long)glyph_index <= face->num_glyphs &&
       
  3503          FT_HAS_GLYPH_NAMES( face )               )
       
  3504     {
       
  3505       FT_Service_GlyphDict  service;
       
  3506 
       
  3507 
       
  3508       FT_FACE_LOOKUP_SERVICE( face,
       
  3509                               service,
       
  3510                               GLYPH_DICT );
       
  3511 
       
  3512       if ( service && service->get_name )
       
  3513         error = service->get_name( face, glyph_index, buffer, buffer_max );
       
  3514     }
       
  3515 
       
  3516     return error;
       
  3517   }
       
  3518 
       
  3519 
       
  3520   /* documentation is in freetype.h */
       
  3521 
       
  3522   FT_EXPORT_DEF( const char* )
       
  3523   FT_Get_Postscript_Name( FT_Face  face )
       
  3524   {
       
  3525     const char*  result = NULL;
       
  3526 
       
  3527 
       
  3528     if ( !face )
       
  3529       goto Exit;
       
  3530 
       
  3531     if ( !result )
       
  3532     {
       
  3533       FT_Service_PsFontName  service;
       
  3534 
       
  3535 
       
  3536       FT_FACE_LOOKUP_SERVICE( face,
       
  3537                               service,
       
  3538                               POSTSCRIPT_FONT_NAME );
       
  3539 
       
  3540       if ( service && service->get_ps_font_name )
       
  3541         result = service->get_ps_font_name( face );
       
  3542     }
       
  3543 
       
  3544   Exit:
       
  3545     return result;
       
  3546   }
       
  3547 
       
  3548 
       
  3549   /* documentation is in tttables.h */
       
  3550 
       
  3551   FT_EXPORT_DEF( void* )
       
  3552   FT_Get_Sfnt_Table( FT_Face      face,
       
  3553                      FT_Sfnt_Tag  tag )
       
  3554   {
       
  3555     void*                  table = 0;
       
  3556     FT_Service_SFNT_Table  service;
       
  3557 
       
  3558 
       
  3559     if ( face && FT_IS_SFNT( face ) )
       
  3560     {
       
  3561       FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
       
  3562       if ( service != NULL )
       
  3563         table = service->get_table( face, tag );
       
  3564     }
       
  3565 
       
  3566     return table;
       
  3567   }
       
  3568 
       
  3569 
       
  3570   /* documentation is in tttables.h */
       
  3571 
       
  3572   FT_EXPORT_DEF( FT_Error )
       
  3573   FT_Load_Sfnt_Table( FT_Face    face,
       
  3574                       FT_ULong   tag,
       
  3575                       FT_Long    offset,
       
  3576                       FT_Byte*   buffer,
       
  3577                       FT_ULong*  length )
       
  3578   {
       
  3579     FT_Service_SFNT_Table  service;
       
  3580 
       
  3581 
       
  3582     if ( !face || !FT_IS_SFNT( face ) )
       
  3583       return FT_Err_Invalid_Face_Handle;
       
  3584 
       
  3585     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
       
  3586     if ( service == NULL )
       
  3587       return FT_Err_Unimplemented_Feature;
       
  3588 
       
  3589     return service->load_table( face, tag, offset, buffer, length );
       
  3590   }
       
  3591 
       
  3592 
       
  3593   /* documentation is in tttables.h */
       
  3594 
       
  3595   FT_EXPORT_DEF( FT_Error )
       
  3596   FT_Sfnt_Table_Info( FT_Face    face,
       
  3597                       FT_UInt    table_index,
       
  3598                       FT_ULong  *tag,
       
  3599                       FT_ULong  *length )
       
  3600   {
       
  3601     FT_Service_SFNT_Table  service;
       
  3602     FT_ULong               offset;
       
  3603 
       
  3604 
       
  3605     if ( !face || !FT_IS_SFNT( face ) )
       
  3606       return FT_Err_Invalid_Face_Handle;
       
  3607 
       
  3608     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
       
  3609     if ( service == NULL )
       
  3610       return FT_Err_Unimplemented_Feature;
       
  3611 
       
  3612     return service->table_info( face, table_index, tag, &offset, length );
       
  3613   }
       
  3614 
       
  3615 
       
  3616   /* documentation is in tttables.h */
       
  3617 
       
  3618   FT_EXPORT_DEF( FT_ULong )
       
  3619   FT_Get_CMap_Language_ID( FT_CharMap  charmap )
       
  3620   {
       
  3621     FT_Service_TTCMaps  service;
       
  3622     FT_Face             face;
       
  3623     TT_CMapInfo         cmap_info;
       
  3624 
       
  3625 
       
  3626     if ( !charmap || !charmap->face )
       
  3627       return 0;
       
  3628 
       
  3629     face = charmap->face;
       
  3630     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
       
  3631     if ( service == NULL )
       
  3632       return 0;
       
  3633     if ( service->get_cmap_info( charmap, &cmap_info ))
       
  3634       return 0;
       
  3635 
       
  3636     return cmap_info.language;
       
  3637   }
       
  3638 
       
  3639 
       
  3640   /* documentation is in tttables.h */
       
  3641 
       
  3642   FT_EXPORT_DEF( FT_Long )
       
  3643   FT_Get_CMap_Format( FT_CharMap  charmap )
       
  3644   {
       
  3645     FT_Service_TTCMaps  service;
       
  3646     FT_Face             face;
       
  3647     TT_CMapInfo         cmap_info;
       
  3648 
       
  3649 
       
  3650     if ( !charmap || !charmap->face )
       
  3651       return -1;
       
  3652 
       
  3653     face = charmap->face;
       
  3654     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
       
  3655     if ( service == NULL )
       
  3656       return -1;
       
  3657     if ( service->get_cmap_info( charmap, &cmap_info ))
       
  3658       return -1;
       
  3659 
       
  3660     return cmap_info.format;
       
  3661   }
       
  3662 
       
  3663 
       
  3664   /* documentation is in ftsizes.h */
       
  3665 
       
  3666   FT_EXPORT_DEF( FT_Error )
       
  3667   FT_Activate_Size( FT_Size  size )
       
  3668   {
       
  3669     FT_Face  face;
       
  3670 
       
  3671 
       
  3672     if ( size == NULL )
       
  3673       return FT_Err_Invalid_Argument;
       
  3674 
       
  3675     face = size->face;
       
  3676     if ( face == NULL || face->driver == NULL )
       
  3677       return FT_Err_Invalid_Argument;
       
  3678 
       
  3679     /* we don't need anything more complex than that; all size objects */
       
  3680     /* are already listed by the face                                  */
       
  3681     face->size = size;
       
  3682 
       
  3683     return FT_Err_Ok;
       
  3684   }
       
  3685 
       
  3686 
       
  3687   /*************************************************************************/
       
  3688   /*************************************************************************/
       
  3689   /*************************************************************************/
       
  3690   /****                                                                 ****/
       
  3691   /****                                                                 ****/
       
  3692   /****                        R E N D E R E R S                        ****/
       
  3693   /****                                                                 ****/
       
  3694   /****                                                                 ****/
       
  3695   /*************************************************************************/
       
  3696   /*************************************************************************/
       
  3697   /*************************************************************************/
       
  3698 
       
  3699   /* lookup a renderer by glyph format in the library's list */
       
  3700   FT_BASE_DEF( FT_Renderer )
       
  3701   FT_Lookup_Renderer( FT_Library       library,
       
  3702                       FT_Glyph_Format  format,
       
  3703                       FT_ListNode*     node )
       
  3704   {
       
  3705     FT_ListNode  cur;
       
  3706     FT_Renderer  result = 0;
       
  3707 
       
  3708 
       
  3709     if ( !library )
       
  3710       goto Exit;
       
  3711 
       
  3712     cur = library->renderers.head;
       
  3713 
       
  3714     if ( node )
       
  3715     {
       
  3716       if ( *node )
       
  3717         cur = (*node)->next;
       
  3718       *node = 0;
       
  3719     }
       
  3720 
       
  3721     while ( cur )
       
  3722     {
       
  3723       FT_Renderer  renderer = FT_RENDERER( cur->data );
       
  3724 
       
  3725 
       
  3726       if ( renderer->glyph_format == format )
       
  3727       {
       
  3728         if ( node )
       
  3729           *node = cur;
       
  3730 
       
  3731         result = renderer;
       
  3732         break;
       
  3733       }
       
  3734       cur = cur->next;
       
  3735     }
       
  3736 
       
  3737   Exit:
       
  3738     return result;
       
  3739   }
       
  3740 
       
  3741 
       
  3742   static FT_Renderer
       
  3743   ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
       
  3744   {
       
  3745     FT_Face      face    = slot->face;
       
  3746     FT_Library   library = FT_FACE_LIBRARY( face );
       
  3747     FT_Renderer  result  = library->cur_renderer;
       
  3748 
       
  3749 
       
  3750     if ( !result || result->glyph_format != slot->format )
       
  3751       result = FT_Lookup_Renderer( library, slot->format, 0 );
       
  3752 
       
  3753     return result;
       
  3754   }
       
  3755 
       
  3756 
       
  3757   static void
       
  3758   ft_set_current_renderer( FT_Library  library )
       
  3759   {
       
  3760     FT_Renderer  renderer;
       
  3761 
       
  3762 
       
  3763     renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
       
  3764     library->cur_renderer = renderer;
       
  3765   }
       
  3766 
       
  3767 
       
  3768   static FT_Error
       
  3769   ft_add_renderer( FT_Module  module )
       
  3770   {
       
  3771     FT_Library   library = module->library;
       
  3772     FT_Memory    memory  = library->memory;
       
  3773     FT_Error     error;
       
  3774     FT_ListNode  node    = NULL;
       
  3775 
       
  3776 
       
  3777     if ( FT_NEW( node ) )
       
  3778       goto Exit;
       
  3779 
       
  3780     {
       
  3781       FT_Renderer         render = FT_RENDERER( module );
       
  3782       FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
       
  3783 
       
  3784 
       
  3785       render->clazz        = clazz;
       
  3786       render->glyph_format = clazz->glyph_format;
       
  3787 
       
  3788       /* allocate raster object if needed */
       
  3789       if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
       
  3790            clazz->raster_class->raster_new                )
       
  3791       {
       
  3792         error = clazz->raster_class->raster_new( memory, &render->raster );
       
  3793         if ( error )
       
  3794           goto Fail;
       
  3795 
       
  3796         render->raster_render = clazz->raster_class->raster_render;
       
  3797         render->render        = clazz->render_glyph;
       
  3798       }
       
  3799 
       
  3800       /* add to list */
       
  3801       node->data = module;
       
  3802       FT_List_Add( &library->renderers, node );
       
  3803 
       
  3804       ft_set_current_renderer( library );
       
  3805     }
       
  3806 
       
  3807   Fail:
       
  3808     if ( error )
       
  3809       FT_FREE( node );
       
  3810 
       
  3811   Exit:
       
  3812     return error;
       
  3813   }
       
  3814 
       
  3815 
       
  3816   static void
       
  3817   ft_remove_renderer( FT_Module  module )
       
  3818   {
       
  3819     FT_Library   library = module->library;
       
  3820     FT_Memory    memory  = library->memory;
       
  3821     FT_ListNode  node;
       
  3822 
       
  3823 
       
  3824     node = FT_List_Find( &library->renderers, module );
       
  3825     if ( node )
       
  3826     {
       
  3827       FT_Renderer  render = FT_RENDERER( module );
       
  3828 
       
  3829 
       
  3830       /* release raster object, if any */
       
  3831       if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
       
  3832            render->raster                                         )
       
  3833         render->clazz->raster_class->raster_done( render->raster );
       
  3834 
       
  3835       /* remove from list */
       
  3836       FT_List_Remove( &library->renderers, node );
       
  3837       FT_FREE( node );
       
  3838 
       
  3839       ft_set_current_renderer( library );
       
  3840     }
       
  3841   }
       
  3842 
       
  3843 
       
  3844   /* documentation is in ftrender.h */
       
  3845 
       
  3846   FT_EXPORT_DEF( FT_Renderer )
       
  3847   FT_Get_Renderer( FT_Library       library,
       
  3848                    FT_Glyph_Format  format )
       
  3849   {
       
  3850     /* test for valid `library' delayed to FT_Lookup_Renderer() */
       
  3851 
       
  3852     return FT_Lookup_Renderer( library, format, 0 );
       
  3853   }
       
  3854 
       
  3855 
       
  3856   /* documentation is in ftrender.h */
       
  3857 
       
  3858   FT_EXPORT_DEF( FT_Error )
       
  3859   FT_Set_Renderer( FT_Library     library,
       
  3860                    FT_Renderer    renderer,
       
  3861                    FT_UInt        num_params,
       
  3862                    FT_Parameter*  parameters )
       
  3863   {
       
  3864     FT_ListNode  node;
       
  3865     FT_Error     error = FT_Err_Ok;
       
  3866 
       
  3867 
       
  3868     if ( !library )
       
  3869       return FT_Err_Invalid_Library_Handle;
       
  3870 
       
  3871     if ( !renderer )
       
  3872       return FT_Err_Invalid_Argument;
       
  3873 
       
  3874     node = FT_List_Find( &library->renderers, renderer );
       
  3875     if ( !node )
       
  3876     {
       
  3877       error = FT_Err_Invalid_Argument;
       
  3878       goto Exit;
       
  3879     }
       
  3880 
       
  3881     FT_List_Up( &library->renderers, node );
       
  3882 
       
  3883     if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
       
  3884       library->cur_renderer = renderer;
       
  3885 
       
  3886     if ( num_params > 0 )
       
  3887     {
       
  3888       FT_Renderer_SetModeFunc  set_mode = renderer->clazz->set_mode;
       
  3889 
       
  3890 
       
  3891       for ( ; num_params > 0; num_params-- )
       
  3892       {
       
  3893         error = set_mode( renderer, parameters->tag, parameters->data );
       
  3894         if ( error )
       
  3895           break;
       
  3896         parameters++;
       
  3897       }
       
  3898     }
       
  3899 
       
  3900   Exit:
       
  3901     return error;
       
  3902   }
       
  3903 
       
  3904 
       
  3905   FT_BASE_DEF( FT_Error )
       
  3906   FT_Render_Glyph_Internal( FT_Library      library,
       
  3907                             FT_GlyphSlot    slot,
       
  3908                             FT_Render_Mode  render_mode )
       
  3909   {
       
  3910     FT_Error     error = FT_Err_Ok;
       
  3911     FT_Renderer  renderer;
       
  3912 
       
  3913 
       
  3914     /* if it is already a bitmap, no need to do anything */
       
  3915     switch ( slot->format )
       
  3916     {
       
  3917     case FT_GLYPH_FORMAT_BITMAP:   /* already a bitmap, don't do anything */
       
  3918       break;
       
  3919 
       
  3920     default:
       
  3921       {
       
  3922         FT_ListNode  node   = 0;
       
  3923         FT_Bool      update = 0;
       
  3924 
       
  3925 
       
  3926         /* small shortcut for the very common case */
       
  3927         if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
       
  3928         {
       
  3929           renderer = library->cur_renderer;
       
  3930           node     = library->renderers.head;
       
  3931         }
       
  3932         else
       
  3933           renderer = FT_Lookup_Renderer( library, slot->format, &node );
       
  3934 
       
  3935         error = FT_Err_Unimplemented_Feature;
       
  3936         while ( renderer )
       
  3937         {
       
  3938           error = renderer->render( renderer, slot, render_mode, NULL );
       
  3939           if ( !error                                               ||
       
  3940                FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
       
  3941             break;
       
  3942 
       
  3943           /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
       
  3944           /* is unsupported by the current renderer for this glyph image */
       
  3945           /* format.                                                     */
       
  3946 
       
  3947           /* now, look for another renderer that supports the same */
       
  3948           /* format.                                               */
       
  3949           renderer = FT_Lookup_Renderer( library, slot->format, &node );
       
  3950           update   = 1;
       
  3951         }
       
  3952 
       
  3953         /* if we changed the current renderer for the glyph image format */
       
  3954         /* we need to select it as the next current one                  */
       
  3955         if ( !error && update && renderer )
       
  3956           FT_Set_Renderer( library, renderer, 0, 0 );
       
  3957       }
       
  3958     }
       
  3959 
       
  3960     return error;
       
  3961   }
       
  3962 
       
  3963 
       
  3964   /* documentation is in freetype.h */
       
  3965 
       
  3966   FT_EXPORT_DEF( FT_Error )
       
  3967   FT_Render_Glyph( FT_GlyphSlot    slot,
       
  3968                    FT_Render_Mode  render_mode )
       
  3969   {
       
  3970     FT_Library  library;
       
  3971 
       
  3972 
       
  3973     if ( !slot || !slot->face )
       
  3974       return FT_Err_Invalid_Argument;
       
  3975 
       
  3976     library = FT_FACE_LIBRARY( slot->face );
       
  3977 
       
  3978     return FT_Render_Glyph_Internal( library, slot, render_mode );
       
  3979   }
       
  3980 
       
  3981 
       
  3982   /*************************************************************************/
       
  3983   /*************************************************************************/
       
  3984   /*************************************************************************/
       
  3985   /****                                                                 ****/
       
  3986   /****                                                                 ****/
       
  3987   /****                         M O D U L E S                           ****/
       
  3988   /****                                                                 ****/
       
  3989   /****                                                                 ****/
       
  3990   /*************************************************************************/
       
  3991   /*************************************************************************/
       
  3992   /*************************************************************************/
       
  3993 
       
  3994 
       
  3995   /*************************************************************************/
       
  3996   /*                                                                       */
       
  3997   /* <Function>                                                            */
       
  3998   /*    Destroy_Module                                                     */
       
  3999   /*                                                                       */
       
  4000   /* <Description>                                                         */
       
  4001   /*    Destroys a given module object.  For drivers, this also destroys   */
       
  4002   /*    all child faces.                                                   */
       
  4003   /*                                                                       */
       
  4004   /* <InOut>                                                               */
       
  4005   /*     module :: A handle to the target driver object.                   */
       
  4006   /*                                                                       */
       
  4007   /* <Note>                                                                */
       
  4008   /*     The driver _must_ be LOCKED!                                      */
       
  4009   /*                                                                       */
       
  4010   static void
       
  4011   Destroy_Module( FT_Module  module )
       
  4012   {
       
  4013     FT_Memory         memory  = module->memory;
       
  4014     FT_Module_Class*  clazz   = module->clazz;
       
  4015     FT_Library        library = module->library;
       
  4016 
       
  4017 
       
  4018     /* finalize client-data - before anything else */
       
  4019     if ( module->generic.finalizer )
       
  4020       module->generic.finalizer( module );
       
  4021 
       
  4022     if ( library && library->auto_hinter == module )
       
  4023       library->auto_hinter = 0;
       
  4024 
       
  4025     /* if the module is a renderer */
       
  4026     if ( FT_MODULE_IS_RENDERER( module ) )
       
  4027       ft_remove_renderer( module );
       
  4028 
       
  4029     /* if the module is a font driver, add some steps */
       
  4030     if ( FT_MODULE_IS_DRIVER( module ) )
       
  4031       Destroy_Driver( FT_DRIVER( module ) );
       
  4032 
       
  4033     /* finalize the module object */
       
  4034     if ( clazz->module_done )
       
  4035       clazz->module_done( module );
       
  4036 
       
  4037     /* discard it */
       
  4038     FT_FREE( module );
       
  4039   }
       
  4040 
       
  4041 
       
  4042   /* documentation is in ftmodapi.h */
       
  4043 
       
  4044   FT_EXPORT_DEF( FT_Error )
       
  4045   FT_Add_Module( FT_Library              library,
       
  4046                  const FT_Module_Class*  clazz )
       
  4047   {
       
  4048     FT_Error   error;
       
  4049     FT_Memory  memory;
       
  4050     FT_Module  module;
       
  4051     FT_UInt    nn;
       
  4052 
       
  4053 
       
  4054 #define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
       
  4055                                 FREETYPE_MINOR                  )
       
  4056 
       
  4057     if ( !library )
       
  4058       return FT_Err_Invalid_Library_Handle;
       
  4059 
       
  4060     if ( !clazz )
       
  4061       return FT_Err_Invalid_Argument;
       
  4062 
       
  4063     /* check freetype version */
       
  4064     if ( clazz->module_requires > FREETYPE_VER_FIXED )
       
  4065       return FT_Err_Invalid_Version;
       
  4066 
       
  4067     /* look for a module with the same name in the library's table */
       
  4068     for ( nn = 0; nn < library->num_modules; nn++ )
       
  4069     {
       
  4070       module = library->modules[nn];
       
  4071       if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
       
  4072       {
       
  4073         /* this installed module has the same name, compare their versions */
       
  4074         if ( clazz->module_version <= module->clazz->module_version )
       
  4075           return FT_Err_Lower_Module_Version;
       
  4076 
       
  4077         /* remove the module from our list, then exit the loop to replace */
       
  4078         /* it by our new version..                                        */
       
  4079         FT_Remove_Module( library, module );
       
  4080         break;
       
  4081       }
       
  4082     }
       
  4083 
       
  4084     memory = library->memory;
       
  4085     error  = FT_Err_Ok;
       
  4086 
       
  4087     if ( library->num_modules >= FT_MAX_MODULES )
       
  4088     {
       
  4089       error = FT_Err_Too_Many_Drivers;
       
  4090       goto Exit;
       
  4091     }
       
  4092 
       
  4093     /* allocate module object */
       
  4094     if ( FT_ALLOC( module, clazz->module_size ) )
       
  4095       goto Exit;
       
  4096 
       
  4097     /* base initialization */
       
  4098     module->library = library;
       
  4099     module->memory  = memory;
       
  4100     module->clazz   = (FT_Module_Class*)clazz;
       
  4101 
       
  4102     /* check whether the module is a renderer - this must be performed */
       
  4103     /* before the normal module initialization                         */
       
  4104     if ( FT_MODULE_IS_RENDERER( module ) )
       
  4105     {
       
  4106       /* add to the renderers list */
       
  4107       error = ft_add_renderer( module );
       
  4108       if ( error )
       
  4109         goto Fail;
       
  4110     }
       
  4111 
       
  4112     /* is the module a auto-hinter? */
       
  4113     if ( FT_MODULE_IS_HINTER( module ) )
       
  4114       library->auto_hinter = module;
       
  4115 
       
  4116     /* if the module is a font driver */
       
  4117     if ( FT_MODULE_IS_DRIVER( module ) )
       
  4118     {
       
  4119       /* allocate glyph loader if needed */
       
  4120       FT_Driver  driver = FT_DRIVER( module );
       
  4121 
       
  4122 
       
  4123       driver->clazz = (FT_Driver_Class)module->clazz;
       
  4124       if ( FT_DRIVER_USES_OUTLINES( driver ) )
       
  4125       {
       
  4126         error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
       
  4127         if ( error )
       
  4128           goto Fail;
       
  4129       }
       
  4130     }
       
  4131 
       
  4132     if ( clazz->module_init )
       
  4133     {
       
  4134       error = clazz->module_init( module );
       
  4135       if ( error )
       
  4136         goto Fail;
       
  4137     }
       
  4138 
       
  4139     /* add module to the library's table */
       
  4140     library->modules[library->num_modules++] = module;
       
  4141 
       
  4142   Exit:
       
  4143     return error;
       
  4144 
       
  4145   Fail:
       
  4146     if ( FT_MODULE_IS_DRIVER( module ) )
       
  4147     {
       
  4148       FT_Driver  driver = FT_DRIVER( module );
       
  4149 
       
  4150 
       
  4151       if ( FT_DRIVER_USES_OUTLINES( driver ) )
       
  4152         FT_GlyphLoader_Done( driver->glyph_loader );
       
  4153     }
       
  4154 
       
  4155     if ( FT_MODULE_IS_RENDERER( module ) )
       
  4156     {
       
  4157       FT_Renderer  renderer = FT_RENDERER( module );
       
  4158 
       
  4159 
       
  4160       if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
       
  4161            renderer->raster                                         )
       
  4162         renderer->clazz->raster_class->raster_done( renderer->raster );
       
  4163     }
       
  4164 
       
  4165     FT_FREE( module );
       
  4166     goto Exit;
       
  4167   }
       
  4168 
       
  4169 
       
  4170   /* documentation is in ftmodapi.h */
       
  4171 
       
  4172   FT_EXPORT_DEF( FT_Module )
       
  4173   FT_Get_Module( FT_Library   library,
       
  4174                  const char*  module_name )
       
  4175   {
       
  4176     FT_Module   result = 0;
       
  4177     FT_Module*  cur;
       
  4178     FT_Module*  limit;
       
  4179 
       
  4180 
       
  4181     if ( !library || !module_name )
       
  4182       return result;
       
  4183 
       
  4184     cur   = library->modules;
       
  4185     limit = cur + library->num_modules;
       
  4186 
       
  4187     for ( ; cur < limit; cur++ )
       
  4188       if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
       
  4189       {
       
  4190         result = cur[0];
       
  4191         break;
       
  4192       }
       
  4193 
       
  4194     return result;
       
  4195   }
       
  4196 
       
  4197 
       
  4198   /* documentation is in ftobjs.h */
       
  4199 
       
  4200   FT_BASE_DEF( const void* )
       
  4201   FT_Get_Module_Interface( FT_Library   library,
       
  4202                            const char*  mod_name )
       
  4203   {
       
  4204     FT_Module  module;
       
  4205 
       
  4206 
       
  4207     /* test for valid `library' delayed to FT_Get_Module() */
       
  4208 
       
  4209     module = FT_Get_Module( library, mod_name );
       
  4210 
       
  4211     return module ? module->clazz->module_interface : 0;
       
  4212   }
       
  4213 
       
  4214 
       
  4215   FT_BASE_DEF( FT_Pointer )
       
  4216   ft_module_get_service( FT_Module    module,
       
  4217                          const char*  service_id )
       
  4218   {
       
  4219     FT_Pointer  result = NULL;
       
  4220 
       
  4221     if ( module )
       
  4222     {
       
  4223       FT_ASSERT( module->clazz && module->clazz->get_interface );
       
  4224 
       
  4225      /* first, look for the service in the module
       
  4226       */
       
  4227       if ( module->clazz->get_interface )
       
  4228         result = module->clazz->get_interface( module, service_id );
       
  4229 
       
  4230       if ( result == NULL )
       
  4231       {
       
  4232        /* we didn't find it, look in all other modules then
       
  4233         */
       
  4234         FT_Library  library = module->library;
       
  4235         FT_Module*  cur     = library->modules;
       
  4236         FT_Module*  limit   = cur + library->num_modules;
       
  4237 
       
  4238         for ( ; cur < limit; cur++ )
       
  4239         {
       
  4240           if ( cur[0] != module )
       
  4241           {
       
  4242             FT_ASSERT( cur[0]->clazz );
       
  4243 
       
  4244             if ( cur[0]->clazz->get_interface )
       
  4245             {
       
  4246               result = cur[0]->clazz->get_interface( cur[0], service_id );
       
  4247               if ( result != NULL )
       
  4248                 break;
       
  4249             }
       
  4250           }
       
  4251         }
       
  4252       }
       
  4253     }
       
  4254 
       
  4255     return result;
       
  4256   }
       
  4257 
       
  4258 
       
  4259   /* documentation is in ftmodapi.h */
       
  4260 
       
  4261   FT_EXPORT_DEF( FT_Error )
       
  4262   FT_Remove_Module( FT_Library  library,
       
  4263                     FT_Module   module )
       
  4264   {
       
  4265     /* try to find the module from the table, then remove it from there */
       
  4266 
       
  4267     if ( !library )
       
  4268       return FT_Err_Invalid_Library_Handle;
       
  4269 
       
  4270     if ( module )
       
  4271     {
       
  4272       FT_Module*  cur   = library->modules;
       
  4273       FT_Module*  limit = cur + library->num_modules;
       
  4274 
       
  4275 
       
  4276       for ( ; cur < limit; cur++ )
       
  4277       {
       
  4278         if ( cur[0] == module )
       
  4279         {
       
  4280           /* remove it from the table */
       
  4281           library->num_modules--;
       
  4282           limit--;
       
  4283           while ( cur < limit )
       
  4284           {
       
  4285             cur[0] = cur[1];
       
  4286             cur++;
       
  4287           }
       
  4288           limit[0] = 0;
       
  4289 
       
  4290           /* destroy the module */
       
  4291           Destroy_Module( module );
       
  4292 
       
  4293           return FT_Err_Ok;
       
  4294         }
       
  4295       }
       
  4296     }
       
  4297     return FT_Err_Invalid_Driver_Handle;
       
  4298   }
       
  4299 
       
  4300 
       
  4301   /*************************************************************************/
       
  4302   /*************************************************************************/
       
  4303   /*************************************************************************/
       
  4304   /****                                                                 ****/
       
  4305   /****                                                                 ****/
       
  4306   /****                         L I B R A R Y                           ****/
       
  4307   /****                                                                 ****/
       
  4308   /****                                                                 ****/
       
  4309   /*************************************************************************/
       
  4310   /*************************************************************************/
       
  4311   /*************************************************************************/
       
  4312 
       
  4313 
       
  4314   /* documentation is in ftmodapi.h */
       
  4315 
       
  4316   FT_EXPORT_DEF( FT_Error )
       
  4317   FT_Reference_Library( FT_Library  library )
       
  4318   {
       
  4319     library->refcount++;
       
  4320 
       
  4321     return FT_Err_Ok;
       
  4322   }
       
  4323 
       
  4324 
       
  4325   /* documentation is in ftmodapi.h */
       
  4326 
       
  4327   FT_EXPORT_DEF( FT_Error )
       
  4328   FT_New_Library( FT_Memory    memory,
       
  4329                   FT_Library  *alibrary )
       
  4330   {
       
  4331     FT_Library  library = NULL;
       
  4332     FT_Error    error;
       
  4333 
       
  4334 
       
  4335     if ( !memory )
       
  4336       return FT_Err_Invalid_Argument;
       
  4337 
       
  4338 #ifdef FT_DEBUG_LEVEL_ERROR
       
  4339     /* init debugging support */
       
  4340     ft_debug_init();
       
  4341 #endif
       
  4342 
       
  4343     /* first of all, allocate the library object */
       
  4344     if ( FT_NEW( library ) )
       
  4345       return error;
       
  4346 
       
  4347     library->memory = memory;
       
  4348 
       
  4349 #ifdef FT_CONFIG_OPTION_PIC
       
  4350     /* initialize position independent code containers */
       
  4351     error = ft_pic_container_init( library );
       
  4352     if ( error )
       
  4353       goto Fail;
       
  4354 #endif
       
  4355 
       
  4356     /* allocate the render pool */
       
  4357     library->raster_pool_size = FT_RENDER_POOL_SIZE;
       
  4358 #if FT_RENDER_POOL_SIZE > 0
       
  4359     if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
       
  4360       goto Fail;
       
  4361 #endif
       
  4362 
       
  4363     library->version_major = FREETYPE_MAJOR;
       
  4364     library->version_minor = FREETYPE_MINOR;
       
  4365     library->version_patch = FREETYPE_PATCH;
       
  4366 
       
  4367     library->refcount = 1;
       
  4368 
       
  4369     /* That's ok now */
       
  4370     *alibrary = library;
       
  4371 
       
  4372     return FT_Err_Ok;
       
  4373 
       
  4374   Fail:
       
  4375 #ifdef FT_CONFIG_OPTION_PIC
       
  4376     ft_pic_container_destroy( library );
       
  4377 #endif
       
  4378     FT_FREE( library );
       
  4379     return error;
       
  4380   }
       
  4381 
       
  4382 
       
  4383   /* documentation is in freetype.h */
       
  4384 
       
  4385   FT_EXPORT_DEF( void )
       
  4386   FT_Library_Version( FT_Library   library,
       
  4387                       FT_Int      *amajor,
       
  4388                       FT_Int      *aminor,
       
  4389                       FT_Int      *apatch )
       
  4390   {
       
  4391     FT_Int  major = 0;
       
  4392     FT_Int  minor = 0;
       
  4393     FT_Int  patch = 0;
       
  4394 
       
  4395 
       
  4396     if ( library )
       
  4397     {
       
  4398       major = library->version_major;
       
  4399       minor = library->version_minor;
       
  4400       patch = library->version_patch;
       
  4401     }
       
  4402 
       
  4403     if ( amajor )
       
  4404       *amajor = major;
       
  4405 
       
  4406     if ( aminor )
       
  4407       *aminor = minor;
       
  4408 
       
  4409     if ( apatch )
       
  4410       *apatch = patch;
       
  4411   }
       
  4412 
       
  4413 
       
  4414   /* documentation is in ftmodapi.h */
       
  4415 
       
  4416   FT_EXPORT_DEF( FT_Error )
       
  4417   FT_Done_Library( FT_Library  library )
       
  4418   {
       
  4419     FT_Memory  memory;
       
  4420 
       
  4421 
       
  4422     if ( !library )
       
  4423       return FT_Err_Invalid_Library_Handle;
       
  4424 
       
  4425     library->refcount--;
       
  4426     if ( library->refcount > 0 )
       
  4427       goto Exit;
       
  4428 
       
  4429     memory = library->memory;
       
  4430 
       
  4431     /* Discard client-data */
       
  4432     if ( library->generic.finalizer )
       
  4433       library->generic.finalizer( library );
       
  4434 
       
  4435     /*
       
  4436      * Close all faces in the library.  If we don't do this, we can have
       
  4437      * some subtle memory leaks.
       
  4438      *
       
  4439      * Example:
       
  4440      *
       
  4441      *  - the cff font driver uses the pshinter module in cff_size_done
       
  4442      *  - if the pshinter module is destroyed before the cff font driver,
       
  4443      *    opened FT_Face objects managed by the driver are not properly
       
  4444      *    destroyed, resulting in a memory leak
       
  4445      *
       
  4446      * Some faces are dependent on other faces, like Type42 faces that
       
  4447      * depend on TrueType faces synthesized internally.
       
  4448      *
       
  4449      * The order of drivers should be specified in driver_name[].
       
  4450      */
       
  4451     {
       
  4452       FT_UInt      m, n;
       
  4453       const char*  driver_name[] = { "type42", NULL };
       
  4454 
       
  4455 
       
  4456       for ( m = 0;
       
  4457             m < sizeof ( driver_name ) / sizeof ( driver_name[0] );
       
  4458             m++ )
       
  4459       {
       
  4460         for ( n = 0; n < library->num_modules; n++ )
       
  4461         {
       
  4462           FT_Module    module      = library->modules[n];
       
  4463           const char*  module_name = module->clazz->module_name;
       
  4464           FT_List      faces;
       
  4465 
       
  4466 
       
  4467           if ( driver_name[m]                                &&
       
  4468                ft_strcmp( module_name, driver_name[m] ) != 0 )
       
  4469             continue;
       
  4470 
       
  4471           if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
       
  4472             continue;
       
  4473 
       
  4474           FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name ));
       
  4475 
       
  4476           faces = &FT_DRIVER( module )->faces_list;
       
  4477           while ( faces->head )
       
  4478           {
       
  4479             FT_Done_Face( FT_FACE( faces->head->data ) );
       
  4480             if ( faces->head )
       
  4481               FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
       
  4482           }
       
  4483         }
       
  4484       }
       
  4485     }
       
  4486 
       
  4487     /* Close all other modules in the library */
       
  4488 #if 1
       
  4489     /* XXX Modules are removed in the reversed order so that  */
       
  4490     /* type42 module is removed before truetype module.  This */
       
  4491     /* avoids double free in some occasions.  It is a hack.   */
       
  4492     while ( library->num_modules > 0 )
       
  4493       FT_Remove_Module( library,
       
  4494                         library->modules[library->num_modules - 1] );
       
  4495 #else
       
  4496     {
       
  4497       FT_UInt  n;
       
  4498 
       
  4499 
       
  4500       for ( n = 0; n < library->num_modules; n++ )
       
  4501       {
       
  4502         FT_Module  module = library->modules[n];
       
  4503 
       
  4504 
       
  4505         if ( module )
       
  4506         {
       
  4507           Destroy_Module( module );
       
  4508           library->modules[n] = 0;
       
  4509         }
       
  4510       }
       
  4511     }
       
  4512 #endif
       
  4513 
       
  4514     /* Destroy raster objects */
       
  4515     FT_FREE( library->raster_pool );
       
  4516     library->raster_pool_size = 0;
       
  4517 
       
  4518 #ifdef FT_CONFIG_OPTION_PIC
       
  4519     /* Destroy pic container contents */
       
  4520     ft_pic_container_destroy( library );
       
  4521 #endif
       
  4522 
       
  4523     FT_FREE( library );
       
  4524 
       
  4525   Exit:
       
  4526     return FT_Err_Ok;
       
  4527   }
       
  4528 
       
  4529 
       
  4530   /* documentation is in ftmodapi.h */
       
  4531 
       
  4532   FT_EXPORT_DEF( void )
       
  4533   FT_Set_Debug_Hook( FT_Library         library,
       
  4534                      FT_UInt            hook_index,
       
  4535                      FT_DebugHook_Func  debug_hook )
       
  4536   {
       
  4537     if ( library && debug_hook &&
       
  4538          hook_index <
       
  4539            ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
       
  4540       library->debug_hooks[hook_index] = debug_hook;
       
  4541   }
       
  4542 
       
  4543 
       
  4544   /* documentation is in ftmodapi.h */
       
  4545 
       
  4546   FT_EXPORT_DEF( FT_TrueTypeEngineType )
       
  4547   FT_Get_TrueType_Engine_Type( FT_Library  library )
       
  4548   {
       
  4549     FT_TrueTypeEngineType  result = FT_TRUETYPE_ENGINE_TYPE_NONE;
       
  4550 
       
  4551 
       
  4552     if ( library )
       
  4553     {
       
  4554       FT_Module  module = FT_Get_Module( library, "truetype" );
       
  4555 
       
  4556 
       
  4557       if ( module )
       
  4558       {
       
  4559         FT_Service_TrueTypeEngine  service;
       
  4560 
       
  4561 
       
  4562         service = (FT_Service_TrueTypeEngine)
       
  4563                     ft_module_get_service( module,
       
  4564                                            FT_SERVICE_ID_TRUETYPE_ENGINE );
       
  4565         if ( service )
       
  4566           result = service->engine_type;
       
  4567       }
       
  4568     }
       
  4569 
       
  4570     return result;
       
  4571   }
       
  4572 
       
  4573 
       
  4574 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
       
  4575 
       
  4576   FT_BASE_DEF( FT_Error )
       
  4577   ft_stub_set_char_sizes( FT_Size     size,
       
  4578                           FT_F26Dot6  width,
       
  4579                           FT_F26Dot6  height,
       
  4580                           FT_UInt     horz_res,
       
  4581                           FT_UInt     vert_res )
       
  4582   {
       
  4583     FT_Size_RequestRec  req;
       
  4584     FT_Driver           driver = size->face->driver;
       
  4585 
       
  4586 
       
  4587     if ( driver->clazz->request_size )
       
  4588     {
       
  4589       req.type   = FT_SIZE_REQUEST_TYPE_NOMINAL;
       
  4590       req.width  = width;
       
  4591       req.height = height;
       
  4592 
       
  4593       if ( horz_res == 0 )
       
  4594         horz_res = vert_res;
       
  4595 
       
  4596       if ( vert_res == 0 )
       
  4597         vert_res = horz_res;
       
  4598 
       
  4599       if ( horz_res == 0 )
       
  4600         horz_res = vert_res = 72;
       
  4601 
       
  4602       req.horiResolution = horz_res;
       
  4603       req.vertResolution = vert_res;
       
  4604 
       
  4605       return driver->clazz->request_size( size, &req );
       
  4606     }
       
  4607 
       
  4608     return 0;
       
  4609   }
       
  4610 
       
  4611 
       
  4612   FT_BASE_DEF( FT_Error )
       
  4613   ft_stub_set_pixel_sizes( FT_Size  size,
       
  4614                            FT_UInt  width,
       
  4615                            FT_UInt  height )
       
  4616   {
       
  4617     FT_Size_RequestRec  req;
       
  4618     FT_Driver           driver = size->face->driver;
       
  4619 
       
  4620 
       
  4621     if ( driver->clazz->request_size )
       
  4622     {
       
  4623       req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
       
  4624       req.width          = width  << 6;
       
  4625       req.height         = height << 6;
       
  4626       req.horiResolution = 0;
       
  4627       req.vertResolution = 0;
       
  4628 
       
  4629       return driver->clazz->request_size( size, &req );
       
  4630     }
       
  4631 
       
  4632     return 0;
       
  4633   }
       
  4634 
       
  4635 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
       
  4636 
       
  4637 
       
  4638   /* documentation is in freetype.h */
       
  4639 
       
  4640   FT_EXPORT_DEF( FT_Error )
       
  4641   FT_Get_SubGlyph_Info( FT_GlyphSlot  glyph,
       
  4642                         FT_UInt       sub_index,
       
  4643                         FT_Int       *p_index,
       
  4644                         FT_UInt      *p_flags,
       
  4645                         FT_Int       *p_arg1,
       
  4646                         FT_Int       *p_arg2,
       
  4647                         FT_Matrix    *p_transform )
       
  4648   {
       
  4649     FT_Error  error = FT_Err_Invalid_Argument;
       
  4650 
       
  4651 
       
  4652     if ( glyph                                      &&
       
  4653          glyph->subglyphs                           &&
       
  4654          glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
       
  4655          sub_index < glyph->num_subglyphs           )
       
  4656     {
       
  4657       FT_SubGlyph  subg = glyph->subglyphs + sub_index;
       
  4658 
       
  4659 
       
  4660       *p_index     = subg->index;
       
  4661       *p_flags     = subg->flags;
       
  4662       *p_arg1      = subg->arg1;
       
  4663       *p_arg2      = subg->arg2;
       
  4664       *p_transform = subg->transform;
       
  4665     }
       
  4666 
       
  4667     return error;
       
  4668   }
       
  4669 
       
  4670 
       
  4671 /* END */