Use LineLayoutTraversal for RenderText functions
[WebKit-https.git] / Source / WebCore / rendering / line / LineLayoutTraversal.cpp
1 /*
2  * Copyright (C) 2019 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "LineLayoutTraversal.h"
28
29 #include "InlineTextBox.h"
30 #include "RenderText.h"
31 #include "SimpleLineLayoutResolver.h"
32
33 namespace WebCore {
34 namespace LineLayoutTraversal {
35
36 FloatRect TextBox::rect() const
37 {
38     auto simple = [](const TextBoxIterator::SimplePath& path) {
39         return (*path.iterator).rect();
40     };
41
42     auto complex = [](const TextBoxIterator::ComplexPath& path) {
43         return path.inlineTextBox->frameRect();
44     };
45
46     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
47 }
48
49 FloatRect TextBox::logicalRect() const
50 {
51     auto simple = [](const TextBoxIterator::SimplePath& path) {
52         return (*path.iterator).rect();
53     };
54
55     auto complex = [](const TextBoxIterator::ComplexPath& path) {
56         return path.inlineTextBox->logicalFrameRect();
57     };
58
59     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
60 }
61
62 bool TextBox::hasHyphen() const
63 {
64     auto simple = [](const TextBoxIterator::SimplePath& path) {
65         return (*path.iterator).hasHyphen();
66     };
67
68     auto complex = [](const TextBoxIterator::ComplexPath& path) {
69         return path.inlineTextBox->hasHyphen();
70     };
71
72     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
73 }
74
75 bool TextBox::isLeftToRightDirection() const
76 {
77     auto simple = [](const TextBoxIterator::SimplePath&) {
78         return true;
79     };
80
81     auto complex = [](const TextBoxIterator::ComplexPath& path) {
82         return path.inlineTextBox->isLeftToRightDirection();
83     };
84
85     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
86 }
87
88 bool TextBox::dirOverride() const
89 {
90     auto simple = [](const TextBoxIterator::SimplePath&) {
91         return false;
92     };
93
94     auto complex = [](const TextBoxIterator::ComplexPath& path) {
95         return path.inlineTextBox->dirOverride();
96     };
97
98     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
99 }
100
101 StringView TextBox::text() const
102 {
103     auto simple = [](const TextBoxIterator::SimplePath& path) {
104         return (*path.iterator).text();
105     };
106
107     auto complex = [](const TextBoxIterator::ComplexPath& path) {
108         return StringView(path.inlineTextBox->renderer().text()).substring(path.inlineTextBox->start(), path.inlineTextBox->len());
109     };
110
111     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
112 }
113
114 bool TextBox::isLineBreak() const
115 {
116     auto simple = [](const TextBoxIterator::SimplePath& path) {
117         return (*path.iterator).isLineBreak();
118     };
119
120     auto complex = [](const TextBoxIterator::ComplexPath& path) {
121         return path.inlineTextBox->isLineBreak();
122     };
123
124     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
125 }
126
127 unsigned TextBox::localStartOffset() const
128 {
129     auto simple = [](const TextBoxIterator::SimplePath& path) {
130         return (*path.iterator).localStart();
131     };
132
133     auto complex = [](const TextBoxIterator::ComplexPath& path) {
134         return path.inlineTextBox->start();
135     };
136
137     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
138 }
139
140 unsigned TextBox::localEndOffset() const
141 {
142     auto simple = [](const TextBoxIterator::SimplePath& path) {
143         return (*path.iterator).localEnd();
144     };
145
146     auto complex = [](const TextBoxIterator::ComplexPath& path) {
147         return path.inlineTextBox->end();
148     };
149
150     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
151 }
152
153 unsigned TextBox::length() const
154 {
155     auto simple = [](const TextBoxIterator::SimplePath& path) {
156         return (*path.iterator).end() - (*path.iterator).start();
157     };
158
159     auto complex = [](const TextBoxIterator::ComplexPath& path) {
160         return path.inlineTextBox->len();
161     };
162
163     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
164 }
165
166 bool TextBox::isLastOnLine() const
167 {
168     auto simple = [](const TextBoxIterator::SimplePath& path) {
169         auto next = path.iterator;
170         ++next;
171         return next == path.end || (*path.iterator).lineIndex() != (*next).lineIndex();
172     };
173
174     auto complex = [](const TextBoxIterator::ComplexPath& path) {
175         auto* next = path.nextInlineTextBoxInTextOrder();
176         return !next || &path.inlineTextBox->root() != &next->root();
177     };
178
179     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
180 }
181
182 bool TextBox::isLast() const
183 {
184     auto simple = [](const TextBoxIterator::SimplePath& path) {
185         auto next = path.iterator;
186         ++next;
187         return next == path.end;
188     };
189
190     auto complex = [](const TextBoxIterator::ComplexPath& path) {
191         return !path.nextInlineTextBoxInTextOrder();
192     };
193
194     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
195 }
196
197
198 inline const TextBoxIterator& TextBox::iterator() const
199 {
200     return static_cast<const TextBoxIterator&>(*this);
201 }
202
203 TextBoxIterator::TextBoxIterator(const InlineTextBox* inlineTextBox)
204     : m_pathVariant(ComplexPath { inlineTextBox, { } })
205 {
206 }
207 TextBoxIterator::TextBoxIterator(Vector<const InlineTextBox*>&& sorted, size_t index)
208     : m_pathVariant(ComplexPath { index < sorted.size() ? sorted[index] : nullptr, WTFMove(sorted), index })
209 {
210 }
211
212 TextBoxIterator::TextBoxIterator(SimpleLineLayout::RunResolver::Iterator iterator, SimpleLineLayout::RunResolver::Iterator end)
213     : m_pathVariant(SimplePath { iterator, end })
214 {
215 }
216
217 TextBoxIterator& TextBoxIterator::traverseNextInVisualOrder()
218 {
219     auto simple = [](SimplePath& path) {
220         ++path.iterator;
221     };
222
223     auto complex = [](ComplexPath& path) {
224         path.inlineTextBox = path.inlineTextBox->nextTextBox();
225     };
226
227     WTF::switchOn(m_pathVariant, simple, complex);
228
229     return *this;
230 }
231
232 const InlineTextBox* TextBoxIterator::ComplexPath::nextInlineTextBoxInTextOrder() const
233 {
234     if (!sortedInlineTextBoxes.isEmpty()) {
235         if (sortedInlineTextBoxIndex + 1 < sortedInlineTextBoxes.size())
236             return sortedInlineTextBoxes[sortedInlineTextBoxIndex + 1];
237         return nullptr;
238     }
239     return inlineTextBox->nextTextBox();
240 }
241
242 TextBoxIterator& TextBoxIterator::traverseNextInTextOrder()
243 {
244     auto simple = [](SimplePath& path) {
245         ++path.iterator;
246     };
247
248     auto complex = [](ComplexPath& path) {
249         path.inlineTextBox = path.nextInlineTextBoxInTextOrder();
250         if (!path.sortedInlineTextBoxes.isEmpty())
251             ++path.sortedInlineTextBoxIndex;
252     };
253
254     WTF::switchOn(m_pathVariant, simple, complex);
255
256     return *this;
257 }
258
259 bool TextBoxIterator::operator==(const TextBoxIterator& other) const
260 {
261     if (m_pathVariant.index() != other.m_pathVariant.index())
262         return false;
263
264     auto simple = [&](const SimplePath& path) {
265         return path.iterator == WTF::get<SimplePath>(other.m_pathVariant).iterator;
266     };
267
268     auto complex = [&](const ComplexPath& path) {
269         return path.inlineTextBox == WTF::get<ComplexPath>(other.m_pathVariant).inlineTextBox;
270     };
271
272     return WTF::switchOn(m_pathVariant, simple, complex);
273 }
274
275 bool TextBoxIterator::atEnd() const
276 {
277     auto simple = [&](const SimplePath& path) {
278         return path.iterator == path.end;
279     };
280
281     auto complex = [&](const ComplexPath& path) {
282         return !path.inlineTextBox;
283     };
284
285     return WTF::switchOn(m_pathVariant, simple, complex);
286 }
287
288 TextBoxIterator firstTextBoxFor(const RenderText& text)
289 {
290     if (auto* simpleLineLayout = text.simpleLineLayout()) {
291         auto range = simpleLineLayout->runResolver().rangeForRenderer(text);
292         return { range.begin(), range.end() };
293     }
294
295     return TextBoxIterator { text.firstTextBox() };
296 }
297
298 TextBoxIterator firstTextBoxInTextOrderFor(const RenderText& text)
299 {
300     if (!text.simpleLineLayout() && text.containsReversedText()) {
301         Vector<const InlineTextBox*> sortedTextBoxes;
302         for (auto* textBox = text.firstTextBox(); textBox; textBox = textBox->nextTextBox())
303             sortedTextBoxes.append(textBox);
304         std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart);
305         return TextBoxIterator { WTFMove(sortedTextBoxes), 0 };
306     }
307
308     return firstTextBoxFor(text);
309 }
310
311 TextBoxRange textBoxesFor(const RenderText& text)
312 {
313     return { firstTextBoxFor(text) };
314 }
315
316 }
317 }