blob: eaa318cb5951c271baa1ab00e740c44f40f0757e [file] [log] [blame]
Leon Scroggins III7a10b332018-01-12 11:24:30 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/android/SkAnimatedImage.h"
9#include "include/codec/SkAndroidCodec.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkPaint.h"
13#include "include/core/SkPictureRecorder.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkString.h"
Hal Canary41248072019-07-11 16:32:53 -040017#include "tools/timer/TimeUtils.h"
Leon Scroggins III7a10b332018-01-12 11:24:30 -050018
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "samplecode/Sample.h"
20#include "tools/Resources.h"
Leon Scroggins III7a10b332018-01-12 11:24:30 -050021
22static constexpr char kPauseKey = 'p';
23static constexpr char kResetKey = 'r';
24
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040025class SampleAnimatedImage : public Sample {
Leon Scroggins III7a10b332018-01-12 11:24:30 -050026public:
27 SampleAnimatedImage()
28 : INHERITED()
Leon Scroggins III7a10b332018-01-12 11:24:30 -050029 , fYOffset(0)
30 {}
31
32protected:
33 void onDrawBackground(SkCanvas* canvas) override {
Mike Reed91919132019-01-02 12:21:01 -050034 SkFont font;
35 font.setSize(20);
Leon Scroggins III7a10b332018-01-12 11:24:30 -050036
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;
Ben Wagner51e15a62019-05-07 15:38:46 -040041 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Leon Scroggins III7a10b332018-01-12 11:24:30 -050042 fYOffset = bounds.height();
43
Ben Wagner51e15a62019-05-07 15:38:46 -040044 canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 5, fYOffset, font, SkPaint());
Leon Scroggins III7a10b332018-01-12 11:24:30 -050045 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
Hal Canary41248072019-07-11 16:32:53 -040059 bool onAnimate(double nanos) override {
Leon Scroggins III7a10b332018-01-12 11:24:30 -050060 if (!fImage) {
61 return false;
62 }
63
Leon Scroggins III495e0f02018-01-29 19:35:55 -050064 const double lastWallTime = fLastWallTime;
Hal Canary41248072019-07-11 16:32:53 -040065 fLastWallTime = TimeUtils::NanosToMSec(nanos);
Leon Scroggins III495e0f02018-01-29 19:35:55 -050066
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
Leon Scroggins III7a10b332018-01-12 11:24:30 -050077 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
Leon Scroggins III42ee2842018-01-14 14:46:51 -050087 fImage = SkAnimatedImage::Make(SkAndroidCodec::MakeFromCodec(std::move(codec)));
Leon Scroggins III7a10b332018-01-12 11:24:30 -050088 if (!fImage) {
89 return;
90 }
91
Leon Scroggins III495e0f02018-01-29 19:35:55 -050092 fTimeToShowNextFrame = fImage->currentFrameDuration();
Leon Scroggins III7a10b332018-01-12 11:24:30 -050093 SkPictureRecorder recorder;
94 auto canvas = recorder.beginRecording(fImage->getBounds());
95 canvas->drawDrawable(fImage.get());
96 fDrawable = recorder.finishRecordingAsDrawable();
97 }
98
Hal Canary8a027312019-07-03 10:55:44 -040099 SkString name() override { return SkString("AnimatedImage"); }
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500100
Hal Canary6cc65e12019-07-03 15:53:04 -0400101 bool onChar(SkUnichar uni) override {
102 if (fImage) {
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500103 switch (uni) {
104 case kPauseKey:
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500105 fRunning = !fRunning;
106 if (fImage->isFinished()) {
107 // fall through
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500108 } else {
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500109 return true;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500110 }
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500111 case kResetKey:
112 fImage->reset();
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500113 fCurrentTime = fLastWallTime;
114 fTimeToShowNextFrame = fCurrentTime + fImage->currentFrameDuration();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500115 return true;
116 default:
117 break;
118 }
119 }
Hal Canary6cc65e12019-07-03 15:53:04 -0400120 return false;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500121 }
122
123private:
124 sk_sp<SkAnimatedImage> fImage;
125 sk_sp<SkDrawable> fDrawable;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500126 SkScalar fYOffset;
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500127 bool fRunning = false;
128 double fCurrentTime = 0.0;
129 double fLastWallTime = 0.0;
130 double fTimeToShowNextFrame = 0.0;
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400131 typedef Sample INHERITED;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500132};
133
134///////////////////////////////////////////////////////////////////////////////
135
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400136DEF_SAMPLE( return new SampleAnimatedImage(); )