diff options
author | 2017-02-03 10:33:25 -0500 | |
---|---|---|
committer | 2017-02-03 16:08:46 +0000 | |
commit | 0dda9cb881900241c1c2193ddf3bede72cda898b (patch) | |
tree | dd12f754b75f3a6802944b404dc196f659f6d338 /src | |
parent | 48ded38da99c1171ba1bb469f6500f8214e9105c (diff) |
Make shadow tessellators fail gracefully and add unit test for this.
Change-Id: I42a9d06a18928588347a6dea2f6150518ba29aa8
Reviewed-on: https://skia-review.googlesource.com/7886
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'src')
-rwxr-xr-x | src/utils/SkShadowTessellator.cpp | 55 | ||||
-rwxr-xr-x | src/utils/SkShadowTessellator.h | 3 | ||||
-rwxr-xr-x | src/utils/SkShadowUtils.cpp | 3 |
3 files changed, 45 insertions, 16 deletions
diff --git a/src/utils/SkShadowTessellator.cpp b/src/utils/SkShadowTessellator.cpp index f140ceb2b1..a0a011f171 100755 --- a/src/utils/SkShadowTessellator.cpp +++ b/src/utils/SkShadowTessellator.cpp @@ -26,6 +26,8 @@ public: int vertexCount() const { return fPositions.count(); } int indexCount() const { return fIndices.count(); } + bool succeeded() const { return fSucceeded; } + // The casts are needed to work around a, older GCC issue where the fact that the pointers are // T* and not const T* causes calls to a deleted unique_ptr constructor. UniqueArray<SkPoint> releasePositions() { @@ -71,6 +73,8 @@ private: SkTDArray<SkPoint> fInitPoints; // temporary buffer SkTDArray<SkPoint> fPointBuffer; + + bool fSucceeded; }; static bool compute_normal(const SkPoint& p0, const SkPoint& p1, SkScalar radius, SkScalar dir, @@ -107,12 +111,12 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, SkColor umbraColor, SkColor penumbraColor, bool transparent) - : fRadius(radius) - , fUmbraColor(umbraColor) - , fPenumbraColor(penumbraColor) - , fTransparent(transparent) - , fPrevUmbraIndex(-1) { - + : fRadius(radius) + , fUmbraColor(umbraColor) + , fPenumbraColor(penumbraColor) + , fTransparent(transparent) + , fPrevUmbraIndex(-1) + , fSucceeded(false) { // Outer ring: 3*numPts // Middle ring: numPts fPositions.setReserve(4 * path.countPoints()); @@ -154,6 +158,10 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, } } + if (!this->indexCount()) { + return; + } + SkVector normal; if (compute_normal(fPositions[fPrevUmbraIndex], fPositions[fFirstVertex], fRadius, fDirection, &normal)) { @@ -198,6 +206,7 @@ SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, *fIndices.push() = fPositions.count() - 1; *fIndices.push() = fFirstVertex + 1; } + fSucceeded = true; } // tesselation tolerance values, in device space pixels @@ -388,6 +397,8 @@ public: return UniqueArray<uint16_t>(static_cast<const uint16_t*>(fIndices.release())); } + bool succeeded() const { return fSucceeded; } + private: void computeClipBounds(const SkPath& path); void checkUmbraAndTransformCentroid(SkScalar scale, const SkVector& xlate, @@ -439,6 +450,8 @@ private: SkTDArray<SkPoint> fInitPoints; // temporary buffer SkTDArray<SkPoint> fPointBuffer; + + bool fSucceeded; }; @@ -448,15 +461,16 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, SkScalar radius, SkColor umbraColor, SkColor penumbraColor, bool transparent) - : fRadius(radius) - , fUmbraColor(umbraColor) - , fPenumbraColor(penumbraColor) - , fTransparent(transparent) - , fValidUmbra(true) - , fPrevUmbraIndex(-1) - , fCurrPolyPoint(0) - , fPrevUmbraOutside(false) - , fFirstUmbraOutside(false) { + : fRadius(radius) + , fUmbraColor(umbraColor) + , fPenumbraColor(penumbraColor) + , fTransparent(transparent) + , fValidUmbra(true) + , fPrevUmbraIndex(-1) + , fCurrPolyPoint(0) + , fPrevUmbraOutside(false) + , fFirstUmbraOutside(false) + , fSucceeded(false) { // TODO: calculate these better // Penumbra ring: 3*numPts @@ -514,6 +528,10 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, } } + if (!this->indexCount()) { + return; + } + SkVector normal; if (compute_normal(fPrevPoint, fFirstPoint, fRadius, fDirection, &normal)) { @@ -579,6 +597,7 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, *fIndices.push() = fFirstVertex + 1; } } + fSucceeded = true; } void SkSpotShadowTessellator::computeClipBounds(const SkPath& path) { @@ -1008,6 +1027,9 @@ sk_sp<SkShadowVertices> SkShadowVertices::MakeAmbient(const SkPath& path, SkScal SkColor umbraColor, SkColor penumbraColor, bool transparent) { SkAmbientShadowTessellator ambientTess(path, radius, umbraColor, penumbraColor, transparent); + if (!ambientTess.succeeded()) { + return nullptr; + } int vcount = ambientTess.vertexCount(); int icount = ambientTess.indexCount(); return sk_sp<SkShadowVertices>(new SkShadowVertices(ambientTess.releasePositions(), @@ -1022,6 +1044,9 @@ sk_sp<SkShadowVertices> SkShadowVertices::MakeSpot(const SkPath& path, SkScalar bool transparent) { SkSpotShadowTessellator spotTess(path, scale, translate, radius, umbraColor, penumbraColor, transparent); + if (!spotTess.succeeded()) { + return nullptr; + } int vcount = spotTess.vertexCount(); int icount = spotTess.indexCount(); return sk_sp<SkShadowVertices>(new SkShadowVertices(spotTess.releasePositions(), diff --git a/src/utils/SkShadowTessellator.h b/src/utils/SkShadowTessellator.h index 13924f204f..c9abd72a29 100755 --- a/src/utils/SkShadowTessellator.h +++ b/src/utils/SkShadowTessellator.h @@ -61,7 +61,8 @@ private: , fPositions(std::move(positions)) , fColors(std::move(colors)) , fIndices(std::move(indices)) { - SkASSERT(SkToBool(fIndices) == SkToBool(indexCnt)); + SkASSERT(SkToBool(fPositions) && SkToBool(fColors) && SkToBool(vertexCnt) && + SkToBool(fIndices) && SkToBool(indexCnt)); } int fVertexCnt; diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp index 32f1c6f165..83699c5625 100755 --- a/src/utils/SkShadowUtils.cpp +++ b/src/utils/SkShadowUtils.cpp @@ -267,6 +267,9 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S } else { // TODO: handle transforming the path as part of the tessellator vertices = factory.makeVertices(path.transformedPath()); + if (!vertices) { + return; + } translate = &kZeroTranslate; } |