void RenderSlider::layout()
{
    ASSERT(needsLayout());

    SliderThumbElement* thumbElement = shadowSliderThumb();
    RenderBox* thumb = thumbElement ? toRenderBox(thumbElement->renderer()) : 0;

    IntSize baseSize(borderAndPaddingWidth(), borderAndPaddingHeight());

    if (thumb) {
        // Allow the theme to set the size of the thumb.
        if (thumb->style()->hasAppearance()) {
            // FIXME: This should pass the style, not the renderer, to the theme.
            theme()->adjustSliderThumbSize(thumb);
        }

        baseSize.expand(thumb->style()->width().calcMinValue(0), thumb->style()->height().calcMinValue(0));
    }

    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());

    IntSize oldSize = size();

    setSize(baseSize);
    computeLogicalWidth();
    computeLogicalHeight();
    updateLayerTransform();

    if (thumb) {
        if (oldSize != size())
            thumb->setChildNeedsLayout(true, false);

        LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());

        IntRect oldThumbRect = thumb->frameRect();

        thumb->layoutIfNeeded();

        IntRect rect = thumbRect();
        thumb->setFrameRect(rect);
        if (thumb->checkForRepaintDuringLayout())
            thumb->repaintDuringLayoutIfMoved(oldThumbRect);

        statePusher.pop();
        addOverflowFromChild(thumb);
    }

    repainter.repaintAfterLayout();    

    setNeedsLayout(false);
}
Пример #2
0
RenderObject* RenderTextControlMultiLine::layoutSpecialExcludedChild(bool relayoutChildren)
{
    RenderObject* placeholderRenderer = RenderTextControl::layoutSpecialExcludedChild(relayoutChildren);
    if (!placeholderRenderer)
        return 0;
    if (!placeholderRenderer->isBox())
        return placeholderRenderer;
    RenderBox* placeholderBox = toRenderBox(placeholderRenderer);
    placeholderBox->style()->setLogicalWidth(Length(contentLogicalWidth() - placeholderBox->borderAndPaddingLogicalWidth(), Fixed));
    placeholderBox->layoutIfNeeded();
    placeholderBox->setX(borderLeft() + paddingLeft());
    placeholderBox->setY(borderTop() + paddingTop());
    return placeholderRenderer;
}
void RenderSlider::layout()
{
    ASSERT(needsLayout());

    RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0;

    IntSize baseSize(borderLeft() + paddingLeft() + paddingRight() + borderRight(),
        borderTop() + paddingTop() + paddingBottom() + borderBottom());

    if (thumb) {
        // Allow the theme to set the size of the thumb.
        if (thumb->style()->hasAppearance()) {
            // FIXME: This should pass the style, not the renderer, to the theme.
            theme()->adjustSliderThumbSize(thumb);
        }

        baseSize.expand(thumb->style()->width().calcMinValue(0), thumb->style()->height().calcMinValue(0));
    }

    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());

    IntSize oldSize = size();

    setSize(baseSize);
    calcWidth();
    calcHeight();

    if (thumb) {
        if (oldSize != size())
            thumb->setChildNeedsLayout(true, false);

        LayoutStateMaintainer statePusher(view(), this, size());

        IntRect oldThumbRect = thumb->frameRect();

        thumb->layoutIfNeeded();

        IntRect rect = thumbRect();
        thumb->setFrameRect(rect);
        if (thumb->checkForRepaintDuringLayout())
            thumb->repaintDuringLayoutIfMoved(oldThumbRect);

        statePusher.pop();
        addOverflowFromChild(thumb);
    }

    repainter.repaintAfterLayout();    

    setNeedsLayout(false);
}
Пример #4
0
RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
{
    RenderBox* legend = findLegend();
    if (legend) {
        if (relayoutChildren)
            legend->setNeedsLayout(true);
        legend->layoutIfNeeded();

        LayoutUnit logicalLeft;
        if (style()->isLeftToRightDirection()) {
            switch (legend->style()->textAlign()) {
            case CENTER:
                logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
                break;
            case RIGHT:
                logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
                break;
            default:
                logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
                break;
            }
        } else {
            switch (legend->style()->textAlign()) {
            case LEFT:
                logicalLeft = borderStart() + paddingStart();
                break;
            case CENTER: {
                // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
                // in LTR).
                LayoutUnit centeredWidth = logicalWidth() - logicalWidthForChild(legend);
                logicalLeft = centeredWidth - centeredWidth / 2;
                break;
            }
            default:
                logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
                break;
            }
        }

        setLogicalLeftForChild(legend, logicalLeft);

        LayoutUnit b = borderBefore();
        LayoutUnit h = logicalHeightForChild(legend);
        setLogicalTopForChild(legend, max<LayoutUnit>((b - h) / 2, 0));
        setLogicalHeight(max(b, h) + paddingBefore());
    }
    return legend;
}
Пример #5
0
void RenderGrid::layoutGridItems()
{
    Vector<GridTrack> columnTracks(maximumIndexInDirection(ForColumns));
    Vector<GridTrack> rowTracks(maximumIndexInDirection(ForRows));
    computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
    ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
    computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
    ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks));

    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);

        size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
        size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());

        // Because the grid area cannot be styled, we don't need to adjust
        // the grid breadth to account for 'box-sizing'.
        LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
        LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();

        if (oldOverrideContainingBlockContentLogicalWidth != columnTracks[columnTrack].m_usedBreadth || oldOverrideContainingBlockContentLogicalHeight != rowTracks[rowTrack].m_usedBreadth)
            child->setNeedsLayout(true, MarkOnlyThis);

        child->setOverrideContainingBlockContentLogicalWidth(columnTracks[columnTrack].m_usedBreadth);
        child->setOverrideContainingBlockContentLogicalHeight(rowTracks[rowTrack].m_usedBreadth);

        // FIXME: Grid items should stretch to fill their cells. Once we
        // implement grid-{column,row}-align, we can also shrink to fit. For
        // now, just size as if we were a regular child.
        child->layoutIfNeeded();

        // FIXME: Handle border & padding on the grid element.
        child->setLogicalLocation(childPosition);
    }

    for (size_t i = 0; i < rowTracks.size(); ++i)
        setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);

    // FIXME: We should handle min / max logical height.

    setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
}
Пример #6
0
void ShadowBlockElement::layoutAsPart(const IntRect& partRect)
{
    RenderBox* parentRenderer = toRenderBox(renderer()->parent());
    RenderBox* selfRenderer = toRenderBox(renderer());
    IntRect oldRect = selfRenderer->frameRect();

    LayoutStateMaintainer statePusher(parentRenderer->view(), parentRenderer, parentRenderer->size(), parentRenderer->style()->isFlippedBlocksWritingMode());

    if (oldRect.size() != partRect.size())
        selfRenderer->setChildNeedsLayout(true, false);

    selfRenderer->layoutIfNeeded();
    selfRenderer->setFrameRect(partRect);

    if (selfRenderer->checkForRepaintDuringLayout())
        selfRenderer->repaintDuringLayoutIfMoved(oldRect);
        
    statePusher.pop();
    parentRenderer->addOverflowFromChild(selfRenderer);
}
RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
{
    RenderBox* legend = findLegend();
    if (legend) {
        if (relayoutChildren)
            legend->setNeedsLayout(true);
        legend->layoutIfNeeded();

        int xPos;
        if (style()->direction() == RTL) {
            switch (legend->style()->textAlign()) {
                case LEFT:
                    xPos = borderLeft() + paddingLeft();
                    break;
                case CENTER:
                    xPos = (width() - legend->width()) / 2;
                    break;
                default:
                    xPos = width() - paddingRight() - borderRight() - legend->width() - legend->marginRight();
            }
        } else {
            switch (legend->style()->textAlign()) {
                case RIGHT:
                    xPos = width() - paddingRight() - borderRight() - legend->width();
                    break;
                case CENTER:
                    xPos = (width() - legend->width()) / 2;
                    break;
                default:
                    xPos = borderLeft() + paddingLeft() + legend->marginLeft();
            }
        }
        int b = borderTop();
        int h = legend->height();
        legend->setLocation(xPos, max((b-h)/2, 0));
        setHeight(max(b, h) + paddingTop());
    }
    return legend;
}
Пример #8
0
void RenderGrid::layoutGridItems()
{
    Vector<GridTrack> columnTracks, rowTracks;
    computedUsedBreadthOfGridTracks(ForColumns, columnTracks);
    // FIXME: The logical width of Grid Columns from the prior step is used in
    // the formatting of Grid items in content-sized Grid Rows to determine
    // their required height. We will probably need to pass columns through.
    computedUsedBreadthOfGridTracks(ForRows, rowTracks);

    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);
        // FIXME: Grid items should stretch to fill their cells. Once we
        // implement grid-{column,row}-align, we can also shrink to fit. For
        // now, just size as if we were a regular child.
        child->layoutIfNeeded();

        // FIXME: Handle border & padding on the grid element.
        child->setLogicalLocation(childPosition);
    }

    // FIXME: Handle border & padding on the grid element.
    for (size_t i = 0; i < rowTracks.size(); ++i)
        setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
}
Пример #9
0
void RenderMathMLRow::computeLineVerticalStretch(LayoutUnit& ascent, LayoutUnit& descent)
{
    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (is<RenderMathMLBlock>(child)) {
            auto* renderOperator = downcast<RenderMathMLBlock>(child)->unembellishedOperator();
            if (renderOperator && renderOperator->hasOperatorFlag(MathMLOperatorDictionary::Stretchy))
                continue;
        }

        child->layoutIfNeeded();

        LayoutUnit childHeightAboveBaseline = ascentForChild(*child);
        LayoutUnit childDepthBelowBaseline = child->logicalHeight() - childHeightAboveBaseline;

        ascent = std::max(ascent, childHeightAboveBaseline);
        descent = std::max(descent, childDepthBelowBaseline);
    }

    // We ensure a minimal stretch size.
    if (ascent + descent <= 0) {
        ascent = style().fontSize();
        descent = 0;
    }
}
void RenderTextControlSingleLine::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;

    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    RenderTextControlInnerBlock* innerTextRenderer = innerTextElement()->renderer();
    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;

    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
    if (innerTextRenderer && !innerTextRenderer->style().logicalHeight().isAuto()) {
        innerTextRenderer->style().setLogicalHeight(Length(Auto));
        setNeedsLayoutOnAncestors(innerTextRenderer, this);
    }
    if (innerBlockRenderer && !innerBlockRenderer->style().logicalHeight().isAuto()) {
        innerBlockRenderer->style().setLogicalHeight(Length(Auto));
        setNeedsLayoutOnAncestors(innerBlockRenderer, this);
    }

    RenderBlockFlow::layoutBlock(false);

    HTMLElement* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
    LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
    if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
        if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
            setNeedsLayout(MarkOnlyThis);

        m_desiredInnerTextLogicalHeight = desiredLogicalHeight;

        innerTextRenderer->style().setLogicalHeight(Length(desiredLogicalHeight, Fixed));
        innerTextRenderer->setNeedsLayout(MarkOnlyThis);
        if (innerBlockRenderer) {
            innerBlockRenderer->style().setLogicalHeight(Length(desiredLogicalHeight, Fixed));
            innerBlockRenderer->setNeedsLayout(MarkOnlyThis);
        }
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight();
        if (containerLogicalHeight > logicalHeightLimit) {
            containerRenderer->style().setLogicalHeight(Length(logicalHeightLimit, Fixed));
            setNeedsLayout(MarkOnlyThis);
        } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) {
            containerRenderer->style().setLogicalHeight(Length(contentLogicalHeight(), Fixed));
            setNeedsLayout(MarkOnlyThis);
        } else
            containerRenderer->style().setLogicalHeight(Length(containerLogicalHeight, Fixed));
    }

    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
    if (needsLayout())
        RenderBlockFlow::layoutBlock(true);

    // Center the child block in the block progression direction (vertical centering for horizontal text fields).
    if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight())
        centerRenderer(*innerTextRenderer);
    else
        centerContainerIfNeeded(containerRenderer);

    // Ignores the paddings for the inner spin button.
    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
        RenderBox* parentBox = innerSpinBox->parentBox();
        if (containerRenderer && !containerRenderer->style().isLeftToRightDirection())
            innerSpinBox->setLogicalLocation(LayoutPoint(-paddingLogicalLeft(), -paddingBefore()));
        else
            innerSpinBox->setLogicalLocation(LayoutPoint(parentBox->logicalWidth() - innerSpinBox->logicalWidth() + paddingLogicalRight(), -paddingBefore()));
        innerSpinBox->setLogicalHeight(logicalHeight() - borderBefore() - borderAfter());
    }

    HTMLElement* placeholderElement = inputElement().placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        LayoutSize innerTextSize;
        if (innerTextRenderer)
            innerTextSize = innerTextRenderer->size();
        placeholderBox->style().setWidth(Length(innerTextSize.width() - placeholderBox->horizontalBorderAndPaddingExtent(), Fixed));
        placeholderBox->style().setHeight(Length(innerTextSize.height() - placeholderBox->verticalBorderAndPaddingExtent(), Fixed));
        bool neededLayout = placeholderBox->needsLayout();
        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset;
        if (innerTextRenderer)
            textOffset = innerTextRenderer->location();
        if (innerBlockElement() && innerBlockElement()->renderBox())
            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);

        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
            // This assumes a shadow tree without floats. If floats are added, the
            // logic should be shared with RenderBlock::layoutBlockChild.
            placeholderBox->repaint();
        }
        // The placeholder gets layout last, after the parent text control and its other children,
        // so in order to get the correct overflow from the placeholder we need to recompute it now.
        if (neededLayout)
            computeOverflow(clientLogicalBottom());
    }

