From 7a10b332a37dab94b1c59685714f6d8c28fc84b9 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Fri, 12 Jan 2018 11:24:30 -0500 Subject: Add an SkDrawable for animated images (e.g. GIF) Bug: b/63909536 SkAnimatedImage is a simple drawable for animating a GIF. Thread-safety is left up to the client. At most two bitmaps are stored in the drawable; one for the current frame and one for a frame that may need to be restored. The backup frame prevents some cases where we would otherwise have to re-decode from the beginning of the image. The API lets the client set the time value, and decodes to match that time. TODO: - Callback for when the animation is complete - Ability to use SkAndroidCodec - Modify the loop count (or leave that up to client?) - Better and/or client-specific caching Other changes: - Add a sample which animates a GIF - Reenable SK_CODEC_PRINTF for debug builds and Android Change-Id: I945ffbccdb6008f2a05ed4d9b2af869a261fb300 Reviewed-on: https://skia-review.googlesource.com/93420 Reviewed-by: Derek Sollenberger Commit-Queue: Leon Scroggins --- samplecode/SampleAnimatedImage.cpp | 130 +++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 samplecode/SampleAnimatedImage.cpp (limited to 'samplecode/SampleAnimatedImage.cpp') diff --git a/samplecode/SampleAnimatedImage.cpp b/samplecode/SampleAnimatedImage.cpp new file mode 100644 index 0000000000..96e53b8e4e --- /dev/null +++ b/samplecode/SampleAnimatedImage.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkAnimatedImage.h" +#include "SkAnimTimer.h" +#include "SkCanvas.h" +#include "SkCodec.h" +#include "SkPaint.h" +#include "SkPictureRecorder.h" +#include "SkRect.h" +#include "SkScalar.h" +#include "SkString.h" + +#include "SampleCode.h" +#include "Resources.h" + +static constexpr char kPauseKey = 'p'; +static constexpr char kResetKey = 'r'; + +class SampleAnimatedImage : public SampleView { +public: + SampleAnimatedImage() + : INHERITED() + , fRunning(false) + , fYOffset(0) + {} + +protected: + void onDrawBackground(SkCanvas* canvas) override { + SkPaint paint; + paint.setAntiAlias(true); + constexpr SkScalar kTextSize = 20; + paint.setTextSize(kTextSize); + + SkString str = SkStringPrintf("Press '%c' to start/pause; '%c' to reset.", + kPauseKey, kResetKey); + const char* text = str.c_str(); + SkRect bounds; + paint.measureText(text, strlen(text), &bounds); + fYOffset = bounds.height(); + + canvas->drawText(text, strlen(text), 5, fYOffset, paint); + fYOffset *= 2; + } + + void onDrawContent(SkCanvas* canvas) override { + if (!fImage) { + return; + } + + canvas->translate(0, fYOffset); + + canvas->drawDrawable(fImage.get()); + canvas->drawDrawable(fDrawable.get(), fImage->getBounds().width(), 0); + } + + bool onAnimate(const SkAnimTimer& animTimer) override { + if (!fImage) { + return false; + } + + fImage->update(animTimer.msec()); + return true; + } + + void onOnceBeforeDraw() override { + sk_sp file(GetResourceAsData("images/alphabetAnim.gif")); + std::unique_ptr codec(SkCodec::MakeFromData(file)); + if (!codec) { + return; + } + + fImage = SkAnimatedImage::MakeFromCodec(std::move(codec)); + if (!fImage) { + return; + } + + SkPictureRecorder recorder; + auto canvas = recorder.beginRecording(fImage->getBounds()); + canvas->drawDrawable(fImage.get()); + fDrawable = recorder.finishRecordingAsDrawable(); + } + + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "AnimatedImage"); + return true; + } + + SkUnichar uni; + if (fImage && SampleCode::CharQ(*evt, &uni)) { + switch (uni) { + case kPauseKey: + if (fRunning) { + fImage->stop(); + fRunning = false; + } else { + fImage->start(); + fRunning = true; + } + return true; + case kResetKey: + fImage->reset(); + return true; + default: + break; + } + } + return this->INHERITED::onQuery(evt); + } + +private: + sk_sp fImage; + sk_sp fDrawable; + bool fRunning; + SkScalar fYOffset; + typedef SampleView INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static SkView* MyFactory() { + return new SampleAnimatedImage; +} + +static SkViewRegister reg(MyFactory); -- cgit v1.2.3