Home | History | Annotate | Download | only in cid
      1 /****************************************************************************
      2  *
      3  * cidobjs.c
      4  *
      5  *   CID objects manager (body).
      6  *
      7  * Copyright 1996-2018 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_DEBUG_H
     21 #include FT_INTERNAL_STREAM_H
     22 
     23 #include "cidgload.h"
     24 #include "cidload.h"
     25 
     26 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
     27 #include FT_INTERNAL_POSTSCRIPT_AUX_H
     28 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
     29 #include FT_DRIVER_H
     30 
     31 #include "ciderrs.h"
     32 
     33 
     34   /**************************************************************************
     35    *
     36    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     37    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     38    * messages during execution.
     39    */
     40 #undef  FT_COMPONENT
     41 #define FT_COMPONENT  trace_cidobjs
     42 
     43 
     44   /**************************************************************************
     45    *
     46    *                           SLOT  FUNCTIONS
     47    *
     48    */
     49 
     50   FT_LOCAL_DEF( void )
     51   cid_slot_done( FT_GlyphSlot  slot )
     52   {
     53     slot->internal->glyph_hints = NULL;
     54   }
     55 
     56 
     57   FT_LOCAL_DEF( FT_Error )
     58   cid_slot_init( FT_GlyphSlot  slot )
     59   {
     60     CID_Face          face;
     61     PSHinter_Service  pshinter;
     62 
     63 
     64     face     = (CID_Face)slot->face;
     65     pshinter = (PSHinter_Service)face->pshinter;
     66 
     67     if ( pshinter )
     68     {
     69       FT_Module  module;
     70 
     71 
     72       module = FT_Get_Module( slot->face->driver->root.library,
     73                               "pshinter" );
     74       if ( module )
     75       {
     76         T1_Hints_Funcs  funcs;
     77 
     78 
     79         funcs = pshinter->get_t1_funcs( module );
     80         slot->internal->glyph_hints = (void*)funcs;
     81       }
     82     }
     83 
     84     return 0;
     85   }
     86 
     87 
     88   /**************************************************************************
     89    *
     90    *                          SIZE  FUNCTIONS
     91    *
     92    */
     93 
     94 
     95   static PSH_Globals_Funcs
     96   cid_size_get_globals_funcs( CID_Size  size )
     97   {
     98     CID_Face          face     = (CID_Face)size->root.face;
     99     PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
    100     FT_Module         module;
    101 
    102 
    103     module = FT_Get_Module( size->root.face->driver->root.library,
    104                             "pshinter" );
    105     return ( module && pshinter && pshinter->get_globals_funcs )
    106            ? pshinter->get_globals_funcs( module )
    107            : 0;
    108   }
    109 
    110 
    111   FT_LOCAL_DEF( void )
    112   cid_size_done( FT_Size  cidsize )         /* CID_Size */
    113   {
    114     CID_Size  size = (CID_Size)cidsize;
    115 
    116 
    117     if ( cidsize->internal->module_data )
    118     {
    119       PSH_Globals_Funcs  funcs;
    120 
    121 
    122       funcs = cid_size_get_globals_funcs( size );
    123       if ( funcs )
    124         funcs->destroy( (PSH_Globals)cidsize->internal->module_data );
    125 
    126       cidsize->internal->module_data = NULL;
    127     }
    128   }
    129 
    130 
    131   FT_LOCAL_DEF( FT_Error )
    132   cid_size_init( FT_Size  cidsize )     /* CID_Size */
    133   {
    134     CID_Size           size  = (CID_Size)cidsize;
    135     FT_Error           error = FT_Err_Ok;
    136     PSH_Globals_Funcs  funcs = cid_size_get_globals_funcs( size );
    137 
    138 
    139     if ( funcs )
    140     {
    141       PSH_Globals   globals;
    142       CID_Face      face = (CID_Face)cidsize->face;
    143       CID_FaceDict  dict = face->cid.font_dicts + face->root.face_index;
    144       PS_Private    priv = &dict->private_dict;
    145 
    146 
    147       error = funcs->create( cidsize->face->memory, priv, &globals );
    148       if ( !error )
    149         cidsize->internal->module_data = globals;
    150     }
    151 
    152     return error;
    153   }
    154 
    155 
    156   FT_LOCAL( FT_Error )
    157   cid_size_request( FT_Size          size,
    158                     FT_Size_Request  req )
    159   {
    160     PSH_Globals_Funcs  funcs;
    161 
    162 
    163     FT_Request_Metrics( size->face, req );
    164 
    165     funcs = cid_size_get_globals_funcs( (CID_Size)size );
    166 
    167     if ( funcs )
    168       funcs->set_scale( (PSH_Globals)size->internal->module_data,
    169                         size->metrics.x_scale,
    170                         size->metrics.y_scale,
    171                         0, 0 );
    172 
    173     return FT_Err_Ok;
    174   }
    175 
    176 
    177   /**************************************************************************
    178    *
    179    *                          FACE  FUNCTIONS
    180    *
    181    */
    182 
    183   /**************************************************************************
    184    *
    185    * @Function:
    186    *   cid_face_done
    187    *
    188    * @Description:
    189    *   Finalizes a given face object.
    190    *
    191    * @Input:
    192    *   face ::
    193    *     A pointer to the face object to destroy.
    194    */
    195   FT_LOCAL_DEF( void )
    196   cid_face_done( FT_Face  cidface )         /* CID_Face */
    197   {
    198     CID_Face      face = (CID_Face)cidface;
    199     FT_Memory     memory;
    200     CID_FaceInfo  cid;
    201     PS_FontInfo   info;
    202 
    203 
    204     if ( !face )
    205       return;
    206 
    207     cid    = &face->cid;
    208     info   = &cid->font_info;
    209     memory = cidface->memory;
    210 
    211     /* release subrs */
    212     if ( face->subrs )
    213     {
    214       FT_Int  n;
    215 
    216 
    217       for ( n = 0; n < cid->num_dicts; n++ )
    218       {
    219         CID_Subrs  subr = face->subrs + n;
    220 
    221 
    222         if ( subr->code )
    223         {
    224           FT_FREE( subr->code[0] );
    225           FT_FREE( subr->code );
    226         }
    227       }
    228 
    229       FT_FREE( face->subrs );
    230     }
    231 
    232     /* release FontInfo strings */
    233     FT_FREE( info->version );
    234     FT_FREE( info->notice );
    235     FT_FREE( info->full_name );
    236     FT_FREE( info->family_name );
    237     FT_FREE( info->weight );
    238 
    239     /* release font dictionaries */
    240     FT_FREE( cid->font_dicts );
    241     cid->num_dicts = 0;
    242 
    243     /* release other strings */
    244     FT_FREE( cid->cid_font_name );
    245     FT_FREE( cid->registry );
    246     FT_FREE( cid->ordering );
    247 
    248     cidface->family_name = NULL;
    249     cidface->style_name  = NULL;
    250 
    251     FT_FREE( face->binary_data );
    252     FT_FREE( face->cid_stream );
    253   }
    254 
    255 
    256   /**************************************************************************
    257    *
    258    * @Function:
    259    *   cid_face_init
    260    *
    261    * @Description:
    262    *   Initializes a given CID face object.
    263    *
    264    * @Input:
    265    *   stream ::
    266    *     The source font stream.
    267    *
    268    *   face_index ::
    269    *     The index of the font face in the resource.
    270    *
    271    *   num_params ::
    272    *     Number of additional generic parameters.  Ignored.
    273    *
    274    *   params ::
    275    *     Additional generic parameters.  Ignored.
    276    *
    277    * @InOut:
    278    *   face ::
    279    *     The newly built face object.
    280    *
    281    * @Return:
    282    *   FreeType error code.  0 means success.
    283    */
    284   FT_LOCAL_DEF( FT_Error )
    285   cid_face_init( FT_Stream      stream,
    286                  FT_Face        cidface,        /* CID_Face */
    287                  FT_Int         face_index,
    288                  FT_Int         num_params,
    289                  FT_Parameter*  params )
    290   {
    291     CID_Face          face = (CID_Face)cidface;
    292     FT_Error          error;
    293     PSAux_Service     psaux;
    294     PSHinter_Service  pshinter;
    295 
    296     FT_UNUSED( num_params );
    297     FT_UNUSED( params );
    298     FT_UNUSED( stream );
    299 
    300 
    301     cidface->num_faces = 1;
    302 
    303     psaux = (PSAux_Service)face->psaux;
    304     if ( !psaux )
    305     {
    306       psaux = (PSAux_Service)FT_Get_Module_Interface(
    307                 FT_FACE_LIBRARY( face ), "psaux" );
    308 
    309       if ( !psaux )
    310       {
    311         FT_ERROR(( "cid_face_init: cannot access `psaux' module\n" ));
    312         error = FT_THROW( Missing_Module );
    313         goto Exit;
    314       }
    315 
    316       face->psaux = psaux;
    317     }
    318 
    319     pshinter = (PSHinter_Service)face->pshinter;
    320     if ( !pshinter )
    321     {
    322       pshinter = (PSHinter_Service)FT_Get_Module_Interface(
    323                    FT_FACE_LIBRARY( face ), "pshinter" );
    324 
    325       face->pshinter = pshinter;
    326     }
    327 
    328     FT_TRACE2(( "CID driver\n" ));
    329 
    330     /* open the tokenizer; this will also check the font format */
    331     if ( FT_STREAM_SEEK( 0 ) )
    332       goto Exit;
    333 
    334     error = cid_face_open( face, face_index );
    335     if ( error )
    336       goto Exit;
    337 
    338     /* if we just wanted to check the format, leave successfully now */
    339     if ( face_index < 0 )
    340       goto Exit;
    341 
    342     /* check the face index */
    343     /* XXX: handle CID fonts with more than a single face */
    344     if ( ( face_index & 0xFFFF ) != 0 )
    345     {
    346       FT_ERROR(( "cid_face_init: invalid face index\n" ));
    347       error = FT_THROW( Invalid_Argument );
    348       goto Exit;
    349     }
    350 
    351     /* now load the font program into the face object */
    352 
    353     /* initialize the face object fields */
    354 
    355     /* set up root face fields */
    356     {
    357       CID_FaceInfo  cid  = &face->cid;
    358       PS_FontInfo   info = &cid->font_info;
    359 
    360 
    361       cidface->num_glyphs   = (FT_Long)cid->cid_count;
    362       cidface->num_charmaps = 0;
    363 
    364       cidface->face_index = face_index & 0xFFFF;
    365 
    366       cidface->face_flags |= FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
    367                              FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
    368                              FT_FACE_FLAG_HINTER;      /* has native hinter */
    369 
    370       if ( info->is_fixed_pitch )
    371         cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
    372 
    373       /* XXX: TODO: add kerning with .afm support */
    374 
    375       /* get style name -- be careful, some broken fonts only */
    376       /* have a /FontName dictionary entry!                   */
    377       cidface->family_name = info->family_name;
    378       /* assume "Regular" style if we don't know better */
    379       cidface->style_name = (char *)"Regular";
    380       if ( cidface->family_name )
    381       {
    382         char*  full   = info->full_name;
    383         char*  family = cidface->family_name;
    384 
    385 
    386         if ( full )
    387         {
    388           while ( *full )
    389           {
    390             if ( *full == *family )
    391             {
    392               family++;
    393               full++;
    394             }
    395             else
    396             {
    397               if ( *full == ' ' || *full == '-' )
    398                 full++;
    399               else if ( *family == ' ' || *family == '-' )
    400                 family++;
    401               else
    402               {
    403                 if ( !*family )
    404                   cidface->style_name = full;
    405                 break;
    406               }
    407             }
    408           }
    409         }
    410       }
    411       else
    412       {
    413         /* do we have a `/FontName'? */
    414         if ( cid->cid_font_name )
    415           cidface->family_name = cid->cid_font_name;
    416       }
    417 
    418       /* compute style flags */
    419       cidface->style_flags = 0;
    420       if ( info->italic_angle )
    421         cidface->style_flags |= FT_STYLE_FLAG_ITALIC;
    422       if ( info->weight )
    423       {
    424         if ( !ft_strcmp( info->weight, "Bold"  ) ||
    425              !ft_strcmp( info->weight, "Black" ) )
    426           cidface->style_flags |= FT_STYLE_FLAG_BOLD;
    427       }
    428 
    429       /* no embedded bitmap support */
    430       cidface->num_fixed_sizes = 0;
    431       cidface->available_sizes = NULL;
    432 
    433       cidface->bbox.xMin =   cid->font_bbox.xMin            >> 16;
    434       cidface->bbox.yMin =   cid->font_bbox.yMin            >> 16;
    435       /* no `U' suffix here to 0xFFFF! */
    436       cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16;
    437       cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16;
    438 
    439       if ( !cidface->units_per_EM )
    440         cidface->units_per_EM = 1000;
    441 
    442       cidface->ascender  = (FT_Short)( cidface->bbox.yMax );
    443       cidface->descender = (FT_Short)( cidface->bbox.yMin );
    444 
    445       cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 );
    446       if ( cidface->height < cidface->ascender - cidface->descender )
    447         cidface->height = (FT_Short)( cidface->ascender - cidface->descender );
    448 
    449       cidface->underline_position  = (FT_Short)info->underline_position;
    450       cidface->underline_thickness = (FT_Short)info->underline_thickness;
    451     }
    452 
    453   Exit:
    454     return error;
    455   }
    456 
    457 
    458   /**************************************************************************
    459    *
    460    * @Function:
    461    *   cid_driver_init
    462    *
    463    * @Description:
    464    *   Initializes a given CID driver object.
    465    *
    466    * @Input:
    467    *   driver ::
    468    *     A handle to the target driver object.
    469    *
    470    * @Return:
    471    *   FreeType error code.  0 means success.
    472    */
    473   FT_LOCAL_DEF( FT_Error )
    474   cid_driver_init( FT_Module  module )
    475   {
    476     PS_Driver  driver = (PS_Driver)module;
    477 
    478     FT_UInt32  seed;
    479 
    480 
    481     /* set default property values, cf. `ftt1drv.h' */
    482 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
    483     driver->hinting_engine = FT_HINTING_FREETYPE;
    484 #else
    485     driver->hinting_engine = FT_HINTING_ADOBE;
    486 #endif
    487 
    488     driver->no_stem_darkening = TRUE;
    489 
    490     driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
    491     driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
    492     driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
    493     driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
    494     driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
    495     driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
    496     driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
    497     driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
    498 
    499     /* compute random seed from some memory addresses */
    500     seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
    501                         (FT_Offset)(char*)&module        ^
    502                         (FT_Offset)(char*)module->memory );
    503     seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
    504 
    505     driver->random_seed = (FT_Int32)seed;
    506     if ( driver->random_seed < 0 )
    507       driver->random_seed = -driver->random_seed;
    508     else if ( driver->random_seed == 0 )
    509       driver->random_seed = 123456789;
    510 
    511     return FT_Err_Ok;
    512   }
    513 
    514 
    515   /**************************************************************************
    516    *
    517    * @Function:
    518    *   cid_driver_done
    519    *
    520    * @Description:
    521    *   Finalizes a given CID driver.
    522    *
    523    * @Input:
    524    *   driver ::
    525    *     A handle to the target CID driver.
    526    */
    527   FT_LOCAL_DEF( void )
    528   cid_driver_done( FT_Module  driver )
    529   {
    530     FT_UNUSED( driver );
    531   }
    532 
    533 
    534 /* END */
    535