b4e8927be58c6e26f3866a1a9c2ef99131048353
[WebKit-https.git] / Source / WebCore / rendering / RenderLineBreak.cpp
1 /**
2  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "RenderLineBreak.h"
24
25 #include "Document.h"
26 #include "HTMLElement.h"
27 #include "RenderBlock.h"
28 #include "RootInlineBox.h"
29 #include "VisiblePosition.h"
30
31 namespace WebCore {
32
33 static const int invalidLineHeight = -1;
34
35 RenderLineBreak::RenderLineBreak(HTMLElement& element)
36     : RenderBoxModelObject(&element, 0)
37     , m_inlineBoxWrapper(nullptr)
38     , m_cachedLineHeight(invalidLineHeight)
39     , m_isWBR(element.hasTagName(HTMLNames::wbrTag))
40 {
41     setIsLineBreak();
42 }
43
44 RenderLineBreak::~RenderLineBreak()
45 {
46     if (m_inlineBoxWrapper)
47         m_inlineBoxWrapper->destroy(renderArena());
48 }
49
50 LayoutUnit RenderLineBreak::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
51 {
52     if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
53         const RenderStyle& firstLineStyle = *this->firstLineStyle();
54         if (&firstLineStyle != style())
55             return firstLineStyle.computedLineHeight(&view());
56     }
57
58     if (m_cachedLineHeight == invalidLineHeight)
59         m_cachedLineHeight = style()->computedLineHeight(&view());
60     
61     return m_cachedLineHeight;
62 }
63
64 int RenderLineBreak::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
65 {
66     const RenderStyle& style = firstLine ? *firstLineStyle() : *this->style();
67     const FontMetrics& fontMetrics = style.fontMetrics();
68     return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
69 }
70
71 InlineBox* RenderLineBreak::createInlineBox()
72 {
73     return new (renderArena()) InlineBox(*this);
74 }
75
76 void RenderLineBreak::setInlineBoxWrapper(InlineBox* inlineBox)
77 {
78     ASSERT(!inlineBox || !m_inlineBoxWrapper);
79     m_inlineBoxWrapper = inlineBox;
80 }
81
82 void RenderLineBreak::replaceInlineBoxWrapper(InlineBox* inlineBox)
83 {
84     deleteInlineBoxWrapper();
85     setInlineBoxWrapper(inlineBox);
86 }
87
88 void RenderLineBreak::deleteInlineBoxWrapper()
89 {
90     if (!m_inlineBoxWrapper)
91         return;
92     if (!documentBeingDestroyed())
93         m_inlineBoxWrapper->remove();
94     m_inlineBoxWrapper->destroy(renderArena());
95     m_inlineBoxWrapper = nullptr;
96 }
97
98 void RenderLineBreak::dirtyLineBoxes(bool fullLayout)
99 {
100     if (!m_inlineBoxWrapper)
101         return;
102     if (fullLayout) {
103         m_inlineBoxWrapper->destroy(renderArena());
104         m_inlineBoxWrapper = nullptr;
105         return;
106     }
107     m_inlineBoxWrapper->dirtyLineBoxes();
108 }
109
110 int RenderLineBreak::caretMinOffset() const
111 {
112     return 0;
113 }
114
115 int RenderLineBreak::caretMaxOffset() const
116
117     return 1;
118 }
119
120 bool RenderLineBreak::canBeSelectionLeaf() const
121 {
122     return true;
123 }
124
125 VisiblePosition RenderLineBreak::positionForPoint(const LayoutPoint&)
126 {
127     return createVisiblePosition(0, DOWNSTREAM);
128 }
129
130 void RenderLineBreak::setSelectionState(SelectionState state)
131 {
132     RenderBoxModelObject::setSelectionState(state);
133     if (!m_inlineBoxWrapper)
134         return;
135     m_inlineBoxWrapper->root().setHasSelectedChildren(state != SelectionNone);
136 }
137
138 LayoutRect RenderLineBreak::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
139 {
140     ASSERT_UNUSED(caretOffset, !caretOffset);
141     ASSERT_UNUSED(inlineBox, inlineBox == m_inlineBoxWrapper);
142     if (!inlineBox)
143         return LayoutRect();
144
145     static const unsigned caretWidth = 1;
146     const RootInlineBox& rootBox = inlineBox->root();
147     return rootBox.computeCaretRect(inlineBox->logicalLeft(), caretWidth, extraWidthToEndOfLine);
148 }
149
150 IntRect RenderLineBreak::linesBoundingBox() const
151 {
152     if (!m_inlineBoxWrapper)
153         return IntRect();
154
155     float logicalLeftSide = m_inlineBoxWrapper->logicalLeft();
156     float logicalRightSide = m_inlineBoxWrapper->logicalRight();
157
158     bool isHorizontal = style()->isHorizontalWritingMode();
159
160     float x = isHorizontal ? logicalLeftSide : m_inlineBoxWrapper->x();
161     float y = isHorizontal ? m_inlineBoxWrapper->y() : logicalLeftSide;
162     float width = isHorizontal ? logicalRightSide - logicalLeftSide : m_inlineBoxWrapper->logicalBottom() - x;
163     float height = isHorizontal ? m_inlineBoxWrapper->logicalBottom() - y : logicalRightSide - logicalLeftSide;
164     return enclosingIntRect(FloatRect(x, y, width, height));
165 }
166
167 void RenderLineBreak::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
168 {
169     if (!m_inlineBoxWrapper)
170         return;
171     rects.append(enclosingIntRect(FloatRect(accumulatedOffset + m_inlineBoxWrapper->topLeft(), m_inlineBoxWrapper->size())));
172 }
173
174 void RenderLineBreak::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
175 {
176     if (!m_inlineBoxWrapper)
177         return;
178     quads.append(localToAbsoluteQuad(FloatRect(m_inlineBoxWrapper->topLeft(), m_inlineBoxWrapper->size()), 0 /* mode */, wasFixed));
179 }
180
181 void RenderLineBreak::updateFromStyle()
182 {
183     m_cachedLineHeight = invalidLineHeight;
184 }
185
186 IntRect RenderLineBreak::borderBoundingBox() const
187 {
188     return IntRect(IntPoint(), linesBoundingBox().size());
189 }
190
191 } // namespace WebCore