Diff
Modified: trunk/Source/WebCore/ChangeLog (276274 => 276275)
--- trunk/Source/WebCore/ChangeLog 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Source/WebCore/ChangeLog 2021-04-19 22:20:53 UTC (rev 276275)
@@ -1,3 +1,26 @@
+2021-04-19 Wenson Hsieh <[email protected]>
+
+ Rename FloatQuad::isEmpty() to boundingBoxIsEmpty() and reimplement isEmpty()
+ https://bugs.webkit.org/show_bug.cgi?id=224769
+
+ Reviewed by Tim Horton.
+
+ The existing `isEmpty()` method on `FloatQuad` only checks that the bounding box of the quad is empty (as
+ indicated by the comment above the method declaration). This means `isEmpty()` returns `false` in cases where
+ the quad consists of one or more non-rectilinear line segments, even though the quad contains no area.
+
+ To address this, we rename the existing `isEmpty()` helper to `boundingBoxIsEmpty()` and reintroduce an
+ `isEmpty()` method that accounts for quads which are equivalent to non-rectilinear line segments.
+
+ No change in behavior.
+
+ * inspector/InspectorOverlay.cpp:
+ (WebCore::drawFragmentHighlight):
+ * platform/graphics/FloatQuad.cpp:
+ * platform/graphics/FloatQuad.h:
+ (WebCore::FloatQuad::isEmpty const): Deleted.
+ (WebCore::FloatQuad::boundingBoxIsEmpty const):
+
2021-04-19 Patrick Angle <[email protected]>
Web Inspector: Grid overlay column line label placement copy/paste error
Modified: trunk/Source/WebCore/inspector/InspectorOverlay.cpp (276274 => 276275)
--- trunk/Source/WebCore/inspector/InspectorOverlay.cpp 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Source/WebCore/inspector/InspectorOverlay.cpp 2021-04-19 22:20:53 UTC (rev 276275)
@@ -286,16 +286,16 @@
if (size >= 4)
contentQuad = highlight.quads[3];
- if (!marginQuad.isEmpty() && marginQuad != borderQuad && highlight.marginColor.isVisible())
+ if (!marginQuad.boundingBoxIsEmpty() && marginQuad != borderQuad && highlight.marginColor.isVisible())
drawOutlinedQuadWithClip(context, marginQuad, borderQuad, highlight.marginColor, bounds);
- if (!borderQuad.isEmpty() && borderQuad != paddingQuad && highlight.borderColor.isVisible())
+ if (!borderQuad.boundingBoxIsEmpty() && borderQuad != paddingQuad && highlight.borderColor.isVisible())
drawOutlinedQuadWithClip(context, borderQuad, paddingQuad, highlight.borderColor, bounds);
- if (!paddingQuad.isEmpty() && paddingQuad != contentQuad && highlight.paddingColor.isVisible())
+ if (!paddingQuad.boundingBoxIsEmpty() && paddingQuad != contentQuad && highlight.paddingColor.isVisible())
drawOutlinedQuadWithClip(context, paddingQuad, contentQuad, highlight.paddingColor, bounds);
- if (!contentQuad.isEmpty() && (highlight.contentColor.isVisible() || highlight.contentOutlineColor.isVisible()))
+ if (!contentQuad.boundingBoxIsEmpty() && (highlight.contentColor.isVisible() || highlight.contentOutlineColor.isVisible()))
drawOutlinedQuad(context, contentQuad, highlight.contentColor, highlight.contentOutlineColor, bounds);
}
Modified: trunk/Source/WebCore/platform/graphics/FloatQuad.cpp (276274 => 276275)
--- trunk/Source/WebCore/platform/graphics/FloatQuad.cpp 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Source/WebCore/platform/graphics/FloatQuad.cpp 2021-04-19 22:20:53 UTC (rev 276275)
@@ -228,6 +228,49 @@
return determinant(m_p2 - m_p1, m_p3 - m_p2) < 0;
}
+bool FloatQuad::isEmpty() const
+{
+ if (areEssentiallyEqual(m_p1, m_p3) || areEssentiallyEqual(m_p2, m_p4)) {
+ // If either diagonal is zero length, then the "quad" either consists of 1 or 2 line segments, or it's just a point.
+ return true;
+ }
+
+ if (areEssentiallyEqual(m_p1, m_p2) && areEssentiallyEqual(m_p3, m_p4)) {
+ // If both top points and both bottom points are equal, then the "quad" is just a single line segment.
+ return true;
+ }
+
+ if (areEssentiallyEqual(m_p1, m_p4) && areEssentiallyEqual(m_p2, m_p3)) {
+ // If both left points and both right points are equal, then the "quad" is just a single line segment.
+ return true;
+ }
+
+ // Fall back to checking whether the 4 points of the quad are colinear (in other words, check whether the three
+ // vectors from one point to each of the other points are capable of forming a 2D basis).
+ auto b1 = m_p1 - m_p2;
+ auto b2 = m_p1 - m_p3;
+ auto b3 = m_p1 - m_p4;
+
+ if (!b1.isZero())
+ b1 = b1 / b1.diagonalLength();
+
+ if (!b2.isZero())
+ b2 = b2 / b2.diagonalLength();
+
+ if (!b3.isZero())
+ b3 = b3 / b3.diagonalLength();
+
+ auto areNormalizedVectorsLinearlyIndependent = [](const FloatSize& u, const FloatSize& v) {
+ if (u.isZero() || v.isZero())
+ return false;
+
+ auto dotProduct = u.width() * v.width() + u.height() * v.height();
+ return !WTF::areEssentiallyEqual<float>(dotProduct, 1) && !WTF::areEssentiallyEqual<float>(dotProduct, -1);
+ };
+
+ return !areNormalizedVectorsLinearlyIndependent(b1, b2) && !areNormalizedVectorsLinearlyIndependent(b2, b3) && !areNormalizedVectorsLinearlyIndependent(b1, b3);
+}
+
Vector<FloatRect> boundingBoxes(const Vector<FloatQuad>& quads)
{
Vector<FloatRect> boxes;
Modified: trunk/Source/WebCore/platform/graphics/FloatQuad.h (276274 => 276275)
--- trunk/Source/WebCore/platform/graphics/FloatQuad.h 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Source/WebCore/platform/graphics/FloatQuad.h 2021-04-19 22:20:53 UTC (rev 276275)
@@ -76,10 +76,11 @@
void setP3(const FloatPoint& p) { m_p3 = p; }
void setP4(const FloatPoint& p) { m_p4 = p; }
- // isEmpty tests that the bounding box is empty. This will not identify
- // "slanted" empty quads.
- bool isEmpty() const { return boundingBox().isEmpty(); }
+ WEBCORE_EXPORT bool isEmpty() const;
+ // This method will not identify "slanted" empty quads.
+ bool boundingBoxIsEmpty() const { return boundingBox().isEmpty(); }
+
// Tests whether this quad can be losslessly represented by a FloatRect,
// that is, if two edges are parallel to the x-axis and the other two
// are parallel to the y-axis. If this method returns true, the
@@ -214,7 +215,7 @@
return !(a == b);
}
-WTF::TextStream& operator<<(WTF::TextStream&, const FloatQuad&);
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FloatQuad&);
Vector<FloatRect> boundingBoxes(const Vector<FloatQuad>&);
WEBCORE_EXPORT FloatRect unitedBoundingBoxes(const Vector<FloatQuad>&);
Modified: trunk/Tools/ChangeLog (276274 => 276275)
--- trunk/Tools/ChangeLog 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Tools/ChangeLog 2021-04-19 22:20:53 UTC (rev 276275)
@@ -1,3 +1,16 @@
+2021-04-19 Wenson Hsieh <[email protected]>
+
+ Rename FloatQuad::isEmpty() to boundingBoxIsEmpty() and reimplement isEmpty()
+ https://bugs.webkit.org/show_bug.cgi?id=224769
+
+ Reviewed by Tim Horton.
+
+ Add an API test to exercise the new `FloatQuad::isEmpty()` method.
+
+ * TestWebKitAPI/Tests/WebCore/FloatQuadTests.cpp:
+ (TestWebKitAPI::checkIsEmpty):
+ (TestWebKitAPI::TEST):
+
2021-04-19 Tim Horton <[email protected]>
Fix the macCatalyst TestWebKitAPI build
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/FloatQuadTests.cpp (276274 => 276275)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/FloatQuadTests.cpp 2021-04-19 21:18:00 UTC (rev 276274)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/FloatQuadTests.cpp 2021-04-19 22:20:53 UTC (rev 276275)
@@ -27,6 +27,7 @@
#include <WebCore/FloatQuad.h>
#include <WebCore/GeometryUtilities.h>
+#include <wtf/text/TextStream.h>
namespace TestWebKitAPI {
using namespace WebCore;
@@ -109,4 +110,60 @@
}, 0.01));
}
+static void checkIsEmpty(bool expectation, FloatQuad&& quad)
+{
+ EXPECT_TRUE(expectation == quad.isEmpty());
+ if (expectation == quad.isEmpty())
+ return;
+
+ TextStream stream;
+ stream << quad;
+ WTFLogAlways("Expected quad: %s to be %s", stream.release().utf8().data(), expectation ? "empty" : "non-empty");
+}
+
+TEST(FloatQuad, IsEmpty)
+{
+ checkIsEmpty(true, { // Line segment.
+ FloatPoint(0, 0),
+ FloatPoint(0, 0),
+ FloatPoint(0, 3),
+ FloatPoint(0, 3),
+ });
+
+ checkIsEmpty(false, { // Triangle.
+ FloatPoint(0, 1),
+ FloatPoint(0, 0),
+ FloatPoint(3, 3),
+ FloatPoint(3, 3),
+ });
+
+ checkIsEmpty(false, { // Another triangle.
+ FloatPoint(0, 0),
+ FloatPoint(0, 0),
+ FloatPoint(3, 3),
+ FloatPoint(0, 3),
+ });
+
+ checkIsEmpty(true, { // Single point.
+ FloatPoint(100, 100),
+ FloatPoint(100, 100),
+ FloatPoint(100, 100),
+ FloatPoint(100, 100),
+ });
+
+ checkIsEmpty(true, { // Two line segments.
+ FloatPoint(0, 0),
+ FloatPoint(100, 100),
+ FloatPoint(0, 0),
+ FloatPoint(50, -100),
+ });
+
+ checkIsEmpty(true, { // 4 distinct but colinear points.
+ FloatPoint(-1, -1),
+ FloatPoint(0, 0),
+ FloatPoint(1, 1),
+ FloatPoint(3, 3),
+ });
+}
+
} // namespace TestWebKitAPI