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