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

Unified Diff: third_party/WebKit/Source/core/layout/LayoutText.cpp

Issue 1994483002: Compute min-content width when hyphenation is enabled (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test Created 4 years, 7 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
Index: third_party/WebKit/Source/core/layout/LayoutText.cpp
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp
index a1edc563a28cd844b0ffe4740927ae1547551cc4..03125c662bed77c4a6dd2f77b77befdf0beeaf56 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -41,10 +41,12 @@
#include "core/layout/line/InlineTextBox.h"
#include "core/paint/PaintLayer.h"
#include "platform/LayoutTestSupport.h"
+#include "platform/fonts/CharacterRange.h"
#include "platform/fonts/FontCache.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/text/BidiResolver.h"
#include "platform/text/Character.h"
+#include "platform/text/Hyphenation.h"
#include "platform/text/TextBreakIterator.h"
#include "platform/text/TextRunIterator.h"
#include "wtf/text/CharacterNames.h"
@@ -863,6 +865,49 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth)
computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds);
}
+static float maxWordFragmentWidth(LayoutText* layoutText,
eae 2016/05/18 17:53:37 This method contains much of the same logic as Bre
+ const ComputedStyle& style, const Font& font, TextDirection textDirection,
+ Hyphenation& hyphenation, unsigned wordOffset, unsigned wordLength,
+ int& suffixStart)
+{
+ suffixStart = 0;
+ const unsigned minimumPrefixLength = 2;
+ const unsigned minimumSuffixLength = 2;
+ if (wordLength <= minimumSuffixLength)
+ return 0;
+
+ StringView word = layoutText->text().createView(wordOffset, wordLength);
+ Vector<size_t, 8> hyphenLocations = hyphenation.hyphenLocations(word,
+ minimumPrefixLength, minimumSuffixLength);
+ if (hyphenLocations.isEmpty())
+ return 0;
+
+ // Narrow prefixes are ignored. See hyphenate in BreakingContextInlineHeaders.h.
+ const int minPrefixWidthNumerator = 5;
+ const int minPrefixWidthDenominator = 4;
+ float minimumFragmentWidthToConsider = font.getFontDescription().computedSize()
+ * minPrefixWidthNumerator / minPrefixWidthDenominator;
+ float maxFragmentWidth = 0;
+
+ // TODO(kojii): getCharacterRange() measures as if the word were not broken
+ // as defined in the spec, and is faster than measuring each fragment, but
+ // ignores the kerning between the last letter and the hyphen.
+ TextRun run = constructTextRun(font, layoutText, wordOffset, wordLength, style, textDirection);
+ size_t end = wordLength;
+ for (size_t start : hyphenLocations) {
+ CharacterRange range = font.getCharacterRange(run, start, end);
+ float fragmentWidth = range.width();
+
+ if (fragmentWidth <= minimumFragmentWidthToConsider)
+ continue;
+
+ maxFragmentWidth = std::max(maxFragmentWidth, fragmentWidth);
+ end = start;
+ }
+ suffixStart = hyphenLocations.first();
+ return maxFragmentWidth + layoutText->hyphenWidth(font, textDirection);
+}
+
void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, FloatRect& glyphBounds)
{
ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
@@ -901,6 +946,13 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.wordBreak() == BreakWordBreak) && styleToUse.autoWrap();
bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.autoWrap();
+ Hyphenation* hyphenation = styleToUse.getHyphens() == HyphensAuto
+ ? Hyphenation::get(f.getFontDescription().locale()) : nullptr;
+ bool disableSoftHyphen = styleToUse.getHyphens() == HyphensNone;
+ float maxWordWidth = 0;
+ if (!hyphenation)
+ maxWordWidth = std::numeric_limits<float>::max();
+
BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
BidiCharacterRun* run;
TextDirection textDirection = styleToUse.direction();
@@ -974,7 +1026,7 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
lastWordBoundary++;
continue;
}
- if (c == softHyphenCharacter) {
+ if (c == softHyphenCharacter && !disableSoftHyphen) {
currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
lastWordBoundary = i + 1;
continue;
@@ -983,7 +1035,7 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
bool hasBreak = breakIterator.isBreakable(i, nextBreakable, breakAll ? LineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Normal);
bool betweenWords = true;
int j = i;
- while (c != newlineCharacter && c != spaceCharacter && c != tabulationCharacter && (c != softHyphenCharacter)) {
+ while (c != newlineCharacter && c != spaceCharacter && c != tabulationCharacter && (c != softHyphenCharacter || disableSoftHyphen)) {
j++;
if (j == len)
break;
@@ -1018,10 +1070,27 @@ void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth;
} else {
w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
- if (c == softHyphenCharacter)
+ if (c == softHyphenCharacter && !disableSoftHyphen)
currMinWidth += hyphenWidth(f, textDirection);
}
+ if (w > maxWordWidth) {
+ int suffixStart;
+ float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, textDirection, *hyphenation, i, wordLen, suffixStart);
+ if (suffixStart) {
+ float suffixWidth;
+ if (wordTrailingSpaceWidth && isSpace)
+ suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth;
+ else
+ suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
+ maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth);
+ currMinWidth += maxFragmentWidth - w;
+ maxWordWidth = std::max(maxWordWidth, maxFragmentWidth);
+ } else {
+ maxWordWidth = w;
+ }
+ }
+
currMinWidth += w;
if (betweenWords) {
if (lastWordBoundary == i)

Powered by Google App Engine
This is Rietveld 408576698