David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 1 | #include <freetype/cache/ftcsbits.h> |
| 2 | #include <freetype/fterrors.h> |
| 3 | |
| 4 | #define FTC_SBITSET_ELEMENT_COUNT 16 |
| 5 | |
| 6 | |
| 7 | typedef struct FTC_SBitSetRec_ |
| 8 | { |
| 9 | FTC_ChunkSetRec root; |
| 10 | FTC_Image_Desc desc; |
| 11 | |
| 12 | } FTC_SBitSetRec, *FTC_SBitSet; |
| 13 | |
| 14 | |
| 15 | typedef struct FTC_SBit_CacheRec_ |
| 16 | { |
| 17 | FTC_Chunk_CacheRec root; |
| 18 | |
| 19 | } FTC_SBit_CacheRec; |
| 20 | |
| 21 | |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 22 | |
| 23 | /*************************************************************************/ |
| 24 | /*************************************************************************/ |
| 25 | /***** *****/ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 26 | /***** SBIT CACHE NODES *****/ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 27 | /***** *****/ |
| 28 | /*************************************************************************/ |
| 29 | /*************************************************************************/ |
| 30 | |
| 31 | |
| 32 | LOCAL_FUNC_X |
| 33 | void ftc_sbit_chunk_node_destroy( FTC_ChunkNode node ) |
| 34 | { |
| 35 | FTC_ChunkSet cset = node->cset; |
| 36 | FT_Memory memory = cset->memory; |
| 37 | FT_UInt count = node->num_elements; |
| 38 | FTC_SBit sbit = (FTC_SBit)node->elements; |
| 39 | |
| 40 | for ( ; count > 0; sbit++, count-- ) |
| 41 | FREE( sbit->buffer ); |
| 42 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 43 | FREE( node->elements ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 44 | FREE( node ); |
| 45 | } |
| 46 | |
| 47 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 48 | |
| 49 | |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 50 | static |
| 51 | FT_Error ftc_bitmap_copy( FT_Memory memory, |
| 52 | FT_Bitmap* source, |
| 53 | FTC_SBit target ) |
| 54 | { |
| 55 | FT_Error error; |
| 56 | FT_Int pitch = source->pitch; |
| 57 | FT_ULong size; |
| 58 | |
| 59 | if ( pitch < 0 ) |
| 60 | pitch = -pitch; |
| 61 | |
| 62 | size = (FT_ULong)( pitch * source->rows ); |
| 63 | |
| 64 | if ( !ALLOC( target->buffer, size ) ) |
| 65 | MEM_Copy( target->buffer, source->buffer, size ); |
| 66 | |
| 67 | return error; |
| 68 | } |
| 69 | |
| 70 | |
| 71 | LOCAL_FUNC_X |
| 72 | FT_Error ftc_sbit_chunk_node_new( FTC_ChunkSet cset, |
| 73 | FT_UInt index, |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 74 | FTC_ChunkNode *anode ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 75 | { |
| 76 | FT_Error error; |
| 77 | FT_Memory memory = cset->memory; |
| 78 | FTC_SBitSet sbitset = (FTC_SBitSet)cset; |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 79 | FTC_ChunkNode node = 0; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 80 | FT_Face face; |
| 81 | FT_Size size; |
| 82 | |
| 83 | |
| 84 | /* allocate node */ |
| 85 | if ( ALLOC( node, sizeof ( *node ) ) ) |
| 86 | goto Exit; |
| 87 | |
| 88 | /* init its inner fields */ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 89 | error = FTC_ChunkNode_Init( node, cset, index, 1 ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 90 | if (error) |
| 91 | goto Exit; |
| 92 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 93 | /* we will now load all glyph images for this chunk */ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 94 | error = FTC_Manager_Lookup_Size( cset->manager, |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 95 | &sbitset->desc.font, |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 96 | &face, &size ); |
| 97 | if ( !error ) |
| 98 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 99 | FT_UInt glyph_index = index * cset->element_count; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 100 | FT_UInt load_flags = FT_LOAD_DEFAULT; |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 101 | FT_UInt image_type = sbitset->desc.image_type; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 102 | FT_UInt count = node->num_elements; |
| 103 | FTC_SBit sbit = (FTC_SBit)node->elements; |
| 104 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 105 | /* determine load flags, depending on the font description's */ |
| 106 | /* image type.. */ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 107 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 108 | if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 109 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 110 | if ( image_type & ftc_image_flag_monochrome ) |
| 111 | load_flags |= FT_LOAD_MONOCHROME; |
| 112 | |
| 113 | /* disable embedded bitmaps loading if necessary */ |
| 114 | if ( image_type & ftc_image_flag_no_sbits ) |
| 115 | load_flags |= FT_LOAD_NO_BITMAP; |
| 116 | } |
| 117 | else |
| 118 | { |
| 119 | FT_ERROR(( "FTC_SBit_Cache: cannot load scalable glyphs in a" |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 120 | " sbit cache, please check your arguments !!\n" )); |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 121 | error = FT_Err_Invalid_Argument; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 122 | goto Exit; |
| 123 | } |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 124 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 125 | /* always render glyphs to bitmaps */ |
| 126 | load_flags |= FT_LOAD_RENDER; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 127 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 128 | if ( image_type & ftc_image_flag_unhinted ) |
| 129 | load_flags |= FT_LOAD_NO_HINTING; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 130 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 131 | if ( image_type & ftc_image_flag_autohinted ) |
| 132 | load_flags |= FT_LOAD_FORCE_AUTOHINT; |
| 133 | } |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 134 | |
| 135 | |
| 136 | /* load a chunk of small bitmaps in a row */ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 137 | for ( ; count > 0; count--, glyph_index++, sbit++ ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 138 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 139 | /* by default, indicates a "missing" glyph */ |
| 140 | sbit->buffer = 0; |
| 141 | |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 142 | error = FT_Load_Glyph( face, glyph_index, load_flags ); |
| 143 | if (!error) |
| 144 | { |
| 145 | FT_Int temp; |
| 146 | FT_GlyphSlot slot = face->glyph; |
| 147 | FT_Bitmap* bitmap = &slot->bitmap; |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 148 | FT_Int xadvance, yadvance; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 149 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 150 | /* check that our values fit in 8-bit containers !! */ |
| 151 | /* if this is not the case, our bitmap is too large */ |
| 152 | /* and we will leave it as "missing" with sbit.buffer = 0 */ |
| 153 | |
| 154 | #define CHECK_CHAR(d) ( temp = (FT_Char)d, temp == d ) |
| 155 | #define CHECK_BYTE(d) ( temp = (FT_Byte)d, temp == d ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 156 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 157 | /* FIXME: add support for vertical layouts maybe.. */ |
| 158 | |
| 159 | /* horizontal advance in pixels */ |
| 160 | xadvance = (slot->metrics.horiAdvance+32) >> 6; |
| 161 | yadvance = (slot->metrics.vertAdvance+32) >> 6; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 162 | |
| 163 | if ( CHECK_BYTE ( bitmap->rows ) && |
| 164 | CHECK_BYTE ( bitmap->width ) && |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 165 | CHECK_CHAR ( bitmap->pitch ) && |
| 166 | CHECK_CHAR ( slot->bitmap_left ) && |
| 167 | CHECK_CHAR ( slot->bitmap_top ) && |
| 168 | CHECK_CHAR ( xadvance ) && |
| 169 | CHECK_CHAR ( yadvance ) ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 170 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 171 | sbit->width = (FT_Byte) bitmap->width; |
| 172 | sbit->height = (FT_Byte) bitmap->rows; |
| 173 | sbit->pitch = (FT_Char) bitmap->pitch; |
| 174 | sbit->left = (FT_Char) slot->bitmap_left; |
| 175 | sbit->top = (FT_Char) slot->bitmap_top; |
| 176 | sbit->xadvance = (FT_Char) xadvance; |
| 177 | sbit->yadvance = (FT_Char) yadvance; |
| 178 | sbit->format = (FT_Byte) bitmap->pixel_mode; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 179 | |
| 180 | /* grab the bitmap when possible */ |
| 181 | if ( slot->flags & ft_glyph_own_bitmap ) |
| 182 | { |
| 183 | slot->flags &= ~ft_glyph_own_bitmap; |
| 184 | sbit->buffer = bitmap->buffer; |
| 185 | } |
| 186 | else |
| 187 | { |
| 188 | /* copy the bitmap into a new buffer - ignore error */ |
| 189 | ftc_bitmap_copy( memory, bitmap, sbit ); |
| 190 | } |
| 191 | } |
| 192 | } |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | /* ignore the errors that might have occured there */ |
| 196 | /* we recognize unloaded glyphs with "sbit.buffer == 0" */ |
| 197 | error = 0; |
| 198 | } |
| 199 | |
| 200 | Exit: |
| 201 | if ( error && node ) |
| 202 | { |
| 203 | FREE( node->elements ); |
| 204 | FREE( node ); |
| 205 | } |
| 206 | |
| 207 | *anode = node; |
| 208 | return error; |
| 209 | } |
| 210 | |
| 211 | |
| 212 | /* this function is important because it is both part of */ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 213 | /* a FTC_ChunkSet_Class and a FTC_CacheNode_Class */ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 214 | /* */ |
| 215 | LOCAL_FUNC_X |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 216 | FT_ULong ftc_sbit_chunk_node_size( FTC_ChunkNode node ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 217 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 218 | FT_ULong size; |
| 219 | FTC_ChunkSet cset = node->cset; |
| 220 | FT_UInt count = node->num_elements; |
| 221 | FT_Int pitch; |
| 222 | FTC_SBit sbit = (FTC_SBit)node->elements; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 223 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 224 | size = sizeof (*node); /* the node itself */ |
| 225 | size += cset->element_count * sizeof(FTC_SBitRec); /* the sbit recors */ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 226 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 227 | for ( ; count > 0; count--, sbit++ ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 228 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 229 | if (sbit->buffer) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 230 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 231 | pitch = sbit->pitch; |
| 232 | if (pitch < 0) |
| 233 | pitch = -pitch; |
| 234 | |
| 235 | /* add the size of a given glyph image */ |
| 236 | size += pitch * sbit->height; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 237 | } |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 238 | } |
| 239 | |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 240 | return size; |
| 241 | } |
| 242 | |
| 243 | |
| 244 | /*************************************************************************/ |
| 245 | /*************************************************************************/ |
| 246 | /***** *****/ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 247 | /***** SBIT CHUNK SETS *****/ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 248 | /***** *****/ |
| 249 | /*************************************************************************/ |
| 250 | /*************************************************************************/ |
| 251 | |
| 252 | |
| 253 | LOCAL_FUNC_X |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 254 | FT_Error ftc_sbit_chunk_set_sizes( FTC_ChunkSet cset, |
| 255 | FTC_Image_Desc* desc ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 256 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 257 | FT_Error error; |
| 258 | FT_Face face; |
| 259 | |
| 260 | cset->element_count = FTC_SBITSET_ELEMENT_COUNT; |
| 261 | cset->element_size = sizeof(FTC_SBitRec); |
| 262 | |
| 263 | /* lookup the FT_Face to obtain the number of glyphs */ |
| 264 | error = FTC_Manager_Lookup_Face( cset->manager, |
| 265 | &desc->font, &face ); |
| 266 | if (!error) |
| 267 | cset->element_max = face->num_glyphs; |
| 268 | |
| 269 | return error; |
| 270 | } |
| 271 | |
| 272 | |
| 273 | |
| 274 | LOCAL_FUNC_X |
| 275 | FT_Error ftc_sbit_chunk_set_init( FTC_SBitSet sset, |
| 276 | FTC_Image_Desc* type ) |
| 277 | { |
| 278 | sset->desc = *type; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 279 | return 0; |
| 280 | } |
| 281 | |
| 282 | |
| 283 | LOCAL_FUNC_X |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 284 | FT_Bool ftc_sbit_chunk_set_compare( FTC_SBitSet sset, |
| 285 | FTC_Image_Desc* type ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 286 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 287 | return !memcmp( &sset->desc, type, sizeof ( *type ) ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | |
| 291 | FT_CPLUSPLUS( const FTC_ChunkSet_Class ) ftc_sbit_chunk_set_class = |
| 292 | { |
| 293 | sizeof( FTC_ImageSetRec ), |
| 294 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 295 | (FTC_ChunkSet_InitFunc) ftc_sbit_chunk_set_init, |
| 296 | (FTC_ChunkSet_DoneFunc) 0, |
| 297 | (FTC_ChunkSet_CompareFunc) ftc_sbit_chunk_set_compare, |
| 298 | (FTC_ChunkSet_SizesFunc) ftc_sbit_chunk_set_sizes, |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 299 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 300 | (FTC_ChunkSet_NewNodeFunc) ftc_sbit_chunk_node_new, |
| 301 | (FTC_ChunkSet_SizeNodeFunc) ftc_sbit_chunk_node_size, |
| 302 | (FTC_ChunkSet_DestroyNodeFunc) ftc_sbit_chunk_node_destroy |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 303 | }; |
| 304 | |
| 305 | |
| 306 | /*************************************************************************/ |
| 307 | /*************************************************************************/ |
| 308 | /***** *****/ |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 309 | /***** SBITS CACHE *****/ |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 310 | /***** *****/ |
| 311 | /*************************************************************************/ |
| 312 | /*************************************************************************/ |
| 313 | |
| 314 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 315 | FT_CPLUSPLUS( const FTC_Chunk_Cache_Class ) ftc_sbit_cache_class = |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 316 | { |
| 317 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 318 | sizeof( FTC_SBit_CacheRec ), |
| 319 | (FTC_Cache_InitFunc) FTC_Chunk_Cache_Init, |
| 320 | (FTC_Cache_DoneFunc) FTC_Chunk_Cache_Done |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 321 | }, |
| 322 | (FTC_ChunkSet_Class*) &ftc_sbit_chunk_set_class |
| 323 | }; |
| 324 | |
| 325 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 326 | FT_EXPORT_FUNC( FT_Error ) |
| 327 | FTC_SBit_Cache_New( FTC_Manager manager, |
| 328 | FTC_SBit_Cache* acache ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 329 | { |
| 330 | return FTC_Manager_Register_Cache( |
| 331 | manager, |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 332 | (FTC_Cache_Class*)&ftc_sbit_cache_class, |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 333 | (FTC_Cache*)acache ); |
| 334 | } |
| 335 | |
| 336 | |
| 337 | FT_EXPORT_DEF( FT_Error ) |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 338 | FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache, |
| 339 | FTC_Image_Desc* desc, |
| 340 | FT_UInt gindex, |
| 341 | FTC_SBit *asbit ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 342 | { |
| 343 | FT_Error error; |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 344 | FTC_ChunkSet cset; |
| 345 | FTC_ChunkNode node; |
| 346 | FT_UInt cindex; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 347 | FTC_Manager manager; |
| 348 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 349 | FTC_SBitSet sset; |
| 350 | FTC_SBit sbit; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 351 | |
| 352 | |
| 353 | /* check for valid `desc' delayed to FT_Lru_Lookup() */ |
| 354 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 355 | if ( !cache || !asbit ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 356 | return FT_Err_Invalid_Argument; |
| 357 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 358 | *asbit = 0; |
| 359 | cset = cache->root.last_cset; |
| 360 | sset = (FTC_SBitSet)cset; |
| 361 | if ( !cset || memcmp( &sset->desc, desc, sizeof ( *desc ) ) ) |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 362 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 363 | error = FT_Lru_Lookup( cache->root.csets_lru, |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 364 | (FT_LruKey)desc, |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 365 | (FT_Pointer*)&cset ); |
| 366 | cache->root.last_cset = cset; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 367 | if ( error ) |
| 368 | goto Exit; |
| 369 | } |
| 370 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 371 | error = FTC_ChunkSet_Lookup_Node( cset, gindex, &node, &cindex ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 372 | if ( error ) |
| 373 | goto Exit; |
| 374 | |
| 375 | /* now compress the manager's cache pool if needed */ |
| 376 | manager = cache->root.root.manager; |
| 377 | if ( manager->num_bytes > manager->max_bytes ) |
| 378 | { |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 379 | FTC_ChunkNode_Ref ( node ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 380 | FTC_Manager_Compress( manager ); |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 381 | FTC_ChunkNode_Unref ( node ); |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 382 | } |
| 383 | |
David Turner | ece6379 | 2000-10-28 23:34:45 +0000 | [diff] [blame^] | 384 | sbit = ((FTC_SBit)((FTC_ChunkNode)node)->elements) + cindex; |
| 385 | if (sbit->buffer == 0) |
| 386 | { |
| 387 | /* the glyph was missing, we return a NULL pointer !! */ |
| 388 | sbit = 0; |
| 389 | } |
| 390 | |
| 391 | *asbit = sbit; |
David Turner | 4e4a436 | 2000-10-28 13:17:11 +0000 | [diff] [blame] | 392 | |
| 393 | Exit: |
| 394 | return error; |
| 395 | } |
| 396 | |