blob: 13f45585614d26521fe8f4186bc34bd64186df5f [file] [log] [blame]
* Copyright 2017 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include "base/memory/ref_counted.h"
#include "base/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "cobalt/math/size_f.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/render_tree/image_node.h"
namespace cobalt {
namespace loader {
namespace image {
// This class represents a general image that is stored in memory. It can be
// either a static image or an animated image. It is intended to be cached in
// an ImageCache.
class Image : public base::RefCountedThreadSafe<Image> {
virtual const math::Size& GetSize() const = 0;
virtual uint32 GetEstimatedSizeInBytes() const = 0;
virtual bool IsOpaque() const = 0;
virtual bool IsAnimated() const = 0;
virtual ~Image() {}
friend class base::RefCountedThreadSafe<Image>;
// StaticImage is a wrapper around render_tree::Image. The images will be
// decoded immediately after fetching and stored in memory.
class StaticImage : public Image {
explicit StaticImage(scoped_refptr<render_tree::Image> image)
: image_(image) {
const math::Size& GetSize() const override { return image_->GetSize(); }
uint32 GetEstimatedSizeInBytes() const override {
return image_->GetEstimatedSizeInBytes();
bool IsAnimated() const override { return false; }
bool IsOpaque() const override { return image_->IsOpaque(); }
scoped_refptr<render_tree::Image> image() { return image_; }
scoped_refptr<render_tree::Image> image_;
// Concrete implementations of AnimatedImage should include mechanisms that
// balance the tradeoff between space usage and efficiency of decoding frames
// when playing animation.
class AnimatedImage : public Image {
// FrameProvider nested classes are used as "frame containers". Typically
// they will be created by an AnimatedImage and have frames pushed into them
// by the creating AnimatedImage object. They can be handed to consumers to
// have frames pulled out of them. Its purpose is to allow AnimatedImage
// objects to be destroyed without affecting consumers of the FrameProvider.
// If the AnimatedImage is destroyed before the consumer is done pulling
// frames out of FrameProvider, they will simply be left with the last frame
// that was in there.
class FrameProvider : public base::RefCountedThreadSafe<FrameProvider> {
FrameProvider() : frame_consumed_(true) {}
void SetFrame(const scoped_refptr<render_tree::Image>& frame) {
base::AutoLock lock(mutex_);
frame_ = frame;
frame_consumed_ = false;
bool FrameConsumed() const {
base::AutoLock lock(mutex_);
return frame_consumed_;
scoped_refptr<render_tree::Image> GetFrame() {
base::AutoLock lock(mutex_);
frame_consumed_ = true;
return frame_;
virtual ~FrameProvider() {}
friend class base::RefCountedThreadSafe<FrameProvider>;
mutable base::Lock mutex_;
// True if a call to FrameConsumed() has been made after the last call to
// SetFrame().
bool frame_consumed_;
scoped_refptr<render_tree::Image> frame_;
bool IsAnimated() const override { return true; }
bool IsOpaque() const override { return false; }
// Start playing the animation, decoding on the given message loop.
// Implementation should be thread safe.
virtual void Play(
const scoped_refptr<base::MessageLoopProxy>& message_loop) = 0;
// Stop playing the animation.
virtual void Stop() = 0;
// Returns a FrameProvider object from which frames can be pulled out of.
// The AnimatedImage object is expected to push frames into the FrameProvider
// as it generates them.
virtual scoped_refptr<FrameProvider> GetFrameProvider() = 0;
// This callback is intended to be used in a render_tree::AnimateNode.
static void AnimateCallback(
scoped_refptr<FrameProvider> frame_provider,
const math::RectF& destination_rect,
const math::Matrix3F& local_transform,
render_tree::ImageNode::Builder* image_node_builder) {
image_node_builder->source = frame_provider->GetFrame();
image_node_builder->destination_rect = destination_rect;
image_node_builder->local_transform = local_transform;
} // namespace image
} // namespace loader
} // namespace cobalt