1 | /* |
2 | * (C) 1999 Lars Knoll (knoll@kde.org) |
3 | * (C) 2000 Dirk Mueller (mueller@kde.org) |
4 | * Copyright (C) 2004-2017 Apple Inc. All rights reserved. |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public License |
17 | * along with this library; see the file COPYING.LIB. If not, write to |
18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | * Boston, MA 02110-1301, USA. |
20 | * |
21 | */ |
22 | |
23 | #pragma once |
24 | |
25 | #include "RenderElement.h" |
26 | #include "RenderTextLineBoxes.h" |
27 | #include "SimpleLineLayout.h" |
28 | #include "Text.h" |
29 | #include <wtf/Forward.h> |
30 | #include <wtf/text/TextBreakIterator.h> |
31 | |
32 | namespace WebCore { |
33 | |
34 | class Font; |
35 | class InlineTextBox; |
36 | struct GlyphOverflow; |
37 | |
38 | class RenderText : public RenderObject { |
39 | WTF_MAKE_ISO_ALLOCATED(RenderText); |
40 | public: |
41 | RenderText(Text&, const String&); |
42 | RenderText(Document&, const String&); |
43 | |
44 | virtual ~RenderText(); |
45 | |
46 | WEBCORE_EXPORT Text* textNode() const; |
47 | |
48 | virtual bool isTextFragment() const; |
49 | |
50 | const RenderStyle& style() const; |
51 | const RenderStyle& firstLineStyle() const; |
52 | const RenderStyle* getCachedPseudoStyle(PseudoId, const RenderStyle* parentStyle = nullptr) const; |
53 | |
54 | Color selectionBackgroundColor() const; |
55 | Color selectionForegroundColor() const; |
56 | Color selectionEmphasisMarkColor() const; |
57 | std::unique_ptr<RenderStyle> selectionPseudoStyle() const; |
58 | |
59 | virtual String originalText() const; |
60 | |
61 | void (InlineTextBox& box) { m_lineBoxes.extract(box); } |
62 | void attachTextBox(InlineTextBox& box) { m_lineBoxes.attach(box); } |
63 | void removeTextBox(InlineTextBox& box) { m_lineBoxes.remove(box); } |
64 | |
65 | StringImpl& text() const { return *m_text.impl(); } // Since m_text can never be null, returning this type means callers won't null check. |
66 | String textWithoutConvertingBackslashToYenSymbol() const; |
67 | |
68 | InlineTextBox* createInlineTextBox() { return m_lineBoxes.createAndAppendLineBox(*this); } |
69 | void dirtyLineBoxes(bool fullLayout); |
70 | |
71 | void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const final; |
72 | Vector<IntRect> absoluteRectsForRange(unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = nullptr) const; |
73 | #if PLATFORM(IOS_FAMILY) |
74 | void collectSelectionRects(Vector<SelectionRect>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max()) final; |
75 | #endif |
76 | |
77 | void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const final; |
78 | Vector<FloatQuad> absoluteQuadsForRange(unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = nullptr) const; |
79 | |
80 | Vector<FloatQuad> absoluteQuadsClippedToEllipsis() const; |
81 | |
82 | Position positionForPoint(const LayoutPoint&) final; |
83 | |
84 | UChar characterAt(unsigned) const; |
85 | unsigned length() const final { return text().length(); } |
86 | |
87 | void positionLineBox(InlineTextBox&); |
88 | |
89 | virtual float width(unsigned from, unsigned length, const FontCascade&, float xPos, HashSet<const Font*>* fallbackFonts = nullptr, GlyphOverflow* = nullptr) const; |
90 | virtual float width(unsigned from, unsigned length, float xPos, bool firstLine = false, HashSet<const Font*>* fallbackFonts = nullptr, GlyphOverflow* = nullptr) const; |
91 | |
92 | float minLogicalWidth() const; |
93 | float maxLogicalWidth() const; |
94 | |
95 | struct Widths { |
96 | float min { 0 }; |
97 | float max { 0 }; |
98 | float beginMin { 0 }; |
99 | float endMin { 0 }; |
100 | float beginMax { 0 }; |
101 | float endMax { 0 }; |
102 | bool beginWS { false }; |
103 | bool endWS { false }; |
104 | bool hasBreakableChar { false }; |
105 | bool hasBreak { false }; |
106 | }; |
107 | Widths trimmedPreferredWidths(float leadWidth, bool& stripFrontSpaces); |
108 | |
109 | float hangablePunctuationStartWidth(unsigned index) const; |
110 | float hangablePunctuationEndWidth(unsigned index) const; |
111 | unsigned firstCharacterIndexStrippingSpaces() const; |
112 | unsigned lastCharacterIndexStrippingSpaces() const; |
113 | static bool isHangableStopOrComma(UChar); |
114 | |
115 | WEBCORE_EXPORT virtual IntRect linesBoundingBox() const; |
116 | LayoutRect linesVisualOverflowBoundingBox() const; |
117 | |
118 | WEBCORE_EXPORT IntPoint firstRunLocation() const; |
119 | |
120 | virtual void setText(const String&, bool force = false); |
121 | void setTextWithOffset(const String&, unsigned offset, unsigned len, bool force = false); |
122 | |
123 | bool canBeSelectionLeaf() const override { return true; } |
124 | |
125 | LayoutRect collectSelectionRectsForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>&); |
126 | |
127 | LayoutUnit marginLeft() const { return minimumValueForLength(style().marginLeft(), 0); } |
128 | LayoutUnit marginRight() const { return minimumValueForLength(style().marginRight(), 0); } |
129 | |
130 | InlineTextBox* firstTextBox() const { return m_lineBoxes.first(); } |
131 | InlineTextBox* lastTextBox() const { return m_lineBoxes.last(); } |
132 | |
133 | int caretMinOffset() const final; |
134 | int caretMaxOffset() const final; |
135 | unsigned countRenderedCharacterOffsetsUntil(unsigned) const; |
136 | bool containsRenderedCharacterOffset(unsigned) const; |
137 | bool containsCaretOffset(unsigned) const; |
138 | bool hasRenderedText() const; |
139 | |
140 | // FIXME: These should return unsigneds. |
141 | int previousOffset(int current) const final; |
142 | int previousOffsetForBackwardDeletion(int current) const final; |
143 | int nextOffset(int current) const final; |
144 | |
145 | bool containsReversedText() const { return m_containsReversedText; } |
146 | |
147 | void momentarilyRevealLastTypedCharacter(unsigned offsetAfterLastTypedCharacter); |
148 | |
149 | InlineTextBox* findNextInlineTextBox(int offset, int& pos) const { return m_lineBoxes.findNext(offset, pos); } |
150 | |
151 | bool isAllCollapsibleWhitespace() const; |
152 | |
153 | bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; } |
154 | |
155 | void removeAndDestroyTextBoxes(); |
156 | |
157 | virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); |
158 | |
159 | virtual std::unique_ptr<InlineTextBox> createTextBox(); |
160 | |
161 | #if ENABLE(TEXT_AUTOSIZING) |
162 | float candidateComputedTextSize() const { return m_candidateComputedTextSize; } |
163 | void setCandidateComputedTextSize(float size) { m_candidateComputedTextSize = size; } |
164 | #endif |
165 | |
166 | void ensureLineBoxes(); |
167 | void deleteLineBoxesBeforeSimpleLineLayout(); |
168 | const SimpleLineLayout::Layout* simpleLineLayout() const; |
169 | |
170 | StringView stringView(unsigned start = 0, Optional<unsigned> stop = WTF::nullopt) const; |
171 | |
172 | LayoutUnit topOfFirstText() const; |
173 | |
174 | bool containsOnlyHTMLWhitespace(unsigned from, unsigned length) const; |
175 | |
176 | bool canUseSimplifiedTextMeasuring() const { return m_canUseSimplifiedTextMeasuring; } |
177 | |
178 | Vector<std::pair<unsigned, unsigned>> draggedContentRangesBetweenOffsets(unsigned startOffset, unsigned endOffset) const; |
179 | |
180 | RenderInline* inlineWrapperForDisplayContents(); |
181 | void setInlineWrapperForDisplayContents(RenderInline*); |
182 | |
183 | static RenderText* findByDisplayContentsInlineWrapperCandidate(RenderElement&); |
184 | |
185 | protected: |
186 | virtual void computePreferredLogicalWidths(float leadWidth); |
187 | void willBeDestroyed() override; |
188 | |
189 | virtual void setRenderedText(const String&); |
190 | virtual UChar previousCharacter() const; |
191 | |
192 | RenderTextLineBoxes m_lineBoxes; |
193 | |
194 | private: |
195 | RenderText(Node&, const String&); |
196 | |
197 | const char* renderName() const override; |
198 | |
199 | bool canHaveChildren() const final { return false; } |
200 | |
201 | VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override; |
202 | |
203 | void setSelectionState(SelectionState) final; |
204 | LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) final; |
205 | LayoutRect localCaretRect(InlineBox*, unsigned caretOffset, LayoutUnit* = nullptr) override; |
206 | LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const final; |
207 | |
208 | void computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow&); |
209 | |
210 | bool computeCanUseSimpleFontCodePath() const; |
211 | |
212 | bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction) final { ASSERT_NOT_REACHED(); return false; } |
213 | |
214 | float widthFromCache(const FontCascade&, unsigned start, unsigned len, float xPos, HashSet<const Font*>* fallbackFonts, GlyphOverflow*, const RenderStyle&) const; |
215 | bool computeUseBackslashAsYenSymbol() const; |
216 | |
217 | void secureText(UChar mask); |
218 | |
219 | LayoutRect collectSelectionRectsForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>*); |
220 | bool computeCanUseSimplifiedTextMeasuring() const; |
221 | |
222 | void node() const = delete; |
223 | void container() const = delete; // Use parent() instead. |
224 | void container(const RenderLayerModelObject&, bool&) const = delete; // Use parent() instead. |
225 | |
226 | // We put the bitfield first to minimize padding on 64-bit. |
227 | unsigned m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines. |
228 | unsigned m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n'). |
229 | unsigned m_hasTab : 1; // Whether or not we have a variable width tab character (e.g., <pre> with '\t'). |
230 | unsigned m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre) |
231 | unsigned m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre) |
232 | unsigned m_linesDirty : 1; // This bit indicates that the text run has already dirtied specific |
233 | // line boxes, and this hint will enable layoutInlineChildren to avoid |
234 | // just dirtying everything when character data is modified (e.g., appended/inserted |
235 | // or removed). |
236 | unsigned m_containsReversedText : 1; |
237 | unsigned m_isAllASCII : 1; |
238 | unsigned m_canUseSimpleFontCodePath : 1; |
239 | mutable unsigned m_knownToHaveNoOverflowAndNoFallbackFonts : 1; |
240 | unsigned m_useBackslashAsYenSymbol : 1; |
241 | unsigned m_originalTextDiffersFromRendered : 1; |
242 | unsigned m_hasInlineWrapperForDisplayContents : 1; |
243 | unsigned m_canUseSimplifiedTextMeasuring : 1; |
244 | |
245 | #if ENABLE(TEXT_AUTOSIZING) |
246 | // FIXME: This should probably be part of the text sizing structures in Document instead. That would save some memory. |
247 | float m_candidateComputedTextSize { 0 }; |
248 | #endif |
249 | float m_minWidth { -1 }; |
250 | float m_maxWidth { -1 }; |
251 | float m_beginMinWidth { 0 }; |
252 | float m_endMinWidth { 0 }; |
253 | |
254 | String m_text; |
255 | }; |
256 | |
257 | String applyTextTransform(const RenderStyle&, const String&, UChar previousCharacter); |
258 | String capitalize(const String&, UChar previousCharacter); |
259 | LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak); |
260 | |
261 | inline UChar RenderText::characterAt(unsigned i) const |
262 | { |
263 | return i >= length() ? 0 : text()[i]; |
264 | } |
265 | |
266 | inline const RenderStyle& RenderText::style() const |
267 | { |
268 | return parent()->style(); |
269 | } |
270 | |
271 | inline const RenderStyle& RenderText::firstLineStyle() const |
272 | { |
273 | return parent()->firstLineStyle(); |
274 | } |
275 | |
276 | inline const RenderStyle* RenderText::getCachedPseudoStyle(PseudoId pseudoId, const RenderStyle* parentStyle) const |
277 | { |
278 | return parent()->getCachedPseudoStyle(pseudoId, parentStyle); |
279 | } |
280 | |
281 | inline Color RenderText::selectionBackgroundColor() const |
282 | { |
283 | return parent()->selectionBackgroundColor(); |
284 | } |
285 | |
286 | inline Color RenderText::selectionForegroundColor() const |
287 | { |
288 | return parent()->selectionForegroundColor(); |
289 | } |
290 | |
291 | inline Color RenderText::selectionEmphasisMarkColor() const |
292 | { |
293 | return parent()->selectionEmphasisMarkColor(); |
294 | } |
295 | |
296 | inline std::unique_ptr<RenderStyle> RenderText::selectionPseudoStyle() const |
297 | { |
298 | return parent()->selectionPseudoStyle(); |
299 | } |
300 | |
301 | inline RenderText* Text::renderer() const |
302 | { |
303 | return downcast<RenderText>(Node::renderer()); |
304 | } |
305 | |
306 | } // namespace WebCore |
307 | |
308 | SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderText, isText()) |
309 | |