Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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 "core/rendering/InlineBox.h"
25 #include "core/rendering/RenderObjectInlines.h"
26 #include "core/rendering/RenderOverflow.h"
27 #include "core/rendering/style/ShadowData.h"
28
29 namespace blink {
30
31 class HitTestRequest;
32 class HitTestResult;
33 class InlineTextBox;
34 class RenderLineBoxList;
35 class SimpleFontData;
36 class VerticalPositionCache;
37
38 struct GlyphOverflow;
39
40 typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
41
42 class InlineFlowBox : public InlineBox {
43 public:
44     InlineFlowBox(RenderObject& obj)
45         : InlineBox(obj)
46         , m_firstChild(0)
47         , m_lastChild(0)
48         , m_prevLineBox(0)
49         , m_nextLineBox(0)
50         , m_includeLogicalLeftEdge(false)
51         , m_includeLogicalRightEdge(false)
52         , m_descendantsHaveSameLineHeightAndBaseline(true)
53         , m_baselineType(AlphabeticBaseline)
54         , m_hasAnnotationsBefore(false)
55         , m_hasAnnotationsAfter(false)
56         , m_lineBreakBidiStatusEor(WTF::Unicode::LeftToRight)
57         , m_lineBreakBidiStatusLastStrong(WTF::Unicode::LeftToRight)
58         , m_lineBreakBidiStatusLast(WTF::Unicode::LeftToRight)
59 #if ENABLE(ASSERT)
60         , m_hasBadChildList(false)
61 #endif
62     {
63         // 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
64         // 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
65         // an invisible marker exists.  The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
66         // text children must not apply.  This change also means that gaps will exist between image bullet list items.  Even when the list bullet
67         // is an image, the line is still considered to be immune from the quirk.
68         m_hasTextChildren = obj.style()->display() == LIST_ITEM;
69         m_hasTextDescendants = m_hasTextChildren;
70     }
71
72 #if ENABLE(ASSERT)
73     virtual ~InlineFlowBox();
74 #endif
75
76 #ifndef NDEBUG
77     virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const override;
78     virtual const char* boxName() const override;
79 #endif
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     virtual bool isLeaf() const override 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 = 0, void* userData = 0) const;
96
97     virtual void setConstructed() override 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     virtual void deleteLine() override final;
106     virtual void extractLine() override final;
107     virtual void attachLine() override final;
108     virtual void adjustPosition(float dx, float dy) override;
109
110     virtual void extractLineBoxFromRenderObject();
111     virtual void attachLineBoxToRenderObject();
112     virtual void removeLineBoxFromRenderObject();
113
114     virtual void clearTruncation() override;
115
116     IntRect roundedFrameRect() const;
117
118     virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) override;
119     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) override;
120
121     bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
122
123     virtual RenderLineBoxList* rendererLineBoxes() const;
124
125     // logicalLeft = left in a horizontal line and top in a vertical line.
126     LayoutUnit marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
127     LayoutUnit marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
128     LayoutUnit marginLogicalLeft() const
129     {
130         if (!includeLogicalLeftEdge())
131             return 0;
132         return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
133     }
134     LayoutUnit marginLogicalRight() const
135     {
136         if (!includeLogicalRightEdge())
137             return 0;
138         return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
139     }
140     int borderLogicalLeft() const
141     {
142         if (!includeLogicalLeftEdge())
143             return 0;
144         return isHorizontal() ? renderer().style(isFirstLineStyle())->borderLeftWidth() : renderer().style(isFirstLineStyle())->borderTopWidth();
145     }
146     int borderLogicalRight() const
147     {
148         if (!includeLogicalRightEdge())
149             return 0;
150         return isHorizontal() ? renderer().style(isFirstLineStyle())->borderRightWidth() : renderer().style(isFirstLineStyle())->borderBottomWidth();
151     }
152     int paddingLogicalLeft() const
153     {
154         if (!includeLogicalLeftEdge())
155             return 0;
156         return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
157     }
158     int paddingLogicalRight() const
159     {
160         if (!includeLogicalRightEdge())
161             return 0;
162         return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
163     }
164
165     bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
166     bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
167     void setEdges(bool includeLeft, bool includeRight)
168     {
169         m_includeLogicalLeftEdge = includeLeft;
170         m_includeLogicalRightEdge = includeRight;
171     }
172
173     // Helper functions used during line construction and placement.
174     void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
175     LayoutUnit getFlowSpacingLogicalWidth();
176     float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing);
177     float placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild,
178         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, LayoutUnit& selectionBottom, 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, MarkLineBoxes);
203
204     virtual RenderObject::SelectionState selectionState() const override;
205
206     virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const override final;
207     virtual 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 setHasTextDescendants() { m_hasTextDescendants = true; }
212
213     void checkConsistency() const;
214     void setHasBadChildList();
215
216     // Line visual and layout overflow are in the coordinate space of the block.  This means that they aren't purely physical directions.
217     // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
218     // 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.
219     LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
220     {
221         return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
222     }
223     LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
224     {
225         if (m_overflow)
226             return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
227         return lineTop;
228     }
229     LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
230     {
231         if (m_overflow)
232             return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
233         return lineBottom;
234     }
235     LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
236     {
237         LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
238         if (!renderer().isHorizontalWritingMode())
239             result = result.transposedRect();
240         return result;
241     }
242
243     LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
244     {
245         return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
246     }
247     LayoutUnit logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().x() : m_overflow->visualOverflowRect().y()) : static_cast<LayoutUnit>(logicalLeft()); }
248     LayoutUnit logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().maxX() : m_overflow->visualOverflowRect().maxY()) : static_cast<LayoutUnit>(ceilf(logicalRight())); }
249     LayoutUnit logicalTopVisualOverflow(LayoutUnit lineTop) const
250     {
251         if (m_overflow)
252             return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
253         return lineTop;
254     }
255     LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
256     {
257         if (m_overflow)
258             return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
259         return lineBottom;
260     }
261     LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
262     {
263         LayoutRect result = visualOverflowRect(lineTop, lineBottom);
264         if (!renderer().isHorizontalWritingMode())
265             result = result.transposedRect();
266         return result;
267     }
268
269     void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
270
271     FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
272     {
273         if (isHorizontal())
274             return FloatRect(m_topLeft.x(), lineTop.toFloat(), width(), (lineBottom - lineTop).toFloat());
275         return FloatRect(lineTop.toFloat(), m_topLeft.y(), (lineBottom - lineTop).toFloat(), height());
276     }
277
278     FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
279     {
280         return FloatRect(logicalLeft(), lineTop.toFloat(), logicalWidth(), (lineBottom - lineTop).toFloat());
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 addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
295     void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
296     void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
297
298     void setLayoutOverflow(const LayoutRect&, const LayoutRect&);
299     void setVisualOverflow(const LayoutRect&, const LayoutRect&);
300
301 protected:
302     OwnPtr<RenderOverflow> m_overflow;
303
304     virtual bool isInlineFlowBox() const override final { return true; }
305
306     InlineBox* m_firstChild;
307     InlineBox* m_lastChild;
308
309     InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
310     InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
311
312     // Maximum logicalTop among all children of an InlineFlowBox. Used to
313     // calculate the offset for TextUnderlinePositionUnder.
314     void computeMaxLogicalTop(float& maxLogicalTop) const;
315
316 private:
317     unsigned m_includeLogicalLeftEdge : 1;
318     unsigned m_includeLogicalRightEdge : 1;
319     unsigned m_hasTextChildren : 1;
320     unsigned m_hasTextDescendants : 1;
321     unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
322
323 protected:
324     // The following members are only used by RootInlineBox but moved here to keep the bits packed.
325
326     // Whether or not this line uses alphabetic or ideographic baselines by default.
327     unsigned m_baselineType : 1; // FontBaseline
328
329     // If the line contains any ruby runs, then this will be true.
330     unsigned m_hasAnnotationsBefore : 1;
331     unsigned m_hasAnnotationsAfter : 1;
332
333     unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
334     unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
335     unsigned m_lineBreakBidiStatusLast : 5; // WTF::Unicode::Direction
336
337     // End of RootInlineBox-specific members.
338
339 #if ENABLE(ASSERT)
340 private:
341     unsigned m_hasBadChildList : 1;
342 #endif
343 };
344
345 DEFINE_INLINE_BOX_TYPE_CASTS(InlineFlowBox);
346
347 #if !ENABLE(ASSERT)
348 inline void InlineFlowBox::checkConsistency() const
349 {
350 }
351 #endif
352
353 inline void InlineFlowBox::setHasBadChildList()
354 {
355 #if ENABLE(ASSERT)
356     m_hasBadChildList = true;
357 #endif
358 }
359
360 } // namespace blink
361
362 #ifndef NDEBUG
363 // Outside the WebCore namespace for ease of invocation from gdb.
364 void showTree(const blink::InlineFlowBox*);
365 #endif
366
367 #endif // InlineFlowBox_h