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 af_property_get_face_globals(FT_Face face,AF_FaceGlobals * aglobals,AF_Module module)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 af_property_set(FT_Module ft_module,const char * property_name,const void * value)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 af_property_get(FT_Module ft_module,const char * property_name,void * value)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 FT_CALLBACK_DEF(FT_Module_Interface)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 ) af_autofitter_init(FT_Module ft_module)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 ) af_autofitter_done(FT_Module ft_module)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 ) af_autofitter_load_glyph(AF_Module module,FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)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