From 1af03d4396a9567e3ca127830676eb4fd5a76266 Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Mon, 31 Jul 2017 09:34:58 -0400 Subject: Compute correct bounds for DrawShadowRec. Bug: skia:6880 Change-Id: Ia8b94e52eec3feb5104d2351bf7a7e6f99101deb Reviewed-on: https://skia-review.googlesource.com/26370 Commit-Queue: Jim Van Verth Reviewed-by: Brian Salomon --- tests/ShadowTest.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 tests/ShadowTest.cpp (limited to 'tests/ShadowTest.cpp') diff --git a/tests/ShadowTest.cpp b/tests/ShadowTest.cpp new file mode 100644 index 0000000000..8a921d8bc8 --- /dev/null +++ b/tests/ShadowTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkCanvas.h" +#include "SkDrawShadowInfo.h" +#include "SkPath.h" +#include "SkShadowTessellator.h" +#include "SkShadowUtils.h" +#include "SkVertices.h" +#include "Test.h" + +void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm, + bool expectSuccess) { + + auto heightParams = SkPoint3::Make(0, 0, 4); + + auto verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, true); + if (expectSuccess != SkToBool(verts)) { + ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", + expectSuccess ? "succeed" : "fail"); + } + verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, false); + if (expectSuccess != SkToBool(verts)) { + ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", + expectSuccess ? "succeed" : "fail"); + } + verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false); + if (expectSuccess != SkToBool(verts)) { + ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", + expectSuccess ? "succeed" : "fail"); + } + verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false); + if (expectSuccess != SkToBool(verts)) { + ERRORF(reporter, "Expected shadow tessellation to %s but it did not.", + expectSuccess ? "succeed" : "fail"); + } +} + +DEF_TEST(ShadowUtils, reporter) { + SkCanvas canvas(100, 100); + + SkPath path; + path.cubicTo(100, 50, 20, 100, 0, 0); + tessellate_shadow(reporter, path, canvas.getTotalMatrix(), true); + + // This line segment has no area and no shadow. + path.reset(); + path.lineTo(10.f, 10.f); + tessellate_shadow(reporter, path, canvas.getTotalMatrix(), false); + + // A series of colinear line segments + path.reset(); + for (int i = 0; i < 10; ++i) { + path.lineTo((SkScalar)i, (SkScalar)i); + } + tessellate_shadow(reporter, path, canvas.getTotalMatrix(), false); +} + +void check_xformed_bounds(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm) { + const SkDrawShadowRec rec = { + SkPoint3::Make(0, 0, 4), + SkPoint3::Make(100, 0, 600), + 800.f, + 0.035f, + 0.25f, + SK_ColorBLACK, + 0 + }; + SkRect bounds; + SkDrawShadowMetrics::GetLocalBounds(path, rec, ctm, &bounds); + ctm.mapRect(&bounds); + + auto verts = SkShadowTessellator::MakeAmbient(path, ctm, rec.fZPlaneParams, true); + if (verts) { + REPORTER_ASSERT(reporter, bounds.contains(verts->bounds())); + } + + SkPoint mapXY = ctm.mapXY(rec.fLightPos.fX, rec.fLightPos.fY); + SkPoint3 devLightPos = SkPoint3::Make(mapXY.fX, mapXY.fY, rec.fLightPos.fZ); + verts = SkShadowTessellator::MakeSpot(path, ctm, rec.fZPlaneParams, devLightPos, + rec.fLightRadius, false); + if (verts) { + REPORTER_ASSERT(reporter, bounds.contains(verts->bounds())); + } +} + +void check_bounds(skiatest::Reporter* reporter, const SkPath& path) { + SkMatrix ctm; + ctm.setTranslate(100, 100); + check_xformed_bounds(reporter, path, ctm); + ctm.postScale(2, 2); + check_xformed_bounds(reporter, path, ctm); + ctm.preRotate(45); + check_xformed_bounds(reporter, path, ctm); + ctm.preSkew(40, -20); + check_xformed_bounds(reporter, path, ctm); + ctm[SkMatrix::kMPersp0] = 0.0001f; + ctm[SkMatrix::kMPersp1] = 12.f; + check_xformed_bounds(reporter, path, ctm); +} + +DEF_TEST(ShadowBounds, reporter) { + SkPath path; + path.addRRect(SkRRect::MakeRectXY(SkRect::MakeLTRB(-50, -20, 40, 30), 4, 4)); + check_bounds(reporter, path); + + path.reset(); + path.addOval(SkRect::MakeLTRB(300, 300, 900, 900)); + check_bounds(reporter, path); + + path.reset(); + path.cubicTo(100, 50, 20, 100, 0, 0); + check_bounds(reporter, path); +} -- cgit v1.2.3