You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.0 KiB
140 lines
4.0 KiB
/* |
|
* 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 "SkAndroidCodec.h" |
|
#include "SkAnimatedImage.h" |
|
#include "SkAnimTimer.h" |
|
#include "SkCanvas.h" |
|
#include "SkFont.h" |
|
#include "SkPaint.h" |
|
#include "SkPictureRecorder.h" |
|
#include "SkRect.h" |
|
#include "SkScalar.h" |
|
#include "SkString.h" |
|
|
|
#include "Sample.h" |
|
#include "Resources.h" |
|
|
|
static constexpr char kPauseKey = 'p'; |
|
static constexpr char kResetKey = 'r'; |
|
|
|
class SampleAnimatedImage : public Sample { |
|
public: |
|
SampleAnimatedImage() |
|
: INHERITED() |
|
, fYOffset(0) |
|
{} |
|
|
|
protected: |
|
void onDrawBackground(SkCanvas* canvas) override { |
|
SkFont font; |
|
font.setSize(20); |
|
|
|
SkString str = SkStringPrintf("Press '%c' to start/pause; '%c' to reset.", |
|
kPauseKey, kResetKey); |
|
const char* text = str.c_str(); |
|
SkRect bounds; |
|
font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &bounds); |
|
fYOffset = bounds.height(); |
|
|
|
canvas->drawSimpleText(text, strlen(text), kUTF8_SkTextEncoding, 5, fYOffset, font, SkPaint()); |
|
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; |
|
} |
|
|
|
const double lastWallTime = fLastWallTime; |
|
fLastWallTime = animTimer.msec(); |
|
|
|
if (fRunning) { |
|
fCurrentTime += fLastWallTime - lastWallTime; |
|
if (fCurrentTime > fTimeToShowNextFrame) { |
|
fTimeToShowNextFrame += fImage->decodeNextFrame(); |
|
if (fImage->isFinished()) { |
|
fRunning = false; |
|
} |
|
} |
|
} |
|
|
|
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::Make(SkAndroidCodec::MakeFromCodec(std::move(codec))); |
|
if (!fImage) { |
|
return; |
|
} |
|
|
|
fTimeToShowNextFrame = fImage->currentFrameDuration(); |
|
SkPictureRecorder recorder; |
|
auto canvas = recorder.beginRecording(fImage->getBounds()); |
|
canvas->drawDrawable(fImage.get()); |
|
fDrawable = recorder.finishRecordingAsDrawable(); |
|
} |
|
|
|
bool onQuery(Sample::Event* evt) override { |
|
if (Sample::TitleQ(*evt)) { |
|
Sample::TitleR(evt, "AnimatedImage"); |
|
return true; |
|
} |
|
|
|
SkUnichar uni; |
|
if (fImage && Sample::CharQ(*evt, &uni)) { |
|
switch (uni) { |
|
case kPauseKey: |
|
fRunning = !fRunning; |
|
if (fImage->isFinished()) { |
|
// fall through |
|
} else { |
|
return true; |
|
} |
|
case kResetKey: |
|
fImage->reset(); |
|
fCurrentTime = fLastWallTime; |
|
fTimeToShowNextFrame = fCurrentTime + fImage->currentFrameDuration(); |
|
return true; |
|
default: |
|
break; |
|
} |
|
} |
|
return this->INHERITED::onQuery(evt); |
|
} |
|
|
|
private: |
|
sk_sp<SkAnimatedImage> fImage; |
|
sk_sp<SkDrawable> fDrawable; |
|
SkScalar fYOffset; |
|
bool fRunning = false; |
|
double fCurrentTime = 0.0; |
|
double fLastWallTime = 0.0; |
|
double fTimeToShowNextFrame = 0.0; |
|
typedef Sample INHERITED; |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
DEF_SAMPLE( return new SampleAnimatedImage(); )
|
|
|