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); }
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); }
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; }
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()); }
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; }
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); }
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 }
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); } }
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()); } }
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()); } }
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; }
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; }