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#ifndef SimpleLineLayoutResolver_h
27#define SimpleLineLayoutResolver_h
28
29#include "LayoutRect.h"
30#include "RenderBlockFlow.h"
31#include "RenderText.h"
32#include "SimpleLineLayoutFunctions.h"
33#include <wtf/Vector.h>
34#include <wtf/text/WTFString.h>
35
36namespace WebCore {
37namespace SimpleLineLayout {
38
39template <class IteratorType>
40class Range {
41public:
42    Range(IteratorType begin, IteratorType end) : m_begin(begin), m_end(end) { }
43
44    IteratorType begin() const { return m_begin; }
45    IteratorType end() const { return m_end; }
46
47private:
48    IteratorType m_begin;
49    IteratorType m_end;
50};
51
52class RunResolver {
53public:
54    class Iterator;
55
56    class Run {
57    public:
58        explicit Run(const Iterator&);
59
60        unsigned start() const;
61        unsigned end() const;
62
63        LayoutRect rect() const;
64        FloatPoint baseline() const;
65        String text() const;
66
67        unsigned lineIndex() const;
68
69    private:
70        const Iterator& m_iterator;
71    };
72
73    class Iterator {
74    public:
75        Iterator(const RunResolver&, unsigned runIndex, unsigned lineIndex);
76
77        Iterator& operator++();
78
79        bool operator==(const Iterator&) const;
80        bool operator!=(const Iterator&) const;
81
82        Run operator*() const;
83
84        Iterator& advance();
85        Iterator& advanceLines(unsigned);
86
87        const RunResolver& resolver() const { return m_resolver; }
88        const SimpleLineLayout::Run& simpleRun() const;
89        unsigned lineIndex() const { return m_lineIndex; }
90
91    private:
92        const RunResolver& m_resolver;
93        unsigned m_runIndex;
94        unsigned m_lineIndex;
95    };
96
97    RunResolver(const RenderBlockFlow&, const Layout&);
98
99    Iterator begin() const;
100    Iterator end() const;
101
102    Range<Iterator> rangeForRect(const LayoutRect&) const;
103
104private:
105    enum class IndexType { First, Last };
106    unsigned lineIndexForHeight(LayoutUnit, IndexType) const;
107
108    const Layout& m_layout;
109    const String m_string;
110    const LayoutUnit m_lineHeight;
111    const LayoutUnit m_baseline;
112    const LayoutUnit m_borderAndPaddingBefore;
113    const float m_ascent;
114    const float m_descent;
115};
116
117class LineResolver {
118public:
119    class Iterator;
120
121    class Iterator {
122    public:
123        explicit Iterator(RunResolver::Iterator);
124
125        Iterator& operator++();
126        bool operator==(const Iterator&) const;
127        bool operator!=(const Iterator&) const;
128
129        const LayoutRect operator*() const;
130
131    private:
132        RunResolver::Iterator m_runIterator;
133        LayoutRect m_rect;
134    };
135
136    LineResolver(const RenderBlockFlow&, const Layout&);
137
138    Iterator begin() const;
139    Iterator end() const;
140
141    Range<Iterator> rangeForRect(const LayoutRect&) const;
142
143private:
144    RunResolver m_runResolver;
145};
146
147RunResolver runResolver(const RenderBlockFlow&, const Layout&);
148LineResolver lineResolver(const RenderBlockFlow&, const Layout&);
149
150inline RunResolver::Run::Run(const Iterator& iterator)
151    : m_iterator(iterator)
152{
153}
154
155inline unsigned RunResolver::Run::start() const
156{
157    return m_iterator.simpleRun().start;
158}
159
160inline unsigned RunResolver::Run::end() const
161{
162    return m_iterator.simpleRun().end;
163}
164
165inline LayoutRect RunResolver::Run::rect() const
166{
167    auto& resolver = m_iterator.resolver();
168    auto& run = m_iterator.simpleRun();
169
170    float baselinePosition = resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline;
171    LayoutPoint linePosition(LayoutUnit::fromFloatFloor(run.left), roundToInt(baselinePosition - resolver.m_ascent + resolver.m_borderAndPaddingBefore));
172    LayoutSize lineSize(LayoutUnit::fromFloatCeil(run.right) - LayoutUnit::fromFloatFloor(run.left), resolver.m_ascent + resolver.m_descent);
173    return LayoutRect(linePosition, lineSize);
174}
175
176inline FloatPoint RunResolver::Run::baseline() const
177{
178    auto& resolver = m_iterator.resolver();
179    auto& run = m_iterator.simpleRun();
180
181    float baselinePosition = resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline;
182    return FloatPoint(run.left, roundToInt(baselinePosition + resolver.m_borderAndPaddingBefore));
183}
184
185inline String RunResolver::Run::text() const
186{
187    auto& resolver = m_iterator.resolver();
188    auto& run = m_iterator.simpleRun();
189    return resolver.m_string.substringSharingImpl(run.start, run.end - run.start);
190}
191
192inline unsigned RunResolver::Run::lineIndex() const
193{
194    return m_iterator.lineIndex();
195}
196
197inline RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex)
198    : m_resolver(resolver)
199    , m_runIndex(runIndex)
200    , m_lineIndex(lineIndex)
201{
202}
203
204inline RunResolver::Iterator& RunResolver::Iterator::operator++()
205{
206    return advance();
207}
208
209inline bool RunResolver::Iterator::operator==(const Iterator& other) const
210{
211    ASSERT(&m_resolver == &other.m_resolver);
212    return m_runIndex == other.m_runIndex;
213}
214
215inline bool RunResolver::Iterator::operator!=(const Iterator& other) const
216{
217    return !(*this == other);
218}
219
220inline RunResolver::Run RunResolver::Iterator::operator*() const
221{
222    return Run(*this);
223}
224
225inline RunResolver::Iterator& RunResolver::Iterator::advance()
226{
227    if (simpleRun().isEndOfLine)
228        ++m_lineIndex;
229    ++m_runIndex;
230    return *this;
231}
232
233inline RunResolver::Iterator& RunResolver::Iterator::advanceLines(unsigned lineCount)
234{
235    unsigned runCount = m_resolver.m_layout.runCount();
236    if (runCount == m_resolver.m_layout.lineCount()) {
237        m_runIndex = std::min(runCount, m_runIndex + lineCount);
238        m_lineIndex = m_runIndex;
239        return *this;
240    }
241    unsigned target = m_lineIndex + lineCount;
242    while (m_lineIndex < target && m_runIndex < runCount)
243        advance();
244
245    return *this;
246}
247
248inline const SimpleLineLayout::Run& RunResolver::Iterator::simpleRun() const
249{
250    return m_resolver.m_layout.runAt(m_runIndex);
251}
252
253inline RunResolver::RunResolver(const RenderBlockFlow& flow, const Layout& layout)
254    : m_layout(layout)
255    , m_string(toRenderText(*flow.firstChild()).text())
256    , m_lineHeight(lineHeightFromFlow(flow))
257    , m_baseline(baselineFromFlow(flow))
258    , m_borderAndPaddingBefore(flow.borderAndPaddingBefore())
259    , m_ascent(flow.style().font().fontMetrics().ascent())
260    , m_descent(flow.style().font().fontMetrics().descent())
261{
262}
263
264inline RunResolver::Iterator RunResolver::begin() const
265{
266    return Iterator(*this, 0, 0);
267}
268
269inline RunResolver::Iterator RunResolver::end() const
270{
271    return Iterator(*this, m_layout.runCount(), m_layout.lineCount());
272}
273
274inline unsigned RunResolver::lineIndexForHeight(LayoutUnit height, IndexType type) const
275{
276    ASSERT(m_lineHeight);
277    float y = height - m_borderAndPaddingBefore;
278    // Lines may overlap, adjust to get the first or last line at this height.
279    if (type == IndexType::First)
280        y += m_lineHeight - (m_baseline + m_descent);
281    else
282        y -= m_baseline - m_ascent;
283    y = std::max<float>(y, 0);
284    return std::min<unsigned>(y / m_lineHeight, m_layout.lineCount() - 1);
285}
286
287inline Range<RunResolver::Iterator> RunResolver::rangeForRect(const LayoutRect& rect) const
288{
289    if (!m_lineHeight)
290        return Range<Iterator>(begin(), end());
291
292    unsigned firstLine = lineIndexForHeight(rect.y(), IndexType::First);
293    unsigned lastLine = std::max(firstLine, lineIndexForHeight(rect.maxY(), IndexType::Last));
294
295    auto rangeBegin = begin().advanceLines(firstLine);
296    if (rangeBegin == end())
297        return Range<Iterator>(end(), end());
298    auto rangeEnd = rangeBegin;
299    ASSERT(lastLine >= firstLine);
300    rangeEnd.advanceLines(lastLine - firstLine + 1);
301    return Range<Iterator>(rangeBegin, rangeEnd);
302}
303
304inline LineResolver::Iterator::Iterator(RunResolver::Iterator runIterator)
305    : m_runIterator(runIterator)
306{
307}
308
309inline LineResolver::Iterator& LineResolver::Iterator::operator++()
310{
311    m_runIterator.advanceLines(1);
312    return *this;
313}
314
315inline bool LineResolver::Iterator::operator==(const Iterator& other) const
316{
317    return m_runIterator == other.m_runIterator;
318}
319
320inline bool LineResolver::Iterator::operator!=(const Iterator& other) const
321{
322    return m_runIterator != other.m_runIterator;
323}
324
325inline const LayoutRect LineResolver::Iterator::operator*() const
326{
327    unsigned currentLine = m_runIterator.lineIndex();
328    auto it = m_runIterator;
329    LayoutRect rect = (*it).rect();
330    while (it.advance().lineIndex() == currentLine)
331        rect.unite((*it).rect());
332
333    return rect;
334}
335
336inline LineResolver::LineResolver(const RenderBlockFlow& flow, const Layout& layout)
337    : m_runResolver(flow, layout)
338{
339}
340
341inline LineResolver::Iterator LineResolver::begin() const
342{
343    return Iterator(m_runResolver.begin());
344}
345
346inline LineResolver::Iterator LineResolver::end() const
347{
348    return Iterator(m_runResolver.end());
349}
350
351inline Range<LineResolver::Iterator> LineResolver::rangeForRect(const LayoutRect& rect) const
352{
353    auto runRange = m_runResolver.rangeForRect(rect);
354    return Range<Iterator>(Iterator(runRange.begin()), Iterator(runRange.end()));
355}
356
357inline RunResolver runResolver(const RenderBlockFlow& flow, const Layout& layout)
358{
359    return RunResolver(flow, layout);
360}
361
362inline LineResolver lineResolver(const RenderBlockFlow& flow, const Layout& layout)
363{
364    return LineResolver(flow, layout);
365}
366
367}
368}
369
370#endif
371