[iOS] Add WebKitSystemInterface for iOS 8.2
[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     auto& segment = resolver.m_flowContents.segmentForPosition(run.start);
80     // We currently split runs on segment boundaries (different RenderText).
81     ASSERT(run.end <= segment.end);
82     if (segment.text.is8Bit())
83         return StringView(segment.text.characters8(), segment.text.length()).substring(run.start - segment.start, run.end - run.start);
84     return StringView(segment.text.characters16(), segment.text.length()).substring(run.start - segment.start, run.end - run.start);
85 }
86
87 RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex)
88     : m_resolver(resolver)
89     , m_runIndex(runIndex)
90     , m_lineIndex(lineIndex)
91 {
92 }
93
94 RunResolver::Iterator& RunResolver::Iterator::advance()
95 {
96     if (simpleRun().isEndOfLine)
97         ++m_lineIndex;
98     ++m_runIndex;
99     return *this;
100 }
101
102 RunResolver::Iterator& RunResolver::Iterator::advanceLines(unsigned lineCount)
103 {
104     unsigned runCount = m_resolver.m_layout.runCount();
105     if (runCount == m_resolver.m_layout.lineCount()) {
106         m_runIndex = std::min(runCount, m_runIndex + lineCount);
107         m_lineIndex = m_runIndex;
108         return *this;
109     }
110     unsigned target = m_lineIndex + lineCount;
111     while (m_lineIndex < target && m_runIndex < runCount)
112         advance();
113
114     return *this;
115 }
116
117 RunResolver::RunResolver(const RenderBlockFlow& flow, const Layout& layout)
118     : m_layout(layout)
119     , m_flowContents(flow)
120     , m_lineHeight(lineHeightFromFlow(flow))
121     , m_baseline(baselineFromFlow(flow))
122     , m_borderAndPaddingBefore(flow.borderAndPaddingBefore())
123     , m_ascent(flow.style().fontCascade().fontMetrics().ascent())
124     , m_descent(flow.style().fontCascade().fontMetrics().descent())
125 {
126 }
127
128 unsigned RunResolver::lineIndexForHeight(LayoutUnit height, IndexType type) const
129 {
130     ASSERT(m_lineHeight);
131     float y = height - m_borderAndPaddingBefore;
132     // Lines may overlap, adjust to get the first or last line at this height.
133     if (type == IndexType::First)
134         y += m_lineHeight - (m_baseline + m_descent);
135     else
136         y -= m_baseline - m_ascent;
137     y = std::max<float>(y, 0);
138     return std::min<unsigned>(y / m_lineHeight, m_layout.lineCount() - 1);
139 }
140
141 Range<RunResolver::Iterator> RunResolver::rangeForRect(const LayoutRect& rect) const
142
143     if (!m_lineHeight)
144         return Range<Iterator>(begin(), end());
145
146     unsigned firstLine = lineIndexForHeight(rect.y(), IndexType::First);
147     unsigned lastLine = std::max(firstLine, lineIndexForHeight(rect.maxY(), IndexType::Last));
148
149     auto rangeBegin = begin().advanceLines(firstLine);
150     if (rangeBegin == end())
151         return Range<Iterator>(end(), end());
152     auto rangeEnd = rangeBegin;
153     ASSERT(lastLine >= firstLine);
154     rangeEnd.advanceLines(lastLine - firstLine + 1);
155     return Range<Iterator>(rangeBegin, rangeEnd);
156 }
157
158 Range<RunResolver::Iterator> RunResolver::rangeForRenderer(const RenderText& renderer) const
159 {
160     auto& segment = m_flowContents.segmentForRenderer(renderer);
161
162     auto rangeBegin = begin();
163     for (;rangeBegin != end() && (*rangeBegin).start() < segment.start; ++rangeBegin) { }
164
165     auto rangeEnd = rangeBegin;
166     for (;rangeEnd != end() && (*rangeEnd).end() <= segment.end; ++rangeEnd) { }
167
168     return Range<Iterator>(rangeBegin, rangeEnd);
169 }
170
171 LineResolver::Iterator::Iterator(RunResolver::Iterator runIterator)
172     : m_runIterator(runIterator)
173 {
174 }
175
176 const LayoutRect LineResolver::Iterator::operator*() const
177 {
178     unsigned currentLine = m_runIterator.lineIndex();
179     auto it = m_runIterator;
180     LayoutRect rect = (*it).rect();
181     while (it.advance().lineIndex() == currentLine)
182         rect.unite((*it).rect());
183
184     return rect;
185 }
186
187 LineResolver::LineResolver(const RenderBlockFlow& flow, const Layout& layout)
188     : m_runResolver(flow, layout)
189 {
190 }
191
192 }
193 }