diff options
author | Leon Scroggins III <scroggo@google.com> | 2018-01-12 11:24:30 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-12 19:36:11 +0000 |
commit | 7a10b332a37dab94b1c59685714f6d8c28fc84b9 (patch) | |
tree | 45a7847d658bd1d9ff3e6499633c512933c0b1e3 /samplecode | |
parent | 65fa8ca85ef146340ddea61bb08c182df499ca62 (diff) |
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 <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'samplecode')
-rw-r--r-- | samplecode/SampleAnimatedImage.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
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<SkData> file(GetResourceAsData("images/alphabetAnim.gif")); + std::unique_ptr<SkCodec> 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<SkAnimatedImage> fImage; + sk_sp<SkDrawable> fDrawable; + bool fRunning; + SkScalar fYOffset; + typedef SampleView INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static SkView* MyFactory() { + return new SampleAnimatedImage; +} + +static SkViewRegister reg(MyFactory); |