1/*
2 * Copyright (C) 2013 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#pragma once
27
28#include "LayoutRect.h"
29#include "RenderBlockFlow.h"
30#include "SimpleLineLayout.h"
31#include "SimpleLineLayoutFlowContents.h"
32#include <wtf/IteratorRange.h>
33#include <wtf/text/WTFString.h>
34
35namespace WebCore {
36namespace SimpleLineLayout {
37
38class RunResolver {
39 WTF_MAKE_FAST_ALLOCATED;
40public:
41 class Iterator;
42
43 class Run {
44 public:
45 explicit Run(const Iterator&);
46
47 // Position relative to the enclosing flow block.
48 unsigned start() const;
49 unsigned end() const;
50 // Position relative to the actual renderer.
51 unsigned localStart() const;
52 unsigned localEnd() const;
53
54 float logicalLeft() const;
55 float logicalRight() const;
56
57 FloatRect rect() const;
58 float expansion() const;
59 ExpansionBehavior expansionBehavior() const;
60 int baselinePosition() const;
61 StringView text() const;
62 String textWithHyphen() const;
63 const RenderObject& renderer() const;
64 bool isEndOfLine() const;
65 bool hasHyphen() const { return m_iterator.simpleRun().hasHyphen; }
66 const SimpleLineLayout::Run& simpleRun() const { return m_iterator.simpleRun(); }
67
68 unsigned lineIndex() const;
69
70 private:
71 float computeBaselinePosition() const;
72 void constructStringForHyphenIfNeeded();
73
74 const Iterator& m_iterator;
75 };
76
77 class Iterator {
78 friend class Run;
79 friend class RunResolver;
80 friend class LineResolver;
81 public:
82 Iterator(const RunResolver&, unsigned runIndex, unsigned lineIndex);
83
84 Iterator& operator++();
85 Iterator& operator--();
86
87 bool operator==(const Iterator&) const;
88 bool operator!=(const Iterator&) const;
89
90 Run operator*() const;
91
92 private:
93 const SimpleLineLayout::Run& simpleRun() const;
94 unsigned lineIndex() const { return m_lineIndex; }
95 Iterator& advance();
96 Iterator& advanceLines(unsigned);
97 const RunResolver& resolver() const { return m_resolver; }
98 bool inQuirksMode() const { return m_resolver.m_inQuirksMode; }
99
100 const RunResolver& m_resolver;
101 unsigned m_runIndex;
102 unsigned m_lineIndex;
103 };
104
105 RunResolver(const RenderBlockFlow&, const Layout&);
106
107 const RenderBlockFlow& flow() const { return m_flowRenderer; }
108 const FlowContents& flowContents() const { return m_flowContents; }
109 Iterator begin() const;
110 Iterator end() const;
111
112 WTF::IteratorRange<Iterator> rangeForRect(const LayoutRect&) const;
113 WTF::IteratorRange<Iterator> rangeForRenderer(const RenderObject&) const;
114 WTF::IteratorRange<Iterator> rangeForLine(unsigned lineIndex) const;
115 Iterator runForPoint(const LayoutPoint&) const;
116 WTF::IteratorRange<Iterator> rangeForRendererWithOffsets(const RenderObject&, unsigned start, unsigned end) const;
117
118private:
119 enum class IndexType { First, Last };
120 unsigned lineIndexForHeight(LayoutUnit, IndexType) const;
121 unsigned adjustLineIndexForStruts(LayoutUnit, IndexType, unsigned lineIndexCandidate) const;
122
123 const RenderBlockFlow& m_flowRenderer;
124 const Layout& m_layout;
125 const FlowContents m_flowContents;
126 const LayoutUnit m_lineHeight;
127 const LayoutUnit m_baseline;
128 const LayoutUnit m_borderAndPaddingBefore;
129 const float m_ascent;
130 const float m_descent;
131 const float m_visualOverflowOffset;
132 const bool m_inQuirksMode;
133};
134
135class LineResolver {
136public:
137 class Iterator {
138 public:
139 explicit Iterator(RunResolver::Iterator);
140
141 Iterator& operator++();
142 bool operator==(const Iterator&) const;
143 bool operator!=(const Iterator&) const;
144
145 FloatRect operator*() const;
146 // FIXME: Use a list to support multiple renderers per line.
147 const RenderObject& renderer() const;
148
149 private:
150 RunResolver::Iterator m_runIterator;
151 };
152
153 LineResolver(const RunResolver&);
154
155 Iterator begin() const;
156 Iterator end() const;
157
158 WTF::IteratorRange<Iterator> rangeForRect(const LayoutRect&) const;
159
160private:
161 const RunResolver& m_runResolver;
162};
163
164RunResolver runResolver(const RenderBlockFlow&, const Layout&);
165LineResolver lineResolver(const RunResolver&);
166
167inline unsigned RunResolver::Run::start() const
168{
169 return m_iterator.simpleRun().start;
170}
171
172inline unsigned RunResolver::Run::end() const
173{
174 return m_iterator.simpleRun().end;
175}
176
177inline float RunResolver::Run::logicalLeft() const
178{
179 return m_iterator.simpleRun().logicalLeft;
180}
181
182inline float RunResolver::Run::logicalRight() const
183{
184 return m_iterator.simpleRun().logicalRight;
185}
186
187inline float RunResolver::Run::expansion() const
188{
189 return m_iterator.simpleRun().expansion;
190}
191
192inline ExpansionBehavior RunResolver::Run::expansionBehavior() const
193{
194 return m_iterator.simpleRun().expansionBehavior;
195}
196
197inline int RunResolver::Run::baselinePosition() const
198{
199 return roundToInt(computeBaselinePosition());
200}
201
202inline bool RunResolver::Run::isEndOfLine() const
203{
204 return m_iterator.simpleRun().isEndOfLine;
205}
206
207inline unsigned RunResolver::Run::lineIndex() const
208{
209 return m_iterator.lineIndex();
210}
211
212inline RunResolver::Iterator& RunResolver::Iterator::operator++()
213{
214 return advance();
215}
216
217inline float RunResolver::Run::computeBaselinePosition() const
218{
219 auto& resolver = m_iterator.resolver();
220 auto offset = resolver.m_borderAndPaddingBefore + resolver.m_lineHeight * lineIndex();
221 if (!resolver.m_layout.hasLineStruts())
222 return offset + resolver.m_baseline;
223 for (auto& strutEntry : resolver.m_layout.struts()) {
224 if (strutEntry.lineBreak > lineIndex())
225 break;
226 offset += strutEntry.offset;
227 }
228 return offset + resolver.m_baseline;
229}
230
231inline RunResolver::Iterator& RunResolver::Iterator::operator--()
232{
233 --m_runIndex;
234 if (simpleRun().isEndOfLine)
235 --m_lineIndex;
236 return *this;
237}
238
239inline bool RunResolver::Iterator::operator==(const Iterator& other) const
240{
241 ASSERT(&m_resolver == &other.m_resolver);
242 return m_runIndex == other.m_runIndex;
243}
244
245inline bool RunResolver::Iterator::operator!=(const Iterator& other) const
246{
247 return !(*this == other);
248}
249
250inline RunResolver::Run RunResolver::Iterator::operator*() const
251{
252 return Run(*this);
253}
254
255inline const SimpleLineLayout::Run& RunResolver::Iterator::simpleRun() const
256{
257 return m_resolver.m_layout.runAt(m_runIndex);
258}
259
260inline RunResolver::Iterator RunResolver::begin() const
261{
262 return Iterator(*this, 0, 0);
263}
264
265inline RunResolver::Iterator RunResolver::end() const
266{
267 return Iterator(*this, m_layout.runCount(), m_layout.lineCount());
268}
269
270inline LineResolver::Iterator& LineResolver::Iterator::operator++()
271{
272 m_runIterator.advanceLines(1);
273 return *this;
274}
275
276inline bool LineResolver::Iterator::operator==(const Iterator& other) const
277{
278 return m_runIterator == other.m_runIterator;
279}
280
281inline bool LineResolver::Iterator::operator!=(const Iterator& other) const
282{
283 return m_runIterator != other.m_runIterator;
284}
285
286inline LineResolver::Iterator LineResolver::begin() const
287{
288 return Iterator(m_runResolver.begin());
289}
290
291inline LineResolver::Iterator LineResolver::end() const
292{
293 return Iterator(m_runResolver.end());
294}
295
296inline WTF::IteratorRange<LineResolver::Iterator> LineResolver::rangeForRect(const LayoutRect& rect) const
297{
298 auto runRange = m_runResolver.rangeForRect(rect);
299 return { Iterator(runRange.begin()), Iterator(runRange.end()) };
300}
301
302inline RunResolver runResolver(const RenderBlockFlow& flow, const Layout& layout)
303{
304 return RunResolver(flow, layout);
305}
306
307inline LineResolver lineResolver(const RunResolver& runResolver)
308{
309 return LineResolver(runResolver);
310}
311
312}
313}
314