Esempio n. 1
0
// Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect.
PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2)
{
  nscoord  xmost1 = aRect1.XMost();
  nscoord  ymost1 = aRect1.YMost();
  nscoord  xmost2 = aRect2.XMost();
  nscoord  ymost2 = aRect2.YMost();
  nscoord  temp;

  x = PR_MAX(aRect1.x, aRect2.x);
  y = PR_MAX(aRect1.y, aRect2.y);

  // Compute the destination width
  temp = PR_MIN(xmost1, xmost2);
  if (temp <= x) {
    width = 0;
  } else {
    width = temp - x;
  }

  // Compute the destination height
  temp = PR_MIN(ymost1, ymost2);
  if (temp <= y) {
    height = 0;
  } else {
    height = temp - y;
  }

  return !IsEmpty();
}
Esempio n. 2
0
static Maybe<nsRect>
EdgeInclusiveIntersection(const nsRect& aRect, const nsRect& aOtherRect)
{
    nscoord left = std::max(aRect.x, aOtherRect.x);
    nscoord top = std::max(aRect.y, aOtherRect.y);
    nscoord right = std::min(aRect.XMost(), aOtherRect.XMost());
    nscoord bottom = std::min(aRect.YMost(), aOtherRect.YMost());
    if (left > right || top > bottom) {
        return Nothing();
    }
    return Some(nsRect(left, top, right - left, bottom - top));
}
Esempio n. 3
0
void
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
                                                         const nsRect& aFloatAvailableSpace,
                                                         nscoord& aLeftResult,
                                                         nscoord& aRightResult,
                                                         nsBlockFrame::
                                                      ReplacedElementWidthToClear
                                                                 *aReplacedWidth)
{
  // The frame is clueless about the float manager and therefore we
  // only give it free space. An example is a table frame - the
  // tables do not flow around floats.
  // However, we can let its margins intersect floats.
  NS_ASSERTION(aFloatAvailableSpace.x >= mContentArea.x, "bad avail space rect x");
  NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
               aFloatAvailableSpace.XMost() <= mContentArea.XMost(),
               "bad avail space rect width");

  nscoord leftOffset, rightOffset;
  if (aFloatAvailableSpace.width == mContentArea.width) {
    // We don't need to compute margins when there are no floats around.
    leftOffset = 0;
    rightOffset = 0;
  } else {
    // We pass in aReplacedWidth to make handling outer table frames
    // work correctly.  For outer table frames, we need to subtract off
    // the margin that's going to be at the edge of them, since we're
    // dealing with margin that it's really the child's responsibility
    // to place.
    nsCSSOffsetState os(aFrame, mReflowState.rendContext, mContentArea.width);
    NS_ASSERTION(!aReplacedWidth ||
                 aFrame->GetType() == nsGkAtoms::tableOuterFrame ||
                 (aReplacedWidth->marginLeft  == os.mComputedMargin.left &&
                  aReplacedWidth->marginRight == os.mComputedMargin.right),
                 "unexpected aReplacedWidth");

    nscoord leftFloatXOffset = aFloatAvailableSpace.x - mContentArea.x;
    leftOffset = NS_MAX(leftFloatXOffset, os.mComputedMargin.left) -
                 (aReplacedWidth ? aReplacedWidth->marginLeft
                                 : os.mComputedMargin.left);
    leftOffset = NS_MAX(leftOffset, 0); // in case of negative margin
    nscoord rightFloatXOffset =
      mContentArea.XMost() - aFloatAvailableSpace.XMost();
    rightOffset = NS_MAX(rightFloatXOffset, os.mComputedMargin.right) -
                  (aReplacedWidth ? aReplacedWidth->marginRight
                                  : os.mComputedMargin.right);
    rightOffset = NS_MAX(rightOffset, 0); // in case of negative margin
  }
  aLeftResult = leftOffset;
  aRightResult = rightOffset;
}
Esempio n. 4
0
void nsRect::UnionRectIncludeEmpty(const nsRect &aRect1, const nsRect &aRect2)
{
  nscoord xmost1 = aRect1.XMost();
  nscoord xmost2 = aRect2.XMost();
  nscoord ymost1 = aRect1.YMost();
  nscoord ymost2 = aRect2.YMost();

  // Compute the origin
  x = PR_MIN(aRect1.x, aRect2.x);
  y = PR_MIN(aRect1.y, aRect2.y);

  // Compute the size
  width = PR_MAX(xmost1, xmost2) - x;
  height = PR_MAX(ymost1, ymost2) - y;
}
static float
ComputeDistanceFromRect(const nsPoint& aPoint, const nsRect& aRect)
{
  nscoord dx = std::max(0, std::max(aRect.x - aPoint.x, aPoint.x - aRect.XMost()));
  nscoord dy = std::max(0, std::max(aRect.y - aPoint.y, aPoint.y - aRect.YMost()));
  return float(NS_hypot(dx, dy));
}
Esempio n. 6
0
/*
 * Reduce rect to 1 app unit width along either left or right edge base on
 * aToRightEdge parameter.
 */
