ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftcsbits.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.