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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 if (string->isNull()) | 101 if (string->isNull()) |
102 return; | 102 return; |
103 | 103 |
104 unsigned length = string->length(); | 104 unsigned length = string->length(); |
105 const StringImpl& input = *string->impl(); | 105 const StringImpl& input = *string->impl(); |
106 | 106 |
107 if (length >= std::numeric_limits<unsigned>::max()) | 107 if (length >= std::numeric_limits<unsigned>::max()) |
108 CRASH(); | 108 CRASH(); |
109 | 109 |
110 StringBuffer<UChar> stringWithPrevious(length + 1); | 110 StringBuffer<UChar> stringWithPrevious(length + 1); |
111 stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; | 111 stringWithPrevious[0] = previous == noBreakSpace ? space : previous; |
112 for (unsigned i = 1; i < length + 1; i++) { | 112 for (unsigned i = 1; i < length + 1; i++) { |
113 // Replace   with a real space since ICU no longer treats   as a
word separator. | 113 // Replace   with a real space since ICU no longer treats   as a
word separator. |
114 if (input[i - 1] == noBreakSpace) | 114 if (input[i - 1] == noBreakSpace) |
115 stringWithPrevious[i] = ' '; | 115 stringWithPrevious[i] = space; |
116 else | 116 else |
117 stringWithPrevious[i] = input[i - 1]; | 117 stringWithPrevious[i] = input[i - 1]; |
118 } | 118 } |
119 | 119 |
120 TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.character
s(), length + 1); | 120 TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.character
s(), length + 1); |
121 if (!boundary) | 121 if (!boundary) |
122 return; | 122 return; |
123 | 123 |
124 StringBuilder result; | 124 StringBuilder result; |
125 result.reserveCapacity(length); | 125 result.reserveCapacity(length); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 { | 311 { |
312 if (node()) | 312 if (node()) |
313 return blink::plainText(rangeOfContents(node()).get()); | 313 return blink::plainText(rangeOfContents(node()).get()); |
314 | 314 |
315 // FIXME: this is just a stopgap until TextIterator is adapted to support ge
nerated text. | 315 // FIXME: this is just a stopgap until TextIterator is adapted to support ge
nerated text. |
316 StringBuilder plainTextBuilder; | 316 StringBuilder plainTextBuilder; |
317 for (InlineTextBox* textBox = firstTextBox(); textBox; textBox = textBox->ne
xtTextBox()) { | 317 for (InlineTextBox* textBox = firstTextBox(); textBox; textBox = textBox->ne
xtTextBox()) { |
318 String text = m_text.substring(textBox->start(), textBox->len()).simplif
yWhiteSpace(WTF::DoNotStripWhiteSpace); | 318 String text = m_text.substring(textBox->start(), textBox->len()).simplif
yWhiteSpace(WTF::DoNotStripWhiteSpace); |
319 plainTextBuilder.append(text); | 319 plainTextBuilder.append(text); |
320 if (textBox->nextTextBox() && textBox->nextTextBox()->start() > textBox-
>end() && text.length() && !text.right(1).containsOnlyWhitespace()) | 320 if (textBox->nextTextBox() && textBox->nextTextBox()->start() > textBox-
>end() && text.length() && !text.right(1).containsOnlyWhitespace()) |
321 plainTextBuilder.append(' '); | 321 plainTextBuilder.append(space); |
322 } | 322 } |
323 return plainTextBuilder.toString(); | 323 return plainTextBuilder.toString(); |
324 } | 324 } |
325 | 325 |
326 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const | 326 void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
latedOffset) const |
327 { | 327 { |
328 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) | 328 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) |
329 rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft
(), box->size()))); | 329 rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft
(), box->size()))); |
330 } | 330 } |
331 | 331 |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 } | 714 } |
715 | 715 |
716 if (f.isFixedPitch() && f.fontDescription().variant() == FontVariantNormal &
& m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) { | 716 if (f.isFixedPitch() && f.fontDescription().variant() == FontVariantNormal &
& m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) { |
717 float monospaceCharacterWidth = f.spaceWidth(); | 717 float monospaceCharacterWidth = f.spaceWidth(); |
718 float w = 0; | 718 float w = 0; |
719 bool isSpace; | 719 bool isSpace; |
720 ASSERT(m_text); | 720 ASSERT(m_text); |
721 StringImpl& text = *m_text.impl(); | 721 StringImpl& text = *m_text.impl(); |
722 for (int i = start; i < start + len; i++) { | 722 for (int i = start; i < start + len; i++) { |
723 char c = text[i]; | 723 char c = text[i]; |
724 if (c <= ' ') { | 724 if (c <= space) { |
725 if (c == ' ' || c == '\n') { | 725 if (c == space || c == newlineCharacter) { |
726 w += monospaceCharacterWidth; | 726 w += monospaceCharacterWidth; |
727 isSpace = true; | 727 isSpace = true; |
728 } else if (c == '\t') { | 728 } else if (c == characterTabulation) { |
729 if (style()->collapseWhiteSpace()) { | 729 if (style()->collapseWhiteSpace()) { |
730 w += monospaceCharacterWidth; | 730 w += monospaceCharacterWidth; |
731 isSpace = true; | 731 isSpace = true; |
732 } else { | 732 } else { |
733 w += f.tabWidth(style()->tabSize(), xPos + w); | 733 w += f.tabWidth(style()->tabSize(), xPos + w); |
734 isSpace = false; | 734 isSpace = false; |
735 } | 735 } |
736 } else | 736 } else |
737 isSpace = false; | 737 isSpace = false; |
738 } else { | 738 } else { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 maxWidth = m_maxWidth; | 791 maxWidth = m_maxWidth; |
792 | 792 |
793 firstLineMinWidth = m_firstLineMinWidth; | 793 firstLineMinWidth = m_firstLineMinWidth; |
794 lastLineMinWidth = m_lastLineLineMinWidth; | 794 lastLineMinWidth = m_lastLineLineMinWidth; |
795 | 795 |
796 hasBreakableChar = m_hasBreakableChar; | 796 hasBreakableChar = m_hasBreakableChar; |
797 hasBreak = m_hasBreak; | 797 hasBreak = m_hasBreak; |
798 | 798 |
799 ASSERT(m_text); | 799 ASSERT(m_text); |
800 StringImpl& text = *m_text.impl(); | 800 StringImpl& text = *m_text.impl(); |
801 if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || te
xt[0] == '\t') { | 801 if (text[0] == space || (text[0] == newlineCharacter && !style()->preserveNe
wline()) || text[0] == characterTabulation) { |
802 const Font& font = style()->font(); // FIXME: This ignores first-line. | 802 const Font& font = style()->font(); // FIXME: This ignores first-line. |
803 if (stripFrontSpaces) { | 803 if (stripFrontSpaces) { |
804 const UChar space = ' '; | 804 const UChar spaceChar = space; |
805 float spaceWidth = font.width(constructTextRun(this, font, &space, 1
, style(), direction)); | 805 float spaceWidth = font.width(constructTextRun(this, font, &spaceCha
r, 1, style(), direction)); |
806 maxWidth -= spaceWidth; | 806 maxWidth -= spaceWidth; |
807 } else { | 807 } else { |
808 maxWidth += font.fontDescription().wordSpacing(); | 808 maxWidth += font.fontDescription().wordSpacing(); |
809 } | 809 } |
810 } | 810 } |
811 | 811 |
812 stripFrontSpaces = collapseWhiteSpace && m_hasEndWhiteSpace; | 812 stripFrontSpaces = collapseWhiteSpace && m_hasEndWhiteSpace; |
813 | 813 |
814 if (!style()->autoWrap() || minWidth > maxWidth) | 814 if (!style()->autoWrap() || minWidth > maxWidth) |
815 minWidth = maxWidth; | 815 minWidth = maxWidth; |
816 | 816 |
817 // Compute our max widths by scanning the string for newlines. | 817 // Compute our max widths by scanning the string for newlines. |
818 if (hasBreak) { | 818 if (hasBreak) { |
819 const Font& f = style()->font(); // FIXME: This ignores first-line. | 819 const Font& f = style()->font(); // FIXME: This ignores first-line. |
820 bool firstLine = true; | 820 bool firstLine = true; |
821 firstLineMaxWidth = maxWidth; | 821 firstLineMaxWidth = maxWidth; |
822 lastLineMaxWidth = maxWidth; | 822 lastLineMaxWidth = maxWidth; |
823 for (int i = 0; i < len; i++) { | 823 for (int i = 0; i < len; i++) { |
824 int linelen = 0; | 824 int linelen = 0; |
825 while (i + linelen < len && text[i + linelen] != '\n') | 825 while (i + linelen < len && text[i + linelen] != newlineCharacter) |
826 linelen++; | 826 linelen++; |
827 | 827 |
828 if (linelen) { | 828 if (linelen) { |
829 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, direction, 0, 0); | 829 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, direction, 0, 0); |
830 if (firstLine) { | 830 if (firstLine) { |
831 firstLine = false; | 831 firstLine = false; |
832 leadWidth = 0; | 832 leadWidth = 0; |
833 firstLineMaxWidth = lastLineMaxWidth; | 833 firstLineMaxWidth = lastLineMaxWidth; |
834 } | 834 } |
835 i += linelen; | 835 i += linelen; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
948 while (i >= run->stop() || (run->next() && run->next()->direction()
== run->direction())) | 948 while (i >= run->stop() || (run->next() && run->next()->direction()
== run->direction())) |
949 run = run->next(); | 949 run = run->next(); |
950 | 950 |
951 ASSERT(run); | 951 ASSERT(run); |
952 ASSERT(i <= run->stop()); | 952 ASSERT(i <= run->stop()); |
953 textDirection = run->direction(); | 953 textDirection = run->direction(); |
954 } | 954 } |
955 | 955 |
956 bool previousCharacterIsSpace = isSpace; | 956 bool previousCharacterIsSpace = isSpace; |
957 bool isNewline = false; | 957 bool isNewline = false; |
958 if (c == '\n') { | 958 if (c == newlineCharacter) { |
959 if (styleToUse->preserveNewline()) { | 959 if (styleToUse->preserveNewline()) { |
960 m_hasBreak = true; | 960 m_hasBreak = true; |
961 isNewline = true; | 961 isNewline = true; |
962 isSpace = false; | 962 isSpace = false; |
963 } else | 963 } else |
964 isSpace = true; | 964 isSpace = true; |
965 } else if (c == '\t') { | 965 } else if (c == characterTabulation) { |
966 if (!styleToUse->collapseWhiteSpace()) { | 966 if (!styleToUse->collapseWhiteSpace()) { |
967 m_hasTab = true; | 967 m_hasTab = true; |
968 isSpace = false; | 968 isSpace = false; |
969 } else | 969 } else |
970 isSpace = true; | 970 isSpace = true; |
971 } else | 971 } else { |
972 isSpace = c == ' '; | 972 isSpace = c == space; |
| 973 } |
973 | 974 |
974 bool isBreakableLocation = isNewline || (isSpace && styleToUse->autoWrap
()); | 975 bool isBreakableLocation = isNewline || (isSpace && styleToUse->autoWrap
()); |
975 if (!i) | 976 if (!i) |
976 m_hasBreakableStart = isBreakableLocation; | 977 m_hasBreakableStart = isBreakableLocation; |
977 if (i == len - 1) { | 978 if (i == len - 1) { |
978 m_hasBreakableEnd = isBreakableLocation; | 979 m_hasBreakableEnd = isBreakableLocation; |
979 m_hasEndWhiteSpace = isNewline || isSpace; | 980 m_hasEndWhiteSpace = isNewline || isSpace; |
980 } | 981 } |
981 | 982 |
982 if (!ignoringSpaces && styleToUse->collapseWhiteSpace() && previousChara
cterIsSpace && isSpace) | 983 if (!ignoringSpaces && styleToUse->collapseWhiteSpace() && previousChara
cterIsSpace && isSpace) |
(...skipping 11 matching lines...) Expand all Loading... |
994 currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoun
dary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); | 995 currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoun
dary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); |
995 if (firstGlyphLeftOverflow < 0) | 996 if (firstGlyphLeftOverflow < 0) |
996 firstGlyphLeftOverflow = glyphOverflow.left; | 997 firstGlyphLeftOverflow = glyphOverflow.left; |
997 lastWordBoundary = i + 1; | 998 lastWordBoundary = i + 1; |
998 continue; | 999 continue; |
999 } | 1000 } |
1000 | 1001 |
1001 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable)
; | 1002 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable)
; |
1002 bool betweenWords = true; | 1003 bool betweenWords = true; |
1003 int j = i; | 1004 int j = i; |
1004 while (c != '\n' && c != ' ' && c != '\t' && (c != softHyphen)) { | 1005 while (c != newlineCharacter && c != space && c != characterTabulation &
& (c != softHyphen)) { |
1005 j++; | 1006 j++; |
1006 if (j == len) | 1007 if (j == len) |
1007 break; | 1008 break; |
1008 c = uncheckedCharacterAt(j); | 1009 c = uncheckedCharacterAt(j); |
1009 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) | 1010 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) |
1010 break; | 1011 break; |
1011 if (breakAll) { | 1012 if (breakAll) { |
1012 betweenWords = false; | 1013 betweenWords = false; |
1013 break; | 1014 break; |
1014 } | 1015 } |
1015 } | 1016 } |
1016 | 1017 |
1017 // Terminate word boundary at bidi run boundary. | 1018 // Terminate word boundary at bidi run boundary. |
1018 if (run) | 1019 if (run) |
1019 j = std::min(j, run->stop() + 1); | 1020 j = std::min(j, run->stop() + 1); |
1020 int wordLen = j - i; | 1021 int wordLen = j - i; |
1021 if (wordLen) { | 1022 if (wordLen) { |
1022 bool isSpace = (j < len) && c == ' '; | 1023 bool isSpace = (j < len) && c == space; |
1023 | 1024 |
1024 // Non-zero only when kerning is enabled, in which case we measure w
ords with their trailing | 1025 // Non-zero only when kerning is enabled, in which case we measure w
ords with their trailing |
1025 // space, then subtract its width. | 1026 // space, then subtract its width. |
1026 float wordTrailingSpaceWidth = 0; | 1027 float wordTrailingSpaceWidth = 0; |
1027 if (isSpace && (f.fontDescription().typesettingFeatures() & Kerning)
) { | 1028 if (isSpace && (f.fontDescription().typesettingFeatures() & Kerning)
) { |
1028 ASSERT(textDirection >=0 && textDirection <= 1); | 1029 ASSERT(textDirection >=0 && textDirection <= 1); |
1029 if (!cachedWordTrailingSpaceWidth[textDirection]) | 1030 if (!cachedWordTrailingSpaceWidth[textDirection]) |
1030 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr
uctTextRun(this, f, &space, 1, styleToUse, textDirection)) + wordSpacing; | 1031 cachedWordTrailingSpaceWidth[textDirection] = f.width(constr
uctTextRun(this, f, &space, 1, styleToUse, textDirection)) + wordSpacing; |
1031 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect
ion]; | 1032 wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirect
ion]; |
1032 } | 1033 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 } | 1153 } |
1153 return true; | 1154 return true; |
1154 } | 1155 } |
1155 | 1156 |
1156 bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const | 1157 bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const |
1157 { | 1158 { |
1158 ASSERT(m_text); | 1159 ASSERT(m_text); |
1159 StringImpl& text = *m_text.impl(); | 1160 StringImpl& text = *m_text.impl(); |
1160 unsigned currPos; | 1161 unsigned currPos; |
1161 for (currPos = from; | 1162 for (currPos = from; |
1162 currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' '
|| text[currPos] == '\t'); | 1163 currPos < from + len && (text[currPos] == newlineCharacter || text[currPos]
== space || text[currPos] == characterTabulation); |
1163 currPos++) { } | 1164 currPos++) { } |
1164 return currPos >= (from + len); | 1165 return currPos >= (from + len); |
1165 } | 1166 } |
1166 | 1167 |
1167 FloatPoint RenderText::firstRunOrigin() const | 1168 FloatPoint RenderText::firstRunOrigin() const |
1168 { | 1169 { |
1169 return IntPoint(firstRunX(), firstRunY()); | 1170 return IntPoint(firstRunX(), firstRunY()); |
1170 } | 1171 } |
1171 | 1172 |
1172 float RenderText::firstRunX() const | 1173 float RenderText::firstRunX() const |
1173 { | 1174 { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1307 return toRenderText(o)->text().isEmpty(); | 1308 return toRenderText(o)->text().isEmpty(); |
1308 } | 1309 } |
1309 | 1310 |
1310 UChar RenderText::previousCharacter() const | 1311 UChar RenderText::previousCharacter() const |
1311 { | 1312 { |
1312 // find previous text renderer if one exists | 1313 // find previous text renderer if one exists |
1313 const RenderObject* previousText = previousInPreOrder(); | 1314 const RenderObject* previousText = previousInPreOrder(); |
1314 for (; previousText; previousText = previousText->previousInPreOrder()) | 1315 for (; previousText; previousText = previousText->previousInPreOrder()) |
1315 if (!isInlineFlowOrEmptyText(previousText)) | 1316 if (!isInlineFlowOrEmptyText(previousText)) |
1316 break; | 1317 break; |
1317 UChar prev = ' '; | 1318 UChar prev = space; |
1318 if (previousText && previousText->isText()) | 1319 if (previousText && previousText->isText()) |
1319 if (StringImpl* previousString = toRenderText(previousText)->text().impl
()) | 1320 if (StringImpl* previousString = toRenderText(previousText)->text().impl
()) |
1320 prev = (*previousString)[previousString->length() - 1]; | 1321 prev = (*previousString)[previousString->length() - 1]; |
1321 return prev; | 1322 return prev; |
1322 } | 1323 } |
1323 | 1324 |
1324 void RenderText::addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* cur
rentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) cons
t | 1325 void RenderText::addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* cur
rentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) cons
t |
1325 { | 1326 { |
1326 // Text nodes aren't event targets, so don't descend any further. | 1327 // Text nodes aren't event targets, so don't descend any further. |
1327 } | 1328 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 break; | 1365 break; |
1365 case TSDISC: | 1366 case TSDISC: |
1366 secureText(bullet); | 1367 secureText(bullet); |
1367 break; | 1368 break; |
1368 case TSSQUARE: | 1369 case TSSQUARE: |
1369 secureText(blackSquare); | 1370 secureText(blackSquare); |
1370 } | 1371 } |
1371 } | 1372 } |
1372 | 1373 |
1373 ASSERT(m_text); | 1374 ASSERT(m_text); |
1374 ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n')); | 1375 ASSERT(!isBR() || (textLength() == 1 && m_text[0] == newlineCharacter)); |
1375 | 1376 |
1376 m_isAllASCII = m_text.containsOnlyASCII(); | 1377 m_isAllASCII = m_text.containsOnlyASCII(); |
1377 m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath(); | 1378 m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath(); |
1378 } | 1379 } |
1379 | 1380 |
1380 void RenderText::secureText(UChar mask) | 1381 void RenderText::secureText(UChar mask) |
1381 { | 1382 { |
1382 if (!m_text.length()) | 1383 if (!m_text.length()) |
1383 return; | 1384 return; |
1384 | 1385 |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 } | 1873 } |
1873 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); | 1874 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); |
1874 } | 1875 } |
1875 | 1876 |
1876 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() | 1877 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() |
1877 { | 1878 { |
1878 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); | 1879 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); |
1879 } | 1880 } |
1880 | 1881 |
1881 } // namespace blink | 1882 } // namespace blink |
OLD | NEW |