xref: /inferno-os/libfreetype/ftcmanag.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftcmanag.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType Cache Manager (body).                                       */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2000-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_CACHE_H
21*37da2899SCharles.Forsyth #include FT_CACHE_MANAGER_H
22*37da2899SCharles.Forsyth #include FT_CACHE_INTERNAL_LRU_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
24*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
25*37da2899SCharles.Forsyth #include FT_SIZES_H
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth #include "ftcerror.h"
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth #undef  FT_COMPONENT
31*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_cache
32*37da2899SCharles.Forsyth 
33*37da2899SCharles.Forsyth #define FTC_LRU_GET_MANAGER( lru )  ( (FTC_Manager)(lru)->user_data )
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth   /*************************************************************************/
37*37da2899SCharles.Forsyth   /*************************************************************************/
38*37da2899SCharles.Forsyth   /*****                                                               *****/
39*37da2899SCharles.Forsyth   /*****                    FACE LRU IMPLEMENTATION                    *****/
40*37da2899SCharles.Forsyth   /*****                                                               *****/
41*37da2899SCharles.Forsyth   /*************************************************************************/
42*37da2899SCharles.Forsyth   /*************************************************************************/
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth   typedef struct FTC_FaceNodeRec_*  FTC_FaceNode;
45*37da2899SCharles.Forsyth   typedef struct FTC_SizeNodeRec_*  FTC_SizeNode;
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth   typedef struct  FTC_FaceNodeRec_
49*37da2899SCharles.Forsyth   {
50*37da2899SCharles.Forsyth     FT_LruNodeRec  lru;
51*37da2899SCharles.Forsyth     FT_Face        face;
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth   } FTC_FaceNodeRec;
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth   typedef struct  FTC_SizeNodeRec_
57*37da2899SCharles.Forsyth   {
58*37da2899SCharles.Forsyth     FT_LruNodeRec  lru;
59*37da2899SCharles.Forsyth     FT_Size        size;
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth   } FTC_SizeNodeRec;
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth 
64*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
ftc_face_node_init(FTC_FaceNode node,FTC_FaceID face_id,FTC_Manager manager)65*37da2899SCharles.Forsyth   ftc_face_node_init( FTC_FaceNode  node,
66*37da2899SCharles.Forsyth                       FTC_FaceID    face_id,
67*37da2899SCharles.Forsyth                       FTC_Manager   manager )
68*37da2899SCharles.Forsyth   {
69*37da2899SCharles.Forsyth     FT_Error  error;
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth     error = manager->request_face( face_id,
73*37da2899SCharles.Forsyth                                    manager->library,
74*37da2899SCharles.Forsyth                                    manager->request_data,
75*37da2899SCharles.Forsyth                                    &node->face );
76*37da2899SCharles.Forsyth     if ( !error )
77*37da2899SCharles.Forsyth     {
78*37da2899SCharles.Forsyth       /* destroy initial size object; it will be re-created later */
79*37da2899SCharles.Forsyth       if ( node->face->size )
80*37da2899SCharles.Forsyth         FT_Done_Size( node->face->size );
81*37da2899SCharles.Forsyth     }
82*37da2899SCharles.Forsyth 
83*37da2899SCharles.Forsyth     return error;
84*37da2899SCharles.Forsyth   }
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth   /* helper function for ftc_face_node_done() */
88*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_select(FTC_SizeNode node,FT_Face face)89*37da2899SCharles.Forsyth   ftc_size_node_select( FTC_SizeNode  node,
90*37da2899SCharles.Forsyth                         FT_Face       face )
91*37da2899SCharles.Forsyth   {
92*37da2899SCharles.Forsyth     return FT_BOOL( node->size->face == face );
93*37da2899SCharles.Forsyth   }
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
ftc_face_node_done(FTC_FaceNode node,FTC_Manager manager)97*37da2899SCharles.Forsyth   ftc_face_node_done( FTC_FaceNode  node,
98*37da2899SCharles.Forsyth                       FTC_Manager   manager )
99*37da2899SCharles.Forsyth   {
100*37da2899SCharles.Forsyth     FT_Face  face    = node->face;
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth 
103*37da2899SCharles.Forsyth     /* we must begin by removing all sizes for the target face */
104*37da2899SCharles.Forsyth     /* from the manager's list                                 */
105*37da2899SCharles.Forsyth     FT_LruList_Remove_Selection( manager->sizes_list,
106*37da2899SCharles.Forsyth                                  (FT_LruNode_SelectFunc)ftc_size_node_select,
107*37da2899SCharles.Forsyth                                  face );
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth     /* all right, we can discard the face now */
110*37da2899SCharles.Forsyth     FT_Done_Face( face );
111*37da2899SCharles.Forsyth     node->face = NULL;
112*37da2899SCharles.Forsyth   }
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
116*37da2899SCharles.Forsyth   const FT_LruList_ClassRec  ftc_face_list_class =
117*37da2899SCharles.Forsyth   {
118*37da2899SCharles.Forsyth     sizeof ( FT_LruListRec ),
119*37da2899SCharles.Forsyth     (FT_LruList_InitFunc)0,
120*37da2899SCharles.Forsyth     (FT_LruList_DoneFunc)0,
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth     sizeof ( FTC_FaceNodeRec ),
123*37da2899SCharles.Forsyth     (FT_LruNode_InitFunc)   ftc_face_node_init,
124*37da2899SCharles.Forsyth     (FT_LruNode_DoneFunc)   ftc_face_node_done,
125*37da2899SCharles.Forsyth     (FT_LruNode_FlushFunc)  0,  /* no flushing needed                      */
126*37da2899SCharles.Forsyth     (FT_LruNode_CompareFunc)0,  /* direct comparison of FTC_FaceID handles */
127*37da2899SCharles.Forsyth   };
128*37da2899SCharles.Forsyth 
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth   /* documentation is in ftcache.h */
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FTC_Manager_Lookup_Face(FTC_Manager manager,FTC_FaceID face_id,FT_Face * aface)133*37da2899SCharles.Forsyth   FTC_Manager_Lookup_Face( FTC_Manager  manager,
134*37da2899SCharles.Forsyth                            FTC_FaceID   face_id,
135*37da2899SCharles.Forsyth                            FT_Face     *aface )
136*37da2899SCharles.Forsyth   {
137*37da2899SCharles.Forsyth     FT_Error      error;
138*37da2899SCharles.Forsyth     FTC_FaceNode  node;
139*37da2899SCharles.Forsyth 
140*37da2899SCharles.Forsyth 
141*37da2899SCharles.Forsyth     if ( aface == NULL )
142*37da2899SCharles.Forsyth       return FTC_Err_Bad_Argument;
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth     *aface = NULL;
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth     if ( !manager )
147*37da2899SCharles.Forsyth       return FTC_Err_Invalid_Cache_Handle;
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth     error = FT_LruList_Lookup( manager->faces_list,
150*37da2899SCharles.Forsyth                                (FT_LruKey)face_id,
151*37da2899SCharles.Forsyth                                (FT_LruNode*)&node );
152*37da2899SCharles.Forsyth     if ( !error )
153*37da2899SCharles.Forsyth       *aface = node->face;
154*37da2899SCharles.Forsyth 
155*37da2899SCharles.Forsyth     return error;
156*37da2899SCharles.Forsyth   }
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth   /*************************************************************************/
160*37da2899SCharles.Forsyth   /*************************************************************************/
161*37da2899SCharles.Forsyth   /*****                                                               *****/
162*37da2899SCharles.Forsyth   /*****                      SIZES LRU IMPLEMENTATION                 *****/
163*37da2899SCharles.Forsyth   /*****                                                               *****/
164*37da2899SCharles.Forsyth   /*************************************************************************/
165*37da2899SCharles.Forsyth   /*************************************************************************/
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth   typedef struct  FTC_SizeQueryRec_
169*37da2899SCharles.Forsyth   {
170*37da2899SCharles.Forsyth     FT_Face  face;
171*37da2899SCharles.Forsyth     FT_UInt  width;
172*37da2899SCharles.Forsyth     FT_UInt  height;
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth   } FTC_SizeQueryRec, *FTC_SizeQuery;
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
ftc_size_node_init(FTC_SizeNode node,FTC_SizeQuery query)178*37da2899SCharles.Forsyth   ftc_size_node_init( FTC_SizeNode   node,
179*37da2899SCharles.Forsyth                       FTC_SizeQuery  query )
180*37da2899SCharles.Forsyth   {
181*37da2899SCharles.Forsyth     FT_Face   face = query->face;
182*37da2899SCharles.Forsyth     FT_Size   size;
183*37da2899SCharles.Forsyth     FT_Error  error;
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth     node->size = NULL;
187*37da2899SCharles.Forsyth     error = FT_New_Size( face, &size );
188*37da2899SCharles.Forsyth     if ( !error )
189*37da2899SCharles.Forsyth     {
190*37da2899SCharles.Forsyth       FT_Activate_Size( size );
191*37da2899SCharles.Forsyth       error = FT_Set_Pixel_Sizes( query->face,
192*37da2899SCharles.Forsyth                                   query->width,
193*37da2899SCharles.Forsyth                                   query->height );
194*37da2899SCharles.Forsyth       if ( error )
195*37da2899SCharles.Forsyth         FT_Done_Size( size );
196*37da2899SCharles.Forsyth       else
197*37da2899SCharles.Forsyth         node->size = size;
198*37da2899SCharles.Forsyth     }
199*37da2899SCharles.Forsyth     return error;
200*37da2899SCharles.Forsyth   }
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( void )
ftc_size_node_done(FTC_SizeNode node)204*37da2899SCharles.Forsyth   ftc_size_node_done( FTC_SizeNode  node )
205*37da2899SCharles.Forsyth   {
206*37da2899SCharles.Forsyth     if ( node->size )
207*37da2899SCharles.Forsyth     {
208*37da2899SCharles.Forsyth       FT_Done_Size( node->size );
209*37da2899SCharles.Forsyth       node->size = NULL;
210*37da2899SCharles.Forsyth     }
211*37da2899SCharles.Forsyth   }
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
ftc_size_node_flush(FTC_SizeNode node,FTC_SizeQuery query)215*37da2899SCharles.Forsyth   ftc_size_node_flush( FTC_SizeNode   node,
216*37da2899SCharles.Forsyth                        FTC_SizeQuery  query )
217*37da2899SCharles.Forsyth   {
218*37da2899SCharles.Forsyth     FT_Size   size = node->size;
219*37da2899SCharles.Forsyth     FT_Error  error;
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth 
222*37da2899SCharles.Forsyth     if ( size->face == query->face )
223*37da2899SCharles.Forsyth     {
224*37da2899SCharles.Forsyth       FT_Activate_Size( size );
225*37da2899SCharles.Forsyth       error = FT_Set_Pixel_Sizes( query->face, query->width, query->height );
226*37da2899SCharles.Forsyth       if ( error )
227*37da2899SCharles.Forsyth       {
228*37da2899SCharles.Forsyth         FT_Done_Size( size );
229*37da2899SCharles.Forsyth         node->size = NULL;
230*37da2899SCharles.Forsyth       }
231*37da2899SCharles.Forsyth     }
232*37da2899SCharles.Forsyth     else
233*37da2899SCharles.Forsyth     {
234*37da2899SCharles.Forsyth       FT_Done_Size( size );
235*37da2899SCharles.Forsyth       node->size = NULL;
236*37da2899SCharles.Forsyth 
237*37da2899SCharles.Forsyth       error = ftc_size_node_init( node, query );
238*37da2899SCharles.Forsyth     }
239*37da2899SCharles.Forsyth     return error;
240*37da2899SCharles.Forsyth   }
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_compare(FTC_SizeNode node,FTC_SizeQuery query)244*37da2899SCharles.Forsyth   ftc_size_node_compare( FTC_SizeNode   node,
245*37da2899SCharles.Forsyth                          FTC_SizeQuery  query )
246*37da2899SCharles.Forsyth   {
247*37da2899SCharles.Forsyth     FT_Size  size = node->size;
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth     return FT_BOOL( size->face                    == query->face   &&
251*37da2899SCharles.Forsyth                     (FT_UInt)size->metrics.x_ppem == query->width  &&
252*37da2899SCharles.Forsyth                     (FT_UInt)size->metrics.y_ppem == query->height );
253*37da2899SCharles.Forsyth   }
254*37da2899SCharles.Forsyth 
255*37da2899SCharles.Forsyth 
256*37da2899SCharles.Forsyth   FT_CALLBACK_TABLE_DEF
257*37da2899SCharles.Forsyth   const FT_LruList_ClassRec  ftc_size_list_class =
258*37da2899SCharles.Forsyth   {
259*37da2899SCharles.Forsyth     sizeof ( FT_LruListRec ),
260*37da2899SCharles.Forsyth     (FT_LruList_InitFunc)0,
261*37da2899SCharles.Forsyth     (FT_LruList_DoneFunc)0,
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth     sizeof ( FTC_SizeNodeRec ),
264*37da2899SCharles.Forsyth     (FT_LruNode_InitFunc)   ftc_size_node_init,
265*37da2899SCharles.Forsyth     (FT_LruNode_DoneFunc)   ftc_size_node_done,
266*37da2899SCharles.Forsyth     (FT_LruNode_FlushFunc)  ftc_size_node_flush,
267*37da2899SCharles.Forsyth     (FT_LruNode_CompareFunc)ftc_size_node_compare
268*37da2899SCharles.Forsyth   };
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth   /* documentation is in ftcache.h */
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FTC_Manager_Lookup_Size(FTC_Manager manager,FTC_Font font,FT_Face * aface,FT_Size * asize)274*37da2899SCharles.Forsyth   FTC_Manager_Lookup_Size( FTC_Manager  manager,
275*37da2899SCharles.Forsyth                            FTC_Font     font,
276*37da2899SCharles.Forsyth                            FT_Face     *aface,
277*37da2899SCharles.Forsyth                            FT_Size     *asize )
278*37da2899SCharles.Forsyth   {
279*37da2899SCharles.Forsyth     FT_Error  error;
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth     /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
283*37da2899SCharles.Forsyth     if ( aface )
284*37da2899SCharles.Forsyth       *aface = 0;
285*37da2899SCharles.Forsyth 
286*37da2899SCharles.Forsyth     if ( asize )
287*37da2899SCharles.Forsyth       *asize = 0;
288*37da2899SCharles.Forsyth 
289*37da2899SCharles.Forsyth     error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
290*37da2899SCharles.Forsyth     if ( !error )
291*37da2899SCharles.Forsyth     {
292*37da2899SCharles.Forsyth       FTC_SizeQueryRec  query;
293*37da2899SCharles.Forsyth       FTC_SizeNode      node;
294*37da2899SCharles.Forsyth 
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth       query.face   = *aface;
297*37da2899SCharles.Forsyth       query.width  = font->pix_width;
298*37da2899SCharles.Forsyth       query.height = font->pix_height;
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth       error = FT_LruList_Lookup( manager->sizes_list,
301*37da2899SCharles.Forsyth                                  (FT_LruKey)&query,
302*37da2899SCharles.Forsyth                                  (FT_LruNode*)&node );
303*37da2899SCharles.Forsyth       if ( !error )
304*37da2899SCharles.Forsyth       {
305*37da2899SCharles.Forsyth         /* select the size as the current one for this face */
306*37da2899SCharles.Forsyth         FT_Activate_Size( node->size );
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth         if ( asize )
309*37da2899SCharles.Forsyth           *asize = node->size;
310*37da2899SCharles.Forsyth       }
311*37da2899SCharles.Forsyth     }
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth     return error;
314*37da2899SCharles.Forsyth   }
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth 
317*37da2899SCharles.Forsyth   /*************************************************************************/
318*37da2899SCharles.Forsyth   /*************************************************************************/
319*37da2899SCharles.Forsyth   /*****                                                               *****/
320*37da2899SCharles.Forsyth   /*****                    SET TABLE MANAGEMENT                       *****/
321*37da2899SCharles.Forsyth   /*****                                                               *****/
322*37da2899SCharles.Forsyth   /*************************************************************************/
323*37da2899SCharles.Forsyth   /*************************************************************************/
324*37da2899SCharles.Forsyth 
325*37da2899SCharles.Forsyth   static void
ftc_family_table_init(FTC_FamilyTable table)326*37da2899SCharles.Forsyth   ftc_family_table_init( FTC_FamilyTable  table )
327*37da2899SCharles.Forsyth   {
328*37da2899SCharles.Forsyth     table->count   = 0;
329*37da2899SCharles.Forsyth     table->size    = 0;
330*37da2899SCharles.Forsyth     table->entries = NULL;
331*37da2899SCharles.Forsyth     table->free    = FTC_FAMILY_ENTRY_NONE;
332*37da2899SCharles.Forsyth   }
333*37da2899SCharles.Forsyth 
334*37da2899SCharles.Forsyth 
335*37da2899SCharles.Forsyth   static void
ftc_family_table_done(FTC_FamilyTable table,FT_Memory memory)336*37da2899SCharles.Forsyth   ftc_family_table_done( FTC_FamilyTable  table,
337*37da2899SCharles.Forsyth                          FT_Memory        memory )
338*37da2899SCharles.Forsyth   {
339*37da2899SCharles.Forsyth     FT_FREE( table->entries );
340*37da2899SCharles.Forsyth     table->free  = 0;
341*37da2899SCharles.Forsyth     table->count = 0;
342*37da2899SCharles.Forsyth     table->size  = 0;
343*37da2899SCharles.Forsyth   }
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
ftc_family_table_alloc(FTC_FamilyTable table,FT_Memory memory,FTC_FamilyEntry * aentry)347*37da2899SCharles.Forsyth   ftc_family_table_alloc( FTC_FamilyTable   table,
348*37da2899SCharles.Forsyth                           FT_Memory         memory,
349*37da2899SCharles.Forsyth                           FTC_FamilyEntry  *aentry )
350*37da2899SCharles.Forsyth   {
351*37da2899SCharles.Forsyth     FTC_FamilyEntry  entry;
352*37da2899SCharles.Forsyth     FT_Error         error = 0;
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth     /* re-allocate table size when needed */
356*37da2899SCharles.Forsyth     if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size )
357*37da2899SCharles.Forsyth     {
358*37da2899SCharles.Forsyth       FT_UInt  old_size = table->size;
359*37da2899SCharles.Forsyth       FT_UInt  new_size, idx;
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth       if ( old_size == 0 )
363*37da2899SCharles.Forsyth         new_size = 8;
364*37da2899SCharles.Forsyth       else
365*37da2899SCharles.Forsyth       {
366*37da2899SCharles.Forsyth         new_size = old_size * 2;
367*37da2899SCharles.Forsyth 
368*37da2899SCharles.Forsyth         /* check for (unlikely) overflow */
369*37da2899SCharles.Forsyth         if ( new_size < old_size )
370*37da2899SCharles.Forsyth           new_size = 65534;
371*37da2899SCharles.Forsyth       }
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) )
374*37da2899SCharles.Forsyth         return error;
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth       table->size = new_size;
377*37da2899SCharles.Forsyth 
378*37da2899SCharles.Forsyth       entry       = table->entries + old_size;
379*37da2899SCharles.Forsyth       table->free = old_size;
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth       for ( idx = old_size; idx + 1 < new_size; idx++, entry++ )
382*37da2899SCharles.Forsyth       {
383*37da2899SCharles.Forsyth         entry->link  = idx + 1;
384*37da2899SCharles.Forsyth         entry->index = idx;
385*37da2899SCharles.Forsyth       }
386*37da2899SCharles.Forsyth 
387*37da2899SCharles.Forsyth       entry->link  = FTC_FAMILY_ENTRY_NONE;
388*37da2899SCharles.Forsyth       entry->index = idx;
389*37da2899SCharles.Forsyth     }
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth     if ( table->free != FTC_FAMILY_ENTRY_NONE )
392*37da2899SCharles.Forsyth     {
393*37da2899SCharles.Forsyth       entry       = table->entries + table->free;
394*37da2899SCharles.Forsyth       table->free = entry->link;
395*37da2899SCharles.Forsyth     }
396*37da2899SCharles.Forsyth     else if ( table->count < table->size )
397*37da2899SCharles.Forsyth     {
398*37da2899SCharles.Forsyth       entry = table->entries + table->count++;
399*37da2899SCharles.Forsyth     }
400*37da2899SCharles.Forsyth     else
401*37da2899SCharles.Forsyth     {
402*37da2899SCharles.Forsyth       FT_ERROR(( "ftc_family_table_alloc: internal bug!" ));
403*37da2899SCharles.Forsyth       return FTC_Err_Invalid_Argument;
404*37da2899SCharles.Forsyth     }
405*37da2899SCharles.Forsyth 
406*37da2899SCharles.Forsyth     entry->link = FTC_FAMILY_ENTRY_NONE;
407*37da2899SCharles.Forsyth     table->count++;
408*37da2899SCharles.Forsyth 
409*37da2899SCharles.Forsyth     *aentry = entry;
410*37da2899SCharles.Forsyth     return error;
411*37da2899SCharles.Forsyth   }
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth 
414*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
ftc_family_table_free(FTC_FamilyTable table,FT_UInt idx)415*37da2899SCharles.Forsyth   ftc_family_table_free( FTC_FamilyTable  table,
416*37da2899SCharles.Forsyth                          FT_UInt          idx )
417*37da2899SCharles.Forsyth   {
418*37da2899SCharles.Forsyth     /* simply add it to the linked list of free entries */
419*37da2899SCharles.Forsyth     if ( idx < table->count )
420*37da2899SCharles.Forsyth     {
421*37da2899SCharles.Forsyth       FTC_FamilyEntry  entry = table->entries + idx;
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth 
424*37da2899SCharles.Forsyth       if ( entry->link != FTC_FAMILY_ENTRY_NONE )
425*37da2899SCharles.Forsyth         FT_ERROR(( "ftc_family_table_free: internal bug!\n" ));
426*37da2899SCharles.Forsyth       else
427*37da2899SCharles.Forsyth       {
428*37da2899SCharles.Forsyth         entry->link = table->free;
429*37da2899SCharles.Forsyth         table->free = entry->index;
430*37da2899SCharles.Forsyth         table->count--;
431*37da2899SCharles.Forsyth       }
432*37da2899SCharles.Forsyth     }
433*37da2899SCharles.Forsyth   }
434*37da2899SCharles.Forsyth 
435*37da2899SCharles.Forsyth 
436*37da2899SCharles.Forsyth   /*************************************************************************/
437*37da2899SCharles.Forsyth   /*************************************************************************/
438*37da2899SCharles.Forsyth   /*****                                                               *****/
439*37da2899SCharles.Forsyth   /*****                    CACHE MANAGER ROUTINES                     *****/
440*37da2899SCharles.Forsyth   /*****                                                               *****/
441*37da2899SCharles.Forsyth   /*************************************************************************/
442*37da2899SCharles.Forsyth   /*************************************************************************/
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth 
445*37da2899SCharles.Forsyth   /* documentation is in ftcache.h */
446*37da2899SCharles.Forsyth 
447*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FTC_Manager_New(FT_Library library,FT_UInt max_faces,FT_UInt max_sizes,FT_ULong max_bytes,FTC_Face_Requester requester,FT_Pointer req_data,FTC_Manager * amanager)448*37da2899SCharles.Forsyth   FTC_Manager_New( FT_Library          library,
449*37da2899SCharles.Forsyth                    FT_UInt             max_faces,
450*37da2899SCharles.Forsyth                    FT_UInt             max_sizes,
451*37da2899SCharles.Forsyth                    FT_ULong            max_bytes,
452*37da2899SCharles.Forsyth                    FTC_Face_Requester  requester,
453*37da2899SCharles.Forsyth                    FT_Pointer          req_data,
454*37da2899SCharles.Forsyth                    FTC_Manager        *amanager )
455*37da2899SCharles.Forsyth   {
456*37da2899SCharles.Forsyth     FT_Error     error;
457*37da2899SCharles.Forsyth     FT_Memory    memory;
458*37da2899SCharles.Forsyth     FTC_Manager  manager = 0;
459*37da2899SCharles.Forsyth 
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth     if ( !library )
462*37da2899SCharles.Forsyth       return FTC_Err_Invalid_Library_Handle;
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth     memory = library->memory;
465*37da2899SCharles.Forsyth 
466*37da2899SCharles.Forsyth     if ( FT_NEW( manager ) )
467*37da2899SCharles.Forsyth       goto Exit;
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth     if ( max_faces == 0 )
470*37da2899SCharles.Forsyth       max_faces = FTC_MAX_FACES_DEFAULT;
471*37da2899SCharles.Forsyth 
472*37da2899SCharles.Forsyth     if ( max_sizes == 0 )
473*37da2899SCharles.Forsyth       max_sizes = FTC_MAX_SIZES_DEFAULT;
474*37da2899SCharles.Forsyth 
475*37da2899SCharles.Forsyth     if ( max_bytes == 0 )
476*37da2899SCharles.Forsyth       max_bytes = FTC_MAX_BYTES_DEFAULT;
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth     error = FT_LruList_New( &ftc_face_list_class,
479*37da2899SCharles.Forsyth                             max_faces,
480*37da2899SCharles.Forsyth                             manager,
481*37da2899SCharles.Forsyth                             memory,
482*37da2899SCharles.Forsyth                             &manager->faces_list );
483*37da2899SCharles.Forsyth     if ( error )
484*37da2899SCharles.Forsyth       goto Exit;
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth     error = FT_LruList_New( &ftc_size_list_class,
487*37da2899SCharles.Forsyth                             max_sizes,
488*37da2899SCharles.Forsyth                             manager,
489*37da2899SCharles.Forsyth                             memory,
490*37da2899SCharles.Forsyth                             &manager->sizes_list );
491*37da2899SCharles.Forsyth     if ( error )
492*37da2899SCharles.Forsyth       goto Exit;
493*37da2899SCharles.Forsyth 
494*37da2899SCharles.Forsyth     manager->library      = library;
495*37da2899SCharles.Forsyth     manager->max_weight   = max_bytes;
496*37da2899SCharles.Forsyth     manager->cur_weight   = 0;
497*37da2899SCharles.Forsyth 
498*37da2899SCharles.Forsyth     manager->request_face = requester;
499*37da2899SCharles.Forsyth     manager->request_data = req_data;
500*37da2899SCharles.Forsyth 
501*37da2899SCharles.Forsyth     ftc_family_table_init( &manager->families );
502*37da2899SCharles.Forsyth 
503*37da2899SCharles.Forsyth     *amanager = manager;
504*37da2899SCharles.Forsyth 
505*37da2899SCharles.Forsyth   Exit:
506*37da2899SCharles.Forsyth     if ( error && manager )
507*37da2899SCharles.Forsyth     {
508*37da2899SCharles.Forsyth       FT_LruList_Destroy( manager->faces_list );
509*37da2899SCharles.Forsyth       FT_LruList_Destroy( manager->sizes_list );
510*37da2899SCharles.Forsyth       FT_FREE( manager );
511*37da2899SCharles.Forsyth     }
512*37da2899SCharles.Forsyth 
513*37da2899SCharles.Forsyth     return error;
514*37da2899SCharles.Forsyth   }
515*37da2899SCharles.Forsyth 
516*37da2899SCharles.Forsyth 
517*37da2899SCharles.Forsyth   /* documentation is in ftcache.h */
518*37da2899SCharles.Forsyth 
519*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FTC_Manager_Done(FTC_Manager manager)520*37da2899SCharles.Forsyth   FTC_Manager_Done( FTC_Manager  manager )
521*37da2899SCharles.Forsyth   {
522*37da2899SCharles.Forsyth     FT_Memory  memory;
523*37da2899SCharles.Forsyth     FT_UInt    idx;
524*37da2899SCharles.Forsyth 
525*37da2899SCharles.Forsyth 
526*37da2899SCharles.Forsyth     if ( !manager || !manager->library )
527*37da2899SCharles.Forsyth       return;
528*37da2899SCharles.Forsyth 
529*37da2899SCharles.Forsyth     memory = manager->library->memory;
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth     /* now discard all caches */
532*37da2899SCharles.Forsyth     for (idx = 0; idx < FTC_MAX_CACHES; idx++ )
533*37da2899SCharles.Forsyth     {
534*37da2899SCharles.Forsyth       FTC_Cache  cache = manager->caches[idx];
535*37da2899SCharles.Forsyth 
536*37da2899SCharles.Forsyth 
537*37da2899SCharles.Forsyth       if ( cache )
538*37da2899SCharles.Forsyth       {
539*37da2899SCharles.Forsyth         cache->clazz->cache_done( cache );
540*37da2899SCharles.Forsyth         FT_FREE( cache );
541*37da2899SCharles.Forsyth         manager->caches[idx] = 0;
542*37da2899SCharles.Forsyth       }
543*37da2899SCharles.Forsyth     }
544*37da2899SCharles.Forsyth 
545*37da2899SCharles.Forsyth     /* discard families table */
546*37da2899SCharles.Forsyth     ftc_family_table_done( &manager->families, memory );
547*37da2899SCharles.Forsyth 
548*37da2899SCharles.Forsyth     /* discard faces and sizes */
549*37da2899SCharles.Forsyth     FT_LruList_Destroy( manager->faces_list );
550*37da2899SCharles.Forsyth     manager->faces_list = 0;
551*37da2899SCharles.Forsyth 
552*37da2899SCharles.Forsyth     FT_LruList_Destroy( manager->sizes_list );
553*37da2899SCharles.Forsyth     manager->sizes_list = 0;
554*37da2899SCharles.Forsyth 
555*37da2899SCharles.Forsyth     FT_FREE( manager );
556*37da2899SCharles.Forsyth   }
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth 
559*37da2899SCharles.Forsyth   /* documentation is in ftcache.h */
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FTC_Manager_Reset(FTC_Manager manager)562*37da2899SCharles.Forsyth   FTC_Manager_Reset( FTC_Manager  manager )
563*37da2899SCharles.Forsyth   {
564*37da2899SCharles.Forsyth     if ( manager )
565*37da2899SCharles.Forsyth     {
566*37da2899SCharles.Forsyth       FT_LruList_Reset( manager->sizes_list );
567*37da2899SCharles.Forsyth       FT_LruList_Reset( manager->faces_list );
568*37da2899SCharles.Forsyth     }
569*37da2899SCharles.Forsyth     /* XXX: FIXME: flush the caches? */
570*37da2899SCharles.Forsyth   }
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth #ifdef FT_DEBUG_ERROR
574*37da2899SCharles.Forsyth 
575*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FTC_Manager_Check(FTC_Manager manager)576*37da2899SCharles.Forsyth   FTC_Manager_Check( FTC_Manager  manager )
577*37da2899SCharles.Forsyth   {
578*37da2899SCharles.Forsyth     FTC_Node  node, first;
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth 
581*37da2899SCharles.Forsyth     first = manager->nodes_list;
582*37da2899SCharles.Forsyth 
583*37da2899SCharles.Forsyth     /* check node weights */
584*37da2899SCharles.Forsyth     if ( first )
585*37da2899SCharles.Forsyth     {
586*37da2899SCharles.Forsyth       FT_ULong  weight = 0;
587*37da2899SCharles.Forsyth 
588*37da2899SCharles.Forsyth 
589*37da2899SCharles.Forsyth       node = first;
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth       do
592*37da2899SCharles.Forsyth       {
593*37da2899SCharles.Forsyth         FTC_FamilyEntry  entry = manager->families.entries + node->fam_index;
594*37da2899SCharles.Forsyth         FTC_Cache     cache;
595*37da2899SCharles.Forsyth 
596*37da2899SCharles.Forsyth         if ( (FT_UInt)node->fam_index >= manager->families.count ||
597*37da2899SCharles.Forsyth              entry->link              != FTC_FAMILY_ENTRY_NONE  )
598*37da2899SCharles.Forsyth           FT_ERROR(( "FTC_Manager_Check: invalid node (family index = %ld\n",
599*37da2899SCharles.Forsyth                      node->fam_index ));
600*37da2899SCharles.Forsyth         else
601*37da2899SCharles.Forsyth         {
602*37da2899SCharles.Forsyth           cache   = entry->cache;
603*37da2899SCharles.Forsyth           weight += cache->clazz->node_weight( node, cache );
604*37da2899SCharles.Forsyth         }
605*37da2899SCharles.Forsyth 
606*37da2899SCharles.Forsyth         node = node->mru_next;
607*37da2899SCharles.Forsyth 
608*37da2899SCharles.Forsyth       } while ( node != first );
609*37da2899SCharles.Forsyth 
610*37da2899SCharles.Forsyth       if ( weight != manager->cur_weight )
611*37da2899SCharles.Forsyth         FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
612*37da2899SCharles.Forsyth                    manager->cur_weight, weight ));
613*37da2899SCharles.Forsyth     }
614*37da2899SCharles.Forsyth 
615*37da2899SCharles.Forsyth     /* check circular list */
616*37da2899SCharles.Forsyth     if ( first )
617*37da2899SCharles.Forsyth     {
618*37da2899SCharles.Forsyth       FT_UFast  count = 0;
619*37da2899SCharles.Forsyth 
620*37da2899SCharles.Forsyth 
621*37da2899SCharles.Forsyth       node = first;
622*37da2899SCharles.Forsyth       do
623*37da2899SCharles.Forsyth       {
624*37da2899SCharles.Forsyth         count++;
625*37da2899SCharles.Forsyth         node = node->mru_next;
626*37da2899SCharles.Forsyth 
627*37da2899SCharles.Forsyth       } while ( node != first );
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth       if ( count != manager->num_nodes )
630*37da2899SCharles.Forsyth         FT_ERROR((
631*37da2899SCharles.Forsyth           "FTC_Manager_Check: invalid cache node count %d instead of %d\n",
632*37da2899SCharles.Forsyth           manager->num_nodes, count ));
633*37da2899SCharles.Forsyth     }
634*37da2899SCharles.Forsyth   }
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth #endif /* FT_DEBUG_ERROR */
637*37da2899SCharles.Forsyth 
638*37da2899SCharles.Forsyth 
639*37da2899SCharles.Forsyth   /* `Compress' the manager's data, i.e., get rid of old cache nodes */
640*37da2899SCharles.Forsyth   /* that are not referenced anymore in order to limit the total     */
641*37da2899SCharles.Forsyth   /* memory used by the cache.                                       */
642*37da2899SCharles.Forsyth 
643*37da2899SCharles.Forsyth   /* documentation is in ftcmanag.h */
644*37da2899SCharles.Forsyth 
645*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FTC_Manager_Compress(FTC_Manager manager)646*37da2899SCharles.Forsyth   FTC_Manager_Compress( FTC_Manager  manager )
647*37da2899SCharles.Forsyth   {
648*37da2899SCharles.Forsyth     FTC_Node   node, first;
649*37da2899SCharles.Forsyth 
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth     if ( !manager )
652*37da2899SCharles.Forsyth       return;
653*37da2899SCharles.Forsyth 
654*37da2899SCharles.Forsyth     first = manager->nodes_list;
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth #ifdef FT_DEBUG_ERROR
657*37da2899SCharles.Forsyth     FTC_Manager_Check( manager );
658*37da2899SCharles.Forsyth 
659*37da2899SCharles.Forsyth     FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
660*37da2899SCharles.Forsyth                manager->cur_weight, manager->max_weight,
661*37da2899SCharles.Forsyth                manager->num_nodes ));
662*37da2899SCharles.Forsyth #endif
663*37da2899SCharles.Forsyth 
664*37da2899SCharles.Forsyth     if ( manager->cur_weight < manager->max_weight || first == NULL )
665*37da2899SCharles.Forsyth       return;
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth     /* go to last node - it's a circular list */
668*37da2899SCharles.Forsyth     node = first->mru_prev;
669*37da2899SCharles.Forsyth     do
670*37da2899SCharles.Forsyth     {
671*37da2899SCharles.Forsyth       FTC_Node  prev = node->mru_prev;
672*37da2899SCharles.Forsyth 
673*37da2899SCharles.Forsyth 
674*37da2899SCharles.Forsyth       prev = ( node == first ) ? NULL : node->mru_prev;
675*37da2899SCharles.Forsyth 
676*37da2899SCharles.Forsyth       if ( node->ref_count <= 0 )
677*37da2899SCharles.Forsyth         ftc_node_destroy( node, manager );
678*37da2899SCharles.Forsyth 
679*37da2899SCharles.Forsyth       node = prev;
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth     } while ( node && manager->cur_weight > manager->max_weight );
682*37da2899SCharles.Forsyth   }
683*37da2899SCharles.Forsyth 
684*37da2899SCharles.Forsyth 
685*37da2899SCharles.Forsyth   /* documentation is in ftcmanag.h */
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FTC_Manager_Register_Cache(FTC_Manager manager,FTC_Cache_Class clazz,FTC_Cache * acache)688*37da2899SCharles.Forsyth   FTC_Manager_Register_Cache( FTC_Manager      manager,
689*37da2899SCharles.Forsyth                               FTC_Cache_Class  clazz,
690*37da2899SCharles.Forsyth                               FTC_Cache       *acache )
691*37da2899SCharles.Forsyth   {
692*37da2899SCharles.Forsyth     FT_Error   error = FTC_Err_Invalid_Argument;
693*37da2899SCharles.Forsyth     FTC_Cache  cache = NULL;
694*37da2899SCharles.Forsyth 
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth     if ( manager && clazz && acache )
697*37da2899SCharles.Forsyth     {
698*37da2899SCharles.Forsyth       FT_Memory  memory = manager->library->memory;
699*37da2899SCharles.Forsyth       FT_UInt    idx  = 0;
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth 
702*37da2899SCharles.Forsyth       /* check for an empty cache slot in the manager's table */
703*37da2899SCharles.Forsyth       for ( idx = 0; idx < FTC_MAX_CACHES; idx++ )
704*37da2899SCharles.Forsyth       {
705*37da2899SCharles.Forsyth         if ( manager->caches[idx] == 0 )
706*37da2899SCharles.Forsyth           break;
707*37da2899SCharles.Forsyth       }
708*37da2899SCharles.Forsyth 
709*37da2899SCharles.Forsyth       /* return an error if there are too many registered caches */
710*37da2899SCharles.Forsyth       if ( idx >= FTC_MAX_CACHES )
711*37da2899SCharles.Forsyth       {
712*37da2899SCharles.Forsyth         error = FTC_Err_Too_Many_Caches;
713*37da2899SCharles.Forsyth         FT_ERROR(( "FTC_Manager_Register_Cache:" ));
714*37da2899SCharles.Forsyth         FT_ERROR(( " too many registered caches\n" ));
715*37da2899SCharles.Forsyth         goto Exit;
716*37da2899SCharles.Forsyth       }
717*37da2899SCharles.Forsyth 
718*37da2899SCharles.Forsyth       if ( !FT_ALLOC( cache, clazz->cache_size ) )
719*37da2899SCharles.Forsyth       {
720*37da2899SCharles.Forsyth         cache->manager = manager;
721*37da2899SCharles.Forsyth         cache->memory  = memory;
722*37da2899SCharles.Forsyth         cache->clazz   = clazz;
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth         /* THIS IS VERY IMPORTANT!  IT WILL WRETCH THE MANAGER */
725*37da2899SCharles.Forsyth         /* IF IT IS NOT SET CORRECTLY                          */
726*37da2899SCharles.Forsyth         cache->cache_index = idx;
727*37da2899SCharles.Forsyth 
728*37da2899SCharles.Forsyth         if ( clazz->cache_init )
729*37da2899SCharles.Forsyth         {
730*37da2899SCharles.Forsyth           error = clazz->cache_init( cache );
731*37da2899SCharles.Forsyth           if ( error )
732*37da2899SCharles.Forsyth           {
733*37da2899SCharles.Forsyth             if ( clazz->cache_done )
734*37da2899SCharles.Forsyth               clazz->cache_done( cache );
735*37da2899SCharles.Forsyth 
736*37da2899SCharles.Forsyth             FT_FREE( cache );
737*37da2899SCharles.Forsyth             goto Exit;
738*37da2899SCharles.Forsyth           }
739*37da2899SCharles.Forsyth         }
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth         manager->caches[idx] = cache;
742*37da2899SCharles.Forsyth       }
743*37da2899SCharles.Forsyth     }
744*37da2899SCharles.Forsyth 
745*37da2899SCharles.Forsyth   Exit:
746*37da2899SCharles.Forsyth     *acache = cache;
747*37da2899SCharles.Forsyth     return error;
748*37da2899SCharles.Forsyth   }
749*37da2899SCharles.Forsyth 
750*37da2899SCharles.Forsyth 
751*37da2899SCharles.Forsyth   /* documentation is in ftcmanag.h */
752*37da2899SCharles.Forsyth 
753*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FTC_Node_Unref(FTC_Node node,FTC_Manager manager)754*37da2899SCharles.Forsyth   FTC_Node_Unref( FTC_Node     node,
755*37da2899SCharles.Forsyth                   FTC_Manager  manager )
756*37da2899SCharles.Forsyth   {
757*37da2899SCharles.Forsyth     if ( node && (FT_UInt)node->fam_index < manager->families.count &&
758*37da2899SCharles.Forsyth          manager->families.entries[node->fam_index].cache )
759*37da2899SCharles.Forsyth     {
760*37da2899SCharles.Forsyth       node->ref_count--;
761*37da2899SCharles.Forsyth     }
762*37da2899SCharles.Forsyth   }
763*37da2899SCharles.Forsyth 
764*37da2899SCharles.Forsyth 
765*37da2899SCharles.Forsyth /* END */
766