Bug 740743 - Implement CSS overflow for <legend>. r=bz
authorMats Palmgren <matspal@gmail.com>
Fri, 13 Apr 2012 17:52:13 +0200
changeset 94933 843a8a7b54c5586c6051e692982e50162848eaef
parent 94932 ae42e4d0ec0b5736c6259430980dff9a360e30b2
child 94934 2f77fddb6f7ab61eff575cb7861bed8d8664808c
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs740743
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 740743 - Implement CSS overflow for <legend>. r=bz
layout/base/nsCSSFrameConstructor.cpp
layout/forms/nsFieldSetFrame.cpp
layout/generic/nsHTMLReflowState.cpp
layout/reftests/forms/legend-ref.html
layout/reftests/forms/legend.html
layout/reftests/forms/reftest.list
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3173,26 +3173,26 @@ nsCSSFrameConstructor::ConstructFieldSet
 
   ProcessChildren(aState, content, styleContext, blockFrame, true,
                   childItems, true, aItem.mPendingBinding);
 
   nsFrameItems fieldsetKids;
   fieldsetKids.AddChild(blockFrame);
 
   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
-    nsLegendFrame* legendFrame = do_QueryFrame(e.get());
-    if (legendFrame) {
+    nsIFrame* child = e.get();
+    if (child->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame) {
       // We want the legend to be the first frame in the fieldset child list.
       // That way the EventStateManager will do the right thing when tabbing
       // from a selection point within the legend (bug 236071), which is
       // used for implementing legend access keys (bug 81481).
       // GetAdjustedParentFrame() below depends on this frame order.
-      childItems.RemoveFrame(legendFrame);
+      childItems.RemoveFrame(child);
       // Make sure to reparent the legend so it has the fieldset as the parent.
-      fieldsetKids.InsertFrame(newFrame, nsnull, legendFrame);
+      fieldsetKids.InsertFrame(newFrame, nsnull, child);
       break;
     }
   }
 
   // Set the inner frame's initial child lists
   blockFrame->SetInitialChildList(kPrincipalList, childItems);
 
   // Set the outer frame's initial child list
@@ -3409,17 +3409,18 @@ nsCSSFrameConstructor::FindHTMLData(Elem
     SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame),
     COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame),
     SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData),
     SIMPLE_TAG_CHAIN(applet, nsCSSFrameConstructor::FindObjectData),
     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
     COMPLEX_TAG_CREATE(fieldset,
                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
     { &nsGkAtoms::legend,
-      FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES, NS_NewLegendFrame) },
+      FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
+                  NS_NewLegendFrame) },
     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
     { &nsGkAtoms::button,
       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES,
                                  NS_NewHTMLButtonControlFrame,
                                  nsCSSAnonBoxes::buttonContent) },
     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
 #if defined(MOZ_MEDIA)
@@ -5808,17 +5809,17 @@ nsCSSFrameConstructor::IsValidSibling(ns
     }
 
     return true;
   }
   else if (nsGkAtoms::fieldSetFrame == parentType ||
            (nsGkAtoms::fieldSetFrame == grandparentType &&
             nsGkAtoms::blockFrame == parentType)) {
     // Legends can be sibling of legends but not of other content in the fieldset
-    nsIAtom* sibType = aSibling->GetType();
+    nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
     nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aContent));
 
     if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
         (!legendContent && (nsGkAtoms::legendFrame == sibType)))
       return false;
   }
 
   return true;
@@ -8895,17 +8896,17 @@ nsCSSFrameConstructor::MaybeRecreateCont
       printf(" is special\n");
     }
 #endif
 
     *aResult = ReframeContainingBlock(aFrame);
     return true;
   }
 
-  if (aFrame->GetType() == nsGkAtoms::legendFrame &&
+  if (aFrame->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame &&
       aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) {
     // When we remove the legend for a fieldset, we should reframe
     // the fieldset to ensure another legend is used, if there is one
     *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), false);
     return true;
   }
 
   // Now check for possibly needing to reconstruct due to a pseudo parent
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -121,16 +121,18 @@ public:
   }
 #endif
 
 protected:
 
   virtual PRIntn GetSkipSides() const;
   void ReparentFrameList(const nsFrameList& aFrameList);
 
+  // mLegendFrame is a nsLegendFrame or a nsHTMLScrollFrame with the
+  // nsLegendFrame as the scrolled frame (aka content insertion frame).
   nsIFrame* mLegendFrame;
   nsIFrame* mContentFrame;
   nsRect    mLegendRect;
   nscoord   mLegendSpace;
 };
 
 nsIFrame*
 NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
