forked from mirrors/gecko-dev
		
	Instead, sort stuff using CSSOrderAwareFrameIterator. The current sorting is broken in presence of dynamic insertions, consider the following <Child(order)> combination in the DOM: <A(1000)> <B(0)> That'd look like: <B(0)> <A(1000)> On the frame tree. However when appending a child before B so that the DOM looks like: <A(1000)> <C(0)> <B(0)> The frame constructor will properly insert after A, and the reordering, which is stable, will end up with: <B(0)> <C(0)> <A(1000)> Which is the wrong frame tree order. We only use -moz-box-ordinal-group in regular sprocket layout, so just handle it there rather than everywhere. Similarly, we only rely on it for in-flow stuff, so remove the test for that added in bug 877890 (flex changed behavior afterwards, interestingly enough). Differential Revision: https://phabricator.services.mozilla.com/D94790
		
			
				
	
	
		
			1487 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1487 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
//
 | 
						|
// Eric Vaughan
 | 
						|
// Netscape Communications
 | 
						|
//
 | 
						|
// See documentation in associated header file
 | 
						|
//
 | 
						|
 | 
						|
#include "nsBoxLayoutState.h"
 | 
						|
#include "nsSprocketLayout.h"
 | 
						|
#include "nsPresContext.h"
 | 
						|
#include "nsCOMPtr.h"
 | 
						|
#include "nsIContent.h"
 | 
						|
#include "nsContainerFrame.h"
 | 
						|
#include "nsBoxFrame.h"
 | 
						|
#include "StackArena.h"
 | 
						|
#include "mozilla/Likely.h"
 | 
						|
#include "mozilla/CSSOrderAwareFrameIterator.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
using mozilla::StyleDirection;
 | 
						|
using namespace mozilla;
 | 
						|
 | 
						|
nsBoxLayout* nsSprocketLayout::gInstance = nullptr;
 | 
						|
 | 
						|
