1 /****************************************************************************
5 * The FreeType basic cache interface (body).
7 * Copyright (C) 2003-2020 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>
29 #define FT_COMPONENT cache
36 typedef struct FTC_BasicAttrRec_
41 } FTC_BasicAttrRec, *FTC_BasicAttrs;
43 #define FTC_BASIC_ATTR_COMPARE( a, b ) \
44 FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
45 (a)->load_flags == (b)->load_flags )
47 #define FTC_BASIC_ATTR_HASH( a ) \
48 ( FTC_SCALER_HASH( &(a)->scaler ) + 31 * (a)->load_flags )
51 typedef struct FTC_BasicQueryRec_
54 FTC_BasicAttrRec attrs;
56 } FTC_BasicQueryRec, *FTC_BasicQuery;
59 typedef struct FTC_BasicFamilyRec_
62 FTC_BasicAttrRec attrs;
64 } FTC_BasicFamilyRec, *FTC_BasicFamily;
67 FT_CALLBACK_DEF( FT_Bool )
68 ftc_basic_family_compare( FTC_MruNode ftcfamily,
71 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
72 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
75 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
79 FT_CALLBACK_DEF( FT_Error )
80 ftc_basic_family_init( FTC_MruNode ftcfamily,
84 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
85 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
86 FTC_Cache cache = (FTC_Cache)ftccache;
89 FTC_Family_Init( FTC_FAMILY( family ), cache );
90 family->attrs = query->attrs;
95 FT_CALLBACK_DEF( FT_UInt )
96 ftc_basic_family_get_count( FTC_Family ftcfamily,
99 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
105 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
108 if ( error || !face )
111 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
112 FT_TRACE1(( "ftc_basic_family_get_count:"
113 " the number of glyphs in this face is %ld,\n"
115 " which is too much and thus truncated\n",
119 result = (FT_UInt)face->num_glyphs;
125 FT_CALLBACK_DEF( FT_Error )
126 ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
131 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
136 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
139 FT_Face face = size->face;
142 error = FT_Load_Glyph(
145 (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
154 FT_CALLBACK_DEF( FT_Error )
155 ftc_basic_family_load_glyph( FTC_Family ftcfamily,
160 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
162 FTC_Scaler scaler = &family->attrs.scaler;
167 /* we will now load the glyph image */
168 error = FTC_Manager_LookupSize( cache->manager,
175 error = FT_Load_Glyph( face,
177 (FT_Int)family->attrs.load_flags );
180 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
181 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
187 error = FT_Get_Glyph( face->glyph, &glyph );
195 error = FT_THROW( Invalid_Argument );
204 FT_CALLBACK_DEF( FT_Bool )
205 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
206 FT_Pointer ftcface_id,
208 FT_Bool* list_changed )
210 FTC_GNode gnode = (FTC_GNode)ftcgnode;
211 FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
212 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
217 *list_changed = FALSE;
218 result = FT_BOOL( family->attrs.scaler.face_id == face_id );
221 /* we must call this function to avoid this node from appearing
222 * in later lookups with the same face_id!
224 FTC_GNode_UnselectFamily( gnode, cache );
237 const FTC_IFamilyClassRec ftc_basic_image_family_class =
240 sizeof ( FTC_BasicFamilyRec ),
242 ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
243 ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
244 NULL, /* FTC_MruNode_ResetFunc node_reset */
245 NULL /* FTC_MruNode_DoneFunc node_done */
248 ftc_basic_family_load_glyph /* FTC_IFamily_LoadGlyphFunc family_load_glyph */
253 const FTC_GCacheClassRec ftc_basic_image_cache_class =
256 ftc_inode_new, /* FTC_Node_NewFunc node_new */
257 ftc_inode_weight, /* FTC_Node_WeightFunc node_weight */
258 ftc_gnode_compare, /* FTC_Node_CompareFunc node_compare */
259 ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
260 ftc_inode_free, /* FTC_Node_FreeFunc node_free */
262 sizeof ( FTC_GCacheRec ),
263 ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
264 ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
267 (FTC_MruListClass)&ftc_basic_image_family_class
271 /* documentation is in ftcache.h */
273 FT_EXPORT_DEF( FT_Error )
274 FTC_ImageCache_New( FTC_Manager manager,
275 FTC_ImageCache *acache )
277 return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
278 (FTC_GCache*)acache );
282 /* documentation is in ftcache.h */
284 FT_EXPORT_DEF( FT_Error )
285 FTC_ImageCache_Lookup( FTC_ImageCache cache,
291 FTC_BasicQueryRec query;
292 FTC_Node node = 0; /* make compiler happy */
297 /* some argument checks are delayed to `FTC_Cache_Lookup' */
300 error = FT_THROW( Invalid_Argument );
309 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
310 * but public `FT_ImageType->flags' is of type `FT_Int32'.
312 * On 16bit systems, higher bits of type->flags cannot be handled.
314 #if 0xFFFFFFFFUL > FT_UINT_MAX
315 if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
316 FT_TRACE1(( "FTC_ImageCache_Lookup:"
317 " higher bits in load_flags 0x%x are dropped\n",
318 (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
321 query.attrs.scaler.face_id = type->face_id;
322 query.attrs.scaler.width = type->width;
323 query.attrs.scaler.height = type->height;
324 query.attrs.load_flags = (FT_UInt)type->flags;
326 query.attrs.scaler.pixel = 1;
327 query.attrs.scaler.x_res = 0; /* make compilers happy */
328 query.attrs.scaler.y_res = 0;
330 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
332 #if 1 /* inlining is about 50% faster! */
333 FTC_GCACHE_LOOKUP_CMP( cache,
334 ftc_basic_family_compare,
341 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
343 FTC_GQUERY( &query ),
348 *aglyph = FTC_INODE( node )->glyph;
362 /* documentation is in ftcache.h */
364 FT_EXPORT_DEF( FT_Error )
365 FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
372 FTC_BasicQueryRec query;
373 FTC_Node node = 0; /* make compiler happy */
378 /* some argument checks are delayed to `FTC_Cache_Lookup' */
379 if ( !aglyph || !scaler )
381 error = FT_THROW( Invalid_Argument );
390 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
391 * but public `FT_Face->face_flags' is of type `FT_Long'.
393 * On long > int systems, higher bits of load_flags cannot be handled.
395 #if FT_ULONG_MAX > FT_UINT_MAX
396 if ( load_flags > FT_UINT_MAX )
397 FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
398 " higher bits in load_flags 0x%lx are dropped\n",
399 load_flags & ~((FT_ULong)FT_UINT_MAX) ));
402 query.attrs.scaler = scaler[0];
403 query.attrs.load_flags = (FT_UInt)load_flags;
405 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
407 FTC_GCACHE_LOOKUP_CMP( cache,
408 ftc_basic_family_compare,
416 *aglyph = FTC_INODE( node )->glyph;
432 * basic small bitmap cache
437 const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
440 sizeof ( FTC_BasicFamilyRec ),
441 ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
442 ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
443 NULL, /* FTC_MruNode_ResetFunc node_reset */
444 NULL /* FTC_MruNode_DoneFunc node_done */
447 ftc_basic_family_get_count,
448 ftc_basic_family_load_bitmap
453 const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
456 ftc_snode_new, /* FTC_Node_NewFunc node_new */
457 ftc_snode_weight, /* FTC_Node_WeightFunc node_weight */
458 ftc_snode_compare, /* FTC_Node_CompareFunc node_compare */
459 ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
460 ftc_snode_free, /* FTC_Node_FreeFunc node_free */
462 sizeof ( FTC_GCacheRec ),
463 ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
464 ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
467 (FTC_MruListClass)&ftc_basic_sbit_family_class
471 /* documentation is in ftcache.h */
473 FT_EXPORT_DEF( FT_Error )
474 FTC_SBitCache_New( FTC_Manager manager,
475 FTC_SBitCache *acache )
477 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
478 (FTC_GCache*)acache );
482 /* documentation is in ftcache.h */
484 FT_EXPORT_DEF( FT_Error )
485 FTC_SBitCache_Lookup( FTC_SBitCache cache,
492 FTC_BasicQueryRec query;
493 FTC_Node node = 0; /* make compiler happy */
500 /* other argument checks delayed to `FTC_Cache_Lookup' */
502 return FT_THROW( Invalid_Argument );
507 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
508 * but public `FT_ImageType->flags' is of type `FT_Int32'.
510 * On 16bit systems, higher bits of type->flags cannot be handled.
512 #if 0xFFFFFFFFUL > FT_UINT_MAX
513 if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
514 FT_TRACE1(( "FTC_ImageCache_Lookup:"
515 " higher bits in load_flags 0x%x are dropped\n",
516 (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
519 query.attrs.scaler.face_id = type->face_id;
520 query.attrs.scaler.width = type->width;
521 query.attrs.scaler.height = type->height;
522 query.attrs.load_flags = (FT_UInt)type->flags;
524 query.attrs.scaler.pixel = 1;
525 query.attrs.scaler.x_res = 0; /* make compilers happy */
526 query.attrs.scaler.y_res = 0;
528 /* beware, the hash must be the same for all glyph ranges! */
529 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
530 gindex / FTC_SBIT_ITEMS_PER_NODE;
532 #if 1 /* inlining is about 50% faster! */
533 FTC_GCACHE_LOOKUP_CMP( cache,
534 ftc_basic_family_compare,
541 error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
544 FTC_GQUERY( &query ),
550 *ansbit = FTC_SNODE( node )->sbits +
551 ( gindex - FTC_GNODE( node )->gindex );
564 /* documentation is in ftcache.h */
566 FT_EXPORT_DEF( FT_Error )
567 FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
575 FTC_BasicQueryRec query;
576 FTC_Node node = 0; /* make compiler happy */
583 /* other argument checks delayed to `FTC_Cache_Lookup' */
584 if ( !ansbit || !scaler )
585 return FT_THROW( Invalid_Argument );
590 * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
591 * but public `FT_Face->face_flags' is of type `FT_Long'.
593 * On long > int systems, higher bits of load_flags cannot be handled.
595 #if FT_ULONG_MAX > FT_UINT_MAX
596 if ( load_flags > FT_UINT_MAX )
597 FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
598 " higher bits in load_flags 0x%lx are dropped\n",
599 load_flags & ~((FT_ULong)FT_UINT_MAX) ));
602 query.attrs.scaler = scaler[0];
603 query.attrs.load_flags = (FT_UInt)load_flags;
605 /* beware, the hash must be the same for all glyph ranges! */
606 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
607 gindex / FTC_SBIT_ITEMS_PER_NODE;
609 FTC_GCACHE_LOOKUP_CMP( cache,
610 ftc_basic_family_compare,
619 *ansbit = FTC_SNODE( node )->sbits +
620 ( gindex - FTC_GNODE( node )->gindex );