Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Unified Diff: third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h

Issue 2077313002: Prevent to measure the whole word when break-all (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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))
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698