static float ComputeDistanceFromRegion(const nsPoint& aPoint, const nsRegion& aRegion) { MOZ_ASSERT(!aRegion.IsEmpty(), "can't compute distance between point and empty region"); float minDist = -1; for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { float dist = ComputeDistanceFromRect(aPoint, iter.Get()); if (dist < minDist || minDist < 0) { minDist = dist; } } return minDist; }
bool nsRegion::Contains(const nsRegion& aRgn) const { // XXX this could be made faster by iterating over // both regions at the same time some how for (auto iter = aRgn.RectIter(); !iter.Done(); iter.Next()) { if (!Contains(iter.Get())) { return false; } } return true; }
void set(nsRegion ®ion) { clear(); for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) { const nsRect& r = iter.Get(); for (int y = r.y; y < r.YMost(); y++) { for (int x = r.x; x < r.XMost(); x++) { bitmap[x + y * width] = REGION_VALUE; } } } }
void TestVisit(nsRegion &r) { unsigned char reference[600 * 600]; unsigned char result[600 * 600]; RegionBitmap ref(reference, 600, 600); RegionBitmap res(result, 600, 600); ref.set(r); ref.dilate(); res.set(r); r.VisitEdges(VisitEdge, &res); res.compare(ref); }
// Subtract aRegion from aExposedRegion as long as that doesn't make the // exposed region get too complex or removes a big chunk of the exposed region. static void SubtractFromExposedRegion(nsRegion* aExposedRegion, const nsRegion& aRegion) { if (aRegion.IsEmpty()) return; nsRegion tmp; tmp.Sub(*aExposedRegion, aRegion); // Don't let *aExposedRegion get too complex, but don't let it fluff out to // its bounds either. Do let aExposedRegion get more complex if by doing so // we reduce its area by at least half. if (tmp.GetNumRects() <= 15 || tmp.Area() <= aExposedRegion->Area()/2) { *aExposedRegion = tmp; } }
static float ComputeDistanceFromRegion(const nsPoint& aPoint, const nsRegion& aRegion) { MOZ_ASSERT(!aRegion.IsEmpty(), "can't compute distance between point and empty region"); nsRegionRectIterator iter(aRegion); const nsRect* r; float minDist = -1; while ((r = iter.Next()) != nullptr) { float dist = ComputeDistanceFromRect(aPoint, *r); if (dist < minDist || minDist < 0) { minDist = dist; } } return minDist; }
void AppendToString(std::stringstream& aStream, const nsRegion& r, const char* pfx, const char* sfx) { aStream << pfx; aStream << "< "; for (auto iter = r.RectIter(); !iter.Done(); iter.Next()) { AppendToString(aStream, iter.Get()); aStream << "; "; } aStream << ">"; aStream << sfx; }
nsRegion nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, const nsRegion& aPreFilterDirtyRegion) { if (aPreFilterDirtyRegion.IsEmpty()) { return nsRegion(); } gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; UniquePtr<UserSpaceMetrics> metrics = UserSpaceMetricsForFrame(aFilteredFrame); nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics, filterChain, nullptr, unused, nullptr, &aPreFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRegion(); } // We've passed in the source's dirty area so the instance knows about it. // Now we can ask the instance to compute the area of the filter output // that's dirty. return instance.ComputePostFilterDirtyRegion(); }
nsRegion nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, const nsRegion& aPreFilterDirtyRegion) { if (aPreFilterDirtyRegion.IsEmpty()) { return nsRegion(); } nsFilterInstance instance(aFilteredFrame, nullptr, nullptr, &aPreFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRegion(); } // We've passed in the source's dirty area so the instance knows about it. // Now we can ask the instance to compute the area of the filter output // that's dirty. nsRegion dirtyRegion; nsresult rv = instance.ComputePostFilterDirtyRegion(&dirtyRegion); if (NS_SUCCEEDED(rv)) { return dirtyRegion; } return nsRegion(); }
/** * @param aDamagedRegion this region, relative to aWidgetView, is invalidated in * every widget child of aWidgetView, plus aWidgetView's own widget */ void nsViewManager::InvalidateWidgetArea(nsView *aWidgetView, const nsRegion &aDamagedRegion) { NS_ASSERTION(aWidgetView->GetViewManager() == this, "InvalidateWidgetArea called on view we don't own"); nsIWidget* widget = aWidgetView->GetWidget(); #if 0 nsRect dbgBounds = aDamagedRegion.GetBounds(); printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n", aWidgetView, aWidgetView->IsAttachedToTopLevel(), widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height); #endif // If the widget is hidden, it don't cover nothing if (widget) { bool visible; widget->IsVisible(visible); if (!visible) return; } if (!widget) { // The root view or a scrolling view might not have a widget // (for example, during printing). We get here when we scroll // during printing to show selected options in a listbox, for example. return; } // Update all child widgets with the damage. In the process, // accumulate the union of all the child widget areas, or at least // some subset of that. nsRegion children; if (widget->GetTransparencyMode() != eTransparencyTransparent) { for (nsIWidget* childWidget = widget->GetFirstChild(); childWidget; childWidget = childWidget->GetNextSibling()) { nsView* view = nsView::GetViewFor(childWidget); NS_ASSERTION(view != aWidgetView, "will recur infinitely"); bool visible; childWidget->IsVisible(visible); nsWindowType type; childWidget->GetWindowType(type); if (view && visible && type != eWindowType_popup) { NS_ASSERTION(type == eWindowType_plugin, "Only plugin or popup widgets can be children!"); // We do not need to invalidate in plugin widgets, but we should // exclude them from the invalidation region IF we're not on // Mac. On Mac we need to draw under plugin widgets, because // plugin widgets are basically invisible #ifndef XP_MACOSX // GetBounds should compensate for chrome on a toplevel widget nsIntRect bounds; childWidget->GetBounds(bounds); nsTArray<nsIntRect> clipRects; childWidget->GetWindowClipRegion(&clipRects); for (PRUint32 i = 0; i < clipRects.Length(); ++i) { nsRect rr = (clipRects[i] + bounds.TopLeft()). ToAppUnits(AppUnitsPerDevPixel()); children.Or(children, rr - aWidgetView->ViewToWidgetOffset()); children.SimplifyInward(20); } #endif } } } nsRegion leftOver; leftOver.Sub(aDamagedRegion, children); if (!leftOver.IsEmpty()) { aWidgetView->SetPendingRefresh(true); const nsRect* r; for (nsRegionRectIterator iter(leftOver); (r = iter.Next());) { nsIntRect bounds = ViewToWidget(aWidgetView, *r); widget->Invalidate(bounds); } } }