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 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 | 960 |
961 return m_maxWidth; | 961 return m_maxWidth; |
962 } | 962 } |
963 | 963 |
964 void LayoutText::computePreferredLogicalWidths(float leadWidth) { | 964 void LayoutText::computePreferredLogicalWidths(float leadWidth) { |
965 HashSet<const SimpleFontData*> fallbackFonts; | 965 HashSet<const SimpleFontData*> fallbackFonts; |
966 FloatRect glyphBounds; | 966 FloatRect glyphBounds; |
967 computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds); | 967 computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphBounds); |
968 } | 968 } |
969 | 969 |
| 970 static float minWordFragmentWidthForBreakAll(LayoutText* layoutText, |
| 971 const ComputedStyle& style, |
| 972 const Font& font, |
| 973 TextDirection textDirection, |
| 974 int start, |
| 975 int length) { |
| 976 DCHECK_GT(length, 0); |
| 977 LazyLineBreakIterator breakIterator(layoutText->text(), style.locale()); |
| 978 int nextBreakable = -1; |
| 979 float min = std::numeric_limits<float>::max(); |
| 980 int end = start + length; |
| 981 for (int i = start; i < end;) { |
| 982 breakIterator.isBreakable(i + 1, nextBreakable, LineBreakType::BreakAll); |
| 983 int fragmentLength = (nextBreakable > i ? nextBreakable : length) - i; |
| 984 // The correct behavior is to measure width without re-shaping, but we |
| 985 // reshape each fragment here because a) the current line breaker does not |
| 986 // support it, b) getCharacterRange() can reshape if the text is too long |
| 987 // to fit in the cache, and c) each fragment here is almost 1 char and thus |
| 988 // reshape is fast. |
| 989 TextRun run = constructTextRun(font, layoutText, i, fragmentLength, style, |
| 990 textDirection); |
| 991 float fragmentWidth = font.width(run); |
| 992 min = std::min(min, fragmentWidth); |
| 993 i += fragmentLength; |
| 994 } |
| 995 return min; |
| 996 } |
| 997 |
970 static float maxWordFragmentWidth(LayoutText* layoutText, | 998 static float maxWordFragmentWidth(LayoutText* layoutText, |
971 const ComputedStyle& style, | 999 const ComputedStyle& style, |
972 const Font& font, | 1000 const Font& font, |
973 TextDirection textDirection, | 1001 TextDirection textDirection, |
974 Hyphenation& hyphenation, | 1002 Hyphenation& hyphenation, |
975 unsigned wordOffset, | 1003 unsigned wordOffset, |
976 unsigned wordLength, | 1004 unsigned wordLength, |
977 int& suffixStart) { | 1005 int& suffixStart) { |
978 suffixStart = 0; | 1006 suffixStart = 0; |
979 if (wordLength <= Hyphenation::minimumSuffixLength) | 1007 if (wordLength <= Hyphenation::minimumSuffixLength) |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 if (c == softHyphenCharacter && !disableSoftHyphen) { | 1162 if (c == softHyphenCharacter && !disableSoftHyphen) { |
1135 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBoundary, | 1163 currMaxWidth += widthFromFont(f, lastWordBoundary, i - lastWordBoundary, |
1136 leadWidth, currMaxWidth, textDirection, | 1164 leadWidth, currMaxWidth, textDirection, |
1137 &fallbackFonts, &glyphBounds); | 1165 &fallbackFonts, &glyphBounds); |
1138 lastWordBoundary = i + 1; | 1166 lastWordBoundary = i + 1; |
1139 continue; | 1167 continue; |
1140 } | 1168 } |
1141 | 1169 |
1142 bool hasBreak = breakIterator.isBreakable( | 1170 bool hasBreak = breakIterator.isBreakable( |
1143 i, nextBreakable, | 1171 i, nextBreakable, |
1144 breakAll ? LineBreakType::BreakAll | 1172 keepAll ? LineBreakType::KeepAll : LineBreakType::Normal); |
1145 : keepAll ? LineBreakType::KeepAll : LineBreakType::Normal); | |
1146 bool betweenWords = true; | 1173 bool betweenWords = true; |
1147 int j = i; | 1174 int j = i; |
1148 while (c != newlineCharacter && c != spaceCharacter && | 1175 while (c != newlineCharacter && c != spaceCharacter && |
1149 c != tabulationCharacter && | 1176 c != tabulationCharacter && |
1150 (c != softHyphenCharacter || disableSoftHyphen)) { | 1177 (c != softHyphenCharacter || disableSoftHyphen)) { |
1151 j++; | 1178 j++; |
1152 if (j == len) | 1179 if (j == len) |
1153 break; | 1180 break; |
1154 c = uncheckedCharacterAt(j); | 1181 c = uncheckedCharacterAt(j); |
1155 if (breakIterator.isBreakable(j, nextBreakable) && | 1182 if (breakIterator.isBreakable(j, nextBreakable) && |
1156 characterAt(j - 1) != softHyphenCharacter) | 1183 characterAt(j - 1) != softHyphenCharacter) |
1157 break; | 1184 break; |
1158 if (breakAll) { | |
1159 betweenWords = false; | |
1160 break; | |
1161 } | |
1162 } | 1185 } |
1163 | 1186 |
1164 // Terminate word boundary at bidi run boundary. | 1187 // Terminate word boundary at bidi run boundary. |
1165 if (run) | 1188 if (run) |
1166 j = std::min(j, run->stop() + 1); | 1189 j = std::min(j, run->stop() + 1); |
1167 int wordLen = j - i; | 1190 int wordLen = j - i; |
1168 if (wordLen) { | 1191 if (wordLen) { |
1169 bool isSpace = (j < len) && c == spaceCharacter; | 1192 bool isSpace = (j < len) && c == spaceCharacter; |
1170 | 1193 |
1171 // Non-zero only when kerning is enabled, in which case we measure words | 1194 // Non-zero only when kerning is enabled, in which case we measure words |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 f, i + suffixStart, wordLen - suffixStart, leadWidth, | 1236 f, i + suffixStart, wordLen - suffixStart, leadWidth, |
1214 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); | 1237 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); |
1215 maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth); | 1238 maxFragmentWidth = std::max(maxFragmentWidth, suffixWidth); |
1216 currMinWidth += maxFragmentWidth - w; | 1239 currMinWidth += maxFragmentWidth - w; |
1217 maxWordWidth = std::max(maxWordWidth, maxFragmentWidth); | 1240 maxWordWidth = std::max(maxWordWidth, maxFragmentWidth); |
1218 } else { | 1241 } else { |
1219 maxWordWidth = w; | 1242 maxWordWidth = w; |
1220 } | 1243 } |
1221 } | 1244 } |
1222 | 1245 |
1223 currMinWidth += w; | 1246 if (breakAll) { |
| 1247 // Because sum of character widths may not be equal to the word width, |
| 1248 // we need to measure twice; once with normal break for max width, |
| 1249 // another with break-all for min width. |
| 1250 currMinWidth = minWordFragmentWidthForBreakAll( |
| 1251 this, styleToUse, f, textDirection, i, wordLen); |
| 1252 } else { |
| 1253 currMinWidth += w; |
| 1254 } |
1224 if (betweenWords) { | 1255 if (betweenWords) { |
1225 if (lastWordBoundary == i) | 1256 if (lastWordBoundary == i) |
1226 currMaxWidth += w; | 1257 currMaxWidth += w; |
1227 else | 1258 else |
1228 currMaxWidth += widthFromFont( | 1259 currMaxWidth += widthFromFont( |
1229 f, lastWordBoundary, j - lastWordBoundary, leadWidth, | 1260 f, lastWordBoundary, j - lastWordBoundary, leadWidth, |
1230 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); | 1261 currMaxWidth, textDirection, &fallbackFonts, &glyphBounds); |
1231 lastWordBoundary = j; | 1262 lastWordBoundary = j; |
1232 } | 1263 } |
1233 | 1264 |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1952 LayoutRect rect = LayoutRect( | 1983 LayoutRect rect = LayoutRect( |
1953 IntRect(firstRunX(), firstRunY(), linesBox.width(), linesBox.height())); | 1984 IntRect(firstRunX(), firstRunY(), linesBox.width(), linesBox.height())); |
1954 LayoutBlock* block = containingBlock(); | 1985 LayoutBlock* block = containingBlock(); |
1955 if (block && hasTextBoxes()) | 1986 if (block && hasTextBoxes()) |
1956 block->adjustChildDebugRect(rect); | 1987 block->adjustChildDebugRect(rect); |
1957 | 1988 |
1958 return rect; | 1989 return rect; |
1959 } | 1990 } |
1960 | 1991 |
1961 } // namespace blink | 1992 } // namespace blink |
OLD | NEW |