The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / ftcsbits.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftcsbits.c                                                             */
4 /*                                                                         */
5 /*    FreeType sbits manager (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_SMALL_BITMAPS_H
22 #include FT_INTERNAL_OBJECTS_H
23 #include FT_INTERNAL_DEBUG_H
24 #include FT_ERRORS_H
25
26 #include "ftcerror.h"
27
28 #include <string.h>         /* memcmp() */
29
30
31 #define FTC_SBITSET_ELEMENT_COUNT  16
32
33
34   typedef struct  FTC_SBitSetRec_
35   {
36     FTC_ChunkSetRec  root;
37     FTC_Image_Desc   desc;
38
39   } FTC_SBitSetRec, *FTC_SBitSet;
40
41
42   typedef struct  FTC_SBit_CacheRec_
43   {
44     FTC_Chunk_CacheRec  root;
45
46   } FTC_SBit_CacheRec;
47
48
49
50   /*************************************************************************/
51   /*************************************************************************/
52   /*****                                                               *****/
53   /*****                     SBIT CACHE NODES                          *****/
54   /*****                                                               *****/
55   /*************************************************************************/
56   /*************************************************************************/
57
58
59   FT_CALLBACK_DEF( void )
60   ftc_sbit_chunk_node_destroy( FTC_ChunkNode  node )
61   {
62     FTC_ChunkSet  cset   = node->cset;
63     FT_Memory     memory = cset->memory;
64     FT_UInt       count  = node->num_elements;
65     FTC_SBit      sbit   = (FTC_SBit)node->elements;
66
67
68     for ( ; count > 0; sbit++, count-- )
69       FREE( sbit->buffer );
70
71     FREE( node->elements );
72     FREE( node );
73   }
74
75
76   FT_CALLBACK_DEF( FT_Error )
77   ftc_bitmap_copy( FT_Memory   memory,
78                    FT_Bitmap*  source,
79                    FTC_SBit    target )
80   {
81     FT_Error  error;
82     FT_Int    pitch = source->pitch;
83     FT_ULong  size;
84
85
86     if ( pitch < 0 )
87       pitch = -pitch;
88
89     size = (FT_ULong)( pitch * source->rows );
90
91     if ( !ALLOC( target->buffer, size ) )
92       MEM_Copy( target->buffer, source->buffer, size );
93
94     return error;
95   }
96
97
98   FT_CALLBACK_DEF( FT_Error )
99   ftc_sbit_chunk_node_new( FTC_ChunkSet    cset,
100                            FT_UInt         index,
101                            FTC_ChunkNode  *anode )
102   {
103     FT_Error       error;
104     FT_Memory      memory  = cset->memory;
105     FTC_SBitSet    sbitset = (FTC_SBitSet)cset;
106     FTC_ChunkNode  node    = 0;
107     FT_Face        face;
108     FT_Size        size;
109
110
111     /* allocate node */
112     if ( ALLOC( node, sizeof ( *node ) ) )
113       goto Exit;
114
115     /* initialize its inner fields */
116     error = FTC_ChunkNode_Init( node, cset, index, 1 );
117     if ( error )
118       goto Exit;
119
120     /* we will now load all glyph images for this chunk */
121     error = FTC_Manager_Lookup_Size( cset->manager,
122                                      &sbitset->desc.font,
123                                      &face, &size );
124     if ( !error )
125     {
126       FT_UInt   glyph_index = index * cset->element_count;
127       FT_UInt   load_flags  = FT_LOAD_DEFAULT;
128       FT_UInt   image_type  = sbitset->desc.image_type;
129       FT_UInt   count       = node->num_elements;
130       FTC_SBit  sbit        = (FTC_SBit)node->elements;
131
132
133       /* determine load flags, depending on the font description's */
134       /* image type                                                */
135
136       if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
137       {
138         if ( image_type & ftc_image_flag_monochrome )
139           load_flags |= FT_LOAD_MONOCHROME;
140
141         /* disable embedded bitmaps loading if necessary */
142         if ( image_type & ftc_image_flag_no_sbits )
143           load_flags |= FT_LOAD_NO_BITMAP;
144       }
145       else
146       {
147         FT_ERROR(( "FTC_SBit_Cache: cannot load scalable glyphs in an"
148                    " sbit cache, please check your arguments!\n" ));
149         error = FTC_Err_Invalid_Argument;
150         goto Exit;
151       }
152
153       /* always render glyphs to bitmaps */
154       load_flags |= FT_LOAD_RENDER;
155
156       if ( image_type & ftc_image_flag_unhinted )
157         load_flags |= FT_LOAD_NO_HINTING;
158
159       if ( image_type & ftc_image_flag_autohinted )
160         load_flags |= FT_LOAD_FORCE_AUTOHINT;
161
162       /* load a chunk of small bitmaps in a row */
163       for ( ; count > 0; count--, glyph_index++, sbit++ )
164       {
165         /* by default, indicates a `missing' glyph */
166         sbit->buffer = 0;
167
168         error = FT_Load_Glyph( face, glyph_index, load_flags );
169         if ( !error )
170         {
171           FT_Int        temp;
172           FT_GlyphSlot  slot   = face->glyph;
173           FT_Bitmap*    bitmap = &slot->bitmap;
174           FT_Int        xadvance, yadvance;
175
176
177           /* check that our values fit into 8-bit containers!       */
178           /* If this is not the case, our bitmap is too large       */
179           /* and we will leave it as `missing' with sbit.buffer = 0 */
180
181 #define CHECK_CHAR( d )  ( temp = (FT_Char)d, temp == d )
182 #define CHECK_BYTE( d )  ( temp = (FT_Byte)d, temp == d )
183
184           /* XXX: FIXME: add support for vertical layouts maybe */
185
186           /* horizontal advance in pixels */
187           xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
188           yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
189
190           if ( CHECK_BYTE( bitmap->rows  )     &&
191                CHECK_BYTE( bitmap->width )     &&
192                CHECK_CHAR( bitmap->pitch )     &&
193                CHECK_CHAR( slot->bitmap_left ) &&
194                CHECK_CHAR( slot->bitmap_top  ) &&
195                CHECK_CHAR( xadvance )          &&
196                CHECK_CHAR( yadvance )          )
197           {
198             sbit->width    = (FT_Byte)bitmap->width;
199             sbit->height   = (FT_Byte)bitmap->rows;
200             sbit->pitch    = (FT_Char)bitmap->pitch;
201             sbit->left     = (FT_Char)slot->bitmap_left;
202             sbit->top      = (FT_Char)slot->bitmap_top;
203             sbit->xadvance = (FT_Char)xadvance;
204             sbit->yadvance = (FT_Char)yadvance;
205             sbit->format   = (FT_Byte)bitmap->pixel_mode;
206
207             /* grab the bitmap when possible */
208             if ( slot->flags & ft_glyph_own_bitmap )
209             {
210               slot->flags &= ~ft_glyph_own_bitmap;
211               sbit->buffer = bitmap->buffer;
212             }
213             else
214             {
215               /* copy the bitmap into a new buffer -- ignore error */
216               ftc_bitmap_copy( memory, bitmap, sbit );
217             }
218           }
219         }
220       }
221
222       /* ignore the errors that might have occurred --        */
223       /* we recognize unloaded glyphs with `sbit.buffer == 0' */
224       error = 0;
225     }
226
227   Exit:
228     if ( error && node )
229     {
230       FREE( node->elements );
231       FREE( node );
232     }
233
234     *anode = node;
235
236     return error;
237   }
238
239
240   /* this function is important because it is both part of */
241   /* an FTC_ChunkSet_Class and an FTC_CacheNode_Class      */
242   /*                                                       */
243   FT_CALLBACK_DEF( FT_ULong )
244   ftc_sbit_chunk_node_size( FTC_ChunkNode  node )
245   {
246     FT_ULong      size;
247     FTC_ChunkSet  cset  = node->cset;
248     FT_UInt       count = node->num_elements;
249     FT_Int        pitch;
250     FTC_SBit      sbit  = (FTC_SBit)node->elements;
251
252
253     /* the node itself */
254     size  = sizeof ( *node );
255
256     /* the sbit records */
257     size += cset->element_count * sizeof ( FTC_SBitRec );
258
259     for ( ; count > 0; count--, sbit++ )
260     {
261       if ( sbit->buffer )
262       {
263         pitch = sbit->pitch;
264         if ( pitch < 0 )
265           pitch = -pitch;
266
267         /* add the size of a given glyph image */
268         size += pitch * sbit->height;
269       }
270     }
271
272     return size;
273   }
274
275
276   /*************************************************************************/
277   /*************************************************************************/
278   /*****                                                               *****/
279   /*****                     SBIT CHUNK SETS                           *****/
280   /*****                                                               *****/
281   /*************************************************************************/
282   /*************************************************************************/
283
284
285   FT_CALLBACK_DEF( FT_Error )
286   ftc_sbit_chunk_set_sizes( FTC_ChunkSet     cset,
287                             FTC_Image_Desc*  desc )
288   {
289     FT_Error  error;
290     FT_Face   face;
291
292
293     cset->element_count = FTC_SBITSET_ELEMENT_COUNT;
294     cset->element_size  = sizeof ( FTC_SBitRec );
295
296     /* lookup the FT_Face to obtain the number of glyphs */
297     error = FTC_Manager_Lookup_Face( cset->manager,
298                                      desc->font.face_id, &face );
299     if ( !error )
300       cset->element_max = face->num_glyphs;
301
302     return error;
303   }
304
305
306   FT_CALLBACK_DEF( FT_Error )
307   ftc_sbit_chunk_set_init( FTC_SBitSet      sset,
308                            FTC_Image_Desc*  type )
309   {
310     sset->desc = *type;
311
312     return 0;
313   }
314
315
316   FT_CALLBACK_DEF( FT_Bool )
317   ftc_sbit_chunk_set_compare( FTC_SBitSet      sset,
318                               FTC_Image_Desc*  type )
319   {
320     return FT_BOOL( !memcmp( &sset->desc, type, sizeof ( *type ) ) );
321   }
322
323
324   FT_CALLBACK_TABLE_DEF
325   const FTC_ChunkSet_Class  ftc_sbit_chunk_set_class =
326   {
327     sizeof( FTC_SBitSetRec ),
328
329     (FTC_ChunkSet_InitFunc)       ftc_sbit_chunk_set_init,
330     (FTC_ChunkSet_DoneFunc)       0,
331     (FTC_ChunkSet_CompareFunc)    ftc_sbit_chunk_set_compare,
332     (FTC_ChunkSet_SizesFunc)      ftc_sbit_chunk_set_sizes,
333
334     (FTC_ChunkSet_NewNodeFunc)    ftc_sbit_chunk_node_new,
335     (FTC_ChunkSet_SizeNodeFunc)   ftc_sbit_chunk_node_size,
336     (FTC_ChunkSet_DestroyNodeFunc)ftc_sbit_chunk_node_destroy
337   };
338
339
340   /*************************************************************************/
341   /*************************************************************************/
342   /*****                                                               *****/
343   /*****                     SBITS CACHE                               *****/
344   /*****                                                               *****/
345   /*************************************************************************/
346   /*************************************************************************/
347
348
349   FT_CALLBACK_TABLE_DEF
350   const FTC_Chunk_Cache_Class  ftc_sbit_cache_class =
351   {
352     {
353       sizeof( FTC_SBit_CacheRec ),
354       (FTC_Cache_InitFunc)FTC_Chunk_Cache_Init,
355       (FTC_Cache_DoneFunc)FTC_Chunk_Cache_Done
356     },
357     (FTC_ChunkSet_Class*)&ftc_sbit_chunk_set_class
358   };
359
360
361   /* documentation is in ftcsbits.h */
362
363   FT_EXPORT_DEF( FT_Error )
364   FTC_SBit_Cache_New( FTC_Manager      manager,
365                       FTC_SBit_Cache  *acache )
366   {
367     return FTC_Manager_Register_Cache(
368              manager,
369              (FTC_Cache_Class*)&ftc_sbit_cache_class,
370              (FTC_Cache*)acache );
371   }
372
373
374   /* documentation is in ftcsbits.h */
375
376   FT_EXPORT_DEF( FT_Error )
377   FTC_SBit_Cache_Lookup( FTC_SBit_Cache   cache,
378                          FTC_Image_Desc*  desc,
379                          FT_UInt          gindex,
380                          FTC_SBit        *ansbit )
381   {
382     FT_Error       error;
383     FTC_ChunkNode  node;
384     FT_UInt        cindex;
385
386
387     /* argument checks delayed to FTC_Chunk_Cache_Lookup */
388     if ( !ansbit )
389       return FTC_Err_Invalid_Argument;
390
391     *ansbit = 0;
392     error   = FTC_Chunk_Cache_Lookup( &cache->root, desc, gindex,
393                                       &node, &cindex );
394     if ( !error )
395       *ansbit = (FTC_SBit)node->elements + cindex;
396
397     return error;
398   }
399
400
401 /* END */