Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h |
| diff --git a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h |
| index c123a226e44773465d4dc62328234378a4bce34f..42ffdcb47383e6017fa1a6526cf90139c1d65ea4 100644 |
| --- a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h |
| +++ b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h |
| @@ -116,6 +116,9 @@ public: |
| private: |
| void skipTrailingWhitespace(InlineIterator&, const LineInfo&); |
| + bool shouldMidWordBreak(UChar, LineLayoutText, const Font&, |
| + float& charWidth, float& widthFromLastBreakingOpportunity, |
| + bool breakAll, int& nextBreakablePositionForBreakAll); |
| bool rewindToMidWordBreak(WordMeasurement&, int end, float width); |
| bool rewindToFirstMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&); |
| bool rewindToMidWordBreak(LineLayoutText, const ComputedStyle&, const Font&, bool breakAll, WordMeasurement&); |
| @@ -542,6 +545,36 @@ ALWAYS_INLINE float textWidth(LineLayoutText text, unsigned from, unsigned len, |
| return font.width(run, fallbackFonts, glyphBounds); |
| } |
| +ALWAYS_INLINE bool BreakingContext::shouldMidWordBreak( |
| + UChar c, LineLayoutText layoutText, const Font& font, |
| + float& charWidth, float& widthFromLastBreakingOpportunity, |
| + bool breakAll, int& nextBreakablePositionForBreakAll) |
| +{ |
| + // For breakWords/breakAll, we need to measure up to normal break |
| + // opportunity and then rewindToMidWordBreak() because ligatures/kerning can |
| + // shorten the width as we add more characters. |
| + // However, doing so can hit the performance when a "word" is really long, |
| + // such as minimized JS, because the next line will re-shape the rest of the |
| + // word in the current architecture. |
| + // This function is a heuristic optimization to stop at 2em overflow. |
| + float overflowAllowance = 2 * font.getFontDescription().computedSize(); |
| + |
| + widthFromLastBreakingOpportunity += charWidth; |
| + bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedCharacterAt(m_current.offset() + 1)); |
| + charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreakingOpportunity, m_collapseWhiteSpace); |
| + if (m_width.committedWidth() + widthFromLastBreakingOpportunity + charWidth <= m_width.availableWidth() + overflowAllowance) |
| + return false; |
| + |
|
kojii
2016/07/05 11:37:58
Up to this point in this function is just a move f
|
| + // breakAll has different break opportunities. Ensure we break only at |
| + // breakAll allows to break. |
| + if (breakAll && |
| + !m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), nextBreakablePositionForBreakAll, LineBreakType::BreakAll)) { |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| ALWAYS_INLINE int lastBreakablePositionForBreakAll(LineLayoutText text, |
| const ComputedStyle& style, int start, int end) |
| { |
| @@ -715,6 +748,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool |
| // rewindToMidWordBreak() finds the mid-word break point. |
| LineBreakType lineBreakType = keepAll ? LineBreakType::KeepAll : LineBreakType::Normal; |
| bool canBreakMidWord = breakAll || breakWords; |
| + int nextBreakablePositionForBreakAll = -1; |
| if (layoutText.isWordBreak()) { |
| m_width.commit(); |
| @@ -756,16 +790,8 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool |
| bool applyWordSpacing = false; |
| // Determine if we should try breaking in the middle of a word. |
| - if (breakWords && !midWordBreak && !U16_IS_TRAIL(c)) { |
| - widthFromLastBreakingOpportunity += charWidth; |
| - bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset() + 1 < layoutText.textLength() && U16_IS_TRAIL(layoutText.uncheckedCharacterAt(m_current.offset() + 1)); |
| - charWidth = textWidth(layoutText, m_current.offset(), midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + widthFromLastBreakingOpportunity, m_collapseWhiteSpace); |
| - // Measure up to 2em overflow since ligatures/kerning can shorten |
| - // the width as we add more characters. rewindToMidWordBreak() can |
| - // measure the accurate mid-word break point then. |
| - midWordBreak = m_width.committedWidth() + widthFromLastBreakingOpportunity + charWidth > m_width.availableWidth() |
| - + 2 * font.getFontDescription().computedSize(); |
| - } |
| + if (canBreakMidWord && !midWordBreak && !U16_IS_TRAIL(c)) |
| + midWordBreak = shouldMidWordBreak(c, layoutText, font, charWidth, widthFromLastBreakingOpportunity, breakAll, nextBreakablePositionForBreakAll); |
| // Determine if we are in the whitespace between words. |
| int nextBreakablePosition = m_current.nextBreakablePosition(); |
| @@ -827,10 +853,6 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool |
| m_appliedStartWidth = true; |
| } |
| - // If we haven't hit a breakable position yet and already don't fit on the line try to move below any floats. |
| - if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) |
| - m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
| - |
| midWordBreak = false; |
| if (!m_width.fitsOnLine()) { |
| if (canBreakMidWord) { |
| @@ -854,6 +876,15 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool |
| } |
| } |
| + // If we haven't hit a breakable position yet and already don't fit on the line try to move below any floats. |
| + if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity) { |
| + float availableWidthBefore = m_width.availableWidth(); |
| + m_width.fitBelowFloats(m_lineInfo.isFirstLine()); |
| + // If availableWidth changes by moving the line below floats, needs to measure midWordBreak again. |
| + if (midWordBreak && availableWidthBefore != m_width.availableWidth()) |
| + midWordBreak = false; |
| + } |
|
kojii
2016/07/05 11:37:58
Doing this before rewindToMidWordBreak was the pre
|
| + |
| // If there is a soft-break available at this whitespace position then take it. |
| applyWordSpacing = wordSpacing && m_currentCharacterIsSpace; |
| if (canBreakAtWhitespace(breakWords, wordMeasurement, stoppedIgnoringSpaces, charWidth, hyphenated, disableSoftHyphen, hyphenWidth, betweenWords, midWordBreak, canBreakMidWord, previousCharacterIsSpace, lastWidthMeasurement, layoutText, font, applyWordSpacing, wordSpacing)) |