• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SampleAnimatedImage()27     SampleAnimatedImage()
28         : INHERITED()
29         , fYOffset(0)
30     {}
31 
32 protected:
onDrawBackground(SkCanvas * canvas)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 
onDrawContent(SkCanvas * canvas)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 
onAnimate(const SkAnimTimer & animTimer)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 
onOnceBeforeDraw()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 
onQuery(Sample::Event * evt)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