PageRenderTime 84ms CodeModel.GetById 17ms app.highlight 61ms RepoModel.GetById 2ms app.codeStats 0ms

/modules/freetype2/src/cache/ftcbasic.c

http://github.com/zpao/v8monkey
C | 851 lines | 572 code | 197 blank | 82 comment | 52 complexity | 791911381d6e479e1186f1851d45dc14 MD5 | raw file
  1/***************************************************************************/
  2/*                                                                         */
  3/*  ftcbasic.c                                                             */
  4/*                                                                         */
  5/*    The FreeType basic cache interface (body).                           */
  6/*                                                                         */
  7/*  Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 FTC_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 */