This is an automated email from the ASF dual-hosted git repository.
Harbs pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new 6888a851d8 Add DisplayUtils class and corresponding tests for bounding
box calculations
6888a851d8 is described below
commit 6888a851d80d1bad4b29e278bc8bc99f538d4341
Author: Harbs <[email protected]>
AuthorDate: Mon Jul 13 09:59:30 2026 +0300
Add DisplayUtils class and corresponding tests for bounding box calculations
---
.../royale/org/apache/royale/utils/DisplayUtils.as | 19 ++-
.../src/test/royale/flexUnitTests/CoreTester.as | 1 +
.../test/royale/flexUnitTests/DisplayUtilsTest.as | 184 +++++++++++++++++++++
3 files changed, 198 insertions(+), 6 deletions(-)
diff --git
a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/DisplayUtils.as
b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/DisplayUtils.as
index e3894ea45b..6800eb6ba2 100644
---
a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/DisplayUtils.as
+++
b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/DisplayUtils.as
@@ -38,7 +38,7 @@ package org.apache.royale.utils
import org.apache.royale.core.ITransformHost;
}
/**
- * The SpriteUtils class is a collection of static functions that are
useful
+ * The DisplayUtils class is a collection of static functions that are
useful
* for geometric operations on visible objects.
*
* @langversion 3.0
@@ -50,9 +50,17 @@ package org.apache.royale.utils
{
/**
- * Gets the bounding box of an object relative to the screen
ignoring any scrolling.
+ * Gets the axis-aligned bounding box of an object in the
top-level visible
+ * coordinate space. On SWF, this is the stage coordinate
space. On JS, this
+ * is the browser layout viewport coordinate space returned by
+ * <code>getBoundingClientRect()</code>. Scrolling the
document or an ancestor
+ * changes the returned position relative to the viewport.
*
* @param obj The object to test.
+ * @param boundsBeforeTransform Optional untransformed local
bounds. On JS,
+ * these bounds are transformed into viewport coordinates for
SVG elements.
+ *
+ * @return The object's axis-aligned bounds in the top-level
visible coordinate space.
*
* @langversion 3.0
* @playerversion Flash 10.2
@@ -76,8 +84,6 @@ package org.apache.royale.utils
var r:Object = (obj.element as
HTMLElement).getBoundingClientRect();
bounds = new Rectangle(r.left, r.top,
r.right - r.left, r.bottom - r.top);
}
- bounds.x -= window.pageXOffset;
- bounds.y -= window.pageYOffset;
if (obj.element is SVGElement)
{
var m:org.apache.royale.geom.Matrix =
getTransormMatrix(obj);
@@ -99,7 +105,8 @@ package org.apache.royale.utils
}
/**
- * Gets a composition all transform matrices applied to an
IUIBase. Currently only works for SVG on JS side.
+ * Gets the composition of all transform matrices applied to
an IUIBase.
+ * Currently only works for SVG elements on JS.
*
* @param obj The object to test.
*
@@ -128,7 +135,7 @@ package org.apache.royale.utils
}
/**
- * Evaluates the bounding box of two objects to see if thier
bounding boxes overlap.
+ * Evaluates the bounding boxes of two objects to see if they
overlap.
*
* @param obj1 The object to test.
* @param obj2 The object to test against.
diff --git
a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
index b95cb19307..d37bb7e970 100644
--- a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
+++ b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
@@ -44,6 +44,7 @@ package flexUnitTests
public var stringUtilsTest:StringUtilsTest;
public var sanitizerTest:SanitizeTest;
public var eventsTest:EventsTest;
+ public var displayUtilsTest:DisplayUtilsTest;
public var objectUtilTests:ObjectUtilsTest;
public var functionalTests:FunctionalTests;
public var taskTests:TaskTests;
diff --git
a/frameworks/projects/Core/src/test/royale/flexUnitTests/DisplayUtilsTest.as
b/frameworks/projects/Core/src/test/royale/flexUnitTests/DisplayUtilsTest.as
new file mode 100644
index 0000000000..1fbbd85679
--- /dev/null
+++ b/frameworks/projects/Core/src/test/royale/flexUnitTests/DisplayUtilsTest.as
@@ -0,0 +1,184 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flexUnitTests
+{
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.geom.Rectangle;
+ import org.apache.royale.test.asserts.*;
+ import org.apache.royale.utils.DisplayUtils;
+
+ public class DisplayUtilsTest
+ {
+ private var target:UIBase;
+
+ COMPILE::JS
+ private var fixture:HTMLElement;
+
+ COMPILE::JS
+ private var originalScrollX:Number;
+
+ COMPILE::JS
+ private var originalScrollY:Number;
+
+ [Before]
+ public function setUp():void
+ {
+ COMPILE::JS
+ {
+ originalScrollX = window.pageXOffset;
+ originalScrollY = window.pageYOffset;
+ window.scrollTo(0, 0);
+
+ fixture = document.createElement("div") as HTMLElement;
+ fixture.style.position = "absolute";
+ fixture.style.left = "0px";
+ fixture.style.top = "0px";
+ fixture.style.width = "1px";
+ fixture.style.height = "3000px";
+ document.body.appendChild(fixture);
+
+ target = new UIBase();
+ target.element.style.position = "absolute";
+ target.element.style.left = "37px";
+ target.element.style.top = "600px";
+ target.element.style.width = "80px";
+ target.element.style.height = "40px";
+ fixture.appendChild(target.element);
+ }
+ }
+
+ [After]
+ public function tearDown():void
+ {
+ COMPILE::JS
+ {
+ window.scrollTo(originalScrollX, originalScrollY);
+ document.body.removeChild(fixture);
+ fixture = null;
+ target = null;
+ }
+ }
+
+ [Test]
+ public function testScreenBoundsAtPageOffsetZero():void
+ {
+ COMPILE::JS
+ {
+ var clientBounds:Object =
target.element.getBoundingClientRect();
+ var bounds:Rectangle =
DisplayUtils.getScreenBoundingRect(target);
+
+ assertRectangleMatchesClientBounds(bounds, clientBounds);
+ }
+ }
+
+ [Test]
+ public function testScreenBoundsAfterDocumentScroll():void
+ {
+ COMPILE::JS
+ {
+ var before:Rectangle =
DisplayUtils.getScreenBoundingRect(target);
+ window.scrollTo(0, 200);
+ var clientBounds:Object =
target.element.getBoundingClientRect();
+ var after:Rectangle =
DisplayUtils.getScreenBoundingRect(target);
+
+ assertRectangleMatchesClientBounds(after, clientBounds);
+ assertNear(before.top - 200, after.top, "Document scrolling
should move viewport bounds");
+ }
+ }
+
+ [Test]
+ public function testScreenBoundsInsideScrollingContainer():void
+ {
+ COMPILE::JS
+ {
+ var scroller:HTMLElement = document.createElement("div") as
HTMLElement;
+ scroller.style.position = "absolute";
+ scroller.style.left = "150px";
+ scroller.style.top = "100px";
+ scroller.style.width = "200px";
+ scroller.style.height = "100px";
+ scroller.style.overflow = "auto";
+ fixture.appendChild(scroller);
+
+ target.element.style.left = "20px";
+ target.element.style.top = "300px";
+ scroller.appendChild(target.element);
+ var before:Rectangle =
DisplayUtils.getScreenBoundingRect(target);
+
+ scroller.scrollTop = 120;
+ var clientBounds:Object =
target.element.getBoundingClientRect();
+ var after:Rectangle =
DisplayUtils.getScreenBoundingRect(target);
+
+ assertRectangleMatchesClientBounds(after, clientBounds);
+ assertNear(before.top - 120, after.top, "Ancestor scrolling
should move viewport bounds");
+ }
+ }
+
+ [Test]
+ public function testBoundsBeforeTransformIsUsed():void
+ {
+ COMPILE::JS
+ {
+ var suppliedBounds:Rectangle = new Rectangle(10, 20, 30, 40);
+ var bounds:Rectangle =
DisplayUtils.getScreenBoundingRect(target, suppliedBounds);
+
+ assertStrictlyEquals(suppliedBounds, bounds);
+ assertEquals(10, bounds.left);
+ assertEquals(20, bounds.top);
+ assertEquals(40, bounds.right);
+ assertEquals(60, bounds.bottom);
+ }
+ }
+
+ [Test]
+ public function testObjectsOverlapUsesViewportBounds():void
+ {
+ COMPILE::JS
+ {
+ var other:UIBase = new UIBase();
+ other.element.style.position = "absolute";
+ other.element.style.left = "100px";
+ other.element.style.top = "620px";
+ other.element.style.width = "40px";
+ other.element.style.height = "40px";
+ fixture.appendChild(other.element);
+
+ assertTrue(DisplayUtils.objectsOverlap(target, other));
+
+ other.element.style.left = "200px";
+ assertFalse(DisplayUtils.objectsOverlap(target, other));
+ }
+ }
+
+ COMPILE::JS
+ private function assertRectangleMatchesClientBounds(bounds:Rectangle,
clientBounds:Object):void
+ {
+ assertNear(clientBounds.left, bounds.left, "Incorrect left
viewport coordinate");
+ assertNear(clientBounds.top, bounds.top, "Incorrect top viewport
coordinate");
+ assertNear(clientBounds.right, bounds.right, "Incorrect right
viewport coordinate");
+ assertNear(clientBounds.bottom, bounds.bottom, "Incorrect bottom
viewport coordinate");
+ }
+
+ COMPILE::JS
+ private function assertNear(expected:Number, actual:Number,
message:String):void
+ {
+ assertTrue(Math.abs(expected - actual) < 0.01, message + ":
expected " + expected + " but was " + actual);
+ }
+ }
+}
\ No newline at end of file