michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsScriptableRegion.h" michael@0: #include // for uint32_t michael@0: #include // for int32_t michael@0: #include "js/RootingAPI.h" // for Rooted michael@0: #include "js/Value.h" // for INT_TO_JSVAL, etc michael@0: #include "jsapi.h" // for JS_DefineElement, etc michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 michael@0: #include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc michael@0: #include "nsID.h" michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nscore.h" // for NS_IMETHODIMP michael@0: michael@0: class JSObject; michael@0: struct JSContext; michael@0: michael@0: nsScriptableRegion::nsScriptableRegion() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsScriptableRegion, nsIScriptableRegion) michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::Init() michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::SetToRegion(nsIScriptableRegion *aRegion) michael@0: { michael@0: aRegion->GetRegion(&mRegion); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::SetToRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) michael@0: { michael@0: mRegion = nsIntRect(aX, aY, aWidth, aHeight); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::IntersectRegion(nsIScriptableRegion *aRegion) michael@0: { michael@0: nsIntRegion region; michael@0: aRegion->GetRegion(®ion); michael@0: mRegion.And(mRegion, region); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::IntersectRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) michael@0: { michael@0: mRegion.And(mRegion, nsIntRect(aX, aY, aWidth, aHeight)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::UnionRegion(nsIScriptableRegion *aRegion) michael@0: { michael@0: nsIntRegion region; michael@0: aRegion->GetRegion(®ion); michael@0: mRegion.Or(mRegion, region); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::UnionRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) michael@0: { michael@0: mRegion.Or(mRegion, nsIntRect(aX, aY, aWidth, aHeight)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::SubtractRegion(nsIScriptableRegion *aRegion) michael@0: { michael@0: nsIntRegion region; michael@0: aRegion->GetRegion(®ion); michael@0: mRegion.Sub(mRegion, region); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::SubtractRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) michael@0: { michael@0: mRegion.Sub(mRegion, nsIntRect(aX, aY, aWidth, aHeight)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::IsEmpty(bool *isEmpty) michael@0: { michael@0: *isEmpty = mRegion.IsEmpty(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::IsEqualRegion(nsIScriptableRegion *aRegion, bool *isEqual) michael@0: { michael@0: nsIntRegion region; michael@0: aRegion->GetRegion(®ion); michael@0: *isEqual = mRegion.IsEqual(region); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::GetBoundingBox(int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight) michael@0: { michael@0: nsIntRect boundRect = mRegion.GetBounds(); michael@0: *aX = boundRect.x; michael@0: *aY = boundRect.y; michael@0: *aWidth = boundRect.width; michael@0: *aHeight = boundRect.height; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::Offset(int32_t aXOffset, int32_t aYOffset) michael@0: { michael@0: mRegion.MoveBy(aXOffset, aYOffset); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::ContainsRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool *containsRect) michael@0: { michael@0: *containsRect = mRegion.Contains(nsIntRect(aX, aY, aWidth, aHeight)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::GetRegion(nsIntRegion* outRgn) michael@0: { michael@0: *outRgn = mRegion; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsScriptableRegion::GetRects(JSContext* aCx, JS::MutableHandle aRects) michael@0: { michael@0: uint32_t numRects = mRegion.GetNumRects(); michael@0: michael@0: if (!numRects) { michael@0: aRects.setNull(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: JS::Rooted destArray(aCx, JS_NewArrayObject(aCx, numRects * 4)); michael@0: if (!destArray) { michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: aRects.setObject(*destArray); michael@0: michael@0: uint32_t n = 0; michael@0: nsIntRegionRectIterator iter(mRegion); michael@0: const nsIntRect *rect; michael@0: michael@0: while ((rect = iter.Next())) { michael@0: if (!JS_DefineElement(aCx, destArray, n, INT_TO_JSVAL(rect->x), nullptr, nullptr, JSPROP_ENUMERATE) || michael@0: !JS_DefineElement(aCx, destArray, n + 1, INT_TO_JSVAL(rect->y), nullptr, nullptr, JSPROP_ENUMERATE) || michael@0: !JS_DefineElement(aCx, destArray, n + 2, INT_TO_JSVAL(rect->width), nullptr, nullptr, JSPROP_ENUMERATE) || michael@0: !JS_DefineElement(aCx, destArray, n + 3, INT_TO_JSVAL(rect->height), nullptr, nullptr, JSPROP_ENUMERATE)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: n += 4; michael@0: } michael@0: michael@0: return NS_OK; michael@0: }