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.
255 lines
8.3 KiB
255 lines
8.3 KiB
/*
|
|
* Copyright 2019 Google LLC
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef SkResources_DEFINED
|
|
#define SkResources_DEFINED
|
|
|
|
#include "include/core/SkData.h"
|
|
#include "include/core/SkMatrix.h"
|
|
#include "include/core/SkRefCnt.h"
|
|
#include "include/core/SkSamplingOptions.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkTypeface.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/private/SkMutex.h"
|
|
#include "include/private/SkTHash.h"
|
|
|
|
#include <memory>
|
|
|
|
class SkAnimCodecPlayer;
|
|
class SkImage;
|
|
|
|
namespace skresources {
|
|
|
|
/**
|
|
* Image asset proxy interface.
|
|
*/
|
|
class SK_API ImageAsset : public SkRefCnt {
|
|
public:
|
|
/**
|
|
* Returns true if the image asset is animated.
|
|
*/
|
|
virtual bool isMultiFrame() = 0;
|
|
|
|
/**
|
|
* DEPRECATED: override getFrameData() instead.
|
|
*
|
|
* Returns the SkImage for a given frame.
|
|
*
|
|
* If the image asset is static, getFrame() is only called once, at animation load time.
|
|
* Otherwise, this gets invoked every time the animation time is adjusted (on every seek).
|
|
*
|
|
* Embedders should cache and serve the same SkImage whenever possible, for efficiency.
|
|
*
|
|
* @param t Frame time code, in seconds, relative to the image layer timeline origin
|
|
* (in-point).
|
|
*/
|
|
virtual sk_sp<SkImage> getFrame(float t);
|
|
|
|
struct FrameData {
|
|
// SkImage payload.
|
|
sk_sp<SkImage> image;
|
|
// Resampling parameters.
|
|
SkSamplingOptions sampling;
|
|
// Additional image transform to be applied before AE scaling rules.
|
|
SkMatrix matrix = SkMatrix::I();
|
|
};
|
|
|
|
/**
|
|
* Returns the payload for a given frame.
|
|
*
|
|
* If the image asset is static, getFrameData() is only called once, at animation load time.
|
|
* Otherwise, this gets invoked every time the animation time is adjusted (on every seek).
|
|
*
|
|
* Embedders should cache and serve the same SkImage whenever possible, for efficiency.
|
|
*
|
|
* @param t Frame time code, in seconds, relative to the image layer timeline origin
|
|
* (in-point).
|
|
*/
|
|
virtual FrameData getFrameData(float t);
|
|
};
|
|
|
|
class MultiFrameImageAsset final : public ImageAsset {
|
|
public:
|
|
/**
|
|
* By default, images are decoded on-the-fly, at rasterization time.
|
|
* Large images may cause jank as decoding is expensive (and can thrash internal caches).
|
|
*
|
|
* Pass |predecode| true to force-decode all images upfront, at the cost of potentially more RAM
|
|
* and slower animation build times.
|
|
*/
|
|
static sk_sp<MultiFrameImageAsset> Make(sk_sp<SkData>, bool predecode = false);
|
|
|
|
bool isMultiFrame() override;
|
|
|
|
sk_sp<SkImage> getFrame(float t) override;
|
|
|
|
private:
|
|
explicit MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer>, bool predecode);
|
|
|
|
sk_sp<SkImage> generateFrame(float t);
|
|
|
|
std::unique_ptr<SkAnimCodecPlayer> fPlayer;
|
|
sk_sp<SkImage> fCachedFrame;
|
|
bool fPreDecode;
|
|
|
|
using INHERITED = ImageAsset;
|
|
};
|
|
|
|
/**
|
|
* External track (e.g. audio playback) interface.
|
|
*
|
|
* Used to wrap data payload and playback controllers.
|
|
*/
|
|
class ExternalTrackAsset : public SkRefCnt {
|
|
public:
|
|
/**
|
|
* Playback control callback, emitted for each corresponding Animation::seek().
|
|
*
|
|
* @param t Frame time code, in seconds, relative to the layer's timeline origin
|
|
* (in-point).
|
|
*
|
|
* Negative |t| values are used to signal off state (stop playback outside layer span).
|
|
*/
|
|
virtual void seek(float t) = 0;
|
|
};
|
|
|
|
/**
|
|
* ResourceProvider is an interface that lets rich-content modules defer loading of external
|
|
* resources (images, fonts, etc.) to embedding clients.
|
|
*/
|
|
class SK_API ResourceProvider : public SkRefCnt {
|
|
public:
|
|
/**
|
|
* Load a generic resource (currently only nested animations) specified by |path| + |name|,
|
|
* and return as an SkData.
|
|
*/
|
|
virtual sk_sp<SkData> load(const char[] /* resource_path */,
|
|
const char[] /* resource_name */) const {
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Load an image asset specified by |path| + |name|, and returns the corresponding
|
|
* ImageAsset proxy.
|
|
*/
|
|
virtual sk_sp<ImageAsset> loadImageAsset(const char[] /* resource_path */,
|
|
const char[] /* resource_name */,
|
|
const char[] /* resource_id */) const {
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Load an external audio track specified by |path|/|name|/|id|.
|
|
*/
|
|
virtual sk_sp<ExternalTrackAsset> loadAudioAsset(const char[] /* resource_path */,
|
|
const char[] /* resource_name */,
|
|
const char[] /* resource_id */) {
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* DEPRECATED: implement loadTypeface() instead.
|
|
*
|
|
* Load an external font and return as SkData.
|
|
*
|
|
* @param name font name ("fName" Lottie property)
|
|
* @param url web font URL ("fPath" Lottie property)
|
|
*
|
|
* -- Note --
|
|
*
|
|
* This mechanism assumes monolithic fonts (single data blob). Some web font providers may
|
|
* serve multiple font blobs, segmented for various unicode ranges, depending on user agent
|
|
* capabilities (woff, woff2). In that case, the embedder would need to advertise no user
|
|
* agent capabilities when fetching the URL, in order to receive full font data.
|
|
*/
|
|
virtual sk_sp<SkData> loadFont(const char[] /* name */,
|
|
const char[] /* url */) const {
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Load an external font and return as SkTypeface.
|
|
*
|
|
* @param name font name
|
|
* @param url web font URL
|
|
*/
|
|
virtual sk_sp<SkTypeface> loadTypeface(const char[] /* name */,
|
|
const char[] /* url */) const {
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
class FileResourceProvider final : public ResourceProvider {
|
|
public:
|
|
static sk_sp<FileResourceProvider> Make(SkString base_dir, bool predecode = false);
|
|
|
|
sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const override;
|
|
|
|
sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
|
|
|
|
private:
|
|
FileResourceProvider(SkString, bool);
|
|
|
|
const SkString fDir;
|
|
const bool fPredecode;
|
|
|
|
using INHERITED = ResourceProvider;
|
|
};
|
|
|
|
class ResourceProviderProxyBase : public ResourceProvider {
|
|
protected:
|
|
explicit ResourceProviderProxyBase(sk_sp<ResourceProvider>);
|
|
|
|
sk_sp<SkData> load(const char[], const char[]) const override;
|
|
sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
|
|
sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override;
|
|
sk_sp<SkData> loadFont(const char[], const char[]) const override;
|
|
sk_sp<ExternalTrackAsset> loadAudioAsset(const char[], const char[], const char[]) override;
|
|
|
|
private:
|
|
const sk_sp<ResourceProvider> fProxy;
|
|
};
|
|
|
|
class CachingResourceProvider final : public ResourceProviderProxyBase {
|
|
public:
|
|
static sk_sp<CachingResourceProvider> Make(sk_sp<ResourceProvider> rp) {
|
|
return rp ? sk_sp<CachingResourceProvider>(new CachingResourceProvider(std::move(rp)))
|
|
: nullptr;
|
|
}
|
|
|
|
private:
|
|
explicit CachingResourceProvider(sk_sp<ResourceProvider>);
|
|
|
|
sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
|
|
|
|
mutable SkMutex fMutex;
|
|
mutable SkTHashMap<SkString, sk_sp<ImageAsset>> fImageCache;
|
|
|
|
using INHERITED = ResourceProviderProxyBase;
|
|
};
|
|
|
|
class DataURIResourceProviderProxy final : public ResourceProviderProxyBase {
|
|
public:
|
|
static sk_sp<DataURIResourceProviderProxy> Make(sk_sp<ResourceProvider> rp,
|
|
bool predecode = false);
|
|
|
|
private:
|
|
DataURIResourceProviderProxy(sk_sp<ResourceProvider>, bool);
|
|
|
|
sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
|
|
sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override;
|
|
|
|
const bool fPredecode;
|
|
|
|
using INHERITED = ResourceProviderProxyBase;
|
|
};
|
|
|
|
} // namespace skresources
|
|
|
|
#endif // SkResources_DEFINED
|