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;
35 class VerticalPositionCache;
39 typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
41 class InlineFlowBox : public InlineBox {
43 explicit InlineFlowBox(RenderBoxModelObject& renderer)
49 , m_includeLogicalLeftEdge(false)
50 , m_includeLogicalRightEdge(false)
51 , m_descendantsHaveSameLineHeightAndBaseline(true)
52 , m_baselineType(AlphabeticBaseline)
53 , m_hasAnnotationsBefore(false)
54 , m_hasAnnotationsAfter(false)
56 , m_hasBadChildList(false)
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 = renderer.style()->display() == LIST_ITEM;
65 m_hasTextDescendants = m_hasTextChildren;
69 virtual ~InlineFlowBox();
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;
75 RenderBoxModelObject& renderer() const { return toRenderBoxModelObject(InlineBox::renderer()); }
77 InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
78 InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
79 void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
80 void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
82 InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
83 InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
85 virtual bool isLeaf() const OVERRIDE FINAL { return false; }
87 InlineBox* firstLeafChild() const;
88 InlineBox* lastLeafChild() const;
90 typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last);
91 void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = 0, void* userData = 0) const;
93 virtual void setConstructed() OVERRIDE FINAL
95 InlineBox::setConstructed();
96 for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
97 child->setConstructed();
100 void addToLine(InlineBox* child);
101 virtual void deleteLine(RenderArena&) OVERRIDE FINAL;
102 virtual void extractLine() OVERRIDE FINAL;
103 virtual void attachLine() OVERRIDE FINAL;
104 virtual void adjustPosition(float dx, float dy);
106 virtual void extractLineBoxFromRenderObject();
107 virtual void attachLineBoxToRenderObject();
108 virtual void removeLineBoxFromRenderObject();
110 virtual void clearTruncation() OVERRIDE;
112 IntRect roundedFrameRect() const;
114 void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
115 void paintMask(PaintInfo&, const LayoutPoint&);
116 void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
117 void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
118 void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
119 virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
120 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
122 bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
124 virtual RenderLineBoxList& rendererLineBoxes() const;
126 // logicalLeft = left in a horizontal line and top in a vertical line.
127 LayoutUnit marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
128 LayoutUnit marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
129 LayoutUnit marginLogicalLeft() const
131 if (!includeLogicalLeftEdge())
133 return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
135 LayoutUnit marginLogicalRight() const
137 if (!includeLogicalRightEdge())
139 return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
141 int borderLogicalLeft() const
143 if (!includeLogicalLeftEdge())
145 return isHorizontal() ? renderer().style(isFirstLineStyle())->borderLeftWidth() : renderer().style(isFirstLineStyle())->borderTopWidth();
147 int borderLogicalRight() const
149 if (!includeLogicalRightEdge())
151 return isHorizontal() ? renderer().style(isFirstLineStyle())->borderRightWidth() : renderer().style(isFirstLineStyle())->borderBottomWidth();
153 int paddingLogicalLeft() const
155 if (!includeLogicalLeftEdge())
157 return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
159 int paddingLogicalRight() const
161 if (!includeLogicalRightEdge())
163 return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
166 bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
167 bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
168 void setEdges(bool includeLeft, bool includeRight)
170 m_includeLogicalLeftEdge = includeLeft;
171 m_includeLogicalRightEdge = includeRight;
174 // Helper functions used during line construction and placement.
175 void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
176 LayoutUnit getFlowSpacingLogicalWidth();
177 float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
178 float placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
179 void beginPlacingBoxRangesInInlineDirection(float logicalLeft) { setLogicalLeft(logicalLeft); }
180 void endPlacingBoxRangesInInlineDirection(float logicalLeft, float logicalRight, float minLogicalLeft, float maxLogicalRight)
182 setLogicalWidth(logicalRight - logicalLeft);
183 if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight))
184 clearKnownToHaveNoOverflow();
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, 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;
197 LayoutUnit computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const;
198 LayoutUnit computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const;
200 void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
202 void removeChild(InlineBox* child);
204 virtual RenderObject::SelectionState selectionState();
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;
209 bool hasTextChildren() const { return m_hasTextChildren; }
210 bool hasTextDescendants() const { return m_hasTextDescendants; }
211 void setHasTextChildren() { m_hasTextChildren = true; setHasTextDescendants(); }
212 void setHasTextDescendants() { m_hasTextDescendants = true; }
214 void checkConsistency() const;
215 void setHasBadChildList();
217 // Line visual and layout overflow are in the coordinate space of the block. This means that they aren't purely physical directions.
218 // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
219 // 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.
220 LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
222 return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
224 LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
227 return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
230 LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
233 return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
236 LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
238 LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
239 if (!renderer().isHorizontalWritingMode())
240 result = result.transposedRect();
244 LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
246 return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
248 LayoutUnit logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().x() : m_overflow->visualOverflowRect().y()) : static_cast<LayoutUnit>(logicalLeft()); }
249 LayoutUnit logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().maxX() : m_overflow->visualOverflowRect().maxY()) : static_cast<LayoutUnit>(ceilf(logicalRight())); }
250 LayoutUnit logicalTopVisualOverflow(LayoutUnit lineTop) const
253 return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
256 LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
259 return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
262 LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
264 LayoutRect result = visualOverflowRect(lineTop, lineBottom);
265 if (!renderer().isHorizontalWritingMode())
266 result = result.transposedRect();
270 void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
271 void setLayoutOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
272 void setVisualOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
274 FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
277 return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
278 return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
281 FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
283 return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
286 bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
287 void clearDescendantsHaveSameLineHeightAndBaseline()
289 m_descendantsHaveSameLineHeightAndBaseline = false;
290 if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
291 parent()->clearDescendantsHaveSameLineHeightAndBaseline();
295 void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
296 void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
297 void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
298 void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
299 void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
302 OwnPtr<RenderOverflow> m_overflow;
304 virtual bool isInlineFlowBox() const OVERRIDE FINAL { return true; }
306 InlineBox* m_firstChild;
307 InlineBox* m_lastChild;
309 InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
310 InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
312 #if ENABLE(CSS3_TEXT)
313 // Maximum logicalTop among all children of an InlineFlowBox. Used to
314 // calculate the offset for TextUnderlinePositionUnder.
315 void computeMaxLogicalTop(float& maxLogicalTop) const;
318 unsigned m_includeLogicalLeftEdge : 1;
319 unsigned m_includeLogicalRightEdge : 1;
320 unsigned m_hasTextChildren : 1;
321 unsigned m_hasTextDescendants : 1;
322 unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
325 // The following members are only used by RootInlineBox but moved here to keep the bits packed.
327 // Whether or not this line uses alphabetic or ideographic baselines by default.
328 unsigned m_baselineType : 1; // FontBaseline
330 // If the line contains any ruby runs, then this will be true.
331 unsigned m_hasAnnotationsBefore : 1;
332 unsigned m_hasAnnotationsAfter : 1;
334 unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
335 unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
336 unsigned m_lineBreakBidiStatusLast : 5; // WTF::Unicode::Direction
338 // End of RootInlineBox-specific members.
342 unsigned m_hasBadChildList : 1;
346 inline InlineFlowBox* toInlineFlowBox(InlineBox* object)
348 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
349 return static_cast<InlineFlowBox*>(object);
352 inline const InlineFlowBox* toInlineFlowBox(const InlineBox* object)
354 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
355 return static_cast<const InlineFlowBox*>(object);
358 // This will catch anyone doing an unnecessary cast.
359 void toInlineFlowBox(const InlineFlowBox*);
362 inline void InlineFlowBox::checkConsistency() const
367 inline void InlineFlowBox::setHasBadChildList()
370 m_hasBadChildList = true;
374 } // namespace WebCore
377 // Outside the WebCore namespace for ease of invocation from gdb.
378 void showTree(const WebCore::InlineFlowBox*);
381 #endif // InlineFlowBox_h