Skip to content

Commit

Permalink
Fonts: fix hinting with synthesized weight inconsistencies
Browse files Browse the repository at this point in the history
Toggling hinting mode with synthesized weights font could
give unsteady glyphs/words widths, which fails the
expectation that hinting does not need a re-rendering.
This could result in paragraphs overlapping each others.
  • Loading branch information
poire-z committed Apr 6, 2022
1 parent b0fdab3 commit 756ae3c
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions crengine/src/lvfntman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2229,16 +2229,24 @@ class LVFreeTypeFace : public LVFont

if (_synth_weight > 0) {
// Tweak some metrics if synthesized weight
if ( _slot->metrics.horiAdvance > 0 ) {
glyph->width = (lUInt16)( FONT_METRIC_TO_PX( myabs(_slot->metrics.horiAdvance) + _synth_weight_strength ) );
// We can't use _slot->metrics.horiAdvance, which may differ whether hinting or not (if hinting,
// it is rounded to a multiple of 64, otherwise not), and could give different values below when
// rounded to px after we add _synth_weight_strength, resulting in different advances and widths.
// Above, FT_LOAD_TARGET_LIGHT ensures that hinting does not change the rounded advance, which
// allows us to not need a re-rendering when switching hinting modes. We want to keep this
// feature also when synthetic weights are in use.
// So, use linearHoriAdvance, which is "The advance width of the unhinted glyph".
lInt32 advance = _slot->linearHoriAdvance >> 10; // expressed in 16.16 fractional pixels (/64/16)
if ( advance > 0 ) {
glyph->width = (lUInt16)( FONT_METRIC_TO_PX( myabs(advance) + _synth_weight_strength ) );
}
else { // probable diacritic
// Compensate the width added to the previous advancing char
// by making the negative originX more negative
glyph->originX = (lInt16)( FONT_METRIC_TO_PX( _slot->metrics.horiBearingX - _synth_weight_strength ) );
}
if (glyph->blackBoxX != 0)
glyph->rsb = (lInt16)(FONT_METRIC_TO_PX( (myabs(_slot->metrics.horiAdvance) + _synth_weight_strength
glyph->rsb = (lInt16)(FONT_METRIC_TO_PX( (myabs(advance) + _synth_weight_strength
- _slot->metrics.horiBearingX - _slot->metrics.width) ) );
}
return true;
Expand Down Expand Up @@ -2992,7 +3000,10 @@ class LVFreeTypeFace : public LVFont
if (_synth_weight > 0 && is_embolden) {
// Tweak some metrics if synthesized weight
if ( _slot->metrics.horiAdvance > 0 ) {
_slot->metrics.horiAdvance += _synth_weight_strength;
// _slot->metrics.horiAdvance += _synth_weight_strength;
// As in getGlyphInfo(), we need to use _slot->linearHoriAdvance to get
// the same advance/width whether hinting or not
_slot->metrics.horiAdvance = (_slot->linearHoriAdvance >> 10) + _synth_weight_strength;
}
else { // probable diacritic
// Compensate the width added to the previous advancing char
Expand Down Expand Up @@ -3067,7 +3078,10 @@ class LVFreeTypeFace : public LVFont
if ( _slot->format == FT_GLYPH_FORMAT_OUTLINE ) {
// Tweak some metrics if synthesized weight
if ( _slot->metrics.horiAdvance > 0 ) {
_slot->metrics.horiAdvance += _synth_weight_strength;
// _slot->metrics.horiAdvance += _synth_weight_strength;
// As in getGlyphInfo(), we need to use _slot->linearHoriAdvance to get
// the same advance/width whether hinting or not
_slot->metrics.horiAdvance = (_slot->linearHoriAdvance >> 10) + _synth_weight_strength;
// (this won't be used with Harfbuzz, but we'll tweak glyph_pos[hg].x_advance the same way)
}
else { // probable diacritic
Expand Down

0 comments on commit 756ae3c

Please sign in to comment.