diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c index ec7b93510..7d599c118 100644 --- a/src/base/ftsynth.c +++ b/src/base/ftsynth.c @@ -22,6 +22,7 @@ #include FT_INTERNAL_OBJECTS_H #include FT_OUTLINE_H #include FT_BITMAP_H +#include FT_TRUETYPE_TABLES_H /************************************************************************** @@ -92,7 +93,7 @@ FT_Library library; FT_Face face; FT_Error error; - FT_Pos xstr, ystr; + FT_Pos xstr, ystr, ppem; if ( !slot ) @@ -105,22 +106,68 @@ slot->format != FT_GLYPH_FORMAT_BITMAP ) return; - /* some reasonable strength */ - xstr = FT_MulFix( face->units_per_EM, - face->size->metrics.y_scale ) / 24; - ystr = xstr; + /* the value that matches the MS Windows embolden looks. + the larger strength value, the more unintended artifacts increase. + using the integer pixel strength inhibits the blurred outlines. + */ + ppem = face->size->metrics.y_ppem; + ystr = (( ppem - 1 ) / 50 ) << 6; + xstr = ystr + 64; + + /* match to the MS. + the important factor that reduces the text layout difference. */ + slot->metrics.horiAdvance += 1 << 6; + slot->linearHoriAdvance += 1 << 16; if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); + { + error = FT_Outline_EmboldenXY( &slot->outline, xstr, ystr); + if ( error ) + return; +#if 1 + /* MS Windows DirectWrite looks. */ + + slot->metrics.width += xstr; + slot->metrics.height += ystr; + slot->metrics.horiBearingY += ystr; +#else + /* MS Windows GDI looks. */ + if ( ystr != 0 ) /* ppem > 50px */ + { + TT_Header *head_table; + FT_Matrix scale = { 1 << 16, 0, 0, 1 << 16 }; + + /* Elboldened EM square box only increase the width of one pixel. + ( ppem, ppem ) -> embolden -> scale -> ( ppem + 1px, ppem ) + + ( ppem + xstr ) * scale.xx = ppem + 1px + ( ppem + ystr ) * scale.yy = ppem + */ + ppem = ppem << 6; + scale.xx = FT_MulDiv( 1 << 16, ppem + 64, ppem + xstr ); + scale.yy = FT_MulDiv( 1 << 16, ppem , ppem + ystr ); + FT_Outline_Transform( &slot->outline, &scale ); + + /* Undocumented behavior in truetype spec. */ + head_table = FT_Get_Sfnt_Table( face, FT_SFNT_HEAD ); + if ( head_table && head_table->Flags & ( 1 << 4 | 1 << 2 ) ) + slot->metrics.horiAdvance = + FT_MulFix( slot->metrics.horiAdvance, scale.xx ); + } + + { + FT_BBox bbox; + FT_Outline_Get_CBox( &slot->outline, &bbox ); + slot->metrics.width = bbox.xMax - bbox.xMin; + slot->metrics.height = bbox.yMax - bbox.yMin; + slot->metrics.horiBearingX = bbox.xMin; + slot->metrics.horiBearingY = bbox.yMax; + } +#endif + } else /* slot->format == FT_GLYPH_FORMAT_BITMAP */ { - /* round to full pixels */ - xstr &= ~63; - if ( xstr == 0 ) - xstr = 1 << 6; - ystr &= ~63; - /* * XXX: overflow check for 16-bit system, for compatibility * with FT_GlyphSlot_Embolden() since FreeType 2.1.10. @@ -140,23 +187,24 @@ error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr ); if ( error ) return; + + slot->metrics.width += xstr; + slot->metrics.height += ystr; + slot->metrics.horiBearingY += ystr; + + /* XXX: 16-bit overflow case must be excluded before here */ + slot->bitmap_top += (FT_Int)( ystr >> 6 ); } + /* XXX: FT_Set_Transform, FT_GlyphSlot_Embolden combination can + produce different results from intention. Recommend the + FT_Outline_Transform and a manual metrics modification. + */ if ( slot->advance.x ) slot->advance.x += xstr; if ( slot->advance.y ) slot->advance.y += ystr; - - slot->metrics.width += xstr; - slot->metrics.height += ystr; - slot->metrics.horiAdvance += xstr; - slot->metrics.vertAdvance += ystr; - slot->metrics.horiBearingY += ystr; - - /* XXX: 16-bit overflow case must be excluded before here */ - if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) - slot->bitmap_top += (FT_Int)( ystr >> 6 ); }