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

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: eae review 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,
869 const ComputedStyle& style, const Font& font, TextDirection textDirection,
870 Hyphenation& hyphenation, unsigned wordOffset, unsigned wordLength,
871 int& suffixStart)
872 {
873 suffixStart = 0;
874 if (wordLength <= Hyphenation::minimumSuffixLength)
875 return 0;
876
877 Vector<size_t, 8> hyphenLocations = hyphenation.hyphenLocations(
878 layoutText->text().createView(wordOffset, wordLength));
879 if (hyphenLocations.isEmpty())
880 return 0;
881
882 float minimumFragmentWidthToConsider = Hyphenation::minimumPrefixWidth(font) ;
883 float maxFragmentWidth = 0;
884 TextRun run = constructTextRun(font, layoutText, wordOffset, wordLength, sty le, textDirection);
885 size_t end = wordLength;
886 for (size_t start : hyphenLocations) {
887 float fragmentWidth = font.getCharacterRange(run, start, end).width();
888
889 if (fragmentWidth <= minimumFragmentWidthToConsider)
890 continue;
891
892 maxFragmentWidth = std::max(maxFragmentWidth, fragmentWidth);
893 end = start;
894 }
895 suffixStart = hyphenLocations.first();
896 return maxFragmentWidth + layoutText->hyphenWidth(font, textDirection);
897 }
898
866 void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si mpleFontData*>& fallbackFonts, FloatRect& glyphBounds) 899 void LayoutText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si mpleFontData*>& fallbackFonts, FloatRect& glyphBounds)
867 { 900 {
868 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow AndNoFallbackFonts); 901 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow AndNoFallbackFonts);
869 902
870 m_minWidth = 0; 903 m_minWidth = 0;
871 m_maxWidth = 0; 904 m_maxWidth = 0;
872 m_firstLineMinWidth = 0; 905 m_firstLineMinWidth = 0;
873 m_lastLineLineMinWidth = 0; 906 m_lastLineLineMinWidth = 0;
874 907
875 if (isBR()) 908 if (isBR())
(...skipping 18 matching lines...) Expand all
894 bool isSpace = false; 927 bool isSpace = false;
895 bool firstWord = true; 928 bool firstWord = true;
896 bool firstLine = true; 929 bool firstLine = true;
897 int nextBreakable = -1; 930 int nextBreakable = -1;
898 int lastWordBoundary = 0; 931 int lastWordBoundary = 0;
899 float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL 932 float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL
900 933
901 bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.w ordBreak() == BreakWordBreak) && styleToUse.autoWrap(); 934 bool breakAll = (styleToUse.wordBreak() == BreakAllWordBreak || styleToUse.w ordBreak() == BreakWordBreak) && styleToUse.autoWrap();
902 bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.auto Wrap(); 935 bool keepAll = styleToUse.wordBreak() == KeepAllWordBreak && styleToUse.auto Wrap();
903 936
937 Hyphenation* hyphenation = styleToUse.getHyphens() == HyphensAuto
938 ? Hyphenation::get(f.getFontDescription().locale()) : nullptr;
939 bool disableSoftHyphen = styleToUse.getHyphens() == HyphensNone;
940 float maxWordWidth = 0;
941 if (!hyphenation)
942 maxWordWidth = std::numeric_limits<float>::max();
943
904 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; 944 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
905 BidiCharacterRun* run; 945 BidiCharacterRun* run;
906 TextDirection textDirection = styleToUse.direction(); 946 TextDirection textDirection = styleToUse.direction();
907 if ((is8Bit() && textDirection == LTR) || isOverride(styleToUse.unicodeBidi( ))) { 947 if ((is8Bit() && textDirection == LTR) || isOverride(styleToUse.unicodeBidi( ))) {
908 run = 0; 948 run = 0;
909 } else { 949 } else {
910 TextRun textRun(text()); 950 TextRun textRun(text());
911 BidiStatus status(textDirection, false); 951 BidiStatus status(textDirection, false);
912 bidiResolver.setStatus(status); 952 bidiResolver.setStatus(status);
913 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0)); 953 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 1007
968 if (ignoringSpaces && !isSpace) 1008 if (ignoringSpaces && !isSpace)
969 ignoringSpaces = false; 1009 ignoringSpaces = false;
970 1010
971 // Ignore spaces and soft hyphens 1011 // Ignore spaces and soft hyphens
972 if (ignoringSpaces) { 1012 if (ignoringSpaces) {
973 ASSERT(lastWordBoundary == i); 1013 ASSERT(lastWordBoundary == i);
974 lastWordBoundary++; 1014 lastWordBoundary++;
975 continue; 1015 continue;
976 } 1016 }
977 if (c == softHyphenCharacter) { 1017 if (c == softHyphenCharacter && !disableSoftHyphen) {
978 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBound ary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); 1018 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBound ary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBounds);
979 lastWordBoundary = i + 1; 1019 lastWordBoundary = i + 1;
980 continue; 1020 continue;
981 } 1021 }
982 1022
983 bool hasBreak = breakIterator.isBreakable(i, nextBreakable, breakAll ? L ineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Norma l); 1023 bool hasBreak = breakIterator.isBreakable(i, nextBreakable, breakAll ? L ineBreakType::BreakAll : keepAll ? LineBreakType::KeepAll : LineBreakType::Norma l);
984 bool betweenWords = true; 1024 bool betweenWords = true;
985 int j = i; 1025 int j = i;
986 while (c != newlineCharacter && c != spaceCharacter && c != tabulationCh aracter && (c != softHyphenCharacter)) { 1026 while (c != newlineCharacter && c != spaceCharacter && c != tabulationCh aracter && (c != softHyphenCharacter || disableSoftHyphen)) {
987 j++; 1027 j++;
988 if (j == len) 1028 if (j == len)
989 break; 1029 break;
990 c = uncheckedCharacterAt(j); 1030 c = uncheckedCharacterAt(j);
991 if (breakIterator.isBreakable(j, nextBreakable) && characterAt(j - 1 ) != softHyphenCharacter) 1031 if (breakIterator.isBreakable(j, nextBreakable) && characterAt(j - 1 ) != softHyphenCharacter)
992 break; 1032 break;
993 if (breakAll) { 1033 if (breakAll) {
994 betweenWords = false; 1034 betweenWords = false;
995 break; 1035 break;
996 } 1036 }
(...skipping 14 matching lines...) Expand all
1011 if (!cachedWordTrailingSpaceWidth[textDirection]) 1051 if (!cachedWordTrailingSpaceWidth[textDirection])
1012 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr uctTextRun(f, &spaceCharacter, 1, styleToUse, textDirection)) + wordSpacing; 1052 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr uctTextRun(f, &spaceCharacter, 1, styleToUse, textDirection)) + wordSpacing;
1013 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect ion]; 1053 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect ion];
1014 } 1054 }
1015 1055
1016 float w; 1056 float w;
1017 if (wordTrailingSpaceWidth && isSpace) { 1057 if (wordTrailingSpaceWidth && isSpace) {
1018 w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, te xtDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth; 1058 w = widthFromFont(f, i, wordLen + 1, leadWidth, currMaxWidth, te xtDirection, &fallbackFonts, &glyphBounds) - wordTrailingSpaceWidth;
1019 } else { 1059 } else {
1020 w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDi rection, &fallbackFonts, &glyphBounds); 1060 w = widthFromFont(f, i, wordLen, leadWidth, currMaxWidth, textDi rection, &fallbackFonts, &glyphBounds);
1021 if (c == softHyphenCharacter) 1061 if (c == softHyphenCharacter && !disableSoftHyphen)
1022 currMinWidth += hyphenWidth(f, textDirection); 1062 currMinWidth += hyphenWidth(f, textDirection);
1023 } 1063 }
1024 1064
1065 if (w > maxWordWidth) {
1066 int suffixStart;
1067 float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, textDirection, *hyphenation, i, wordLen, suffixStart);
1068 if (suffixStart) {
1069 float suffixWidth;
1070 if (wordTrailingSpaceWidth && isSpace)
1071 suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyp hBounds) - wordTrailingSpaceWidth;
1072 else
1073 suffixWidth = widthFromFont(f, i + suffixStart, wordLen - suffixStart, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBou nds);
1074 maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth);
1075 currMinWidth += maxFragmentWidth - w;
1076 maxWordWidth = std::max(maxWordWidth, maxFragmentWidth);
1077 } else {
1078 maxWordWidth = w;
1079 }
1080 }
1081
1025 currMinWidth += w; 1082 currMinWidth += w;
1026 if (betweenWords) { 1083 if (betweenWords) {
1027 if (lastWordBoundary == i) 1084 if (lastWordBoundary == i)
1028 currMaxWidth += w; 1085 currMaxWidth += w;
1029 else 1086 else
1030 currMaxWidth += widthFromFont(f, lastWordBoundary, j - lastW ordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBound s); 1087 currMaxWidth += widthFromFont(f, lastWordBoundary, j - lastW ordBoundary, leadWidth, currMaxWidth, textDirection, &fallbackFonts, &glyphBound s);
1031 lastWordBoundary = j; 1088 lastWordBoundary = j;
1032 } 1089 }
1033 1090
1034 bool isCollapsibleWhiteSpace = (j < len) && styleToUse.isCollapsible WhiteSpace(c); 1091 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()) { 1756 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1700 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box, in validationReason); 1757 paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*box, in validationReason);
1701 if (box->truncation() != cNoTruncation) { 1758 if (box->truncation() != cNoTruncation) {
1702 if (EllipsisBox* ellipsisBox = box->root().ellipsisBox()) 1759 if (EllipsisBox* ellipsisBox = box->root().ellipsisBox())
1703 paintInvalidationContainer.invalidateDisplayItemClientOnBacking( *ellipsisBox, invalidationReason); 1760 paintInvalidationContainer.invalidateDisplayItemClientOnBacking( *ellipsisBox, invalidationReason);
1704 } 1761 }
1705 } 1762 }
1706 } 1763 }
1707 1764
1708 } // namespace blink 1765 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698