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