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 "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"
17#include "tools/timer/TimeUtils.h"
18
19#include "samplecode/Sample.h"
20#include "tools/Resources.h"
21
22static constexpr char kPauseKey = 'p';
23static constexpr char kResetKey = 'r';
24
25class SampleAnimatedImage : public Sample {
26    sk_sp<SkAnimatedImage>  fImage;
27    sk_sp<SkDrawable>       fDrawable;
28    SkScalar                fYOffset = 0;
29    bool                    fRunning = false;
30    double                  fCurrentTime = 0.0;
31    double                  fLastWallTime = 0.0;
32    double                  fTimeToShowNextFrame = 0.0;
33
34    void onDrawBackground(SkCanvas* canvas) override {
35        SkFont font;
36        font.setSize(20);
37
38        SkString str = SkStringPrintf("Press '%c' to start/pause; '%c' to reset.",
39                kPauseKey, kResetKey);
40        const char* text = str.c_str();
41        SkRect bounds;
42        font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
43        fYOffset = bounds.height();
44
45        canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 5, fYOffset, font, SkPaint());
46        fYOffset *= 2;
47    }
48
49    void onDrawContent(SkCanvas* canvas) override {
50        if (!fImage) {
51            return;
52        }
53
54        canvas->translate(0, fYOffset);
55
56        canvas->drawDrawable(fImage.get());
57        canvas->drawDrawable(fDrawable.get(), fImage->getBounds().width(), 0);
58    }
59
60    bool onAnimate(double nanos) override {
61        if (!fImage) {
62            return false;
63        }
64
65        const double lastWallTime = fLastWallTime;
66        fLastWallTime = TimeUtils::NanosToMSec(nanos);
67
68        if (fRunning) {
69            fCurrentTime += fLastWallTime - lastWallTime;
70            if (fCurrentTime > fTimeToShowNextFrame) {
71                fTimeToShowNextFrame += fImage->decodeNextFrame();
72                if (fImage->isFinished()) {
73                    fRunning = false;
74                }
75            }
76        }
77
78        return true;
79    }
80
81    void onOnceBeforeDraw() override {
82        sk_sp<SkData> file(GetResourceAsData("images/alphabetAnim.gif"));
83        std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(file));
84        if (!codec) {
85            return;
86        }
87
88        fImage = SkAnimatedImage::Make(SkAndroidCodec::MakeFromCodec(std::move(codec)));
89        if (!fImage) {
90            return;
91        }
92
93        fTimeToShowNextFrame = fImage->currentFrameDuration();
94        SkPictureRecorder recorder;
95        auto canvas = recorder.beginRecording(fImage->getBounds());
96        canvas->drawDrawable(fImage.get());
97        fDrawable = recorder.finishRecordingAsDrawable();
98    }
99
100    SkString name() override { return SkString("AnimatedImage"); }
101
102    bool onChar(SkUnichar uni) override {
103        if (fImage) {
104            switch (uni) {
105                case kPauseKey:
106                    fRunning = !fRunning;
107                    if (!fImage->isFinished()) {
108                        return true;
109                    }
110                    [[fallthrough]];
111                case kResetKey:
112                    fImage->reset();
113                    fCurrentTime = fLastWallTime;
114                    fTimeToShowNextFrame = fCurrentTime + fImage->currentFrameDuration();
115                    return true;
116                default:
117                    break;
118            }
119        }
120        return false;
121    }
122};
123
124DEF_SAMPLE( return new SampleAnimatedImage(); )
125