1 /***************************************************************************/ 2 /* */ 3 /* ftcimage.c */ 4 /* */ 5 /* FreeType Image cache (body). */ 6 /* */ 7 /* Copyright 2000-2001 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_CACHE_H 21 #include FT_CACHE_IMAGE_H 22 #include FT_CACHE_INTERNAL_GLYPH_H 23 #include FT_INTERNAL_MEMORY_H 24 25 #include "ftcerror.h" 26 27 28 /* the FT_Glyph image node type */ 29 typedef struct FTC_ImageNodeRec_ 30 { 31 FTC_GlyphNodeRec gnode; 32 FT_Glyph glyph; 33 34 } FTC_ImageNodeRec, *FTC_ImageNode; 35 36 37 #define FTC_IMAGE_NODE( x ) ( (FTC_ImageNode)( x ) ) 38 #define FTC_IMAGE_NODE_GINDEX( x ) FTC_GLYPH_NODE_GINDEX( x ) 39 40 41 /* the glyph image query */ 42 typedef struct FTC_ImageQueryRec_ 43 { 44 FTC_GlyphQueryRec gquery; 45 FTC_ImageTypeRec type; 46 47 } FTC_ImageQueryRec, *FTC_ImageQuery; 48 49 50 #define FTC_IMAGE_QUERY( x ) ( (FTC_ImageQuery)( x ) ) 51 52 53 /* the glyph image set type */ 54 typedef struct FTC_ImageFamilyRec_ 55 { 56 FTC_GlyphFamilyRec gfam; 57 FTC_ImageTypeRec type; 58 59 } FTC_ImageFamilyRec, *FTC_ImageFamily; 60 61 62 #define FTC_IMAGE_FAMILY( x ) ( (FTC_ImageFamily)( x ) ) 63 #define FTC_IMAGE_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &(x)->gfam ) 64 65 66 /*************************************************************************/ 67 /*************************************************************************/ 68 /***** *****/ 69 /***** GLYPH IMAGE NODES *****/ 70 /***** *****/ 71 /*************************************************************************/ 72 /*************************************************************************/ 73 74 75 /* finalize a given glyph image node */ 76 FT_CALLBACK_DEF( void ) ftc_image_node_done(FTC_ImageNode inode,FTC_Cache cache)77 ftc_image_node_done( FTC_ImageNode inode, 78 FTC_Cache cache ) 79 { 80 if ( inode->glyph ) 81 { 82 FT_Done_Glyph( inode->glyph ); 83 inode->glyph = NULL; 84 } 85 86 ftc_glyph_node_done( FTC_GLYPH_NODE( inode ), cache ); 87 } 88 89 90 /* initialize a new glyph image node */ 91 FT_CALLBACK_DEF( FT_Error ) ftc_image_node_init(FTC_ImageNode inode,FTC_GlyphQuery gquery,FTC_Cache cache)92 ftc_image_node_init( FTC_ImageNode inode, 93 FTC_GlyphQuery gquery, 94 FTC_Cache cache ) 95 { 96 FTC_ImageFamily ifam = FTC_IMAGE_FAMILY( gquery->query.family ); 97 FT_Error error; 98 FT_Face face; 99 FT_Size size; 100 101 102 /* initialize its inner fields */ 103 ftc_glyph_node_init( FTC_GLYPH_NODE( inode ), 104 gquery->gindex, 105 FTC_GLYPH_FAMILY( ifam ) ); 106 107 /* we will now load the glyph image */ 108 error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager, 109 &ifam->type.font, 110 &face, &size ); 111 if ( !error ) 112 { 113 FT_UInt gindex = FTC_GLYPH_NODE_GINDEX( inode ); 114 115 116 error = FT_Load_Glyph( face, gindex, ifam->type.flags ); 117 if ( !error ) 118 { 119 if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || 120 face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) 121 { 122 /* ok, copy it */ 123 FT_Glyph glyph; 124 125 126 error = FT_Get_Glyph( face->glyph, &glyph ); 127 if ( !error ) 128 { 129 inode->glyph = glyph; 130 goto Exit; 131 } 132 } 133 else 134 error = FTC_Err_Invalid_Argument; 135 } 136 } 137 138 /* in case of error */ 139 ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache ); 140 141 Exit: 142 return error; 143 } 144 145 146 FT_CALLBACK_DEF( FT_ULong ) ftc_image_node_weight(FTC_ImageNode inode)147 ftc_image_node_weight( FTC_ImageNode inode ) 148 { 149 FT_ULong size = 0; 150 FT_Glyph glyph = inode->glyph; 151 152 153 switch ( glyph->format ) 154 { 155 case FT_GLYPH_FORMAT_BITMAP: 156 { 157 FT_BitmapGlyph bitg; 158 159 160 bitg = (FT_BitmapGlyph)glyph; 161 size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) + 162 sizeof ( *bitg ); 163 } 164 break; 165 166 case FT_GLYPH_FORMAT_OUTLINE: 167 { 168 FT_OutlineGlyph outg; 169 170 171 outg = (FT_OutlineGlyph)glyph; 172 size = outg->outline.n_points * 173 ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) + 174 outg->outline.n_contours * sizeof ( FT_Short ) + 175 sizeof ( *outg ); 176 } 177 break; 178 179 default: 180 ; 181 } 182 183 size += sizeof ( *inode ); 184 return size; 185 } 186 187 188 /*************************************************************************/ 189 /*************************************************************************/ 190 /***** *****/ 191 /***** GLYPH IMAGE SETS *****/ 192 /***** *****/ 193 /*************************************************************************/ 194 /*************************************************************************/ 195 196 197 FT_CALLBACK_DEF( FT_Error ) ftc_image_family_init(FTC_ImageFamily ifam,FTC_ImageQuery iquery,FTC_Cache cache)198 ftc_image_family_init( FTC_ImageFamily ifam, 199 FTC_ImageQuery iquery, 200 FTC_Cache cache ) 201 { 202 FTC_Manager manager = cache->manager; 203 FT_Error error; 204 FT_Face face; 205 206 207 ifam->type = iquery->type; 208 209 /* we need to compute "iquery.item_total" now */ 210 error = FTC_Manager_Lookup_Face( manager, 211 iquery->type.font.face_id, 212 &face ); 213 if ( !error ) 214 { 215 error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( ifam ), 216 FTC_IMAGE_TYPE_HASH( &ifam->type ), 217 1, 218 face->num_glyphs, 219 FTC_GLYPH_QUERY( iquery ), 220 cache ); 221 } 222 223 return error; 224 } 225 226 227 FT_CALLBACK_DEF( FT_Bool ) ftc_image_family_compare(FTC_ImageFamily ifam,FTC_ImageQuery iquery)228 ftc_image_family_compare( FTC_ImageFamily ifam, 229 FTC_ImageQuery iquery ) 230 { 231 FT_Bool result; 232 233 234 result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) ); 235 if ( result ) 236 FTC_GLYPH_FAMILY_FOUND( ifam, iquery ); 237 238 return result; 239 } 240 241 242 /*************************************************************************/ 243 /*************************************************************************/ 244 /***** *****/ 245 /***** GLYPH IMAGE CACHE *****/ 246 /***** *****/ 247 /*************************************************************************/ 248 /*************************************************************************/ 249 250 251 252 FT_CALLBACK_TABLE_DEF 253 const FTC_Cache_ClassRec ftc_image_cache_class = 254 { 255 sizeof ( FTC_CacheRec ), 256 (FTC_Cache_InitFunc) ftc_cache_init, 257 (FTC_Cache_ClearFunc)ftc_cache_clear, 258 (FTC_Cache_DoneFunc) ftc_cache_done, 259 260 sizeof ( FTC_ImageFamilyRec ), 261 (FTC_Family_InitFunc) ftc_image_family_init, 262 (FTC_Family_CompareFunc)ftc_image_family_compare, 263 (FTC_Family_DoneFunc) ftc_glyph_family_done, 264 265 sizeof ( FTC_ImageNodeRec ), 266 (FTC_Node_InitFunc) ftc_image_node_init, 267 (FTC_Node_WeightFunc) ftc_image_node_weight, 268 (FTC_Node_CompareFunc)ftc_glyph_node_compare, 269 (FTC_Node_DoneFunc) ftc_image_node_done 270 }; 271 272 273 /* documentation is in ftcimage.h */ 274 275 FT_EXPORT_DEF( FT_Error ) FTC_ImageCache_New(FTC_Manager manager,FTC_ImageCache * acache)276 FTC_ImageCache_New( FTC_Manager manager, 277 FTC_ImageCache *acache ) 278 { 279 return FTC_Manager_Register_Cache( 280 manager, 281 (FTC_Cache_Class)&ftc_image_cache_class, 282 FTC_CACHE_P( acache ) ); 283 } 284 285 286 /* documentation is in ftcimage.h */ 287 288 FT_EXPORT_DEF( FT_Error ) FTC_ImageCache_Lookup(FTC_ImageCache cache,FTC_ImageType type,FT_UInt gindex,FT_Glyph * aglyph,FTC_Node * anode)289 FTC_ImageCache_Lookup( FTC_ImageCache cache, 290 FTC_ImageType type, 291 FT_UInt gindex, 292 FT_Glyph *aglyph, 293 FTC_Node *anode ) 294 { 295 FTC_ImageQueryRec iquery; 296 FTC_ImageNode node; 297 FT_Error error; 298 299 300 /* some argument checks are delayed to ftc_cache_lookup */ 301 if ( !aglyph ) 302 return FTC_Err_Invalid_Argument; 303 304 if ( anode ) 305 *anode = NULL; 306 307 iquery.gquery.gindex = gindex; 308 iquery.type = *type; 309 310 error = ftc_cache_lookup( FTC_CACHE( cache ), 311 FTC_QUERY( &iquery ), 312 (FTC_Node*)&node ); 313 if ( !error ) 314 { 315 *aglyph = node->glyph; 316 317 if ( anode ) 318 { 319 *anode = (FTC_Node)node; 320 FTC_NODE( node )->ref_count++; 321 } 322 } 323 324 return error; 325 } 326 327 328 /* backwards-compatibility functions */ 329 330 FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_New(FTC_Manager manager,FTC_Image_Cache * acache)331 FTC_Image_Cache_New( FTC_Manager manager, 332 FTC_Image_Cache *acache ) 333 { 334 return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache ); 335 } 336 337 338 FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_Lookup(FTC_Image_Cache icache,FTC_Image_Desc * desc,FT_UInt gindex,FT_Glyph * aglyph)339 FTC_Image_Cache_Lookup( FTC_Image_Cache icache, 340 FTC_Image_Desc* desc, 341 FT_UInt gindex, 342 FT_Glyph *aglyph ) 343 { 344 FTC_ImageTypeRec type0; 345 346 347 if ( !desc ) 348 return FTC_Err_Invalid_Argument; 349 350 type0.font = desc->font; 351 352 /* convert image type flags to load flags */ 353 { 354 FT_UInt load_flags = FT_LOAD_DEFAULT; 355 FT_UInt type = desc->image_type; 356 357 358 /* determine load flags, depending on the font description's */ 359 /* image type */ 360 361 if ( ftc_image_format( type ) == ftc_image_format_bitmap ) 362 { 363 if ( type & ftc_image_flag_monochrome ) 364 load_flags |= FT_LOAD_MONOCHROME; 365 366 /* disable embedded bitmaps loading if necessary */ 367 if ( type & ftc_image_flag_no_sbits ) 368 load_flags |= FT_LOAD_NO_BITMAP; 369 } 370 else 371 { 372 /* we want an outline, don't load embedded bitmaps */ 373 load_flags |= FT_LOAD_NO_BITMAP; 374 375 if ( type & ftc_image_flag_unscaled ) 376 load_flags |= FT_LOAD_NO_SCALE; 377 } 378 379 /* always render glyphs to bitmaps */ 380 load_flags |= FT_LOAD_RENDER; 381 382 if ( type & ftc_image_flag_unhinted ) 383 load_flags |= FT_LOAD_NO_HINTING; 384 385 if ( type & ftc_image_flag_autohinted ) 386 load_flags |= FT_LOAD_FORCE_AUTOHINT; 387 388 type0.flags = load_flags; 389 } 390 391 return FTC_ImageCache_Lookup( (FTC_ImageCache)icache, 392 &type0, 393 gindex, 394 aglyph, 395 NULL ); 396 } 397 398 399 /* END */ 400