1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ftcbasic.c */ |
|
4 /* */ |
|
5 /* The FreeType basic cache interface (body). */ |
|
6 /* */ |
|
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 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 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS |
|
34 |
|
35 /* |
|
36 * These structures correspond to the FTC_Font and FTC_ImageDesc types |
|
37 * that were defined in version 2.1.7. |
|
38 */ |
|
39 typedef struct FTC_OldFontRec_ |
|
40 { |
|
41 FTC_FaceID face_id; |
|
42 FT_UShort pix_width; |
|
43 FT_UShort pix_height; |
|
44 |
|
45 } FTC_OldFontRec, *FTC_OldFont; |
|
46 |
|
47 |
|
48 typedef struct FTC_OldImageDescRec_ |
|
49 { |
|
50 FTC_OldFontRec font; |
|
51 FT_UInt32 flags; |
|
52 |
|
53 } FTC_OldImageDescRec, *FTC_OldImageDesc; |
|
54 |
|
55 |
|
56 /* |
|
57 * Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly |
|
58 * identical, bit-wise. The only difference is that the `width' and |
|
59 * `height' fields are expressed as 16-bit integers in the old structure, |
|
60 * and as normal `int' in the new one. |
|
61 * |
|
62 * We are going to perform a weird hack to detect which structure is |
|
63 * being passed to the image and sbit caches. If the new structure's |
|
64 * `width' is larger than 0x10000, we assume that we are really receiving |
|
65 * an FTC_OldImageDesc. |
|
66 */ |
|
67 |
|
68 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ |
|
69 |
|
70 |
|
71 /* |
|
72 * Basic Families |
|
73 * |
|
74 */ |
|
75 typedef struct FTC_BasicAttrRec_ |
|
76 { |
|
77 FTC_ScalerRec scaler; |
|
78 FT_UInt load_flags; |
|
79 |
|
80 } FTC_BasicAttrRec, *FTC_BasicAttrs; |
|
81 |
|
82 #define FTC_BASIC_ATTR_COMPARE( a, b ) \ |
|
83 FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \ |
|
84 (a)->load_flags == (b)->load_flags ) |
|
85 |
|
86 #define FTC_BASIC_ATTR_HASH( a ) \ |
|
87 ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags ) |
|
88 |
|
89 |
|
90 typedef struct FTC_BasicQueryRec_ |
|
91 { |
|
92 FTC_GQueryRec gquery; |
|
93 FTC_BasicAttrRec attrs; |
|
94 |
|
95 } FTC_BasicQueryRec, *FTC_BasicQuery; |
|
96 |
|
97 |
|
98 typedef struct FTC_BasicFamilyRec_ |
|
99 { |
|
100 FTC_FamilyRec family; |
|
101 FTC_BasicAttrRec attrs; |
|
102 |
|
103 } FTC_BasicFamilyRec, *FTC_BasicFamily; |
|
104 |
|
105 |
|
106 FT_CALLBACK_DEF( FT_Bool ) |
|
107 ftc_basic_family_compare( FTC_MruNode ftcfamily, |
|
108 FT_Pointer ftcquery ) |
|
109 { |
|
110 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
|
111 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
|
112 |
|
113 |
|
114 return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ); |
|
115 } |
|
116 |
|
117 |
|
118 FT_CALLBACK_DEF( FT_Error ) |
|
119 ftc_basic_family_init( FTC_MruNode ftcfamily, |
|
120 FT_Pointer ftcquery, |
|
121 FT_Pointer ftccache ) |
|
122 { |
|
123 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
|
124 FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
|
125 FTC_Cache cache = (FTC_Cache)ftccache; |
|
126 |
|
127 |
|
128 FTC_Family_Init( FTC_FAMILY( family ), cache ); |
|
129 family->attrs = query->attrs; |
|
130 return 0; |
|
131 } |
|
132 |
|
133 |
|
134 FT_CALLBACK_DEF( FT_UInt ) |
|
135 ftc_basic_family_get_count( FTC_Family ftcfamily, |
|
136 FTC_Manager manager ) |
|
137 { |
|
138 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
|
139 FT_Error error; |
|
140 FT_Face face; |
|
141 FT_UInt result = 0; |
|
142 |
|
143 |
|
144 error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id, |
|
145 &face ); |
|
146 |
|
147 if ( error || !face ) |
|
148 return result; |
|
149 |
|
150 if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs ) |
|
151 { |
|
152 FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " )); |
|
153 FT_TRACE1(( "in this face, truncated\n", face->num_glyphs )); |
|
154 } |
|
155 |
|
156 if ( !error ) |
|
157 result = (FT_UInt)face->num_glyphs; |
|
158 |
|
159 return result; |
|
160 } |
|
161 |
|
162 |
|
163 FT_CALLBACK_DEF( FT_Error ) |
|
164 ftc_basic_family_load_bitmap( FTC_Family ftcfamily, |
|
165 FT_UInt gindex, |
|
166 FTC_Manager manager, |
|
167 FT_Face *aface ) |
|
168 { |
|
169 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
|
170 FT_Error error; |
|
171 FT_Size size; |
|
172 |
|
173 |
|
174 error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size ); |
|
175 if ( !error ) |
|
176 { |
|
177 FT_Face face = size->face; |
|
178 |
|
179 |
|
180 error = FT_Load_Glyph( face, gindex, |
|
181 family->attrs.load_flags | FT_LOAD_RENDER ); |
|
182 if ( !error ) |
|
183 *aface = face; |
|
184 } |
|
185 |
|
186 return error; |
|
187 } |
|
188 |
|
189 |
|
190 FT_CALLBACK_DEF( FT_Error ) |
|
191 ftc_basic_family_load_glyph( FTC_Family ftcfamily, |
|
192 FT_UInt gindex, |
|
193 FTC_Cache cache, |
|
194 FT_Glyph *aglyph ) |
|
195 { |
|
196 FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
|
197 FT_Error error; |
|
198 FTC_Scaler scaler = &family->attrs.scaler; |
|
199 FT_Face face; |
|
200 FT_Size size; |
|
201 |
|
202 |
|
203 /* we will now load the glyph image */ |
|
204 error = FTC_Manager_LookupSize( cache->manager, |
|
205 scaler, |
|
206 &size ); |
|
207 if ( !error ) |
|
208 { |
|
209 face = size->face; |
|
210 |
|
211 error = FT_Load_Glyph( face, gindex, family->attrs.load_flags ); |
|
212 if ( !error ) |
|
213 { |
|
214 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || |
|
215 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) |
|
216 { |
|
217 /* ok, copy it */ |
|
218 FT_Glyph glyph; |
|
219 |
|
220 |
|
221 error = FT_Get_Glyph( face->glyph, &glyph ); |
|
222 if ( !error ) |
|
223 { |
|
224 *aglyph = glyph; |
|
225 goto Exit; |
|
226 } |
|
227 } |
|
228 else |
|
229 error = FTC_Err_Invalid_Argument; |
|
230 } |
|
231 } |
|
232 |
|
233 Exit: |
|
234 return error; |
|
235 } |
|
236 |
|
237 |
|
238 FT_CALLBACK_DEF( FT_Bool ) |
|
239 ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode, |
|
240 FT_Pointer ftcface_id, |
|
241 FTC_Cache cache, |
|
242 FT_Bool* list_changed ) |
|
243 { |
|
244 FTC_GNode gnode = (FTC_GNode)ftcgnode; |
|
245 FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
|
246 FTC_BasicFamily family = (FTC_BasicFamily)gnode->family; |
|
247 FT_Bool result; |
|
248 |
|
249 |
|
250 if ( list_changed ) |
|
251 *list_changed = FALSE; |
|
252 result = FT_BOOL( family->attrs.scaler.face_id == face_id ); |
|
253 if ( result ) |
|
254 { |
|
255 /* we must call this function to avoid this node from appearing |
|
256 * in later lookups with the same face_id! |
|
257 */ |
|
258 FTC_GNode_UnselectFamily( gnode, cache ); |
|
259 } |
|
260 return result; |
|
261 } |
|
262 |
|
263 |
|
264 /* |
|
265 * |
|
266 * basic image cache |
|
267 * |
|
268 */ |
|
269 |
|
270 FT_CALLBACK_TABLE_DEF |
|
271 const FTC_IFamilyClassRec ftc_basic_image_family_class = |
|
272 { |
|
273 { |
|
274 sizeof ( FTC_BasicFamilyRec ), |
|
275 ftc_basic_family_compare, |
|
276 ftc_basic_family_init, |
|
277 0, /* FTC_MruNode_ResetFunc */ |
|
278 0 /* FTC_MruNode_DoneFunc */ |
|
279 }, |
|
280 ftc_basic_family_load_glyph |
|
281 }; |
|
282 |
|
283 |
|
284 FT_CALLBACK_TABLE_DEF |
|
285 const FTC_GCacheClassRec ftc_basic_image_cache_class = |
|
286 { |
|
287 { |
|
288 ftc_inode_new, |
|
289 ftc_inode_weight, |
|
290 ftc_gnode_compare, |
|
291 ftc_basic_gnode_compare_faceid, |
|
292 ftc_inode_free, |
|
293 |
|
294 sizeof ( FTC_GCacheRec ), |
|
295 ftc_gcache_init, |
|
296 ftc_gcache_done |
|
297 }, |
|
298 (FTC_MruListClass)&ftc_basic_image_family_class |
|
299 }; |
|
300 |
|
301 |
|
302 /* documentation is in ftcache.h */ |
|
303 |
|
304 FT_EXPORT_DEF( FT_Error ) |
|
305 FTC_ImageCache_New( FTC_Manager manager, |
|
306 FTC_ImageCache *acache ) |
|
307 { |
|
308 return FTC_GCache_New( manager, &ftc_basic_image_cache_class, |
|
309 (FTC_GCache*)acache ); |
|
310 } |
|
311 |
|
312 |
|
313 /* documentation is in ftcache.h */ |
|
314 |
|
315 FT_EXPORT_DEF( FT_Error ) |
|
316 FTC_ImageCache_Lookup( FTC_ImageCache cache, |
|
317 FTC_ImageType type, |
|
318 FT_UInt gindex, |
|
319 FT_Glyph *aglyph, |
|
320 FTC_Node *anode ) |
|
321 { |
|
322 FTC_BasicQueryRec query; |
|
323 FTC_Node node = 0; /* make compiler happy */ |
|
324 FT_Error error; |
|
325 FT_PtrDist hash; |
|
326 |
|
327 |
|
328 /* some argument checks are delayed to FTC_Cache_Lookup */ |
|
329 if ( !aglyph ) |
|
330 { |
|
331 error = FTC_Err_Invalid_Argument; |
|
332 goto Exit; |
|
333 } |
|
334 |
|
335 *aglyph = NULL; |
|
336 if ( anode ) |
|
337 *anode = NULL; |
|
338 |
|
339 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU ) |
|
340 |
|
341 /* |
|
342 * This one is a major hack used to detect whether we are passed a |
|
343 * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one. |
|
344 */ |
|
345 if ( (FT_ULong)type->width >= 0x10000L ) |
|
346 { |
|
347 FTC_OldImageDesc desc = (FTC_OldImageDesc)type; |
|
348 |
|
349 |
|
350 query.attrs.scaler.face_id = desc->font.face_id; |
|
351 query.attrs.scaler.width = desc->font.pix_width; |
|
352 query.attrs.scaler.height = desc->font.pix_height; |
|
353 query.attrs.load_flags = desc->flags; |
|
354 } |
|
355 else |
|
356 |
|
357 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ |
|
358 |
|
359 { |
|
360 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
|
361 { |
|
362 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
|
363 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) )); |
|
364 } |
|
365 |
|
366 query.attrs.scaler.face_id = type->face_id; |
|
367 query.attrs.scaler.width = type->width; |
|
368 query.attrs.scaler.height = type->height; |
|
369 query.attrs.load_flags = (FT_UInt)type->flags; |
|
370 } |
|
371 |
|
372 query.attrs.scaler.pixel = 1; |
|
373 query.attrs.scaler.x_res = 0; /* make compilers happy */ |
|
374 query.attrs.scaler.y_res = 0; |
|
375 |
|
376 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
|
377 |
|
378 #if 1 /* inlining is about 50% faster! */ |
|
379 FTC_GCACHE_LOOKUP_CMP( cache, |
|
380 ftc_basic_family_compare, |
|
381 FTC_GNode_Compare, |
|
382 hash, gindex, |
|
383 &query, |
|
384 node, |
|
385 error ); |
|
386 #else |
|
387 error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
|
388 hash, gindex, |
|
389 FTC_GQUERY( &query ), |
|
390 &node ); |
|
391 #endif |
|
392 if ( !error ) |
|
393 { |
|
394 *aglyph = FTC_INODE( node )->glyph; |
|
395 |
|
396 if ( anode ) |
|
397 { |
|
398 *anode = node; |
|
399 node->ref_count++; |
|
400 } |
|
401 } |
|
402 |
|
403 Exit: |
|
404 return error; |
|
405 } |
|
406 |
|
407 |
|
408 /* documentation is in ftcache.h */ |
|
409 |
|
410 FT_EXPORT_DEF( FT_Error ) |
|
411 FTC_ImageCache_LookupScaler( FTC_ImageCache cache, |
|
412 FTC_Scaler scaler, |
|
413 FT_ULong load_flags, |
|
414 FT_UInt gindex, |
|
415 FT_Glyph *aglyph, |
|
416 FTC_Node *anode ) |
|
417 { |
|
418 FTC_BasicQueryRec query; |
|
419 FTC_Node node = 0; /* make compiler happy */ |
|
420 FT_Error error; |
|
421 FT_PtrDist hash; |
|
422 |
|
423 |
|
424 /* some argument checks are delayed to FTC_Cache_Lookup */ |
|
425 if ( !aglyph || !scaler ) |
|
426 { |
|
427 error = FTC_Err_Invalid_Argument; |
|
428 goto Exit; |
|
429 } |
|
430 |
|
431 *aglyph = NULL; |
|
432 if ( anode ) |
|
433 *anode = NULL; |
|
434 |
|
435 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
|
436 if ( load_flags > FT_UINT_MAX ) |
|
437 { |
|
438 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
|
439 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); |
|
440 } |
|
441 |
|
442 query.attrs.scaler = scaler[0]; |
|
443 query.attrs.load_flags = (FT_UInt)load_flags; |
|
444 |
|
445 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
|
446 |
|
447 FTC_GCACHE_LOOKUP_CMP( cache, |
|
448 ftc_basic_family_compare, |
|
449 FTC_GNode_Compare, |
|
450 hash, gindex, |
|
451 &query, |
|
452 node, |
|
453 error ); |
|
454 if ( !error ) |
|
455 { |
|
456 *aglyph = FTC_INODE( node )->glyph; |
|
457 |
|
458 if ( anode ) |
|
459 { |
|
460 *anode = node; |
|
461 node->ref_count++; |
|
462 } |
|
463 } |
|
464 |
|
465 Exit: |
|
466 return error; |
|
467 } |
|
468 |
|
469 |
|
470 |
|
471 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS |
|
472 |
|
473 /* yet another backwards-legacy structure */ |
|
474 typedef struct FTC_OldImage_Desc_ |
|
475 { |
|
476 FTC_FontRec font; |
|
477 FT_UInt image_type; |
|
478 |
|
479 } FTC_OldImage_Desc; |
|
480 |
|
481 |
|
482 #define FTC_OLD_IMAGE_FORMAT( x ) ( (x) & 7 ) |
|
483 |
|
484 |
|
485 #define ftc_old_image_format_bitmap 0x0000 |
|
486 #define ftc_old_image_format_outline 0x0001 |
|
487 |
|
488 #define ftc_old_image_format_mask 0x000F |
|
489 |
|
490 #define ftc_old_image_flag_monochrome 0x0010 |
|
491 #define ftc_old_image_flag_unhinted 0x0020 |
|
492 #define ftc_old_image_flag_autohinted 0x0040 |
|
493 #define ftc_old_image_flag_unscaled 0x0080 |
|
494 #define ftc_old_image_flag_no_sbits 0x0100 |
|
495 |
|
496 /* monochrome bitmap */ |
|
497 #define ftc_old_image_mono ftc_old_image_format_bitmap | \ |
|
498 ftc_old_image_flag_monochrome |
|
499 |
|
500 /* anti-aliased bitmap */ |
|
501 #define ftc_old_image_grays ftc_old_image_format_bitmap |
|
502 |
|
503 /* scaled outline */ |
|
504 #define ftc_old_image_outline ftc_old_image_format_outline |
|
505 |
|
506 |
|
507 static void |
|
508 ftc_image_type_from_old_desc( FTC_ImageType typ, |
|
509 FTC_OldImage_Desc* desc ) |
|
510 { |
|
511 typ->face_id = desc->font.face_id; |
|
512 typ->width = desc->font.pix_width; |
|
513 typ->height = desc->font.pix_height; |
|
514 |
|
515 /* convert image type flags to load flags */ |
|
516 { |
|
517 FT_UInt load_flags = FT_LOAD_DEFAULT; |
|
518 FT_UInt type = desc->image_type; |
|
519 |
|
520 |
|
521 /* determine load flags, depending on the font description's */ |
|
522 /* image type */ |
|
523 |
|
524 if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap ) |
|
525 { |
|
526 if ( type & ftc_old_image_flag_monochrome ) |
|
527 load_flags |= FT_LOAD_MONOCHROME; |
|
528 |
|
529 /* disable embedded bitmaps loading if necessary */ |
|
530 if ( type & ftc_old_image_flag_no_sbits ) |
|
531 load_flags |= FT_LOAD_NO_BITMAP; |
|
532 } |
|
533 else |
|
534 { |
|
535 /* we want an outline, don't load embedded bitmaps */ |
|
536 load_flags |= FT_LOAD_NO_BITMAP; |
|
537 |
|
538 if ( type & ftc_old_image_flag_unscaled ) |
|
539 load_flags |= FT_LOAD_NO_SCALE; |
|
540 } |
|
541 |
|
542 /* always render glyphs to bitmaps */ |
|
543 load_flags |= FT_LOAD_RENDER; |
|
544 |
|
545 if ( type & ftc_old_image_flag_unhinted ) |
|
546 load_flags |= FT_LOAD_NO_HINTING; |
|
547 |
|
548 if ( type & ftc_old_image_flag_autohinted ) |
|
549 load_flags |= FT_LOAD_FORCE_AUTOHINT; |
|
550 |
|
551 typ->flags = load_flags; |
|
552 } |
|
553 } |
|
554 |
|
555 |
|
556 FT_EXPORT( FT_Error ) |
|
557 FTC_Image_Cache_New( FTC_Manager manager, |
|
558 FTC_ImageCache *acache ); |
|
559 |
|
560 FT_EXPORT( FT_Error ) |
|
561 FTC_Image_Cache_Lookup( FTC_ImageCache icache, |
|
562 FTC_OldImage_Desc* desc, |
|
563 FT_UInt gindex, |
|
564 FT_Glyph *aglyph ); |
|
565 |
|
566 |
|
567 FT_EXPORT_DEF( FT_Error ) |
|
568 FTC_Image_Cache_New( FTC_Manager manager, |
|
569 FTC_ImageCache *acache ) |
|
570 { |
|
571 return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache ); |
|
572 } |
|
573 |
|
574 |
|
575 |
|
576 FT_EXPORT_DEF( FT_Error ) |
|
577 FTC_Image_Cache_Lookup( FTC_ImageCache icache, |
|
578 FTC_OldImage_Desc* desc, |
|
579 FT_UInt gindex, |
|
580 FT_Glyph *aglyph ) |
|
581 { |
|
582 FTC_ImageTypeRec type0; |
|
583 |
|
584 |
|
585 if ( !desc ) |
|
586 return FTC_Err_Invalid_Argument; |
|
587 |
|
588 ftc_image_type_from_old_desc( &type0, desc ); |
|
589 |
|
590 return FTC_ImageCache_Lookup( (FTC_ImageCache)icache, |
|
591 &type0, |
|
592 gindex, |
|
593 aglyph, |
|
594 NULL ); |
|
595 } |
|
596 |
|
597 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ |
|
598 |
|
599 |
|
600 /* |
|
601 * |
|
602 * basic small bitmap cache |
|
603 * |
|
604 */ |
|
605 |
|
606 |
|
607 FT_CALLBACK_TABLE_DEF |
|
608 const FTC_SFamilyClassRec ftc_basic_sbit_family_class = |
|
609 { |
|
610 { |
|
611 sizeof( FTC_BasicFamilyRec ), |
|
612 ftc_basic_family_compare, |
|
613 ftc_basic_family_init, |
|
614 0, /* FTC_MruNode_ResetFunc */ |
|
615 0 /* FTC_MruNode_DoneFunc */ |
|
616 }, |
|
617 ftc_basic_family_get_count, |
|
618 ftc_basic_family_load_bitmap |
|
619 }; |
|
620 |
|
621 |
|
622 FT_CALLBACK_TABLE_DEF |
|
623 const FTC_GCacheClassRec ftc_basic_sbit_cache_class = |
|
624 { |
|
625 { |
|
626 ftc_snode_new, |
|
627 ftc_snode_weight, |
|
628 ftc_snode_compare, |
|
629 ftc_basic_gnode_compare_faceid, |
|
630 ftc_snode_free, |
|
631 |
|
632 sizeof ( FTC_GCacheRec ), |
|
633 ftc_gcache_init, |
|
634 ftc_gcache_done |
|
635 }, |
|
636 (FTC_MruListClass)&ftc_basic_sbit_family_class |
|
637 }; |
|
638 |
|
639 |
|
640 /* documentation is in ftcache.h */ |
|
641 |
|
642 FT_EXPORT_DEF( FT_Error ) |
|
643 FTC_SBitCache_New( FTC_Manager manager, |
|
644 FTC_SBitCache *acache ) |
|
645 { |
|
646 return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class, |
|
647 (FTC_GCache*)acache ); |
|
648 } |
|
649 |
|
650 |
|
651 /* documentation is in ftcache.h */ |
|
652 |
|
653 FT_EXPORT_DEF( FT_Error ) |
|
654 FTC_SBitCache_Lookup( FTC_SBitCache cache, |
|
655 FTC_ImageType type, |
|
656 FT_UInt gindex, |
|
657 FTC_SBit *ansbit, |
|
658 FTC_Node *anode ) |
|
659 { |
|
660 FT_Error error; |
|
661 FTC_BasicQueryRec query; |
|
662 FTC_Node node = 0; /* make compiler happy */ |
|
663 FT_PtrDist hash; |
|
664 |
|
665 |
|
666 if ( anode ) |
|
667 *anode = NULL; |
|
668 |
|
669 /* other argument checks delayed to FTC_Cache_Lookup */ |
|
670 if ( !ansbit ) |
|
671 return FTC_Err_Invalid_Argument; |
|
672 |
|
673 *ansbit = NULL; |
|
674 |
|
675 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU ) |
|
676 |
|
677 /* This one is a major hack used to detect whether we are passed a |
|
678 * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one. |
|
679 */ |
|
680 if ( (FT_ULong)type->width >= 0x10000L ) |
|
681 { |
|
682 FTC_OldImageDesc desc = (FTC_OldImageDesc)type; |
|
683 |
|
684 |
|
685 query.attrs.scaler.face_id = desc->font.face_id; |
|
686 query.attrs.scaler.width = desc->font.pix_width; |
|
687 query.attrs.scaler.height = desc->font.pix_height; |
|
688 query.attrs.load_flags = desc->flags; |
|
689 } |
|
690 else |
|
691 |
|
692 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ |
|
693 |
|
694 { |
|
695 if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
|
696 { |
|
697 FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
|
698 FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) )); |
|
699 } |
|
700 |
|
701 query.attrs.scaler.face_id = type->face_id; |
|
702 query.attrs.scaler.width = type->width; |
|
703 query.attrs.scaler.height = type->height; |
|
704 query.attrs.load_flags = (FT_UInt)type->flags; |
|
705 } |
|
706 |
|
707 query.attrs.scaler.pixel = 1; |
|
708 query.attrs.scaler.x_res = 0; /* make compilers happy */ |
|
709 query.attrs.scaler.y_res = 0; |
|
710 |
|
711 /* beware, the hash must be the same for all glyph ranges! */ |
|
712 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
|
713 gindex / FTC_SBIT_ITEMS_PER_NODE; |
|
714 |
|
715 #if 1 /* inlining is about 50% faster! */ |
|
716 FTC_GCACHE_LOOKUP_CMP( cache, |
|
717 ftc_basic_family_compare, |
|
718 FTC_SNode_Compare, |
|
719 hash, gindex, |
|
720 &query, |
|
721 node, |
|
722 error ); |
|
723 #else |
|
724 error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
|
725 hash, |
|
726 gindex, |
|
727 FTC_GQUERY( &query ), |
|
728 &node ); |
|
729 #endif |
|
730 if ( error ) |
|
731 goto Exit; |
|
732 |
|
733 *ansbit = FTC_SNODE( node )->sbits + |
|
734 ( gindex - FTC_GNODE( node )->gindex ); |
|
735 |
|
736 if ( anode ) |
|
737 { |
|
738 *anode = node; |
|
739 node->ref_count++; |
|
740 } |
|
741 |
|
742 Exit: |
|
743 return error; |
|
744 } |
|
745 |
|
746 |
|
747 /* documentation is in ftcache.h */ |
|
748 |
|
749 FT_EXPORT_DEF( FT_Error ) |
|
750 FTC_SBitCache_LookupScaler( FTC_SBitCache cache, |
|
751 FTC_Scaler scaler, |
|
752 FT_ULong load_flags, |
|
753 FT_UInt gindex, |
|
754 FTC_SBit *ansbit, |
|
755 FTC_Node *anode ) |
|
756 { |
|
757 FT_Error error; |
|
758 FTC_BasicQueryRec query; |
|
759 FTC_Node node = 0; /* make compiler happy */ |
|
760 FT_PtrDist hash; |
|
761 |
|
762 |
|
763 if ( anode ) |
|
764 *anode = NULL; |
|
765 |
|
766 /* other argument checks delayed to FTC_Cache_Lookup */ |
|
767 if ( !ansbit || !scaler ) |
|
768 return FTC_Err_Invalid_Argument; |
|
769 |
|
770 *ansbit = NULL; |
|
771 |
|
772 /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
|
773 if ( load_flags > FT_UINT_MAX ) |
|
774 { |
|
775 FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
|
776 FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); |
|
777 } |
|
778 |
|
779 query.attrs.scaler = scaler[0]; |
|
780 query.attrs.load_flags = (FT_UInt)load_flags; |
|
781 |
|
782 /* beware, the hash must be the same for all glyph ranges! */ |
|
783 hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
|
784 gindex / FTC_SBIT_ITEMS_PER_NODE; |
|
785 |
|
786 FTC_GCACHE_LOOKUP_CMP( cache, |
|
787 ftc_basic_family_compare, |
|
788 FTC_SNode_Compare, |
|
789 hash, gindex, |
|
790 &query, |
|
791 node, |
|
792 error ); |
|
793 if ( error ) |
|
794 goto Exit; |
|
795 |
|
796 *ansbit = FTC_SNODE( node )->sbits + |
|
797 ( gindex - FTC_GNODE( node )->gindex ); |
|
798 |
|
799 if ( anode ) |
|
800 { |
|
801 *anode = node; |
|
802 node->ref_count++; |
|
803 } |
|
804 |
|
805 Exit: |
|
806 return error; |
|
807 } |
|
808 |
|
809 |
|
810 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS |
|
811 |
|
812 FT_EXPORT( FT_Error ) |
|
813 FTC_SBit_Cache_New( FTC_Manager manager, |
|
814 FTC_SBitCache *acache ); |
|
815 |
|
816 FT_EXPORT( FT_Error ) |
|
817 FTC_SBit_Cache_Lookup( FTC_SBitCache cache, |
|
818 FTC_OldImage_Desc* desc, |
|
819 FT_UInt gindex, |
|
820 FTC_SBit *ansbit ); |
|
821 |
|
822 |
|
823 FT_EXPORT_DEF( FT_Error ) |
|
824 FTC_SBit_Cache_New( FTC_Manager manager, |
|
825 FTC_SBitCache *acache ) |
|
826 { |
|
827 return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache ); |
|
828 } |
|
829 |
|
830 |
|
831 FT_EXPORT_DEF( FT_Error ) |
|
832 FTC_SBit_Cache_Lookup( FTC_SBitCache cache, |
|
833 FTC_OldImage_Desc* desc, |
|
834 FT_UInt gindex, |
|
835 FTC_SBit *ansbit ) |
|
836 { |
|
837 FTC_ImageTypeRec type0; |
|
838 |
|
839 |
|
840 if ( !desc ) |
|
841 return FTC_Err_Invalid_Argument; |
|
842 |
|
843 ftc_image_type_from_old_desc( &type0, desc ); |
|
844 |
|
845 return FTC_SBitCache_Lookup( (FTC_SBitCache)cache, |
|
846 &type0, |
|
847 gindex, |
|
848 ansbit, |
|
849 NULL ); |
|
850 } |
|
851 |
|
852 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ |
|
853 |
|
854 |
|
855 /* END */ |
|