Bug 1331894 - Crash in InvalidArrayIndex_CRASH | mozilla::layers::BuildPathFromPolygon - Cull polygons with no area
MozReview-Commit-ID: KCkIA68vvgW
--- a/gfx/2d/Polygon.h
+++ b/gfx/2d/Polygon.h
@@ -179,20 +179,21 @@ public:
for (size_t i = 0; i < pointCount; ++i) {
const Point4DType p1 = points[(i + 1) % pointCount];
const Point4DType p2 = points[i];
const Point4DType normal(p2.y - p1.y, p1.x - p2.x, 0.0f, 0.0f);
const PolygonTyped<Units> plane({p1, p2}, normal);
ClipPolygonWithPlane(polygon, plane);
- }
- if (polygon.GetPoints().Length() < 3) {
- return PolygonTyped<Units>();
+ if (polygon.IsEmpty()) {
+ // The clipping created a polygon with no area.
+ return PolygonTyped<Units>();
+ }
}
return polygon;
}
static PolygonTyped<Units> FromRect(const RectTyped<Units>& aRect)
{
return PolygonTyped<Units> {
@@ -214,16 +215,22 @@ public:
}
const Point4DType& operator[](size_t aIndex) const
{
MOZ_ASSERT(mPoints.Length() > aIndex);
return mPoints[aIndex];
}
+ bool IsEmpty() const
+ {
+ // If the polygon has less than three points, it has no visible area.
+ return mPoints.Length() < 3;
+ }
+
void SplitPolygon(const Point4DType& aNormal,
const nsTArray<float>& aDots,
nsTArray<Point4DType>& aBackPoints,
nsTArray<Point4DType>& aFrontPoints) const
{
static const auto Sign = [](const float& f) {
if (f > 0.0f) return 1;
if (f < 0.0f) return -1;
@@ -265,17 +272,17 @@ public:
}
}
}
nsTArray<TriangleTyped<Units>> ToTriangles() const
{
nsTArray<TriangleTyped<Units>> triangles;
- if (mPoints.Length() < 3) {
+ if (IsEmpty()) {
return triangles;
}
for (size_t i = 1; i < mPoints.Length() - 1; ++i) {
TriangleTyped<Units> triangle(Point(mPoints[0].x, mPoints[0].y),
Point(mPoints[i].x, mPoints[i].y),
Point(mPoints[i+1].x, mPoints[i+1].y));
triangles.AppendElement(Move(triangle));
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -275,23 +275,28 @@ Compositor::DrawGeometry(const gfx::Rect
}
if (!aGeometry || !SupportsLayerGeometry()) {
DrawQuad(aRect, aClipRect, aEffectChain,
aOpacity, aTransform, aVisibleRect);
return;
}
- // Cull invisible polygons.
+ // Cull completely invisible polygons.
if (aRect.Intersect(aGeometry->BoundingBox()).IsEmpty()) {
return;
}
const gfx::Polygon clipped = aGeometry->ClipPolygon(aRect);
+ // Cull polygons with no area.
+ if (clipped.IsEmpty()) {
+ return;
+ }
+
DrawPolygon(clipped, aRect, aClipRect, aEffectChain,
aOpacity, aTransform, aVisibleRect);
}
void
Compositor::DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
const gfx::Rect& aRect,
const gfx::IntRect& aClipRect,
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -361,16 +361,18 @@ BasicCompositor::SupportsLayerGeometry()
{
return gfxPrefs::BasicLayerGeometry();
}
static RefPtr<gfx::Path>
BuildPathFromPolygon(const RefPtr<DrawTarget>& aDT,
const gfx::Polygon& aPolygon)
{
+ MOZ_ASSERT(!aPolygon.IsEmpty());
+
RefPtr<PathBuilder> pathBuilder = aDT->CreatePathBuilder();
const nsTArray<Point4D>& points = aPolygon.GetPoints();
pathBuilder->MoveTo(points[0].As2DPoint());
for (size_t i = 1; i < points.Length(); ++i) {
pathBuilder->LineTo(points[i].As2DPoint());
}