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:
parent
1f8be68917
commit
aff27a23ad
@ -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; }
|
|
||||||
|
|
||||||
// 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() {
|
|
||||||
return UniqueArray<SkPoint>(static_cast<const SkPoint*>(fPositions.release()));
|
|
||||||
}
|
}
|
||||||
UniqueArray<SkColor> releaseColors() {
|
int vCount = this->vertexCount();
|
||||||
return UniqueArray<SkColor>(static_cast<const SkColor*>(fColors.release()));
|
int iCount = this->indexCount();
|
||||||
}
|
// We copy here for two reasons: 1) To tighten up our arrays and 2) to get into memory
|
||||||
UniqueArray<uint16_t> releaseIndices() {
|
// allocated by new[] rather than malloc.
|
||||||
return UniqueArray<uint16_t>(static_cast<const uint16_t*>(fIndices.release()));
|
// TODO: If we know we're not caching then we should avoid this.
|
||||||
|
SkPoint* positions = new SkPoint[vCount];
|
||||||
|
SkColor* colors = new SkColor[vCount];
|
||||||
|
uint16_t* indices = new uint16_t[iCount];
|
||||||
|
memcpy(positions, fPositions.begin(), sizeof(SkPoint) * vCount);
|
||||||
|
memcpy(colors, fColors.begin(), sizeof(SkColor) * vCount);
|
||||||
|
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,7 +122,7 @@ 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)
|
||||||
@ -122,7 +132,6 @@ SkShadowTessellator::SkShadowTessellator(SkScalar radius, SkColor umbraColor,
|
|||||||
, 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,7 +229,7 @@ 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;
|
||||||
@ -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));
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
static sk_sp<SkShadowVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm,
|
sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm, SkScalar radius,
|
||||||
SkScalar radius, SkColor umbraColor,
|
SkColor umbraColor, SkColor penumbraColor, bool transparent);
|
||||||
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
|
||||||
|
@ -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,8 +99,8 @@ 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,9 +149,9 @@ 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,22 +166,22 @@ 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,7 +192,7 @@ 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)) {
|
||||||
@ -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,7 +277,7 @@ 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();
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user