LCOV - code coverage report
Current view: top level - layout/forms - nsFieldSetFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 295 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsFieldSetFrame.h"
       7             : 
       8             : #include <algorithm>
       9             : #include "gfxContext.h"
      10             : #include "mozilla/gfx/2D.h"
      11             : #include "mozilla/Likely.h"
      12             : #include "mozilla/Maybe.h"
      13             : #include "nsCSSAnonBoxes.h"
      14             : #include "nsCSSRendering.h"
      15             : #include "nsDisplayList.h"
      16             : #include "nsGkAtoms.h"
      17             : #include "nsIFrameInlines.h"
      18             : #include "nsLayoutUtils.h"
      19             : #include "nsLegendFrame.h"
      20             : #include "nsStyleConsts.h"
      21             : 
      22             : using namespace mozilla;
      23             : using namespace mozilla::gfx;
      24             : using namespace mozilla::layout;
      25             : 
      26             : nsContainerFrame*
      27           0 : NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      28             : {
      29           0 :   return new (aPresShell) nsFieldSetFrame(aContext);
      30             : }
      31             : 
      32           0 : NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
      33             : 
      34           0 : nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext)
      35             :   : nsContainerFrame(aContext, kClassID)
      36           0 :   , mLegendRect(GetWritingMode())
      37             : {
      38           0 :   mLegendSpace  = 0;
      39           0 : }
      40             : 
      41             : nsRect
      42           0 : nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
      43             : {
      44           0 :   WritingMode wm = GetWritingMode();
      45           0 :   Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
      46           0 :   nscoord legendBorder = StyleBorder()->GetComputedBorderWidth(legendSide);
      47           0 :   LogicalRect r(wm, LogicalPoint(wm, 0, 0), GetLogicalSize(wm));
      48           0 :   nsSize containerSize = r.Size(wm).GetPhysicalSize(wm);
      49           0 :   if (legendBorder < mLegendRect.BSize(wm)) {
      50           0 :     nscoord off = (mLegendRect.BSize(wm) - legendBorder) / 2;
      51           0 :     r.BStart(wm) += off;
      52           0 :     r.BSize(wm) -= off;
      53             :   }
      54           0 :   return r.GetPhysicalRect(wm, containerSize);
      55             : }
      56             : 
      57             : nsIFrame*
      58           0 : nsFieldSetFrame::GetInner() const
      59             : {
      60           0 :   nsIFrame* last = mFrames.LastChild();
      61           0 :   if (last &&
      62           0 :       last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) {
      63           0 :     return last;
      64             :   }
      65           0 :   MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
      66           0 :   return nullptr;
      67             : }
      68             : 
      69             : nsIFrame*
      70           0 : nsFieldSetFrame::GetLegend() const
      71             : {
      72           0 :   if (mFrames.FirstChild() == GetInner()) {
      73           0 :     MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
      74           0 :     return nullptr;
      75             :   }
      76           0 :   MOZ_ASSERT(mFrames.FirstChild() &&
      77             :              mFrames.FirstChild()->GetContentInsertionFrame()->IsLegendFrame());
      78           0 :   return mFrames.FirstChild();
      79             : }
      80             : 
      81             : class nsDisplayFieldSetBorder : public nsDisplayItem {
      82             : public:
      83           0 :   nsDisplayFieldSetBorder(nsDisplayListBuilder* aBuilder,
      84             :                           nsFieldSetFrame* aFrame)
      85           0 :     : nsDisplayItem(aBuilder, aFrame) {
      86           0 :     MOZ_COUNT_CTOR(nsDisplayFieldSetBorder);
      87           0 :   }
      88             : #ifdef NS_BUILD_REFCNT_LOGGING
      89           0 :   virtual ~nsDisplayFieldSetBorder() {
      90           0 :     MOZ_COUNT_DTOR(nsDisplayFieldSetBorder);
      91           0 :   }
      92             : #endif
      93             :   virtual void Paint(nsDisplayListBuilder* aBuilder,
      94             :                      gfxContext* aCtx) override;
      95             :   virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
      96             :   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
      97             :                                          const nsDisplayItemGeometry* aGeometry,
      98             :                                          nsRegion *aInvalidRegion) override;
      99             :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
     100           0 :   NS_DISPLAY_DECL_NAME("FieldSetBorder", TYPE_FIELDSET_BORDER_BACKGROUND)
     101             : };
     102             : 
     103             : void
     104           0 : nsDisplayFieldSetBorder::Paint(nsDisplayListBuilder* aBuilder,
     105             :                                gfxContext* aCtx)
     106             : {
     107           0 :   image::DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
     108           0 :     PaintBorder(aBuilder, *aCtx, ToReferenceFrame(), mVisibleRect);
     109             : 
     110           0 :   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
     111           0 : }
     112             : 
     113             : nsDisplayItemGeometry*
     114           0 : nsDisplayFieldSetBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
     115             : {
     116           0 :   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
     117             : }
     118             : 
     119             : void
     120           0 : nsDisplayFieldSetBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
     121             :                                                    const nsDisplayItemGeometry* aGeometry,
     122             :                                                    nsRegion *aInvalidRegion)
     123             : {
     124             :   auto geometry =
     125           0 :     static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
     126             : 
     127           0 :   if (aBuilder->ShouldSyncDecodeImages() &&
     128           0 :       geometry->ShouldInvalidateToSyncDecodeImages()) {
     129             :     bool snap;
     130           0 :     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
     131             :   }
     132             : 
     133           0 :   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
     134           0 : }
     135             : 
     136             : nsRect
     137           0 : nsDisplayFieldSetBorder::GetBounds(nsDisplayListBuilder* aBuilder,
     138             :                                    bool* aSnap)
     139             : {
     140             :   // Just go ahead and claim our frame's overflow rect as the bounds, because we
     141             :   // may have border-image-outset or other features that cause borders to extend
     142             :   // outside the border rect.  We could try to duplicate all the complexity
     143             :   // nsDisplayBorder has here, but keeping things in sync would be a pain, and
     144             :   // this code is not typically performance-sensitive.
     145           0 :   *aSnap = false;
     146           0 :   return Frame()->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
     147             : }
     148             : 
     149             : void
     150           0 : nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     151             :                                   const nsRect&           aDirtyRect,
     152             :                                   const nsDisplayListSet& aLists) {
     153             :   // Paint our background and border in a special way.
     154             :   // REVIEW: We don't really need to check frame emptiness here; if it's empty,
     155             :   // the background/border display item won't do anything, and if it isn't empty,
     156             :   // we need to paint the outline
     157           0 :   if (!(GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) &&
     158           0 :       IsVisibleForPainting(aBuilder)) {
     159           0 :     if (StyleEffects()->mBoxShadow) {
     160           0 :       aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     161           0 :         nsDisplayBoxShadowOuter(aBuilder, this));
     162             :     }
     163             : 
     164           0 :     nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
     165           0 :       aBuilder, this, VisualBorderRectRelativeToSelf(),
     166             :       aLists.BorderBackground(),
     167           0 :       /* aAllowWillPaintBorderOptimization = */ false);
     168             : 
     169           0 :     aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     170           0 :       nsDisplayFieldSetBorder(aBuilder, this));
     171             : 
     172           0 :     DisplayOutlineUnconditional(aBuilder, aLists);
     173             : 
     174           0 :     DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame");
     175             :   }
     176             : 
     177           0 :   if (GetPrevInFlow()) {
     178           0 :     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
     179             :   }
     180             : 
     181           0 :   nsDisplayListCollection contentDisplayItems;
     182           0 :   if (nsIFrame* inner = GetInner()) {
     183             :     // Collect the inner frame's display items into their own collection.
     184             :     // We need to be calling BuildDisplayList on it before the legend in
     185             :     // case it contains out-of-flow frames whose placeholders are in the
     186             :     // legend. However, we want the inner frame's display items to be
     187             :     // after the legend's display items in z-order, so we need to save them
     188             :     // and append them later.
     189           0 :     BuildDisplayListForChild(aBuilder, inner, aDirtyRect, contentDisplayItems);
     190             :   }
     191           0 :   if (nsIFrame* legend = GetLegend()) {
     192             :     // The legend's background goes on our BlockBorderBackgrounds list because
     193             :     // it's a block child.
     194           0 :     nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
     195           0 :     BuildDisplayListForChild(aBuilder, legend, aDirtyRect, set);
     196             :   }
     197             :   // Put the inner frame's display items on the master list. Note that this
     198             :   // moves its border/background display items to our BorderBackground() list,
     199             :   // which isn't really correct, but it's OK because the inner frame is
     200             :   // anonymous and can't have its own border and background.
     201           0 :   contentDisplayItems.MoveTo(aLists);
     202           0 : }
     203             : 
     204             : image::DrawResult
     205           0 : nsFieldSetFrame::PaintBorder(
     206             :   nsDisplayListBuilder* aBuilder,
     207             :   gfxContext& aRenderingContext,
     208             :   nsPoint aPt,
     209             :   const nsRect& aDirtyRect)
     210             : {
     211             :   // If the border is smaller than the legend, move the border down
     212             :   // to be centered on the legend.  We call VisualBorderRectRelativeToSelf() to
     213             :   // compute the border positioning.
     214             :   // FIXME: This means border-radius clamping is incorrect; we should
     215             :   // override nsIFrame::GetBorderRadii.
     216           0 :   nsRect rect = VisualBorderRectRelativeToSelf() + aPt;
     217           0 :   nsPresContext* presContext = PresContext();
     218             : 
     219           0 :   PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
     220           0 :                                ? PaintBorderFlags::SYNC_DECODE_IMAGES
     221           0 :                                : PaintBorderFlags();
     222             : 
     223           0 :   DrawResult result = DrawResult::SUCCESS;
     224             : 
     225           0 :   nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
     226           0 :                                       this, rect);
     227             : 
     228           0 :   if (nsIFrame* legend = GetLegend()) {
     229             :     // We want to avoid drawing our border under the legend, so clip out the
     230             :     // legend while drawing our border.  We don't want to use mLegendRect here,
     231             :     // because we do want to draw our border under the legend's inline-start and
     232             :     // -end margins.  And we use GetNormalRect(), not GetRect(), because we do
     233             :     // not want relative positioning applied to the legend to change how our
     234             :     // border looks.
     235           0 :     nsRect legendRect = legend->GetNormalRect() + aPt;
     236             : 
     237           0 :     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     238             :     // We set up a clip path which has our rect clockwise and the legend rect
     239             :     // counterclockwise, with FILL_WINDING as the fill rule.  That will allow us
     240             :     // to paint within our rect but outside the legend rect.  For "our rect" we
     241             :     // use our visual overflow rect (relative to ourselves, so it's not affected
     242             :     // by transforms), because we can have borders sticking outside our border
     243             :     // box (e.g. due to border-image-outset).
     244             :     RefPtr<PathBuilder> pathBuilder =
     245           0 :       drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
     246           0 :     int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     247           0 :     AppendRectToPath(pathBuilder,
     248           0 :                      NSRectToSnappedRect(GetVisualOverflowRectRelativeToSelf() + aPt,
     249             :                                          appUnitsPerDevPixel,
     250           0 :                                          *drawTarget),
     251           0 :                      true);
     252           0 :     AppendRectToPath(pathBuilder,
     253           0 :                      NSRectToSnappedRect(legendRect, appUnitsPerDevPixel,
     254           0 :                                          *drawTarget),
     255           0 :                      false);
     256           0 :     RefPtr<Path> clipPath = pathBuilder->Finish();
     257             : 
     258           0 :     aRenderingContext.Save();
     259           0 :     aRenderingContext.Clip(clipPath);
     260             :     result &=
     261             :       nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
     262           0 :                                   aDirtyRect, rect, mStyleContext, borderFlags);
     263           0 :     aRenderingContext.Restore();
     264             :   } else {
     265             :     result &=
     266             :       nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
     267           0 :                                   aDirtyRect, nsRect(aPt, mRect.Size()),
     268           0 :                                   mStyleContext, borderFlags);
     269             :   }
     270             : 
     271           0 :   return result;
     272             : }
     273             : 
     274             : nscoord
     275           0 : nsFieldSetFrame::GetIntrinsicISize(gfxContext* aRenderingContext,
     276             :                                    nsLayoutUtils::IntrinsicISizeType aType)
     277             : {
     278           0 :   nscoord legendWidth = 0;
     279           0 :   nscoord contentWidth = 0;
     280           0 :   if (nsIFrame* legend = GetLegend()) {
     281           0 :     legendWidth =
     282           0 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext, legend, aType);
     283             :   }
     284             : 
     285           0 :   if (nsIFrame* inner = GetInner()) {
     286             :     // Ignore padding on the inner, since the padding will be applied to the
     287             :     // outer instead, and the padding computed for the inner is wrong
     288             :     // for percentage padding.
     289           0 :     contentWidth =
     290           0 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType,
     291             :                                            nsLayoutUtils::IGNORE_PADDING);
     292             :   }
     293             : 
     294           0 :   return std::max(legendWidth, contentWidth);
     295             : }
     296             : 
     297             : 
     298             : nscoord
     299           0 : nsFieldSetFrame::GetMinISize(gfxContext* aRenderingContext)
     300             : {
     301           0 :   nscoord result = 0;
     302           0 :   DISPLAY_MIN_WIDTH(this, result);
     303             : 
     304           0 :   result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
     305           0 :   return result;
     306             : }
     307             : 
     308             : nscoord
     309           0 : nsFieldSetFrame::GetPrefISize(gfxContext* aRenderingContext)
     310             : {
     311           0 :   nscoord result = 0;
     312           0 :   DISPLAY_PREF_WIDTH(this, result);
     313             : 
     314           0 :   result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
     315           0 :   return result;
     316             : }
     317             : 
     318             : /* virtual */
     319             : void
     320           0 : nsFieldSetFrame::Reflow(nsPresContext*           aPresContext,
     321             :                         ReflowOutput&     aDesiredSize,
     322             :                         const ReflowInput& aReflowInput,
     323             :                         nsReflowStatus&          aStatus)
     324             : {
     325           0 :   MarkInReflow();
     326           0 :   DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
     327           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     328             : 
     329           0 :   NS_PRECONDITION(aReflowInput.ComputedISize() != NS_INTRINSICSIZE,
     330             :                   "Should have a precomputed inline-size!");
     331             : 
     332             :   // Initialize OUT parameter
     333           0 :   aStatus.Reset();
     334             : 
     335           0 :   nsOverflowAreas ocBounds;
     336           0 :   nsReflowStatus ocStatus;
     337           0 :   if (GetPrevInFlow()) {
     338           0 :     ReflowOverflowContainerChildren(aPresContext, aReflowInput, ocBounds, 0,
     339           0 :                                     ocStatus);
     340             :   }
     341             : 
     342             :   //------------ Handle Incremental Reflow -----------------
     343             :   bool reflowInner;
     344             :   bool reflowLegend;
     345           0 :   nsIFrame* legend = GetLegend();
     346           0 :   nsIFrame* inner = GetInner();
     347           0 :   if (aReflowInput.ShouldReflowAllKids()) {
     348           0 :     reflowInner = inner != nullptr;
     349           0 :     reflowLegend = legend != nullptr;
     350             :   } else {
     351           0 :     reflowInner = inner && NS_SUBTREE_DIRTY(inner);
     352           0 :     reflowLegend = legend && NS_SUBTREE_DIRTY(legend);
     353             :   }
     354             : 
     355             :   // We don't allow fieldsets to break vertically. If we did, we'd
     356             :   // need logic here to push and pull overflow frames.
     357             :   // Since we're not applying our padding in this frame, we need to add it here
     358             :   // to compute the available width for our children.
     359           0 :   WritingMode wm = GetWritingMode();
     360           0 :   WritingMode innerWM = inner ? inner->GetWritingMode() : wm;
     361           0 :   WritingMode legendWM = legend ? legend->GetWritingMode() : wm;
     362           0 :   LogicalSize innerAvailSize = aReflowInput.ComputedSizeWithPadding(innerWM);
     363           0 :   LogicalSize legendAvailSize = aReflowInput.ComputedSizeWithPadding(legendWM);
     364           0 :   innerAvailSize.BSize(innerWM) = legendAvailSize.BSize(legendWM) =
     365             :     NS_UNCONSTRAINEDSIZE;
     366             : 
     367             :   // get our border and padding
     368           0 :   LogicalMargin border = aReflowInput.ComputedLogicalBorderPadding() -
     369           0 :                          aReflowInput.ComputedLogicalPadding();
     370             : 
     371             :   // Figure out how big the legend is if there is one.
     372             :   // get the legend's margin
     373           0 :   LogicalMargin legendMargin(wm);
     374             :   // reflow the legend only if needed
     375           0 :   Maybe<ReflowInput> legendReflowInput;
     376           0 :   if (legend) {
     377             :     legendReflowInput.emplace(aPresContext, aReflowInput, legend,
     378           0 :                                 legendAvailSize);
     379             :   }
     380           0 :   if (reflowLegend) {
     381           0 :     ReflowOutput legendDesiredSize(aReflowInput);
     382             : 
     383             :     // We'll move the legend to its proper place later, so the position
     384             :     // and containerSize passed here are unimportant.
     385           0 :     const nsSize dummyContainerSize;
     386           0 :     ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowInput,
     387           0 :                 wm, LogicalPoint(wm), dummyContainerSize,
     388           0 :                 NS_FRAME_NO_MOVE_FRAME, aStatus);
     389             : #ifdef NOISY_REFLOW
     390             :     printf("  returned (%d, %d)\n",
     391             :            legendDesiredSize.Width(), legendDesiredSize.Height());
     392             : #endif
     393             :     // figure out the legend's rectangle
     394           0 :     legendMargin = legend->GetLogicalUsedMargin(wm);
     395           0 :     mLegendRect =
     396           0 :       LogicalRect(wm, 0, 0,
     397           0 :                   legendDesiredSize.ISize(wm) + legendMargin.IStartEnd(wm),
     398           0 :                   legendDesiredSize.BSize(wm) + legendMargin.BStartEnd(wm));
     399           0 :     nscoord oldSpace = mLegendSpace;
     400           0 :     mLegendSpace = 0;
     401           0 :     if (mLegendRect.BSize(wm) > border.BStart(wm)) {
     402             :       // center the border on the legend
     403           0 :       mLegendSpace = mLegendRect.BSize(wm) - border.BStart(wm);
     404             :     } else {
     405           0 :       mLegendRect.BStart(wm) =
     406           0 :         (border.BStart(wm) - mLegendRect.BSize(wm)) / 2;
     407             :     }
     408             : 
     409             :     // if the legend space changes then we need to reflow the
     410             :     // content area as well.
     411           0 :     if (mLegendSpace != oldSpace && inner) {
     412           0 :       reflowInner = true;
     413             :     }
     414             : 
     415             :     FinishReflowChild(legend, aPresContext, legendDesiredSize,
     416           0 :                       legendReflowInput.ptr(), wm, LogicalPoint(wm),
     417           0 :                       dummyContainerSize, NS_FRAME_NO_MOVE_FRAME);
     418           0 :   } else if (!legend) {
     419           0 :     mLegendRect.SetEmpty();
     420           0 :     mLegendSpace = 0;
     421             :   } else {
     422             :     // mLegendSpace and mLegendRect haven't changed, but we need
     423             :     // the used margin when placing the legend.
     424           0 :     legendMargin = legend->GetLogicalUsedMargin(wm);
     425             :   }
     426             : 
     427             :   // This containerSize is incomplete as yet: it does not include the size
     428             :   // of the |inner| frame itself.
     429           0 :   nsSize containerSize = (LogicalSize(wm, 0, mLegendSpace) +
     430           0 :                           border.Size(wm)).GetPhysicalSize(wm);
     431             :   // reflow the content frame only if needed
     432           0 :   if (reflowInner) {
     433             :     ReflowInput kidReflowInput(aPresContext, aReflowInput, inner,
     434             :                                      innerAvailSize, nullptr,
     435           0 :                                      ReflowInput::CALLER_WILL_INIT);
     436             :     // Override computed padding, in case it's percentage padding
     437             :     kidReflowInput.Init(aPresContext, nullptr, nullptr,
     438           0 :                         &aReflowInput.ComputedPhysicalPadding());
     439             :     // Our child is "height:100%" but we actually want its height to be reduced
     440             :     // by the amount of content-height the legend is eating up, unless our
     441             :     // height is unconstrained (in which case the child's will be too).
     442           0 :     if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
     443           0 :       kidReflowInput.SetComputedBSize(
     444           0 :          std::max(0, aReflowInput.ComputedBSize() - mLegendSpace));
     445             :     }
     446             : 
     447           0 :     if (aReflowInput.ComputedMinBSize() > 0) {
     448           0 :       kidReflowInput.ComputedMinBSize() =
     449           0 :         std::max(0, aReflowInput.ComputedMinBSize() - mLegendSpace);
     450             :     }
     451             : 
     452           0 :     if (aReflowInput.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) {
     453           0 :       kidReflowInput.ComputedMaxBSize() =
     454           0 :         std::max(0, aReflowInput.ComputedMaxBSize() - mLegendSpace);
     455             :     }
     456             : 
     457             :     ReflowOutput kidDesiredSize(kidReflowInput,
     458           0 :                                        aDesiredSize.mFlags);
     459             :     // Reflow the frame
     460           0 :     NS_ASSERTION(kidReflowInput.ComputedPhysicalMargin() == nsMargin(0,0,0,0),
     461             :                  "Margins on anonymous fieldset child not supported!");
     462           0 :     LogicalPoint pt(wm, border.IStart(wm), border.BStart(wm) + mLegendSpace);
     463             : 
     464             :     // We don't know the correct containerSize until we have reflowed |inner|,
     465             :     // so we use a dummy value for now; FinishReflowChild will fix the position
     466             :     // if necessary.
     467           0 :     const nsSize dummyContainerSize;
     468           0 :     ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowInput,
     469           0 :                 wm, pt, dummyContainerSize, 0, aStatus);
     470             : 
     471             :     // Update containerSize to account for size of the inner frame, so that
     472             :     // FinishReflowChild can position it correctly.
     473           0 :     containerSize += kidDesiredSize.PhysicalSize();
     474             :     FinishReflowChild(inner, aPresContext, kidDesiredSize,
     475           0 :                       &kidReflowInput, wm, pt, containerSize, 0);
     476           0 :     NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
     477           0 :   } else if (inner) {
     478             :     // |inner| didn't need to be reflowed but we do need to include its size
     479             :     // in containerSize.
     480           0 :     containerSize += inner->GetSize();
     481             :   }
     482             : 
     483           0 :   LogicalRect contentRect(wm);
     484           0 :   if (inner) {
     485             :     // We don't support margins on inner, so our content rect is just the
     486             :     // inner's border-box. (We don't really care about container size at this
     487             :     // point, as we'll figure out the actual positioning later.)
     488           0 :     contentRect = inner->GetLogicalRect(wm, containerSize);
     489             :   }
     490             : 
     491             :   // Our content rect must fill up the available width
     492           0 :   LogicalSize availSize = aReflowInput.ComputedSizeWithPadding(wm);
     493           0 :   if (availSize.ISize(wm) > contentRect.ISize(wm)) {
     494           0 :     contentRect.ISize(wm) = innerAvailSize.ISize(wm);
     495             :   }
     496             : 
     497           0 :   if (legend) {
     498             :     // The legend is positioned inline-wards within the inner's content rect
     499             :     // (so that padding on the fieldset affects the legend position).
     500           0 :     LogicalRect innerContentRect = contentRect;
     501           0 :     innerContentRect.Deflate(wm, aReflowInput.ComputedLogicalPadding());
     502             :     // If the inner content rect is larger than the legend, we can align the
     503             :     // legend.
     504           0 :     if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) {
     505             :       // NOTE legend @align values are: left/right/center/top/bottom.
     506             :       // GetLogicalAlign converts left/right to start/end for the given WM.
     507             :       // @see HTMLLegendElement::ParseAttribute, nsLegendFrame::GetLogicalAlign
     508             :       int32_t align = static_cast<nsLegendFrame*>
     509           0 :         (legend->GetContentInsertionFrame())->GetLogicalAlign(wm);
     510           0 :       switch (align) {
     511             :         case NS_STYLE_TEXT_ALIGN_END:
     512           0 :           mLegendRect.IStart(wm) =
     513           0 :             innerContentRect.IEnd(wm) - mLegendRect.ISize(wm);
     514           0 :           break;
     515             :         case NS_STYLE_TEXT_ALIGN_CENTER:
     516             :           // Note: rounding removed; there doesn't seem to be any need
     517           0 :           mLegendRect.IStart(wm) = innerContentRect.IStart(wm) +
     518           0 :             (innerContentRect.ISize(wm) - mLegendRect.ISize(wm)) / 2;
     519           0 :           break;
     520             :         case NS_STYLE_TEXT_ALIGN_START:
     521             :         case NS_STYLE_VERTICAL_ALIGN_TOP:
     522             :         case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
     523           0 :           mLegendRect.IStart(wm) = innerContentRect.IStart(wm);
     524           0 :           break;
     525             :         default:
     526           0 :           MOZ_ASSERT_UNREACHABLE("unexpected GetLogicalAlign value");
     527             :       }
     528             :     } else {
     529             :       // otherwise just start-align it.
     530           0 :       mLegendRect.IStart(wm) = innerContentRect.IStart(wm);
     531             :     }
     532             : 
     533             :     // place the legend
     534           0 :     LogicalRect actualLegendRect = mLegendRect;
     535           0 :     actualLegendRect.Deflate(wm, legendMargin);
     536           0 :     LogicalPoint actualLegendPos(actualLegendRect.Origin(wm));
     537             : 
     538             :     // Note that legend's writing mode may be different from the fieldset's,
     539             :     // so we need to convert offsets before applying them to it (bug 1134534).
     540             :     LogicalMargin offsets =
     541           0 :       legendReflowInput->ComputedLogicalOffsets().
     542           0 :         ConvertTo(wm, legendReflowInput->GetWritingMode());
     543             :     ReflowInput::ApplyRelativePositioning(legend, wm, offsets,
     544             :                                                 &actualLegendPos,
     545           0 :                                                 containerSize);
     546             : 
     547           0 :     legend->SetPosition(wm, actualLegendPos, containerSize);
     548           0 :     nsContainerFrame::PositionFrameView(legend);
     549           0 :     nsContainerFrame::PositionChildViews(legend);
     550             :   }
     551             : 
     552             :   // Return our size and our result.
     553           0 :   LogicalSize finalSize(wm, contentRect.ISize(wm) + border.IStartEnd(wm),
     554           0 :                         mLegendSpace + border.BStartEnd(wm) +
     555           0 :                         (inner ? inner->BSize(wm) : 0));
     556           0 :   aDesiredSize.SetSize(wm, finalSize);
     557           0 :   aDesiredSize.SetOverflowAreasToDesiredBounds();
     558             : 
     559           0 :   if (legend) {
     560           0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
     561             :   }
     562           0 :   if (inner) {
     563           0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner);
     564             :   }
     565             : 
     566             :   // Merge overflow container bounds and status.
     567           0 :   aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
     568           0 :   aStatus.MergeCompletionStatusFrom(ocStatus);
     569             : 
     570           0 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus);
     571             : 
     572           0 :   InvalidateFrame();
     573             : 
     574           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     575           0 : }
     576             : 
     577             : #ifdef DEBUG
     578             : void
     579           0 : nsFieldSetFrame::SetInitialChildList(ChildListID    aListID,
     580             :                                      nsFrameList&   aChildList)
     581             : {
     582           0 :   nsContainerFrame::SetInitialChildList(aListID, aChildList);
     583           0 :   MOZ_ASSERT(aListID != kPrincipalList || GetInner(),
     584             :              "Setting principal child list should populate our inner frame");
     585           0 : }
     586             : void
     587           0 : nsFieldSetFrame::AppendFrames(ChildListID    aListID,
     588             :                               nsFrameList&   aFrameList)
     589             : {
     590           0 :   MOZ_CRASH("nsFieldSetFrame::AppendFrames not supported");
     591             : }
     592             : 
     593             : void
     594           0 : nsFieldSetFrame::InsertFrames(ChildListID    aListID,
     595             :                               nsIFrame*      aPrevFrame,
     596             :                               nsFrameList&   aFrameList)
     597             : {
     598           0 :   MOZ_CRASH("nsFieldSetFrame::InsertFrames not supported");
     599             : }
     600             : 
     601             : void
     602           0 : nsFieldSetFrame::RemoveFrame(ChildListID    aListID,
     603             :                              nsIFrame*      aOldFrame)
     604             : {
     605           0 :   MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported");
     606             : }
     607             : #endif
     608             : 
     609             : #ifdef ACCESSIBILITY
     610             : a11y::AccType
     611           0 : nsFieldSetFrame::AccessibleType()
     612             : {
     613           0 :   return a11y::eHTMLGroupboxType;
     614             : }
     615             : #endif
     616             : 
     617             : nscoord
     618           0 : nsFieldSetFrame::GetLogicalBaseline(WritingMode aWM) const
     619             : {
     620           0 :   switch (StyleDisplay()->mDisplay) {
     621             :     case mozilla::StyleDisplay::Grid:
     622             :     case mozilla::StyleDisplay::InlineGrid:
     623             :     case mozilla::StyleDisplay::Flex:
     624             :     case mozilla::StyleDisplay::InlineFlex:
     625           0 :       return BaselineBOffset(aWM, BaselineSharingGroup::eFirst,
     626           0 :                              AlignmentContext::eInline);
     627             :     default:
     628           0 :       return BSize(aWM) - BaselineBOffset(aWM, BaselineSharingGroup::eLast,
     629           0 :                                           AlignmentContext::eInline);
     630             :   }
     631             : }
     632             : 
     633             : bool
     634           0 : nsFieldSetFrame::GetVerticalAlignBaseline(WritingMode aWM,
     635             :                                           nscoord* aBaseline) const
     636             : {
     637           0 :   nsIFrame* inner = GetInner();
     638           0 :   MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM));
     639           0 :   if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) {
     640           0 :     return false;
     641             :   }
     642           0 :   nscoord innerBStart = inner->BStart(aWM, GetSize());
     643           0 :   *aBaseline += innerBStart;
     644           0 :   return true;
     645             : }
     646             : 
     647             : bool
     648           0 : nsFieldSetFrame::GetNaturalBaselineBOffset(WritingMode          aWM,
     649             :                                            BaselineSharingGroup aBaselineGroup,
     650             :                                            nscoord*             aBaseline) const
     651             : {
     652           0 :   nsIFrame* inner = GetInner();
     653           0 :   MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM));
     654           0 :   if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) {
     655           0 :     return false;
     656             :   }
     657           0 :   nscoord innerBStart = inner->BStart(aWM, GetSize());
     658           0 :   if (aBaselineGroup == BaselineSharingGroup::eFirst) {
     659           0 :     *aBaseline += innerBStart;
     660             :   } else {
     661           0 :     *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM));
     662             :   }
     663           0 :   return true;
     664             : }
     665             : 
     666             : void
     667           0 : nsFieldSetFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
     668             : {
     669           0 :   if (nsIFrame* kid = GetInner()) {
     670           0 :     aResult.AppendElement(OwnedAnonBox(kid));
     671             :   }
     672           0 : }
     673             : 

Generated by: LCOV version 1.13