blob: 5d504e59d401efdbb69701d3d0fb630c5fc4605c [file] [log] [blame]
Werner Lembergeddd9902000-10-12 05:05:40 +00001/***************************************************************************/
2/* */
3/* ftcimage.c */
4/* */
5/* FreeType Image cache (body). */
6/* */
7/* Copyright 2000 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
David Turnerece63792000-10-28 23:34:45 +000019#include <freetype/cache/ftcimage.h>
20#include <freetype/internal/ftmemory.h>
Werner Lemberg8728f292000-08-23 17:32:42 +000021
Werner Lembergeddd9902000-10-12 05:05:40 +000022#include <string.h>
23
David Turnerece63792000-10-28 23:34:45 +000024
25 /* the FT_Glyph image "glyph node" type */
26 typedef struct FTC_GlyphImageRec_
27 {
28 FTC_GlyphNodeRec root;
29 FT_Glyph ft_glyph;
30
31 } FTC_GlyphImageRec, *FTC_GlyphImage;
32
33
34 /* the glyph image queue type */
35 typedef struct FTC_ImageSetRec_
36 {
37 FTC_GlyphSetRec root;
38 FTC_Image_Desc description;
39
40 } FTC_ImageSetRec, *FTC_ImageSet;
41
42
43 typedef struct FTC_Image_CacheRec_
44 {
45 FTC_Glyph_CacheRec root;
46
47 } FTC_Image_CacheRec;
48
Werner Lembergddbb8e72000-10-26 10:04:16 +000049
Werner Lembergeddd9902000-10-12 05:05:40 +000050
51 /*************************************************************************/
52 /*************************************************************************/
53 /***** *****/
54 /***** GLYPH IMAGE NODES *****/
55 /***** *****/
56 /*************************************************************************/
57 /*************************************************************************/
58
59
David Turnerebdce832000-09-19 01:11:11 +000060 LOCAL_FUNC_X
David Turner4e4a4362000-10-28 13:17:11 +000061 void ftc_glyph_image_node_destroy( FTC_GlyphImage node,
62 FTC_GlyphSet gset )
David Turner3b2c50e2000-08-23 21:11:13 +000063 {
David Turner4e4a4362000-10-28 13:17:11 +000064 FT_Memory memory = gset->memory;
Werner Lembergeddd9902000-10-12 05:05:40 +000065
66
David Turner9b8f5c42000-10-28 07:26:59 +000067 FT_Done_Glyph( node->ft_glyph );
David Turner3b2c50e2000-08-23 21:11:13 +000068 FREE( node );
David Turnerb466a762000-08-23 11:22:30 +000069 }
70
Werner Lemberg8728f292000-08-23 17:32:42 +000071
Werner Lemberg4e9dae62000-08-29 16:50:01 +000072 LOCAL_FUNC_X
David Turner4e4a4362000-10-28 13:17:11 +000073 FT_Error ftc_glyph_image_node_new( FTC_GlyphSet gset,
74 FT_UInt glyph_index,
75 FTC_GlyphImage *anode )
Werner Lembergeddd9902000-10-12 05:05:40 +000076 {
David Turner4e4a4362000-10-28 13:17:11 +000077 FT_Memory memory = gset->memory;
78 FTC_ImageSet imageset = (FTC_ImageSet)gset;
David Turnerebdce832000-09-19 01:11:11 +000079 FT_Error error;
David Turner9b8f5c42000-10-28 07:26:59 +000080 FTC_GlyphImage node = 0;
David Turnerebdce832000-09-19 01:11:11 +000081 FT_Face face;
82 FT_Size size;
David Turnerb466a762000-08-23 11:22:30 +000083
Werner Lembergeddd9902000-10-12 05:05:40 +000084
David Turnerebdce832000-09-19 01:11:11 +000085 /* allocate node */
Werner Lembergeddd9902000-10-12 05:05:40 +000086 if ( ALLOC( node, sizeof ( *node ) ) )
David Turnerebdce832000-09-19 01:11:11 +000087 goto Exit;
Werner Lemberg4e9dae62000-08-29 16:50:01 +000088
David Turnerebdce832000-09-19 01:11:11 +000089 /* init its inner fields */
David Turner4e4a4362000-10-28 13:17:11 +000090 FTC_GlyphNode_Init( FTC_GLYPHNODE(node), gset, glyph_index );
David Turnerebdce832000-09-19 01:11:11 +000091
92 /* we will now load the glyph image */
David Turner4e4a4362000-10-28 13:17:11 +000093 error = FTC_Manager_Lookup_Size( gset->manager,
94 &imageset->description.font,
David Turnerb466a762000-08-23 11:22:30 +000095 &face, &size );
Werner Lemberg8728f292000-08-23 17:32:42 +000096 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +000097 {
David Turner9b8f5c42000-10-28 07:26:59 +000098 FT_UInt glyph_index = node->root.glyph_index;
David Turner80b96f32000-08-29 16:04:28 +000099 FT_UInt load_flags = FT_LOAD_DEFAULT;
David Turner4e4a4362000-10-28 13:17:11 +0000100 FT_UInt image_type = imageset->description.image_type;
Werner Lembergeddd9902000-10-12 05:05:40 +0000101
102
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000103 if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
Werner Lembergeddd9902000-10-12 05:05:40 +0000104 {
105 load_flags |= FT_LOAD_RENDER;
David Turner80b96f32000-08-29 16:04:28 +0000106 if ( image_type & ftc_image_flag_monochrome )
107 load_flags |= FT_LOAD_MONOCHROME;
Werner Lembergeddd9902000-10-12 05:05:40 +0000108
David Turner80b96f32000-08-29 16:04:28 +0000109 /* disable embedded bitmaps loading if necessary */
Werner Lembergf50c2952000-09-22 06:52:20 +0000110 if ( image_type & ftc_image_flag_no_sbits )
David Turner80b96f32000-08-29 16:04:28 +0000111 load_flags |= FT_LOAD_NO_BITMAP;
112 }
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000113 else if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_outline )
David Turner80b96f32000-08-29 16:04:28 +0000114 {
115 /* disable embedded bitmaps loading */
116 load_flags |= FT_LOAD_NO_BITMAP;
Werner Lembergeddd9902000-10-12 05:05:40 +0000117
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000118 if ( image_type & ftc_image_flag_unscaled )
David Turner80b96f32000-08-29 16:04:28 +0000119 load_flags |= FT_LOAD_NO_SCALE;
120 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000121
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000122 if ( image_type & ftc_image_flag_unhinted )
David Turner80b96f32000-08-29 16:04:28 +0000123 load_flags |= FT_LOAD_NO_HINTING;
Werner Lembergeddd9902000-10-12 05:05:40 +0000124
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000125 if ( image_type & ftc_image_flag_autohinted )
David Turner80b96f32000-08-29 16:04:28 +0000126 load_flags |= FT_LOAD_FORCE_AUTOHINT;
127
128 error = FT_Load_Glyph( face, glyph_index, load_flags );
Werner Lemberg8728f292000-08-23 17:32:42 +0000129 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +0000130 {
David Turner80b96f32000-08-29 16:04:28 +0000131 if ( face->glyph->format == ft_glyph_format_bitmap ||
132 face->glyph->format == ft_glyph_format_outline )
Werner Lembergeddd9902000-10-12 05:05:40 +0000133 {
David Turnerb466a762000-08-23 11:22:30 +0000134 /* ok, copy it */
135 FT_Glyph glyph;
Werner Lembergeddd9902000-10-12 05:05:40 +0000136
137
David Turnerb466a762000-08-23 11:22:30 +0000138 error = FT_Get_Glyph( face->glyph, &glyph );
Werner Lemberg8728f292000-08-23 17:32:42 +0000139 if ( !error )
David Turner9b8f5c42000-10-28 07:26:59 +0000140 node->ft_glyph = glyph;
David Turnerb466a762000-08-23 11:22:30 +0000141 }
David Turnerb466a762000-08-23 11:22:30 +0000142 else
David Turner80b96f32000-08-29 16:04:28 +0000143 error = FT_Err_Invalid_Argument;
David Turner3b2c50e2000-08-23 21:11:13 +0000144 }
145 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000146
David Turner3b2c50e2000-08-23 21:11:13 +0000147 Exit:
Werner Lembergeddd9902000-10-12 05:05:40 +0000148 if ( error && node )
149 FREE( node );
David Turner3b2c50e2000-08-23 21:11:13 +0000150
David Turnerebdce832000-09-19 01:11:11 +0000151 *anode = node;
David Turner3b2c50e2000-08-23 21:11:13 +0000152 return error;
153 }
154
155
Werner Lembergeddd9902000-10-12 05:05:40 +0000156 /* this function is important because it is both part of */
David Turner4e4a4362000-10-28 13:17:11 +0000157 /* a FTC_GlyphSet_Class and a FTC_CacheNode_Class */
Werner Lembergeddd9902000-10-12 05:05:40 +0000158 /* */
Werner Lemberg4e9dae62000-08-29 16:50:01 +0000159 LOCAL_FUNC_X
David Turner9b8f5c42000-10-28 07:26:59 +0000160 FT_ULong ftc_glyph_image_node_size( FTC_GlyphImage node )
David Turner3b2c50e2000-08-23 21:11:13 +0000161 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000162 FT_ULong size = 0;
David Turner9b8f5c42000-10-28 07:26:59 +0000163 FT_Glyph glyph = node->ft_glyph;
Werner Lembergeddd9902000-10-12 05:05:40 +0000164
165
166 switch ( glyph->format )
David Turner3b2c50e2000-08-23 21:11:13 +0000167 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000168 case ft_glyph_format_bitmap:
169 {
170 FT_BitmapGlyph bitg;
171
172
173 bitg = (FT_BitmapGlyph)glyph;
174 size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) +
175 sizeof ( *bitg );
176 }
177 break;
178
179 case ft_glyph_format_outline:
180 {
181 FT_OutlineGlyph outg;
182
183
184 outg = (FT_OutlineGlyph)glyph;
185 size = outg->outline.n_points *
186 ( sizeof( FT_Vector ) + sizeof ( FT_Byte ) ) +
187 outg->outline.n_contours * sizeof ( FT_Short ) +
188 sizeof ( *outg );
189 }
190 break;
191
192 default:
193 ;
David Turner3b2c50e2000-08-23 21:11:13 +0000194 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000195
196 size += sizeof ( *node );
David Turnerebdce832000-09-19 01:11:11 +0000197 return size;
David Turner80b96f32000-08-29 16:04:28 +0000198 }
199
David Turner3b2c50e2000-08-23 21:11:13 +0000200
Werner Lembergeddd9902000-10-12 05:05:40 +0000201 /*************************************************************************/
202 /*************************************************************************/
203 /***** *****/
David Turnerece63792000-10-28 23:34:45 +0000204 /***** GLYPH IMAGE SETS *****/
Werner Lembergeddd9902000-10-12 05:05:40 +0000205 /***** *****/
206 /*************************************************************************/
207 /*************************************************************************/
David Turnerebdce832000-09-19 01:11:11 +0000208
209
210 LOCAL_FUNC_X
David Turner4e4a4362000-10-28 13:17:11 +0000211 FT_Error ftc_image_set_init( FTC_ImageSet iset,
212 FTC_Image_Desc* type )
David Turner3b2c50e2000-08-23 21:11:13 +0000213 {
David Turner4e4a4362000-10-28 13:17:11 +0000214 iset->description = *type;
David Turnerebdce832000-09-19 01:11:11 +0000215 return 0;
David Turner3b2c50e2000-08-23 21:11:13 +0000216 }
217
218
David Turnerebdce832000-09-19 01:11:11 +0000219 LOCAL_FUNC_X
David Turner4e4a4362000-10-28 13:17:11 +0000220 FT_Bool ftc_image_set_compare( FTC_ImageSet iset,
221 FTC_Image_Desc* type )
David Turnerebdce832000-09-19 01:11:11 +0000222 {
David Turner4e4a4362000-10-28 13:17:11 +0000223 return !memcmp( &iset->description, type, sizeof ( *type ) );
David Turnerebdce832000-09-19 01:11:11 +0000224 }
David Turnerebdce832000-09-19 01:11:11 +0000225
Werner Lembergeddd9902000-10-12 05:05:40 +0000226
David Turner4e4a4362000-10-28 13:17:11 +0000227 FT_CPLUSPLUS( const FTC_GlyphSet_Class ) ftc_glyph_image_set_class =
David Turnerebdce832000-09-19 01:11:11 +0000228 {
David Turner4e4a4362000-10-28 13:17:11 +0000229 sizeof( FTC_ImageSetRec ),
Werner Lembergeddd9902000-10-12 05:05:40 +0000230
David Turner4e4a4362000-10-28 13:17:11 +0000231 (FTC_GlyphSet_InitFunc) ftc_image_set_init,
232 (FTC_GlyphSet_DoneFunc) 0,
233 (FTC_GlyphSet_CompareFunc) ftc_image_set_compare,
Werner Lembergeddd9902000-10-12 05:05:40 +0000234
David Turner4e4a4362000-10-28 13:17:11 +0000235 (FTC_GlyphSet_NewNodeFunc) ftc_glyph_image_node_new,
236 (FTC_GlyphSet_SizeNodeFunc) ftc_glyph_image_node_size,
237 (FTC_GlyphSet_DestroyNodeFunc)ftc_glyph_image_node_destroy
David Turnerebdce832000-09-19 01:11:11 +0000238 };
239
240
Werner Lembergeddd9902000-10-12 05:05:40 +0000241 /*************************************************************************/
242 /*************************************************************************/
243 /***** *****/
244 /***** GLYPH IMAGE CACHE *****/
245 /***** *****/
246 /*************************************************************************/
247 /*************************************************************************/
David Turnerebdce832000-09-19 01:11:11 +0000248
249
Werner Lembergeddd9902000-10-12 05:05:40 +0000250 FT_CPLUSPLUS( const FTC_Glyph_Cache_Class ) ftc_glyph_image_cache_class =
David Turnerebdce832000-09-19 01:11:11 +0000251 {
252 {
David Turner4e4a4362000-10-28 13:17:11 +0000253 sizeof( FTC_Image_CacheRec ),
254 (FTC_Cache_InitFunc) FTC_Glyph_Cache_Init,
255 (FTC_Cache_DoneFunc) FTC_Glyph_Cache_Done
David Turnerebdce832000-09-19 01:11:11 +0000256 },
David Turner4e4a4362000-10-28 13:17:11 +0000257 (FTC_GlyphSet_Class*) &ftc_glyph_image_set_class
David Turnerebdce832000-09-19 01:11:11 +0000258 };
259
260
261 FT_EXPORT_FUNC( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager,
262 FTC_Image_Cache* acache )
263 {
264 return FTC_Manager_Register_Cache(
265 manager,
266 (FTC_Cache_Class*)&ftc_glyph_image_cache_class,
267 (FTC_Cache*)acache );
268 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000269
David Turnerebdce832000-09-19 01:11:11 +0000270
David Turner9b8f5c42000-10-28 07:26:59 +0000271 FT_EXPORT_DEF( FT_Error )
272 FTC_Image_Cache_Lookup( FTC_Image_Cache cache,
273 FTC_Image_Desc* desc,
274 FT_UInt gindex,
275 FT_Glyph* aglyph )
David Turner3b2c50e2000-08-23 21:11:13 +0000276 {
David Turner4e4a4362000-10-28 13:17:11 +0000277 FT_Error error;
278 FTC_GlyphSet gset;
279 FTC_GlyphNode node;
280 FTC_Manager manager;
David Turner3b2c50e2000-08-23 21:11:13 +0000281
David Turner4e4a4362000-10-28 13:17:11 +0000282 FTC_ImageSet img_set;
Werner Lembergd1b74752000-08-24 16:29:15 +0000283
Werner Lembergeddd9902000-10-12 05:05:40 +0000284
Werner Lembergd1b74752000-08-24 16:29:15 +0000285 /* check for valid `desc' delayed to FT_Lru_Lookup() */
286
287 if ( !cache || !aglyph )
288 return FT_Err_Invalid_Argument;
289
David Turner4e4a4362000-10-28 13:17:11 +0000290 *aglyph = 0;
291 gset = cache->root.last_gset;
292 img_set = (FTC_ImageSet)gset;
293 if ( !gset || memcmp( &img_set->description, desc, sizeof ( *desc ) ) )
David Turner35db7322000-08-24 12:39:40 +0000294 {
David Turner4e4a4362000-10-28 13:17:11 +0000295 error = FT_Lru_Lookup( cache->root.gsets_lru,
Werner Lembergd1b74752000-08-24 16:29:15 +0000296 (FT_LruKey)desc,
David Turner4e4a4362000-10-28 13:17:11 +0000297 (FT_Pointer*)&gset );
298 cache->root.last_gset = gset;
Werner Lembergd1b74752000-08-24 16:29:15 +0000299 if ( error )
David Turner35db7322000-08-24 12:39:40 +0000300 goto Exit;
301 }
David Turner3b2c50e2000-08-23 21:11:13 +0000302
David Turner4e4a4362000-10-28 13:17:11 +0000303 error = FTC_GlyphSet_Lookup_Node( gset, gindex, &node );
Werner Lembergd1b74752000-08-24 16:29:15 +0000304 if ( error )
David Turner3b2c50e2000-08-23 21:11:13 +0000305 goto Exit;
306
David Turnerebdce832000-09-19 01:11:11 +0000307 /* now compress the manager's cache pool if needed */
308 manager = cache->root.root.manager;
Werner Lembergeddd9902000-10-12 05:05:40 +0000309 if ( manager->num_bytes > manager->max_bytes )
David Turnerebdce832000-09-19 01:11:11 +0000310 {
David Turner9b8f5c42000-10-28 07:26:59 +0000311 FTC_GlyphNode_Ref ( node );
David Turnerebdce832000-09-19 01:11:11 +0000312 FTC_Manager_Compress( manager );
David Turner9b8f5c42000-10-28 07:26:59 +0000313 FTC_GlyphNode_Unref ( node );
David Turnerebdce832000-09-19 01:11:11 +0000314 }
David Turner80b96f32000-08-29 16:04:28 +0000315
David Turner9b8f5c42000-10-28 07:26:59 +0000316 *aglyph = ((FTC_GlyphImage)node)->ft_glyph;
David Turner3b2c50e2000-08-23 21:11:13 +0000317
318 Exit:
319 return error;
320 }
321
322
Werner Lembergeddd9902000-10-12 05:05:40 +0000323/* END */