ref: 01705395b08167b654a24f26673ee6e75a84f2be
parent: 274207eb9a0e3bb20edf30e9a62e25120d5d15e5
author: Werner Lemberg <[email protected]>
date: Thu Jul 18 09:13:12 EDT 2013
[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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2013-07-18 Behdad Esfahbod <[email protected]>
+
+ [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 <[email protected]>
[sfnt] Ignore invalid magic number in `head' or `bhed'.
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -353,16 +353,16 @@
/* */
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 @@
(*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 @@
/* */
/* 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_Byte* sbit_table;
FT_ULong sbit_table_size;
+ TT_SbitTableType sbit_table_type;
FT_UInt sbit_num_strikes;
FT_Byte* kern_table;
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -88,6 +88,7 @@
#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' )
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -175,7 +175,7 @@
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,
@@ -182,8 +182,10 @@
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,14 +198,23 @@
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;
+ }
+
FT_Stream_OpenMemory( &stream, data, png_len );
png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
@@ -238,10 +249,32 @@
&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 )
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -29,7 +29,7 @@
#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,
@@ -36,7 +36,8 @@
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
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -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 ),
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -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,7 +61,16 @@
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;
if ( table_size < 8 )
@@ -71,47 +80,122 @@
goto Exit;
}
- if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
- goto Exit;
+ switch ( (FT_UInt)face->sbit_table_type )
+ {
+ case TT_SBIT_TABLE_TYPE_EBLC:
+ {
+ FT_Byte* p;
+ FT_Fixed version;
+ FT_ULong num_strikes;
+ FT_UInt count;
- face->sbit_table_size = table_size;
- p = face->sbit_table;
- p_limit = p + table_size;
+ if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
+ goto Exit;
- version = FT_NEXT_ULONG( p );
- num_strikes = FT_NEXT_ULONG( p );
+ face->sbit_table_size = table_size;
- if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
- {
- FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
- error = FT_THROW( Invalid_File_Format );
- goto Fail;
+ 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;
@@ -118,6 +202,7 @@
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,9 +536,7 @@
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;
bit_width = bitmap->width;
@@ -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,9 +675,7 @@
FT_Bitmap* bitmap;
FT_UShort rval;
- FT_UNUSED( load_flags );
-
/* check that we can write the glyph into the bitmap */
bitmap = decoder->bitmap;
bit_width = bitmap->width;
@@ -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,9 +862,7 @@
FT_Error error = FT_Err_Ok;
FT_ULong png_len;
- FT_UNUSED( load_flags );
-
if ( limit - p < 4 )
{
FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
@@ -759,7 +878,7 @@
goto Exit;
}
- error = Load_SBit_Png( decoder->bitmap,
+ error = Load_SBit_Png( decoder->face->root.glyph,
x_pos,
y_pos,
decoder->bit_depth,
@@ -766,7 +885,8 @@
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_Error error = FT_Err_Ok;
- FT_UNUSED( load_flags );
- FT_UNUSED( stream );
- FT_UNUSED( map );
+ switch ( (FT_UInt)face->sbit_table_type )
+ {
+ 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_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 )
{
- error = tt_sbit_decoder_load_image( decoder,
- load_flags,
- glyph_index,
- 0,
- 0 );
- tt_sbit_decoder_done( decoder );
+ 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;
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -28,11 +28,11 @@
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 )