tor-browser

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

afmodule.c (14279B)


      1 /****************************************************************************
      2 *
      3 * afmodule.c
      4 *
      5 *   Auto-fitter module implementation (body).
      6 *
      7 * Copyright (C) 2003-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 "afglobal.h"
     20 #include "afmodule.h"
     21 #include "afloader.h"
     22 #include "aferrors.h"
     23 
     24 #ifdef FT_DEBUG_AUTOFIT
     25 
     26 #ifndef FT_MAKE_OPTION_SINGLE_OBJECT
     27 
     28 #ifdef __cplusplus
     29  extern "C" {
     30 #endif
     31  extern void
     32  af_glyph_hints_dump_segments( AF_GlyphHints  hints,
     33                                FT_Bool        to_stdout );
     34  extern void
     35  af_glyph_hints_dump_points( AF_GlyphHints  hints,
     36                              FT_Bool        to_stdout );
     37  extern void
     38  af_glyph_hints_dump_edges( AF_GlyphHints  hints,
     39                             FT_Bool        to_stdout );
     40 #ifdef __cplusplus
     41  }
     42 #endif
     43 
     44 #endif
     45 
     46  int  af_debug_disable_horz_hints_;
     47  int  af_debug_disable_vert_hints_;
     48  int  af_debug_disable_blue_hints_;
     49 
     50  /* we use a global object instead of a local one for debugging */
     51  static AF_GlyphHintsRec  af_debug_hints_rec_[1];
     52 
     53  void*  af_debug_hints_ = af_debug_hints_rec_;
     54 #endif
     55 
     56 #include <freetype/internal/ftobjs.h>
     57 #include <freetype/internal/ftdebug.h>
     58 #include <freetype/ftdriver.h>
     59 #include <freetype/internal/services/svprop.h>
     60 
     61 
     62  /**************************************************************************
     63   *
     64   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     65   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     66   * messages during execution.
     67   */
     68 #undef  FT_COMPONENT
     69 #define FT_COMPONENT  afmodule
     70 
     71 
     72  static FT_Error
     73  af_property_get_face_globals( FT_Face          face,
     74                                AF_FaceGlobals*  aglobals,
     75                                AF_Module        module )
     76  {
     77    FT_Error        error = FT_Err_Ok;
     78    AF_FaceGlobals  globals;
     79 
     80 
     81    if ( !face )
     82      return FT_THROW( Invalid_Face_Handle );
     83 
     84    globals = (AF_FaceGlobals)face->autohint.data;
     85    if ( !globals )
     86    {
     87      /* trigger computation of the global style data */
     88      /* in case it hasn't been done yet              */
     89      error = af_face_globals_new( face, &globals, module );
     90      if ( !error )
     91      {
     92        face->autohint.data      = (FT_Pointer)globals;
     93        face->autohint.finalizer = af_face_globals_free;
     94      }
     95    }
     96 
     97    if ( !error )
     98      *aglobals = globals;
     99 
    100    return error;
    101  }
    102 
    103 
    104  static FT_Error
    105  af_property_set( FT_Module    ft_module,
    106                   const char*  property_name,
    107                   const void*  value,
    108                   FT_Bool      value_is_string )
    109  {
    110    FT_Error   error  = FT_Err_Ok;
    111    AF_Module  module = (AF_Module)ft_module;
    112 
    113 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    114    FT_UNUSED( value_is_string );
    115 #endif
    116 
    117 
    118    if ( !ft_strcmp( property_name, "fallback-script" ) )
    119    {
    120      AF_Script*  fallback_script;
    121      FT_UInt     ss;
    122 
    123 
    124 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    125      if ( value_is_string )
    126        return FT_THROW( Invalid_Argument );
    127 #endif
    128 
    129      fallback_script = (AF_Script*)value;
    130 
    131      /* We translate the fallback script to a fallback style that uses */
    132      /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its  */
    133      /* coverage value.                                                */
    134      for ( ss = 0; af_style_classes[ss]; ss++ )
    135      {
    136        AF_StyleClass  style_class = af_style_classes[ss];
    137 
    138 
    139        if ( style_class->script   == *fallback_script    &&
    140             style_class->coverage == AF_COVERAGE_DEFAULT )
    141        {
    142          module->fallback_style = ss;
    143          break;
    144        }
    145      }
    146 
    147      if ( !af_style_classes[ss] )
    148      {
    149        FT_TRACE2(( "af_property_set: Invalid value %u for property `%s'\n",
    150                    *fallback_script, property_name ));
    151        return FT_THROW( Invalid_Argument );
    152      }
    153 
    154      return error;
    155    }
    156    else if ( !ft_strcmp( property_name, "default-script" ) )
    157    {
    158      AF_Script*  default_script;
    159 
    160 
    161 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    162      if ( value_is_string )
    163        return FT_THROW( Invalid_Argument );
    164 #endif
    165 
    166      default_script = (AF_Script*)value;
    167 
    168      module->default_script = *default_script;
    169 
    170      return error;
    171    }
    172    else if ( !ft_strcmp( property_name, "increase-x-height" ) )
    173    {
    174      FT_Prop_IncreaseXHeight*  prop;
    175      AF_FaceGlobals            globals;
    176 
    177 
    178 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    179      if ( value_is_string )
    180        return FT_THROW( Invalid_Argument );
    181 #endif
    182 
    183      prop = (FT_Prop_IncreaseXHeight*)value;
    184 
    185      error = af_property_get_face_globals( prop->face, &globals, module );
    186      if ( !error )
    187        globals->increase_x_height = prop->limit;
    188 
    189      return error;
    190    }
    191    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    192    {
    193      FT_Int*  darken_params;
    194      FT_Int   x1, y1, x2, y2, x3, y3, x4, y4;
    195 
    196 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    197      FT_Int   dp[8];
    198 
    199 
    200      if ( value_is_string )
    201      {
    202        const char*  s = (const char*)value;
    203        char*        ep;
    204        int          i;
    205 
    206 
    207        /* eight comma-separated numbers */
    208        for ( i = 0; i < 7; i++ )
    209        {
    210          dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
    211          if ( *ep != ',' || s == ep )
    212            return FT_THROW( Invalid_Argument );
    213 
    214          s = ep + 1;
    215        }
    216 
    217        dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
    218        if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
    219          return FT_THROW( Invalid_Argument );
    220 
    221        darken_params = dp;
    222      }
    223      else
    224 #endif
    225        darken_params = (FT_Int*)value;
    226 
    227      x1 = darken_params[0];
    228      y1 = darken_params[1];
    229      x2 = darken_params[2];
    230      y2 = darken_params[3];
    231      x3 = darken_params[4];
    232      y3 = darken_params[5];
    233      x4 = darken_params[6];
    234      y4 = darken_params[7];
    235 
    236      if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
    237           y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
    238           x1 > x2  || x2 > x3  || x3 > x4              ||
    239           y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
    240        return FT_THROW( Invalid_Argument );
    241 
    242      module->darken_params[0] = x1;
    243      module->darken_params[1] = y1;
    244      module->darken_params[2] = x2;
    245      module->darken_params[3] = y2;
    246      module->darken_params[4] = x3;
    247      module->darken_params[5] = y3;
    248      module->darken_params[6] = x4;
    249      module->darken_params[7] = y4;
    250 
    251      return error;
    252    }
    253    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    254    {
    255 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    256      if ( value_is_string )
    257      {
    258        const char*  s   = (const char*)value;
    259        long         nsd = ft_strtol( s, NULL, 10 );
    260 
    261 
    262        if ( !nsd )
    263          module->no_stem_darkening = FALSE;
    264        else
    265          module->no_stem_darkening = TRUE;
    266      }
    267      else
    268 #endif
    269      {
    270        FT_Bool*  no_stem_darkening = (FT_Bool*)value;
    271 
    272 
    273        module->no_stem_darkening = *no_stem_darkening;
    274      }
    275 
    276      return error;
    277    }
    278 
    279    FT_TRACE2(( "af_property_set: missing property `%s'\n",
    280                property_name ));
    281    return FT_THROW( Missing_Property );
    282  }
    283 
    284 
    285  static FT_Error
    286  af_property_get( FT_Module    ft_module,
    287                   const char*  property_name,
    288                   void*        value )
    289  {
    290    FT_Error   error          = FT_Err_Ok;
    291    AF_Module  module         = (AF_Module)ft_module;
    292 
    293 
    294    if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
    295    {
    296      FT_Prop_GlyphToScriptMap*  prop = (FT_Prop_GlyphToScriptMap*)value;
    297      AF_FaceGlobals             globals;
    298 
    299 
    300      error = af_property_get_face_globals( prop->face, &globals, module );
    301      if ( !error )
    302        prop->map = globals->glyph_styles;
    303 
    304      return error;
    305    }
    306    else if ( !ft_strcmp( property_name, "fallback-script" ) )
    307    {
    308      AF_Script*  val = (AF_Script*)value;
    309 
    310      AF_StyleClass  style_class = af_style_classes[module->fallback_style];
    311 
    312 
    313      *val = style_class->script;
    314 
    315      return error;
    316    }
    317    else if ( !ft_strcmp( property_name, "default-script" ) )
    318    {
    319      AF_Script*  val = (AF_Script*)value;
    320 
    321 
    322      *val = module->default_script;
    323 
    324      return error;
    325    }
    326    else if ( !ft_strcmp( property_name, "increase-x-height" ) )
    327    {
    328      FT_Prop_IncreaseXHeight*  prop = (FT_Prop_IncreaseXHeight*)value;
    329      AF_FaceGlobals            globals;
    330 
    331 
    332      error = af_property_get_face_globals( prop->face, &globals, module );
    333      if ( !error )
    334        prop->limit = globals->increase_x_height;
    335 
    336      return error;
    337    }
    338    else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    339    {
    340      FT_Int*  darken_params = module->darken_params;
    341      FT_Int*  val           = (FT_Int*)value;
    342 
    343 
    344      val[0] = darken_params[0];
    345      val[1] = darken_params[1];
    346      val[2] = darken_params[2];
    347      val[3] = darken_params[3];
    348      val[4] = darken_params[4];
    349      val[5] = darken_params[5];
    350      val[6] = darken_params[6];
    351      val[7] = darken_params[7];
    352 
    353      return error;
    354    }
    355    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    356    {
    357      FT_Bool   no_stem_darkening = module->no_stem_darkening;
    358      FT_Bool*  val               = (FT_Bool*)value;
    359 
    360 
    361      *val = no_stem_darkening;
    362 
    363      return error;
    364    }
    365 
    366    FT_TRACE2(( "af_property_get: missing property `%s'\n",
    367                property_name ));
    368    return FT_THROW( Missing_Property );
    369  }
    370 
    371 
    372  FT_DEFINE_SERVICE_PROPERTIESREC(
    373    af_service_properties,
    374 
    375    af_property_set,  /* FT_Properties_SetFunc set_property */
    376    af_property_get   /* FT_Properties_GetFunc get_property */
    377  )
    378 
    379 
    380  FT_DEFINE_SERVICEDESCREC1(
    381    af_services,
    382 
    383    FT_SERVICE_ID_PROPERTIES, &af_service_properties )
    384 
    385 
    386  FT_CALLBACK_DEF( FT_Module_Interface )
    387  af_get_interface( FT_Module    module,
    388                    const char*  module_interface )
    389  {
    390    FT_UNUSED( module );
    391 
    392    return ft_service_list_lookup( af_services, module_interface );
    393  }
    394 
    395 
    396  FT_CALLBACK_DEF( FT_Error )
    397  af_autofitter_init( FT_Module  ft_module )      /* AF_Module */
    398  {
    399    AF_Module  module = (AF_Module)ft_module;
    400 
    401 
    402    module->fallback_style    = AF_STYLE_FALLBACK;
    403    module->default_script    = AF_SCRIPT_DEFAULT;
    404    module->no_stem_darkening = TRUE;
    405 
    406    module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
    407    module->darken_params[1]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
    408    module->darken_params[2]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
    409    module->darken_params[3]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
    410    module->darken_params[4]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
    411    module->darken_params[5]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
    412    module->darken_params[6]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
    413    module->darken_params[7]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
    414 
    415 #if defined( FT_CONFIG_OPTION_USE_HARFBUZZ )         && \
    416    defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
    417    ft_hb_funcs_init( module );
    418 #endif
    419 
    420    return FT_Err_Ok;
    421  }
    422 
    423 
    424  FT_CALLBACK_DEF( void )
    425  af_autofitter_done( FT_Module  ft_module )      /* AF_Module */
    426  {
    427    FT_UNUSED( ft_module );
    428 
    429 #if defined( FT_CONFIG_OPTION_USE_HARFBUZZ )         && \
    430    defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
    431    ft_hb_funcs_done( (AF_Module)ft_module );
    432 #endif
    433 
    434 #ifdef FT_DEBUG_AUTOFIT
    435    if ( af_debug_hints_rec_->memory )
    436      af_glyph_hints_done( af_debug_hints_rec_ );
    437 #endif
    438  }
    439 
    440 
    441  FT_CALLBACK_DEF( FT_Error )
    442  af_autofitter_load_glyph( FT_AutoHinter  module_,
    443                            FT_GlyphSlot   slot,
    444                            FT_Size        size,
    445                            FT_UInt        glyph_index,
    446                            FT_Int32       load_flags )
    447  {
    448    AF_Module  module = (AF_Module)module_;
    449 
    450    FT_Error   error  = FT_Err_Ok;
    451    FT_Memory  memory = module->root.memory;
    452 
    453 #ifdef FT_DEBUG_AUTOFIT
    454 
    455    /* in debug mode, we use a global object that survives this routine */
    456 
    457    AF_GlyphHints  hints = af_debug_hints_rec_;
    458    AF_LoaderRec   loader[1];
    459 
    460    FT_UNUSED( size );
    461 
    462 
    463    if ( hints->memory )
    464      af_glyph_hints_done( hints );
    465 
    466    af_glyph_hints_init( hints, memory );
    467    af_loader_init( loader, hints );
    468 
    469    error = af_loader_load_glyph( loader, module, slot->face,
    470                                  glyph_index, load_flags );
    471 
    472 #ifdef FT_DEBUG_LEVEL_TRACE
    473    if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] )
    474    {
    475 #endif
    476      af_glyph_hints_dump_points( hints, 0 );
    477      af_glyph_hints_dump_segments( hints, 0 );
    478      af_glyph_hints_dump_edges( hints, 0 );
    479 #ifdef FT_DEBUG_LEVEL_TRACE
    480    }
    481 #endif
    482 
    483    af_loader_done( loader );
    484 
    485    return error;
    486 
    487 #else /* !FT_DEBUG_AUTOFIT */
    488 
    489    AF_GlyphHintsRec  hints[1];
    490    AF_LoaderRec      loader[1];
    491 
    492    FT_UNUSED( size );
    493 
    494 
    495    af_glyph_hints_init( hints, memory );
    496    af_loader_init( loader, hints );
    497 
    498    error = af_loader_load_glyph( loader, module, slot->face,
    499                                  glyph_index, load_flags );
    500 
    501    af_loader_done( loader );
    502    af_glyph_hints_done( hints );
    503 
    504    return error;
    505 
    506 #endif /* !FT_DEBUG_AUTOFIT */
    507  }
    508 
    509 
    510  FT_DEFINE_AUTOHINTER_INTERFACE(
    511    af_autofitter_interface,
    512 
    513    NULL,                     /* FT_AutoHinter_GlobalResetFunc reset_face        */
    514    NULL,                     /* FT_AutoHinter_GlobalGetFunc   get_global_hints  */
    515    NULL,                     /* FT_AutoHinter_GlobalDoneFunc  done_global_hints */
    516    af_autofitter_load_glyph  /* FT_AutoHinter_GlyphLoadFunc   load_glyph        */
    517  )
    518 
    519  FT_DEFINE_MODULE(
    520    autofit_module_class,
    521 
    522    FT_MODULE_HINTER,
    523    sizeof ( AF_ModuleRec ),
    524 
    525    "autofitter",
    526    0x10000L,   /* version 1.0 of the autofitter  */
    527    0x20000L,   /* requires FreeType 2.0 or above */
    528 
    529    (const void*)&af_autofitter_interface,
    530 
    531    af_autofitter_init,  /* FT_Module_Constructor module_init   */
    532    af_autofitter_done,  /* FT_Module_Destructor  module_done   */
    533    af_get_interface     /* FT_Module_Requester   get_interface */
    534  )
    535 
    536 
    537 /* END */