diff options
Diffstat (limited to 'src/3rdparty/freetype/src/base/ftbitmap.c')
-rw-r--r-- | src/3rdparty/freetype/src/base/ftbitmap.c | 271 |
1 files changed, 202 insertions, 69 deletions
diff --git a/src/3rdparty/freetype/src/base/ftbitmap.c b/src/3rdparty/freetype/src/base/ftbitmap.c index 46fcce6136..19a1a80795 100644 --- a/src/3rdparty/freetype/src/base/ftbitmap.c +++ b/src/3rdparty/freetype/src/base/ftbitmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility functions for bitmaps (body). */ /* */ -/* Copyright 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2004-2009, 2011, 2013, 2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,6 +17,8 @@ #include <ft2build.h> +#include FT_INTERNAL_DEBUG_H + #include FT_BITMAP_H #include FT_IMAGE_H #include FT_INTERNAL_OBJECTS_H @@ -31,7 +33,8 @@ FT_EXPORT_DEF( void ) FT_Bitmap_New( FT_Bitmap *abitmap ) { - *abitmap = null_bitmap; + if ( abitmap ) + *abitmap = null_bitmap; } @@ -42,25 +45,42 @@ const FT_Bitmap *source, FT_Bitmap *target) { - FT_Memory memory = library->memory; + FT_Memory memory; FT_Error error = FT_Err_Ok; - FT_Int pitch = source->pitch; - FT_ULong size; + FT_Int pitch; + FT_ULong size; + + FT_Int source_pitch_sign, target_pitch_sign; + + + if ( !library ) + return FT_THROW( Invalid_Library_Handle ); + + if ( !source || !target ) + return FT_THROW( Invalid_Argument ); if ( source == target ) return FT_Err_Ok; + source_pitch_sign = source->pitch < 0 ? -1 : 1; + target_pitch_sign = target->pitch < 0 ? -1 : 1; + if ( source->buffer == NULL ) { *target = *source; + if ( source_pitch_sign != target_pitch_sign ) + target->pitch = -target->pitch; return FT_Err_Ok; } + memory = library->memory; + pitch = source->pitch; + if ( pitch < 0 ) pitch = -pitch; - size = (FT_ULong)( pitch * source->rows ); + size = (FT_ULong)pitch * source->rows; if ( target->buffer ) { @@ -68,9 +88,9 @@ FT_ULong target_size; - if ( target_pitch < 0 ) + if ( target_pitch < 0 ) target_pitch = -target_pitch; - target_size = (FT_ULong)( target_pitch * target->rows ); + target_size = (FT_ULong)target_pitch * target->rows; if ( target_size != size ) (void)FT_QREALLOC( target->buffer, target_size, size ); @@ -87,13 +107,35 @@ *target = *source; target->buffer = p; - FT_MEM_COPY( target->buffer, source->buffer, size ); + if ( source_pitch_sign == target_pitch_sign ) + FT_MEM_COPY( target->buffer, source->buffer, size ); + else + { + /* take care of bitmap flow */ + FT_UInt i; + FT_Byte* s = source->buffer; + FT_Byte* t = target->buffer; + + + t += pitch * ( target->rows - 1 ); + + for ( i = target->rows; i > 0; i-- ) + { + FT_ARRAY_COPY( t, s, pitch ); + + s += pitch; + t -= pitch; + } + } } return error; } + /* Enlarge `bitmap' horizontally and vertically by `xpixels' */ + /* and `ypixels', respectively. */ + static FT_Error ft_bitmap_assure_buffer( FT_Memory memory, FT_Bitmap* bitmap, @@ -104,8 +146,8 @@ int pitch; int new_pitch; FT_UInt bpp; - FT_Int i, width, height; - unsigned char* buffer; + FT_UInt i, width, height; + unsigned char* buffer = NULL; width = bitmap->width; @@ -135,24 +177,24 @@ new_pitch = ( width + xpixels ); break; default: - return FT_Err_Invalid_Glyph_Format; + return FT_THROW( Invalid_Glyph_Format ); } /* if no need to allocate memory */ if ( ypixels == 0 && new_pitch <= pitch ) { /* zero the padding */ - FT_Int bit_width = pitch * 8; - FT_Int bit_last = ( width + xpixels ) * bpp; + FT_UInt bit_width = pitch * 8; + FT_UInt bit_last = ( width + xpixels ) * bpp; if ( bit_last < bit_width ) { FT_Byte* line = bitmap->buffer + ( bit_last >> 3 ); FT_Byte* end = bitmap->buffer + pitch; - FT_Int shift = bit_last & 7; + FT_UInt shift = bit_last & 7; FT_UInt mask = 0xFF00U >> shift; - FT_Int count = height; + FT_UInt count = height; for ( ; count > 0; count--, line += pitch, end += pitch ) @@ -166,19 +208,22 @@ write++; } if ( write < end ) - FT_MEM_ZERO( write, end-write ); + FT_MEM_ZERO( write, end - write ); } } return FT_Err_Ok; } + /* otherwise allocate new buffer */ if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) return error; + /* new rows get added at the top of the bitmap, */ + /* thus take care of the flow direction */ if ( bitmap->pitch > 0 ) { - FT_Int len = ( width * bpp + 7 ) >> 3; + FT_UInt len = ( width * bpp + 7 ) >> 3; for ( i = 0; i < bitmap->rows; i++ ) @@ -187,7 +232,7 @@ } else { - FT_Int len = ( width * bpp + 7 ) >> 3; + FT_UInt len = ( width * bpp + 7 ) >> 3; for ( i = 0; i < bitmap->rows; i++ ) @@ -218,27 +263,28 @@ { FT_Error error; unsigned char* p; - FT_Int i, x, y, pitch; + FT_Int i, x, pitch; + FT_UInt y; FT_Int xstr, ystr; if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); if ( !bitmap || !bitmap->buffer ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) || ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) ) - return FT_Err_Invalid_Argument; - + return FT_THROW( Invalid_Argument ); + xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6; ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6; if ( xstr == 0 && ystr == 0 ) return FT_Err_Ok; else if ( xstr < 0 || ystr < 0 ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); switch ( bitmap->pixel_mode ) { @@ -246,17 +292,11 @@ case FT_PIXEL_MODE_GRAY4: { FT_Bitmap tmp; - FT_Int align; - - if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 ) - align = ( bitmap->width + xstr + 3 ) / 4; - else - align = ( bitmap->width + xstr + 1 ) / 2; + /* convert to 8bpp */ FT_Bitmap_New( &tmp ); - - error = FT_Bitmap_Convert( library, bitmap, &tmp, align ); + error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 ); if ( error ) return error; @@ -277,12 +317,17 @@ case FT_PIXEL_MODE_LCD_V: ystr *= 3; break; + + case FT_PIXEL_MODE_BGRA: + /* We don't embolden color glyphs. */ + return FT_Err_Ok; } error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr ); if ( error ) return error; + /* take care of bitmap flow */ pitch = bitmap->pitch; if ( pitch > 0 ) p = bitmap->buffer + pitch * ystr; @@ -303,7 +348,7 @@ */ for ( x = pitch - 1; x >= 0; x-- ) { - unsigned char tmp; + unsigned char tmp; tmp = p[x]; @@ -318,7 +363,7 @@ p[x] |= p[x - 1] << ( 8 - i ); #if 0 - if ( p[x] == 0xff ) + if ( p[x] == 0xFF ) break; #endif } @@ -328,12 +373,12 @@ { if ( p[x] + p[x - i] > bitmap->num_grays - 1 ) { - p[x] = (unsigned char)(bitmap->num_grays - 1); + p[x] = (unsigned char)( bitmap->num_grays - 1 ); break; } else { - p[x] = (unsigned char)(p[x] + p[x-i]); + p[x] = (unsigned char)( p[x] + p[x - i] ); if ( p[x] == bitmap->num_grays - 1 ) break; } @@ -369,6 +414,52 @@ } + static FT_Byte + ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) + { + FT_UInt a = bgra[3]; + FT_UInt l; + + + /* Short-circuit transparent color to avoid division by zero. */ + if ( !a ) + return 0; + + /* + * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722 + * coefficients for RGB channels *on the linear colors*. + * A gamma of 2.2 is fair to assume. And then, we need to + * undo the premultiplication too. + * + * http://accessibility.kde.org/hsl-adjusted.php + * + * We do the computation with integers only, applying a gamma of 2.0. + * We guarantee 32-bit arithmetic to avoid overflow but the resulting + * luminosity fits into 16 bits. + * + */ + + l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + + 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + + 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; + + /* + * Final transparency can be determined as follows. + * + * - If alpha is zero, we want 0. + * - If alpha is zero and luminosity is zero, we want 255. + * - If alpha is zero and luminosity is one, we want 0. + * + * So the formula is a * (1 - l) = a - l * a. + * + * We still need to undo premultiplication by dividing l by a*a. + * + */ + + return (FT_Byte)( a - l / a ); + } + + /* documentation is in ftbitmap.h */ FT_EXPORT_DEF( FT_Error ) @@ -380,9 +471,15 @@ FT_Error error = FT_Err_Ok; FT_Memory memory; + FT_Byte* s; + FT_Byte* t; + if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); + + if ( !source || !target ) + return FT_THROW( Invalid_Argument ); memory = library->memory; @@ -394,14 +491,17 @@ case FT_PIXEL_MODE_GRAY4: case FT_PIXEL_MODE_LCD: case FT_PIXEL_MODE_LCD_V: + case FT_PIXEL_MODE_BGRA: { - FT_Int pad; - FT_Long old_size; + FT_Int pad, old_target_pitch, target_pitch; + FT_ULong old_size; + + old_target_pitch = target->pitch; + if ( old_target_pitch < 0 ) + old_target_pitch = -old_target_pitch; - old_size = target->rows * target->pitch; - if ( old_size < 0 ) - old_size = -old_size; + old_size = target->rows * old_target_pitch; target->pixel_mode = FT_PIXEL_MODE_GRAY; target->rows = source->rows; @@ -415,26 +515,39 @@ pad = alignment - pad; } - target->pitch = source->width + pad; + target_pitch = source->width + pad; - if ( target->rows * target->pitch > old_size && + if ( target_pitch > 0 && + (FT_ULong)target->rows > FT_ULONG_MAX / target_pitch ) + return FT_THROW( Invalid_Argument ); + + if ( target->rows * target_pitch > old_size && FT_QREALLOC( target->buffer, - old_size, target->rows * target->pitch ) ) + old_size, target->rows * target_pitch ) ) return error; + + target->pitch = target->pitch < 0 ? -target_pitch : target_pitch; } break; default: - error = FT_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); } + s = source->buffer; + t = target->buffer; + + /* take care of bitmap flow */ + if ( source->pitch < 0 ) + s -= source->pitch * ( source->rows - 1 ); + if ( target->pitch < 0 ) + t -= target->pitch * ( target->rows - 1 ); + switch ( source->pixel_mode ) { case FT_PIXEL_MODE_MONO: { - FT_Byte* s = source->buffer; - FT_Byte* t = target->buffer; - FT_Int i; + FT_UInt i; target->num_grays = 2; @@ -443,7 +556,7 @@ { FT_Byte* ss = s; FT_Byte* tt = t; - FT_Int j; + FT_UInt j; /* get the full bytes */ @@ -491,12 +604,8 @@ case FT_PIXEL_MODE_LCD: case FT_PIXEL_MODE_LCD_V: { - FT_Int width = source->width; - FT_Byte* s = source->buffer; - FT_Byte* t = target->buffer; - FT_Int s_pitch = source->pitch; - FT_Int t_pitch = target->pitch; - FT_Int i; + FT_Int width = source->width; + FT_UInt i; target->num_grays = 256; @@ -505,8 +614,8 @@ { FT_ARRAY_COPY( t, s, width ); - s += s_pitch; - t += t_pitch; + s += source->pitch; + t += target->pitch; } } break; @@ -514,9 +623,7 @@ case FT_PIXEL_MODE_GRAY2: { - FT_Byte* s = source->buffer; - FT_Byte* t = target->buffer; - FT_Int i; + FT_UInt i; target->num_grays = 4; @@ -525,7 +632,7 @@ { FT_Byte* ss = s; FT_Byte* tt = t; - FT_Int j; + FT_UInt j; /* get the full bytes */ @@ -566,9 +673,7 @@ case FT_PIXEL_MODE_GRAY4: { - FT_Byte* s = source->buffer; - FT_Byte* t = target->buffer; - FT_Int i; + FT_UInt i; target->num_grays = 16; @@ -577,7 +682,7 @@ { FT_Byte* ss = s; FT_Byte* tt = t; - FT_Int j; + FT_UInt j; /* get the full bytes */ @@ -603,6 +708,34 @@ break; + case FT_PIXEL_MODE_BGRA: + { + FT_UInt i; + + + target->num_grays = 256; + + for ( i = source->rows; i > 0; i-- ) + { + FT_Byte* ss = s; + FT_Byte* tt = t; + FT_UInt j; + + + for ( j = source->width; j > 0; j-- ) + { + tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss ); + + ss += 4; + tt += 1; + } + + s += source->pitch; + t += target->pitch; + } + } + break; + default: ; } @@ -646,10 +779,10 @@ if ( !library ) - return FT_Err_Invalid_Library_Handle; + return FT_THROW( Invalid_Library_Handle ); if ( !bitmap ) - return FT_Err_Invalid_Argument; + return FT_THROW( Invalid_Argument ); memory = library->memory; |