Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutFieldset.cpp

Issue 2215133005: Add grid/flex layout support for <fieldset> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed more ClusterFuzz tests Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 93b43a8cf4a1d18ce98c3a02bc47b474edc5acb4..be509a6a4acaa6ca698f72c54cc557230490500c 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().toInt();
+ 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,68 @@ void LayoutFieldset::paintMask(const PaintInfo& paintInfo, const LayoutPoint& pa
FieldsetPainter(*this).paintMask(paintInfo, paintOffset);
}
+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 {
+ if (beforeChild && isHTMLLegendElement(beforeChild->node())) {
+ m_innerBlock->addChild(newChild);
+ } 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);
+ m_innerBlock->setNeedsLayout(LayoutInvalidationReason::FieldsetChanged, MarkOnlyThis);
+ }
+ setShouldDoFullPaintInvalidation();
+ } 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutFieldset.h ('k') | third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698