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