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

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

Issue 1538453002: Refactor and comment BreakingContext::handleText() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 68da4d7afdd3e19bac0e64a4a266bb826418b1d1..bbc5ef5e943141bb21d4d4752a140c18650f4a3d 100644
--- a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
+++ b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
@@ -101,6 +101,7 @@ public:
void handleEmptyInline();
void handleReplaced();
bool handleText(WordMeasurements&, bool& hyphenated);
+ void prepareForNextCharacter(const LineLayoutText&, bool& prohibitBreakInside, bool previousCharacterIsSpace, bool previousCharacterShouldCollapseIfPreWap);
void commitAndUpdateLineBreakIfNeeded();
InlineIterator handleEndOfLine();
@@ -545,8 +546,6 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
LineLayoutText layoutText(m_current.object());
- bool isSVGText = layoutText.isSVGInlineText();
-
// If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
// then we need to mark the start of the autowrap inline as a potential linebreak now.
if (m_autoWrap && !ComputedStyle::autoWrap(m_lastWS) && m_ignoringSpaces) {
@@ -580,7 +579,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
float hyphenWidth = 0;
- if (isSVGText) {
+ if (layoutText.isSVGInlineText()) {
breakWords = false;
breakAll = false;
keepAll = false;
@@ -635,187 +634,172 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
bool betweenWords = c == newlineCharacter || (m_currWS != PRE && !m_atStart && m_layoutTextInfo.m_lineBreakIterator.isBreakable(m_current.offset(), nextBreakablePosition, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Normal));
m_current.setNextBreakablePosition(nextBreakablePosition);
- if (betweenWords || midWordBreak) {
- bool stoppedIgnoringSpaces = false;
+ // If we're in the middle of a word or at the start of a new one and can't break there, then continue to the next character.
+ if (!betweenWords && !midWordBreak) {
if (m_ignoringSpaces) {
- lastSpaceWordSpacing = 0;
- if (!m_currentCharacterIsSpace) {
- // Stop ignoring spaces and begin at this
- // new point.
- m_ignoringSpaces = false;
- wordSpacingForWordMeasurement = 0;
- lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
- m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
- stoppedIgnoringSpaces = true;
- } else {
- // Just keep ignoring these spaces.
- nextCharacter(c, lastCharacter, secondToLastCharacter);
- continue;
- }
+ // Stop ignoring spaces and begin at this
+ // new point.
+ m_ignoringSpaces = false;
+ lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+ wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
+ lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
+ m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
}
- wordMeasurements.grow(wordMeasurements.size() + 1);
- WordMeasurement& wordMeasurement = wordMeasurements.last();
+ prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharacterIsSpace, previousCharacterShouldCollapseIfPreWap);
+ m_atStart = false;
+ nextCharacter(c, lastCharacter, secondToLastCharacter);
+ continue;
+ }
- wordMeasurement.layoutText = layoutText;
- wordMeasurement.endOffset = m_current.offset();
- wordMeasurement.startOffset = lastSpace;
+ // If we're ignoring space and we're at a collapsible space such as a space or tab, continue to the next character.
+ bool stoppedIgnoringSpaces = false;
+ if (m_ignoringSpaces) {
+ lastSpaceWordSpacing = 0;
+ if (!m_currentCharacterIsSpace) {
+ // Stop ignoring spaces and begin at this
+ // new point.
+ m_ignoringSpaces = false;
+ wordSpacingForWordMeasurement = 0;
+ lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
+ m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
+ stoppedIgnoringSpaces = true;
+ } else {
+ // Just keep ignoring these spaces.
+ nextCharacter(c, lastCharacter, secondToLastCharacter);
+ continue;
+ }
+ }
- float lastWidthMeasurement;
- if (wordTrailingSpaceWidth && c == spaceCharacter)
- lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWidth;
- else
- lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds);
+ // We're in the first whitespace after a word or in whitespace that we don't collapse, which means we may have a breaking opportunity here.
+ wordMeasurements.grow(wordMeasurements.size() + 1);
+ WordMeasurement& wordMeasurement = wordMeasurements.last();
- wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasurement;
- wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0);
- lastWidthMeasurement += lastSpaceWordSpacing;
- m_width.addUncommittedWidth(lastWidthMeasurement);
+ wordMeasurement.layoutText = layoutText;
+ wordMeasurement.endOffset = m_current.offset();
+ wordMeasurement.startOffset = lastSpace;
- if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && lastWidthMeasurement)
- m_width.setTrailingWhitespaceWidth(lastWidthMeasurement);
+ float lastWidthMeasurement;
+ if (wordTrailingSpaceWidth && c == spaceCharacter)
+ lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset() + 1 - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) - wordTrailingSpaceWidth;
+ else
+ lastWidthMeasurement = textWidth(layoutText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds);
- if (!m_appliedStartWidth) {
- m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded(m_current.object(), true, false).toFloat());
- m_appliedStartWidth = true;
- }
+ wordMeasurement.width = lastWidthMeasurement + wordSpacingForWordMeasurement;
+ wordMeasurement.glyphBounds.move(wordSpacingForWordMeasurement, 0);
+ lastWidthMeasurement += lastSpaceWordSpacing;
+ m_width.addUncommittedWidth(lastWidthMeasurement);
- applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
+ if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && lastWidthMeasurement)
+ m_width.setTrailingWhitespaceWidth(lastWidthMeasurement);
- if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity)
- m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+ if (!m_appliedStartWidth) {
+ m_width.addUncommittedWidth(inlineLogicalWidthFromAncestorsIfNeeded(m_current.object(), true, false).toFloat());
+ m_appliedStartWidth = true;
+ }
- if (m_autoWrap || breakWords) {
- // If we break only after white-space, consider the current character
- // as candidate width for this line.
- bool lineWasTooWide = false;
- if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
- float charWidth = textWidth(layoutText, m_current.offset(), 1, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0);
- // Check if line is too big even without the extra space
- // at the end of the line. If it is not, do nothing.
- // If the line needs the extra whitespace to be too long,
- // then move the line break to the space and skip all
- // additional whitespace.
- if (!m_width.fitsOnLine(charWidth)) {
- lineWasTooWide = true;
- m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
- skipTrailingWhitespace(m_lineBreak, m_lineInfo);
- }
+ applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
+
+ if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine() && !widthMeasurementAtLastBreakOpportunity)
+ m_width.fitBelowFloats(m_lineInfo.isFirstLine());
+
+ if (m_autoWrap || breakWords) {
+ // If we break only after white-space, consider the current character
+ // as candidate width for this line.
+ bool lineWasTooWide = false;
+ if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
+ float charWidth = textWidth(layoutText, m_current.offset(), 1, font, m_width.currentWidth(), m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, &wordMeasurement.glyphBounds) + (applyWordSpacing ? wordSpacing : 0);
+ // Check if line is too big even without the extra space
+ // at the end of the line. If it is not, do nothing.
+ // If the line needs the extra whitespace to be too long,
+ // then move the line break to the space and skip all
+ // additional whitespace.
+ if (!m_width.fitsOnLine(charWidth)) {
+ lineWasTooWide = true;
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ skipTrailingWhitespace(m_lineBreak, m_lineInfo);
+ }
+ }
+ if (lineWasTooWide || !m_width.fitsOnLine()) {
+ if (m_lineBreak.atTextParagraphSeparator()) {
+ if (!stoppedIgnoringSpaces && m_current.offset() > 0)
+ m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
+ m_lineBreak.increment();
+ m_lineInfo.setPreviousLineBrokeCleanly(true);
+ wordMeasurement.endOffset = m_lineBreak.offset();
}
- if (lineWasTooWide || !m_width.fitsOnLine()) {
- if (m_lineBreak.atTextParagraphSeparator()) {
- if (!stoppedIgnoringSpaces && m_current.offset() > 0)
- m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
- m_lineBreak.increment();
- m_lineInfo.setPreviousLineBrokeCleanly(true);
+ if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.object().isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLayoutText(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyphenCharacter)
+ hyphenated = true;
+ if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
+ if (charWidth) {
wordMeasurement.endOffset = m_lineBreak.offset();
- }
- if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.object().isText() && LineLayoutText(m_lineBreak.object()).textLength() && LineLayoutText(m_lineBreak.object()).characterAt(m_lineBreak.offset() - 1) == softHyphenCharacter)
- hyphenated = true;
- if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
- if (charWidth) {
- wordMeasurement.endOffset = m_lineBreak.offset();
- wordMeasurement.width = charWidth;
- }
- }
- // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
- if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSpace || !previousCharacterIsSpace) {
- m_atEnd = true;
- return false;
- }
- } else {
- if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll && !m_currentCharacterIsSpace))
- m_width.addUncommittedWidth(-lastWidthMeasurement);
- if (hyphenWidth) {
- // Subtract the width of the soft hyphen out since we fit on a line.
- m_width.addUncommittedWidth(-hyphenWidth);
- hyphenWidth = 0;
+ wordMeasurement.width = charWidth;
}
}
- }
-
- if (c == newlineCharacter && m_preservesNewline) {
- if (!stoppedIgnoringSpaces && m_current.offset())
- m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
- m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
- m_lineBreak.increment();
- m_lineInfo.setPreviousLineBrokeCleanly(true);
- return true;
- }
-
- if (m_autoWrap && betweenWords) {
- m_width.commit();
- widthFromLastBreakingOpportunity = 0;
- m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
- // Auto-wrapping text should not wrap in the middle of a word once it has had an
- // opportunity to break after a word.
- breakWords = false;
- widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement;
- }
-
- if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (WTF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark_SpacingCombining))) {
- // Remember this as a breakable position in case
- // adding the end width forces a break.
- m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
- midWordBreak &= (breakWords || breakAll);
- }
-
- if (betweenWords) {
- lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
- wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
- lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offset() : lastSpace;
- }
-
- if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
- // If we encounter a newline, or if we encounter a
- // second space, we need to go ahead and break up this
- // run and enter a mode where we start collapsing spaces.
- if (m_currentCharacterIsSpace && previousCharacterIsSpace) {
- m_ignoringSpaces = true;
-
- // We just entered a mode where we are ignoring
- // spaces. Create a midpoint to terminate the run
- // before the second space.
- m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
- m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
+ // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
+ if (m_ignoringSpaces || !m_collapseWhiteSpace || !m_currentCharacterIsSpace || !previousCharacterIsSpace) {
+ m_atEnd = true;
+ return false;
+ }
+ } else {
+ if (!betweenWords || (midWordBreak && !m_autoWrap) || (breakAll && !m_currentCharacterIsSpace))
+ m_width.addUncommittedWidth(-lastWidthMeasurement);
+ if (hyphenWidth) {
+ // Subtract the width of the soft hyphen out since we fit on a line.
+ m_width.addUncommittedWidth(-hyphenWidth);
+ hyphenWidth = 0;
}
}
- } else if (m_ignoringSpaces) {
- // Stop ignoring spaces and begin at this
- // new point.
- m_ignoringSpaces = false;
- lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
- wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
- lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
- m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
}
- if (isSVGText && m_current.offset()) {
- // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
- if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_current.offset()))
+ if (c == newlineCharacter && m_preservesNewline) {
+ if (!stoppedIgnoringSpaces && m_current.offset())
m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ m_lineBreak.increment();
+ m_lineInfo.setPreviousLineBrokeCleanly(true);
+ return true;
}
- if (prohibitBreakInside) {
- m_current.setNextBreakablePosition(layoutText.textLength());
- prohibitBreakInside = false;
+ if (m_autoWrap && betweenWords) {
+ m_width.commit();
+ widthFromLastBreakingOpportunity = 0;
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ // Auto-wrapping text should not wrap in the middle of a word once it has had an
+ // opportunity to break after a word.
+ breakWords = false;
+ widthMeasurementAtLastBreakOpportunity = lastWidthMeasurement;
}
- if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
- m_startOfIgnoredSpaces.setObject(m_current.object());
- m_startOfIgnoredSpaces.setOffset(m_current.offset());
+ if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (WTF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark_SpacingCombining))) {
+ // Remember this as a breakable position in case
+ // adding the end width forces a break.
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ midWordBreak &= (breakWords || breakAll);
}
- if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) {
- if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
- m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ if (betweenWords) {
+ lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+ wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
+ lastSpace = !breakAll || m_currentCharacterIsSpace ? m_current.offset() : lastSpace;
}
- if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
- m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object()));
- else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace)
- m_trailingObjects.clear();
+ if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
+ // If we encounter a newline, or if we encounter a
+ // second space, we need to go ahead and break up this
+ // run and enter a mode where we start collapsing spaces.
+ if (m_currentCharacterIsSpace && previousCharacterIsSpace) {
+ m_ignoringSpaces = true;
+
+ // We just entered a mode where we are ignoring
+ // spaces. Create a midpoint to terminate the run
+ // before the second space.
+ m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
+ m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
+ }
+ }
+ prepareForNextCharacter(layoutText, prohibitBreakInside, previousCharacterIsSpace, previousCharacterShouldCollapseIfPreWap);
m_atStart = false;
nextCharacter(c, lastCharacter, secondToLastCharacter);
}
@@ -859,6 +843,32 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
return false;
}
+inline void BreakingContext::prepareForNextCharacter(const LineLayoutText& layoutText, bool& prohibitBreakInside, bool previousCharacterIsSpace, bool previousCharacterShouldCollapseIfPreWap)
+{
+ if (layoutText.isSVGInlineText() && m_current.offset()) {
+ // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
+ if (LineLayoutSVGInlineText(layoutText).characterStartsNewTextChunk(m_current.offset()))
+ m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
+ }
+ if (prohibitBreakInside) {
+ m_current.setNextBreakablePosition(layoutText.textLength());
+ prohibitBreakInside = false;
+ }
+ if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
+ m_startOfIgnoredSpaces.setObject(m_current.object());
+ m_startOfIgnoredSpaces.setOffset(m_current.offset());
+ }
+ if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) {
+ if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
+ }
+ if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
+ m_trailingObjects.setTrailingWhitespace(LineLayoutText(m_current.object()));
+ else if (!m_currentStyle->collapseWhiteSpace() || !m_currentCharacterIsSpace)
+ m_trailingObjects.clear();
+}
+
+
inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
{
bool checkForBreak = m_autoWrap;
« 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