Enable fieldsets to be flexboxes, grids and multicolumn.
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Mar 2017 18:00:35 +0000 (18:00 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Mar 2017 18:00:35 +0000 (18:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169082

Source/WebCore:

Reviewed by Simon Fraser .

Added new tests in fast/forms/fieldset.

This patch eliminates RenderFieldset and moves the functionality into RenderBlock so that
derived classes can also be fieldsets.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
Remove RenderFieldset from the project.

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::titleUIElement):
Call in to RenderBlock now instead of RenderFieldset.

* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::createElementRenderer):
* html/HTMLFieldSetElement.h:
The fieldset DOM element now uses RenderElement::createFor to make renderers so that multiple display types
can be supported. A special flag has been added that indicates only to make flexbox and block-related
renderers (not table display types).

* rendering/OrderIterator.cpp:
(WebCore::OrderIterator::shouldSkipChild):
(WebCore::OrderIteratorPopulator::collectChild):
* rendering/OrderIterator.h:
Streamline child collection for flexboxes and grids to indicate whether the child should be skipped as a return
value from collectChild. Add a shouldSkipChild method that skips both out of flow positioned objects and
excluded children like the legends of fieldsets.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlockRareData::RenderBlockRareData):
When the legend is taller than the fieldset's borderBefore(), intrinsic border is added to the CSS border width.
This intrinsic border being factored in ensures that the padding and content boxes of fieldsets are correct
across any layout system, since the legend is now just treated as part of the border.

(WebCore::RenderBlock::computePreferredLogicalWidths):
(WebCore::RenderBlock::computeBlockPreferredLogicalWidths):
Call the new computePreferredWidthsForExcludedChildren to ensure that excluded children contribute to
preferred width in their own way and not as part of a specific layout system.

(WebCore::RenderBlock::renderName):
Hacked to still return RenderFieldSet for RenderBlockFlow-backed fieldsets for layout test compatibility.

(WebCore::RenderBlock::layoutExcludedChildren):
Renamed from layoutSpecialExcludedChild to more accurately reflect the fact that multiple excluded children
can be included here (e.g., both a multicolumn flow thread and a legend). The RenderBlock base class handles
the layout of legends by both placing them and setting the correct intrinsic border before amount on the
block.

(WebCore::RenderBlock::findFieldsetLegend):
Moved from RenderFieldset.

(WebCore::RenderBlock::adjustBorderBoxRectForPainting):
(WebCore::RenderBlock::paintRectToClipOutFromBorder):
These methods are used when painting to shrink the border box as needed to account for the legend and to
provide the portion of the border that needs to be clipped out. These methods have been enhanced to
properly support all writing modes.

(WebCore::RenderBlock::intrinsicBorderForFieldset):
(WebCore::RenderBlock::setIntrinsicBorderForFieldset):
(WebCore::RenderBlock::borderTop):
(WebCore::RenderBlock::borderLeft):
(WebCore::RenderBlock::borderBottom):
(WebCore::RenderBlock::borderRight):
(WebCore::RenderBlock::borderBefore):
These methods are overridden for border to ensure that the intrinsic border added by a tall legend is
properly factored in.

(WebCore::RenderBlock::computePreferredWidthsForExcludedChildren):
* rendering/RenderBlock.h:
This method computes the preferred widths for legend children in order to ensure that the legend properly
grows the width of the fieldset when it is the widest item.

(WebCore::RenderBlock::adjustBorderBoxLogicalHeightForBoxSizing):
(WebCore::RenderBlock::adjustContentBoxLogicalHeightForBoxSizing):
Preserve the behavior of fieldsets in that the available content size includes the space lost accounting
for the legend. I don't think this makes much sense, but it matches the behavior of other browsers
(and our old behavior).

(WebCore::RenderBlock::paintExcludedChildrenInBorder):
Method for painting the excluded children that might be present in our border. We only do this if the
paint phase is a box decoration painting phase and if the legend isn't self-painting.

* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::willCreateColumns):
Allow fieldsets to create columns now.

(WebCore::RenderBlockFlow::layoutBlockChildren):
(WebCore::RenderBlockFlow::layoutExcludedChildren):
Renamed this method and change it to call the base class to ensure that legends in multicolumn fieldsets
get handled properly.

(WebCore::RenderBlockFlow::addChild):
Patched to make sure legends don't get put into the multicolumn flow thread, as they need to
remain outside of it.

(WebCore::RenderBlockFlow::layoutSpecialExcludedChild): Deleted.
Renamed to layoutExcludedChildren.

* rendering/RenderBlockFlow.h:
* rendering/RenderBox.cpp:
(WebCore::RenderBox::paintBoxDecorations):
(WebCore::RenderBox::paintMask):
Patched to call the new adjustBorderBoxRectForPainting and paintRectToClipOutFromBorder methods in
order to properly shrink the border box rect for painting and to clip out the portion of the border
covered by the legend.

(WebCore::RenderBox::avoidsFloats):
Add fieldsets as avoiding floats. RenderFieldset used to subclass this method to return true, but with
its removal, we need to put this in the base class along with legends.

* rendering/RenderBox.h:
(WebCore::RenderBox::isGridItem):
(WebCore::RenderBox::isFlexItem):
Patched to exclude legends so that they don't try to size like they are really in the grid or flexbox.

(WebCore::RenderBox::adjustBorderBoxRectForPainting):
This method is overridden by RenderBLock to handle adjusting fieldset border rects for painting.

* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintBorder):
* rendering/RenderBoxModelObject.h:
(WebCore::RenderBoxModelObject::paintRectToClipOutFromBorder):
Patched to properly paint fieldsets using the new helpers.

* rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::FlexBoxIterator::next):
(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
(WebCore::RenderDeprecatedFlexibleBox::layoutHorizontalBox):
Make sure deprecated flexible boxes lay out their legends properly by calling layoutExcludedChildren.

* rendering/RenderElement.cpp:
(WebCore::RenderElement::createFor):
* rendering/RenderElement.h:
Patched to take a flag that limits what renderers can be created so that fieldsets don't make table
display types.

* rendering/RenderFieldset.cpp: Removed.
* rendering/RenderFieldset.h: Removed.
Remove RenderFieldset files from the tree.

* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::computeIntrinsicLogicalWidths):
(WebCore::RenderFlexibleBox::firstLineBaseline):
(WebCore::RenderFlexibleBox::layoutBlock):
(WebCore::RenderFlexibleBox::layoutFlexItems):
(WebCore::RenderFlexibleBox::prepareOrderIteratorAndMargins):
Make sure flexible boxes lay out their legends properly by calling layoutExcludedChildren.
Patch methods to use the OrderIterator's new shouldSkipChild method to ensure legends aren't
part of the flexible box layout.

* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::layoutBlock):
(WebCore::RenderGrid::computeIntrinsicLogicalWidths):
(WebCore::RenderGrid::placeItemsOnGrid):
(WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
(WebCore::RenderGrid::layoutGridItems):
Make sure grids lay out their legends properly by calling layoutExcludedChildren.
Patch methods to use the OrderIterator's new shouldSkipChild method to ensure legends aren't
part of the grid's layout.

* rendering/RenderMultiColumnFlowThread.cpp:
(WebCore::RenderMultiColumnFlowThread::populate):
Pull legends back up into the block and don't let them be part of the flow thread.

* rendering/RenderMultiColumnSet.cpp:
(WebCore::RenderMultiColumnSet::requiresBalancing):
Fix an assert to allow legends to exist as siblings of multicolumn sets.

* rendering/RenderObject.cpp:
(WebCore::RenderObject::isFieldset):
Changed to examine the HTML element rather than RenderFieldset.

* rendering/RenderObject.h:
(WebCore::RenderObject::isExcludedFromNormalLayout):
(WebCore::RenderObject::setIsExcludedFromNormalLayout):
(WebCore::RenderObject::RenderObjectBitfields::RenderObjectBitfields):
RenderObjects now have a new bit that is set for excluded objects like legends, flow threads,
placeholders, and ruby text. This bit lets code easily detect that an object is excluded from
the layout system and can be skipped.

(WebCore::RenderObject::isExcludedAndPlacedInBorder):
Helper method for asking if an object is painting inside the border. Used to know we
need to factor it into preferred width calculations outside of any one layout system
and also to know that we need to paint it when we paint the fieldset's border instead of
later (after we might have scrolled or clipped the child painting area).

* rendering/RenderRubyRun.cpp:
(WebCore::RenderRubyRun::layoutExcludedChildren):
(WebCore::RenderRubyRun::layoutSpecialExcludedChild): Deleted.
* rendering/RenderRubyRun.h:
Rename layoutSpecialExcludedChild to layoutExcludedChildren.

* rendering/RenderTable.cpp:
(WebCore::RenderTable::adjustBorderBoxRectForPainting):
(WebCore::RenderTable::paintBoxDecorations):
(WebCore::RenderTable::paintMask):
(WebCore::RenderTable::subtractCaptionRect): Deleted.
* rendering/RenderTable.h:
Patched tables to share the same border box rect adjustment used by fieldsets when subtracting
out captions. This is prep work to allow tables to be fieldsets, but for now I didn't go all the
way.

* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::paintBoxDecorations):
(WebCore::RenderTableCell::paintMask):
Make sure table cells adjust their border box rects for painting. Again this is prep work for
cells potentially being fieldsets, but not supported yet.

* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::layoutExcludedChildren):
(WebCore::RenderTextControl::layoutSpecialExcludedChild): Deleted.
* rendering/RenderTextControl.h:
* rendering/RenderTextControlMultiLine.cpp:
(WebCore::RenderTextControlMultiLine::layoutExcludedChildren):
(WebCore::RenderTextControlMultiLine::layoutSpecialExcludedChild): Deleted.
* rendering/RenderTextControlMultiLine.h:
Renamed the methods for doing the excluded child layout.

* rendering/RenderTreeAsText.cpp:
(WebCore::RenderTreeAsText::writeRenderObject):
Make sure to dump the original fieldset border and not the border with the extra legend stuff in it.

LayoutTests:

Reviewed by Simon Fraser.

* fast/forms/fieldset/abs-pos-child-sizing-expected.html: Added.
* fast/forms/fieldset/abs-pos-child-sizing.html: Added.
* fast/forms/fieldset/fieldset-deprecated-flexbox-expected.html: Added.
* fast/forms/fieldset/fieldset-deprecated-flexbox.html: Added.
* fast/forms/fieldset/fieldset-flexbox-expected.html: Added.
* fast/forms/fieldset/fieldset-flexbox.html: Added.
* fast/forms/fieldset/fieldset-grid-expected.html: Added.
* fast/forms/fieldset/fieldset-grid.html: Added.
* fast/forms/fieldset/fieldset-multicolumn-expected.html: Added.
* fast/forms/fieldset/fieldset-multicolumn.html: Added.
* fast/forms/fieldset/fieldset-overflow-auto-expected.html: Added.
* fast/forms/fieldset/fieldset-overflow-auto.html: Added.
* fast/forms/fieldset/fieldset-overflow-hidden-expected.html: Added.
* fast/forms/fieldset/fieldset-overflow-hidden.html: Added.
* fast/forms/fieldset/fieldset-positioned-children-expected.html: Added.
* fast/forms/fieldset/fieldset-positioned-children.html: Added.
* fast/forms/fieldset/fieldset-positioned-legend-expected.html: Added.
* fast/forms/fieldset/fieldset-positioned-legend.html: Added.
* fast/forms/fieldset/fieldset-self-painting-legend-expected.html: Added.
* fast/forms/fieldset/fieldset-self-painting-legend.html: Added.
* fast/forms/fieldset/fieldset-writing-modes-expected.html: Added.
* fast/forms/fieldset/fieldset-writing-modes.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213455 268f45cc-cd09-0410-ab3c-d52691b4dbfc

62 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/forms/fieldset/abs-pos-child-sizing-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/abs-pos-child-sizing.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-flexbox-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-flexbox.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-grid-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-grid.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-multicolumn-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-multicolumn.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-overflow-auto-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-overflow-auto.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-positioned-children-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-positioned-children.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-positioned-legend-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-positioned-legend.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-writing-modes-expected.html [new file with mode: 0644]
LayoutTests/fast/forms/fieldset/fieldset-writing-modes.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
Source/WebCore/html/HTMLFieldSetElement.cpp
Source/WebCore/html/HTMLFieldSetElement.h
Source/WebCore/rendering/OrderIterator.cpp
Source/WebCore/rendering/OrderIterator.h
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBlock.h
Source/WebCore/rendering/RenderBlockFlow.cpp
Source/WebCore/rendering/RenderBlockFlow.h
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderBoxModelObject.h
Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderElement.h
Source/WebCore/rendering/RenderFieldset.cpp [deleted file]
Source/WebCore/rendering/RenderFieldset.h [deleted file]
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
Source/WebCore/rendering/RenderMultiColumnSet.cpp
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderObject.h
Source/WebCore/rendering/RenderRubyRun.cpp
Source/WebCore/rendering/RenderRubyRun.h
Source/WebCore/rendering/RenderTable.cpp
Source/WebCore/rendering/RenderTable.h
Source/WebCore/rendering/RenderTableCell.cpp
Source/WebCore/rendering/RenderTextControl.cpp
Source/WebCore/rendering/RenderTextControl.h
Source/WebCore/rendering/RenderTextControlMultiLine.cpp
Source/WebCore/rendering/RenderTextControlMultiLine.h
Source/WebCore/rendering/RenderTreeAsText.cpp
Source/WebCore/rendering/RenderingAllInOne.cpp

