void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge) { dirtyForLayoutFromPercentageHeightDescendants(layoutScope); RenderBox* next = firstChildBox(); RenderBox* lastNormalFlowChild = 0; while (next) { RenderBox* child = next; next = child->nextSiblingBox(); // FIXME: this should only be set from clearNeedsLayout crbug.com/361250 child->setLayoutDidGetCalled(true); updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child); if (child->isOutOfFlowPositioned()) { child->containingBlock()->insertPositionedObject(child); adjustPositionedBlock(child); continue; } // Lay out the child. layoutBlockChild(child); lastNormalFlowChild = child; } // Negative margins can cause our height to shrink below our minimal height (border/padding). // If this happens, ensure that the computed height is increased to the minimal height. setLogicalHeight(std::max(logicalHeight() + afterEdge, beforeEdge + afterEdge)); }
LayoutRect RenderNamedFlowThread::decorationsClipRectForBoxInNamedFlowFragment(const RenderBox& box, RenderNamedFlowFragment& fragment) const { LayoutRect visualOverflowRect = fragment.visualOverflowRectForBox(&box); LayoutUnit initialLogicalX = style().isHorizontalWritingMode() ? visualOverflowRect.x() : visualOverflowRect.y(); // The visual overflow rect returned by visualOverflowRectForBox is already flipped but the // RenderRegion::rectFlowPortionForBox method expects it unflipped. flipForWritingModeLocalCoordinates(visualOverflowRect); visualOverflowRect = fragment.rectFlowPortionForBox(&box, visualOverflowRect); // Now flip it again. flipForWritingModeLocalCoordinates(visualOverflowRect); // Take the scrolled offset of this object's parents into consideration. IntSize scrolledContentOffset; RenderBlock* containingBlock = box.containingBlock(); while (containingBlock) { if (containingBlock->isRenderNamedFlowThread()) { // We've reached the flow thread, take the scrolled offset of the region into consideration. ASSERT(containingBlock == this); scrolledContentOffset += fragment.fragmentContainer().scrolledContentOffset(); break; } scrolledContentOffset += containingBlock->scrolledContentOffset(); containingBlock = containingBlock->containingBlock(); } if (!scrolledContentOffset.isZero()) { if (style().isFlippedBlocksWritingMode()) scrolledContentOffset = -scrolledContentOffset; visualOverflowRect.inflateX(scrolledContentOffset.width()); visualOverflowRect.inflateY(scrolledContentOffset.height()); } // Layers are in physical coordinates so the origin must be moved to the physical top-left of the flowthread. if (style().isFlippedBlocksWritingMode()) { if (style().isHorizontalWritingMode()) visualOverflowRect.moveBy(LayoutPoint(0, height())); else visualOverflowRect.moveBy(LayoutPoint(width(), 0)); } const RenderBox* iterBox = &box; while (iterBox && iterBox != this) { RenderBlock* containerBlock = iterBox->containingBlock(); // FIXME: This doesn't work properly with flipped writing modes. // https://bugs.webkit.org/show_bug.cgi?id=125149 if (iterBox->isPositioned()) { // For positioned elements, just use the layer's absolute bounding box. visualOverflowRect.moveBy(iterBox->layer()->absoluteBoundingBox().location()); break; } LayoutRect currentBoxRect = iterBox->frameRect(); if (iterBox->style().isFlippedBlocksWritingMode()) { if (iterBox->style().isHorizontalWritingMode()) currentBoxRect.setY(currentBoxRect.height() - currentBoxRect.maxY()); else currentBoxRect.setX(currentBoxRect.width() - currentBoxRect.maxX()); } if (containerBlock->style().writingMode() != iterBox->style().writingMode()) iterBox->flipForWritingMode(currentBoxRect); visualOverflowRect.moveBy(currentBoxRect.location()); iterBox = containerBlock; } // Since the purpose of this method is to make sure the borders of a fragmented // element don't overflow the region in the fragmentation direction, there's no // point in restricting the clipping rect on the logical X axis. // This also saves us the trouble of handling percent-based widths and margins // since the absolute bounding box of a positioned element would not contain // the correct coordinates relative to the region we're interested in, but rather // relative to the actual flow thread. if (style().isHorizontalWritingMode()) { if (initialLogicalX < visualOverflowRect.x()) visualOverflowRect.shiftXEdgeTo(initialLogicalX); if (visualOverflowRect.width() < frameRect().width()) visualOverflowRect.setWidth(frameRect().width()); } else { if (initialLogicalX < visualOverflowRect.y()) visualOverflowRect.shiftYEdgeTo(initialLogicalX); if (visualOverflowRect.height() < frameRect().height()) visualOverflowRect.setHeight(frameRect().height()); } return visualOverflowRect; }
void RenderMathMLRow::layoutRowItems(LayoutUnit& ascent, LayoutUnit& descent) { // We first stretch the vertical operators. // For inline formulas, we can then calculate the logical width. LayoutUnit width = borderAndPaddingStart(); for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { if (child->isOutOfFlowPositioned()) continue; if (is<RenderMathMLBlock>(child)) { auto renderOperator = downcast<RenderMathMLBlock>(child)->unembellishedOperator(); if (renderOperator && renderOperator->hasOperatorFlag(MathMLOperatorDictionary::Stretchy) && renderOperator->isVertical()) renderOperator->stretchTo(ascent, descent); } child->layoutIfNeeded(); width += child->marginStart() + child->logicalWidth() + child->marginEnd(); } width += borderEnd() + paddingEnd(); // FIXME: RenderMathMLRoot classes should also recalculate the exact logical width instead of using the preferred width. // See http://webkit.org/b/153987 if ((!isRenderMathMLMath() || style().display() == INLINE) && !isRenderMathMLRoot()) setLogicalWidth(width); LayoutUnit verticalOffset = borderTop() + paddingTop(); LayoutUnit maxAscent = 0, maxDescent = 0; // Used baseline alignment. LayoutUnit horizontalOffset = borderAndPaddingStart(); bool shouldFlipHorizontal = !style().isLeftToRightDirection(); for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { if (child->isOutOfFlowPositioned()) { child->containingBlock()->insertPositionedObject(*child); continue; } LayoutUnit childHorizontalExtent = child->logicalWidth(); LayoutUnit ascent = ascentForChild(*child); LayoutUnit descent = child->verticalMarginExtent() + child->logicalHeight() - ascent; maxAscent = std::max(maxAscent, ascent); maxDescent = std::max(maxDescent, descent); LayoutUnit childVerticalMarginBoxExtent = maxAscent + maxDescent; horizontalOffset += child->marginStart(); setLogicalHeight(std::max(logicalHeight(), verticalOffset + borderBottom() + paddingBottom() + childVerticalMarginBoxExtent + horizontalScrollbarHeight())); LayoutPoint childLocation(shouldFlipHorizontal ? logicalWidth() - horizontalOffset - childHorizontalExtent : horizontalOffset, verticalOffset + child->marginTop()); child->setLocation(childLocation); horizontalOffset += childHorizontalExtent + child->marginEnd(); } LayoutUnit centerBlockOffset = 0; // FIXME: Remove the FLEX when it is not required by the css. if (style().display() == BLOCK || style().display() == FLEX) centerBlockOffset = std::max<LayoutUnit>(0, (logicalWidth() - (horizontalOffset + borderEnd() + paddingEnd())) / 2); if (shouldFlipHorizontal && centerBlockOffset > 0) centerBlockOffset = -centerBlockOffset; for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { LayoutUnit ascent = ascentForChild(*child); LayoutUnit startOffset = maxAscent - ascent; child->setLocation(child->location() + LayoutPoint(centerBlockOffset, startOffset)); } ascent = maxAscent; descent = maxDescent; }