aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-05-17 08:53:36 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-17 13:40:42 +0000
commit4204da25aa4c6e0b321314aa32fd9affb4865563 (patch)
tree87ef273357fda474b96cc672d9247b216159b4fb
parent63e7973d1f01bd03216659b9d2267f83a752c8fb (diff)
move shadows to device virtual
This CL keeps the impl for each device backend in the utils file for simplicity (shared helpers). Future CLs may move into their respective impl as they become more specialized. Bug: skia: Change-Id: I97ce6cdcc5106ebf4c84778f943cc32d0b7613c1 Reviewed-on: https://skia-review.googlesource.com/15893 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Mike Reed <reed@google.com>
-rw-r--r--include/core/SkCanvas.h4
-rw-r--r--include/utils/SkNWayCanvas.h1
-rw-r--r--src/core/SkCanvas.cpp15
-rw-r--r--src/core/SkColorSpaceXformCanvas.cpp7
-rw-r--r--src/core/SkDevice.h3
-rw-r--r--src/core/SkDrawShadowRec.h23
-rw-r--r--src/core/SkLiteDL.cpp17
-rw-r--r--src/core/SkLiteDL.h1
-rw-r--r--src/core/SkLiteRecorder.cpp3
-rw-r--r--src/core/SkLiteRecorder.h1
-rw-r--r--src/core/SkRecordDraw.cpp5
-rw-r--r--src/core/SkRecorder.cpp4
-rw-r--r--src/core/SkRecorder.h1
-rw-r--r--src/core/SkRecords.h5
-rw-r--r--src/gpu/SkGpuDevice.h1
-rw-r--r--src/utils/SkNWayCanvas.cpp7
-rw-r--r--src/utils/SkShadowUtils.cpp181
17 files changed, 200 insertions, 79 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index e03b4f3daf..8ab281814e 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -24,6 +24,7 @@ class SkData;
class SkDraw;
class SkDrawable;
class SkDrawFilter;
+struct SkDrawShadowRec;
class SkImage;
class SkImageFilter;
class SkLights;
@@ -1237,6 +1238,8 @@ public:
*/
void temporary_internal_getRgnClip(SkRegion* region);
+ void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
+
protected:
// default impl defers to getDevice()->newSurface(info)
virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
@@ -1331,6 +1334,7 @@ protected:
const SkPaint* paint);
virtual void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint);
+ virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
enum ClipEdgeStyle {
kHard_ClipEdgeStyle,
diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h
index ba0745e420..7701d50e26 100644
--- a/include/utils/SkNWayCanvas.h
+++ b/include/utils/SkNWayCanvas.h
@@ -71,6 +71,7 @@ protected:
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 10e2181aff..afc1203e6b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1909,6 +1909,21 @@ void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
}
}
+void SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
+ this->onDrawShadowRec(path, rec);
+}
+
+void SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ SkPaint paint;
+ const SkRect& pathBounds = path.getBounds();
+
+ LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
+ while (iter.next()) {
+ iter.fDevice->drawShadow(path, rec);
+ }
+ LOOPER_END
+}
+
//////////////////////////////////////////////////////////////////////////////
// These are the virtual drawing methods
//////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp
index 65297a1801..530552862d 100644
--- a/src/core/SkColorSpaceXformCanvas.cpp
+++ b/src/core/SkColorSpaceXformCanvas.cpp
@@ -8,6 +8,7 @@
#include "SkColorFilter.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkColorSpaceXformer.h"
+#include "SkDrawShadowRec.h"
#include "SkGradientShader.h"
#include "SkImageFilter.h"
#include "SkImagePriv.h"
@@ -217,7 +218,11 @@ public:
fTarget->drawImageLattice(fXformer->apply(bitmap).get(), lattice, dst,
MaybePaint(paint, fXformer.get()));
}
-
+ void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override {
+ SkDrawShadowRec newRec(rec);
+ newRec.fColor = fXformer->apply(rec.fColor);
+ fTarget->private_draw_shadow_rec(path, newRec);
+ }
void onDrawPicture(const SkPicture* pic,
const SkMatrix* matrix,
const SkPaint* paint) override {
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index 17ccfdd198..17ea6f71f7 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -15,6 +15,7 @@
class SkBitmap;
class SkDrawFilter;
+struct SkDrawShadowRec;
class SkImageFilterCache;
struct SkIRect;
class SkMatrix;
@@ -234,6 +235,8 @@ protected:
const SkScalar pos[], int scalarsPerPos,
const SkPoint& offset, const SkPaint& paint) = 0;
virtual void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) = 0;
+ virtual void drawShadow(const SkPath&, const SkDrawShadowRec&);
+
// default implementation unrolls the blob runs.
virtual void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
const SkPaint& paint, SkDrawFilter* drawFilter);
diff --git a/src/core/SkDrawShadowRec.h b/src/core/SkDrawShadowRec.h
new file mode 100644
index 0000000000..19199c0cad
--- /dev/null
+++ b/src/core/SkDrawShadowRec.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDrawShadowRec_DEFINED
+#define SkDrawShadowRec_DEFINED
+
+#include "SkPath.h"
+
+struct SkDrawShadowRec {
+ SkPoint3 fZPlaneParams;
+ SkPoint3 fLightPos;
+ SkScalar fLightRadius;
+ float fAmbientAlpha;
+ float fSpotAlpha;
+ SkColor fColor;
+ uint32_t fFlags;
+};
+
+#endif
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index b3149a7d42..f1101b1be2 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -8,6 +8,7 @@
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDrawFilter.h"
+#include "SkDrawShadowRec.h"
#include "SkImage.h"
#include "SkImageFilter.h"
#include "SkLiteDL.h"
@@ -55,7 +56,7 @@ namespace {
M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \
M(DrawText) M(DrawPosText) M(DrawPosTextH) \
M(DrawTextOnPath) M(DrawTextRSXform) M(DrawTextBlob) \
- M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas)
+ M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas) M(DrawShadowRec)
#define M(T) T,
enum class Type : uint8_t { TYPES(M) };
@@ -477,6 +478,17 @@ namespace {
maybe_unset(cull), &paint);
}
};
+ struct DrawShadowRec final : Op {
+ static const auto kType = Type::DrawShadowRec;
+ DrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec)
+ : fPath(path), fRec(rec)
+ {}
+ SkPath fPath;
+ SkDrawShadowRec fRec;
+ void draw(SkCanvas* c, const SkMatrix&) const {
+ c->private_draw_shadow_rec(fPath, fRec);
+ }
+ };
}
template <typename T, typename... Args>
@@ -662,6 +674,9 @@ void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const S
texs, count,
colors, colors ? count : 0);
}
+void SkLiteDL::drawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ this->push<DrawShadowRec>(0, path, rec);
+}
typedef void(*draw_fn)(const void*, SkCanvas*, const SkMatrix&);
typedef void(*void_fn)(const void*);
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index c5df350957..31ef38e6bf 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -77,6 +77,7 @@ public:
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&);
void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
SkBlendMode, const SkRect*, const SkPaint*);
+ void drawShadowRec(const SkPath&, const SkDrawShadowRec&);
private:
template <typename T, typename... Args>
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index 5affb3d4ab..dbee48e1bd 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -194,3 +194,6 @@ void SkLiteRecorder::onDrawAtlas(const SkImage* atlas,
const SkPaint* paint) {
fDL->drawAtlas(atlas, xforms, texs, colors, count, bmode, cull, paint);
}
+void SkLiteRecorder::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ fDL->drawShadowRec(path, rec);
+}
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index 3c156af721..4d49eb5336 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -77,6 +77,7 @@ public:
void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
int, SkBlendMode, const SkRect*, const SkPaint*) override;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
private:
typedef SkNoDrawCanvas INHERITED;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index e668cc874c..953e874854 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -125,6 +125,7 @@ DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.
DRAW(DrawAtlas, drawAtlas(r.atlas.get(),
r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
DRAW(DrawVertices, drawVertices(r.vertices, r.bmode, r.paint));
+DRAW(DrawShadowRec, private_draw_shadow_rec(r.path, r.rec));
DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get()));
#undef DRAW
@@ -455,6 +456,10 @@ private:
}
}
+ Bounds bounds(const DrawShadowRec& op) const {
+ return this->adjustAndMap(op.path.getBounds(), nullptr);
+ }
+
Bounds bounds(const DrawPicture& op) const {
SkRect dst = op.picture->cullRect();
op.matrix.mapRect(&dst);
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 64d613df96..1eeef532e6 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -338,6 +338,10 @@ void SkRecorder::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], cons
this->copy(cull));
}
+void SkRecorder::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ APPEND(DrawShadowRec, path, rec);
+}
+
void SkRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
APPEND(DrawAnnotation, rect, SkString(key), sk_ref_sp(value));
}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 5344934665..04e75edd26 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -121,6 +121,7 @@ public:
void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
int count, SkBlendMode, const SkRect* cull, const SkPaint*) override;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
void onClipRect(const SkRect& rect, SkClipOp, ClipEdgeStyle) override;
void onClipRRect(const SkRRect& rrect, SkClipOp, ClipEdgeStyle) override;
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 6af4aad3f5..a63ef1c6a5 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -11,6 +11,7 @@
#include "SkData.h"
#include "SkCanvas.h"
#include "SkDrawable.h"
+#include "SkDrawShadowRec.h"
#include "SkImage.h"
#include "SkImageFilter.h"
#include "SkMatrix.h"
@@ -80,6 +81,7 @@ namespace SkRecords {
M(DrawTextBlob) \
M(DrawAtlas) \
M(DrawVertices) \
+ M(DrawShadowRec) \
M(DrawAnnotation)
// Defines SkRecords::Type, an enum of all record types.
@@ -345,6 +347,9 @@ RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag,
SkPaint paint;
sk_sp<SkVertices> vertices;
SkBlendMode bmode);
+RECORD(DrawShadowRec, kDraw_Tag,
+ SkPath path;
+ SkDrawShadowRec rec);
RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548
SkRect rect;
SkString key;
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 340f39a072..0b60a96516 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -92,6 +92,7 @@ public:
void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
const SkPaint& paint, SkDrawFilter* drawFilter) override;
void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override;
+ void drawShadow(const SkPath&, const SkDrawShadowRec&) override;
void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
const SkColor[], int count, SkBlendMode, const SkPaint&) override;
void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override;
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index 4f6ad46d85..208f3b4719 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -299,6 +299,13 @@ void SkNWayCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4]
}
}
+void SkNWayCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->private_draw_shadow_rec(path, rec);
+ }
+}
+
void SkNWayCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
Iter iter(fList);
while (iter.next()) {
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 806c98e68b..f0ab230acc 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -9,6 +9,8 @@
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
+#include "SkDevice.h"
+#include "SkDrawShadowRec.h"
#include "SkPath.h"
#include "SkPM4f.h"
#include "SkRandom.h"
@@ -20,9 +22,9 @@
#if SK_SUPPORT_GPU
#include "GrShape.h"
#include "effects/GrBlurredEdgeFragmentProcessor.h"
-#endif
#include "../../src/effects/shadows/SkAmbientShadowMaskFilter.h"
#include "../../src/effects/shadows/SkSpotShadowMaskFilter.h"
+#endif
/**
* Gaussian color filter -- produces a Gaussian ramp based on the color's B value,
@@ -444,7 +446,9 @@ static void* kNamespace;
* they are first found in SkResourceCache.
*/
template <typename FACTORY>
-void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, SkColor color) {
+ void draw_shadow(const FACTORY& factory,
+ std::function<void(const SkVertices*, SkBlendMode, const SkPaint&,
+ SkScalar tx, SkScalar ty)> drawProc, ShadowedPath& path, SkColor color) {
FindContext<FACTORY> context(&path.viewMatrix(), &factory);
SkResourceCache::Key* key = nullptr;
@@ -496,82 +500,83 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
SkColorFilter::MakeModeFilter(color, SkBlendMode::kModulate),
SkGaussianColorFilter::Make()));
- if (translate->fX || translate->fY) {
- canvas->save();
- canvas->translate(translate->fX, translate->fY);
- }
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
- if (translate->fX || translate->fY) {
- canvas->restore();
- }
+
+ drawProc(vertices.get(), SkBlendMode::kModulate, paint, translate->fX, translate->fY);
}
}
-static bool draw_analytic_shadows(SkCanvas* canvas, const SkPath& path, SkScalar occluderZ,
- const SkPoint3& devLightPos, SkScalar lightRadius,
- SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
- uint32_t flags) {
- // only supported in GPU code
- if (!canvas->getGrContext()) {
- return false;
- }
+static bool tilted(const SkPoint3& zPlaneParams) {
+ return !SkScalarNearlyZero(zPlaneParams.fX) || !SkScalarNearlyZero(zPlaneParams.fY);
+}
+
+static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
+ SkPoint3 result;
+ m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
+ result.fZ = pt.fZ;
+ return result;
+}
+
+#if SK_SUPPORT_GPU
+#include "SkGpuDevice.h"
+void SkGpuDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
+ // check z plane
+ bool tiltZPlane = tilted(rec.fZPlaneParams);
+ bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
+
+ const SkMatrix& ctm = this->ctm();
- SkRect rect;
- SkRRect rrect;
- const SkMatrix& ctm = canvas->getTotalMatrix();
- if (ctm.rectStaysRect() && ctm.isSimilarity()) {
+ if (!tiltZPlane && !skipAnalytic && ctm.rectStaysRect() && ctm.isSimilarity()) {
+ SkPoint3 devLightPos = map(ctm, rec.fLightPos);
+
+ const SkScalar occluderZ = rec.fZPlaneParams.fZ;
+ SkPaint ambientPaint, spotPaint;
+ ambientPaint.setColor(rec.fColor);
+ spotPaint.setColor(rec.fColor);
+ if (rec.fAmbientAlpha > 0) {
+ ambientPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ, rec.fAmbientAlpha,
+ rec.fFlags));
+ }
+ if (rec.fSpotAlpha > 0) {
+ spotPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
+ rec.fLightRadius, rec.fSpotAlpha,
+ rec.fFlags));
+ }
+
+ SkRect rect;
+ SkRRect rrect;
if (path.isRect(&rect)) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawRect(rect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawRect(rect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawRect(rect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawRect(rect, spotPaint);
}
- return true;
+ return;
} else if (path.isRRect(&rrect) && rrect.isSimpleCircular() &&
rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawRRect(rrect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawRRect(rrect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawRRect(rrect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawRRect(rrect, spotPaint);
}
- return true;
+ return;
} else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
rect.width() > SK_ScalarNearlyZero) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawOval(rect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawOval(rect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawOval(rect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawOval(rect, spotPaint);
}
- return true;
+ return;
}
}
- return false;
+ // failed to find an accelerated case
+ this->INHERITED::drawShadow(path, rec);
}
+#endif
static SkColor compute_render_color(SkColor color, float alpha) {
return SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color),
@@ -583,26 +588,47 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
const SkPoint3& devLightPos, SkScalar lightRadius,
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
uint32_t flags) {
- // check z plane
- bool tiltZPlane = !SkScalarNearlyZero(zPlaneParams.fX) || !SkScalarNearlyZero(zPlaneParams.fY);
-
- // try fast paths
- bool skipAnalytic = SkToBool(flags & SkShadowFlags::kGeometricOnly_ShadowFlag) || tiltZPlane;
- if (!skipAnalytic && draw_analytic_shadows(canvas, path, zPlaneParams.fZ, devLightPos,
- lightRadius, ambientAlpha, spotAlpha, color,
- flags)) {
+ SkMatrix inverse;
+ if (!canvas->getTotalMatrix().invert(&inverse)) {
return;
}
+ SkPoint pt = inverse.mapXY(devLightPos.fX, devLightPos.fY);
+
+ SkDrawShadowRec rec;
+ rec.fZPlaneParams = zPlaneParams;
+ rec.fLightPos = { pt.fX, pt.fY, devLightPos.fZ };
+ rec.fLightRadius = lightRadius;
+ rec.fAmbientAlpha = SkScalarToFloat(ambientAlpha);
+ rec.fSpotAlpha = SkScalarToFloat(spotAlpha);
+ rec.fColor = color;
+ rec.fFlags = flags;
+
+ canvas->private_draw_shadow_rec(path, rec);
+}
+
+void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
+ auto drawVertsProc = [this](const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint,
+ SkScalar tx, SkScalar ty) {
+ SkAutoDeviceCTMRestore adr(this, SkMatrix::Concat(this->ctm(),
+ SkMatrix::MakeTrans(tx, ty)));
+ this->drawVertices(vertices, mode, paint);
+ };
- SkAutoCanvasRestore acr(canvas, true);
- SkMatrix viewMatrix = canvas->getTotalMatrix();
- canvas->resetMatrix();
+ SkMatrix viewMatrix = this->ctm();
+ SkAutoDeviceCTMRestore adr(this, SkMatrix::I());
ShadowedPath shadowedPath(&path, &viewMatrix);
- bool transparent = SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
+ bool tiltZPlane = tilted(rec.fZPlaneParams);
+ bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
bool uncached = tiltZPlane || path.isVolatile();
+ SkColor color = rec.fColor;
+ SkPoint3 zPlaneParams = rec.fZPlaneParams;
+ SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
+ float lightRadius = rec.fLightRadius;
+
+ float ambientAlpha = rec.fAmbientAlpha;
if (ambientAlpha > 0) {
ambientAlpha = SkTMin(ambientAlpha, 1.f);
if (uncached) {
@@ -614,19 +640,20 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
// Run the vertex color through a GaussianColorFilter and then modulate the grayscale
// result of that against our 'color' param.
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
- SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
- SkGaussianColorFilter::Make()));
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
+ SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
+ SkGaussianColorFilter::Make()));
+ this->drawVertices(vertices.get(), SkBlendMode::kModulate, paint);
} else {
AmbientVerticesFactory factory;
factory.fOccluderHeight = zPlaneParams.fZ;
factory.fTransparent = transparent;
SkColor renderColor = compute_render_color(color, ambientAlpha);
- draw_shadow(factory, canvas, shadowedPath, renderColor);
+ draw_shadow(factory, drawVertsProc, shadowedPath, renderColor);
}
}
+ float spotAlpha = rec.fSpotAlpha;
if (spotAlpha > 0) {
spotAlpha = SkTMin(spotAlpha, 1.f);
if (uncached) {
@@ -641,7 +668,7 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
SkGaussianColorFilter::Make()));
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
+ this->drawVertices(vertices.get(), SkBlendMode::kModulate, paint);
} else {
SpotVerticesFactory factory;
SkScalar occluderHeight = zPlaneParams.fZ;
@@ -690,7 +717,7 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
}
#endif
SkColor renderColor = compute_render_color(color, spotAlpha);
- draw_shadow(factory, canvas, shadowedPath, renderColor);
+ draw_shadow(factory, drawVertsProc, shadowedPath, renderColor);
}
}
}