Use SkVertices for tessellated spot and ambient shadow rendering.

Change-Id: Ia81e7a771d345286533752708e4304c1ae3b97c9
Reviewed-on: https://skia-review.googlesource.com/8042
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Stan Iliev <stani@google.com>
This commit is contained in:
Brian Salomon 2017-02-06 15:47:44 -05:00 committed by Skia Commit-Bot
parent 1f8be68917
commit aff27a23ad
4 changed files with 119 additions and 163 deletions

View File

@ -9,40 +9,50 @@
#include "SkColorPriv.h" #include "SkColorPriv.h"
#include "SkGeometry.h" #include "SkGeometry.h"
#include "SkPath.h" #include "SkPath.h"
#include "SkVertices.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrPathUtils.h" #include "GrPathUtils.h"
#endif #endif
template <typename T> using UniqueArray = SkShadowVertices::UniqueArray<T>;
/** /**
* Base class * Base class
*/ */
class SkShadowTessellator { class SkBaseShadowTessellator {
public: public:
SkShadowTessellator(SkScalar radius, SkColor umbraColor, SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor, SkColor penumbraColor,
SkColor penumbraColor, bool transparent); bool transparent);
virtual ~SkShadowTessellator() {} virtual ~SkBaseShadowTessellator() {}
int vertexCount() const { return fPositions.count(); } sk_sp<SkVertices> releaseVertices() {
int indexCount() const { return fIndices.count(); } if (!fSucceeded) {
return nullptr;
bool succeeded() const { return fSucceeded; } }
int vCount = this->vertexCount();
// The casts are needed to work around a, older GCC issue where the fact that the pointers are int iCount = this->indexCount();
// T* and not const T* causes calls to a deleted unique_ptr constructor. // We copy here for two reasons: 1) To tighten up our arrays and 2) to get into memory
UniqueArray<SkPoint> releasePositions() { // allocated by new[] rather than malloc.
return UniqueArray<SkPoint>(static_cast<const SkPoint*>(fPositions.release())); // TODO: If we know we're not caching then we should avoid this.
} SkPoint* positions = new SkPoint[vCount];
UniqueArray<SkColor> releaseColors() { SkColor* colors = new SkColor[vCount];
return UniqueArray<SkColor>(static_cast<const SkColor*>(fColors.release())); uint16_t* indices = new uint16_t[iCount];
} memcpy(positions, fPositions.begin(), sizeof(SkPoint) * vCount);
UniqueArray<uint16_t> releaseIndices() { memcpy(colors, fColors.begin(), sizeof(SkColor) * vCount);
return UniqueArray<uint16_t>(static_cast<const uint16_t*>(fIndices.release())); memcpy(indices, fIndices.begin(), sizeof(uint16_t) * iCount);
return SkVertices::MakeIndexed(SkCanvas::kTriangles_VertexMode,
std::unique_ptr<const SkPoint[]>(positions),
std::unique_ptr<const SkColor[]>(colors),
nullptr,
vCount,
std::unique_ptr<const uint16_t[]>(indices),
iCount);
} }
protected: protected:
int vertexCount() const { return fPositions.count(); }
int indexCount() const { return fIndices.count(); }
virtual void handleLine(const SkPoint& p) = 0; virtual void handleLine(const SkPoint& p) = 0;
void handleLine(const SkMatrix& m, SkPoint* p); void handleLine(const SkMatrix& m, SkPoint* p);
@ -112,17 +122,16 @@ static void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScala
*n = SkScalarFloorToInt(steps); *n = SkScalarFloorToInt(steps);
} }
SkShadowTessellator::SkShadowTessellator(SkScalar radius, SkColor umbraColor, SkBaseShadowTessellator::SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor,
SkColor penumbraColor, bool transparent) SkColor penumbraColor, bool transparent)
: fFirstVertex(-1) : fFirstVertex(-1)
, fSucceeded(false) , fSucceeded(false)
, fTransparent(transparent) , fTransparent(transparent)
, fUmbraColor(umbraColor) , fUmbraColor(umbraColor)
, fPenumbraColor(penumbraColor) , fPenumbraColor(penumbraColor)
, fRadius(radius) , fRadius(radius)
, fDirection(1) , fDirection(1)
, fPrevUmbraIndex(-1) { , fPrevUmbraIndex(-1) {
fInitPoints.setReserve(3); fInitPoints.setReserve(3);
// child classes will set reserve for positions, colors and indices // child classes will set reserve for positions, colors and indices
@ -133,12 +142,12 @@ static const SkScalar kQuadTolerance = 0.2f;
static const SkScalar kCubicTolerance = 0.2f; static const SkScalar kCubicTolerance = 0.2f;
static const SkScalar kConicTolerance = 0.5f; static const SkScalar kConicTolerance = 0.5f;
void SkShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) { void SkBaseShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) {
m.mapPoints(p, 1); m.mapPoints(p, 1);
this->handleLine(*p); this->handleLine(*p);
} }
void SkShadowTessellator::handleQuad(const SkPoint pts[3]) { void SkBaseShadowTessellator::handleQuad(const SkPoint pts[3]) {
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
// TODO: Pull PathUtils out of Ganesh? // TODO: Pull PathUtils out of Ganesh?
int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
@ -157,12 +166,12 @@ void SkShadowTessellator::handleQuad(const SkPoint pts[3]) {
#endif #endif
} }
void SkShadowTessellator::handleQuad(const SkMatrix& m, SkPoint pts[3]) { void SkBaseShadowTessellator::handleQuad(const SkMatrix& m, SkPoint pts[3]) {
m.mapPoints(pts, 3); m.mapPoints(pts, 3);
this->handleQuad(pts); this->handleQuad(pts);
} }
void SkShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) { void SkBaseShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) {
m.mapPoints(pts, 4); m.mapPoints(pts, 4);
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
// TODO: Pull PathUtils out of Ganesh? // TODO: Pull PathUtils out of Ganesh?
@ -183,7 +192,7 @@ void SkShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) {
#endif #endif
} }
void SkShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w) { void SkBaseShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w) {
m.mapPoints(pts, 3); m.mapPoints(pts, 3);
SkAutoConicToQuads quadder; SkAutoConicToQuads quadder;
const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
@ -200,7 +209,7 @@ void SkShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScala
} }
} }
void SkShadowTessellator::addArc(const SkVector& nextNormal) { void SkBaseShadowTessellator::addArc(const SkVector& nextNormal) {
// fill in fan from previous quad // fill in fan from previous quad
SkScalar rotSin, rotCos; SkScalar rotSin, rotCos;
int numSteps; int numSteps;
@ -220,8 +229,8 @@ void SkShadowTessellator::addArc(const SkVector& nextNormal) {
} }
} }
void SkShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, void SkBaseShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
const SkVector& nextNormal) { const SkVector& nextNormal) {
// close out previous arc // close out previous arc
*fPositions.push() = fPrevPoint + nextNormal; *fPositions.push() = fPrevPoint + nextNormal;
*fColors.push() = fPenumbraColor; *fColors.push() = fPenumbraColor;
@ -235,7 +244,7 @@ void SkShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint,
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
class SkAmbientShadowTessellator : public SkShadowTessellator { class SkAmbientShadowTessellator : public SkBaseShadowTessellator {
public: public:
SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm,
SkScalar radius, SkColor umbraColor, SkScalar radius, SkColor umbraColor,
@ -247,7 +256,7 @@ private:
int fCentroidCount; int fCentroidCount;
typedef SkShadowTessellator INHERITED; typedef SkBaseShadowTessellator INHERITED;
}; };
SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
@ -435,7 +444,7 @@ void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
class SkSpotShadowTessellator : public SkShadowTessellator { class SkSpotShadowTessellator : public SkBaseShadowTessellator {
public: public:
SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm,
SkScalar scale, const SkVector& translate, SkScalar scale, const SkVector& translate,
@ -463,7 +472,7 @@ private:
bool fFirstUmbraOutside; bool fFirstUmbraOutside;
bool fValidUmbra; bool fValidUmbra;
typedef SkShadowTessellator INHERITED; typedef SkBaseShadowTessellator INHERITED;
}; };
SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm,
@ -475,7 +484,6 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
, fPrevUmbraOutside(false) , fPrevUmbraOutside(false)
, fFirstUmbraOutside(false) , fFirstUmbraOutside(false)
, fValidUmbra(true) { , fValidUmbra(true) {
// TODO: calculate these better // TODO: calculate these better
// Penumbra ring: 3*numPts // Penumbra ring: 3*numPts
// Umbra ring: numPts // Umbra ring: numPts
@ -948,33 +956,18 @@ void SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector&
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkShadowVertices> SkShadowVertices::MakeAmbient(const SkPath& path, const SkMatrix& ctm, sk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm,
SkScalar radius, SkColor umbra, SkScalar radius, SkColor umbra, SkColor penumbra,
SkColor penumbra, bool transparent) { bool transparent) {
SkAmbientShadowTessellator ambientTess(path, ctm, radius, umbra, penumbra, transparent); SkAmbientShadowTessellator ambientTess(path, ctm, radius, umbra, penumbra, transparent);
if (!ambientTess.succeeded()) { return ambientTess.releaseVertices();
return nullptr;
}
int vcount = ambientTess.vertexCount();
int icount = ambientTess.indexCount();
return sk_sp<SkShadowVertices>(new SkShadowVertices(ambientTess.releasePositions(),
ambientTess.releaseColors(),
ambientTess.releaseIndices(), vcount,
icount));
} }
sk_sp<SkShadowVertices> SkShadowVertices::MakeSpot(const SkPath& path, const SkMatrix& ctm, sk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm,
SkScalar scale, const SkVector& translate, SkScalar scale, const SkVector& translate,
SkScalar radius, SkColor umbraColor, SkScalar radius, SkColor umbraColor,
SkColor penumbraColor, bool transparent) { SkColor penumbraColor, bool transparent) {
SkSpotShadowTessellator spotTess(path, ctm, scale, translate, radius, umbraColor, SkSpotShadowTessellator spotTess(path, ctm, scale, translate, radius, umbraColor,
penumbraColor, transparent); penumbraColor, transparent);
if (!spotTess.succeeded()) { return spotTess.releaseVertices();
return nullptr;
}
int vcount = spotTess.vertexCount();
int icount = spotTess.indexCount();
return sk_sp<SkShadowVertices>(new SkShadowVertices(spotTess.releasePositions(),
spotTess.releaseColors(),
spotTess.releaseIndices(), vcount, icount));
} }

View File

@ -8,68 +8,31 @@
#ifndef SkShadowTessellator_DEFINED #ifndef SkShadowTessellator_DEFINED
#define SkShadowTessellator_DEFINED #define SkShadowTessellator_DEFINED
#include "SkTDArray.h"
#include "SkRefCnt.h"
#include "SkPoint.h"
#include "SkColor.h" #include "SkColor.h"
#include "SkPoint.h"
#include "SkRefCnt.h"
class SkMatrix; class SkMatrix;
class SkPath; class SkPath;
class SkVertices;
class SkShadowVertices : public SkRefCnt { namespace SkShadowTessellator {
public: /**
/** * This function generates an ambient shadow mesh for a path by walking the path, outsetting by
* This function generates an ambient shadow mesh for a path by walking the path, outsetting by * the radius, and setting inner and outer colors to umbraColor and penumbraColor, respectively.
* the radius, and setting inner and outer colors to umbraColor and penumbraColor, respectively. * If transparent is true, then the center of the ambient shadow will be filled in.
* If transparent is true, then the center of the ambient shadow will be filled in. */
*/ sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm, SkScalar radius,
static sk_sp<SkShadowVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm, SkColor umbraColor, SkColor penumbraColor, bool transparent);
SkScalar radius, SkColor umbraColor,
SkColor penumbraColor, bool transparent);
/** /**
* This function generates a spot shadow mesh for a path by walking the transformed path, * This function generates a spot shadow mesh for a path by walking the transformed path,
* further transforming by the scale and translation, and outsetting and insetting by a radius. * further transforming by the scale and translation, and outsetting and insetting by a radius.
* The center will be clipped against the original path unless transparent is true. * The center will be clipped against the original path unless transparent is true.
*/ */
static sk_sp<SkShadowVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, SkScalar scale,
SkScalar scale, const SkVector& translate, const SkVector& translate, SkScalar radius, SkColor umbraColor,
SkScalar radius, SkColor umbraColor, SkColor penumbraColor, bool transparent);
SkColor penumbraColor, bool transparent); }
int vertexCount() const { return fVertexCnt; }
const SkPoint* positions() const { return fPositions.get(); }
const SkColor* colors() const { return fColors.get(); }
int indexCount() const { return fIndexCnt; }
const uint16_t* indices() const { return fIndices.get(); }
size_t size() const {
return sizeof(*this) + fVertexCnt * (sizeof(SkPoint) + sizeof(SkColor)) +
fIndexCnt * sizeof(uint16_t);
}
private:
template<typename T> using Deleter = SkTDArray<SkPoint>::Deleter;
template<typename T> using UniqueArray = std::unique_ptr<const T[], Deleter<T>>;
SkShadowVertices(UniqueArray<SkPoint>&& positions, UniqueArray<SkColor>&& colors,
UniqueArray<uint16_t>&& indices, int vertexCnt, int indexCnt)
: fVertexCnt(vertexCnt)
, fIndexCnt(indexCnt)
, fPositions(std::move(positions))
, fColors(std::move(colors))
, fIndices(std::move(indices)) {
SkASSERT(SkToBool(fPositions) && SkToBool(fColors) && SkToBool(vertexCnt) &&
SkToBool(fIndices) && SkToBool(indexCnt));
}
int fVertexCnt;
int fIndexCnt;
UniqueArray<SkPoint> fPositions;
UniqueArray<SkColor> fColors;
UniqueArray<uint16_t> fIndices;
};
#endif #endif

