Copying content with shadow DOM doesn't copy any contents
[WebKit-https.git] / Source / WebCore / editing / TextIterator.h
1 /*
2  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 // FIXME: Move each iterator class into a separate header file.
29
30 #include "FindOptions.h"
31 #include "Range.h"
32 #include "TextIteratorBehavior.h"
33 #include <wtf/Vector.h>
34 #include <wtf/text/StringView.h>
35
36 namespace WebCore {
37
38 class InlineTextBox;
39 class RenderText;
40 class RenderTextFragment;
41
42 namespace SimpleLineLayout {
43 class RunResolver;
44 }
45
46 WEBCORE_EXPORT String plainText(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
47
48 WEBCORE_EXPORT String plainText(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
49 WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
50 Ref<Range> findPlainText(const Range&, const String&, FindOptions);
51 WEBCORE_EXPORT Ref<Range> findClosestPlainText(const Range&, const String&, FindOptions, unsigned);
52 WEBCORE_EXPORT bool hasAnyPlainText(const Range&, TextIteratorBehavior = TextIteratorDefaultBehavior);
53 bool findPlainText(const String& document, const String&, FindOptions); // Lets us use the search algorithm on a string.
54
55 // FIXME: Move this somewhere else in the editing directory. It doesn't belong here.
56 bool isRendererReplacedElement(RenderObject*);
57
58 class BitStack {
59 public:
60     BitStack();
61     ~BitStack();
62
63     void push(bool);
64     void pop();
65
66     bool top() const;
67     unsigned size() const;
68
69 private:
70     unsigned m_size;
71     Vector<unsigned, 1> m_words;
72 };
73
74 class TextIteratorCopyableText {
75 public:
76     TextIteratorCopyableText()
77         : m_singleCharacter(0)
78         , m_offset(0)
79         , m_length(0)
80     {
81     }
82
83     StringView text() const { return m_singleCharacter ? StringView(&m_singleCharacter, 1) : StringView(m_string).substring(m_offset, m_length); }
84     void appendToStringBuilder(StringBuilder&) const;
85
86     void reset();
87     void set(String&&);
88     void set(String&&, unsigned offset, unsigned length);
89     void set(UChar);
90
91 private:
92     UChar m_singleCharacter;
93     String m_string;
94     unsigned m_offset;
95     unsigned m_length;
96 };
97
98 // Iterates through the DOM range, returning all the text, and 0-length boundaries
99 // at points where replaced elements break up the text flow. The text is delivered in
100 // the chunks it's already stored in, to avoid copying any text.
101
102 class TextIterator {
103 public:
104     explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);
105     WEBCORE_EXPORT explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
106     WEBCORE_EXPORT ~TextIterator();
107
108     bool atEnd() const { return !m_positionNode; }
109     WEBCORE_EXPORT void advance();
110
111     StringView text() const { ASSERT(!atEnd()); return m_text; }
112     WEBCORE_EXPORT Ref<Range> range() const;
113     WEBCORE_EXPORT Node* node() const;
114
115     const TextIteratorCopyableText& copyableText() const { ASSERT(!atEnd()); return m_copyableText; }
116     void appendTextToStringBuilder(StringBuilder& builder) const { copyableText().appendToStringBuilder(builder); }
117
118     WEBCORE_EXPORT static int rangeLength(const Range*, bool spacesForReplacedElements = false);
119     WEBCORE_EXPORT static RefPtr<Range> rangeFromLocationAndLength(ContainerNode* scope, int rangeLocation, int rangeLength, bool spacesForReplacedElements = false);
120     WEBCORE_EXPORT static bool getLocationAndLengthFromRange(Node* scope, const Range*, size_t& location, size_t& length);
121     WEBCORE_EXPORT static Ref<Range> subrange(Range& entireRange, int characterOffset, int characterCount);
122
123 private:
124     void init();
125     void exitNode(Node*);
126     bool shouldRepresentNodeOffsetZero();
127     bool shouldEmitSpaceBeforeAndAfterNode(Node&);
128     void representNodeOffsetZero();
129     bool handleTextNode();
130     bool handleReplacedElement();
131     bool handleNonTextNode();
132     void handleTextBox();
133     void handleTextNodeFirstLetter(RenderTextFragment&);
134     void emitCharacter(UChar, Node& characterNode, Node* offsetBaseNode, int textStartOffset, int textEndOffset);
135     void emitText(Text& textNode, RenderText&, int textStartOffset, int textEndOffset);
136
137     Node* baseNodeForEmittingNewLine() const;
138
139     const TextIteratorBehavior m_behavior { TextIteratorDefaultBehavior };
140
141     // Current position, not necessarily of the text being returned, but position as we walk through the DOM tree.
142     Node* m_node { nullptr };
143     int m_offset { 0 };
144     bool m_handledNode { false };
145     bool m_handledChildren { false };
146     BitStack m_fullyClippedStack;
147
148     // The range.
149     Node* m_startContainer { nullptr };
150     int m_startOffset { 0 };
151     Node* m_endContainer { nullptr };
152     int m_endOffset { 0 };
153     Node* m_pastEndNode { nullptr };
154
155     // The current text and its position, in the form to be returned from the iterator.
156     Node* m_positionNode { nullptr };
157     mutable Node* m_positionOffsetBaseNode { nullptr };
158     mutable int m_positionStartOffset { 0 };
159     mutable int m_positionEndOffset { 0 };
160     TextIteratorCopyableText m_copyableText;
161     StringView m_text;
162
163     // Used when there is still some pending text from the current node; when these are false and null, we go back to normal iterating.
164     Node* m_nodeForAdditionalNewline { nullptr };
165     InlineTextBox* m_textBox { nullptr };
166
167     // Used when iterating over :first-letter text to save pointer to remaining text box.
168     InlineTextBox* m_remainingTextBox { nullptr };
169
170     // Used to point to RenderText object for :first-letter.
171     RenderText* m_firstLetterText { nullptr };
172
173     // Used to do the whitespace collapsing logic.
174     Text* m_lastTextNode { nullptr };
175     bool m_lastTextNodeEndedWithCollapsedSpace { false };
176     UChar m_lastCharacter { 0 };
177
178     // Used to do simple line layout run logic.
179     bool m_nextRunNeedsWhitespace { false };
180     unsigned m_accumulatedSimpleTextLengthInFlow { 0 };
181     Text* m_previousSimpleTextNodeInFlow { nullptr };
182     std::unique_ptr<SimpleLineLayout::RunResolver> m_flowRunResolverCache;
183
184     // Used when text boxes are out of order (Hebrew/Arabic with embedded LTR text)
185     Vector<InlineTextBox*> m_sortedTextBoxes;
186     size_t m_sortedTextBoxesPosition { 0 };
187
188     // Used when deciding whether to emit a "positioning" (e.g. newline) before any other content
189     bool m_hasEmitted { false };
190
191     // Used when deciding text fragment created by :first-letter should be looked into.
192     bool m_handledFirstLetter { false };
193 };
194
195 // Iterates through the DOM range, returning all the text, and 0-length boundaries
196 // at points where replaced elements break up the text flow. The text comes back in
197 // chunks so as to optimize for performance of the iteration.
198 class SimplifiedBackwardsTextIterator {
199 public:
200     explicit SimplifiedBackwardsTextIterator(const Range&);
201
202     bool atEnd() const { return !m_positionNode; }
203     void advance();
204
205     StringView text() const { ASSERT(!atEnd()); return m_text; }
206     WEBCORE_EXPORT Ref<Range> range() const;
207     Node* node() const { ASSERT(!atEnd()); return m_node; }
208
209 private:
210     void exitNode();
211     bool handleTextNode();
212     RenderText* handleFirstLetter(int& startOffset, int& offsetInNode);
213     bool handleReplacedElement();
214     bool handleNonTextNode();
215     void emitCharacter(UChar, Node&, int startOffset, int endOffset);
216     bool advanceRespectingRange(Node*);
217
218     const TextIteratorBehavior m_behavior { TextIteratorDefaultBehavior };
219
220     // Current position, not necessarily of the text being returned, but position as we walk through the DOM tree.
221     Node* m_node { nullptr };
222     int m_offset { 0 };
223     bool m_handledNode { false };
224     bool m_handledChildren { false };
225     BitStack m_fullyClippedStack;
226
227     // The range.
228     Node* m_startContainer { nullptr };
229     int m_startOffset { 0 };
230     Node* m_endContainer { nullptr };
231     int m_endOffset { 0 };
232     
233     // The current text and its position, in the form to be returned from the iterator.
234     Node* m_positionNode { nullptr };
235     int m_positionStartOffset { 0 };
236     int m_positionEndOffset { 0 };
237     TextIteratorCopyableText m_copyableText;
238     StringView m_text;
239
240     // Used to do the whitespace logic.
241     Text* m_lastTextNode { nullptr };
242     UChar m_lastCharacter { 0 };
243
244     // Whether m_node has advanced beyond the iteration range (i.e. m_startContainer).
245     bool m_havePassedStartContainer { false };
246
247     // Should handle first-letter renderer in the next call to handleTextNode.
248     bool m_shouldHandleFirstLetter { false };
249 };
250
251 // Builds on the text iterator, adding a character position so we can walk one
252 // character at a time, or faster, as needed. Useful for searching.
253 class CharacterIterator {
254 public:
255     explicit CharacterIterator(const Range&, TextIteratorBehavior = TextIteratorDefaultBehavior);
256     
257     bool atEnd() const { return m_underlyingIterator.atEnd(); }
258     void advance(int numCharacters);
259     
260     StringView text() const { return m_underlyingIterator.text().substring(m_runOffset); }
261     Ref<Range> range() const;
262
263     bool atBreak() const { return m_atBreak; }
264     int characterOffset() const { return m_offset; }
265
266 private:
267     TextIterator m_underlyingIterator;
268
269     int m_offset;
270     int m_runOffset;
271     bool m_atBreak;
272 };
273     
274 class BackwardsCharacterIterator {
275 public:
276     explicit BackwardsCharacterIterator(const Range&);
277
278     bool atEnd() const { return m_underlyingIterator.atEnd(); }
279     void advance(int numCharacters);
280
281     Ref<Range> range() const;
282
283 private:
284     SimplifiedBackwardsTextIterator m_underlyingIterator;
285
286     int m_offset;
287     int m_runOffset;
288     bool m_atBreak;
289 };
290
291 // Similar to the TextIterator, except that the chunks of text returned are "well behaved", meaning
292 // they never split up a word. This is useful for spell checking and perhaps one day for searching as well.
293 class WordAwareIterator {
294 public:
295     explicit WordAwareIterator(const Range&);
296
297     bool atEnd() const { return !m_didLookAhead && m_underlyingIterator.atEnd(); }
298     void advance();
299
300     StringView text() const;
301
302 private:
303     TextIterator m_underlyingIterator;
304
305     // Text from the previous chunk from the text iterator.
306     TextIteratorCopyableText m_previousText;
307
308     // Many chunks from text iterator concatenated.
309     Vector<UChar> m_buffer;
310     
311     // Did we have to look ahead in the text iterator to confirm the current chunk?
312     bool m_didLookAhead;
313 };
314
315 } // namespace WebCore