index bd0ccd4..add2ff5 100644 (file)
@@ -1,3 +1,33 @@
+2017-03-06  Dave Hyatt  <hyatt@apple.com>
+
+        Enable fieldsets to be flexboxes, grids and multicolumn.
+        https://bugs.webkit.org/show_bug.cgi?id=169082
+
+        Reviewed by Simon Fraser.
+
+        * fast/forms/fieldset/abs-pos-child-sizing-expected.html: Added.
+        * fast/forms/fieldset/abs-pos-child-sizing.html: Added.
+        * fast/forms/fieldset/fieldset-deprecated-flexbox-expected.html: Added.
+        * fast/forms/fieldset/fieldset-deprecated-flexbox.html: Added.
+        * fast/forms/fieldset/fieldset-flexbox-expected.html: Added.
+        * fast/forms/fieldset/fieldset-flexbox.html: Added.
+        * fast/forms/fieldset/fieldset-grid-expected.html: Added.
+        * fast/forms/fieldset/fieldset-grid.html: Added.
+        * fast/forms/fieldset/fieldset-multicolumn-expected.html: Added.
+        * fast/forms/fieldset/fieldset-multicolumn.html: Added.
+        * fast/forms/fieldset/fieldset-overflow-auto-expected.html: Added.
+        * fast/forms/fieldset/fieldset-overflow-auto.html: Added.
+        * fast/forms/fieldset/fieldset-overflow-hidden-expected.html: Added.
+        * fast/forms/fieldset/fieldset-overflow-hidden.html: Added.
+        * fast/forms/fieldset/fieldset-positioned-children-expected.html: Added.
+        * fast/forms/fieldset/fieldset-positioned-children.html: Added.
+        * fast/forms/fieldset/fieldset-positioned-legend-expected.html: Added.
+        * fast/forms/fieldset/fieldset-positioned-legend.html: Added.
+        * fast/forms/fieldset/fieldset-self-painting-legend-expected.html: Added.
+        * fast/forms/fieldset/fieldset-self-painting-legend.html: Added.
+        * fast/forms/fieldset/fieldset-writing-modes-expected.html: Added.
+        * fast/forms/fieldset/fieldset-writing-modes.html: Added.
+
 2017-03-06  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Tracks panel should clip and scroll content when numerous tracks are available