#if PLATFORM(IOS)
    // FIXME: We should not be adjusting styles during layout. <rdar://problem/7675493>
    if (inputElement().isSearchField())
        RenderThemeIOS::adjustRoundBorderRadius(style(), *this);
#endif
}
Пример #11
0
void RenderTextControlSingleLine::layout()
{
    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    LayoutUnit oldHeight = height();
    computeLogicalHeight();

    LayoutUnit oldWidth = width();
    computeLogicalWidth();

    bool relayoutChildren = oldHeight != height() || oldWidth != width();

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    ASSERT(innerTextRenderer);
    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;
    HTMLElement* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredHeight = textBlockHeight();
    LayoutUnit currentHeight = innerTextRenderer->height();

    LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight();
    if (currentHeight > heightLimit) {
        if (desiredHeight != currentHeight)
            relayoutChildren = true;
        innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
        m_desiredInnerTextHeight = desiredHeight;
        if (innerBlockRenderer)
            innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerHeight = containerRenderer->height();
        if (containerHeight > heightLimit) {
            containerRenderer->style()->setHeight(Length(heightLimit, Fixed));
            relayoutChildren = true;
        } else if (containerRenderer->height() < contentHeight()) {
            containerRenderer->style()->setHeight(Length(contentHeight(), Fixed));
            relayoutChildren = true;
        } else
            containerRenderer->style()->setHeight(Length(containerHeight, Fixed));
    }

    RenderBlock::layoutBlock(relayoutChildren);

    // Center the child block vertically
    currentHeight = innerTextRenderer->height();
    if (!container && currentHeight != contentHeight()) {
        LayoutUnit heightDiff = currentHeight - contentHeight();
        innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
    } else if (inputElement()->isSearchField() && containerRenderer && containerRenderer->height() > contentHeight()) {
        // A quirk for find-in-page box on Safari Windows.
        // http://webkit.org/b/63157
        LayoutUnit heightDiff = containerRenderer->height() - contentHeight();
        containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
    }

    // Ignores the paddings for the inner spin button.
    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
        RenderBox* parentBox = innerSpinBox->parentBox();
        if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
            innerSpinBox->setLocation(LayoutPoint(-paddingLeft(), -paddingTop()));
        else
            innerSpinBox->setLocation(LayoutPoint(parentBox->width() - innerSpinBox->width() + paddingRight(), -paddingTop()));
        innerSpinBox->setHeight(height() - borderTop() - borderBottom());
    }

    HTMLElement* placeholderElement = inputElement()->placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed));
        placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed));
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset = innerTextRenderer->location();
        if (innerBlockElement() && innerBlockElement()->renderBox())
            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);
    }
}
Пример #12
0
void RenderSlider::layout()
{
    ASSERT(needsLayout());

    RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0;

    IntSize baseSize(borderLeft() + paddingLeft() + paddingRight() + borderRight(),
        borderTop() + paddingTop() + paddingBottom() + borderBottom());

    if (thumb) {
        // Allow the theme to set the size of the thumb.
        if (thumb->style()->hasAppearance()) {
            // FIXME: This should pass the style, not the renderer, to the theme.
            theme()->adjustSliderThumbSize(thumb);
        }

        baseSize.expand(thumb->style()->width().calcMinValue(0), thumb->style()->height().calcMinValue(0));
    }

    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());

    IntSize oldSize = size();

    setSize(baseSize);
    calcWidth();
    calcHeight();

    IntRect overflowRect(IntPoint(), size());

    if (thumb) {
        if (oldSize != size())
            thumb->setChildNeedsLayout(true, false);

        LayoutStateMaintainer statePusher(view(), this, size());

        IntRect oldThumbRect = thumb->frameRect();

        thumb->layoutIfNeeded();

        IntRect thumbRect;

        thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
        thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));

        double fraction = sliderPosition(static_cast<HTMLInputElement*>(node()));
        IntRect contentRect = contentBoxRect();
        if (style()->appearance() == SliderVerticalPart) {
            thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2);
            thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction)));
        } else {
            thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction));
            thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2);
        }

        thumb->setFrameRect(thumbRect);

        if (thumb->checkForRepaintDuringLayout())
            thumb->repaintDuringLayoutIfMoved(oldThumbRect);

        statePusher.pop();

        IntRect thumbOverflowRect = thumb->overflowRect();
        thumbOverflowRect.move(thumb->x(), thumb->y());
        overflowRect.unite(thumbOverflowRect);
    }

    // FIXME: m_overflowWidth and m_overflowHeight should be renamed
    // m_overflowRight and m_overflowBottom.
    m_overflowLeft = overflowRect.x();
    m_overflowTop = overflowRect.y();
    m_overflowWidth = overflowRect.right();
    m_overflowHeight = overflowRect.bottom();

    repainter.repaintAfterLayout();    

    setNeedsLayout(false);
}
void RenderTextControlSingleLine::layout()
{
    SubtreeLayoutScope layoutScope(this);

    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    RenderBox* viewPortRenderer = editingViewPortElement() ? editingViewPortElement()->renderBox() : 0;

    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
    if (innerTextRenderer && !innerTextRenderer->style()->logicalHeight().isAuto()) {
        innerTextRenderer->style()->setLogicalHeight(Length(Auto));
        layoutScope.setNeedsLayout(innerTextRenderer);
    }
    if (viewPortRenderer && !viewPortRenderer->style()->logicalHeight().isAuto()) {
        viewPortRenderer->style()->setLogicalHeight(Length(Auto));
        layoutScope.setNeedsLayout(viewPortRenderer);
    }

    RenderBlockFlow::layoutBlock(false);

    Element* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
    LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
    if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
        if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
            layoutScope.setNeedsLayout(this);

        m_desiredInnerTextLogicalHeight = desiredLogicalHeight;

        innerTextRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
        layoutScope.setNeedsLayout(innerTextRenderer);
        if (viewPortRenderer) {
            viewPortRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
            layoutScope.setNeedsLayout(viewPortRenderer);
        }
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight();
        if (containerLogicalHeight > logicalHeightLimit) {
            containerRenderer->style()->setLogicalHeight(Length(logicalHeightLimit, Fixed));
            layoutScope.setNeedsLayout(this);
        } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) {
            containerRenderer->style()->setLogicalHeight(Length(contentLogicalHeight(), Fixed));
            layoutScope.setNeedsLayout(this);
        } else
            containerRenderer->style()->setLogicalHeight(Length(containerLogicalHeight, Fixed));
    }

    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
    if (needsLayout())
        RenderBlockFlow::layoutBlock(true);

    // Center the child block in the block progression direction (vertical centering for horizontal text fields).
    if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight()) {
        LayoutUnit logicalHeightDiff = innerTextRenderer->logicalHeight() - contentLogicalHeight();
        innerTextRenderer->setLogicalTop(innerTextRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
    } else
        centerContainerIfNeeded(containerRenderer);

    HTMLElement* placeholderElement = inputElement()->placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        LayoutSize innerTextSize;

        if (innerTextRenderer)
            innerTextSize = innerTextRenderer->size();
        placeholderBox->style()->setWidth(Length(innerTextSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed));
        placeholderBox->style()->setHeight(Length(innerTextSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed));
        bool neededLayout = placeholderBox->needsLayout();
        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset;
        if (innerTextRenderer)
            textOffset = innerTextRenderer->location();
        if (editingViewPortElement() && editingViewPortElement()->renderBox())
            textOffset += toLayoutSize(editingViewPortElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);

        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
            // This assumes a shadow tree without floats. If floats are added, the
            // logic should be shared with RenderBlockFlow::layoutBlockChild.
            placeholderBox->repaint();
        }
        // The placeholder gets layout last, after the parent text control and its other children,
        // so in order to get the correct overflow from the placeholder we need to recompute it now.
        if (neededLayout)
            computeOverflow(clientLogicalBottom());
    }
}
Пример #14
0
void RenderTextControlSingleLine::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;

    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
    ASSERT(innerTextRenderer);
    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;

    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
    innerTextRenderer->style()->setHeight(Length(Auto));
    if (innerBlockRenderer)
        innerBlockRenderer->style()->setHeight(Length(Auto));

    RenderBlock::layoutBlock(false);

    HTMLElement* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredHeight = textBlockHeight();
    LayoutUnit currentHeight = innerTextRenderer->height();

    LayoutUnit heightLimit = computeHeightLimit();
    if (currentHeight > heightLimit) {
        if (desiredHeight != currentHeight)
            setNeedsLayout(true, MarkOnlyThis);

        innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
        m_desiredInnerTextHeight = desiredHeight;
        if (innerBlockRenderer)
            innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerHeight = containerRenderer->height();
        if (containerHeight > heightLimit) {
            containerRenderer->style()->setHeight(Length(heightLimit, Fixed));
            setNeedsLayout(true, MarkOnlyThis);
        } else if (containerRenderer->height() < contentHeight()) {
            containerRenderer->style()->setHeight(Length(contentHeight(), Fixed));
            setNeedsLayout(true, MarkOnlyThis);
        } else
            containerRenderer->style()->setHeight(Length(containerHeight, Fixed));
    }

    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
    if (needsLayout())
        RenderBlock::layoutBlock(true);

    // Center the child block vertically
    currentHeight = innerTextRenderer->height();
    if (!container && currentHeight != contentHeight()) {
        LayoutUnit heightDiff = currentHeight - contentHeight();
        innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
    } else
        centerContainerIfNeeded(containerRenderer);

    // Ignores the paddings for the inner spin button.
    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
        RenderBox* parentBox = innerSpinBox->parentBox();
        if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
            innerSpinBox->setLocation(LayoutPoint(-paddingLeft(), -paddingTop()));
        else
            innerSpinBox->setLocation(LayoutPoint(parentBox->width() - innerSpinBox->width() + paddingRight(), -paddingTop()));
        innerSpinBox->setHeight(height() - borderTop() - borderBottom());
    }

    HTMLElement* placeholderElement = inputElement()->placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed));
        placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed));
        bool neededLayout = placeholderBox->needsLayout();
        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset = innerTextRenderer->location();
        if (innerBlockElement() && innerBlockElement()->renderBox())
            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);

        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
            // This assumes a shadow tree without floats. If floats are added, the
            // logic should be shared with RenderBlock::layoutBlockChild.
            placeholderBox->repaint();
        }
        // The placeholder gets layout last, after the parent text control and its other children,
        // so in order to get the correct overflow from the placeholder we need to recompute it now.
        if (neededLayout)
            computeOverflow(clientLogicalBottom());
    }
}
Пример #15
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;
}
Пример #16
0
RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
{
    RenderBox* legend = findLegend();
    if (legend) {
        if (relayoutChildren)
            legend->setNeedsLayout(true);
        legend->layoutIfNeeded();

        LayoutUnit logicalLeft;
        if (style()->isLeftToRightDirection()) {
            switch (legend->style()->textAlign()) {
            case CENTER:
                logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
                break;
            case RIGHT:
                logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
                break;
            default:
                logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
                break;
            }
        } else {
            switch (legend->style()->textAlign()) {
            case LEFT:
                logicalLeft = borderStart() + paddingStart();
                break;
            case CENTER: {
                // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
                // in LTR).
                LayoutUnit centeredWidth = logicalWidth() - logicalWidthForChild(legend);
                logicalLeft = centeredWidth - centeredWidth / 2;
                break;
            }
            default:
                logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
                break;
            }
        }

        setLogicalLeftForChild(legend, logicalLeft);

        LayoutUnit fieldsetBorderBefore = borderBefore();
        LayoutUnit legendLogicalHeight = logicalHeightForChild(legend);

        LayoutUnit legendLogicalTop;
        LayoutUnit collapsedLegendExtent;
        // FIXME: We need to account for the legend's margin before too.
        if (fieldsetBorderBefore > legendLogicalHeight) {
            // The <legend> is smaller than the associated fieldset before border
            // so the latter determines positioning of the <legend>. The sizing depends
            // on the legend's margins as we want to still follow the author's cues.
            // Firefox completely ignores the margins in this case which seems wrong.
            legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
            collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(legend));
        } else
            collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(legend);

        setLogicalTopForChild(legend, legendLogicalTop);
        setLogicalHeight(paddingBefore() + collapsedLegendExtent);
    }
    return legend;
}