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