misc/libfreetype/src/type1/t1objs.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  t1objs.c                                                               */
       
     4 /*                                                                         */
       
     5 /*    Type 1 objects manager (body).                                       */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    10 /*  This file is part of the FreeType project, and may only be used,       */
       
    11 /*  modified, and distributed under the terms of the FreeType project      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19 #include <ft2build.h>
       
    20 #include FT_INTERNAL_CALC_H
       
    21 #include FT_INTERNAL_DEBUG_H
       
    22 #include FT_INTERNAL_STREAM_H
       
    23 #include FT_TRUETYPE_IDS_H
       
    24 
       
    25 #include "t1gload.h"
       
    26 #include "t1load.h"
       
    27 
       
    28 #include "t1errors.h"
       
    29 
       
    30 #ifndef T1_CONFIG_OPTION_NO_AFM
       
    31 #include "t1afm.h"
       
    32 #endif
       
    33 
       
    34 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
       
    35 #include FT_INTERNAL_POSTSCRIPT_AUX_H
       
    36 
       
    37 
       
    38   /*************************************************************************/
       
    39   /*                                                                       */
       
    40   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    41   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    42   /* messages during execution.                                            */
       
    43   /*                                                                       */
       
    44 #undef  FT_COMPONENT
       
    45 #define FT_COMPONENT  trace_t1objs
       
    46 
       
    47 
       
    48   /*************************************************************************/
       
    49   /*                                                                       */
       
    50   /*                            SIZE FUNCTIONS                             */
       
    51   /*                                                                       */
       
    52   /*  note that we store the global hints in the size's "internal" root    */
       
    53   /*  field                                                                */
       
    54   /*                                                                       */
       
    55   /*************************************************************************/
       
    56 
       
    57 
       
    58   static PSH_Globals_Funcs
       
    59   T1_Size_Get_Globals_Funcs( T1_Size  size )
       
    60   {
       
    61     T1_Face           face     = (T1_Face)size->root.face;
       
    62     PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
       
    63     FT_Module         module;
       
    64 
       
    65 
       
    66     module = FT_Get_Module( size->root.face->driver->root.library,
       
    67                             "pshinter" );
       
    68     return ( module && pshinter && pshinter->get_globals_funcs )
       
    69            ? pshinter->get_globals_funcs( module )
       
    70            : 0 ;
       
    71   }
       
    72 
       
    73 
       
    74   FT_LOCAL_DEF( void )
       
    75   T1_Size_Done( T1_Size  size )
       
    76   {
       
    77     if ( size->root.internal )
       
    78     {
       
    79       PSH_Globals_Funcs  funcs;
       
    80 
       
    81 
       
    82       funcs = T1_Size_Get_Globals_Funcs( size );
       
    83       if ( funcs )
       
    84         funcs->destroy( (PSH_Globals)size->root.internal );
       
    85 
       
    86       size->root.internal = 0;
       
    87     }
       
    88   }
       
    89 
       
    90 
       
    91   FT_LOCAL_DEF( FT_Error )
       
    92   T1_Size_Init( T1_Size  size )
       
    93   {
       
    94     FT_Error           error = T1_Err_Ok;
       
    95     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
       
    96 
       
    97 
       
    98     if ( funcs )
       
    99     {
       
   100       PSH_Globals  globals;
       
   101       T1_Face      face = (T1_Face)size->root.face;
       
   102 
       
   103 
       
   104       error = funcs->create( size->root.face->memory,
       
   105                              &face->type1.private_dict, &globals );
       
   106       if ( !error )
       
   107         size->root.internal = (FT_Size_Internal)(void*)globals;
       
   108     }
       
   109 
       
   110     return error;
       
   111   }
       
   112 
       
   113 
       
   114   FT_LOCAL_DEF( FT_Error )
       
   115   T1_Size_Request( T1_Size          size,
       
   116                    FT_Size_Request  req )
       
   117   {
       
   118     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
       
   119 
       
   120 
       
   121     FT_Request_Metrics( size->root.face, req );
       
   122 
       
   123     if ( funcs )
       
   124       funcs->set_scale( (PSH_Globals)size->root.internal,
       
   125                         size->root.metrics.x_scale,
       
   126                         size->root.metrics.y_scale,
       
   127                         0, 0 );
       
   128 
       
   129     return T1_Err_Ok;
       
   130   }
       
   131 
       
   132 
       
   133   /*************************************************************************/
       
   134   /*                                                                       */
       
   135   /*                            SLOT  FUNCTIONS                            */
       
   136   /*                                                                       */
       
   137   /*************************************************************************/
       
   138 
       
   139   FT_LOCAL_DEF( void )
       
   140   T1_GlyphSlot_Done( T1_GlyphSlot  slot )
       
   141   {
       
   142     slot->root.internal->glyph_hints = 0;
       
   143   }
       
   144 
       
   145 
       
   146   FT_LOCAL_DEF( FT_Error )
       
   147   T1_GlyphSlot_Init( T1_GlyphSlot  slot )
       
   148   {
       
   149     T1_Face           face;
       
   150     PSHinter_Service  pshinter;
       
   151 
       
   152 
       
   153     face     = (T1_Face)slot->root.face;
       
   154     pshinter = (PSHinter_Service)face->pshinter;
       
   155 
       
   156     if ( pshinter )
       
   157     {
       
   158       FT_Module  module;
       
   159 
       
   160 
       
   161       module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" );
       
   162       if (module)
       
   163       {
       
   164         T1_Hints_Funcs  funcs;
       
   165 
       
   166         funcs = pshinter->get_t1_funcs( module );
       
   167         slot->root.internal->glyph_hints = (void*)funcs;
       
   168       }
       
   169     }
       
   170     return 0;
       
   171   }
       
   172 
       
   173 
       
   174   /*************************************************************************/
       
   175   /*                                                                       */
       
   176   /*                            FACE  FUNCTIONS                            */
       
   177   /*                                                                       */
       
   178   /*************************************************************************/
       
   179 
       
   180 
       
   181   /*************************************************************************/
       
   182   /*                                                                       */
       
   183   /* <Function>                                                            */
       
   184   /*    T1_Face_Done                                                       */
       
   185   /*                                                                       */
       
   186   /* <Description>                                                         */
       
   187   /*    The face object destructor.                                        */
       
   188   /*                                                                       */
       
   189   /* <Input>                                                               */
       
   190   /*    face :: A typeless pointer to the face object to destroy.          */
       
   191   /*                                                                       */
       
   192   FT_LOCAL_DEF( void )
       
   193   T1_Face_Done( T1_Face  face )
       
   194   {
       
   195     FT_Memory  memory;
       
   196     T1_Font    type1;
       
   197 
       
   198 
       
   199     if ( !face )
       
   200       return;
       
   201 
       
   202     memory = face->root.memory;
       
   203     type1  = &face->type1;
       
   204 
       
   205 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
       
   206     /* release multiple masters information */
       
   207     FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
       
   208 
       
   209     if ( face->buildchar )
       
   210     {
       
   211       FT_FREE( face->buildchar );
       
   212 
       
   213       face->buildchar     = NULL;
       
   214       face->len_buildchar = 0;
       
   215     }
       
   216 
       
   217     T1_Done_Blend( face );
       
   218     face->blend = 0;
       
   219 #endif
       
   220 
       
   221     /* release font info strings */
       
   222     {
       
   223       PS_FontInfo  info = &type1->font_info;
       
   224 
       
   225 
       
   226       FT_FREE( info->version );
       
   227       FT_FREE( info->notice );
       
   228       FT_FREE( info->full_name );
       
   229       FT_FREE( info->family_name );
       
   230       FT_FREE( info->weight );
       
   231     }
       
   232 
       
   233     /* release top dictionary */
       
   234     FT_FREE( type1->charstrings_len );
       
   235     FT_FREE( type1->charstrings );
       
   236     FT_FREE( type1->glyph_names );
       
   237 
       
   238     FT_FREE( type1->subrs );
       
   239     FT_FREE( type1->subrs_len );
       
   240 
       
   241     FT_FREE( type1->subrs_block );
       
   242     FT_FREE( type1->charstrings_block );
       
   243     FT_FREE( type1->glyph_names_block );
       
   244 
       
   245     FT_FREE( type1->encoding.char_index );
       
   246     FT_FREE( type1->encoding.char_name );
       
   247     FT_FREE( type1->font_name );
       
   248 
       
   249 #ifndef T1_CONFIG_OPTION_NO_AFM
       
   250     /* release afm data if present */
       
   251     if ( face->afm_data )
       
   252       T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
       
   253 #endif
       
   254 
       
   255     /* release unicode map, if any */
       
   256 #if 0
       
   257     FT_FREE( face->unicode_map_rec.maps );
       
   258     face->unicode_map_rec.num_maps = 0;
       
   259     face->unicode_map              = NULL;
       
   260 #endif
       
   261 
       
   262     face->root.family_name = NULL;
       
   263     face->root.style_name  = NULL;
       
   264   }
       
   265 
       
   266 
       
   267   /*************************************************************************/
       
   268   /*                                                                       */
       
   269   /* <Function>                                                            */
       
   270   /*    T1_Face_Init                                                       */
       
   271   /*                                                                       */
       
   272   /* <Description>                                                         */
       
   273   /*    The face object constructor.                                       */
       
   274   /*                                                                       */
       
   275   /* <Input>                                                               */
       
   276   /*    stream     ::  input stream where to load font data.               */
       
   277   /*                                                                       */
       
   278   /*    face_index :: The index of the font face in the resource.          */
       
   279   /*                                                                       */
       
   280   /*    num_params :: Number of additional generic parameters.  Ignored.   */
       
   281   /*                                                                       */
       
   282   /*    params     :: Additional generic parameters.  Ignored.             */
       
   283   /*                                                                       */
       
   284   /* <InOut>                                                               */
       
   285   /*    face       :: The face record to build.                            */
       
   286   /*                                                                       */
       
   287   /* <Return>                                                              */
       
   288   /*    FreeType error code.  0 means success.                             */
       
   289   /*                                                                       */
       
   290   FT_LOCAL_DEF( FT_Error )
       
   291   T1_Face_Init( FT_Stream      stream,
       
   292                 T1_Face        face,
       
   293                 FT_Int         face_index,
       
   294                 FT_Int         num_params,
       
   295                 FT_Parameter*  params )
       
   296   {
       
   297     FT_Error            error;
       
   298     FT_Service_PsCMaps  psnames;
       
   299     PSAux_Service       psaux;
       
   300     T1_Font             type1 = &face->type1;
       
   301     PS_FontInfo         info = &type1->font_info;
       
   302 
       
   303     FT_UNUSED( num_params );
       
   304     FT_UNUSED( params );
       
   305     FT_UNUSED( stream );
       
   306 
       
   307 
       
   308     face->root.num_faces = 1;
       
   309 
       
   310     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
       
   311     face->psnames = psnames;
       
   312 
       
   313     face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
       
   314                                            "psaux" );
       
   315     psaux = (PSAux_Service)face->psaux;
       
   316 
       
   317     face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
       
   318                                               "pshinter" );
       
   319 
       
   320     /* open the tokenizer; this will also check the font format */
       
   321     error = T1_Open_Face( face );
       
   322     if ( error )
       
   323       goto Exit;
       
   324 
       
   325     /* if we just wanted to check the format, leave successfully now */
       
   326     if ( face_index < 0 )
       
   327       goto Exit;
       
   328 
       
   329     /* check the face index */
       
   330     if ( face_index > 0 )
       
   331     {
       
   332       FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
       
   333       error = T1_Err_Invalid_Argument;
       
   334       goto Exit;
       
   335     }
       
   336 
       
   337     /* now load the font program into the face object */
       
   338 
       
   339     /* initialize the face object fields */
       
   340 
       
   341     /* set up root face fields */
       
   342     {
       
   343       FT_Face  root = (FT_Face)&face->root;
       
   344 
       
   345 
       
   346       root->num_glyphs = type1->num_glyphs;
       
   347       root->face_index = 0;
       
   348 
       
   349       root->face_flags = FT_FACE_FLAG_SCALABLE    |
       
   350                          FT_FACE_FLAG_HORIZONTAL  |
       
   351                          FT_FACE_FLAG_GLYPH_NAMES |
       
   352                          FT_FACE_FLAG_HINTER;
       
   353 
       
   354       if ( info->is_fixed_pitch )
       
   355         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
       
   356 
       
   357       if ( face->blend )
       
   358         root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
       
   359 
       
   360       /* XXX: TODO -- add kerning with .afm support */
       
   361 
       
   362 
       
   363       /* The following code to extract the family and the style is very   */
       
   364       /* simplistic and might get some things wrong.  For a full-featured */
       
   365       /* algorithm you might have a look at the whitepaper given at       */
       
   366       /*                                                                  */
       
   367       /*   http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
       
   368 
       
   369       /* get style name -- be careful, some broken fonts only */
       
   370       /* have a `/FontName' dictionary entry!                 */
       
   371       root->family_name = info->family_name;
       
   372       root->style_name  = NULL;
       
   373 
       
   374       if ( root->family_name )
       
   375       {
       
   376         char*  full   = info->full_name;
       
   377         char*  family = root->family_name;
       
   378 
       
   379 
       
   380         if ( full )
       
   381         {
       
   382           FT_Bool  the_same = TRUE;
       
   383 
       
   384 
       
   385           while ( *full )
       
   386           {
       
   387             if ( *full == *family )
       
   388             {
       
   389               family++;
       
   390               full++;
       
   391             }
       
   392             else
       
   393             {
       
   394               if ( *full == ' ' || *full == '-' )
       
   395                 full++;
       
   396               else if ( *family == ' ' || *family == '-' )
       
   397                 family++;
       
   398               else
       
   399               {
       
   400                 the_same = FALSE;
       
   401 
       
   402                 if ( !*family )
       
   403                   root->style_name = full;
       
   404                 break;
       
   405               }
       
   406             }
       
   407           }
       
   408 
       
   409           if ( the_same )
       
   410             root->style_name = (char *)"Regular";
       
   411         }
       
   412       }
       
   413       else
       
   414       {
       
   415         /* do we have a `/FontName'? */
       
   416         if ( type1->font_name )
       
   417           root->family_name = type1->font_name;
       
   418       }
       
   419 
       
   420       if ( !root->style_name )
       
   421       {
       
   422         if ( info->weight )
       
   423           root->style_name = info->weight;
       
   424         else
       
   425           /* assume `Regular' style because we don't know better */
       
   426           root->style_name = (char *)"Regular";
       
   427       }
       
   428 
       
   429       /* compute style flags */
       
   430       root->style_flags = 0;
       
   431       if ( info->italic_angle )
       
   432         root->style_flags |= FT_STYLE_FLAG_ITALIC;
       
   433       if ( info->weight )
       
   434       {
       
   435         if ( !ft_strcmp( info->weight, "Bold"  ) ||
       
   436              !ft_strcmp( info->weight, "Black" ) )
       
   437           root->style_flags |= FT_STYLE_FLAG_BOLD;
       
   438       }
       
   439 
       
   440       /* no embedded bitmap support */
       
   441       root->num_fixed_sizes = 0;
       
   442       root->available_sizes = 0;
       
   443 
       
   444       root->bbox.xMin =   type1->font_bbox.xMin            >> 16;
       
   445       root->bbox.yMin =   type1->font_bbox.yMin            >> 16;
       
   446       /* no `U' suffix here to 0xFFFF! */
       
   447       root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;
       
   448       root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;
       
   449 
       
   450       /* Set units_per_EM if we didn't set it in parse_font_matrix. */
       
   451       if ( !root->units_per_EM )
       
   452         root->units_per_EM = 1000;
       
   453 
       
   454       root->ascender  = (FT_Short)( root->bbox.yMax );
       
   455       root->descender = (FT_Short)( root->bbox.yMin );
       
   456 
       
   457       root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
       
   458       if ( root->height < root->ascender - root->descender )
       
   459         root->height = (FT_Short)( root->ascender - root->descender );
       
   460 
       
   461       /* now compute the maximum advance width */
       
   462       root->max_advance_width =
       
   463         (FT_Short)( root->bbox.xMax );
       
   464       {
       
   465         FT_Pos  max_advance;
       
   466 
       
   467 
       
   468         error = T1_Compute_Max_Advance( face, &max_advance );
       
   469 
       
   470         /* in case of error, keep the standard width */
       
   471         if ( !error )
       
   472           root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance );
       
   473         else
       
   474           error = T1_Err_Ok;   /* clear error */
       
   475       }
       
   476 
       
   477       root->max_advance_height = root->height;
       
   478 
       
   479       root->underline_position  = (FT_Short)info->underline_position;
       
   480       root->underline_thickness = (FT_Short)info->underline_thickness;
       
   481     }
       
   482 
       
   483     {
       
   484       FT_Face  root = &face->root;
       
   485 
       
   486 
       
   487       if ( psnames && psaux )
       
   488       {
       
   489         FT_CharMapRec    charmap;
       
   490         T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
       
   491         FT_CMap_Class    clazz;
       
   492 
       
   493 
       
   494         charmap.face = root;
       
   495 
       
   496         /* first of all, try to synthesize a Unicode charmap */
       
   497         charmap.platform_id = TT_PLATFORM_MICROSOFT;
       
   498         charmap.encoding_id = TT_MS_ID_UNICODE_CS;
       
   499         charmap.encoding    = FT_ENCODING_UNICODE;
       
   500 
       
   501         error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
       
   502         if ( error && FT_Err_No_Unicode_Glyph_Name != error )
       
   503           goto Exit;
       
   504         error = FT_Err_Ok;
       
   505 
       
   506         /* now, generate an Adobe Standard encoding when appropriate */
       
   507         charmap.platform_id = TT_PLATFORM_ADOBE;
       
   508         clazz               = NULL;
       
   509 
       
   510         switch ( type1->encoding_type )
       
   511         {
       
   512         case T1_ENCODING_TYPE_STANDARD:
       
   513           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
       
   514           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
       
   515           clazz               = cmap_classes->standard;
       
   516           break;
       
   517 
       
   518         case T1_ENCODING_TYPE_EXPERT:
       
   519           charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
       
   520           charmap.encoding_id = TT_ADOBE_ID_EXPERT;
       
   521           clazz               = cmap_classes->expert;
       
   522           break;
       
   523 
       
   524         case T1_ENCODING_TYPE_ARRAY:
       
   525           charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
       
   526           charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
       
   527           clazz               = cmap_classes->custom;
       
   528           break;
       
   529 
       
   530         case T1_ENCODING_TYPE_ISOLATIN1:
       
   531           charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
       
   532           charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
       
   533           clazz               = cmap_classes->unicode;
       
   534           break;
       
   535 
       
   536         default:
       
   537           ;
       
   538         }
       
   539 
       
   540         if ( clazz )
       
   541           error = FT_CMap_New( clazz, NULL, &charmap, NULL );
       
   542 
       
   543 #if 0
       
   544         /* Select default charmap */
       
   545         if (root->num_charmaps)
       
   546           root->charmap = root->charmaps[0];
       
   547 #endif
       
   548       }
       
   549     }
       
   550 
       
   551   Exit:
       
   552     return error;
       
   553   }
       
   554 
       
   555 
       
   556   /*************************************************************************/
       
   557   /*                                                                       */
       
   558   /* <Function>                                                            */
       
   559   /*    T1_Driver_Init                                                     */
       
   560   /*                                                                       */
       
   561   /* <Description>                                                         */
       
   562   /*    Initializes a given Type 1 driver object.                          */
       
   563   /*                                                                       */
       
   564   /* <Input>                                                               */
       
   565   /*    driver :: A handle to the target driver object.                    */
       
   566   /*                                                                       */
       
   567   /* <Return>                                                              */
       
   568   /*    FreeType error code.  0 means success.                             */
       
   569   /*                                                                       */
       
   570   FT_LOCAL_DEF( FT_Error )
       
   571   T1_Driver_Init( T1_Driver  driver )
       
   572   {
       
   573     FT_UNUSED( driver );
       
   574 
       
   575     return T1_Err_Ok;
       
   576   }
       
   577 
       
   578 
       
   579   /*************************************************************************/
       
   580   /*                                                                       */
       
   581   /* <Function>                                                            */
       
   582   /*    T1_Driver_Done                                                     */
       
   583   /*                                                                       */
       
   584   /* <Description>                                                         */
       
   585   /*    Finalizes a given Type 1 driver.                                   */
       
   586   /*                                                                       */
       
   587   /* <Input>                                                               */
       
   588   /*    driver :: A handle to the target Type 1 driver.                    */
       
   589   /*                                                                       */
       
   590   FT_LOCAL_DEF( void )
       
   591   T1_Driver_Done( T1_Driver  driver )
       
   592   {
       
   593     FT_UNUSED( driver );
       
   594   }
       
   595 
       
   596 
       
   597 /* END */