ftcsbits.c revision a40b1b64a091cc7f981d2c471e2fef64a6ace77f
1/***************************************************************************/ 2/* */ 3/* ftcsbits.c */ 4/* */ 5/* FreeType sbits manager (body). */ 6/* */ 7/* Copyright 2000-2001, 2002, 2003 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_INTERNAL_SBITS_H 22#include FT_INTERNAL_OBJECTS_H 23#include FT_INTERNAL_DEBUG_H 24#include FT_ERRORS_H 25 26#include "ftcerror.h" 27 28 29 30 /*************************************************************************/ 31 /*************************************************************************/ 32 /***** *****/ 33 /***** SBIT CACHE NODES *****/ 34 /***** *****/ 35 /*************************************************************************/ 36 /*************************************************************************/ 37 38 39 static FT_Error 40 ftc_sbit_copy_bitmap( FTC_SBit sbit, 41 FT_Bitmap* bitmap, 42 FT_Memory memory ) 43 { 44 FT_Error error; 45 FT_Int pitch = bitmap->pitch; 46 FT_ULong size; 47 48 49 if ( pitch < 0 ) 50 pitch = -pitch; 51 52 size = (FT_ULong)( pitch * bitmap->rows ); 53 54 if ( !FT_ALLOC( sbit->buffer, size ) ) 55 FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); 56 57 return error; 58 } 59 60 61 FT_EXPORT_DEF( void ) 62 FTC_SNode_Free( FTC_SNode snode, 63 FTC_Cache cache ) 64 { 65 FTC_SBit sbit = snode->sbits; 66 FT_UInt count = snode->count; 67 FT_Memory memory = cache->memory; 68 69 70 for ( ; count > 0; sbit++, count-- ) 71 FT_FREE( sbit->buffer ); 72 73 FTC_GNode_Done( FTC_GNODE( snode ), cache ); 74 75 FT_FREE( snode ); 76 } 77 78 79 static FT_Error 80 ftc_snode_load( FTC_SNode snode, 81 FTC_Manager manager, 82 FT_UInt gindex, 83 FT_ULong *asize ) 84 { 85 FT_Error error; 86 FTC_GNode gnode = FTC_GNODE( snode ); 87 FTC_Family family = gnode->family; 88 FT_Memory memory = manager->memory; 89 FT_Face face; 90 FTC_SBit sbit; 91 FTC_SFamilyClass clazz; 92 93 94 if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count ) 95 { 96 FT_ERROR(( "ftc_snode_load: invalid glyph index" )); 97 return FTC_Err_Invalid_Argument; 98 } 99 100 sbit = snode->sbits + ( gindex - gnode->gindex ); 101 clazz = (FTC_SFamilyClass) family->clazz; 102 103 sbit->buffer = 0; 104 105 error = clazz->family_load_glyph( family, gindex, manager, &face ); 106 if ( error ) 107 goto BadGlyph; 108 109 { 110 FT_Int temp; 111 FT_GlyphSlot slot = face->glyph; 112 FT_Bitmap* bitmap = &slot->bitmap; 113 FT_Int xadvance, yadvance; 114 115 if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) 116 { 117 FT_ERROR(( "%s: glyph loaded didn't returned a bitmap !!\n", 118 "ftc_snode_load" )); 119 goto BadGlyph; 120 } 121 122 /* check that our values fit into 8-bit containers! */ 123 /* If this is not the case, our bitmap is too large */ 124 /* and we will leave it as `missing' with sbit.buffer = 0 */ 125 126#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) 127#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) 128 129 /* horizontal advance in pixels */ 130 xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6; 131 yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6; 132 133 if ( !CHECK_BYTE( bitmap->rows ) || 134 !CHECK_BYTE( bitmap->width ) || 135 !CHECK_CHAR( bitmap->pitch ) || 136 !CHECK_CHAR( slot->bitmap_left ) || 137 !CHECK_CHAR( slot->bitmap_top ) || 138 !CHECK_CHAR( xadvance ) || 139 !CHECK_CHAR( yadvance ) ) 140 goto BadGlyph; 141 142 sbit->width = (FT_Byte)bitmap->width; 143 sbit->height = (FT_Byte)bitmap->rows; 144 sbit->pitch = (FT_Char)bitmap->pitch; 145 sbit->left = (FT_Char)slot->bitmap_left; 146 sbit->top = (FT_Char)slot->bitmap_top; 147 sbit->xadvance = (FT_Char)xadvance; 148 sbit->yadvance = (FT_Char)yadvance; 149 sbit->format = (FT_Byte)bitmap->pixel_mode; 150 sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); 151 152 /* copy the bitmap into a new buffer -- ignore error */ 153 error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); 154 155 /* now, compute size */ 156 if ( asize ) 157 *asize = ABS( sbit->pitch ) * sbit->height; 158 159 } /* glyph loading successful */ 160 161 /* ignore the errors that might have occurred -- */ 162 /* we mark unloaded glyphs with `sbit.buffer == 0' */ 163 /* and 'width == 255', 'height == 0' */ 164 /* */ 165 if ( error && error != FTC_Err_Out_Of_Memory ) 166 { 167 BadGlyph: 168 sbit->width = 255; 169 sbit->height = 0; 170 sbit->buffer = NULL; 171 error = 0; 172 } 173 174 return error; 175 } 176 177 178 FT_EXPORT_DEF( FT_Error ) 179 FTC_SNode_New( FTC_SNode *psnode, 180 FTC_GQuery gquery, 181 FTC_Cache cache ) 182 { 183 FT_Memory memory = cache->memory; 184 FT_Error error; 185 FTC_SNode snode = NULL; 186 FT_UInt gindex = gquery->gindex; 187 FTC_Family family = gquery->family; 188 189 FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache ); 190 FT_UInt total; 191 192 total = clazz->family_get_count( family, cache->manager ); 193 if ( total == 0 || gindex >= total ) 194 { 195 error = FT_Err_Invalid_Argument; 196 goto Exit; 197 } 198 199 if ( !FT_NEW( snode ) ) 200 { 201 FT_UInt count, start; 202 203 start = gindex - (gindex % FTC_SBIT_ITEMS_PER_NODE); 204 count = total - start; 205 if ( count > FTC_SBIT_ITEMS_PER_NODE ) 206 count = FTC_SBIT_ITEMS_PER_NODE; 207 208 FTC_GNode_Init( FTC_GNODE( snode ), start, family ); 209 210 snode->count = count; 211 212 error = ftc_snode_load( snode, 213 cache->manager, 214 gindex, 215 NULL ); 216 if ( error ) 217 { 218 FTC_SNode_Free( snode, cache ); 219 snode = NULL; 220 } 221 } 222 223 Exit: 224 *psnode = snode; 225 return error; 226 } 227 228 229 FT_EXPORT_DEF( FT_ULong ) 230 FTC_SNode_Weight( FTC_SNode snode ) 231 { 232 FT_UInt count = snode->count; 233 FTC_SBit sbit = snode->sbits; 234 FT_Int pitch; 235 FT_ULong size; 236 237 238 FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE ); 239 240 /* the node itself */ 241 size = sizeof ( *snode ); 242 243 for ( ; count > 0; count--, sbit++ ) 244 { 245 if ( sbit->buffer ) 246 { 247 pitch = sbit->pitch; 248 if ( pitch < 0 ) 249 pitch = -pitch; 250 251 /* add the size of a given glyph image */ 252 size += pitch * sbit->height; 253 } 254 } 255 256 return size; 257 } 258 259 260 FT_EXPORT_DEF( FT_Bool ) 261 FTC_SNode_Compare( FTC_SNode snode, 262 FTC_GQuery gquery, 263 FTC_Cache cache ) 264 { 265 FTC_GNode gnode = FTC_GNODE( snode ); 266 FT_UInt gindex = gquery->gindex; 267 FT_Bool result; 268 269 result = FT_BOOL( gnode->family == gquery->family && 270 (FT_UInt)(gindex - gnode->gindex) < snode->count ); 271 if ( result ) 272 { 273 /* check if we need to load the glyph bitmap now */ 274 FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex ); 275 276 277 if ( sbit->buffer == NULL && sbit->width != 255 ) 278 { 279 FT_ULong size; 280 281 282 if ( !ftc_snode_load( snode, cache->manager, 283 gindex, &size ) ) 284 { 285 cache->manager->cur_weight += size; 286 } 287 } 288 } 289 290 return result; 291 } 292 293/* END */ 294