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 "Sample.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 "SkUTF.h"
     20 #include "sk_tool_utils.h"
     21 
     22 ////////////////////////////////////////////////////////////////////////////
     23 
     24 class ShadowsView : public Sample {
     25     SkPath    fRectPath;
     26     SkPath    fRRPath;
     27     SkPath    fCirclePath;
     28     SkPath    fFunkyRRPath;
     29     SkPath    fCubicPath;
     30     SkPath    fStarPath;
     31     SkPath    fSquareRRectPath;
     32     SkPath    fWideRectPath;
     33     SkPath    fWideOvalPath;
     34     SkPath    fNotchPath;
     35     SkPath    fTabPath;
     36 
     37     SkPoint3  fLightPos;
     38     SkScalar  fZDelta;
     39     SkScalar  fAnimTranslate;
     40     SkScalar  fAnimAngle;
     41     SkScalar  fAnimAlpha;
     42 
     43     bool      fShowAmbient;
     44     bool      fShowSpot;
     45     bool      fUseAlt;
     46     bool      fShowObject;
     47     bool      fIgnoreShadowAlpha;
     48     bool      fDoAlphaAnimation;
     49 
     50 public:
     51     ShadowsView()
     52         : fZDelta(0)
     53         , fAnimTranslate(0)
     54         , fAnimAngle(0)
     55         , fAnimAlpha(1)
     56         , fShowAmbient(true)
     57         , fShowSpot(true)
     58         , fUseAlt(false)
     59         , fShowObject(true)
     60         , fIgnoreShadowAlpha(false)
     61         , fDoAlphaAnimation(false) {}
     62 
     63 protected:
     64     void onOnceBeforeDraw() override {
     65         fCirclePath.addCircle(0, 0, 50);
     66         fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
     67         fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
     68         fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100),
     69                                   40 * SK_Scalar1, 20 * SK_Scalar1,
     70                                   SkPath::kCW_Direction);
     71         fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
     72                            20 * SK_Scalar1, 100 * SK_Scalar1,
     73                            0 * SK_Scalar1, 0 * SK_Scalar1);
     74         fStarPath.moveTo(0.0f, -50.0f);
     75         fStarPath.lineTo(14.43f, -25.0f);
     76         fStarPath.lineTo(43.30f, -25.0f);
     77         fStarPath.lineTo(28.86f, 0.0f);
     78         fStarPath.lineTo(43.30f, 25.0f);
     79         fStarPath.lineTo(14.43f, 25.0f);
     80         fStarPath.lineTo(0.0f, 50.0f);
     81         fStarPath.lineTo(-14.43f, 25.0f);
     82         fStarPath.lineTo(-43.30f, 25.0f);
     83         fStarPath.lineTo(-28.86f, 0.0f);
     84         fStarPath.lineTo(-43.30f, -25.0f);
     85         fStarPath.lineTo(-14.43f, -25.0f);
     86         fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100),
     87                                                       10, 10));
     88         fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70));
     89         fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70));
     90 
     91         fNotchPath.moveTo(0, 80);
     92         fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), -90, -90, false);
     93         fNotchPath.lineTo(-75, 100);
     94         fNotchPath.lineTo(-75, -100);
     95         fNotchPath.lineTo(75, -100);
     96         fNotchPath.lineTo(75, 100);
     97         fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, -90, false);
     98 
     99         fTabPath.moveTo(-75, -100);
    100         fTabPath.lineTo(75, -100);
    101         fTabPath.lineTo(75, 100);
    102         fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, 90, false);
    103         fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 90, 90, false);
    104         fTabPath.lineTo(-75, 100);
    105 
    106         fLightPos = SkPoint3::Make(350, 0, 600);
    107     }
    108 
    109     bool onQuery(Sample::Event* evt) override {
    110         if (Sample::TitleQ(*evt)) {
    111             Sample::TitleR(evt, "AndroidShadows");
    112             return true;
    113         }
    114 
    115         SkUnichar uni;
    116         if (Sample::CharQ(*evt, &uni)) {
    117             bool handled = false;
    118             switch (uni) {
    119                 case 'W':
    120                     fShowAmbient = !fShowAmbient;
    121                     handled = true;
    122                     break;
    123                 case 'S':
    124                     fShowSpot = !fShowSpot;
    125                     handled = true;
    126                     break;
    127                 case 'T':
    128                     fUseAlt = !fUseAlt;
    129                     handled = true;
    130                     break;
    131                 case 'O':
    132                     fShowObject = !fShowObject;
    133                     handled = true;
    134                     break;
    135                 case 'N':
    136                     fDoAlphaAnimation = !fDoAlphaAnimation;
    137                     if (!fDoAlphaAnimation) {
    138                         fAnimAlpha = 1;
    139                     }
    140                     handled = true;
    141                     break;
    142                 case '>':
    143                     fZDelta += 0.5f;
    144                     handled = true;
    145                     break;
    146                 case '<':
    147                     fZDelta -= 0.5f;
    148                     handled = true;
    149                     break;
    150                 case '?':
    151                     fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
    152                     handled = true;
    153                     break;
    154                 default:
    155                     break;
    156             }
    157             if (handled) {
    158                 return true;
    159             }
    160         }
    161         return this->INHERITED::onQuery(evt);
    162     }
    163 
    164     void drawBG(SkCanvas* canvas) {
    165         canvas->drawColor(0xFFDDDDDD);
    166     }
    167 
    168     void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
    169                           const SkPoint3& zPlaneParams,
    170                           const SkPaint& paint, SkScalar ambientAlpha,
    171                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
    172         if (fIgnoreShadowAlpha) {
    173             ambientAlpha = 1;
    174             spotAlpha = 1;
    175         }
    176         if (!fShowAmbient) {
    177             ambientAlpha = 0;
    178         }
    179         if (!fShowSpot) {
    180             spotAlpha = 0;
    181         }
    182         uint32_t flags = 0;
    183         if (fUseAlt) {
    184             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
    185         }
    186 
    187         SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0);
    188         SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
    189         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth,
    190                                   ambientColor, spotColor, flags);
    191 
    192         if (fShowObject) {
    193             canvas->drawPath(path, paint);
    194         } else {
    195             SkPaint strokePaint;
    196 
    197             strokePaint.setColor(paint.getColor());
    198             strokePaint.setStyle(SkPaint::kStroke_Style);
    199 
    200             canvas->drawPath(path, strokePaint);
    201         }
    202     }
    203 
    204     void onDrawContent(SkCanvas* canvas) override {
    205         this->drawBG(canvas);
    206         const SkScalar kLightWidth = 800;
    207         const SkScalar kAmbientAlpha = 0.039f;
    208         const SkScalar kSpotAlpha = 0.19f;
    209 
    210         SkPaint paint;
    211         paint.setAntiAlias(true);
    212 
    213         SkPoint3 lightPos = fLightPos;
    214         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0);
    215 
    216         paint.setColor(SK_ColorWHITE);
    217         canvas->translate(200, 90);
    218         zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
    219         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    220                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    221 
    222         paint.setColor(SK_ColorRED);
    223         canvas->translate(250, 0);
    224         zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
    225         this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    226                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    227 
    228         paint.setColor(SK_ColorBLUE);
    229         canvas->translate(-250, 110);
    230         zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta);
    231         this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    232                                lightPos, kLightWidth, fAnimAlpha*0.5f);
    233 
    234         paint.setColor(SK_ColorGREEN);
    235         canvas->translate(250, 0);
    236         zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta);
    237         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    238                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    239 
    240         paint.setColor(SK_ColorYELLOW);
    241         canvas->translate(-250, 110);
    242         zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
    243         this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    244                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    245 
    246         paint.setColor(SK_ColorCYAN);
    247         canvas->translate(250, 0);
    248         zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
    249         this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
    250                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
    251 
    252         paint.setColor(SK_ColorWHITE);
    253         canvas->translate(250, -180);
    254         zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
    255         this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint,
    256                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
    257 
    258         paint.setColor(SK_ColorWHITE);
    259         canvas->translate(150, 0);
    260         zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
    261         this->drawShadowedPath(canvas, fNotchPath, zPlaneParams, paint,
    262                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
    263 
    264         paint.setColor(SK_ColorWHITE);
    265         canvas->translate(200, 0);
    266         zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
    267         this->drawShadowedPath(canvas, fTabPath, zPlaneParams, paint,
    268                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
    269 
    270         // circular reveal
    271         SkPath tmpPath;
    272         SkPath tmpClipPath;
    273         tmpClipPath.addCircle(fAnimTranslate, 0, 60);
    274         Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath);
    275 
    276         paint.setColor(SK_ColorMAGENTA);
    277         canvas->translate(-725, 240);
    278         zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
    279         this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
    280                                lightPos, kLightWidth, .5f);
    281 
    282         // path ops bug
    283         SkPath tmpClipPathBug;
    284         tmpClipPathBug.addCircle(88.0344925f, 0, 60);
    285         Op(fSquareRRectPath, tmpClipPathBug, kIntersect_SkPathOp, &tmpPath);
    286 
    287         canvas->translate(250, 0);
    288         zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
    289         this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
    290                                lightPos, kLightWidth, .5f);
    291 
    292         // perspective paths
    293         SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2,
    294                                       fWideRectPath.getBounds().height()/2);
    295         SkPoint translate = SkPoint::Make(100, 450);
    296         paint.setColor(SK_ColorWHITE);
    297         Sk3DView view;
    298         view.save();
    299         view.rotateX(fAnimAngle);
    300         SkMatrix persp;
    301         view.getMatrix(&persp);
    302         persp.preTranslate(-pivot.fX, -pivot.fY);
    303         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
    304         canvas->setMatrix(persp);
    305         SkScalar radians = SkDegreesToRadians(fAnimAngle);
    306         zPlaneParams = SkPoint3::Make(0,
    307                                       SkScalarSin(radians),
    308                                       SkTMax(1.0f, 16 + fZDelta) - SkScalarSin(radians)*pivot.fY);
    309         this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f,
    310                                lightPos, kLightWidth, .5f);
    311 
    312         pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2,
    313                               fWideOvalPath.getBounds().height() / 2);
    314         translate = SkPoint::Make(100, 600);
    315         view.restore();
    316         view.save();
    317         view.rotateY(fAnimAngle);
    318         view.getMatrix(&persp);
    319         persp.preTranslate(-pivot.fX, -pivot.fY);
    320         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
    321         canvas->setMatrix(persp);
    322         zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
    323                                       0,
    324                                       SkTMax(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX);
    325         this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f,
    326                                lightPos, kLightWidth, .5f);
    327 
    328         pivot = SkPoint::Make(fStarPath.getBounds().width() / 2,
    329                               fStarPath.getBounds().height() / 2);
    330         translate = SkPoint::Make(700, 250);
    331         view.restore();
    332         view.rotateY(fAnimAngle);
    333         view.getMatrix(&persp);
    334         persp.preTranslate(-pivot.fX, -pivot.fY);
    335         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
    336         canvas->setMatrix(persp);
    337         zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
    338                                       0,
    339                                       SkTMax(1.0f, 8 + fZDelta) + SkScalarSin(radians)*pivot.fX);
    340         this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, .1f,
    341                                lightPos, kLightWidth, .5f);
    342     }
    343 
    344     bool onAnimate(const SkAnimTimer& timer) override {
    345         fAnimTranslate = timer.pingPong(30, 0, 125, -125);
    346         fAnimAngle = timer.pingPong(15, 0, 0, 20);
    347         if (fDoAlphaAnimation) {
    348             fAnimAlpha = timer.pingPong(5, 0, 1, 0);
    349         }
    350         return true;
    351     }
    352 
    353 private:
    354     typedef Sample INHERITED;
    355 };
    356 
    357 //////////////////////////////////////////////////////////////////////////////
    358 
    359 DEF_SAMPLE( return new ShadowsView(); )
    360