[FREETYPE]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / cache / ftcbasic.c
1 /***************************************************************************/
2 /* */
3 /* ftcbasic.c */
4 /* */
5 /* The FreeType basic cache interface (body). */
6 /* */
7 /* Copyright 2003-2007, 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_INTERNAL_OBJECTS_H
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_CACHE_H
23 #include "ftcglyph.h"
24 #include "ftcimage.h"
25 #include "ftcsbits.h"
26
27 #include "ftccback.h"
28 #include "ftcerror.h"
29
30 #define FT_COMPONENT trace_cache
31
32
33 /*
34 * Basic Families
35 *
36 */
37 typedef struct FTC_BasicAttrRec_
38 {
39 FTC_ScalerRec scaler;
40 FT_UInt load_flags;
41
42 } FTC_BasicAttrRec, *FTC_BasicAttrs;
43
44 #define FTC_BASIC_ATTR_COMPARE( a, b ) \
45 FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
46 (a)->load_flags == (b)->load_flags )
47
48 #define FTC_BASIC_ATTR_HASH( a ) \
49 ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
50
51
52 typedef struct FTC_BasicQueryRec_
53 {
54 FTC_GQueryRec gquery;
55 FTC_BasicAttrRec attrs;
56
57 } FTC_BasicQueryRec, *FTC_BasicQuery;
58
59
60 typedef struct FTC_BasicFamilyRec_
61 {
62 FTC_FamilyRec family;
63 FTC_BasicAttrRec attrs;
64
65 } FTC_BasicFamilyRec, *FTC_BasicFamily;
66
67
68 FT_CALLBACK_DEF( FT_Bool )
69 ftc_basic_family_compare( FTC_MruNode ftcfamily,
70 FT_Pointer ftcquery )
71 {
72 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
73 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
74
75
76 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
77 }
78
79
80 FT_CALLBACK_DEF( FT_Error )
81 ftc_basic_family_init( FTC_MruNode ftcfamily,
82 FT_Pointer ftcquery,
83 FT_Pointer ftccache )
84 {
85 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
86 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
87 FTC_Cache cache = (FTC_Cache)ftccache;
88
89
90 FTC_Family_Init( FTC_FAMILY( family ), cache );
91 family->attrs = query->attrs;
92 return 0;
93 }
94
95
96 FT_CALLBACK_DEF( FT_UInt )
97 ftc_basic_family_get_count( FTC_Family ftcfamily,
98 FTC_Manager manager )
99 {
100 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
101 FT_Error error;
102 FT_Face face;
103 FT_UInt result = 0;
104
105
106 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
107 &face );
108
109 if ( error || !face )
110 return result;
111
112 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
113 {
114 FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
115 FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
116 }
117
118 if ( !error )
119 result = (FT_UInt)face->num_glyphs;
120
121 return result;
122 }
123
124
125 FT_CALLBACK_DEF( FT_Error )
126 ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
127 FT_UInt gindex,
128 FTC_Manager manager,
129 FT_Face *aface )
130 {
131 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
132 FT_Error error;
133 FT_Size size;
134
135
136 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
137 if ( !error )
138 {
139 FT_Face face = size->face;
140
141
142 error = FT_Load_Glyph( face, gindex,
143 family->attrs.load_flags | FT_LOAD_RENDER );
144 if ( !error )
145 *aface = face;
146 }
147
148 return error;
149 }
150
151
152 FT_CALLBACK_DEF( FT_Error )
153 ftc_basic_family_load_glyph( FTC_Family ftcfamily,
154 FT_UInt gindex,
155 FTC_Cache cache,
156 FT_Glyph *aglyph )
157 {
158 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
159 FT_Error error;
160 FTC_Scaler scaler = &family->attrs.scaler;
161 FT_Face face;
162 FT_Size size;
163
164
165 /* we will now load the glyph image */
166 error = FTC_Manager_LookupSize( cache->manager,
167 scaler,
168 &size );
169 if ( !error )
170 {
171 face = size->face;
172
173 error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
174 if ( !error )
175 {
176 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
177 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
178 {
179 /* ok, copy it */
180 FT_Glyph glyph;
181
182
183 error = FT_Get_Glyph( face->glyph, &glyph );
184 if ( !error )
185 {
186 *aglyph = glyph;
187 goto Exit;
188 }
189 }
190 else
191 error = FT_THROW( Invalid_Argument );
192 }
193 }
194
195 Exit:
196 return error;
197 }
198
199
200 FT_CALLBACK_DEF( FT_Bool )
201 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
202 FT_Pointer ftcface_id,
203 FTC_Cache cache,
204 FT_Bool* list_changed )
205 {
206 FTC_GNode gnode = (FTC_GNode)ftcgnode;
207 FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
208 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
209 FT_Bool result;
210
211
212 if ( list_changed )
213 *list_changed = FALSE;
214 result = FT_BOOL( family->attrs.scaler.face_id == face_id );
215 if ( result )
216 {
217 /* we must call this function to avoid this node from appearing
218 * in later lookups with the same face_id!
219 */
220 FTC_GNode_UnselectFamily( gnode, cache );
221 }
222 return result;
223 }
224
225
226 /*
227 *
228 * basic image cache
229 *
230 */
231
232 FT_CALLBACK_TABLE_DEF
233 const FTC_IFamilyClassRec ftc_basic_image_family_class =
234 {
235 {
236 sizeof ( FTC_BasicFamilyRec ),
237 ftc_basic_family_compare,
238 ftc_basic_family_init,
239 0, /* FTC_MruNode_ResetFunc */
240 0 /* FTC_MruNode_DoneFunc */
241 },
242 ftc_basic_family_load_glyph
243 };
244
245
246 FT_CALLBACK_TABLE_DEF
247 const FTC_GCacheClassRec ftc_basic_image_cache_class =
248 {
249 {
250 ftc_inode_new,
251 ftc_inode_weight,
252 ftc_gnode_compare,
253 ftc_basic_gnode_compare_faceid,
254 ftc_inode_free,
255
256 sizeof ( FTC_GCacheRec ),
257 ftc_gcache_init,
258 ftc_gcache_done
259 },
260 (FTC_MruListClass)&ftc_basic_image_family_class
261 };
262
263
264 /* documentation is in ftcache.h */
265
266 FT_EXPORT_DEF( FT_Error )
267 FTC_ImageCache_New( FTC_Manager manager,
268 FTC_ImageCache *acache )
269 {
270 return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
271 (FTC_GCache*)acache );
272 }
273
274
275 /* documentation is in ftcache.h */
276
277 FT_EXPORT_DEF( FT_Error )
278 FTC_ImageCache_Lookup( FTC_ImageCache cache,
279 FTC_ImageType type,
280 FT_UInt gindex,
281 FT_Glyph *aglyph,
282 FTC_Node *anode )
283 {
284 FTC_BasicQueryRec query;
285 FTC_Node node = 0; /* make compiler happy */
286 FT_Error error;
287 FT_PtrDist hash;
288
289
290 /* some argument checks are delayed to FTC_Cache_Lookup */
291 if ( !aglyph )
292 {
293 error = FT_THROW( Invalid_Argument );
294 goto Exit;
295 }
296
297 *aglyph = NULL;
298 if ( anode )
299 *anode = NULL;
300
301 {
302 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
303 {
304 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
305 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
306 }
307
308 query.attrs.scaler.face_id = type->face_id;
309 query.attrs.scaler.width = type->width;
310 query.attrs.scaler.height = type->height;
311 query.attrs.load_flags = (FT_UInt)type->flags;
312 }
313
314 query.attrs.scaler.pixel = 1;
315 query.attrs.scaler.x_res = 0; /* make compilers happy */
316 query.attrs.scaler.y_res = 0;
317
318 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
319
320 #if 1 /* inlining is about 50% faster! */
321 FTC_GCACHE_LOOKUP_CMP( cache,
322 ftc_basic_family_compare,
323 FTC_GNode_Compare,
324 hash, gindex,
325 &query,
326 node,
327 error );
328 #else
329 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
330 hash, gindex,
331 FTC_GQUERY( &query ),
332 &node );
333 #endif
334 if ( !error )
335 {
336 *aglyph = FTC_INODE( node )->glyph;
337
338 if ( anode )
339 {
340 *anode = node;
341 node->ref_count++;
342 }
343 }
344
345 Exit:
346 return error;
347 }
348
349
350 /* documentation is in ftcache.h */
351
352 FT_EXPORT_DEF( FT_Error )
353 FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
354 FTC_Scaler scaler,
355 FT_ULong load_flags,
356 FT_UInt gindex,
357 FT_Glyph *aglyph,
358 FTC_Node *anode )
359 {
360 FTC_BasicQueryRec query;
361 FTC_Node node = 0; /* make compiler happy */
362 FT_Error error;
363 FT_PtrDist hash;
364
365
366 /* some argument checks are delayed to FTC_Cache_Lookup */
367 if ( !aglyph || !scaler )
368 {
369 error = FT_THROW( Invalid_Argument );
370 goto Exit;
371 }
372
373 *aglyph = NULL;
374 if ( anode )
375 *anode = NULL;
376
377 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
378 if ( load_flags > FT_UINT_MAX )
379 {
380 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
381 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
382 }
383
384 query.attrs.scaler = scaler[0];
385 query.attrs.load_flags = (FT_UInt)load_flags;
386
387 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
388
389 FTC_GCACHE_LOOKUP_CMP( cache,
390 ftc_basic_family_compare,
391 FTC_GNode_Compare,
392 hash, gindex,
393 &query,
394 node,
395 error );
396 if ( !error )
397 {
398 *aglyph = FTC_INODE( node )->glyph;
399
400 if ( anode )
401 {
402 *anode = node;
403 node->ref_count++;
404 }
405 }
406
407 Exit:
408 return error;
409 }
410
411
412 /*
413 *
414 * basic small bitmap cache
415 *
416 */
417
418 FT_CALLBACK_TABLE_DEF
419 const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
420 {
421 {
422 sizeof ( FTC_BasicFamilyRec ),
423 ftc_basic_family_compare,
424 ftc_basic_family_init,
425 0, /* FTC_MruNode_ResetFunc */
426 0 /* FTC_MruNode_DoneFunc */
427 },
428 ftc_basic_family_get_count,
429 ftc_basic_family_load_bitmap
430 };
431
432
433 FT_CALLBACK_TABLE_DEF
434 const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
435 {
436 {
437 ftc_snode_new,
438 ftc_snode_weight,
439 ftc_snode_compare,
440 ftc_basic_gnode_compare_faceid,
441 ftc_snode_free,
442
443 sizeof ( FTC_GCacheRec ),
444 ftc_gcache_init,
445 ftc_gcache_done
446 },
447 (FTC_MruListClass)&ftc_basic_sbit_family_class
448 };
449
450
451 /* documentation is in ftcache.h */
452
453 FT_EXPORT_DEF( FT_Error )
454 FTC_SBitCache_New( FTC_Manager manager,
455 FTC_SBitCache *acache )
456 {
457 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
458 (FTC_GCache*)acache );
459 }
460
461
462 /* documentation is in ftcache.h */
463
464 FT_EXPORT_DEF( FT_Error )
465 FTC_SBitCache_Lookup( FTC_SBitCache cache,
466 FTC_ImageType type,
467 FT_UInt gindex,
468 FTC_SBit *ansbit,
469 FTC_Node *anode )
470 {
471 FT_Error error;
472 FTC_BasicQueryRec query;
473 FTC_Node node = 0; /* make compiler happy */
474 FT_PtrDist hash;
475
476
477 if ( anode )
478 *anode = NULL;
479
480 /* other argument checks delayed to FTC_Cache_Lookup */
481 if ( !ansbit )
482 return FT_THROW( Invalid_Argument );
483
484 *ansbit = NULL;
485
486 {
487 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
488 {
489 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
490 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
491 }
492
493 query.attrs.scaler.face_id = type->face_id;
494 query.attrs.scaler.width = type->width;
495 query.attrs.scaler.height = type->height;
496 query.attrs.load_flags = (FT_UInt)type->flags;
497 }
498
499 query.attrs.scaler.pixel = 1;
500 query.attrs.scaler.x_res = 0; /* make compilers happy */
501 query.attrs.scaler.y_res = 0;
502
503 /* beware, the hash must be the same for all glyph ranges! */
504 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
505 gindex / FTC_SBIT_ITEMS_PER_NODE;
506
507 #if 1 /* inlining is about 50% faster! */
508 FTC_GCACHE_LOOKUP_CMP( cache,
509 ftc_basic_family_compare,
510 FTC_SNode_Compare,
511 hash, gindex,
512 &query,
513 node,
514 error );
515 #else
516 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
517 hash,
518 gindex,
519 FTC_GQUERY( &query ),
520 &node );
521 #endif
522 if ( error )
523 goto Exit;
524
525 *ansbit = FTC_SNODE( node )->sbits +
526 ( gindex - FTC_GNODE( node )->gindex );
527
528 if ( anode )
529 {
530 *anode = node;
531 node->ref_count++;
532 }
533
534 Exit:
535 return error;
536 }
537
538
539 /* documentation is in ftcache.h */
540
541 FT_EXPORT_DEF( FT_Error )
542 FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
543 FTC_Scaler scaler,
544 FT_ULong load_flags,
545 FT_UInt gindex,
546 FTC_SBit *ansbit,
547 FTC_Node *anode )
548 {
549 FT_Error error;
550 FTC_BasicQueryRec query;
551 FTC_Node node = 0; /* make compiler happy */
552 FT_PtrDist hash;
553
554
555 if ( anode )
556 *anode = NULL;
557
558 /* other argument checks delayed to FTC_Cache_Lookup */
559 if ( !ansbit || !scaler )
560 return FT_THROW( Invalid_Argument );
561
562 *ansbit = NULL;
563
564 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
565 if ( load_flags > FT_UINT_MAX )
566 {
567 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
568 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
569 }
570
571 query.attrs.scaler = scaler[0];
572 query.attrs.load_flags = (FT_UInt)load_flags;
573
574 /* beware, the hash must be the same for all glyph ranges! */
575 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
576 gindex / FTC_SBIT_ITEMS_PER_NODE;
577
578 FTC_GCACHE_LOOKUP_CMP( cache,
579 ftc_basic_family_compare,
580 FTC_SNode_Compare,
581 hash, gindex,
582 &query,
583 node,
584 error );
585 if ( error )
586 goto Exit;
587
588 *ansbit = FTC_SNODE( node )->sbits +
589 ( gindex - FTC_GNODE( node )->gindex );
590
591 if ( anode )
592 {
593 *anode = node;
594 node->ref_count++;
595 }
596
597 Exit:
598 return error;
599 }
600
601
602 /* END */