Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftcsbits.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ftcsbits.c */ 00004 /* */ 00005 /* FreeType sbits manager (body). */ 00006 /* */ 00007 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include <ft2build.h> 00020 #include FT_CACHE_H 00021 #include "ftcsbits.h" 00022 #include FT_INTERNAL_OBJECTS_H 00023 #include FT_INTERNAL_DEBUG_H 00024 #include FT_ERRORS_H 00025 00026 #include "ftccback.h" 00027 #include "ftcerror.h" 00028 00029 #undef FT_COMPONENT 00030 #define FT_COMPONENT trace_cache 00031 00032 00033 /*************************************************************************/ 00034 /*************************************************************************/ 00035 /***** *****/ 00036 /***** SBIT CACHE NODES *****/ 00037 /***** *****/ 00038 /*************************************************************************/ 00039 /*************************************************************************/ 00040 00041 00042 static FT_Error 00043 ftc_sbit_copy_bitmap( FTC_SBit sbit, 00044 FT_Bitmap* bitmap, 00045 FT_Memory memory ) 00046 { 00047 FT_Error error; 00048 FT_Int pitch = bitmap->pitch; 00049 FT_ULong size; 00050 00051 00052 if ( pitch < 0 ) 00053 pitch = -pitch; 00054 00055 size = (FT_ULong)( pitch * bitmap->rows ); 00056 00057 if ( !FT_ALLOC( sbit->buffer, size ) ) 00058 FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); 00059 00060 return error; 00061 } 00062 00063 00064 FT_LOCAL_DEF( void ) 00065 ftc_snode_free( FTC_Node ftcsnode, 00066 FTC_Cache cache ) 00067 { 00068 FTC_SNode snode = (FTC_SNode)ftcsnode; 00069 FTC_SBit sbit = snode->sbits; 00070 FT_UInt count = snode->count; 00071 FT_Memory memory = cache->memory; 00072 00073 00074 for ( ; count > 0; sbit++, count-- ) 00075 FT_FREE( sbit->buffer ); 00076 00077 FTC_GNode_Done( FTC_GNODE( snode ), cache ); 00078 00079 FT_FREE( snode ); 00080 } 00081 00082 00083 FT_LOCAL_DEF( void ) 00084 FTC_SNode_Free( FTC_SNode snode, 00085 FTC_Cache cache ) 00086 { 00087 ftc_snode_free( FTC_NODE( snode ), cache ); 00088 } 00089 00090 00091 /* 00092 * This function tries to load a small bitmap within a given FTC_SNode. 00093 * Note that it returns a non-zero error code _only_ in the case of 00094 * out-of-memory condition. For all other errors (e.g., corresponding 00095 * to a bad font file), this function will mark the sbit as `unavailable' 00096 * and return a value of 0. 00097 * 00098 * You should also read the comment within the @ftc_snode_compare 00099 * function below to see how out-of-memory is handled during a lookup. 00100 */ 00101 static FT_Error 00102 ftc_snode_load( FTC_SNode snode, 00103 FTC_Manager manager, 00104 FT_UInt gindex, 00105 FT_ULong *asize ) 00106 { 00107 FT_Error error; 00108 FTC_GNode gnode = FTC_GNODE( snode ); 00109 FTC_Family family = gnode->family; 00110 FT_Memory memory = manager->memory; 00111 FT_Face face; 00112 FTC_SBit sbit; 00113 FTC_SFamilyClass clazz; 00114 00115 00116 if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count ) 00117 { 00118 FT_ERROR(( "ftc_snode_load: invalid glyph index" )); 00119 return FTC_Err_Invalid_Argument; 00120 } 00121 00122 sbit = snode->sbits + ( gindex - gnode->gindex ); 00123 clazz = (FTC_SFamilyClass)family->clazz; 00124 00125 sbit->buffer = 0; 00126 00127 error = clazz->family_load_glyph( family, gindex, manager, &face ); 00128 if ( error ) 00129 goto BadGlyph; 00130 00131 { 00132 FT_Int temp; 00133 FT_GlyphSlot slot = face->glyph; 00134 FT_Bitmap* bitmap = &slot->bitmap; 00135 FT_Pos xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */ 00136 00137 00138 if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) 00139 { 00140 FT_TRACE0(( "ftc_snode_load:" 00141 " glyph loaded didn't return a bitmap\n" )); 00142 goto BadGlyph; 00143 } 00144 00145 /* Check that our values fit into 8-bit containers! */ 00146 /* If this is not the case, our bitmap is too large */ 00147 /* and we will leave it as `missing' with sbit.buffer = 0 */ 00148 00149 #define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) 00150 #define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) 00151 00152 /* horizontal advance in pixels */ 00153 xadvance = ( slot->advance.x + 32 ) >> 6; 00154 yadvance = ( slot->advance.y + 32 ) >> 6; 00155 00156 if ( !CHECK_BYTE( bitmap->rows ) || 00157 !CHECK_BYTE( bitmap->width ) || 00158 !CHECK_CHAR( bitmap->pitch ) || 00159 !CHECK_CHAR( slot->bitmap_left ) || 00160 !CHECK_CHAR( slot->bitmap_top ) || 00161 !CHECK_CHAR( xadvance ) || 00162 !CHECK_CHAR( yadvance ) ) 00163 { 00164 FT_TRACE2(( "ftc_snode_load:" 00165 " glyph too large for small bitmap cache\n")); 00166 goto BadGlyph; 00167 } 00168 00169 sbit->width = (FT_Byte)bitmap->width; 00170 sbit->height = (FT_Byte)bitmap->rows; 00171 sbit->pitch = (FT_Char)bitmap->pitch; 00172 sbit->left = (FT_Char)slot->bitmap_left; 00173 sbit->top = (FT_Char)slot->bitmap_top; 00174 sbit->xadvance = (FT_Char)xadvance; 00175 sbit->yadvance = (FT_Char)yadvance; 00176 sbit->format = (FT_Byte)bitmap->pixel_mode; 00177 sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); 00178 00179 /* copy the bitmap into a new buffer -- ignore error */ 00180 error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); 00181 00182 /* now, compute size */ 00183 if ( asize ) 00184 *asize = FT_ABS( sbit->pitch ) * sbit->height; 00185 00186 } /* glyph loading successful */ 00187 00188 /* ignore the errors that might have occurred -- */ 00189 /* we mark unloaded glyphs with `sbit.buffer == 0' */ 00190 /* and `width == 255', `height == 0' */ 00191 /* */ 00192 if ( error && error != FTC_Err_Out_Of_Memory ) 00193 { 00194 BadGlyph: 00195 sbit->width = 255; 00196 sbit->height = 0; 00197 sbit->buffer = NULL; 00198 error = FTC_Err_Ok; 00199 if ( asize ) 00200 *asize = 0; 00201 } 00202 00203 return error; 00204 } 00205 00206 00207 FT_LOCAL_DEF( FT_Error ) 00208 FTC_SNode_New( FTC_SNode *psnode, 00209 FTC_GQuery gquery, 00210 FTC_Cache cache ) 00211 { 00212 FT_Memory memory = cache->memory; 00213 FT_Error error; 00214 FTC_SNode snode = NULL; 00215 FT_UInt gindex = gquery->gindex; 00216 FTC_Family family = gquery->family; 00217 00218 FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache ); 00219 FT_UInt total; 00220 00221 00222 total = clazz->family_get_count( family, cache->manager ); 00223 if ( total == 0 || gindex >= total ) 00224 { 00225 error = FTC_Err_Invalid_Argument; 00226 goto Exit; 00227 } 00228 00229 if ( !FT_NEW( snode ) ) 00230 { 00231 FT_UInt count, start; 00232 00233 00234 start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE ); 00235 count = total - start; 00236 if ( count > FTC_SBIT_ITEMS_PER_NODE ) 00237 count = FTC_SBIT_ITEMS_PER_NODE; 00238 00239 FTC_GNode_Init( FTC_GNODE( snode ), start, family ); 00240 00241 snode->count = count; 00242 00243 error = ftc_snode_load( snode, 00244 cache->manager, 00245 gindex, 00246 NULL ); 00247 if ( error ) 00248 { 00249 FTC_SNode_Free( snode, cache ); 00250 snode = NULL; 00251 } 00252 } 00253 00254 Exit: 00255 *psnode = snode; 00256 return error; 00257 } 00258 00259 00260 FT_LOCAL_DEF( FT_Error ) 00261 ftc_snode_new( FTC_Node *ftcpsnode, 00262 FT_Pointer ftcgquery, 00263 FTC_Cache cache ) 00264 { 00265 FTC_SNode *psnode = (FTC_SNode*)ftcpsnode; 00266 FTC_GQuery gquery = (FTC_GQuery)ftcgquery; 00267 00268 00269 return FTC_SNode_New( psnode, gquery, cache ); 00270 } 00271 00272 00273 FT_LOCAL_DEF( FT_Offset ) 00274 ftc_snode_weight( FTC_Node ftcsnode, 00275 FTC_Cache cache ) 00276 { 00277 FTC_SNode snode = (FTC_SNode)ftcsnode; 00278 FT_UInt count = snode->count; 00279 FTC_SBit sbit = snode->sbits; 00280 FT_Int pitch; 00281 FT_Offset size; 00282 00283 FT_UNUSED( cache ); 00284 00285 00286 FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE ); 00287 00288 /* the node itself */ 00289 size = sizeof ( *snode ); 00290 00291 for ( ; count > 0; count--, sbit++ ) 00292 { 00293 if ( sbit->buffer ) 00294 { 00295 pitch = sbit->pitch; 00296 if ( pitch < 0 ) 00297 pitch = -pitch; 00298 00299 /* add the size of a given glyph image */ 00300 size += pitch * sbit->height; 00301 } 00302 } 00303 00304 return size; 00305 } 00306 00307 00308 #if 0 00309 00310 FT_LOCAL_DEF( FT_Offset ) 00311 FTC_SNode_Weight( FTC_SNode snode ) 00312 { 00313 return ftc_snode_weight( FTC_NODE( snode ), NULL ); 00314 } 00315 00316 #endif /* 0 */ 00317 00318 00319 FT_LOCAL_DEF( FT_Bool ) 00320 ftc_snode_compare( FTC_Node ftcsnode, 00321 FT_Pointer ftcgquery, 00322 FTC_Cache cache ) 00323 { 00324 FTC_SNode snode = (FTC_SNode)ftcsnode; 00325 FTC_GQuery gquery = (FTC_GQuery)ftcgquery; 00326 FTC_GNode gnode = FTC_GNODE( snode ); 00327 FT_UInt gindex = gquery->gindex; 00328 FT_Bool result; 00329 00330 00331 result = FT_BOOL( gnode->family == gquery->family && 00332 (FT_UInt)( gindex - gnode->gindex ) < snode->count ); 00333 if ( result ) 00334 { 00335 /* check if we need to load the glyph bitmap now */ 00336 FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex ); 00337 00338 00339 /* 00340 * The following code illustrates what to do when you want to 00341 * perform operations that may fail within a lookup function. 00342 * 00343 * Here, we want to load a small bitmap on-demand; we thus 00344 * need to call the `ftc_snode_load' function which may return 00345 * a non-zero error code only when we are out of memory (OOM). 00346 * 00347 * The correct thing to do is to use @FTC_CACHE_TRYLOOP and 00348 * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop 00349 * that is capable of flushing the cache incrementally when 00350 * an OOM errors occur. 00351 * 00352 * However, we need to `lock' the node before this operation to 00353 * prevent it from being flushed within the loop. 00354 * 00355 * When we exit the loop, we unlock the node, then check the `error' 00356 * variable. If it is non-zero, this means that the cache was 00357 * completely flushed and that no usable memory was found to load 00358 * the bitmap. 00359 * 00360 * We then prefer to return a value of 0 (i.e., NO MATCH). This 00361 * ensures that the caller will try to allocate a new node. 00362 * This operation consequently _fail_ and the lookup function 00363 * returns the appropriate OOM error code. 00364 * 00365 * Note that `buffer == NULL && width == 255' is a hack used to 00366 * tag `unavailable' bitmaps in the array. We should never try 00367 * to load these. 00368 * 00369 */ 00370 00371 if ( sbit->buffer == NULL && sbit->width != 255 ) 00372 { 00373 FT_ULong size; 00374 FT_Error error; 00375 00376 00377 ftcsnode->ref_count++; /* lock node to prevent flushing */ 00378 /* in retry loop */ 00379 00380 FTC_CACHE_TRYLOOP( cache ) 00381 { 00382 error = ftc_snode_load( snode, cache->manager, gindex, &size ); 00383 } 00384 FTC_CACHE_TRYLOOP_END(); 00385 00386 ftcsnode->ref_count--; /* unlock the node */ 00387 00388 if ( error ) 00389 result = 0; 00390 else 00391 cache->manager->cur_weight += size; 00392 } 00393 } 00394 00395 return result; 00396 } 00397 00398 00399 FT_LOCAL_DEF( FT_Bool ) 00400 FTC_SNode_Compare( FTC_SNode snode, 00401 FTC_GQuery gquery, 00402 FTC_Cache cache ) 00403 { 00404 return ftc_snode_compare( FTC_NODE( snode ), gquery, cache ); 00405 } 00406 00407 00408 /* END */ Generated on Sat May 26 2012 04:32:40 for ReactOS by
1.7.6.1
|