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