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