#ifndef RenderBlock_h
#define RenderBlock_h
#include "ColumnInfo.h"
#include "GapRects.h"
#include "PODIntervalTree.h"
#include "RenderBox.h"
#include "RenderLineBoxList.h"
#include "RootInlineBox.h"
#include "TextBreakIterator.h"
#include "TextRun.h"
#include <wtf/OwnPtr.h>
#include <wtf/ListHashSet.h>
#if ENABLE(CSS_SHAPES)
#include "ShapeInsideInfo.h"
#include "ShapeValue.h"
#endif
namespace WebCore {
class BidiContext;
class InlineIterator;
class LayoutStateMaintainer;
class LineLayoutState;
class LineWidth;
class LogicalSelectionOffsetCaches;
class RenderInline;
class RenderText;
struct BidiRun;
struct PaintInfo;
class LineInfo;
class RenderRubyRun;
#if ENABLE(CSS_SHAPES)
class BasicShape;
#endif
class TextLayout;
class WordMeasurement;
template <class Iterator, class Run> class BidiResolver;
template <class Run> class BidiRunList;
template <class Iterator> struct MidpointState;
typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
typedef MidpointState<InlineIterator> LineMidpointState;
typedef WTF::ListHashSet<RenderBox*, 16> TrackedRendererListHashSet;
typedef WTF::HashMap<const RenderBlock*, OwnPtr<TrackedRendererListHashSet> > TrackedDescendantsMap;
typedef WTF::HashMap<const RenderBox*, OwnPtr<HashSet<RenderBlock*> > > TrackedContainerMap;
typedef Vector<WordMeasurement, 64> WordMeasurements;
enum CaretType { CursorCaret, DragCaret };
enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
enum ShapeOutsideFloatOffsetMode { ShapeOutsideFloatShapeOffset, ShapeOutsideFloatBoundingBoxOffset };
#if ENABLE(IOS_TEXT_AUTOSIZING)
enum LineCount {
NOT_SET = 0, NO_LINE = 1, ONE_LINE = 2, MULTI_LINE = 3
};
#endif
enum TextRunFlag {
DefaultTextRunFlags = 0,
RespectDirection = 1 << 0,
RespectDirectionOverride = 1 << 1
};
typedef unsigned TextRunFlags;
class RenderBlock : public RenderBox {
public:
friend class LineLayoutState;
#ifndef NDEBUG
template <class> friend struct ValueToString;
#endif
explicit RenderBlock(ContainerNode*);
virtual ~RenderBlock();
static RenderBlock* createAnonymous(Document*);
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
bool beingDestroyed() const { return m_beingDestroyed; }
virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
void deleteLineBoxTree();
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*);
virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
void insertPositionedObject(RenderBox*);
static void removePositionedObject(RenderBox*);
void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
void removeFloatingObjects();
TrackedRendererListHashSet* positionedObjects() const;
bool hasPositionedObjects() const
{
TrackedRendererListHashSet* objects = positionedObjects();
return objects && !objects->isEmpty();
}
void addPercentHeightDescendant(RenderBox*);
static void removePercentHeightDescendant(RenderBox*);
TrackedRendererListHashSet* percentHeightDescendants() const;
static bool hasPercentHeightContainerMap();
static bool hasPercentHeightDescendant(RenderBox*);
static void clearPercentHeightDescendantsFrom(RenderBox*);
static void removePercentHeightDescendantIfNeeded(RenderBox*);
void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
bool hasMarginBeforeQuirk(const RenderBox* child) const;
bool hasMarginAfterQuirk(const RenderBox* child) const;
RootInlineBox* createAndAppendRootInlineBox();
bool generatesLineBoxesForInlineChild(RenderObject*);
void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
void markPositionedObjectsForLayout();
virtual void markForPaginationRelayoutIfNeeded();
bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
bool containsFloat(RenderBox*) const;
LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
{
return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight)
- logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight));
}
LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
{
return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region), shouldIndentText, 0, logicalHeight, offsetMode);
}
LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
{
return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region), shouldIndentText, 0, logicalHeight, offsetMode);
}
LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
{
return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight)
: logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight);
}
LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
{
return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight)
: logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight);
}
LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
{
return availableLogicalWidthForLine(position, shouldIndentText, regionAtBlockOffset(position), logicalHeight);
}
LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
{
return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), shouldIndentText, 0, logicalHeight, offsetMode);
}
LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
{
return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), shouldIndentText, 0, logicalHeight, offsetMode);
}
LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
{
return roundToInt(logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
}
LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
{
return floorToInt(logicalRightOffsetForLine(position, shouldIndentText, logicalHeight));
}
LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
{
return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
: logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
}
LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
{
return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
: logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
}
LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
LayoutUnit textIndentOffset() const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
virtual LayoutUnit availableLogicalWidth() const;
LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const;
void adjustStartEdgeForWritingModeIncludingColumns(LayoutRect&) const;
RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
bool containsNonZeroBidiLevel() const;
GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer);
LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
RootInlineBox* lineAtIndex(int) const;
int lineCount(const RootInlineBox* = 0, bool* = 0) const;
int heightForLineCount(int);
void clearTruncation();
void adjustRectForColumns(LayoutRect&) const;
virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const;
void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const;
void addContinuationWithOutline(RenderInline*);
bool paintsContinuationOutline(RenderInline*);
virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); }
bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); }
RenderInline* inlineElementContinuation() const;
RenderBlock* blockElementContinuation() const;
using RenderBoxModelObject::continuation;
using RenderBoxModelObject::setContinuation;
static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*);
static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*);
RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); }
RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); }
static void collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child);
virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE;
static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
{
return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
}
static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
static TextRun constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
#if ENABLE(8BIT_TEXTRUN)
static TextRun constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
#endif
static TextRun constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
ColumnInfo* columnInfo() const;
int columnGap() const;
void updateColumnInfoFromStyle(RenderStyle*);
unsigned columnCount(ColumnInfo*) const;
LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); }
void setPaginationStrut(LayoutUnit);
bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; }
void clearShouldBreakAtLineToAvoidWidow() const;
RootInlineBox* lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : 0; }
void setBreakAtLineToAvoidWidow(RootInlineBox*);
LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : LayoutUnit(); }
void setPageLogicalOffset(LayoutUnit);
RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
void setLineGridBox(RootInlineBox* box)
{
if (!m_rareData)
m_rareData = adoptPtr(new RenderBlockRareData(this));
if (m_rareData->m_lineGridBox)
m_rareData->m_lineGridBox->destroy(renderArena());
m_rareData->m_lineGridBox = box;
}
void layoutLineGridBox();
enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); }
LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); }
LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); }
LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const { return child->marginEnd(style()); }
void setMarginStartForChild(RenderBox* child, LayoutUnit value) const { child->setMarginStart(value, style()); }
void setMarginEndForChild(RenderBox* child, LayoutUnit value) const { child->setMarginEnd(value, style()); }
void setMarginBeforeForChild(RenderBox* child, LayoutUnit value) const { child->setMarginBefore(value, style()); }
void setMarginAfterForChild(RenderBox* child, LayoutUnit value) const { child->setMarginAfter(value, style()); }
LayoutUnit collapsedMarginBeforeForChild(const RenderBox* child) const;
LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const;
void updateLogicalWidthForAlignment(const ETextAlign&, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
virtual void updateFirstLetter();
class MarginValues {
public:
MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
: m_positiveMarginBefore(beforePos)
, m_negativeMarginBefore(beforeNeg)
, m_positiveMarginAfter(afterPos)
, m_negativeMarginAfter(afterNeg)
{ }
LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
private:
LayoutUnit m_positiveMarginBefore;
LayoutUnit m_negativeMarginBefore;
LayoutUnit m_positiveMarginAfter;
LayoutUnit m_negativeMarginAfter;
};
MarginValues marginValuesForChild(RenderBox* child) const;
virtual void scrollbarsChanged(bool , bool ) { };
LayoutUnit logicalLeftOffsetForContent(RenderRegion*) const;
LayoutUnit logicalRightOffsetForContent(RenderRegion*) const;
LayoutUnit availableLogicalWidthForContent(RenderRegion* region) const
{
return max<LayoutUnit>(0, logicalRightOffsetForContent(region) - logicalLeftOffsetForContent(region)); }
LayoutUnit startOffsetForContent(RenderRegion* region) const
{
return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
}
LayoutUnit endOffsetForContent(RenderRegion* region) const
{
return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
}
LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const
{
return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset));
}
LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const
{
return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset));
}
LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const
{
return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset));
}
LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const
{
return startOffsetForContent(regionAtBlockOffset(blockOffset));
}
LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const
{
return endOffsetForContent(regionAtBlockOffset(blockOffset));
}
LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); }
LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop);
LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0);
void placeRunInIfNeeded(RenderObject* newChild);
bool runInIsPlacedIntoSiblingBlock(RenderObject* runIn);
#ifndef NDEBUG
void checkPositionedObjectsNeedLayout();
void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
#endif
#if ENABLE(IOS_TEXT_AUTOSIZING)
int immediateLineCount();
void adjustComputedFontSizes(float size, float visibleWidth);
void resetComputedFontSize() {
m_widthForTextAutosizing = -1;
m_lineCountForTextAutosizing = NOT_SET;
}
#endif
#if ENABLE(CSS_SHAPES)
ShapeInsideInfo* ensureShapeInsideInfo()
{
if (!m_rareData || !m_rareData->m_shapeInsideInfo)
setShapeInsideInfo(ShapeInsideInfo::createInfo(this));
return m_rareData->m_shapeInsideInfo.get();
}
ShapeInsideInfo* shapeInsideInfo() const
{
if (!m_rareData || !m_rareData->m_shapeInsideInfo)
return 0;
return ShapeInsideInfo::isEnabledFor(this) ? m_rareData->m_shapeInsideInfo.get() : 0;
}
void setShapeInsideInfo(PassOwnPtr<ShapeInsideInfo> value)
{
if (!m_rareData)
m_rareData = adoptPtr(new RenderBlockRareData(this));
m_rareData->m_shapeInsideInfo = value;
}
void markShapeInsideDescendantsForLayout();
ShapeInsideInfo* layoutShapeInsideInfo() const;
bool allowsShapeInsideInfoSharing() const { return !isInline() && !isFloating(); }
#endif
protected:
virtual void willBeDestroyed();
LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); }
void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
void setMustDiscardMarginBefore(bool = true);
void setMustDiscardMarginAfter(bool = true);
bool mustDiscardMarginBefore() const;
bool mustDiscardMarginAfter() const;
bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
bool mustDiscardMarginAfterForChild(const RenderBox*) const;
bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
bool mustSeparateMarginAfterForChild(const RenderBox*) const;
void initMaxMarginValues()
{
if (m_rareData) {
m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this),
RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this));
m_rareData->m_paginationStrut = 0;
m_rareData->m_discardMarginBefore = false;
m_rareData->m_discardMarginAfter = false;
}
}
virtual void layout();
void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
void markFixedPositionObjectForLayoutIfNeeded(RenderObject* child);
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual void paintObject(PaintInfo&, const LayoutPoint&);
virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
bool paintChild(RenderBox*, PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
LayoutUnit logicalRightOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatShapeOffset) const;
LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatShapeOffset) const;
virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
virtual void adjustInlineDirectionLineBounds(int , float& , float& ) const { }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
virtual int firstLineBoxBaseline() const;
virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
int lastLineBoxBaseline(LineDirectionMode) const;
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
static void startDelayUpdateScrollInfo();
static void finishDelayUpdateScrollInfo();
void updateScrollInfoAfterLayout();
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual bool hasLineIfEmpty() const;
bool simplifiedLayout();
virtual void simplifiedNormalFlowLayout();
void setDesiredColumnCountAndWidth(int, LayoutUnit);
public:
void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
void clearLayoutOverflow();
protected:
virtual void addOverflowFromChildren();
void addOverflowFromFloats();
void addOverflowFromPositionedObjects();
void addOverflowFromBlockChildren();
void addOverflowFromInlineChildren();
void addVisualOverflowFromTheme();
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
#if ENABLE(SVG)
void forceLayoutInlineChildren()
{
LayoutUnit repaintLogicalTop = 0;
LayoutUnit repaintLogicalBottom = 0;
clearFloats();
layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
}
#endif
bool updateRegionsAndExclusionsBeforeChildLayout(RenderFlowThread*);
void updateRegionsAndExclusionsAfterChildLayout(RenderFlowThread*, bool heightChanged = false);
void computeRegionRangeForBlock(RenderFlowThread*);
void updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox*);
virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
private:
#if ENABLE(CSS_SHAPES)
void computeShapeSize();
void updateShapeInsideInfoAfterStyleChange(const ShapeValue*, const ShapeValue* oldShape);
#endif
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
virtual const char* renderName() const;
virtual bool isRenderBlock() const { return true; }
virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
void makeChildrenNonInline(RenderObject* insertionPoint = 0);
virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild);
void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual bool isSelfCollapsingBlock() const;
virtual LayoutUnit collapsedMarginBefore() const { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
virtual LayoutUnit collapsedMarginAfter() const { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE;
void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
virtual RootInlineBox* createRootInlineBox();
virtual RenderObject* layoutSpecialExcludedChild(bool ) { return 0; }
void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
Node* nodeForHitTest() const;
struct FloatWithRect {
FloatWithRect(RenderBox* f)
: object(f)
, rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
, everHadLayout(f->everHadLayout())
{
}
RenderBox* object;
LayoutRect rect;
bool everHadLayout;
};
struct FloatingObject {
WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
public:
enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 };
FloatingObject(EFloat type)
: m_renderer(0)
, m_originatingLine(0)
, m_paginationStrut(0)
, m_shouldPaint(true)
, m_isDescendant(false)
, m_isPlaced(false)
#ifndef NDEBUG
, m_isInPlacedTree(false)
#endif
{
ASSERT(type != NoFloat);
if (type == LeftFloat)
m_type = FloatLeft;
else if (type == RightFloat)
m_type = FloatRight;
}
FloatingObject(Type type, const LayoutRect& frameRect)
: m_renderer(0)
, m_originatingLine(0)
, m_frameRect(frameRect)
, m_paginationStrut(0)
, m_type(type)
, m_shouldPaint(true)
, m_isDescendant(false)
, m_isPlaced(true)
#ifndef NDEBUG
, m_isInPlacedTree(false)
#endif
{
}
FloatingObject* clone() const
{
FloatingObject* cloneObject = new FloatingObject(type(), m_frameRect);
cloneObject->m_renderer = m_renderer;
cloneObject->m_originatingLine = m_originatingLine;
cloneObject->m_paginationStrut = m_paginationStrut;
cloneObject->m_shouldPaint = m_shouldPaint;
cloneObject->m_isDescendant = m_isDescendant;
cloneObject->m_isPlaced = m_isPlaced;
return cloneObject;
}
Type type() const { return static_cast<Type>(m_type); }
RenderBox* renderer() const { return m_renderer; }
bool isPlaced() const { return m_isPlaced; }
void setIsPlaced(bool placed = true) { m_isPlaced = placed; }
inline LayoutUnit x() const { ASSERT(isPlaced()); return m_frameRect.x(); }
inline LayoutUnit maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); }
inline LayoutUnit y() const { ASSERT(isPlaced()); return m_frameRect.y(); }
inline LayoutUnit maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); }
inline LayoutUnit width() const { return m_frameRect.width(); }
inline LayoutUnit height() const { return m_frameRect.height(); }
void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); }
void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); }
void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); }
void setHeight(LayoutUnit height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); }
const LayoutRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; }
void setFrameRect(const LayoutRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; }
#ifndef NDEBUG
bool isInPlacedTree() const { return m_isInPlacedTree; }
void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; }
#endif
bool shouldPaint() const { return m_shouldPaint; }
void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; }
bool isDescendant() const { return m_isDescendant; }
void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; }
RenderBox* m_renderer;
RootInlineBox* m_originatingLine;
LayoutRect m_frameRect;
int m_paginationStrut;
private:
unsigned m_type : 2; unsigned m_shouldPaint : 1;
unsigned m_isDescendant : 1;
unsigned m_isPlaced : 1;
#ifndef NDEBUG
unsigned m_isInPlacedTree : 1;
#endif
};
LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
LayoutUnit logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); }
LayoutUnit logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); }
LayoutUnit logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); }
LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); }
LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); }
int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); }
int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); }
int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); }
void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop)
{
if (isHorizontalWritingMode())
child->setY(logicalTop);
else
child->setX(logicalTop);
}
void setLogicalLeftForFloat(FloatingObject* child, LayoutUnit logicalLeft)
{
if (isHorizontalWritingMode())
child->setX(logicalLeft);
else
child->setY(logicalLeft);
}
void setLogicalHeightForFloat(FloatingObject* child, LayoutUnit logicalHeight)
{
if (isHorizontalWritingMode())
child->setHeight(logicalHeight);
else
child->setWidth(logicalHeight);
}
void setLogicalWidthForFloat(FloatingObject* child, LayoutUnit logicalWidth)
{
if (isHorizontalWritingMode())
child->setWidth(logicalWidth);
else
child->setHeight(logicalWidth);
}
LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
{
#if ENABLE(CSS_SHAPES)
ShapeOutsideInfo *shapeOutside = child->renderer()->shapeOutsideInfo();
if (shapeOutside)
return child->x();
#endif
if (isHorizontalWritingMode())
return child->x() + child->renderer()->marginLeft();
else
return child->x() + marginBeforeForChild(child->renderer());
}
LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
{
#if ENABLE(CSS_SHAPES)
ShapeOutsideInfo *shapeOutside = child->renderer()->shapeOutsideInfo();
if (shapeOutside)
return child->y();
#endif
if (isHorizontalWritingMode())
return child->y() + marginBeforeForChild(child->renderer());
else
return child->y() + child->renderer()->marginTop();
}
LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
struct RenderTextInfo {
RenderTextInfo();
~RenderTextInfo();
RenderText* m_text;
OwnPtr<TextLayout> m_layout;
LazyLineBreakIterator m_lineBreakIterator;
const Font* m_font;
};
class LineBreaker {
public:
LineBreaker(RenderBlock* block)
: m_block(block)
{
reset();
}
InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
bool lineWasHyphenated() { return m_hyphenated; }
const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
EClear clear() { return m_clear; }
private:
void reset();
InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
RenderBlock* m_block;
bool m_hyphenated;
EClear m_clear;
Vector<RenderBox*> m_positionedObjects;
};
void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
void deleteEllipsisLineBoxes();
void checkLinesForTextOverflow();
bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
void appendFloatingObjectToLastLine(FloatingObject*);
void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false);
void paintContents(PaintInfo&, const LayoutPoint&);
void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false);
void paintColumnRules(PaintInfo&, const LayoutPoint&);
void paintSelection(PaintInfo&, const LayoutPoint&);
void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
FloatingObject* insertFloatingObject(RenderBox*);
void removeFloatingObject(RenderBox*);
void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
bool positionNewFloats();
void clearFloats();
LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
virtual bool avoidsFloats() const;
bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
bool hasOverhangingFloat(RenderBox*);
void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset);
LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats);
LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
virtual RenderBlock* firstLineBlock() const;
virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE;
virtual RenderStyle* outlineStyleForRepaint() const;
virtual RenderObject* hoverAncestor() const;
virtual void updateDragState(bool dragOn);
virtual void childBecameNonInline(RenderObject* child);
virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool ) OVERRIDE
{
return selectionGapRectsForRepaint(repaintContainer);
}
virtual bool shouldPaintSelectionGaps() const;
bool isSelectionRoot() const;
GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches&, const PaintInfo*);
#if PLATFORM(IOS)
public:
#endif
LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
#if PLATFORM(IOS)
private:
#endif
friend class LogicalSelectionOffsetCaches;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
LayoutUnit desiredColumnWidth() const;
unsigned desiredColumnCount() const;
void paintContinuationOutlines(PaintInfo&, const LayoutPoint&);
virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
void adjustPointToColumnContents(LayoutPoint&) const;
void fitBorderToLinesIfNeeded(); void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const;
void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
void newLine(EClear);
Position positionForBox(InlineBox*, bool start = true) const;
VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&);
virtual void calcColumnWidth();
void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild);
bool expandsToEncloseOverhangingFloats() const;
void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont);
void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
RenderObject* newChild, RenderBoxModelObject* oldCont);
RenderBlock* clone() const;
RenderBlock* continuationBefore(RenderObject* beforeChild);
RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true);
RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild);
class MarginInfo {
bool m_canCollapseWithChildren : 1;
bool m_canCollapseMarginBeforeWithChildren : 1;
bool m_canCollapseMarginAfterWithChildren : 1;
bool m_quirkContainer : 1;
bool m_atBeforeSideOfBlock : 1;
bool m_atAfterSideOfBlock : 1;
bool m_hasMarginBeforeQuirk : 1;
bool m_hasMarginAfterQuirk : 1;
bool m_determinedMarginBeforeQuirk : 1;
bool m_discardMargin : 1;
LayoutUnit m_positiveMargin;
LayoutUnit m_negativeMargin;
public:
MarginInfo(RenderBlock*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
void clearMargin()
{
m_positiveMargin = 0;
m_negativeMargin = 0;
}
void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; }
void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; }
void setPositiveMarginIfLarger(LayoutUnit p)
{
ASSERT(!m_discardMargin);
if (p > m_positiveMargin)
m_positiveMargin = p;
}
void setNegativeMarginIfLarger(LayoutUnit n)
{
ASSERT(!m_discardMargin);
if (n > m_negativeMargin)
m_negativeMargin = n;
}
void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
void setDiscardMargin(bool value) { m_discardMargin = value; }
bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
bool quirkContainer() const { return m_quirkContainer; }
bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
LayoutUnit positiveMargin() const { return m_positiveMargin; }
LayoutUnit negativeMargin() const { return m_negativeMargin; }
bool discardMargin() const { return m_discardMargin; }
LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
};
void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
void adjustFloatingBlock(const MarginInfo&);
RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn);
void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
void moveRunInToOriginalPosition(RenderObject* runIn);
LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
void setCollapsedBottomMargin(const MarginInfo&);
RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
#if ENABLE(CSS_SHAPES)
void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, LayoutUnit&, LineLayoutState&);
void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
#endif
const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&);
void linkToEndLineIfNeeded(LineLayoutState&);
static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
protected:
void dirtyForLayoutFromPercentageHeightDescendants();
void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&);
enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
virtual ColumnInfo::PaginationUnit paginationUnit() const;
LayoutUnit applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset); LayoutUnit applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo&);
public:
LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
protected:
bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage);
void updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight);
LayoutUnit adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins = false); void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
void offsetForContents(LayoutPoint&) const;
bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
bool logicalWidthChangedInRegions(RenderFlowThread*) const;
virtual bool requiresColumns(int desiredColumnCount) const;
virtual bool updateLogicalWidthAndColumnWidth();
virtual bool canCollapseAnonymousBlockChild() const { return true; }
public:
virtual LayoutUnit offsetFromLogicalTopOfFirstPage() const;
RenderRegion* regionAtBlockOffset(LayoutUnit) const;
RenderRegion* clampToStartAndEndRegions(RenderRegion*) const;
protected:
struct FloatingObjectHashFunctions {
static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); }
static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
struct FloatingObjectHashTranslator {
static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); }
static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; }
};
typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet;
typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator;
typedef PODInterval<int, FloatingObject*> FloatingObjectInterval;
typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree;
typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena;
template <FloatingObject::Type FloatTypeValue>
class FloatIntervalSearchAdapter {
public:
typedef FloatingObjectInterval IntervalType;
FloatIntervalSearchAdapter(const RenderBlock* renderer, int lowValue, int highValue, LayoutUnit& offset, LayoutUnit* heightRemaining)
: m_renderer(renderer)
, m_lowValue(lowValue)
, m_highValue(highValue)
, m_offset(offset)
, m_heightRemaining(heightRemaining)
#if ENABLE(CSS_SHAPES)
, m_last(0)
#endif
{
}
inline int lowValue() const { return m_lowValue; }
inline int highValue() const { return m_highValue; }
void collectIfNeeded(const IntervalType&) const;
#if ENABLE(CSS_SHAPES)
const FloatingObject* lastFloat() const { return m_last; }
#endif
private:
const RenderBlock* m_renderer;
int m_lowValue;
int m_highValue;
LayoutUnit& m_offset;
LayoutUnit* m_heightRemaining;
#if ENABLE(CSS_SHAPES)
mutable const FloatingObject* m_last;
#endif
};
void createFloatingObjects();
public:
class FloatingObjects {
WTF_MAKE_NONCOPYABLE(FloatingObjects); WTF_MAKE_FAST_ALLOCATED;
public:
void clear();
void add(FloatingObject*);
void remove(FloatingObject*);
void addPlacedObject(FloatingObject*);
void removePlacedObject(FloatingObject*);
void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; }
bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
bool hasRightObjects() const { return m_rightObjectsCount > 0; }
const FloatingObjectSet& set() const { return m_set; }
const FloatingObjectTree& placedFloatsTree()
{
computePlacedFloatsTreeIfNeeded();
return m_placedFloatsTree;
}
private:
FloatingObjects(const RenderBlock*, bool horizontalWritingMode);
void computePlacedFloatsTree();
inline void computePlacedFloatsTreeIfNeeded()
{
if (!m_placedFloatsTree.isInitialized())
computePlacedFloatsTree();
}
void increaseObjectsCount(FloatingObject::Type);
void decreaseObjectsCount(FloatingObject::Type);
FloatingObjectInterval intervalForFloatingObject(FloatingObject*);
FloatingObjectSet m_set;
FloatingObjectTree m_placedFloatsTree;
unsigned m_leftObjectsCount;
unsigned m_rightObjectsCount;
bool m_horizontalWritingMode;
const RenderBlock* m_renderer;
friend void RenderBlock::createFloatingObjects();
};
struct RenderBlockRareData {
WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
public:
RenderBlockRareData(const RenderBlock* block)
: m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
, m_paginationStrut(0)
, m_pageLogicalOffset(0)
, m_lineGridBox(0)
, m_lineBreakToAvoidWidow(0)
, m_shouldBreakAtLineToAvoidWidow(false)
, m_discardMarginBefore(false)
, m_discardMarginAfter(false)
{
}
static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block)
{
return std::max<LayoutUnit>(block->marginBefore(), 0);
}
static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block)
{
return std::max<LayoutUnit>(-block->marginBefore(), 0);
}
static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block)
{
return std::max<LayoutUnit>(block->marginAfter(), 0);
}
static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block)
{
return std::max<LayoutUnit>(-block->marginAfter(), 0);
}
MarginValues m_margins;
LayoutUnit m_paginationStrut;
LayoutUnit m_pageLogicalOffset;
RootInlineBox* m_lineGridBox;
RootInlineBox* m_lineBreakToAvoidWidow;
#if ENABLE(CSS_SHAPES)
OwnPtr<ShapeInsideInfo> m_shapeInsideInfo;
#endif
bool m_shouldBreakAtLineToAvoidWidow : 1;
bool m_discardMarginBefore : 1;
bool m_discardMarginAfter : 1;
};
protected:
OwnPtr<FloatingObjects> m_floatingObjects;
OwnPtr<RenderBlockRareData> m_rareData;
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes;
mutable signed m_lineHeight : 27;
unsigned m_hasMarginBeforeQuirk : 1; unsigned m_hasMarginAfterQuirk : 1;
unsigned m_beingDestroyed : 1;
unsigned m_hasMarkupTruncation : 1;
unsigned m_hasBorderOrPaddingLogicalWidthChanged : 1;
#if ENABLE(IOS_TEXT_AUTOSIZING)
int m_widthForTextAutosizing;
unsigned m_lineCountForTextAutosizing : 2;
#endif
friend class RenderRubyBase;
friend class LineWidth;
private:
static bool s_canPropagateFloatIntoSibling;
};
inline RenderBlock* toRenderBlock(RenderObject* object)
{
ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
return static_cast<RenderBlock*>(object);
}
inline const RenderBlock* toRenderBlock(const RenderObject* object)
{
ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
return static_cast<const RenderBlock*>(object);
}
void toRenderBlock(const RenderBlock*);
#ifndef NDEBUG
template <> struct ValueToString<int> {
static String string(const int value);
};
template<> struct ValueToString<RenderBlock::FloatingObject*> {
static String string(const RenderBlock::FloatingObject*);
};
#endif
}
#endif // RenderBlock_h