Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / cache / ftcbasic.c
1 /***************************************************************************/
2 /* */
3 /* ftcbasic.c */
4 /* */
5 /* The FreeType basic cache interface (body). */
6 /* */
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2009 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_CACHE_H
22 #include "ftcglyph.h"
23 #include "ftcimage.h"
24 #include "ftcsbits.h"
25
26 #include "ftccback.h"
27 #include "ftcerror.h"
28
29 #define FT_COMPONENT trace_cache
30
31
32 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
33
34 /*
35 * These structures correspond to the FTC_Font and FTC_ImageDesc types
36 * that were defined in version 2.1.7.
37 */
38 typedef struct FTC_OldFontRec_
39 {
40 FTC_FaceID face_id;
41 FT_UShort pix_width;
42 FT_UShort pix_height;
43
44 } FTC_OldFontRec, *FTC_OldFont;
45
46
47 typedef struct FTC_OldImageDescRec_
48 {
49 FTC_OldFontRec font;
50 FT_UInt32 flags;
51
52 } FTC_OldImageDescRec, *FTC_OldImageDesc;
53
54
55 /*
56 * Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly
57 * identical, bit-wise. The only difference is that the `width' and
58 * `height' fields are expressed as 16-bit integers in the old structure,
59 * and as normal `int' in the new one.
60 *
61 * We are going to perform a weird hack to detect which structure is
62 * being passed to the image and sbit caches. If the new structure's
63 * `width' is larger than 0x10000, we assume that we are really receiving
64 * an FTC_OldImageDesc.
65 */
66
67 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
68
69
70 /*
71 * Basic Families
72 *
73 */
74 typedef struct FTC_BasicAttrRec_
75 {
76 FTC_ScalerRec scaler;
77 FT_UInt load_flags;
78
79 } FTC_BasicAttrRec, *FTC_BasicAttrs;
80
81 #define FTC_BASIC_ATTR_COMPARE( a, b ) \
82 FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
83 (a)->load_flags == (b)->load_flags )
84
85 #define FTC_BASIC_ATTR_HASH( a ) \
86 ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
87
88
89 typedef struct FTC_BasicQueryRec_
90 {
91 FTC_GQueryRec gquery;
92 FTC_BasicAttrRec attrs;
93
94 } FTC_BasicQueryRec, *FTC_BasicQuery;
95
96
97 typedef struct FTC_BasicFamilyRec_
98 {
99 FTC_FamilyRec family;
100 FTC_BasicAttrRec attrs;
101
102 } FTC_BasicFamilyRec, *FTC_BasicFamily;
103
104
105 FT_CALLBACK_DEF( FT_Bool )
106 ftc_basic_family_compare( FTC_MruNode ftcfamily,
107 FT_Pointer ftcquery )
108 {
109 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
110 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
111
112
113 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
114 }
115
116
117 FT_CALLBACK_DEF( FT_Error )
118 ftc_basic_family_init( FTC_MruNode ftcfamily,
119 FT_Pointer ftcquery,
120 FT_Pointer ftccache )
121 {
122 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
123 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
124 FTC_Cache cache = (FTC_Cache)ftccache;
125
126
127 FTC_Family_Init( FTC_FAMILY( family ), cache );
128 family->attrs = query->attrs;
129 return 0;
130 }
131
132
133 FT_CALLBACK_DEF( FT_UInt )
134 ftc_basic_family_get_count( FTC_Family ftcfamily,
135 FTC_Manager manager )
136 {
137 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
138 FT_Error error;
139 FT_Face face;
140 FT_UInt result = 0;
141
142
143 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
144 &face );
145
146 if ( error || !face )
147 return result;
148
149 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
150 {
151 FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
152 FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
153 }
154
155 if ( !error )
156 result = (FT_UInt)face->num_glyphs;
157
158 return result;
159 }
160
161
162 FT_CALLBACK_DEF( FT_Error )
163 ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
164 FT_UInt gindex,
165 FTC_Manager manager,
166 FT_Face *aface )
167 {
168 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
169 FT_Error error;
170 FT_Size size;
171
172
173 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
174 if ( !error )
175 {
176 FT_Face face = size->face;
177
178
179 error = FT_Load_Glyph( face, gindex,
180 family->attrs.load_flags | FT_LOAD_RENDER );
181 if ( !error )
182 *aface = face;
183 }
184
185 return error;
186 }
187
188
189 FT_CALLBACK_DEF( FT_Error )
190 ftc_basic_family_load_glyph( FTC_Family ftcfamily,
191 FT_UInt gindex,
192 FTC_Cache cache,
193 FT_Glyph *aglyph )
194 {
195 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
196 FT_Error error;
197 FTC_Scaler scaler = &family->attrs.scaler;
198 FT_Face face;
199 FT_Size size;
200
201
202 /* we will now load the glyph image */
203 error = FTC_Manager_LookupSize( cache->manager,
204 scaler,
205 &size );
206 if ( !error )
207 {
208 face = size->face;
209
210 error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
211 if ( !error )
212 {
213 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
214 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
215 {
216 /* ok, copy it */
217 FT_Glyph glyph;
218
219
220 error = FT_Get_Glyph( face->glyph, &glyph );
221 if ( !error )
222 {
223 *aglyph = glyph;
224 goto Exit;
225 }
226 }
227 else
228 error = FTC_Err_Invalid_Argument;
229 }
230 }
231
232 Exit:
233 return error;
234 }
235
236
237 FT_CALLBACK_DEF( FT_Bool )
238 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
239 FT_Pointer ftcface_id,
240 FTC_Cache cache )
241 {
242 FTC_GNode gnode = (FTC_GNode)ftcgnode;
243 FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
244 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
245 FT_Bool result;
246
247
248 result = FT_BOOL( family->attrs.scaler.face_id == face_id );
249 if ( result )
250 {
251 /* we must call this function to avoid this node from appearing
252 * in later lookups with the same face_id!
253 */
254 FTC_GNode_UnselectFamily( gnode, cache );
255 }
256 return result;
257 }
258
259
260 /*
261 *
262 * basic image cache
263 *
264 */
265
266 FT_CALLBACK_TABLE_DEF
267 const FTC_IFamilyClassRec ftc_basic_image_family_class =
268 {
269 {
270 sizeof ( FTC_BasicFamilyRec ),
271 ftc_basic_family_compare,
272 ftc_basic_family_init,
273 0, /* FTC_MruNode_ResetFunc */
274 0 /* FTC_MruNode_DoneFunc */
275 },
276 ftc_basic_family_load_glyph
277 };
278
279
280 FT_CALLBACK_TABLE_DEF
281 const FTC_GCacheClassRec ftc_basic_image_cache_class =
282 {
283 {
284 ftc_inode_new,
285 ftc_inode_weight,
286 ftc_gnode_compare,
287 ftc_basic_gnode_compare_faceid,
288 ftc_inode_free,
289
290 sizeof ( FTC_GCacheRec ),
291 ftc_gcache_init,
292 ftc_gcache_done
293 },
294 (FTC_MruListClass)&ftc_basic_image_family_class
295 };
296
297
298 /* documentation is in ftcache.h */
299
300 FT_EXPORT_DEF( FT_Error )
301 FTC_ImageCache_New( FTC_Manager manager,
302 FTC_ImageCache *acache )
303 {
304 return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
305 (FTC_GCache*)acache );
306 }
307
308
309 /* documentation is in ftcache.h */
310
311 FT_EXPORT_DEF( FT_Error )
312 FTC_ImageCache_Lookup( FTC_ImageCache cache,
313 FTC_ImageType type,
314 FT_UInt gindex,
315 FT_Glyph *aglyph,
316 FTC_Node *anode )
317 {
318 FTC_BasicQueryRec query;
319 FTC_Node node = 0; /* make compiler happy */
320 FT_Error error;
321 FT_UInt32 hash;
322
323
324 /* some argument checks are delayed to FTC_Cache_Lookup */
325 if ( !aglyph )
326 {
327 error = FTC_Err_Invalid_Argument;
328 goto Exit;
329 }
330
331 *aglyph = NULL;
332 if ( anode )
333 *anode = NULL;
334
335 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )
336
337 /*
338 * This one is a major hack used to detect whether we are passed a
339 * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
340 */
341 if ( (FT_ULong)type->width >= 0x10000L )
342 {
343 FTC_OldImageDesc desc = (FTC_OldImageDesc)type;
344
345
346 query.attrs.scaler.face_id = desc->font.face_id;
347 query.attrs.scaler.width = desc->font.pix_width;
348 query.attrs.scaler.height = desc->font.pix_height;
349 query.attrs.load_flags = desc->flags;
350 }
351 else
352
353 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
354
355 {
356 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
357 {
358 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
359 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
360 }
361
362 query.attrs.scaler.face_id = type->face_id;
363 query.attrs.scaler.width = type->width;
364 query.attrs.scaler.height = type->height;
365 query.attrs.load_flags = (FT_UInt)type->flags;
366 }
367
368 query.attrs.scaler.pixel = 1;
369 query.attrs.scaler.x_res = 0; /* make compilers happy */
370 query.attrs.scaler.y_res = 0;
371
372 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
373
374 #if 1 /* inlining is about 50% faster! */
375 FTC_GCACHE_LOOKUP_CMP( cache,
376 ftc_basic_family_compare,
377 FTC_GNode_Compare,
378 hash, gindex,
379 &query,
380 node,
381 error );
382 #else
383 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
384 hash, gindex,
385 FTC_GQUERY( &query ),
386 &node );
387 #endif
388 if ( !error )
389 {
390 *aglyph = FTC_INODE( node )->glyph;
391
392 if ( anode )
393 {
394 *anode = node;
395 node->ref_count++;
396 }
397 }
398
399 Exit:
400 return error;
401 }
402
403
404 /* documentation is in ftcache.h */
405
406 FT_EXPORT_DEF( FT_Error )
407 FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
408 FTC_Scaler scaler,
409 FT_ULong load_flags,
410 FT_UInt gindex,
411 FT_Glyph *aglyph,
412 FTC_Node *anode )
413 {
414 FTC_BasicQueryRec query;
415 FTC_Node node = 0; /* make compiler happy */
416 FT_Error error;
417 FT_UInt32 hash;
418
419
420 /* some argument checks are delayed to FTC_Cache_Lookup */
421 if ( !aglyph || !scaler )
422 {
423 error = FTC_Err_Invalid_Argument;
424 goto Exit;
425 }
426
427 *aglyph = NULL;
428 if ( anode )
429 *anode = NULL;
430
431 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
432 if ( load_flags > FT_UINT_MAX )
433 {
434 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
435 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
436 }
437
438 query.attrs.scaler = scaler[0];
439 query.attrs.load_flags = (FT_UInt)load_flags;
440
441 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
442
443 FTC_GCACHE_LOOKUP_CMP( cache,
444 ftc_basic_family_compare,
445 FTC_GNode_Compare,
446 hash, gindex,
447 &query,
448 node,
449 error );
450 if ( !error )
451 {
452 *aglyph = FTC_INODE( node )->glyph;
453
454 if ( anode )
455 {
456 *anode = node;
457 node->ref_count++;
458 }
459 }
460
461 Exit:
462 return error;
463 }
464
465
466
467 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
468
469 /* yet another backwards-legacy structure */
470 typedef struct FTC_OldImage_Desc_
471 {
472 FTC_FontRec font;
473 FT_UInt image_type;
474
475 } FTC_OldImage_Desc;
476
477
478 #define FTC_OLD_IMAGE_FORMAT( x ) ( (x) & 7 )
479
480
481 #define ftc_old_image_format_bitmap 0x0000
482 #define ftc_old_image_format_outline 0x0001
483
484 #define ftc_old_image_format_mask 0x000F
485
486 #define ftc_old_image_flag_monochrome 0x0010
487 #define ftc_old_image_flag_unhinted 0x0020
488 #define ftc_old_image_flag_autohinted 0x0040
489 #define ftc_old_image_flag_unscaled 0x0080
490 #define ftc_old_image_flag_no_sbits 0x0100
491
492 /* monochrome bitmap */
493 #define ftc_old_image_mono ftc_old_image_format_bitmap | \
494 ftc_old_image_flag_monochrome
495
496 /* anti-aliased bitmap */
497 #define ftc_old_image_grays ftc_old_image_format_bitmap
498
499 /* scaled outline */
500 #define ftc_old_image_outline ftc_old_image_format_outline
501
502
503 static void
504 ftc_image_type_from_old_desc( FTC_ImageType typ,
505 FTC_OldImage_Desc* desc )
506 {
507 typ->face_id = desc->font.face_id;
508 typ->width = desc->font.pix_width;
509 typ->height = desc->font.pix_height;
510
511 /* convert image type flags to load flags */
512 {
513 FT_UInt load_flags = FT_LOAD_DEFAULT;
514 FT_UInt type = desc->image_type;
515
516
517 /* determine load flags, depending on the font description's */
518 /* image type */
519
520 if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )
521 {
522 if ( type & ftc_old_image_flag_monochrome )
523 load_flags |= FT_LOAD_MONOCHROME;
524
525 /* disable embedded bitmaps loading if necessary */
526 if ( type & ftc_old_image_flag_no_sbits )
527 load_flags |= FT_LOAD_NO_BITMAP;
528 }
529 else
530 {
531 /* we want an outline, don't load embedded bitmaps */
532 load_flags |= FT_LOAD_NO_BITMAP;
533
534 if ( type & ftc_old_image_flag_unscaled )
535 load_flags |= FT_LOAD_NO_SCALE;
536 }
537
538 /* always render glyphs to bitmaps */
539 load_flags |= FT_LOAD_RENDER;
540
541 if ( type & ftc_old_image_flag_unhinted )
542 load_flags |= FT_LOAD_NO_HINTING;
543
544 if ( type & ftc_old_image_flag_autohinted )
545 load_flags |= FT_LOAD_FORCE_AUTOHINT;
546
547 typ->flags = load_flags;
548 }
549 }
550
551
552 FT_EXPORT( FT_Error )
553 FTC_Image_Cache_New( FTC_Manager manager,
554 FTC_ImageCache *acache );
555
556 FT_EXPORT( FT_Error )
557 FTC_Image_Cache_Lookup( FTC_ImageCache icache,
558 FTC_OldImage_Desc* desc,
559 FT_UInt gindex,
560 FT_Glyph *aglyph );
561
562
563 FT_EXPORT_DEF( FT_Error )
564 FTC_Image_Cache_New( FTC_Manager manager,
565 FTC_ImageCache *acache )
566 {
567 return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
568 }
569
570
571
572 FT_EXPORT_DEF( FT_Error )
573 FTC_Image_Cache_Lookup( FTC_ImageCache icache,
574 FTC_OldImage_Desc* desc,
575 FT_UInt gindex,
576 FT_Glyph *aglyph )
577 {
578 FTC_ImageTypeRec type0;
579
580
581 if ( !desc )
582 return FTC_Err_Invalid_Argument;
583
584 ftc_image_type_from_old_desc( &type0, desc );
585
586 return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
587 &type0,
588 gindex,
589 aglyph,
590 NULL );
591 }
592
593 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
594
595
596 /*
597 *
598 * basic small bitmap cache
599 *
600 */
601
602
603 FT_CALLBACK_TABLE_DEF
604 const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
605 {
606 {
607 sizeof( FTC_BasicFamilyRec ),
608 ftc_basic_family_compare,
609 ftc_basic_family_init,
610 0, /* FTC_MruNode_ResetFunc */
611 0 /* FTC_MruNode_DoneFunc */
612 },
613 ftc_basic_family_get_count,
614 ftc_basic_family_load_bitmap
615 };
616
617
618 FT_CALLBACK_TABLE_DEF
619 const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
620 {
621 {
622 ftc_snode_new,
623 ftc_snode_weight,
624 ftc_snode_compare,
625 ftc_basic_gnode_compare_faceid,
626 ftc_snode_free,
627
628 sizeof ( FTC_GCacheRec ),
629 ftc_gcache_init,
630 ftc_gcache_done
631 },
632 (FTC_MruListClass)&ftc_basic_sbit_family_class
633 };
634
635
636 /* documentation is in ftcache.h */
637
638 FT_EXPORT_DEF( FT_Error )
639 FTC_SBitCache_New( FTC_Manager manager,
640 FTC_SBitCache *acache )
641 {
642 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
643 (FTC_GCache*)acache );
644 }
645
646
647 /* documentation is in ftcache.h */
648
649 FT_EXPORT_DEF( FT_Error )
650 FTC_SBitCache_Lookup( FTC_SBitCache cache,
651 FTC_ImageType type,
652 FT_UInt gindex,
653 FTC_SBit *ansbit,
654 FTC_Node *anode )
655 {
656 FT_Error error;
657 FTC_BasicQueryRec query;
658 FTC_Node node = 0; /* make compiler happy */
659 FT_UInt32 hash;
660
661
662 if ( anode )
663 *anode = NULL;
664
665 /* other argument checks delayed to FTC_Cache_Lookup */
666 if ( !ansbit )
667 return FTC_Err_Invalid_Argument;
668
669 *ansbit = NULL;
670
671 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )
672
673 /* This one is a major hack used to detect whether we are passed a
674 * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
675 */
676 if ( (FT_ULong)type->width >= 0x10000L )
677 {
678 FTC_OldImageDesc desc = (FTC_OldImageDesc)type;
679
680
681 query.attrs.scaler.face_id = desc->font.face_id;
682 query.attrs.scaler.width = desc->font.pix_width;
683 query.attrs.scaler.height = desc->font.pix_height;
684 query.attrs.load_flags = desc->flags;
685 }
686 else
687
688 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
689
690 {
691 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
692 {
693 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
694 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
695 }
696
697 query.attrs.scaler.face_id = type->face_id;
698 query.attrs.scaler.width = type->width;
699 query.attrs.scaler.height = type->height;
700 query.attrs.load_flags = (FT_UInt)type->flags;
701 }
702
703 query.attrs.scaler.pixel = 1;
704 query.attrs.scaler.x_res = 0; /* make compilers happy */
705 query.attrs.scaler.y_res = 0;
706
707 /* beware, the hash must be the same for all glyph ranges! */
708 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
709 gindex / FTC_SBIT_ITEMS_PER_NODE;
710
711 #if 1 /* inlining is about 50% faster! */
712 FTC_GCACHE_LOOKUP_CMP( cache,
713 ftc_basic_family_compare,
714 FTC_SNode_Compare,
715 hash, gindex,
716 &query,
717 node,
718 error );
719 #else
720 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
721 hash,
722 gindex,
723 FTC_GQUERY( &query ),
724 &node );
725 #endif
726 if ( error )
727 goto Exit;
728
729 *ansbit = FTC_SNODE( node )->sbits +
730 ( gindex - FTC_GNODE( node )->gindex );
731
732 if ( anode )
733 {
734 *anode = node;
735 node->ref_count++;
736 }
737
738 Exit:
739 return error;
740 }
741
742
743 /* documentation is in ftcache.h */
744
745 FT_EXPORT_DEF( FT_Error )
746 FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
747 FTC_Scaler scaler,
748 FT_ULong load_flags,
749 FT_UInt gindex,
750 FTC_SBit *ansbit,
751 FTC_Node *anode )
752 {
753 FT_Error error;
754 FTC_BasicQueryRec query;
755 FTC_Node node = 0; /* make compiler happy */
756 FT_UInt32 hash;
757
758
759 if ( anode )
760 *anode = NULL;
761
762 /* other argument checks delayed to FTC_Cache_Lookup */
763 if ( !ansbit || !scaler )
764 return FTC_Err_Invalid_Argument;
765
766 *ansbit = NULL;
767
768 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
769 if ( load_flags > FT_UINT_MAX )
770 {
771 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
772 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
773 }
774
775 query.attrs.scaler = scaler[0];
776 query.attrs.load_flags = (FT_UInt)load_flags;
777
778 /* beware, the hash must be the same for all glyph ranges! */
779 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
780 gindex / FTC_SBIT_ITEMS_PER_NODE;
781
782 FTC_GCACHE_LOOKUP_CMP( cache,
783 ftc_basic_family_compare,
784 FTC_SNode_Compare,
785 hash, gindex,
786 &query,
787 node,
788 error );
789 if ( error )
790 goto Exit;
791
792 *ansbit = FTC_SNODE( node )->sbits +
793 ( gindex - FTC_GNODE( node )->gindex );
794
795 if ( anode )
796 {
797 *anode = node;
798 node->ref_count++;
799 }
800
801 Exit:
802 return error;
803 }
804
805
806 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
807
808 FT_EXPORT( FT_Error )
809 FTC_SBit_Cache_New( FTC_Manager manager,
810 FTC_SBitCache *acache );
811
812 FT_EXPORT( FT_Error )
813 FTC_SBit_Cache_Lookup( FTC_SBitCache cache,
814 FTC_OldImage_Desc* desc,
815 FT_UInt gindex,
816 FTC_SBit *ansbit );
817
818
819 FT_EXPORT_DEF( FT_Error )
820 FTC_SBit_Cache_New( FTC_Manager manager,
821 FTC_SBitCache *acache )
822 {
823 return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
824 }
825
826
827 FT_EXPORT_DEF( FT_Error )
828 FTC_SBit_Cache_Lookup( FTC_SBitCache cache,
829 FTC_OldImage_Desc* desc,
830 FT_UInt gindex,
831 FTC_SBit *ansbit )
832 {
833 FTC_ImageTypeRec type0;
834
835
836 if ( !desc )
837 return FT_Err_Invalid_Argument;
838
839 ftc_image_type_from_old_desc( &type0, desc );
840
841 return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
842 &type0,
843 gindex,
844 ansbit,
845 NULL );
846 }
847
848 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
849
850
851 /* END */