1 /***************************************************************************/ 2 /* */ 3 /* afmodule.c */ 4 /* */ 5 /* Auto-fitter module implementation (body). */ 6 /* */ 7 /* Copyright 2003-2016 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,FT_Bool value_is_string)108 af_property_set( FT_Module ft_module, 109 const char* property_name, 110 const void* value, 111 FT_Bool value_is_string ) 112 { 113 FT_Error error = FT_Err_Ok; 114 AF_Module module = (AF_Module)ft_module; 115 116 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 117 FT_UNUSED( value_is_string ); 118 #endif 119 120 121 if ( !ft_strcmp( property_name, "fallback-script" ) ) 122 { 123 FT_UInt* fallback_script; 124 FT_UInt ss; 125 126 127 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 128 if ( value_is_string ) 129 return FT_THROW( Invalid_Argument ); 130 #endif 131 132 fallback_script = (FT_UInt*)value; 133 134 /* We translate the fallback script to a fallback style that uses */ 135 /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its */ 136 /* coverage value. */ 137 for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) 138 { 139 AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; 140 141 142 if ( (FT_UInt)style_class->script == *fallback_script && 143 style_class->coverage == AF_COVERAGE_DEFAULT ) 144 { 145 module->fallback_style = ss; 146 break; 147 } 148 } 149 150 if ( !AF_STYLE_CLASSES_GET[ss] ) 151 { 152 FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n", 153 fallback_script, property_name )); 154 return FT_THROW( Invalid_Argument ); 155 } 156 157 return error; 158 } 159 else if ( !ft_strcmp( property_name, "default-script" ) ) 160 { 161 FT_UInt* default_script; 162 163 164 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 165 if ( value_is_string ) 166 return FT_THROW( Invalid_Argument ); 167 #endif 168 169 default_script = (FT_UInt*)value; 170 171 module->default_script = *default_script; 172 173 return error; 174 } 175 else if ( !ft_strcmp( property_name, "increase-x-height" ) ) 176 { 177 FT_Prop_IncreaseXHeight* prop; 178 AF_FaceGlobals globals; 179 180 181 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 182 if ( value_is_string ) 183 return FT_THROW( Invalid_Argument ); 184 #endif 185 186 prop = (FT_Prop_IncreaseXHeight*)value; 187 188 error = af_property_get_face_globals( prop->face, &globals, module ); 189 if ( !error ) 190 globals->increase_x_height = prop->limit; 191 192 return error; 193 } 194 #ifdef AF_CONFIG_OPTION_USE_WARPER 195 else if ( !ft_strcmp( property_name, "warping" ) ) 196 { 197 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 198 if ( value_is_string ) 199 { 200 const char* s = (const char*)value; 201 long w = ft_strtol( s, NULL, 10 ); 202 203 204 if ( w == 0 ) 205 module->warping = 0; 206 else if ( w == 1 ) 207 module->warping = 1; 208 else 209 return FT_THROW( Invalid_Argument ); 210 } 211 else 212 #endif 213 { 214 FT_Bool* warping = (FT_Bool*)value; 215 216 217 module->warping = *warping; 218 } 219 220 return error; 221 } 222 #endif /* AF_CONFIG_OPTION_USE_WARPER */ 223 else if ( !ft_strcmp( property_name, "darkening-parameters" ) ) 224 { 225 FT_Int* darken_params; 226 FT_Int x1, y1, x2, y2, x3, y3, x4, y4; 227 228 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 229 FT_Int dp[8]; 230 231 232 if ( value_is_string ) 233 { 234 const char* s = (const char*)value; 235 char* ep; 236 int i; 237 238 239 /* eight comma-separated numbers */ 240 for ( i = 0; i < 7; i++ ) 241 { 242 dp[i] = (FT_Int)ft_strtol( s, &ep, 10 ); 243 if ( *ep != ',' || s == ep ) 244 return FT_THROW( Invalid_Argument ); 245 246 s = ep + 1; 247 } 248 249 dp[7] = (FT_Int)ft_strtol( s, &ep, 10 ); 250 if ( !( *ep == '\0' || *ep == ' ' ) || s == ep ) 251 return FT_THROW( Invalid_Argument ); 252 253 darken_params = dp; 254 } 255 else 256 #endif 257 darken_params = (FT_Int*)value; 258 259 x1 = darken_params[0]; 260 y1 = darken_params[1]; 261 x2 = darken_params[2]; 262 y2 = darken_params[3]; 263 x3 = darken_params[4]; 264 y3 = darken_params[5]; 265 x4 = darken_params[6]; 266 y4 = darken_params[7]; 267 268 if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || 269 y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 || 270 x1 > x2 || x2 > x3 || x3 > x4 || 271 y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 ) 272 return FT_THROW( Invalid_Argument ); 273 274 module->darken_params[0] = x1; 275 module->darken_params[1] = y1; 276 module->darken_params[2] = x2; 277 module->darken_params[3] = y2; 278 module->darken_params[4] = x3; 279 module->darken_params[5] = y3; 280 module->darken_params[6] = x4; 281 module->darken_params[7] = y4; 282 283 return error; 284 } 285 else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) 286 { 287 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES 288 if ( value_is_string ) 289 { 290 const char* s = (const char*)value; 291 long nsd = ft_strtol( s, NULL, 10 ); 292 293 294 if ( nsd == 0 ) 295 module->no_stem_darkening = 0; 296 else if ( nsd == 1 ) 297 module->no_stem_darkening = 1; 298 else 299 return FT_THROW( Invalid_Argument ); 300 } 301 else 302 #endif 303 { 304 FT_Bool* no_stem_darkening = (FT_Bool*)value; 305 306 307 module->no_stem_darkening = *no_stem_darkening; 308 } 309 310 return error; 311 } 312 313 FT_TRACE0(( "af_property_set: missing property `%s'\n", 314 property_name )); 315 return FT_THROW( Missing_Property ); 316 } 317 318 319 static FT_Error af_property_get(FT_Module ft_module,const char * property_name,void * value)320 af_property_get( FT_Module ft_module, 321 const char* property_name, 322 void* value ) 323 { 324 FT_Error error = FT_Err_Ok; 325 AF_Module module = (AF_Module)ft_module; 326 FT_UInt fallback_style = module->fallback_style; 327 FT_UInt default_script = module->default_script; 328 #ifdef AF_CONFIG_OPTION_USE_WARPER 329 FT_Bool warping = module->warping; 330 #endif 331 332 333 if ( !ft_strcmp( property_name, "glyph-to-script-map" ) ) 334 { 335 FT_Prop_GlyphToScriptMap* prop = (FT_Prop_GlyphToScriptMap*)value; 336 AF_FaceGlobals globals; 337 338 339 error = af_property_get_face_globals( prop->face, &globals, module ); 340 if ( !error ) 341 prop->map = globals->glyph_styles; 342 343 return error; 344 } 345 else if ( !ft_strcmp( property_name, "fallback-script" ) ) 346 { 347 FT_UInt* val = (FT_UInt*)value; 348 349 AF_StyleClass style_class = AF_STYLE_CLASSES_GET[fallback_style]; 350 351 352 *val = style_class->script; 353 354 return error; 355 } 356 else if ( !ft_strcmp( property_name, "default-script" ) ) 357 { 358 FT_UInt* val = (FT_UInt*)value; 359 360 361 *val = default_script; 362 363 return error; 364 } 365 else if ( !ft_strcmp( property_name, "increase-x-height" ) ) 366 { 367 FT_Prop_IncreaseXHeight* prop = (FT_Prop_IncreaseXHeight*)value; 368 AF_FaceGlobals globals; 369 370 371 error = af_property_get_face_globals( prop->face, &globals, module ); 372 if ( !error ) 373 prop->limit = globals->increase_x_height; 374 375 return error; 376 } 377 #ifdef AF_CONFIG_OPTION_USE_WARPER 378 else if ( !ft_strcmp( property_name, "warping" ) ) 379 { 380 FT_Bool* val = (FT_Bool*)value; 381 382 383 *val = warping; 384 385 return error; 386 } 387 #endif /* AF_CONFIG_OPTION_USE_WARPER */ 388 else if ( !ft_strcmp( property_name, "darkening-parameters" ) ) 389 { 390 FT_Int* darken_params = module->darken_params; 391 FT_Int* val = (FT_Int*)value; 392 393 394 val[0] = darken_params[0]; 395 val[1] = darken_params[1]; 396 val[2] = darken_params[2]; 397 val[3] = darken_params[3]; 398 val[4] = darken_params[4]; 399 val[5] = darken_params[5]; 400 val[6] = darken_params[6]; 401 val[7] = darken_params[7]; 402 403 return error; 404 } 405 else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) 406 { 407 FT_Bool no_stem_darkening = module->no_stem_darkening; 408 FT_Bool* val = (FT_Bool*)value; 409 410 411 *val = no_stem_darkening; 412 413 return error; 414 } 415 416 FT_TRACE0(( "af_property_get: missing property `%s'\n", 417 property_name )); 418 return FT_THROW( Missing_Property ); 419 } 420 421 422 FT_DEFINE_SERVICE_PROPERTIESREC( 423 af_service_properties, 424 (FT_Properties_SetFunc)af_property_set, /* set_property */ 425 (FT_Properties_GetFunc)af_property_get ) /* get_property */ 426 427 428 FT_DEFINE_SERVICEDESCREC1( 429 af_services, 430 FT_SERVICE_ID_PROPERTIES, &AF_SERVICE_PROPERTIES_GET ) 431 432 FT_CALLBACK_DEF(FT_Module_Interface)433 FT_CALLBACK_DEF( FT_Module_Interface ) 434 af_get_interface( FT_Module module, 435 const char* module_interface ) 436 { 437 /* AF_SERVICES_GET dereferences `library' in PIC mode */ 438 #ifdef FT_CONFIG_OPTION_PIC 439 FT_Library library; 440 441 442 if ( !module ) 443 return NULL; 444 library = module->library; 445 if ( !library ) 446 return NULL; 447 #else 448 FT_UNUSED( module ); 449 #endif 450 451 return ft_service_list_lookup( AF_SERVICES_GET, module_interface ); 452 } 453 454 455 FT_CALLBACK_DEF( FT_Error ) af_autofitter_init(FT_Module ft_module)456 af_autofitter_init( FT_Module ft_module ) /* AF_Module */ 457 { 458 AF_Module module = (AF_Module)ft_module; 459 460 461 module->fallback_style = AF_STYLE_FALLBACK; 462 module->default_script = AF_SCRIPT_DEFAULT; 463 #ifdef AF_CONFIG_OPTION_USE_WARPER 464 module->warping = 0; 465 #endif 466 module->no_stem_darkening = TRUE; 467 468 module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; 469 module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; 470 module->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; 471 module->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; 472 module->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; 473 module->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; 474 module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; 475 module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; 476 477 return FT_Err_Ok; 478 } 479 480 481 FT_CALLBACK_DEF( void ) af_autofitter_done(FT_Module ft_module)482 af_autofitter_done( FT_Module ft_module ) /* AF_Module */ 483 { 484 FT_UNUSED( ft_module ); 485 486 #ifdef FT_DEBUG_AUTOFIT 487 if ( _af_debug_hints_rec->memory ) 488 af_glyph_hints_done( _af_debug_hints_rec ); 489 #endif 490 } 491 492 493 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)494 af_autofitter_load_glyph( AF_Module module, 495 FT_GlyphSlot slot, 496 FT_Size size, 497 FT_UInt glyph_index, 498 FT_Int32 load_flags ) 499 { 500 FT_Error error = FT_Err_Ok; 501 FT_Memory memory = module->root.library->memory; 502 503 #ifdef FT_DEBUG_AUTOFIT 504 505 /* in debug mode, we use a global object that survives this routine */ 506 507 AF_GlyphHints hints = _af_debug_hints_rec; 508 AF_LoaderRec loader[1]; 509 510 FT_UNUSED( size ); 511 512 513 if ( hints->memory ) 514 af_glyph_hints_done( hints ); 515 516 af_glyph_hints_init( hints, memory ); 517 af_loader_init( loader, hints ); 518 519 error = af_loader_load_glyph( loader, module, slot->face, 520 glyph_index, load_flags ); 521 522 af_glyph_hints_dump_points( hints, 0 ); 523 af_glyph_hints_dump_segments( hints, 0 ); 524 af_glyph_hints_dump_edges( hints, 0 ); 525 526 af_loader_done( loader ); 527 528 return error; 529 530 #else /* !FT_DEBUG_AUTOFIT */ 531 532 AF_GlyphHintsRec hints[1]; 533 AF_LoaderRec loader[1]; 534 535 FT_UNUSED( size ); 536 537 538 af_glyph_hints_init( hints, memory ); 539 af_loader_init( loader, hints ); 540 541 error = af_loader_load_glyph( loader, module, slot->face, 542 glyph_index, load_flags ); 543 544 af_loader_done( loader ); 545 af_glyph_hints_done( hints ); 546 547 return error; 548 549 #endif /* !FT_DEBUG_AUTOFIT */ 550 } 551 552 553 FT_DEFINE_AUTOHINTER_INTERFACE( 554 af_autofitter_interface, 555 NULL, /* reset_face */ 556 NULL, /* get_global_hints */ 557 NULL, /* done_global_hints */ 558 (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph ) /* load_glyph */ 559 560 561 FT_DEFINE_MODULE( 562 autofit_module_class, 563 564 FT_MODULE_HINTER, 565 sizeof ( AF_ModuleRec ), 566 567 "autofitter", 568 0x10000L, /* version 1.0 of the autofitter */ 569 0x20000L, /* requires FreeType 2.0 or above */ 570 571 (const void*)&AF_INTERFACE_GET, 572 573 (FT_Module_Constructor)af_autofitter_init, 574 (FT_Module_Destructor) af_autofitter_done, 575 (FT_Module_Requester) af_get_interface ) 576 577 578 /* END */ 579