[truetype] Fix 'sbix' table handling.

* src/sfnt/ttsbit.c (tt_face_load_sbix_image): Correct calculation of
'metrics->horiBearingY'.
Set vertical metrics.

* src/sfnt/sfobjs.c (sfnt_load_face): Adjust setting of `FT_FACE_FLAG_SBIX`.
Handle metrics of fonts with 'sbix' table.

* src/truetype/ttgload.c (TT_Load_Glyph): For 'sbix' embedded bitmaps, apply
bbox offset and bearing values of the corresponding glyph in the 'glyf'
table if it exists and has a contour.

* src/truetype/ttobjs.c (tt_face_init): Handle font with 'sbix' table.

Fixes issue #998.
This commit is contained in:
Werner Lemberg 2022-02-07 06:55:54 +01:00
parent 907715a6a2
commit ac4c1ebf7e
4 changed files with 63 additions and 15 deletions

View File

@ -851,12 +851,6 @@
is_apple_sbit = 0; is_apple_sbit = 0;
is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
/* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
* outline rendered on top. We don't support that yet, so just ignore
* the 'glyf' outline and advertise it as a bitmap-only font. */
if ( is_apple_sbix )
has_outline = FALSE;
/* if this font doesn't contain outlines, we try to load */ /* if this font doesn't contain outlines, we try to load */
/* a `bhed' table */ /* a `bhed' table */
if ( !has_outline && sfnt->load_bhed ) if ( !has_outline && sfnt->load_bhed )
@ -1059,10 +1053,12 @@
if ( has_outline == TRUE ) if ( has_outline == TRUE )
{ {
/* by default (and for backward compatibility) we handle */
/* fonts with an 'sbix' table as bitmap-only */
if ( is_apple_sbix )
flags |= FT_FACE_FLAG_SBIX; /* with 'sbix' bitmaps */
else
flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
flags |= FT_FACE_FLAG_SBIX; /* and 'sbix' bitmaps */
} }
/* The sfnt driver only supports bitmap fonts natively, thus we */ /* The sfnt driver only supports bitmap fonts natively, thus we */
@ -1286,7 +1282,8 @@
* *
* Set up metrics. * Set up metrics.
*/ */
if ( FT_IS_SCALABLE( root ) ) if ( FT_IS_SCALABLE( root ) ||
FT_HAS_SBIX( root ) )
{ {
/* XXX What about if outline header is missing */ /* XXX What about if outline header is missing */
/* (e.g. sfnt wrapped bitmap)? */ /* (e.g. sfnt wrapped bitmap)? */

View File

@ -1580,17 +1580,34 @@
if ( !error ) if ( !error )
{ {
FT_Short abearing; FT_Short abearing; /* not used here */
FT_UShort aadvance; FT_UShort aadvance;
tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance ); tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
metrics->horiBearingX = (FT_Short)originOffsetX; metrics->horiBearingX = (FT_Short)originOffsetX;
metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height ); metrics->vertBearingX = (FT_Short)originOffsetX;
metrics->horiBearingY = (FT_Short)( originOffsetY + metrics->height );
metrics->vertBearingY = (FT_Short)originOffsetY;
metrics->horiAdvance = (FT_UShort)( aadvance * metrics->horiAdvance = (FT_UShort)( aadvance *
face->root.size->metrics.x_ppem / face->root.size->metrics.x_ppem /
face->header.Units_Per_EM ); face->header.Units_Per_EM );
if ( face->vertical_info )
tt_face_get_metrics( face, TRUE, glyph_index, &abearing, &aadvance );
else if ( face->os2.version != 0xFFFFU )
aadvance = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
face->os2.sTypoDescender );
else
aadvance = (FT_UShort)FT_ABS( face->horizontal.Ascender -
face->horizontal.Descender );
metrics->vertAdvance = (FT_UShort)( aadvance *
face->root.size->metrics.x_ppem /
face->header.Units_Per_EM );
} }
return error; return error;

View File

@ -2897,8 +2897,12 @@
} }
else else
{ {
if ( FT_IS_SCALABLE( glyph->face ) ) if ( FT_IS_SCALABLE( glyph->face ) ||
FT_HAS_SBIX( glyph->face ) )
{ {
TT_Face face = (TT_Face)glyph->face;
/* for the bbox we need the header only */ /* for the bbox we need the header only */
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
@ -2906,6 +2910,35 @@
glyph->linearHoriAdvance = loader.linear; glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.vadvance; glyph->linearVertAdvance = loader.vadvance;
/* Bitmaps from the 'sbix' table need special treatment: */
/* if there is a glyph contour, the bitmap origin must be */
/* shifted to be relative to the lower left corner of the */
/* glyph bounding box, also taking the left-side bearing */
/* (or top bearing) into account. */
if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
loader.n_contours > 0 )
{
FT_Int bitmap_left;
FT_Int bitmap_top;
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
{
/* This is a guess, since Apple's CoreText engine doesn't */
/* really do vertical typesetting. */
bitmap_left = loader.bbox.xMin;
bitmap_top = loader.top_bearing;
}
else
{
bitmap_left = loader.left_bearing;
bitmap_top = loader.bbox.yMin;
}
glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6;
}
/* sanity checks: if `xxxAdvance' in the sbit metric */ /* sanity checks: if `xxxAdvance' in the sbit metric */
/* structure isn't set, use `linearXXXAdvance' */ /* structure isn't set, use `linearXXXAdvance' */
if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )

View File

@ -727,7 +727,8 @@
if ( error ) if ( error )
goto Exit; goto Exit;
if ( FT_IS_SCALABLE( ttface ) ) if ( FT_IS_SCALABLE( ttface ) ||
FT_HAS_SBIX( ttface ) )
{ {
#ifdef FT_CONFIG_OPTION_INCREMENTAL #ifdef FT_CONFIG_OPTION_INCREMENTAL
if ( !ttface->internal->incremental_interface ) if ( !ttface->internal->incremental_interface )