1 /***************************************************************************/
5 /* FreeType sbits manager (body). */
7 /* Copyright 2000-2001, 2002 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
21 #include FT_CACHE_SMALL_BITMAPS_H
22 #include FT_CACHE_INTERNAL_GLYPH_H
23 #include FT_INTERNAL_OBJECTS_H
24 #include FT_INTERNAL_DEBUG_H
30 #define FTC_SBIT_ITEMS_PER_NODE 16
33 typedef struct FTC_SBitNodeRec_* FTC_SBitNode;
35 typedef struct FTC_SBitNodeRec_
37 FTC_GlyphNodeRec gnode;
38 FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];
43 #define FTC_SBIT_NODE( x ) ( (FTC_SBitNode)( x ) )
46 typedef struct FTC_SBitQueryRec_
48 FTC_GlyphQueryRec gquery;
49 FTC_ImageTypeRec type;
51 } FTC_SBitQueryRec, *FTC_SBitQuery;
54 #define FTC_SBIT_QUERY( x ) ( (FTC_SBitQuery)( x ) )
57 typedef struct FTC_SBitFamilyRec_* FTC_SBitFamily;
59 /* sbit family structure */
60 typedef struct FTC_SBitFamilyRec_
62 FTC_GlyphFamilyRec gfam;
63 FTC_ImageTypeRec type;
68 #define FTC_SBIT_FAMILY( x ) ( (FTC_SBitFamily)( x ) )
69 #define FTC_SBIT_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &( x )->cset )
72 /*************************************************************************/
73 /*************************************************************************/
75 /***** SBIT CACHE NODES *****/
77 /*************************************************************************/
78 /*************************************************************************/
82 ftc_sbit_copy_bitmap( FTC_SBit sbit,
87 FT_Int pitch = bitmap->pitch;
94 size = (FT_ULong)( pitch * bitmap->rows );
96 if ( !FT_ALLOC( sbit->buffer, size ) )
97 FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
103 FT_CALLBACK_DEF( void )
104 ftc_sbit_node_done( FTC_SBitNode snode,
107 FTC_SBit sbit = snode->sbits;
108 FT_UInt count = FTC_GLYPH_NODE( snode )->item_count;
109 FT_Memory memory = cache->memory;
112 for ( ; count > 0; sbit++, count-- )
113 FT_FREE( sbit->buffer );
115 ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
120 ftc_sbit_node_load( FTC_SBitNode snode,
127 FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
134 if ( gindex < (FT_UInt)gnode->item_start ||
135 gindex >= (FT_UInt)gnode->item_start + gnode->item_count )
137 FT_ERROR(( "ftc_sbit_node_load: invalid glyph index" ));
138 return FTC_Err_Invalid_Argument;
141 memory = manager->library->memory;
143 sbit = snode->sbits + ( gindex - gnode->item_start );
145 error = FTC_Manager_Lookup_Size( manager, &sfam->type.font,
149 /* by default, indicates a `missing' glyph */
152 error = FT_Load_Glyph( face, gindex, sfam->type.flags | FT_LOAD_RENDER );
156 FT_GlyphSlot slot = face->glyph;
157 FT_Bitmap* bitmap = &slot->bitmap;
158 FT_Int xadvance, yadvance;
161 /* check that our values fit into 8-bit containers! */
162 /* If this is not the case, our bitmap is too large */
163 /* and we will leave it as `missing' with sbit.buffer = 0 */
165 #define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
166 #define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
168 /* XXX: FIXME: add support for vertical layouts maybe */
170 /* horizontal advance in pixels */
171 xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
172 yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
174 if ( CHECK_BYTE( bitmap->rows ) &&
175 CHECK_BYTE( bitmap->width ) &&
176 CHECK_CHAR( bitmap->pitch ) &&
177 CHECK_CHAR( slot->bitmap_left ) &&
178 CHECK_CHAR( slot->bitmap_top ) &&
179 CHECK_CHAR( xadvance ) &&
180 CHECK_CHAR( yadvance ) )
182 sbit->width = (FT_Byte)bitmap->width;
183 sbit->height = (FT_Byte)bitmap->rows;
184 sbit->pitch = (FT_Char)bitmap->pitch;
185 sbit->left = (FT_Char)slot->bitmap_left;
186 sbit->top = (FT_Char)slot->bitmap_top;
187 sbit->xadvance = (FT_Char)xadvance;
188 sbit->yadvance = (FT_Char)yadvance;
189 sbit->format = (FT_Byte)bitmap->pixel_mode;
190 sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
192 #if 0 /* this doesn't work well with embedded bitmaps !! */
194 /* grab the bitmap when possible - this is a hack! */
195 if ( slot->flags & FT_GLYPH_OWN_BITMAP )
197 slot->flags &= ~FT_GLYPH_OWN_BITMAP;
198 sbit->buffer = bitmap->buffer;
203 /* copy the bitmap into a new buffer -- ignore error */
204 error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
207 /* now, compute size */
209 *asize = ABS( sbit->pitch ) * sbit->height;
211 } /* glyph dimensions ok */
213 } /* glyph loading successful */
215 /* ignore the errors that might have occurred -- */
216 /* we mark unloaded glyphs with `sbit.buffer == 0' */
217 /* and 'width == 255', 'height == 0' */
219 if ( error && error != FT_Err_Out_Of_Memory )
223 /* sbit->buffer == NULL too! */
231 FT_CALLBACK_DEF( FT_Error )
232 ftc_sbit_node_init( FTC_SBitNode snode,
233 FTC_GlyphQuery gquery,
239 ftc_glyph_node_init( FTC_GLYPH_NODE( snode ),
241 FTC_GLYPH_FAMILY( gquery->query.family ) );
243 error = ftc_sbit_node_load( snode,
245 FTC_SBIT_FAMILY( FTC_QUERY( gquery )->family ),
249 ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
255 FT_CALLBACK_DEF( FT_ULong )
256 ftc_sbit_node_weight( FTC_SBitNode snode )
258 FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
259 FT_UInt count = gnode->item_count;
260 FTC_SBit sbit = snode->sbits;
265 /* the node itself */
266 size = sizeof ( *snode );
268 /* the sbit records */
269 size += FTC_GLYPH_NODE( snode )->item_count * sizeof ( FTC_SBitRec );
271 for ( ; count > 0; count--, sbit++ )
279 /* add the size of a given glyph image */
280 size += pitch * sbit->height;
288 FT_CALLBACK_DEF( FT_Bool )
289 ftc_sbit_node_compare( FTC_SBitNode snode,
290 FTC_SBitQuery squery,
293 FTC_GlyphQuery gquery = FTC_GLYPH_QUERY( squery );
294 FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
298 result = ftc_glyph_node_compare( gnode, gquery );
301 /* check if we need to load the glyph bitmap now */
302 FT_UInt gindex = gquery->gindex;
303 FTC_SBit sbit = snode->sbits + ( gindex - gnode->item_start );
306 if ( sbit->buffer == NULL && sbit->width != 255 )
311 /* yes, it's safe to ignore errors here */
312 ftc_sbit_node_load( snode,
314 FTC_SBIT_FAMILY( FTC_QUERY( squery )->family ),
318 cache->manager->cur_weight += size;
326 /*************************************************************************/
327 /*************************************************************************/
329 /***** SBITS FAMILIES *****/
331 /*************************************************************************/
332 /*************************************************************************/
335 FT_CALLBACK_DEF( FT_Error )
336 ftc_sbit_family_init( FTC_SBitFamily sfam,
337 FTC_SBitQuery squery,
340 FTC_Manager manager = cache->manager;
345 sfam->type = squery->type;
347 /* we need to compute "cquery.item_total" now */
348 error = FTC_Manager_Lookup_Face( manager,
349 squery->type.font.face_id,
353 error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( sfam ),
354 FTC_IMAGE_TYPE_HASH( &sfam->type ),
355 FTC_SBIT_ITEMS_PER_NODE,
357 FTC_GLYPH_QUERY( squery ),
365 FT_CALLBACK_DEF( FT_Bool )
366 ftc_sbit_family_compare( FTC_SBitFamily sfam,
367 FTC_SBitQuery squery )
372 /* we need to set the "cquery.cset" field or our query for */
373 /* faster glyph comparisons in ftc_sbit_node_compare */
375 result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &sfam->type, &squery->type ) );
377 FTC_GLYPH_FAMILY_FOUND( sfam, squery );
383 /*************************************************************************/
384 /*************************************************************************/
386 /***** SBITS CACHE *****/
388 /*************************************************************************/
389 /*************************************************************************/
392 FT_CALLBACK_TABLE_DEF
393 const FTC_Cache_ClassRec ftc_sbit_cache_class =
395 sizeof ( FTC_CacheRec ),
396 (FTC_Cache_InitFunc) ftc_cache_init,
397 (FTC_Cache_ClearFunc)ftc_cache_clear,
398 (FTC_Cache_DoneFunc) ftc_cache_done,
400 sizeof ( FTC_SBitFamilyRec ),
401 (FTC_Family_InitFunc) ftc_sbit_family_init,
402 (FTC_Family_CompareFunc)ftc_sbit_family_compare,
403 (FTC_Family_DoneFunc) ftc_glyph_family_done,
405 sizeof ( FTC_SBitNodeRec ),
406 (FTC_Node_InitFunc) ftc_sbit_node_init,
407 (FTC_Node_WeightFunc) ftc_sbit_node_weight,
408 (FTC_Node_CompareFunc)ftc_sbit_node_compare,
409 (FTC_Node_DoneFunc) ftc_sbit_node_done
413 /* documentation is in ftcsbits.h */
415 FT_EXPORT_DEF( FT_Error )
416 FTC_SBitCache_New( FTC_Manager manager,
417 FTC_SBitCache *acache )
419 return FTC_Manager_Register_Cache( manager,
420 &ftc_sbit_cache_class,
421 (FTC_Cache*)acache );
425 /* documentation is in ftcsbits.h */
427 #ifdef FTC_CACHE_USE_INLINE
429 #define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
430 ftc_sbit_family_compare( (FTC_SBitFamily)(f), (FTC_SBitQuery)(q) )
432 #define GEN_CACHE_NODE_COMPARE( n, q, c ) \
433 ftc_sbit_node_compare( (FTC_SBitNode)(n), (FTC_SBitQuery)(q), c )
435 #define GEN_CACHE_LOOKUP ftc_sbit_cache_lookup
436 #include "ftccache.i"
438 #else /* !FTC_CACHE_USE_INLINE */
440 #define ftc_sbit_cache_lookup ftc_cache_lookup
442 #endif /* !FTC_CACHE_USE_INLINE */
444 FT_EXPORT_DEF( FT_Error )
445 FTC_SBitCache_Lookup( FTC_SBitCache cache,
452 FTC_SBitQueryRec squery;
456 /* other argument checks delayed to ftc_cache_lookup */
458 return FTC_Err_Invalid_Argument;
465 squery.gquery.gindex = gindex;
468 error = ftc_sbit_cache_lookup( FTC_CACHE( cache ),
469 FTC_QUERY( &squery ),
473 *ansbit = node->sbits + ( gindex - FTC_GLYPH_NODE( node )->item_start );
477 *anode = FTC_NODE( node );
478 FTC_NODE( node )->ref_count++;
485 /* backwards-compatibility functions */
487 FT_EXPORT_DEF( FT_Error )
488 FTC_SBit_Cache_New( FTC_Manager manager,
489 FTC_SBit_Cache *acache )
491 return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
495 FT_EXPORT_DEF( FT_Error )
496 FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache,
497 FTC_Image_Desc* desc,
501 FTC_ImageTypeRec type0;
505 return FTC_Err_Invalid_Argument;
507 type0.font = desc->font;
510 /* convert image type flags to load flags */
512 FT_UInt load_flags = FT_LOAD_DEFAULT;
513 FT_UInt type = desc->image_type;
516 /* determine load flags, depending on the font description's */
519 if ( ftc_image_format( type ) == ftc_image_format_bitmap )
521 if ( type & ftc_image_flag_monochrome )
522 load_flags |= FT_LOAD_MONOCHROME;
524 /* disable embedded bitmaps loading if necessary */
525 if ( type & ftc_image_flag_no_sbits )
526 load_flags |= FT_LOAD_NO_BITMAP;
530 /* we want an outline, don't load embedded bitmaps */
531 load_flags |= FT_LOAD_NO_BITMAP;
533 if ( type & ftc_image_flag_unscaled )
534 load_flags |= FT_LOAD_NO_SCALE;
537 /* always render glyphs to bitmaps */
538 load_flags |= FT_LOAD_RENDER;
540 if ( type & ftc_image_flag_unhinted )
541 load_flags |= FT_LOAD_NO_HINTING;
543 if ( type & ftc_image_flag_autohinted )
544 load_flags |= FT_LOAD_FORCE_AUTOHINT;
546 type0.flags = load_flags;
549 return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,