Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |