Changeset 214726 in webkit


Ignore:
Timestamp:
Apr 1, 2017 10:39:29 PM (7 years ago)
Author:
Alan Bujtas
Message:

Long Arabic text in ContentEditable with css white-space=pre hangs Safari
https://bugs.webkit.org/show_bug.cgi?id=170245

Reviewed by Myles C. Maxfield.

While searching for mid-word break, we measure the text by codepoints in a loop until the accumulated width > available width.
When we see that the accumulated width for the individual codepoints overflows, we join the codepoints and re-measure them.
These 2 widths could be considerably different for number of reasons (ligatures is a prime example). When we figure that
the run still fits, we go back to the main loop (since we are not supposed to wrap the line here) and take the next codepoint.
However this time we start the measurement from the last whitespace, so we end up remeasuring a potentially long chuck of text
until we hit the wrapping point. This is way too expensive.
This patch changes the logic so that we just go back to measuring individual codepoints until we hit the constrain again.

Covered by existing tests.

  • rendering/line/BreakingContext.h:

(WebCore::BreakingContext::handleText): canUseSimpleFontCodePath() is just to mitigate the potential risk of regression and
complex text is more likely to fall into this category.

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r214724 r214726  
     12017-04-01  Zalan Bujtas  <zalan@apple.com>
     2
     3        Long Arabic text in ContentEditable with css white-space=pre hangs Safari
     4        https://bugs.webkit.org/show_bug.cgi?id=170245
     5
     6        Reviewed by Myles C. Maxfield.
     7
     8        While searching for mid-word break, we measure the text by codepoints in a loop until the accumulated width > available width.
     9        When we see that the accumulated width for the individual codepoints overflows, we join the codepoints and re-measure them.
     10        These 2 widths could be considerably different for number of reasons (ligatures is a prime example). When we figure that
     11        the run still fits, we go back to the main loop (since we are not supposed to wrap the line here) and take the next codepoint.
     12        However this time we start the measurement from the last whitespace, so we end up remeasuring a potentially long chuck of text
     13        until we hit the wrapping point. This is way too expensive.
     14        This patch changes the logic so that we just go back to measuring individual codepoints until we hit the constrain again. 
     15
     16        Covered by existing tests.
     17
     18        * rendering/line/BreakingContext.h:
     19        (WebCore::BreakingContext::handleText): canUseSimpleFontCodePath() is just to mitigate the potential risk of regression and
     20        complex text is more likely to fall into this category.
     21
    1222017-04-01  Jon Lee  <jonlee@apple.com>
    223
  • trunk/Source/WebCore/rendering/line/BreakingContext.h

    r213944 r214726  
    795795    float wordSpacingForWordMeasurement = 0;
    796796
    797     float wrapW = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, true);
     797    float wrapWidthOffset = m_width.uncommittedWidth() + inlineLogicalWidth(m_current.renderer(), !m_appliedStartWidth, true);
     798    float wrapW = wrapWidthOffset;
    798799    float charWidth = 0;
    799800    bool breakNBSP = m_autoWrap && m_currentStyle->nbspMode() == SPACE;
     
    10291030            if (m_autoWrap && betweenWords) {
    10301031                commitLineBreakAtCurrentWidth(renderObject, m_current.offset(), m_current.nextBreakablePosition());
    1031                 wrapW = 0;
     1032                wrapWidthOffset = 0;
     1033                wrapW = wrapWidthOffset;
    10321034                // Auto-wrapping text should not wrap in the middle of a word once it has had an
    10331035                // opportunity to break after a word.
     
    10611063                }
    10621064            }
    1063            
     1065            // Measuring the width of complex text character-by-character, rather than measuring it all together,
     1066            // could produce considerably different width values.
     1067            if (!renderText.canUseSimpleFontCodePath() && midWordBreak && m_width.fitsOnLine()) {
     1068                midWordBreak = false;
     1069                wrapW = wrapWidthOffset + additionalTempWidth;
     1070            }
    10641071            isLineEmpty = m_lineInfo.isEmpty();
    10651072        } else {
Note: See TracChangeset for help on using the changeset viewer.