diff --git a/LayoutTests/fast/forms/fieldset/abs-pos-child-sizing-expected.html b/LayoutTests/fast/forms/fieldset/abs-pos-child-sizing-expected.html
new file mode 100644 (file)
index 0000000..6120d1e
--- /dev/null
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html><head>
+    <meta charset="utf-8">
+        <style type="text/css">
+            html,body {
+                color:black; background-color:white; font-size:16px; padding:0; margin:0;
+            }
+        
+        div {
+            position: absolute;
+            background: rgba(0,255,0,0.5);
+            top:0; bottom:0;
+            left:0; right:0;
+            z-index: 0;
+        }
+        c {
+            display: block;
+            background: blue;
+            height:100%;
+        }
+        
+        legend { height: 24px; }
+        
+        fieldset {
+            position: absolute;
+            border: 2px green solid;
+            width: 100px;
+            height: 100px;
+            margin-bottom:40px;
+        }
+        
+        #t1,#t3 { padding: 3px 5px 7px 11px; }
+        #t2,#t4 { padding: 0; }
+        
+        #t1 div, #t3 div {
+            /* same numbers as padding above */
+            left: -11px; right: -5px;
+            top:  -3px;  bottom:-7px;
+        }
+        
+        #t2 { top: 120px; }
+        #t3 { top: 240px; }
+        #t4 { top: 360px; }
+        
+        x {
+            position: absolute;
+            width:100px;
+            height:100px;
+        }
+        #t1 x, #t2 x {
+            height:78px; /* compensate for legend */
+        }
+        </style>
+</head>
+<body>
+    
+    
+    <fieldset id="t1">
+        <legend>legend</legend>
+        <x><div></div><c></c></x>
+    </fieldset>
+    
+    <fieldset id="t2">
+        <legend>legend</legend>
+        <x><div></div></x>
+    </fieldset>
+    
+    <fieldset id="t3">
+        <x><div></div><c></c></x>
+    </fieldset>
+    
+    <fieldset id="t4">
+        <x><div></div></x>
+    </fieldset>
+    
+    
+</body>
+</html>
+
diff --git a/LayoutTests/fast/forms/fieldset/abs-pos-child-sizing.html b/LayoutTests/fast/forms/fieldset/abs-pos-child-sizing.html
new file mode 100644 (file)
index 0000000..7647537
--- /dev/null
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html><head>
+    <meta charset="utf-8">
+        <style type="text/css">
+            html,body {
+                color:black; background-color:white; font-size:16px; padding:0; margin:0;
+            }
+        
+        div {
+            position: absolute;
+            background: rgba(0,255,0,0.5);
+            top:0; bottom:0;
+            left:0; right:0;
+            z-index: 0;
+        }
+        c {
+            display: block;
+            background: blue;
+            height:100%;
+        }
+        
+        legend { height: 24px; }
+        
+        fieldset {
+            position: absolute;
+            border: 2px green solid;
+            width: 100px;
+            height: 100px;
+            margin-bottom:40px;
+        }
+        
+        #t1,#t3 { padding: 3px 5px 7px 11px; }
+        #t2,#t4 { padding: 0; }
+        
+        #t2 { top: 120px; }
+        #t3 { top: 240px; }
+        #t4 { top: 360px; }
+            </style>
+</head>
+<body>
+    
+    
+    <fieldset id="t1">
+        <legend>legend</legend>
+        <div></div><c></c>
+    </fieldset>
+    
+    <fieldset id="t2">
+        <legend>legend</legend>
+        <div></div>
+    </fieldset>
+    
+    <fieldset id="t3">
+        <div></div><c></c>
+    </fieldset>
+    
+    <fieldset id="t4">
+        <div></div>
+    </fieldset>
+    
+    
+</body>
+</html>
+
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox-expected.html
new file mode 100644 (file)
index 0000000..8b56810
--- /dev/null
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { margin:0; vertical-align:bottom; -webkit-logical-width:320px; -webkit-logical-height:80px; display:flex; justify-content: center; align-items: stretch; background-color:#dddddd; border:12px solid navy; padding:28px }
+            </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend</legend>
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </fieldset>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox.html b/LayoutTests/fast/forms/fieldset/fieldset-deprecated-flexbox.html
new file mode 100644 (file)
index 0000000..d106771
--- /dev/null
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { margin:0; vertical-align:bottom; -webkit-logical-width:320px; -webkit-logical-height:80px; display:-webkit-inline-box; -webkit-box-pack: center; -webkit-box-align: stretch; background-color:#dddddd; border:12px solid navy; padding:28px }
+            </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend</legend>
+           <div>Fieldset Contents</div>
+           
+           <div>More Fieldset Contents</div>
+           
+       </fieldset>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-flexbox-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-flexbox-expected.html
new file mode 100644 (file)
index 0000000..a615244
--- /dev/null
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .fieldset > div { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            .fieldset { margin:0; vertical-align:bottom; -webkit-logical-width:320px; -webkit-logical-height:80px; display:inline-flex; justify-content: center; align-items: stretch; background-color:#dddddd; border:12px solid navy; padding:28px }
+            </style>
+    </head>
+    <body>
+        <div class=fieldset style="writing-mode:vertical-lr;">
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </div>
+        
+        <div class=fieldset style="writing-mode:vertical-rl; ">
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </div>
+        
+        
+        <div class=fieldset style="writing-mode:horizontal-bt">
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-flexbox.html b/LayoutTests/fast/forms/fieldset/fieldset-flexbox.html
new file mode 100644 (file)
index 0000000..8d28d71
--- /dev/null
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { margin:0; vertical-align:bottom; -webkit-logical-width:320px; -webkit-logical-height:80px; display:inline-flex; justify-content: center; align-items: stretch; background-color:#dddddd; border:12px solid navy; padding:28px }
+            </style>
+    </head>
+    <body>
+        <fieldset style="writing-mode:vertical-lr;">
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </fieldset>
+
+        <fieldset style="writing-mode:vertical-rl; ">
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </fieldset>
+        
+        
+       <fieldset style="writing-mode:horizontal-bt">
+           <div>Fieldset Contents</div>
+           
+           <div>More Fieldset Contents</div>
+           
+       </fieldset>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-grid-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-grid-expected.html
new file mode 100644 (file)
index 0000000..9067642
--- /dev/null
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+    <body>
+        <fieldset style="overflow:hidden; width:200px; height:200px;">
+            <legend>Legend</legend>
+            <div style="display:grid; grid-template-columns: repeat(4,50px); grid-auto-rows: 20px;">
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+            </div>
+        </fieldset>
+        <fieldset>
+            <legend>Legend</legend>
+            <div style="display:grid; grid-auto-columns: 50px; grid-auto-rows: 20px;">
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+                <p>X
+            </div>
+        </fieldset>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-grid.html b/LayoutTests/fast/forms/fieldset/fieldset-grid.html
new file mode 100644 (file)
index 0000000..af41bc4
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+    <body>
+        <fieldset style="display:grid; overflow:hidden; grid-template-columns: repeat(4,50px); grid-auto-rows: 20px; width:200px; height:200px;">
+            <legend>Legend</legend>
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+        </fieldset>
+        <fieldset style="display:grid; grid-auto-columns: 50px; grid-auto-rows: 20px;">
+            <legend>Legend</legend>
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+            <p>X
+        </fieldset>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-multicolumn-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-multicolumn-expected.html
new file mode 100644 (file)
index 0000000..1ad02ab
--- /dev/null
@@ -0,0 +1,14 @@
+<fieldset style="float:left"><legend style="font-size:48px">Legend Title</legend>
+    <div style="columns:2;">
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    </div>
+</fieldset>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-multicolumn.html b/LayoutTests/fast/forms/fieldset/fieldset-multicolumn.html
new file mode 100644 (file)
index 0000000..b377df6
--- /dev/null
@@ -0,0 +1,12 @@
+<fieldset style="columns:2;float:left"><legend style="font-size:48px">Legend Title</legend>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+    This content should be in two columns. It really should be.<br>
+</fieldset>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-overflow-auto-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-overflow-auto-expected.html
new file mode 100644 (file)
index 0000000..d5e7d92
--- /dev/null
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px }
+            .fieldset { vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block;  padding:40px; -webkit-padding-before:0}
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px; -webkit-margin-after:34px;background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .behind-box { position:absolute; border:12px solid navy; z-index:-1 }
+            #scroll { overflow:auto; position:absolute;bottom:0;left:0;right:0; top:80px; bottom:12px; right:12px; left:12px; padding:28px 28px 0 28px  }
+        </style>
+    </head>
+    <body>
+        <div class=fieldset>
+            <div class="behind-box" style="left:0; top:34px; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div id=scroll>
+                
+            <div class=contents>Fieldset Contents</div>
+            
+                <div class=contents>More Fieldset Contents</div>
+            <div class=contents>More Fieldset Contents</div>
+            <div class=contents>More Fieldset Contents</div>
+            <div class=contents>More Fieldset Contents</div>
+            <div class=contents>More Fieldset Contents</div>
+            <div class=contents style="margin-bottom:0">More Fieldset Contents</div>
+            
+            </div>
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-overflow-auto.html b/LayoutTests/fast/forms/fieldset/fieldset-overflow-auto.html
new file mode 100644 (file)
index 0000000..56068be
--- /dev/null
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset div:not(.positioned) { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { overflow:auto; position:relative; margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; border:12px solid navy; padding:28px }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .positioned { height:0 }
+        </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend Title</legend>
+            
+            <div class=positioned>
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            </div>
+            
+        </fieldset>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden-expected.html
new file mode 100644 (file)
index 0000000..5b64707
--- /dev/null
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px }
+            .fieldset { vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block;  padding:40px; -webkit-padding-before:0}
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px; -webkit-margin-after:34px;background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .behind-box { position:absolute; border:12px solid navy; z-index:-1 }
+           
+        </style>
+    </head>
+    <body>
+        <div class=fieldset>
+            <div class="behind-box" style="left:0; top:34px; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden.html b/LayoutTests/fast/forms/fieldset/fieldset-overflow-hidden.html
new file mode 100644 (file)
index 0000000..24626af
--- /dev/null
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div:not(.positioned) { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { overflow:hidden; position:relative; margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; border:12px solid navy; padding:28px }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            
+        </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            
+        </fieldset>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-positioned-children-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-positioned-children-expected.html
new file mode 100644 (file)
index 0000000..e306172
--- /dev/null
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px }
+            .fieldset { vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block;  padding:40px; -webkit-padding-before:0}
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px; -webkit-margin-after:34px;background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .behind-box { position:absolute; border:12px solid navy; z-index:-1 }
+            .positioned { position:absolute; top:90px; bottom:22px; right:22px; left:22px; background-color:darkblue; z-index:-1 }
+        </style>
+    </head>
+    <body>
+        <div class=fieldset>
+            <div class="behind-box" style="left:0; top:34px; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+            <div class="positioned"></div>
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-positioned-children.html b/LayoutTests/fast/forms/fieldset/fieldset-positioned-children.html
new file mode 100644 (file)
index 0000000..1817d22
--- /dev/null
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div:not(.positioned) { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { position:relative; margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; border:12px solid navy; padding:28px }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .positioned { position:absolute; top:10px; bottom:10px; right:10px; left:10px; background-color:darkblue; z-index:-1 }
+        </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            <div class=positioned></div>
+        </fieldset>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-positioned-legend-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-positioned-legend-expected.html
new file mode 100644 (file)
index 0000000..273d53f
--- /dev/null
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px;  }
+            .fieldset { position:relative; vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block;   border:12px solid navy; padding:28px; }
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px;background-color:#3080f080; border:8px solid lightblue; font-size:48px; position:absolute;bottom:0;right:0; position:absolute }
+            .behind-box { position:absolute;; z-index:-1;  }
+           
+        </style>
+    </head>
+    <body>
+        <div class=fieldset>
+            <div class="behind-box" style="left:0; top:34px; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-positioned-legend.html b/LayoutTests/fast/forms/fieldset/fieldset-positioned-legend.html
new file mode 100644 (file)
index 0000000..a5046a3
--- /dev/null
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div:not(.positioned) { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px;   }
+            fieldset { position:relative; margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; border:12px solid navy; padding:28px; }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f080; border:8px solid lightblue; font-size:48px; position:absolute;bottom:0;right:0 }
+            
+        </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            
+        </fieldset>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend-expected.html
new file mode 100644 (file)
index 0000000..13fb13e
--- /dev/null
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px;  }
+            .fieldset { vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block;  padding:40px; -webkit-padding-before:0;  }
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px; -webkit-margin-after:34px;background-color:#3080f080; border:8px solid lightblue; font-size:48px; transform:translateX(10px) }
+            .behind-box { position:absolute; border:12px solid navy; z-index:-1; border-top:12px solid transparent }
+           
+        </style>
+    </head>
+    <body>
+        <div class=fieldset>
+            <div class="behind-box" style="left:0; top:34px; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+            
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend.html b/LayoutTests/fast/forms/fieldset/fieldset-self-painting-legend.html
new file mode 100644 (file)
index 0000000..0577cc0
--- /dev/null
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div:not(.positioned) { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px;   }
+            fieldset { position:relative; margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; border:12px solid navy; padding:28px; border-top:12px solid transparent }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f080; border:8px solid lightblue; font-size:48px; transform:translateX(10px); }
+            
+        </style>
+    </head>
+    <body>
+        <fieldset>
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+            
+        </fieldset>
+
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-writing-modes-expected.html b/LayoutTests/fast/forms/fieldset/fieldset-writing-modes-expected.html
new file mode 100644 (file)
index 0000000..a07428a
--- /dev/null
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            .contents { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px }
+            .fieldset { vertical-align:bottom; -webkit-logical-width:320px; position:relative; display:inline-block; writing-mode:vertical-rl; padding:40px; -webkit-padding-before:0}
+            .legend {  -webkit-logical-height:64px; -webkit-logical-width: 284px; -webkit-margin-after:34px;background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+            .behind-box { position:absolute; background-color:#dddddd; border:12px solid navy; z-index:-1 }
+        </style>
+    </head>
+    <body>
+        <div class=fieldset style="writing-mode:vertical-lr">
+            <div class="behind-box" style="left:34px; top:0; right:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+        </div>
+        
+        <div class=fieldset style="writing-mode:vertical-rl;">
+            <div class="behind-box" style="right:34px; top:0; left:0; bottom:0;"></div>
+            <div class=legend>Legend Title</div>
+            
+            <div class=contents>Fieldset Contents</div>
+            
+            <div class=contents>More Fieldset Contents</div>
+            
+        </div>
+        
+        
+       
+       <div class=fieldset style="writing-mode:horizontal-bt">
+           <div class="behind-box" style="bottom:34px; top:0; right:0; left:0;"></div>
+           <div class=legend>Legend Title</div>
+           
+           <div class=contents>Fieldset Contents</div>
+           
+           <div class=contents>More Fieldset Contents</div>
+           
+       </div>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/fieldset/fieldset-writing-modes.html b/LayoutTests/fast/forms/fieldset/fieldset-writing-modes.html
new file mode 100644 (file)
index 0000000..897c09f
--- /dev/null
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+    <head>
+        <style>
+            fieldset > div { border:2px solid skyblue; background-color:#cccccc; -webkit-margin-before:6px; -webkit-margin-after:6px  }
+            fieldset { margin:0; vertical-align:bottom; -webkit-logical-width:320px; display:inline-block; background-color:#dddddd; border:12px solid navy; padding:28px }
+            legend { padding:0; -webkit-logical-height:64px; -webkit-logical-width: 284px; background-color:#3080f0; border:8px solid lightblue; font-size:48px }
+        </style>
+    </head>
+    <body>
+        <fieldset style="writing-mode:vertical-lr;">
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </fieldset>
+
+        <fieldset style="writing-mode:vertical-rl; ">
+            <legend>Legend Title</legend>
+            
+            <div>Fieldset Contents</div>
+            
+            <div>More Fieldset Contents</div>
+            
+        </fieldset>
+        
+        
+       <fieldset style="writing-mode:horizontal-bt">
+           <legend>Legend Title</legend>
+           
+           <div>Fieldset Contents</div>
+           
+           <div>More Fieldset Contents</div>
+           
+       </fieldset>
+    </body>
+</html>
index 2aa9905..dd2aa7b 100644 (file)
@@ -2422,7 +2422,6 @@ set(WebCore_SOURCES
     rendering/RenderDetailsMarker.cpp
     rendering/RenderElement.cpp
     rendering/RenderEmbeddedObject.cpp
-    rendering/RenderFieldset.cpp
     rendering/RenderFileUploadControl.cpp
     rendering/RenderFlexibleBox.cpp
     rendering/RenderFlowThread.cpp
index 4396b82..1300973 100644 (file)
@@ -1,3 +1,232 @@
+2017-03-06  Dave Hyatt  <hyatt@apple.com>
+
+        Enable fieldsets to be flexboxes, grids and multicolumn.
+        https://bugs.webkit.org/show_bug.cgi?id=169082
+
+        Reviewed by Simon Fraser .
+
+        Added new tests in fast/forms/fieldset.
+
+        This patch eliminates RenderFieldset and moves the functionality into RenderBlock so that
+        derived classes can also be fieldsets.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Remove RenderFieldset from the project.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::titleUIElement):
+        Call in to RenderBlock now instead of RenderFieldset.
+
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::createElementRenderer):
+        * html/HTMLFieldSetElement.h:
+        The fieldset DOM element now uses RenderElement::createFor to make renderers so that multiple display types
+        can be supported. A special flag has been added that indicates only to make flexbox and block-related
+        renderers (not table display types).
+
+        * rendering/OrderIterator.cpp:
+        (WebCore::OrderIterator::shouldSkipChild):
+        (WebCore::OrderIteratorPopulator::collectChild):
+        * rendering/OrderIterator.h:
+        Streamline child collection for flexboxes and grids to indicate whether the child should be skipped as a return
+        value from collectChild. Add a shouldSkipChild method that skips both out of flow positioned objects and
+        excluded children like the legends of fieldsets.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlockRareData::RenderBlockRareData):
+        When the legend is taller than the fieldset's borderBefore(), intrinsic border is added to the CSS border width.
+        This intrinsic border being factored in ensures that the padding and content boxes of fieldsets are correct
+        across any layout system, since the legend is now just treated as part of the border.
+
+        (WebCore::RenderBlock::computePreferredLogicalWidths):
+        (WebCore::RenderBlock::computeBlockPreferredLogicalWidths):
+        Call the new computePreferredWidthsForExcludedChildren to ensure that excluded children contribute to
+        preferred width in their own way and not as part of a specific layout system.
+
+        (WebCore::RenderBlock::renderName):
+        Hacked to still return RenderFieldSet for RenderBlockFlow-backed fieldsets for layout test compatibility.
+
+        (WebCore::RenderBlock::layoutExcludedChildren):
+        Renamed from layoutSpecialExcludedChild to more accurately reflect the fact that multiple excluded children
+        can be included here (e.g., both a multicolumn flow thread and a legend). The RenderBlock base class handles
+        the layout of legends by both placing them and setting the correct intrinsic border before amount on the
+        block.
+
+        (WebCore::RenderBlock::findFieldsetLegend):
+        Moved from RenderFieldset.
+
+        (WebCore::RenderBlock::adjustBorderBoxRectForPainting):
+        (WebCore::RenderBlock::paintRectToClipOutFromBorder):
+        These methods are used when painting to shrink the border box as needed to account for the legend and to
+        provide the portion of the border that needs to be clipped out. These methods have been enhanced to
+        properly support all writing modes.
+
+        (WebCore::RenderBlock::intrinsicBorderForFieldset):
+        (WebCore::RenderBlock::setIntrinsicBorderForFieldset):
+        (WebCore::RenderBlock::borderTop):
+        (WebCore::RenderBlock::borderLeft):
+        (WebCore::RenderBlock::borderBottom):
+        (WebCore::RenderBlock::borderRight):
+        (WebCore::RenderBlock::borderBefore):
+        These methods are overridden for border to ensure that the intrinsic border added by a tall legend is
+        properly factored in.
+
+        (WebCore::RenderBlock::computePreferredWidthsForExcludedChildren):
+        * rendering/RenderBlock.h:
+        This method computes the preferred widths for legend children in order to ensure that the legend properly
+        grows the width of the fieldset when it is the widest item.
+
+        (WebCore::RenderBlock::adjustBorderBoxLogicalHeightForBoxSizing):
+        (WebCore::RenderBlock::adjustContentBoxLogicalHeightForBoxSizing):
+        Preserve the behavior of fieldsets in that the available content size includes the space lost accounting
+        for the legend. I don't think this makes much sense, but it matches the behavior of other browsers
+        (and our old behavior).
+
+        (WebCore::RenderBlock::paintExcludedChildrenInBorder):
+        Method for painting the excluded children that might be present in our border. We only do this if the
+        paint phase is a box decoration painting phase and if the legend isn't self-painting.
+
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::willCreateColumns):
+        Allow fieldsets to create columns now.
+
+        (WebCore::RenderBlockFlow::layoutBlockChildren):
+        (WebCore::RenderBlockFlow::layoutExcludedChildren):
+        Renamed this method and change it to call the base class to ensure that legends in multicolumn fieldsets
+        get handled properly.
+
+        (WebCore::RenderBlockFlow::addChild):
+        Patched to make sure legends don't get put into the multicolumn flow thread, as they need to
+        remain outside of it.
+
+        (WebCore::RenderBlockFlow::layoutSpecialExcludedChild): Deleted.
+        Renamed to layoutExcludedChildren.
+
+        * rendering/RenderBlockFlow.h:
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintBoxDecorations):
+        (WebCore::RenderBox::paintMask):
+        Patched to call the new adjustBorderBoxRectForPainting and paintRectToClipOutFromBorder methods in
+        order to properly shrink the border box rect for painting and to clip out the portion of the border
+        covered by the legend.
+
+        (WebCore::RenderBox::avoidsFloats):
+        Add fieldsets as avoiding floats. RenderFieldset used to subclass this method to return true, but with
+        its removal, we need to put this in the base class along with legends.
+
+        * rendering/RenderBox.h:
+        (WebCore::RenderBox::isGridItem):
+        (WebCore::RenderBox::isFlexItem):
+        Patched to exclude legends so that they don't try to size like they are really in the grid or flexbox.
+
+        (WebCore::RenderBox::adjustBorderBoxRectForPainting):
+        This method is overridden by RenderBLock to handle adjusting fieldset border rects for painting.
+
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintBorder):
+        * rendering/RenderBoxModelObject.h:
+        (WebCore::RenderBoxModelObject::paintRectToClipOutFromBorder):
+        Patched to properly paint fieldsets using the new helpers.
+
+        * rendering/RenderDeprecatedFlexibleBox.cpp:
+        (WebCore::FlexBoxIterator::next):
+        (WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
+        (WebCore::RenderDeprecatedFlexibleBox::layoutHorizontalBox):
+        Make sure deprecated flexible boxes lay out their legends properly by calling layoutExcludedChildren.
+
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::createFor):
+        * rendering/RenderElement.h:
+        Patched to take a flag that limits what renderers can be created so that fieldsets don't make table
+        display types.
+
+        * rendering/RenderFieldset.cpp: Removed.
+        * rendering/RenderFieldset.h: Removed.
+        Remove RenderFieldset files from the tree.
+
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::computeIntrinsicLogicalWidths):
+        (WebCore::RenderFlexibleBox::firstLineBaseline):
+        (WebCore::RenderFlexibleBox::layoutBlock):
+        (WebCore::RenderFlexibleBox::layoutFlexItems):
+        (WebCore::RenderFlexibleBox::prepareOrderIteratorAndMargins):
+        Make sure flexible boxes lay out their legends properly by calling layoutExcludedChildren.
+        Patch methods to use the OrderIterator's new shouldSkipChild method to ensure legends aren't
+        part of the flexible box layout.
+
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::layoutBlock):
+        (WebCore::RenderGrid::computeIntrinsicLogicalWidths):
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        (WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
+        (WebCore::RenderGrid::layoutGridItems):
+        Make sure grids lay out their legends properly by calling layoutExcludedChildren.
+        Patch methods to use the OrderIterator's new shouldSkipChild method to ensure legends aren't
+        part of the grid's layout.
+
+        * rendering/RenderMultiColumnFlowThread.cpp:
+        (WebCore::RenderMultiColumnFlowThread::populate):
+        Pull legends back up into the block and don't let them be part of the flow thread.
+
+        * rendering/RenderMultiColumnSet.cpp:
+        (WebCore::RenderMultiColumnSet::requiresBalancing):
+        Fix an assert to allow legends to exist as siblings of multicolumn sets.
+
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::isFieldset):
+        Changed to examine the HTML element rather than RenderFieldset.
+
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::isExcludedFromNormalLayout):
+        (WebCore::RenderObject::setIsExcludedFromNormalLayout):
+        (WebCore::RenderObject::RenderObjectBitfields::RenderObjectBitfields):
+        RenderObjects now have a new bit that is set for excluded objects like legends, flow threads,
+        placeholders, and ruby text. This bit lets code easily detect that an object is excluded from
+        the layout system and can be skipped.
+
+        (WebCore::RenderObject::isExcludedAndPlacedInBorder):
+        Helper method for asking if an object is painting inside the border. Used to know we
+        need to factor it into preferred width calculations outside of any one layout system
+        and also to know that we need to paint it when we paint the fieldset's border instead of
+        later (after we might have scrolled or clipped the child painting area).
+
+        * rendering/RenderRubyRun.cpp:
+        (WebCore::RenderRubyRun::layoutExcludedChildren):
+        (WebCore::RenderRubyRun::layoutSpecialExcludedChild): Deleted.
+        * rendering/RenderRubyRun.h:
+        Rename layoutSpecialExcludedChild to layoutExcludedChildren.
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::adjustBorderBoxRectForPainting):
+        (WebCore::RenderTable::paintBoxDecorations):
+        (WebCore::RenderTable::paintMask):
+        (WebCore::RenderTable::subtractCaptionRect): Deleted.
+        * rendering/RenderTable.h:
+        Patched tables to share the same border box rect adjustment used by fieldsets when subtracting
+        out captions. This is prep work to allow tables to be fieldsets, but for now I didn't go all the
+        way.
+
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::paintBoxDecorations):
+        (WebCore::RenderTableCell::paintMask):
+        Make sure table cells adjust their border box rects for painting. Again this is prep work for
+        cells potentially being fieldsets, but not supported yet.
+
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::layoutExcludedChildren):
+        (WebCore::RenderTextControl::layoutSpecialExcludedChild): Deleted.
+        * rendering/RenderTextControl.h:
+        * rendering/RenderTextControlMultiLine.cpp:
+        (WebCore::RenderTextControlMultiLine::layoutExcludedChildren):
+        (WebCore::RenderTextControlMultiLine::layoutSpecialExcludedChild): Deleted.
+        * rendering/RenderTextControlMultiLine.h:
+        Renamed the methods for doing the excluded child layout.
+
+        * rendering/RenderTreeAsText.cpp:
+        (WebCore::RenderTreeAsText::writeRenderObject):
+        Make sure to dump the original fieldset border and not the border with the extra legend stuff in it.
+
 2017-03-06  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Tracks panel should clip and scroll content when numerous tracks are available
