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