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 22 static constexpr char kPauseKey = 'p'; 23 static constexpr char kResetKey = 'r'; 24 25 class 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 onDrawBackground(SkCanvas * canvas)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 onDrawContent(SkCanvas * canvas)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 onAnimate(double nanos)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 onOnceBeforeDraw()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 name()100 SkString name() override { return SkString("AnimatedImage"); } 101 onChar(SkUnichar uni)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 124 DEF_SAMPLE( return new SampleAnimatedImage(); ) 125