1/*
2 * Copyright (C) 2003, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#pragma once
22
23#include "BidiContext.h"
24#include "InlineFlowBox.h"
25#include "RenderBox.h"
26#include <wtf/WeakPtr.h>
27
28namespace WebCore {
29
30class EllipsisBox;
31class HitTestResult;
32class LogicalSelectionOffsetCaches;
33class RenderBlockFlow;
34class RenderFragmentContainer;
35
36struct BidiStatus;
37struct GapRects;
38
39class RootInlineBox : public InlineFlowBox, public CanMakeWeakPtr<RootInlineBox> {
40 WTF_MAKE_ISO_ALLOCATED(RootInlineBox);
41public:
42 explicit RootInlineBox(RenderBlockFlow&);
43 virtual ~RootInlineBox();
44
45 RenderBlockFlow& blockFlow() const;
46
47 void detachEllipsisBox();
48
49 RootInlineBox* nextRootBox() const;
50 RootInlineBox* prevRootBox() const;
51
52 void adjustPosition(float dx, float dy) final;
53
54 LayoutUnit lineTop() const { return m_lineTop; }
55 LayoutUnit lineBottom() const { return m_lineBottom; }
56
57 LayoutUnit lineTopWithLeading() const { return m_lineTopWithLeading; }
58 LayoutUnit lineBottomWithLeading() const { return m_lineBottomWithLeading; }
59
60 LayoutUnit paginationStrut() const { return m_paginationStrut; }
61 void setPaginationStrut(LayoutUnit strut) { m_paginationStrut = strut; }
62
63 bool isFirstAfterPageBreak() const { return m_isFirstAfterPageBreak; }
64 void setIsFirstAfterPageBreak(bool isFirstAfterPageBreak) { m_isFirstAfterPageBreak = isFirstAfterPageBreak; }
65
66 LayoutUnit paginatedLineWidth() const { return m_paginatedLineWidth; }
67 void setPaginatedLineWidth(LayoutUnit width) { m_paginatedLineWidth = width; }
68
69 // It should not be assumed the containingFragment() is always valid.
70 // It can also be nullptr if the flow has no fragment chain.
71 RenderFragmentContainer* containingFragment() const;
72 void setContainingFragment(RenderFragmentContainer&);
73 void clearContainingFragment();
74
75 LayoutUnit selectionTop() const;
76 LayoutUnit selectionBottom() const;
77 LayoutUnit selectionHeight() const { return std::max<LayoutUnit>(0, selectionBottom() - selectionTop()); }
78
79 LayoutUnit selectionTopAdjustedForPrecedingBlock() const;
80 LayoutUnit selectionHeightAdjustedForPrecedingBlock() const { return std::max<LayoutUnit>(0, selectionBottom() - selectionTopAdjustedForPrecedingBlock()); }
81
82 int blockDirectionPointInLine() const;
83
84 LayoutUnit alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
85 void setLineTopBottomPositions(LayoutUnit top, LayoutUnit bottom, LayoutUnit topWithLeading, LayoutUnit bottomWithLeading)
86 {
87 m_lineTop = top;
88 m_lineBottom = bottom;
89 m_lineTopWithLeading = topWithLeading;
90 m_lineBottomWithLeading = bottomWithLeading;
91 }
92
93 RenderObject* lineBreakObj() const { return m_lineBreakObj.get(); }
94 BidiStatus lineBreakBidiStatus() const;
95 void setLineBreakInfo(RenderObject*, unsigned breakPos, const BidiStatus&);
96
97 unsigned lineBreakPos() const { return m_lineBreakPos; }
98 void setLineBreakPos(unsigned p) { m_lineBreakPos = p; }
99
100 using InlineBox::endsWithBreak;
101 using InlineBox::setEndsWithBreak;
102
103 void childRemoved(InlineBox* box);
104
105 bool lineCanAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
106 // Return the truncatedWidth, the width of the truncated text + ellipsis.
107 float placeEllipsis(const AtomString& ellipsisStr, bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, InlineBox* markupBox = nullptr);
108 // Return the position of the EllipsisBox or -1.
109 float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) final;
110
111 using InlineBox::hasEllipsisBox;
112 EllipsisBox* ellipsisBox() const;
113
114 void paintEllipsisBox(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) const;
115
116 void clearTruncation() final;
117
118 bool isHyphenated() const;
119
120 int baselinePosition(FontBaseline baselineType) const final;
121 LayoutUnit lineHeight() const final;
122
123 void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
124 bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override;
125
126 using InlineBox::hasSelectedChildren;
127 using InlineBox::setHasSelectedChildren;
128
129 RenderObject::SelectionState selectionState() final;
130 InlineBox* firstSelectedBox();
131 InlineBox* lastSelectedBox();
132
133 GapRects lineSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
134 LayoutUnit selTop, LayoutUnit selHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
135
136 IntRect computeCaretRect(float logicalLeftPosition, unsigned caretWidth, LayoutUnit* extraWidthToEndOfLine) const;
137
138 InlineBox* closestLeafChildForPoint(const IntPoint&, bool onlyEditableLeaves);
139 InlineBox* closestLeafChildForLogicalLeftPosition(int, bool onlyEditableLeaves = false);
140
141 using CleanLineFloatList = Vector<WeakPtr<RenderBox>>;
142 void appendFloat(RenderBox& floatingBox)
143 {
144 ASSERT(!isDirty());
145 if (m_floats)
146 m_floats->append(makeWeakPtr(floatingBox));
147 else
148 m_floats = std::make_unique<CleanLineFloatList>(1, makeWeakPtr(floatingBox));
149 }
150
151 void removeFloat(RenderBox& floatingBox)
152 {
153 ASSERT(m_floats);
154 ASSERT(m_floats->contains(&floatingBox));
155 m_floats->remove(m_floats->find(&floatingBox));
156 }
157
158 CleanLineFloatList* floatsPtr() { ASSERT(!isDirty()); return m_floats.get(); }
159
160 void extractLineBoxFromRenderObject() final;
161 void attachLineBoxToRenderObject() final;
162 void removeLineBoxFromRenderObject() final;
163
164 FontBaseline baselineType() const { return static_cast<FontBaseline>(m_baselineType); }
165
166 bool hasAnnotationsBefore() const { return m_hasAnnotationsBefore; }
167 bool hasAnnotationsAfter() const { return m_hasAnnotationsAfter; }
168
169 LayoutRect paddedLayoutOverflowRect(LayoutUnit endPadding) const;
170
171 void ascentAndDescentForBox(InlineBox&, GlyphOverflowAndFallbackFontsMap&, int& ascent, int& descent, bool& affectsAscent, bool& affectsDescent) const;
172 LayoutUnit verticalPositionForBox(InlineBox*, VerticalPositionCache&);
173 bool fitsToGlyphs() const;
174 bool includesRootLineBoxFontOrLeading() const;
175
176 LayoutUnit logicalTopVisualOverflow() const
177 {
178 return InlineFlowBox::logicalTopVisualOverflow(lineTop());
179 }
180 LayoutUnit logicalBottomVisualOverflow() const
181 {
182 return InlineFlowBox::logicalBottomVisualOverflow(lineBottom());
183 }
184 LayoutUnit logicalTopLayoutOverflow() const
185 {
186 return InlineFlowBox::logicalTopLayoutOverflow(lineTop());
187 }
188 LayoutUnit logicalBottomLayoutOverflow() const
189 {
190 return InlineFlowBox::logicalBottomLayoutOverflow(lineBottom());
191 }
192
193 Node* getLogicalStartBoxWithNode(InlineBox*&) const;
194 Node* getLogicalEndBoxWithNode(InlineBox*&) const;
195
196 virtual bool isTrailingFloatsRootInlineBox() const { return false; }
197
198#if ENABLE(TREE_DEBUGGING)
199 const char* boxName() const final;
200#endif
201private:
202 bool isRootInlineBox() const final { return true; }
203
204 bool includeLeadingForBox(InlineBox&) const;
205 bool includeFontForBox(InlineBox&) const;
206 bool includeGlyphsForBox(InlineBox&) const;
207 bool includeInitialLetterForBox(InlineBox&) const;
208 bool includeMarginForBox(InlineBox&) const;
209
210 LayoutUnit lineSnapAdjustment(LayoutUnit delta = 0_lu) const;
211
212 LayoutUnit beforeAnnotationsAdjustment() const;
213
214 // Where this line ended. The exact object and the position within that object are stored so that
215 // we can create an InlineIterator beginning just after the end of this line.
216 WeakPtr<RenderObject> m_lineBreakObj;
217 RefPtr<BidiContext> m_lineBreakContext;
218
219 LayoutUnit m_lineTop;
220 LayoutUnit m_lineBottom;
221
222 LayoutUnit m_lineTopWithLeading;
223 LayoutUnit m_lineBottomWithLeading;
224
225 LayoutUnit m_paginationStrut;
226 LayoutUnit m_paginatedLineWidth;
227
228 // Floats hanging off the line are pushed into this vector during layout. It is only
229 // good for as long as the line has not been marked dirty.
230 std::unique_ptr<CleanLineFloatList> m_floats;
231
232 unsigned m_lineBreakPos { 0 };
233};
234
235inline RootInlineBox* RootInlineBox::nextRootBox() const
236{
237 return downcast<RootInlineBox>(m_nextLineBox);
238}
239
240inline RootInlineBox* RootInlineBox::prevRootBox() const
241{
242 return downcast<RootInlineBox>(m_prevLineBox);
243}
244
245} // namespace WebCore
246
247SPECIALIZE_TYPE_TRAITS_INLINE_BOX(RootInlineBox, isRootInlineBox())
248