index b0e668d..19d0c77 100644 (file)
                A8DF4AEF0980C42C0052981B /* RenderTableSection.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF4AE50980C42C0052981B /* RenderTableSection.h */; };
                A8DF4AF00980C42C0052981B /* RenderTableRow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DF4AE60980C42C0052981B /* RenderTableRow.cpp */; };
                A8DF4AF10980C42C0052981B /* RenderTableCol.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF4AE70980C42C0052981B /* RenderTableCol.h */; };
-               A8EA73C30A1900E300A8EF5F /* RenderFieldset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8EA73AF0A1900E300A8EF5F /* RenderFieldset.cpp */; };
-               A8EA73C40A1900E300A8EF5F /* RenderFieldset.h in Headers */ = {isa = PBXBuildFile; fileRef = A8EA73B00A1900E300A8EF5F /* RenderFieldset.h */; };
                A8EA79F10A1916DF00A8EF5F /* HTMLOListElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A8EA79E50A1916DF00A8EF5F /* HTMLOListElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A8EA79F20A1916DF00A8EF5F /* HTMLUListElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A8EA79E60A1916DF00A8EF5F /* HTMLUListElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A8EA79F30A1916DF00A8EF5F /* HTMLUListElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8EA79E70A1916DF00A8EF5F /* HTMLUListElement.cpp */; };
                A8DF4AE50980C42C0052981B /* RenderTableSection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderTableSection.h; sourceTree = "<group>"; };
                A8DF4AE60980C42C0052981B /* RenderTableRow.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTableRow.cpp; sourceTree = "<group>"; };
                A8DF4AE70980C42C0052981B /* RenderTableCol.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderTableCol.h; sourceTree = "<group>"; };
-               A8EA73AF0A1900E300A8EF5F /* RenderFieldset.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderFieldset.cpp; sourceTree = "<group>"; };
-               A8EA73B00A1900E300A8EF5F /* RenderFieldset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderFieldset.h; sourceTree = "<group>"; };
                A8EA79E50A1916DF00A8EF5F /* HTMLOListElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLOListElement.h; sourceTree = "<group>"; };
                A8EA79E60A1916DF00A8EF5F /* HTMLUListElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLUListElement.h; sourceTree = "<group>"; };
                A8EA79E70A1916DF00A8EF5F /* HTMLUListElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLUListElement.cpp; sourceTree = "<group>"; };
                                E43A023A17EB370A004CDD25 /* RenderElement.h */,
                                0F5B7A5210F65D7A00376302 /* RenderEmbeddedObject.cpp */,
                                0F5B7A5310F65D7A00376302 /* RenderEmbeddedObject.h */,
-                               A8EA73AF0A1900E300A8EF5F /* RenderFieldset.cpp */,
-                               A8EA73B00A1900E300A8EF5F /* RenderFieldset.h */,
                                066C772E0AB603FD00238CC4 /* RenderFileUploadControl.cpp */,
                                066C772F0AB603FD00238CC4 /* RenderFileUploadControl.h */,
                                53C8298B13D8D92700DE2DEB /* RenderFlexibleBox.cpp */,
                                9B32CDA913DF7FA900F34D13 /* RenderedPosition.h in Headers */,
                                E43A023B17EB370A004CDD25 /* RenderElement.h in Headers */,
                                0F5B7A5510F65D7A00376302 /* RenderEmbeddedObject.h in Headers */,
-                               A8EA73C40A1900E300A8EF5F /* RenderFieldset.h in Headers */,
                                066C77310AB603FD00238CC4 /* RenderFileUploadControl.h in Headers */,
                                53C8298E13D8D92700DE2DEB /* RenderFlexibleBox.h in Headers */,
                                508CCA4F13CF106B003151F3 /* RenderFlowThread.h in Headers */,
                                9B32CDAA13DF7FA900F34D13 /* RenderedPosition.cpp in Sources */,
                                E43A023D17EB3713004CDD25 /* RenderElement.cpp in Sources */,
                                0F5B7A5410F65D7A00376302 /* RenderEmbeddedObject.cpp in Sources */,
-                               A8EA73C30A1900E300A8EF5F /* RenderFieldset.cpp in Sources */,
                                066C77300AB603FD00238CC4 /* RenderFileUploadControl.cpp in Sources */,
                                53C8298D13D8D92700DE2DEB /* RenderFlexibleBox.cpp in Sources */,
                                508CCA5013CF106B003151F3 /* RenderFlowThread.cpp in Sources */,
index 9ea0872..8c6af1b 100644 (file)
@@ -68,7 +68,6 @@
 #include "Page.h"
 #include "ProgressTracker.h"
 #include "RenderButton.h"
-#include "RenderFieldset.h"
 #include "RenderFileUploadControl.h"
 #include "RenderHTMLCanvas.h"
 #include "RenderImage.h"
@@ -1081,7 +1080,7 @@ AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
     
     // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
     if (isFieldset())
-        return axObjectCache()->getOrCreate(downcast<RenderFieldset>(*m_renderer).findLegend(RenderFieldset::IncludeFloatingOrOutOfFlow));
+        return axObjectCache()->getOrCreate(downcast<RenderBlock>(*m_renderer).findFieldsetLegend(RenderBlock::FieldsetIncludeFloatingOrOutOfFlow));
     
     if (isFigure())
         return captionForFigure();
index eb73565..a3f2a2b 100644 (file)
@@ -46,7 +46,7 @@
 #include "HTMLTableElement.h"
 #include "HostWindow.h"
 #include "RenderAncestorIterator.h"
-#include "RenderFieldset.h"
+#include "RenderBlock.h"
 #include "RenderObject.h"
 #include "SVGElement.h"
 #include "Settings.h"
@@ -186,9 +186,11 @@ static void setAtkRelationSetFromCoreObject(AccessibilityObject* coreObject, Atk
         if (AccessibilityObject* label = coreObject->titleUIElement())
             atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper());
     } else if (coreObject->roleValue() == LegendRole) {
-        if (RenderFieldset* renderFieldset = ancestorsOfType<RenderFieldset>(*coreObject->renderer()).first()) {
-            AccessibilityObject* fieldset = coreObject->axObjectCache()->getOrCreate(renderFieldset);
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, fieldset->wrapper());
+        if (RenderBlock* renderFieldset = ancestorsOfType<RenderBlock>(*coreObject->renderer()).first()) {
+            if (renderFieldset->isFieldset()) {
+                AccessibilityObject* fieldset = coreObject->axObjectCache()->getOrCreate(renderFieldset);
+                atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, fieldset->wrapper());
+            }
         }
     } else if (AccessibilityObject* control = coreObject->correspondingControlForLabelElement()) {
         atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, control->wrapper());
index a79ad15..ccb70d1 100644 (file)
@@ -31,7 +31,7 @@
 #include "HTMLNames.h"
 #include "HTMLObjectElement.h"
 #include "NodeRareData.h"
