Commit f45bb828 authored by Malay Keshav's avatar Malay Keshav Committed by Commit Bot

Implement a thread safe wrapper for Skottie

This patch implements a thread safe wrapper for the core skottie
animation object. We want to share the same animation resource file for
multiple SkiaVectorAnimation objects. This would allow us to do that.

This is also needed to implement the Phase 2 and Phase 3 of
rasterization where the rasterization would be handled by different
threads.

go/cros-skottie

Bug: 890512, 890224
Change-Id: I40371e58985ea4db5661f28a2ee8b31aab354a03
Component: Skia vector animation, skottie
Reviewed-on: https://chromium-review.googlesource.com/c/1253071Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596118}
parent e4453a95
...@@ -224,6 +224,8 @@ jumbo_component("gfx") { ...@@ -224,6 +224,8 @@ jumbo_component("gfx") {
"skia_vector_animation.cc", "skia_vector_animation.cc",
"skia_vector_animation.h", "skia_vector_animation.h",
"skia_vector_animation_observer.h", "skia_vector_animation_observer.h",
"skottie_wrapper.cc",
"skottie_wrapper.h",
] ]
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/gfx/skia_vector_animation_observer.h" #include "ui/gfx/skia_vector_animation_observer.h"
#include "ui/gfx/skottie_wrapper.h"
namespace gfx { namespace gfx {
...@@ -68,15 +69,8 @@ double SkiaVectorAnimation::TimerControl::GetNormalizedEndOffset() const { ...@@ -68,15 +69,8 @@ double SkiaVectorAnimation::TimerControl::GetNormalizedEndOffset() const {
return end_offset_.InMillisecondsF() * progress_per_millisecond_; return end_offset_.InMillisecondsF() * progress_per_millisecond_;
} }
SkiaVectorAnimation::SkiaVectorAnimation( SkiaVectorAnimation::SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie)
const scoped_refptr<base::RefCountedMemory>& data_stream) { : skottie_(skottie) {}
TRACE_EVENT0("ui", "SkiaVectorAnimation Parse");
SkMemoryStream sk_stream(data_stream->front(), data_stream->size());
animation_ = skottie::Animation::Make(&sk_stream);
}
SkiaVectorAnimation::SkiaVectorAnimation(std::unique_ptr<SkMemoryStream> stream)
: animation_(skottie::Animation::Make(stream.get())) {}
SkiaVectorAnimation::~SkiaVectorAnimation() {} SkiaVectorAnimation::~SkiaVectorAnimation() {}
...@@ -88,13 +82,13 @@ void SkiaVectorAnimation::SetAnimationObserver( ...@@ -88,13 +82,13 @@ void SkiaVectorAnimation::SetAnimationObserver(
base::TimeDelta SkiaVectorAnimation::GetAnimationDuration() const { base::TimeDelta SkiaVectorAnimation::GetAnimationDuration() const {
return base::TimeDelta::FromMilliseconds( return base::TimeDelta::FromMilliseconds(
std::floor(SkScalarToFloat(animation_->duration()) * 1000.f)); std::floor(SkScalarToFloat(skottie_->duration()) * 1000.f));
} }
gfx::Size SkiaVectorAnimation::GetOriginalSize() const { gfx::Size SkiaVectorAnimation::GetOriginalSize() const {
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
// The size should have no fractional component. // The size should have no fractional component.
gfx::SizeF float_size = gfx::SkSizeToSizeF(animation_->size()); gfx::SizeF float_size = gfx::SkSizeToSizeF(skottie_->size());
gfx::Size rounded_size = gfx::ToRoundedSize(float_size); gfx::Size rounded_size = gfx::ToRoundedSize(float_size);
float height_diff = std::abs(float_size.height() - rounded_size.height()); float height_diff = std::abs(float_size.height() - rounded_size.height());
...@@ -103,7 +97,7 @@ gfx::Size SkiaVectorAnimation::GetOriginalSize() const { ...@@ -103,7 +97,7 @@ gfx::Size SkiaVectorAnimation::GetOriginalSize() const {
DCHECK_LE(height_diff, std::numeric_limits<float>::epsilon()); DCHECK_LE(height_diff, std::numeric_limits<float>::epsilon());
DCHECK_LE(width_diff, std::numeric_limits<float>::epsilon()); DCHECK_LE(width_diff, std::numeric_limits<float>::epsilon());
#endif #endif
return gfx::ToRoundedSize(gfx::SkSizeToSizeF(animation_->size())); return gfx::ToRoundedSize(gfx::SkSizeToSizeF(skottie_->size()));
} }
void SkiaVectorAnimation::Start(Style style) { void SkiaVectorAnimation::Start(Style style) {
...@@ -158,8 +152,7 @@ float SkiaVectorAnimation::GetCurrentProgress() const { ...@@ -158,8 +152,7 @@ float SkiaVectorAnimation::GetCurrentProgress() const {
} else { } else {
// It may be that the timer hasn't been initialized which may happen if // It may be that the timer hasn't been initialized which may happen if
// the animation was paused while it was in |kScheculePlay| state. // the animation was paused while it was in |kScheculePlay| state.
return scheduled_start_offset_.InMillisecondsF() / return scheduled_start_offset_.InMillisecondsF() / skottie_->duration();
animation_->duration();
} }
case PlayState::kSchedulePlay: case PlayState::kSchedulePlay:
case PlayState::kPlaying: case PlayState::kPlaying:
...@@ -214,17 +207,16 @@ void SkiaVectorAnimation::PaintFrame(gfx::Canvas* canvas, ...@@ -214,17 +207,16 @@ void SkiaVectorAnimation::PaintFrame(gfx::Canvas* canvas,
DCHECK_GE(t, 0.f); DCHECK_GE(t, 0.f);
DCHECK_LE(t, 1.f); DCHECK_LE(t, 1.f);
animation_->seek(t);
float scale = canvas->UndoDeviceScaleFactor(); float scale = canvas->UndoDeviceScaleFactor();
gfx::Size pixel_size = gfx::ScaleToRoundedSize(size, scale);
SkBitmap bitmap; SkBitmap bitmap;
bitmap.allocN32Pixels(std::round(size.width() * scale), bitmap.allocN32Pixels(std::round(pixel_size.width()),
std::round(size.height() * scale), false); std::round(pixel_size.height()), false);
SkCanvas skcanvas(bitmap); SkCanvas skcanvas(bitmap);
skcanvas.clear(SK_ColorTRANSPARENT); skcanvas.clear(SK_ColorTRANSPARENT);
SkRect dst = SkRect::MakeXYWH(0, 0, std::round(size.width() * scale),
std::round(size.height() * scale)); skottie_->Draw(&skcanvas, t, pixel_size);
animation_->render(&skcanvas, &dst);
canvas->DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), 0, 0); canvas->DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), 0, 0);
} }
......
...@@ -20,6 +20,7 @@ namespace gfx { ...@@ -20,6 +20,7 @@ namespace gfx {
class Canvas; class Canvas;
class SkiaVectorAnimationTest; class SkiaVectorAnimationTest;
class SkiaVectorAnimationObserver; class SkiaVectorAnimationObserver;
class SkottieWrapper;
// This class is a wrapper over the Skia object for lottie vector graphic // This class is a wrapper over the Skia object for lottie vector graphic
// animations. It has its own timeline manager for the animation controls. The // animations. It has its own timeline manager for the animation controls. The
...@@ -80,9 +81,7 @@ class GFX_EXPORT SkiaVectorAnimation { ...@@ -80,9 +81,7 @@ class GFX_EXPORT SkiaVectorAnimation {
kLoop // Same as LINEAR, except the animation repeats after it ends. kLoop // Same as LINEAR, except the animation repeats after it ends.
}; };
explicit SkiaVectorAnimation( explicit SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie);
const scoped_refptr<base::RefCountedMemory>& data_stream);
explicit SkiaVectorAnimation(std::unique_ptr<SkMemoryStream> stream);
~SkiaVectorAnimation(); ~SkiaVectorAnimation();
void SetAnimationObserver(SkiaVectorAnimationObserver* Observer); void SetAnimationObserver(SkiaVectorAnimationObserver* Observer);
...@@ -138,6 +137,9 @@ class GFX_EXPORT SkiaVectorAnimation { ...@@ -138,6 +137,9 @@ class GFX_EXPORT SkiaVectorAnimation {
// paint. // paint.
void PaintFrame(gfx::Canvas* canvas, float t, const gfx::Size& size); void PaintFrame(gfx::Canvas* canvas, float t, const gfx::Size& size);
// Returns the skottie object that contins the animation data.
scoped_refptr<SkottieWrapper> skottie() const { return skottie_; }
private: private:
friend class SkiaVectorAnimationTest; friend class SkiaVectorAnimationTest;
...@@ -229,7 +231,7 @@ class GFX_EXPORT SkiaVectorAnimation { ...@@ -229,7 +231,7 @@ class GFX_EXPORT SkiaVectorAnimation {
SkiaVectorAnimationObserver* observer_ = nullptr; SkiaVectorAnimationObserver* observer_ = nullptr;
sk_sp<skottie::Animation> animation_; scoped_refptr<SkottieWrapper> skottie_;
DISALLOW_COPY_AND_ASSIGN(SkiaVectorAnimation); DISALLOW_COPY_AND_ASSIGN(SkiaVectorAnimation);
}; };
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkStream.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/skia_vector_animation_observer.h" #include "ui/gfx/skia_vector_animation_observer.h"
#include "ui/gfx/skottie_wrapper.h"
namespace gfx { namespace gfx {
namespace { namespace {
...@@ -101,6 +102,9 @@ class SkiaVectorAnimationTest : public testing::Test { ...@@ -101,6 +102,9 @@ class SkiaVectorAnimationTest : public testing::Test {
void SetUp() override { void SetUp() override {
canvas_.reset(new gfx::Canvas(gfx::Size(kAnimationWidth, kAnimationHeight), canvas_.reset(new gfx::Canvas(gfx::Size(kAnimationWidth, kAnimationHeight),
1.f, false)); 1.f, false));
skottie_ = base::MakeRefCounted<SkottieWrapper>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
} }
void TearDown() override { animation_.reset(nullptr); } void TearDown() override { animation_.reset(nullptr); }
...@@ -186,6 +190,7 @@ class SkiaVectorAnimationTest : public testing::Test { ...@@ -186,6 +190,7 @@ class SkiaVectorAnimationTest : public testing::Test {
protected: protected:
std::unique_ptr<SkiaVectorAnimation> animation_; std::unique_ptr<SkiaVectorAnimation> animation_;
scoped_refptr<SkottieWrapper> skottie_;
private: private:
std::unique_ptr<gfx::Canvas> canvas_; std::unique_ptr<gfx::Canvas> canvas_;
...@@ -197,15 +202,17 @@ class SkiaVectorAnimationTest : public testing::Test { ...@@ -197,15 +202,17 @@ class SkiaVectorAnimationTest : public testing::Test {
TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) { TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) {
auto bytes = base::MakeRefCounted<base::RefCountedBytes>( auto bytes = base::MakeRefCounted<base::RefCountedBytes>(
std::vector<unsigned char>(kData, kData + std::strlen(kData))); std::vector<unsigned char>(kData, kData + std::strlen(kData)));
animation_ = std::make_unique<SkiaVectorAnimation>(bytes.get()); skottie_ = base::MakeRefCounted<SkottieWrapper>(bytes.get());
animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth);
EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight);
EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(), EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(),
kAnimationDuration); kAnimationDuration);
EXPECT_TRUE(IsStopped()); EXPECT_TRUE(IsStopped());
animation_ = std::make_unique<SkiaVectorAnimation>( skottie_ = base::MakeRefCounted<SkottieWrapper>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth);
EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight);
EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(), EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(),
...@@ -215,8 +222,6 @@ TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) { ...@@ -215,8 +222,6 @@ TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) {
TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) { TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) {
TestAnimationObserver observer; TestAnimationObserver observer;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
// Advance clock by 300 milliseconds. // Advance clock by 300 milliseconds.
...@@ -256,8 +261,6 @@ TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) { ...@@ -256,8 +261,6 @@ TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) {
TEST_F(SkiaVectorAnimationTest, StopLinearAnimation) { TEST_F(SkiaVectorAnimationTest, StopLinearAnimation) {
TestAnimationObserver observer; TestAnimationObserver observer;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
// Advance clock by 300 milliseconds. // Advance clock by 300 milliseconds.
...@@ -285,8 +288,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLinearAnimation) { ...@@ -285,8 +288,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLinearAnimation) {
TestAnimationObserver observer; TestAnimationObserver observer;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
// Advance clock by 300 milliseconds. // Advance clock by 300 milliseconds.
...@@ -344,8 +345,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLinearAnimation) { ...@@ -344,8 +345,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLinearAnimation) {
const int start_time_ms = 400; const int start_time_ms = 400;
const int duration_ms = 1000; const int duration_ms = 1000;
const float total_duration_ms = kAnimationDuration * 1000.f; const float total_duration_ms = kAnimationDuration * 1000.f;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -390,8 +389,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLinearAnimation) { ...@@ -390,8 +389,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLinearAnimation) {
TEST_F(SkiaVectorAnimationTest, PlayLoopAnimation) { TEST_F(SkiaVectorAnimationTest, PlayLoopAnimation) {
TestAnimationObserver observer; TestAnimationObserver observer;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
// Advance clock by 300 milliseconds. // Advance clock by 300 milliseconds.
...@@ -436,8 +433,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLoopAnimation) { ...@@ -436,8 +433,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLoopAnimation) {
const int duration_ms = 1000; const int duration_ms = 1000;
const float total_duration_ms = kAnimationDuration * 1000.f; const float total_duration_ms = kAnimationDuration * 1000.f;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -498,8 +493,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLoopAnimation) { ...@@ -498,8 +493,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLoopAnimation) {
const int start_time_ms = 400; const int start_time_ms = 400;
const int duration_ms = 1000; const int duration_ms = 1000;
const float total_duration_ms = kAnimationDuration * 1000.f; const float total_duration_ms = kAnimationDuration * 1000.f;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -550,8 +543,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLoopAnimation) { ...@@ -550,8 +543,6 @@ TEST_F(SkiaVectorAnimationTest, PausingLoopAnimation) {
} }
TEST_F(SkiaVectorAnimationTest, PlayThrobbingAnimation) { TEST_F(SkiaVectorAnimationTest, PlayThrobbingAnimation) {
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -607,8 +598,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfThrobbingAnimation) { ...@@ -607,8 +598,6 @@ TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfThrobbingAnimation) {
const int duration_ms = 1000; const int duration_ms = 1000;
const float total_duration_ms = kAnimationDuration * 1000.f; const float total_duration_ms = kAnimationDuration * 1000.f;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -688,8 +677,6 @@ TEST_F(SkiaVectorAnimationTest, PausingThrobbingAnimation) { ...@@ -688,8 +677,6 @@ TEST_F(SkiaVectorAnimationTest, PausingThrobbingAnimation) {
const int start_time_ms = 400; const int start_time_ms = 400;
const int duration_ms = 1000; const int duration_ms = 1000;
const float total_duration_ms = kAnimationDuration * 1000.f; const float total_duration_ms = kAnimationDuration * 1000.f;
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
AdvanceClock(200); AdvanceClock(200);
...@@ -782,8 +769,6 @@ TEST_F(SkiaVectorAnimationTest, PauseBeforePlay) { ...@@ -782,8 +769,6 @@ TEST_F(SkiaVectorAnimationTest, PauseBeforePlay) {
// Test to see if the race condition is handled correctly. It may happen that // Test to see if the race condition is handled correctly. It may happen that
// we pause the video before it even starts playing. // we pause the video before it even starts playing.
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
TestAnimationObserver observer; TestAnimationObserver observer;
animation_->SetAnimationObserver(&observer); animation_->SetAnimationObserver(&observer);
...@@ -814,8 +799,6 @@ TEST_F(SkiaVectorAnimationTest, PauseBeforePlay) { ...@@ -814,8 +799,6 @@ TEST_F(SkiaVectorAnimationTest, PauseBeforePlay) {
TEST_F(SkiaVectorAnimationTest, PaintTest) { TEST_F(SkiaVectorAnimationTest, PaintTest) {
std::unique_ptr<gfx::Canvas> canvas(new gfx::Canvas( std::unique_ptr<gfx::Canvas> canvas(new gfx::Canvas(
gfx::Size(kAnimationWidth, kAnimationHeight), 1.f, false)); gfx::Size(kAnimationWidth, kAnimationHeight), 1.f, false));
animation_ = std::make_unique<SkiaVectorAnimation>(
std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
// Advance clock by 300 milliseconds. // Advance clock by 300 milliseconds.
AdvanceClock(300); AdvanceClock(300);
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/skottie_wrapper.h"
#include "base/memory/ref_counted_memory.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkStream.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
SkottieWrapper::SkottieWrapper(
const scoped_refptr<base::RefCountedMemory>& data_stream) {
TRACE_EVENT0("ui", "SkottieWrapper Parse");
SkMemoryStream sk_stream(data_stream->front(), data_stream->size());
animation_ = skottie::Animation::Make(&sk_stream);
}
SkottieWrapper::SkottieWrapper(std::unique_ptr<SkMemoryStream> stream)
: animation_(skottie::Animation::Make(stream.get())) {}
SkottieWrapper::~SkottieWrapper() {}
void SkottieWrapper::Draw(SkCanvas* canvas, float t, const gfx::Size& size) {
SkRect dst = SkRect::MakeXYWH(0, 0, size.width(), size.height());
{
base::AutoLock lock(lock_);
animation_->seek(t);
animation_->render(canvas, &dst);
}
}
} // namespace gfx
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_SKOTTIE_WRAPPER_H_
#define UI_GFX_SKOTTIE_WRAPPER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "third_party/skia/modules/skottie/include/Skottie.h"
#include "ui/gfx/gfx_export.h"
class SkCanvas;
class SkMemoryStream;
namespace base {
class RefCountedMemory;
} // namespace base
namespace gfx {
class Size;
// A wrapper over Skia's Skottie object that can be shared by multiple
// SkiaVectorAnimation objects. This class is thread safe when performing a draw
// on an SkCanvas.
class GFX_EXPORT SkottieWrapper
: public base::RefCountedThreadSafe<SkottieWrapper> {
public:
explicit SkottieWrapper(
const scoped_refptr<base::RefCountedMemory>& data_stream);
explicit SkottieWrapper(std::unique_ptr<SkMemoryStream> stream);
// A thread safe call that will draw an image of size |size| for the frame at
// normalized time instant |t| onto the |canvas|.
void Draw(SkCanvas* canvas, float t, const Size& size);
float duration() const { return animation_->duration(); }
SkSize size() const { return animation_->size(); }
private:
friend class base::RefCountedThreadSafe<SkottieWrapper>;
~SkottieWrapper();
base::Lock lock_;
sk_sp<skottie::Animation> animation_;
DISALLOW_COPY_AND_ASSIGN(SkottieWrapper);
};
} // namespace gfx
#endif // UI_GFX_SKOTTIE_WRAPPER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment