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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 134 |
135 RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str) | 135 RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str) |
136 : RenderObject(!node || node->isDocumentNode() ? 0 : node) | 136 : RenderObject(!node || node->isDocumentNode() ? 0 : node) |
137 , m_hasTab(false) | 137 , m_hasTab(false) |
138 , m_linesDirty(false) | 138 , m_linesDirty(false) |
139 , m_containsReversedText(false) | 139 , m_containsReversedText(false) |
140 , m_knownToHaveNoOverflowAndNoFallbackFonts(false) | 140 , m_knownToHaveNoOverflowAndNoFallbackFonts(false) |
141 , m_needsTranscoding(false) | 141 , m_needsTranscoding(false) |
142 , m_minWidth(-1) | 142 , m_minWidth(-1) |
143 , m_maxWidth(-1) | 143 , m_maxWidth(-1) |
144 , m_beginMinWidth(0) | 144 , m_firstLineMinWidth(0) |
145 , m_endMinWidth(0) | 145 , m_lastLineLineMinWidth(0) |
146 , m_text(str) | 146 , m_text(str) |
147 , m_firstTextBox(0) | 147 , m_firstTextBox(0) |
148 , m_lastTextBox(0) | 148 , m_lastTextBox(0) |
149 { | 149 { |
150 ASSERT(m_text); | 150 ASSERT(m_text); |
151 // FIXME: Some clients of RenderText (and subclasses) pass Document as node
to create anonymous renderer. | 151 // FIXME: Some clients of RenderText (and subclasses) pass Document as node
to create anonymous renderer. |
152 // They should be switched to passing null and using setDocumentForAnonymous
. | 152 // They should be switched to passing null and using setDocumentForAnonymous
. |
153 if (node && node->isDocumentNode()) | 153 if (node && node->isDocumentNode()) |
154 setDocumentForAnonymous(toDocument(node)); | 154 setDocumentForAnonymous(toDocument(node)); |
155 | 155 |
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 run.setCharactersLength(textLength() - start); | 761 run.setCharactersLength(textLength() - start); |
762 ASSERT(run.charactersLength() >= run.length()); | 762 ASSERT(run.charactersLength() >= run.length()); |
763 | 763 |
764 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); | 764 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); |
765 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); | 765 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); |
766 run.setXPos(xPos); | 766 run.setXPos(xPos); |
767 return f.width(run, fallbackFonts, glyphOverflow); | 767 return f.width(run, fallbackFonts, glyphOverflow); |
768 } | 768 } |
769 | 769 |
770 void RenderText::trimmedPrefWidths(float leadWidth, | 770 void RenderText::trimmedPrefWidths(float leadWidth, |
771 float& beginMinW, bool& beginWS, | 771 float& firstLineMinWidth, bool& hasBreakableStart, |
772 float& endMinW, bool& endWS, | 772 float& lastLineMinWidth, bool& hasBreakableEnd, |
773 bool& hasBreakableChar, bool& hasBreak, | 773 bool& hasBreakableChar, bool& hasBreak, |
774 float& beginMaxW, float& endMaxW, | 774 float& firstLineMaxWidth, float& lastLineMaxWidth, |
775 float& minW, float& maxW, bool& stripFrontSpa
ces) | 775 float& minWidth, float& maxWidth, bool& stripFrontSpaces) |
776 { | 776 { |
777 bool collapseWhiteSpace = style()->collapseWhiteSpace(); | 777 bool collapseWhiteSpace = style()->collapseWhiteSpace(); |
778 if (!collapseWhiteSpace) | 778 if (!collapseWhiteSpace) |
779 stripFrontSpaces = false; | 779 stripFrontSpaces = false; |
780 | 780 |
781 if (m_hasTab || preferredLogicalWidthsDirty()) | 781 if (m_hasTab || preferredLogicalWidthsDirty()) |
782 computePreferredLogicalWidths(leadWidth); | 782 computePreferredLogicalWidths(leadWidth); |
783 | 783 |
784 beginWS = !stripFrontSpaces && m_hasBeginWS; | 784 hasBreakableStart = !stripFrontSpaces && m_hasBreakableStart; |
785 endWS = m_hasEndWS; | 785 hasBreakableEnd = m_hasBreakableEnd; |
786 | 786 |
787 int len = textLength(); | 787 int len = textLength(); |
788 | 788 |
789 if (!len || (stripFrontSpaces && text()->containsOnlyWhitespace())) { | 789 if (!len || (stripFrontSpaces && text()->containsOnlyWhitespace())) { |
790 beginMinW = 0; | 790 firstLineMinWidth = 0; |
791 endMinW = 0; | 791 lastLineMinWidth = 0; |
792 beginMaxW = 0; | 792 firstLineMaxWidth = 0; |
793 endMaxW = 0; | 793 lastLineMaxWidth = 0; |
794 minW = 0; | 794 minWidth = 0; |
795 maxW = 0; | 795 maxWidth = 0; |
796 hasBreak = false; | 796 hasBreak = false; |
797 return; | 797 return; |
798 } | 798 } |
799 | 799 |
800 minW = m_minWidth; | 800 minWidth = m_minWidth; |
801 maxW = m_maxWidth; | 801 maxWidth = m_maxWidth; |
802 | 802 |
803 beginMinW = m_beginMinWidth; | 803 firstLineMinWidth = m_firstLineMinWidth; |
804 endMinW = m_endMinWidth; | 804 lastLineMinWidth = m_lastLineLineMinWidth; |
805 | 805 |
806 hasBreakableChar = m_hasBreakableChar; | 806 hasBreakableChar = m_hasBreakableChar; |
807 hasBreak = m_hasBreak; | 807 hasBreak = m_hasBreak; |
808 | 808 |
809 ASSERT(m_text); | 809 ASSERT(m_text); |
810 StringImpl& text = *m_text.impl(); | 810 StringImpl& text = *m_text.impl(); |
811 if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || te
xt[0] == '\t') { | 811 if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || te
xt[0] == '\t') { |
812 const Font& font = style()->font(); // FIXME: This ignores first-line. | 812 const Font& font = style()->font(); // FIXME: This ignores first-line. |
813 if (stripFrontSpaces) { | 813 if (stripFrontSpaces) { |
814 const UChar space = ' '; | 814 const UChar space = ' '; |
815 float spaceWidth = font.width(RenderBlock::constructTextRun(this, fo
nt, &space, 1, style())); | 815 float spaceWidth = font.width(RenderBlock::constructTextRun(this, fo
nt, &space, 1, style())); |
816 maxW -= spaceWidth; | 816 maxWidth -= spaceWidth; |
817 } else | 817 } else { |
818 maxW += font.wordSpacing(); | 818 maxWidth += font.wordSpacing(); |
| 819 } |
819 } | 820 } |
820 | 821 |
821 stripFrontSpaces = collapseWhiteSpace && m_hasEndWS; | 822 stripFrontSpaces = collapseWhiteSpace && m_hasBreakableEnd; |
822 | 823 |
823 if (!style()->autoWrap() || minW > maxW) | 824 if (!style()->autoWrap() || minWidth > maxWidth) |
824 minW = maxW; | 825 minWidth = maxWidth; |
825 | 826 |
826 // Compute our max widths by scanning the string for newlines. | 827 // Compute our max widths by scanning the string for newlines. |
827 if (hasBreak) { | 828 if (hasBreak) { |
828 const Font& f = style()->font(); // FIXME: This ignores first-line. | 829 const Font& f = style()->font(); // FIXME: This ignores first-line. |
829 bool firstLine = true; | 830 bool firstLine = true; |
830 beginMaxW = maxW; | 831 firstLineMaxWidth = maxWidth; |
831 endMaxW = maxW; | 832 lastLineMaxWidth = maxWidth; |
832 for (int i = 0; i < len; i++) { | 833 for (int i = 0; i < len; i++) { |
833 int linelen = 0; | 834 int linelen = 0; |
834 while (i + linelen < len && text[i + linelen] != '\n') | 835 while (i + linelen < len && text[i + linelen] != '\n') |
835 linelen++; | 836 linelen++; |
836 | 837 |
837 if (linelen) { | 838 if (linelen) { |
838 endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0,
0); | 839 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, 0, 0); |
839 if (firstLine) { | 840 if (firstLine) { |
840 firstLine = false; | 841 firstLine = false; |
841 leadWidth = 0; | 842 leadWidth = 0; |
842 beginMaxW = endMaxW; | 843 firstLineMaxWidth = lastLineMaxWidth; |
843 } | 844 } |
844 i += linelen; | 845 i += linelen; |
845 } else if (firstLine) { | 846 } else if (firstLine) { |
846 beginMaxW = 0; | 847 firstLineMaxWidth = 0; |
847 firstLine = false; | 848 firstLine = false; |
848 leadWidth = 0; | 849 leadWidth = 0; |
849 } | 850 } |
850 | 851 |
851 if (i == len - 1) | 852 if (i == len - 1) { |
852 // A <pre> run that ends with a newline, as in, e.g., | 853 // A <pre> run that ends with a newline, as in, e.g., |
853 // <pre>Some text\n\n<span>More text</pre> | 854 // <pre>Some text\n\n<span>More text</pre> |
854 endMaxW = 0; | 855 lastLineMaxWidth = 0; |
| 856 } |
855 } | 857 } |
856 } | 858 } |
857 } | 859 } |
858 | 860 |
859 float RenderText::minLogicalWidth() const | 861 float RenderText::minLogicalWidth() const |
860 { | 862 { |
861 if (preferredLogicalWidthsDirty()) | 863 if (preferredLogicalWidthsDirty()) |
862 const_cast<RenderText*>(this)->computePreferredLogicalWidths(0); | 864 const_cast<RenderText*>(this)->computePreferredLogicalWidths(0); |
863 | 865 |
864 return m_minWidth; | 866 return m_minWidth; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 } | 927 } |
926 | 928 |
927 return maxFragmentWidth; | 929 return maxFragmentWidth; |
928 } | 930 } |
929 | 931 |
930 void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
mpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow) | 932 void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
mpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow) |
931 { | 933 { |
932 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow
AndNoFallbackFonts); | 934 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow
AndNoFallbackFonts); |
933 | 935 |
934 m_minWidth = 0; | 936 m_minWidth = 0; |
935 m_beginMinWidth = 0; | |
936 m_endMinWidth = 0; | |
937 m_maxWidth = 0; | 937 m_maxWidth = 0; |
| 938 m_firstLineMinWidth = 0; |
| 939 m_lastLineLineMinWidth = 0; |
938 | 940 |
939 if (isBR()) | 941 if (isBR()) |
940 return; | 942 return; |
941 | 943 |
942 float currMinWidth = 0; | 944 float currMinWidth = 0; |
943 float currMaxWidth = 0; | 945 float currMaxWidth = 0; |
944 m_hasBreakableChar = false; | 946 m_hasBreakableChar = false; |
945 m_hasBreak = false; | 947 m_hasBreak = false; |
946 m_hasTab = false; | 948 m_hasTab = false; |
947 m_hasBeginWS = false; | 949 m_hasBreakableStart = false; |
948 m_hasEndWS = false; | 950 m_hasBreakableEnd = false; |
949 | 951 |
950 RenderStyle* styleToUse = style(); | 952 RenderStyle* styleToUse = style(); |
951 const Font& f = styleToUse->font(); // FIXME: This ignores first-line. | 953 const Font& f = styleToUse->font(); // FIXME: This ignores first-line. |
952 float wordSpacing = styleToUse->wordSpacing(); | 954 float wordSpacing = styleToUse->wordSpacing(); |
953 int len = textLength(); | 955 int len = textLength(); |
954 LazyLineBreakIterator breakIterator(m_text, styleToUse->locale()); | 956 LazyLineBreakIterator breakIterator(m_text, styleToUse->locale()); |
955 bool needsWordSpacing = false; | 957 bool needsWordSpacing = false; |
956 bool ignoringSpaces = false; | 958 bool ignoringSpaces = false; |
957 bool isSpace = false; | 959 bool isSpace = false; |
958 bool firstWord = true; | 960 bool firstWord = true; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 } else if (c == '\t') { | 1004 } else if (c == '\t') { |
1003 if (!styleToUse->collapseWhiteSpace()) { | 1005 if (!styleToUse->collapseWhiteSpace()) { |
1004 m_hasTab = true; | 1006 m_hasTab = true; |
1005 isSpace = false; | 1007 isSpace = false; |
1006 } else | 1008 } else |
1007 isSpace = true; | 1009 isSpace = true; |
1008 } else | 1010 } else |
1009 isSpace = c == ' '; | 1011 isSpace = c == ' '; |
1010 | 1012 |
1011 if ((isSpace || isNewline) && !i) | 1013 if ((isSpace || isNewline) && !i) |
1012 m_hasBeginWS = true; | 1014 m_hasBreakableStart = true; |
1013 if ((isSpace || isNewline) && i == len - 1) | 1015 if ((isSpace || isNewline) && i == len - 1) |
1014 m_hasEndWS = true; | 1016 m_hasBreakableEnd = true; |
1015 | 1017 |
1016 if (!ignoringSpaces && styleToUse->collapseWhiteSpace() && previousChara
cterIsSpace && isSpace) | 1018 if (!ignoringSpaces && styleToUse->collapseWhiteSpace() && previousChara
cterIsSpace && isSpace) |
1017 ignoringSpaces = true; | 1019 ignoringSpaces = true; |
1018 | 1020 |
1019 if (ignoringSpaces && !isSpace) | 1021 if (ignoringSpaces && !isSpace) |
1020 ignoringSpaces = false; | 1022 ignoringSpaces = false; |
1021 | 1023 |
1022 // Ignore spaces and soft hyphens | 1024 // Ignore spaces and soft hyphens |
1023 if (ignoringSpaces) { | 1025 if (ignoringSpaces) { |
1024 ASSERT(lastWordBoundary == i); | 1026 ASSERT(lastWordBoundary == i); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !contains
OnlyWhitespace(j, len-j)) | 1101 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !contains
OnlyWhitespace(j, len-j)) |
1100 currMaxWidth += wordSpacing; | 1102 currMaxWidth += wordSpacing; |
1101 | 1103 |
1102 if (firstWord) { | 1104 if (firstWord) { |
1103 firstWord = false; | 1105 firstWord = false; |
1104 // If the first character in the run is breakable, then we consi
der ourselves to have a beginning | 1106 // If the first character in the run is breakable, then we consi
der ourselves to have a beginning |
1105 // minimum width of 0, since a break could occur right before ou
r run starts, preventing us from ever | 1107 // minimum width of 0, since a break could occur right before ou
r run starts, preventing us from ever |
1106 // being appended to a previous text run when considering the to
tal minimum width of the containing block. | 1108 // being appended to a previous text run when considering the to
tal minimum width of the containing block. |
1107 if (hasBreak) | 1109 if (hasBreak) |
1108 m_hasBreakableChar = true; | 1110 m_hasBreakableChar = true; |
1109 m_beginMinWidth = hasBreak ? 0 : currMinWidth; | 1111 m_firstLineMinWidth = hasBreak ? 0 : currMinWidth; |
1110 } | 1112 } |
1111 m_endMinWidth = currMinWidth; | 1113 m_lastLineLineMinWidth = currMinWidth; |
1112 | 1114 |
1113 if (currMinWidth > m_minWidth) | 1115 if (currMinWidth > m_minWidth) |
1114 m_minWidth = currMinWidth; | 1116 m_minWidth = currMinWidth; |
1115 currMinWidth = 0; | 1117 currMinWidth = 0; |
1116 | 1118 |
1117 i += wordLen - 1; | 1119 i += wordLen - 1; |
1118 } else { | 1120 } else { |
1119 // Nowrap can never be broken, so don't bother setting the | 1121 // Nowrap can never be broken, so don't bother setting the |
1120 // breakable character boolean. Pre can only be broken if we encount
er a newline. | 1122 // breakable character boolean. Pre can only be broken if we encount
er a newline. |
1121 if (style()->autoWrap() || isNewline) | 1123 if (style()->autoWrap() || isNewline) |
1122 m_hasBreakableChar = true; | 1124 m_hasBreakableChar = true; |
1123 | 1125 |
1124 if (currMinWidth > m_minWidth) | 1126 if (currMinWidth > m_minWidth) |
1125 m_minWidth = currMinWidth; | 1127 m_minWidth = currMinWidth; |
1126 currMinWidth = 0; | 1128 currMinWidth = 0; |
1127 | 1129 |
1128 if (isNewline) { // Only set if preserveNewline was true and we saw
a newline. | 1130 if (isNewline) { // Only set if preserveNewline was true and we saw
a newline. |
1129 if (firstLine) { | 1131 if (firstLine) { |
1130 firstLine = false; | 1132 firstLine = false; |
1131 leadWidth = 0; | 1133 leadWidth = 0; |
1132 if (!styleToUse->autoWrap()) | 1134 if (!styleToUse->autoWrap()) |
1133 m_beginMinWidth = currMaxWidth; | 1135 m_firstLineMinWidth = currMaxWidth; |
1134 } | 1136 } |
1135 | 1137 |
1136 if (currMaxWidth > m_maxWidth) | 1138 if (currMaxWidth > m_maxWidth) |
1137 m_maxWidth = currMaxWidth; | 1139 m_maxWidth = currMaxWidth; |
1138 currMaxWidth = 0; | 1140 currMaxWidth = 0; |
1139 } else { | 1141 } else { |
1140 TextRun run = RenderBlock::constructTextRun(this, f, this, i, 1,
styleToUse); | 1142 TextRun run = RenderBlock::constructTextRun(this, f, this, i, 1,
styleToUse); |
1141 run.setCharactersLength(len - i); | 1143 run.setCharactersLength(len - i); |
1142 ASSERT(run.charactersLength() >= run.length()); | 1144 ASSERT(run.charactersLength() >= run.length()); |
1143 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize(
)); | 1145 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize(
)); |
(...skipping 15 matching lines...) Expand all Loading... |
1159 currMaxWidth += wordSpacing; | 1161 currMaxWidth += wordSpacing; |
1160 | 1162 |
1161 m_minWidth = max(currMinWidth, m_minWidth); | 1163 m_minWidth = max(currMinWidth, m_minWidth); |
1162 m_maxWidth = max(currMaxWidth, m_maxWidth); | 1164 m_maxWidth = max(currMaxWidth, m_maxWidth); |
1163 | 1165 |
1164 if (!styleToUse->autoWrap()) | 1166 if (!styleToUse->autoWrap()) |
1165 m_minWidth = m_maxWidth; | 1167 m_minWidth = m_maxWidth; |
1166 | 1168 |
1167 if (styleToUse->whiteSpace() == PRE) { | 1169 if (styleToUse->whiteSpace() == PRE) { |
1168 if (firstLine) | 1170 if (firstLine) |
1169 m_beginMinWidth = m_maxWidth; | 1171 m_firstLineMinWidth = m_maxWidth; |
1170 m_endMinWidth = currMaxWidth; | 1172 m_lastLineLineMinWidth = currMaxWidth; |
1171 } | 1173 } |
1172 | 1174 |
1173 setPreferredLogicalWidthsDirty(false); | 1175 setPreferredLogicalWidthsDirty(false); |
1174 } | 1176 } |
1175 | 1177 |
1176 bool RenderText::isAllCollapsibleWhitespace() const | 1178 bool RenderText::isAllCollapsibleWhitespace() const |
1177 { | 1179 { |
1178 unsigned length = textLength(); | 1180 unsigned length = textLength(); |
1179 if (is8Bit()) { | 1181 if (is8Bit()) { |
1180 for (unsigned i = 0; i < length; ++i) { | 1182 for (unsigned i = 0; i < length; ++i) { |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1927 void RenderText::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | 1929 void RenderText::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
1928 { | 1930 { |
1929 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering)
; | 1931 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering)
; |
1930 RenderObject::reportMemoryUsage(memoryObjectInfo); | 1932 RenderObject::reportMemoryUsage(memoryObjectInfo); |
1931 info.addMember(m_text, "text"); | 1933 info.addMember(m_text, "text"); |
1932 info.addMember(m_firstTextBox, "firstTextBox"); | 1934 info.addMember(m_firstTextBox, "firstTextBox"); |
1933 info.addMember(m_lastTextBox, "lastTextBox"); | 1935 info.addMember(m_lastTextBox, "lastTextBox"); |
1934 } | 1936 } |
1935 | 1937 |
1936 } // namespace WebCore | 1938 } // namespace WebCore |
OLD | NEW |