tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cidobjs.c (13996B)


      1 /****************************************************************************
      2 *
      3 * cidobjs.c
      4 *
      5 *   CID objects manager (body).
      6 *
      7 * Copyright (C) 1996-2025 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 */