Home | History | Annotate | Download | only in samplecode
      1 
      2 /*
      3  * Copyright 2017 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 "Resources.h"
     10 #include "SkCanvas.h"
     11 #include "SkImage.h"
     12 #include "SkPath.h"
     13 #include "SkPoint3.h"
     14 #include "SkShadowUtils.h"
     15 
     16 ////////////////////////////////////////////////////////////////////////////
     17 // Sample to demonstrate tonal color shadows
     18 
     19 class ShadowColorView : public SampleView {
     20     SkPath    fRectPath;
     21     int       fZIndex;
     22 
     23     bool      fShowAmbient;
     24     bool      fShowSpot;
     25     bool      fUseAlt;
     26     bool      fShowObject;
     27     bool      fTwoPassColor;
     28     bool      fDarkBackground;
     29 
     30 public:
     31     ShadowColorView()
     32         : fZIndex(8)
     33         , fShowAmbient(true)
     34         , fShowSpot(true)
     35         , fUseAlt(false)
     36         , fShowObject(true)
     37         , fTwoPassColor(false)
     38         , fDarkBackground(false) {}
     39 
     40 protected:
     41     void onOnceBeforeDraw() override {
     42         fRectPath.addRect(SkRect::MakeXYWH(-50, -50, 100, 100));
     43     }
     44 
     45     // overrides from SkEventSink
     46     bool onQuery(SkEvent* evt) override {
     47         if (SampleCode::TitleQ(*evt)) {
     48             SampleCode::TitleR(evt, "ShadowColor");
     49             return true;
     50         }
     51 
     52         SkUnichar uni;
     53         if (SampleCode::CharQ(*evt, &uni)) {
     54             bool handled = false;
     55             switch (uni) {
     56                 case 'W':
     57                     fShowAmbient = !fShowAmbient;
     58                     handled = true;
     59                     break;
     60                 case 'S':
     61                     fShowSpot = !fShowSpot;
     62                     handled = true;
     63                     break;
     64                 case 'T':
     65                     fUseAlt = !fUseAlt;
     66                     handled = true;
     67                     break;
     68                 case 'O':
     69                     fShowObject = !fShowObject;
     70                     handled = true;
     71                     break;
     72                 case 'X':
     73                     fTwoPassColor = !fTwoPassColor;
     74                     handled = true;
     75                     break;
     76                 case 'Z':
     77                     fDarkBackground = !fDarkBackground;
     78                     handled = true;
     79                     break;
     80                 case '>':
     81                     fZIndex = SkTMin(9, fZIndex+1);
     82                     handled = true;
     83                     break;
     84                 case '<':
     85                     fZIndex = SkTMax(0, fZIndex-1);
     86                     handled = true;
     87                     break;
     88                 default:
     89                     break;
     90             }
     91             if (handled) {
     92                 this->inval(nullptr);
     93                 return true;
     94             }
     95         }
     96         return this->INHERITED::onQuery(evt);
     97     }
     98 
     99     void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
    100                           const SkPoint3& zPlaneParams,
    101                           const SkPaint& paint, SkScalar ambientAlpha,
    102                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
    103         if (!fShowAmbient) {
    104             ambientAlpha = 0;
    105         }
    106         if (!fShowSpot) {
    107             spotAlpha = 0;
    108         }
    109         uint32_t flags = 0;
    110         if (fUseAlt) {
    111             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
    112         }
    113 
    114         if (fTwoPassColor) {
    115             SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
    116                                       lightPos, lightWidth,
    117                                       ambientAlpha, 0, SK_ColorBLACK, flags);
    118 
    119             if (paint.getColor() != SK_ColorBLACK) {
    120                 SkColor color = paint.getColor();
    121 
    122                 uint8_t max = SkTMax(SkTMax(SkColorGetR(color), SkColorGetG(color)),
    123                                      SkColorGetB(color));
    124                 uint8_t min = SkTMin(SkTMin(SkColorGetR(color), SkColorGetG(color)),
    125                                      SkColorGetB(color));
    126                 SkScalar luminance = 0.5f*(max + min) / 255.f;
    127                 SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f;
    128                 spotAlpha -= (alpha - 0.3f)*.5f;
    129 
    130                 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
    131                                           lightPos, lightWidth,
    132                                           0, alpha, paint.getColor(), flags);
    133             }
    134 
    135             SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
    136                                       lightPos, lightWidth,
    137                                       0, spotAlpha, SK_ColorBLACK, flags);
    138         } else {
    139             flags |= SkShadowFlags::kTonalColor_ShadowFlag;
    140             SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
    141                                       lightPos, lightWidth,
    142                                       ambientAlpha, spotAlpha, paint.getColor(), flags);
    143         }
    144         if (fShowObject) {
    145             canvas->drawPath(path, paint);
    146         } else {
    147             SkPaint strokePaint;
    148 
    149             strokePaint.setColor(paint.getColor());
    150             strokePaint.setStyle(SkPaint::kStroke_Style);
    151 
    152             canvas->drawPath(path, strokePaint);
    153         }
    154     }
    155 
    156     void onDrawContent(SkCanvas* canvas) override {
    157         const SkScalar kLightWidth = 600;
    158         const SkScalar kAmbientAlpha = 0.03f;
    159         const SkScalar kSpotAlpha = 0.25f;
    160 
    161         const SkScalar kZValues[10] = { 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 };
    162 
    163         const SkColor kColors[30] = {
    164             // purples
    165             0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5,
    166             0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9,
    167             // oranges
    168             0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000,
    169             0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC,
    170             // teals
    171             0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2,
    172             0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0
    173         };
    174 
    175         SkPaint paint;
    176         paint.setAntiAlias(true);
    177         if (fDarkBackground) {
    178             canvas->drawColor(0xFF111111);
    179             paint.setColor(SK_ColorWHITE);
    180         } else {
    181             canvas->drawColor(0xFFEAEAEA);
    182             paint.setColor(SK_ColorBLACK);
    183         }
    184 
    185         if (fTwoPassColor) {
    186             canvas->drawText("Two pass", 8, 10, 15, paint);
    187         } else {
    188             canvas->drawText("One pass", 8, 10, 15, paint);
    189         }
    190 
    191         SkPoint3 lightPos = { 75, -400, 600 };
    192         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kZValues[fZIndex]);
    193         SkScalar yPos = 75;
    194 
    195         for (int row = 0; row < 3; ++row) {
    196             lightPos.fX = 75;
    197             SkScalar xPos = 75;
    198             for (int col = 0; col < 10; ++col) {
    199                 paint.setColor(kColors[10*row + col]);
    200 
    201                 canvas->save();
    202                 canvas->translate(xPos, yPos);
    203                 this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha,
    204                                        lightPos, kLightWidth, kSpotAlpha);
    205                 canvas->restore();
    206 
    207                 lightPos.fX += 120;
    208                 xPos += 120;
    209             }
    210 
    211             lightPos.fY += 200;
    212             yPos += 200;
    213         }
    214     }
    215 
    216 private:
    217     typedef SampleView INHERITED;
    218 };
    219 
    220 //////////////////////////////////////////////////////////////////////////////
    221 
    222 static SkView* MyFactory() { return new ShadowColorView; }
    223 static SkViewRegister reg(MyFactory);
    224