xref: /inferno-os/libfreetype/ftcimage.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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 )
ftc_image_node_done(FTC_ImageNode inode,FTC_Cache cache)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 )
ftc_image_node_init(FTC_ImageNode inode,FTC_GlyphQuery gquery,FTC_Cache cache)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 )
ftc_image_node_weight(FTC_ImageNode inode)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 )
ftc_image_family_init(FTC_ImageFamily ifam,FTC_ImageQuery iquery,FTC_Cache cache)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 )
ftc_image_family_compare(FTC_ImageFamily ifam,FTC_ImageQuery iquery)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 )
FTC_ImageCache_New(FTC_Manager manager,FTC_ImageCache * acache)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 )
FTC_ImageCache_Lookup(FTC_ImageCache cache,FTC_ImageType type,FT_UInt gindex,FT_Glyph * aglyph,FTC_Node * anode)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 )
FTC_Image_Cache_New(FTC_Manager manager,FTC_Image_Cache * acache)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 )
FTC_Image_Cache_Lookup(FTC_Image_Cache icache,FTC_Image_Desc * desc,FT_UInt gindex,FT_Glyph * aglyph)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 */
400