Remove "virtual" from all lines that have both "virtual" and "override".
[WebKit-https.git] / Source / WebCore / rendering / InlineFlowBox.h
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007 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 #ifndef InlineFlowBox_h
22 #define InlineFlowBox_h
23
24 #include "InlineBox.h"
25 #include "RenderOverflow.h"
26 #include "ShadowData.h"
27
28 namespace WebCore {
29
30 class HitTestRequest;
31 class HitTestResult;
32 class InlineTextBox;
33 class RenderLineBoxList;
34 class Font;
35 class VerticalPositionCache;
36
37 struct GlyphOverflow;
38
39 typedef HashMap<const InlineTextBox*, std::pair<Vector<const Font*>, GlyphOverflow>> GlyphOverflowAndFallbackFontsMap;
40
41 class InlineFlowBox : public InlineBox {
42 public:
43     explicit InlineFlowBox(RenderBoxModelObject& renderer)
44         : InlineBox(renderer)
45         , m_firstChild(nullptr)
46         , m_lastChild(nullptr)
47         , m_prevLineBox(nullptr)
48         , m_nextLineBox(nullptr)
49         , m_includeLogicalLeftEdge(false)
50         , m_includeLogicalRightEdge(false)
51         , m_descendantsHaveSameLineHeightAndBaseline(true)
52         , m_baselineType(AlphabeticBaseline)
53         , m_hasAnnotationsBefore(false)
54         , m_hasAnnotationsAfter(false)
55         , m_isFirstAfterPageBreak(false)
56         , m_hasAnonymousInlineBlock(false)
57 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
58         , m_hasBadChildList(false)
59 #endif
60     {
61         // Internet Explorer and Firefox always create a marker for list items, even when the list-style-type is none.  We do not make a marker
62         // in the list-style-type: none case, since it is wasteful to do so.  However, in order to match other browsers we have to pretend like
63         // an invisible marker exists.  The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
64         // text children must not apply.  This change also means that gaps will exist between image bullet list items.  Even when the list bullet
65         // is an image, the line is still considered to be immune from the quirk.
66         m_hasTextChildren = renderer.style().display() == LIST_ITEM;
67         m_hasTextDescendants = m_hasTextChildren;
68     }
69
70 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
71     virtual ~InlineFlowBox();
72 #endif
73
74 #if ENABLE(TREE_DEBUGGING)
75     void showLineTreeAndMark(const InlineBox* markedBox, int depth) const override;
76     const char* boxName() const override;
77 #endif
78
79     RenderBoxModelObject& renderer() const { return downcast<RenderBoxModelObject>(InlineBox::renderer()); }
80     const RenderStyle& lineStyle() const { return isFirstLine() ? renderer().firstLineStyle() : renderer().style(); }
81
82     InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
83     InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
84     void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
85     void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
86
87     InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
88     InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
89
90     bool isLeaf() const override final { return false; }
91     
92     InlineBox* firstLeafChild() const;
93     InlineBox* lastLeafChild() const;
94
95     typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last);
96     void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = nullptr, void* userData = nullptr) const;
97
98     void setConstructed() override final
99     {
100         InlineBox::setConstructed();
101         for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
102             child->setConstructed();
103     }
104
105     void addToLine(InlineBox* child);
106     void deleteLine() override final;
107     void extractLine() override final;
108     void attachLine() override final;
109     void adjustPosition(float dx, float dy) override;
110
111     virtual void extractLineBoxFromRenderObject();
112     virtual void attachLineBoxToRenderObject();
113     virtual void removeLineBoxFromRenderObject();
114
115     void clearTruncation() override;
116
117     void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
118     void paintMask(PaintInfo&, const LayoutPoint&);
119     void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
120     void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
121     void paintBoxShadow(const PaintInfo&, const RenderStyle&, ShadowStyle, const LayoutRect&);
122     void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
123     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) override;
124
125     bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
126
127     // logicalLeft = left in a horizontal line and top in a vertical line.
128     LayoutUnit marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
129     LayoutUnit marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
130     LayoutUnit marginLogicalLeft() const
131     {
132         if (!includeLogicalLeftEdge())
133             return 0;
134         return isHorizontal() ? renderer().marginLeft() : renderer().marginTop();
135     }
136     LayoutUnit marginLogicalRight() const
137     {
138         if (!includeLogicalRightEdge())
139             return 0;
140         return isHorizontal() ? renderer().marginRight() : renderer().marginBottom();
141     }
142     float borderLogicalLeft() const
143     {
144         if (!includeLogicalLeftEdge())
145             return 0;
146         return isHorizontal() ? lineStyle().borderLeftWidth() : lineStyle().borderTopWidth();
147     }
148     float borderLogicalRight() const
149     {
150         if (!includeLogicalRightEdge())
151             return 0;
152         return isHorizontal() ? lineStyle().borderRightWidth() : lineStyle().borderBottomWidth();
153     }
154     float paddingLogicalLeft() const
155     {
156         if (!includeLogicalLeftEdge())
157             return 0;
158         return isHorizontal() ? renderer().paddingLeft() : renderer().paddingTop();
159     }
160     float paddingLogicalRight() const
161     {
162         if (!includeLogicalRightEdge())
163             return 0;
164         return isHorizontal() ? renderer().paddingRight() : renderer().paddingBottom();
165     }
166
167     bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
168     bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
169     void setEdges(bool includeLeft, bool includeRight)
170     {
171         m_includeLogicalLeftEdge = includeLeft;
172         m_includeLogicalRightEdge = includeRight;
173     }
174
175     // Helper functions used during line construction and placement.
176     void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
177     LayoutUnit getFlowSpacingLogicalWidth();
178     float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing);
179     float placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing);
180     void beginPlacingBoxRangesInInlineDirection(float logicalLeft) { setLogicalLeft(logicalLeft); }
181     void endPlacingBoxRangesInInlineDirection(float logicalLeft, float logicalRight, float minLogicalLeft, float maxLogicalRight)
182     {
183         setLogicalWidth(logicalRight - logicalLeft);
184         if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight))
185             clearKnownToHaveNoOverflow();
186     }
187
188     void computeLogicalBoxHeights(RootInlineBox&, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom,
189         int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
190         bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&);
191     void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
192         int maxPositionTop, int maxPositionBottom);
193     void placeBoxesInBlockDirection(LayoutUnit logicalTop, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, bool& setLineTop,
194         LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline);
195     void flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom);
196     bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const;
197
198     LayoutUnit computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const;
199     LayoutUnit computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const;
200
201     void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
202     
203     void removeChild(InlineBox* child);
204
205     RenderObject::SelectionState selectionState() override;
206
207     bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const override final;
208     float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool&) override;
209
210     bool hasTextChildren() const { return m_hasTextChildren; }
211     bool hasTextDescendants() const { return m_hasTextDescendants; }
212     void setHasTextChildren() { m_hasTextChildren = true; setHasTextDescendants(); }
213     void setHasTextDescendants() { m_hasTextDescendants = true; }
214     
215     bool hasAnonymousInlineBlock() const { return m_hasAnonymousInlineBlock; }
216     void setHasAnonymousInlineBlock(bool b) { m_hasAnonymousInlineBlock = b; }
217     RenderBlockFlow* anonymousInlineBlock() const;
218     
219     void checkConsistency() const;
220     void setHasBadChildList();
221
222     // Line visual and layout overflow are in the coordinate space of the block.  This means that they aren't purely physical directions.
223     // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
224     // respectively are flipped when compared to their physical counterparts.  For example minX is on the left in vertical-lr, but it is on the right in vertical-rl.
225     LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
226     { 
227         return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
228     }
229     LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
230     {
231         if (m_overflow)
232             return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
233         return lineTop;
234     }
235     LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
236     {
237         if (m_overflow)
238             return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
239         return lineBottom;
240     }
241     LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
242     {
243         LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
244         if (!renderer().isHorizontalWritingMode())
245             result = result.transposedRect();
246         return result;
247     }
248
249     LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
250     { 
251         return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
252     }
253     LayoutUnit logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().x() : m_overflow->visualOverflowRect().y()) : LayoutUnit(logicalLeft()); }
254     LayoutUnit logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().maxX() : m_overflow->visualOverflowRect().maxY()) : LayoutUnit(ceilf(logicalRight())); }
255     LayoutUnit logicalTopVisualOverflow(LayoutUnit lineTop) const
256     {
257         if (m_overflow)
258             return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
259         return lineTop;
260     }
261     LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
262     {
263         if (m_overflow)
264             return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
265         return lineBottom;
266     }
267     LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
268     {
269         LayoutRect result = visualOverflowRect(lineTop, lineBottom);
270         if (!renderer().isHorizontalWritingMode())
271             result = result.transposedRect();
272         return result;
273     }
274
275     void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
276     void setLayoutOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
277     void setVisualOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
278
279     FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
280     {
281         if (isHorizontal())
282             return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
283         return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
284     }
285     
286     FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
287     {
288         return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
289     }
290     
291     bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
292     void clearDescendantsHaveSameLineHeightAndBaseline()
293     { 
294         m_descendantsHaveSameLineHeightAndBaseline = false;
295         if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
296             parent()->clearDescendantsHaveSameLineHeightAndBaseline();
297     }
298
299     void computeReplacedAndTextLineTopAndBottom(LayoutUnit& lineTop, LayoutUnit& lineBottom) const;
300     
301     // Used to calculate the underline offset for TextUnderlinePositionUnder.
302     void maxLogicalBottomForTextDecorationLine(float& maxLogicalBottom, const RenderElement* decorationRenderer, TextDecoration) const;
303     void minLogicalTopForTextDecorationLine(float& minLogicalTop, const RenderElement* decorationRenderer, TextDecoration) const;
304
305 private:
306     bool isInlineFlowBox() const override final { return true; }
307     void boxModelObject() const = delete;
308
309     void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
310     void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
311     void addTextBoxVisualOverflow(InlineTextBox&, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
312     void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
313     void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
314     void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
315
316 protected:
317     RefPtr<RenderOverflow> m_overflow;
318
319     InlineBox* m_firstChild;
320     InlineBox* m_lastChild;
321     
322     InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
323     InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
324
325 private:
326     unsigned m_includeLogicalLeftEdge : 1;
327     unsigned m_includeLogicalRightEdge : 1;
328     unsigned m_hasTextChildren : 1;
329     unsigned m_hasTextDescendants : 1;
330     unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
331
332 protected:
333     // The following members are only used by RootInlineBox but moved here to keep the bits packed.
334
335     // Whether or not this line uses alphabetic or ideographic baselines by default.
336     unsigned m_baselineType : 1; // FontBaseline
337
338     // If the line contains any ruby runs, then this will be true.
339     unsigned m_hasAnnotationsBefore : 1;
340     unsigned m_hasAnnotationsAfter : 1;
341
342     unsigned m_lineBreakBidiStatusEor : 5; // UCharDirection
343     unsigned m_lineBreakBidiStatusLastStrong : 5; // UCharDirection
344     unsigned m_lineBreakBidiStatusLast : 5; // UCharDirection
345
346     unsigned m_isFirstAfterPageBreak : 1;
347     unsigned m_hasAnonymousInlineBlock : 1;
348
349     // End of RootInlineBox-specific members.
350
351 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
352 private:
353     unsigned m_hasBadChildList : 1;
354 #endif
355 };
356
357 #ifdef NDEBUG
358
359 inline void InlineFlowBox::checkConsistency() const
360 {
361 }
362
363 #endif
364
365 #if ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
366
367 inline void InlineFlowBox::setHasBadChildList()
368 {
369 }
370
371 #endif
372
373 } // namespace WebCore
374
375 SPECIALIZE_TYPE_TRAITS_INLINE_BOX(InlineFlowBox, isInlineFlowBox())
376
377 #if ENABLE(TREE_DEBUGGING)
378 // Outside the WebCore namespace for ease of invocation from gdb.
379 void showTree(const WebCore::InlineFlowBox*);
380 #endif
381
382 #endif // InlineFlowBox_h