[sfnt] Add support for Apple's `sbix' color bitmap table.

* include/freetype/internal/tttypes.h (TT_SBit_MetricsRec): Widen
fields to FT_Short and FT_UShort, respectively.
(TT_SBitTableType): New enumeration.
(TT_FaceRec): Add `sbit_table_type' field.

* include/freetype/tttags.h (TTAG_sbix): New macro.

* src/sfnt/pngshim.c (Load_SBit_Png): Pass a more generic
FT_GlyphSlot argument instead FT_Bitmap.
Add flag to control map and metrics handling.
Update all users.

* src/sfnt/ttsbit.c: Include `ttmtx.h'.
(tt_face_load_eblc): Renamed to...
(tt_face_load_sbit): This.
Handlic `sbix' bitmaps.
(tt_face_free_eblc): Renamed to...
(tt_face_load_sbit): This.
Updated.
(tt_face_load_strike_metrics): Handle `sbix' bitmaps.
(tt_face_load_sbix_image): New function.
(tt_sbit_decoder_alloc_bitmap, tt_sbit_decoder_load_image,
tt_sbit_decoder_load_byte_aligned, tt_sbit_decoder_load_bit_aligned,
tt_sbit_decoder_load_compound, tt_sbit_decoder_load_png,
tt_sbit_decoder_load_image, tt_sbit_decoder_load_bitmap): Don't pass
and handle load flags.
(tt_sbit_decoder_load_bitmap) [!FT_CONFIG_OPTION_USE_PNG]: Better
handle formats 17-19.
Move color to grayscale conversion to...
(tt_face_load_sbit_image): Here.
Handle `sbix' bitmaps.

* src/sfnt/pngshim.h: Updated.
* src/sfnt/ttsbit.h: Updated.
* src/sfnt/sfdriver.c: Updated.
This commit is contained in:
Werner Lemberg 2013-07-18 13:13:12 +02:00
parent 274207eb9a
commit 01705395b0
8 changed files with 512 additions and 200 deletions

View File

@ -1,3 +1,43 @@
2013-07-18 Behdad Esfahbod <behdad@google.com>
[sfnt] Add support for Apple's `sbix' color bitmap table.
* include/freetype/internal/tttypes.h (TT_SBit_MetricsRec): Widen
fields to FT_Short and FT_UShort, respectively.
(TT_SBitTableType): New enumeration.
(TT_FaceRec): Add `sbit_table_type' field.
* include/freetype/tttags.h (TTAG_sbix): New macro.
* src/sfnt/pngshim.c (Load_SBit_Png): Pass a more generic
FT_GlyphSlot argument instead FT_Bitmap.
Add flag to control map and metrics handling.
Update all users.
* src/sfnt/ttsbit.c: Include `ttmtx.h'.
(tt_face_load_eblc): Renamed to...
(tt_face_load_sbit): This.
Handlic `sbix' bitmaps.
(tt_face_free_eblc): Renamed to...
(tt_face_load_sbit): This.
Updated.
(tt_face_load_strike_metrics): Handle `sbix' bitmaps.
(tt_face_load_sbix_image): New function.
(tt_sbit_decoder_alloc_bitmap, tt_sbit_decoder_load_image,
tt_sbit_decoder_load_byte_aligned, tt_sbit_decoder_load_bit_aligned,
tt_sbit_decoder_load_compound, tt_sbit_decoder_load_png,
tt_sbit_decoder_load_image, tt_sbit_decoder_load_bitmap): Don't pass
and handle load flags.
(tt_sbit_decoder_load_bitmap) [!FT_CONFIG_OPTION_USE_PNG]: Better
handle formats 17-19.
Move color to grayscale conversion to...
(tt_face_load_sbit_image): Here.
Handle `sbix' bitmaps.
* src/sfnt/pngshim.h: Updated.
* src/sfnt/ttsbit.h: Updated.
* src/sfnt/sfdriver.c: Updated.
2013-07-18 Werner Lemberg <wl@gnu.org>
[sfnt] Ignore invalid magic number in `head' or `bhed'.

View File

