#ifndef InlineFlowBox_h
#define InlineFlowBox_h
#include "InlineBox.h"
#include "RenderOverflow.h"
#include "ShadowData.h"
namespace WebCore {
class HitTestRequest;
class HitTestResult;
class InlineTextBox;
class RenderLineBoxList;
class VerticalPositionCache;
typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
class InlineFlowBox : public InlineBox {
public:
InlineFlowBox(RenderObject* obj)
: InlineBox(obj)
, m_firstChild(0)
, m_lastChild(0)
, m_prevLineBox(0)
, m_nextLineBox(0)
, m_includeLogicalLeftEdge(false)
, m_includeLogicalRightEdge(false)
, m_descendantsHaveSameLineHeightAndBaseline(true)
#ifndef NDEBUG
, m_hasBadChildList(false)
#endif
{
m_hasTextChildren = obj->style()->display() == LIST_ITEM;
m_hasTextDescendants = m_hasTextChildren;
}
#ifndef NDEBUG
virtual ~InlineFlowBox();
virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
virtual const char* boxName() const;
#endif
InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
virtual bool isLeaf() const { return false; }
InlineBox* firstLeafChild() const;
InlineBox* lastLeafChild() const;
typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last);
void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = 0, void* userData = 0) const;
virtual void setConstructed()
{
InlineBox::setConstructed();
for (InlineBox* child = firstChild(); child; child = child->next())
child->setConstructed();
}
void addToLine(InlineBox* child);
virtual void deleteLine(RenderArena*);
virtual void extractLine();
virtual void attachLine();
virtual void adjustPosition(float dx, float dy);
virtual void extractLineBoxFromRenderObject();
virtual void attachLineBoxToRenderObject();
virtual void removeLineBoxFromRenderObject();
virtual void clearTruncation();
IntRect roundedFrameRect() const;
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
virtual void paintMask(PaintInfo&, int tx, int ty);
void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const IntRect&, CompositeOperator = CompositeSourceOver);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const IntRect&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, const IntRect&);
virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const IntPoint& pointInContainer, int tx, int ty, int lineTop, int lineBottom);
virtual RenderLineBoxList* rendererLineBoxes() const;
int marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
int marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
int marginLogicalLeft() const
{
if (!includeLogicalLeftEdge())
return 0;
return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
}
int marginLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
}
int borderLogicalLeft() const
{
if (!includeLogicalLeftEdge())
return 0;
return isHorizontal() ? renderer()->style()->borderLeftWidth() : renderer()->style()->borderTopWidth();
}
int borderLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
return isHorizontal() ? renderer()->style()->borderRightWidth() : renderer()->style()->borderBottomWidth();
}
int paddingLogicalLeft() const
{
if (!includeLogicalLeftEdge())
return 0;
return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
}
int paddingLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
}
bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
void setEdges(bool includeLeft, bool includeRight)
{
m_includeLogicalLeftEdge = includeLeft;
m_includeLogicalRightEdge = includeRight;
}
void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
int getFlowSpacingLogicalWidth();
float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
void computeLogicalBoxHeights(RootInlineBox*, int& maxPositionTop, int& maxPositionBottom,
int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&);
void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
int maxPositionTop, int maxPositionBottom);
void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop,
int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline);
void flipLinesInBlockDirection(int lineTop, int lineBottom);
bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const;
int computeOverAnnotationAdjustment(int allowedPosition) const;
int computeUnderAnnotationAdjustment(int allowedPosition) const;
void computeOverflow(int lineTop, int lineBottom, GlyphOverflowAndFallbackFontsMap&);
void removeChild(InlineBox* child);
virtual RenderObject::SelectionState selectionState();
virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, bool&);
bool hasTextChildren() const { return m_hasTextChildren; }
bool hasTextDescendants() const { return m_hasTextDescendants; }
void checkConsistency() const;
void setHasBadChildList();
IntRect layoutOverflowRect(int lineTop, int lineBottom) const
{
return m_overflow ? m_overflow->layoutOverflowRect() : enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
}
int logicalLeftLayoutOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->minXLayoutOverflow() : m_overflow->minYLayoutOverflow()) : logicalLeft(); }
int logicalRightLayoutOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->maxXLayoutOverflow() : m_overflow->maxYLayoutOverflow()) : ceilf(logicalRight()); }
int logicalTopLayoutOverflow(int lineTop) const
{
if (m_overflow)
return isHorizontal() ? m_overflow->minYLayoutOverflow() : m_overflow->minXLayoutOverflow();
return lineTop;
}
int logicalBottomLayoutOverflow(int lineBottom) const
{
if (m_overflow)
return isHorizontal() ? m_overflow->maxYLayoutOverflow() : m_overflow->maxXLayoutOverflow();
return lineBottom;
}
IntRect logicalLayoutOverflowRect(int lineTop, int lineBottom) const
{
IntRect result = layoutOverflowRect(lineTop, lineBottom);
if (!renderer()->isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
IntRect visualOverflowRect(int lineTop, int lineBottom) const
{
return m_overflow ? m_overflow->visualOverflowRect() : enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
}
int logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->minXVisualOverflow() : m_overflow->minYVisualOverflow()) : logicalLeft(); }
int logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->maxXVisualOverflow() : m_overflow->maxYVisualOverflow()) : ceilf(logicalRight()); }
int logicalTopVisualOverflow(int lineTop) const
{
if (m_overflow)
return isHorizontal() ? m_overflow->minYVisualOverflow() : m_overflow->minXVisualOverflow();
return lineTop;
}
int logicalBottomVisualOverflow(int lineBottom) const
{
if (m_overflow)
return isHorizontal() ? m_overflow->maxYVisualOverflow() : m_overflow->maxXVisualOverflow();
return lineBottom;
}
IntRect logicalVisualOverflowRect(int lineTop, int lineBottom) const
{
IntRect result = visualOverflowRect(lineTop, lineBottom);
if (!renderer()->isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
void setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow, int lineTop, int lineBottom);
void setLayoutOverflow(const IntRect&, int lineTop, int lineBottom);
void setVisualOverflow(const IntRect&, int lineTop, int lineBottom);
FloatRect frameRectIncludingLineHeight(int lineTop, int lineBottom) const
{
if (isHorizontal())
return FloatRect(m_x, lineTop, width(), lineBottom - lineTop);
return FloatRect(lineTop, m_y, lineBottom - lineTop, height());
}
FloatRect logicalFrameRectIncludingLineHeight(int lineTop, int lineBottom) const
{
return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
}
bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
void clearDescendantsHaveSameLineHeightAndBaseline()
{
m_descendantsHaveSameLineHeightAndBaseline = false;
if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
parent()->clearDescendantsHaveSameLineHeightAndBaseline();
}
private:
void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow);
void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow);
protected:
OwnPtr<RenderOverflow> m_overflow;
virtual bool isInlineFlowBox() const { return true; }
InlineBox* m_firstChild;
InlineBox* m_lastChild;
InlineFlowBox* m_prevLineBox; InlineFlowBox* m_nextLineBox;
bool m_includeLogicalLeftEdge : 1;
bool m_includeLogicalRightEdge : 1;
bool m_hasTextChildren : 1;
bool m_hasTextDescendants : 1;
bool m_descendantsHaveSameLineHeightAndBaseline : 1;
#ifndef NDEBUG
bool m_hasBadChildList;
#endif
};
#ifdef NDEBUG
inline void InlineFlowBox::checkConsistency() const
{
}
#endif
inline void InlineFlowBox::setHasBadChildList()
{
#ifndef NDEBUG
m_hasBadChildList = true;
#endif
}
}
#ifndef NDEBUG
void showTree(const WebCore::InlineFlowBox*);
#endif
#endif // InlineFlowBox_h