-#include "RenderFieldset.h"
+#include "RenderElement.h"
 #include <wtf/StdLibExtras.h>
 
 namespace WebCore {
@@ -154,7 +154,7 @@ const AtomicString& HTMLFieldSetElement::formControlType() const
 
 RenderPtr<RenderElement> HTMLFieldSetElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
 {
-    return createRenderer<RenderFieldset>(*this, WTFMove(style));
+    return RenderElement::createFor(*this, WTFMove(style), RenderElement::OnlyCreateBlockAndFlexboxRenderers);
 }
 
 HTMLLegendElement* HTMLFieldSetElement::legend() const
index 441a218..a644f92 100644 (file)
@@ -30,7 +30,6 @@ namespace WebCore {
 
 class FormAssociatedElement;
 class HTMLFormControlsCollection;
-class RenderFieldSet;
 
 class HTMLFieldSetElement final : public HTMLFormControlElement {
 public:
@@ -47,8 +46,6 @@ public:
     void addInvalidDescendant(const HTMLFormControlElement&);
     void removeInvalidDescendant(const HTMLFormControlElement&);
 
-    RenderFieldSet* renderer() const;
-
 private:
     HTMLFieldSetElement(const QualifiedName&, Document&, HTMLFormElement*);
     ~HTMLFieldSetElement();
index b11bccc..4fab596 100644 (file)
@@ -77,14 +77,20 @@ void OrderIterator::reset()
     m_isReset = true;
 }
 
+bool OrderIterator::shouldSkipChild(const RenderObject& child) const
+{
+    return child.isOutOfFlowPositioned() || child.isExcludedFromNormalLayout();
+}
+
 OrderIteratorPopulator::~OrderIteratorPopulator()
 {
     m_iterator.reset();
 }
 
-void OrderIteratorPopulator::collectChild(const RenderBox& child)
+bool OrderIteratorPopulator::collectChild(const RenderBox& child)
 {
     m_iterator.m_orderValues.insert(child.style().order());
+    return !m_iterator.shouldSkipChild(child);
 }
 
 
index 101c618..0cfa629 100644 (file)
@@ -37,6 +37,7 @@
 namespace WebCore {
 
 class RenderBox;
+class RenderObject;
     
 class OrderIterator {
 public:
@@ -48,6 +49,8 @@ public:
     RenderBox* first();
     RenderBox* next();
 
+    bool shouldSkipChild(const RenderObject&) const;
+
 private:
     void reset();
 
@@ -69,7 +72,7 @@ public:
     }
     ~OrderIteratorPopulator();
 
-    void collectChild(const RenderBox&);
+    bool collectChild(const RenderBox&);
 
 private:
     OrderIterator& m_iterator;
index 6661cfe..44c1d78 100644 (file)
@@ -245,15 +245,13 @@ struct RenderBlockRareData {
     WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
 public:
     RenderBlockRareData()
-        : m_paginationStrut(0)
-        , m_pageLogicalOffset(0)
-        , m_flowThreadContainingBlock(std::nullopt)
     {
     }
 
     LayoutUnit m_paginationStrut;
     LayoutUnit m_pageLogicalOffset;
-
+    LayoutUnit m_intrinsicBorderForFieldset;
+    
     std::optional<RenderFlowThread*> m_flowThreadContainingBlock;
 };
 
@@ -1605,6 +1603,9 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOf
 
 bool RenderBlock::paintChild(RenderBox& child, PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect, PaintBlockType paintType)
 {
+    if (child.isExcludedAndPlacedInBorder())
+        return true;
+
     // Check for page-break-before: always, and if it's set, break and bail.
     bool checkBeforeAlways = !childrenInline() && (usePrintRect && alwaysPageBreak(child.style().breakBefore()));
     LayoutUnit absoluteChildY = paintOffset.y() + child.y();
@@ -1695,7 +1696,11 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
                 paintInfo.context().restore();
         }
     }
-
+    
+    // Paint legends just above the border before we scroll or clip.
+    if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground || paintPhase == PaintPhaseSelection)
+        paintExcludedChildrenInBorder(paintInfo, paintOffset);
+    
     if (paintPhase == PaintPhaseMask && style().visibility() == VISIBLE) {
         paintMask(paintInfo, paintOffset);
         return;
@@ -2767,9 +2772,20 @@ void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth
     RenderObject* child = firstChild();
     RenderBlock* containingBlock = this->containingBlock();
     LayoutUnit floatLeftWidth = 0, floatRightWidth = 0;
+
+    LayoutUnit childMinWidth;
+    LayoutUnit childMaxWidth;
+    bool hadExcludedChildren = computePreferredWidthsForExcludedChildren(childMinWidth, childMaxWidth);
+    if (hadExcludedChildren) {
+        minLogicalWidth = std::max(childMinWidth, minLogicalWidth);
+        maxLogicalWidth = std::max(childMaxWidth, maxLogicalWidth);
+    }
+
     while (child) {
-        // Positioned children don't affect the min/max width
-        if (child->isOutOfFlowPositioned()) {
+        // Positioned children don't affect the min/max width. Legends in fieldsets are skipped here
+        // since they compute outside of any one layout system. Other children excluded from
+        // normal layout are only used with block flows, so it's ok to calculate them here.
+        if (child->isOutOfFlowPositioned() || child->isExcludedAndPlacedInBorder()) {
             child = child->nextSibling();
             continue;
         }
@@ -3770,7 +3786,8 @@ const char* RenderBlock::renderName() const
 {
     if (isBody())
         return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
-
+    if (isFieldset())
+        return "RenderFieldSet"; // FIXME: Remove eventually, but done to keep tests from breaking.
     if (isFloating())
         return "RenderBlock (floating)";
     if (isOutOfFlowPositioned())
@@ -3902,4 +3919,267 @@ std::optional<LayoutUnit> RenderBlock::availableLogicalHeightForPercentageComput
     
     return availableHeight;
 }
+    
+void RenderBlock::layoutExcludedChildren(bool relayoutChildren)
+{
+    if (!isFieldset())
+        return;
+
+    setIntrinsicBorderForFieldset(0);
+
+    RenderBox* box = findFieldsetLegend();
+    if (!box)
+        return;
+
+    box->setIsExcludedFromNormalLayout(true);
+    for (auto& child : childrenOfType<RenderBox>(*this)) {
+        if (&child == box || !child.isLegend())
+            continue;
+        child.setIsExcludedFromNormalLayout(false);
+    }
+
+    RenderBox& legend = *box;
+    if (relayoutChildren)
+        legend.setChildNeedsLayout(MarkOnlyThis);
+    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 legendAfterMargin = marginAfterForChild(legend);
+    LayoutUnit topPositionForLegend = std::max(LayoutUnit(), (fieldsetBorderBefore - legendLogicalHeight) / 2);
+    LayoutUnit bottomPositionForLegend = topPositionForLegend + legendLogicalHeight + legendAfterMargin;
+
+    // Place the legend now.
+    setLogicalTopForChild(legend, topPositionForLegend);
+
+    // If the bottom of the legend (including its after margin) is below the fieldset border,
+    // then we need to add in sufficient intrinsic border to account for this gap.
+    // FIXME: Should we support the before margin of the legend? Not entirely clear.
+    // FIXME: Consider dropping support for the after margin of the legend. Not sure other
+    // browsers support that anyway.
+    if (bottomPositionForLegend > fieldsetBorderBefore)
+        setIntrinsicBorderForFieldset(bottomPositionForLegend - fieldsetBorderBefore);
+    
+    // Now that the legend is included in the border extent, we can set our logical height
+    // to the borderBefore (which includes the legend and its after margin if they were bigger
+    // than the actual fieldset border) and then add in our padding before.
+    setLogicalHeight(borderBefore() + paddingBefore());
+}
+
+RenderBox* RenderBlock::findFieldsetLegend(FieldsetFindLegendOption option) const
+{
+    for (auto& legend : childrenOfType<RenderBox>(*this)) {
+        if (option == FieldsetIgnoreFloatingOrOutOfFlow && legend.isFloatingOrOutOfFlowPositioned())
+            continue;
+        if (legend.isLegend())
+            return const_cast<RenderBox*>(&legend);
+    }
+    return nullptr;
+}
+
+void RenderBlock::adjustBorderBoxRectForPainting(LayoutRect& paintRect)
+{
+    if (!isFieldset() || !intrinsicBorderForFieldset())
+        return;
+    
+    auto* legend = findFieldsetLegend();
+    if (!legend)
+        return;
+
+    if (style().isHorizontalWritingMode()) {
+        LayoutUnit yOff = std::max(LayoutUnit(), (legend->height() - RenderBox::borderBefore()) / 2);
+        paintRect.setHeight(paintRect.height() - yOff);
+        if (style().writingMode() == TopToBottomWritingMode)
+            paintRect.setY(paintRect.y() + yOff);
+    } else {
+        LayoutUnit xOff = std::max(LayoutUnit(), (legend->width() - RenderBox::borderBefore()) / 2);
+        paintRect.setWidth(paintRect.width() - xOff);
+        if (style().writingMode() == LeftToRightWritingMode)
+            paintRect.setX(paintRect.x() + xOff);
+    }
+}
+
+LayoutRect RenderBlock::paintRectToClipOutFromBorder(const LayoutRect& paintRect)
+{
+    LayoutRect clipRect;
+    if (!isFieldset())
+        return clipRect;
+    auto* legend = findFieldsetLegend();
+    if (!legend)
+        return clipRect;
+
+    LayoutUnit borderExtent = RenderBox::borderBefore();
+    if (style().isHorizontalWritingMode()) {
+        clipRect.setX(paintRect.x() + legend->x());
+        clipRect.setY(style().writingMode() == TopToBottomWritingMode ? paintRect.y() : paintRect.y() + paintRect.height() - borderExtent);
+        clipRect.setWidth(legend->width());
+        clipRect.setHeight(borderExtent);
+    } else {
+        clipRect.setX(style().writingMode() == LeftToRightWritingMode ? paintRect.x() : paintRect.x() + paintRect.width() - borderExtent);
+        clipRect.setY(paintRect.y() + legend->y());
+        clipRect.setWidth(borderExtent);
+        clipRect.setHeight(legend->height());
+    }
+    return clipRect;
+}
+
+LayoutUnit RenderBlock::intrinsicBorderForFieldset() const
+{
+    auto* rareData = getBlockRareData(this);
+    return rareData ? rareData->m_intrinsicBorderForFieldset : LayoutUnit();
+}
+
+void RenderBlock::setIntrinsicBorderForFieldset(LayoutUnit padding)
+{
+    auto* rareData = getBlockRareData(this);
+    if (!rareData) {
+        if (!padding)
+            return;
+        rareData = &ensureBlockRareData(this);
+    }
+    rareData->m_intrinsicBorderForFieldset = padding;
+}
+
+LayoutUnit RenderBlock::borderTop() const
+{
+    if (style().writingMode() != TopToBottomWritingMode || !intrinsicBorderForFieldset())
+        return RenderBox::borderTop();
+    return RenderBox::borderTop() + intrinsicBorderForFieldset();
+}
+
+LayoutUnit RenderBlock::borderLeft() const
+{
+    if (style().writingMode() != LeftToRightWritingMode || !intrinsicBorderForFieldset())
+        return RenderBox::borderLeft();
+    return RenderBox::borderLeft() + intrinsicBorderForFieldset();
+}
+
+LayoutUnit RenderBlock::borderBottom() const
+{
+    if (style().writingMode() != BottomToTopWritingMode || !intrinsicBorderForFieldset())
+        return RenderBox::borderBottom();
+    return RenderBox::borderBottom() + intrinsicBorderForFieldset();
+}
+
+LayoutUnit RenderBlock::borderRight() const
+{
+    if (style().writingMode() != RightToLeftWritingMode || !intrinsicBorderForFieldset())
+        return RenderBox::borderRight();
+    return RenderBox::borderRight() + intrinsicBorderForFieldset();
+}
+
+LayoutUnit RenderBlock::borderBefore() const
+{
+    return RenderBox::borderBefore() + intrinsicBorderForFieldset();
+}
+
+bool RenderBlock::computePreferredWidthsForExcludedChildren(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
+{
+    if (!isFieldset())
+        return false;
+    
+    auto* legend = findFieldsetLegend();
+    if (!legend)
+        return false;
+    
+    legend->setIsExcludedFromNormalLayout(true);
+
+    computeChildPreferredLogicalWidths(*legend, minWidth, maxWidth);
+    
+    // These are going to be added in later, so we subtract them out to reflect the
+    // fact that the legend is outside the scrollable area.
+    auto scrollbarWidth = intrinsicScrollbarLogicalWidth();
+    minWidth -= scrollbarWidth;
+    maxWidth -= scrollbarWidth;
+    
+    const auto& childStyle = legend->style();
+    auto startMarginLength = childStyle.marginStartUsing(&style());
+    auto endMarginLength = childStyle.marginEndUsing(&style());
+    LayoutUnit margin;
+    LayoutUnit marginStart;
+    LayoutUnit marginEnd;
+    if (startMarginLength.isFixed())
+        marginStart += startMarginLength.value();
+    if (endMarginLength.isFixed())
+        marginEnd += endMarginLength.value();
+    margin = marginStart + marginEnd;
+    
+    minWidth += margin;
+    maxWidth += margin;
+
+    return true;
+}
+
+LayoutUnit RenderBlock::adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const
+{
+    // FIXME: We're doing this to match other browsers even though it's questionable.
+    // Shouldn't height:100px mean the fieldset content gets 100px of height even if the
+    // resulting fieldset becomes much taller because of the legend?
+    LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
+    if (style().boxSizing() == CONTENT_BOX)
+        return height + bordersPlusPadding - intrinsicBorderForFieldset();
+    return std::max(height, bordersPlusPadding);
+}
+
+LayoutUnit RenderBlock::adjustContentBoxLogicalHeightForBoxSizing(std::optional<LayoutUnit> height) const
+{
+    // FIXME: We're doing this to match other browsers even though it's questionable.
+    // Shouldn't height:100px mean the fieldset content gets 100px of height even if the
+    // resulting fieldset becomes much taller because of the legend?
+    if (!height)
+        return 0;
+    LayoutUnit result = height.value();
+    if (style().boxSizing() == BORDER_BOX)
+        result -= borderAndPaddingLogicalHeight();
+    else
+        result -= intrinsicBorderForFieldset();
+    return std::max(LayoutUnit(), result);
+}
+
+void RenderBlock::paintExcludedChildrenInBorder(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!isFieldset())
+        return;
+    
+    RenderBox* box = findFieldsetLegend();
+    if (!box || !box->isExcludedFromNormalLayout() || box->hasSelfPaintingLayer())
+        return;
+    
+    LayoutPoint childPoint = flipForWritingModeForChild(box, paintOffset);
+    box->paintAsInlineBlock(paintInfo, childPoint);
+}
+    
 } // namespace WebCore
index 6d955ec..fbd6083 100644 (file)
@@ -230,6 +230,20 @@ public:
     LayoutUnit pageLogicalOffset() const;
     void setPageLogicalOffset(LayoutUnit);
 
+    // Fieldset legends that are taller than the fieldset border add in intrinsic border
+    // in order to ensure that content gets properly pushed down across all layout systems
+    // (flexbox, block, etc.)
+    LayoutUnit intrinsicBorderForFieldset() const;
+    void setIntrinsicBorderForFieldset(LayoutUnit);
+    LayoutUnit borderTop() const override;
+    LayoutUnit borderBottom() const override;
+    LayoutUnit borderLeft() const override;
+    LayoutUnit borderRight() const override;
+    LayoutUnit borderBefore() const override;
+    LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const override;
+    LayoutUnit adjustContentBoxLogicalHeightForBoxSizing(std::optional<LayoutUnit> height) const override;
+    void paintExcludedChildrenInBorder(PaintInfo&, const LayoutPoint&);
+    
     // Accessors for logical width/height and margins in the containing block's block-flow direction.
     enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
     LayoutUnit logicalWidthForChild(const RenderBox& child) const { return isHorizontalWritingMode() ? child.width() : child.height(); }
@@ -383,6 +397,14 @@ public:
     // children.
     RenderBlock* firstLineBlock() const override;
 
+    enum FieldsetFindLegendOption { FieldsetIgnoreFloatingOrOutOfFlow, FieldsetIncludeFloatingOrOutOfFlow };
+    RenderBox* findFieldsetLegend(FieldsetFindLegendOption = FieldsetIgnoreFloatingOrOutOfFlow) const;
+    virtual void layoutExcludedChildren(bool /*relayoutChildren*/);
+    virtual bool computePreferredWidthsForExcludedChildren(LayoutUnit&, LayoutUnit&) const;
+    
+    void adjustBorderBoxRectForPainting(LayoutRect&) override;
+    LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) override;
+    
 protected:
     virtual void addOverflowFromChildren();
     // FIXME-BLOCKFLOW: Remove virtualization when all callers have moved to RenderBlockFlow
index 7a11c3d..f1e9724 100644 (file)
@@ -432,7 +432,7 @@ void RenderBlockFlow::computeColumnCountAndWidth()
 bool RenderBlockFlow::willCreateColumns(std::optional<unsigned> desiredColumnCount) const
 {
     // The following types are not supposed to create multicol context.
-    if (isFieldset() || isFileUploadControl() || isTextControl() || isListBox())
+    if (isFileUploadControl() || isTextControl() || isListBox())
         return false;
 
     if (!firstChild())
@@ -637,7 +637,7 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
     // Fieldsets need to find their legend and position it inside the border of the object.
     // The legend then gets skipped during normal layout. The same is true for ruby text.
     // It doesn't get included in the normal layout process but is instead skipped.
-    RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
+    layoutExcludedChildren(relayoutChildren);
 
     LayoutUnit previousFloatLogicalBottom = 0;
     maxFloatLogicalBottom = 0;
@@ -648,7 +648,7 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
         RenderBox& child = *next;
         next = child.nextSiblingBox();
 
-        if (childToExclude == &child)
+        if (child.isExcludedFromNormalLayout())
             continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
 
         updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
@@ -3874,11 +3874,15 @@ void RenderBlockFlow::adjustComputedFontSizes(float size, float visibleWidth)
 }
 #endif // ENABLE(TEXT_AUTOSIZING)
 
-RenderObject* RenderBlockFlow::layoutSpecialExcludedChild(bool relayoutChildren)
+void RenderBlockFlow::layoutExcludedChildren(bool relayoutChildren)
 {
-    RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread();
+    RenderBlock::layoutExcludedChildren(relayoutChildren);
+
+    auto* flowThread = multiColumnFlowThread();
     if (!flowThread)
-        return nullptr;
+        return;
+
+    flowThread->setIsExcludedFromNormalLayout(true);
 
     setLogicalTopForChild(*flowThread, borderAndPaddingBefore());
 
@@ -3904,13 +3908,11 @@ RenderObject* RenderBlockFlow::layoutSpecialExcludedChild(bool relayoutChildren)
         flowThread->setNeedsHeightsRecalculation(false);
     }
     determineLogicalLeftPositionForChild(*flowThread);
-
-    return flowThread;
 }
 
 void RenderBlockFlow::addChild(RenderObject* newChild, RenderObject* beforeChild)
 {
-    if (multiColumnFlowThread())
+    if (multiColumnFlowThread() && (!isFieldset() || !newChild->isLegend()))
         return multiColumnFlowThread()->addChild(newChild, beforeChild);
     auto* beforeChildOrPlaceholder = beforeChild;
     if (auto* containingFlowThread = flowThreadContainingBlock())
index f161117..9d8d45f 100644 (file)
@@ -469,18 +469,19 @@ protected:
     
     virtual void cachePriorCharactersIfNeeded(const LazyLineBreakIterator&) {};
     
+protected:
+    // Called to lay out the legend for a fieldset or the ruby text of a ruby run. Also used by multi-column layout to handle
+    // the flow thread child.
+    void layoutExcludedChildren(bool relayoutChildren) override;
+    
 private:
     bool recomputeLogicalWidthAndColumnWidth();
     LayoutUnit columnGap() const;
     
     RenderBlockFlow* previousSiblingWithOverhangingFloats(bool& parentHasFloats) const;
 
-    // Called to lay out the legend for a fieldset or the ruby text of a ruby run. Also used by multi-column layout to handle
-    // the flow thread child.
-    virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/);
-
     void checkForPaginationLogicalHeightChange(bool& relayoutChildren, LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged);
-    
+
     void paintInlineChildren(PaintInfo&, const LayoutPoint&) override;
     void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) override;
 
