Changeset 63357 in webkit


Ignore:
Timestamp:
Jul 14, 2010, 2:41:02 PM (15 years ago)
Author:
mitz@apple.com
Message:

<rdar://problem/7759909> Certain text runs measure 1 pixel wider when measured as a whole than when measured piecewise
https://bugs.webkit.org/show_bug.cgi?id=42279

Reviewed by Simon Fraser.

No test because the issue cannot be reproduced with standard fonts.

Word- and run-rounding works by advancing ahead to the nearest integral width. As the total
width accumulated becomes large, the float type’s low precision results in accumulated rounding
error, sometimes crossing an integer. Consequently, word-rounding makes different decisions when
measuring a multi-word run than when measuring its words individually. To work around this,
word- and run-rounding are applied only to the width accumulated since the last rounding
character.

  • platform/graphics/WidthIterator.cpp:

(WebCore::WidthIterator::advance):

  • platform/graphics/mac/ComplexTextController.cpp:

(WebCore::ComplexTextController::adjustGlyphsAndAdvances):

Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r63356 r63357  
     12010-07-14  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        <rdar://problem/7759909> Certain text runs measure 1 pixel wider when measured as a whole than when measured piecewise
     6        https://bugs.webkit.org/show_bug.cgi?id=42279
     7
     8        No test because the issue cannot be reproduced with standard fonts.
     9
     10        Word- and run-rounding works by advancing ahead to the nearest integral width. As the total
     11        width accumulated becomes large, the float type’s low precision results in accumulated rounding
     12        error, sometimes crossing an integer. Consequently, word-rounding makes different decisions when
     13        measuring a multi-word run than when measuring its words individually. To work around this,
     14        word- and run-rounding are applied only to the width accumulated since the last rounding
     15        character.
     16
     17        * platform/graphics/WidthIterator.cpp:
     18        (WebCore::WidthIterator::advance):
     19        * platform/graphics/mac/ComplexTextController.cpp:
     20        (WebCore::ComplexTextController::adjustGlyphsAndAdvances):
     21
    1222010-07-14  Tony Gentilcore  <tonyg@chromium.org>
    223
  • trunk/WebCore/platform/graphics/WidthIterator.cpp

    r62100 r63357  
    8585    bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_padding) && !m_run.spacingDisabled();
    8686
    87     float runWidthSoFar = m_runWidthSoFar;
     87    float widthSinceLastRounding = m_runWidthSoFar;
     88    m_runWidthSoFar = floorf(m_runWidthSoFar);
     89    widthSinceLastRounding -= m_runWidthSoFar;
     90
    8891    float lastRoundingWidth = m_finalRoundingWidth;
    8992    FloatRect bounds;
     
    132135        if (c == '\t' && m_run.allowTabs()) {
    133136            float tabWidth = m_font->tabWidth();
    134             width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth);
     137            width = tabWidth - fmodf(m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding, tabWidth);
    135138        } else {
    136139            width = fontData->widthForGlyph(glyph);
     
    217220        if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
    218221                || (m_run.applyRunRounding() && currentCharacter >= m_end)) {
    219             float totalWidth = runWidthSoFar + width;
    220             width += ceilf(totalWidth) - totalWidth;
    221         }
    222 
    223         runWidthSoFar += width;
     222            float totalWidth = widthSinceLastRounding + width;
     223            widthSinceLastRounding = ceilf(totalWidth);
     224            width += widthSinceLastRounding - totalWidth;
     225            m_runWidthSoFar += widthSinceLastRounding;
     226            widthSinceLastRounding = 0;
     227        } else
     228            widthSinceLastRounding += width;
    224229
    225230        if (glyphBuffer)
     
    236241
    237242    m_currentCharacter = currentCharacter;
    238     m_runWidthSoFar = runWidthSoFar;
     243    m_runWidthSoFar += widthSinceLastRounding;
    239244    m_finalRoundingWidth = lastRoundingWidth;
    240245}
  • trunk/WebCore/platform/graphics/mac/ComplexTextController.cpp

    r61441 r63357  
    432432void ComplexTextController::adjustGlyphsAndAdvances()
    433433{
     434    CGFloat widthSinceLastRounding = 0;
    434435    size_t runCount = m_complexTextRuns.size();
    435436    for (size_t r = 0; r < runCount; ++r) {
     
    475476            if (ch == '\t' && m_run.allowTabs()) {
    476477                float tabWidth = m_font.tabWidth();
    477                 advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);
     478                advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth + widthSinceLastRounding, tabWidth);
    478479            } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
    479480                advance.width = 0;
     
    533534            // width so that the total run width will be on an integer boundary.
    534535            if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) {
    535                 CGFloat totalWidth = m_totalWidth + advance.width;
    536                 CGFloat extraWidth = ceilCGFloat(totalWidth) - totalWidth;
     536                CGFloat totalWidth = widthSinceLastRounding + advance.width;
     537                widthSinceLastRounding = ceilCGFloat(totalWidth);
     538                CGFloat extraWidth = widthSinceLastRounding - totalWidth;
    537539                if (m_run.ltr())
    538540                    advance.width += extraWidth;
    539541                else {
    540                     m_totalWidth += extraWidth;
    541542                    if (m_lastRoundingGlyph)
    542543                        m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth;
     
    545546                    m_lastRoundingGlyph = m_adjustedAdvances.size() + 1;
    546547                }
    547             }
    548 
    549             m_totalWidth += advance.width;
     548                m_totalWidth += widthSinceLastRounding;
     549                widthSinceLastRounding = 0;
     550            } else
     551                widthSinceLastRounding += advance.width;
     552
    550553            advance.height *= -1;
    551554            m_adjustedAdvances.append(advance);
     
    566569            complexTextRun.setIsNonMonotonic();
    567570    }
     571    m_totalWidth += widthSinceLastRounding;
    568572}
    569573
Note: See TracChangeset for help on using the changeset viewer.