Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2018 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 "SkAndroidCodec.h"
      9 #include "SkAnimatedImage.h"
     10 #include "SkAnimTimer.h"
     11 #include "SkCanvas.h"
     12 #include "SkFont.h"
     13 #include "SkPaint.h"
     14 #include "SkPictureRecorder.h"
     15 #include "SkRect.h"
     16 #include "SkScalar.h"
     17 #include "SkString.h"
     18 
     19 #include "Sample.h"
     20 #include "Resources.h"
     21 
     22 static constexpr char kPauseKey = 'p';
     23 static constexpr char kResetKey = 'r';
     24 
     25 class SampleAnimatedImage : public Sample {
     26 public:
     27     SampleAnimatedImage()
     28         : INHERITED()
     29         , fYOffset(0)
     30     {}
     31 
     32 protected:
     33     void onDrawBackground(SkCanvas* canvas) override {
     34         SkFont font;
     35         font.setSize(20);
     36 
     37         SkString str = SkStringPrintf("Press '%c' to start/pause; '%c' to reset.",
     38                 kPauseKey, kResetKey);
     39         const char* text = str.c_str();
     40         SkRect bounds;
     41         font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &bounds);
     42         fYOffset = bounds.height();
     43 
     44         canvas->drawSimpleText(text, strlen(text), kUTF8_SkTextEncoding, 5, fYOffset, font, SkPaint());
     45         fYOffset *= 2;
     46     }
     47 
     48     void onDrawContent(SkCanvas* canvas) override {
     49         if (!fImage) {
     50             return;
     51         }
     52 
     53         canvas->translate(0, fYOffset);
     54 
     55         canvas->drawDrawable(fImage.get());
     56         canvas->drawDrawable(fDrawable.get(), fImage->getBounds().width(), 0);
     57     }
     58 
     59     bool onAnimate(const SkAnimTimer& animTimer) override {
     60         if (!fImage) {
     61             return false;
     62         }
     63 
     64         const double lastWallTime = fLastWallTime;
     65         fLastWallTime = animTimer.msec();
     66 
     67         if (fRunning) {
     68             fCurrentTime += fLastWallTime - lastWallTime;
     69             if (fCurrentTime > fTimeToShowNextFrame) {
     70                 fTimeToShowNextFrame += fImage->decodeNextFrame();
     71                 if (fImage->isFinished()) {
     72                     fRunning = false;
     73                 }
     74             }
     75         }
     76 
     77         return true;
     78     }
     79 
     80     void onOnceBeforeDraw() override {
     81         sk_sp<SkData> file(GetResourceAsData("images/alphabetAnim.gif"));
     82         std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(file));
     83         if (!codec) {
     84             return;
     85         }
     86 
     87         fImage = SkAnimatedImage::Make(SkAndroidCodec::MakeFromCodec(std::move(codec)));
     88         if (!fImage) {
     89             return;
     90         }
     91 
     92         fTimeToShowNextFrame = fImage->currentFrameDuration();
     93         SkPictureRecorder recorder;
     94         auto canvas = recorder.beginRecording(fImage->getBounds());
     95         canvas->drawDrawable(fImage.get());
     96         fDrawable = recorder.finishRecordingAsDrawable();
     97     }
     98 
     99     bool onQuery(Sample::Event* evt) override {
    100         if (Sample::TitleQ(*evt)) {
    101             Sample::TitleR(evt, "AnimatedImage");
    102             return true;
    103         }
    104 
    105         SkUnichar uni;
    106         if (fImage && Sample::CharQ(*evt, &uni)) {
    107             switch (uni) {
    108                 case kPauseKey:
    109                     fRunning = !fRunning;
    110                     if (fImage->isFinished()) {
    111                         // fall through
    112                     } else {
    113                         return true;
    114                     }
    115                 case kResetKey:
    116                     fImage->reset();
    117                     fCurrentTime = fLastWallTime;
    118                     fTimeToShowNextFrame = fCurrentTime + fImage->currentFrameDuration();
    119                     return true;
    120                 default:
    121                     break;
    122             }
    123         }
    124         return this->INHERITED::onQuery(evt);
    125     }
    126 
    127 private:
    128     sk_sp<SkAnimatedImage>  fImage;
    129     sk_sp<SkDrawable>       fDrawable;
    130     SkScalar                fYOffset;
    131     bool                    fRunning = false;
    132     double                  fCurrentTime = 0.0;
    133     double                  fLastWallTime = 0.0;
    134     double                  fTimeToShowNextFrame = 0.0;
    135     typedef Sample INHERITED;
    136 };
    137 
    138 ///////////////////////////////////////////////////////////////////////////////
    139 
    140 DEF_SAMPLE( return new SampleAnimatedImage(); )
    141