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