Home | History | Annotate | Download | only in samplecode
      1 
      2 /*
      3  * Copyright 2016 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SampleCode.h"
      9 #include "SkAnimTimer.h"
     10 #include "SkBlurMask.h"
     11 #include "SkBlurMaskFilter.h"
     12 #include "SkColorFilter.h"
     13 #include "SkCamera.h"
     14 #include "SkCanvas.h"
     15 #include "SkPath.h"
     16 #include "SkPathOps.h"
     17 #include "SkPoint3.h"
     18 #include "SkShadowUtils.h"
     19 #include "SkUtils.h"
     20 #include "SkView.h"
     21 #include "sk_tool_utils.h"
     22 
     23 ////////////////////////////////////////////////////////////////////////////
     24 
     25 class ShadowsView : public SampleView {
     26     SkPath    fRectPath;
     27     SkPath    fRRPath;
     28     SkPath    fCirclePath;
     29     SkPath    fFunkyRRPath;
     30     SkPath    fCubicPath;
     31     SkPath    fSquareRRectPath;
     32     SkPath    fWideRectPath;
     33     SkPath    fWideOvalPath;
     34     SkPoint3  fLightPos;
     35     SkScalar  fZDelta;
     36     SkScalar  fAnimTranslate;
     37     SkScalar  fAnimAngle;
     38     SkScalar  fAnimAlpha;
     39 
     40     bool      fShowAmbient;
     41     bool      fShowSpot;
     42     bool      fUseAlt;
     43     bool      fShowObject;
     44     bool      fIgnoreShadowAlpha;
     45     bool      fDoAlphaAnimation;
     46 
     47 public:
     48     ShadowsView()
     49         : fZDelta(0)
     50         , fAnimTranslate(0)
     51         , fAnimAngle(0)
     52         , fAnimAlpha(1)
     53         , fShowAmbient(true)
     54         , fShowSpot(true)
     55         , fUseAlt(false)
     56         , fShowObject(true)
     57         , fIgnoreShadowAlpha(false)
     58         , fDoAlphaAnimation(false) {}
     59 
     60 protected:
     61     void onOnceBeforeDraw() override {
     62         fCirclePath.addCircle(0, 0, 50);
     63         fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
     64         fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
     65         fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100),
     66                                   40 * SK_Scalar1, 20 * SK_Scalar1,
     67                                   SkPath::kCW_Direction);
     68         fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
     69                            20 * SK_Scalar1, 100 * SK_Scalar1,
     70                            0 * SK_Scalar1, 0 * SK_Scalar1);
     71         fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100),
     72                                                       10, 10));
     73         fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70));
     74         fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70));
     75 
     76         fLightPos = SkPoint3::Make(350, 0, 600);
     77     }
     78 
     79     // overrides from SkEventSink
     80     bool onQuery(SkEvent* evt) override {
     81         if (SampleCode::TitleQ(*evt)) {
     82             SampleCode::TitleR(evt, "AndroidShadows");
     83             return true;
     84         }
     85 
     86         SkUnichar uni;
     87         if (SampleCode::CharQ(*evt, &uni)) {
     88             bool handled = false;
     89             switch (uni) {
     90                 case 'W':
     91                     fShowAmbient = !fShowAmbient;
     92                     handled = true;
     93                     break;
     94                 case 'S':
     95                     fShowSpot = !fShowSpot;
     96                     handled = true;
     97                     break;
     98                 case 'T':
     99                     fUseAlt = !fUseAlt;
    100                     handled = true;
    101                     break;
    102                 case 'O':
    103                     fShowObject = !fShowObject;
    104                     handled = true;
    105                     break;
    106                 case 'N':
    107                     fDoAlphaAnimation = !fDoAlphaAnimation;
    108                     if (!fDoAlphaAnimation) {
    109                         fAnimAlpha = 1;
    110                     }
    111                     handled = true;
    112                     break;
    113                 case '>':
    114                     fZDelta += 0.5f;
    115                     handled = true;
    116                     break;
    117                 case '<':
    118                     fZDelta -= 0.5f;
    119                     handled = true;
    120                     break;
    121                 case '?':
    122                     fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
    123                     handled = true;
    124                     break;
    125                 default:
    126                     break;
    127             }
    128             if (handled) {
    129                 return true;
    130             }
    131         }
    132         return this->INHERITED::onQuery(evt);
    133     }
    134 
    135     void drawBG(SkCanvas* canvas) {
    136         canvas->drawColor(0xFFDDDDDD);
    137     }
    138 
    139     void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
    140                           const SkPoint3& zPlaneParams,
    141                           const SkPaint& paint, SkScalar ambientAlpha,
    142                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
    143         if (fIgnoreShadowAlpha) {
    144             ambientAlpha = 255;
    145             spotAlpha = 255;
    146         }
    147         if (!fShowAmbient) {
    148             ambientAlpha = 0;
    149         }
    150         if (!fShowSpot) {
    151             spotAlpha = 0;
    152         }
    153         uint32_t flags = 0;
    154         if (fUseAlt) {
    155             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
    156         }
    157 
    158         SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0);
    159         SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
    160         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth,
    161                                   ambientColor, spotColor, flags);
    162 
    163         if (fShowObject) {
    164             canvas->drawPath(path, paint);
    165         } else {
    166             SkPaint strokePaint;
    167 
    168             strokePaint.setColor(paint.getColor());
    169             strokePaint.setStyle(SkPaint::kStroke_Style);
    170 
    171             canvas->drawPath(path, strokePaint);
    172         }
    173     }
    174 
    175     void onDrawContent(SkCanvas* canvas) override {
    176         this->drawBG(canvas);
    177         const SkScalar kLightWidth = 800;
    178         const SkScalar kAmbientAlpha = 0.1f;
    179         const SkScalar kSpotAlpha = 0.25f;
    180 
    181         SkPaint paint;
    182         paint.setAntiAlias(true);
    183 
    184         SkPoint3 lightPos = fLightPos;
    185         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0);
    186 
    187         paint.setColor(SK_ColorWHITE);
    188         canvas->translate(200, 90);
    189         zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
    190         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    191                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    192 
    193         paint.setColor(SK_ColorRED);
    194         canvas->translate(250, 0);
    195         zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
    196         this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    197                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    198 
    199         paint.setColor(SK_ColorBLUE);
    200         canvas->translate(-250, 110);
    201         zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta);
    202         this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    203                                lightPos, kLightWidth, fAnimAlpha*0.5f);
    204 
    205         paint.setColor(SK_ColorGREEN);
    206         canvas->translate(250, 0);
    207         zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta);
    208         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    209                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    210 
    211         paint.setColor(SK_ColorYELLOW);
    212         canvas->translate(-250, 110);
    213         zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
    214         this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    215                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    216 
    217         paint.setColor(SK_ColorCYAN);
    218         canvas->translate(250, 0);
    219         zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
    220         this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    221                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    222 
    223         // circular reveal
    224         SkPath tmpPath;
    225         SkPath tmpClipPath;
    226         tmpClipPath.addCircle(fAnimTranslate, 0, 60);
    227         Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath);
    228 
    229         paint.setColor(SK_ColorMAGENTA);
    230         canvas->translate(-125, 60);
    231         zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
    232         this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
    233                                lightPos, kLightWidth, .5f);
    234 
    235         // perspective paths
    236         SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2,
    237                                       fWideRectPath.getBounds().height()/2);
    238         SkPoint translate = SkPoint::Make(100, 450);
    239         paint.setColor(SK_ColorWHITE);
    240         Sk3DView view;
    241         view.save();
    242         view.rotateX(fAnimAngle);
    243         SkMatrix persp;
    244         view.getMatrix(&persp);
    245         persp.preTranslate(-pivot.fX, -pivot.fY);
    246         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
    247         canvas->setMatrix(persp);
    248         SkScalar radians = SkDegreesToRadians(fAnimAngle);
    249         zPlaneParams = SkPoint3::Make(0,
    250                                       SkScalarSin(-radians),
    251                                       SkTMax(1.0f, 16 + fZDelta) - SkScalarSin(-radians)*pivot.fY);
    252         this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f,
    253                                lightPos, kLightWidth, .5f);
    254 
    255         pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2,
    256                               fWideOvalPath.getBounds().height() / 2);
    257         translate = SkPoint::Make(100, 600);
    258         view.restore();
    259         view.rotateY(fAnimAngle);
    260         view.getMatrix(&persp);
    261         persp.preTranslate(-pivot.fX, -pivot.fY);
    262         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
    263         canvas->setMatrix(persp);
    264         zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
    265                                       0,
    266                                       SkTMax(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX);
    267         this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f,
    268                                lightPos, kLightWidth, .5f);
    269     }
    270 
    271     bool onAnimate(const SkAnimTimer& timer) override {
    272         fAnimTranslate = timer.pingPong(30, 0, 200, -200);
    273         fAnimAngle = timer.pingPong(15, 0, 0, 20);
    274         if (fDoAlphaAnimation) {
    275             fAnimAlpha = timer.pingPong(5, 0, 1, 0);
    276         }
    277         return true;
    278     }
    279 
    280 private:
    281     typedef SampleView INHERITED;
    282 };
    283 
    284 //////////////////////////////////////////////////////////////////////////////
    285 
    286 static SkView* MyFactory() { return new ShadowsView; }
    287 static SkViewRegister reg(MyFactory);
    288