Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SampleCode.h"
      9 #include "SkAnimTimer.h"
     10 #include "SkView.h"
     11 #include "SkCanvas.h"
     12 #include "SkDrawable.h"
     13 #include "SkInterpolator.h"
     14 #include "SkPictureRecorder.h"
     15 #include "SkPointPriv.h"
     16 #include "SkRandom.h"
     17 
     18 const SkRect gUnitSquare = { -1, -1, 1, 1 };
     19 
     20 static void color_to_floats(SkColor c, SkScalar f[4]) {
     21     f[0] = SkIntToScalar(SkColorGetA(c));
     22     f[1] = SkIntToScalar(SkColorGetR(c));
     23     f[2] = SkIntToScalar(SkColorGetG(c));
     24     f[3] = SkIntToScalar(SkColorGetB(c));
     25 }
     26 
     27 static SkColor floats_to_color(const SkScalar f[4]) {
     28     return SkColorSetARGB(SkScalarRoundToInt(f[0]),
     29                           SkScalarRoundToInt(f[1]),
     30                           SkScalarRoundToInt(f[2]),
     31                           SkScalarRoundToInt(f[3]));
     32 }
     33 
     34 static bool oval_contains(const SkRect& r, SkScalar x, SkScalar y) {
     35     SkMatrix m;
     36     m.setRectToRect(r, gUnitSquare, SkMatrix::kFill_ScaleToFit);
     37     SkPoint pt;
     38     m.mapXY(x, y, &pt);
     39     return SkPointPriv::LengthSqd(pt) <= 1;
     40 }
     41 
     42 static SkColor rand_opaque_color(uint32_t seed) {
     43     SkRandom rand(seed);
     44     return rand.nextU() | (0xFF << 24);
     45 }
     46 
     47 class HTDrawable : public SkDrawable {
     48     SkRect          fR;
     49     SkColor         fColor;
     50     SkInterpolator* fInterp;
     51     SkMSec          fTime;
     52 
     53 public:
     54     HTDrawable(SkRandom& rand) {
     55         fR = SkRect::MakeXYWH(rand.nextRangeF(0, 640), rand.nextRangeF(0, 480),
     56                               rand.nextRangeF(20, 200), rand.nextRangeF(20, 200));
     57         fColor = rand_opaque_color(rand.nextU());
     58         fInterp = nullptr;
     59         fTime = 0;
     60     }
     61 
     62     void spawnAnimation(SkMSec now) {
     63         this->setTime(now);
     64 
     65         delete fInterp;
     66         fInterp = new SkInterpolator(5, 3);
     67         SkScalar values[5];
     68         color_to_floats(fColor, values); values[4] = 0;
     69         fInterp->setKeyFrame(0, now, values);
     70         values[0] = 0; values[4] = 180;
     71         fInterp->setKeyFrame(1, now + 1000, values);
     72         color_to_floats(rand_opaque_color(fColor), values); values[4] = 360;
     73         fInterp->setKeyFrame(2, now + 2000, values);
     74 
     75         fInterp->setMirror(true);
     76         fInterp->setRepeatCount(3);
     77 
     78         this->notifyDrawingChanged();
     79     }
     80 
     81     bool hitTest(SkScalar x, SkScalar y) {
     82         return oval_contains(fR, x, y);
     83     }
     84 
     85     void setTime(SkMSec time) { fTime = time; }
     86 
     87     void onDraw(SkCanvas* canvas) override {
     88         SkAutoCanvasRestore acr(canvas, false);
     89 
     90         SkPaint paint;
     91         paint.setAntiAlias(true);
     92 
     93         if (fInterp) {
     94             SkScalar values[5];
     95             SkInterpolator::Result res = fInterp->timeToValues(fTime, values);
     96             fColor = floats_to_color(values);
     97 
     98             canvas->save();
     99             canvas->rotate(values[4], fR.centerX(), fR.centerY());
    100 
    101             switch (res) {
    102                 case SkInterpolator::kFreezeEnd_Result:
    103                     delete fInterp;
    104                     fInterp = nullptr;
    105                     break;
    106                 default:
    107                     break;
    108             }
    109         }
    110         paint.setColor(fColor);
    111         canvas->drawRect(fR, paint);
    112     }
    113 
    114     SkRect onGetBounds() override { return fR; }
    115 };
    116 
    117 class HTView : public SampleView {
    118 public:
    119     enum {
    120         N = 50,
    121         W = 640,
    122         H = 480,
    123     };
    124 
    125     struct Rec {
    126         HTDrawable* fDrawable;
    127     };
    128     Rec fArray[N];
    129     sk_sp<SkDrawable> fRoot;
    130     SkMSec fTime;
    131 
    132     HTView() {
    133         SkRandom rand;
    134 
    135         SkPictureRecorder recorder;
    136         SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(W, H));
    137         for (int i = 0; i < N; ++i) {
    138             fArray[i].fDrawable = new HTDrawable(rand);
    139             canvas->drawDrawable(fArray[i].fDrawable);
    140             fArray[i].fDrawable->unref();
    141         }
    142         fRoot = recorder.finishRecordingAsDrawable();
    143     }
    144 
    145 protected:
    146     bool onQuery(SkEvent* evt) override {
    147         if (SampleCode::TitleQ(*evt)) {
    148             SampleCode::TitleR(evt, "HT");
    149             return true;
    150         }
    151         return this->INHERITED::onQuery(evt);
    152     }
    153 
    154     void onDrawContent(SkCanvas* canvas) override {
    155         canvas->drawDrawable(fRoot.get());
    156     }
    157 
    158     bool onAnimate(const SkAnimTimer& timer) override {
    159         fTime = timer.msec();
    160         for (int i = 0; i < N; ++i) {
    161             fArray[i].fDrawable->setTime(fTime);
    162         }
    163         return true;
    164     }
    165 
    166     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
    167         // search backwards to find the top-most
    168         for (int i = N - 1; i >= 0; --i) {
    169             if (fArray[i].fDrawable->hitTest(x, y)) {
    170                 fArray[i].fDrawable->spawnAnimation(fTime);
    171                 break;
    172             }
    173         }
    174         return nullptr;
    175     }
    176 
    177 private:
    178     typedef SampleView INHERITED;
    179 };
    180 
    181 //////////////////////////////////////////////////////////////////////////////
    182 
    183 static SkView* MyFactory() { return new HTView; }
    184 static SkViewRegister reg(MyFactory);
    185