Add some additional checks for shadow generation

Change-Id: I4dae4173ad879827e4e1fa3ad12aa0447d1df252
Reviewed-on: https://skia-review.googlesource.com/110360
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2018-02-26 13:54:34 -05:00 committed by Skia Commit-Bot
parent 1693d43f37
commit a947e29bfd
3 changed files with 34 additions and 1 deletions

View File

@ -107,6 +107,24 @@ struct SK_API SkPoint3 {
fZ -= v.fZ;
}
/** Returns true if fX, fY, and fZ are measurable values.
@return true for values other than infinities and NaN
*/
bool isFinite() const {
SkScalar accum = 0;
accum *= fX;
accum *= fY;
accum *= fZ;
// accum is either NaN or it is finite (zero).
SkASSERT(0 == accum || SkScalarIsNaN(accum));
// value==value will be true iff value is not NaN
// TODO: is it faster to say !accum or accum==accum?
return !SkScalarIsNaN(accum);
}
/** Returns the dot product of a and b, treating them as 3D vectors
*/
static SkScalar DotProduct(const SkPoint3& a, const SkPoint3& b) {

View File

@ -177,6 +177,12 @@ void SkBaseShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) {
void SkBaseShadowTessellator::handleQuad(const SkPoint pts[3]) {
#if SK_SUPPORT_GPU
// check for degeneracy
SkVector v0 = pts[1] - pts[0];
SkVector v1 = pts[2] - pts[0];
if (SkScalarNearlyZero(v0.cross(v1))) {
return;
}
// TODO: Pull PathUtils out of Ganesh?
int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
fPointBuffer.setReserve(maxCount);
@ -277,7 +283,7 @@ bool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) {
};
} else {
SkMatrix ctmInverse;
if (!ctm.invert(&ctmInverse)) {
if (!ctm.invert(&ctmInverse) || !ctmInverse.isFinite()) {
return false;
}
// multiply by transpose

View File

@ -535,6 +535,11 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
canvas->private_draw_shadow_rec(path, rec);
}
static bool validate_rec(const SkDrawShadowRec& rec) {
return rec.fLightPos.isFinite() && rec.fZPlaneParams.isFinite() &&
SkScalarIsFinite(rec.fLightRadius);
}
void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
auto drawVertsProc = [this](const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint,
SkScalar tx, SkScalar ty) {
@ -543,6 +548,10 @@ void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
this->drawVertices(vertices, mode, paint);
};
if (!validate_rec(rec)) {
return;
}
SkMatrix viewMatrix = this->ctm();
SkAutoDeviceCTMRestore adr(this, SkMatrix::I());