@ -353,16 +353,16 @@ FT_BEGIN_HEADER
/* */
typedef struct TT_SBit_MetricsRec_
{
FT_Byte height;
FT_Byte width;
FT_UShort height;
FT_UShort width;
FT_Char horiBearingX;
FT_Char horiBearingY;
FT_Byte horiAdvance;
FT_Short horiBearingX;
FT_Short horiBearingY;
FT_UShort horiAdvance;
FT_Char vertBearingX;
FT_Char vertBearingY;
FT_Byte vertAdvance;
FT_Short vertBearingX;
FT_Short vertBearingY;
FT_UShort vertAdvance;
} TT_SBit_MetricsRec, *TT_SBit_Metrics;
@ -979,6 +979,20 @@ FT_BEGIN_HEADER
(*TT_Loader_EndGlyphFunc)( TT_Loader loader );
typedef enum TT_SbitTableType_
{
TT_SBIT_TABLE_TYPE_NONE = 0,
TT_SBIT_TABLE_TYPE_EBLC, /* `EBLC' (Microsoft), */
/* `bloc' (Apple), or */
/* `CBLC' (Google) */
TT_SBIT_TABLE_TYPE_SBIX, /* `sbix' (Apple) */
/* do not remove */
TT_SBIT_TABLE_TYPE_MAX
} TT_SbitTableType;
/*************************************************************************/
/* */
/* TrueType Face Type */
@ -1090,13 +1104,6 @@ FT_BEGIN_HEADER
/* */
/* pclt :: The `pclt' SFNT table. */
/* */
/* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */
/* sizes, embedded in this font. */
/* */
/* sbit_strikes :: An array of sbit strikes embedded in this */
/* font. This table is optional in a */
/* TrueType/OpenType font. */
/* */
/* num_sbit_scales :: The number of sbit scales for this font. */
/* */
/* sbit_scales :: Array of sbit scales embedded in this */
@ -1302,6 +1309,7 @@ FT_BEGIN_HEADER
FT_Byte* sbit_table;
FT_ULong sbit_table_size;
TT_SbitTableType sbit_table_type;
FT_UInt sbit_num_strikes;
FT_Byte* kern_table;

View File

@ -88,6 +88,7 @@ FT_BEGIN_HEADER
#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
#define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' )
#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' )
#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )

View File

