Ejemplo n.º 1
0
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;
}
Ejemplo n.º 3
0
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;
}