View File

@ -13,6 +13,7 @@
#include "SkResourceCache.h" #include "SkResourceCache.h"
#include "SkShadowTessellator.h" #include "SkShadowTessellator.h"
#include "SkTLazy.h" #include "SkTLazy.h"
#include "SkVertices.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrShape.h" #include "GrShape.h"
#include "effects/GrBlurredEdgeFragmentProcessor.h" #include "effects/GrBlurredEdgeFragmentProcessor.h"
@ -98,9 +99,9 @@ struct AmbientVerticesFactory {
return true; return true;
} }
sk_sp<SkShadowVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const { sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const {
return SkShadowVertices::MakeAmbient(path, ctm, fRadius, fUmbraColor, fPenumbraColor, return SkShadowTessellator::MakeAmbient(path, ctm, fRadius, fUmbraColor, fPenumbraColor,
fTransparent); fTransparent);
} }
}; };
@ -148,10 +149,10 @@ struct SpotVerticesFactory {
return false; return false;
} }
sk_sp<SkShadowVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const { sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const {
bool transparent = OccluderType::kTransparent == fOccluderType; bool transparent = OccluderType::kTransparent == fOccluderType;
return SkShadowVertices::MakeSpot(path, ctm, fScale, fOffset, fRadius, fUmbraColor, return SkShadowTessellator::MakeSpot(path, ctm, fScale, fOffset, fRadius, fUmbraColor,
fPenumbraColor, transparent); fPenumbraColor, transparent);
} }
}; };
@ -165,23 +166,23 @@ class CachedTessellations : public SkRefCnt {
public: public:
size_t size() const { return fAmbientSet.size() + fSpotSet.size(); } size_t size() const { return fAmbientSet.size() + fSpotSet.size(); }
sk_sp<SkShadowVertices> find(const AmbientVerticesFactory& ambient, const SkMatrix& matrix, sk_sp<SkVertices> find(const AmbientVerticesFactory& ambient, const SkMatrix& matrix,
SkVector* translate) const { SkVector* translate) const {
return fAmbientSet.find(ambient, matrix, translate); return fAmbientSet.find(ambient, matrix, translate);
} }
sk_sp<SkShadowVertices> add(const SkPath& devPath, const AmbientVerticesFactory& ambient, sk_sp<SkVertices> add(const SkPath& devPath, const AmbientVerticesFactory& ambient,
const SkMatrix& matrix) { const SkMatrix& matrix) {
return fAmbientSet.add(devPath, ambient, matrix); return fAmbientSet.add(devPath, ambient, matrix);
} }
sk_sp<SkShadowVertices> find(const SpotVerticesFactory& spot, const SkMatrix& matrix, sk_sp<SkVertices> find(const SpotVerticesFactory& spot, const SkMatrix& matrix,
SkVector* translate) const { SkVector* translate) const {
return fSpotSet.find(spot, matrix, translate); return fSpotSet.find(spot, matrix, translate);
} }
sk_sp<SkShadowVertices> add(const SkPath& devPath, const SpotVerticesFactory& spot, sk_sp<SkVertices> add(const SkPath& devPath, const SpotVerticesFactory& spot,
const SkMatrix& matrix) { const SkMatrix& matrix) {
return fSpotSet.add(devPath, spot, matrix); return fSpotSet.add(devPath, spot, matrix);
} }
@ -191,8 +192,8 @@ private:
public: public:
size_t size() const { return fSize; } size_t size() const { return fSize; }
sk_sp<SkShadowVertices> find(const FACTORY& factory, const SkMatrix& matrix, sk_sp<SkVertices> find(const FACTORY& factory, const SkMatrix& matrix,
SkVector* translate) const { SkVector* translate) const {
for (int i = 0; i < MAX_ENTRIES; ++i) { for (int i = 0; i < MAX_ENTRIES; ++i) {
if (fEntries[i].fFactory.isCompatible(factory, translate)) { if (fEntries[i].fFactory.isCompatible(factory, translate)) {
const SkMatrix& m = fEntries[i].fMatrix; const SkMatrix& m = fEntries[i].fMatrix;
@ -214,9 +215,8 @@ private:
return nullptr; return nullptr;
} }
sk_sp<SkShadowVertices> add(const SkPath& devPath, const FACTORY& factory, sk_sp<SkVertices> add(const SkPath& path, const FACTORY& factory, const SkMatrix& matrix) {
const SkMatrix& matrix) { sk_sp<SkVertices> vertices = factory.makeVertices(path, matrix);
sk_sp<SkShadowVertices> vertices = factory.makeVertices(devPath, matrix);
if (!vertices) { if (!vertices) {
return nullptr; return nullptr;
} }
@ -237,7 +237,7 @@ private:
private: private:
struct Entry { struct Entry {
FACTORY fFactory; FACTORY fFactory;
sk_sp<SkShadowVertices> fVertices; sk_sp<SkVertices> fVertices;
SkMatrix fMatrix; SkMatrix fMatrix;
}; };
Entry fEntries[MAX_ENTRIES]; Entry fEntries[MAX_ENTRIES];
@ -277,8 +277,8 @@ public:
sk_sp<CachedTessellations> refTessellations() const { return fTessellations; } sk_sp<CachedTessellations> refTessellations() const { return fTessellations; }
template <typename FACTORY> template <typename FACTORY>
sk_sp<SkShadowVertices> find(const FACTORY& factory, const SkMatrix& matrix, sk_sp<SkVertices> find(const FACTORY& factory, const SkMatrix& matrix,
SkVector* translate) const { SkVector* translate) const {
return fTessellations->find(factory, matrix, translate); return fTessellations->find(factory, matrix, translate);
} }
@ -300,7 +300,7 @@ struct FindContext {
const SkMatrix* const fViewMatrix; const SkMatrix* const fViewMatrix;
// If this is valid after Find is called then we found the vertices and they should be drawn // If this is valid after Find is called then we found the vertices and they should be drawn
// with fTranslate applied. // with fTranslate applied.
sk_sp<SkShadowVertices> fVertices; sk_sp<SkVertices> fVertices;
SkVector fTranslate = {0, 0}; SkVector fTranslate = {0, 0};
// If this is valid after Find then the caller should add the vertices to the tessellation set // If this is valid after Find then the caller should add the vertices to the tessellation set
@ -385,7 +385,7 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
SkResourceCache::Find(*key, FindVisitor<FACTORY>, &context); SkResourceCache::Find(*key, FindVisitor<FACTORY>, &context);
} }
sk_sp<SkShadowVertices> vertices; sk_sp<SkVertices> vertices;
const SkVector* translate; const SkVector* translate;
static constexpr SkVector kZeroTranslate = {0, 0}; static constexpr SkVector kZeroTranslate = {0, 0};
bool foundInCache = SkToBool(context.fVertices); bool foundInCache = SkToBool(context.fVertices);
@ -426,9 +426,7 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
canvas->save(); canvas->save();
canvas->translate(translate->fX, translate->fY); canvas->translate(translate->fX, translate->fY);
} }
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, vertices->vertexCount(), canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
vertices->positions(), nullptr, vertices->colors(), vertices->indices(),
vertices->indexCount(), paint);
if (translate->fX || translate->fY) { if (translate->fX || translate->fY) {
canvas->restore(); canvas->restore();
} }

View File

@ -9,6 +9,7 @@
#include "SkPath.h" #include "SkPath.h"
#include "SkShadowTessellator.h" #include "SkShadowTessellator.h"
#include "SkShadowUtils.h" #include "SkShadowUtils.h"
#include "SkVertices.h"
#include "Test.h" #include "Test.h"
void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm, void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm,
@ -16,27 +17,28 @@ void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const S
static constexpr SkScalar kRadius = 2.f; static constexpr SkScalar kRadius = 2.f;
static constexpr SkColor kUmbraColor = 0xFFFFFFFF; static constexpr SkColor kUmbraColor = 0xFFFFFFFF;
static constexpr SkColor kPenumbraColor = 0x20202020; static constexpr SkColor kPenumbraColor = 0x20202020;
auto verts = SkShadowVertices::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor, auto verts =
true); SkShadowTessellator::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor, true);
if (expectSuccess != SkToBool(verts)) { if (expectSuccess != SkToBool(verts)) {
ERRORF(reporter, "Expected shadow tessellation to % but it did not.", ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
expectSuccess ? "succeed" : "fail"); expectSuccess ? "succeed" : "fail");
} }
verts = SkShadowVertices::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor, false); verts = SkShadowTessellator::MakeAmbient(path, ctm, kRadius, kUmbraColor, kPenumbraColor,
false);
if (expectSuccess != SkToBool(verts)) { if (expectSuccess != SkToBool(verts)) {
ERRORF(reporter, "Expected shadow tessellation to % but it did not.", ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
expectSuccess ? "succeed" : "fail"); expectSuccess ? "succeed" : "fail");
} }
verts = SkShadowVertices::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor, verts = SkShadowTessellator::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor,
kPenumbraColor, false); kPenumbraColor, false);
if (expectSuccess != SkToBool(verts)) { if (expectSuccess != SkToBool(verts)) {
ERRORF(reporter, "Expected shadow tessellation to % but it did not.", ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
expectSuccess ? "succeed" : "fail"); expectSuccess ? "succeed" : "fail");
} }
verts = SkShadowVertices::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor, verts = SkShadowTessellator::MakeSpot(path, ctm, 1.5f, {0, 0}, kRadius, kUmbraColor,
kPenumbraColor, true); kPenumbraColor, true);
if (expectSuccess != SkToBool(verts)) { if (expectSuccess != SkToBool(verts)) {
ERRORF(reporter, "Expected shadow tessellation to % but it did not.", ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
expectSuccess ? "succeed" : "fail"); expectSuccess ? "succeed" : "fail");
} }
} }