// 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(); }
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)); }
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; }
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)); }
/* * 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; }
// 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; }
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); } } }
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; }
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); }
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); } }
// 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())); }
//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()))); }
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); }
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; }