forked from minhngoc25a/freetype2
[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:
parent
274207eb9a
commit
01705395b0
40
ChangeLog
40
ChangeLog
|
@ -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'.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue