+2013-10-08 Bem Jones-Bey <bjonesbe@adobe.com>
+
+ Move m_floatingObjects to RenderBlockFlow from RenderBlock
+ https://bugs.webkit.org/show_bug.cgi?id=122512
+
+ Reviewed by David Hyatt.
+
+ Floats are part of block flow, not every RenderBlock can contain
+ floars. This change makes it so that RenderBlock no longer can contain
+ floats, only RenderBlockFlow can.
+
+ This also moves a bunch of line layout stuff over to RenderBlockFlow,
+ but makes no effort to move all of line layout, as all of that is
+ destined to move out of both RenderBlockFlow and RenderBlock into its
+ own class.
+
+ No new tests, no behavior change.
+
+ * rendering/InlineIterator.h:
+ (WebCore::InlineBidiResolver::appendRun):
+ * rendering/LineWidth.cpp:
+ (WebCore::LineWidth::LineWidth):
+ * rendering/LineWidth.h:
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::styleWillChange):
+ (WebCore::RenderBlock::styleDidChange):
+ (WebCore::RenderBlock::splitFlow):
+ (WebCore::RenderBlock::deleteLineBoxTree):
+ (WebCore::RenderBlock::removeChild):
+ (WebCore::RenderBlock::computeOverflow):
+ (WebCore::RenderBlock::selectionGaps):
+ (WebCore::RenderBlock::adjustForBorderFit):
+ * rendering/RenderBlock.h:
+ (WebCore::RenderBlock::containsFloats):
+ (WebCore::RenderBlock::shouldSkipCreatingRunsForObject):
+ (WebCore::RenderBlock::addOverflowFromFloats):
+ (WebCore::RenderBlock::logicalRightFloatOffsetForLine):
+ (WebCore::RenderBlock::logicalLeftFloatOffsetForLine):
+ (WebCore::RenderBlock::moveAllChildrenOnRemovalTo):
+ (WebCore::RenderBlock::paintFloats):
+ (WebCore::RenderBlock::hitTestFloats):
+ (WebCore::RenderBlock::clipOutFloatingObjects):
+ * rendering/RenderBlockFlow.cpp:
+ (WebCore::RenderBlockFlow::clearFloats):
+ (WebCore::RenderBlockFlow::layoutBlock):
+ (WebCore::RenderBlockFlow::layoutBlockChild):
+ (WebCore::RenderBlockFlow::collapseMargins):
+ (WebCore::RenderBlockFlow::clearFloatsIfNeeded):
+ (WebCore::RenderBlockFlow::adjustBlockChildForPagination):
+ (WebCore::RenderBlockFlow::containsFloat):
+ (WebCore::RenderBlockFlow::styleDidChange):
+ (WebCore::RenderBlockFlow::styleWillChange):
+ (WebCore::RenderBlockFlow::deleteLineBoxTree):
+ (WebCore::RenderBlockFlow::moveAllChildrenOnRemovalTo):
+ (WebCore::RenderBlockFlow::addOverflowFromFloats):
+ (WebCore::RenderBlockFlow::computeOverflow):
+ (WebCore::RenderBlockFlow::repaintOverhangingFloats):
+ (WebCore::RenderBlockFlow::paintFloats):
+ (WebCore::RenderBlockFlow::clipOutFloatingObjects):
+ (WebCore::RenderBlockFlow::createFloatingObjects):
+ (WebCore::RenderBlockFlow::removeFloatingObjects):
+ (WebCore::RenderBlockFlow::insertFloatingObject):
+ (WebCore::RenderBlockFlow::removeFloatingObject):
+ (WebCore::RenderBlockFlow::removeFloatingObjectsBelow):
+ (WebCore::RenderBlockFlow::computeLogicalLocationForFloat):
+ (WebCore::RenderBlockFlow::positionNewFloats):
+ (WebCore::RenderBlockFlow::newLine):
+ (WebCore::RenderBlockFlow::logicalLeftFloatOffsetForLine):
+ (WebCore::RenderBlockFlow::logicalRightFloatOffsetForLine):
+ (WebCore::RenderBlockFlow::nextFloatLogicalBottomBelow):
+ (WebCore::RenderBlockFlow::lowestFloatLogicalBottom):
+ (WebCore::RenderBlockFlow::addOverhangingFloats):
+ (WebCore::RenderBlockFlow::hasOverhangingFloat):
+ (WebCore::RenderBlockFlow::addIntrudingFloats):
+ (WebCore::RenderBlockFlow::markAllDescendantsWithFloatsForLayout):
+ (WebCore::RenderBlockFlow::markSiblingsWithFloatsForLayout):
+ (WebCore::RenderBlockFlow::getClearDelta):
+ (WebCore::RenderBlockFlow::hitTestFloats):
+ (WebCore::RenderBlockFlow::adjustForBorderFit):
+ * rendering/RenderBlockFlow.h:
+ (WebCore::RenderBlockFlow::hasOverhangingFloats):
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::LineBreaker::LineBreaker):
+ (WebCore::RenderBlockFlow::appendRunsForObject):
+ (WebCore::RenderBlockFlow::createLineBoxes):
+ (WebCore::RenderBlockFlow::constructLine):
+ (WebCore::RenderBlockFlow::setMarginsForRubyRun):
+ (WebCore::updateLogicalInlinePositions):
+ (WebCore::RenderBlockFlow::computeInlineDirectionPositionsForLine):
+ (WebCore::RenderBlockFlow::computeInlineDirectionPositionsForSegment):
+ (WebCore::RenderBlockFlow::computeBlockDirectionPositionsForLine):
+ (WebCore::setStaticPositions):
+ (WebCore::RenderBlockFlow::handleTrailingSpaces):
+ (WebCore::RenderBlockFlow::appendFloatingObjectToLastLine):
+ (WebCore::constructBidiRunsForLine):
+ (WebCore::RenderBlockFlow::createLineBoxesFromBidiRuns):
+ (WebCore::RenderBlockFlow::layoutRunsAndFloats):
+ (WebCore::RenderBlockFlow::restartLayoutRunsAndFloatsInRange):
+ (WebCore::pushShapeContentOverflowBelowTheContentBox):
+ (WebCore::RenderBlockFlow::updateShapeAndSegmentsForCurrentLine):
+ (WebCore::RenderBlockFlow::updateShapeAndSegmentsForCurrentLineInFlowThread):
+ (WebCore::RenderBlockFlow::adjustLogicalLineTopAndLogicalHeightIfNeeded):
+ (WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange):
+ (WebCore::RenderBlockFlow::linkToEndLineIfNeeded):
+ (WebCore::RenderBlockFlow::repaintDirtyFloats):
+ (WebCore::RenderBlockFlow::checkFloatsInCleanLine):
+ (WebCore::RenderBlockFlow::determineStartPosition):
+ (WebCore::RenderBlockFlow::determineEndPosition):
+ (WebCore::RenderBlockFlow::checkPaginationAndFloatsAtEndLine):
+ (WebCore::RenderBlockFlow::matchedEndLine):
+ (WebCore::shouldSkipWhitespaceAfterStartObject):
+ (WebCore::updateSegmentsForShapes):
+ (WebCore::RenderBlockFlow::deleteEllipsisLineBoxes):
+ (WebCore::RenderBlockFlow::checkLinesForTextOverflow):
+ (WebCore::RenderBlockFlow::positionNewFloatOnLine):
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::outermostBlockContainingFloatingObject):
+ (WebCore::RenderBox::removeFloatingOrPositionedChildFromBlockLists):
+ * rendering/RenderBox.h:
+ * rendering/RenderBoxModelObject.cpp:
+ (WebCore::RenderBoxModelObject::moveChildrenTo):
+ * rendering/RenderInline.cpp:
+ (WebCore::RenderInline::splitFlow):
+
2013-10-08 Dean Jackson <dino@apple.com>
Support unprefixed WebGL context creation
#define InlineIterator_h
#include "BidiRun.h"
-#include "RenderBlock.h"
+#include "RenderBlockFlow.h"
#include "RenderInline.h"
#include "RenderText.h"
#include <wtf/StdLibExtras.h>
if (isolateTracker.inIsolate())
isolateTracker.addFakeRunIfNecessary(obj, start, *this);
else
- RenderBlock::appendRunsForObject(m_runs, start, obj->length(), obj, *this);
+ RenderBlockFlow::appendRunsForObject(m_runs, start, obj->length(), obj, *this);
// FIXME: start/obj should be an InlineIterator instead of two separate variables.
start = 0;
obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracker);
if (isolateTracker.inIsolate())
isolateTracker.addFakeRunIfNecessary(obj, start, *this);
else
- RenderBlock::appendRunsForObject(m_runs, start, end, obj, *this);
+ RenderBlockFlow::appendRunsForObject(m_runs, start, end, obj, *this);
}
m_eor.increment();
#include "config.h"
#include "LineWidth.h"
-#include "RenderBlock.h"
+#include "RenderBlockFlow.h"
#include "RenderRubyRun.h"
namespace WebCore {
-LineWidth::LineWidth(RenderBlock& block, bool isFirstLine, IndentTextOrNot shouldIndentText)
+LineWidth::LineWidth(RenderBlockFlow& block, bool isFirstLine, IndentTextOrNot shouldIndentText)
: m_block(block)
, m_uncommittedWidth(0)
, m_committedWidth(0)
namespace WebCore {
class FloatingObject;
-class RenderBlock;
+class RenderBlockFlow;
class RenderObject;
class RenderRubyRun;
class LineWidth {
public:
- LineWidth(RenderBlock&, bool isFirstLine, IndentTextOrNot shouldIndentText);
+ LineWidth(RenderBlockFlow&, bool isFirstLine, IndentTextOrNot shouldIndentText);
bool fitsOnLine(bool ignoringTrailingSpace = false) const;
bool fitsOnLineIncludingExtraWidth(float extra) const;
void computeAvailableWidthFromLeftAndRight();
bool fitsOnLineExcludingTrailingCollapsedWhitespace() const;
- RenderBlock& m_block;
+ RenderBlockFlow& m_block;
float m_uncommittedWidth;
float m_committedWidth;
float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
using namespace HTMLNames;
struct SameSizeAsRenderBlock : public RenderBox {
- void* pointers[2];
+ void* pointers[1];
RenderLineBoxList lineBoxes;
uint32_t bitfields;
};
static bool gColumnFlowSplitEnabled = true;
-bool RenderBlock::s_canPropagateFloatIntoSibling = false;
-
// This class helps dispatching the 'overflow' event on layout change. overflow can be set on RenderBoxes, yet the existing code
// only works on RenderBlocks. If this change, this class should be shared with other RenderBoxes.
class OverflowEventDispatcher {
void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
RenderStyle* oldStyle = style();
- s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
setReplaced(newStyle->isDisplayInlineType());
if (cb->isRenderBlock())
toRenderBlock(cb)->removePositionedObjects(this, NewContainingBlock);
}
-
- if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
- markAllDescendantsWithFloatsForLayout();
}
RenderBox::styleWillChange(diff, newStyle);
propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
m_lineHeight = -1;
-
- // After our style changed, if we lose our ability to propagate floats into next sibling
- // blocks, then we need to find the top most parent containing that overhanging float and
- // then mark its descendants with floats for layout and clear all floats from its next
- // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
- bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
- if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
- RenderBlock* parentBlock = this;
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
-
- for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
- if (curr->isRenderBlock()) {
- RenderBlock* currBlock = toRenderBlock(curr);
-
- if (currBlock->hasOverhangingFloats()) {
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- RenderBox& renderer = (*it)->renderer();
- if (currBlock->hasOverhangingFloat(&renderer)) {
- parentBlock = currBlock;
- break;
- }
- }
- }
- }
- }
-
- parentBlock->markAllDescendantsWithFloatsForLayout();
- parentBlock->markSiblingsWithFloatsForLayout();
- }
// It's possible for our border/padding to change, but for the overall logical width of the block to
// end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
// We can reuse this block and make it the preBlock of the next continuation.
pre = block;
pre->removePositionedObjects(0);
- pre->removeFloatingObjects();
+ // FIXME-BLOCKFLOW remove this when splitFlow is moved to RenderBlockFlow.
+ if (pre->isRenderBlockFlow())
+ toRenderBlockFlow(pre)->removeFloatingObjects();
block = toRenderBlock(block->parent());
} else {
// No anonymous block available for use. Make one.
void RenderBlock::deleteLineBoxTree()
{
- if (containsFloats())
- m_floatingObjects->clearLineBoxTreePointers();
m_lineBoxes.deleteLineBoxTree(renderArena());
if (AXObjectCache* cache = document().existingAXObjectCache())
child->destroy();
}
-void RenderBlock::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert)
-{
- moveAllChildrenTo(toBlock, fullRemoveInsert);
-
- // When a portion of the render tree is being detached, anonymous blocks
- // will be combined as their children are deleted. In this process, the
- // anonymous block later in the tree is merged into the one preceeding it.
- // It can happen that the later block (this) contains floats that the
- // previous block (toBlock) did not contain, and thus are not in the
- // floating objects list for toBlock. This can result in toBlock containing
- // floats that are not in it's floating objects list, but are in the
- // floating objects lists of siblings and parents. This can cause problems
- // when the float itself is deleted, since the deletion code assumes that
- // if a float is not in it's containing block's floating objects list, it
- // isn't in any floating objects list. In order to preserve this condition
- // (removing it has serious performance implications), we need to copy the
- // floating objects from the old block (this) to the new block (toBlock).
- // The float's metrics will likely all be wrong, but since toBlock is
- // already marked for layout, this will get fixed before anything gets
- // displayed.
- // See bug https://bugs.webkit.org/show_bug.cgi?id=115566
- if (m_floatingObjects) {
- if (!toBlock->m_floatingObjects)
- toBlock->createFloatingObjects();
-
- const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set();
- auto end = fromFloatingObjectSet.end();
-
- for (auto it = fromFloatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = it->get();
-
- // Don't insert the object again if it's already in the list
- if (toBlock->containsFloat(&floatingObject->renderer()))
- continue;
-
- toBlock->m_floatingObjects->add(floatingObject->unsafeClone());
- }
- }
-}
-
void RenderBlock::removeChild(RenderObject* oldChild)
{
// No need to waste time in merging or removing empty anonymous blocks.
}
}
-void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
+void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool)
{
clearOverflow();
// Add overflow from children.
addOverflowFromChildren();
- if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
- addOverflowFromFloats();
-
// Add in the overflow from positioned objects.
addOverflowFromPositionedObjects();
}
}
-void RenderBlock::addOverflowFromFloats()
-{
- if (!m_floatingObjects)
- return;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- if (r->isDescendant())
- addOverflowFromChild(&r->renderer(), IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
- }
-}
-
void RenderBlock::addOverflowFromPositionedObjects()
{
TrackedRendererListHashSet* positionedDescendants = positionedObjects();
setChildNeedsLayout(MarkOnlyThis);
}
-void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
-{
- // Repaint any overhanging floats (if we know we're the one to paint them).
- // Otherwise, bail out.
- if (!hasOverhangingFloats())
- return;
-
- // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
- // in this block. Better yet would be to push extra state for the containers of other floats.
- LayoutStateDisabler layoutStateDisabler(&view());
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- // Only repaint the object if it is overhanging, is not in its own layer, and
- // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
- // condition is replaced with being a descendant of us.
- if (r->logicalBottom(isHorizontalWritingMode()) > logicalHeight()
- && !r->renderer().hasSelfPaintingLayer()
- && (r->shouldPaint() || (paintAllDescendants && r->renderer().isDescendantOf(this)))) {
- r->renderer().repaint();
- r->renderer().repaintOverhangingFloats(false);
- }
- }
-}
-
void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
LayoutPoint adjustedPaintOffset = paintOffset + location();
return LayoutPoint(point.x() + width() - child->renderer().width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
}
-void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
-{
- if (!m_floatingObjects)
- return;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- // Only paint the object if our m_shouldPaint flag is set.
- if (r->shouldPaint() && !r->renderer().hasSelfPaintingLayer()) {
- PaintInfo currentPaintInfo(paintInfo);
- currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
- // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner.
- LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->renderer().x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->renderer().y()));
- r->renderer().paint(currentPaintInfo, childPoint);
- if (!preservePhase) {
- currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
- r->renderer().paint(currentPaintInfo, childPoint);
- currentPaintInfo.phase = PaintPhaseFloat;
- r->renderer().paint(currentPaintInfo, childPoint);
- currentPaintInfo.phase = PaintPhaseForeground;
- r->renderer().paint(currentPaintInfo, childPoint);
- currentPaintInfo.phase = PaintPhaseOutline;
- r->renderer().paint(currentPaintInfo, childPoint);
- }
- }
- }
-}
-
RenderInline* RenderBlock::inlineElementContinuation() const
{
RenderBoxModelObject* continuation = this->continuation();
if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
- if (m_floatingObjects) {
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
- offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
- r->renderer().width(), r->renderer().height());
- rootBlock->flipForWritingMode(floatBox);
- floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
- paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
- }
- }
+ clipOutFloatingObjects(rootBlock, paintInfo, rootBlockPhysicalPosition, offsetFromRootBlock);
}
// FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
removePositionedObject(deadObjects.at(i));
}
-void RenderBlock::removeFloatingObjects()
-{
- if (!m_floatingObjects)
- return;
-
- m_floatingObjects->clear();
-}
-
-FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
-{
- ASSERT(o->isFloating());
-
- // Create the list of special objects if we don't aleady have one
- if (!m_floatingObjects)
- createFloatingObjects();
- else {
- // Don't insert the object again if it's already in the list
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*o);
- if (it != floatingObjectSet.end())
- return it->get();
- }
-
- // Create the special object entry & append it to the list
-
- std::unique_ptr<FloatingObject> object = FloatingObject::create(*o);
-
- // Our location is irrelevant if we're unsplittable or no pagination is in effect.
- // Just go ahead and lay out the float.
- bool isChildRenderBlock = o->isRenderBlock();
- if (isChildRenderBlock && !o->needsLayout() && view().layoutState()->pageLogicalHeightChanged())
- o->setChildNeedsLayout(MarkOnlyThis);
-
- bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
- if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
- o->layoutIfNeeded();
- else {
- o->updateLogicalWidth();
- o->computeAndSetBlockDirectionMargins(this);
- }
-
- object->setLogicalWidth(logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o), isHorizontalWritingMode());
-
-#if ENABLE(CSS_SHAPES)
- if (ShapeOutsideInfo* shapeOutside = o->shapeOutsideInfo())
- shapeOutside->setShapeSize(logicalWidthForChild(o), logicalHeightForChild(o));
-#endif
-
- return m_floatingObjects->add(std::move(object));
-}
-
-void RenderBlock::removeFloatingObject(RenderBox* o)
-{
- if (m_floatingObjects) {
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*o);
- if (it != floatingObjectSet.end()) {
- FloatingObject* r = it->get();
- if (childrenInline()) {
- LayoutUnit logicalTop = r->logicalTop(isHorizontalWritingMode());
- LayoutUnit logicalBottom = r->logicalBottom(isHorizontalWritingMode());
-
- // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
- if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == LayoutUnit::max())
- logicalBottom = LayoutUnit::max();
- else {
- // Special-case zero- and less-than-zero-height floats: those don't touch
- // the line that they're on, but it still needs to be dirtied. This is
- // accomplished by pretending they have a height of 1.
- logicalBottom = max(logicalBottom, logicalTop + 1);
- }
- if (r->originatingLine()) {
- if (!selfNeedsLayout()) {
- ASSERT(&r->originatingLine()->renderer() == this);
- r->originatingLine()->markDirty();
- }
-#if !ASSERT_DISABLED
- r->setOriginatingLine(0);
-#endif
- }
- markLinesDirtyInBlockRange(0, logicalBottom);
- }
- m_floatingObjects->remove(r);
- }
- }
-}
-
-void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
-{
- if (!containsFloats())
- return;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- FloatingObject* curr = floatingObjectSet.last().get();
- while (curr != lastFloat && (!curr->isPlaced() || curr->logicalTop(isHorizontalWritingMode()) >= logicalOffset)) {
- m_floatingObjects->remove(curr);
- if (floatingObjectSet.isEmpty())
- break;
- curr = floatingObjectSet.last().get();
- }
-}
-
-LayoutPoint RenderBlock::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
-{
- RenderBox* childBox = &floatingObject->renderer();
- LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
- LayoutUnit logicalRightOffset; // Constant part of right offset.
-#if ENABLE(CSS_SHAPES)
- // FIXME Bug 102948: This only works for shape outside directly set on this block.
- ShapeInsideInfo* shapeInsideInfo = this->layoutShapeInsideInfo();
- // FIXME: Implement behavior for right floats.
- if (shapeInsideInfo) {
- LayoutSize floatLogicalSize = LayoutSize(childBox->logicalWidth(), childBox->logicalHeight());
- // FIXME: If the float doesn't fit in the shape we should push it under the content box
- logicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(floatLogicalSize);
- if (logicalHeight() > logicalTopOffset)
- logicalTopOffset = logicalHeight();
-
- SegmentList segments = shapeInsideInfo->computeSegmentsForLine(logicalTopOffset, childBox->logicalHeight());
- // FIXME Bug 102949: Add support for shapes with multiple segments.
- if (segments.size() == 1) {
- // The segment offsets are relative to the content box.
- logicalRightOffset = logicalLeftOffset + segments[0].logicalRight;
- logicalLeftOffset += segments[0].logicalLeft;
- }
- } else
-#endif
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset);
-
- LayoutUnit floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset); // The width we look for.
-
- LayoutUnit floatLogicalLeft;
-
- bool insideFlowThread = flowThreadContainingBlock();
-
- if (childBox->style()->floating() == LeftFloat) {
- LayoutUnit heightRemainingLeft = 1;
- LayoutUnit heightRemainingRight = 1;
- floatLogicalLeft = logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
- while (logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
- logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
- floatLogicalLeft = logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
- if (insideFlowThread) {
- // Have to re-evaluate all of our offsets, since they may have changed.
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
- logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
- floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset);
- }
- }
- floatLogicalLeft = max(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft);
- } else {
- LayoutUnit heightRemainingLeft = 1;
- LayoutUnit heightRemainingRight = 1;
- floatLogicalLeft = logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
- while (floatLogicalLeft - logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
- logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
- floatLogicalLeft = logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
- if (insideFlowThread) {
- // Have to re-evaluate all of our offsets, since they may have changed.
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
- logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
- floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset);
- }
- }
- floatLogicalLeft -= floatingObject->logicalWidth(isHorizontalWritingMode()); // Use the original width of the float here, since the local variable
- // |floatLogicalWidth| was capped to the available line width.
- // See fast/block/float/clamped-right-float.html.
- }
-
- return LayoutPoint(floatLogicalLeft, logicalTopOffset);
-}
-
-bool RenderBlock::positionNewFloats()
-{
- if (!m_floatingObjects)
- return false;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- if (floatingObjectSet.isEmpty())
- return false;
-
- // If all floats have already been positioned, then we have no work to do.
- if (floatingObjectSet.last()->isPlaced())
- return false;
-
- // Move backwards through our floating object list until we find a float that has
- // already been positioned. Then we'll be able to move forward, positioning all of
- // the new floats that need it.
- auto it = floatingObjectSet.end();
- --it; // Go to last item.
- auto begin = floatingObjectSet.begin();
- FloatingObject* lastPlacedFloatingObject = 0;
- while (it != begin) {
- --it;
- if ((*it)->isPlaced()) {
- lastPlacedFloatingObject = it->get();
- ++it;
- break;
- }
- }
-
- LayoutUnit logicalTop = logicalHeight();
-
- // The float cannot start above the top position of the last positioned float.
- if (lastPlacedFloatingObject)
- logicalTop = max(lastPlacedFloatingObject->logicalTop(isHorizontalWritingMode()), logicalTop);
-
- auto end = floatingObjectSet.end();
- // Now walk through the set of unpositioned floats and place them.
- for (; it != end; ++it) {
- FloatingObject* floatingObject = it->get();
- // The containing block is responsible for positioning floats, so if we have floats in our
- // list that come from somewhere else, do not attempt to position them.
- if (floatingObject->renderer().containingBlock() != this)
- continue;
-
- RenderBox* childBox = &floatingObject->renderer();
-
- LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
-
- LayoutRect oldRect = childBox->frameRect();
-
- if (childBox->style()->clear() & CLEFT)
- logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
- if (childBox->style()->clear() & CRIGHT)
- logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
-
- LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop);
-
- floatingObject->setLogicalLeft(floatLogicalLocation.x(), isHorizontalWritingMode());
-
- setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
- setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
-
- estimateRegionRangeForBoxChild(childBox);
-
- LayoutState* layoutState = view().layoutState();
- bool isPaginated = layoutState->isPaginated();
- if (isPaginated && !childBox->needsLayout())
- childBox->markForPaginationRelayoutIfNeeded();
-
- childBox->layoutIfNeeded();
-
- if (isPaginated) {
- // If we are unsplittable and don't fit, then we need to move down.
- // We include our margins as part of the unsplittable area.
- LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true);
-
- // See if we have a pagination strut that is making us move down further.
- // Note that an unsplittable child can't also have a pagination strut, so this is
- // exclusive with the case above.
- RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
- if (childBlock && childBlock->paginationStrut()) {
- newLogicalTop += childBlock->paginationStrut();
- childBlock->setPaginationStrut(0);
- }
-
- if (newLogicalTop != floatLogicalLocation.y()) {
- floatingObject->setPaginationStrut(newLogicalTop - floatLogicalLocation.y());
-
- floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop);
- floatingObject->setLogicalLeft(floatLogicalLocation.x(), isHorizontalWritingMode());
-
- setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
- setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
-
- if (childBlock)
- childBlock->setChildNeedsLayout(MarkOnlyThis);
- childBox->layoutIfNeeded();
- }
-
- if (updateRegionRangeForBoxChild(childBox)) {
- childBox->setNeedsLayout(MarkOnlyThis);
- childBox->layoutIfNeeded();
- }
- }
-
- floatingObject->setLogicalTop(floatLogicalLocation.y(), isHorizontalWritingMode());
-
- floatingObject->setLogicalHeight(logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox), isHorizontalWritingMode());
-
- m_floatingObjects->addPlacedObject(floatingObject);
-
- // If the child moved, we have to repaint it.
- if (childBox->checkForRepaintDuringLayout())
- childBox->repaintDuringLayoutIfMoved(oldRect);
- }
- return true;
-}
-
-void RenderBlock::newLine(EClear clear)
-{
- positionNewFloats();
- // set y position
- LayoutUnit newY = 0;
- switch (clear)
- {
- case CLEFT:
- newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
- break;
- case CRIGHT:
- newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
- break;
- case CBOTH:
- newY = lowestFloatLogicalBottom();
- default:
- break;
- }
- if (height() < newY)
- setLogicalHeight(newY);
-}
-
void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
{
insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
}
-LayoutUnit RenderBlock::logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
-{
- if (m_floatingObjects && m_floatingObjects->hasLeftObjects())
- return m_floatingObjects->logicalLeftOffset(fixedOffset, logicalTop, logicalHeight, offsetMode, heightRemaining);
-
- return fixedOffset;
-}
-
LayoutUnit RenderBlock::adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
{
LayoutUnit left = offsetFromFloats;
return left;
}
-LayoutUnit RenderBlock::logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
-{
- if (m_floatingObjects && m_floatingObjects->hasRightObjects())
- return m_floatingObjects->logicalRightOffset(fixedOffset, logicalTop, logicalHeight, offsetMode, heightRemaining);
-
- return fixedOffset;
-}
-
LayoutUnit RenderBlock::adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
{
LayoutUnit right = offsetFromFloats;
return right;
}
-LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
-{
- if (!m_floatingObjects)
- return logicalHeight;
-
- LayoutUnit bottom = LayoutUnit::max();
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- LayoutUnit floatBottom;
-#if ENABLE(CSS_SHAPES)
- ShapeOutsideInfo* shapeOutside = r->renderer().shapeOutsideInfo();
- if (offsetMode == ShapeOutsideFloatShapeOffset && shapeOutside)
- floatBottom = r->logicalTop(isHorizontalWritingMode()) + marginBeforeForChild(&(r->renderer())) + shapeOutside->shapeLogicalBottom();
- else
-#endif
- floatBottom = r->logicalBottom(isHorizontalWritingMode());
- if (floatBottom > logicalHeight)
- bottom = min(floatBottom, bottom);
- }
-
- return bottom == LayoutUnit::max() ? LayoutUnit() : bottom;
-}
-
-LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
-{
- if (!m_floatingObjects)
- return 0;
- LayoutUnit lowestFloatBottom = 0;
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- if (r->isPlaced() && r->type() & floatType)
- lowestFloatBottom = max(lowestFloatBottom, r->logicalBottom(isHorizontalWritingMode()));
- }
- return lowestFloatBottom;
-}
-
void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest)
{
if (logicalTop >= logicalBottom)
}
}
-LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats)
-{
- // Prevent floats from being added to the canvas by the root element, e.g., <html>.
- if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
- return 0;
-
- LayoutUnit childLogicalTop = child->logicalTop();
- LayoutUnit childLogicalLeft = child->logicalLeft();
- LayoutUnit lowestFloatLogicalBottom = 0;
-
- // Floats that will remain the child's responsibility to paint should factor into its
- // overflow.
- auto childEnd = child->m_floatingObjects->set().end();
- for (auto childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
- FloatingObject* r = childIt->get();
- LayoutUnit logicalBottomForFloat = min(r->logicalBottom(isHorizontalWritingMode()), LayoutUnit::max() - childLogicalTop);
- LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
- lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
-
- if (logicalBottom > logicalHeight()) {
- // If the object is not in the list, we add it now.
- if (!containsFloat(&r->renderer())) {
- LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft);
- bool shouldPaint = false;
-
- // The nearest enclosing layer always paints the float (so that zindex and stacking
- // behaves properly). We always want to propagate the desire to paint the float as
- // far out as we can, to the outermost block that overlaps the float, stopping only
- // if we hit a self-painting layer boundary.
- if (r->renderer().enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer()) {
- r->setShouldPaint(false);
- shouldPaint = true;
- }
- // We create the floating object list lazily.
- if (!m_floatingObjects)
- createFloatingObjects();
-
- m_floatingObjects->add(r->copyToNewContainer(offset, shouldPaint, true));
- }
- } else {
- if (makeChildPaintOtherFloats && !r->shouldPaint() && !r->renderer().hasSelfPaintingLayer()
- && r->renderer().isDescendantOf(child) && r->renderer().enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
- // The float is not overhanging from this block, so if it is a descendant of the child, the child should
- // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
- // layer.
- // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
- // it should paint.
- r->setShouldPaint(true);
- }
-
- // Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the
- // child now.
- if (r->isDescendant())
- child->addOverflowFromChild(&r->renderer(), LayoutSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
- }
- }
- return lowestFloatLogicalBottom;
-}
-
-bool RenderBlock::hasOverhangingFloat(RenderBox* renderer)
-{
- if (!m_floatingObjects || hasColumns() || !parent())
- return false;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*renderer);
- if (it == floatingObjectSet.end())
- return false;
-
- return (*it)->logicalBottom(isHorizontalWritingMode()) > logicalHeight();
-}
-
-void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
-{
- ASSERT(!avoidsFloats());
-
- // If the parent or previous sibling doesn't have any floats to add, don't bother.
- if (!prev->m_floatingObjects)
- return;
-
- logicalLeftOffset += marginLogicalLeft();
-
- const FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
- auto prevEnd = prevSet.end();
- for (auto prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
- FloatingObject* r = prevIt->get();
- if (r->logicalBottom(isHorizontalWritingMode()) > logicalTopOffset) {
- if (!m_floatingObjects || !m_floatingObjects->set().contains<FloatingObject&, FloatingObjectHashTranslator>(*r)) {
- // We create the floating object list lazily.
- if (!m_floatingObjects)
- createFloatingObjects();
-
- // Applying the child's margin makes no sense in the case where the child was passed in.
- // since this margin was added already through the modification of the |logicalLeftOffset| variable
- // above. |logicalLeftOffset| will equal the margin in this case, so it's already been taken
- // into account. Only apply this code if prev is the parent, since otherwise the left margin
- // will get applied twice.
- LayoutSize offset = isHorizontalWritingMode()
- ? LayoutSize(logicalLeftOffset - (prev != parent() ? prev->marginLeft() : LayoutUnit()), logicalTopOffset)
- : LayoutSize(logicalTopOffset, logicalLeftOffset - (prev != parent() ? prev->marginTop() : LayoutUnit()));
-
- m_floatingObjects->add(r->copyToNewContainer(offset));
- }
- }
- }
-}
-
bool RenderBlock::avoidsFloats() const
{
// Floats can't intrude into our box if we have a non-auto column count or width.
return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
}
-bool RenderBlock::containsFloat(RenderBox* renderer) const
-{
- return m_floatingObjects && m_floatingObjects->set().contains<RenderBox&, FloatingObjectHashTranslator>(*renderer);
-}
-
-void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
-{
- if (!everHadLayout() && !containsFloats())
- return;
-
- MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain;
- setChildNeedsLayout(markParents);
-
- if (floatToRemove)
- removeFloatingObject(floatToRemove);
-
- // Iterate over our children and mark them as needed.
- if (!childrenInline()) {
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || !child->isRenderBlock())
- continue;
- RenderBlock* childBlock = toRenderBlock(child);
- if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
- childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
- }
- }
-}
-
-void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
-{
- if (!m_floatingObjects)
- return;
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
-
- for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) {
- if (!next->isRenderBlock() || next->isFloatingOrOutOfFlowPositioned() || toRenderBlock(next)->avoidsFloats())
- continue;
-
- RenderBlock* nextBlock = toRenderBlock(next);
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- RenderBox* floatingBox = &(*it)->renderer();
- if (floatToRemove && floatingBox != floatToRemove)
- continue;
- if (nextBlock->containsFloat(floatingBox))
- nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
- }
- }
-}
-
-LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
-{
- // There is no need to compute clearance if we have no floats.
- if (!containsFloats())
- return 0;
-
- // At least one float is present. We need to perform the clearance computation.
- bool clearSet = child->style()->clear() != CNONE;
- LayoutUnit logicalBottom = 0;
- switch (child->style()->clear()) {
- case CNONE:
- break;
- case CLEFT:
- logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
- break;
- case CRIGHT:
- logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
- break;
- case CBOTH:
- logicalBottom = lowestFloatLogicalBottom();
- break;
- }
-
- // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
- LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : LayoutUnit();
- if (!result && child->avoidsFloats()) {
- LayoutUnit newLogicalTop = logicalTop;
- while (true) {
- LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
- if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
- return newLogicalTop - logicalTop;
-
- RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child));
- LayoutRect borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
- LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
-
- // FIXME: None of this is right for perpendicular writing-mode children.
- LayoutUnit childOldLogicalWidth = child->logicalWidth();
- LayoutUnit childOldMarginLeft = child->marginLeft();
- LayoutUnit childOldMarginRight = child->marginRight();
- LayoutUnit childOldLogicalTop = child->logicalTop();
-
- child->setLogicalTop(newLogicalTop);
- child->updateLogicalWidth();
- region = regionAtBlockOffset(logicalTopForChild(child));
- borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
- LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
-
- child->setLogicalTop(childOldLogicalTop);
- child->setLogicalWidth(childOldLogicalWidth);
- child->setMarginLeft(childOldMarginLeft);
- child->setMarginRight(childOldMarginRight);
-
- if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) {
- // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then
- // we need to force a relayout as though we shifted. This happens because of the dynamic addition of overhanging floats
- // from previous siblings when negative margins exist on a child (see the addOverhangingFloats call at the end of collapseMargins).
- if (childLogicalWidthAtOldLogicalTopOffset != childLogicalWidthAtNewLogicalTopOffset)
- child->setChildNeedsLayout(MarkOnlyThis);
- return newLogicalTop - logicalTop;
- }
-
- newLogicalTop = nextFloatLogicalBottomBelow(newLogicalTop);
- ASSERT(newLogicalTop >= logicalTop);
- if (newLogicalTop < logicalTop)
- break;
- }
- ASSERT_NOT_REACHED();
- }
- return result;
-}
-
bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
{
if (!scrollsOverflow())
return false;
}
-bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
-{
- if (!m_floatingObjects)
- return false;
-
- LayoutPoint adjustedLocation = accumulatedOffset;
- if (isRenderView())
- adjustedLocation += toLayoutSize(toRenderView(*this).frameView().scrollPosition());
-
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto begin = floatingObjectSet.begin();
- for (auto it = floatingObjectSet.end(); it != begin;) {
- --it;
- FloatingObject* floatingObject = it->get();
- if (floatingObject->shouldPaint() && !floatingObject->renderer().hasSelfPaintingLayer()) {
- LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer().x();
- LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer().y();
- LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
- if (floatingObject->renderer().hitTest(request, result, locationInContainer, childPoint)) {
- updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint));
- return true;
- }
- }
- }
-
- return false;
-}
-
class ColumnRectIterator {
WTF_MAKE_NONCOPYABLE(ColumnRectIterator);
public:
else {
for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
if (!obj->isFloatingOrOutOfFlowPositioned()) {
- if (obj->isRenderBlockFlow() && !obj->hasOverflowClip())
+ if (obj->isRenderBlock() && !obj->hasOverflowClip())
toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), left, right);
else if (obj->style()->visibility() == VISIBLE) {
// We are a replaced element or some kind of non-block-flow object.
}
}
}
-
- if (m_floatingObjects) {
- const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- auto end = floatingObjectSet.end();
- for (auto it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* r = it->get();
- // Only examine the object if our m_shouldPaint flag is set.
- if (r->shouldPaint()) {
- LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->renderer().x();
- LayoutUnit floatRight = floatLeft + r->renderer().width();
- left = min(left, floatLeft);
- right = max(right, floatRight);
- }
- }
- }
}
}
return "RenderBlock";
}
-void RenderBlock::createFloatingObjects()
-{
- m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
-}
-
template <typename CharacterType>
static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
{
struct BidiRun;
struct PaintInfo;
-class LineBreaker;
class LineInfo;
class RenderRubyRun;
#if ENABLE(CSS_SHAPES)
InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
- void deleteLineBoxTree();
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual void deleteLineBoxTree();
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
static void removePositionedObject(RenderBox*);
void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
- void removeFloatingObjects();
-
TrackedRendererListHashSet* positionedObjects() const;
bool hasPositionedObjects() const
{
bool generatesLineBoxesForInlineChild(RenderObject*);
- void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
- void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
void markPositionedObjectsForLayout();
virtual void markForPaginationRelayoutIfNeeded() OVERRIDE FINAL;
- bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
- bool containsFloat(RenderBox*) const;
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all of the line layout code has been moved out of RenderBlock
+ virtual bool containsFloats() const { return false; }
// Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to
// compute the region all over again when you already know it.
{
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&, const String&, const RenderStyle&,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
void setDesiredColumnCountAndWidth(int, LayoutUnit);
public:
- void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
+ virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
void clearLayoutOverflow();
protected:
virtual void addOverflowFromChildren();
- void addOverflowFromFloats();
void addOverflowFromPositionedObjects();
void addOverflowFromBlockChildren();
void addOverflowFromInlineChildren();
virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
private:
- LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const;
- LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const;
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit, LayoutUnit fixedOffset, LayoutUnit*, LayoutUnit, ShapeOutsideFloatOffsetMode) const { return fixedOffset; };
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit, LayoutUnit fixedOffset, LayoutUnit*, LayoutUnit, ShapeOutsideFloatOffsetMode) const { return fixedOffset; }
LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
void makeChildrenNonInline(RenderObject* insertionPoint = 0);
virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
- void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) { moveAllChildrenTo(toBlock, fullRemoveInsert); }
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild) OVERRIDE;
virtual bool isSelfCollapsingBlock() const OVERRIDE FINAL;
- virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
-
- BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
-
void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
return child->y() + child->renderer().marginTop();
}
- LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
-
- 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();
-
- // Positions new floats and also adjust all floats encountered on the line if any of them
- // have to move to the next page/column.
- bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
- void appendFloatingObjectToLastLine(FloatingObject*);
-
- // End of functions defined in RenderBlockLineLayout.cpp.
-
- void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false);
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool) { }
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);
-
- // Called from lineWidth, to position the floats added in the last line.
- // Returns true if and only if it has positioned any floats.
- bool positionNewFloats();
-
- LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
-
virtual bool avoidsFloats() const OVERRIDE;
- 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, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
-
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);
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&) { return false; }
virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
+ // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
+ virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) { };
friend class LogicalSelectionOffsetCaches;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE;
void adjustPointToColumnContents(LayoutPoint&) const;
void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
- void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
+ virtual void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
- void newLine(EClear);
-
Position positionForBox(InlineBox*, bool start = true) const;
VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&);
void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
void moveRunInToOriginalPosition(RenderObject* runIn);
- // Helper function for layoutInlineChildren()
- 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*&, const LayoutSize&, 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();
// FIXME: This is temporary to allow us to move code from RenderBlock into RenderBlockFlow that accesses member variables that we haven't moved out of
// RenderBlock yet.
friend class RenderBlockFlow;
-
-protected:
- void createFloatingObjects();
+ // FIXME-BLOCKFLOW: Remove this when the line layout stuff has all moved out of RenderBlock
+ friend class LineBreaker;
public:
// Allocated only when some of these fields have non-default values
protected:
- OwnPtr<FloatingObjects> m_floatingObjects;
OwnPtr<RenderBlockRareData> m_rareData;
RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
// RenderRubyBase objects need to be able to split and merge, moving their children around
// (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
friend class RenderRubyBase;
- friend class LineBreaker;
- friend class LineWidth; // Needs to know FloatingObject
private:
// Used to store state between styleWillChange and styleDidChange
#include "RenderBlockFlow.h"
#include "FloatingObjects.h"
+#include "HitTestLocation.h"
#include "LayoutRepainter.h"
#include "RenderFlowThread.h"
#include "RenderLayer.h"
namespace WebCore {
+bool RenderBlock::s_canPropagateFloatIntoSibling = false;
+
struct SameSizeAsMarginInfo {
uint32_t bitfields : 16;
LayoutUnit margins[2];
// We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add
// floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
// See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
- if (!parent() || !parent()->isRenderBlock())
+ if (!parent() || !parent()->isRenderBlockFlow())
return;
// Attempt to locate a previous sibling with overhanging floats. We skip any elements that are
// out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
// to avoid floats.
- RenderBlock* parentBlock = toRenderBlock(parent());
+ RenderBlockFlow* parentBlock = toRenderBlockFlow(parent());
bool parentHasFloats = false;
RenderObject* prev = previousSibling();
- while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
+ while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlockFlow() || toRenderBlockFlow(prev)->avoidsFloats())) {
if (prev->isFloating())
parentHasFloats = true;
prev = prev->previousSibling();
}
// Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
- RenderBlock* block = toRenderBlock(prev);
+ RenderBlockFlow* block = toRenderBlockFlow(prev);
if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
// One of our children's floats may have become an overhanging float for us. We need to look for it.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) {
- RenderBlock* block = toRenderBlock(child);
+ RenderBlockFlow* block = toRenderBlockFlow(child);
if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
addOverhangingFloats(block, false);
}
// If the child has overhanging floats that intrude into following siblings (or possibly out
// of this block), then the parent gets notified of the floats now.
if (childBlockFlow && childBlockFlow->containsFloats())
- maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
+ maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlockFlow(child), !childNeededLayout));
if (childOffset.width() || childOffset.height()) {
view().addLayoutDelta(childOffset);
setLogicalHeight(logicalTop);
RenderObject* prev = child->previousSibling();
if (prev && prev->isRenderBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
- RenderBlock* block = toRenderBlock(prev);
+ RenderBlockFlow* block = toRenderBlockFlow(prev);
if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop)
addOverhangingFloats(block, false);
}
LayoutUnit logicalTop = yPos + heightIncrease;
// After margin collapsing, one of our floats may now intrude into the child. If the child doesn't contain floats of its own it
// won't get picked up for relayout even though the logical top estimate was wrong - so add the newly intruding float now.
- if (containsFloats() && child->isRenderBlock() && !toRenderBlock(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
- toRenderBlock(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
+ if (containsFloats() && child->isRenderBlockFlow() && !toRenderBlockFlow(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
+ toRenderBlockFlow(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
return logicalTop;
}
if (childRenderBlock) {
if (!child->avoidsFloats() && childRenderBlock->containsFloats())
- childRenderBlock->markAllDescendantsWithFloatsForLayout();
+ toRenderBlockFlow(childRenderBlock)->markAllDescendantsWithFloatsForLayout();
if (!child->needsLayout())
child->markForPaginationRelayoutIfNeeded();
}
// to this grid.
}
+bool RenderBlockFlow::containsFloat(RenderBox* renderer) const
+{
+ return m_floatingObjects && m_floatingObjects->set().contains<RenderBox&, FloatingObjectHashTranslator>(*renderer);
+}
+
+void RenderBlockFlow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderBlock::styleDidChange(diff, oldStyle);
+
+ // After our style changed, if we lose our ability to propagate floats into next sibling
+ // blocks, then we need to find the top most parent containing that overhanging float and
+ // then mark its descendants with floats for layout and clear all floats from its next
+ // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
+ bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
+ if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
+ RenderBlockFlow* parentBlock = this;
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+
+ for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
+ if (curr->isRenderBlockFlow()) {
+ RenderBlockFlow* currBlock = toRenderBlockFlow(curr);
+
+ if (currBlock->hasOverhangingFloats()) {
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ RenderBox& renderer = (*it)->renderer();
+ if (currBlock->hasOverhangingFloat(&renderer)) {
+ parentBlock = currBlock;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ parentBlock->markAllDescendantsWithFloatsForLayout();
+ parentBlock->markSiblingsWithFloatsForLayout();
+ }
+}
+
+void RenderBlockFlow::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+ RenderStyle* oldStyle = style();
+ s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
+
+ if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()) {
+ if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+ markAllDescendantsWithFloatsForLayout();
+ }
+
+ RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderBlockFlow::deleteLineBoxTree()
+{
+ if (containsFloats())
+ m_floatingObjects->clearLineBoxTreePointers();
+ RenderBlock::deleteLineBoxTree();
+}
+
+void RenderBlockFlow::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert)
+{
+ RenderBlockFlow* toBlockFlow = toRenderBlockFlow(toBlock);
+ moveAllChildrenTo(toBlockFlow, fullRemoveInsert);
+
+ // When a portion of the render tree is being detached, anonymous blocks
+ // will be combined as their children are deleted. In this process, the
+ // anonymous block later in the tree is merged into the one preceeding it.
+ // It can happen that the later block (this) contains floats that the
+ // previous block (toBlockFlow) did not contain, and thus are not in the
+ // floating objects list for toBlockFlow. This can result in toBlockFlow
+ // containing floats that are not in it's floating objects list, but are in
+ // the floating objects lists of siblings and parents. This can cause
+ // problems when the float itself is deleted, since the deletion code
+ // assumes that if a float is not in it's containing block's floating
+ // objects list, it isn't in any floating objects list. In order to
+ // preserve this condition (removing it has serious performance
+ // implications), we need to copy the floating objects from the old block
+ // (this) to the new block (toBlockFlow). The float's metrics will likely
+ // all be wrong, but since toBlockFlow is already marked for layout, this
+ // will get fixed before anything gets displayed.
+ // See bug https://bugs.webkit.org/show_bug.cgi?id=115566
+ if (m_floatingObjects) {
+ if (!toBlockFlow->m_floatingObjects)
+ toBlockFlow->createFloatingObjects();
+
+ const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set();
+ auto end = fromFloatingObjectSet.end();
+
+ for (auto it = fromFloatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+
+ // Don't insert the object again if it's already in the list
+ if (toBlockFlow->containsFloat(&floatingObject->renderer()))
+ continue;
+
+ toBlockFlow->m_floatingObjects->add(floatingObject->unsafeClone());
+ }
+ }
+}
+
+void RenderBlockFlow::addOverflowFromFloats()
+{
+ if (!m_floatingObjects)
+ return;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* r = it->get();
+ if (r->isDescendant())
+ addOverflowFromChild(&r->renderer(), IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
+ }
+}
+
+void RenderBlockFlow::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
+{
+ RenderBlock::computeOverflow(oldClientAfterEdge, recomputeFloats);
+
+ if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
+ addOverflowFromFloats();
+}
+
+void RenderBlockFlow::repaintOverhangingFloats(bool paintAllDescendants)
+{
+ // Repaint any overhanging floats (if we know we're the one to paint them).
+ // Otherwise, bail out.
+ if (!hasOverhangingFloats())
+ return;
+
+ // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
+ // in this block. Better yet would be to push extra state for the containers of other floats.
+ LayoutStateDisabler layoutStateDisabler(&view());
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+ // Only repaint the object if it is overhanging, is not in its own layer, and
+ // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
+ // condition is replaced with being a descendant of us.
+ if (floatingObject->logicalBottom(isHorizontalWritingMode()) > logicalHeight()
+ && !floatingObject->renderer().hasSelfPaintingLayer()
+ && (floatingObject->shouldPaint() || (paintAllDescendants && floatingObject->renderer().isDescendantOf(this)))) {
+ floatingObject->renderer().repaint();
+ floatingObject->renderer().repaintOverhangingFloats(false);
+ }
+ }
+}
+
+void RenderBlockFlow::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
+{
+ if (!m_floatingObjects)
+ return;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* r = it->get();
+ // Only paint the object if our m_shouldPaint flag is set.
+ if (r->shouldPaint() && !r->renderer().hasSelfPaintingLayer()) {
+ PaintInfo currentPaintInfo(paintInfo);
+ currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+ // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner.
+ LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->renderer().x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->renderer().y()));
+ r->renderer().paint(currentPaintInfo, childPoint);
+ if (!preservePhase) {
+ currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
+ r->renderer().paint(currentPaintInfo, childPoint);
+ currentPaintInfo.phase = PaintPhaseFloat;
+ r->renderer().paint(currentPaintInfo, childPoint);
+ currentPaintInfo.phase = PaintPhaseForeground;
+ r->renderer().paint(currentPaintInfo, childPoint);
+ currentPaintInfo.phase = PaintPhaseOutline;
+ r->renderer().paint(currentPaintInfo, childPoint);
+ }
+ }
+ }
+}
+
+
+void RenderBlockFlow::clipOutFloatingObjects(RenderBlock* rootBlock, const PaintInfo* paintInfo, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock)
+{
+ if (m_floatingObjects) {
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+ LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(floatingObject),
+ offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(floatingObject),
+ floatingObject->renderer().width(), floatingObject->renderer().height());
+ rootBlock->flipForWritingMode(floatBox);
+ floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
+ paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
+ }
+ }
+}
+
+void RenderBlockFlow::createFloatingObjects()
+{
+ m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
+}
+
+void RenderBlockFlow::removeFloatingObjects()
+{
+ if (!m_floatingObjects)
+ return;
+
+ m_floatingObjects->clear();
+}
+
+FloatingObject* RenderBlockFlow::insertFloatingObject(RenderBox* floatBox)
+{
+ ASSERT(floatBox->isFloating());
+
+ // Create the list of special objects if we don't aleady have one
+ if (!m_floatingObjects)
+ createFloatingObjects();
+ else {
+ // Don't insert the floatingObject again if it's already in the list
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*floatBox);
+ if (it != floatingObjectSet.end())
+ return it->get();
+ }
+
+ // Create the special floatingObject entry & append it to the list
+
+ std::unique_ptr<FloatingObject> floatingObject = FloatingObject::create(*floatBox);
+
+ // Our location is irrelevant if we're unsplittable or no pagination is in effect.
+ // Just go ahead and lay out the float.
+ bool isChildRenderBlock = floatBox->isRenderBlock();
+ if (isChildRenderBlock && !floatBox->needsLayout() && view().layoutState()->pageLogicalHeightChanged())
+ floatBox->setChildNeedsLayout(MarkOnlyThis);
+
+ bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
+ if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
+ floatBox->layoutIfNeeded();
+ else {
+ floatBox->updateLogicalWidth();
+ floatBox->computeAndSetBlockDirectionMargins(this);
+ }
+
+ floatingObject->setLogicalWidth(logicalWidthForChild(floatBox) + marginStartForChild(floatBox) + marginEndForChild(floatBox), isHorizontalWritingMode());
+
+#if ENABLE(CSS_SHAPES)
+ if (ShapeOutsideInfo* shapeOutside = floatBox->shapeOutsideInfo())
+ shapeOutside->setShapeSize(logicalWidthForChild(floatBox), logicalHeightForChild(floatBox));
+#endif
+
+ return m_floatingObjects->add(std::move(floatingObject));
+}
+
+void RenderBlockFlow::removeFloatingObject(RenderBox* floatBox)
+{
+ if (m_floatingObjects) {
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*floatBox);
+ if (it != floatingObjectSet.end()) {
+ FloatingObject* floatingObject = it->get();
+ if (childrenInline()) {
+ LayoutUnit logicalTop = floatingObject->logicalTop(isHorizontalWritingMode());
+ LayoutUnit logicalBottom = floatingObject->logicalBottom(isHorizontalWritingMode());
+
+ // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
+ if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == LayoutUnit::max())
+ logicalBottom = LayoutUnit::max();
+ else {
+ // Special-case zero- and less-than-zero-height floats: those don't touch
+ // the line that they're on, but it still needs to be dirtied. This is
+ // accomplished by pretending they have a height of 1.
+ logicalBottom = max(logicalBottom, logicalTop + 1);
+ }
+ if (floatingObject->originatingLine()) {
+ if (!selfNeedsLayout()) {
+ ASSERT(&floatingObject->originatingLine()->renderer() == this);
+ floatingObject->originatingLine()->markDirty();
+ }
+#if !ASSERT_DISABLED
+ floatingObject->setOriginatingLine(0);
+#endif
+ }
+ markLinesDirtyInBlockRange(0, logicalBottom);
+ }
+ m_floatingObjects->remove(floatingObject);
+ }
+ }
+}
+
+void RenderBlockFlow::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
+{
+ if (!containsFloats())
+ return;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ FloatingObject* curr = floatingObjectSet.last().get();
+ while (curr != lastFloat && (!curr->isPlaced() || curr->logicalTop(isHorizontalWritingMode()) >= logicalOffset)) {
+ m_floatingObjects->remove(curr);
+ if (floatingObjectSet.isEmpty())
+ break;
+ curr = floatingObjectSet.last().get();
+ }
+}
+
+LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
+{
+ RenderBox* childBox = &floatingObject->renderer();
+ LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ LayoutUnit logicalRightOffset; // Constant part of right offset.
+#if ENABLE(CSS_SHAPES)
+ // FIXME Bug 102948: This only works for shape outside directly set on this block.
+ ShapeInsideInfo* shapeInsideInfo = this->layoutShapeInsideInfo();
+ // FIXME: Implement behavior for right floats.
+ if (shapeInsideInfo) {
+ LayoutSize floatLogicalSize = LayoutSize(childBox->logicalWidth(), childBox->logicalHeight());
+ // FIXME: If the float doesn't fit in the shape we should push it under the content box
+ logicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(floatLogicalSize);
+ if (logicalHeight() > logicalTopOffset)
+ logicalTopOffset = logicalHeight();
+
+ SegmentList segments = shapeInsideInfo->computeSegmentsForLine(logicalTopOffset, childBox->logicalHeight());
+ // FIXME Bug 102949: Add support for shapes with multiple segments.
+ if (segments.size() == 1) {
+ // The segment offsets are relative to the content box.
+ logicalRightOffset = logicalLeftOffset + segments[0].logicalRight;
+ logicalLeftOffset += segments[0].logicalLeft;
+ }
+ } else
+#endif
+ logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset);
+
+ LayoutUnit floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset); // The width we look for.
+
+ LayoutUnit floatLogicalLeft;
+
+ bool insideFlowThread = flowThreadContainingBlock();
+
+ if (childBox->style()->floating() == LeftFloat) {
+ LayoutUnit heightRemainingLeft = 1;
+ LayoutUnit heightRemainingRight = 1;
+ floatLogicalLeft = logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
+ while (logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
+ logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
+ floatLogicalLeft = logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
+ if (insideFlowThread) {
+ // Have to re-evaluate all of our offsets, since they may have changed.
+ logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
+ logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset);
+ }
+ }
+ floatLogicalLeft = max(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft);
+ } else {
+ LayoutUnit heightRemainingLeft = 1;
+ LayoutUnit heightRemainingRight = 1;
+ floatLogicalLeft = logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
+ while (floatLogicalLeft - logicalLeftOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
+ logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
+ floatLogicalLeft = logicalRightOffsetForLineIgnoringShapeOutside(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
+ if (insideFlowThread) {
+ // Have to re-evaluate all of our offsets, since they may have changed.
+ logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
+ logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ floatLogicalWidth = min(floatingObject->logicalWidth(isHorizontalWritingMode()), logicalRightOffset - logicalLeftOffset);
+ }
+ }
+ // Use the original width of the float here, since the local variable
+ // |floatLogicalWidth| was capped to the available line width. See
+ // fast/block/float/clamped-right-float.html.
+ floatLogicalLeft -= floatingObject->logicalWidth(isHorizontalWritingMode());
+ }
+
+ return LayoutPoint(floatLogicalLeft, logicalTopOffset);
+}
+
+bool RenderBlockFlow::positionNewFloats()
+{
+ if (!m_floatingObjects)
+ return false;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ if (floatingObjectSet.isEmpty())
+ return false;
+
+ // If all floats have already been positioned, then we have no work to do.
+ if (floatingObjectSet.last()->isPlaced())
+ return false;
+
+ // Move backwards through our floating object list until we find a float that has
+ // already been positioned. Then we'll be able to move forward, positioning all of
+ // the new floats that need it.
+ auto it = floatingObjectSet.end();
+ --it; // Go to last item.
+ auto begin = floatingObjectSet.begin();
+ FloatingObject* lastPlacedFloatingObject = 0;
+ while (it != begin) {
+ --it;
+ if ((*it)->isPlaced()) {
+ lastPlacedFloatingObject = it->get();
+ ++it;
+ break;
+ }
+ }
+
+ LayoutUnit logicalTop = logicalHeight();
+
+ // The float cannot start above the top position of the last positioned float.
+ if (lastPlacedFloatingObject)
+ logicalTop = max(lastPlacedFloatingObject->logicalTop(isHorizontalWritingMode()), logicalTop);
+
+ auto end = floatingObjectSet.end();
+ // Now walk through the set of unpositioned floats and place them.
+ for (; it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+ // The containing block is responsible for positioning floats, so if we have floats in our
+ // list that come from somewhere else, do not attempt to position them.
+ if (floatingObject->renderer().containingBlock() != this)
+ continue;
+
+ RenderBox* childBox = &floatingObject->renderer();
+
+ LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
+
+ LayoutRect oldRect = childBox->frameRect();
+
+ if (childBox->style()->clear() & CLEFT)
+ logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
+ if (childBox->style()->clear() & CRIGHT)
+ logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
+
+ LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop);
+
+ floatingObject->setLogicalLeft(floatLogicalLocation.x(), isHorizontalWritingMode());
+
+ setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
+ setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
+
+ estimateRegionRangeForBoxChild(childBox);
+
+ LayoutState* layoutState = view().layoutState();
+ bool isPaginated = layoutState->isPaginated();
+ if (isPaginated && !childBox->needsLayout())
+ childBox->markForPaginationRelayoutIfNeeded();
+
+ childBox->layoutIfNeeded();
+
+ if (isPaginated) {
+ // If we are unsplittable and don't fit, then we need to move down.
+ // We include our margins as part of the unsplittable area.
+ LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true);
+
+ // See if we have a pagination strut that is making us move down further.
+ // Note that an unsplittable child can't also have a pagination strut, so this is
+ // exclusive with the case above.
+ RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
+ if (childBlock && childBlock->paginationStrut()) {
+ newLogicalTop += childBlock->paginationStrut();
+ childBlock->setPaginationStrut(0);
+ }
+
+ if (newLogicalTop != floatLogicalLocation.y()) {
+ floatingObject->setPaginationStrut(newLogicalTop - floatLogicalLocation.y());
+
+ floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop);
+ floatingObject->setLogicalLeft(floatLogicalLocation.x(), isHorizontalWritingMode());
+
+ setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
+ setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
+
+ if (childBlock)
+ childBlock->setChildNeedsLayout(MarkOnlyThis);
+ childBox->layoutIfNeeded();
+ }
+
+ if (updateRegionRangeForBoxChild(childBox)) {
+ childBox->setNeedsLayout(MarkOnlyThis);
+ childBox->layoutIfNeeded();
+ }
+ }
+
+ floatingObject->setLogicalTop(floatLogicalLocation.y(), isHorizontalWritingMode());
+
+ floatingObject->setLogicalHeight(logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox), isHorizontalWritingMode());
+
+ m_floatingObjects->addPlacedObject(floatingObject);
+
+ // If the child moved, we have to repaint it.
+ if (childBox->checkForRepaintDuringLayout())
+ childBox->repaintDuringLayoutIfMoved(oldRect);
+ }
+ return true;
+}
+
+void RenderBlockFlow::newLine(EClear clear)
+{
+ positionNewFloats();
+ // set y position
+ LayoutUnit newY = 0;
+ switch (clear) {
+ case CLEFT:
+ newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
+ break;
+ case CRIGHT:
+ newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
+ break;
+ case CBOTH:
+ newY = lowestFloatLogicalBottom();
+ default:
+ break;
+ }
+ if (height() < newY)
+ setLogicalHeight(newY);
+}
+
+LayoutUnit RenderBlockFlow::logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
+{
+ if (m_floatingObjects && m_floatingObjects->hasLeftObjects())
+ return m_floatingObjects->logicalLeftOffset(fixedOffset, logicalTop, logicalHeight, offsetMode, heightRemaining);
+
+ return fixedOffset;
+}
+
+LayoutUnit RenderBlockFlow::logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
+{
+ if (m_floatingObjects && m_floatingObjects->hasRightObjects())
+ return m_floatingObjects->logicalRightOffset(fixedOffset, logicalTop, logicalHeight, offsetMode, heightRemaining);
+
+ return fixedOffset;
+}
+
+LayoutUnit RenderBlockFlow::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const
+{
+ if (!m_floatingObjects)
+ return logicalHeight;
+
+ LayoutUnit bottom = LayoutUnit::max();
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+ LayoutUnit floatBottom;
+#if ENABLE(CSS_SHAPES)
+ ShapeOutsideInfo* shapeOutside = floatingObject->renderer().shapeOutsideInfo();
+ if (offsetMode == ShapeOutsideFloatShapeOffset && shapeOutside)
+ floatBottom = floatingObject->logicalTop(isHorizontalWritingMode()) + marginBeforeForChild(&(floatingObject->renderer())) + shapeOutside->shapeLogicalBottom();
+ else
+#endif
+ floatBottom = floatingObject->logicalBottom(isHorizontalWritingMode());
+ if (floatBottom > logicalHeight)
+ bottom = min(floatBottom, bottom);
+ }
+
+ return bottom == LayoutUnit::max() ? LayoutUnit() : bottom;
+}
+
+LayoutUnit RenderBlockFlow::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
+{
+ if (!m_floatingObjects)
+ return 0;
+ LayoutUnit lowestFloatBottom = 0;
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = it->get();
+ if (floatingObject->isPlaced() && floatingObject->type() & floatType)
+ lowestFloatBottom = max(lowestFloatBottom, floatingObject->logicalBottom(isHorizontalWritingMode()));
+ }
+ return lowestFloatBottom;
+}
+
+LayoutUnit RenderBlockFlow::addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats)
+{
+ // Prevent floats from being added to the canvas by the root element, e.g., <html>.
+ if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
+ return 0;
+
+ LayoutUnit childLogicalTop = child->logicalTop();
+ LayoutUnit childLogicalLeft = child->logicalLeft();
+ LayoutUnit lowestFloatLogicalBottom = 0;
+
+ // Floats that will remain the child's responsibility to paint should factor into its
+ // overflow.
+ auto childEnd = child->m_floatingObjects->set().end();
+ for (auto childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
+ FloatingObject* floatingObject = childIt->get();
+ LayoutUnit logicalBottomForFloat = min(floatingObject->logicalBottom(isHorizontalWritingMode()), LayoutUnit::max() - childLogicalTop);
+ LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
+ lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
+
+ if (logicalBottom > logicalHeight()) {
+ // If the object is not in the list, we add it now.
+ if (!containsFloat(&floatingObject->renderer())) {
+ LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft);
+ bool shouldPaint = false;
+
+ // The nearest enclosing layer always paints the float (so that zindex and stacking
+ // behaves properly). We always want to propagate the desire to paint the float as
+ // far out as we can, to the outermost block that overlaps the float, stopping only
+ // if we hit a self-painting layer boundary.
+ if (floatingObject->renderer().enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer()) {
+ floatingObject->setShouldPaint(false);
+ shouldPaint = true;
+ }
+ // We create the floating object list lazily.
+ if (!m_floatingObjects)
+ createFloatingObjects();
+
+ m_floatingObjects->add(floatingObject->copyToNewContainer(offset, shouldPaint, true));
+ }
+ } else {
+ if (makeChildPaintOtherFloats && !floatingObject->shouldPaint() && !floatingObject->renderer().hasSelfPaintingLayer()
+ && floatingObject->renderer().isDescendantOf(child) && floatingObject->renderer().enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
+ // The float is not overhanging from this block, so if it is a descendant of the child, the child should
+ // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
+ // layer.
+ // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
+ // it should paint.
+ floatingObject->setShouldPaint(true);
+ }
+
+ // Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the
+ // child now.
+ if (floatingObject->isDescendant())
+ child->addOverflowFromChild(&floatingObject->renderer(), LayoutSize(xPositionForFloatIncludingMargin(floatingObject), yPositionForFloatIncludingMargin(floatingObject)));
+ }
+ }
+ return lowestFloatLogicalBottom;
+}
+
+bool RenderBlockFlow::hasOverhangingFloat(RenderBox* renderer)
+{
+ if (!m_floatingObjects || hasColumns() || !parent())
+ return false;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto it = floatingObjectSet.find<RenderBox&, FloatingObjectHashTranslator>(*renderer);
+ if (it == floatingObjectSet.end())
+ return false;
+
+ return (*it)->logicalBottom(isHorizontalWritingMode()) > logicalHeight();
+}
+
+void RenderBlockFlow::addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
+{
+ ASSERT(!avoidsFloats());
+
+ // If the parent or previous sibling doesn't have any floats to add, don't bother.
+ if (!prev->m_floatingObjects)
+ return;
+
+ logicalLeftOffset += marginLogicalLeft();
+
+ const FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
+ auto prevEnd = prevSet.end();
+ for (auto prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
+ FloatingObject* floatingObject = prevIt->get();
+ if (floatingObject->logicalBottom(isHorizontalWritingMode()) > logicalTopOffset) {
+ if (!m_floatingObjects || !m_floatingObjects->set().contains<FloatingObject&, FloatingObjectHashTranslator>(*floatingObject)) {
+ // We create the floating object list lazily.
+ if (!m_floatingObjects)
+ createFloatingObjects();
+
+ // Applying the child's margin makes no sense in the case where the child was passed in.
+ // since this margin was added already through the modification of the |logicalLeftOffset| variable
+ // above. |logicalLeftOffset| will equal the margin in this case, so it's already been taken
+ // into account. Only apply this code if prev is the parent, since otherwise the left margin
+ // will get applied twice.
+ LayoutSize offset = isHorizontalWritingMode()
+ ? LayoutSize(logicalLeftOffset - (prev != parent() ? prev->marginLeft() : LayoutUnit()), logicalTopOffset)
+ : LayoutSize(logicalTopOffset, logicalLeftOffset - (prev != parent() ? prev->marginTop() : LayoutUnit()));
+
+ m_floatingObjects->add(floatingObject->copyToNewContainer(offset));
+ }
+ }
+ }
+}
+
+void RenderBlockFlow::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
+{
+ if (!everHadLayout() && !containsFloats())
+ return;
+
+ MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain;
+ setChildNeedsLayout(markParents);
+
+ if (floatToRemove)
+ removeFloatingObject(floatToRemove);
+
+ // Iterate over our children and mark them as needed.
+ if (!childrenInline()) {
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || !child->isRenderBlock())
+ continue;
+ if (!child->isRenderBlockFlow()) {
+ RenderBlock* childBlock = toRenderBlock(child);
+ if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout())
+ childBlock->setChildNeedsLayout(markParents);
+ continue;
+ }
+ RenderBlockFlow* childBlock = toRenderBlockFlow(child);
+ if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
+ childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
+ }
+ }
+}
+
+void RenderBlockFlow::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
+{
+ if (!m_floatingObjects)
+ return;
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+
+ for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) {
+ if (!next->isRenderBlockFlow() || next->isFloatingOrOutOfFlowPositioned() || toRenderBlock(next)->avoidsFloats())
+ continue;
+
+ RenderBlockFlow* nextBlock = toRenderBlockFlow(next);
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ RenderBox* floatingBox = &(*it)->renderer();
+ if (floatToRemove && floatingBox != floatToRemove)
+ continue;
+ if (nextBlock->containsFloat(floatingBox))
+ nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
+ }
+ }
+}
+
+LayoutUnit RenderBlockFlow::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
+{
+ // There is no need to compute clearance if we have no floats.
+ if (!containsFloats())
+ return 0;
+
+ // At least one float is present. We need to perform the clearance computation.
+ bool clearSet = child->style()->clear() != CNONE;
+ LayoutUnit logicalBottom = 0;
+ switch (child->style()->clear()) {
+ case CNONE:
+ break;
+ case CLEFT:
+ logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
+ break;
+ case CRIGHT:
+ logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
+ break;
+ case CBOTH:
+ logicalBottom = lowestFloatLogicalBottom();
+ break;
+ }
+
+ // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
+ LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : LayoutUnit();
+ if (!result && child->avoidsFloats()) {
+ LayoutUnit newLogicalTop = logicalTop;
+ while (true) {
+ LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
+ if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
+ return newLogicalTop - logicalTop;
+
+ RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child));
+ LayoutRect borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
+ LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
+
+ // FIXME: None of this is right for perpendicular writing-mode children.
+ LayoutUnit childOldLogicalWidth = child->logicalWidth();
+ LayoutUnit childOldMarginLeft = child->marginLeft();
+ LayoutUnit childOldMarginRight = child->marginRight();
+ LayoutUnit childOldLogicalTop = child->logicalTop();
+
+ child->setLogicalTop(newLogicalTop);
+ child->updateLogicalWidth();
+ region = regionAtBlockOffset(logicalTopForChild(child));
+ borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
+ LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
+
+ child->setLogicalTop(childOldLogicalTop);
+ child->setLogicalWidth(childOldLogicalWidth);
+ child->setMarginLeft(childOldMarginLeft);
+ child->setMarginRight(childOldMarginRight);
+
+ if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) {
+ // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then
+ // we need to force a relayout as though we shifted. This happens because of the dynamic addition of overhanging floats
+ // from previous siblings when negative margins exist on a child (see the addOverhangingFloats call at the end of collapseMargins).
+ if (childLogicalWidthAtOldLogicalTopOffset != childLogicalWidthAtNewLogicalTopOffset)
+ child->setChildNeedsLayout(MarkOnlyThis);
+ return newLogicalTop - logicalTop;
+ }
+
+ newLogicalTop = nextFloatLogicalBottomBelow(newLogicalTop);
+ ASSERT(newLogicalTop >= logicalTop);
+ if (newLogicalTop < logicalTop)
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ }
+ return result;
+}
+
+bool RenderBlockFlow::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
+{
+ if (!m_floatingObjects)
+ return false;
+
+ LayoutPoint adjustedLocation = accumulatedOffset;
+ if (isRenderView())
+ adjustedLocation += toLayoutSize(toRenderView(*this).frameView().scrollPosition());
+
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto begin = floatingObjectSet.begin();
+ for (auto it = floatingObjectSet.end(); it != begin;) {
+ --it;
+ FloatingObject* floatingObject = it->get();
+ if (floatingObject->shouldPaint() && !floatingObject->renderer().hasSelfPaintingLayer()) {
+ LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer().x();
+ LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer().y();
+ LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
+ if (floatingObject->renderer().hitTest(request, result, locationInContainer, childPoint)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void RenderBlockFlow::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const
+{
+ RenderBlock::adjustForBorderFit(x, left, right);
+
+ if (style()->visibility() == VISIBLE) {
+ if (m_floatingObjects) {
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ auto end = floatingObjectSet.end();
+ for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* r = it->get();
+ // Only examine the object if our m_shouldPaint flag is set.
+ if (r->shouldPaint()) {
+ LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->renderer().x();
+ LayoutUnit floatRight = floatLeft + r->renderer().width();
+ left = min(left, floatLeft);
+ right = max(right, floatRight);
+ }
+ }
+ }
+ }
+}
+
+
} // namespace WebCore
namespace WebCore {
+class LineBreaker;
+
class RenderBlockFlow : public RenderBlock {
public:
explicit RenderBlockFlow(Element*);
}
void layoutLineGridBox();
+ bool containsFloats() const OVERRIDE { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
+ bool containsFloat(RenderBox*) const;
+
+ virtual void deleteLineBoxTree() OVERRIDE;
+ virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE;
+
+ void removeFloatingObjects();
+ void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
+ void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
+
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 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);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+
+ void createFloatingObjects();
+
+private:
+ virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) OVERRIDE;
+ virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
+ virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE;
+ virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) OVERRIDE;
+
+ FloatingObject* insertFloatingObject(RenderBox*);
+ void removeFloatingObject(RenderBox*);
+ void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
+ LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
+
+ // Called from lineWidth, to position the floats added in the last line.
+ // Returns true if and only if it has positioned any floats.
+ bool positionNewFloats();
+
+ void newLine(EClear);
+
+ virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const OVERRIDE;
+ virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const OVERRIDE;
+ LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
+ LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
+
+ LayoutUnit addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
+ bool hasOverhangingFloat(RenderBox*);
+ void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
+ bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
+ LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
+
+ virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE;
+ void addOverflowFromFloats();
+ virtual void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const OVERRIDE;
+
+
+// FIXME-BLOCKFLOW: These methods have implementations in
+// RenderBlockLineLayout. They should be moved to the proper header once the
+// line layout code is separated from RenderBlock and RenderBlockFlow.
+// START METHODS DEFINED IN RenderBlockLineLayout
+public:
+ static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
+
+private:
+ InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
+ RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
+ void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
+ void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
+ BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
+ float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
+ void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
+ BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
+ void appendFloatingObjectToLastLine(FloatingObject*);
+ // Helper function for layoutInlineChildren()
+ RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
+ void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
+ const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&);
+ void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
+#if ENABLE(CSS_SHAPES)
+ void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, const LayoutSize&, LineLayoutState&);
+ void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
+ bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
+#endif
+ void linkToEndLineIfNeeded(LineLayoutState&);
+ static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
+ 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 checkPaginationAndFloatsAtEndLine(LineLayoutState&);
+ bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
+ void deleteEllipsisLineBoxes();
+ void checkLinesForTextOverflow();
+ // Positions new floats and also adjust all floats encountered on the line if any of them
+ // have to move to the next page/column.
+ bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
+
+
+// END METHODS DEFINED IN RenderBlockLineLayout
+
public:
// FIXME-BLOCKFLOW: These can be made protected again once all callers have been moved here.
void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
void updateRegionForLine(RootInlineBox*) const;
protected:
+ OwnPtr<FloatingObjects> m_floatingObjects;
OwnPtr<RenderBlockFlowRareData> m_rareData;
+
+ friend class LineBreaker;
+ friend class LineWidth; // Needs to know FloatingObject
};
inline RenderBlockFlow& toRenderBlockFlow(RenderObject& object)
#include "LineLayoutState.h"
#include "Logging.h"
#include "RenderArena.h"
+#include "RenderBlockFlow.h"
#include "RenderCombineText.h"
#include "RenderCounter.h"
#include "RenderFlowThread.h"
class LineBreaker {
public:
- LineBreaker(RenderBlock* block)
+ LineBreaker(RenderBlockFlow* block)
: m_block(block)
{
reset();
void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
- RenderBlock* m_block;
+ RenderBlockFlow* m_block;
bool m_hyphenated;
EClear m_clear;
Vector<RenderBox*> m_positionedObjects;
return new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir());
}
-void RenderBlock::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+void RenderBlockFlow::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
{
if (start > end || shouldSkipCreatingRunsForObject(obj))
return;
return false;
}
-InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox, bool startNewSegment)
+InlineFlowBox* RenderBlockFlow::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox, bool startNewSegment)
{
// See if we have an unconstructed line box for this object that is also
// the last item on the line.
return endsWithASCIISpaces(renderText->characters16(), pos, length);
}
-RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
+RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
{
ASSERT(bidiRuns.firstRun());
logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
}
-void RenderBlock::setMarginsForRubyRun(BidiRun* run, RenderRubyRun* renderer, RenderObject* previousObject, const LineInfo& lineInfo)
+void RenderBlockFlow::setMarginsForRubyRun(BidiRun* run, RenderRubyRun* renderer, RenderObject* previousObject, const LineInfo& lineInfo)
{
int startOverhang;
int endOverhang;
return shouldIndentText;
}
-static void updateLogicalInlinePositions(RenderBlock* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
+static void updateLogicalInlinePositions(RenderBlockFlow* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
{
LayoutUnit lineLogicalHeight = block->minLineHeightForReplacedRenderer(firstLine, boxLogicalHeight);
lineLogicalLeft = block->pixelSnappedLogicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
}
-void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
+void RenderBlockFlow::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
{
ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing, textBoxDataMap);
}
-BidiRun* RenderBlock::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, ETextAlign textAlign, float& logicalLeft,
+BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, ETextAlign textAlign, float& logicalLeft,
float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
WordMeasurements& wordMeasurements)
{
return r;
}
-void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
+void RenderBlockFlow::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
VerticalPositionCache& verticalPositionCache)
{
setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache));
}
-static void setStaticPositions(RenderBlock* block, RenderBox* child)
+static void setStaticPositions(RenderBlockFlow* block, RenderBox* child)
{
// FIXME: The math here is actually not really right. It's a best-guess approximation that
// will work for the common cases
return firstSpace;
}
-inline BidiRun* RenderBlock::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
+inline BidiRun* RenderBlockFlow::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
{
if (!bidiRuns.runCount()
|| !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
return trailingSpaceRun;
}
-void RenderBlock::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
+void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
{
ASSERT(!floatingObject->originatingLine());
floatingObject->setOriginatingLine(lastRootBox());
}
}
-static inline void constructBidiRunsForLine(const RenderBlock* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly)
+static inline void constructBidiRunsForLine(const RenderBlockFlow* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly)
{
#if !ENABLE(CSS_SHAPES)
UNUSED_PARAM(block);
}
// This function constructs line boxes for all of the text runs in the resolver and computes their position.
-RootInlineBox* RenderBlock::createLineBoxesFromBidiRuns(BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
+RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
{
if (!bidiRuns.runCount())
return 0;
}
}
-void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
+void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
{
// We want to skip ahead to the first dirty line
InlineBidiResolver resolver;
}
// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
-inline const InlineIterator& RenderBlock::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver, const InlineIterator& oldEnd)
+inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver, const InlineIterator& oldEnd)
{
removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
setLogicalHeight(newLogicalHeight);
return shapeInsideInfo->shapeLogicalBottom();
}
-static inline void pushShapeContentOverflowBelowTheContentBox(RenderBlock* block, ShapeInsideInfo* shapeInsideInfo, LayoutUnit lineTop, LayoutUnit lineHeight)
+static inline void pushShapeContentOverflowBelowTheContentBox(RenderBlockFlow* block, ShapeInsideInfo* shapeInsideInfo, LayoutUnit lineTop, LayoutUnit lineHeight)
{
ASSERT(shapeInsideInfo);
block->setLogicalHeight(newLogicalHeight);
}
-void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState& layoutState)
+void RenderBlockFlow::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState& layoutState)
{
if (layoutState.flowThread())
return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo, layoutState);
pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
}
-void RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*& shapeInsideInfo, LineLayoutState& layoutState)
+void RenderBlockFlow::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*& shapeInsideInfo, LineLayoutState& layoutState)
{
ASSERT(layoutState.flowThread());
pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
}
-bool RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo* shapeInsideInfo, LayoutUnit absoluteLogicalTop, LineLayoutState& layoutState, InlineBidiResolver& resolver, FloatingObject* lastFloatFromPreviousLine, InlineIterator& end, WordMeasurements& wordMeasurements)
+bool RenderBlockFlow::adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo* shapeInsideInfo, LayoutUnit absoluteLogicalTop, LineLayoutState& layoutState, InlineBidiResolver& resolver, FloatingObject* lastFloatFromPreviousLine, InlineIterator& end, WordMeasurements& wordMeasurements)
{
LayoutUnit adjustedLogicalLineTop = adjustLogicalLineTop(shapeInsideInfo, resolver.position(), end, wordMeasurements);
}
#endif
-void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
+void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
{
RenderStyle* styleToUse = style();
bool paginated = view().layoutState() && view().layoutState()->isPaginated();
if (paginated) {
LayoutUnit adjustment = 0;
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
+ adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
if (adjustment) {
LayoutUnit oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, layoutState.lineInfo().isFirstLine());
lineBox->adjustBlockDirectionPosition(adjustment);
}
if (layoutState.flowThread())
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->updateRegionForLine(lineBox);
+ updateRegionForLine(lineBox);
}
}
}
// In case we already adjusted the line positions during this layout to avoid widows
// then we need to ignore the possibility of having a new widows situation.
// Otherwise, we risk leaving empty containers which is against the block fragmentation principles.
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- if (paginated && !style()->hasAutoWidows() && !toRenderBlockFlow(this)->didBreakAtLineToAvoidWidow()) {
+ if (paginated && !style()->hasAutoWidows() && !didBreakAtLineToAvoidWidow()) {
// Check the line boxes to make sure we didn't create unacceptable widows.
// However, we'll prioritize orphans - so nothing we do here should create
// a new orphan.
lineBox = lineBox->prevRootBox();
// We now want to break at this line. Remember for next layout and trigger relayout.
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->setBreakAtLineToAvoidWidow(lineCount(lineBox));
+ setBreakAtLineToAvoidWidow(lineCount(lineBox));
markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), lineBox->lineBottomWithLeading(), lineBox);
}
}
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->clearDidBreakAtLineToAvoidWidow();
+ clearDidBreakAtLineToAvoidWidow();
}
-void RenderBlock::linkToEndLineIfNeeded(LineLayoutState& layoutState)
+void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
{
if (layoutState.endLine()) {
if (layoutState.endLineMatched()) {
line->attachLine();
if (paginated) {
delta -= line->paginationStrut();
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->adjustLinePositionForPagination(line, delta, layoutState.flowThread());
+ adjustLinePositionForPagination(line, delta, layoutState.flowThread());
}
if (delta) {
layoutState.updateRepaintRangeFromBox(line, delta);
line->adjustBlockDirectionPosition(delta);
}
if (layoutState.flowThread())
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->updateRegionForLine(line);
+ updateRegionForLine(line);
if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
Vector<RenderBox*>::iterator end = cleanLineFloats->end();
for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
if (layoutState.flowThread())
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->updateRegionForLine(trailingFloatsLineBox);
+ updateRegionForLine(trailingFloatsLineBox);
}
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
}
}
-void RenderBlock::repaintDirtyFloats(Vector<FloatWithRect>& floats)
+void RenderBlockFlow::repaintDirtyFloats(Vector<FloatWithRect>& floats)
{
size_t floatCount = floats.size();
// Floats that did not have layout did not repaint when we laid them out. They would have
checkLinesForTextOverflow();
}
-void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
+void RenderBlockFlow::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
{
Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
if (!cleanLineFloats)
}
}
-RootInlineBox* RenderBlock::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
+RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
{
RootInlineBox* curr = 0;
RootInlineBox* last = 0;
break;
}
paginationDelta -= curr->paginationStrut();
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
+ adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
if (paginationDelta) {
if (containsFloats() || !layoutState.floats().isEmpty()) {
// FIXME: Do better eventually. For now if we ever shift because of pagination and floats are present just go to a full layout.
curr->adjustBlockDirectionPosition(paginationDelta);
}
if (layoutState.flowThread())
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->updateRegionForLine(curr);
+ updateRegionForLine(curr);
}
// If a new float has been inserted before this line or before its last known float, just do a full layout.
return curr;
}
-void RenderBlock::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
+void RenderBlockFlow::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
{
ASSERT(!layoutState.endLine());
size_t floatIndex = layoutState.floatIndex();
layoutState.setEndLine(last);
}
-bool RenderBlock::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
+bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
{
LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop();
// strut yet.
LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
lineDelta -= oldPaginationStrut;
- // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
- toRenderBlockFlow(this)->adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
+ adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
lineBox->setPaginationStrut(oldPaginationStrut);
}
if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.flowThread()))
return true;
}
-bool RenderBlock::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
+bool RenderBlockFlow::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
{
if (resolver.position() == endLineStart) {
if (resolver.status() != endLineStatus)
// This is currently just used for list markers and inline flows that have line boxes. Neither should
// have an effect on whitespace at the start of the line.
-static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, LineMidpointState& lineMidpointState)
+static bool shouldSkipWhitespaceAfterStartObject(RenderBlockFlow* block, RenderObject* o, LineMidpointState& lineMidpointState)
{
RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
while (next && next->isFloatingOrOutOfFlowPositioned())
}
#if ENABLE(CSS_SHAPES)
-static void updateSegmentsForShapes(RenderBlock* block, const FloatingObject* lastFloatFromPreviousLine, const WordMeasurements& wordMeasurements, LineWidth& width, bool isFirstLine)
+static void updateSegmentsForShapes(RenderBlockFlow* block, const FloatingObject* lastFloatFromPreviousLine, const WordMeasurements& wordMeasurements, LineWidth& width, bool isFirstLine)
{
ASSERT(lastFloatFromPreviousLine);
}
}
-void RenderBlock::deleteEllipsisLineBoxes()
+void RenderBlockFlow::deleteEllipsisLineBoxes()
{
ETextAlign textAlign = style()->textAlign();
bool ltr = style()->isLeftToRightDirection();
}
}
-void RenderBlock::checkLinesForTextOverflow()
+void RenderBlockFlow::checkLinesForTextOverflow()
{
// Determine the width of the ellipsis using the current font.
// FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
}
}
-bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
+bool RenderBlockFlow::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
{
if (!positionNewFloats())
return false;
RenderBoxModelObject::willBeDestroyed();
}
-RenderBlock* RenderBox::outermostBlockContainingFloatingObject()
+RenderBlockFlow* RenderBox::outermostBlockContainingFloatingObject()
{
ASSERT(isFloating());
- RenderBlock* parentBlock = 0;
+ RenderBlockFlow* parentBlock = 0;
for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
- if (curr->isRenderBlock()) {
- RenderBlock* currBlock = toRenderBlock(curr);
+ if (curr->isRenderBlockFlow()) {
+ RenderBlockFlow* currBlock = toRenderBlockFlow(curr);
if (!parentBlock || currBlock->containsFloat(this))
parentBlock = currBlock;
}
}
- if (parentBlock) {
- RenderObject* parent = parentBlock->parent();
- if (parent && parent->isFlexibleBoxIncludingDeprecated())
- parentBlock = toRenderBlock(parent);
- }
return parentBlock;
}
return;
if (isFloating()) {
- if (RenderBlock* parentBlock = outermostBlockContainingFloatingObject()) {
+ if (RenderBlockFlow* parentBlock = outermostBlockContainingFloatingObject()) {
parentBlock->markSiblingsWithFloatsForLayout(this);
parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
}
namespace WebCore {
+class RenderBlockFlow;
class RenderBoxRegionInfo;
class RenderRegion;
struct PaintInfo;
virtual VisiblePosition positionForPoint(const LayoutPoint&) OVERRIDE;
- RenderBlock* outermostBlockContainingFloatingObject();
+ RenderBlockFlow* outermostBlockContainingFloatingObject();
void removeFloatingOrPositionedChildFromBlockLists();
// anonymous blocks which can no longer carry positioned objects (see r120761)
// or when fullRemoveInsert is false.
if (fullRemoveInsert && isRenderBlock()) {
- RenderBlock* block = toRenderBlock(this);
- block->removePositionedObjects(0);
- block->removeFloatingObjects();
+ toRenderBlock(this)->removePositionedObjects(0);
+ if (isRenderBlockFlow())
+ toRenderBlockFlow(this)->removeFloatingObjects();
}
ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
// We can reuse this block and make it the preBlock of the next continuation.
pre = block;
pre->removePositionedObjects(0);
- pre->removeFloatingObjects();
+ // FIXME-BLOCKFLOW: The enclosing method should likely be switched over
+ // to only work on RenderBlockFlow, in which case this conversion can be
+ // removed.
+ if (pre->isRenderBlockFlow())
+ toRenderBlockFlow(pre)->removeFloatingObjects();
block = block->containingBlock();
} else {
// No anonymous block available for use. Make one.