@@ -555,17 +557,18 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   // use the computed width if the inner content does not fill it
   if (aReflowState.ComputedWidth() > contentRect.width) {
     contentRect.width = aReflowState.ComputedWidth();
   }
 
   if (mLegendFrame) {
     // if the content rect is larger then the  legend we can align the legend
     if (contentRect.width > mLegendRect.width) {
-      PRInt32 align = static_cast<nsLegendFrame*>(mLegendFrame)->GetAlign();
+      PRInt32 align = static_cast<nsLegendFrame*>
+        (mLegendFrame->GetContentInsertionFrame())->GetAlign();
 
       switch(align) {
         case NS_STYLE_TEXT_ALIGN_RIGHT:
           mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left;
           break;
         case NS_STYLE_TEXT_ALIGN_CENTER:
           // Note: rounding removed; there doesn't seem to be any need
           mLegendRect.x = contentRect.width / 2 - mLegendRect.width / 2 + borderPadding.left;
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1868,23 +1868,26 @@ nsHTMLReflowState::InitConstraints(nsPre
 
     } else if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
       // XXX not sure if this belongs here or somewhere else - cwk
       InitAbsoluteConstraints(aPresContext, cbrs, aContainingBlockWidth,
                               aContainingBlockHeight, aFrameType);
     } else {
       AutoMaybeNullInflationContainer an(frame);
 
-      bool isBlock =
-        NS_CSS_FRAME_TYPE_BLOCK == NS_FRAME_GET_TYPE(mFrameType);
-      // make sure legend frames with display:block and width:auto still
-      // shrink-wrap
+      bool isBlock = NS_CSS_FRAME_TYPE_BLOCK == NS_FRAME_GET_TYPE(mFrameType);
+      PRUint32 computeSizeFlags = isBlock ? 0 : nsIFrame::eShrinkWrap;
 
-      PRUint32 computeSizeFlags = 0;
-      if (!isBlock || aFrameType == nsGkAtoms::legendFrame) {
+      // Make sure legend frames with display:block and width:auto still
+      // shrink-wrap.
+      if (isBlock &&
+          ((aFrameType == nsGkAtoms::legendFrame &&
+            frame->GetStyleContext()->GetPseudo() != nsCSSAnonBoxes::scrolledContent) ||
+           (aFrameType == nsGkAtoms::scrollFrame &&
+            frame->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame))) {
         computeSizeFlags |= nsIFrame::eShrinkWrap;
       }
 
       nsSize size =
         frame->ComputeSize(rendContext,
                            nsSize(aContainingBlockWidth,
                                   aContainingBlockHeight),
                            availableWidth,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/legend-ref.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html><head>
+    <title>Testcase for bug 740743</title>
+    <style type="text/css">
+
+        html,body {
+            color:black; background-color:white; font-size:16px; padding:0; margin:0;
+        }
+	
+fieldset { padding: 2px; }
+legend { padding: 0; }
+span { background: lime; display: block;}
+legend > span {
+   padding-left: 2px;
+   padding-right: 2px;
+}
+
+.s10 { width:10px; height:10px; }
+.h10 { height:10px; }
+.w50 { width:50px; }
+.hidden { overflow:hidden; }
+.scroll { overflow:scroll; }
+.auto { overflow:auto; }
+
+.o { text-overflow: ellipsis; }
+
+#inline span { display:inline; }
+#inline-block span { display:inline-block; }
+
+    </style>
+</head>
+<body>
+
+<fieldset><legend><span class="hidden s10"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="scroll s10">Legend Test</span></legend></fieldset>
+<fieldset><legend><span class="auto s10">Legend Test</span></legend></fieldset>
+<fieldset><legend><span class="hidden w50"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="scroll w50">Legend Test</span></legend></fieldset>
+<fieldset><legend><span class="auto w50"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="hidden">Legend Test</span></legend></fieldset>
+<fieldset><legend><span class="auto"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="auto"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="auto"><b>Legend Test</b></span></legend></fieldset>
+
+<fieldset><legend><span class="hidden w50 o"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend><span class="hidden w50 o">Test Legend</span></legend></fieldset>
+<fieldset><legend><span class="hidden o">Test Legend</span></legend></fieldset>
+<fieldset><legend><span class="auto w50 o"><b>Legend Test</b></span></legend></fieldset>
+<fieldset><legend align="right"><span class="hidden w50 o">Test Legend</span></legend></fieldset>
+<fieldset><legend align="center"><span class="hidden w50 o">Test Legend</span></legend></fieldset>
+
+<div id="inline">
+<span class="hidden s10"><b>Legend Test</b></span>
+<span class="scroll s10">Legend Test</span>
+<span class="auto s10">Legend Test</span>
+<span class="hidden w50"><b>Legend Test</b></span>
+<span class="scroll w50">Legend Test</span>
+<span class="auto w50"><b>Legend Test</b></span>
+<span class="hidden">Legend Test</span>
+<span class="auto"><b>Legend Test</b></span>
+
+<span class="hidden w50 o"><b>Legend Test</b></span>
+<span class="hidden w50 o">Test Legend</span>
+<span class="hidden o">Test Legend</span>
+<span class="auto w50 o"><b>Legend Test</b></span>
+<span class="hidden w50 o">Test Legend</span>
+<span class="hidden w50 o">Test Legend</span>
+</div>
+
+<div id="inline-block">
+<span class="hidden s10"><b>Legend Test</b></span>
+<span class="scroll s10">Legend Test</span>
+<span class="auto s10">Legend Test</span>
+<span class="hidden w50"><b>Legend Test</b></span>
+<span class="scroll w50">Legend Test</span>
+<span class="auto w50"><b>Legend Test</b></span>
+<span class="hidden">Legend Test</span>
+<span class="auto"><b>Legend Test</b></span>
+<span class="auto"><b>Legend Test</b></span>
+
+<span class="hidden w50 o"><b>Legend Test</b></span>
+<span class="hidden w50 o">Test Legend</span>
+<span class="hidden o">Test Legend</span>
+<span class="auto w50 o"><b>Legend Test</b></span>
+<span class="hidden w50 o">Test Legend</span>
+<span class="hidden w50 o">Test Legend</span>
+</div>
+
+<span class="auto w50"><b>Legend Test</b></span>
+<span><b>Legend Test</b></span>
+<span><b>Legend Test</b></span>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/legend.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+<html><head>
+    <title>Testcase for bug 740743</title>
+    <style type="text/css">
+
+        html,body {
+            color:black; background-color:white; font-size:16px; padding:0; margin:0;
+        }
+	
+fieldset { padding: 2px; }
+legend { background: lime; }
+.s10 { width:10px; height:10px; }
+.h10 { height:10px; }
+.w50 { width:50px; }
+.hidden { overflow:hidden; }
+.scroll { overflow:scroll; }
+.auto { overflow:auto; }
+
+.o { text-overflow: ellipsis; }
+
+#inline legend { display:inline; }
+#inline-block legend { display:inline-block; }
+    </style>
+</head>
+<body>
+
+<fieldset><legend class="hidden s10"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="scroll s10">Legend Test</legend></fieldset>
+<fieldset><legend class="auto s10">Legend Test</legend></fieldset>
+<fieldset><legend class="hidden w50"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="scroll w50">Legend Test</legend></fieldset>
+<fieldset><legend class="auto w50"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="hidden">Legend Test</legend></fieldset>
+<fieldset><legend class="auto"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="auto" style="width:auto"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend style="width:auto"><b>Legend Test</b></legend></fieldset>
+
+<fieldset><legend class="hidden w50 o"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="hidden w50 o">Test Legend</legend></fieldset>
+<fieldset><legend class="hidden o">Test Legend</legend></fieldset>
+<fieldset><legend class="auto w50 o"><b>Legend Test</b></legend></fieldset>
+<fieldset><legend class="hidden w50 o" align="right">Test Legend</legend></fieldset>
+<fieldset><legend class="hidden w50 o" align="center">Test Legend</legend></fieldset>
+
+<div id="inline">
+<legend class="hidden s10"><b>Legend Test</b></legend>
+<legend class="scroll s10">Legend Test</legend>
+<legend class="auto s10">Legend Test</legend>
+<legend class="hidden w50"><b>Legend Test</b></legend>
+<legend class="scroll w50">Legend Test</legend>
+<legend class="auto w50"><b>Legend Test</b></legend>
+<legend class="hidden">Legend Test</legend>
+<legend class="auto"><b>Legend Test</b></legend>
+
+<legend class="hidden w50 o"><b>Legend Test</b></legend>
+<legend class="hidden w50 o">Test Legend</legend>
+<legend class="hidden o">Test Legend</legend>
+<legend class="auto w50 o"><b>Legend Test</b></legend>
+<legend class="hidden w50 o" align="right">Test Legend</legend>
+<legend class="hidden w50 o" align="center">Test Legend</legend>
+</div>
+
+<div id="inline-block">
+<legend class="hidden s10"><b>Legend Test</b></legend>
+<legend class="scroll s10">Legend Test</legend>
+<legend class="auto s10">Legend Test</legend>
+<legend class="hidden w50"><b>Legend Test</b></legend>
+<legend class="scroll w50">Legend Test</legend>
+<legend class="auto w50"><b>Legend Test</b></legend>
+<legend class="hidden">Legend Test</legend>
+<legend class="auto"><b>Legend Test</b></legend>
+<legend class="auto" style="width:auto"><b>Legend Test</b></legend>
+
+<legend class="hidden w50 o"><b>Legend Test</b></legend>
+<legend class="hidden w50 o">Test Legend</legend>
+<legend class="hidden o">Test Legend</legend>
+<legend class="auto w50 o"><b>Legend Test</b></legend>
+<legend class="hidden w50 o" align="right">Test Legend</legend>
+<legend class="hidden w50 o" align="center">Test Legend</legend>
+</div>
+
+<legend class="auto w50"><b>Legend Test</b></legend>
+<legend class="auto" zstyle="width:auto"><b>Legend Test</b></legend>
+<legend style="width:auto"><b>Legend Test</b></legend>
+
+</body>
+</html>
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -59,16 +59,18 @@ fails-if(Android) != textarea-rtl.html t
 
 == select-multiple.html select-multiple-ref.html
 == select-boguskids.html select-boguskids-ref.html
 == select-dynamic-boguskids.html select-boguskids-ref.html
 
 asserts(2) == button-first-letter-1.html button-first-letter-1-ref.html
 asserts(1) != button-first-letter-1.html button-first-letter-1-noref.html
 
+== legend.html legend-ref.html
+
 # placeholder
 include placeholder/reftest.list
 
 # input
 include input/reftest.list
 
 # output element
 include output/reftest.list