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