34d226a3324fb9be50bc3fed0cb5b2465a57fb1f
[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 unsigned TextBox::localStartOffset() const
115 {
116     auto simple = [](const TextBoxIterator::SimplePath& path) {
117         return (*path.iterator).localStart();
118     };
119
120     auto complex = [](const TextBoxIterator::ComplexPath& path) {
121         return path.inlineTextBox->start();
122     };
123
124     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
125 }
126
127 unsigned TextBox::localEndOffset() const
128 {
129     auto simple = [](const TextBoxIterator::SimplePath& path) {
130         return (*path.iterator).localEnd();
131     };
132
133     auto complex = [](const TextBoxIterator::ComplexPath& path) {
134         return path.inlineTextBox->end();
135     };
136
137     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
138 }
139
140 unsigned TextBox::length() const
141 {
142     auto simple = [](const TextBoxIterator::SimplePath& path) {
143         return (*path.iterator).end() - (*path.iterator).start();
144     };
145
146     auto complex = [](const TextBoxIterator::ComplexPath& path) {
147         return path.inlineTextBox->len();
148     };
149
150     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
151 }
152
153 bool TextBox::isLastOnLine() const
154 {
155     auto simple = [](const TextBoxIterator::SimplePath& path) {
156         auto next = path.iterator;
157         ++next;
158         return next == path.end || (*path.iterator).lineIndex() != (*next).lineIndex();
159     };
160
161     auto complex = [](const TextBoxIterator::ComplexPath& path) {
162         auto* next = path.nextInlineTextBoxInTextOrder();
163         return !next || &path.inlineTextBox->root() != &next->root();
164     };
165
166     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
167 }
168
169 bool TextBox::isLast() const
170 {
171     auto simple = [](const TextBoxIterator::SimplePath& path) {
172         auto next = path.iterator;
173         ++next;
174         return next == path.end;
175     };
176
177     auto complex = [](const TextBoxIterator::ComplexPath& path) {
178         return !path.nextInlineTextBoxInTextOrder();
179     };
180
181     return WTF::switchOn(iterator().m_pathVariant, simple, complex);
182 }
183
184
185 inline const TextBoxIterator& TextBox::iterator() const
186 {
187     return static_cast<const TextBoxIterator&>(*this);
188 }
189
190 TextBoxIterator::TextBoxIterator(const InlineTextBox* inlineTextBox)
191     : m_pathVariant(ComplexPath { inlineTextBox, { } })
192 {
193 }
194 TextBoxIterator::TextBoxIterator(Vector<const InlineTextBox*>&& sorted, size_t index)
195     : m_pathVariant(ComplexPath { index < sorted.size() ? sorted[index] : nullptr, WTFMove(sorted), index })
196 {
197 }
198
199 TextBoxIterator::TextBoxIterator(SimpleLineLayout::RunResolver::Iterator iterator, SimpleLineLayout::RunResolver::Iterator end)
200     : m_pathVariant(SimplePath { iterator, end })
201 {
202 }
203
204 TextBoxIterator& TextBoxIterator::traverseNextInVisualOrder()
205 {
206     auto simple = [](SimplePath& path) {
207         ++path.iterator;
208     };
209
210     auto complex = [](ComplexPath& path) {
211         path.inlineTextBox = path.inlineTextBox->nextTextBox();
212     };
213
214     WTF::switchOn(m_pathVariant, simple, complex);
215
216     return *this;
217 }
218
219 const InlineTextBox* TextBoxIterator::ComplexPath::nextInlineTextBoxInTextOrder() const
220 {
221     if (!sortedInlineTextBoxes.isEmpty()) {
222         if (sortedInlineTextBoxIndex + 1 < sortedInlineTextBoxes.size())
223             return sortedInlineTextBoxes[sortedInlineTextBoxIndex + 1];
224         return nullptr;
225     }
226     return inlineTextBox->nextTextBox();
227 }
228
229 TextBoxIterator& TextBoxIterator::traverseNextInTextOrder()
230 {
231     auto simple = [](SimplePath& path) {
232         ++path.iterator;
233     };
234
235     auto complex = [](ComplexPath& path) {
236         path.inlineTextBox = path.nextInlineTextBoxInTextOrder();
237         if (!path.sortedInlineTextBoxes.isEmpty())
238             ++path.sortedInlineTextBoxIndex;
239     };
240
241     WTF::switchOn(m_pathVariant, simple, complex);
242
243     return *this;
244 }
245
246 bool TextBoxIterator::operator==(const TextBoxIterator& other) const
247 {
248     if (m_pathVariant.index() != other.m_pathVariant.index())
249         return false;
250
251     auto simple = [&](const SimplePath& path) {
252         return path.iterator == WTF::get<SimplePath>(other.m_pathVariant).iterator;
253     };
254
255     auto complex = [&](const ComplexPath& path) {
256         return path.inlineTextBox == WTF::get<ComplexPath>(other.m_pathVariant).inlineTextBox;
257     };
258
259     return WTF::switchOn(m_pathVariant, simple, complex);
260 }
261
262 bool TextBoxIterator::atEnd() const
263 {
264     auto simple = [&](const SimplePath& path) {
265         return path.iterator == path.end;
266     };
267
268     auto complex = [&](const ComplexPath& path) {
269         return !path.inlineTextBox;
270     };
271
272     return WTF::switchOn(m_pathVariant, simple, complex);
273 }
274
275 TextBoxIterator firstTextBoxInVisualOrderFor(const RenderText& text)
276 {
277     if (auto* simpleLineLayout = text.simpleLineLayout()) {
278         auto range = simpleLineLayout->runResolver().rangeForRenderer(text);
279         return { range.begin(), range.end() };
280     }
281
282     return TextBoxIterator { text.firstTextBox() };
283 }
284
285 TextBoxIterator firstTextBoxInTextOrderFor(const RenderText& text)
286 {
287     if (!text.simpleLineLayout() && text.containsReversedText()) {
288         Vector<const InlineTextBox*> sortedTextBoxes;
289         for (auto* textBox = text.firstTextBox(); textBox; textBox = textBox->nextTextBox())
290             sortedTextBoxes.append(textBox);
291         std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart);
292         return TextBoxIterator { WTFMove(sortedTextBoxes), 0 };
293     }
294
295     return firstTextBoxInVisualOrderFor(text);
296 }
297
298 TextBoxRange textBoxRangeFor(const RenderText& text)
299 {
300     return { firstTextBoxInVisualOrderFor(text) };
301 }
302
303 }
304 }