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