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