1 /***************************************************************************/ 2 /* */ 3 /* ttdriver.c */ 4 /* */ 5 /* TrueType font driver implementation (body). */ 6 /* */ 7 /* Copyright 1996-2013 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 #include FT_INTERNAL_SFNT_H 23 #include FT_SERVICE_XFREE86_NAME_H 24 25 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 26 #include FT_MULTIPLE_MASTERS_H 27 #include FT_SERVICE_MULTIPLE_MASTERS_H 28 #endif 29 30 #include FT_SERVICE_TRUETYPE_ENGINE_H 31 #include FT_SERVICE_TRUETYPE_GLYF_H 32 #include FT_SERVICE_PROPERTIES_H 33 #include FT_TRUETYPE_DRIVER_H 34 35 #include "ttdriver.h" 36 #include "ttgload.h" 37 #include "ttpload.h" 38 39 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 40 #include "ttgxvar.h" 41 #endif 42 43 #include "tterrors.h" 44 45 #include "ttpic.h" 46 47 /*************************************************************************/ 48 /* */ 49 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 50 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 51 /* messages during execution. */ 52 /* */ 53 #undef FT_COMPONENT 54 #define FT_COMPONENT trace_ttdriver 55 56 57 /* 58 * PROPERTY SERVICE 59 * 60 */ 61 static FT_Error tt_property_set(FT_Module module,const char * property_name,const void * value)62 tt_property_set( FT_Module module, /* TT_Driver */ 63 const char* property_name, 64 const void* value ) 65 { 66 FT_Error error = FT_Err_Ok; 67 TT_Driver driver = (TT_Driver)module; 68 69 70 if ( !ft_strcmp( property_name, "interpreter-version" ) ) 71 { 72 FT_UInt* interpreter_version = (FT_UInt*)value; 73 74 75 #ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING 76 if ( *interpreter_version != TT_INTERPRETER_VERSION_35 ) 77 error = FT_ERR( Unimplemented_Feature ); 78 else 79 #endif 80 driver->interpreter_version = *interpreter_version; 81 82 return error; 83 } 84 85 FT_TRACE0(( "tt_property_set: missing property `%s'\n", 86 property_name )); 87 return FT_THROW( Missing_Property ); 88 } 89 90 91 static FT_Error tt_property_get(FT_Module module,const char * property_name,const void * value)92 tt_property_get( FT_Module module, /* TT_Driver */ 93 const char* property_name, 94 const void* value ) 95 { 96 FT_Error error = FT_Err_Ok; 97 TT_Driver driver = (TT_Driver)module; 98 99 FT_UInt interpreter_version = driver->interpreter_version; 100 101 102 if ( !ft_strcmp( property_name, "interpreter-version" ) ) 103 { 104 FT_UInt* val = (FT_UInt*)value; 105 106 107 *val = interpreter_version; 108 109 return error; 110 } 111 112 FT_TRACE0(( "tt_property_get: missing property `%s'\n", 113 property_name )); 114 return FT_THROW( Missing_Property ); 115 } 116 117 118 FT_DEFINE_SERVICE_PROPERTIESREC( 119 tt_service_properties, 120 (FT_Properties_SetFunc)tt_property_set, 121 (FT_Properties_GetFunc)tt_property_get ) 122 123 124 /*************************************************************************/ 125 /*************************************************************************/ 126 /*************************************************************************/ 127 /**** ****/ 128 /**** ****/ 129 /**** F A C E S ****/ 130 /**** ****/ 131 /**** ****/ 132 /*************************************************************************/ 133 /*************************************************************************/ 134 /*************************************************************************/ 135 136 137 #undef PAIR_TAG 138 #define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ 139 (FT_ULong)right ) 140 141 142 /*************************************************************************/ 143 /* */ 144 /* <Function> */ 145 /* tt_get_kerning */ 146 /* */ 147 /* <Description> */ 148 /* A driver method used to return the kerning vector between two */ 149 /* glyphs of the same face. */ 150 /* */ 151 /* <Input> */ 152 /* face :: A handle to the source face object. */ 153 /* */ 154 /* left_glyph :: The index of the left glyph in the kern pair. */ 155 /* */ 156 /* right_glyph :: The index of the right glyph in the kern pair. */ 157 /* */ 158 /* <Output> */ 159 /* kerning :: The kerning vector. This is in font units for */ 160 /* scalable formats, and in pixels for fixed-sizes */ 161 /* formats. */ 162 /* */ 163 /* <Return> */ 164 /* FreeType error code. 0 means success. */ 165 /* */ 166 /* <Note> */ 167 /* Only horizontal layouts (left-to-right & right-to-left) are */ 168 /* supported by this function. Other layouts, or more sophisticated */ 169 /* kernings, are out of scope of this method (the basic driver */ 170 /* interface is meant to be simple). */ 171 /* */ 172 /* They can be implemented by format-specific interfaces. */ 173 /* */ 174 static FT_Error tt_get_kerning(FT_Face ttface,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)175 tt_get_kerning( FT_Face ttface, /* TT_Face */ 176 FT_UInt left_glyph, 177 FT_UInt right_glyph, 178 FT_Vector* kerning ) 179 { 180 TT_Face face = (TT_Face)ttface; 181 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 182 183 184 kerning->x = 0; 185 kerning->y = 0; 186 187 if ( sfnt ) 188 kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); 189 190 return 0; 191 } 192 193 194 #undef PAIR_TAG 195 196 197 static FT_Error tt_get_advances(FT_Face ttface,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * advances)198 tt_get_advances( FT_Face ttface, 199 FT_UInt start, 200 FT_UInt count, 201 FT_Int32 flags, 202 FT_Fixed *advances ) 203 { 204 FT_UInt nn; 205 TT_Face face = (TT_Face) ttface; 206 207 208 /* XXX: TODO: check for sbits */ 209 210 if ( flags & FT_LOAD_VERTICAL_LAYOUT ) 211 { 212 for ( nn = 0; nn < count; nn++ ) 213 { 214 FT_Short tsb; 215 FT_UShort ah; 216 217 218 /* since we don't need `tsb', we use zero for `yMax' parameter */ 219 TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah ); 220 advances[nn] = ah; 221 } 222 } 223 else 224 { 225 for ( nn = 0; nn < count; nn++ ) 226 { 227 FT_Short lsb; 228 FT_UShort aw; 229 230 231 TT_Get_HMetrics( face, start + nn, &lsb, &aw ); 232 advances[nn] = aw; 233 } 234 } 235 236 return FT_Err_Ok; 237 } 238 239 /*************************************************************************/ 240 /*************************************************************************/ 241 /*************************************************************************/ 242 /**** ****/ 243 /**** ****/ 244 /**** S I Z E S ****/ 245 /**** ****/ 246 /**** ****/ 247 /*************************************************************************/ 248 /*************************************************************************/ 249 /*************************************************************************/ 250 251 252 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 253 254 static FT_Error tt_size_select(FT_Size size,FT_ULong strike_index)255 tt_size_select( FT_Size size, 256 FT_ULong strike_index ) 257 { 258 TT_Face ttface = (TT_Face)size->face; 259 TT_Size ttsize = (TT_Size)size; 260 FT_Error error = FT_Err_Ok; 261 262 263 ttsize->strike_index = strike_index; 264 265 if ( FT_IS_SCALABLE( size->face ) ) 266 { 267 /* use the scaled metrics, even when tt_size_reset fails */ 268 FT_Select_Metrics( size->face, strike_index ); 269 270 tt_size_reset( ttsize ); 271 } 272 else 273 { 274 SFNT_Service sfnt = (SFNT_Service) ttface->sfnt; 275 FT_Size_Metrics* metrics = &size->metrics; 276 277 278 error = sfnt->load_strike_metrics( ttface, strike_index, metrics ); 279 if ( error ) 280 ttsize->strike_index = 0xFFFFFFFFUL; 281 } 282 283 return error; 284 } 285 286 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 287 288 289 static FT_Error tt_size_request(FT_Size size,FT_Size_Request req)290 tt_size_request( FT_Size size, 291 FT_Size_Request req ) 292 { 293 TT_Size ttsize = (TT_Size)size; 294 FT_Error error = FT_Err_Ok; 295 296 297 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 298 299 if ( FT_HAS_FIXED_SIZES( size->face ) ) 300 { 301 TT_Face ttface = (TT_Face)size->face; 302 SFNT_Service sfnt = (SFNT_Service) ttface->sfnt; 303 FT_ULong strike_index; 304 305 306 error = sfnt->set_sbit_strike( ttface, req, &strike_index ); 307 308 if ( error ) 309 ttsize->strike_index = 0xFFFFFFFFUL; 310 else 311 return tt_size_select( size, strike_index ); 312 } 313 314 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 315 316 FT_Request_Metrics( size->face, req ); 317 318 if ( FT_IS_SCALABLE( size->face ) ) 319 { 320 error = tt_size_reset( ttsize ); 321 ttsize->root.metrics = ttsize->metrics; 322 } 323 324 return error; 325 } 326 327 328 /*************************************************************************/ 329 /* */ 330 /* <Function> */ 331 /* tt_glyph_load */ 332 /* */ 333 /* <Description> */ 334 /* A driver method used to load a glyph within a given glyph slot. */ 335 /* */ 336 /* <Input> */ 337 /* slot :: A handle to the target slot object where the glyph */ 338 /* will be loaded. */ 339 /* */ 340 /* size :: A handle to the source face size at which the glyph */ 341 /* must be scaled, loaded, etc. */ 342 /* */ 343 /* glyph_index :: The index of the glyph in the font file. */ 344 /* */ 345 /* load_flags :: A flag indicating what to load for this glyph. The */ 346 /* FT_LOAD_XXX constants can be used to control the */ 347 /* glyph loading process (e.g., whether the outline */ 348 /* should be scaled, whether to load bitmaps or not, */ 349 /* whether to hint the outline, etc). */ 350 /* */ 351 /* <Return> */ 352 /* FreeType error code. 0 means success. */ 353 /* */ 354 static FT_Error tt_glyph_load(FT_GlyphSlot ttslot,FT_Size ttsize,FT_UInt glyph_index,FT_Int32 load_flags)355 tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ 356 FT_Size ttsize, /* TT_Size */ 357 FT_UInt glyph_index, 358 FT_Int32 load_flags ) 359 { 360 TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; 361 TT_Size size = (TT_Size)ttsize; 362 FT_Face face = ttslot->face; 363 FT_Error error; 364 365 366 if ( !slot ) 367 return FT_THROW( Invalid_Slot_Handle ); 368 369 if ( !size ) 370 return FT_THROW( Invalid_Size_Handle ); 371 372 if ( !face ) 373 return FT_THROW( Invalid_Argument ); 374 375 #ifdef FT_CONFIG_OPTION_INCREMENTAL 376 if ( glyph_index >= (FT_UInt)face->num_glyphs && 377 !face->internal->incremental_interface ) 378 #else 379 if ( glyph_index >= (FT_UInt)face->num_glyphs ) 380 #endif 381 return FT_THROW( Invalid_Argument ); 382 383 if ( load_flags & FT_LOAD_NO_HINTING ) 384 { 385 /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */ 386 /* are necessary to disable hinting for tricky fonts */ 387 388 if ( FT_IS_TRICKY( face ) ) 389 load_flags &= ~FT_LOAD_NO_HINTING; 390 391 if ( load_flags & FT_LOAD_NO_AUTOHINT ) 392 load_flags |= FT_LOAD_NO_HINTING; 393 } 394 395 if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) 396 { 397 load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE; 398 399 if ( !FT_IS_TRICKY( face ) ) 400 load_flags |= FT_LOAD_NO_HINTING; 401 } 402 403 /* now load the glyph outline if necessary */ 404 error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); 405 406 /* force drop-out mode to 2 - irrelevant now */ 407 /* slot->outline.dropout_mode = 2; */ 408 409 return error; 410 } 411 412 413 /*************************************************************************/ 414 /*************************************************************************/ 415 /*************************************************************************/ 416 /**** ****/ 417 /**** ****/ 418 /**** D R I V E R I N T E R F A C E ****/ 419 /**** ****/ 420 /**** ****/ 421 /*************************************************************************/ 422 /*************************************************************************/ 423 /*************************************************************************/ 424 425 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 426 FT_DEFINE_SERVICE_MULTIMASTERSREC( 427 tt_service_gx_multi_masters, 428 (FT_Get_MM_Func) NULL, 429 (FT_Set_MM_Design_Func) NULL, 430 (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, 431 (FT_Get_MM_Var_Func) TT_Get_MM_Var, 432 (FT_Set_Var_Design_Func)TT_Set_Var_Design ) 433 #endif 434 435 static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine = 436 { 437 #ifdef TT_USE_BYTECODE_INTERPRETER 438 439 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 440 FT_TRUETYPE_ENGINE_TYPE_UNPATENTED 441 #else 442 FT_TRUETYPE_ENGINE_TYPE_PATENTED 443 #endif 444 445 #else /* !TT_USE_BYTECODE_INTERPRETER */ 446 447 FT_TRUETYPE_ENGINE_TYPE_NONE 448 449 #endif /* TT_USE_BYTECODE_INTERPRETER */ 450 }; 451 452 FT_DEFINE_SERVICE_TTGLYFREC( 453 tt_service_truetype_glyf, 454 (TT_Glyf_GetLocationFunc)tt_face_get_location ) 455 456 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 457 FT_DEFINE_SERVICEDESCREC5( 458 tt_services, 459 FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE, 460 FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET, 461 FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, 462 FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, 463 FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) 464 #else 465 FT_DEFINE_SERVICEDESCREC4( 466 tt_services, 467 FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE, 468 FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, 469 FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, 470 FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) 471 #endif 472 473 FT_CALLBACK_DEF(FT_Module_Interface)474 FT_CALLBACK_DEF( FT_Module_Interface ) 475 tt_get_interface( FT_Module driver, /* TT_Driver */ 476 const char* tt_interface ) 477 { 478 FT_Library library; 479 FT_Module_Interface result; 480 FT_Module sfntd; 481 SFNT_Service sfnt; 482 483 484 /* TT_SERVICES_GET derefers `library' in PIC mode */ 485 #ifdef FT_CONFIG_OPTION_PIC 486 if ( !driver ) 487 return NULL; 488 library = driver->library; 489 if ( !library ) 490 return NULL; 491 #endif 492 493 result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface ); 494 if ( result != NULL ) 495 return result; 496 497 #ifndef FT_CONFIG_OPTION_PIC 498 if ( !driver ) 499 return NULL; 500 library = driver->library; 501 if ( !library ) 502 return NULL; 503 #endif 504 505 /* only return the default interface from the SFNT module */ 506 sfntd = FT_Get_Module( library, "sfnt" ); 507 if ( sfntd ) 508 { 509 sfnt = (SFNT_Service)( sfntd->clazz->module_interface ); 510 if ( sfnt ) 511 return sfnt->get_interface( driver, tt_interface ); 512 } 513 514 return 0; 515 } 516 517 518 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 519 520 #ifdef TT_USE_BYTECODE_INTERPRETER 521 #define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER 522 #else 523 #define TT_HINTER_FLAG 0 524 #endif 525 526 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 527 #define TT_SIZE_SELECT tt_size_select 528 #else 529 #define TT_SIZE_SELECT 0 530 #endif 531 532 FT_DEFINE_DRIVER( 533 tt_driver_class, 534 535 FT_MODULE_FONT_DRIVER | 536 FT_MODULE_DRIVER_SCALABLE | 537 TT_HINTER_FLAG, 538 539 sizeof ( TT_DriverRec ), 540 541 "truetype", /* driver name */ 542 0x10000L, /* driver version == 1.0 */ 543 0x20000L, /* driver requires FreeType 2.0 or above */ 544 545 (void*)0, /* driver specific interface */ 546 547 tt_driver_init, 548 tt_driver_done, 549 tt_get_interface, 550 551 sizeof ( TT_FaceRec ), 552 sizeof ( TT_SizeRec ), 553 sizeof ( FT_GlyphSlotRec ), 554 555 tt_face_init, 556 tt_face_done, 557 tt_size_init, 558 tt_size_done, 559 tt_slot_init, 560 0, /* FT_Slot_DoneFunc */ 561 562 tt_glyph_load, 563 564 tt_get_kerning, 565 0, /* FT_Face_AttachFunc */ 566 tt_get_advances, 567 568 tt_size_request, 569 TT_SIZE_SELECT 570 ) 571 572 573 /* END */ 574