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