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