static Maybe<CSSOrderAwareFrameIterator> IterFor(nsIFrame* aBoxFrame) {
 | 
						|
  Maybe<CSSOrderAwareFrameIterator> ret;
 | 
						|
  if (aBoxFrame->IsXULBoxFrame()) {
 | 
						|
    ret.emplace(aBoxFrame, mozilla::layout::kPrincipalList,
 | 
						|
                CSSOrderAwareFrameIterator::ChildFilter::IncludeAll,
 | 
						|
                CSSOrderAwareFrameIterator::OrderState::Unknown,
 | 
						|
                CSSOrderAwareFrameIterator::OrderingProperty::BoxOrdinalGroup);
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
nsresult NS_NewSprocketLayout(nsCOMPtr<nsBoxLayout>& aNewLayout) {
 | 
						|
  if (!nsSprocketLayout::gInstance) {
 | 
						|
    nsSprocketLayout::gInstance = new nsSprocketLayout();
 | 
						|
    NS_IF_ADDREF(nsSprocketLayout::gInstance);
 | 
						|
  }
 | 
						|
  // we have not instance variables so just return our static one.
 | 
						|
  aNewLayout = nsSprocketLayout::gInstance;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*static*/
 | 
						|
void nsSprocketLayout::Shutdown() { NS_IF_RELEASE(gInstance); }
 | 
						|
 | 
						|
nsSprocketLayout::nsSprocketLayout() = default;
 | 
						|
 | 
						|
bool nsSprocketLayout::IsXULHorizontal(nsIFrame* aBox) {
 | 
						|
  return aBox->HasAnyStateBits(NS_STATE_IS_HORIZONTAL);
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::GetFrameState(nsIFrame* aBox, nsFrameState& aState) {
 | 
						|
  aState = aBox->GetStateBits();
 | 
						|
}
 | 
						|
 | 
						|
static StyleDirection GetFrameDirection(nsIFrame* aBox) {
 | 
						|
  return aBox->StyleVisibility()->mDirection;
 | 
						|
}
 | 
						|
 | 
						|
static void HandleBoxPack(nsIFrame* aBox, const nsFrameState& aFrameState,
 | 
						|
                          nscoord& aX, nscoord& aY, const nsRect& aOriginalRect,
 | 
						|
                          const nsRect& aClientRect) {
 | 
						|
  // In the normal direction we lay out our kids in the positive direction
 | 
						|
  // (e.g., |x| will get bigger for a horizontal box, and |y| will get bigger
 | 
						|
  // for a vertical box).  In the reverse direction, the opposite is true. We'll
 | 
						|
  // be laying out each child at a smaller |x| or |y|.
 | 
						|
  StyleDirection frameDirection = GetFrameDirection(aBox);
 | 
						|
 | 
						|
  if (aFrameState & NS_STATE_IS_HORIZONTAL) {
 | 
						|
    if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL) {
 | 
						|
      // The normal direction. |x| increases as we move through our children.
 | 
						|
      aX = aClientRect.x;
 | 
						|
    } else {
 | 
						|
      // The reverse direction. |x| decreases as we move through our children.
 | 
						|
      aX = aClientRect.x + aOriginalRect.width;
 | 
						|
    }
 | 
						|
    // |y| is always in the normal direction in horizontal boxes
 | 
						|
    aY = aClientRect.y;
 | 
						|
  } else {
 | 
						|
    // take direction property into account for |x| in vertical boxes
 | 
						|
    if (frameDirection == StyleDirection::Ltr) {
 | 
						|
      // The normal direction. |x| increases as we move through our children.
 | 
						|
      aX = aClientRect.x;
 | 
						|
    } else {
 | 
						|
      // The reverse direction. |x| decreases as we move through our children.
 | 
						|
      aX = aClientRect.x + aOriginalRect.width;
 | 
						|
    }
 | 
						|
    if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL) {
 | 
						|
      // The normal direction. |y| increases as we move through our children.
 | 
						|
      aY = aClientRect.y;
 | 
						|
    } else {
 | 
						|
      // The reverse direction. |y| decreases as we move through our children.
 | 
						|
      aY = aClientRect.y + aOriginalRect.height;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Get our pack/alignment information.
 | 
						|
  nsIFrame::Halignment halign = aBox->GetXULHAlign();
 | 
						|
  nsIFrame::Valignment valign = aBox->GetXULVAlign();
 | 
						|
 | 
						|
  // The following code handles box PACKING.  Packing comes into play in the
 | 
						|
  // case where the computed size for all of our children (now stored in our
 | 
						|
  // client rect) is smaller than the size available for the box (stored in
 | 
						|
  // |aOriginalRect|).
 | 
						|
  //
 | 
						|
  // Here we adjust our |x| and |y| variables accordingly so that we start at
 | 
						|
  // the beginning, middle, or end of the box.
 | 
						|
  //
 | 
						|
  // XXXdwh JUSTIFY needs to be implemented!
 | 
						|
  if (aFrameState & NS_STATE_IS_HORIZONTAL) {
 | 
						|
    switch (halign) {
 | 
						|
      case nsBoxFrame::hAlign_Left:
 | 
						|
        break;  // Nothing to do.  The default initialized us properly.
 | 
						|
 | 
						|
      case nsBoxFrame::hAlign_Center:
 | 
						|
        if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          aX += (aOriginalRect.width - aClientRect.width) / 2;
 | 
						|
        else
 | 
						|
          aX -= (aOriginalRect.width - aClientRect.width) / 2;
 | 
						|
        break;
 | 
						|
 | 
						|
      case nsBoxFrame::hAlign_Right:
 | 
						|
        if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          aX += (aOriginalRect.width - aClientRect.width);
 | 
						|
        else
 | 
						|
          aX -= (aOriginalRect.width - aClientRect.width);
 | 
						|
        break;  // Nothing to do for the reverse dir.  The default initialized
 | 
						|
                // us properly.
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    switch (valign) {
 | 
						|
      case nsBoxFrame::vAlign_Top:
 | 
						|
      case nsBoxFrame::vAlign_BaseLine:  // This value is technically impossible
 | 
						|
                                         // to specify for pack.
 | 
						|
        break;  // Don't do anything.  We were initialized correctly.
 | 
						|
 | 
						|
      case nsBoxFrame::vAlign_Middle:
 | 
						|
        if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          aY += (aOriginalRect.height - aClientRect.height) / 2;
 | 
						|
        else
 | 
						|
          aY -= (aOriginalRect.height - aClientRect.height) / 2;
 | 
						|
        break;
 | 
						|
 | 
						|
      case nsBoxFrame::vAlign_Bottom:
 | 
						|
        if (aFrameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          aY += (aOriginalRect.height - aClientRect.height);
 | 
						|
        else
 | 
						|
          aY -= (aOriginalRect.height - aClientRect.height);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
nsSprocketLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aState) {
 | 
						|
  // See if we are collapsed. If we are, then simply iterate over all our
 | 
						|
  // children and give them a rect of 0 width and height.
 | 
						|
  if (aBox->IsXULCollapsed()) {
 | 
						|
    for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
      nsBoxFrame::LayoutChildAt(aState, iter->get(), nsRect(0, 0, 0, 0));
 | 
						|
    }
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  nsBoxLayoutState::AutoReflowDepth depth(aState);
 | 
						|
  mozilla::AutoStackArena arena;
 | 
						|
 | 
						|
  // ----- figure out our size ----------
 | 
						|
  const nsSize originalSize = aBox->GetSize();
 | 
						|
 | 
						|
  // -- make sure we remove our border and padding  ----
 | 
						|
  nsRect clientRect;
 | 
						|
  aBox->GetXULClientRect(clientRect);
 | 
						|
 | 
						|
  // |originalClientRect| represents the rect of the entire box (excluding
 | 
						|
  // borders and padding).  We store it here because we're going to use
 | 
						|
  // |clientRect| to hold the required size for all our kids.  As an example,
 | 
						|
  // consider an hbox with a specified width of 300.  If the kids total only 150
 | 
						|
  // pixels of width, then we have 150 pixels left over.  |clientRect| is going
 | 
						|
  // to hold a width of 150 and is going to be adjusted based off the value of
 | 
						|
  // the PACK property.  If flexible objects are in the box, then the two rects
 | 
						|
  // will match.
 | 
						|
  nsRect originalClientRect(clientRect);
 | 
						|
 | 
						|
  // The frame state contains cached knowledge about our box, such as our
 | 
						|
  // orientation and direction.
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
 | 
						|
  // Build a list of our children's desired sizes and computed sizes
 | 
						|
  nsBoxSize* boxSizes = nullptr;
 | 
						|
  nsComputedBoxSize* computedBoxSizes = nullptr;
 | 
						|
 | 
						|
  nscoord min = 0;
 | 
						|
  nscoord max = 0;
 | 
						|
  int32_t flexes = 0;
 | 
						|
  PopulateBoxSizes(aBox, aState, boxSizes, min, max, flexes);
 | 
						|
 | 
						|
  // The |size| variable will hold the total size of children along the axis of
 | 
						|
  // the box.  Continuing with the example begun in the comment above, size
 | 
						|
  // would be 150 pixels.
 | 
						|
  nscoord size = clientRect.width;
 | 
						|
  if (!IsXULHorizontal(aBox)) size = clientRect.height;
 | 
						|
  ComputeChildSizes(aBox, aState, size, boxSizes, computedBoxSizes);
 | 
						|
 | 
						|
  // After the call to ComputeChildSizes, the |size| variable contains the
 | 
						|
  // total required size of all the children.  We adjust our clientRect in the
 | 
						|
  // appropriate dimension to match this size.  In our example, we now assign
 | 
						|
  // 150 pixels into the clientRect.width.
 | 
						|
  //
 | 
						|
  // The variables |min| and |max| hold the minimum required size box must be
 | 
						|
  // in the OPPOSITE orientation, e.g., for a horizontal box, |min| is the
 | 
						|
  // minimum height we require to enclose our children, and |max| is the maximum
 | 
						|
  // height required to enclose our children.
 | 
						|
  if (IsXULHorizontal(aBox)) {
 | 
						|
    clientRect.width = size;
 | 
						|
    if (clientRect.height < min) clientRect.height = min;
 | 
						|
 | 
						|
    if (frameState & NS_STATE_AUTO_STRETCH) {
 | 
						|
      if (clientRect.height > max) clientRect.height = max;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    clientRect.height = size;
 | 
						|
    if (clientRect.width < min) clientRect.width = min;
 | 
						|
 | 
						|
    if (frameState & NS_STATE_AUTO_STRETCH) {
 | 
						|
      if (clientRect.width > max) clientRect.width = max;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // With the sizes computed, now it's time to lay out our children.
 | 
						|
  bool finished;
 | 
						|
  nscoord passes = 0;
 | 
						|
 | 
						|
  // We flow children at their preferred locations (along with the appropriate
 | 
						|
  // computed flex). After we flow a child, it is possible that the child will
 | 
						|
  // change its size.  If/when this happens, we have to do another pass.
 | 
						|
  // Typically only 2 passes are required, but the code is prepared to do as
 | 
						|
  // many passes as are necessary to achieve equilibrium.
 | 
						|
  nscoord x = 0;
 | 
						|
  nscoord y = 0;
 | 
						|
  nscoord origX = 0;
 | 
						|
  nscoord origY = 0;
 | 
						|
 | 
						|
  // |childResized| lets us know if a child changed its size after we attempted
 | 
						|
  // to lay it out at the specified size.  If this happens, we usually have to
 | 
						|
  // do another pass.
 | 
						|
  bool childResized = false;
 | 
						|
 | 
						|
  // |passes| stores our number of passes.  If for any reason we end up doing
 | 
						|
  // more than, say, 10 passes, we assert to indicate that something is
 | 
						|
  // seriously screwed up.
 | 
						|
  passes = 0;
 | 
						|
  do {
 | 
						|
    // Always assume that we're done.  This will change if, for example,
 | 
						|
    // children don't stay the same size after being flowed.
 | 
						|
    finished = true;
 | 
						|
 | 
						|
    // Handle box packing.
 | 
						|
    HandleBoxPack(aBox, frameState, x, y, originalClientRect, clientRect);
 | 
						|
 | 
						|
    // Now that packing is taken care of we set up a few additional
 | 
						|
    // tracking variables.
 | 
						|
    origX = x;
 | 
						|
    origY = y;
 | 
						|
 | 
						|
    // Now we iterate over our box children and our box size lists in
 | 
						|
    // parallel.  For each child, we look at its sizes and figure out
 | 
						|
    // where to place it.
 | 
						|
    nsComputedBoxSize* childComputedBoxSize = computedBoxSizes;
 | 
						|
    nsBoxSize* childBoxSize = boxSizes;
 | 
						|
 | 
						|
    auto iter = IterFor(aBox);
 | 
						|
    int32_t count = 0;
 | 
						|
    while ((iter && !iter->AtEnd()) || (childBoxSize && childBoxSize->bogus)) {
 | 
						|
      // If for some reason, our lists are not the same length, we guard
 | 
						|
      // by bailing out of the loop.
 | 
						|
      if (childBoxSize == nullptr) {
 | 
						|
        MOZ_ASSERT_UNREACHABLE("Lists not the same length.");
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      nscoord width = clientRect.width;
 | 
						|
      nscoord height = clientRect.height;
 | 
						|
 | 
						|
      if (!childBoxSize->bogus) {
 | 
						|
        nsIFrame* child = iter->get();
 | 
						|
 | 
						|
        // We have a valid box size entry.  This entry already contains
 | 
						|
        // information about our sizes along the axis of the box (e.g., widths
 | 
						|
        // in a horizontal box).  If our default ALIGN is not stretch, however,
 | 
						|
        // then we also need to know the child's size along the opposite axis.
 | 
						|
        if (!(frameState & NS_STATE_AUTO_STRETCH)) {
 | 
						|
          nsSize prefSize = child->GetXULPrefSize(aState);
 | 
						|
          nsSize minSize = child->GetXULMinSize(aState);
 | 
						|
          nsSize maxSize = child->GetXULMaxSize(aState);
 | 
						|
          prefSize = nsIFrame::XULBoundsCheck(minSize, prefSize, maxSize);
 | 
						|
 | 
						|
          AddXULMargin(child, prefSize);
 | 
						|
          width = std::min(prefSize.width, originalClientRect.width);
 | 
						|
          height = std::min(prefSize.height, originalClientRect.height);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // Obtain the computed size along the axis of the box for this child from
 | 
						|
      // the computedBoxSize entry. We store the result in |width| for
 | 
						|
      // horizontal boxes and |height| for vertical boxes.
 | 
						|
      if (frameState & NS_STATE_IS_HORIZONTAL)
 | 
						|
        width = childComputedBoxSize->size;
 | 
						|
      else
 | 
						|
        height = childComputedBoxSize->size;
 | 
						|
 | 
						|
      // Adjust our x/y for the left/right spacing.
 | 
						|
      if (frameState & NS_STATE_IS_HORIZONTAL) {
 | 
						|
        if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          x += (childBoxSize->left);
 | 
						|
        else
 | 
						|
          x -= (childBoxSize->right);
 | 
						|
      } else {
 | 
						|
        if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          y += (childBoxSize->left);
 | 
						|
        else
 | 
						|
          y -= (childBoxSize->right);
 | 
						|
      }
 | 
						|
 | 
						|
      // Now we build a child rect.
 | 
						|
      nscoord rectX = x;
 | 
						|
      nscoord rectY = y;
 | 
						|
      if (!(frameState & NS_STATE_IS_DIRECTION_NORMAL)) {
 | 
						|
        if (frameState & NS_STATE_IS_HORIZONTAL)
 | 
						|
          rectX -= width;
 | 
						|
        else
 | 
						|
          rectY -= height;
 | 
						|
      }
 | 
						|
 | 
						|
      // We now create an accurate child rect based off our computed size
 | 
						|
      // information.
 | 
						|
      nsRect childRect(rectX, rectY, width, height);
 | 
						|
 | 
						|
      // Sanity check against our clientRect.  It is possible that a child
 | 
						|
      // specified a size that is too large to fit.  If that happens, then we
 | 
						|
      // have to grow our client rect.  Remember, clientRect is not the total
 | 
						|
      // rect of the enclosing box.  It currently holds our perception of how
 | 
						|
      // big the children needed to be.
 | 
						|
      if (childRect.width > clientRect.width)
 | 
						|
        clientRect.width = childRect.width;
 | 
						|
 | 
						|
      if (childRect.height > clientRect.height)
 | 
						|
        clientRect.height = childRect.height;
 | 
						|
 | 
						|
      // Either |nextX| or |nextY| is updated by this function call, according
 | 
						|
      // to our axis.
 | 
						|
      nscoord nextX = x;
 | 
						|
      nscoord nextY = y;
 | 
						|
 | 
						|
      ComputeChildsNextPosition(aBox, x, y, nextX, nextY, childRect);
 | 
						|
 | 
						|
      // Now we further update our nextX/Y along our axis.
 | 
						|
      // We also set childRect.y/x along the opposite axis appropriately for a
 | 
						|
      // stretch alignment.  (Non-stretch alignment is handled below.)
 | 
						|
      if (frameState & NS_STATE_IS_HORIZONTAL) {
 | 
						|
        if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          nextX += (childBoxSize->right);
 | 
						|
        else
 | 
						|
          nextX -= (childBoxSize->left);
 | 
						|
        childRect.y = originalClientRect.y;
 | 
						|
      } else {
 | 
						|
        if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
          nextY += (childBoxSize->right);
 | 
						|
        else
 | 
						|
          nextY -= (childBoxSize->left);
 | 
						|
        if (GetFrameDirection(aBox) == StyleDirection::Ltr) {
 | 
						|
          childRect.x = originalClientRect.x;
 | 
						|
        } else {
 | 
						|
          // keep the right edge of the box the same
 | 
						|
          childRect.x =
 | 
						|
              clientRect.x + originalClientRect.width - childRect.width;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // If we encounter a completely bogus box size, we just leave this child
 | 
						|
      // completely alone and continue through the loop to the next child.
 | 
						|
      if (childBoxSize->bogus) {
 | 
						|
        childComputedBoxSize = childComputedBoxSize->next;
 | 
						|
        childBoxSize = childBoxSize->next;
 | 
						|
        count++;
 | 
						|
        x = nextX;
 | 
						|
        y = nextY;
 | 
						|
        // FIXME(emilio): shouldn't this update `child` / `iter`? This looks
 | 
						|
        // broken.
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      nsIFrame* child = iter->get();
 | 
						|
      nsMargin margin(0, 0, 0, 0);
 | 
						|
 | 
						|
      bool layout = true;
 | 
						|
 | 
						|
      // Deflate the rect of our child by its margin.
 | 
						|
      child->GetXULMargin(margin);
 | 
						|
      childRect.Deflate(margin);
 | 
						|
      if (childRect.width < 0) childRect.width = 0;
 | 
						|
      if (childRect.height < 0) childRect.height = 0;
 | 
						|
 | 
						|
      // Now we're trying to figure out if we have to lay out this child, i.e.,
 | 
						|
      // to call the child's XULLayout method.
 | 
						|
      if (passes > 0) {
 | 
						|
        layout = false;
 | 
						|
      } else {
 | 
						|
        // Always perform layout if we are dirty or have dirty children
 | 
						|
        if (!child->IsSubtreeDirty()) {
 | 
						|
          layout = false;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      nsRect oldRect(child->GetRect());
 | 
						|
 | 
						|
      // Non-stretch alignment will be handled in AlignChildren(), so don't
 | 
						|
      // change child out-of-axis positions yet.
 | 
						|
      if (!(frameState & NS_STATE_AUTO_STRETCH)) {
 | 
						|
        if (frameState & NS_STATE_IS_HORIZONTAL) {
 | 
						|
          childRect.y = oldRect.y;
 | 
						|
        } else {
 | 
						|
          childRect.x = oldRect.x;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // We computed a childRect.  Now we want to set the bounds of the child to
 | 
						|
      // be that rect. If our old rect is different, then we know our size
 | 
						|
      // changed and we cache that fact in the |sizeChanged| variable.
 | 
						|
 | 
						|
      child->SetXULBounds(aState, childRect);
 | 
						|
      bool sizeChanged = (childRect.width != oldRect.width ||
 | 
						|
                          childRect.height != oldRect.height);
 | 
						|
 | 
						|
      if (sizeChanged) {
 | 
						|
        // Our size is different.  Sanity check against our maximum allowed size
 | 
						|
        // to ensure we didn't exceed it.
 | 
						|
        nsSize minSize = child->GetXULMinSize(aState);
 | 
						|
        nsSize maxSize = child->GetXULMaxSize(aState);
 | 
						|
        maxSize = nsIFrame::XULBoundsCheckMinMax(minSize, maxSize);
 | 
						|
 | 
						|
        // make sure the size is in our max size.
 | 
						|
        if (childRect.width > maxSize.width) childRect.width = maxSize.width;
 | 
						|
 | 
						|
        if (childRect.height > maxSize.height)
 | 
						|
          childRect.height = maxSize.height;
 | 
						|
 | 
						|
        // set it again
 | 
						|
        child->SetXULBounds(aState, childRect);
 | 
						|
      }
 | 
						|
 | 
						|
      // If we already determined that layout was required or if our size has
 | 
						|
      // changed, then we make sure to call layout on the child, since its
 | 
						|
      // children may need to be shifted around as a result of the size change.
 | 
						|
      if (layout || sizeChanged) child->XULLayout(aState);
 | 
						|
 | 
						|
      // If the child was a block or inline (e.g., HTML) it may have changed its
 | 
						|
      // rect *during* layout. We have to check for this.
 | 
						|
      nsRect newChildRect(child->GetRect());
 | 
						|
 | 
						|
      if (!newChildRect.IsEqualInterior(childRect)) {
 | 
						|
#ifdef DEBUG_GROW
 | 
						|
        printf(" GREW from (%d,%d) -> (%d,%d)\n", childRect.width,
 | 
						|
               childRect.height, newChildRect.width, newChildRect.height);
 | 
						|
#endif
 | 
						|
        newChildRect.Inflate(margin);
 | 
						|
        childRect.Inflate(margin);
 | 
						|
 | 
						|
        // The child changed size during layout.  The ChildResized method
 | 
						|
        // handles this scenario.
 | 
						|
        ChildResized(aBox, aState, child, childBoxSize, childComputedBoxSize,
 | 
						|
                     boxSizes, computedBoxSizes, childRect, newChildRect,
 | 
						|
                     clientRect, flexes, finished);
 | 
						|
 | 
						|
        // We note that a child changed size, which means that another pass will
 | 
						|
        // be required.
 | 
						|
        childResized = true;
 | 
						|
 | 
						|
        // Now that a child resized, it's entirely possible that OUR rect is too
 | 
						|
        // small.  Now we ensure that |originalClientRect| is grown to
 | 
						|
        // accommodate the size of |clientRect|.
 | 
						|
        if (clientRect.width > originalClientRect.width)
 | 
						|
          originalClientRect.width = clientRect.width;
 | 
						|
 | 
						|
        if (clientRect.height > originalClientRect.height)
 | 
						|
          originalClientRect.height = clientRect.height;
 | 
						|
 | 
						|
        if (!(frameState & NS_STATE_IS_DIRECTION_NORMAL)) {
 | 
						|
          // Our childRect had its XMost() or YMost() (depending on our layout
 | 
						|
          // direction), positioned at a certain point.  Ensure that the
 | 
						|
          // newChildRect satisfies the same constraint.  Note that this is
 | 
						|
          // just equivalent to adjusting the x/y by the difference in
 | 
						|
          // width/height between childRect and newChildRect.  So we don't need
 | 
						|
          // to reaccount for the left and right of the box layout state again.
 | 
						|
          if (frameState & NS_STATE_IS_HORIZONTAL)
 | 
						|
            newChildRect.x = childRect.XMost() - newChildRect.width;
 | 
						|
          else
 | 
						|
            newChildRect.y = childRect.YMost() - newChildRect.height;
 | 
						|
        }
 | 
						|
 | 
						|
        if (!(frameState & NS_STATE_IS_HORIZONTAL)) {
 | 
						|
          if (GetFrameDirection(aBox) != StyleDirection::Ltr) {
 | 
						|
            // keep the right edge the same
 | 
						|
            newChildRect.x = childRect.XMost() - newChildRect.width;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        // If the child resized then recompute its position.
 | 
						|
        ComputeChildsNextPosition(aBox, x, y, nextX, nextY, newChildRect);
 | 
						|
 | 
						|
        if (newChildRect.width >= margin.left + margin.right &&
 | 
						|
            newChildRect.height >= margin.top + margin.bottom)
 | 
						|
          newChildRect.Deflate(margin);
 | 
						|
 | 
						|
        if (childRect.width >= margin.left + margin.right &&
 | 
						|
            childRect.height >= margin.top + margin.bottom)
 | 
						|
          childRect.Deflate(margin);
 | 
						|
 | 
						|
        child->SetXULBounds(aState, newChildRect);
 | 
						|
 | 
						|
        // If we are the first box that changed size, then we don't need to do a
 | 
						|
        // second pass
 | 
						|
        if (count == 0) finished = true;
 | 
						|
      }
 | 
						|
 | 
						|
      // Now update our x/y finally.
 | 
						|
      x = nextX;
 | 
						|
      y = nextY;
 | 
						|
 | 
						|
      // Move to the next child.
 | 
						|
      childComputedBoxSize = childComputedBoxSize->next;
 | 
						|
      childBoxSize = childBoxSize->next;
 | 
						|
 | 
						|
      iter->Next();
 | 
						|
      count++;
 | 
						|
    }
 | 
						|
 | 
						|
    // Sanity-checking code to ensure we don't do an infinite # of passes.
 | 
						|
    passes++;
 | 
						|
    NS_ASSERTION(passes < 10, "A Box's child is constantly growing!!!!!");
 | 
						|
    if (passes >= 10) break;
 | 
						|
  } while (false == finished);
 | 
						|
 | 
						|
  // Get rid of our size lists.
 | 
						|
  while (boxSizes) {
 | 
						|
    nsBoxSize* toDelete = boxSizes;
 | 
						|
    boxSizes = boxSizes->next;
 | 
						|
    delete toDelete;
 | 
						|
  }
 | 
						|
 | 
						|
  while (computedBoxSizes) {
 | 
						|
    nsComputedBoxSize* toDelete = computedBoxSizes;
 | 
						|
    computedBoxSizes = computedBoxSizes->next;
 | 
						|
    delete toDelete;
 | 
						|
  }
 | 
						|
 | 
						|
  if (childResized) {
 | 
						|
    // See if one of our children forced us to get bigger
 | 
						|
    nsRect tmpClientRect(originalClientRect);
 | 
						|
    nsMargin bp(0, 0, 0, 0);
 | 
						|
    aBox->GetXULBorderAndPadding(bp);
 | 
						|
    tmpClientRect.Inflate(bp);
 | 
						|
 | 
						|
    if (tmpClientRect.width > originalSize.width ||
 | 
						|
        tmpClientRect.height > originalSize.height) {
 | 
						|
      // if it did reset our bounds.
 | 
						|
      nsRect bounds(aBox->GetRect());
 | 
						|
      if (tmpClientRect.width > originalSize.width)
 | 
						|
        bounds.width = tmpClientRect.width;
 | 
						|
 | 
						|
      if (tmpClientRect.height > originalSize.height)
 | 
						|
        bounds.height = tmpClientRect.height;
 | 
						|
 | 
						|
      aBox->SetXULBounds(aState, bounds);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Because our size grew, we now have to readjust because of box packing.
 | 
						|
  // Repack in order to update our x and y to the correct values.
 | 
						|
  HandleBoxPack(aBox, frameState, x, y, originalClientRect, clientRect);
 | 
						|
 | 
						|
  // Compare against our original x and y and only worry about adjusting the
 | 
						|
  // children if we really did have to change the positions because of packing
 | 
						|
  // (typically for 'center' or 'end' pack values).
 | 
						|
  if (x != origX || y != origY) {
 | 
						|
    // reposition all our children
 | 
						|
    for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
      nsIFrame* child = iter->get();
 | 
						|
      nsRect childRect(child->GetRect());
 | 
						|
      childRect.x += (x - origX);
 | 
						|
      childRect.y += (y - origY);
 | 
						|
      child->SetXULBounds(aState, childRect);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Perform out-of-axis alignment for non-stretch alignments
 | 
						|
  if (!(frameState & NS_STATE_AUTO_STRETCH)) {
 | 
						|
    AlignChildren(aBox, aState);
 | 
						|
  }
 | 
						|
 | 
						|
  // That's it!  If you made it this far without having a nervous breakdown,
 | 
						|
  // congratulations!  Go get yourself a beer.
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::PopulateBoxSizes(nsIFrame* aBox,
 | 
						|
                                        nsBoxLayoutState& aState,
 | 
						|
                                        nsBoxSize*& aBoxSizes,
 | 
						|
                                        nscoord& aMinSize, nscoord& aMaxSize,
 | 
						|
                                        int32_t& aFlexes) {
 | 
						|
  // used for the equal size flag
 | 
						|
  nscoord biggestPrefWidth = 0;
 | 
						|
  nscoord biggestMinWidth = 0;
 | 
						|
  nscoord smallestMaxWidth = NS_UNCONSTRAINEDSIZE;
 | 
						|
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
 | 
						|
  aMinSize = 0;
 | 
						|
  aMaxSize = NS_UNCONSTRAINEDSIZE;
 | 
						|
 | 
						|
  bool isHorizontal;
 | 
						|
 | 
						|
  if (IsXULHorizontal(aBox))
 | 
						|
    isHorizontal = true;
 | 
						|
  else
 | 
						|
    isHorizontal = false;
 | 
						|
 | 
						|
  // this is a nice little optimization
 | 
						|
  // it turns out that if we only have 1 flexable child
 | 
						|
  // then it does not matter what its preferred size is
 | 
						|
  // there is nothing to flex it relative. This is great
 | 
						|
  // because we can avoid asking for a preferred size in this
 | 
						|
  // case. Why is this good? Well you might have html inside it
 | 
						|
  // and asking html for its preferred size is rather expensive.
 | 
						|
  // so we can just optimize it out this way.
 | 
						|
 | 
						|
  // set flexes
 | 
						|
  aFlexes = 0;
 | 
						|
  nsBoxSize* currentBox = aBoxSizes;
 | 
						|
  nsBoxSize* last = nullptr;
 | 
						|
 | 
						|
  nscoord maxFlex = 0;
 | 
						|
  int32_t childCount = 0;
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
    while (currentBox && currentBox->bogus) {
 | 
						|
      last = currentBox;
 | 
						|
      currentBox = currentBox->next;
 | 
						|
    }
 | 
						|
    ++childCount;
 | 
						|
    nsSize pref(0, 0);
 | 
						|
    nsSize minSize(0, 0);
 | 
						|
    nsSize maxSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 | 
						|
    bool collapsed = child->IsXULCollapsed();
 | 
						|
 | 
						|
    if (!collapsed) {
 | 
						|
      // only one flexible child? Cool we will just make its preferred size
 | 
						|
      // 0 then and not even have to ask for it.
 | 
						|
      // if (flexes != 1)  {
 | 
						|
 | 
						|
      pref = child->GetXULPrefSize(aState);
 | 
						|
      minSize = child->GetXULMinSize(aState);
 | 
						|
      maxSize =
 | 
						|
          nsIFrame::XULBoundsCheckMinMax(minSize, child->GetXULMaxSize(aState));
 | 
						|
      child->GetXULBoxAscent(aState);
 | 
						|
      //}
 | 
						|
 | 
						|
      pref = nsIFrame::XULBoundsCheck(minSize, pref, maxSize);
 | 
						|
 | 
						|
      AddXULMargin(child, pref);
 | 
						|
      AddXULMargin(child, minSize);
 | 
						|
      AddXULMargin(child, maxSize);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!currentBox) {
 | 
						|
      // create one.
 | 
						|
      currentBox = new (aState) nsBoxSize();
 | 
						|
      if (!aBoxSizes) {
 | 
						|
        aBoxSizes = currentBox;
 | 
						|
        last = aBoxSizes;
 | 
						|
      } else {
 | 
						|
        last->next = currentBox;
 | 
						|
        last = currentBox;
 | 
						|
      }
 | 
						|
 | 
						|
      nscoord minWidth;
 | 
						|
      nscoord maxWidth;
 | 
						|
      nscoord prefWidth;
 | 
						|
 | 
						|
      // get sizes from child
 | 
						|
      if (isHorizontal) {
 | 
						|
        minWidth = minSize.width;
 | 
						|
        maxWidth = maxSize.width;
 | 
						|
        prefWidth = pref.width;
 | 
						|
      } else {
 | 
						|
        minWidth = minSize.height;
 | 
						|
        maxWidth = maxSize.height;
 | 
						|
        prefWidth = pref.height;
 | 
						|
      }
 | 
						|
 | 
						|
      nscoord flex = child->GetXULFlex();
 | 
						|
 | 
						|
      // set them if you collapsed you are not flexible.
 | 
						|
      if (collapsed) {
 | 
						|
        currentBox->flex = 0;
 | 
						|
      } else {
 | 
						|
        if (flex > maxFlex) {
 | 
						|
          maxFlex = flex;
 | 
						|
        }
 | 
						|
        currentBox->flex = flex;
 | 
						|
      }
 | 
						|
 | 
						|
      // we specified all our children are equal size;
 | 
						|
      if (frameState & NS_STATE_EQUAL_SIZE) {
 | 
						|
        if (prefWidth > biggestPrefWidth) biggestPrefWidth = prefWidth;
 | 
						|
 | 
						|
        if (minWidth > biggestMinWidth) biggestMinWidth = minWidth;
 | 
						|
 | 
						|
        if (maxWidth < smallestMaxWidth) smallestMaxWidth = maxWidth;
 | 
						|
      } else {  // not we can set our children right now.
 | 
						|
        currentBox->pref = prefWidth;
 | 
						|
        currentBox->min = minWidth;
 | 
						|
        currentBox->max = maxWidth;
 | 
						|
      }
 | 
						|
 | 
						|
      NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,
 | 
						|
                   "Bad min, pref, max widths!");
 | 
						|
    }
 | 
						|
 | 
						|
    if (!isHorizontal) {
 | 
						|
      if (minSize.width > aMinSize) aMinSize = minSize.width;
 | 
						|
 | 
						|
      if (maxSize.width < aMaxSize) aMaxSize = maxSize.width;
 | 
						|
 | 
						|
    } else {
 | 
						|
      if (minSize.height > aMinSize) aMinSize = minSize.height;
 | 
						|
 | 
						|
      if (maxSize.height < aMaxSize) aMaxSize = maxSize.height;
 | 
						|
    }
 | 
						|
 | 
						|
    currentBox->collapsed = collapsed;
 | 
						|
    aFlexes += currentBox->flex;
 | 
						|
 | 
						|
    last = currentBox;
 | 
						|
    currentBox = currentBox->next;
 | 
						|
  }
 | 
						|
 | 
						|
  if (childCount > 0) {
 | 
						|
    nscoord maxAllowedFlex = nscoord_MAX / childCount;
 | 
						|
 | 
						|
    if (MOZ_UNLIKELY(maxFlex > maxAllowedFlex)) {
 | 
						|
      // clamp all the flexes
 | 
						|
      currentBox = aBoxSizes;
 | 
						|
      while (currentBox) {
 | 
						|
        currentBox->flex = std::min(currentBox->flex, maxAllowedFlex);
 | 
						|
        currentBox = currentBox->next;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
#ifdef DEBUG
 | 
						|
  else {
 | 
						|
    NS_ASSERTION(maxFlex == 0, "How did that happen?");
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  // we specified all our children are equal size;
 | 
						|
  if (frameState & NS_STATE_EQUAL_SIZE) {
 | 
						|
    smallestMaxWidth = std::max(smallestMaxWidth, biggestMinWidth);
 | 
						|
    biggestPrefWidth = nsIFrame::XULBoundsCheck(
 | 
						|
        biggestMinWidth, biggestPrefWidth, smallestMaxWidth);
 | 
						|
 | 
						|
    currentBox = aBoxSizes;
 | 
						|
 | 
						|
    while (currentBox) {
 | 
						|
      if (!currentBox->collapsed) {
 | 
						|
        currentBox->pref = biggestPrefWidth;
 | 
						|
        currentBox->min = biggestMinWidth;
 | 
						|
        currentBox->max = smallestMaxWidth;
 | 
						|
      } else {
 | 
						|
        currentBox->pref = 0;
 | 
						|
        currentBox->min = 0;
 | 
						|
        currentBox->max = 0;
 | 
						|
      }
 | 
						|
      currentBox = currentBox->next;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::ComputeChildsNextPosition(
 | 
						|
    nsIFrame* aBox, const nscoord& aCurX, const nscoord& aCurY, nscoord& aNextX,
 | 
						|
    nscoord& aNextY, const nsRect& aCurrentChildSize) {
 | 
						|
  // Get the position along the box axis for the child.
 | 
						|
  // The out-of-axis position is not set.
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
 | 
						|
  if (IsXULHorizontal(aBox)) {
 | 
						|
    // horizontal box's children.
 | 
						|
    if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
      aNextX = aCurX + aCurrentChildSize.width;
 | 
						|
    else
 | 
						|
      aNextX = aCurX - aCurrentChildSize.width;
 | 
						|
 | 
						|
  } else {
 | 
						|
    // vertical box's children.
 | 
						|
    if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
 | 
						|
      aNextY = aCurY + aCurrentChildSize.height;
 | 
						|
    else
 | 
						|
      aNextY = aCurY - aCurrentChildSize.height;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::AlignChildren(nsIFrame* aBox, nsBoxLayoutState& aState) {
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
  bool isHorizontal = (frameState & NS_STATE_IS_HORIZONTAL) != 0;
 | 
						|
  nsRect clientRect;
 | 
						|
  aBox->GetXULClientRect(clientRect);
 | 
						|
 | 
						|
  MOZ_ASSERT(!(frameState & NS_STATE_AUTO_STRETCH),
 | 
						|
             "Only AlignChildren() with non-stretch alignment");
 | 
						|
 | 
						|
  // These are only calculated if needed
 | 
						|
  nsIFrame::Halignment halign;
 | 
						|
  nsIFrame::Valignment valign;
 | 
						|
  nscoord maxAscent = 0;
 | 
						|
  bool isLTR;
 | 
						|
 | 
						|
  if (isHorizontal) {
 | 
						|
    valign = aBox->GetXULVAlign();
 | 
						|
    if (valign == nsBoxFrame::vAlign_BaseLine) {
 | 
						|
      maxAscent = aBox->GetXULBoxAscent(aState);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    isLTR = GetFrameDirection(aBox) == StyleDirection::Ltr;
 | 
						|
    halign = aBox->GetXULHAlign();
 | 
						|
  }
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
    nsMargin margin;
 | 
						|
    child->GetXULMargin(margin);
 | 
						|
    nsRect childRect = child->GetRect();
 | 
						|
 | 
						|
    if (isHorizontal) {
 | 
						|
      const nscoord startAlign = clientRect.y + margin.top;
 | 
						|
      const nscoord endAlign =
 | 
						|
          clientRect.YMost() - margin.bottom - childRect.height;
 | 
						|
 | 
						|
      nscoord y = 0;
 | 
						|
      switch (valign) {
 | 
						|
        case nsBoxFrame::vAlign_Top:
 | 
						|
          y = startAlign;
 | 
						|
          break;
 | 
						|
        case nsBoxFrame::vAlign_Middle:
 | 
						|
          // Should this center the border box?
 | 
						|
          // This centers the margin box, the historical behavior.
 | 
						|
          y = (startAlign + endAlign) / 2;
 | 
						|
          break;
 | 
						|
        case nsBoxFrame::vAlign_Bottom:
 | 
						|
          y = endAlign;
 | 
						|
          break;
 | 
						|
        case nsBoxFrame::vAlign_BaseLine:
 | 
						|
          // Alignments don't force the box to grow (only sizes do),
 | 
						|
          // so keep the children within the box.
 | 
						|
          y = maxAscent - child->GetXULBoxAscent(aState);
 | 
						|
          y = std::max(startAlign, y);
 | 
						|
          y = std::min(y, endAlign);
 | 
						|
          break;
 | 
						|
      }
 | 
						|
 | 
						|
      childRect.y = y;
 | 
						|
 | 
						|
    } else {  // vertical box
 | 
						|
      const nscoord leftAlign = clientRect.x + margin.left;
 | 
						|
      const nscoord rightAlign =
 | 
						|
          clientRect.XMost() - margin.right - childRect.width;
 | 
						|
 | 
						|
      nscoord x = 0;
 | 
						|
      switch (halign) {
 | 
						|
        case nsBoxFrame::hAlign_Left:  // start
 | 
						|
          x = isLTR ? leftAlign : rightAlign;
 | 
						|
          break;
 | 
						|
        case nsBoxFrame::hAlign_Center:
 | 
						|
          x = (leftAlign + rightAlign) / 2;
 | 
						|
          break;
 | 
						|
        case nsBoxFrame::hAlign_Right:  // end
 | 
						|
          x = isLTR ? rightAlign : leftAlign;
 | 
						|
          break;
 | 
						|
      }
 | 
						|
 | 
						|
      childRect.x = x;
 | 
						|
    }
 | 
						|
 | 
						|
    if (childRect.TopLeft() != child->GetPosition()) {
 | 
						|
      child->SetXULBounds(aState, childRect);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::ChildResized(
 | 
						|
    nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChild,
 | 
						|
    nsBoxSize* aChildBoxSize, nsComputedBoxSize* aChildComputedSize,
 | 
						|
    nsBoxSize* aBoxSizes, nsComputedBoxSize* aComputedBoxSizes,
 | 
						|
    const nsRect& aChildLayoutRect, nsRect& aChildActualRect,
 | 
						|
    nsRect& aContainingRect, int32_t aFlexes, bool& aFinished)
 | 
						|
 | 
						|
{
 | 
						|
  nsRect childCurrentRect(aChildLayoutRect);
 | 
						|
 | 
						|
  bool isHorizontal = IsXULHorizontal(aBox);
 | 
						|
  nscoord childLayoutWidth = GET_WIDTH(aChildLayoutRect, isHorizontal);
 | 
						|
  nscoord& childActualWidth = GET_WIDTH(aChildActualRect, isHorizontal);
 | 
						|
  nscoord& containingWidth = GET_WIDTH(aContainingRect, isHorizontal);
 | 
						|
 | 
						|
  // nscoord childLayoutHeight = GET_HEIGHT(aChildLayoutRect,isHorizontal);
 | 
						|
  nscoord& childActualHeight = GET_HEIGHT(aChildActualRect, isHorizontal);
 | 
						|
  nscoord& containingHeight = GET_HEIGHT(aContainingRect, isHorizontal);
 | 
						|
 | 
						|
  bool recompute = false;
 | 
						|
 | 
						|
  // if we are a horizontal box see if the child will fit inside us.
 | 
						|
  if (childActualHeight > containingHeight) {
 | 
						|
    // if we are a horizontal box and the child is bigger than our height
 | 
						|
 | 
						|
    // ok if the height changed then we need to reflow everyone but us at the
 | 
						|
    // new height so we will set the changed index to be us. And signal that we
 | 
						|
    // need a new pass.
 | 
						|
 | 
						|
    nsSize min = aChild->GetXULMinSize(aState);
 | 
						|
    nsSize max =
 | 
						|
        nsIFrame::XULBoundsCheckMinMax(min, aChild->GetXULMaxSize(aState));
 | 
						|
    AddXULMargin(aChild, max);
 | 
						|
 | 
						|
    if (isHorizontal)
 | 
						|
      childActualHeight =
 | 
						|
          max.height < childActualHeight ? max.height : childActualHeight;
 | 
						|
    else
 | 
						|
      childActualHeight =
 | 
						|
          max.width < childActualHeight ? max.width : childActualHeight;
 | 
						|
 | 
						|
    // only set if it changes
 | 
						|
    if (childActualHeight > containingHeight) {
 | 
						|
      containingHeight = childActualHeight;
 | 
						|
 | 
						|
      // remember we do not need to clear the resized list because changing the
 | 
						|
      // height of a horizontal box will not affect the width of any of its
 | 
						|
      // children because block flow left to right, top to bottom. Just trust me
 | 
						|
      // on this one.
 | 
						|
      aFinished = false;
 | 
						|
 | 
						|
      // only recompute if there are flexes.
 | 
						|
      if (aFlexes > 0) {
 | 
						|
        // relayout everything
 | 
						|
        recompute = true;
 | 
						|
        InvalidateComputedSizes(aComputedBoxSizes);
 | 
						|
        nsComputedBoxSize* node = aComputedBoxSizes;
 | 
						|
 | 
						|
        while (node) {
 | 
						|
          node->resized = false;
 | 
						|
          node = node->next;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (childActualWidth > childLayoutWidth) {
 | 
						|
    nsSize min = aChild->GetXULMinSize(aState);
 | 
						|
    nsSize max =
 | 
						|
        nsIFrame::XULBoundsCheckMinMax(min, aChild->GetXULMaxSize(aState));
 | 
						|
 | 
						|
    AddXULMargin(aChild, max);
 | 
						|
 | 
						|
    // our width now becomes the new size
 | 
						|
 | 
						|
    if (isHorizontal)
 | 
						|
      childActualWidth =
 | 
						|
          max.width < childActualWidth ? max.width : childActualWidth;
 | 
						|
    else
 | 
						|
      childActualWidth =
 | 
						|
          max.height < childActualWidth ? max.height : childActualWidth;
 | 
						|
 | 
						|
    if (childActualWidth > childLayoutWidth) {
 | 
						|
      aChildComputedSize->size = childActualWidth;
 | 
						|
      aChildBoxSize->min = childActualWidth;
 | 
						|
      if (aChildBoxSize->pref < childActualWidth)
 | 
						|
        aChildBoxSize->pref = childActualWidth;
 | 
						|
      if (aChildBoxSize->max < childActualWidth)
 | 
						|
        aChildBoxSize->max = childActualWidth;
 | 
						|
 | 
						|
      // if we have flexible elements with us then reflex things. Otherwise we
 | 
						|
      // can skip doing it.
 | 
						|
      if (aFlexes > 0) {
 | 
						|
        InvalidateComputedSizes(aComputedBoxSizes);
 | 
						|
 | 
						|
        nsComputedBoxSize* node = aComputedBoxSizes;
 | 
						|
        aChildComputedSize->resized = true;
 | 
						|
 | 
						|
        while (node) {
 | 
						|
          if (node->resized) node->valid = true;
 | 
						|
 | 
						|
          node = node->next;
 | 
						|
        }
 | 
						|
 | 
						|
        recompute = true;
 | 
						|
        aFinished = false;
 | 
						|
      } else {
 | 
						|
        containingWidth += aChildComputedSize->size - childLayoutWidth;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (recompute)
 | 
						|
    ComputeChildSizes(aBox, aState, containingWidth, aBoxSizes,
 | 
						|
                      aComputedBoxSizes);
 | 
						|
 | 
						|
  if (!childCurrentRect.IsEqualInterior(aChildActualRect)) {
 | 
						|
    // the childRect includes the margin
 | 
						|
    // make sure we remove it before setting
 | 
						|
    // the bounds.
 | 
						|
    nsMargin margin(0, 0, 0, 0);
 | 
						|
    aChild->GetXULMargin(margin);
 | 
						|
    nsRect rect(aChildActualRect);
 | 
						|
    if (rect.width >= margin.left + margin.right &&
 | 
						|
        rect.height >= margin.top + margin.bottom)
 | 
						|
      rect.Deflate(margin);
 | 
						|
 | 
						|
    aChild->SetXULBounds(aState, rect);
 | 
						|
    aChild->XULLayout(aState);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::InvalidateComputedSizes(
 | 
						|
    nsComputedBoxSize* aComputedBoxSizes) {
 | 
						|
  while (aComputedBoxSizes) {
 | 
						|
    aComputedBoxSizes->valid = false;
 | 
						|
    aComputedBoxSizes = aComputedBoxSizes->next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::ComputeChildSizes(
 | 
						|
    nsIFrame* aBox, nsBoxLayoutState& aState, nscoord& aGivenSize,
 | 
						|
    nsBoxSize* aBoxSizes, nsComputedBoxSize*& aComputedBoxSizes) {
 | 
						|
  // nscoord onePixel = aState.PresContext()->IntScaledPixelsToTwips(1);
 | 
						|
 | 
						|
  int32_t sizeRemaining = aGivenSize;
 | 
						|
  int32_t spacerConstantsRemaining = 0;
 | 
						|
 | 
						|
  // ----- calculate the spacers constants and the size remaining -----
 | 
						|
 | 
						|
  if (!aComputedBoxSizes) aComputedBoxSizes = new (aState) nsComputedBoxSize();
 | 
						|
 | 
						|
  nsBoxSize* boxSizes = aBoxSizes;
 | 
						|
  nsComputedBoxSize* computedBoxSizes = aComputedBoxSizes;
 | 
						|
  int32_t count = 0;
 | 
						|
  int32_t validCount = 0;
 | 
						|
 | 
						|
  while (boxSizes) {
 | 
						|
    NS_ASSERTION(
 | 
						|
        (boxSizes->min <= boxSizes->pref && boxSizes->pref <= boxSizes->max),
 | 
						|
        "bad pref, min, max size");
 | 
						|
 | 
						|
    // ignore collapsed children
 | 
						|
    //  if (boxSizes->collapsed)
 | 
						|
    //  {
 | 
						|
    //  computedBoxSizes->valid = true;
 | 
						|
    //  computedBoxSizes->size = boxSizes->pref;
 | 
						|
    // validCount++;
 | 
						|
    //      boxSizes->flex = 0;
 | 
						|
    // }// else {
 | 
						|
 | 
						|
    if (computedBoxSizes->valid) {
 | 
						|
      sizeRemaining -= computedBoxSizes->size;
 | 
						|
      validCount++;
 | 
						|
    } else {
 | 
						|
      if (boxSizes->flex == 0) {
 | 
						|
        computedBoxSizes->valid = true;
 | 
						|
        computedBoxSizes->size = boxSizes->pref;
 | 
						|
        validCount++;
 | 
						|
      }
 | 
						|
 | 
						|
      spacerConstantsRemaining += boxSizes->flex;
 | 
						|
      sizeRemaining -= boxSizes->pref;
 | 
						|
    }
 | 
						|
 | 
						|
    sizeRemaining -= (boxSizes->left + boxSizes->right);
 | 
						|
 | 
						|
    //}
 | 
						|
 | 
						|
    boxSizes = boxSizes->next;
 | 
						|
 | 
						|
    if (boxSizes && !computedBoxSizes->next)
 | 
						|
      computedBoxSizes->next = new (aState) nsComputedBoxSize();
 | 
						|
 | 
						|
    computedBoxSizes = computedBoxSizes->next;
 | 
						|
    count++;
 | 
						|
  }
 | 
						|
 | 
						|
  // everything accounted for?
 | 
						|
  if (validCount < count) {
 | 
						|
    // ----- Ok we are give a size to fit into so stretch or squeeze to fit
 | 
						|
    // ----- Make sure we look at our min and max size
 | 
						|
    bool limit = true;
 | 
						|
    for (int pass = 1; true == limit; pass++) {
 | 
						|
      limit = false;
 | 
						|
      boxSizes = aBoxSizes;
 | 
						|
      computedBoxSizes = aComputedBoxSizes;
 | 
						|
 | 
						|
      while (boxSizes) {
 | 
						|
        // ignore collapsed spacers
 | 
						|
 | 
						|
        //    if (!boxSizes->collapsed) {
 | 
						|
 | 
						|
        nscoord pref = 0;
 | 
						|
        nscoord max = NS_UNCONSTRAINEDSIZE;
 | 
						|
        nscoord min = 0;
 | 
						|
        nscoord flex = 0;
 | 
						|
 | 
						|
        pref = boxSizes->pref;
 | 
						|
        min = boxSizes->min;
 | 
						|
        max = boxSizes->max;
 | 
						|
        flex = boxSizes->flex;
 | 
						|
 | 
						|
        // ----- look at our min and max limits make sure we aren't too small or
 | 
						|
        // too big -----
 | 
						|
        if (!computedBoxSizes->valid) {
 | 
						|
          int32_t newSize = pref + int32_t(int64_t(sizeRemaining) * flex /
 | 
						|
                                           spacerConstantsRemaining);
 | 
						|
 | 
						|
          if (newSize <= min) {
 | 
						|
            computedBoxSizes->size = min;
 | 
						|
            computedBoxSizes->valid = true;
 | 
						|
            spacerConstantsRemaining -= flex;
 | 
						|
            sizeRemaining += pref;
 | 
						|
            sizeRemaining -= min;
 | 
						|
            limit = true;
 | 
						|
          } else if (newSize >= max) {
 | 
						|
            computedBoxSizes->size = max;
 | 
						|
            computedBoxSizes->valid = true;
 | 
						|
            spacerConstantsRemaining -= flex;
 | 
						|
            sizeRemaining += pref;
 | 
						|
            sizeRemaining -= max;
 | 
						|
            limit = true;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        // }
 | 
						|
        boxSizes = boxSizes->next;
 | 
						|
        computedBoxSizes = computedBoxSizes->next;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // ---- once we have removed and min and max issues just stretch us out in the
 | 
						|
  // remaining space
 | 
						|
  // ---- or shrink us. Depends on the size remaining and the spacer constants
 | 
						|
  aGivenSize = 0;
 | 
						|
  boxSizes = aBoxSizes;
 | 
						|
  computedBoxSizes = aComputedBoxSizes;
 | 
						|
 | 
						|
  while (boxSizes) {
 | 
						|
    // ignore collapsed spacers
 | 
						|
    //  if (!(boxSizes && boxSizes->collapsed)) {
 | 
						|
 | 
						|
    nscoord pref = 0;
 | 
						|
    nscoord flex = 0;
 | 
						|
    pref = boxSizes->pref;
 | 
						|
    flex = boxSizes->flex;
 | 
						|
 | 
						|
    if (!computedBoxSizes->valid) {
 | 
						|
      computedBoxSizes->size = pref + int32_t(int64_t(sizeRemaining) * flex /
 | 
						|
                                              spacerConstantsRemaining);
 | 
						|
      computedBoxSizes->valid = true;
 | 
						|
    }
 | 
						|
 | 
						|
    aGivenSize += (boxSizes->left + boxSizes->right);
 | 
						|
    aGivenSize += computedBoxSizes->size;
 | 
						|
 | 
						|
    // }
 | 
						|
 | 
						|
    boxSizes = boxSizes->next;
 | 
						|
    computedBoxSizes = computedBoxSizes->next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
nsSize nsSprocketLayout::GetXULPrefSize(nsIFrame* aBox,
 | 
						|
                                        nsBoxLayoutState& aState) {
 | 
						|
  nsSize vpref(0, 0);
 | 
						|
  bool isHorizontal = IsXULHorizontal(aBox);
 | 
						|
 | 
						|
  nscoord biggestPref = 0;
 | 
						|
 | 
						|
  // run through all the children and get their min, max, and preferred sizes
 | 
						|
  // return us the size of the box
 | 
						|
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
  bool isEqual = !!(frameState & NS_STATE_EQUAL_SIZE);
 | 
						|
  int32_t count = 0;
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
    // ignore collapsed children
 | 
						|
    if (child->IsXULCollapsed()) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    nsSize pref = child->GetXULPrefSize(aState);
 | 
						|
    AddXULMargin(child, pref);
 | 
						|
 | 
						|
    if (isEqual) {
 | 
						|
      if (isHorizontal) {
 | 
						|
        if (pref.width > biggestPref) biggestPref = pref.width;
 | 
						|
      } else {
 | 
						|
        if (pref.height > biggestPref) biggestPref = pref.height;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    AddLargestSize(vpref, pref, isHorizontal);
 | 
						|
    count++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isEqual) {
 | 
						|
    if (isHorizontal)
 | 
						|
      vpref.width = biggestPref * count;
 | 
						|
    else
 | 
						|
      vpref.height = biggestPref * count;
 | 
						|
  }
 | 
						|
 | 
						|
  // now add our border and padding
 | 
						|
  AddXULBorderAndPadding(aBox, vpref);
 | 
						|
 | 
						|
  return vpref;
 | 
						|
}
 | 
						|
 | 
						|
nsSize nsSprocketLayout::GetXULMinSize(nsIFrame* aBox,
 | 
						|
                                       nsBoxLayoutState& aState) {
 | 
						|
  nsSize minSize(0, 0);
 | 
						|
  bool isHorizontal = IsXULHorizontal(aBox);
 | 
						|
 | 
						|
  nscoord biggestMin = 0;
 | 
						|
 | 
						|
  // run through all the children and get their min, max, and preferred sizes
 | 
						|
  // return us the size of the box
 | 
						|
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
  bool isEqual = !!(frameState & NS_STATE_EQUAL_SIZE);
 | 
						|
  int32_t count = 0;
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
 | 
						|
    // ignore collapsed children
 | 
						|
    if (child->IsXULCollapsed()) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    nsSize min = child->GetXULMinSize(aState);
 | 
						|
    nsSize pref(0, 0);
 | 
						|
 | 
						|
    // if the child is not flexible then
 | 
						|
    // its min size is its pref size.
 | 
						|
    if (child->GetXULFlex() == 0) {
 | 
						|
      pref = child->GetXULPrefSize(aState);
 | 
						|
      if (isHorizontal)
 | 
						|
        min.width = pref.width;
 | 
						|
      else
 | 
						|
        min.height = pref.height;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isEqual) {
 | 
						|
      if (isHorizontal) {
 | 
						|
        if (min.width > biggestMin) biggestMin = min.width;
 | 
						|
      } else {
 | 
						|
        if (min.height > biggestMin) biggestMin = min.height;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    AddXULMargin(child, min);
 | 
						|
    AddLargestSize(minSize, min, isHorizontal);
 | 
						|
    count++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isEqual) {
 | 
						|
    if (isHorizontal)
 | 
						|
      minSize.width = biggestMin * count;
 | 
						|
    else
 | 
						|
      minSize.height = biggestMin * count;
 | 
						|
  }
 | 
						|
 | 
						|
  // now add our border and padding
 | 
						|
  AddXULBorderAndPadding(aBox, minSize);
 | 
						|
 | 
						|
  return minSize;
 | 
						|
}
 | 
						|
 | 
						|
nsSize nsSprocketLayout::GetXULMaxSize(nsIFrame* aBox,
 | 
						|
                                       nsBoxLayoutState& aState) {
 | 
						|
  bool isHorizontal = IsXULHorizontal(aBox);
 | 
						|
 | 
						|
  nscoord smallestMax = NS_UNCONSTRAINEDSIZE;
 | 
						|
  nsSize maxSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 | 
						|
 | 
						|
  // run through all the children and get their min, max, and preferred sizes
 | 
						|
  // return us the size of the box
 | 
						|
 | 
						|
  nsFrameState frameState = nsFrameState(0);
 | 
						|
  GetFrameState(aBox, frameState);
 | 
						|
  bool isEqual = !!(frameState & NS_STATE_EQUAL_SIZE);
 | 
						|
  int32_t count = 0;
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
 | 
						|
    // ignore collapsed children
 | 
						|
    if (child->IsXULCollapsed()) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    // if completely redefined don't even ask our child for its size.
 | 
						|
    nsSize min = child->GetXULMinSize(aState);
 | 
						|
    nsSize max =
 | 
						|
        nsIFrame::XULBoundsCheckMinMax(min, child->GetXULMaxSize(aState));
 | 
						|
 | 
						|
    AddXULMargin(child, max);
 | 
						|
    AddSmallestSize(maxSize, max, isHorizontal);
 | 
						|
 | 
						|
    if (isEqual) {
 | 
						|
      if (isHorizontal) {
 | 
						|
        if (max.width < smallestMax) smallestMax = max.width;
 | 
						|
      } else {
 | 
						|
        if (max.height < smallestMax) smallestMax = max.height;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    count++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isEqual) {
 | 
						|
    if (isHorizontal) {
 | 
						|
      if (smallestMax != NS_UNCONSTRAINEDSIZE)
 | 
						|
        maxSize.width = smallestMax * count;
 | 
						|
      else
 | 
						|
        maxSize.width = NS_UNCONSTRAINEDSIZE;
 | 
						|
    } else {
 | 
						|
      if (smallestMax != NS_UNCONSTRAINEDSIZE)
 | 
						|
        maxSize.height = smallestMax * count;
 | 
						|
      else
 | 
						|
        maxSize.height = NS_UNCONSTRAINEDSIZE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // now add our border and padding
 | 
						|
  AddXULBorderAndPadding(aBox, maxSize);
 | 
						|
 | 
						|
  return maxSize;
 | 
						|
}
 | 
						|
 | 
						|
nscoord nsSprocketLayout::GetAscent(nsIFrame* aBox, nsBoxLayoutState& aState) {
 | 
						|
  nscoord vAscent = 0;
 | 
						|
 | 
						|
  bool isHorizontal = IsXULHorizontal(aBox);
 | 
						|
 | 
						|
  // run through all the children and get their min, max, and preferred sizes
 | 
						|
  // return us the size of the box
 | 
						|
 | 
						|
  for (auto iter = IterFor(aBox); iter && !iter->AtEnd(); iter->Next()) {
 | 
						|
    nsIFrame* child = iter->get();
 | 
						|
 | 
						|
    // ignore collapsed children
 | 
						|
    // if (!child->IsXULCollapsed())
 | 
						|
    //{
 | 
						|
    // if completely redefined don't even ask our child for its size.
 | 
						|
    nscoord ascent = child->GetXULBoxAscent(aState);
 | 
						|
 | 
						|
    nsMargin margin;
 | 
						|
    child->GetXULMargin(margin);
 | 
						|
    ascent += margin.top;
 | 
						|
 | 
						|
    if (isHorizontal) {
 | 
						|
      if (ascent > vAscent) vAscent = ascent;
 | 
						|
    } else {
 | 
						|
      if (vAscent == 0) vAscent = ascent;
 | 
						|
    }
 | 
						|
    //}
 | 
						|
 | 
						|
    child = nsIFrame::GetNextXULBox(child);
 | 
						|
  }
 | 
						|
 | 
						|
  nsMargin borderPadding;
 | 
						|
  aBox->GetXULBorderAndPadding(borderPadding);
 | 
						|
 | 
						|
  return vAscent + borderPadding.top;
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::SetLargestSize(nsSize& aSize1, const nsSize& aSize2,
 | 
						|
                                      bool aIsHorizontal) {
 | 
						|
  if (aIsHorizontal) {
 | 
						|
    if (aSize1.height < aSize2.height) aSize1.height = aSize2.height;
 | 
						|
  } else {
 | 
						|
    if (aSize1.width < aSize2.width) aSize1.width = aSize2.width;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::SetSmallestSize(nsSize& aSize1, const nsSize& aSize2,
 | 
						|
                                       bool aIsHorizontal) {
 | 
						|
  if (aIsHorizontal) {
 | 
						|
    if (aSize1.height > aSize2.height) aSize1.height = aSize2.height;
 | 
						|
  } else {
 | 
						|
    if (aSize1.width > aSize2.width) aSize1.width = aSize2.width;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::AddLargestSize(nsSize& aSize, const nsSize& aSizeToAdd,
 | 
						|
                                      bool aIsHorizontal) {
 | 
						|
  if (aIsHorizontal)
 | 
						|
    AddCoord(aSize.width, aSizeToAdd.width);
 | 
						|
  else
 | 
						|
    AddCoord(aSize.height, aSizeToAdd.height);
 | 
						|
 | 
						|
  SetLargestSize(aSize, aSizeToAdd, aIsHorizontal);
 | 
						|
}
 | 
						|
 | 
						|
void nsSprocketLayout::AddCoord(nscoord& aCoord, nscoord aCoordToAdd) {
 | 
						|
  if (aCoord != NS_UNCONSTRAINEDSIZE) {
 | 
						|
    if (aCoordToAdd == NS_UNCONSTRAINEDSIZE)
 | 
						|
      aCoord = aCoordToAdd;
 | 
						|
    else
 | 
						|
      aCoord += aCoordToAdd;
 | 
						|
  }
 | 
						|
}
 | 
						|
void nsSprocketLayout::AddSmallestSize(nsSize& aSize, const nsSize& aSizeToAdd,
 | 
						|
                                       bool aIsHorizontal) {
 | 
						|
  if (aIsHorizontal)
 | 
						|
    AddCoord(aSize.width, aSizeToAdd.width);
 | 
						|
  else
 | 
						|
    AddCoord(aSize.height, aSizeToAdd.height);
 | 
						|
 | 
						|
  SetSmallestSize(aSize, aSizeToAdd, aIsHorizontal);
 | 
						|
}
 | 
						|
 | 
						|
bool nsSprocketLayout::GetDefaultFlex(int32_t& aFlex) {
 | 
						|
  aFlex = 0;
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
nsComputedBoxSize::nsComputedBoxSize() {
 | 
						|
  resized = false;
 | 
						|
  valid = false;
 | 
						|
  size = 0;
 | 
						|
  next = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
nsBoxSize::nsBoxSize() {
 | 
						|
  pref = 0;
 | 
						|
  min = 0;
 | 
						|
  max = NS_UNCONSTRAINEDSIZE;
 | 
						|
  collapsed = false;
 | 
						|
  left = 0;
 | 
						|
  right = 0;
 | 
						|
  flex = 0;
 | 
						|
  next = nullptr;
 | 
						|
  bogus = false;
 | 
						|
}
 | 
						|
 | 
						|
void* nsBoxSize::operator new(size_t sz,
 | 
						|
                              nsBoxLayoutState& aState) noexcept(true) {
 | 
						|
  return mozilla::AutoStackArena::Allocate(sz);
 | 
						|
}
 | 
						|
 | 
						|
void nsBoxSize::operator delete(void* aPtr, size_t sz) {}
 | 
						|
 | 
						|
void* nsComputedBoxSize::operator new(size_t sz,
 | 
						|
                                      nsBoxLayoutState& aState) noexcept(true) {
 | 
						|
  return mozilla::AutoStackArena::Allocate(sz);
 | 
						|
}
 | 
						|
 | 
						|
void nsComputedBoxSize::operator delete(void* aPtr, size_t sz) {}
 |