ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftobjs.c                                                               */
00004 /*                                                                         */
00005 /*    The FreeType private base classes (body).                            */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
00008 /*            2010 by                                                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020 #include <ft2build.h>
00021 #include FT_LIST_H
00022 #include FT_OUTLINE_H
00023 #include FT_INTERNAL_VALIDATE_H
00024 #include FT_INTERNAL_OBJECTS_H
00025 #include FT_INTERNAL_DEBUG_H
00026 #include FT_INTERNAL_RFORK_H
00027 #include FT_INTERNAL_STREAM_H
00028 #include FT_INTERNAL_SFNT_H    /* for SFNT_Load_Table_Func */
00029 #include FT_TRUETYPE_TABLES_H
00030 #include FT_TRUETYPE_TAGS_H
00031 #include FT_TRUETYPE_IDS_H
00032 
00033 #include FT_SERVICE_SFNT_H
00034 #include FT_SERVICE_POSTSCRIPT_NAME_H
00035 #include FT_SERVICE_GLYPH_DICT_H
00036 #include FT_SERVICE_TT_CMAP_H
00037 #include FT_SERVICE_KERNING_H
00038 #include FT_SERVICE_TRUETYPE_ENGINE_H
00039 
00040 #ifdef FT_CONFIG_OPTION_MAC_FONTS
00041 #include "ftbase.h"
00042 #endif
00043 
00044 #define GRID_FIT_METRICS
00045 
00046 
00047   FT_BASE_DEF( FT_Pointer )
00048   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
00049                           const char*     service_id )
00050   {
00051     FT_Pointer      result = NULL;
00052     FT_ServiceDesc  desc   = service_descriptors;
00053 
00054 
00055     if ( desc && service_id )
00056     {
00057       for ( ; desc->serv_id != NULL; desc++ )
00058       {
00059         if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
00060         {
00061           result = (FT_Pointer)desc->serv_data;
00062           break;
00063         }
00064       }
00065     }
00066 
00067     return result;
00068   }
00069 
00070 
00071   FT_BASE_DEF( void )
00072   ft_validator_init( FT_Validator        valid,
00073                      const FT_Byte*      base,
00074                      const FT_Byte*      limit,
00075                      FT_ValidationLevel  level )
00076   {
00077     valid->base  = base;
00078     valid->limit = limit;
00079     valid->level = level;
00080     valid->error = FT_Err_Ok;
00081   }
00082 
00083 
00084   FT_BASE_DEF( FT_Int )
00085   ft_validator_run( FT_Validator  valid )
00086   {
00087     /* This function doesn't work!  None should call it. */
00088     FT_UNUSED( valid );
00089 
00090     return -1;
00091   }
00092 
00093 
00094   FT_BASE_DEF( void )
00095   ft_validator_error( FT_Validator  valid,
00096                       FT_Error      error )
00097   {
00098     /* since the cast below also disables the compiler's */
00099     /* type check, we introduce a dummy variable, which  */
00100     /* will be optimized away                            */
00101     volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
00102 
00103 
00104     valid->error = error;
00105 
00106     /* throw away volatileness; use `jump_buffer' or the  */
00107     /* compiler may warn about an unused local variable   */
00108     ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
00109   }
00110 
00111 
00112   /*************************************************************************/
00113   /*************************************************************************/
00114   /*************************************************************************/
00115   /****                                                                 ****/
00116   /****                                                                 ****/
00117   /****                           S T R E A M                           ****/
00118   /****                                                                 ****/
00119   /****                                                                 ****/
00120   /*************************************************************************/
00121   /*************************************************************************/
00122   /*************************************************************************/
00123 
00124 
00125   /* create a new input stream from an FT_Open_Args structure */
00126   /*                                                          */
00127   FT_BASE_DEF( FT_Error )
00128   FT_Stream_New( FT_Library           library,
00129                  const FT_Open_Args*  args,
00130                  FT_Stream           *astream )
00131   {
00132     FT_Error   error;
00133     FT_Memory  memory;
00134     FT_Stream  stream;
00135 
00136 
00137     *astream = 0;
00138 
00139     if ( !library )
00140       return FT_Err_Invalid_Library_Handle;
00141 
00142     if ( !args )
00143       return FT_Err_Invalid_Argument;
00144 
00145     memory = library->memory;
00146 
00147     if ( FT_NEW( stream ) )
00148       goto Exit;
00149 
00150     stream->memory = memory;
00151 
00152     if ( args->flags & FT_OPEN_MEMORY )
00153     {
00154       /* create a memory-based stream */
00155       FT_Stream_OpenMemory( stream,
00156                             (const FT_Byte*)args->memory_base,
00157                             args->memory_size );
00158     }
00159     else if ( args->flags & FT_OPEN_PATHNAME )
00160     {
00161       /* create a normal system stream */
00162       error = FT_Stream_Open( stream, args->pathname );
00163       stream->pathname.pointer = args->pathname;
00164     }
00165     else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
00166     {
00167       /* use an existing, user-provided stream */
00168 
00169       /* in this case, we do not need to allocate a new stream object */
00170       /* since the caller is responsible for closing it himself       */
00171       FT_FREE( stream );
00172       stream = args->stream;
00173     }
00174     else
00175       error = FT_Err_Invalid_Argument;
00176 
00177     if ( error )
00178       FT_FREE( stream );
00179     else
00180       stream->memory = memory;  /* just to be certain */
00181 
00182     *astream = stream;
00183 
00184   Exit:
00185     return error;
00186   }
00187 
00188 
00189   FT_BASE_DEF( void )
00190   FT_Stream_Free( FT_Stream  stream,
00191                   FT_Int     external )
00192   {
00193     if ( stream )
00194     {
00195       FT_Memory  memory = stream->memory;
00196 
00197 
00198       FT_Stream_Close( stream );
00199 
00200       if ( !external )
00201         FT_FREE( stream );
00202     }
00203   }
00204 
00205 
00206   /*************************************************************************/
00207   /*                                                                       */
00208   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00209   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00210   /* messages during execution.                                            */
00211   /*                                                                       */
00212 #undef  FT_COMPONENT
00213 #define FT_COMPONENT  trace_objs
00214 
00215 
00216   /*************************************************************************/
00217   /*************************************************************************/
00218   /*************************************************************************/
00219   /****                                                                 ****/
00220   /****                                                                 ****/
00221   /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
00222   /****                                                                 ****/
00223   /****                                                                 ****/
00224   /*************************************************************************/
00225   /*************************************************************************/
00226   /*************************************************************************/
00227 
00228 
00229   static FT_Error
00230   ft_glyphslot_init( FT_GlyphSlot  slot )
00231   {
00232     FT_Driver         driver   = slot->face->driver;
00233     FT_Driver_Class   clazz    = driver->clazz;
00234     FT_Memory         memory   = driver->root.memory;
00235     FT_Error          error    = FT_Err_Ok;
00236     FT_Slot_Internal  internal = NULL;
00237 
00238 
00239     slot->library = driver->root.library;
00240 
00241     if ( FT_NEW( internal ) )
00242       goto Exit;
00243 
00244     slot->internal = internal;
00245 
00246     if ( FT_DRIVER_USES_OUTLINES( driver ) )
00247       error = FT_GlyphLoader_New( memory, &internal->loader );
00248 
00249     if ( !error && clazz->init_slot )
00250       error = clazz->init_slot( slot );
00251 
00252   Exit:
00253     return error;
00254   }
00255 
00256 
00257   FT_BASE_DEF( void )
00258   ft_glyphslot_free_bitmap( FT_GlyphSlot  slot )
00259   {
00260     if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
00261     {
00262       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
00263 
00264 
00265       FT_FREE( slot->bitmap.buffer );
00266       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
00267     }
00268     else
00269     {
00270       /* assume that the bitmap buffer was stolen or not */
00271       /* allocated from the heap                         */
00272       slot->bitmap.buffer = NULL;
00273     }
00274   }
00275 
00276 
00277   FT_BASE_DEF( void )
00278   ft_glyphslot_set_bitmap( FT_GlyphSlot  slot,
00279                            FT_Byte*      buffer )
00280   {
00281     ft_glyphslot_free_bitmap( slot );
00282 
00283     slot->bitmap.buffer = buffer;
00284 
00285     FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
00286   }
00287 
00288 
00289   FT_BASE_DEF( FT_Error )
00290   ft_glyphslot_alloc_bitmap( FT_GlyphSlot  slot,
00291                              FT_ULong      size )
00292   {
00293     FT_Memory  memory = FT_FACE_MEMORY( slot->face );
00294     FT_Error   error;
00295 
00296 
00297     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
00298       FT_FREE( slot->bitmap.buffer );
00299     else
00300       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00301 
00302     (void)FT_ALLOC( slot->bitmap.buffer, size );
00303     return error;
00304   }
00305 
00306 
00307   static void
00308   ft_glyphslot_clear( FT_GlyphSlot  slot )
00309   {
00310     /* free bitmap if needed */
00311     ft_glyphslot_free_bitmap( slot );
00312 
00313     /* clear all public fields in the glyph slot */
00314     FT_ZERO( &slot->metrics );
00315     FT_ZERO( &slot->outline );
00316 
00317     slot->bitmap.width      = 0;
00318     slot->bitmap.rows       = 0;
00319     slot->bitmap.pitch      = 0;
00320     slot->bitmap.pixel_mode = 0;
00321     /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
00322 
00323     slot->bitmap_left   = 0;
00324     slot->bitmap_top    = 0;
00325     slot->num_subglyphs = 0;
00326     slot->subglyphs     = 0;
00327     slot->control_data  = 0;
00328     slot->control_len   = 0;
00329     slot->other         = 0;
00330     slot->format        = FT_GLYPH_FORMAT_NONE;
00331 
00332     slot->linearHoriAdvance = 0;
00333     slot->linearVertAdvance = 0;
00334     slot->lsb_delta         = 0;
00335     slot->rsb_delta         = 0;
00336   }
00337 
00338 
00339   static void
00340   ft_glyphslot_done( FT_GlyphSlot  slot )
00341   {
00342     FT_Driver        driver = slot->face->driver;
00343     FT_Driver_Class  clazz  = driver->clazz;
00344     FT_Memory        memory = driver->root.memory;
00345 
00346 
00347     if ( clazz->done_slot )
00348       clazz->done_slot( slot );
00349 
00350     /* free bitmap buffer if needed */
00351     ft_glyphslot_free_bitmap( slot );
00352 
00353     /* slot->internal might be NULL in out-of-memory situations */
00354     if ( slot->internal )
00355     {
00356       /* free glyph loader */
00357       if ( FT_DRIVER_USES_OUTLINES( driver ) )
00358       {
00359         FT_GlyphLoader_Done( slot->internal->loader );
00360         slot->internal->loader = 0;
00361       }
00362 
00363       FT_FREE( slot->internal );
00364     }
00365   }
00366 
00367 
00368   /* documentation is in ftobjs.h */
00369 
00370   FT_BASE_DEF( FT_Error )
00371   FT_New_GlyphSlot( FT_Face        face,
00372                     FT_GlyphSlot  *aslot )
00373   {
00374     FT_Error         error;
00375     FT_Driver        driver;
00376     FT_Driver_Class  clazz;
00377     FT_Memory        memory;
00378     FT_GlyphSlot     slot;
00379 
00380 
00381     if ( !face || !face->driver )
00382       return FT_Err_Invalid_Argument;
00383 
00384     driver = face->driver;
00385     clazz  = driver->clazz;
00386     memory = driver->root.memory;
00387 
00388     FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
00389     if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
00390     {
00391       slot->face = face;
00392 
00393       error = ft_glyphslot_init( slot );
00394       if ( error )
00395       {
00396         ft_glyphslot_done( slot );
00397         FT_FREE( slot );
00398         goto Exit;
00399       }
00400 
00401       slot->next  = face->glyph;
00402       face->glyph = slot;
00403 
00404       if ( aslot )
00405         *aslot = slot;
00406     }
00407     else if ( aslot )
00408       *aslot = 0;
00409 
00410 
00411   Exit:
00412     FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
00413     return error;
00414   }
00415 
00416 
00417   /* documentation is in ftobjs.h */
00418 
00419   FT_BASE_DEF( void )
00420   FT_Done_GlyphSlot( FT_GlyphSlot  slot )
00421   {
00422     if ( slot )
00423     {
00424       FT_Driver     driver = slot->face->driver;
00425       FT_Memory     memory = driver->root.memory;
00426       FT_GlyphSlot  prev;
00427       FT_GlyphSlot  cur;
00428 
00429 
00430       /* Remove slot from its parent face's list */
00431       prev = NULL;
00432       cur  = slot->face->glyph;
00433 
00434       while ( cur )
00435       {
00436         if ( cur == slot )
00437         {
00438           if ( !prev )
00439             slot->face->glyph = cur->next;
00440           else
00441             prev->next = cur->next;
00442 
00443           ft_glyphslot_done( slot );
00444           FT_FREE( slot );
00445           break;
00446         }
00447         prev = cur;
00448         cur  = cur->next;
00449       }
00450     }
00451   }
00452 
00453 
00454   /* documentation is in freetype.h */
00455 
00456   FT_EXPORT_DEF( void )
00457   FT_Set_Transform( FT_Face     face,
00458                     FT_Matrix*  matrix,
00459                     FT_Vector*  delta )
00460   {
00461     FT_Face_Internal  internal;
00462 
00463 
00464     if ( !face )
00465       return;
00466 
00467     internal = face->internal;
00468 
00469     internal->transform_flags = 0;
00470 
00471     if ( !matrix )
00472     {
00473       internal->transform_matrix.xx = 0x10000L;
00474       internal->transform_matrix.xy = 0;
00475       internal->transform_matrix.yx = 0;
00476       internal->transform_matrix.yy = 0x10000L;
00477       matrix = &internal->transform_matrix;
00478     }
00479     else
00480       internal->transform_matrix = *matrix;
00481 
00482     /* set transform_flags bit flag 0 if `matrix' isn't the identity */
00483     if ( ( matrix->xy | matrix->yx ) ||
00484          matrix->xx != 0x10000L      ||
00485          matrix->yy != 0x10000L      )
00486       internal->transform_flags |= 1;
00487 
00488     if ( !delta )
00489     {
00490       internal->transform_delta.x = 0;
00491       internal->transform_delta.y = 0;
00492       delta = &internal->transform_delta;
00493     }
00494     else
00495       internal->transform_delta = *delta;
00496 
00497     /* set transform_flags bit flag 1 if `delta' isn't the null vector */
00498     if ( delta->x | delta->y )
00499       internal->transform_flags |= 2;
00500   }
00501 
00502 
00503   static FT_Renderer
00504   ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
00505 
00506 
00507 #ifdef GRID_FIT_METRICS
00508   static void
00509   ft_glyphslot_grid_fit_metrics( FT_GlyphSlot  slot,
00510                                  FT_Bool       vertical )
00511   {
00512     FT_Glyph_Metrics*  metrics = &slot->metrics;
00513     FT_Pos             right, bottom;
00514 
00515 
00516     if ( vertical )
00517     {
00518       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
00519       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
00520 
00521       right  = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
00522       bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
00523 
00524       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
00525       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
00526 
00527       metrics->width  = right - metrics->vertBearingX;
00528       metrics->height = bottom - metrics->vertBearingY;
00529     }
00530     else
00531     {
00532       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
00533       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
00534 
00535       right  = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
00536       bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
00537 
00538       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
00539       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
00540 
00541       metrics->width  = right - metrics->horiBearingX;
00542       metrics->height = metrics->horiBearingY - bottom;
00543     }
00544 
00545     metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
00546     metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
00547   }
00548 #endif /* GRID_FIT_METRICS */
00549 
00550 
00551   /* documentation is in freetype.h */
00552 
00553   FT_EXPORT_DEF( FT_Error )
00554   FT_Load_Glyph( FT_Face   face,
00555                  FT_UInt   glyph_index,
00556                  FT_Int32  load_flags )
00557   {
00558     FT_Error      error;
00559     FT_Driver     driver;
00560     FT_GlyphSlot  slot;
00561     FT_Library    library;
00562     FT_Bool       autohint = FALSE;
00563     FT_Module     hinter;
00564 
00565 
00566     if ( !face || !face->size || !face->glyph )
00567       return FT_Err_Invalid_Face_Handle;
00568 
00569     /* The validity test for `glyph_index' is performed by the */
00570     /* font drivers.                                           */
00571 
00572     slot = face->glyph;
00573     ft_glyphslot_clear( slot );
00574 
00575     driver  = face->driver;
00576     library = driver->root.library;
00577     hinter  = library->auto_hinter;
00578 
00579     /* resolve load flags dependencies */
00580 
00581     if ( load_flags & FT_LOAD_NO_RECURSE )
00582       load_flags |= FT_LOAD_NO_SCALE         |
00583                     FT_LOAD_IGNORE_TRANSFORM;
00584 
00585     if ( load_flags & FT_LOAD_NO_SCALE )
00586     {
00587       load_flags |= FT_LOAD_NO_HINTING |
00588                     FT_LOAD_NO_BITMAP;
00589 
00590       load_flags &= ~FT_LOAD_RENDER;
00591     }
00592 
00593     /*
00594      * Determine whether we need to auto-hint or not.
00595      * The general rules are:
00596      *
00597      * - Do only auto-hinting if we have a hinter module, a scalable font
00598      *   format dealing with outlines, and no transforms except simple
00599      *   slants and/or rotations by integer multiples of 90 degrees.
00600      *
00601      * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
00602      *   have a native font hinter.
00603      *
00604      * - Otherwise, auto-hint for LIGHT hinting mode.
00605      *
00606      * - Exception: The font is `tricky' and requires the native hinter to
00607      *   load properly.
00608      */
00609 
00610     if ( hinter                                           &&
00611          !( load_flags & FT_LOAD_NO_HINTING )             &&
00612          !( load_flags & FT_LOAD_NO_AUTOHINT )            &&
00613          FT_DRIVER_IS_SCALABLE( driver )                  &&
00614          FT_DRIVER_USES_OUTLINES( driver )                &&
00615          !FT_IS_TRICKY( face )                            &&
00616          ( ( face->internal->transform_matrix.yx == 0 &&
00617              face->internal->transform_matrix.xx != 0 ) ||
00618            ( face->internal->transform_matrix.xx == 0 &&
00619              face->internal->transform_matrix.yx != 0 ) ) )
00620     {
00621       if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
00622            !FT_DRIVER_HAS_HINTER( driver )         )
00623         autohint = TRUE;
00624       else
00625       {
00626         FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
00627 
00628 
00629         if ( mode == FT_RENDER_MODE_LIGHT             ||
00630              face->internal->ignore_unpatented_hinter )
00631           autohint = TRUE;
00632       }
00633     }
00634 
00635     if ( autohint )
00636     {
00637       FT_AutoHinter_Service  hinting;
00638 
00639 
00640       /* try to load embedded bitmaps first if available            */
00641       /*                                                            */
00642       /* XXX: This is really a temporary hack that should disappear */
00643       /*      promptly with FreeType 2.1!                           */
00644       /*                                                            */
00645       if ( FT_HAS_FIXED_SIZES( face )             &&
00646           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
00647       {
00648         error = driver->clazz->load_glyph( slot, face->size,
00649                                            glyph_index,
00650                                            load_flags | FT_LOAD_SBITS_ONLY );
00651 
00652         if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
00653           goto Load_Ok;
00654       }
00655 
00656       {
00657         FT_Face_Internal  internal        = face->internal;
00658         FT_Int            transform_flags = internal->transform_flags;
00659 
00660 
00661         /* since the auto-hinter calls FT_Load_Glyph by itself, */
00662         /* make sure that glyphs aren't transformed             */
00663         internal->transform_flags = 0;
00664 
00665         /* load auto-hinted outline */
00666         hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
00667 
00668         error   = hinting->load_glyph( (FT_AutoHinter)hinter,
00669                                        slot, face->size,
00670                                        glyph_index, load_flags );
00671 
00672         internal->transform_flags = transform_flags;
00673       }
00674     }
00675     else
00676     {
00677       error = driver->clazz->load_glyph( slot,
00678                                          face->size,
00679                                          glyph_index,
00680                                          load_flags );
00681       if ( error )
00682         goto Exit;
00683 
00684       if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
00685       {
00686         /* check that the loaded outline is correct */
00687         error = FT_Outline_Check( &slot->outline );
00688         if ( error )
00689           goto Exit;
00690 
00691 #ifdef GRID_FIT_METRICS
00692         if ( !( load_flags & FT_LOAD_NO_HINTING ) )
00693           ft_glyphslot_grid_fit_metrics( slot,
00694               FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
00695 #endif
00696       }
00697     }
00698 
00699   Load_Ok:
00700     /* compute the advance */
00701     if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
00702     {
00703       slot->advance.x = 0;
00704       slot->advance.y = slot->metrics.vertAdvance;
00705     }
00706     else
00707     {
00708       slot->advance.x = slot->metrics.horiAdvance;
00709       slot->advance.y = 0;
00710     }
00711 
00712     /* compute the linear advance in 16.16 pixels */
00713     if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
00714          ( FT_IS_SCALABLE( face ) )                  )
00715     {
00716       FT_Size_Metrics*  metrics = &face->size->metrics;
00717 
00718 
00719       /* it's tricky! */
00720       slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
00721                                            metrics->x_scale, 64 );
00722 
00723       slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
00724                                            metrics->y_scale, 64 );
00725     }
00726 
00727     if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
00728     {
00729       FT_Face_Internal  internal = face->internal;
00730 
00731 
00732       /* now, transform the glyph image if needed */
00733       if ( internal->transform_flags )
00734       {
00735         /* get renderer */
00736         FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
00737 
00738 
00739         if ( renderer )
00740           error = renderer->clazz->transform_glyph(
00741                                      renderer, slot,
00742                                      &internal->transform_matrix,
00743                                      &internal->transform_delta );
00744         else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
00745         {
00746           /* apply `standard' transformation if no renderer is available */
00747           if ( &internal->transform_matrix )
00748             FT_Outline_Transform( &slot->outline,
00749                                   &internal->transform_matrix );
00750 
00751           if ( &internal->transform_delta )
00752             FT_Outline_Translate( &slot->outline,
00753                                   internal->transform_delta.x,
00754                                   internal->transform_delta.y );
00755         }
00756 
00757         /* transform advance */
00758         FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
00759       }
00760     }
00761 
00762     FT_TRACE5(( "  x advance: %d\n" , slot->advance.x ));
00763     FT_TRACE5(( "  y advance: %d\n" , slot->advance.y ));
00764 
00765     FT_TRACE5(( "  linear x advance: %d\n" , slot->linearHoriAdvance ));
00766     FT_TRACE5(( "  linear y advance: %d\n" , slot->linearVertAdvance ));
00767 
00768     /* do we need to render the image now? */
00769     if ( !error                                    &&
00770          slot->format != FT_GLYPH_FORMAT_BITMAP    &&
00771          slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
00772          load_flags & FT_LOAD_RENDER )
00773     {
00774       FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
00775 
00776 
00777       if ( mode == FT_RENDER_MODE_NORMAL      &&
00778            (load_flags & FT_LOAD_MONOCHROME ) )
00779         mode = FT_RENDER_MODE_MONO;
00780 
00781       error = FT_Render_Glyph( slot, mode );
00782     }
00783 
00784   Exit:
00785     return error;
00786   }
00787 
00788 
00789   /* documentation is in freetype.h */
00790 
00791   FT_EXPORT_DEF( FT_Error )
00792   FT_Load_Char( FT_Face   face,
00793                 FT_ULong  char_code,
00794                 FT_Int32  load_flags )
00795   {
00796     FT_UInt  glyph_index;
00797 
00798 
00799     if ( !face )
00800       return FT_Err_Invalid_Face_Handle;
00801 
00802     glyph_index = (FT_UInt)char_code;
00803     if ( face->charmap )
00804       glyph_index = FT_Get_Char_Index( face, char_code );
00805 
00806     return FT_Load_Glyph( face, glyph_index, load_flags );
00807   }
00808 
00809 
00810   /* destructor for sizes list */
00811   static void
00812   destroy_size( FT_Memory  memory,
00813                 FT_Size    size,
00814                 FT_Driver  driver )
00815   {
00816     /* finalize client-specific data */
00817     if ( size->generic.finalizer )
00818       size->generic.finalizer( size );
00819 
00820     /* finalize format-specific stuff */
00821     if ( driver->clazz->done_size )
00822       driver->clazz->done_size( size );
00823 
00824     FT_FREE( size->internal );
00825     FT_FREE( size );
00826   }
00827 
00828 
00829   static void
00830   ft_cmap_done_internal( FT_CMap  cmap );
00831 
00832 
00833   static void
00834   destroy_charmaps( FT_Face    face,
00835                     FT_Memory  memory )
00836   {
00837     FT_Int  n;
00838 
00839 
00840     if ( !face )
00841       return;
00842 
00843     for ( n = 0; n < face->num_charmaps; n++ )
00844     {
00845       FT_CMap  cmap = FT_CMAP( face->charmaps[n] );
00846 
00847 
00848       ft_cmap_done_internal( cmap );
00849 
00850       face->charmaps[n] = NULL;
00851     }
00852 
00853     FT_FREE( face->charmaps );
00854     face->num_charmaps = 0;
00855   }
00856 
00857 
00858   /* destructor for faces list */
00859   static void
00860   destroy_face( FT_Memory  memory,
00861                 FT_Face    face,
00862                 FT_Driver  driver )
00863   {
00864     FT_Driver_Class  clazz = driver->clazz;
00865 
00866 
00867     /* discard auto-hinting data */
00868     if ( face->autohint.finalizer )
00869       face->autohint.finalizer( face->autohint.data );
00870 
00871     /* Discard glyph slots for this face.                           */
00872     /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
00873     while ( face->glyph )
00874       FT_Done_GlyphSlot( face->glyph );
00875 
00876     /* discard all sizes for this face */
00877     FT_List_Finalize( &face->sizes_list,
00878                       (FT_List_Destructor)destroy_size,
00879                       memory,
00880                       driver );
00881     face->size = 0;
00882 
00883     /* now discard client data */
00884     if ( face->generic.finalizer )
00885       face->generic.finalizer( face );
00886 
00887     /* discard charmaps */
00888     destroy_charmaps( face, memory );
00889 
00890     /* finalize format-specific stuff */
00891     if ( clazz->done_face )
00892       clazz->done_face( face );
00893 
00894     /* close the stream for this face if needed */
00895     FT_Stream_Free(
00896       face->stream,
00897       ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
00898 
00899     face->stream = 0;
00900 
00901     /* get rid of it */
00902     if ( face->internal )
00903     {
00904       FT_FREE( face->internal );
00905     }
00906     FT_FREE( face );
00907   }
00908 
00909 
00910   static void
00911   Destroy_Driver( FT_Driver  driver )
00912   {
00913     FT_List_Finalize( &driver->faces_list,
00914                       (FT_List_Destructor)destroy_face,
00915                       driver->root.memory,
00916                       driver );
00917 
00918     /* check whether we need to drop the driver's glyph loader */
00919     if ( FT_DRIVER_USES_OUTLINES( driver ) )
00920       FT_GlyphLoader_Done( driver->glyph_loader );
00921   }
00922 
00923 
00924   /*************************************************************************/
00925   /*                                                                       */
00926   /* <Function>                                                            */
00927   /*    find_unicode_charmap                                               */
00928   /*                                                                       */
00929   /* <Description>                                                         */
00930   /*    This function finds a Unicode charmap, if there is one.            */
00931   /*    And if there is more than one, it tries to favour the more         */
00932   /*    extensive one, i.e., one that supports UCS-4 against those which   */
00933   /*    are limited to the BMP (said UCS-2 encoding.)                      */
00934   /*                                                                       */
00935   /*    This function is called from open_face() (just below), and also    */
00936   /*    from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ).                */
00937   /*                                                                       */
00938   static FT_Error
00939   find_unicode_charmap( FT_Face  face )
00940   {
00941     FT_CharMap*  first;
00942     FT_CharMap*  cur;
00943 
00944 
00945     /* caller should have already checked that `face' is valid */
00946     FT_ASSERT( face );
00947 
00948     first = face->charmaps;
00949 
00950     if ( !first )
00951       return FT_Err_Invalid_CharMap_Handle;
00952 
00953     /*
00954      *  The original TrueType specification(s) only specified charmap
00955      *  formats that are capable of mapping 8 or 16 bit character codes to
00956      *  glyph indices.
00957      *
00958      *  However, recent updates to the Apple and OpenType specifications
00959      *  introduced new formats that are capable of mapping 32-bit character
00960      *  codes as well.  And these are already used on some fonts, mainly to
00961      *  map non-BMP Asian ideographs as defined in Unicode.
00962      *
00963      *  For compatibility purposes, these fonts generally come with
00964      *  *several* Unicode charmaps:
00965      *
00966      *   - One of them in the "old" 16-bit format, that cannot access
00967      *     all glyphs in the font.
00968      *
00969      *   - Another one in the "new" 32-bit format, that can access all
00970      *     the glyphs.
00971      *
00972      *  This function has been written to always favor a 32-bit charmap
00973      *  when found.  Otherwise, a 16-bit one is returned when found.
00974      */
00975 
00976     /* Since the `interesting' table, with IDs (3,10), is normally the */
00977     /* last one, we loop backwards.  This loses with type1 fonts with  */
00978     /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP  */
00979     /* chars (.01% ?), and this is the same about 99.99% of the time!  */
00980 
00981     cur = first + face->num_charmaps;  /* points after the last one */
00982 
00983     for ( ; --cur >= first; )
00984     {
00985       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
00986       {
00987         /* XXX If some new encodings to represent UCS-4 are added, */
00988         /*     they should be added here.                          */
00989         if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
00990                cur[0]->encoding_id == TT_MS_ID_UCS_4        )     ||
00991              ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
00992                cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32    ) )
00993         {
00994 #ifdef FT_MAX_CHARMAP_CACHEABLE
00995           if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
00996           {
00997             FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
00998                        "at too late position (%d)\n", cur - first ));
00999             continue;
01000           }
01001 #endif
01002           face->charmap = cur[0];
01003           return FT_Err_Ok;
01004         }
01005       }
01006     }
01007 
01008     /* We do not have any UCS-4 charmap.                */
01009     /* Do the loop again and search for UCS-2 charmaps. */
01010     cur = first + face->num_charmaps;
01011 
01012     for ( ; --cur >= first; )
01013     {
01014       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
01015       {
01016 #ifdef FT_MAX_CHARMAP_CACHEABLE
01017         if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
01018         {
01019           FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
01020                      "at too late position (%d)\n", cur - first ));
01021           continue;
01022         }
01023 #endif
01024         face->charmap = cur[0];
01025         return FT_Err_Ok;
01026       }
01027     }
01028 
01029     return FT_Err_Invalid_CharMap_Handle;
01030   }
01031 
01032 
01033   /*************************************************************************/
01034   /*                                                                       */
01035   /* <Function>                                                            */
01036   /*    find_variant_selector_charmap                                      */
01037   /*                                                                       */
01038   /* <Description>                                                         */
01039   /*    This function finds the variant selector charmap, if there is one. */
01040   /*    There can only be one (platform=0, specific=5, format=14).         */
01041   /*                                                                       */
01042   static FT_CharMap
01043   find_variant_selector_charmap( FT_Face  face )
01044   {
01045     FT_CharMap*  first;
01046     FT_CharMap*  end;
01047     FT_CharMap*  cur;
01048 
01049 
01050     /* caller should have already checked that `face' is valid */
01051     FT_ASSERT( face );
01052 
01053     first = face->charmaps;
01054 
01055     if ( !first )
01056       return NULL;
01057 
01058     end = first + face->num_charmaps;  /* points after the last one */
01059 
01060     for ( cur = first; cur < end; ++cur )
01061     {
01062       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
01063            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
01064            FT_Get_CMap_Format( cur[0] ) == 14                  )
01065       {
01066 #ifdef FT_MAX_CHARMAP_CACHEABLE
01067         if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
01068         {
01069           FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
01070                      "at too late position (%d)\n", cur - first ));
01071           continue;
01072         }
01073 #endif
01074         return cur[0];
01075       }
01076     }
01077 
01078     return NULL;
01079   }
01080 
01081 
01082   /*************************************************************************/
01083   /*                                                                       */
01084   /* <Function>                                                            */
01085   /*    open_face                                                          */
01086   /*                                                                       */
01087   /* <Description>                                                         */
01088   /*    This function does some work for FT_Open_Face().                   */
01089   /*                                                                       */
01090   static FT_Error
01091   open_face( FT_Driver      driver,
01092              FT_Stream      stream,
01093              FT_Long        face_index,
01094              FT_Int         num_params,
01095              FT_Parameter*  params,
01096              FT_Face       *aface )
01097   {
01098     FT_Memory         memory;
01099     FT_Driver_Class   clazz;
01100     FT_Face           face = 0;
01101     FT_Error          error, error2;
01102     FT_Face_Internal  internal = NULL;
01103 
01104 
01105     clazz  = driver->clazz;
01106     memory = driver->root.memory;
01107 
01108     /* allocate the face object and perform basic initialization */
01109     if ( FT_ALLOC( face, clazz->face_object_size ) )
01110       goto Fail;
01111 
01112     if ( FT_NEW( internal ) )
01113       goto Fail;
01114 
01115     face->internal = internal;
01116 
01117     face->driver   = driver;
01118     face->memory   = memory;
01119     face->stream   = stream;
01120 
01121 #ifdef FT_CONFIG_OPTION_INCREMENTAL
01122     {
01123       int  i;
01124 
01125 
01126       face->internal->incremental_interface = 0;
01127       for ( i = 0; i < num_params && !face->internal->incremental_interface;
01128             i++ )
01129         if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
01130           face->internal->incremental_interface =
01131             (FT_Incremental_Interface)params[i].data;
01132     }
01133 #endif
01134 
01135     if ( clazz->init_face )
01136       error = clazz->init_face( stream,
01137                                 face,
01138                                 (FT_Int)face_index,
01139                                 num_params,
01140                                 params );
01141     if ( error )
01142       goto Fail;
01143 
01144     /* select Unicode charmap by default */
01145     error2 = find_unicode_charmap( face );
01146 
01147     /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
01148     /* is returned.                                                      */
01149 
01150     /* no error should happen, but we want to play safe */
01151     if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
01152     {
01153       error = error2;
01154       goto Fail;
01155     }
01156 
01157     *aface = face;
01158 
01159   Fail:
01160     if ( error )
01161     {
01162       destroy_charmaps( face, memory );
01163       if ( clazz->done_face )
01164         clazz->done_face( face );
01165       FT_FREE( internal );
01166       FT_FREE( face );
01167       *aface = 0;
01168     }
01169 
01170     return error;
01171   }
01172 
01173 
01174   /* there's a Mac-specific extended implementation of FT_New_Face() */
01175   /* in src/base/ftmac.c                                             */
01176 
01177 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
01178 
01179   /* documentation is in freetype.h */
01180 
01181   FT_EXPORT_DEF( FT_Error )
01182   FT_New_Face( FT_Library   library,
01183                const char*  pathname,
01184                FT_Long      face_index,
01185                FT_Face     *aface )
01186   {
01187     FT_Open_Args  args;
01188 
01189 
01190     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
01191     if ( !pathname )
01192       return FT_Err_Invalid_Argument;
01193 
01194     args.flags    = FT_OPEN_PATHNAME;
01195     args.pathname = (char*)pathname;
01196     args.stream   = NULL;
01197 
01198     return FT_Open_Face( library, &args, face_index, aface );
01199   }
01200 
01201 #endif  /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
01202 
01203 
01204   /* documentation is in freetype.h */
01205 
01206   FT_EXPORT_DEF( FT_Error )
01207   FT_New_Memory_Face( FT_Library      library,
01208                       const FT_Byte*  file_base,
01209                       FT_Long         file_size,
01210                       FT_Long         face_index,
01211                       FT_Face        *aface )
01212   {
01213     FT_Open_Args  args;
01214 
01215 
01216     /* test for valid `library' and `face' delayed to FT_Open_Face() */
01217     if ( !file_base )
01218       return FT_Err_Invalid_Argument;
01219 
01220     args.flags       = FT_OPEN_MEMORY;
01221     args.memory_base = file_base;
01222     args.memory_size = file_size;
01223     args.stream      = NULL;
01224 
01225     return FT_Open_Face( library, &args, face_index, aface );
01226   }
01227 
01228 
01229 #ifdef FT_CONFIG_OPTION_MAC_FONTS
01230 
01231   /* The behavior here is very similar to that in base/ftmac.c, but it     */
01232   /* is designed to work on non-mac systems, so no mac specific calls.     */
01233   /*                                                                       */
01234   /* We look at the file and determine if it is a mac dfont file or a mac  */
01235   /* resource file, or a macbinary file containing a mac resource file.    */
01236   /*                                                                       */
01237   /* Unlike ftmac I'm not going to look at a `FOND'.  I don't really see   */
01238   /* the point, especially since there may be multiple `FOND' resources.   */
01239   /* Instead I'll just look for `sfnt' and `POST' resources, ordered as    */
01240   /* they occur in the file.                                               */
01241   /*                                                                       */
01242   /* Note that multiple `POST' resources do not mean multiple postscript   */
01243   /* fonts; they all get jammed together to make what is essentially a     */
01244   /* pfb file.                                                             */
01245   /*                                                                       */
01246   /* We aren't interested in `NFNT' or `FONT' bitmap resources.            */
01247   /*                                                                       */
01248   /* As soon as we get an `sfnt' load it into memory and pass it off to    */
01249   /* FT_Open_Face.                                                         */
01250   /*                                                                       */
01251   /* If we have a (set of) `POST' resources, massage them into a (memory)  */
01252   /* pfb file and pass that to FT_Open_Face.  (As with ftmac.c I'm not     */
01253   /* going to try to save the kerning info.  After all that lives in the   */
01254   /* `FOND' which isn't in the file containing the `POST' resources so     */
01255   /* we don't really have access to it.                                    */
01256 
01257 
01258   /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
01259   /* It frees the memory it uses.                                  */
01260   /* From ftmac.c.                                                 */
01261   static void
01262   memory_stream_close( FT_Stream  stream )
01263   {
01264     FT_Memory  memory = stream->memory;
01265 
01266 
01267     FT_FREE( stream->base );
01268 
01269     stream->size  = 0;
01270     stream->base  = 0;
01271     stream->close = 0;
01272   }
01273 
01274 
01275   /* Create a new memory stream from a buffer and a size. */
01276   /* From ftmac.c.                                        */
01277   static FT_Error
01278   new_memory_stream( FT_Library           library,
01279                      FT_Byte*             base,
01280                      FT_ULong             size,
01281                      FT_Stream_CloseFunc  close,
01282                      FT_Stream           *astream )
01283   {
01284     FT_Error   error;
01285     FT_Memory  memory;
01286     FT_Stream  stream;
01287 
01288 
01289     if ( !library )
01290       return FT_Err_Invalid_Library_Handle;
01291 
01292     if ( !base )
01293       return FT_Err_Invalid_Argument;
01294 
01295     *astream = 0;
01296     memory = library->memory;
01297     if ( FT_NEW( stream ) )
01298       goto Exit;
01299 
01300     FT_Stream_OpenMemory( stream, base, size );
01301 
01302     stream->close = close;
01303 
01304     *astream = stream;
01305 
01306   Exit:
01307     return error;
01308   }
01309 
01310 
01311   /* Create a new FT_Face given a buffer and a driver name. */
01312   /* from ftmac.c */
01313   FT_LOCAL_DEF( FT_Error )
01314   open_face_from_buffer( FT_Library   library,
01315                          FT_Byte*     base,
01316                          FT_ULong     size,
01317                          FT_Long      face_index,
01318                          const char*  driver_name,
01319                          FT_Face     *aface )
01320   {
01321     FT_Open_Args  args;
01322     FT_Error      error;
01323     FT_Stream     stream = NULL;
01324     FT_Memory     memory = library->memory;
01325 
01326 
01327     error = new_memory_stream( library,
01328                                base,
01329                                size,
01330                                memory_stream_close,
01331                                &stream );
01332     if ( error )
01333     {
01334       FT_FREE( base );
01335       return error;
01336     }
01337 
01338     args.flags = FT_OPEN_STREAM;
01339     args.stream = stream;
01340     if ( driver_name )
01341     {
01342       args.flags = args.flags | FT_OPEN_DRIVER;
01343       args.driver = FT_Get_Module( library, driver_name );
01344     }
01345 
01346 #ifdef FT_MACINTOSH
01347     /* At this point, face_index has served its purpose;      */
01348     /* whoever calls this function has already used it to     */
01349     /* locate the correct font data.  We should not propagate */
01350     /* this index to FT_Open_Face() (unless it is negative).  */
01351 
01352     if ( face_index > 0 )
01353       face_index = 0;
01354 #endif
01355 
01356     error = FT_Open_Face( library, &args, face_index, aface );
01357 
01358     if ( error == FT_Err_Ok )
01359       (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
01360     else
01361 #ifdef FT_MACINTOSH
01362       FT_Stream_Free( stream, 0 );
01363 #else
01364     {
01365       FT_Stream_Close( stream );
01366       FT_FREE( stream );
01367     }
01368 #endif
01369 
01370     return error;
01371   }
01372 
01373 
01374   /* Look up `TYP1' or `CID ' table from sfnt table directory.       */
01375   /* `offset' and `length' must exclude the binary header in tables. */
01376 
01377   /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
01378   /* format too.  Here, since we can't expect that the TrueType font */
01379   /* driver is loaded unconditially, we must parse the font by       */
01380   /* ourselves.  We are only interested in the name of the table and */
01381   /* the offset.                                                     */
01382 
01383   static FT_Error
01384   ft_lookup_PS_in_sfnt_stream( FT_Stream  stream,
01385                                FT_Long    face_index,
01386                                FT_ULong*  offset,
01387                                FT_ULong*  length,
01388                                FT_Bool*   is_sfnt_cid )
01389   {
01390     FT_Error   error;
01391     FT_UShort  numTables;
01392     FT_Long    pstable_index;
01393     FT_ULong   tag;
01394     int        i;
01395 
01396 
01397     *offset = 0;
01398     *length = 0;
01399     *is_sfnt_cid = FALSE;
01400 
01401     /* TODO: support for sfnt-wrapped PS/CID in TTC format */
01402 
01403     /* version check for 'typ1' (should be ignored?) */
01404     if ( FT_READ_ULONG( tag ) )
01405       return error;
01406     if ( tag != TTAG_typ1 )
01407       return FT_Err_Unknown_File_Format;
01408 
01409     if ( FT_READ_USHORT( numTables ) )
01410       return error;
01411     if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
01412       return error;
01413 
01414     pstable_index = -1;
01415     *is_sfnt_cid  = FALSE;
01416 
01417     for ( i = 0; i < numTables; i++ )
01418     {
01419       if ( FT_READ_ULONG( tag )     || FT_STREAM_SKIP( 4 )      ||
01420            FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
01421         return error;
01422 
01423       if ( tag == TTAG_CID )
01424       {
01425         pstable_index++;
01426         *offset += 22;
01427         *length -= 22;
01428         *is_sfnt_cid = TRUE;
01429         if ( face_index < 0 )
01430           return FT_Err_Ok;
01431       }
01432       else if ( tag == TTAG_TYP1 )
01433       {
01434         pstable_index++;
01435         *offset += 24;
01436         *length -= 24;
01437         *is_sfnt_cid = FALSE;
01438         if ( face_index < 0 )
01439           return FT_Err_Ok;
01440       }
01441       if ( face_index >= 0 && pstable_index == face_index )
01442         return FT_Err_Ok;
01443     }
01444     return FT_Err_Table_Missing;
01445   }
01446 
01447 
01448   FT_LOCAL_DEF( FT_Error )
01449   open_face_PS_from_sfnt_stream( FT_Library     library,
01450                                  FT_Stream      stream,
01451                                  FT_Long        face_index,
01452                                  FT_Int         num_params,
01453                                  FT_Parameter  *params,
01454                                  FT_Face       *aface )
01455   {
01456     FT_Error   error;
01457     FT_Memory  memory = library->memory;
01458     FT_ULong   offset, length;
01459     FT_Long    pos;
01460     FT_Bool    is_sfnt_cid;
01461     FT_Byte*   sfnt_ps;
01462 
01463     FT_UNUSED( num_params );
01464     FT_UNUSED( params );
01465 
01466 
01467     pos = FT_Stream_Pos( stream );
01468 
01469     error = ft_lookup_PS_in_sfnt_stream( stream,
01470                                          face_index,
01471                                          &offset,
01472                                          &length,
01473                                          &is_sfnt_cid );
01474     if ( error )
01475       goto Exit;
01476 
01477     if ( FT_Stream_Seek( stream, pos + offset ) )
01478       goto Exit;
01479 
01480     if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
01481       goto Exit;
01482 
01483     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
01484     if ( error )
01485       goto Exit;
01486 
01487     error = open_face_from_buffer( library,
01488                                    sfnt_ps,
01489                                    length,
01490                                    face_index < 0 ? face_index : 0,
01491                                    is_sfnt_cid ? "cid" : "type1",
01492                                    aface );
01493   Exit:
01494     {
01495       FT_Error  error1;
01496 
01497 
01498       if ( error == FT_Err_Unknown_File_Format )
01499       {
01500         error1 = FT_Stream_Seek( stream, pos );
01501         if ( error1 )
01502           return error1;
01503       }
01504 
01505       return error;
01506     }
01507   }
01508 
01509 
01510 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
01511 
01512   /* The resource header says we've got resource_cnt `POST' (type1) */
01513   /* resources in this file.  They all need to be coalesced into    */
01514   /* one lump which gets passed on to the type1 driver.             */
01515   /* Here can be only one PostScript font in a file so face_index   */
01516   /* must be 0 (or -1).                                             */
01517   /*                                                                */
01518   static FT_Error
01519   Mac_Read_POST_Resource( FT_Library  library,
01520                           FT_Stream   stream,
01521                           FT_Long    *offsets,
01522                           FT_Long     resource_cnt,
01523                           FT_Long     face_index,
01524                           FT_Face    *aface )
01525   {
01526     FT_Error   error  = FT_Err_Cannot_Open_Resource;
01527     FT_Memory  memory = library->memory;
01528     FT_Byte*   pfb_data;
01529     int        i, type, flags;
01530     FT_Long    len;
01531     FT_Long    pfb_len, pfb_pos, pfb_lenpos;
01532     FT_Long    rlen, temp;
01533 
01534 
01535     if ( face_index == -1 )
01536       face_index = 0;
01537     if ( face_index != 0 )
01538       return error;
01539 
01540     /* Find the length of all the POST resources, concatenated.  Assume */
01541     /* worst case (each resource in its own section).                   */
01542     pfb_len = 0;
01543     for ( i = 0; i < resource_cnt; ++i )
01544     {
01545       error = FT_Stream_Seek( stream, offsets[i] );
01546       if ( error )
01547         goto Exit;
01548       if ( FT_READ_LONG( temp ) )
01549         goto Exit;
01550       pfb_len += temp + 6;
01551     }
01552 
01553     if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
01554       goto Exit;
01555 
01556     pfb_data[0] = 0x80;
01557     pfb_data[1] = 1;            /* Ascii section */
01558     pfb_data[2] = 0;            /* 4-byte length, fill in later */
01559     pfb_data[3] = 0;
01560     pfb_data[4] = 0;
01561     pfb_data[5] = 0;
01562     pfb_pos     = 6;
01563     pfb_lenpos  = 2;
01564 
01565     len = 0;
01566     type = 1;
01567     for ( i = 0; i < resource_cnt; ++i )
01568     {
01569       error = FT_Stream_Seek( stream, offsets[i] );
01570       if ( error )
01571         goto Exit2;
01572       if ( FT_READ_LONG( rlen ) )
01573         goto Exit;
01574       if ( FT_READ_USHORT( flags ) )
01575         goto Exit;
01576       FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
01577                    i, offsets[i], rlen, flags ));
01578 
01579       /* postpone the check of rlen longer than buffer until FT_Stream_Read() */
01580       if ( ( flags >> 8 ) == 0 )        /* Comment, should not be loaded */
01581         continue;
01582 
01583       /* the flags are part of the resource, so rlen >= 2.  */
01584       /* but some fonts declare rlen = 0 for empty fragment */
01585       if ( rlen > 2 )
01586         rlen -= 2;
01587       else
01588         rlen = 0;
01589 
01590       if ( ( flags >> 8 ) == type )
01591         len += rlen;
01592       else
01593       {
01594         if ( pfb_lenpos + 3 > pfb_len + 2 )
01595           goto Exit2;
01596         pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
01597         pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
01598         pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
01599         pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
01600 
01601         if ( ( flags >> 8 ) == 5 )      /* End of font mark */
01602           break;
01603 
01604         if ( pfb_pos + 6 > pfb_len + 2 )
01605           goto Exit2;
01606         pfb_data[pfb_pos++] = 0x80;
01607 
01608         type = flags >> 8;
01609         len = rlen;
01610 
01611         pfb_data[pfb_pos++] = (FT_Byte)type;
01612         pfb_lenpos          = pfb_pos;
01613         pfb_data[pfb_pos++] = 0;        /* 4-byte length, fill in later */
01614         pfb_data[pfb_pos++] = 0;
01615         pfb_data[pfb_pos++] = 0;
01616         pfb_data[pfb_pos++] = 0;
01617       }
01618 
01619       error = FT_Err_Cannot_Open_Resource;
01620       if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
01621         goto Exit2;
01622 
01623       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
01624       if ( error )
01625         goto Exit2;
01626       pfb_pos += rlen;
01627     }
01628 
01629     if ( pfb_pos + 2 > pfb_len + 2 )
01630       goto Exit2;
01631     pfb_data[pfb_pos++] = 0x80;
01632     pfb_data[pfb_pos++] = 3;
01633 
01634     if ( pfb_lenpos + 3 > pfb_len + 2 )
01635       goto Exit2;
01636     pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
01637     pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
01638     pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
01639     pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
01640 
01641     return open_face_from_buffer( library,
01642                                   pfb_data,
01643                                   pfb_pos,
01644                                   face_index,
01645                                   "type1",
01646                                   aface );
01647 
01648   Exit2:
01649     FT_FREE( pfb_data );
01650 
01651   Exit:
01652     return error;
01653   }
01654 
01655 
01656   /* The resource header says we've got resource_cnt `sfnt'      */
01657   /* (TrueType/OpenType) resources in this file.  Look through   */
01658   /* them for the one indicated by face_index, load it into mem, */
01659   /* pass it on the the truetype driver and return it.           */
01660   /*                                                             */
01661   static FT_Error
01662   Mac_Read_sfnt_Resource( FT_Library  library,
01663                           FT_Stream   stream,
01664                           FT_Long    *offsets,
01665                           FT_Long     resource_cnt,
01666                           FT_Long     face_index,
01667                           FT_Face    *aface )
01668   {
01669     FT_Memory  memory = library->memory;
01670     FT_Byte*   sfnt_data;
01671     FT_Error   error;
01672     FT_Long    flag_offset;
01673     FT_Long    rlen;
01674     int        is_cff;
01675     FT_Long    face_index_in_resource = 0;
01676 
01677 
01678     if ( face_index == -1 )
01679       face_index = 0;
01680     if ( face_index >= resource_cnt )
01681       return FT_Err_Cannot_Open_Resource;
01682 
01683     flag_offset = offsets[face_index];
01684     error = FT_Stream_Seek( stream, flag_offset );
01685     if ( error )
01686       goto Exit;
01687 
01688     if ( FT_READ_LONG( rlen ) )
01689       goto Exit;
01690     if ( rlen == -1 )
01691       return FT_Err_Cannot_Open_Resource;
01692 
01693     error = open_face_PS_from_sfnt_stream( library,
01694                                            stream,
01695                                            face_index,
01696                                            0, NULL,
01697                                            aface );
01698     if ( !error )
01699       goto Exit;
01700 
01701     /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
01702     if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
01703       goto Exit;
01704 
01705     if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
01706       return error;
01707     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
01708     if ( error )
01709       goto Exit;
01710 
01711     is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
01712     error = open_face_from_buffer( library,
01713                                    sfnt_data,
01714                                    rlen,
01715                                    face_index_in_resource,
01716                                    is_cff ? "cff" : "truetype",
01717                                    aface );
01718 
01719   Exit:
01720     return error;
01721   }
01722 
01723 
01724   /* Check for a valid resource fork header, or a valid dfont    */
01725   /* header.  In a resource fork the first 16 bytes are repeated */
01726   /* at the location specified by bytes 4-7.  In a dfont bytes   */
01727   /* 4-7 point to 16 bytes of zeroes instead.                    */
01728   /*                                                             */
01729   static FT_Error
01730   IsMacResource( FT_Library  library,
01731                  FT_Stream   stream,
01732                  FT_Long     resource_offset,
01733                  FT_Long     face_index,
01734                  FT_Face    *aface )
01735   {
01736     FT_Memory  memory = library->memory;
01737     FT_Error   error;
01738     FT_Long    map_offset, rdara_pos;
01739     FT_Long    *data_offsets;
01740     FT_Long    count;
01741 
01742 
01743     error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
01744                                        &map_offset, &rdara_pos );
01745     if ( error )
01746       return error;
01747 
01748     error = FT_Raccess_Get_DataOffsets( library, stream,
01749                                         map_offset, rdara_pos,
01750                                         TTAG_POST,
01751                                         &data_offsets, &count );
01752     if ( !error )
01753     {
01754       error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
01755                                       face_index, aface );
01756       FT_FREE( data_offsets );
01757       /* POST exists in an LWFN providing a single face */
01758       if ( !error )
01759         (*aface)->num_faces = 1;
01760       return error;
01761     }
01762 
01763     error = FT_Raccess_Get_DataOffsets( library, stream,
01764                                         map_offset, rdara_pos,
01765                                         TTAG_sfnt,
01766                                         &data_offsets, &count );
01767     if ( !error )
01768     {
01769       FT_Long  face_index_internal = face_index % count;
01770 
01771 
01772       error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
01773                                       face_index_internal, aface );
01774       FT_FREE( data_offsets );
01775       if ( !error )
01776         (*aface)->num_faces = count;
01777     }
01778 
01779     return error;
01780   }
01781 
01782 
01783   /* Check for a valid macbinary header, and if we find one   */
01784   /* check that the (flattened) resource fork in it is valid. */
01785   /*                                                          */
01786   static FT_Error
01787   IsMacBinary( FT_Library  library,
01788                FT_Stream   stream,
01789                FT_Long     face_index,
01790                FT_Face    *aface )
01791   {
01792     unsigned char  header[128];
01793     FT_Error       error;
01794     FT_Long        dlen, offset;
01795 
01796 
01797     if ( NULL == stream )
01798       return FT_Err_Invalid_Stream_Operation;
01799 
01800     error = FT_Stream_Seek( stream, 0 );
01801     if ( error )
01802       goto Exit;
01803 
01804     error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
01805     if ( error )
01806       goto Exit;
01807 
01808     if (            header[ 0] !=  0 ||
01809                     header[74] !=  0 ||
01810                     header[82] !=  0 ||
01811                     header[ 1] ==  0 ||
01812                     header[ 1] >  33 ||
01813                     header[63] !=  0 ||
01814          header[2 + header[1]] !=  0 )
01815       return FT_Err_Unknown_File_Format;
01816 
01817     dlen = ( header[0x53] << 24 ) |
01818            ( header[0x54] << 16 ) |
01819            ( header[0x55] <<  8 ) |
01820              header[0x56];
01821 #if 0
01822     rlen = ( header[0x57] << 24 ) |
01823            ( header[0x58] << 16 ) |
01824            ( header[0x59] <<  8 ) |
01825              header[0x5a];
01826 #endif /* 0 */
01827     offset = 128 + ( ( dlen + 127 ) & ~127 );
01828 
01829     return IsMacResource( library, stream, offset, face_index, aface );
01830 
01831   Exit:
01832     return error;
01833   }
01834 
01835 
01836   static FT_Error
01837   load_face_in_embedded_rfork( FT_Library           library,
01838                                FT_Stream            stream,
01839                                FT_Long              face_index,
01840                                FT_Face             *aface,
01841                                const FT_Open_Args  *args )
01842   {
01843 
01844 #undef  FT_COMPONENT
01845 #define FT_COMPONENT  trace_raccess
01846 
01847     FT_Memory  memory = library->memory;
01848     FT_Error   error  = FT_Err_Unknown_File_Format;
01849     int        i;
01850 
01851     char *     file_names[FT_RACCESS_N_RULES];
01852     FT_Long    offsets[FT_RACCESS_N_RULES];
01853     FT_Error   errors[FT_RACCESS_N_RULES];
01854     FT_Bool    is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
01855 
01856     FT_Open_Args  args2;
01857     FT_Stream     stream2 = 0;
01858 
01859 
01860     FT_Raccess_Guess( library, stream,
01861                       args->pathname, file_names, offsets, errors );
01862 
01863     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
01864     {
01865       is_darwin_vfs = raccess_rule_by_darwin_vfs( i );
01866       if ( is_darwin_vfs && vfs_rfork_has_no_font )
01867       {
01868         FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"
01869                     " is already checked and"
01870                     " no font is found\n", i ));
01871         continue;
01872       }  
01873 
01874       if ( errors[i] )
01875       {
01876         FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
01877         continue;
01878       }
01879 
01880       args2.flags    = FT_OPEN_PATHNAME;
01881       args2.pathname = file_names[i] ? file_names[i] : args->pathname;
01882 
01883       FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
01884                   i, args2.pathname, offsets[i] ));
01885 
01886       error = FT_Stream_New( library, &args2, &stream2 );
01887       if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )
01888         vfs_rfork_has_no_font = TRUE;
01889 
01890       if ( error )
01891       {
01892         FT_TRACE3(( "failed\n" ));
01893         continue;
01894       }
01895 
01896       error = IsMacResource( library, stream2, offsets[i],
01897                              face_index, aface );
01898       FT_Stream_Free( stream2, 0 );
01899 
01900       FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
01901 
01902       if ( !error )
01903           break;
01904       else if ( is_darwin_vfs )
01905           vfs_rfork_has_no_font = TRUE;
01906     }
01907 
01908     for (i = 0; i < FT_RACCESS_N_RULES; i++)
01909     {
01910       if ( file_names[i] )
01911         FT_FREE( file_names[i] );
01912     }
01913 
01914     /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
01915     if ( error )
01916       error = FT_Err_Unknown_File_Format;
01917 
01918     return error;
01919 
01920 #undef  FT_COMPONENT
01921 #define FT_COMPONENT  trace_objs
01922 
01923   }
01924 
01925 
01926   /* Check for some macintosh formats without Carbon framework.    */
01927   /* Is this a macbinary file?  If so look at the resource fork.   */
01928   /* Is this a mac dfont file?                                     */
01929   /* Is this an old style resource fork? (in data)                 */
01930   /* Else call load_face_in_embedded_rfork to try extra rules      */
01931   /* (defined in `ftrfork.c').                                     */
01932   /*                                                               */
01933   static FT_Error
01934   load_mac_face( FT_Library           library,
01935                  FT_Stream            stream,
01936                  FT_Long              face_index,
01937                  FT_Face             *aface,
01938                  const FT_Open_Args  *args )
01939   {
01940     FT_Error error;
01941     FT_UNUSED( args );
01942 
01943 
01944     error = IsMacBinary( library, stream, face_index, aface );
01945     if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
01946     {
01947 
01948 #undef  FT_COMPONENT
01949 #define FT_COMPONENT  trace_raccess
01950 
01951       FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
01952 
01953       error = IsMacResource( library, stream, 0, face_index, aface );
01954 
01955       FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
01956 
01957 #undef  FT_COMPONENT
01958 #define FT_COMPONENT  trace_objs
01959 
01960     }
01961 
01962     if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format      ||
01963            FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
01964          ( args->flags & FT_OPEN_PATHNAME )                            )
01965       error = load_face_in_embedded_rfork( library, stream,
01966                                            face_index, aface, args );
01967     return error;
01968   }
01969 #endif
01970 
01971 #endif  /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
01972 
01973 
01974   /* documentation is in freetype.h */
01975 
01976   FT_EXPORT_DEF( FT_Error )
01977   FT_Open_Face( FT_Library           library,
01978                 const FT_Open_Args*  args,
01979                 FT_Long              face_index,
01980                 FT_Face             *aface )
01981   {
01982     FT_Error     error;
01983     FT_Driver    driver;
01984     FT_Memory    memory;
01985     FT_Stream    stream = NULL;
01986     FT_Face      face   = NULL;
01987     FT_ListNode  node   = NULL;
01988     FT_Bool      external_stream;
01989     FT_Module*   cur;
01990     FT_Module*   limit;
01991 
01992 
01993     /* test for valid `library' delayed to */
01994     /* FT_Stream_New()                     */
01995 
01996     if ( ( !aface && face_index >= 0 ) || !args )
01997       return FT_Err_Invalid_Argument;
01998 
01999     external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
02000                                args->stream                     );
02001 
02002     /* create input stream */
02003     error = FT_Stream_New( library, args, &stream );
02004     if ( error )
02005       goto Fail3;
02006 
02007     memory = library->memory;
02008 
02009     /* If the font driver is specified in the `args' structure, use */
02010     /* it.  Otherwise, we scan the list of registered drivers.      */
02011     if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
02012     {
02013       driver = FT_DRIVER( args->driver );
02014 
02015       /* not all modules are drivers, so check... */
02016       if ( FT_MODULE_IS_DRIVER( driver ) )
02017       {
02018         FT_Int         num_params = 0;
02019         FT_Parameter*  params     = 0;
02020 
02021 
02022         if ( args->flags & FT_OPEN_PARAMS )
02023         {
02024           num_params = args->num_params;
02025           params     = args->params;
02026         }
02027 
02028         error = open_face( driver, stream, face_index,
02029                            num_params, params, &face );
02030         if ( !error )
02031           goto Success;
02032       }
02033       else
02034         error = FT_Err_Invalid_Handle;
02035 
02036       FT_Stream_Free( stream, external_stream );
02037       goto Fail;
02038     }
02039     else
02040     {
02041       /* check each font driver for an appropriate format */
02042       cur   = library->modules;
02043       limit = cur + library->num_modules;
02044 
02045 
02046       for ( ; cur < limit; cur++ )
02047       {
02048         /* not all modules are font drivers, so check... */
02049         if ( FT_MODULE_IS_DRIVER( cur[0] ) )
02050         {
02051           FT_Int         num_params = 0;
02052           FT_Parameter*  params     = 0;
02053 
02054 
02055           driver = FT_DRIVER( cur[0] );
02056 
02057           if ( args->flags & FT_OPEN_PARAMS )
02058           {
02059             num_params = args->num_params;
02060             params     = args->params;
02061           }
02062 
02063           error = open_face( driver, stream, face_index,
02064                              num_params, params, &face );
02065           if ( !error )
02066             goto Success;
02067 
02068 #ifdef FT_CONFIG_OPTION_MAC_FONTS
02069           if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
02070                FT_ERROR_BASE( error ) == FT_Err_Table_Missing           )
02071           {
02072             /* TrueType but essential tables are missing */
02073             if ( FT_Stream_Seek( stream, 0 ) )
02074               break;
02075 
02076             error = open_face_PS_from_sfnt_stream( library,
02077                                                    stream,
02078                                                    face_index,
02079                                                    num_params,
02080                                                    params,
02081                                                    aface );
02082             if ( !error )
02083             {
02084               FT_Stream_Free( stream, external_stream );
02085               return error;
02086             }
02087           }
02088 #endif
02089 
02090           if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
02091             goto Fail3;
02092         }
02093       }
02094 
02095   Fail3:
02096     /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
02097     /* it may be because we have an empty data fork, so we need to check   */
02098     /* the resource fork.                                                  */
02099     if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream       &&
02100          FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format      &&
02101          FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
02102       goto Fail2;
02103 
02104 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
02105     error = load_mac_face( library, stream, face_index, aface, args );
02106     if ( !error )
02107     {
02108       /* We don't want to go to Success here.  We've already done that. */
02109       /* On the other hand, if we succeeded we still need to close this */
02110       /* stream (we opened a different stream which extracted the       */
02111       /* interesting information out of this stream here.  That stream  */
02112       /* will still be open and the face will point to it).             */
02113       FT_Stream_Free( stream, external_stream );
02114       return error;
02115     }
02116 
02117     if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
02118       goto Fail2;
02119 #endif  /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
02120 
02121       /* no driver is able to handle this format */
02122       error = FT_Err_Unknown_File_Format;
02123 
02124   Fail2:
02125       FT_Stream_Free( stream, external_stream );
02126       goto Fail;
02127     }
02128 
02129   Success:
02130     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
02131 
02132     /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
02133     if ( external_stream )
02134       face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
02135 
02136     /* add the face object to its driver's list */
02137     if ( FT_NEW( node ) )
02138       goto Fail;
02139 
02140     node->data = face;
02141     /* don't assume driver is the same as face->driver, so use */
02142     /* face->driver instead.                                   */
02143     FT_List_Add( &face->driver->faces_list, node );
02144 
02145     /* now allocate a glyph slot object for the face */
02146     FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
02147 
02148     if ( face_index >= 0 )
02149     {
02150       error = FT_New_GlyphSlot( face, NULL );
02151       if ( error )
02152         goto Fail;
02153 
02154       /* finally, allocate a size object for the face */
02155       {
02156         FT_Size  size;
02157 
02158 
02159         FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
02160 
02161         error = FT_New_Size( face, &size );
02162         if ( error )
02163           goto Fail;
02164 
02165         face->size = size;
02166       }
02167     }
02168 
02169     /* some checks */
02170 
02171     if ( FT_IS_SCALABLE( face ) )
02172     {
02173       if ( face->height < 0 )
02174         face->height = (FT_Short)-face->height;
02175 
02176       if ( !FT_HAS_VERTICAL( face ) )
02177         face->max_advance_height = (FT_Short)face->height;
02178     }
02179 
02180     if ( FT_HAS_FIXED_SIZES( face ) )
02181     {
02182       FT_Int  i;
02183 
02184 
02185       for ( i = 0; i < face->num_fixed_sizes; i++ )
02186       {
02187         FT_Bitmap_Size*  bsize = face->available_sizes + i;
02188 
02189 
02190         if ( bsize->height < 0 )
02191           bsize->height = (FT_Short)-bsize->height;
02192         if ( bsize->x_ppem < 0 )
02193           bsize->x_ppem = (FT_Short)-bsize->x_ppem;
02194         if ( bsize->y_ppem < 0 )
02195           bsize->y_ppem = -bsize->y_ppem;
02196       }
02197     }
02198 
02199     /* initialize internal face data */
02200     {
02201       FT_Face_Internal  internal = face->internal;
02202 
02203 
02204       internal->transform_matrix.xx = 0x10000L;
02205       internal->transform_matrix.xy = 0;
02206       internal->transform_matrix.yx = 0;
02207       internal->transform_matrix.yy = 0x10000L;
02208 
02209       internal->transform_delta.x = 0;
02210       internal->transform_delta.y = 0;
02211 
02212       internal->refcount = 1;
02213     }
02214 
02215     if ( aface )
02216       *aface = face;
02217     else
02218       FT_Done_Face( face );
02219 
02220     goto Exit;
02221 
02222   Fail:
02223     FT_Done_Face( face );
02224 
02225   Exit:
02226     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
02227 
02228     return error;
02229   }
02230 
02231 
02232   /* documentation is in freetype.h */
02233 
02234   FT_EXPORT_DEF( FT_Error )
02235   FT_Attach_File( FT_Face      face,
02236                   const char*  filepathname )
02237   {
02238     FT_Open_Args  open;
02239 
02240 
02241     /* test for valid `face' delayed to FT_Attach_Stream() */
02242 
02243     if ( !filepathname )
02244       return FT_Err_Invalid_Argument;
02245 
02246     open.stream   = NULL;
02247     open.flags    = FT_OPEN_PATHNAME;
02248     open.pathname = (char*)filepathname;
02249 
02250     return FT_Attach_Stream( face, &open );
02251   }
02252 
02253 
02254   /* documentation is in freetype.h */
02255 
02256   FT_EXPORT_DEF( FT_Error )
02257   FT_Attach_Stream( FT_Face        face,
02258                     FT_Open_Args*  parameters )
02259   {
02260     FT_Stream  stream;
02261     FT_Error   error;
02262     FT_Driver  driver;
02263 
02264     FT_Driver_Class  clazz;
02265 
02266 
02267     /* test for valid `parameters' delayed to FT_Stream_New() */
02268 
02269     if ( !face )
02270       return FT_Err_Invalid_Face_Handle;
02271 
02272     driver = face->driver;
02273     if ( !driver )
02274       return FT_Err_Invalid_Driver_Handle;
02275 
02276     error = FT_Stream_New( driver->root.library, parameters, &stream );
02277     if ( error )
02278       goto Exit;
02279 
02280     /* we implement FT_Attach_Stream in each driver through the */
02281     /* `attach_file' interface                                  */
02282 
02283     error = FT_Err_Unimplemented_Feature;
02284     clazz = driver->clazz;
02285     if ( clazz->attach_file )
02286       error = clazz->attach_file( face, stream );
02287 
02288     /* close the attached stream */
02289     FT_Stream_Free( stream,
02290                     (FT_Bool)( parameters->stream &&
02291                                ( parameters->flags & FT_OPEN_STREAM ) ) );
02292 
02293   Exit:
02294     return error;
02295   }
02296 
02297 
02298   /* documentation is in freetype.h */
02299 
02300   FT_EXPORT_DEF( FT_Error )
02301   FT_Reference_Face( FT_Face  face )
02302   {
02303     face->internal->refcount++;
02304 
02305     return FT_Err_Ok;
02306   }
02307 
02308 
02309   /* documentation is in freetype.h */
02310 
02311   FT_EXPORT_DEF( FT_Error )
02312   FT_Done_Face( FT_Face  face )
02313   {
02314     FT_Error     error;
02315     FT_Driver    driver;
02316     FT_Memory    memory;
02317     FT_ListNode  node;
02318 
02319 
02320     error = FT_Err_Invalid_Face_Handle;
02321     if ( face && face->driver )
02322     {
02323       face->internal->refcount--;
02324       if ( face->internal->refcount > 0 )
02325         error = FT_Err_Ok;
02326       else
02327       {
02328         driver = face->driver;
02329         memory = driver->root.memory;
02330 
02331         /* find face in driver's list */
02332         node = FT_List_Find( &driver->faces_list, face );
02333         if ( node )
02334         {
02335           /* remove face object from the driver's list */
02336           FT_List_Remove( &driver->faces_list, node );
02337           FT_FREE( node );
02338 
02339           /* now destroy the object proper */
02340           destroy_face( memory, face, driver );
02341           error = FT_Err_Ok;
02342         }
02343       }
02344     }
02345 
02346     return error;
02347   }
02348 
02349 
02350   /* documentation is in ftobjs.h */
02351 
02352   FT_EXPORT_DEF( FT_Error )
02353   FT_New_Size( FT_Face   face,
02354                FT_Size  *asize )
02355   {
02356     FT_Error         error;
02357     FT_Memory        memory;
02358     FT_Driver        driver;
02359     FT_Driver_Class  clazz;
02360 
02361     FT_Size          size = 0;
02362     FT_ListNode      node = 0;
02363 
02364 
02365     if ( !face )
02366       return FT_Err_Invalid_Face_Handle;
02367 
02368     if ( !asize )
02369       return FT_Err_Invalid_Size_Handle;
02370 
02371     if ( !face->driver )
02372       return FT_Err_Invalid_Driver_Handle;
02373 
02374     *asize = 0;
02375 
02376     driver = face->driver;
02377     clazz  = driver->clazz;
02378     memory = face->memory;
02379 
02380     /* Allocate new size object and perform basic initialisation */
02381     if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
02382       goto Exit;
02383 
02384     size->face = face;
02385 
02386     /* for now, do not use any internal fields in size objects */
02387     size->internal = 0;
02388 
02389     if ( clazz->init_size )
02390       error = clazz->init_size( size );
02391 
02392     /* in case of success, add to the face's list */
02393     if ( !error )
02394     {
02395       *asize     = size;
02396       node->data = size;
02397       FT_List_Add( &face->sizes_list, node );
02398     }
02399 
02400   Exit:
02401     if ( error )
02402     {
02403       FT_FREE( node );
02404       FT_FREE( size );
02405     }
02406 
02407     return error;
02408   }
02409 
02410 
02411   /* documentation is in ftobjs.h */
02412 
02413   FT_EXPORT_DEF( FT_Error )
02414   FT_Done_Size( FT_Size  size )
02415   {
02416     FT_Error     error;
02417     FT_Driver    driver;
02418     FT_Memory    memory;
02419     FT_Face      face;
02420     FT_ListNode  node;
02421 
02422 
02423     if ( !size )
02424       return FT_Err_Invalid_Size_Handle;
02425 
02426     face = size->face;
02427     if ( !face )
02428       return FT_Err_Invalid_Face_Handle;
02429 
02430     driver = face->driver;
02431     if ( !driver )
02432       return FT_Err_Invalid_Driver_Handle;
02433 
02434     memory = driver->root.memory;
02435 
02436     error = FT_Err_Ok;
02437     node  = FT_List_Find( &face->sizes_list, size );
02438     if ( node )
02439     {
02440       FT_List_Remove( &face->sizes_list, node );
02441       FT_FREE( node );
02442 
02443       if ( face->size == size )
02444       {
02445         face->size = 0;
02446         if ( face->sizes_list.head )
02447           face->size = (FT_Size)(face->sizes_list.head->data);
02448       }
02449 
02450       destroy_size( memory, size, driver );
02451     }
02452     else
02453       error = FT_Err_Invalid_Size_Handle;
02454 
02455     return error;
02456   }
02457 
02458 
02459   /* documentation is in ftobjs.h */
02460 
02461   FT_BASE_DEF( FT_Error )
02462   FT_Match_Size( FT_Face          face,
02463                  FT_Size_Request  req,
02464                  FT_Bool          ignore_width,
02465                  FT_ULong*        size_index )
02466   {
02467     FT_Int   i;
02468     FT_Long  w, h;
02469 
02470 
02471     if ( !FT_HAS_FIXED_SIZES( face ) )
02472       return FT_Err_Invalid_Face_Handle;
02473 
02474     /* FT_Bitmap_Size doesn't provide enough info... */
02475     if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
02476       return FT_Err_Unimplemented_Feature;
02477 
02478     w = FT_REQUEST_WIDTH ( req );
02479     h = FT_REQUEST_HEIGHT( req );
02480 
02481     if ( req->width && !req->height )
02482       h = w;
02483     else if ( !req->width && req->height )
02484       w = h;
02485 
02486     w = FT_PIX_ROUND( w );
02487     h = FT_PIX_ROUND( h );
02488 
02489     for ( i = 0; i < face->num_fixed_sizes; i++ )
02490     {
02491       FT_Bitmap_Size*  bsize = face->available_sizes + i;
02492 
02493 
02494       if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
02495         continue;
02496 
02497       if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
02498       {
02499         if ( size_index )
02500           *size_index = (FT_ULong)i;
02501 
02502         return FT_Err_Ok;
02503       }
02504     }
02505 
02506     return FT_Err_Invalid_Pixel_Size;
02507   }
02508 
02509 
02510   /* documentation is in ftobjs.h */
02511 
02512   FT_BASE_DEF( void )
02513   ft_synthesize_vertical_metrics( FT_Glyph_Metrics*  metrics,
02514                                   FT_Pos             advance )
02515   {
02516     FT_Pos  height = metrics->height;
02517 
02518 
02519     /* compensate for glyph with bbox above/below the baseline */
02520     if ( metrics->horiBearingY < 0 )
02521     {
02522       if ( height < metrics->horiBearingY )
02523         height = metrics->horiBearingY;
02524     }
02525     else if ( metrics->horiBearingY > 0 )
02526       height -= metrics->horiBearingY;
02527 
02528     /* the factor 1.2 is a heuristical value */
02529     if ( !advance )
02530       advance = height * 12 / 10;
02531 
02532     metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
02533     metrics->vertBearingY = ( advance - height ) / 2;
02534     metrics->vertAdvance  = advance;
02535   }
02536 
02537 
02538   static void
02539   ft_recompute_scaled_metrics( FT_Face           face,
02540                                FT_Size_Metrics*  metrics )
02541   {
02542     /* Compute root ascender, descender, test height, and max_advance */
02543 
02544 #ifdef GRID_FIT_METRICS
02545     metrics->ascender    = FT_PIX_CEIL( FT_MulFix( face->ascender,
02546                                                    metrics->y_scale ) );
02547 
02548     metrics->descender   = FT_PIX_FLOOR( FT_MulFix( face->descender,
02549                                                     metrics->y_scale ) );
02550 
02551     metrics->height      = FT_PIX_ROUND( FT_MulFix( face->height,
02552                                                     metrics->y_scale ) );
02553 
02554     metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
02555                                                     metrics->x_scale ) );
02556 #else /* !GRID_FIT_METRICS */
02557     metrics->ascender    = FT_MulFix( face->ascender,
02558                                       metrics->y_scale );
02559 
02560     metrics->descender   = FT_MulFix( face->descender,
02561                                       metrics->y_scale );
02562 
02563     metrics->height      = FT_MulFix( face->height,
02564                                       metrics->y_scale );
02565 
02566     metrics->max_advance = FT_MulFix( face->max_advance_width,
02567                                       metrics->x_scale );
02568 #endif /* !GRID_FIT_METRICS */
02569   }
02570 
02571 
02572   FT_BASE_DEF( void )
02573   FT_Select_Metrics( FT_Face   face,
02574                      FT_ULong  strike_index )
02575   {
02576     FT_Size_Metrics*  metrics;
02577     FT_Bitmap_Size*   bsize;
02578 
02579 
02580     metrics = &face->size->metrics;
02581     bsize   = face->available_sizes + strike_index;
02582 
02583     metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
02584     metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
02585 
02586     if ( FT_IS_SCALABLE( face ) )
02587     {
02588       metrics->x_scale = FT_DivFix( bsize->x_ppem,
02589                                     face->units_per_EM );
02590       metrics->y_scale = FT_DivFix( bsize->y_ppem,
02591                                     face->units_per_EM );
02592 
02593       ft_recompute_scaled_metrics( face, metrics );
02594     }
02595     else
02596     {
02597       metrics->x_scale     = 1L << 16;
02598       metrics->y_scale     = 1L << 16;
02599       metrics->ascender    = bsize->y_ppem;
02600       metrics->descender   = 0;
02601       metrics->height      = bsize->height << 6;
02602       metrics->max_advance = bsize->x_ppem;
02603     }
02604   }
02605 
02606 
02607   FT_BASE_DEF( void )
02608   FT_Request_Metrics( FT_Face          face,
02609                       FT_Size_Request  req )
02610   {
02611     FT_Size_Metrics*  metrics;
02612 
02613 
02614     metrics = &face->size->metrics;
02615 
02616     if ( FT_IS_SCALABLE( face ) )
02617     {
02618       FT_Long  w = 0, h = 0, scaled_w = 0, scaled_h = 0;
02619 
02620 
02621       switch ( req->type )
02622       {
02623       case FT_SIZE_REQUEST_TYPE_NOMINAL:
02624         w = h = face->units_per_EM;
02625         break;
02626 
02627       case FT_SIZE_REQUEST_TYPE_REAL_DIM:
02628         w = h = face->ascender - face->descender;
02629         break;
02630 
02631       case FT_SIZE_REQUEST_TYPE_BBOX:
02632         w = face->bbox.xMax - face->bbox.xMin;
02633         h = face->bbox.yMax - face->bbox.yMin;
02634         break;
02635 
02636       case FT_SIZE_REQUEST_TYPE_CELL:
02637         w = face->max_advance_width;
02638         h = face->ascender - face->descender;
02639         break;
02640 
02641       case FT_SIZE_REQUEST_TYPE_SCALES:
02642         metrics->x_scale = (FT_Fixed)req->width;
02643         metrics->y_scale = (FT_Fixed)req->height;
02644         if ( !metrics->x_scale )
02645           metrics->x_scale = metrics->y_scale;
02646         else if ( !metrics->y_scale )
02647           metrics->y_scale = metrics->x_scale;
02648         goto Calculate_Ppem;
02649 
02650       case FT_SIZE_REQUEST_TYPE_MAX:
02651         break;
02652       }
02653 
02654       /* to be on the safe side */
02655       if ( w < 0 )
02656         w = -w;
02657 
02658       if ( h < 0 )
02659         h = -h;
02660 
02661       scaled_w = FT_REQUEST_WIDTH ( req );
02662       scaled_h = FT_REQUEST_HEIGHT( req );
02663 
02664       /* determine scales */
02665       if ( req->width )
02666       {
02667         metrics->x_scale = FT_DivFix( scaled_w, w );
02668 
02669         if ( req->height )
02670         {
02671           metrics->y_scale = FT_DivFix( scaled_h, h );
02672 
02673           if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
02674           {
02675             if ( metrics->y_scale > metrics->x_scale )
02676               metrics->y_scale = metrics->x_scale;
02677             else
02678               metrics->x_scale = metrics->y_scale;
02679           }
02680         }
02681         else
02682         {
02683           metrics->y_scale = metrics->x_scale;
02684           scaled_h = FT_MulDiv( scaled_w, h, w );
02685         }
02686       }
02687       else
02688       {
02689         metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
02690         scaled_w = FT_MulDiv( scaled_h, w, h );
02691       }
02692 
02693   Calculate_Ppem:
02694       /* calculate the ppems */
02695       if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
02696       {
02697         scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
02698         scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
02699       }
02700 
02701       metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
02702       metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
02703 
02704       ft_recompute_scaled_metrics( face, metrics );
02705     }
02706     else
02707     {
02708       FT_ZERO( metrics );
02709       metrics->x_scale = 1L << 16;
02710       metrics->y_scale = 1L << 16;
02711     }
02712   }
02713 
02714 
02715   /* documentation is in freetype.h */
02716 
02717   FT_EXPORT_DEF( FT_Error )
02718   FT_Select_Size( FT_Face  face,
02719                   FT_Int   strike_index )
02720   {
02721     FT_Driver_Class  clazz;
02722 
02723 
02724     if ( !face || !FT_HAS_FIXED_SIZES( face ) )
02725       return FT_Err_Invalid_Face_Handle;
02726 
02727     if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
02728       return FT_Err_Invalid_Argument;
02729 
02730     clazz = face->driver->clazz;
02731 
02732     if ( clazz->select_size )
02733       return clazz->select_size( face->size, (FT_ULong)strike_index );
02734 
02735     FT_Select_Metrics( face, (FT_ULong)strike_index );
02736 
02737     return FT_Err_Ok;
02738   }
02739 
02740 
02741   /* documentation is in freetype.h */
02742 
02743   FT_EXPORT_DEF( FT_Error )
02744   FT_Request_Size( FT_Face          face,
02745                    FT_Size_Request  req )
02746   {
02747     FT_Driver_Class  clazz;
02748     FT_ULong         strike_index;
02749 
02750 
02751     if ( !face )
02752       return FT_Err_Invalid_Face_Handle;
02753 
02754     if ( !req || req->width < 0 || req->height < 0 ||
02755          req->type >= FT_SIZE_REQUEST_TYPE_MAX )
02756       return FT_Err_Invalid_Argument;
02757 
02758     clazz = face->driver->clazz;
02759 
02760     if ( clazz->request_size )
02761       return clazz->request_size( face->size, req );
02762 
02763     /*
02764      * The reason that a driver doesn't have `request_size' defined is
02765      * either that the scaling here suffices or that the supported formats
02766      * are bitmap-only and size matching is not implemented.
02767      *
02768      * In the latter case, a simple size matching is done.
02769      */
02770     if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
02771     {
02772       FT_Error  error;
02773 
02774 
02775       error = FT_Match_Size( face, req, 0, &strike_index );
02776       if ( error )
02777         return error;
02778 
02779       FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
02780                   strike_index ));
02781 
02782       return FT_Select_Size( face, (FT_Int)strike_index );
02783     }
02784 
02785     FT_Request_Metrics( face, req );
02786 
02787     return FT_Err_Ok;
02788   }
02789 
02790 
02791   /* documentation is in freetype.h */
02792 
02793   FT_EXPORT_DEF( FT_Error )
02794   FT_Set_Char_Size( FT_Face     face,
02795                     FT_F26Dot6  char_width,
02796                     FT_F26Dot6  char_height,
02797                     FT_UInt     horz_resolution,
02798                     FT_UInt     vert_resolution )
02799   {
02800     FT_Size_RequestRec  req;
02801 
02802 
02803     if ( !char_width )
02804       char_width = char_height;
02805     else if ( !char_height )
02806       char_height = char_width;
02807 
02808     if ( !horz_resolution )
02809       horz_resolution = vert_resolution;
02810     else if ( !vert_resolution )
02811       vert_resolution = horz_resolution;
02812 
02813     if ( char_width  < 1 * 64 )
02814       char_width  = 1 * 64;
02815     if ( char_height < 1 * 64 )
02816       char_height = 1 * 64;
02817 
02818     if ( !horz_resolution )
02819       horz_resolution = vert_resolution = 72;
02820 
02821     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
02822     req.width          = char_width;
02823     req.height         = char_height;
02824     req.horiResolution = horz_resolution;
02825     req.vertResolution = vert_resolution;
02826 
02827     return FT_Request_Size( face, &req );
02828   }
02829 
02830 
02831   /* documentation is in freetype.h */
02832 
02833   FT_EXPORT_DEF( FT_Error )
02834   FT_Set_Pixel_Sizes( FT_Face  face,
02835                       FT_UInt  pixel_width,
02836                       FT_UInt  pixel_height )
02837   {
02838     FT_Size_RequestRec  req;
02839 
02840 
02841     if ( pixel_width == 0 )
02842       pixel_width = pixel_height;
02843     else if ( pixel_height == 0 )
02844       pixel_height = pixel_width;
02845 
02846     if ( pixel_width  < 1 )
02847       pixel_width  = 1;
02848     if ( pixel_height < 1 )
02849       pixel_height = 1;
02850 
02851     /* use `>=' to avoid potential compiler warning on 16bit platforms */
02852     if ( pixel_width  >= 0xFFFFU )
02853       pixel_width  = 0xFFFFU;
02854     if ( pixel_height >= 0xFFFFU )
02855       pixel_height = 0xFFFFU;
02856 
02857     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
02858     req.width          = pixel_width << 6;
02859     req.height         = pixel_height << 6;
02860     req.horiResolution = 0;
02861     req.vertResolution = 0;
02862 
02863     return FT_Request_Size( face, &req );
02864   }
02865 
02866 
02867   /* documentation is in freetype.h */
02868 
02869   FT_EXPORT_DEF( FT_Error )
02870   FT_Get_Kerning( FT_Face     face,
02871                   FT_UInt     left_glyph,
02872                   FT_UInt     right_glyph,
02873                   FT_UInt     kern_mode,
02874                   FT_Vector  *akerning )
02875   {
02876     FT_Error   error = FT_Err_Ok;
02877     FT_Driver  driver;
02878 
02879 
02880     if ( !face )
02881       return FT_Err_Invalid_Face_Handle;
02882 
02883     if ( !akerning )
02884       return FT_Err_Invalid_Argument;
02885 
02886     driver = face->driver;
02887 
02888     akerning->x = 0;
02889     akerning->y = 0;
02890 
02891     if ( driver->clazz->get_kerning )
02892     {
02893       error = driver->clazz->get_kerning( face,
02894                                           left_glyph,
02895                                           right_glyph,
02896                                           akerning );
02897       if ( !error )
02898       {
02899         if ( kern_mode != FT_KERNING_UNSCALED )
02900         {
02901           akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
02902           akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
02903 
02904           if ( kern_mode != FT_KERNING_UNFITTED )
02905           {
02906             /* we scale down kerning values for small ppem values */
02907             /* to avoid that rounding makes them too big.         */
02908             /* `25' has been determined heuristically.            */
02909             if ( face->size->metrics.x_ppem < 25 )
02910               akerning->x = FT_MulDiv( akerning->x,
02911                                        face->size->metrics.x_ppem, 25 );
02912             if ( face->size->metrics.y_ppem < 25 )
02913               akerning->y = FT_MulDiv( akerning->y,
02914                                        face->size->metrics.y_ppem, 25 );
02915 
02916             akerning->x = FT_PIX_ROUND( akerning->x );
02917             akerning->y = FT_PIX_ROUND( akerning->y );
02918           }
02919         }
02920       }
02921     }
02922 
02923     return error;
02924   }
02925 
02926 
02927   /* documentation is in freetype.h */
02928 
02929   FT_EXPORT_DEF( FT_Error )
02930   FT_Get_Track_Kerning( FT_Face    face,
02931                         FT_Fixed   point_size,
02932                         FT_Int     degree,
02933                         FT_Fixed*  akerning )
02934   {
02935     FT_Service_Kerning  service;
02936     FT_Error            error = FT_Err_Ok;
02937 
02938 
02939     if ( !face )
02940       return FT_Err_Invalid_Face_Handle;
02941 
02942     if ( !akerning )
02943       return FT_Err_Invalid_Argument;
02944 
02945     FT_FACE_FIND_SERVICE( face, service, KERNING );
02946     if ( !service )
02947       return FT_Err_Unimplemented_Feature;
02948 
02949     error = service->get_track( face,
02950                                 point_size,
02951                                 degree,
02952                                 akerning );
02953 
02954     return error;
02955   }
02956 
02957 
02958   /* documentation is in freetype.h */
02959 
02960   FT_EXPORT_DEF( FT_Error )
02961   FT_Select_Charmap( FT_Face      face,
02962                      FT_Encoding  encoding )
02963   {
02964     FT_CharMap*  cur;
02965     FT_CharMap*  limit;
02966 
02967 
02968     if ( !face )
02969       return FT_Err_Invalid_Face_Handle;
02970 
02971     if ( encoding == FT_ENCODING_NONE )
02972       return FT_Err_Invalid_Argument;
02973 
02974     /* FT_ENCODING_UNICODE is special.  We try to find the `best' Unicode */
02975     /* charmap available, i.e., one with UCS-4 characters, if possible.   */
02976     /*                                                                    */
02977     /* This is done by find_unicode_charmap() above, to share code.       */
02978     if ( encoding == FT_ENCODING_UNICODE )
02979       return find_unicode_charmap( face );
02980 
02981     cur = face->charmaps;
02982     if ( !cur )
02983       return FT_Err_Invalid_CharMap_Handle;
02984 
02985     limit = cur + face->num_charmaps;
02986 
02987     for ( ; cur < limit; cur++ )
02988     {
02989       if ( cur[0]->encoding == encoding )
02990       {
02991 #ifdef FT_MAX_CHARMAP_CACHEABLE
02992         if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
02993         {
02994           FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
02995                      "but in too late position to cache\n",
02996                      cur - face->charmaps ));
02997           continue;
02998         }
02999 #endif
03000         face->charmap = cur[0];
03001         return 0;
03002       }
03003     }
03004 
03005     return FT_Err_Invalid_Argument;
03006   }
03007 
03008 
03009   /* documentation is in freetype.h */
03010 
03011   FT_EXPORT_DEF( FT_Error )
03012   FT_Set_Charmap( FT_Face     face,
03013                   FT_CharMap  charmap )
03014   {
03015     FT_CharMap*  cur;
03016     FT_CharMap*  limit;
03017 
03018 
03019     if ( !face )
03020       return FT_Err_Invalid_Face_Handle;
03021 
03022     cur = face->charmaps;
03023     if ( !cur )
03024       return FT_Err_Invalid_CharMap_Handle;
03025     if ( FT_Get_CMap_Format( charmap ) == 14 )
03026       return FT_Err_Invalid_Argument;
03027 
03028     limit = cur + face->num_charmaps;
03029 
03030     for ( ; cur < limit; cur++ )
03031     {
03032       if ( cur[0] == charmap )
03033       {
03034 #ifdef FT_MAX_CHARMAP_CACHEABLE
03035         if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
03036         {
03037           FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
03038                      "but in too late position to cache\n",
03039                      cur - face->charmaps ));
03040           continue;
03041         }
03042 #endif
03043         face->charmap = cur[0];
03044         return 0;
03045       }
03046     }
03047     return FT_Err_Invalid_Argument;
03048   }
03049 
03050 
03051   /* documentation is in freetype.h */
03052 
03053   FT_EXPORT_DEF( FT_Int )
03054   FT_Get_Charmap_Index( FT_CharMap  charmap )
03055   {
03056     FT_Int  i;
03057 
03058 
03059     if ( !charmap || !charmap->face )
03060       return -1;
03061 
03062     for ( i = 0; i < charmap->face->num_charmaps; i++ )
03063       if ( charmap->face->charmaps[i] == charmap )
03064         break;
03065 
03066     FT_ASSERT( i < charmap->face->num_charmaps );
03067 
03068 #ifdef FT_MAX_CHARMAP_CACHEABLE
03069     if ( i > FT_MAX_CHARMAP_CACHEABLE )
03070     {
03071       FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
03072                  "but in too late position to cache\n",
03073                  i ));
03074       return -i;
03075     }
03076 #endif
03077     return i;
03078   }
03079 
03080 
03081   static void
03082   ft_cmap_done_internal( FT_CMap  cmap )
03083   {
03084     FT_CMap_Class  clazz  = cmap->clazz;
03085     FT_Face        face   = cmap->charmap.face;
03086     FT_Memory      memory = FT_FACE_MEMORY(face);
03087 
03088 
03089     if ( clazz->done )
03090       clazz->done( cmap );
03091 
03092     FT_FREE( cmap );
03093   }
03094 
03095 
03096   FT_BASE_DEF( void )
03097   FT_CMap_Done( FT_CMap  cmap )
03098   {
03099     if ( cmap )
03100     {
03101       FT_Face    face   = cmap->charmap.face;
03102       FT_Memory  memory = FT_FACE_MEMORY( face );
03103       FT_Error   error;
03104       FT_Int     i, j;
03105 
03106 
03107       for ( i = 0; i < face->num_charmaps; i++ )
03108       {
03109         if ( (FT_CMap)face->charmaps[i] == cmap )
03110         {
03111           FT_CharMap  last_charmap = face->charmaps[face->num_charmaps - 1];
03112 
03113 
03114           if ( FT_RENEW_ARRAY( face->charmaps,
03115                                face->num_charmaps,
03116                                face->num_charmaps - 1 ) )
03117             return;
03118 
03119           /* remove it from our list of charmaps */
03120           for ( j = i + 1; j < face->num_charmaps; j++ )
03121           {
03122             if ( j == face->num_charmaps - 1 )
03123               face->charmaps[j - 1] = last_charmap;
03124             else
03125               face->charmaps[j - 1] = face->charmaps[j];
03126           }
03127 
03128           face->num_charmaps--;
03129 
03130           if ( (FT_CMap)face->charmap == cmap )
03131             face->charmap = NULL;
03132 
03133           ft_cmap_done_internal( cmap );
03134 
03135           break;
03136         }
03137       }
03138     }
03139   }
03140 
03141 
03142   FT_BASE_DEF( FT_Error )
03143   FT_CMap_New( FT_CMap_Class  clazz,
03144                FT_Pointer     init_data,
03145                FT_CharMap     charmap,
03146                FT_CMap       *acmap )
03147   {
03148     FT_Error   error = FT_Err_Ok;
03149     FT_Face    face;
03150     FT_Memory  memory;
03151     FT_CMap    cmap;
03152 
03153 
03154     if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
03155       return FT_Err_Invalid_Argument;
03156 
03157     face   = charmap->face;
03158     memory = FT_FACE_MEMORY( face );
03159 
03160     if ( !FT_ALLOC( cmap, clazz->size ) )
03161     {
03162       cmap->charmap = *charmap;
03163       cmap->clazz   = clazz;
03164 
03165       if ( clazz->init )
03166       {
03167         error = clazz->init( cmap, init_data );
03168         if ( error )
03169           goto Fail;
03170       }
03171 
03172       /* add it to our list of charmaps */
03173       if ( FT_RENEW_ARRAY( face->charmaps,
03174                            face->num_charmaps,
03175                            face->num_charmaps + 1 ) )
03176         goto Fail;
03177 
03178       face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
03179     }
03180 
03181   Exit:
03182     if ( acmap )
03183       *acmap = cmap;
03184 
03185     return error;
03186 
03187   Fail:
03188     ft_cmap_done_internal( cmap );
03189     cmap = NULL;
03190     goto Exit;
03191   }
03192 
03193 
03194   /* documentation is in freetype.h */
03195 
03196   FT_EXPORT_DEF( FT_UInt )
03197   FT_Get_Char_Index( FT_Face   face,
03198                      FT_ULong  charcode )
03199   {
03200     FT_UInt  result = 0;
03201 
03202 
03203     if ( face && face->charmap )
03204     {
03205       FT_CMap  cmap = FT_CMAP( face->charmap );
03206 
03207 
03208       if ( charcode > 0xFFFFFFFFUL )
03209       {
03210         FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03211         FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03212       }
03213       result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
03214     }
03215     return result;
03216   }
03217 
03218 
03219   /* documentation is in freetype.h */
03220 
03221   FT_EXPORT_DEF( FT_ULong )
03222   FT_Get_First_Char( FT_Face   face,
03223                      FT_UInt  *agindex )
03224   {
03225     FT_ULong  result = 0;
03226     FT_UInt   gindex = 0;
03227 
03228 
03229     if ( face && face->charmap && face->num_glyphs )
03230     {
03231       gindex = FT_Get_Char_Index( face, 0 );
03232       if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
03233         result = FT_Get_Next_Char( face, 0, &gindex );
03234     }
03235 
03236     if ( agindex )
03237       *agindex = gindex;
03238 
03239     return result;
03240   }
03241 
03242 
03243   /* documentation is in freetype.h */
03244 
03245   FT_EXPORT_DEF( FT_ULong )
03246   FT_Get_Next_Char( FT_Face   face,
03247                     FT_ULong  charcode,
03248                     FT_UInt  *agindex )
03249   {
03250     FT_ULong  result = 0;
03251     FT_UInt   gindex = 0;
03252 
03253 
03254     if ( face && face->charmap && face->num_glyphs )
03255     {
03256       FT_UInt32  code = (FT_UInt32)charcode;
03257       FT_CMap    cmap = FT_CMAP( face->charmap );
03258 
03259 
03260       do {
03261         gindex = cmap->clazz->char_next( cmap, &code );
03262       } while ( gindex >= (FT_UInt)face->num_glyphs );
03263 
03264       result = ( gindex == 0 ) ? 0 : code;
03265     }
03266 
03267     if ( agindex )
03268       *agindex = gindex;
03269 
03270     return result;
03271   }
03272 
03273 
03274   /* documentation is in freetype.h */
03275 
03276   FT_EXPORT_DEF( FT_UInt )
03277   FT_Face_GetCharVariantIndex( FT_Face   face,
03278                                FT_ULong  charcode,
03279                                FT_ULong  variantSelector )
03280   {
03281     FT_UInt  result = 0;
03282 
03283 
03284     if ( face && face->charmap &&
03285         face->charmap->encoding == FT_ENCODING_UNICODE )
03286     {
03287       FT_CharMap  charmap = find_variant_selector_charmap( face );
03288       FT_CMap     ucmap = FT_CMAP( face->charmap );
03289 
03290 
03291       if ( charmap != NULL )
03292       {
03293         FT_CMap  vcmap = FT_CMAP( charmap );
03294 
03295 
03296         if ( charcode > 0xFFFFFFFFUL )
03297         {
03298           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03299           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03300         }
03301         if ( variantSelector > 0xFFFFFFFFUL )
03302         {
03303           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03304           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03305         }
03306 
03307         result = vcmap->clazz->char_var_index( vcmap, ucmap,
03308                                                (FT_UInt32)charcode,
03309                                                (FT_UInt32)variantSelector );
03310       }
03311     }
03312 
03313     return result;
03314   }
03315 
03316 
03317   /* documentation is in freetype.h */
03318 
03319   FT_EXPORT_DEF( FT_Int )
03320   FT_Face_GetCharVariantIsDefault( FT_Face   face,
03321                                    FT_ULong  charcode,
03322                                    FT_ULong  variantSelector )
03323   {
03324     FT_Int  result = -1;
03325 
03326 
03327     if ( face )
03328     {
03329       FT_CharMap  charmap = find_variant_selector_charmap( face );
03330 
03331 
03332       if ( charmap != NULL )
03333       {
03334         FT_CMap  vcmap = FT_CMAP( charmap );
03335 
03336 
03337         if ( charcode > 0xFFFFFFFFUL )
03338         {
03339           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03340           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03341         }
03342         if ( variantSelector > 0xFFFFFFFFUL )
03343         {
03344           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03345           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03346         }
03347 
03348         result = vcmap->clazz->char_var_default( vcmap,
03349                                                  (FT_UInt32)charcode,
03350                                                  (FT_UInt32)variantSelector );
03351       }
03352     }
03353 
03354     return result;
03355   }
03356 
03357 
03358   /* documentation is in freetype.h */
03359 
03360   FT_EXPORT_DEF( FT_UInt32* )
03361   FT_Face_GetVariantSelectors( FT_Face  face )
03362   {
03363     FT_UInt32  *result = NULL;
03364 
03365 
03366     if ( face )
03367     {
03368       FT_CharMap  charmap = find_variant_selector_charmap( face );
03369 
03370 
03371       if ( charmap != NULL )
03372       {
03373         FT_CMap    vcmap  = FT_CMAP( charmap );
03374         FT_Memory  memory = FT_FACE_MEMORY( face );
03375 
03376 
03377         result = vcmap->clazz->variant_list( vcmap, memory );
03378       }
03379     }
03380 
03381     return result;
03382   }
03383 
03384 
03385   /* documentation is in freetype.h */
03386 
03387   FT_EXPORT_DEF( FT_UInt32* )
03388   FT_Face_GetVariantsOfChar( FT_Face   face,
03389                              FT_ULong  charcode )
03390   {
03391     FT_UInt32  *result = NULL;
03392 
03393 
03394     if ( face )
03395     {
03396       FT_CharMap  charmap = find_variant_selector_charmap( face );
03397 
03398 
03399       if ( charmap != NULL )
03400       {
03401         FT_CMap    vcmap  = FT_CMAP( charmap );
03402         FT_Memory  memory = FT_FACE_MEMORY( face );
03403 
03404 
03405         if ( charcode > 0xFFFFFFFFUL )
03406         {
03407           FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
03408           FT_TRACE1(( " 0x%x is truncated\n", charcode ));
03409         }
03410 
03411         result = vcmap->clazz->charvariant_list( vcmap, memory,
03412                                                  (FT_UInt32)charcode );
03413       }
03414     }
03415     return result;
03416   }
03417 
03418 
03419   /* documentation is in freetype.h */
03420 
03421   FT_EXPORT_DEF( FT_UInt32* )
03422   FT_Face_GetCharsOfVariant( FT_Face   face,
03423                              FT_ULong  variantSelector )
03424   {
03425     FT_UInt32  *result = NULL;
03426 
03427 
03428     if ( face )
03429     {
03430       FT_CharMap  charmap = find_variant_selector_charmap( face );
03431 
03432 
03433       if ( charmap != NULL )
03434       {
03435         FT_CMap    vcmap  = FT_CMAP( charmap );
03436         FT_Memory  memory = FT_FACE_MEMORY( face );
03437 
03438 
03439         if ( variantSelector > 0xFFFFFFFFUL )
03440         {
03441           FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
03442           FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
03443         }
03444 
03445         result = vcmap->clazz->variantchar_list( vcmap, memory,
03446                                                  (FT_UInt32)variantSelector );
03447       }
03448     }
03449 
03450     return result;
03451   }
03452 
03453 
03454   /* documentation is in freetype.h */
03455 
03456   FT_EXPORT_DEF( FT_UInt )
03457   FT_Get_Name_Index( FT_Face     face,
03458                      FT_String*  glyph_name )
03459   {
03460     FT_UInt  result = 0;
03461 
03462 
03463     if ( face && FT_HAS_GLYPH_NAMES( face ) )
03464     {
03465       FT_Service_GlyphDict  service;
03466 
03467 
03468       FT_FACE_LOOKUP_SERVICE( face,
03469                               service,
03470                               GLYPH_DICT );
03471 
03472       if ( service && service->name_index )
03473         result = service->name_index( face, glyph_name );
03474     }
03475 
03476     return result;
03477   }
03478 
03479 
03480   /* documentation is in freetype.h */
03481 
03482   FT_EXPORT_DEF( FT_Error )
03483   FT_Get_Glyph_Name( FT_Face     face,
03484                      FT_UInt     glyph_index,
03485                      FT_Pointer  buffer,
03486                      FT_UInt     buffer_max )
03487   {
03488     FT_Error  error = FT_Err_Invalid_Argument;
03489 
03490 
03491     /* clean up buffer */
03492     if ( buffer && buffer_max > 0 )
03493       ((FT_Byte*)buffer)[0] = 0;
03494 
03495     if ( face                                     &&
03496          (FT_Long)glyph_index <= face->num_glyphs &&
03497          FT_HAS_GLYPH_NAMES( face )               )
03498     {
03499       FT_Service_GlyphDict  service;
03500 
03501 
03502       FT_FACE_LOOKUP_SERVICE( face,
03503                               service,
03504                               GLYPH_DICT );
03505 
03506       if ( service && service->get_name )
03507         error = service->get_name( face, glyph_index, buffer, buffer_max );
03508     }
03509 
03510     return error;
03511   }
03512 
03513 
03514   /* documentation is in freetype.h */
03515 
03516   FT_EXPORT_DEF( const char* )
03517   FT_Get_Postscript_Name( FT_Face  face )
03518   {
03519     const char*  result = NULL;
03520 
03521 
03522     if ( !face )
03523       goto Exit;
03524 
03525     if ( !result )
03526     {
03527       FT_Service_PsFontName  service;
03528 
03529 
03530       FT_FACE_LOOKUP_SERVICE( face,
03531                               service,
03532                               POSTSCRIPT_FONT_NAME );
03533 
03534       if ( service && service->get_ps_font_name )
03535         result = service->get_ps_font_name( face );
03536     }
03537 
03538   Exit:
03539     return result;
03540   }
03541 
03542 
03543   /* documentation is in tttables.h */
03544 
03545   FT_EXPORT_DEF( void* )
03546   FT_Get_Sfnt_Table( FT_Face      face,
03547                      FT_Sfnt_Tag  tag )
03548   {
03549     void*                  table = 0;
03550     FT_Service_SFNT_Table  service;
03551 
03552 
03553     if ( face && FT_IS_SFNT( face ) )
03554     {
03555       FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03556       if ( service != NULL )
03557         table = service->get_table( face, tag );
03558     }
03559 
03560     return table;
03561   }
03562 
03563 
03564   /* documentation is in tttables.h */
03565 
03566   FT_EXPORT_DEF( FT_Error )
03567   FT_Load_Sfnt_Table( FT_Face    face,
03568                       FT_ULong   tag,
03569                       FT_Long    offset,
03570                       FT_Byte*   buffer,
03571                       FT_ULong*  length )
03572   {
03573     FT_Service_SFNT_Table  service;
03574 
03575 
03576     if ( !face || !FT_IS_SFNT( face ) )
03577       return FT_Err_Invalid_Face_Handle;
03578 
03579     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03580     if ( service == NULL )
03581       return FT_Err_Unimplemented_Feature;
03582 
03583     return service->load_table( face, tag, offset, buffer, length );
03584   }
03585 
03586 
03587   /* documentation is in tttables.h */
03588 
03589   FT_EXPORT_DEF( FT_Error )
03590   FT_Sfnt_Table_Info( FT_Face    face,
03591                       FT_UInt    table_index,
03592                       FT_ULong  *tag,
03593                       FT_ULong  *length )
03594   {
03595     FT_Service_SFNT_Table  service;
03596     FT_ULong               offset;
03597 
03598 
03599     if ( !face || !FT_IS_SFNT( face ) )
03600       return FT_Err_Invalid_Face_Handle;
03601 
03602     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
03603     if ( service == NULL )
03604       return FT_Err_Unimplemented_Feature;
03605 
03606     return service->table_info( face, table_index, tag, &offset, length );
03607   }
03608 
03609 
03610   /* documentation is in tttables.h */
03611 
03612   FT_EXPORT_DEF( FT_ULong )
03613   FT_Get_CMap_Language_ID( FT_CharMap  charmap )
03614   {
03615     FT_Service_TTCMaps  service;
03616     FT_Face             face;
03617     TT_CMapInfo         cmap_info;
03618 
03619 
03620     if ( !charmap || !charmap->face )
03621       return 0;
03622 
03623     face = charmap->face;
03624     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
03625     if ( service == NULL )
03626       return 0;
03627     if ( service->get_cmap_info( charmap, &cmap_info ))
03628       return 0;
03629 
03630     return cmap_info.language;
03631   }
03632 
03633 
03634   /* documentation is in tttables.h */
03635 
03636   FT_EXPORT_DEF( FT_Long )
03637   FT_Get_CMap_Format( FT_CharMap  charmap )
03638   {
03639     FT_Service_TTCMaps  service;
03640     FT_Face             face;
03641     TT_CMapInfo         cmap_info;
03642 
03643 
03644     if ( !charmap || !charmap->face )
03645       return -1;
03646 
03647     face = charmap->face;
03648     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
03649     if ( service == NULL )
03650       return -1;
03651     if ( service->get_cmap_info( charmap, &cmap_info ))
03652       return -1;
03653 
03654     return cmap_info.format;
03655   }
03656 
03657 
03658   /* documentation is in ftsizes.h */
03659 
03660   FT_EXPORT_DEF( FT_Error )
03661   FT_Activate_Size( FT_Size  size )
03662   {
03663     FT_Face  face;
03664 
03665 
03666     if ( size == NULL )
03667       return FT_Err_Invalid_Argument;
03668 
03669     face = size->face;
03670     if ( face == NULL || face->driver == NULL )
03671       return FT_Err_Invalid_Argument;
03672 
03673     /* we don't need anything more complex than that; all size objects */
03674     /* are already listed by the face                                  */
03675     face->size = size;
03676 
03677     return FT_Err_Ok;
03678   }
03679 
03680 
03681   /*************************************************************************/
03682   /*************************************************************************/
03683   /*************************************************************************/
03684   /****                                                                 ****/
03685   /****                                                                 ****/
03686   /****                        R E N D E R E R S                        ****/
03687   /****                                                                 ****/
03688   /****                                                                 ****/
03689   /*************************************************************************/
03690   /*************************************************************************/
03691   /*************************************************************************/
03692 
03693   /* lookup a renderer by glyph format in the library's list */
03694   FT_BASE_DEF( FT_Renderer )
03695   FT_Lookup_Renderer( FT_Library       library,
03696                       FT_Glyph_Format  format,
03697                       FT_ListNode*     node )
03698   {
03699     FT_ListNode  cur;
03700     FT_Renderer  result = 0;
03701 
03702 
03703     if ( !library )
03704       goto Exit;
03705 
03706     cur = library->renderers.head;
03707 
03708     if ( node )
03709     {
03710       if ( *node )
03711         cur = (*node)->next;
03712       *node = 0;
03713     }
03714 
03715     while ( cur )
03716     {
03717       FT_Renderer  renderer = FT_RENDERER( cur->data );
03718 
03719 
03720       if ( renderer->glyph_format == format )
03721       {
03722         if ( node )
03723           *node = cur;
03724 
03725         result = renderer;
03726         break;
03727       }
03728       cur = cur->next;
03729     }
03730 
03731   Exit:
03732     return result;
03733   }
03734 
03735 
03736   static FT_Renderer
03737   ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
03738   {
03739     FT_Face      face    = slot->face;
03740     FT_Library   library = FT_FACE_LIBRARY( face );
03741     FT_Renderer  result  = library->cur_renderer;
03742 
03743 
03744     if ( !result || result->glyph_format != slot->format )
03745       result = FT_Lookup_Renderer( library, slot->format, 0 );
03746 
03747     return result;
03748   }
03749 
03750 
03751   static void
03752   ft_set_current_renderer( FT_Library  library )
03753   {
03754     FT_Renderer  renderer;
03755 
03756 
03757     renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
03758     library->cur_renderer = renderer;
03759   }
03760 
03761 
03762   static FT_Error
03763   ft_add_renderer( FT_Module  module )
03764   {
03765     FT_Library   library = module->library;
03766     FT_Memory    memory  = library->memory;
03767     FT_Error     error;
03768     FT_ListNode  node    = NULL;
03769 
03770 
03771     if ( FT_NEW( node ) )
03772       goto Exit;
03773 
03774     {
03775       FT_Renderer         render = FT_RENDERER( module );
03776       FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
03777 
03778 
03779       render->clazz        = clazz;
03780       render->glyph_format = clazz->glyph_format;
03781 
03782       /* allocate raster object if needed */
03783       if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
03784            clazz->raster_class->raster_new                )
03785       {
03786         error = clazz->raster_class->raster_new( memory, &render->raster );
03787         if ( error )
03788           goto Fail;
03789 
03790         render->raster_render = clazz->raster_class->raster_render;
03791         render->render        = clazz->render_glyph;
03792       }
03793 
03794       /* add to list */
03795       node->data = module;
03796       FT_List_Add( &library->renderers, node );
03797 
03798       ft_set_current_renderer( library );
03799     }
03800 
03801   Fail:
03802     if ( error )
03803       FT_FREE( node );
03804 
03805   Exit:
03806     return error;
03807   }
03808 
03809 
03810   static void
03811   ft_remove_renderer( FT_Module  module )
03812   {
03813     FT_Library   library = module->library;
03814     FT_Memory    memory  = library->memory;
03815     FT_ListNode  node;
03816 
03817 
03818     node = FT_List_Find( &library->renderers, module );
03819     if ( node )
03820     {
03821       FT_Renderer  render = FT_RENDERER( module );
03822 
03823 
03824       /* release raster object, if any */
03825       if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
03826            render->raster                                         )
03827         render->clazz->raster_class->raster_done( render->raster );
03828 
03829       /* remove from list */
03830       FT_List_Remove( &library->renderers, node );
03831       FT_FREE( node );
03832 
03833       ft_set_current_renderer( library );
03834     }
03835   }
03836 
03837 
03838   /* documentation is in ftrender.h */
03839 
03840   FT_EXPORT_DEF( FT_Renderer )
03841   FT_Get_Renderer( FT_Library       library,
03842                    FT_Glyph_Format  format )
03843   {
03844     /* test for valid `library' delayed to FT_Lookup_Renderer() */
03845 
03846     return FT_Lookup_Renderer( library, format, 0 );
03847   }
03848 
03849 
03850   /* documentation is in ftrender.h */
03851 
03852   FT_EXPORT_DEF( FT_Error )
03853   FT_Set_Renderer( FT_Library     library,
03854                    FT_Renderer    renderer,
03855                    FT_UInt        num_params,
03856                    FT_Parameter*  parameters )
03857   {
03858     FT_ListNode  node;
03859     FT_Error     error = FT_Err_Ok;
03860 
03861 
03862     if ( !library )
03863       return FT_Err_Invalid_Library_Handle;
03864 
03865     if ( !renderer )
03866       return FT_Err_Invalid_Argument;
03867 
03868     node = FT_List_Find( &library->renderers, renderer );
03869     if ( !node )
03870     {
03871       error = FT_Err_Invalid_Argument;
03872       goto Exit;
03873     }
03874 
03875     FT_List_Up( &library->renderers, node );
03876 
03877     if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
03878       library->cur_renderer = renderer;
03879 
03880     if ( num_params > 0 )
03881     {
03882       FT_Renderer_SetModeFunc  set_mode = renderer->clazz->set_mode;
03883 
03884 
03885       for ( ; num_params > 0; num_params-- )
03886       {
03887         error = set_mode( renderer, parameters->tag, parameters->data );
03888         if ( error )
03889           break;
03890       }
03891     }
03892 
03893   Exit:
03894     return error;
03895   }
03896 
03897 
03898   FT_BASE_DEF( FT_Error )
03899   FT_Render_Glyph_Internal( FT_Library      library,
03900                             FT_GlyphSlot    slot,
03901                             FT_Render_Mode  render_mode )
03902   {
03903     FT_Error     error = FT_Err_Ok;
03904     FT_Renderer  renderer;
03905 
03906 
03907     /* if it is already a bitmap, no need to do anything */
03908     switch ( slot->format )
03909     {
03910     case FT_GLYPH_FORMAT_BITMAP:   /* already a bitmap, don't do anything */
03911       break;
03912 
03913     default:
03914       {
03915         FT_ListNode  node   = 0;
03916         FT_Bool      update = 0;
03917 
03918 
03919         /* small shortcut for the very common case */
03920         if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
03921         {
03922           renderer = library->cur_renderer;
03923           node     = library->renderers.head;
03924         }
03925         else
03926           renderer = FT_Lookup_Renderer( library, slot->format, &node );
03927 
03928         error = FT_Err_Unimplemented_Feature;
03929         while ( renderer )
03930         {
03931           error = renderer->render( renderer, slot, render_mode, NULL );
03932           if ( !error                                               ||
03933                FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
03934             break;
03935 
03936           /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
03937           /* is unsupported by the current renderer for this glyph image */
03938           /* format.                                                     */
03939 
03940           /* now, look for another renderer that supports the same */
03941           /* format.                                               */
03942           renderer = FT_Lookup_Renderer( library, slot->format, &node );
03943           update   = 1;
03944         }
03945 
03946         /* if we changed the current renderer for the glyph image format */
03947         /* we need to select it as the next current one                  */
03948         if ( !error && update && renderer )
03949           FT_Set_Renderer( library, renderer, 0, 0 );
03950       }
03951     }
03952 
03953     return error;
03954   }
03955 
03956 
03957   /* documentation is in freetype.h */
03958 
03959   FT_EXPORT_DEF( FT_Error )
03960   FT_Render_Glyph( FT_GlyphSlot    slot,
03961                    FT_Render_Mode  render_mode )
03962   {
03963     FT_Library  library;
03964 
03965 
03966     if ( !slot || !slot->face )
03967       return FT_Err_Invalid_Argument;
03968 
03969     library = FT_FACE_LIBRARY( slot->face );
03970 
03971     return FT_Render_Glyph_Internal( library, slot, render_mode );
03972   }
03973 
03974 
03975   /*************************************************************************/
03976   /*************************************************************************/
03977   /*************************************************************************/
03978   /****                                                                 ****/
03979   /****                                                                 ****/
03980   /****                         M O D U L E S                           ****/
03981   /****                                                                 ****/
03982   /****                                                                 ****/
03983   /*************************************************************************/
03984   /*************************************************************************/
03985   /*************************************************************************/
03986 
03987 
03988   /*************************************************************************/
03989   /*                                                                       */
03990   /* <Function>                                                            */
03991   /*    Destroy_Module                                                     */
03992   /*                                                                       */
03993   /* <Description>                                                         */
03994   /*    Destroys a given module object.  For drivers, this also destroys   */
03995   /*    all child faces.                                                   */
03996   /*                                                                       */
03997   /* <InOut>                                                               */
03998   /*     module :: A handle to the target driver object.                   */
03999   /*                                                                       */
04000   /* <Note>                                                                */
04001   /*     The driver _must_ be LOCKED!                                      */
04002   /*                                                                       */
04003   static void
04004   Destroy_Module( FT_Module  module )
04005   {
04006     FT_Memory         memory  = module->memory;
04007     FT_Module_Class*  clazz   = module->clazz;
04008     FT_Library        library = module->library;
04009 
04010 
04011     /* finalize client-data - before anything else */
04012     if ( module->generic.finalizer )
04013       module->generic.finalizer( module );
04014 
04015     if ( library && library->auto_hinter == module )
04016       library->auto_hinter = 0;
04017 
04018     /* if the module is a renderer */
04019     if ( FT_MODULE_IS_RENDERER( module ) )
04020       ft_remove_renderer( module );
04021 
04022     /* if the module is a font driver, add some steps */
04023     if ( FT_MODULE_IS_DRIVER( module ) )
04024       Destroy_Driver( FT_DRIVER( module ) );
04025 
04026     /* finalize the module object */
04027     if ( clazz->module_done )
04028       clazz->module_done( module );
04029 
04030     /* discard it */
04031     FT_FREE( module );
04032   }
04033 
04034 
04035   /* documentation is in ftmodapi.h */
04036 
04037   FT_EXPORT_DEF( FT_Error )
04038   FT_Add_Module( FT_Library              library,
04039                  const FT_Module_Class*  clazz )
04040   {
04041     FT_Error   error;
04042     FT_Memory  memory;
04043     FT_Module  module;
04044     FT_UInt    nn;
04045 
04046 
04047 #define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
04048                                 FREETYPE_MINOR                  )
04049 
04050     if ( !library )
04051       return FT_Err_Invalid_Library_Handle;
04052 
04053     if ( !clazz )
04054       return FT_Err_Invalid_Argument;
04055 
04056     /* check freetype version */
04057     if ( clazz->module_requires > FREETYPE_VER_FIXED )
04058       return FT_Err_Invalid_Version;
04059 
04060     /* look for a module with the same name in the library's table */
04061     for ( nn = 0; nn < library->num_modules; nn++ )
04062     {
04063       module = library->modules[nn];
04064       if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
04065       {
04066         /* this installed module has the same name, compare their versions */
04067         if ( clazz->module_version <= module->clazz->module_version )
04068           return FT_Err_Lower_Module_Version;
04069 
04070         /* remove the module from our list, then exit the loop to replace */
04071         /* it by our new version..                                        */
04072         FT_Remove_Module( library, module );
04073         break;
04074       }
04075     }
04076 
04077     memory = library->memory;
04078     error  = FT_Err_Ok;
04079 
04080     if ( library->num_modules >= FT_MAX_MODULES )
04081     {
04082       error = FT_Err_Too_Many_Drivers;
04083       goto Exit;
04084     }
04085 
04086     /* allocate module object */
04087     if ( FT_ALLOC( module, clazz->module_size ) )
04088       goto Exit;
04089 
04090     /* base initialization */
04091     module->library = library;
04092     module->memory  = memory;
04093     module->clazz   = (FT_Module_Class*)clazz;
04094 
04095     /* check whether the module is a renderer - this must be performed */
04096     /* before the normal module initialization                         */
04097     if ( FT_MODULE_IS_RENDERER( module ) )
04098     {
04099       /* add to the renderers list */
04100       error = ft_add_renderer( module );
04101       if ( error )
04102         goto Fail;
04103     }
04104 
04105     /* is the module a auto-hinter? */
04106     if ( FT_MODULE_IS_HINTER( module ) )
04107       library->auto_hinter = module;
04108 
04109     /* if the module is a font driver */
04110     if ( FT_MODULE_IS_DRIVER( module ) )
04111     {
04112       /* allocate glyph loader if needed */
04113       FT_Driver  driver = FT_DRIVER( module );
04114 
04115 
04116       driver->clazz = (FT_Driver_Class)module->clazz;
04117       if ( FT_DRIVER_USES_OUTLINES( driver ) )
04118       {
04119         error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
04120         if ( error )
04121           goto Fail;
04122       }
04123     }
04124 
04125     if ( clazz->module_init )
04126     {
04127       error = clazz->module_init( module );
04128       if ( error )
04129         goto Fail;
04130     }
04131 
04132     /* add module to the library's table */
04133     library->modules[library->num_modules++] = module;
04134 
04135   Exit:
04136     return error;
04137 
04138   Fail:
04139     if ( FT_MODULE_IS_DRIVER( module ) )
04140     {
04141       FT_Driver  driver = FT_DRIVER( module );
04142 
04143 
04144       if ( FT_DRIVER_USES_OUTLINES( driver ) )
04145         FT_GlyphLoader_Done( driver->glyph_loader );
04146     }
04147 
04148     if ( FT_MODULE_IS_RENDERER( module ) )
04149     {
04150       FT_Renderer  renderer = FT_RENDERER( module );
04151 
04152 
04153       if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 
04154            renderer->raster                                         )
04155         renderer->clazz->raster_class->raster_done( renderer->raster );
04156     }
04157 
04158     FT_FREE( module );
04159     goto Exit;
04160   }
04161 
04162 
04163   /* documentation is in ftmodapi.h */
04164 
04165   FT_EXPORT_DEF( FT_Module )
04166   FT_Get_Module( FT_Library   library,
04167                  const char*  module_name )
04168   {
04169     FT_Module   result = 0;
04170     FT_Module*  cur;
04171     FT_Module*  limit;
04172 
04173 
04174     if ( !library || !module_name )
04175       return result;
04176 
04177     cur   = library->modules;
04178     limit = cur + library->num_modules;
04179 
04180     for ( ; cur < limit; cur++ )
04181       if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
04182       {
04183         result = cur[0];
04184         break;
04185       }
04186 
04187     return result;
04188   }
04189 
04190 
04191   /* documentation is in ftobjs.h */
04192 
04193   FT_BASE_DEF( const void* )
04194   FT_Get_Module_Interface( FT_Library   library,
04195                            const char*  mod_name )
04196   {
04197     FT_Module  module;
04198 
04199 
04200     /* test for valid `library' delayed to FT_Get_Module() */
04201 
04202     module = FT_Get_Module( library, mod_name );
04203 
04204     return module ? module->clazz->module_interface : 0;
04205   }
04206 
04207 
04208   FT_BASE_DEF( FT_Pointer )
04209   ft_module_get_service( FT_Module    module,
04210                          const char*  service_id )
04211   {
04212     FT_Pointer  result = NULL;
04213 
04214     if ( module )
04215     {
04216       FT_ASSERT( module->clazz && module->clazz->get_interface );
04217 
04218      /* first, look for the service in the module
04219       */
04220       if ( module->clazz->get_interface )
04221         result = module->clazz->get_interface( module, service_id );
04222 
04223       if ( result == NULL )
04224       {
04225        /* we didn't find it, look in all other modules then
04226         */
04227         FT_Library  library = module->library;
04228         FT_Module*  cur     = library->modules;
04229         FT_Module*  limit   = cur + library->num_modules;
04230 
04231         for ( ; cur < limit; cur++ )
04232         {
04233           if ( cur[0] != module )
04234           {
04235             FT_ASSERT( cur[0]->clazz );
04236 
04237             if ( cur[0]->clazz->get_interface )
04238             {
04239               result = cur[0]->clazz->get_interface( cur[0], service_id );
04240               if ( result != NULL )
04241                 break;
04242             }
04243           }
04244         }
04245       }
04246     }
04247 
04248     return result;
04249   }
04250 
04251 
04252   /* documentation is in ftmodapi.h */
04253 
04254   FT_EXPORT_DEF( FT_Error )
04255   FT_Remove_Module( FT_Library  library,
04256                     FT_Module   module )
04257   {
04258     /* try to find the module from the table, then remove it from there */
04259 
04260     if ( !library )
04261       return FT_Err_Invalid_Library_Handle;
04262 
04263     if ( module )
04264     {
04265       FT_Module*  cur   = library->modules;
04266       FT_Module*  limit = cur + library->num_modules;
04267 
04268 
04269       for ( ; cur < limit; cur++ )
04270       {
04271         if ( cur[0] == module )
04272         {
04273           /* remove it from the table */
04274           library->num_modules--;
04275           limit--;
04276           while ( cur < limit )
04277           {
04278             cur[0] = cur[1];
04279             cur++;
04280           }
04281           limit[0] = 0;
04282 
04283           /* destroy the module */
04284           Destroy_Module( module );
04285 
04286           return FT_Err_Ok;
04287         }
04288       }
04289     }
04290     return FT_Err_Invalid_Driver_Handle;
04291   }
04292 
04293 
04294   /*************************************************************************/
04295   /*************************************************************************/
04296   /*************************************************************************/
04297   /****                                                                 ****/
04298   /****                                                                 ****/
04299   /****                         L I B R A R Y                           ****/
04300   /****                                                                 ****/
04301   /****                                                                 ****/
04302   /*************************************************************************/
04303   /*************************************************************************/
04304   /*************************************************************************/
04305 
04306 
04307   /* documentation is in ftmodapi.h */
04308 
04309   FT_EXPORT_DEF( FT_Error )
04310   FT_Reference_Library( FT_Library  library )
04311   {
04312     library->refcount++;
04313 
04314     return FT_Err_Ok;
04315   }
04316 
04317 
04318   /* documentation is in ftmodapi.h */
04319 
04320   FT_EXPORT_DEF( FT_Error )
04321   FT_New_Library( FT_Memory    memory,
04322                   FT_Library  *alibrary )
04323   {
04324     FT_Library  library = NULL;
04325     FT_Error    error;
04326 
04327 
04328     if ( !memory )
04329       return FT_Err_Invalid_Argument;
04330 
04331 #ifdef FT_DEBUG_LEVEL_ERROR
04332     /* init debugging support */
04333     ft_debug_init();
04334 #endif
04335 
04336     /* first of all, allocate the library object */
04337     if ( FT_NEW( library ) )
04338       return error;
04339 
04340     library->memory = memory;
04341 
04342 #ifdef FT_CONFIG_OPTION_PIC
04343     /* initialize position independent code containers */
04344     error = ft_pic_container_init( library );
04345     if ( error )
04346       goto Fail;
04347 #endif
04348 
04349     /* allocate the render pool */
04350     library->raster_pool_size = FT_RENDER_POOL_SIZE;
04351 #if FT_RENDER_POOL_SIZE > 0
04352     if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
04353       goto Fail;
04354 #endif
04355 
04356     library->version_major = FREETYPE_MAJOR;
04357     library->version_minor = FREETYPE_MINOR;
04358     library->version_patch = FREETYPE_PATCH;
04359 
04360     library->refcount = 1;
04361 
04362     /* That's ok now */
04363     *alibrary = library;
04364 
04365     return FT_Err_Ok;
04366 
04367   Fail:
04368 #ifdef FT_CONFIG_OPTION_PIC
04369     ft_pic_container_destroy( library );
04370 #endif
04371     FT_FREE( library );
04372     return error;
04373   }
04374 
04375 
04376   /* documentation is in freetype.h */
04377 
04378   FT_EXPORT_DEF( void )
04379   FT_Library_Version( FT_Library   library,
04380                       FT_Int      *amajor,
04381                       FT_Int      *aminor,
04382                       FT_Int      *apatch )
04383   {
04384     FT_Int  major = 0;
04385     FT_Int  minor = 0;
04386     FT_Int  patch = 0;
04387 
04388 
04389     if ( library )
04390     {
04391       major = library->version_major;
04392       minor = library->version_minor;
04393       patch = library->version_patch;
04394     }
04395 
04396     if ( amajor )
04397       *amajor = major;
04398 
04399     if ( aminor )
04400       *aminor = minor;
04401 
04402     if ( apatch )
04403       *apatch = patch;
04404   }
04405 
04406 
04407   /* documentation is in ftmodapi.h */
04408 
04409   FT_EXPORT_DEF( FT_Error )
04410   FT_Done_Library( FT_Library  library )
04411   {
04412     FT_Memory  memory;
04413 
04414 
04415     if ( !library )
04416       return FT_Err_Invalid_Library_Handle;
04417 
04418     library->refcount--;
04419     if ( library->refcount > 0 )
04420       goto Exit;
04421 
04422     memory = library->memory;
04423 
04424     /* Discard client-data */
04425     if ( library->generic.finalizer )
04426       library->generic.finalizer( library );
04427 
04428     /*
04429      * Close all faces in the library.  If we don't do this, we can have
04430      * some subtle memory leaks.
04431      *
04432      * Example:
04433      *
04434      *  - the cff font driver uses the pshinter module in cff_size_done
04435      *  - if the pshinter module is destroyed before the cff font driver,
04436      *    opened FT_Face objects managed by the driver are not properly
04437      *    destroyed, resulting in a memory leak
04438      *
04439      * Some faces are dependent on other faces, like Type42 faces that
04440      * depend on TrueType faces synthesized internally.
04441      *
04442      * The order of drivers should be specified in driver_name[].
04443      */
04444     {
04445       FT_UInt      m, n;
04446       const char*  driver_name[] = { "type42", NULL };
04447 
04448 
04449       for ( m = 0;
04450             m < sizeof ( driver_name ) / sizeof ( driver_name[0] );
04451             m++ )
04452       {
04453         for ( n = 0; n < library->num_modules; n++ )
04454         {
04455           FT_Module    module      = library->modules[n];
04456           const char*  module_name = module->clazz->module_name;
04457           FT_List      faces;
04458 
04459 
04460           if ( driver_name[m]                                &&
04461                ft_strcmp( module_name, driver_name[m] ) != 0 )
04462             continue;
04463 
04464           if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
04465             continue;
04466 
04467           FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name ));
04468 
04469           faces = &FT_DRIVER( module )->faces_list;
04470           while ( faces->head )
04471           {
04472             FT_Done_Face( FT_FACE( faces->head->data ) );
04473             if ( faces->head )
04474               FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
04475           }
04476         }
04477       }
04478     }
04479 
04480     /* Close all other modules in the library */
04481 #if 1
04482     /* XXX Modules are removed in the reversed order so that  */
04483     /* type42 module is removed before truetype module.  This */
04484     /* avoids double free in some occasions.  It is a hack.   */
04485     while ( library->num_modules > 0 )
04486       FT_Remove_Module( library,
04487                         library->modules[library->num_modules - 1] );
04488 #else
04489     {
04490       FT_UInt  n;
04491 
04492 
04493       for ( n = 0; n < library->num_modules; n++ )
04494       {
04495         FT_Module  module = library->modules[n];
04496 
04497 
04498         if ( module )
04499         {
04500           Destroy_Module( module );
04501           library->modules[n] = 0;
04502         }
04503       }
04504     }
04505 #endif
04506 
04507     /* Destroy raster objects */
04508     FT_FREE( library->raster_pool );
04509     library->raster_pool_size = 0;
04510 
04511 #ifdef FT_CONFIG_OPTION_PIC
04512     /* Destroy pic container contents */
04513     ft_pic_container_destroy( library );
04514 #endif
04515 
04516     FT_FREE( library );
04517 
04518   Exit:
04519     return FT_Err_Ok;
04520   }
04521 
04522 
04523   /* documentation is in ftmodapi.h */
04524 
04525   FT_EXPORT_DEF( void )
04526   FT_Set_Debug_Hook( FT_Library         library,
04527                      FT_UInt            hook_index,
04528                      FT_DebugHook_Func  debug_hook )
04529   {
04530     if ( library && debug_hook &&
04531          hook_index <
04532            ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
04533       library->debug_hooks[hook_index] = debug_hook;
04534   }
04535 
04536 
04537   /* documentation is in ftmodapi.h */
04538 
04539   FT_EXPORT_DEF( FT_TrueTypeEngineType )
04540   FT_Get_TrueType_Engine_Type( FT_Library  library )
04541   {
04542     FT_TrueTypeEngineType  result = FT_TRUETYPE_ENGINE_TYPE_NONE;
04543 
04544 
04545     if ( library )
04546     {
04547       FT_Module  module = FT_Get_Module( library, "truetype" );
04548 
04549 
04550       if ( module )
04551       {
04552         FT_Service_TrueTypeEngine  service;
04553 
04554 
04555         service = (FT_Service_TrueTypeEngine)
04556                     ft_module_get_service( module,
04557                                            FT_SERVICE_ID_TRUETYPE_ENGINE );
04558         if ( service )
04559           result = service->engine_type;
04560       }
04561     }
04562 
04563     return result;
04564   }
04565 
04566 
04567 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
04568 
04569   FT_BASE_DEF( FT_Error )
04570   ft_stub_set_char_sizes( FT_Size     size,
04571                           FT_F26Dot6  width,
04572                           FT_F26Dot6  height,
04573                           FT_UInt     horz_res,
04574                           FT_UInt     vert_res )
04575   {
04576     FT_Size_RequestRec  req;
04577     FT_Driver           driver = size->face->driver;
04578 
04579 
04580     if ( driver->clazz->request_size )
04581     {
04582       req.type   = FT_SIZE_REQUEST_TYPE_NOMINAL;
04583       req.width  = width;
04584       req.height = height;
04585 
04586       if ( horz_res == 0 )
04587         horz_res = vert_res;
04588 
04589       if ( vert_res == 0 )
04590         vert_res = horz_res;
04591 
04592       if ( horz_res == 0 )
04593         horz_res = vert_res = 72;
04594 
04595       req.horiResolution = horz_res;
04596       req.vertResolution = vert_res;
04597 
04598       return driver->clazz->request_size( size, &req );
04599     }
04600 
04601     return 0;
04602   }
04603 
04604 
04605   FT_BASE_DEF( FT_Error )
04606   ft_stub_set_pixel_sizes( FT_Size  size,
04607                            FT_UInt  width,
04608                            FT_UInt  height )
04609   {
04610     FT_Size_RequestRec  req;
04611     FT_Driver           driver = size->face->driver;
04612 
04613 
04614     if ( driver->clazz->request_size )
04615     {
04616       req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
04617       req.width          = width  << 6;
04618       req.height         = height << 6;
04619       req.horiResolution = 0;
04620       req.vertResolution = 0;
04621 
04622       return driver->clazz->request_size( size, &req );
04623     }
04624 
04625     return 0;
04626   }
04627 
04628 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
04629 
04630 
04631   /* documentation is in freetype.h */
04632 
04633   FT_EXPORT_DEF( FT_Error )
04634   FT_Get_SubGlyph_Info( FT_GlyphSlot  glyph,
04635                         FT_UInt       sub_index,
04636                         FT_Int       *p_index,
04637                         FT_UInt      *p_flags,
04638                         FT_Int       *p_arg1,
04639                         FT_Int       *p_arg2,
04640                         FT_Matrix    *p_transform )
04641   {
04642     FT_Error  error = FT_Err_Invalid_Argument;
04643 
04644 
04645     if ( glyph                                      &&
04646          glyph->subglyphs                           &&
04647          glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
04648          sub_index < glyph->num_subglyphs           )
04649     {
04650       FT_SubGlyph  subg = glyph->subglyphs + sub_index;
04651 
04652 
04653       *p_index     = subg->index;
04654       *p_flags     = subg->flags;
04655       *p_arg1      = subg->arg1;
04656       *p_arg2      = subg->arg2;
04657       *p_transform = subg->transform;
04658     }
04659 
04660     return error;
04661   }
04662 
04663 
04664 /* END */

Generated on Sat May 26 2012 04:32:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.