summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/cache/ftcsbits.c
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/3rdparty/freetype/src/cache/ftcsbits.c
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/3rdparty/freetype/src/cache/ftcsbits.c')
-rw-r--r--src/3rdparty/freetype/src/cache/ftcsbits.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/src/3rdparty/freetype/src/cache/ftcsbits.c b/src/3rdparty/freetype/src/cache/ftcsbits.c
new file mode 100644
index 0000000000..72f139d565
--- /dev/null
+++ b/src/3rdparty/freetype/src/cache/ftcsbits.c
@@ -0,0 +1,401 @@
+/***************************************************************************/
+/* */
+/* ftcsbits.c */
+/* */
+/* FreeType sbits manager (body). */
+/* */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcsbits.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_ERRORS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** SBIT CACHE NODES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static FT_Error
+ ftc_sbit_copy_bitmap( FTC_SBit sbit,
+ FT_Bitmap* bitmap,
+ FT_Memory memory )
+ {
+ FT_Error error;
+ FT_Int pitch = bitmap->pitch;
+ FT_ULong size;
+
+
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ size = (FT_ULong)( pitch * bitmap->rows );
+
+ if ( !FT_ALLOC( sbit->buffer, size ) )
+ FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ ftc_snode_free( FTC_Node ftcsnode,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FTC_SBit sbit = snode->sbits;
+ FT_UInt count = snode->count;
+ FT_Memory memory = cache->memory;
+
+
+ for ( ; count > 0; sbit++, count-- )
+ FT_FREE( sbit->buffer );
+
+ FTC_GNode_Done( FTC_GNODE( snode ), cache );
+
+ FT_FREE( snode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_SNode_Free( FTC_SNode snode,
+ FTC_Cache cache )
+ {
+ ftc_snode_free( FTC_NODE( snode ), cache );
+ }
+
+
+ /*
+ * This function tries to load a small bitmap within a given FTC_SNode.
+ * Note that it returns a non-zero error code _only_ in the case of
+ * out-of-memory condition. For all other errors (e.g., corresponding
+ * to a bad font file), this function will mark the sbit as `unavailable'
+ * and return a value of 0.
+ *
+ * You should also read the comment within the @ftc_snode_compare
+ * function below to see how out-of-memory is handled during a lookup.
+ */
+ static FT_Error
+ ftc_snode_load( FTC_SNode snode,
+ FTC_Manager manager,
+ FT_UInt gindex,
+ FT_ULong *asize )
+ {
+ FT_Error error;
+ FTC_GNode gnode = FTC_GNODE( snode );
+ FTC_Family family = gnode->family;
+ FT_Memory memory = manager->memory;
+ FT_Face face;
+ FTC_SBit sbit;
+ FTC_SFamilyClass clazz;
+
+
+ if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
+ {
+ FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
+ return FTC_Err_Invalid_Argument;
+ }
+
+ sbit = snode->sbits + ( gindex - gnode->gindex );
+ clazz = (FTC_SFamilyClass)family->clazz;
+
+ sbit->buffer = 0;
+
+ error = clazz->family_load_glyph( family, gindex, manager, &face );
+ if ( error )
+ goto BadGlyph;
+
+ {
+ FT_Int temp;
+ FT_GlyphSlot slot = face->glyph;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_Int xadvance, yadvance;
+
+
+ if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
+ {
+ FT_ERROR(( "%s: glyph loaded didn't return a bitmap!\n",
+ "ftc_snode_load" ));
+ goto BadGlyph;
+ }
+
+ /* Check that our values fit into 8-bit containers! */
+ /* If this is not the case, our bitmap is too large */
+ /* and we will leave it as `missing' with sbit.buffer = 0 */
+
+#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
+#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
+
+ /* horizontal advance in pixels */
+ xadvance = ( slot->advance.x + 32 ) >> 6;
+ yadvance = ( slot->advance.y + 32 ) >> 6;
+
+ if ( !CHECK_BYTE( bitmap->rows ) ||
+ !CHECK_BYTE( bitmap->width ) ||
+ !CHECK_CHAR( bitmap->pitch ) ||
+ !CHECK_CHAR( slot->bitmap_left ) ||
+ !CHECK_CHAR( slot->bitmap_top ) ||
+ !CHECK_CHAR( xadvance ) ||
+ !CHECK_CHAR( yadvance ) )
+ goto BadGlyph;
+
+ sbit->width = (FT_Byte)bitmap->width;
+ sbit->height = (FT_Byte)bitmap->rows;
+ sbit->pitch = (FT_Char)bitmap->pitch;
+ sbit->left = (FT_Char)slot->bitmap_left;
+ sbit->top = (FT_Char)slot->bitmap_top;
+ sbit->xadvance = (FT_Char)xadvance;
+ sbit->yadvance = (FT_Char)yadvance;
+ sbit->format = (FT_Byte)bitmap->pixel_mode;
+ sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
+
+ /* copy the bitmap into a new buffer -- ignore error */
+ error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
+
+ /* now, compute size */
+ if ( asize )
+ *asize = FT_ABS( sbit->pitch ) * sbit->height;
+
+ } /* glyph loading successful */
+
+ /* ignore the errors that might have occurred -- */
+ /* we mark unloaded glyphs with `sbit.buffer == 0' */
+ /* and `width == 255', `height == 0' */
+ /* */
+ if ( error && error != FTC_Err_Out_Of_Memory )
+ {
+ BadGlyph:
+ sbit->width = 255;
+ sbit->height = 0;
+ sbit->buffer = NULL;
+ error = 0;
+ if ( asize )
+ *asize = 0;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_SNode_New( FTC_SNode *psnode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_SNode snode = NULL;
+ FT_UInt gindex = gquery->gindex;
+ FTC_Family family = gquery->family;
+
+ FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
+ FT_UInt total;
+
+
+ total = clazz->family_get_count( family, cache->manager );
+ if ( total == 0 || gindex >= total )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if ( !FT_NEW( snode ) )
+ {
+ FT_UInt count, start;
+
+
+ start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
+ count = total - start;
+ if ( count > FTC_SBIT_ITEMS_PER_NODE )
+ count = FTC_SBIT_ITEMS_PER_NODE;
+
+ FTC_GNode_Init( FTC_GNODE( snode ), start, family );
+
+ snode->count = count;
+
+ error = ftc_snode_load( snode,
+ cache->manager,
+ gindex,
+ NULL );
+ if ( error )
+ {
+ FTC_SNode_Free( snode, cache );
+ snode = NULL;
+ }
+ }
+
+ Exit:
+ *psnode = snode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_snode_new( FTC_Node *ftcpsnode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_SNode_New( psnode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_ULong )
+ ftc_snode_weight( FTC_Node ftcsnode,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FT_UInt count = snode->count;
+ FTC_SBit sbit = snode->sbits;
+ FT_Int pitch;
+ FT_ULong size;
+
+ FT_UNUSED( cache );
+
+
+ FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
+
+ /* the node itself */
+ size = sizeof ( *snode );
+
+ for ( ; count > 0; count--, sbit++ )
+ {
+ if ( sbit->buffer )
+ {
+ pitch = sbit->pitch;
+ if ( pitch < 0 )
+ pitch = -pitch;
+
+ /* add the size of a given glyph image */
+ size += pitch * sbit->height;
+ }
+ }
+
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_ULong )
+ FTC_SNode_Weight( FTC_SNode snode )
+ {
+ return ftc_snode_weight( FTC_NODE( snode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ ftc_snode_compare( FTC_Node ftcsnode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_SNode snode = (FTC_SNode)ftcsnode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+ FTC_GNode gnode = FTC_GNODE( snode );
+ FT_UInt gindex = gquery->gindex;
+ FT_Bool result;
+
+
+ result = FT_BOOL( gnode->family == gquery->family &&
+ (FT_UInt)( gindex - gnode->gindex ) < snode->count );
+ if ( result )
+ {
+ /* check if we need to load the glyph bitmap now */
+ FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
+
+
+ /*
+ * The following code illustrates what to do when you want to
+ * perform operations that may fail within a lookup function.
+ *
+ * Here, we want to load a small bitmap on-demand; we thus
+ * need to call the `ftc_snode_load' function which may return
+ * a non-zero error code only when we are out of memory (OOM).
+ *
+ * The correct thing to do is to use @FTC_CACHE_TRYLOOP and
+ * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
+ * that is capable of flushing the cache incrementally when
+ * an OOM errors occur.
+ *
+ * However, we need to `lock' the node before this operation to
+ * prevent it from being flushed within the loop.
+ *
+ * When we exit the loop, we unlock the node, then check the `error'
+ * variable. If it is non-zero, this means that the cache was
+ * completely flushed and that no usable memory was found to load
+ * the bitmap.
+ *
+ * We then prefer to return a value of 0 (i.e., NO MATCH). This
+ * ensures that the caller will try to allocate a new node.
+ * This operation consequently _fail_ and the lookup function
+ * returns the appropriate OOM error code.
+ *
+ * Note that `buffer == NULL && width == 255' is a hack used to
+ * tag `unavailable' bitmaps in the array. We should never try
+ * to load these.
+ *
+ */
+
+ if ( sbit->buffer == NULL && sbit->width != 255 )
+ {
+ FT_ULong size;
+ FT_Error error;
+
+
+ ftcsnode->ref_count++; /* lock node to prevent flushing */
+ /* in retry loop */
+
+ FTC_CACHE_TRYLOOP( cache )
+ {
+ error = ftc_snode_load( snode, cache->manager, gindex, &size );
+ }
+ FTC_CACHE_TRYLOOP_END();
+
+ ftcsnode->ref_count--; /* unlock the node */
+
+ if ( error )
+ result = 0;
+ else
+ cache->manager->cur_weight += size;
+ }
+ }
+
+ return result;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ FTC_SNode_Compare( FTC_SNode snode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );
+ }
+
+
+/* END */