1 /****************************************************************************
5 * The FreeType basic cache interface (body).
7 * Copyright (C) 2003-2023 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
19 #include <freetype/internal/ftobjs.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/ftcache.h>
30 #define FT_COMPONENT cache
37 typedef struct FTC_BasicAttrRec_
42 } FTC_BasicAttrRec, *FTC_BasicAttrs;
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 )
48 #define FTC_BASIC_ATTR_HASH( a ) \
49 ( FTC_SCALER_HASH( &(a)->scaler ) + 31 * (a)->load_flags )
52 typedef struct FTC_BasicQueryRec_
55 FTC_BasicAttrRec attrs;
57 } FTC_BasicQueryRec, *FTC_BasicQuery;
60 typedef struct FTC_BasicFamilyRec_
63 FTC_BasicAttrRec attrs;
65 } FTC_BasicFamilyRec, *FTC_BasicFamily;
68 FT_CALLBACK_DEF( FT_Bool )
69 ftc_basic_family_compare( FTC_MruNode ftcfamily,
72 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
73 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
76 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
80 FT_CALLBACK_DEF( FT_Error )
81 ftc_basic_family_init( FTC_MruNode ftcfamily,
85 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
86 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
87 FTC_Cache cache = (FTC_Cache)ftccache;
90 FTC_Family_Init( FTC_FAMILY( family ), cache );
91 family->attrs = query->attrs;
96 FT_CALLBACK_DEF( FT_UInt )
97 ftc_basic_family_get_count( FTC_Family ftcfamily,
100 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
106 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
109 if ( error || !face )
112 #ifdef FT_DEBUG_LEVEL_TRACE
113 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
115 FT_TRACE1(( "ftc_basic_family_get_count:"
116 " the number of glyphs in this face is %ld,\n",
119 " which is too much and thus truncated\n" ));
123 result = (FT_UInt)face->num_glyphs;
129 FT_CALLBACK_DEF( FT_Error )
130 ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
135 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
140 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
143 FT_Face face = size->face;
146 error = FT_Load_Glyph(
149 (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
158 FT_CALLBACK_DEF( FT_Error )
159 ftc_basic_family_load_glyph( FTC_Family ftcfamily,
164 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
166 FTC_Scaler scaler = &family->attrs.scaler;
171 /* we will now load the glyph image */
172 error = FTC_Manager_LookupSize( cache->manager,
179 error = FT_Load_Glyph( face,
181 (FT_Int)family->attrs.load_flags );
184 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
185 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ||
186 face->glyph->format == FT_GLYPH_FORMAT_SVG )
192 error = FT_Get_Glyph( face->glyph, &glyph );
200 error = FT_THROW( Invalid_Argument );
209 FT_CALLBACK_DEF( FT_Bool )
210 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
211 FT_Pointer ftcface_id,
213 FT_Bool* list_changed )
215 FTC_GNode gnode = (FTC_GNode)ftcgnode;
216 FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
217 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
222 *list_changed = FALSE;
223 result = FT_BOOL( family->attrs.scaler.face_id == face_id );
226 /* we must call this function to avoid this node from appearing
227 * in later lookups with the same face_id!
229 FTC_GNode_UnselectFamily( gnode, cache );
242 const FTC_IFamilyClassRec ftc_basic_image_family_class =
245 sizeof ( FTC_BasicFamilyRec ),
247 ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
248 ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
249 NULL, /* FTC_MruNode_ResetFunc node_reset */
250 NULL /* FTC_MruNode_DoneFunc node_done */
253 ftc_basic_family_load_glyph /* FTC_IFamily_LoadGlyphFunc family_load_glyph */
258 const FTC_GCacheClassRec ftc_basic_image_cache_class =
261 ftc_inode_new, /* FTC_Node_NewFunc node_new */
262 ftc_inode_weight, /* FTC_Node_WeightFunc node_weight */
263 ftc_gnode_compare, /* FTC_Node_CompareFunc node_compare */
264 ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
265 ftc_inode_free, /* FTC_Node_FreeFunc node_free */
267 sizeof ( FTC_GCacheRec ),
268 ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
269 ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
272 (FTC_MruListClass)&ftc_basic_image_family_class
276 /* documentation is in ftcache.h */
278 FT_EXPORT_DEF( FT_Error )
279 FTC_ImageCache_New( FTC_Manager manager,
280 FTC_ImageCache *acache )
282 return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
283 (FTC_GCache*)acache );
287 /* documentation is in ftcache.h */
289 FT_EXPORT_DEF( FT_Error )
290 FTC_ImageCache_Lookup( FTC_ImageCache cache,
296 FTC_BasicQueryRec query;
297 FTC_Node node = 0; /* make compiler happy */
302 /* some argument checks are delayed to `FTC_Cache_Lookup' */
305 error = FT_THROW( Invalid_Argument );
314 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
315 * but public `FT_ImageType->flags' is of type `FT_Int32'.
317 * On 16bit systems, higher bits of type->flags cannot be handled.
319 #if 0xFFFFFFFFUL > FT_UINT_MAX
320 if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
321 FT_TRACE1(( "FTC_ImageCache_Lookup:"
322 " higher bits in load_flags 0x%lx are dropped\n",
323 (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
326 query.attrs.scaler.face_id = type->face_id;
327 query.attrs.scaler.width = type->width;
328 query.attrs.scaler.height = type->height;
329 query.attrs.load_flags = (FT_UInt)type->flags;
331 query.attrs.scaler.pixel = 1;
332 query.attrs.scaler.x_res = 0; /* make compilers happy */
333 query.attrs.scaler.y_res = 0;
335 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
337 #if 1 /* inlining is about 50% faster! */
338 FTC_GCACHE_LOOKUP_CMP( cache,
339 ftc_basic_family_compare,
346 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
348 FTC_GQUERY( &query ),
353 *aglyph = FTC_INODE( node )->glyph;
367 /* documentation is in ftcache.h */
369 FT_EXPORT_DEF( FT_Error )
370 FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
377 FTC_BasicQueryRec query;
378 FTC_Node node = 0; /* make compiler happy */
383 /* some argument checks are delayed to `FTC_Cache_Lookup' */
384 if ( !aglyph || !scaler )
386 error = FT_THROW( Invalid_Argument );
395 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
396 * but public `FT_Face->face_flags' is of type `FT_Long'.
398 * On long > int systems, higher bits of load_flags cannot be handled.
400 #if FT_ULONG_MAX > FT_UINT_MAX
401 if ( load_flags > FT_UINT_MAX )
402 FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
403 " higher bits in load_flags 0x%lx are dropped\n",
404 load_flags & ~((FT_ULong)FT_UINT_MAX) ));
407 query.attrs.scaler = scaler[0];
408 query.attrs.load_flags = (FT_UInt)load_flags;
410 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
412 FTC_GCACHE_LOOKUP_CMP( cache,
413 ftc_basic_family_compare,
421 *aglyph = FTC_INODE( node )->glyph;
437 * basic small bitmap cache
442 const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
445 sizeof ( FTC_BasicFamilyRec ),
446 ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
447 ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
448 NULL, /* FTC_MruNode_ResetFunc node_reset */
449 NULL /* FTC_MruNode_DoneFunc node_done */
452 ftc_basic_family_get_count,
453 ftc_basic_family_load_bitmap
458 const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
461 ftc_snode_new, /* FTC_Node_NewFunc node_new */
462 ftc_snode_weight, /* FTC_Node_WeightFunc node_weight */
463 ftc_snode_compare, /* FTC_Node_CompareFunc node_compare */
464 ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
465 ftc_snode_free, /* FTC_Node_FreeFunc node_free */
467 sizeof ( FTC_GCacheRec ),
468 ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
469 ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
472 (FTC_MruListClass)&ftc_basic_sbit_family_class
476 /* documentation is in ftcache.h */
478 FT_EXPORT_DEF( FT_Error )
479 FTC_SBitCache_New( FTC_Manager manager,
480 FTC_SBitCache *acache )
482 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
483 (FTC_GCache*)acache );
487 /* documentation is in ftcache.h */
489 FT_EXPORT_DEF( FT_Error )
490 FTC_SBitCache_Lookup( FTC_SBitCache cache,
497 FTC_BasicQueryRec query;
498 FTC_Node node = 0; /* make compiler happy */
505 /* other argument checks delayed to `FTC_Cache_Lookup' */
507 return FT_THROW( Invalid_Argument );
512 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
513 * but public `FT_ImageType->flags' is of type `FT_Int32'.
515 * On 16bit systems, higher bits of type->flags cannot be handled.
517 #if 0xFFFFFFFFUL > FT_UINT_MAX
518 if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
519 FT_TRACE1(( "FTC_ImageCache_Lookup:"
520 " higher bits in load_flags 0x%lx are dropped\n",
521 (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
524 query.attrs.scaler.face_id = type->face_id;
525 query.attrs.scaler.width = type->width;
526 query.attrs.scaler.height = type->height;
527 query.attrs.load_flags = (FT_UInt)type->flags;
529 query.attrs.scaler.pixel = 1;
530 query.attrs.scaler.x_res = 0; /* make compilers happy */
531 query.attrs.scaler.y_res = 0;
533 /* beware, the hash must be the same for all glyph ranges! */
534 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
535 gindex / FTC_SBIT_ITEMS_PER_NODE;
537 #if 1 /* inlining is about 50% faster! */
538 FTC_GCACHE_LOOKUP_CMP( cache,
539 ftc_basic_family_compare,
546 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
549 FTC_GQUERY( &query ),
555 *ansbit = FTC_SNODE( node )->sbits +
556 ( gindex - FTC_GNODE( node )->gindex );
569 /* documentation is in ftcache.h */
571 FT_EXPORT_DEF( FT_Error )
572 FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
580 FTC_BasicQueryRec query;
581 FTC_Node node = 0; /* make compiler happy */
588 /* other argument checks delayed to `FTC_Cache_Lookup' */
589 if ( !ansbit || !scaler )
590 return FT_THROW( Invalid_Argument );
595 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
596 * but public `FT_Face->face_flags' is of type `FT_Long'.
598 * On long > int systems, higher bits of load_flags cannot be handled.
600 #if FT_ULONG_MAX > FT_UINT_MAX
601 if ( load_flags > FT_UINT_MAX )
602 FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
603 " higher bits in load_flags 0x%lx are dropped\n",
604 load_flags & ~((FT_ULong)FT_UINT_MAX) ));
607 query.attrs.scaler = scaler[0];
608 query.attrs.load_flags = (FT_UInt)load_flags;
610 /* beware, the hash must be the same for all glyph ranges! */
611 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
612 gindex / FTC_SBIT_ITEMS_PER_NODE;
614 FTC_GCACHE_LOOKUP_CMP( cache,
615 ftc_basic_family_compare,
624 *ansbit = FTC_SNODE( node )->sbits +
625 ( gindex - FTC_GNODE( node )->gindex );