tor-browser

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

t1objs.c (17541B)


      1 /****************************************************************************
      2 *
      3 * t1objs.c
      4 *
      5 *   Type 1 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/ftcalc.h>
     20 #include <freetype/internal/ftdebug.h>
     21 #include <freetype/internal/ftstream.h>
     22 #include <freetype/ttnameid.h>
     23 #include <freetype/ftdriver.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 <freetype/internal/services/svpscmap.h>
     35 #include <freetype/internal/psaux.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  t1objs
     46 
     47 
     48  /**************************************************************************
     49   *
     50   *                           SIZE FUNCTIONS
     51   *
     52   */
     53 
     54 
     55  static PSH_Globals_Funcs
     56  T1_Size_Get_Globals_Funcs( T1_Size  size )
     57  {
     58    T1_Face           face     = (T1_Face)size->root.face;
     59    PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
     60    FT_Module         module;
     61 
     62 
     63    module = FT_Get_Module( size->root.face->driver->root.library,
     64                            "pshinter" );
     65    return ( module && pshinter && pshinter->get_globals_funcs )
     66           ? pshinter->get_globals_funcs( module )
     67           : 0;
     68  }
     69 
     70 
     71  FT_LOCAL_DEF( void )
     72  T1_Size_Done( FT_Size  t1size )          /* T1_Size */
     73  {
     74    T1_Size  size = (T1_Size)t1size;
     75 
     76 
     77    if ( t1size->internal->module_data )
     78    {
     79      PSH_Globals_Funcs  funcs;
     80 
     81 
     82      funcs = T1_Size_Get_Globals_Funcs( size );
     83      if ( funcs )
     84        funcs->destroy( (PSH_Globals)t1size->internal->module_data );
     85 
     86      t1size->internal->module_data = NULL;
     87    }
     88  }
     89 
     90 
     91  FT_LOCAL_DEF( FT_Error )
     92  T1_Size_Init( FT_Size  t1size )      /* T1_Size */
     93  {
     94    T1_Size            size  = (T1_Size)t1size;
     95    FT_Error           error = FT_Err_Ok;
     96    PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
     97 
     98 
     99    if ( funcs )
    100    {
    101      PSH_Globals  globals;
    102      T1_Face      face = (T1_Face)size->root.face;
    103 
    104 
    105      error = funcs->create( size->root.face->memory,
    106                             &face->type1.private_dict, &globals );
    107      if ( !error )
    108        t1size->internal->module_data = globals;
    109    }
    110 
    111    return error;
    112  }
    113 
    114 
    115  FT_LOCAL_DEF( FT_Error )
    116  T1_Size_Request( FT_Size          t1size,     /* T1_Size */
    117                   FT_Size_Request  req )
    118  {
    119    FT_Error  error;
    120 
    121    T1_Size            size  = (T1_Size)t1size;
    122    PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
    123 
    124 
    125    error = FT_Request_Metrics( size->root.face, req );
    126    if ( error )
    127      goto Exit;
    128 
    129    if ( funcs )
    130      funcs->set_scale( (PSH_Globals)t1size->internal->module_data,
    131                        size->root.metrics.x_scale,
    132                        size->root.metrics.y_scale,
    133                        0, 0 );
    134 
    135  Exit:
    136    return error;
    137  }
    138 
    139 
    140  /**************************************************************************
    141   *
    142   *                           SLOT  FUNCTIONS
    143   *
    144   */
    145 
    146  FT_LOCAL_DEF( void )
    147  T1_GlyphSlot_Done( FT_GlyphSlot  slot )
    148  {
    149    /* `slot->internal` might be NULL in out-of-memory situations. */
    150    if ( slot->internal )
    151      slot->internal->glyph_hints = NULL;
    152  }
    153 
    154 
    155  FT_LOCAL_DEF( FT_Error )
    156  T1_GlyphSlot_Init( FT_GlyphSlot  slot )
    157  {
    158    T1_Face           face;
    159    PSHinter_Service  pshinter;
    160 
    161 
    162    face     = (T1_Face)slot->face;
    163    pshinter = (PSHinter_Service)face->pshinter;
    164 
    165    if ( pshinter )
    166    {
    167      FT_Module  module;
    168 
    169 
    170      module = FT_Get_Module( slot->library, "pshinter" );
    171      if ( module )
    172      {
    173        T1_Hints_Funcs  funcs;
    174 
    175 
    176        funcs = pshinter->get_t1_funcs( module );
    177        slot->internal->glyph_hints = (void*)funcs;
    178      }
    179    }
    180 
    181    return 0;
    182  }
    183 
    184 
    185  /**************************************************************************
    186   *
    187   *                           FACE  FUNCTIONS
    188   *
    189   */
    190 
    191 
    192  /**************************************************************************
    193   *
    194   * @Function:
    195   *   T1_Face_Done
    196   *
    197   * @Description:
    198   *   The face object destructor.
    199   *
    200   * @Input:
    201   *   face ::
    202   *     A typeless pointer to the face object to destroy.
    203   */
    204  FT_LOCAL_DEF( void )
    205  T1_Face_Done( FT_Face  t1face )         /* T1_Face */
    206  {
    207    T1_Face    face = (T1_Face)t1face;
    208    FT_Memory  memory;
    209    T1_Font    type1;
    210 
    211 
    212    if ( !face )
    213      return;
    214 
    215    memory = face->root.memory;
    216    type1  = &face->type1;
    217 
    218 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
    219    /* release multiple masters information */
    220    FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
    221 
    222    if ( face->buildchar )
    223    {
    224      FT_FREE( face->buildchar );
    225 
    226      face->len_buildchar = 0;
    227    }
    228 
    229    T1_Done_Blend( t1face );
    230    face->blend = NULL;
    231 #endif
    232 
    233    /* release font info strings */
    234    {
    235      PS_FontInfo  info = &type1->font_info;
    236 
    237 
    238      FT_FREE( info->version );
    239      FT_FREE( info->notice );
    240      FT_FREE( info->full_name );
    241      FT_FREE( info->family_name );
    242      FT_FREE( info->weight );
    243    }
    244 
    245    /* release top dictionary */
    246    FT_FREE( type1->charstrings_len );
    247    FT_FREE( type1->charstrings );
    248    FT_FREE( type1->glyph_names );
    249 
    250    FT_FREE( type1->subrs );
    251    FT_FREE( type1->subrs_len );
    252 
    253    ft_hash_num_free( type1->subrs_hash, memory );
    254    FT_FREE( type1->subrs_hash );
    255 
    256    FT_FREE( type1->subrs_block );
    257    FT_FREE( type1->charstrings_block );
    258    FT_FREE( type1->glyph_names_block );
    259 
    260    FT_FREE( type1->encoding.char_index );
    261    FT_FREE( type1->encoding.char_name );
    262    FT_FREE( type1->font_name );
    263 
    264 #ifndef T1_CONFIG_OPTION_NO_AFM
    265    /* release afm data if present */
    266    if ( face->afm_data )
    267      T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
    268 #endif
    269 
    270    /* release unicode map, if any */
    271 #if 0
    272    FT_FREE( face->unicode_map_rec.maps );
    273    face->unicode_map_rec.num_maps = 0;
    274    face->unicode_map              = NULL;
    275 #endif
    276 
    277    face->root.family_name = NULL;
    278    face->root.style_name  = NULL;
    279  }
    280 
    281 
    282  /**************************************************************************
    283   *
    284   * @Function:
    285   *   T1_Face_Init
    286   *
    287   * @Description:
    288   *   The face object constructor.
    289   *
    290   * @Input:
    291   *   stream ::
    292   *     Dummy argument for compatibility with the `FT_Face_InitFunc` API.
    293   *     Ignored.  The stream should be passed through `face->root.stream`.
    294   *
    295   *   face_index ::
    296   *     The index of the font face in the resource.
    297   *
    298   *   num_params ::
    299   *     Number of additional generic parameters.  Ignored.
    300   *
    301   *   params ::
    302   *     Additional generic parameters.  Ignored.
    303   *
    304   * @InOut:
    305   *   face ::
    306   *     The face record to build.
    307   *
    308   * @Return:
    309   *   FreeType error code.  0 means success.
    310   */
    311  FT_LOCAL_DEF( FT_Error )
    312  T1_Face_Init( FT_Stream      stream,
    313                FT_Face        t1face,          /* T1_Face */
    314                FT_Int         face_index,
    315                FT_Int         num_params,
    316                FT_Parameter*  params )
    317  {
    318    T1_Face             face = (T1_Face)t1face;
    319    FT_Error            error;
    320    FT_Service_PsCMaps  psnames;
    321    PSAux_Service       psaux;
    322    T1_Font             type1 = &face->type1;
    323    PS_FontInfo         info = &type1->font_info;
    324 
    325    FT_UNUSED( num_params );
    326    FT_UNUSED( params );
    327    FT_UNUSED( stream );
    328 
    329 
    330    face->root.num_faces = 1;
    331 
    332    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    333    face->psnames = psnames;
    334 
    335    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
    336                                           "psaux" );
    337    psaux = (PSAux_Service)face->psaux;
    338    if ( !psaux )
    339    {
    340      FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" ));
    341      error = FT_THROW( Missing_Module );
    342      goto Exit;
    343    }
    344 
    345    face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
    346                                              "pshinter" );
    347 
    348    FT_TRACE2(( "Type 1 driver\n" ));
    349 
    350    /* open the tokenizer; this will also check the font format */
    351    error = T1_Open_Face( face );
    352    if ( error )
    353      goto Exit;
    354 
    355    FT_TRACE2(( "T1_Face_Init: %p (index %d)\n",
    356                (void *)face,
    357                face_index ));
    358 
    359    /* if we just wanted to check the format, leave successfully now */
    360    if ( face_index < 0 )
    361      goto Exit;
    362 
    363    /* check the face index */
    364    if ( ( face_index & 0xFFFF ) > 0 )
    365    {
    366      FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
    367      error = FT_THROW( Invalid_Argument );
    368      goto Exit;
    369    }
    370 
    371    /* now load the font program into the face object */
    372 
    373    /* initialize the face object fields */
    374 
    375    /* set up root face fields */
    376    {
    377      FT_Face  root = (FT_Face)&face->root;
    378 
    379 
    380      root->num_glyphs = type1->num_glyphs;
    381      root->face_index = 0;
    382 
    383      root->face_flags |= FT_FACE_FLAG_SCALABLE    |
    384                          FT_FACE_FLAG_HORIZONTAL  |
    385                          FT_FACE_FLAG_GLYPH_NAMES |
    386                          FT_FACE_FLAG_HINTER;
    387 
    388      if ( info->is_fixed_pitch )
    389        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
    390 
    391      if ( face->blend )
    392        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
    393 
    394      /* The following code to extract the family and the style is very   */
    395      /* simplistic and might get some things wrong.  For a full-featured */
    396      /* algorithm you might have a look at the whitepaper given at       */
    397      /*                                                                  */
    398      /*   https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
    399 
    400      /* get style name -- be careful, some broken fonts only */
    401      /* have a `/FontName' dictionary entry!                 */
    402      root->family_name = info->family_name;
    403      root->style_name  = NULL;
    404 
    405      if ( root->family_name )
    406      {
    407        char*  full   = info->full_name;
    408        char*  family = root->family_name;
    409 
    410 
    411        if ( full )
    412        {
    413          FT_Bool  the_same = TRUE;
    414 
    415 
    416          while ( *full )
    417          {
    418            if ( *full == *family )
    419            {
    420              family++;
    421              full++;
    422            }
    423            else
    424            {
    425              if ( *full == ' ' || *full == '-' )
    426                full++;
    427              else if ( *family == ' ' || *family == '-' )
    428                family++;
    429              else
    430              {
    431                the_same = FALSE;
    432 
    433                if ( !*family )
    434                  root->style_name = full;
    435                break;
    436              }
    437            }
    438          }
    439 
    440          if ( the_same )
    441            root->style_name = (char *)"Regular";
    442        }
    443      }
    444      else
    445      {
    446        /* do we have a `/FontName'? */
    447        if ( type1->font_name )
    448          root->family_name = type1->font_name;
    449      }
    450 
    451      if ( !root->style_name )
    452      {
    453        if ( info->weight )
    454          root->style_name = info->weight;
    455        else
    456          /* assume `Regular' style because we don't know better */
    457          root->style_name = (char *)"Regular";
    458      }
    459 
    460      /* compute style flags */
    461      root->style_flags = 0;
    462      if ( info->italic_angle )
    463        root->style_flags |= FT_STYLE_FLAG_ITALIC;
    464      if ( info->weight )
    465      {
    466        if ( !ft_strcmp( info->weight, "Bold"  ) ||
    467             !ft_strcmp( info->weight, "Black" ) )
    468          root->style_flags |= FT_STYLE_FLAG_BOLD;
    469      }
    470 
    471      /* no embedded bitmap support */
    472      root->num_fixed_sizes = 0;
    473      root->available_sizes = NULL;
    474 
    475      root->bbox.xMin =   type1->font_bbox.xMin            >> 16;
    476      root->bbox.yMin =   type1->font_bbox.yMin            >> 16;
    477      /* no `U' suffix here to 0xFFFF! */
    478      root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;
    479      root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;
    480 
    481      /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */
    482      if ( !root->units_per_EM )
    483        root->units_per_EM = 1000;
    484 
    485      root->ascender  = (FT_Short)( root->bbox.yMax );
    486      root->descender = (FT_Short)( root->bbox.yMin );
    487 
    488      root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
    489      if ( root->height < root->ascender - root->descender )
    490        root->height = (FT_Short)( root->ascender - root->descender );
    491 
    492      /* now compute the maximum advance width */
    493      root->max_advance_width =
    494        (FT_Short)( root->bbox.xMax );
    495      {
    496        FT_Pos  max_advance;
    497 
    498 
    499        error = T1_Compute_Max_Advance( face, &max_advance );
    500 
    501        /* in case of error, keep the standard width */
    502        if ( !error )
    503          root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance );
    504        else
    505          error = FT_Err_Ok;   /* clear error */
    506      }
    507 
    508      root->max_advance_height = root->height;
    509 
    510      root->underline_position  = (FT_Short)info->underline_position;
    511      root->underline_thickness = (FT_Short)info->underline_thickness;
    512    }
    513 
    514    {
    515      FT_Face  root = &face->root;
    516 
    517 
    518      if ( psnames )
    519      {
    520        FT_CharMapRec    charmap;
    521        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
    522        FT_CMap_Class    clazz;
    523 
    524 
    525        charmap.face = root;
    526 
    527        /* first of all, try to synthesize a Unicode charmap */
    528        charmap.platform_id = TT_PLATFORM_MICROSOFT;
    529        charmap.encoding_id = TT_MS_ID_UNICODE_CS;
    530        charmap.encoding    = FT_ENCODING_UNICODE;
    531 
    532        error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
    533        if ( error                                      &&
    534             FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
    535             FT_ERR_NEQ( error, Unimplemented_Feature ) )
    536          goto Exit;
    537        error = FT_Err_Ok;
    538 
    539        /* now, generate an Adobe Standard encoding when appropriate */
    540        charmap.platform_id = TT_PLATFORM_ADOBE;
    541        clazz               = NULL;
    542 
    543        switch ( type1->encoding_type )
    544        {
    545        case T1_ENCODING_TYPE_STANDARD:
    546          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
    547          charmap.encoding_id = TT_ADOBE_ID_STANDARD;
    548          clazz               = cmap_classes->standard;
    549          break;
    550 
    551        case T1_ENCODING_TYPE_EXPERT:
    552          charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
    553          charmap.encoding_id = TT_ADOBE_ID_EXPERT;
    554          clazz               = cmap_classes->expert;
    555          break;
    556 
    557        case T1_ENCODING_TYPE_ARRAY:
    558          charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
    559          charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
    560          clazz               = cmap_classes->custom;
    561          break;
    562 
    563        case T1_ENCODING_TYPE_ISOLATIN1:
    564          charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
    565          charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
    566          clazz               = cmap_classes->unicode;
    567          break;
    568 
    569        default:
    570          ;
    571        }
    572 
    573        if ( clazz )
    574          error = FT_CMap_New( clazz, NULL, &charmap, NULL );
    575      }
    576    }
    577 
    578  Exit:
    579    return error;
    580  }
    581 
    582 
    583  /**************************************************************************
    584   *
    585   * @Function:
    586   *   T1_Driver_Init
    587   *
    588   * @Description:
    589   *   Initializes a given Type 1 driver object.
    590   *
    591   * @Input:
    592   *   driver ::
    593   *     A handle to the target driver object.
    594   *
    595   * @Return:
    596   *   FreeType error code.  0 means success.
    597   */
    598  FT_LOCAL_DEF( FT_Error )
    599  T1_Driver_Init( FT_Module  module )
    600  {
    601    PS_Driver  driver = (PS_Driver)module;
    602 
    603    FT_UInt32  seed;
    604 
    605 
    606    /* set default property values, cf. `ftt1drv.h' */
    607    driver->hinting_engine = FT_HINTING_ADOBE;
    608 
    609    driver->no_stem_darkening = TRUE;
    610 
    611    driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
    612    driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
    613    driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
    614    driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
    615    driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
    616    driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
    617    driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
    618    driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
    619 
    620    /* compute random seed from some memory addresses */
    621    seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
    622                        (FT_Offset)(char*)&module        ^
    623                        (FT_Offset)(char*)module->memory );
    624    seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
    625 
    626    driver->random_seed = (FT_Int32)seed;
    627    if ( driver->random_seed < 0 )
    628      driver->random_seed = -driver->random_seed;
    629    else if ( driver->random_seed == 0 )
    630      driver->random_seed = 123456789;
    631 
    632    return FT_Err_Ok;
    633  }
    634 
    635 
    636  /**************************************************************************
    637   *
    638   * @Function:
    639   *   T1_Driver_Done
    640   *
    641   * @Description:
    642   *   Finalizes a given Type 1 driver.
    643   *
    644   * @Input:
    645   *   driver ::
    646   *     A handle to the target Type 1 driver.
    647   */
    648  FT_LOCAL_DEF( void )
    649  T1_Driver_Done( FT_Module  driver )
    650  {
    651    FT_UNUSED( driver );
    652  }
    653 
    654 
    655 /* END */