blob: 03773159e26fffda1e4d8d98ed8c0a94fe31a6f8 [file] [log] [blame]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2007 David Smith (catfish.man@gmail.com)
* Copyright (C) 2003-2013 Apple Inc. All rights reserved.
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RenderBlockFlow_h
#define RenderBlockFlow_h
#include "RenderBlock.h"
namespace WebCore {
class MarginInfo;
class RenderBlockFlow : public RenderBlock {
public:
explicit RenderBlockFlow(ContainerNode*);
virtual ~RenderBlockFlow();
virtual bool isRenderBlockFlow() const OVERRIDE FINAL { return true; }
virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
protected:
// Only used by RenderSVGText, which explicitly overrides RenderBlock::layoutBlock(), do NOT use for anything else.
void forceLayoutInlineChildren()
{
LayoutUnit repaintLogicalTop = 0;
LayoutUnit repaintLogicalBottom = 0;
rebuildFloatsFromIntruding();
layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
}
private:
void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom, SubtreeLayoutScope&);
void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
void adjustFloatingBlock(const MarginInfo&);
void rebuildFloatsFromIntruding();
public:
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;
// Allocated only when some of these fields have non-default values
struct RenderBlockFlowRareData {
WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
public:
RenderBlockFlowRareData(const RenderBlockFlow* block)
: m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
, m_discardMarginBefore(false)
, m_discardMarginAfter(false)
{
}
static LayoutUnit positiveMarginBeforeDefault(const RenderBlockFlow* block)
{
return std::max<LayoutUnit>(block->marginBefore(), 0);
}
static LayoutUnit negativeMarginBeforeDefault(const RenderBlockFlow* block)
{
return std::max<LayoutUnit>(-block->marginBefore(), 0);
}
static LayoutUnit positiveMarginAfterDefault(const RenderBlockFlow* block)
{
return std::max<LayoutUnit>(block->marginAfter(), 0);
}
static LayoutUnit negativeMarginAfterDefault(const RenderBlockFlow* block)
{
return std::max<LayoutUnit>(-block->marginAfter(), 0);
}
MarginValues m_margins;
bool m_discardMarginBefore : 1;
bool m_discardMarginAfter : 1;
};
protected:
LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); }
LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); }
LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(this); }
LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::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(RenderBlockFlowRareData::positiveMarginBeforeDefault(this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(this),
RenderBlockFlowRareData::positiveMarginAfterDefault(this), RenderBlockFlowRareData::negativeMarginAfterDefault(this));
m_rareData->m_discardMarginBefore = false;
m_rareData->m_discardMarginAfter = false;
}
}
private:
virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
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&);
LayoutUnit applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset); // If the child has a before break, then return a new yPos that shifts to the top of the next page/column.
LayoutUnit applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo&); // If the child has an after break, then return a new offset that shifts to the top of the next page/column.
LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
protected:
OwnPtr<RenderBlockFlowRareData> m_rareData;
friend class MarginInfo;
};
inline RenderBlockFlow& toRenderBlockFlow(RenderObject& object)
{
ASSERT_WITH_SECURITY_IMPLICATION(object.isRenderBlockFlow());
return static_cast<RenderBlockFlow&>(object);
}
inline const RenderBlockFlow& toRenderBlockFlow(const RenderObject& object)
{
ASSERT_WITH_SECURITY_IMPLICATION(object.isRenderBlockFlow());
return static_cast<const RenderBlockFlow&>(object);
}
inline RenderBlockFlow* toRenderBlockFlow(RenderObject* object)
{
ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlockFlow());
return static_cast<RenderBlockFlow*>(object);
}
inline const RenderBlockFlow* toRenderBlockFlow(const RenderObject* object)
{
ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlockFlow());
return static_cast<const RenderBlockFlow*>(object);
}
// This will catch anyone doing an unnecessary cast.
void toRenderBlockFlow(const RenderBlockFlow*);
void toRenderBlockFlow(const RenderBlockFlow&);
} // namespace WebCore
#endif // RenderBlockFlow_h