Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ftcsbits.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftcsbits.c */
4 /* */
5 /* FreeType sbits manager (body). */
6 /* */
7 /* Copyright 2000-2006, 2009-2011, 2013 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 "ftcsbits.h"
22 #include FT_INTERNAL_OBJECTS_H
23 #include FT_INTERNAL_DEBUG_H
24 #include FT_ERRORS_H
25 
26 #include "ftccback.h"
27 #include "ftcerror.h"
28 
29 #undef FT_COMPONENT
30 #define FT_COMPONENT trace_cache
31 
32 
33  /*************************************************************************/
34  /*************************************************************************/
35  /***** *****/
36  /***** SBIT CACHE NODES *****/
37  /***** *****/
38  /*************************************************************************/
39  /*************************************************************************/
40 
41 
42  static FT_Error
43  ftc_sbit_copy_bitmap( FTC_SBit sbit,
44  FT_Bitmap* bitmap,
45  FT_Memory memory )
46  {
48  FT_Int pitch = bitmap->pitch;
49  FT_ULong size;
50 
51 
52  if ( pitch < 0 )
53  pitch = -pitch;
54 
55  size = (FT_ULong)( pitch * bitmap->rows );
56 
57  if ( !FT_ALLOC( sbit->buffer, size ) )
58  FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
59 
60  return error;
61  }
62 
63 
64  FT_LOCAL_DEF( void )
66  FTC_Cache cache )
67  {
68  FTC_SNode snode = (FTC_SNode)ftcsnode;
69  FTC_SBit sbit = snode->sbits;
70  FT_UInt count = snode->count;
71  FT_Memory memory = cache->memory;
72 
73 
74  for ( ; count > 0; sbit++, count-- )
75  FT_FREE( sbit->buffer );
76 
77  FTC_GNode_Done( FTC_GNODE( snode ), cache );
78 
79  FT_FREE( snode );
80  }
81 
82 
83  FT_LOCAL_DEF( void )
85  FTC_Cache cache )
86  {
87  ftc_snode_free( FTC_NODE( snode ), cache );
88  }
89 
90 
91  /*
92  * This function tries to load a small bitmap within a given FTC_SNode.
93  * Note that it returns a non-zero error code _only_ in the case of
94  * out-of-memory condition. For all other errors (e.g., corresponding
95  * to a bad font file), this function will mark the sbit as `unavailable'
96  * and return a value of 0.
97  *
98  * You should also read the comment within the @ftc_snode_compare
99  * function below to see how out-of-memory is handled during a lookup.
100  */
101  static FT_Error
102  ftc_snode_load( FTC_SNode snode,
103  FTC_Manager manager,
104  FT_UInt gindex,
105  FT_ULong *asize )
106  {
107  FT_Error error;
108  FTC_GNode gnode = FTC_GNODE( snode );
109  FTC_Family family = gnode->family;
110  FT_Memory memory = manager->memory;
111  FT_Face face;
112  FTC_SBit sbit;
113  FTC_SFamilyClass clazz;
114 
115 
116  if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
117  {
118  FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
119  return FT_THROW( Invalid_Argument );
120  }
121 
122  sbit = snode->sbits + ( gindex - gnode->gindex );
123  clazz = (FTC_SFamilyClass)family->clazz;
124 
125  sbit->buffer = 0;
126 
127  error = clazz->family_load_glyph( family, gindex, manager, &face );
128  if ( error )
129  goto BadGlyph;
130 
131  {
132  FT_Int temp;
133  FT_GlyphSlot slot = face->glyph;
134  FT_Bitmap* bitmap = &slot->bitmap;
135  FT_Pos xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */
136 
137 
138  if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
139  {
140  FT_TRACE0(( "ftc_snode_load:"
141  " glyph loaded didn't return a bitmap\n" ));
142  goto BadGlyph;
143  }
144 
145  /* Check that our values fit into 8-bit containers! */
146  /* If this is not the case, our bitmap is too large */
147  /* and we will leave it as `missing' with sbit.buffer = 0 */
148 
149 #define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
150 #define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
151 
152  /* horizontal advance in pixels */
153  xadvance = ( slot->advance.x + 32 ) >> 6;
154  yadvance = ( slot->advance.y + 32 ) >> 6;
155 
156  if ( !CHECK_BYTE( bitmap->rows ) ||
157  !CHECK_BYTE( bitmap->width ) ||
158  !CHECK_CHAR( bitmap->pitch ) ||
159  !CHECK_CHAR( slot->bitmap_left ) ||
160  !CHECK_CHAR( slot->bitmap_top ) ||
161  !CHECK_CHAR( xadvance ) ||
162  !CHECK_CHAR( yadvance ) )
163  {
164  FT_TRACE2(( "ftc_snode_load:"
165  " glyph too large for small bitmap cache\n"));
166  goto BadGlyph;
167  }
168 
169  sbit->width = (FT_Byte)bitmap->width;
170  sbit->height = (FT_Byte)bitmap->rows;
171  sbit->pitch = (FT_Char)bitmap->pitch;
172  sbit->left = (FT_Char)slot->bitmap_left;
173  sbit->top = (FT_Char)slot->bitmap_top;
174  sbit->xadvance = (FT_Char)xadvance;
175  sbit->yadvance = (FT_Char)yadvance;
176  sbit->format = (FT_Byte)bitmap->pixel_mode;
177  sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
178 
179  /* copy the bitmap into a new buffer -- ignore error */
180  error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
181 
182  /* now, compute size */
183  if ( asize )
184  *asize = FT_ABS( sbit->pitch ) * sbit->height;
185 
186  } /* glyph loading successful */
187 
188  /* ignore the errors that might have occurred -- */
189  /* we mark unloaded glyphs with `sbit.buffer == 0' */
190  /* and `width == 255', `height == 0' */
191  /* */
192  if ( error && FT_ERR_NEQ( error, Out_Of_Memory ) )
193  {
194  BadGlyph:
195  sbit->width = 255;
196  sbit->height = 0;
197  sbit->buffer = NULL;
198  error = FT_Err_Ok;
199  if ( asize )
200  *asize = 0;
201  }
202 
203  return error;
204  }
205 
206 
209  FTC_GQuery gquery,
210  FTC_Cache cache )
211  {
212  FT_Memory memory = cache->memory;
213  FT_Error error;
214  FTC_SNode snode = NULL;
215  FT_UInt gindex = gquery->gindex;
216  FTC_Family family = gquery->family;
217 
219  FT_UInt total;
220  FT_UInt node_count;
221 
222 
223  total = clazz->family_get_count( family, cache->manager );
224  if ( total == 0 || gindex >= total )
225  {
226  error = FT_THROW( Invalid_Argument );
227  goto Exit;
228  }
229 
230  if ( !FT_NEW( snode ) )
231  {
233 
234 
235  start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
236  count = total - start;
237  if ( count > FTC_SBIT_ITEMS_PER_NODE )
238  count = FTC_SBIT_ITEMS_PER_NODE;
239 
240  FTC_GNode_Init( FTC_GNODE( snode ), start, family );
241 
242  snode->count = count;
243  for ( node_count = 0; node_count < count; node_count++ )
244  {
245  snode->sbits[node_count].width = 255;
246  }
247 
248  error = ftc_snode_load( snode,
249  cache->manager,
250  gindex,
251  NULL );
252  if ( error )
253  {
254  FTC_SNode_Free( snode, cache );
255  snode = NULL;
256  }
257  }
258 
259  Exit:
260  *psnode = snode;
261  return error;
262  }
263 
264 
266  ftc_snode_new( FTC_Node *ftcpsnode,
267  FT_Pointer ftcgquery,
268  FTC_Cache cache )
269  {
270  FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;
271  FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
272 
273 
274  return FTC_SNode_New( psnode, gquery, cache );
275  }
276 
277 
280  FTC_Cache cache )
281  {
282  FTC_SNode snode = (FTC_SNode)ftcsnode;
283  FT_UInt count = snode->count;
284  FTC_SBit sbit = snode->sbits;
285  FT_Int pitch;
286  FT_Offset size;
287 
288  FT_UNUSED( cache );
289 
290 
292 
293  /* the node itself */
294  size = sizeof ( *snode );
295 
296  for ( ; count > 0; count--, sbit++ )
297  {
298  if ( sbit->buffer )
299  {
300  pitch = sbit->pitch;
301  if ( pitch < 0 )
302  pitch = -pitch;
303 
304  /* add the size of a given glyph image */
305  size += pitch * sbit->height;
306  }
307  }
308 
309  return size;
310  }
311 
312 
313 #if 0
314 
316  FTC_SNode_Weight( FTC_SNode snode )
317  {
318  return ftc_snode_weight( FTC_NODE( snode ), NULL );
319  }
320 
321 #endif /* 0 */
322 
323 
326  FT_Pointer ftcgquery,
327  FTC_Cache cache,
328  FT_Bool* list_changed )
329  {
330  FTC_SNode snode = (FTC_SNode)ftcsnode;
331  FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
332  FTC_GNode gnode = FTC_GNODE( snode );
333  FT_UInt gindex = gquery->gindex;
334  FT_Bool result;
335 
336 
337  if (list_changed)
338  *list_changed = FALSE;
339  result = FT_BOOL( gnode->family == gquery->family &&
340  (FT_UInt)( gindex - gnode->gindex ) < snode->count );
341  if ( result )
342  {
343  /* check if we need to load the glyph bitmap now */
344  FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
345 
346 
347  /*
348  * The following code illustrates what to do when you want to
349  * perform operations that may fail within a lookup function.
350  *
351  * Here, we want to load a small bitmap on-demand; we thus
352  * need to call the `ftc_snode_load' function which may return
353  * a non-zero error code only when we are out of memory (OOM).
354  *
355  * The correct thing to do is to use @FTC_CACHE_TRYLOOP and
356  * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
357  * that is capable of flushing the cache incrementally when
358  * an OOM errors occur.
359  *
360  * However, we need to `lock' the node before this operation to
361  * prevent it from being flushed within the loop.
362  *
363  * When we exit the loop, we unlock the node, then check the `error'
364  * variable. If it is non-zero, this means that the cache was
365  * completely flushed and that no usable memory was found to load
366  * the bitmap.
367  *
368  * We then prefer to return a value of 0 (i.e., NO MATCH). This
369  * ensures that the caller will try to allocate a new node.
370  * This operation consequently _fail_ and the lookup function
371  * returns the appropriate OOM error code.
372  *
373  * Note that `buffer == NULL && width == 255' is a hack used to
374  * tag `unavailable' bitmaps in the array. We should never try
375  * to load these.
376  *
377  */
378 
379  if ( sbit->buffer == NULL && sbit->width == 255 )
380  {
381  FT_ULong size;
382  FT_Error error;
383 
384 
385  ftcsnode->ref_count++; /* lock node to prevent flushing */
386  /* in retry loop */
387 
388  FTC_CACHE_TRYLOOP( cache )
389  {
390  error = ftc_snode_load( snode, cache->manager, gindex, &size );
391  }
392  FTC_CACHE_TRYLOOP_END( list_changed );
393 
394  ftcsnode->ref_count--; /* unlock the node */
395 
396  if ( error )
397  result = 0;
398  else
399  cache->manager->cur_weight += size;
400  }
401  }
402 
403  return result;
404  }
405 
406 
407 #ifdef FTC_INLINE
408 
411  FTC_GQuery gquery,
412  FTC_Cache cache,
413  FT_Bool* list_changed )
414  {
415  return ftc_snode_compare( FTC_NODE( snode ), gquery,
416  cache, list_changed );
417  }
418 
419 #endif
420 
421 /* END */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
FT_Byte width
Definition: ftcache.h:911
int FT_Error
Definition: fttypes.h:296
#define CHECK_CHAR(d)
#define FTC_CACHE_TRYLOOP_END(list_changed)
Definition: ftccache.h:329
unsigned long FT_ULong
Definition: fttypes.h:249
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:59
FT_Char top
Definition: ftcache.h:914
#define FTC_SBIT_ITEMS_PER_NODE
Definition: ftcsbits.h:30
#define NULL
Definition: ftobjs.h:61
signed int FT_Int
Definition: fttypes.h:216
int rows
Definition: ftimage.h:312
#define FT_ABS(a)
Definition: ftobjs.h:73
FTC_SNode_New(FTC_SNode *psnode, FTC_GQuery gquery, FTC_Cache cache)
Definition: ftcsbits.c:208
FT_Short pitch
Definition: ftcache.h:918
return FT_THROW(Missing_Property)
FT_Byte max_grays
Definition: ftcache.h:917
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
FTC_SFamily_GetCountFunc family_get_count
Definition: ftcsbits.h:58
unsigned char * buffer
Definition: ftimage.h:315
signed char FT_Char
Definition: fttypes.h:139
GLuint start
FT_Int bitmap_top
Definition: freetype.h:1629
FT_Char left
Definition: ftcache.h:913
int pitch
Definition: ftimage.h:314
FT_Vector advance
Definition: freetype.h:1623
return FT_Err_Ok
Definition: ftbbox.c:645
#define FTC_NODE(x)
Definition: ftccache.h:69
#define FTC_CACHE_TRYLOOP(cache)
Definition: ftccache.h:318
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
GLenum GLuint GLint GLenum face
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
FT_Memory memory
Definition: ftcmanag.h:94
unsigned char FT_Byte
Definition: fttypes.h:150
#define FT_ASSERT(condition)
Definition: ftdebug.h:211
FT_Char xadvance
Definition: ftcache.h:919
FTC_GNode_Init(FTC_GNode gnode, FT_UInt gindex, FTC_Family family)
Definition: ftcglyph.c:31
FT_Bitmap bitmap
Definition: freetype.h:1627
#define FT_FREE(ptr)
Definition: ftmemory.h:286
FTC_Family family
Definition: ftcglyph.h:163
FT_Error error
Definition: cffdrivr.c:411
FTC_SFamily_LoadGlyphFunc family_load_glyph
Definition: ftcsbits.h:59
FT_Pos x
Definition: ftimage.h:77
void * FT_Pointer
Definition: fttypes.h:307
ftc_snode_free(FTC_Node ftcsnode, FTC_Cache cache)
Definition: ftcsbits.c:65
FT_Pos y
Definition: ftimage.h:78
FT_Char yadvance
Definition: ftcache.h:920
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
short num_grays
Definition: ftimage.h:316
FT_UInt gindex
Definition: ftcglyph.h:162
#define FTC_GNODE(x)
Definition: ftcglyph.h:156
FT_Byte * buffer
Definition: ftcache.h:922
#define FT_ERR_NEQ(x, e)
Definition: fttypes.h:589
#define FALSE
Definition: ftobjs.h:57
#define CHECK_BYTE(d)
const FTC_SFamilyClassRec * FTC_SFamilyClass
Definition: ftcsbits.h:63
ftc_snode_weight(FTC_Node ftcsnode, FTC_Cache cache)
Definition: ftcsbits.c:279
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FTC_Family family
Definition: ftcglyph.h:151
int width
Definition: ftimage.h:313
#define FT_BOOL(x)
Definition: fttypes.h:574
FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE]
Definition: ftcsbits.h:36
FT_BEGIN_HEADER struct FTC_FamilyRec_ * FTC_Family
FTC_GNode_Done(FTC_GNode gnode, FTC_Cache cache)
Definition: ftcglyph.c:55
FTC_MruListClassRec clazz
Definition: ftcsbits.h:57
FTC_SNode_Compare(FTC_SNode snode, FTC_GQuery gquery, FTC_Cache cache, FT_Bool *list_changed)
Definition: ftcsbits.c:410
FT_Int bitmap_left
Definition: freetype.h:1628
FT_Glyph_Format format
Definition: freetype.h:1625
FT_UInt count
Definition: ftcsbits.h:35
GLuint64EXT * result
FT_GlyphSlot glyph
Definition: freetype.h:956
unsigned int FT_UInt
Definition: fttypes.h:227
FTC_SNode_Free(FTC_SNode snode, FTC_Cache cache)
Definition: ftcsbits.c:84
char pixel_mode
Definition: ftimage.h:317
FT_Byte height
Definition: ftcache.h:912
struct FTC_GQueryRec_ * FTC_GQuery
GLuint GLuint GLsizei count
FT_UInt gindex
Definition: ftcglyph.h:152
struct FTC_SNodeRec_ * FTC_SNode
#define FT_NEW(ptr)
Definition: ftmemory.h:288
FT_TRACE0(("cff_property_set: missing property `%s'\, property_name))
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:203
ftc_snode_compare(FTC_Node ftcsnode, FT_Pointer ftcgquery, FTC_Cache cache, FT_Bool *list_changed)
Definition: ftcsbits.c:325
GLsizeiptr size
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
FT_Byte format
Definition: ftcache.h:916
size_t FT_Offset
Definition: fttypes.h:320
#define FTC_CACHE__SFAMILY_CLASS(x)
Definition: ftcsbits.h:67
ftc_snode_new(FTC_Node *ftcpsnode, FT_Pointer ftcgquery, FTC_Cache cache)
Definition: ftcsbits.c:266