@ -175,15 +175,17 @@
static FT_Error
Load_SBit_Png( FT_Bitmap* map,
Load_SBit_Png( FT_GlyphSlot slot,
FT_Int x_offset,
FT_Int y_offset,
FT_Int pix_bits,
TT_SBit_Metrics metrics,
FT_Memory memory,
FT_Byte* data,
FT_UInt png_len )
FT_UInt png_len,
FT_Bool populate_map_and_metrics )
{
FT_Bitmap *map = &slot->bitmap;
FT_Error error = FT_Err_Ok;
FT_StreamRec stream;
@ -196,9 +198,18 @@
png_byte* *rows;
if ( x_offset < 0 || x_offset + metrics->width > map->width ||
y_offset < 0 || y_offset + metrics->height > map->rows ||
pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA )
if ( x_offset < 0 ||
y_offset < 0 )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
if ( !populate_map_and_metrics &&
( x_offset + metrics->width > map->width ||
y_offset + metrics->height > map->rows ||
pix_bits != 32 ||
map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
@ -238,11 +249,33 @@
&bitdepth, &color_type, &interlace,
NULL, NULL );
if ( error != FT_Err_Ok ||
(FT_Int)imgWidth != metrics->width ||
(FT_Int)imgHeight != metrics->height )
if ( error ||
( !populate_map_and_metrics &&
( (FT_Int)imgWidth != metrics->width ||
(FT_Int)imgHeight != metrics->height ) ) )
goto DestroyExit;
if ( populate_map_and_metrics )
{
FT_Long size;
metrics->width = (FT_Int)imgWidth;
metrics->height = (FT_Int)imgHeight;
map->width = metrics->width;
map->rows = metrics->height;
map->pixel_mode = FT_PIXEL_MODE_BGRA;
map->pitch = map->width * 4;
map->num_grays = 256;
size = map->rows * map->pitch;
error = ft_glyphslot_alloc_bitmap( slot, size );
if ( error )
goto DestroyExit;
}
/* convert palette/gray image to rgb */
if ( color_type == PNG_COLOR_TYPE_PALETTE )
png_set_palette_to_rgb( png );

View File

@ -29,14 +29,15 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_OPTION_USE_PNG
FT_LOCAL( FT_Error )
Load_SBit_Png( FT_Bitmap* map,
Load_SBit_Png( FT_GlyphSlot slot,
FT_Int x_offset,
FT_Int y_offset,
FT_Int pix_bits,
TT_SBit_Metrics metrics,
FT_Memory memory,
FT_Byte* data,
FT_UInt png_len );
FT_UInt png_len,
FT_Bool populate_map_and_metrics );
#endif

View File

@ -499,8 +499,8 @@
tt_face_load_hmtx,
/* see `ttsbit.h' and `sfnt.h' */
PUT_EMBEDDED_BITMAPS( tt_face_load_eblc ),
PUT_EMBEDDED_BITMAPS( tt_face_free_eblc ),
PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),

View File

@ -28,6 +28,7 @@
#include "sferrors.h"
#include "ttmtx.h"
#include "pngshim.h"
@ -42,17 +43,16 @@
FT_LOCAL_DEF( FT_Error )
tt_face_load_eblc( TT_Face face,
tt_face_load_sbit( TT_Face face,
FT_Stream stream )
{
FT_Error error = FT_Err_Ok;
FT_Fixed version;
FT_ULong num_strikes, table_size;
FT_Byte* p;
FT_Byte* p_limit;
FT_UInt count;
FT_ULong table_size;
face->sbit_table = NULL;
face->sbit_table_size = 0;
face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
face->sbit_num_strikes = 0;
/* this table is optional */
@ -61,6 +61,15 @@
error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
if ( error )
error = face->goto_table( face, TTAG_bloc, stream, &table_size );
if ( !error )
face->sbit_table_type = TT_SBIT_TABLE_TYPE_EBLC;
if ( error )
{
error = face->goto_table( face, TTAG_sbix, stream, &table_size );
if ( !error )
face->sbit_table_type = TT_SBIT_TABLE_TYPE_SBIX;
}
if ( error )
goto Exit;
@ -71,53 +80,129 @@
goto Exit;
}
if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
goto Exit;
face->sbit_table_size = table_size;
p = face->sbit_table;
p_limit = p + table_size;
version = FT_NEXT_ULONG( p );
num_strikes = FT_NEXT_ULONG( p );
if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
switch ( (FT_UInt)face->sbit_table_type )
{
FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
case TT_SBIT_TABLE_TYPE_EBLC:
{
FT_Byte* p;
FT_Fixed version;
FT_ULong num_strikes;
FT_UInt count;
if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
goto Exit;
face->sbit_table_size = table_size;
p = face->sbit_table;
version = FT_NEXT_ULONG( p );
num_strikes = FT_NEXT_ULONG( p );
if ( ( version & 0xFFFF0000UL ) != 0x00020000UL )
{
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
if ( num_strikes >= 0x10000UL )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
/*
* Count the number of strikes available in the table. We are a bit
* paranoid there and don't trust the data.
*/
count = (FT_UInt)num_strikes;
if ( 8 + 48UL * count > table_size )
count = (FT_UInt)( ( table_size - 8 ) / 48 );
face->sbit_num_strikes = count;
}
break;
case TT_SBIT_TABLE_TYPE_SBIX:
{
FT_UShort version;
FT_UShort flags;
FT_ULong num_strikes;
FT_UInt count;
if ( FT_FRAME_ENTER( 8 ) )
goto Exit;
version = FT_GET_USHORT();
flags = FT_GET_USHORT();
num_strikes = FT_GET_ULONG();
FT_FRAME_EXIT();
if ( version != 1 )
{
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
if ( flags != 0x0001 || num_strikes >= 0x10000UL )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
/*
* Count the number of strikes available in the table. We are a bit
* paranoid there and don't trust the data.
*/
count = (FT_UInt)num_strikes;
if ( 8 + 4UL * count > table_size )
count = (FT_UInt)( ( table_size - 8 ) / 4 );
if ( FT_STREAM_SEEK( FT_STREAM_POS() - 8 ) )
goto Exit;
face->sbit_table_size = 8 + count * 4;
if ( FT_FRAME_EXTRACT( face->sbit_table_size, face->sbit_table ) )
goto Exit;
face->sbit_num_strikes = count;
}
break;
default:
error = FT_THROW( Unknown_File_Format );
break;
}
/*
* Count the number of strikes available in the table. We are a bit
* paranoid there and don't trust the data.
*/
count = (FT_UInt)num_strikes;
if ( 8 + 48UL * count > table_size )
count = (FT_UInt)( ( p_limit - p ) / 48 );
if ( !error )
FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
face->sbit_num_strikes = count;
return FT_Err_Ok;
FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
Exit:
return error;
if ( error )
{
if ( face->sbit_table )
FT_FRAME_RELEASE( face->sbit_table );
face->sbit_table_size = 0;
face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
}
Fail:
FT_FRAME_RELEASE( face->sbit_table );
face->sbit_table_size = 0;
goto Exit;
return error;
}
FT_LOCAL_DEF( void )
tt_face_free_eblc( TT_Face face )
tt_face_free_sbit( TT_Face face )
{
FT_Stream stream = face->root.stream;
FT_FRAME_RELEASE( face->sbit_table );
face->sbit_table_size = 0;
face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
face->sbit_num_strikes = 0;
}
@ -136,28 +221,84 @@
FT_ULong strike_index,
FT_Size_Metrics* metrics )
{
FT_Byte* strike;
if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
return FT_THROW( Invalid_Argument );
strike = face->sbit_table + 8 + strike_index * 48;
switch ( (FT_UInt)face->sbit_table_type )
{
case TT_SBIT_TABLE_TYPE_EBLC:
{
FT_Byte* strike;
metrics->x_ppem = (FT_UShort)strike[44];
metrics->y_ppem = (FT_UShort)strike[45];
metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
metrics->height = metrics->ascender - metrics->descender;
strike = face->sbit_table + 8 + strike_index * 48;
/* XXX: Is this correct? */
metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
strike[18] + /* max_width */
(FT_Char)strike[23] /* min_advance_SB */
) << 6;
metrics->x_ppem = (FT_UShort)strike[44];
metrics->y_ppem = (FT_UShort)strike[45];
return FT_Err_Ok;
metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
metrics->height = metrics->ascender - metrics->descender;
/* Is this correct? */
metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
strike[18] + /* max_width */
(FT_Char)strike[23] /* min_advance_SB */
) << 6;
return FT_Err_Ok;
}
case TT_SBIT_TABLE_TYPE_SBIX:
{
FT_Stream stream = face->root.stream;
FT_UInt offset, ppem, resolution, upem;
TT_HoriHeader *hori;
FT_ULong table_size;
FT_Error error = FT_Err_Ok;
FT_Byte* p;
p = face->sbit_table + 8 + 4 * strike_index;
offset = FT_NEXT_ULONG( p );
error = face->goto_table( face, TTAG_sbix, stream, &table_size );
if ( error )
return error;
if ( offset + 4 > table_size )
return FT_THROW( Invalid_File_Format );
if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) ||
FT_FRAME_ENTER( 4 ) )
return error;
ppem = FT_GET_USHORT();
resolution = FT_GET_USHORT();
FT_UNUSED( resolution ); /* What to do with this? */
FT_FRAME_EXIT();
upem = face->header.Units_Per_EM;
hori = &face->horizontal;
metrics->x_ppem = ppem;
metrics->y_ppem = ppem;
metrics->ascender = ppem * hori->Ascender / upem;
metrics->descender = ppem * hori->Descender / upem;
metrics->height = ppem * ( hori->Ascender -
hori->Descender +
hori->Line_Gap ) / upem;
metrics->max_advance = ppem * hori->advance_Width_Max / upem;
return error;
}
default:
return FT_THROW( Unknown_File_Format );
}
}
@ -253,8 +394,7 @@
static FT_Error
tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder,
FT_UInt load_flags )
tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder )
{
FT_Error error = FT_Err_Ok;
FT_UInt width, height;
@ -301,18 +441,9 @@
break;
case 32:
if ( load_flags & FT_LOAD_COLOR )
{
map->pixel_mode = FT_PIXEL_MODE_BGRA;
map->pitch = map->width * 4;
map->num_grays = 256;
}
else
{
map->pixel_mode = FT_PIXEL_MODE_GRAY;
map->pitch = map->width;
map->num_grays = 256;
}
map->pixel_mode = FT_PIXEL_MODE_BGRA;
map->pitch = map->width * 4;
map->num_grays = 256;
break;
default:
@ -382,13 +513,11 @@
/* forward declaration */
static FT_Error
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_UInt glyph_index,
FT_Int x_pos,
FT_Int y_pos );
typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_Byte* p,
FT_Byte* plimit,
FT_Int x_pos,
@ -397,7 +526,6 @@
static FT_Error
tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
@ -408,8 +536,6 @@
FT_Int bit_height, bit_width, pitch, width, height, line_bits, h;
FT_Bitmap* bitmap;
FT_UNUSED( load_flags );
/* check that we can write the glyph into the bitmap */
bitmap = decoder->bitmap;
@ -538,7 +664,6 @@
static FT_Error
tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
@ -550,8 +675,6 @@
FT_Bitmap* bitmap;
FT_UShort rval;
FT_UNUSED( load_flags );
/* check that we can write the glyph into the bitmap */
bitmap = decoder->bitmap;
@ -664,7 +787,6 @@
static FT_Error
tt_sbit_decoder_load_compound( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
@ -702,7 +824,7 @@
/* NB: a recursive call */
error = tt_sbit_decoder_load_image( decoder, load_flags, gindex,
error = tt_sbit_decoder_load_image( decoder, gindex,
x_pos + dx, y_pos + dy );
if ( error )
break;
@ -732,7 +854,6 @@
static FT_Error
tt_sbit_decoder_load_png( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
@ -741,8 +862,6 @@
FT_Error error = FT_Err_Ok;
FT_ULong png_len;
FT_UNUSED( load_flags );
if ( limit - p < 4 )
{
@ -759,14 +878,15 @@
goto Exit;
}
error = Load_SBit_Png( decoder->bitmap,
error = Load_SBit_Png( decoder->face->root.glyph,
x_pos,
y_pos,
decoder->bit_depth,
decoder->metrics,
decoder->stream->memory,
p,
png_len );
png_len,
FALSE );
Exit:
if ( !error )
@ -779,7 +899,6 @@
static FT_Error
tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_UInt glyph_format,
FT_ULong glyph_start,
FT_ULong glyph_size,
@ -859,13 +978,15 @@
loader = tt_sbit_decoder_load_compound;
break;
#ifdef FT_CONFIG_OPTION_USE_PNG
case 17: /* small metrics, PNG image data */
case 18: /* big metrics, PNG image data */
case 19: /* metrics in EBLC, PNG image data */
#ifdef FT_CONFIG_OPTION_USE_PNG
loader = tt_sbit_decoder_load_png;
break;
#else
error = FT_THROW( Unimplemented_Feature );
#endif /* FT_CONFIG_OPTION_USE_PNG */
break;
default:
error = FT_THROW( Invalid_Table );
@ -874,64 +995,12 @@
if ( !decoder->bitmap_allocated )
{
error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags );
error = tt_sbit_decoder_alloc_bitmap( decoder );
if ( error )
goto Fail;
}
if ( decoder->bit_depth == 32 &&
decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA )
{
/* Flatten color bitmaps if color was not requested. */
FT_Library library = decoder->face->root.glyph->library;
FT_Memory memory = decoder->stream->memory;
FT_Bitmap color, *orig;
if ( decoder->bitmap->pixel_mode != FT_PIXEL_MODE_GRAY ||
x_pos != 0 || y_pos != 0 )
{
/* Shouldn't happen. */
error = FT_THROW( Invalid_Table );
goto Fail;
}
FT_Bitmap_New( &color );
color.rows = decoder->bitmap->rows;
color.width = decoder->bitmap->width;
color.pitch = color.width * 4;
color.pixel_mode = FT_PIXEL_MODE_BGRA;
if ( FT_ALLOC( color.buffer, color.rows * color.pitch ) )
goto Fail;
orig = decoder->bitmap;
decoder->bitmap = &color;
error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
decoder->bitmap = orig;
/* explicitly test against FT_Err_Ok to avoid compiler warnings */
/* (we do an assignment within a conditional) */
if ( error ||
( error = FT_Bitmap_Convert( library,
&color,
decoder->bitmap,
1 ) ) != FT_Err_Ok )
{
FT_Bitmap_Done( library, &color );
goto Fail;
}
FT_Bitmap_Done( library, &color );
}
else
error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
error = loader( decoder, p, p_limit, x_pos, y_pos );
}
Fail:
@ -944,7 +1013,6 @@
static FT_Error
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
FT_UInt load_flags,
FT_UInt glyph_index,
FT_Int x_pos,
FT_Int y_pos )
@ -993,17 +1061,15 @@
switch ( index_format )
{
case 1: /* 4-byte offsets relative to `image_offset' */
{
p += 4 * ( glyph_index - start );
if ( p + 8 > p_limit )
goto NoBitmap;
p += 4 * ( glyph_index - start );
if ( p + 8 > p_limit )
goto NoBitmap;
image_start = FT_NEXT_ULONG( p );
image_end = FT_NEXT_ULONG( p );
image_start = FT_NEXT_ULONG( p );
image_end = FT_NEXT_ULONG( p );
if ( image_start == image_end ) /* missing glyph */
goto NoBitmap;
}
if ( image_start == image_end ) /* missing glyph */
goto NoBitmap;
break;
case 2: /* big metrics, constant image size */
@ -1025,17 +1091,15 @@
break;
case 3: /* 2-byte offsets relative to 'image_offset' */
{
p += 2 * ( glyph_index - start );
if ( p + 4 > p_limit )
goto NoBitmap;
p += 2 * ( glyph_index - start );
if ( p + 4 > p_limit )
goto NoBitmap;
image_start = FT_NEXT_USHORT( p );
image_end = FT_NEXT_USHORT( p );
image_start = FT_NEXT_USHORT( p );
image_end = FT_NEXT_USHORT( p );
if ( image_start == image_end ) /* missing glyph */
goto NoBitmap;
}
if ( image_start == image_end ) /* missing glyph */
goto NoBitmap;
break;
case 4: /* sparse glyph array with (glyph,offset) pairs */
@ -1124,7 +1188,6 @@
image_format, glyph_index ));
return tt_sbit_decoder_load_bitmap( decoder,
load_flags,
image_format,
image_start,
image_end,
@ -1142,6 +1205,129 @@
}
static FT_Error
tt_face_load_sbix_image( TT_Face face,
FT_ULong strike_index,
FT_UInt glyph_index,
FT_Stream stream,
FT_Bitmap *map,
TT_SBit_MetricsRec *metrics )
{
FT_UInt sbix_pos, strike_offset, glyph_start, glyph_end;
FT_ULong table_size, data_size;
FT_Int originOffsetX, originOffsetY;
FT_Tag graphicType;
FT_Int recurse_depth = 0;
FT_Error error = FT_Err_Ok;
FT_Byte* p;
FT_UNUSED( map );
metrics->width = 0;
metrics->height = 0;
p = face->sbit_table + 8 + 4 * strike_index;
strike_offset = FT_NEXT_ULONG( p );
error = face->goto_table( face, TTAG_sbix, stream, &table_size );
if ( error )
return error;
sbix_pos = FT_STREAM_POS();
retry:
if ( glyph_index > (FT_UInt)face->root.num_glyphs )
return FT_THROW( Invalid_Argument );
if ( strike_offset >= table_size ||
table_size - strike_offset < 4 + glyph_index * 4 + 8 )
return FT_THROW( Invalid_File_Format );
if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) ||
FT_FRAME_ENTER( 8 ) )
return error;
glyph_start = FT_GET_ULONG();
glyph_end = FT_GET_ULONG();
FT_FRAME_EXIT();
if ( glyph_start == glyph_end )
return FT_THROW( Invalid_Argument );
if ( glyph_start > glyph_end ||
glyph_end - glyph_start < 8 ||
table_size - strike_offset < glyph_end )
return FT_THROW( Invalid_File_Format );
if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) ||
FT_FRAME_ENTER( glyph_end - glyph_start ) )
return error;
originOffsetX = FT_GET_SHORT();
originOffsetY = FT_GET_SHORT();
graphicType = FT_GET_TAG4();
data_size = glyph_end - glyph_start - 8;
switch ( graphicType )
{
case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ):
if ( recurse_depth < 4 )
{
glyph_index = FT_GET_USHORT();
FT_FRAME_EXIT();
recurse_depth++;
goto retry;
}
error = FT_THROW( Invalid_File_Format );
break;
case FT_MAKE_TAG( 'p', 'n', 'g', ' ' ):
#ifdef FT_CONFIG_OPTION_USE_PNG
error = Load_SBit_Png( face->root.glyph,
0,
0,
32,
metrics,
stream->memory,
stream->cursor,
data_size,
TRUE );
#else
error = FT_THROW( Unimplemented_Feature );
#endif
break;
case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ):
case FT_MAKE_TAG( 't', 'i', 'f', 'f' ):
error = FT_THROW( Unknown_File_Format );
break;
default:
error = FT_THROW( Unimplemented_Feature );
break;
}
FT_FRAME_EXIT();
if ( !error )
{
FT_Short abearing;
FT_UShort aadvance;
tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
metrics->horiBearingX = originOffsetX;
metrics->horiBearingY = -originOffsetY + metrics->height;
metrics->horiAdvance = aadvance * face->root.size->metrics.x_ppem /
face->root.units_per_EM;
}
return error;
}
FT_LOCAL( FT_Error )
tt_face_load_sbit_image( TT_Face face,
FT_ULong strike_index,
@ -1151,23 +1337,66 @@
FT_Bitmap *map,
TT_SBit_MetricsRec *metrics )
{
TT_SBitDecoderRec decoder[1];
FT_Error error;
FT_UNUSED( load_flags );
FT_UNUSED( stream );
FT_UNUSED( map );
FT_Error error = FT_Err_Ok;
error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
if ( !error )
switch ( (FT_UInt)face->sbit_table_type )
{
error = tt_sbit_decoder_load_image( decoder,
load_flags,
glyph_index,
0,
0 );
tt_sbit_decoder_done( decoder );
case TT_SBIT_TABLE_TYPE_EBLC:
{
TT_SBitDecoderRec decoder[1];
error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
if ( !error )
{
error = tt_sbit_decoder_load_image( decoder,
glyph_index,
0,
0 );
tt_sbit_decoder_done( decoder );
}
}
break;
case TT_SBIT_TABLE_TYPE_SBIX:
error = tt_face_load_sbix_image( face,
strike_index,
glyph_index,
stream,
map,
metrics );
break;
default:
error = FT_THROW( Unknown_File_Format );
break;
}
/* Flatten color bitmaps if color was not requested. */
if ( !error &&
!( load_flags & FT_LOAD_COLOR ) &&
map->pixel_mode == FT_PIXEL_MODE_BGRA )
{
FT_Bitmap new_map;
FT_Library library = face->root.glyph->library;
FT_Bitmap_New( &new_map );
/* Convert to 8bit grayscale. */
error = FT_Bitmap_Convert( library, map, &new_map, 1 );
if ( error )
FT_Bitmap_Done( library, &new_map );
else
{
map->pixel_mode = new_map.pixel_mode;
map->pitch = new_map.pitch;
map->num_grays = new_map.num_grays;
ft_glyphslot_set_bitmap( face->root.glyph, new_map.buffer );
face->root.glyph->internal->flags |= FT_GLYPH_OWN_BITMAP;
}
}
return error;

View File

@ -28,11 +28,11 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
tt_face_load_eblc( TT_Face face,
tt_face_load_sbit( TT_Face face,
FT_Stream stream );
FT_LOCAL( void )
tt_face_free_eblc( TT_Face face );
tt_face_free_sbit( TT_Face face );
FT_LOCAL( FT_Error )