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