https://bugs.webkit.org/show_bug.cgi?id=54244
[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 VerticalPositionCache;
35
36 typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
37
38 class InlineFlowBox : public InlineBox {
39 public:
40     InlineFlowBox(RenderObject* obj)
41         : InlineBox(obj)
42         , m_firstChild(0)
43         , m_lastChild(0)
44         , m_prevLineBox(0)
45         , m_nextLineBox(0)
46         , m_includeLogicalLeftEdge(false)
47         , m_includeLogicalRightEdge(false)
48 #ifndef NDEBUG
49         , m_hasBadChildList(false)
50 #endif
51     {
52         // 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
53         // 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
54         // an invisible marker exists.  The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
55         // text children must not apply.  This change also means that gaps will exist between image bullet list items.  Even when the list bullet
56         // is an image, the line is still considered to be immune from the quirk.
57         m_hasTextChildren = obj->style()->display() == LIST_ITEM;
58     }
59
60 #ifndef NDEBUG
61     virtual ~InlineFlowBox();
62 #endif
63
64     InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
65     InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
66     void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
67     void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
68
69     InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
70     InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
71
72     virtual bool isLeaf() const { return false; }
73     
74     InlineBox* firstLeafChild() const;
75     InlineBox* lastLeafChild() const;
76
77     virtual void setConstructed()
78     {
79         InlineBox::setConstructed();
80         for (InlineBox* child = firstChild(); child; child = child->next())
81             child->setConstructed();
82     }
83
84     void addToLine(InlineBox* child);
85     virtual void deleteLine(RenderArena*);
86     virtual void extractLine();
87     virtual void attachLine();
88     virtual void adjustPosition(float dx, float dy);
89
90     virtual void extractLineBoxFromRenderObject();
91     virtual void attachLineBoxToRenderObject();
92     virtual void removeLineBoxFromRenderObject();
93
94     virtual void clearTruncation();
95
96     IntRect roundedFrameRect() const;
97     
98     virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
99     virtual void paintMask(PaintInfo&, int tx, int ty);
100     void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
101     void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
102     void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, int tx, int ty, int w, int h);
103     virtual void paint(PaintInfo&, int tx, int ty);
104     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
105
106     virtual RenderLineBoxList* rendererLineBoxes() const;
107
108     // logicalLeft = left in a horizontal line and top in a vertical line.
109     int marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
110     int marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
111     int marginLogicalLeft() const
112     {
113         if (!includeLogicalLeftEdge())
114             return 0;
115         return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
116     }
117     int marginLogicalRight() const
118     {
119         if (!includeLogicalRightEdge())
120             return 0;
121         return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
122     }
123     int borderLogicalLeft() const
124     {
125         if (!includeLogicalLeftEdge())
126             return 0;
127         return isHorizontal() ? renderer()->style()->borderLeftWidth() : renderer()->style()->borderTopWidth();
128     }
129     int borderLogicalRight() const
130     {
131         if (!includeLogicalRightEdge())
132             return 0;
133         return isHorizontal() ? renderer()->style()->borderRightWidth() : renderer()->style()->borderBottomWidth();
134     }
135     int paddingLogicalLeft() const
136     {
137         if (!includeLogicalLeftEdge())
138             return 0;
139         return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
140     }
141     int paddingLogicalRight() const
142     {
143         if (!includeLogicalRightEdge())
144             return 0;
145         return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
146     }
147
148     bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
149     bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
150     void setEdges(bool includeLeft, bool includeRight)
151     {
152         m_includeLogicalLeftEdge = includeLeft;
153         m_includeLogicalRightEdge = includeRight;
154     }
155
156     // Helper functions used during line construction and placement.
157     void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
158     int getFlowSpacingLogicalWidth();
159     bool onEndChain(RenderObject* endObject);
160     float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
161     void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
162                                   int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
163                                   bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&);
164     void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
165                                    int maxPositionTop, int maxPositionBottom);
166     void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop,
167                                     int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline);
168     void flipLinesInBlockDirection(int lineTop, int lineBottom);
169     bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const;
170
171     int computeOverAnnotationAdjustment(int allowedPosition) const;
172     int computeUnderAnnotationAdjustment(int allowedPosition) const;
173
174     void computeOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
175     
176     void removeChild(InlineBox* child);
177
178     virtual RenderObject::SelectionState selectionState();
179
180     virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
181     virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, bool&);
182
183     bool hasTextChildren() const { return m_hasTextChildren; }
184
185     void checkConsistency() const;
186     void setHasBadChildList();
187
188     // Line visual and layout overflow are in the coordinate space of the block.  This means that they aren't purely physical directions.
189     // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
190     // 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.
191     int minYLayoutOverflow() const { return m_overflow ? m_overflow->minYLayoutOverflow() : m_y; }
192     int maxYLayoutOverflow() const { return m_overflow ? m_overflow->maxYLayoutOverflow() : ceilf(m_y + height()); }
193     int minXLayoutOverflow() const { return m_overflow ? m_overflow->minXLayoutOverflow() : m_x; }
194     int maxXLayoutOverflow() const { return m_overflow ? m_overflow->maxXLayoutOverflow() : ceilf(m_x + width()); }
195     IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : enclosingIntRect(FloatRect(m_x, m_y, width(), height())); }
196     int logicalLeftLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minXLayoutOverflow() : minYLayoutOverflow(); }
197     int logicalRightLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxXLayoutOverflow() : maxYLayoutOverflow(); }
198     int logicalTopLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minYVisualOverflow() : minXVisualOverflow(); }
199     int logicalBottomLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxYLayoutOverflow() : maxXLayoutOverflow(); }
200     IntRect logicalLayoutOverflowRect() const
201     {
202         IntRect result = layoutOverflowRect();
203         if (!renderer()->style()->isHorizontalWritingMode())
204             result = result.transposedRect();
205         return result;
206     }
207
208     int minYVisualOverflow() const { return m_overflow ? m_overflow->minYVisualOverflow() : m_y; }
209     int maxYVisualOverflow() const { return m_overflow ? m_overflow->maxYVisualOverflow() : ceilf(m_y + height()); }
210     int minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : m_x; }
211     int maxXVisualOverflow() const { return m_overflow ? m_overflow->maxXVisualOverflow() : ceilf(m_x + width()); }
212     IntRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : enclosingIntRect(FloatRect(m_x, m_y, width(), height())); }
213     int logicalLeftVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minXVisualOverflow() : minYVisualOverflow(); }
214     int logicalRightVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxXVisualOverflow() : maxYVisualOverflow(); }
215     int logicalTopVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minYVisualOverflow() : minXVisualOverflow(); }
216     int logicalBottomVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxYVisualOverflow() : maxXVisualOverflow(); }
217     IntRect logicalVisualOverflowRect() const
218     {
219         IntRect result = visualOverflowRect();
220         if (!renderer()->style()->isHorizontalWritingMode())
221             result = result.transposedRect();
222         return result;
223     }
224
225     void setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow);
226     void setLayoutOverflow(const IntRect&);
227     void setVisualOverflow(const IntRect&);
228
229 private:
230     void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow);
231     void addTextBoxVisualOverflow(const InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
232     void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow);
233
234 protected:
235     OwnPtr<RenderOverflow> m_overflow;
236
237     virtual bool isInlineFlowBox() const { return true; }
238
239     InlineBox* m_firstChild;
240     InlineBox* m_lastChild;
241     
242     InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
243     InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
244
245     bool m_includeLogicalLeftEdge : 1;
246     bool m_includeLogicalRightEdge : 1;
247     bool m_hasTextChildren : 1;
248
249 #ifndef NDEBUG
250     bool m_hasBadChildList;
251 #endif
252 };
253
254 #ifdef NDEBUG
255 inline void InlineFlowBox::checkConsistency() const
256 {
257 }
258 #endif
259
260 inline void InlineFlowBox::setHasBadChildList()
261 {
262 #ifndef NDEBUG
263     m_hasBadChildList = true;
264 #endif
265 }
266
267 } // namespace WebCore
268
269 #ifndef NDEBUG
270 // Outside the WebCore namespace for ease of invocation from gdb.
271 void showTree(const WebCore::InlineFlowBox*);
272 #endif
273
274 #endif // InlineFlowBox_h