| Index: third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
|
| index 1af7515adb104d99aa17dda22498d3289939bd56..9ef8dc2b46ff70a141f3c227213fb7d8eafe93ac 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
|
| @@ -25,6 +25,7 @@
|
|
|
| #include "core/CSSPropertyNames.h"
|
| #include "core/HTMLNames.h"
|
| +#include "core/dom/AXObjectCache.h"
|
| #include "core/html/HTMLLegendElement.h"
|
| #include "core/paint/FieldsetPainter.h"
|
|
|
| @@ -34,27 +35,83 @@ namespace blink {
|
|
|
| using namespace HTMLNames;
|
|
|
| +namespace {
|
| +
|
| +void setInnerBlockPadding(bool isHorizontalWritingMode, const LayoutObject* innerBlock, const LayoutUnit& padding)
|
| +{
|
| + if (isHorizontalWritingMode)
|
| + innerBlock->mutableStyleRef().setPaddingTop(Length(padding, Fixed));
|
| + else
|
| + innerBlock->mutableStyleRef().setPaddingLeft(Length(padding, Fixed));
|
| +}
|
| +
|
| +void resetInnerBlockPadding(bool isHorizontalWritingMode, const LayoutObject* innerBlock)
|
| +{
|
| + if (isHorizontalWritingMode)
|
| + innerBlock->mutableStyleRef().setPaddingTop(Length(0, Fixed));
|
| + else
|
| + innerBlock->mutableStyleRef().setPaddingLeft(Length(0, Fixed));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| LayoutFieldset::LayoutFieldset(Element* element)
|
| - : LayoutBlockFlow(element)
|
| + : LayoutFlexibleBox(element)
|
| + , m_innerBlock(nullptr)
|
| +{
|
| +}
|
| +
|
| +int LayoutFieldset::baselinePosition(FontBaseline baseline, bool firstLine, LineDirectionMode direction, LinePositionMode position) const
|
| {
|
| + return LayoutBlock::baselinePosition(baseline, firstLine, direction, position);
|
| }
|
|
|
| -void LayoutFieldset::computePreferredLogicalWidths()
|
| +void LayoutFieldset::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
|
| {
|
| - LayoutBlockFlow::computePreferredLogicalWidths();
|
| - if (LayoutBox* legend = findInFlowLegend()) {
|
| - int legendMinWidth = legend->minPreferredLogicalWidth();
|
| + for (LayoutBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
|
| + if (child->isOutOfFlowPositioned())
|
| + continue;
|
| +
|
| + LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*child);
|
| +
|
| + LayoutUnit minPreferredLogicalWidth;
|
| + LayoutUnit maxPreferredLogicalWidth;
|
| + computeChildPreferredLogicalWidths(*child, minPreferredLogicalWidth, maxPreferredLogicalWidth);
|
| + DCHECK_GE(minPreferredLogicalWidth, LayoutUnit());
|
| + DCHECK_GE(maxPreferredLogicalWidth, LayoutUnit());
|
| + minPreferredLogicalWidth += margin;
|
| + maxPreferredLogicalWidth += margin;
|
| + minLogicalWidth = std::max(minPreferredLogicalWidth, minLogicalWidth);
|
| + maxLogicalWidth = std::max(maxPreferredLogicalWidth, maxLogicalWidth);
|
| + }
|
|
|
| - Length legendMarginLeft = legend->style()->marginLeft();
|
| - Length legendMarginRight = legend->style()->marginRight();
|
| + maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
|
|
|
| - if (legendMarginLeft.isFixed())
|
| - legendMinWidth += legendMarginLeft.value();
|
| + // Due to negative margins, it is possible that we calculated a negative intrinsic width. Make sure that we
|
| + // never return a negative width.
|
| + minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
|
| + maxLogicalWidth = std::max(LayoutUnit(), maxLogicalWidth);
|
|
|
| - if (legendMarginRight.isFixed())
|
| - legendMinWidth += legendMarginRight.value();
|
| + LayoutUnit scrollbarWidth(scrollbarLogicalWidth());
|
| + maxLogicalWidth += scrollbarWidth;
|
| + minLogicalWidth += scrollbarWidth;
|
| +}
|
| +
|
| +void LayoutFieldset::setLogicalLeftForChild(LayoutBox& child, LayoutUnit logicalLeft)
|
| +{
|
| + if (isHorizontalWritingMode()) {
|
| + child.setX(logicalLeft);
|
| + } else {
|
| + child.setY(logicalLeft);
|
| + }
|
| +}
|
|
|
| - m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWidth + borderAndPaddingWidth());
|
| +void LayoutFieldset::setLogicalTopForChild(LayoutBox& child, LayoutUnit logicalTop)
|
| +{
|
| + if (isHorizontalWritingMode()) {
|
| + child.setY(logicalTop);
|
| + } else {
|
| + child.setX(logicalTop);
|
| }
|
| }
|
|
|
| @@ -106,6 +163,7 @@ LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren,
|
|
|
| LayoutUnit legendLogicalTop;
|
| LayoutUnit collapsedLegendExtent;
|
| + LayoutUnit innerBlockPadding;
|
| // 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
|
| @@ -114,16 +172,22 @@ LayoutObject* LayoutFieldset::layoutSpecialExcludedChild(bool relayoutChildren,
|
| // Firefox completely ignores the margins in this case which seems wrong.
|
| legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
|
| collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(*legend));
|
| + innerBlockPadding = marginAfterForChild(*legend) ? marginAfterForChild(*legend) - legendLogicalTop : LayoutUnit();
|
| } else {
|
| collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(*legend);
|
| + innerBlockPadding = legendLogicalHeight - borderAfter() + marginAfterForChild(*legend);
|
| }
|
|
|
| + if (m_innerBlock)
|
| + setInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock, innerBlockPadding);
|
| setLogicalTopForChild(*legend, legendLogicalTop);
|
| setLogicalHeight(paddingBefore() + collapsedLegendExtent);
|
|
|
| if (legend->frameRect() != oldLegendFrameRect) {
|
| // We need to invalidate the fieldset border if the legend's frame changed.
|
| setShouldDoFullPaintInvalidation();
|
| + if (m_innerBlock)
|
| + m_innerBlock->setNeedsLayout(LayoutInvalidationReason::FieldsetChanged, MarkOnlyThis);
|
| }
|
| }
|
| return legend;
|
| @@ -153,4 +217,66 @@ void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa
|
| FieldsetPainter(*this).paintMask(paintInfo, paintOffset);
|
| }
|
|
|
| +void LayoutFieldset::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
|
| +{
|
| + LayoutFlexibleBox::styleDidChange(diff, oldStyle);
|
| +}
|
| +
|
| +void LayoutFieldset::updateAnonymousChildStyle(const LayoutObject& child, ComputedStyle& childStyle) const
|
| +{
|
| + childStyle.setFlexShrink(1.0f);
|
| + childStyle.setFlexGrow(1.0f);
|
| + // min-width: 0; is needed for correct shrinking.
|
| + childStyle.setMinWidth(Length(0, Fixed));
|
| + childStyle.setFlexDirection(style()->flexDirection());
|
| + childStyle.setJustifyContent(style()->justifyContent());
|
| + childStyle.setFlexWrap(style()->flexWrap());
|
| + childStyle.setAlignItems(style()->alignItems());
|
| + childStyle.setAlignContent(style()->alignContent());
|
| + // Let anonymous block to be the 1st for correct layout positioning.
|
| + childStyle.setOrder(1);
|
| +}
|
| +
|
| +void LayoutFieldset::addChild(LayoutObject* newChild, LayoutObject* beforeChild)
|
| +{
|
| + if (!m_innerBlock)
|
| + createInnerBlock();
|
| +
|
| + if (isHTMLLegendElement(newChild->node())) {
|
| + // Let legend block to be the 2nd for correct layout positioning.
|
| + newChild->mutableStyle()->setOrder(2);
|
| + LayoutFlexibleBox::addChild(newChild, m_innerBlock);
|
| + } else {
|
| + m_innerBlock->addChild(newChild, beforeChild);
|
| + if (AXObjectCache* cache = document().existingAXObjectCache())
|
| + cache->childrenChanged(this);
|
| + }
|
| +}
|
| +
|
| +void LayoutFieldset::createInnerBlock()
|
| +{
|
| + if (m_innerBlock) {
|
| + DCHECK(firstChild() == m_innerBlock);
|
| + return;
|
| + }
|
| + m_innerBlock = createAnonymousBlock(style()->display());
|
| + LayoutFlexibleBox::addChild(m_innerBlock);
|
| +}
|
| +
|
| +void LayoutFieldset::removeChild(LayoutObject* oldChild)
|
| +{
|
| + if (isHTMLLegendElement(oldChild->node())) {
|
| + LayoutFlexibleBox::removeChild(oldChild);
|
| + if (m_innerBlock)
|
| + resetInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock);
|
| + } else if (oldChild == m_innerBlock) {
|
| + LayoutFlexibleBox::removeChild(oldChild);
|
| + m_innerBlock = nullptr;
|
| + } else if (oldChild->parent() == this) {
|
| + LayoutFlexibleBox::removeChild(oldChild);
|
| + } else if (m_innerBlock) {
|
| + m_innerBlock->removeChild(oldChild);
|
| + }
|
| +}
|
| +
|
| } // namespace blink
|
|
|