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