ソースを参照

LibWeb: Use NaN safe min() and max() functions to compute DOMQuad bounds

Tim Ledbetter 1 年間 前
コミット
5136b495a6

+ 1 - 0
Tests/LibWeb/Text/expected/geometry/domquad.txt

@@ -2,3 +2,4 @@
 2. {"p1":{"x":0,"y":0,"z":0,"w":1},"p2":{"x":100,"y":0,"z":0,"w":1},"p3":{"x":100,"y":100,"z":0,"w":1},"p4":{"x":0,"y":100,"z":0,"w":1}}
 3. {"p1":{"x":0,"y":0,"z":0,"w":1},"p2":{"x":100,"y":0,"z":0,"w":1},"p3":{"x":100,"y":100,"z":0,"w":1},"p4":{"x":0,"y":100,"z":0,"w":1}}
 4. {"x":0,"y":0,"width":100,"height":100,"top":0,"right":100,"bottom":100,"left":0}
+5. {"x":null,"y":null,"width":null,"height":null,"top":null,"right":null,"bottom":null,"left":null}

+ 8 - 0
Tests/LibWeb/Text/input/geometry/domquad.html

@@ -32,5 +32,13 @@
             new DOMPoint(100, 100),
             new DOMPoint(0, 100)
         ).getBounds());
+
+        // 5. Getting the bounds of a DOMQuad with points set to Infinity
+        testPart(() => DOMQuad.fromRect({ 
+            x: -Infinity,
+            y: -Infinity,
+            width: Infinity,
+            height: Infinity
+        }).getBounds());
     });
 </script>

+ 16 - 4
Userland/Libraries/LibWeb/Geometry/DOMQuad.cpp

@@ -47,20 +47,32 @@ JS::NonnullGCPtr<DOMQuad> DOMQuad::from_quad(JS::VM& vm, DOMQuadInit const& othe
 // https://drafts.fxtf.org/geometry/#dom-domquad-getbounds
 JS::NonnullGCPtr<DOMRect> DOMQuad::get_bounds() const
 {
+    auto nan_safe_minimum = [](double a, double b, double c, double d) -> double {
+        if (isnan(a) || isnan(b) || isnan(c) || isnan(d))
+            return NAN;
+        return min(a, min(b, min(c, d)));
+    };
+
+    auto nan_safe_maximum = [](double a, double b, double c, double d) -> double {
+        if (isnan(a) || isnan(b) || isnan(c) || isnan(d))
+            return NAN;
+        return max(a, max(b, max(c, d)));
+    };
+
     // 1. Let bounds be a DOMRect object.
     auto bounds = DOMRect::create(realm(), {});
 
     // 2. Let left be the NaN-safe minimum of point 1’s x coordinate, point 2’s x coordinate, point 3’s x coordinate and point 4’s x coordinate.
-    auto left = min(m_p1->x(), min(m_p2->x(), min(m_p3->x(), m_p4->x())));
+    auto left = nan_safe_minimum(m_p1->x(), m_p2->x(), m_p3->x(), m_p4->x());
 
     // 3. Let top be the NaN-safe minimum of point 1’s y coordinate, point 2’s y coordinate, point 3’s y coordinate and point 4’s y coordinate.
-    auto top = min(m_p1->y(), min(m_p2->y(), min(m_p3->y(), m_p4->y())));
+    auto top = nan_safe_minimum(m_p1->y(), m_p2->y(), m_p3->y(), m_p4->y());
 
     // 4. Let right be the NaN-safe maximum of point 1’s x coordinate, point 2’s x coordinate, point 3’s x coordinate and point 4’s x coordinate.
-    auto right = max(m_p1->x(), max(m_p2->x(), max(m_p3->x(), m_p4->x())));
+    auto right = nan_safe_maximum(m_p1->x(), m_p2->x(), m_p3->x(), m_p4->x());
 
     // 5. Let bottom be the NaN-safe maximum of point 1’s y coordinate, point 2’s y coordinate, point 3’s y coordinate and point 4’s y coordinate.
-    auto bottom = max(m_p1->y(), max(m_p2->y(), max(m_p3->y(), m_p4->y())));
+    auto bottom = nan_safe_maximum(m_p1->y(), m_p2->y(), m_p3->y(), m_p4->y());
 
     // 6. Set x coordinate of bounds to left, y coordinate of bounds to top, width dimension of bounds to right - left and height dimension of bounds to bottom - top.
     bounds->set_x(left);