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