2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
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.
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.
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.
21 #ifndef InlineFlowBox_h
22 #define InlineFlowBox_h
24 #include "InlineBox.h"
25 #include "RenderOverflow.h"
26 #include "ShadowData.h"
33 class RenderLineBoxList;
34 class VerticalPositionCache;
36 typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
38 class InlineFlowBox : public InlineBox {
40 InlineFlowBox(RenderObject* obj)
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)
54 , m_hasBadChildList(false)
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;
67 virtual ~InlineFlowBox();
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;
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; }
78 InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
79 InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
81 virtual bool isLeaf() const { return false; }
83 InlineBox* firstLeafChild() const;
84 InlineBox* lastLeafChild() const;
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;
89 virtual void setConstructed()
91 InlineBox::setConstructed();
92 for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
93 child->setConstructed();
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);
102 virtual void extractLineBoxFromRenderObject();
103 virtual void attachLineBoxToRenderObject();
104 virtual void removeLineBoxFromRenderObject();
106 virtual void clearTruncation() OVERRIDE;
108 IntRect roundedFrameRect() const;
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;
118 bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
120 virtual RenderLineBoxList* rendererLineBoxes() const;
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
127 if (!includeLogicalLeftEdge())
129 return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
131 LayoutUnit marginLogicalRight() const
133 if (!includeLogicalRightEdge())
135 return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
137 int borderLogicalLeft() const
139 if (!includeLogicalLeftEdge())
141 return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderLeftWidth() : renderer()->style(isFirstLineStyle())->borderTopWidth();
143 int borderLogicalRight() const
145 if (!includeLogicalRightEdge())
147 return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderRightWidth() : renderer()->style(isFirstLineStyle())->borderBottomWidth();
149 int paddingLogicalLeft() const
151 if (!includeLogicalLeftEdge())
153 return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
155 int paddingLogicalRight() const
157 if (!includeLogicalRightEdge())
159 return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
162 bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
163 bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
164 void setEdges(bool includeLeft, bool includeRight)
166 m_includeLogicalLeftEdge = includeLeft;
167 m_includeLogicalRightEdge = includeRight;
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;
184 LayoutUnit computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const;
185 LayoutUnit computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const;
187 void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
189 void removeChild(InlineBox* child);
191 virtual RenderObject::SelectionState selectionState();
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;
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; }
201 void checkConsistency() const;
202 void setHasBadChildList();
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
209 return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
211 LayoutUnit logicalLeftLayoutOverflow() const
213 return m_overflow ? (isHorizontal() ? m_overflow->layoutOverflowRect().x() : m_overflow->layoutOverflowRect().y()) :
214 static_cast<LayoutUnit>(logicalLeft());
216 LayoutUnit logicalRightLayoutOverflow() const
218 return m_overflow ? (isHorizontal() ? m_overflow->layoutOverflowRect().maxX() : m_overflow->layoutOverflowRect().maxY()) :
219 static_cast<LayoutUnit>(ceilf(logicalRight()));
221 LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
224 return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
227 LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
230 return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
233 LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
235 LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
236 if (!renderer()->isHorizontalWritingMode())
237 result = result.transposedRect();
241 LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
243 return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
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
250 return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
253 LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
256 return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
259 LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
261 LayoutRect result = visualOverflowRect(lineTop, lineBottom);
262 if (!renderer()->isHorizontalWritingMode())
263 result = result.transposedRect();
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);
271 FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
274 return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
275 return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
278 FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
280 return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
283 bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
284 void clearDescendantsHaveSameLineHeightAndBaseline()
286 m_descendantsHaveSameLineHeightAndBaseline = false;
287 if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
288 parent()->clearDescendantsHaveSameLineHeightAndBaseline();
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;
299 OwnPtr<RenderOverflow> m_overflow;
301 virtual bool isInlineFlowBox() const { return true; }
303 InlineBox* m_firstChild;
304 InlineBox* m_lastChild;
306 InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
307 InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
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;
317 // The following members are only used by RootInlineBox but moved here to keep the bits packed.
319 // Whether or not this line uses alphabetic or ideographic baselines by default.
320 unsigned m_baselineType : 1; // FontBaseline
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;
327 unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
328 unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
329 unsigned m_lineBreakBidiStatusLast : 5; // WTF::Unicode::Direction
331 // End of RootInlineBox-specific members.
335 unsigned m_hasBadChildList : 1;
339 inline InlineFlowBox* toInlineFlowBox(InlineBox* object)
341 ASSERT(!object || object->isInlineFlowBox());
342 return static_cast<InlineFlowBox*>(object);
345 inline const InlineFlowBox* toInlineFlowBox(const InlineBox* object)
347 ASSERT(!object || object->isInlineFlowBox());
348 return static_cast<const InlineFlowBox*>(object);
351 // This will catch anyone doing an unnecessary cast.
352 void toInlineFlowBox(const InlineFlowBox*);
355 inline void InlineFlowBox::checkConsistency() const
360 inline void InlineFlowBox::setHasBadChildList()
363 m_hasBadChildList = true;
367 } // namespace WebCore
370 // Outside the WebCore namespace for ease of invocation from gdb.
371 void showTree(const WebCore::InlineFlowBox*);
374 #endif // InlineFlowBox_h