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