update for HEAD-2003050101
[reactos.git] / lib / freetype / src / cache / ftcimage.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftcimage.c                                                             */
4 /*                                                                         */
5 /*    FreeType Image cache (body).                                         */
6 /*                                                                         */
7 /*  Copyright 2000-2001 by                                                 */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_CACHE_H
21 #include FT_CACHE_IMAGE_H
22 #include FT_CACHE_INTERNAL_GLYPH_H
23 #include FT_INTERNAL_MEMORY_H
24
25 #include "ftcerror.h"
26
27
28   /* the FT_Glyph image node type */
29   typedef struct  FTC_ImageNodeRec_
30   {
31     FTC_GlyphNodeRec  gnode;
32     FT_Glyph          glyph;
33
34   } FTC_ImageNodeRec, *FTC_ImageNode;
35
36
37 #define FTC_IMAGE_NODE( x )         ( (FTC_ImageNode)( x ) )
38 #define FTC_IMAGE_NODE_GINDEX( x )  FTC_GLYPH_NODE_GINDEX( x )
39
40
41   /* the glyph image query */
42   typedef struct  FTC_ImageQueryRec_
43   {
44     FTC_GlyphQueryRec  gquery;
45     FTC_ImageTypeRec   type;
46
47   } FTC_ImageQueryRec, *FTC_ImageQuery;
48
49
50 #define FTC_IMAGE_QUERY( x )  ( (FTC_ImageQuery)( x ) )
51
52
53   /* the glyph image set type */
54   typedef struct  FTC_ImageFamilyRec_
55   {
56     FTC_GlyphFamilyRec  gfam;
57     FTC_ImageTypeRec    type;
58
59   } FTC_ImageFamilyRec, *FTC_ImageFamily;
60
61
62 #define FTC_IMAGE_FAMILY( x )         ( (FTC_ImageFamily)( x ) )
63 #define FTC_IMAGE_FAMILY_MEMORY( x )  FTC_GLYPH_FAMILY_MEMORY( &(x)->gfam )
64
65
66   /*************************************************************************/
67   /*************************************************************************/
68   /*****                                                               *****/
69   /*****                    GLYPH IMAGE NODES                          *****/
70   /*****                                                               *****/
71   /*************************************************************************/
72   /*************************************************************************/
73
74
75   /* finalize a given glyph image node */
76   FT_CALLBACK_DEF( void )
77   ftc_image_node_done( FTC_ImageNode  inode,
78                        FTC_Cache      cache )
79   {
80     if ( inode->glyph )
81     {
82       FT_Done_Glyph( inode->glyph );
83       inode->glyph = NULL;
84     }
85
86     ftc_glyph_node_done( FTC_GLYPH_NODE( inode ), cache );
87   }
88
89
90   /* initialize a new glyph image node */
91   FT_CALLBACK_DEF( FT_Error )
92   ftc_image_node_init( FTC_ImageNode   inode,
93                        FTC_GlyphQuery  gquery,
94                        FTC_Cache       cache )
95   {
96     FTC_ImageFamily  ifam = FTC_IMAGE_FAMILY( gquery->query.family );
97     FT_Error         error;
98     FT_Face          face;
99     FT_Size          size;
100
101
102     /* initialize its inner fields */
103     ftc_glyph_node_init( FTC_GLYPH_NODE( inode ),
104                          gquery->gindex,
105                          FTC_GLYPH_FAMILY( ifam ) );
106
107     /* we will now load the glyph image */
108     error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager,
109                                      &ifam->type.font,
110                                      &face, &size );
111     if ( !error )
112     {
113       FT_UInt  gindex = FTC_GLYPH_NODE_GINDEX( inode );
114
115
116       error = FT_Load_Glyph( face, gindex, ifam->type.flags );
117       if ( !error )
118       {
119         if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
120              face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
121         {
122           /* ok, copy it */
123           FT_Glyph  glyph;
124
125
126           error = FT_Get_Glyph( face->glyph, &glyph );
127           if ( !error )
128           {
129             inode->glyph = glyph;
130             goto Exit;
131           }
132         }
133         else
134           error = FTC_Err_Invalid_Argument;
135       }
136     }
137
138     /* in case of error */
139     ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache );
140
141   Exit:
142     return error;
143   }
144
145
146   FT_CALLBACK_DEF( FT_ULong )
147   ftc_image_node_weight( FTC_ImageNode  inode )
148   {
149     FT_ULong  size  = 0;
150     FT_Glyph  glyph = inode->glyph;
151
152
153     switch ( glyph->format )
154     {
155     case FT_GLYPH_FORMAT_BITMAP:
156       {
157         FT_BitmapGlyph  bitg;
158
159
160         bitg = (FT_BitmapGlyph)glyph;
161         size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) +
162                sizeof ( *bitg );
163       }
164       break;
165
166     case FT_GLYPH_FORMAT_OUTLINE:
167       {
168         FT_OutlineGlyph  outg;
169
170
171         outg = (FT_OutlineGlyph)glyph;
172         size = outg->outline.n_points *
173                  ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
174                outg->outline.n_contours * sizeof ( FT_Short ) +
175                sizeof ( *outg );
176       }
177       break;
178
179     default:
180       ;
181     }
182
183     size += sizeof ( *inode );
184     return size;
185   }
186
187
188   /*************************************************************************/
189   /*************************************************************************/
190   /*****                                                               *****/
191   /*****                    GLYPH IMAGE SETS                           *****/
192   /*****                                                               *****/
193   /*************************************************************************/
194   /*************************************************************************/
195
196
197   FT_CALLBACK_DEF( FT_Error )
198   ftc_image_family_init( FTC_ImageFamily  ifam,
199                          FTC_ImageQuery   iquery,
200                          FTC_Cache        cache )
201   {
202     FTC_Manager  manager = cache->manager;
203     FT_Error     error;
204     FT_Face      face;
205
206
207     ifam->type = iquery->type;
208
209     /* we need to compute "iquery.item_total" now */
210     error = FTC_Manager_Lookup_Face( manager,
211                                      iquery->type.font.face_id,
212                                      &face );
213     if ( !error )
214     {
215       error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( ifam ),
216                                      FTC_IMAGE_TYPE_HASH( &ifam->type ),
217                                      1,
218                                      face->num_glyphs,
219                                      FTC_GLYPH_QUERY( iquery ),
220                                      cache );
221     }
222
223     return error;
224   }
225
226
227   FT_CALLBACK_DEF( FT_Bool )
228   ftc_image_family_compare( FTC_ImageFamily  ifam,
229                             FTC_ImageQuery   iquery )
230   {
231     FT_Bool  result;
232
233
234     result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) );
235     if ( result )
236       FTC_GLYPH_FAMILY_FOUND( ifam, iquery );
237
238     return result;
239   }
240
241
242   /*************************************************************************/
243   /*************************************************************************/
244   /*****                                                               *****/
245   /*****                    GLYPH IMAGE CACHE                          *****/
246   /*****                                                               *****/
247   /*************************************************************************/
248   /*************************************************************************/
249
250
251
252   FT_CALLBACK_TABLE_DEF
253   const FTC_Cache_ClassRec  ftc_image_cache_class =
254   {
255     sizeof ( FTC_CacheRec ),
256     (FTC_Cache_InitFunc) ftc_cache_init,
257     (FTC_Cache_ClearFunc)ftc_cache_clear,
258     (FTC_Cache_DoneFunc) ftc_cache_done,
259
260     sizeof ( FTC_ImageFamilyRec ),
261     (FTC_Family_InitFunc)   ftc_image_family_init,
262     (FTC_Family_CompareFunc)ftc_image_family_compare,
263     (FTC_Family_DoneFunc)   ftc_glyph_family_done,
264
265     sizeof ( FTC_ImageNodeRec ),
266     (FTC_Node_InitFunc)   ftc_image_node_init,
267     (FTC_Node_WeightFunc) ftc_image_node_weight,
268     (FTC_Node_CompareFunc)ftc_glyph_node_compare,
269     (FTC_Node_DoneFunc)   ftc_image_node_done
270   };
271
272
273   /* documentation is in ftcimage.h */
274
275   FT_EXPORT_DEF( FT_Error )
276   FTC_ImageCache_New( FTC_Manager      manager,
277                       FTC_ImageCache  *acache )
278   {
279     return FTC_Manager_Register_Cache(
280              manager,
281              (FTC_Cache_Class)&ftc_image_cache_class,
282              FTC_CACHE_P( acache ) );
283   }
284
285
286   /* documentation is in ftcimage.h */
287
288   FT_EXPORT_DEF( FT_Error )
289   FTC_ImageCache_Lookup( FTC_ImageCache  cache,
290                          FTC_ImageType   type,
291                          FT_UInt         gindex,
292                          FT_Glyph       *aglyph,
293                          FTC_Node       *anode )
294   {
295     FTC_ImageQueryRec  iquery;
296     FTC_ImageNode      node;
297     FT_Error           error;
298
299
300     /* some argument checks are delayed to ftc_cache_lookup */
301     if ( !aglyph )
302       return FTC_Err_Invalid_Argument;
303
304     if ( anode )
305       *anode  = NULL;
306
307     iquery.gquery.gindex = gindex;
308     iquery.type          = *type;
309
310     error = ftc_cache_lookup( FTC_CACHE( cache ),
311                               FTC_QUERY( &iquery ),
312                               (FTC_Node*)&node );
313     if ( !error )
314     {
315       *aglyph = node->glyph;
316
317       if ( anode )
318       {
319         *anode = (FTC_Node)node;
320         FTC_NODE( node )->ref_count++;
321       }
322     }
323
324     return error;
325   }
326
327
328   /* backwards-compatibility functions */
329
330   FT_EXPORT_DEF( FT_Error )
331   FTC_Image_Cache_New( FTC_Manager       manager,
332                        FTC_Image_Cache  *acache )
333   {
334     return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
335   }
336
337
338   FT_EXPORT_DEF( FT_Error )
339   FTC_Image_Cache_Lookup( FTC_Image_Cache  icache,
340                           FTC_Image_Desc*  desc,
341                           FT_UInt          gindex,
342                           FT_Glyph        *aglyph )
343   {
344     FTC_ImageTypeRec  type0;
345
346
347     if ( !desc )
348       return FTC_Err_Invalid_Argument;
349
350     type0.font = desc->font;
351
352     /* convert image type flags to load flags */
353     {
354       FT_UInt  load_flags = FT_LOAD_DEFAULT;
355       FT_UInt  type       = desc->image_type;
356
357
358       /* determine load flags, depending on the font description's */
359       /* image type                                                */
360
361       if ( ftc_image_format( type ) == ftc_image_format_bitmap )
362       {
363         if ( type & ftc_image_flag_monochrome )
364           load_flags |= FT_LOAD_MONOCHROME;
365
366         /* disable embedded bitmaps loading if necessary */
367         if ( type & ftc_image_flag_no_sbits )
368           load_flags |= FT_LOAD_NO_BITMAP;
369       }
370       else
371       {
372         /* we want an outline, don't load embedded bitmaps */
373         load_flags |= FT_LOAD_NO_BITMAP;
374
375         if ( type & ftc_image_flag_unscaled )
376           load_flags |= FT_LOAD_NO_SCALE;
377       }
378
379       /* always render glyphs to bitmaps */
380       load_flags |= FT_LOAD_RENDER;
381
382       if ( type & ftc_image_flag_unhinted )
383         load_flags |= FT_LOAD_NO_HINTING;
384
385       if ( type & ftc_image_flag_autohinted )
386         load_flags |= FT_LOAD_FORCE_AUTOHINT;
387
388       type0.flags = load_flags;
389     }
390
391     return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
392                                    &type0,
393                                    gindex,
394                                    aglyph,
395                                    NULL );
396   }
397
398
399 /* END */