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

Side by Side 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * (C) 1999 Lars Knoll (knoll@kde.org) 2 * (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Dirk Mueller (mueller@kde.org) 3 * (C) 2000 Dirk Mueller (mueller@kde.org)
4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) 6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 23 matching lines...) Expand all
34 #include "core/layout/LayoutBlock.h" 34 #include "core/layout/LayoutBlock.h"
35 #include "core/layout/LayoutTextCombine.h" 35 #include "core/layout/LayoutTextCombine.h"
36 #include "core/layout/LayoutView.h" 36 #include "core/layout/LayoutView.h"
37 #include "core/layout/api/LineLayoutBox.h" 37 #include "core/layout/api/LineLayoutBox.h"
38 #include "core/layout/line/AbstractInlineTextBox.h" 38 #include "core/layout/line/AbstractInlineTextBox.h"
39 #include "core/layout/line/EllipsisBox.h" 39 #include "core/layout/line/EllipsisBox.h"
40 #include "core/layout/line/GlyphOverflow.h" 40 #include "core/layout/line/GlyphOverflow.h"
41 #include "core/layout/line/InlineTextBox.h" 41 #include "core/layout/line/InlineTextBox.h"
42 #include "core/paint/PaintLayer.h" 42 #include "core/paint/PaintLayer.h"
43 #include "platform/LayoutTestSupport.h" 43 #include "platform/LayoutTestSupport.h"
44 #include "platform/fonts/CharacterRange.h"
44 #include "platform/fonts/FontCache.h" 45 #include "platform/fonts/FontCache.h"
45 #include "platform/geometry/FloatQuad.h" 46 #include "platform/geometry/FloatQuad.h"
46 #include "platform/text/BidiResolver.h" 47 #include "platform/text/BidiResolver.h"
47 #include "platform/text/Character.h" 48 #include "platform/text/Character.h"
49 #include "platform/text/Hyphenation.h"
48 #include "platform/text/TextBreakIterator.h" 50 #include "platform/text/TextBreakIterator.h"
49 #include "platform/text/TextRunIterator.h" 51 #include "platform/text/TextRunIterator.h"
50 #include "wtf/text/CharacterNames.h" 52 #include "wtf/text/CharacterNames.h"
51 #include "wtf/text/StringBuffer.h" 53 #include "wtf/text/StringBuffer.h"
52 #include "wtf/text/StringBuilder.h" 54 #include "wtf/text/StringBuilder.h"
53 55
54 using namespace WTF; 56 using namespace WTF;
55 using namespace Unicode; 57 using namespace Unicode;
56 58
57 namespace blink { 59 namespace blink {
(...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 return m_maxWidth; 858 return m_maxWidth;
857 } 859 }
858 860
859 void LayoutText::computePreferredLogicalWidths(float leadWidth) 861 void LayoutText::computePreferredLogicalWidths(float leadWidth)
860 { 862 {
861 HashSet<const SimpleFontData*> fallbackFonts; 863 HashSet<const SimpleFontData*> fallbackFonts;
862 FloatRect glyphBounds; 864 FloatRect glyphBounds;
863 computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds); 865 computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds);
864 } 866 }
865 867
868 static float maxWordFragmentWidth(LayoutText* layoutText,
eae 2016/05/18 17:53:37 This method contains much of the same logic as Bre
869 const ComputedStyle& style, const Font& font, TextDirection textDirection,
870 Hyphenation& hyphenation, unsigned wordOffset, unsigned wordLength,
871 int& suffixStart)
872 {
873 suffixStart = 0;
874 const unsigned minimumPrefixLength = 2;
875 const unsigned minimumSuffixLength = 2;
876 if (wordLength <= minimumSuffixLength)
877 return 0;
878
879 StringView word = layoutText->text().createView(wordOffset, wordLength);
880 Vector<size_t, 8> hyphenLocations = hyphenation.hyphenLocations(word,
881 minimumPrefixLength, minimumSuffixLength);
882 if (hyphenLocations.isEmpty())
883 return 0;
884
885 // Narrow prefixes are ignored. See hyphenate in BreakingContextInlineHeader s.h.
886 const int minPrefixWidthNumerator = 5;
887 const int minPrefixWidthDenominator = 4;
888 float minimumFragmentWidthToConsider = font.getFontDescription().computedSiz e()
889 * minPrefixWidthNumerator / minPrefixWidthDenominator;
890 float maxFragmentWidth = 0;
891
892 // TODO(kojii): getCharacterRange() measures as if the word were not broken
893 // as defined in the spec, and is faster than measuring each fragment, but
894 // ignores the kerning between the last letter and the hyphen.
895 TextRun run = constructTextRun(font, layoutText, wordOffset, wordLength, sty le, textDirection);
896 size_t end = wordLength;
897 for (size_t start : hyphenLocations) {
898 CharacterRange range = font.getCharacterRange(run, start, end);
899 float fragmentWidth = range.width();
900
901 if (fragmentWidth <= minimumFragmentWidthToConsider)
902 continue;
903
904 maxFragmentWidth = std::max(maxFragmentWidth, fragmentWidth);
905 end = start;
906 }
907 suffixStart = hyphenLocations.first();
908 return maxFragmentWidth + layoutText->hyphenWidth(font, textDirection);
909 }
910
866 void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si mpleFontData*>& fallbackFonts, FloatRect& glyphBounds) 911 void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si mpleFontData*>& fallbackFonts, FloatRect& glyphBounds)
867 { 912 {
868 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow AndNoFallbackFonts); 913 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow AndNoFallbackFonts);
869 914
870 m_minWidth = 0; 915 m_minWidth = 0;
871 m_maxWidth = 0; 916 m_maxWidth = 0;
872 m_firstLineMinWidth = 0; 917 m_firstLineMinWidth = 0;
873 m_lastLineLineMinWidth = 0; 918 m_lastLineLineMinWidth = 0;
874 919
875 if (isBR()) 920 if (isBR())
(...skipping 18 matching lines...) Expand all
894 bool isSpace = false; 939 bool isSpace = false;
895 bool firstWord = true; 940 bool firstWord = true;
896 bool firstLine = true; 941 bool firstLine = true;
897 int nextBreakable = -1; 942 int nextBreakable = -1;
898 int lastWordBoundary = 0; 943 int lastWordBoundary = 0;
899 float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL 944 float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL
900 945
901 bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.w ordBreak() == BreakWordBreak) && styleToUse.autoWrap(); 946 bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.w ordBreak() == BreakWordBreak) && styleToUse.autoWrap();
902 bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.auto Wrap(); 947 bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.auto Wrap();
903 948
949 Hyphenation* hyphenation = styleToUse.getHyphens() == HyphensAuto
950 ? Hyphenation::get(f.getFontDescription().locale()) : nullptr;
951 bool disableSoftHyphen = styleToUse.getHyphens() == HyphensNone;
952 float maxWordWidth = 0;
953 if (!hyphenation)
954 maxWordWidth = std::numeric_limits<float>::max();
955
904 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; 956 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
905 BidiCharacterRun* run; 957 BidiCharacterRun* run;
906 TextDirection textDirection = styleToUse.direction(); 958 TextDirection textDirection = styleToUse.direction();
907 if ((is8Bit() && textDirection == LTR) || isOverride(styleToUse.unicodeBidi( ))) { 959 if ((is8Bit() && textDirection == LTR) || isOverride(styleToUse.unicodeBidi( ))) {
908 run = 0; 960 run = 0;
909 } else { 961 } else {
910 TextRun textRun(text()); 962 TextRun textRun(text());
911 BidiStatus status(textDirection, false); 963 BidiStatus status(textDirection, false);
912 bidiResolver.setStatus(status); 964 bidiResolver.setStatus(status);
913 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0)); 965 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 1019
968 if (ignoringSpaces && !isSpace) 1020 if (ignoringSpaces && !isSpace)
969 ignoringSpaces = false; 1021 ignoringSpaces = false;
970 1022
971 // Ignore spaces and soft hyphens 1023 // Ignore spaces and soft hyphens
972 if (ignoringSpaces) { 1024 if (ignoringSpaces) {
973 ASSERT(lastWordBoundary == i); 1025 ASSERT(lastWordBoundary == i);
974 lastWordBoundary++; 1026 lastWordBoundary++;
975 continue; 1027 continue;
976 } 1028 }
977 if (c == softHyphenCharacter) { 1029 if (c == softHyphenCharacter && !disableSoftHyphen) {
978 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBound ary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); 1030 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBound ary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
979 lastWordBoundary = i + 1; 1031 lastWordBoundary = i + 1;
980 continue; 1032 continue;
981 } 1033 }
982 1034
983 bool hasBreak = breakIterator.isBreakable(i, nextBreakable, breakAll ? L ineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Norma l); 1035 bool hasBreak = breakIterator.isBreakable(i, nextBreakable, breakAll ? L ineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Norma l);
984 bool betweenWords = true; 1036 bool betweenWords = true;
985 int j = i; 1037 int j = i;
986 while (c != newlineCharacter && c != spaceCharacter && c != tabulationCh aracter && (c != softHyphenCharacter)) { 1038 while (c != newlineCharacter && c != spaceCharacter && c != tabulationCh aracter && (c != softHyphenCharacter || disableSoftHyphen)) {
987 j++; 1039 j++;
988 if (j == len) 1040 if (j == len)
989 break; 1041 break;
990 c = uncheckedCharacterAt(j); 1042 c = uncheckedCharacterAt(j);
991 if (breakIterator.isBreakable(j, nextBreakable) && characterAt(j - 1 ) != softHyphenCharacter) 1043 if (breakIterator.isBreakable(j, nextBreakable) && characterAt(j - 1 ) != softHyphenCharacter)
992 break; 1044 break;
993 if (breakAll) { 1045 if (breakAll) {
994 betweenWords = false; 1046 betweenWords = false;
995 break; 1047 break;
996 } 1048 }
(...skipping 14 matching lines...) Expand all
1011 if (!cachedWordTrailingSpaceWidth[textDirection]) 1063 if (!cachedWordTrailingSpaceWidth[textDirection])
1012 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr uctTextRun(f, &spaceCharacter, 1, styleToUse, textDirection)) + wordSpacing; 1064 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr uctTextRun(f, &spaceCharacter, 1, styleToUse, textDirection)) + wordSpacing;
1013 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect ion]; 1065 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect ion];
1014 } 1066 }
1015 1067
1016 float w; 1068 float w;
1017 if (wordTrailingSpaceWidth && isSpace) { 1069 if (wordTrailingSpaceWidth && isSpace) {
1018 w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, te xtDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth; 1070 w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, te xtDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth;
1019 } else { 1071 } else {
1020 w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDi rection, &fallbackFonts, &glyphBounds); 1072 w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDi rection, &fallbackFonts, &glyphBounds);
1021 if (c == softHyphenCharacter) 1073 if (c == softHyphenCharacter && !disableSoftHyphen)
1022 currMinWidth += hyphenWidth(f, textDirection); 1074 currMinWidth += hyphenWidth(f, textDirection);
1023 } 1075 }
1024 1076
1077 if (w > maxWordWidth) {
1078 int suffixStart;
1079 float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, textDirection, *hyphenation, i, wordLen, suffixStart);
1080 if (suffixStart) {
1081 float suffixWidth;
1082 if (wordTrailingSpaceWidth && isSpace)
1083 suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyp hBounds) - wordTrailingSpaceWidth;
1084 else
1085 suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBou nds);
1086 maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth);
1087 currMinWidth += maxFragmentWidth - w;
1088 maxWordWidth = std::max(maxWordWidth, maxFragmentWidth);
1089 } else {
1090 maxWordWidth = w;
1091 }
1092 }
1093
1025 currMinWidth += w; 1094 currMinWidth += w;
1026 if (betweenWords) { 1095 if (betweenWords) {
1027 if (lastWordBoundary == i) 1096 if (lastWordBoundary == i)
1028 currMaxWidth += w; 1097 currMaxWidth += w;
1029 else 1098 else
1030 currMaxWidth += widthFromFont(f, lastWordBoundary, j - lastW ordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBound s); 1099 currMaxWidth += widthFromFont(f, lastWordBoundary, j - lastW ordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBound s);
1031 lastWordBoundary = j; 1100 lastWordBoundary = j;
1032 } 1101 }
1033 1102
1034 bool isCollapsibleWhiteSpace = (j < len) && styleToUse.isCollapsible WhiteSpace(c); 1103 bool isCollapsibleWhiteSpace = (j < len) && styleToUse.isCollapsible WhiteSpace(c);
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { 1768 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1700 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box, in validationReason); 1769 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box, in validationReason);
1701 if (box->truncation() != cNoTruncation) { 1770 if (box->truncation() != cNoTruncation) {
1702 if (EllipsisBox* ellipsisBox = box->root().ellipsisBox()) 1771 if (EllipsisBox* ellipsisBox = box->root().ellipsisBox())
1703 paintInvalidationContainer.invalidateDisplayItemClientOnBacking( *ellipsisBox, invalidationReason); 1772 paintInvalidationContainer.invalidateDisplayItemClientOnBacking( *ellipsisBox, invalidationReason);
1704 } 1773 }
1705 } 1774 }
1706 } 1775 }
1707 1776
1708 } // namespace blink 1777 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698