00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00093
00094
00095
00096
00097
00098
00099
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;
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
00146
00147
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
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 goto BadGlyph;
00164
00165 sbit->width = (FT_Byte)bitmap->width;
00166 sbit->height = (FT_Byte)bitmap->rows;
00167 sbit->pitch = (FT_Char)bitmap->pitch;
00168 sbit->left = (FT_Char)slot->bitmap_left;
00169 sbit->top = (FT_Char)slot->bitmap_top;
00170 sbit->xadvance = (FT_Char)xadvance;
00171 sbit->yadvance = (FT_Char)yadvance;
00172 sbit->format = (FT_Byte)bitmap->pixel_mode;
00173 sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
00174
00175
00176 error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
00177
00178
00179 if ( asize )
00180 *asize = FT_ABS( sbit->pitch ) * sbit->height;
00181
00182 }
00183
00184
00185
00186
00187
00188 if ( error && error != FTC_Err_Out_Of_Memory )
00189 {
00190 BadGlyph:
00191 sbit->width = 255;
00192 sbit->height = 0;
00193 sbit->buffer = NULL;
00194 error = 0;
00195 if ( asize )
00196 *asize = 0;
00197 }
00198
00199 return error;
00200 }
00201
00202
00203 FT_LOCAL_DEF( FT_Error )
00204 FTC_SNode_New( FTC_SNode *psnode,
00205 FTC_GQuery gquery,
00206 FTC_Cache cache )
00207 {
00208 FT_Memory memory = cache->memory;
00209 FT_Error error;
00210 FTC_SNode snode = NULL;
00211 FT_UInt gindex = gquery->gindex;
00212 FTC_Family family = gquery->family;
00213
00214 FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
00215 FT_UInt total;
00216
00217
00218 total = clazz->family_get_count( family, cache->manager );
00219 if ( total == 0 || gindex >= total )
00220 {
00221 error = FT_Err_Invalid_Argument;
00222 goto Exit;
00223 }
00224
00225 if ( !FT_NEW( snode ) )
00226 {
00227 FT_UInt count, start;
00228
00229
00230 start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
00231 count = total - start;
00232 if ( count > FTC_SBIT_ITEMS_PER_NODE )
00233 count = FTC_SBIT_ITEMS_PER_NODE;
00234
00235 FTC_GNode_Init( FTC_GNODE( snode ), start, family );
00236
00237 snode->count = count;
00238
00239 error = ftc_snode_load( snode,
00240 cache->manager,
00241 gindex,
00242 NULL );
00243 if ( error )
00244 {
00245 FTC_SNode_Free( snode, cache );
00246 snode = NULL;
00247 }
00248 }
00249
00250 Exit:
00251 *psnode = snode;
00252 return error;
00253 }
00254
00255
00256 FT_LOCAL_DEF( FT_Error )
00257 ftc_snode_new( FTC_Node *ftcpsnode,
00258 FT_Pointer ftcgquery,
00259 FTC_Cache cache )
00260 {
00261 FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;
00262 FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
00263
00264
00265 return FTC_SNode_New( psnode, gquery, cache );
00266 }
00267
00268
00269 FT_LOCAL_DEF( FT_Offset )
00270 ftc_snode_weight( FTC_Node ftcsnode,
00271 FTC_Cache cache )
00272 {
00273 FTC_SNode snode = (FTC_SNode)ftcsnode;
00274 FT_UInt count = snode->count;
00275 FTC_SBit sbit = snode->sbits;
00276 FT_Int pitch;
00277 FT_Offset size;
00278
00279 FT_UNUSED( cache );
00280
00281
00282 FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
00283
00284
00285 size = sizeof ( *snode );
00286
00287 for ( ; count > 0; count--, sbit++ )
00288 {
00289 if ( sbit->buffer )
00290 {
00291 pitch = sbit->pitch;
00292 if ( pitch < 0 )
00293 pitch = -pitch;
00294
00295
00296 size += pitch * sbit->height;
00297 }
00298 }
00299
00300 return size;
00301 }
00302
00303
00304 #if 0
00305
00306 FT_LOCAL_DEF( FT_Offset )
00307 FTC_SNode_Weight( FTC_SNode snode )
00308 {
00309 return ftc_snode_weight( FTC_NODE( snode ), NULL );
00310 }
00311
00312 #endif
00313
00314
00315 FT_LOCAL_DEF( FT_Bool )
00316 ftc_snode_compare( FTC_Node ftcsnode,
00317 FT_Pointer ftcgquery,
00318 FTC_Cache cache )
00319 {
00320 FTC_SNode snode = (FTC_SNode)ftcsnode;
00321 FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
00322 FTC_GNode gnode = FTC_GNODE( snode );
00323 FT_UInt gindex = gquery->gindex;
00324 FT_Bool result;
00325
00326
00327 result = FT_BOOL( gnode->family == gquery->family &&
00328 (FT_UInt)( gindex - gnode->gindex ) < snode->count );
00329 if ( result )
00330 {
00331
00332 FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 if ( sbit->buffer == NULL && sbit->width != 255 )
00368 {
00369 FT_ULong size;
00370 FT_Error error;
00371
00372
00373 ftcsnode->ref_count++;
00374
00375
00376 FTC_CACHE_TRYLOOP( cache )
00377 {
00378 error = ftc_snode_load( snode, cache->manager, gindex, &size );
00379 }
00380 FTC_CACHE_TRYLOOP_END();
00381
00382 ftcsnode->ref_count--;
00383
00384 if ( error )
00385 result = 0;
00386 else
00387 cache->manager->cur_weight += size;
00388 }
00389 }
00390
00391 return result;
00392 }
00393
00394
00395 FT_LOCAL_DEF( FT_Bool )
00396 FTC_SNode_Compare( FTC_SNode snode,
00397 FTC_GQuery gquery,
00398 FTC_Cache cache )
00399 {
00400 return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );
00401 }
00402
00403
00404