static void
ReduceRectToVerticalEdge(nsRect& aRect, bool aToRightEdge)
{
  if (aToRightEdge) {
    aRect.x = aRect.XMost() - 1;
  }
  aRect.width = 1;
}
Esempio n. 7
0
// Find difference between rects as an nsMargin
nsMargin nsRect::operator-(const nsRect& aRect) const
{
  nsMargin margin;
  margin.left = aRect.x - x;
  margin.right = XMost() - aRect.XMost();
  margin.top = aRect.y - y;
  margin.bottom = YMost() - aRect.YMost();
  return margin;
}
Esempio n. 8
0
static void
ClipMarker(const nsRect&                          aContentArea,
           const nsRect&                          aMarkerRect,
           DisplayListClipState::AutoSaveRestore& aClipState)
{
  nscoord rightOverflow = aMarkerRect.XMost() - aContentArea.XMost();
  nsRect markerRect = aMarkerRect;
  if (rightOverflow > 0) {
    // Marker overflows on the right side (content width < marker width).
    markerRect.width -= rightOverflow;
    aClipState.ClipContentDescendants(markerRect);
  } else {
    nscoord leftOverflow = aContentArea.x - aMarkerRect.x;
    if (leftOverflow > 0) {
      // Marker overflows on the left side
      markerRect.width -= leftOverflow;
      markerRect.x += leftOverflow;
      aClipState.ClipContentDescendants(markerRect);
    }
  }
}
Esempio n. 9
0
void
nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
                                                         const nsRect& aFloatAvailableSpace,
                                                         nscoord& aLeftResult,
                                                         nscoord& aRightResult)
{
  nsRect contentArea =
    mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
  // The frame is clueless about the float manager and therefore we
  // only give it free space. An example is a table frame - the
  // tables do not flow around floats.
  // However, we can let its margins intersect floats.
  NS_ASSERTION(aFloatAvailableSpace.x >= contentArea.x, "bad avail space rect x");
  NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
               aFloatAvailableSpace.XMost() <= contentArea.XMost(),
               "bad avail space rect width");

  nscoord leftOffset, rightOffset;
  if (aFloatAvailableSpace.width == contentArea.width) {
    // We don't need to compute margins when there are no floats around.
    leftOffset = 0;
    rightOffset = 0;
  } else {
    nsMargin frameMargin;
    nsCSSOffsetState os(aFrame, mReflowState.rendContext, contentArea.width);
    frameMargin = os.ComputedPhysicalMargin();

    nscoord leftFloatXOffset = aFloatAvailableSpace.x - contentArea.x;
    leftOffset = std::max(leftFloatXOffset, frameMargin.left) -
                 frameMargin.left;
    leftOffset = std::max(leftOffset, 0); // in case of negative margin
    nscoord rightFloatXOffset =
      contentArea.XMost() - aFloatAvailableSpace.XMost();
    rightOffset = std::max(rightFloatXOffset, frameMargin.right) -
                  frameMargin.right;
    rightOffset = std::max(rightOffset, 0); // in case of negative margin
  }
  aLeftResult = leftOffset;
  aRightResult = rightOffset;
}
Esempio n. 10
0
void
DOMRect::SetLayoutRect(const nsRect& aLayoutRect)
{
  double scale = 65536.0;
  // Round to the nearest 1/scale units. We choose scale so it can be represented
  // exactly by machine floating point.
  double scaleInv = 1/scale;
  double t2pScaled = scale/nsPresContext::AppUnitsPerCSSPixel();
  double x = RoundFloat(aLayoutRect.x*t2pScaled)*scaleInv;
  double y = RoundFloat(aLayoutRect.y*t2pScaled)*scaleInv;
  SetRect(x, y, RoundFloat(aLayoutRect.XMost()*t2pScaled)*scaleInv - x,
          RoundFloat(aLayoutRect.YMost()*t2pScaled)*scaleInv - y);
}
Esempio n. 11
0
void nsViewManager::InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
  nscoord aY1, nscoord aY2, bool aInCutOut) {
  nscoord height = aY2 - aY1;
  if (aRect.x < aCutOut.x) {
    nsRect r(aRect.x, aY1, aCutOut.x - aRect.x, height);
    InvalidateView(aView, r);
  }
  if (!aInCutOut && aCutOut.x < aCutOut.XMost()) {
    nsRect r(aCutOut.x, aY1, aCutOut.width, height);
    InvalidateView(aView, r);
  }
  if (aCutOut.XMost() < aRect.XMost()) {
    nsRect r(aCutOut.XMost(), aY1, aRect.XMost() - aCutOut.XMost(), height);
    InvalidateView(aView, r);
  }
}
Esempio n. 12
0
// Intersection. Returns TRUE if the receiver overlaps aRect and
// FALSE otherwise
PRBool nsRect::Intersects(const nsRect &aRect) const
{
  return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
                   (aRect.x < XMost()) && (aRect.y < YMost()));
}
Esempio n. 13
0
//Also Returns true if aRect is Empty
PRBool nsRect::Contains(const nsRect &aRect) const
{
  return aRect.IsEmpty() || 
          ((PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
                    (aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost())));
}
Esempio n. 14
0
nsFlowAreaRect
nsFloatManager::GetFlowArea(nscoord aYOffset, BandInfoType aInfoType,
                            nscoord aHeight, nsRect aContentArea,
                            SavedState* aState) const
{
  NS_ASSERTION(aHeight >= 0, "unexpected max height");
  NS_ASSERTION(aContentArea.width >= 0, "unexpected content area width");

  nscoord top = aYOffset + mY;
  if (top < nscoord_MIN) {
    NS_WARNING("bad value");
    top = nscoord_MIN;
  }

  // Determine the last float that we should consider.
  PRUint32 floatCount;
  if (aState) {
    // Use the provided state.
    floatCount = aState->mFloatInfoCount;
    NS_ABORT_IF_FALSE(floatCount <= mFloats.Length(), "bad state");
  } else {
    // Use our current state.
    floatCount = mFloats.Length();
  }

  // If there are no floats at all, or we're below the last one, return
  // quickly.
  if (floatCount == 0 ||
      (mFloats[floatCount-1].mLeftYMost <= top &&
       mFloats[floatCount-1].mRightYMost <= top)) {
    return nsFlowAreaRect(aContentArea.x, aYOffset, aContentArea.width,
                          aHeight, PR_FALSE);
  }

  nscoord bottom;
  if (aHeight == nscoord_MAX) {
    // This warning (and the two below) are possible to hit on pages
    // with really large objects.
    NS_WARN_IF_FALSE(aInfoType == BAND_FROM_POINT,
                     "bad height");
    bottom = nscoord_MAX;
  } else {
    bottom = top + aHeight;
    if (bottom < top || bottom > nscoord_MAX) {
      NS_WARNING("bad value");
      bottom = nscoord_MAX;
    }
  }
  nscoord left = mX + aContentArea.x;
  nscoord right = mX + aContentArea.XMost();
  if (right < left) {
    NS_WARNING("bad value");
    right = left;
  }

  // Walk backwards through the floats until we either hit the front of
  // the list or we're above |top|.
  PRBool haveFloats = PR_FALSE;
  for (PRUint32 i = floatCount; i > 0; --i) {
    const FloatInfo &fi = mFloats[i-1];
    if (fi.mLeftYMost <= top && fi.mRightYMost <= top) {
      // There aren't any more floats that could intersect this band.
      break;
    }
    if (fi.mRect.IsEmpty()) {
      // For compatibility, ignore floats with empty rects, even though it
      // disagrees with the spec.  (We might want to fix this in the
      // future, though.)
      continue;
    }
    nscoord floatTop = fi.mRect.y, floatBottom = fi.mRect.YMost();
    if (top < floatTop && aInfoType == BAND_FROM_POINT) {
      // This float is below our band.  Shrink our band's height if needed.
      if (floatTop < bottom) {
        bottom = floatTop;
      }
    }
    // If top == bottom (which happens only with WIDTH_WITHIN_HEIGHT),
    // we include floats that begin at our 0-height vertical area.  We
    // need to to this to satisfy the invariant that a
    // WIDTH_WITHIN_HEIGHT call is at least as narrow on both sides as a
    // BAND_WITHIN_POINT call beginning at its top.
    else if (top < floatBottom &&
             (floatTop < bottom || (floatTop == bottom && top == bottom))) {
      // This float is in our band.

      // Shrink our band's height if needed.
      if (floatBottom < bottom && aInfoType == BAND_FROM_POINT) {
        bottom = floatBottom;
      }

      // Shrink our band's width if needed.
      if (fi.mFrame->GetStyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
        // A left float.
        nscoord rightEdge = fi.mRect.XMost();
        if (rightEdge > left) {
          left = rightEdge;
          // Only set haveFloats to true if the float is inside our
          // containing block.  This matches the spec for what some
          // callers want and disagrees for other callers, so we should
          // probably provide better information at some point.
          haveFloats = PR_TRUE;
        }
      } else {
        // A right float.
        nscoord leftEdge = fi.mRect.x;
        if (leftEdge < right) {
          right = leftEdge;
          // See above.
          haveFloats = PR_TRUE;
        }
      }
    }
  }

  nscoord height = (bottom == nscoord_MAX) ? nscoord_MAX : (bottom - top);
  return nsFlowAreaRect(left - mX, top - mY, right - left, height, haveFloats);
}
Esempio n. 15
0
nsRect nsRegion::GetLargestRectangle (const nsRect& aContainingRect) const {
  nsRect bestRect;

  if (GetNumRects() <= 1) {
    bestRect = GetBounds();
    return bestRect;
  }

  AxisPartition xaxis, yaxis;

  // Step 1: Calculate the grid lines
  nsRegionRectIterator iter(*this);
  const nsRect *currentRect;
  while ((currentRect = iter.Next())) {
    xaxis.InsertCoord(currentRect->x);
    xaxis.InsertCoord(currentRect->XMost());
    yaxis.InsertCoord(currentRect->y);
    yaxis.InsertCoord(currentRect->YMost());
  }
  if (!aContainingRect.IsEmpty()) {
    xaxis.InsertCoord(aContainingRect.x);
    xaxis.InsertCoord(aContainingRect.XMost());
    yaxis.InsertCoord(aContainingRect.y);
    yaxis.InsertCoord(aContainingRect.YMost());
  }

  // Step 2: Fill out the grid with the areas
  // Note: due to the ordering of rectangles in the region, it is not always
  // possible to combine steps 2 and 3 so we don't try to be clever.
  int32_t matrixHeight = yaxis.GetNumStops() - 1;
  int32_t matrixWidth = xaxis.GetNumStops() - 1;
  int32_t matrixSize = matrixHeight * matrixWidth;
  nsTArray<SizePair> areas(matrixSize);
  areas.SetLength(matrixSize);

  iter.Reset();
  while ((currentRect = iter.Next())) {
    int32_t xstart = xaxis.IndexOf(currentRect->x);
    int32_t xend = xaxis.IndexOf(currentRect->XMost());
    int32_t y = yaxis.IndexOf(currentRect->y);
    int32_t yend = yaxis.IndexOf(currentRect->YMost());

    for (; y < yend; y++) {
      nscoord height = yaxis.StopSize(y);
      for (int32_t x = xstart; x < xend; x++) {
        nscoord width = xaxis.StopSize(x);
        int64_t size = width*int64_t(height);
        if (currentRect->Intersects(aContainingRect)) {
          areas[y*matrixWidth+x].mSizeContainingRect = size;
        }
        areas[y*matrixWidth+x].mSize = size;
      }
    }
  }

  // Step 3: Find the maximum submatrix sum that does not contain a rectangle
  {
    // First get the prefix sum array
    int32_t m = matrixHeight + 1;
    int32_t n = matrixWidth + 1;
    nsTArray<SizePair> pareas(m*n);
    pareas.SetLength(m*n);
    for (int32_t y = 1; y < m; y++) {
      for (int32_t x = 1; x < n; x++) {
        SizePair area = areas[(y-1)*matrixWidth+x-1];
        if (!area.mSize) {
          area = SizePair::VeryLargeNegative();
        }
        area = area + pareas[    y*n+x-1]
                    + pareas[(y-1)*n+x  ]
                    - pareas[(y-1)*n+x-1];
        pareas[y*n+x] = area;
      }
    }

    // No longer need the grid
    areas.SetLength(0);

    SizePair bestArea;
    struct {
      int32_t left, top, right, bottom;
    } bestRectIndices = { 0, 0, 0, 0 };
    for (int32_t m1 = 0; m1 < m; m1++) {
      for (int32_t m2 = m1+1; m2 < m; m2++) {
        nsTArray<SizePair> B;
        B.SetLength(n);
        for (int32_t i = 0; i < n; i++) {
          B[i] = pareas[m2*n+i] - pareas[m1*n+i];
        }
        int32_t minIdx, maxIdx;
        SizePair area = MaxSum1D(B, n, &minIdx, &maxIdx);
        if (area > bestArea) {
          bestRectIndices.left = minIdx;
          bestRectIndices.top = m1;
          bestRectIndices.right = maxIdx;
          bestRectIndices.bottom = m2;
          bestArea = area;
        }
      }
    }

    bestRect.MoveTo(xaxis.StopAt(bestRectIndices.left),
                    yaxis.StopAt(bestRectIndices.top));
    bestRect.SizeTo(xaxis.StopAt(bestRectIndices.right) - bestRect.x,
                    yaxis.StopAt(bestRectIndices.bottom) - bestRect.y);
  }

  return bestRect;
}