e2ea35d52f7ace6128cc0a8acf91d2c0a19afde0
[WebKit-https.git] / Source / WebCore / rendering / SimpleLineLayoutResolver.cpp
1 /*
2  * Copyright (C) 2014 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 "SimpleLineLayoutResolver.h"
28
29 #include "RenderBlockFlow.h"
30 #include "RenderText.h"
31 #include "SimpleLineLayoutFunctions.h"
32
33 namespace WebCore {
34 namespace SimpleLineLayout {
35
36 static float baselinePosition(float lineHeight, float baseline, int lineIndex)
37 {
38     return lineHeight * lineIndex + baseline;
39 }
40
41 static LayoutPoint linePosition(float logicalLeft, float logicalTop)
42 {
43     return LayoutPoint(LayoutUnit::fromFloatFloor(logicalLeft), roundToInt(logicalTop));
44 }
45
46 static LayoutSize lineSize(float logicalLeft, float logicalRight, float height)
47 {
48     return LayoutSize(LayoutUnit::fromFloatCeil(logicalRight) - LayoutUnit::fromFloatFloor(logicalLeft), height);
49 }
50
51 RunResolver::Run::Run(const Iterator& iterator)
52     : m_iterator(iterator)
53 {
54 }
55
56 LayoutRect RunResolver::Run::rect() const
57 {
58     auto& run = m_iterator.simpleRun();
59     auto& resolver = m_iterator.resolver();
60     float baseline = baselinePosition(resolver.m_lineHeight, resolver.m_baseline, m_iterator.lineIndex());
61     LayoutPoint position = linePosition(run.logicalLeft, baseline - resolver.m_ascent + resolver.m_borderAndPaddingBefore);
62     LayoutSize size = lineSize(run.logicalLeft, run.logicalRight, resolver.m_ascent + resolver.m_descent);
63     return LayoutRect(position, size);
64 }
65
66 FloatPoint RunResolver::Run::baseline() const
67 {
68     auto& resolver = m_iterator.resolver();
69     auto& run = m_iterator.simpleRun();
70
71     float baseline = baselinePosition(resolver.m_lineHeight, resolver.m_baseline, m_iterator.lineIndex());
72     return FloatPoint(run.logicalLeft, roundToInt(baseline + resolver.m_borderAndPaddingBefore));
73 }
74
75 StringView RunResolver::Run::text() const
76 {
77     auto& resolver = m_iterator.resolver();
78     auto& run = m_iterator.simpleRun();
79     const auto& renderer = resolver.m_flowContents.renderer(run.start);
80     ASSERT(renderer.is8Bit());
81     return StringView(renderer.characters8(), renderer.textLength()).substring(run.start, run.end - run.start);
82 }
83
84 RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex)
85     : m_resolver(resolver)
86     , m_runIndex(runIndex)
87     , m_lineIndex(lineIndex)
88 {
89 }
90
91 RunResolver::Iterator& RunResolver::Iterator::advance()
92 {
93     if (simpleRun().isEndOfLine)
94         ++m_lineIndex;
95     ++m_runIndex;
96     return *this;
97 }
98
99 RunResolver::Iterator& RunResolver::Iterator::advanceLines(unsigned lineCount)
100 {
101     unsigned runCount = m_resolver.m_layout.runCount();
102     if (runCount == m_resolver.m_layout.lineCount()) {
103         m_runIndex = std::min(runCount, m_runIndex + lineCount);
104         m_lineIndex = m_runIndex;
105         return *this;
106     }
107     unsigned target = m_lineIndex + lineCount;
108     while (m_lineIndex < target && m_runIndex < runCount)
109         advance();
110
111     return *this;
112 }
113
114 RunResolver::RunResolver(const RenderBlockFlow& flow, const Layout& layout)
115     : m_layout(layout)
116     , m_flowContents(flow)
117     , m_lineHeight(lineHeightFromFlow(flow))
118     , m_baseline(baselineFromFlow(flow))
119     , m_borderAndPaddingBefore(flow.borderAndPaddingBefore())
120     , m_ascent(flow.style().font().fontMetrics().ascent())
121     , m_descent(flow.style().font().fontMetrics().descent())
122 {
123 }
124
125 unsigned RunResolver::lineIndexForHeight(LayoutUnit height, IndexType type) const
126 {
127     ASSERT(m_lineHeight);
128     float y = height - m_borderAndPaddingBefore;
129     // Lines may overlap, adjust to get the first or last line at this height.
130     if (type == IndexType::First)
131         y += m_lineHeight - (m_baseline + m_descent);
132     else
133         y -= m_baseline - m_ascent;
134     y = std::max<float>(y, 0);
135     return std::min<unsigned>(y / m_lineHeight, m_layout.lineCount() - 1);
136 }
137
138 Range<RunResolver::Iterator> RunResolver::rangeForRect(const LayoutRect& rect) const
139
140     if (!m_lineHeight)
141         return Range<Iterator>(begin(), end());
142
143     unsigned firstLine = lineIndexForHeight(rect.y(), IndexType::First);
144     unsigned lastLine = std::max(firstLine, lineIndexForHeight(rect.maxY(), IndexType::Last));
145
146     auto rangeBegin = begin().advanceLines(firstLine);
147     if (rangeBegin == end())
148         return Range<Iterator>(end(), end());
149     auto rangeEnd = rangeBegin;
150     ASSERT(lastLine >= firstLine);
151     rangeEnd.advanceLines(lastLine - firstLine + 1);
152     return Range<Iterator>(rangeBegin, rangeEnd);
153 }
154
155 Range<RunResolver::Iterator> RunResolver::rangeForRenderer(const RenderText& renderer) const
156 {
157     unsigned startPosition = 0;
158     unsigned endPosition = 0;
159     m_flowContents.resolveRendererPositions(renderer, startPosition, endPosition);
160     auto rangeBegin = begin();
161     for (;(*rangeBegin).start() < startPosition && rangeBegin != end(); ++rangeBegin) { }
162     auto rangeEnd = rangeBegin;
163     for (;(*rangeEnd).end() <= endPosition && rangeEnd != end(); ++rangeEnd) { }
164     return Range<Iterator>(rangeBegin, rangeEnd);
165 }
166
167 LineResolver::Iterator::Iterator(RunResolver::Iterator runIterator)
168     : m_runIterator(runIterator)
169 {
170 }
171
172 const LayoutRect LineResolver::Iterator::operator*() const
173 {
174     unsigned currentLine = m_runIterator.lineIndex();
175     auto it = m_runIterator;
176     LayoutRect rect = (*it).rect();
177     while (it.advance().lineIndex() == currentLine)
178         rect.unite((*it).rect());
179
180     return rect;
181 }
182
183 LineResolver::LineResolver(const RenderBlockFlow& flow, const Layout& layout)
184     : m_runResolver(flow, layout)
185 {
186 }
187
188 }
189 }