cffobjs.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  cffobjs.c                                                              */
00004 /*                                                                         */
00005 /*    OpenType objects manager (body).                                     */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_CALC_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_ERRORS_H
00024 #include FT_TRUETYPE_IDS_H
00025 #include FT_TRUETYPE_TAGS_H
00026 #include FT_INTERNAL_SFNT_H
00027 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
00028 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
00029 #include "cffobjs.h"
00030 #include "cffload.h"
00031 #include "cffcmap.h"
00032 #include "cfferrs.h"
00033 #include "cffpic.h"
00034 
00035 
00036   /*************************************************************************/
00037   /*                                                                       */
00038   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00039   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00040   /* messages during execution.                                            */
00041   /*                                                                       */
00042 #undef  FT_COMPONENT
00043 #define FT_COMPONENT  trace_cffobjs
00044 
00045 
00046   /*************************************************************************/
00047   /*                                                                       */
00048   /*                            SIZE FUNCTIONS                             */
00049   /*                                                                       */
00050   /*  Note that we store the global hints in the size's `internal' root    */
00051   /*  field.                                                               */
00052   /*                                                                       */
00053   /*************************************************************************/
00054 
00055 
00056   static PSH_Globals_Funcs
00057   cff_size_get_globals_funcs( CFF_Size  size )
00058   {
00059     CFF_Face          face     = (CFF_Face)size->root.face;
00060     CFF_Font          font     = (CFF_Font)face->extra.data;
00061     PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
00062     FT_Module         module;
00063 
00064 
00065     module = FT_Get_Module( size->root.face->driver->root.library,
00066                             "pshinter" );
00067     return ( module && pshinter && pshinter->get_globals_funcs )
00068            ? pshinter->get_globals_funcs( module )
00069            : 0;
00070   }
00071 
00072 
00073   FT_LOCAL_DEF( void )
00074   cff_size_done( FT_Size  cffsize )        /* CFF_Size */
00075   {
00076     CFF_Size      size     = (CFF_Size)cffsize;
00077     CFF_Face      face     = (CFF_Face)size->root.face;
00078     CFF_Font      font     = (CFF_Font)face->extra.data;
00079     CFF_Internal  internal = (CFF_Internal)cffsize->internal;
00080 
00081 
00082     if ( internal )
00083     {
00084       PSH_Globals_Funcs  funcs;
00085 
00086 
00087       funcs = cff_size_get_globals_funcs( size );
00088       if ( funcs )
00089       {
00090         FT_UInt  i;
00091 
00092 
00093         funcs->destroy( internal->topfont );
00094 
00095         for ( i = font->num_subfonts; i > 0; i-- )
00096           funcs->destroy( internal->subfonts[i - 1] );
00097       }
00098 
00099       /* `internal' is freed by destroy_size (in ftobjs.c) */
00100     }
00101   }
00102 
00103 
00104   /* CFF and Type 1 private dictionaries have slightly different      */
00105   /* structures; we need to synthesize a Type 1 dictionary on the fly */
00106 
00107   static void
00108   cff_make_private_dict( CFF_SubFont  subfont,
00109                          PS_Private   priv )
00110   {
00111     CFF_Private  cpriv = &subfont->private_dict;
00112     FT_UInt      n, count;
00113 
00114 
00115     FT_MEM_ZERO( priv, sizeof ( *priv ) );
00116 
00117     count = priv->num_blue_values = cpriv->num_blue_values;
00118     for ( n = 0; n < count; n++ )
00119       priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
00120 
00121     count = priv->num_other_blues = cpriv->num_other_blues;
00122     for ( n = 0; n < count; n++ )
00123       priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
00124 
00125     count = priv->num_family_blues = cpriv->num_family_blues;
00126     for ( n = 0; n < count; n++ )
00127       priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
00128 
00129     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
00130     for ( n = 0; n < count; n++ )
00131       priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
00132 
00133     priv->blue_scale = cpriv->blue_scale;
00134     priv->blue_shift = (FT_Int)cpriv->blue_shift;
00135     priv->blue_fuzz  = (FT_Int)cpriv->blue_fuzz;
00136 
00137     priv->standard_width[0]  = (FT_UShort)cpriv->standard_width;
00138     priv->standard_height[0] = (FT_UShort)cpriv->standard_height;
00139 
00140     count = priv->num_snap_widths = cpriv->num_snap_widths;
00141     for ( n = 0; n < count; n++ )
00142       priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
00143 
00144     count = priv->num_snap_heights = cpriv->num_snap_heights;
00145     for ( n = 0; n < count; n++ )
00146       priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
00147 
00148     priv->force_bold     = cpriv->force_bold;
00149     priv->language_group = cpriv->language_group;
00150     priv->lenIV          = cpriv->lenIV;
00151   }
00152 
00153 
00154   FT_LOCAL_DEF( FT_Error )
00155   cff_size_init( FT_Size  cffsize )         /* CFF_Size */
00156   {
00157     CFF_Size           size  = (CFF_Size)cffsize;
00158     FT_Error           error = CFF_Err_Ok;
00159     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
00160 
00161 
00162     if ( funcs )
00163     {
00164       CFF_Face      face     = (CFF_Face)cffsize->face;
00165       CFF_Font      font     = (CFF_Font)face->extra.data;
00166       CFF_Internal  internal;
00167 
00168       PS_PrivateRec  priv;
00169       FT_Memory      memory = cffsize->face->memory;
00170 
00171       FT_UInt  i;
00172 
00173 
00174       if ( FT_NEW( internal ) )
00175         goto Exit;
00176 
00177       cff_make_private_dict( &font->top_font, &priv );
00178       error = funcs->create( cffsize->face->memory, &priv,
00179                              &internal->topfont );
00180       if ( error )
00181         goto Exit;
00182 
00183       for ( i = font->num_subfonts; i > 0; i-- )
00184       {
00185         CFF_SubFont  sub = font->subfonts[i - 1];
00186 
00187 
00188         cff_make_private_dict( sub, &priv );
00189         error = funcs->create( cffsize->face->memory, &priv,
00190                                &internal->subfonts[i - 1] );
00191         if ( error )
00192           goto Exit;
00193       }
00194 
00195       cffsize->internal = (FT_Size_Internal)(void*)internal;
00196     }
00197 
00198     size->strike_index = 0xFFFFFFFFUL;
00199 
00200   Exit:
00201     return error;
00202   }
00203 
00204 
00205 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00206 
00207   FT_LOCAL_DEF( FT_Error )
00208   cff_size_select( FT_Size   size,
00209                    FT_ULong  strike_index )
00210   {
00211     CFF_Size           cffsize = (CFF_Size)size;
00212     PSH_Globals_Funcs  funcs;
00213 
00214 
00215     cffsize->strike_index = strike_index;
00216 
00217     FT_Select_Metrics( size->face, strike_index );
00218 
00219     funcs = cff_size_get_globals_funcs( cffsize );
00220 
00221     if ( funcs )
00222     {
00223       CFF_Face      face     = (CFF_Face)size->face;
00224       CFF_Font      font     = (CFF_Font)face->extra.data;
00225       CFF_Internal  internal = (CFF_Internal)size->internal;
00226 
00227       FT_ULong  top_upm  = font->top_font.font_dict.units_per_em;
00228       FT_UInt   i;
00229 
00230 
00231       funcs->set_scale( internal->topfont,
00232                         size->metrics.x_scale, size->metrics.y_scale,
00233                         0, 0 );
00234 
00235       for ( i = font->num_subfonts; i > 0; i-- )
00236       {
00237         CFF_SubFont  sub     = font->subfonts[i - 1];
00238         FT_ULong     sub_upm = sub->font_dict.units_per_em;
00239         FT_Pos       x_scale, y_scale;
00240 
00241 
00242         if ( top_upm != sub_upm )
00243         {
00244           x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
00245           y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
00246         }
00247         else
00248         {
00249           x_scale = size->metrics.x_scale;
00250           y_scale = size->metrics.y_scale;
00251         }
00252 
00253         funcs->set_scale( internal->subfonts[i - 1],
00254                           x_scale, y_scale, 0, 0 );
00255       }
00256     }
00257 
00258     return CFF_Err_Ok;
00259   }
00260 
00261 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
00262 
00263 
00264   FT_LOCAL_DEF( FT_Error )
00265   cff_size_request( FT_Size          size,
00266                     FT_Size_Request  req )
00267   {
00268     CFF_Size           cffsize = (CFF_Size)size;
00269     PSH_Globals_Funcs  funcs;
00270 
00271 
00272 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
00273 
00274     if ( FT_HAS_FIXED_SIZES( size->face ) )
00275     {
00276       CFF_Face      cffface = (CFF_Face)size->face;
00277       SFNT_Service  sfnt    = (SFNT_Service)cffface->sfnt;
00278       FT_ULong      strike_index;
00279 
00280 
00281       if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
00282         cffsize->strike_index = 0xFFFFFFFFUL;
00283       else
00284         return cff_size_select( size, strike_index );
00285     }
00286 
00287 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
00288 
00289     FT_Request_Metrics( size->face, req );
00290 
00291     funcs = cff_size_get_globals_funcs( cffsize );
00292 
00293     if ( funcs )
00294     {
00295       CFF_Face      cffface  = (CFF_Face)size->face;
00296       CFF_Font      font     = (CFF_Font)cffface->extra.data;
00297       CFF_Internal  internal = (CFF_Internal)size->internal;
00298 
00299       FT_ULong  top_upm  = font->top_font.font_dict.units_per_em;
00300       FT_UInt   i;
00301 
00302 
00303       funcs->set_scale( internal->topfont,
00304                         size->metrics.x_scale, size->metrics.y_scale,
00305                         0, 0 );
00306 
00307       for ( i = font->num_subfonts; i > 0; i-- )
00308       {
00309         CFF_SubFont  sub     = font->subfonts[i - 1];
00310         FT_ULong     sub_upm = sub->font_dict.units_per_em;
00311         FT_Pos       x_scale, y_scale;
00312 
00313 
00314         if ( top_upm != sub_upm )
00315         {
00316           x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
00317           y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
00318         }
00319         else
00320         {
00321           x_scale = size->metrics.x_scale;
00322           y_scale = size->metrics.y_scale;
00323         }
00324 
00325         funcs->set_scale( internal->subfonts[i - 1],
00326                           x_scale, y_scale, 0, 0 );
00327       }
00328     }
00329 
00330     return CFF_Err_Ok;
00331   }
00332 
00333 
00334   /*************************************************************************/
00335   /*                                                                       */
00336   /*                            SLOT  FUNCTIONS                            */
00337   /*                                                                       */
00338   /*************************************************************************/
00339 
00340   FT_LOCAL_DEF( void )
00341   cff_slot_done( FT_GlyphSlot  slot )
00342   {
00343     slot->internal->glyph_hints = 0;
00344   }
00345 
00346 
00347   FT_LOCAL_DEF( FT_Error )
00348   cff_slot_init( FT_GlyphSlot  slot )
00349   {
00350     CFF_Face          face     = (CFF_Face)slot->face;
00351     CFF_Font          font     = (CFF_Font)face->extra.data;
00352     PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
00353 
00354 
00355     if ( pshinter )
00356     {
00357       FT_Module  module;
00358 
00359 
00360       module = FT_Get_Module( slot->face->driver->root.library,
00361                               "pshinter" );
00362       if ( module )
00363       {
00364         T2_Hints_Funcs  funcs;
00365 
00366 
00367         funcs = pshinter->get_t2_funcs( module );
00368         slot->internal->glyph_hints = (void*)funcs;
00369       }
00370     }
00371 
00372     return CFF_Err_Ok;
00373   }
00374 
00375 
00376   /*************************************************************************/
00377   /*                                                                       */
00378   /*                           FACE  FUNCTIONS                             */
00379   /*                                                                       */
00380   /*************************************************************************/
00381 
00382   static FT_String*
00383   cff_strcpy( FT_Memory         memory,
00384               const FT_String*  source )
00385   {
00386     FT_Error    error;
00387     FT_String*  result;
00388 
00389 
00390     (void)FT_STRDUP( result, source );
00391 
00392     FT_UNUSED( error );
00393 
00394     return result;
00395   }
00396 
00397 
00398   FT_LOCAL_DEF( FT_Error )
00399   cff_face_init( FT_Stream      stream,
00400                  FT_Face        cffface,        /* CFF_Face */
00401                  FT_Int         face_index,
00402                  FT_Int         num_params,
00403                  FT_Parameter*  params )
00404   {
00405     CFF_Face            face = (CFF_Face)cffface;
00406     FT_Error            error;
00407     SFNT_Service        sfnt;
00408     FT_Service_PsCMaps  psnames;
00409     PSHinter_Service    pshinter;
00410     FT_Bool             pure_cff    = 1;
00411     FT_Bool             sfnt_format = 0;
00412     FT_Library library = cffface->driver->root.library;
00413 
00414 
00415 #if 0
00416     FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt,     SFNT );
00417     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames,  POSTSCRIPT_NAMES );
00418     FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER );
00419 
00420     if ( !sfnt )
00421       goto Bad_Format;
00422 #else
00423     sfnt = (SFNT_Service)FT_Get_Module_Interface(
00424              library, "sfnt" );
00425     if ( !sfnt )
00426       goto Bad_Format;
00427 
00428     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
00429 
00430     pshinter = (PSHinter_Service)FT_Get_Module_Interface(
00431                  library, "pshinter" );
00432 #endif
00433 
00434     /* create input stream from resource */
00435     if ( FT_STREAM_SEEK( 0 ) )
00436       goto Exit;
00437 
00438     /* check whether we have a valid OpenType file */
00439     error = sfnt->init_face( stream, face, face_index, num_params, params );
00440     if ( !error )
00441     {
00442       if ( face->format_tag != TTAG_OTTO )  /* `OTTO'; OpenType/CFF font */
00443       {
00444         FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
00445         goto Bad_Format;
00446       }
00447 
00448       /* if we are performing a simple font format check, exit immediately */
00449       if ( face_index < 0 )
00450         return CFF_Err_Ok;
00451 
00452       /* UNDOCUMENTED!  A CFF in an SFNT can have only a single font. */
00453       if ( face_index > 0 )
00454       {
00455         FT_ERROR(( "cff_face_init: invalid face index\n" ));
00456         error = CFF_Err_Invalid_Argument;
00457         goto Exit;
00458       }
00459 
00460       sfnt_format = 1;
00461 
00462       /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
00463       /* font; in the latter case it doesn't have a `head' table         */
00464       error = face->goto_table( face, TTAG_head, stream, 0 );
00465       if ( !error )
00466       {
00467         pure_cff = 0;
00468 
00469         /* load font directory */
00470         error = sfnt->load_face( stream, face, 0, num_params, params );
00471         if ( error )
00472           goto Exit;
00473       }
00474       else
00475       {
00476         /* load the `cmap' table explicitly */
00477         error = sfnt->load_cmap( face, stream );
00478         if ( error )
00479           goto Exit;
00480 
00481         /* XXX: we don't load the GPOS table, as OpenType Layout     */
00482         /* support will be added later to a layout library on top of */
00483         /* FreeType 2                                                */
00484       }
00485 
00486       /* now load the CFF part of the file */
00487       error = face->goto_table( face, TTAG_CFF, stream, 0 );
00488       if ( error )
00489         goto Exit;
00490     }
00491     else
00492     {
00493       /* rewind to start of file; we are going to load a pure-CFF font */
00494       if ( FT_STREAM_SEEK( 0 ) )
00495         goto Exit;
00496       error = CFF_Err_Ok;
00497     }
00498 
00499     /* now load and parse the CFF table in the file */
00500     {
00501       CFF_Font         cff;
00502       CFF_FontRecDict  dict;
00503       FT_Memory        memory = cffface->memory;
00504       FT_Int32         flags;
00505       FT_UInt          i;
00506 
00507 
00508       if ( FT_NEW( cff ) )
00509         goto Exit;
00510 
00511       face->extra.data = cff;
00512       error = cff_font_load( library, stream, face_index, cff, pure_cff );
00513       if ( error )
00514         goto Exit;
00515 
00516       cff->pshinter = pshinter;
00517       cff->psnames  = (void*)psnames;
00518 
00519       cffface->face_index = face_index;
00520 
00521       /* Complement the root flags with some interesting information. */
00522       /* Note that this is only necessary for pure CFF and CEF fonts; */
00523       /* SFNT based fonts use the `name' table instead.               */
00524 
00525       cffface->num_glyphs = cff->num_glyphs;
00526 
00527       dict = &cff->top_font.font_dict;
00528 
00529       /* we need the `PSNames' module for CFF and CEF formats */
00530       /* which aren't CID-keyed                               */
00531       if ( dict->cid_registry == 0xFFFFU && !psnames )
00532       {
00533         FT_ERROR(( "cff_face_init:"
00534                    " cannot open CFF & CEF fonts\n"
00535                    "              "
00536                    " without the `PSNames' module\n" ));
00537         goto Bad_Format;
00538       }
00539 
00540       if ( !dict->units_per_em )
00541         dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
00542 
00543       /* Normalize the font matrix so that `matrix->xx' is 1; the */
00544       /* scaling is done with `units_per_em' then (at this point, */
00545       /* it already contains the scaling factor, but without      */
00546       /* normalization of the matrix).                            */
00547       /*                                                          */
00548       /* Note that the offsets must be expressed in integer font  */
00549       /* units.                                                   */
00550 
00551       {
00552         FT_Matrix*  matrix = &dict->font_matrix;
00553         FT_Vector*  offset = &dict->font_offset;
00554         FT_ULong*   upm    = &dict->units_per_em;
00555         FT_Fixed    temp   = FT_ABS( matrix->yy );
00556 
00557 
00558         if ( temp != 0x10000L )
00559         {
00560           *upm = FT_DivFix( *upm, temp );
00561 
00562           matrix->xx = FT_DivFix( matrix->xx, temp );
00563           matrix->yx = FT_DivFix( matrix->yx, temp );
00564           matrix->xy = FT_DivFix( matrix->xy, temp );
00565           matrix->yy = FT_DivFix( matrix->yy, temp );
00566           offset->x  = FT_DivFix( offset->x,  temp );
00567           offset->y  = FT_DivFix( offset->y,  temp );
00568         }
00569 
00570         offset->x >>= 16;
00571         offset->y >>= 16;
00572       }
00573 
00574       for ( i = cff->num_subfonts; i > 0; i-- )
00575       {
00576         CFF_FontRecDict  sub = &cff->subfonts[i - 1]->font_dict;
00577         CFF_FontRecDict  top = &cff->top_font.font_dict;
00578 
00579         FT_Matrix*  matrix;
00580         FT_Vector*  offset;
00581         FT_ULong*   upm;
00582         FT_Fixed    temp;
00583 
00584 
00585         if ( sub->units_per_em )
00586         {
00587           FT_Long  scaling;
00588 
00589 
00590           if ( top->units_per_em > 1 && sub->units_per_em > 1 )
00591             scaling = FT_MIN( top->units_per_em, sub->units_per_em );
00592           else
00593             scaling = 1;
00594 
00595           FT_Matrix_Multiply_Scaled( &top->font_matrix,
00596                                      &sub->font_matrix,
00597                                      scaling );
00598           FT_Vector_Transform_Scaled( &sub->font_offset,
00599                                       &top->font_matrix,
00600                                       scaling );
00601 
00602           sub->units_per_em = FT_MulDiv( sub->units_per_em,
00603                                          top->units_per_em,
00604                                          scaling );
00605         }
00606         else
00607         {
00608           sub->font_matrix = top->font_matrix;
00609           sub->font_offset = top->font_offset;
00610 
00611           sub->units_per_em = top->units_per_em;
00612         }
00613 
00614         matrix = &sub->font_matrix;
00615         offset = &sub->font_offset;
00616         upm    = &sub->units_per_em;
00617         temp   = FT_ABS( matrix->yy );
00618 
00619         if ( temp != 0x10000L )
00620         {
00621           *upm = FT_DivFix( *upm, temp );
00622 
00623           /* if *upm is larger than 100*1000 we divide by 1000 --     */
00624           /* this can happen if e.g. there is no top-font FontMatrix  */
00625           /* and the subfont FontMatrix already contains the complete */
00626           /* scaling for the subfont (see section 5.11 of the PLRM)   */
00627 
00628           /* 100 is a heuristic value */
00629 
00630           if ( *upm > 100L * 1000L )
00631             *upm = ( *upm + 500 ) / 1000;
00632 
00633           matrix->xx = FT_DivFix( matrix->xx, temp );
00634           matrix->yx = FT_DivFix( matrix->yx, temp );
00635           matrix->xy = FT_DivFix( matrix->xy, temp );
00636           matrix->yy = FT_DivFix( matrix->yy, temp );
00637           offset->x  = FT_DivFix( offset->x,  temp );
00638           offset->y  = FT_DivFix( offset->y,  temp );
00639         }
00640 
00641         offset->x >>= 16;
00642         offset->y >>= 16;
00643       }
00644 
00645       if ( pure_cff )
00646       {
00647         char*  style_name = NULL;
00648 
00649 
00650         /* set up num_faces */
00651         cffface->num_faces = cff->num_faces;
00652 
00653         /* compute number of glyphs */
00654         if ( dict->cid_registry != 0xFFFFU )
00655           cffface->num_glyphs = cff->charset.max_cid;
00656         else
00657           cffface->num_glyphs = cff->charstrings_index.count;
00658 
00659         /* set global bbox, as well as EM size */
00660         cffface->bbox.xMin =   dict->font_bbox.xMin            >> 16;
00661         cffface->bbox.yMin =   dict->font_bbox.yMin            >> 16;
00662         /* no `U' suffix here to 0xFFFF! */
00663         cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
00664         cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;
00665 
00666         cffface->units_per_EM = (FT_UShort)( dict->units_per_em );
00667 
00668         cffface->ascender  = (FT_Short)( cffface->bbox.yMax );
00669         cffface->descender = (FT_Short)( cffface->bbox.yMin );
00670 
00671         cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
00672         if ( cffface->height < cffface->ascender - cffface->descender )
00673           cffface->height = (FT_Short)( cffface->ascender - cffface->descender );
00674 
00675         cffface->underline_position  =
00676           (FT_Short)( dict->underline_position >> 16 );
00677         cffface->underline_thickness =
00678           (FT_Short)( dict->underline_thickness >> 16 );
00679 
00680         /* retrieve font family & style name */
00681         cffface->family_name = cff_index_get_name( &cff->name_index,
00682                                                    face_index );
00683 
00684         if ( cffface->family_name )
00685         {
00686           char*  full   = cff_index_get_sid_string( &cff->string_index,
00687                                                     dict->full_name,
00688                                                     psnames );
00689           char*  fullp  = full;
00690           char*  family = cffface->family_name;
00691           char*  family_name = 0;
00692 
00693 
00694           if ( dict->family_name )
00695           {
00696             family_name = cff_index_get_sid_string( &cff->string_index,
00697                                                     dict->family_name,
00698                                                     psnames);
00699             if ( family_name )
00700               family = family_name;
00701           }
00702 
00703           /* We try to extract the style name from the full name.   */
00704           /* We need to ignore spaces and dashes during the search. */
00705           if ( full && family )
00706           {
00707             while ( *fullp )
00708             {
00709               /* skip common characters at the start of both strings */
00710               if ( *fullp == *family )
00711               {
00712                 family++;
00713                 fullp++;
00714                 continue;
00715               }
00716 
00717               /* ignore spaces and dashes in full name during comparison */
00718               if ( *fullp == ' ' || *fullp == '-' )
00719               {
00720                 fullp++;
00721                 continue;
00722               }
00723 
00724               /* ignore spaces and dashes in family name during comparison */
00725               if ( *family == ' ' || *family == '-' )
00726               {
00727                 family++;
00728                 continue;
00729               }
00730 
00731               if ( !*family && *fullp )
00732               {
00733                 /* The full name begins with the same characters as the  */
00734                 /* family name, with spaces and dashes removed.  In this */
00735                 /* case, the remaining string in `fullp' will be used as */
00736                 /* the style name.                                       */
00737                 style_name = cff_strcpy( memory, fullp );
00738               }
00739               break;
00740             }
00741 
00742             if ( family_name )
00743               FT_FREE( family_name );
00744             FT_FREE( full );
00745           }
00746         }
00747         else
00748         {
00749           char  *cid_font_name =
00750                    cff_index_get_sid_string( &cff->string_index,
00751                                              dict->cid_font_name,
00752                                              psnames );
00753 
00754 
00755           /* do we have a `/FontName' for a CID-keyed font? */
00756           if ( cid_font_name )
00757             cffface->family_name = cid_font_name;
00758         }
00759 
00760         if ( style_name )
00761           cffface->style_name = style_name;
00762         else
00763           /* assume "Regular" style if we don't know better */
00764           cffface->style_name = cff_strcpy( memory, (char *)"Regular" );
00765 
00766         /*******************************************************************/
00767         /*                                                                 */
00768         /* Compute face flags.                                             */
00769         /*                                                                 */
00770         flags = (FT_UInt32)( FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
00771                              FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
00772                              FT_FACE_FLAG_HINTER );    /* has native hinter */
00773 
00774         if ( sfnt_format )
00775           flags |= (FT_UInt32)FT_FACE_FLAG_SFNT;
00776 
00777         /* fixed width font? */
00778         if ( dict->is_fixed_pitch )
00779           flags |= (FT_UInt32)FT_FACE_FLAG_FIXED_WIDTH;
00780 
00781   /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
00782 #if 0
00783         /* kerning available? */
00784         if ( face->kern_pairs )
00785           flags |= (FT_UInt32)FT_FACE_FLAG_KERNING;
00786 #endif
00787 
00788         cffface->face_flags = flags;
00789 
00790         /*******************************************************************/
00791         /*                                                                 */
00792         /* Compute style flags.                                            */
00793         /*                                                                 */
00794         flags = 0;
00795 
00796         if ( dict->italic_angle )
00797           flags |= FT_STYLE_FLAG_ITALIC;
00798 
00799         {
00800           char  *weight = cff_index_get_sid_string( &cff->string_index,
00801                                                     dict->weight,
00802                                                     psnames );
00803 
00804 
00805           if ( weight )
00806             if ( !ft_strcmp( weight, "Bold"  ) ||
00807                  !ft_strcmp( weight, "Black" ) )
00808               flags |= FT_STYLE_FLAG_BOLD;
00809           FT_FREE( weight );
00810         }
00811 
00812         /* double check */
00813         if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
00814           if ( !ft_strncmp( cffface->style_name, "Bold", 4 )  ||
00815                !ft_strncmp( cffface->style_name, "Black", 5 ) )
00816             flags |= FT_STYLE_FLAG_BOLD;
00817 
00818         cffface->style_flags = flags;
00819       }
00820 
00821 
00822 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
00823       /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
00824       /* has unset this flag because of the 3.0 `post' table.          */
00825       if ( dict->cid_registry == 0xFFFFU )
00826         cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
00827 #endif
00828 
00829       if ( dict->cid_registry != 0xFFFFU && pure_cff )
00830         cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
00831 
00832 
00833       /*******************************************************************/
00834       /*                                                                 */
00835       /* Compute char maps.                                              */
00836       /*                                                                 */
00837 
00838       /* Try to synthesize a Unicode charmap if there is none available */
00839       /* already.  If an OpenType font contains a Unicode "cmap", we    */
00840       /* will use it, whatever be in the CFF part of the file.          */
00841       {
00842         FT_CharMapRec  cmaprec;
00843         FT_CharMap     cmap;
00844         FT_UInt        nn;
00845         CFF_Encoding   encoding = &cff->encoding;
00846 
00847 
00848         for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
00849         {
00850           cmap = cffface->charmaps[nn];
00851 
00852           /* Windows Unicode (3,1)? */
00853           if ( cmap->platform_id == 3 && cmap->encoding_id == 1 )
00854             goto Skip_Unicode;
00855 
00856           /* Deprecated Unicode platform id? */
00857           if ( cmap->platform_id == 0 )
00858             goto Skip_Unicode; /* Standard Unicode (deprecated) */
00859         }
00860 
00861         /* since CID-keyed fonts don't contain glyph names, we can't */
00862         /* construct a cmap                                          */
00863         if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
00864           goto Exit;
00865 
00866         /* we didn't find a Unicode charmap -- synthesize one */
00867         cmaprec.face        = cffface;
00868         cmaprec.platform_id = 3;
00869         cmaprec.encoding_id = 1;
00870         cmaprec.encoding    = FT_ENCODING_UNICODE;
00871 
00872         nn = (FT_UInt)cffface->num_charmaps;
00873 
00874         FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL );
00875 
00876         /* if no Unicode charmap was previously selected, select this one */
00877         if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
00878           cffface->charmap = cffface->charmaps[nn];
00879 
00880       Skip_Unicode:
00881         if ( encoding->count > 0 )
00882         {
00883           FT_CMap_Class  clazz;
00884 
00885 
00886           cmaprec.face        = cffface;
00887           cmaprec.platform_id = 7;  /* Adobe platform id */
00888 
00889           if ( encoding->offset == 0 )
00890           {
00891             cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
00892             cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
00893             clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
00894           }
00895           else if ( encoding->offset == 1 )
00896           {
00897             cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
00898             cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
00899             clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
00900           }
00901           else
00902           {
00903             cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
00904             cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
00905             clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
00906           }
00907 
00908           FT_CMap_New( clazz, NULL, &cmaprec, NULL );
00909         }
00910       }
00911     }
00912 
00913   Exit:
00914     return error;
00915 
00916   Bad_Format:
00917     error = CFF_Err_Unknown_File_Format;
00918     goto Exit;
00919   }
00920 
00921 
00922   FT_LOCAL_DEF( void )
00923   cff_face_done( FT_Face  cffface )         /* CFF_Face */
00924   {
00925     CFF_Face      face = (CFF_Face)cffface;
00926     FT_Memory     memory;
00927     SFNT_Service  sfnt;
00928 
00929 
00930     if ( !face )
00931       return;
00932 
00933     memory = cffface->memory;
00934     sfnt   = (SFNT_Service)face->sfnt;
00935 
00936     if ( sfnt )
00937       sfnt->done_face( face );
00938 
00939     {
00940       CFF_Font  cff = (CFF_Font)face->extra.data;
00941 
00942 
00943       if ( cff )
00944       {
00945         cff_font_done( cff );
00946         FT_FREE( face->extra.data );
00947       }
00948     }
00949   }
00950 
00951 
00952   FT_LOCAL_DEF( FT_Error )
00953   cff_driver_init( FT_Module  module )
00954   {
00955     FT_UNUSED( module );
00956 
00957     return CFF_Err_Ok;
00958   }
00959 
00960 
00961   FT_LOCAL_DEF( void )
00962   cff_driver_done( FT_Module  module )
00963   {
00964     FT_UNUSED( module );
00965   }
00966 
00967 
00968 /* END */

Generated on Tue Jul 5 14:13:46 2011 for ROOT_528-00b_version by  doxygen 1.5.1