aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/shadowutils.cpp38
-rw-r--r--gm/tonalshadows.cpp85
-rw-r--r--gn/gm.gni1
-rw-r--r--include/utils/SkShadowUtils.h34
-rw-r--r--samplecode/SampleAndroidShadows.cpp41
-rwxr-xr-xsamplecode/SampleShadowUtils.cpp1
-rw-r--r--src/gpu/GrRenderTargetContext.cpp2
-rw-r--r--src/utils/SkShadowUtils.cpp2
8 files changed, 168 insertions, 36 deletions
diff --git a/gm/shadowutils.cpp b/gm/shadowutils.cpp
index 5cbed5c81f..d9cdfd5768 100644
--- a/gm/shadowutils.cpp
+++ b/gm/shadowutils.cpp
@@ -15,7 +15,6 @@ void draw_shadow(SkCanvas* canvas, const SkPath& path, int height, SkColor color
SkScalar lightR, bool isAmbient, uint32_t flags) {
SkScalar ambientAlpha = isAmbient ? .5f : 0.f;
SkScalar spotAlpha = isAmbient ? 0.f : .5f;
- flags |= SkShadowFlags::kDisableTonalColor_ShadowFlag;
SkShadowUtils::DrawShadow(canvas, path, height, lightPos, lightR, ambientAlpha, spotAlpha,
color, flags);
}
@@ -23,7 +22,13 @@ void draw_shadow(SkCanvas* canvas, const SkPath& path, int height, SkColor color
static constexpr int kW = 800;
static constexpr int kH = 800;
-void draw_paths(SkCanvas* canvas, bool hideOccluders) {
+enum ShadowMode {
+ kDebugColorNoOccluders,
+ kDebugColorOccluders,
+ kGrayscale
+};
+
+void draw_paths(SkCanvas* canvas, ShadowMode mode) {
SkTArray<SkPath> paths;
paths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
SkRRect oddRRect;
@@ -52,7 +57,7 @@ void draw_paths(SkCanvas* canvas, bool hideOccluders) {
m->setRotate(33.f, 25.f, 25.f);
m->postScale(1.2f, 0.8f, 25.f, 25.f);
for (auto& m : matrices) {
- for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
+ for (int flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
for (const auto& path : paths) {
SkRect postMBounds = path.getBounds();
m.mapRect(&postMBounds);
@@ -68,13 +73,22 @@ void draw_paths(SkCanvas* canvas, bool hideOccluders) {
canvas->save();
canvas->concat(m);
- draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR, true, flags);
- draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR, false, flags);
- // Draw the path outline in green on top of the ambient and spot shadows.
+ if (kDebugColorNoOccluders == mode || kDebugColorOccluders == mode) {
+ flags |= SkShadowFlags::kDisableTonalColor_ShadowFlag;
+ draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR,
+ true, flags);
+ draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR,
+ false, flags);
+ } else if (kGrayscale == mode) {
+ SkShadowUtils::DrawShadow(canvas, path, kHeight, lightPos, kLightR,
+ 0.1f, 0.25f, SK_ColorBLACK, flags);
+ }
+
SkPaint paint;
paint.setAntiAlias(true);
- if (hideOccluders) {
+ if (kDebugColorNoOccluders == mode) {
+ // Draw the path outline in green on top of the ambient and spot shadows.
if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
paint.setColor(SK_ColorCYAN);
} else {
@@ -83,7 +97,7 @@ void draw_paths(SkCanvas* canvas, bool hideOccluders) {
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(0);
} else {
- paint.setColor(SK_ColorLTGRAY);
+ paint.setColor(kDebugColorOccluders == mode ? SK_ColorLTGRAY : SK_ColorWHITE);
if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
paint.setAlpha(128);
}
@@ -112,9 +126,13 @@ void draw_paths(SkCanvas* canvas, bool hideOccluders) {
}
DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
- draw_paths(canvas, true);
+ draw_paths(canvas, kDebugColorNoOccluders);
}
DEF_SIMPLE_GM(shadow_utils_occl, canvas, kW, kH) {
- draw_paths(canvas, false);
+ draw_paths(canvas, kDebugColorOccluders);
+}
+
+DEF_SIMPLE_GM(shadow_utils_gray, canvas, kW, kH) {
+ draw_paths(canvas, kGrayscale);
}
diff --git a/gm/tonalshadows.cpp b/gm/tonalshadows.cpp
new file mode 100644
index 0000000000..83c1b748e4
--- /dev/null
+++ b/gm/tonalshadows.cpp
@@ -0,0 +1,85 @@
+/*
+* 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 "gm.h"
+#include "SkCanvas.h"
+#include "SkPath.h"
+#include "SkShadowUtils.h"
+
+enum BackgroundMode {
+ kLightBackground,
+ kDarkBackground
+};
+
+static constexpr int kW = 1225;
+static constexpr int kH = 550;
+
+void draw_content(SkCanvas* canvas, BackgroundMode mode) {
+ const SkScalar kLightWidth = 600;
+ const SkScalar kAmbientAlpha = 0.03f;
+ const SkScalar kSpotAlpha = 0.25f;
+
+ const SkColor kColors[30] = {
+ // purples
+ 0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5,
+ 0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9,
+ // oranges
+ 0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000,
+ 0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC,
+ // teals
+ 0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2,
+ 0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0
+ };
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ if (mode == kDarkBackground) {
+ canvas->drawColor(0xFF111111);
+ } else {
+ canvas->drawColor(0xFFEAEAEA);
+ }
+
+ SkPath path;
+ path.addRect(SkRect::MakeXYWH(-50, -50, 100, 100));
+
+ SkPoint3 lightPos = { 75, -400, 600 };
+ SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 16);
+ SkScalar yPos = 75;
+
+ for (int row = 0; row < 3; ++row) {
+ lightPos.fX = 75;
+ SkScalar xPos = 75;
+ for (int col = 0; col < 10; ++col) {
+ paint.setColor(kColors[10 * row + col]);
+
+ canvas->save();
+ canvas->translate(xPos, yPos);
+ SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
+ lightPos, kLightWidth,
+ kAmbientAlpha, kSpotAlpha, paint.getColor(), 0);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+
+ lightPos.fX += 120;
+ xPos += 120;
+ }
+
+ lightPos.fY += 200;
+ yPos += 200;
+ }
+}
+
+DEF_SIMPLE_GM(tonalshadows_light, canvas, kW, kH) {
+ draw_content(canvas, kLightBackground);
+}
+
+DEF_SIMPLE_GM(tonalshadows_dark, canvas, kW, kH) {
+ draw_content(canvas, kDarkBackground);
+}
+
+
+
diff --git a/gn/gm.gni b/gn/gm.gni
index d24b8bbb27..85fc6e13a3 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -317,6 +317,7 @@ gm_sources = [
"$_gm/tilemodes.cpp",
"$_gm/tilemodes_scaled.cpp",
"$_gm/tinybitmap.cpp",
+ "$_gm/tonalshadows.cpp",
"$_gm/transparency.cpp",
"$_gm/typeface.cpp",
"$_gm/variedtext.cpp",
diff --git a/include/utils/SkShadowUtils.h b/include/utils/SkShadowUtils.h
index c362488f15..9550a925b9 100644
--- a/include/utils/SkShadowUtils.h
+++ b/include/utils/SkShadowUtils.h
@@ -84,9 +84,9 @@ public:
* set the alpha to (S_a + C_a - S_a*C_a).
*
* @param r Red value of color
- * @param g Red value of color
- * @param b Red value of color
- * @param a Red value of color
+ * @param g Green value of color
+ * @param b Blue value of color
+ * @param a Alpha value of color
* @param colorScale Factor to scale color values by
* @param tonalAlpha Value to set alpha to
*/
@@ -96,14 +96,28 @@ public:
SkScalar min = SkTMin(SkTMin(r, g), b);
SkScalar luminance = 0.5f*(max + min);
- // We get best results with a luminance between 0.3 and 0.5, with smoothstep applied
- SkScalar adjustedLuminance = (0.6f - 0.4f*luminance)*luminance*luminance + 0.3f;
- // Similarly, we need to tone down the given greyscale alpha depending on how
- // much color we're applying.
- a -= (0.5f*adjustedLuminance - 0.15f);
+ // We compute a color alpha value based on the luminance of the color, scaled by an
+ // adjusted alpha value. We want the following properties to match the UX examples
+ // (assuming a = 0.25) and to ensure that we have reasonable results when the color
+ // is black and/or the alpha is 0:
+ // f(0, a) = 0
+ // f(luminance, 0) = 0
+ // f(1, 0.25) = .5
+ // f(0.5, 0.25) = .4
+ // f(1, 1) = 1
+ // The following functions match this as closely as possible.
+ SkScalar alphaAdjust = (2.6f + (-2.66667f + 1.06667f*a)*a)*a;
+ SkScalar colorAlpha = (3.544762f + (-4.891428f + 2.3466f*luminance)*luminance)*luminance;
+ colorAlpha = SkTPin(alphaAdjust*colorAlpha, 0.0f, 1.0f);
- *colorScale = adjustedLuminance*(SK_Scalar1 - a);
- *tonalAlpha = *colorScale + a;
+ // Similarly, we set the greyscale alpha based on luminance and alpha so that
+ // f(0, a) = a
+ // f(luminance, 0) = 0
+ // f(1, 0.25) = 0.15
+ SkScalar greyscaleAlpha = SkTPin(a*(1 - 0.4f*luminance), 0.0f, 1.0f);
+
+ *colorScale = colorAlpha*(SK_Scalar1 - greyscaleAlpha);
+ *tonalAlpha = *colorScale + greyscaleAlpha;
}
};
diff --git a/samplecode/SampleAndroidShadows.cpp b/samplecode/SampleAndroidShadows.cpp
index 3db994adda..2621cec073 100644
--- a/samplecode/SampleAndroidShadows.cpp
+++ b/samplecode/SampleAndroidShadows.cpp
@@ -35,23 +35,27 @@ class ShadowsView : public SampleView {
SkScalar fZDelta;
SkScalar fAnimTranslate;
SkScalar fAnimAngle;
+ SkScalar fAnimAlpha;
bool fShowAmbient;
bool fShowSpot;
bool fUseAlt;
bool fShowObject;
bool fIgnoreShadowAlpha;
+ bool fDoAlphaAnimation;
public:
ShadowsView()
: fZDelta(0)
, fAnimTranslate(0)
, fAnimAngle(0)
+ , fAnimAlpha(1)
, fShowAmbient(true)
, fShowSpot(true)
, fUseAlt(false)
, fShowObject(true)
- , fIgnoreShadowAlpha(false) {}
+ , fIgnoreShadowAlpha(false)
+ , fDoAlphaAnimation(false) {}
protected:
void onOnceBeforeDraw() override {
@@ -99,6 +103,13 @@ protected:
fShowObject = !fShowObject;
handled = true;
break;
+ case 'N':
+ fDoAlphaAnimation = !fDoAlphaAnimation;
+ if (!fDoAlphaAnimation) {
+ fAnimAlpha = 1;
+ }
+ handled = true;
+ break;
case '>':
fZDelta += 0.5f;
handled = true;
@@ -175,38 +186,38 @@ protected:
paint.setColor(SK_ColorWHITE);
canvas->translate(200, 90);
zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
- this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, kAmbientAlpha,
- lightPos, kLightWidth, kSpotAlpha);
+ this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
paint.setColor(SK_ColorRED);
canvas->translate(250, 0);
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
- this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha,
- lightPos, kLightWidth, kSpotAlpha);
+ this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
paint.setColor(SK_ColorBLUE);
canvas->translate(-250, 110);
zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta);
- this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, kAmbientAlpha,
- lightPos, kLightWidth, 0.5f);
+ this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*0.5f);
paint.setColor(SK_ColorGREEN);
canvas->translate(250, 0);
zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta);
- this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, kAmbientAlpha,
- lightPos, kLightWidth, kSpotAlpha);
+ this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
paint.setColor(SK_ColorYELLOW);
canvas->translate(-250, 110);
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
- this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, kAmbientAlpha,
- lightPos, kLightWidth, kSpotAlpha);
+ this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
paint.setColor(SK_ColorCYAN);
canvas->translate(250, 0);
zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
- this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint,
- kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
+ this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
+ lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
// circular reveal
SkPath tmpPath;
@@ -259,7 +270,9 @@ protected:
bool onAnimate(const SkAnimTimer& timer) override {
fAnimTranslate = timer.pingPong(30, 0, 200, -200);
fAnimAngle = timer.pingPong(15, 0, 0, 20);
-
+ if (fDoAlphaAnimation) {
+ fAnimAlpha = timer.pingPong(5, 0, 1, 0);
+ }
return true;
}
diff --git a/samplecode/SampleShadowUtils.cpp b/samplecode/SampleShadowUtils.cpp
index 7e6079156d..7d30a10d0b 100755
--- a/samplecode/SampleShadowUtils.cpp
+++ b/samplecode/SampleShadowUtils.cpp
@@ -121,6 +121,7 @@ protected:
if (!fShowSpot) {
spotAlpha = 0;
}
+ flags |= SkShadowFlags::kDisableTonalColor_ShadowFlag;
if (fUseAlt) {
flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
}
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 6f93a1c190..1c617c9410 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1141,7 +1141,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
SkScalar colorScale;
SkScalar tonalAlpha;
SkShadowUtils::ComputeTonalColorParams(color.fRGBA[0], color.fRGBA[1],
- color.fRGBA[2], rec.fSpotAlpha,
+ color.fRGBA[2], color.fRGBA[3]*rec.fSpotAlpha,
&colorScale, &tonalAlpha);
color.fRGBA[0] *= colorScale;
color.fRGBA[1] *= colorScale;
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 44010b7d01..85e9979d79 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -466,7 +466,7 @@ static SkColor compute_render_color(SkColor color, float alpha, bool useTonalCol
SkShadowUtils::ComputeTonalColorParams(color4f.fR,
color4f.fG,
color4f.fB,
- alpha,
+ color4f.fA*alpha,
&colorScale, &tonalAlpha);
// After pre-multiplying, we want the alpha to be scaled by tonalAlpha, and
// the color scaled by colorScale. This scale factor gives that.