OLD | NEW |
(Empty) | |
| 1 /***************************************************************************/ |
| 2 /* */ |
| 3 /* ftcbasic.c */ |
| 4 /* */ |
| 5 /* The FreeType basic cache interface (body). */ |
| 6 /* */ |
| 7 /* Copyright 2003-2007, 2009-2011, 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_OBJECTS_H |
| 21 #include FT_INTERNAL_DEBUG_H |
| 22 #include FT_CACHE_H |
| 23 #include "ftcglyph.h" |
| 24 #include "ftcimage.h" |
| 25 #include "ftcsbits.h" |
| 26 |
| 27 #include "ftccback.h" |
| 28 #include "ftcerror.h" |
| 29 |
| 30 #define FT_COMPONENT trace_cache |
| 31 |
| 32 |
| 33 /* |
| 34 * Basic Families |
| 35 * |
| 36 */ |
| 37 typedef struct FTC_BasicAttrRec_ |
| 38 { |
| 39 FTC_ScalerRec scaler; |
| 40 FT_UInt load_flags; |
| 41 |
| 42 } FTC_BasicAttrRec, *FTC_BasicAttrs; |
| 43 |
| 44 #define FTC_BASIC_ATTR_COMPARE( a, b ) \ |
| 45 FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \ |
| 46 (a)->load_flags == (b)->load_flags ) |
| 47 |
| 48 #define FTC_BASIC_ATTR_HASH( a ) \ |
| 49 ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags ) |
| 50 |
| 51 |
| 52 typedef struct FTC_BasicQueryRec_ |
| 53 { |
| 54 FTC_GQueryRec gquery; |
| 55 FTC_BasicAttrRec attrs; |
| 56 |
| 57 } FTC_BasicQueryRec, *FTC_BasicQuery; |
| 58 |
| 59 |
| 60 typedef struct FTC_BasicFamilyRec_ |
| 61 { |
| 62 FTC_FamilyRec family; |
| 63 FTC_BasicAttrRec attrs; |
| 64 |
| 65 } FTC_BasicFamilyRec, *FTC_BasicFamily; |
| 66 |
| 67 |
| 68 FT_CALLBACK_DEF( FT_Bool ) |
| 69 ftc_basic_family_compare( FTC_MruNode ftcfamily, |
| 70 FT_Pointer ftcquery ) |
| 71 { |
| 72 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
| 73 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
| 74 |
| 75 |
| 76 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ); |
| 77 } |
| 78 |
| 79 |
| 80 FT_CALLBACK_DEF( FT_Error ) |
| 81 ftc_basic_family_init( FTC_MruNode ftcfamily, |
| 82 FT_Pointer ftcquery, |
| 83 FT_Pointer ftccache ) |
| 84 { |
| 85 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
| 86 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
| 87 FTC_Cache cache = (FTC_Cache)ftccache; |
| 88 |
| 89 |
| 90 FTC_Family_Init( FTC_FAMILY( family ), cache ); |
| 91 family->attrs = query->attrs; |
| 92 return 0; |
| 93 } |
| 94 |
| 95 |
| 96 FT_CALLBACK_DEF( FT_UInt ) |
| 97 ftc_basic_family_get_count( FTC_Family ftcfamily, |
| 98 FTC_Manager manager ) |
| 99 { |
| 100 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
| 101 FT_Error error; |
| 102 FT_Face face; |
| 103 FT_UInt result = 0; |
| 104 |
| 105 |
| 106 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id, |
| 107 &face ); |
| 108 |
| 109 if ( error || !face ) |
| 110 return result; |
| 111 |
| 112 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs ) |
| 113 { |
| 114 FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " )); |
| 115 FT_TRACE1(( "in this face, truncated\n", face->num_glyphs )); |
| 116 } |
| 117 |
| 118 if ( !error ) |
| 119 result = (FT_UInt)face->num_glyphs; |
| 120 |
| 121 return result; |
| 122 } |
| 123 |
| 124 |
| 125 FT_CALLBACK_DEF( FT_Error ) |
| 126 ftc_basic_family_load_bitmap( FTC_Family ftcfamily, |
| 127 FT_UInt gindex, |
| 128 FTC_Manager manager, |
| 129 FT_Face *aface ) |
| 130 { |
| 131 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
| 132 FT_Error error; |
| 133 FT_Size size; |
| 134 |
| 135 |
| 136 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size ); |
| 137 if ( !error ) |
| 138 { |
| 139 FT_Face face = size->face; |
| 140 |
| 141 |
| 142 error = FT_Load_Glyph( face, gindex, |
| 143 family->attrs.load_flags | FT_LOAD_RENDER ); |
| 144 if ( !error ) |
| 145 *aface = face; |
| 146 } |
| 147 |
| 148 return error; |
| 149 } |
| 150 |
| 151 |
| 152 FT_CALLBACK_DEF( FT_Error ) |
| 153 ftc_basic_family_load_glyph( FTC_Family ftcfamily, |
| 154 FT_UInt gindex, |
| 155 FTC_Cache cache, |
| 156 FT_Glyph *aglyph ) |
| 157 { |
| 158 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
| 159 FT_Error error; |
| 160 FTC_Scaler scaler = &family->attrs.scaler; |
| 161 FT_Face face; |
| 162 FT_Size size; |
| 163 |
| 164 |
| 165 /* we will now load the glyph image */ |
| 166 error = FTC_Manager_LookupSize( cache->manager, |
| 167 scaler, |
| 168 &size ); |
| 169 if ( !error ) |
| 170 { |
| 171 face = size->face; |
| 172 |
| 173 error = FT_Load_Glyph( face, gindex, family->attrs.load_flags ); |
| 174 if ( !error ) |
| 175 { |
| 176 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || |
| 177 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) |
| 178 { |
| 179 /* ok, copy it */ |
| 180 FT_Glyph glyph; |
| 181 |
| 182 |
| 183 error = FT_Get_Glyph( face->glyph, &glyph ); |
| 184 if ( !error ) |
| 185 { |
| 186 *aglyph = glyph; |
| 187 goto Exit; |
| 188 } |
| 189 } |
| 190 else |
| 191 error = FT_THROW( Invalid_Argument ); |
| 192 } |
| 193 } |
| 194 |
| 195 Exit: |
| 196 return error; |
| 197 } |
| 198 |
| 199 |
| 200 FT_CALLBACK_DEF( FT_Bool ) |
| 201 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode, |
| 202 FT_Pointer ftcface_id, |
| 203 FTC_Cache cache, |
| 204 FT_Bool* list_changed ) |
| 205 { |
| 206 FTC_GNode gnode = (FTC_GNode)ftcgnode; |
| 207 FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
| 208 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family; |
| 209 FT_Bool result; |
| 210 |
| 211 |
| 212 if ( list_changed ) |
| 213 *list_changed = FALSE; |
| 214 result = FT_BOOL( family->attrs.scaler.face_id == face_id ); |
| 215 if ( result ) |
| 216 { |
| 217 /* we must call this function to avoid this node from appearing |
| 218 * in later lookups with the same face_id! |
| 219 */ |
| 220 FTC_GNode_UnselectFamily( gnode, cache ); |
| 221 } |
| 222 return result; |
| 223 } |
| 224 |
| 225 |
| 226 /* |
| 227 * |
| 228 * basic image cache |
| 229 * |
| 230 */ |
| 231 |
| 232 FT_CALLBACK_TABLE_DEF |
| 233 const FTC_IFamilyClassRec ftc_basic_image_family_class = |
| 234 { |
| 235 { |
| 236 sizeof ( FTC_BasicFamilyRec ), |
| 237 ftc_basic_family_compare, |
| 238 ftc_basic_family_init, |
| 239 0, /* FTC_MruNode_ResetFunc */ |
| 240 0 /* FTC_MruNode_DoneFunc */ |
| 241 }, |
| 242 ftc_basic_family_load_glyph |
| 243 }; |
| 244 |
| 245 |
| 246 FT_CALLBACK_TABLE_DEF |
| 247 const FTC_GCacheClassRec ftc_basic_image_cache_class = |
| 248 { |
| 249 { |
| 250 ftc_inode_new, |
| 251 ftc_inode_weight, |
| 252 ftc_gnode_compare, |
| 253 ftc_basic_gnode_compare_faceid, |
| 254 ftc_inode_free, |
| 255 |
| 256 sizeof ( FTC_GCacheRec ), |
| 257 ftc_gcache_init, |
| 258 ftc_gcache_done |
| 259 }, |
| 260 (FTC_MruListClass)&ftc_basic_image_family_class |
| 261 }; |
| 262 |
| 263 |
| 264 /* documentation is in ftcache.h */ |
| 265 |
| 266 FT_EXPORT_DEF( FT_Error ) |
| 267 FTC_ImageCache_New( FTC_Manager manager, |
| 268 FTC_ImageCache *acache ) |
| 269 { |
| 270 return FTC_GCache_New( manager, &ftc_basic_image_cache_class, |
| 271 (FTC_GCache*)acache ); |
| 272 } |
| 273 |
| 274 |
| 275 /* documentation is in ftcache.h */ |
| 276 |
| 277 FT_EXPORT_DEF( FT_Error ) |
| 278 FTC_ImageCache_Lookup( FTC_ImageCache cache, |
| 279 FTC_ImageType type, |
| 280 FT_UInt gindex, |
| 281 FT_Glyph *aglyph, |
| 282 FTC_Node *anode ) |
| 283 { |
| 284 FTC_BasicQueryRec query; |
| 285 FTC_Node node = 0; /* make compiler happy */ |
| 286 FT_Error error; |
| 287 FT_PtrDist hash; |
| 288 |
| 289 |
| 290 /* some argument checks are delayed to FTC_Cache_Lookup */ |
| 291 if ( !aglyph ) |
| 292 { |
| 293 error = FT_THROW( Invalid_Argument ); |
| 294 goto Exit; |
| 295 } |
| 296 |
| 297 *aglyph = NULL; |
| 298 if ( anode ) |
| 299 *anode = NULL; |
| 300 |
| 301 { |
| 302 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
| 303 { |
| 304 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
| 305 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX
)) )); |
| 306 } |
| 307 |
| 308 query.attrs.scaler.face_id = type->face_id; |
| 309 query.attrs.scaler.width = type->width; |
| 310 query.attrs.scaler.height = type->height; |
| 311 query.attrs.load_flags = (FT_UInt)type->flags; |
| 312 } |
| 313 |
| 314 query.attrs.scaler.pixel = 1; |
| 315 query.attrs.scaler.x_res = 0; /* make compilers happy */ |
| 316 query.attrs.scaler.y_res = 0; |
| 317 |
| 318 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
| 319 |
| 320 #if 1 /* inlining is about 50% faster! */ |
| 321 FTC_GCACHE_LOOKUP_CMP( cache, |
| 322 ftc_basic_family_compare, |
| 323 FTC_GNode_Compare, |
| 324 hash, gindex, |
| 325 &query, |
| 326 node, |
| 327 error ); |
| 328 #else |
| 329 error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
| 330 hash, gindex, |
| 331 FTC_GQUERY( &query ), |
| 332 &node ); |
| 333 #endif |
| 334 if ( !error ) |
| 335 { |
| 336 *aglyph = FTC_INODE( node )->glyph; |
| 337 |
| 338 if ( anode ) |
| 339 { |
| 340 *anode = node; |
| 341 node->ref_count++; |
| 342 } |
| 343 } |
| 344 |
| 345 Exit: |
| 346 return error; |
| 347 } |
| 348 |
| 349 |
| 350 /* documentation is in ftcache.h */ |
| 351 |
| 352 FT_EXPORT_DEF( FT_Error ) |
| 353 FTC_ImageCache_LookupScaler( FTC_ImageCache cache, |
| 354 FTC_Scaler scaler, |
| 355 FT_ULong load_flags, |
| 356 FT_UInt gindex, |
| 357 FT_Glyph *aglyph, |
| 358 FTC_Node *anode ) |
| 359 { |
| 360 FTC_BasicQueryRec query; |
| 361 FTC_Node node = 0; /* make compiler happy */ |
| 362 FT_Error error; |
| 363 FT_PtrDist hash; |
| 364 |
| 365 |
| 366 /* some argument checks are delayed to FTC_Cache_Lookup */ |
| 367 if ( !aglyph || !scaler ) |
| 368 { |
| 369 error = FT_THROW( Invalid_Argument ); |
| 370 goto Exit; |
| 371 } |
| 372 |
| 373 *aglyph = NULL; |
| 374 if ( anode ) |
| 375 *anode = NULL; |
| 376 |
| 377 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
| 378 if ( load_flags > FT_UINT_MAX ) |
| 379 { |
| 380 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
| 381 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX))
)); |
| 382 } |
| 383 |
| 384 query.attrs.scaler = scaler[0]; |
| 385 query.attrs.load_flags = (FT_UInt)load_flags; |
| 386 |
| 387 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
| 388 |
| 389 FTC_GCACHE_LOOKUP_CMP( cache, |
| 390 ftc_basic_family_compare, |
| 391 FTC_GNode_Compare, |
| 392 hash, gindex, |
| 393 &query, |
| 394 node, |
| 395 error ); |
| 396 if ( !error ) |
| 397 { |
| 398 *aglyph = FTC_INODE( node )->glyph; |
| 399 |
| 400 if ( anode ) |
| 401 { |
| 402 *anode = node; |
| 403 node->ref_count++; |
| 404 } |
| 405 } |
| 406 |
| 407 Exit: |
| 408 return error; |
| 409 } |
| 410 |
| 411 |
| 412 /* |
| 413 * |
| 414 * basic small bitmap cache |
| 415 * |
| 416 */ |
| 417 |
| 418 FT_CALLBACK_TABLE_DEF |
| 419 const FTC_SFamilyClassRec ftc_basic_sbit_family_class = |
| 420 { |
| 421 { |
| 422 sizeof ( FTC_BasicFamilyRec ), |
| 423 ftc_basic_family_compare, |
| 424 ftc_basic_family_init, |
| 425 0, /* FTC_MruNode_ResetFunc */ |
| 426 0 /* FTC_MruNode_DoneFunc */ |
| 427 }, |
| 428 ftc_basic_family_get_count, |
| 429 ftc_basic_family_load_bitmap |
| 430 }; |
| 431 |
| 432 |
| 433 FT_CALLBACK_TABLE_DEF |
| 434 const FTC_GCacheClassRec ftc_basic_sbit_cache_class = |
| 435 { |
| 436 { |
| 437 ftc_snode_new, |
| 438 ftc_snode_weight, |
| 439 ftc_snode_compare, |
| 440 ftc_basic_gnode_compare_faceid, |
| 441 ftc_snode_free, |
| 442 |
| 443 sizeof ( FTC_GCacheRec ), |
| 444 ftc_gcache_init, |
| 445 ftc_gcache_done |
| 446 }, |
| 447 (FTC_MruListClass)&ftc_basic_sbit_family_class |
| 448 }; |
| 449 |
| 450 |
| 451 /* documentation is in ftcache.h */ |
| 452 |
| 453 FT_EXPORT_DEF( FT_Error ) |
| 454 FTC_SBitCache_New( FTC_Manager manager, |
| 455 FTC_SBitCache *acache ) |
| 456 { |
| 457 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class, |
| 458 (FTC_GCache*)acache ); |
| 459 } |
| 460 |
| 461 |
| 462 /* documentation is in ftcache.h */ |
| 463 |
| 464 FT_EXPORT_DEF( FT_Error ) |
| 465 FTC_SBitCache_Lookup( FTC_SBitCache cache, |
| 466 FTC_ImageType type, |
| 467 FT_UInt gindex, |
| 468 FTC_SBit *ansbit, |
| 469 FTC_Node *anode ) |
| 470 { |
| 471 FT_Error error; |
| 472 FTC_BasicQueryRec query; |
| 473 FTC_Node node = 0; /* make compiler happy */ |
| 474 FT_PtrDist hash; |
| 475 |
| 476 |
| 477 if ( anode ) |
| 478 *anode = NULL; |
| 479 |
| 480 /* other argument checks delayed to FTC_Cache_Lookup */ |
| 481 if ( !ansbit ) |
| 482 return FT_THROW( Invalid_Argument ); |
| 483 |
| 484 *ansbit = NULL; |
| 485 |
| 486 { |
| 487 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
| 488 { |
| 489 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
| 490 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX
)) )); |
| 491 } |
| 492 |
| 493 query.attrs.scaler.face_id = type->face_id; |
| 494 query.attrs.scaler.width = type->width; |
| 495 query.attrs.scaler.height = type->height; |
| 496 query.attrs.load_flags = (FT_UInt)type->flags; |
| 497 } |
| 498 |
| 499 query.attrs.scaler.pixel = 1; |
| 500 query.attrs.scaler.x_res = 0; /* make compilers happy */ |
| 501 query.attrs.scaler.y_res = 0; |
| 502 |
| 503 /* beware, the hash must be the same for all glyph ranges! */ |
| 504 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
| 505 gindex / FTC_SBIT_ITEMS_PER_NODE; |
| 506 |
| 507 #if 1 /* inlining is about 50% faster! */ |
| 508 FTC_GCACHE_LOOKUP_CMP( cache, |
| 509 ftc_basic_family_compare, |
| 510 FTC_SNode_Compare, |
| 511 hash, gindex, |
| 512 &query, |
| 513 node, |
| 514 error ); |
| 515 #else |
| 516 error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
| 517 hash, |
| 518 gindex, |
| 519 FTC_GQUERY( &query ), |
| 520 &node ); |
| 521 #endif |
| 522 if ( error ) |
| 523 goto Exit; |
| 524 |
| 525 *ansbit = FTC_SNODE( node )->sbits + |
| 526 ( gindex - FTC_GNODE( node )->gindex ); |
| 527 |
| 528 if ( anode ) |
| 529 { |
| 530 *anode = node; |
| 531 node->ref_count++; |
| 532 } |
| 533 |
| 534 Exit: |
| 535 return error; |
| 536 } |
| 537 |
| 538 |
| 539 /* documentation is in ftcache.h */ |
| 540 |
| 541 FT_EXPORT_DEF( FT_Error ) |
| 542 FTC_SBitCache_LookupScaler( FTC_SBitCache cache, |
| 543 FTC_Scaler scaler, |
| 544 FT_ULong load_flags, |
| 545 FT_UInt gindex, |
| 546 FTC_SBit *ansbit, |
| 547 FTC_Node *anode ) |
| 548 { |
| 549 FT_Error error; |
| 550 FTC_BasicQueryRec query; |
| 551 FTC_Node node = 0; /* make compiler happy */ |
| 552 FT_PtrDist hash; |
| 553 |
| 554 |
| 555 if ( anode ) |
| 556 *anode = NULL; |
| 557 |
| 558 /* other argument checks delayed to FTC_Cache_Lookup */ |
| 559 if ( !ansbit || !scaler ) |
| 560 return FT_THROW( Invalid_Argument ); |
| 561 |
| 562 *ansbit = NULL; |
| 563 |
| 564 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
| 565 if ( load_flags > FT_UINT_MAX ) |
| 566 { |
| 567 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
| 568 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX))
)); |
| 569 } |
| 570 |
| 571 query.attrs.scaler = scaler[0]; |
| 572 query.attrs.load_flags = (FT_UInt)load_flags; |
| 573 |
| 574 /* beware, the hash must be the same for all glyph ranges! */ |
| 575 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
| 576 gindex / FTC_SBIT_ITEMS_PER_NODE; |
| 577 |
| 578 FTC_GCACHE_LOOKUP_CMP( cache, |
| 579 ftc_basic_family_compare, |
| 580 FTC_SNode_Compare, |
| 581 hash, gindex, |
| 582 &query, |
| 583 node, |
| 584 error ); |
| 585 if ( error ) |
| 586 goto Exit; |
| 587 |
| 588 *ansbit = FTC_SNODE( node )->sbits + |
| 589 ( gindex - FTC_GNODE( node )->gindex ); |
| 590 |
| 591 if ( anode ) |
| 592 { |
| 593 *anode = node; |
| 594 node->ref_count++; |
| 595 } |
| 596 |
| 597 Exit: |
| 598 return error; |
| 599 } |
| 600 |
| 601 |
| 602 /* END */ |
OLD | NEW |