skia2/samplecode/SampleShadowReference.cpp

201 lines
6.5 KiB
C++
Raw Normal View History

/*
* 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 "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRRect.h"
#include "include/utils/SkShadowUtils.h"
#include "samplecode/Sample.h"
#include "tools/Resources.h"
////////////////////////////////////////////////////////////////////////////
// Sample to compare the Material Design shadow reference to our results
class ShadowRefView : public Sample {
SkPath fRRectPath;
sk_sp<SkImage> fReferenceImage;
bool fShowAmbient;
bool fShowSpot;
bool fUseAlt;
bool fShowObject;
public:
ShadowRefView()
: fShowAmbient(true)
, fShowSpot(true)
, fUseAlt(false)
, fShowObject(true) {}
protected:
void onOnceBeforeDraw() override {
fRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-130, -128.5, 130, 128.5), 4, 4));
fReferenceImage = GetResourceAsImage("images/shadowreference.png");
}
SkString name() override { return SkString("ShadowReference"); }
bool onChar(SkUnichar uni) override {
bool handled = false;
switch (uni) {
case 'W':
fShowAmbient = !fShowAmbient;
handled = true;
break;
case 'S':
fShowSpot = !fShowSpot;
handled = true;
break;
case 'T':
fUseAlt = !fUseAlt;
handled = true;
break;
case 'O':
fShowObject = !fShowObject;
handled = true;
break;
default:
break;
}
if (handled) {
return true;
}
return false;
}
void drawBG(SkCanvas* canvas) {
canvas->drawColor(0xFFFFFFFF);
canvas->drawImage(fReferenceImage, 10, 30);
}
void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
const SkPoint3& zPlaneParams,
const SkPaint& paint, SkScalar ambientAlpha,
const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
if (!fShowAmbient) {
ambientAlpha = 0;
}
if (!fShowSpot) {
spotAlpha = 0;
}
uint32_t flags = 0;
if (fUseAlt) {
flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
}
SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0);
SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
lightPos, lightWidth,
ambientColor, spotColor, flags);
if (fShowObject) {
canvas->drawPath(path, paint);
} else {
SkPaint strokePaint;
strokePaint.setColor(paint.getColor());
strokePaint.setStyle(SkPaint::kStroke_Style);
canvas->drawPath(path, strokePaint);
}
}
void onDrawContent(SkCanvas* canvas) override {
this->drawBG(canvas);
const SkScalar kDP = 4; // the reference image is 4x bigger than it is displayed on
// on the web page, so we need to reflect that here and
// multiply the heights and light params accordingly
const SkScalar kLightWidth = kDP*400;
const SkScalar kAmbientAlpha = 0.03f;
const SkScalar kSpotAlpha = 0.35f;
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(SK_ColorWHITE);
SkPoint3 lightPos = { 175, -800, kDP * 600 };
SkScalar xPos = 230;
SkScalar yPos = 254.25f;
SkRect clipRect = SkRect::MakeXYWH(45, 75, 122, 250);
SkPoint clipDelta = SkPoint::Make(320, 0);
SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kDP * 2);
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
lightPos.fX += 320;
xPos += 320;
clipRect.offset(clipDelta);
zPlaneParams.fZ = kDP * 3;
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
lightPos.fX += 320;
xPos += 320;
clipRect.offset(clipDelta);
zPlaneParams.fZ = kDP * 4;
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
lightPos.fX += 320;
xPos += 320;
clipRect.offset(clipDelta);
zPlaneParams.fZ = kDP * 6;
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
lightPos.fX += 320;
xPos += 320;
clipRect.offset(clipDelta);
zPlaneParams.fZ = kDP * 8;
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
lightPos.fX += 320;
xPos += 320;
clipRect.offset(clipDelta);
zPlaneParams.fZ = kDP * 16;
canvas->save();
canvas->clipRect(clipRect);
canvas->translate(xPos, yPos);
this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha,
lightPos, kLightWidth, kSpotAlpha);
canvas->restore();
}
private:
using INHERITED = Sample;
};
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE( return new ShadowRefView(); )