index 6a9975e..3a1ba2a 100644 (file)
@@ -1336,6 +1336,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
 
     LayoutRect paintRect = borderBoxRectInRegion(currentRenderNamedFlowFragment());
     paintRect.moveBy(paintOffset);
+    adjustBorderBoxRectForPainting(paintRect);
 
 #if PLATFORM(IOS)
     // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
@@ -1585,6 +1586,7 @@ void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
         return;
 
     LayoutRect paintRect = LayoutRect(paintOffset, size());
+    adjustBorderBoxRectForPainting(paintRect);
     paintMaskImages(paintInfo, paintRect);
 }
 
@@ -4555,7 +4557,7 @@ bool RenderBox::createsNewFormattingContext() const
 
 bool RenderBox::avoidsFloats() const
 {
-    return (isReplaced() && !isAnonymousInlineBlock()) || isHR() || isLegend() || createsNewFormattingContext();
+    return (isReplaced() && !isAnonymousInlineBlock()) || isHR() || isLegend() || isFieldset() || createsNewFormattingContext();
 }
 
 void RenderBox::addVisualEffectOverflow()
index 1c76bf7..065547f 100644 (file)
@@ -328,9 +328,11 @@ public:
     LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const override;
     
     LayoutUnit adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const;
-    LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
     LayoutUnit adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit width) const;
-    LayoutUnit adjustContentBoxLogicalHeightForBoxSizing(std::optional<LayoutUnit> height) const;
+
+    // Overridden by fieldsets to subtract out the intrinsic border.
+    virtual LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
+    virtual LayoutUnit adjustContentBoxLogicalHeightForBoxSizing(std::optional<LayoutUnit> height) const;
 
     struct ComputedMarginValues {
         LayoutUnit m_before;
@@ -618,8 +620,10 @@ public:
 
     const RenderBox* findEnclosingScrollableContainer() const;
     
-    bool isGridItem() const { return parent() && parent()->isRenderGrid(); }
-    bool isFlexItem() const { return parent() && parent()->isFlexibleBox(); }
+    bool isGridItem() const { return parent() && parent()->isRenderGrid() && !isExcludedFromNormalLayout(); }
+    bool isFlexItem() const { return parent() && parent()->isFlexibleBox() && !isExcludedFromNormalLayout(); }
+
+    virtual void adjustBorderBoxRectForPainting(LayoutRect&) { };
 
 protected:
     RenderBox(Element&, RenderStyle&&, BaseTypeFlags);
index a5d3661..a4e0ee9 100644 (file)
@@ -1718,6 +1718,12 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
     if (rect.isEmpty())
         return;
 
+    auto rectToClipOut = paintRectToClipOutFromBorder(rect);
+    bool appliedClipAlready = !rectToClipOut.isEmpty();
+    GraphicsContextStateSaver stateSave(graphicsContext, appliedClipAlready);
+    if (!rectToClipOut.isEmpty())
+        graphicsContext.clipOut(snapRectToDevicePixels(rectToClipOut, document().deviceScaleFactor()));
+
     // border-image is not affected by border-radius.
     if (paintNinePieceImage(graphicsContext, rect, style, style.borderImage()))
         return;
@@ -1856,7 +1862,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
     }
 
     bool clipToOuterBorder = outerBorder.isRounded();
-    GraphicsContextStateSaver stateSaver(graphicsContext, clipToOuterBorder);
+    GraphicsContextStateSaver stateSaver(graphicsContext, clipToOuterBorder && !appliedClipAlready);
     if (clipToOuterBorder) {
         // Clip to the inner and outer radii rects.
         if (bleedAvoidance != BackgroundBleedUseTransparencyLayer)
index 0751843..31daedb 100644 (file)
@@ -236,6 +236,8 @@ public:
 
     RenderBoxModelObject* continuation() const;
 
+    virtual LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) { return LayoutRect(); };
+    
 protected:
     RenderBoxModelObject(Element&, RenderStyle&&, BaseTypeFlags);
     RenderBoxModelObject(Document&, RenderStyle&&, BaseTypeFlags);
index 563e536..ad4695d 100644 (file)
@@ -95,7 +95,7 @@ public:
 
             if (m_currentChild && notFirstOrdinalValue())
                 m_ordinalValues.add(m_currentChild->style().boxOrdinalGroup());
-        } while (!m_currentChild || (!m_currentChild->isAnonymous()
+        } while (!m_currentChild || m_currentChild->isExcludedFromNormalLayout() || (!m_currentChild->isAnonymous()
                  && m_currentChild->style().boxOrdinalGroup() != m_currentOrdinal));
         return m_currentChild;
     }
@@ -302,6 +302,11 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
     LayoutSize oldLayoutDelta = view().layoutDelta();
 #endif
 
+    // Fieldsets need to find their legend and position it inside the border of the object.
+    // The legend then gets skipped during normal layout. The same is true for ruby text.
+    // It doesn't get included in the normal layout process but is instead skipped.
+    layoutExcludedChildren(relayoutChildren);
+
     ChildFrameRects oldChildRects;
     appendChildFrameRects(this, oldChildRects);
     
@@ -427,9 +432,6 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
             
             // Apply the child's current layout delta.
             layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
-            
-            // Now do the layout.
-            layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
 
             // Update our height and overflow height.
             if (style().boxAlign() == BBASELINE) {
index d3944e5..18d63cd 100644 (file)
@@ -156,13 +156,13 @@ RenderElement::~RenderElement()
         view().unregisterForVisibleInViewportCallback(*this);
 }
 
-RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&& style)
+RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&& style, RendererCreationType creationType)
 {
     // Minimal support for content properties replacing an entire element.
     // Works only if we have exactly one piece of content and it's a URL.
     // Otherwise acts as if we didn't support this feature.
     const ContentData* contentData = style.contentData();
-    if (contentData && !contentData->next() && is<ImageContentData>(*contentData) && !element.isPseudoElement()) {
+    if (creationType == CreateAllRenderers && contentData && !contentData->next() && is<ImageContentData>(*contentData) && !element.isPseudoElement()) {
         Style::loadPendingResources(style, element.document(), &element);
         auto& styleImage = downcast<ImageContentData>(*contentData).image();
         auto image = createRenderer<RenderImage>(element, WTFMove(style), const_cast<StyleImage*>(&styleImage));
@@ -175,32 +175,15 @@ RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&
     case CONTENTS:
         return nullptr;
     case INLINE:
-        return createRenderer<RenderInline>(element, WTFMove(style));
+        if (creationType == CreateAllRenderers)
+            return createRenderer<RenderInline>(element, WTFMove(style));
+        FALLTHROUGH; // Fieldsets should make a block flow if display:inline is set.
     case BLOCK:
     case INLINE_BLOCK:
     case COMPACT:
         return createRenderer<RenderBlockFlow>(element, WTFMove(style));
     case LIST_ITEM:
         return createRenderer<RenderListItem>(element, WTFMove(style));
-    case TABLE:
-    case INLINE_TABLE:
-        return createRenderer<RenderTable>(element, WTFMove(style));
-    case TABLE_ROW_GROUP:
-    case TABLE_HEADER_GROUP:
-    case TABLE_FOOTER_GROUP:
-        return createRenderer<RenderTableSection>(element, WTFMove(style));
-    case TABLE_ROW:
-        return createRenderer<RenderTableRow>(element, WTFMove(style));
-    case TABLE_COLUMN_GROUP:
-    case TABLE_COLUMN:
-        return createRenderer<RenderTableCol>(element, WTFMove(style));
-    case TABLE_CELL:
-        return createRenderer<RenderTableCell>(element, WTFMove(style));
-    case TABLE_CAPTION:
-        return createRenderer<RenderTableCaption>(element, WTFMove(style));
-    case BOX:
-    case INLINE_BOX:
-        return createRenderer<RenderDeprecatedFlexibleBox>(element, WTFMove(style));
     case FLEX:
     case INLINE_FLEX:
     case WEBKIT_FLEX:
@@ -209,6 +192,34 @@ RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&
     case GRID:
     case INLINE_GRID:
         return createRenderer<RenderGrid>(element, WTFMove(style));
+    case BOX:
+    case INLINE_BOX:
+        return createRenderer<RenderDeprecatedFlexibleBox>(element, WTFMove(style));
+    default: {
+        if (creationType == OnlyCreateBlockAndFlexboxRenderers)
+            return createRenderer<RenderBlockFlow>(element, WTFMove(style));
+        switch (style.display()) {
+        case TABLE:
+        case INLINE_TABLE:
+            return createRenderer<RenderTable>(element, WTFMove(style));
+        case TABLE_CELL:
+            return createRenderer<RenderTableCell>(element, WTFMove(style));
+        case TABLE_CAPTION:
+            return createRenderer<RenderTableCaption>(element, WTFMove(style));
+        case TABLE_ROW_GROUP:
+        case TABLE_HEADER_GROUP:
+        case TABLE_FOOTER_GROUP:
+            return createRenderer<RenderTableSection>(element, WTFMove(style));
+        case TABLE_ROW:
+            return createRenderer<RenderTableRow>(element, WTFMove(style));
+        case TABLE_COLUMN_GROUP:
+        case TABLE_COLUMN:
+            return createRenderer<RenderTableCol>(element, WTFMove(style));
+        default:
+            break;
+        }
+        break;
+    }
     }
     ASSERT_NOT_REACHED();
     return nullptr;
@@ -1208,9 +1219,10 @@ void RenderElement::paintAsInlineBlock(PaintInfo& paintInfo, const LayoutPoint&
     // Paint all phases atomically, as though the element established its own stacking context.
     // (See Appendix E.2, section 6.4 on inline block/table/replaced elements in the CSS2.1 specification.)
     // This is also used by other elements (e.g. flex items and grid items).
-    if (paintInfo.phase == PaintPhaseSelection) {
+    PaintPhase paintPhaseToUse = isExcludedAndPlacedInBorder() ? paintInfo.phase : PaintPhaseForeground;
+    if (paintInfo.phase == PaintPhaseSelection)
         paint(paintInfo, childPoint);
-    } else if (paintInfo.phase == PaintPhaseForeground) {
+    else if (paintInfo.phase == paintPhaseToUse) {
         paintPhase(*this, PaintPhaseBlockBackground, paintInfo, childPoint);
         paintPhase(*this, PaintPhaseChildBlockBackgrounds, paintInfo, childPoint);
         paintPhase(*this, PaintPhaseFloat, paintInfo, childPoint);
@@ -1218,7 +1230,7 @@ void RenderElement::paintAsInlineBlock(PaintInfo& paintInfo, const LayoutPoint&
         paintPhase(*this, PaintPhaseOutline, paintInfo, childPoint);
 
         // Reset |paintInfo| to the original phase.
-        paintInfo.phase = PaintPhaseForeground;
+        paintInfo.phase = paintPhaseToUse;
     }
 }
 
index e19a38e..fda09e5 100644 (file)
@@ -36,7 +36,8 @@ class RenderElement : public RenderObject {
 public:
     virtual ~RenderElement();
 
-    static RenderPtr<RenderElement> createFor(Element&, RenderStyle&&);
+    enum RendererCreationType { CreateAllRenderers, OnlyCreateBlockAndFlexboxRenderers };
+    static RenderPtr<RenderElement> createFor(Element&, RenderStyle&&, RendererCreationType = CreateAllRenderers);
 
     bool hasInitializedStyle() const { return m_hasInitializedStyle; }
 
diff --git a/Source/WebCore/rendering/RenderFieldset.cpp b/Source/WebCore/rendering/RenderFieldset.cpp
deleted file mode 100644 (file)
index 8971252..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "RenderFieldset.h"
-
-#include "CSSPropertyNames.h"
-#include "GraphicsContext.h"
-#include "HTMLFieldSetElement.h"
-#include "HTMLLegendElement.h"
-#include "HTMLNames.h"
-#include "PaintInfo.h"
-#include "RenderChildIterator.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-RenderFieldset::RenderFieldset(HTMLFieldSetElement& element, RenderStyle&& style)
-    : RenderBlockFlow(element, WTFMove(style))
-{
-}
-
-void RenderFieldset::computePreferredLogicalWidths()
-{
-    RenderBlockFlow::computePreferredLogicalWidths();
-    if (RenderBox* legend = findLegend()) {
-        int legendMinWidth = legend->minPreferredLogicalWidth();
-
-        Length legendMarginLeft = legend->style().marginLeft();
-        Length legendMarginRight = legend->style().marginLeft();
-
-        if (legendMarginLeft.isFixed())
-            legendMinWidth += legendMarginLeft.value();
-
-        if (legendMarginRight.isFixed())
-            legendMinWidth += legendMarginRight.value();
-
-        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, legendMinWidth + horizontalBorderAndPaddingExtent());
-    }
-}
-
-RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
-{
-    RenderBox* box = findLegend();
-    if (!box)
-        return nullptr;
-
-    RenderBox& legend = *box;
-    if (relayoutChildren)
-        legend.setNeedsLayout();
-    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 = std::max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(legend));
-    } else
-        collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(legend);
-
-    setLogicalTopForChild(legend, legendLogicalTop);
-    setLogicalHeight(paddingBefore() + collapsedLegendExtent);
-
-    return &legend;
-}
-
-RenderBox* RenderFieldset::findLegend(FindLegendOption option)
-{
-    for (auto& legend : childrenOfType<RenderBox>(*this)) {
-        if (option == IgnoreFloatingOrOutOfFlow && legend.isFloatingOrOutOfFlowPositioned())
-            continue;
-        
-        if (is<HTMLLegendElement>(legend.element()))
-            return &legend;
-    }
-    return nullptr;
-}
-
-void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
-    if (!paintInfo.shouldPaintWithinRoot(*this))
-        return;
-
-    LayoutRect paintRect(paintOffset, size());
-    RenderBox* legend = findLegend();
-    if (!legend)
-        return RenderBlockFlow::paintBoxDecorations(paintInfo, paintOffset);
-
-    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
-    // cases the legend is embedded in the right and bottom borders respectively.
-    // https://bugs.webkit.org/show_bug.cgi?id=47236
-    if (style().isHorizontalWritingMode()) {
-        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
-        paintRect.setHeight(paintRect.height() - yOff);
-        paintRect.setY(paintRect.y() + yOff);
-    } else {
-        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
-        paintRect.setWidth(paintRect.width() - xOff);
-        paintRect.setX(paintRect.x() + xOff);
-    }
-
-    if (!boxShadowShouldBeAppliedToBackground(paintRect.location(), determineBackgroundBleedAvoidance(paintInfo.context())))
-        paintBoxShadow(paintInfo, paintRect, style(), Normal);
-    paintFillLayers(paintInfo, style().visitedDependentColor(CSSPropertyBackgroundColor), style().backgroundLayers(), paintRect);
-    paintBoxShadow(paintInfo, paintRect, style(), Inset);
-
-    if (!style().hasBorder())
-        return;
-    
-    // Create a clipping region around the legend and paint the border as normal
-    GraphicsContext& graphicsContext = paintInfo.context();
-    GraphicsContextStateSaver stateSaver(graphicsContext);
-
-    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
-    // cases the legend is embedded in the right and bottom borders respectively.
-    // https://bugs.webkit.org/show_bug.cgi?id=47236
-    LayoutRect clipRect;
-    if (style().isHorizontalWritingMode()) {
-        clipRect.setX(paintRect.x() + legend->x());
-        clipRect.setY(paintRect.y());
-        clipRect.setWidth(legend->width());
-        clipRect.setHeight(std::max<LayoutUnit>(style().borderTopWidth(), legend->height() - ((legend->height() - borderTop()) / 2)));
-    } else {
-        clipRect.setX(paintRect.x());
-        clipRect.setY(paintRect.y() + legend->y());
-        clipRect.setWidth(std::max<LayoutUnit>(style().borderLeftWidth(), legend->width()));
-        clipRect.setHeight(legend->height());
-    }
-    graphicsContext.clipOut(snapRectToDevicePixels(clipRect, document().deviceScaleFactor()));
-
-    paintBorder(paintInfo, paintRect, style());
-}
-
-void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
-    if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
-        return;
-
-    LayoutRect paintRect = LayoutRect(paintOffset, size());
-    RenderBox* legend = findLegend();
-    if (!legend)
-        return RenderBlockFlow::paintMask(paintInfo, paintOffset);
-
-    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
-    // cases the legend is embedded in the right and bottom borders respectively.
-    // https://bugs.webkit.org/show_bug.cgi?id=47236
-    if (style().isHorizontalWritingMode()) {
-        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
-        paintRect.expand(0, -yOff);
-        paintRect.move(0, yOff);
-    } else {
-        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
-        paintRect.expand(-xOff, 0);
-        paintRect.move(xOff, 0);
-    }
-
-    paintMaskImages(paintInfo, paintRect);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFieldset.h b/Source/WebCore/rendering/RenderFieldset.h
deleted file mode 100644 (file)
index 62582c9..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006, 2009 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#pragma once
-
-#include "HTMLFieldSetElement.h"
-#include "RenderBlockFlow.h"
-
-namespace WebCore {
-
-class HTMLFieldSetElement;
-
-class RenderFieldset final : public RenderBlockFlow {
-public:
-    RenderFieldset(HTMLFieldSetElement&, RenderStyle&&);
-
-    enum FindLegendOption { IgnoreFloatingOrOutOfFlow, IncludeFloatingOrOutOfFlow };
-    RenderBox* findLegend(FindLegendOption = IgnoreFloatingOrOutOfFlow);
-
-    HTMLFieldSetElement& fieldSetElement() const { return downcast<HTMLFieldSetElement>(nodeForNonAnonymous()); }
-
-private:
-    void element() const = delete;
-
-    const char* renderName() const override { return "RenderFieldSet"; }
-    bool isFieldset() const override { return true; }
-
-    RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override;
-
-    void computePreferredLogicalWidths() override;
-    bool avoidsFloats() const override { return true; }
-
-    void paintBoxDecorations(PaintInfo&, const LayoutPoint&) override;
-    void paintMask(PaintInfo&, const LayoutPoint&) override;
-};
-
-} // namespace WebCore
-
-SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderFieldset, isFieldset())
index 13a91c9..f319364 100644 (file)
@@ -79,12 +79,16 @@ const char* RenderFlexibleBox::renderName() const
 
 void RenderFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
 {
+    LayoutUnit childMinWidth;
+    LayoutUnit childMaxWidth;
+    bool hadExcludedChildren = computePreferredWidthsForExcludedChildren(childMinWidth, childMaxWidth);
+
     // FIXME: We're ignoring flex-basis here and we shouldn't. We can't start
     // honoring it though until the flex shorthand stops setting it to 0. See
     // https://bugs.webkit.org/show_bug.cgi?id=116117 and
     // https://crbug.com/240765.
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        if (child->isOutOfFlowPositioned())
+        if (child->isOutOfFlowPositioned() || child->isExcludedFromNormalLayout())
             continue;
         
         LayoutUnit margin = marginIntrinsicLogicalWidthForChild(*child);
@@ -117,6 +121,11 @@ void RenderFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidt
     minLogicalWidth = std::max(LayoutUnit(), minLogicalWidth);
     maxLogicalWidth = std::max(LayoutUnit(), maxLogicalWidth);
     
+    if (hadExcludedChildren) {
+        minLogicalWidth = std::max(minLogicalWidth, childMinWidth);
+        maxLogicalWidth = std::max(maxLogicalWidth, childMaxWidth);
+    }
+
     LayoutUnit scrollbarWidth(scrollbarLogicalWidth());
     maxLogicalWidth += scrollbarWidth;
     minLogicalWidth += scrollbarWidth;
@@ -174,7 +183,7 @@ std::optional<int> RenderFlexibleBox::firstLineBaseline() const
     RenderBox* baselineChild = nullptr;
     int childNumber = 0;
     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
-        if (child->isOutOfFlowPositioned())
+        if (m_orderIterator.shouldSkipChild(*child))
             continue;
         if (alignmentForChild(*child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(*child)) {
             baselineChild = child;
@@ -275,8 +284,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
 
     prepareOrderIteratorAndMargins();
 
+    // Fieldsets need to find their legend and position it inside the border of the object.
+    // The legend then gets skipped during normal layout. The same is true for ruby text.
+    // It doesn't get included in the normal layout process but is instead skipped.
+    layoutExcludedChildren(relayoutChildren);
+
     ChildFrameRects oldChildRects;
     appendChildFrameRects(oldChildRects);
+
     layoutFlexItems(relayoutChildren);
 
     endAndCommitUpdateScrollInfoAfterLayoutTransaction();
@@ -502,8 +517,6 @@ LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHei
     return contentLogicalWidth();
 }
 
-// MERGEPOINT
-
 std::optional<LayoutUnit> RenderFlexibleBox::computeMainAxisExtentForChild(const RenderBox& child, SizeType sizeType, const Length& size)
 {
     // If we have a horizontal flow, that means the main size is the width.
@@ -846,9 +859,10 @@ void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren)
     Vector<FlexItem> allItems;
     m_orderIterator.first();
     for (RenderBox* child = m_orderIterator.currentChild(); child; child = m_orderIterator.next()) {
-        if (child->isOutOfFlowPositioned()) {
+        if (m_orderIterator.shouldSkipChild(*child)) {
             // Out-of-flow children are not flex items, so we skip them here.
-            prepareChildForPositionedLayout(*child);
+            if (child->isOutOfFlowPositioned())
+                prepareChildForPositionedLayout(*child);
             continue;
         }
         allItems.append(constructFlexItem(*child, relayoutChildren));
@@ -1039,9 +1053,7 @@ void RenderFlexibleBox::prepareOrderIteratorAndMargins()
     OrderIteratorPopulator populator(m_orderIterator);
 
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        populator.collectChild(*child);
-
-        if (child->isOutOfFlowPositioned())
+        if (!populator.collectChild(*child))
             continue;
 
         // Before running the flex algorithm, 'auto' has a margin of 0.
index 6ac47de..be5b0d2 100644 (file)
@@ -241,6 +241,11 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
     setLogicalHeight(0);
     updateLogicalWidth();
 
+    // Fieldsets need to find their legend and position it inside the border of the object.
+    // The legend then gets skipped during normal layout. The same is true for ruby text.
+    // It doesn't get included in the normal layout process but is instead skipped.
+    layoutExcludedChildren(relayoutChildren);
+
     placeItemsOnGrid(m_grid, TrackSizing);
 
     // At this point the logical width is always definite as the above call to updateLogicalWidth()
@@ -393,12 +398,21 @@ LayoutUnit RenderGrid::guttersSize(const Grid& grid, GridTrackSizingDirection di
 
 void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
 {
+    LayoutUnit childMinWidth;
+    LayoutUnit childMaxWidth;
+    bool hadExcludedChildren = computePreferredWidthsForExcludedChildren(childMinWidth, childMaxWidth);
+    
     Grid grid(const_cast<RenderGrid&>(*this));
     placeItemsOnGrid(grid, IntrinsicSizeComputation);
 
     GridTrackSizingAlgorithm algorithm(this, grid);
     computeTrackSizesForIndefiniteSize(algorithm, ForColumns, grid, minLogicalWidth, maxLogicalWidth);
 
+    if (hadExcludedChildren) {
+        minLogicalWidth = std::max(minLogicalWidth, childMinWidth);
+        maxLogicalWidth = std::max(maxLogicalWidth, childMaxWidth);
+    }
+
     LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth();
     minLogicalWidth += scrollbarWidth;
     maxLogicalWidth += scrollbarWidth;
@@ -581,7 +595,7 @@ void RenderGrid::placeItemsOnGrid(Grid& grid, SizingOperation sizingOperation) c
     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
     bool hasAnyOrthogonalGridItem = false;
     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
-        if (child->isOutOfFlowPositioned())
+        if (grid.orderIterator().shouldSkipChild(*child))
             continue;
 
         hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem || isOrthogonalChild(*child);
@@ -624,7 +638,7 @@ void RenderGrid::placeItemsOnGrid(Grid& grid, SizingOperation sizingOperation) c
 
 #if ENABLE(ASSERT)
     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
-        if (child->isOutOfFlowPositioned())
+        if (grid.orderIterator().shouldSkipChild(*child))
             continue;
 
         GridArea area = grid.gridItemArea(*child);
@@ -644,11 +658,9 @@ void RenderGrid::populateExplicitGridAndOrderIterator(Grid& grid) const
     unsigned maximumColumnIndex = GridPositionsResolver::explicitGridColumnCount(style(), autoRepeatColumns);
 
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        if (child->isOutOfFlowPositioned())
+        if (!populator.collectChild(*child))
             continue;
-
-        populator.collectChild(*child);
-
+        
         GridSpan rowPositions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), *child, ForRows, autoRepeatRows);
         if (!rowPositions.isIndefinite()) {
             smallestRowStart = std::min(smallestRowStart, rowPositions.untranslatedStartLine());
@@ -884,8 +896,10 @@ void RenderGrid::layoutGridItems()
     populateGridPositionsForDirection(ForRows);
 
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        if (child->isOutOfFlowPositioned()) {
-            prepareChildForPositionedLayout(*child);
+        
+        if (m_grid.orderIterator().shouldSkipChild(*child)) {
+            if (child->isOutOfFlowPositioned())
+                prepareChildForPositionedLayout(*child);
             continue;
         }
 
index 1589a79..1d5628c 100644 (file)
@@ -153,6 +153,14 @@ void RenderMultiColumnFlowThread::populate()
     LayoutStateDisabler layoutStateDisabler(view());
     RenderTreeInternalMutationScope reparentingIsOn(view());
     multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, true);
+    
+    if (multicolContainer->isFieldset()) {
+        // Keep legends out of the flow thread.
+        for (auto& box : childrenOfType<RenderBox>(*this)) {
+            if (box.isLegend())
+                moveChildTo(multicolContainer, &box, true);
+        }
+    }
 }
 
 void RenderMultiColumnFlowThread::evacuateAndDestroy()
index f4dc9f6..1fd23a7 100644 (file)
@@ -319,7 +319,7 @@ bool RenderMultiColumnSet::requiresBalancing() const
         return false;
 
     if (RenderBox* next = RenderMultiColumnFlowThread::nextColumnSetOrSpannerSiblingOf(this)) {
-        if (!next->isRenderMultiColumnSet()) {
+        if (!next->isRenderMultiColumnSet() && !next->isLegend()) {
             // If we're followed by a spanner, we need to balance.
             ASSERT(multiColumnFlowThread()->findColumnSpannerPlaceholder(next));
             return true;
index 5c84b8b..ba5540b 100644 (file)
@@ -158,6 +158,12 @@ bool RenderObject::isLegend() const
     return node() && node()->hasTagName(legendTag);
 }
 
+    
+bool RenderObject::isFieldset() const
+{
+    return node() && node()->hasTagName(fieldsetTag);
+}
+
 bool RenderObject::isHTMLMarquee() const
 {
     return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
index 482fc02..2bdcb68 100644 (file)
@@ -226,7 +226,7 @@ public:
 
     virtual bool isDetailsMarker() const { return false; }
     virtual bool isEmbeddedObject() const { return false; }
-    virtual bool isFieldset() const { return false; }
+    bool isFieldset() const;
     virtual bool isFileUploadControl() const { return false; }
     virtual bool isFrame() const { return false; }
     virtual bool isFrameSet() const { return false; }
@@ -448,6 +448,10 @@ public:
     bool hasOutlineAutoAncestor() const { return m_bitfields.hasRareData() && rareData().hasOutlineAutoAncestor(); }
     bool isRegisteredForVisibleInViewportCallback() { return m_bitfields.hasRareData() && rareData().isRegisteredForVisibleInViewportCallback(); }
 
+    bool isExcludedFromNormalLayout() const { return m_bitfields.isExcludedFromNormalLayout(); }
+    void setIsExcludedFromNormalLayout(bool excluded) { m_bitfields.setIsExcludedFromNormalLayout(excluded); }
+    bool isExcludedAndPlacedInBorder() const { return isExcludedFromNormalLayout() && isLegend(); }
+
     enum VisibleInViewportState {
         VisibilityUnknown,
         VisibleInViewport,
@@ -901,6 +905,7 @@ private:
             , m_hasTransformRelatedProperty(false)
             , m_everHadLayout(false)
             , m_childrenInline(false)
+            , m_isExcludedFromNormalLayout(false)
             , m_positionedState(IsStaticallyPositioned)
             , m_selectionState(SelectionNone)
             , m_flowThreadState(NotInsideFlowThread)
@@ -936,6 +941,8 @@ private:
 
         // from RenderBlock
         ADD_BOOLEAN_BITFIELD(childrenInline, ChildrenInline);
+        
+        ADD_BOOLEAN_BITFIELD(isExcludedFromNormalLayout, IsExcludedFromNormalLayout);
 
     private:
         unsigned m_positionedState : 2; // PositionedState
index c65f2c7..ea251cd 100644 (file)
@@ -213,17 +213,19 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby
     return renderer;
 }
 
-RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren)
+void RenderRubyRun::layoutExcludedChildren(bool relayoutChildren)
 {
+    RenderBlockFlow::layoutExcludedChildren(relayoutChildren);
+
     StackStats::LayoutCheckPoint layoutCheckPoint;
     // Don't bother positioning the RenderRubyRun yet.
     RenderRubyText* rt = rubyText();
     if (!rt)
-        return 0;
+        return;
+    rt->setIsExcludedFromNormalLayout(true);
     if (relayoutChildren)
         rt->setChildNeedsLayout(MarkOnlyThis);
     rt->layoutIfNeeded();
-    return rt;
 }
 
 void RenderRubyRun::layout()
index c6677ec..a73618e 100644 (file)
@@ -51,7 +51,7 @@ public:
     RenderRubyBase* rubyBase() const;
     RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist
 
-    RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override;
+    void layoutExcludedChildren(bool relayoutChildren) override;
     void layout() override;
     void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0) override;
 
index 44b3ed3..6ebc7d0 100644 (file)
@@ -753,7 +753,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
         paintOutline(paintInfo, LayoutRect(paintOffset, size()));
 }
 
-void RenderTable::subtractCaptionRect(LayoutRect& rect) const
+void RenderTable::adjustBorderBoxRectForPainting(LayoutRect& rect)
 {
     for (unsigned i = 0; i < m_captions.size(); i++) {
         LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
@@ -768,6 +768,8 @@ void RenderTable::subtractCaptionRect(LayoutRect& rect) const
                 rect.move(captionLogicalHeight, 0);
         }
     }
+    
+    RenderBlock::adjustBorderBoxRectForPainting(rect);
 }
 
 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -776,8 +778,8 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& p
         return;
 
     LayoutRect rect(paintOffset, size());
-    subtractCaptionRect(rect);
-
+    adjustBorderBoxRectForPainting(rect);
+    
     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context());
     if (!boxShadowShouldBeAppliedToBackground(rect.location(), bleedAvoidance))
         paintBoxShadow(paintInfo, rect, style(), Normal);
@@ -794,7 +796,7 @@ void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset
         return;
 
     LayoutRect rect(paintOffset, size());
-    subtractCaptionRect(rect);
+    adjustBorderBoxRectForPainting(rect);
 
     paintMaskImages(paintInfo, rect);
 }
index 82ed277..b8833d1 100644 (file)
@@ -314,7 +314,7 @@ private:
 
     void addOverflowFromChildren() final;
 
-    void subtractCaptionRect(LayoutRect&) const;
+    void adjustBorderBoxRectForPainting(LayoutRect&) override;
 
     void recalcCollapsedBorders();
     void recalcSections() const;
index 2cf3bfb..21dcd22 100644 (file)
@@ -1307,6 +1307,8 @@ void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoin
         return;
 
     LayoutRect paintRect = LayoutRect(paintOffset, frameRect().size());
+    adjustBorderBoxRectForPainting(paintRect);
+
     paintBoxShadow(paintInfo, paintRect, style(), Normal);
     
     // Paint our cell background.
@@ -1329,7 +1331,10 @@ void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOf
     if (!tableElt->collapseBorders() && style().emptyCells() == HIDE && !firstChild())
         return;
    
-    paintMaskImages(paintInfo, LayoutRect(paintOffset, frameRect().size()));
+    LayoutRect paintRect = LayoutRect(paintOffset, frameRect().size());
+    adjustBorderBoxRectForPainting(paintRect);
+
+    paintMaskImages(paintInfo, paintRect);
 }
 
 bool RenderTableCell::boxShadowShouldBeAppliedToBackground(const LayoutPoint&, BackgroundBleedAvoidance, InlineFlowBox*) const
index 6eac07f..33ef5d7 100644 (file)
@@ -197,19 +197,22 @@ void RenderTextControl::addFocusRingRects(Vector<LayoutRect>& rects, const Layou
         rects.append(LayoutRect(additionalOffset, size()));
 }
 
-RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildren)
+void RenderTextControl::layoutExcludedChildren(bool relayoutChildren)
 {
+    RenderBlockFlow::layoutExcludedChildren(relayoutChildren);
+
     HTMLElement* placeholder = textFormControlElement().placeholderElement();
     RenderElement* placeholderRenderer = placeholder ? placeholder->renderer() : 0;
     if (!placeholderRenderer)
-        return 0;
+        return;
+    placeholderRenderer->setIsExcludedFromNormalLayout(true);
+
     if (relayoutChildren) {
         // The markParents arguments should be false because this function is
         // called from layout() of the parent and the placeholder layout doesn't
         // affect the parent layout.
         placeholderRenderer->setChildNeedsLayout(MarkOnlyThis);
     }
-    return placeholderRenderer;
 }
 
 #if PLATFORM(IOS)
index 4176a2c..1e661ea 100644 (file)
@@ -64,7 +64,7 @@ protected:
     virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
 
     LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override;
-    RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override;
+    void layoutExcludedChildren(bool relayoutChildren) override;
 
 private:
     void element() const = delete;
index 2c3385d..b221790 100644 (file)
@@ -87,9 +87,13 @@ int RenderTextControlMultiLine::baselinePosition(FontBaseline baselineType, bool
     return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
 }
 
-RenderObject* RenderTextControlMultiLine::layoutSpecialExcludedChild(bool relayoutChildren)
+void RenderTextControlMultiLine::layoutExcludedChildren(bool relayoutChildren)
 {
-    RenderObject* placeholderRenderer = RenderTextControl::layoutSpecialExcludedChild(relayoutChildren);
+    RenderTextControl::layoutExcludedChildren(relayoutChildren);
+    HTMLElement* placeholder = textFormControlElement().placeholderElement();
+    RenderElement* placeholderRenderer = placeholder ? placeholder->renderer() : 0;
+    if (!placeholderRenderer)
+        return;
     if (is<RenderBox>(placeholderRenderer)) {
         auto& placeholderBox = downcast<RenderBox>(*placeholderRenderer);
         placeholderBox.mutableStyle().setLogicalWidth(Length(contentLogicalWidth() - placeholderBox.borderAndPaddingLogicalWidth(), Fixed));
@@ -97,7 +101,6 @@ RenderObject* RenderTextControlMultiLine::layoutSpecialExcludedChild(bool relayo
         placeholderBox.setX(borderLeft() + paddingLeft());
         placeholderBox.setY(borderTop() + paddingTop());
     }
-    return placeholderRenderer;
 }
     
 }
index aaf7aa7..5f2bdf9 100644 (file)
@@ -45,7 +45,7 @@ private:
     LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const override;
     int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override;
 
-    RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override;
+    void layoutExcludedChildren(bool relayoutChildren) override;
 };
 
 inline RenderTextControlMultiLine* HTMLTextAreaElement::renderer() const
index d7d37aa..403b5b4 100644 (file)
@@ -272,14 +272,30 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
             return;
 
         const RenderBoxModelObject& box = downcast<RenderBoxModelObject>(o);
-        if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) {
+        LayoutUnit borderTop = box.borderTop();
+        LayoutUnit borderRight = box.borderRight();
+        LayoutUnit borderBottom = box.borderBottom();
+        LayoutUnit borderLeft = box.borderLeft();
+        if (box.isFieldset()) {
+            const auto& block = downcast<RenderBlock>(box);
+            if (o.style().writingMode() == TopToBottomWritingMode)
+                borderTop -= block.intrinsicBorderForFieldset();
+            else if (o.style().writingMode() == BottomToTopWritingMode)
+                borderBottom -= block.intrinsicBorderForFieldset();
+            else if (o.style().writingMode() == LeftToRightWritingMode)
+                borderLeft -= block.intrinsicBorderForFieldset();
+            else if (o.style().writingMode() == RightToLeftWritingMode)
+                borderRight -= block.intrinsicBorderForFieldset();
+            
+        }
+        if (borderTop || borderRight || borderBottom || borderLeft) {
             ts << " [border:";
 
             BorderValue prevBorder = o.style().borderTop();
-            if (!box.borderTop())
+            if (!borderTop)
                 ts << " none";
             else {
-                ts << " (" << box.borderTop() << "px ";
+                ts << " (" << borderTop << "px ";
                 printBorderStyle(ts, o.style().borderTopStyle());
                 Color col = o.style().borderTopColor();
                 if (!col.isValid())
@@ -289,10 +305,10 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
 
             if (o.style().borderRight() != prevBorder) {
                 prevBorder = o.style().borderRight();
-                if (!box.borderRight())
+                if (!borderRight)
                     ts << " none";
                 else {
-                    ts << " (" << box.borderRight() << "px ";
+                    ts << " (" << borderRight << "px ";
                     printBorderStyle(ts, o.style().borderRightStyle());
                     Color col = o.style().borderRightColor();
                     if (!col.isValid())
@@ -303,10 +319,10 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
 
             if (o.style().borderBottom() != prevBorder) {
                 prevBorder = box.style().borderBottom();
-                if (!box.borderBottom())
+                if (!borderBottom)
                     ts << " none";
                 else {
-                    ts << " (" << box.borderBottom() << "px ";
+                    ts << " (" << borderBottom << "px ";
                     printBorderStyle(ts, o.style().borderBottomStyle());
                     Color col = o.style().borderBottomColor();
                     if (!col.isValid())
@@ -317,10 +333,10 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
 
             if (o.style().borderLeft() != prevBorder) {
                 prevBorder = o.style().borderLeft();
-                if (!box.borderLeft())
+                if (!borderLeft)
                     ts << " none";
                 else {
-                    ts << " (" << box.borderLeft() << "px ";
+                    ts << " (" << borderLeft << "px ";
                     printBorderStyle(ts, o.style().borderLeftStyle());
                     Color col = o.style().borderLeftColor();
                     if (!col.isValid())
index ac57615..a797a7e 100644 (file)
@@ -62,7 +62,6 @@
 #include "RenderDetailsMarker.cpp"
 #include "RenderElement.cpp"
 #include "RenderEmbeddedObject.cpp"
-#include "RenderFieldset.cpp"
 #include "RenderFileUploadControl.cpp"
 #include "RenderFlexibleBox.cpp"
 #include "RenderFlowThread.cpp"