/*
|
* Copyright 2017 Google Inc.
|
*
|
* Use of this source code is governed by a BSD-style license that can be
|
* found in the LICENSE file.
|
*/
|
|
#ifndef SkFrameHolder_DEFINED
|
#define SkFrameHolder_DEFINED
|
|
#include "SkTypes.h"
|
#include "SkCodecAnimation.h"
|
#include "SkCodecAnimationPriv.h"
|
#include "SkRect.h"
|
|
/**
|
* Base class for a single frame of an animated image.
|
*
|
* Separate from SkCodec::FrameInfo, which is a pared down
|
* interface that only contains the info the client needs.
|
*/
|
class SkFrame : public SkNoncopyable {
|
public:
|
SkFrame(int id)
|
: fId(id)
|
, fHasAlpha(false)
|
, fRequiredFrame(kUninitialized)
|
, fDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep)
|
, fDuration(0)
|
, fBlend(SkCodecAnimation::Blend::kPriorFrame)
|
{
|
fRect.setEmpty();
|
}
|
|
virtual ~SkFrame() {}
|
|
/**
|
* An explicit move constructor, as
|
* https://en.cppreference.com/w/cpp/language/move_constructor says that
|
* there is no implicit move constructor if there are user-declared
|
* destructors, and we have one, immediately above.
|
*
|
* Without a move constructor, it is harder to use an SkFrame, or an
|
* SkFrame subclass, inside a std::vector.
|
*/
|
SkFrame(SkFrame&&) = default;
|
|
/**
|
* 0-based index of the frame in the image sequence.
|
*/
|
int frameId() const { return fId; }
|
|
/**
|
* How this frame reports its alpha.
|
*
|
* This only considers the rectangle of this frame, and
|
* considers it to have alpha even if it is opaque once
|
* blended with the frame behind it.
|
*/
|
SkEncodedInfo::Alpha reportedAlpha() const {
|
return this->onReportedAlpha();
|
}
|
|
/**
|
* Cached value representing whether the frame has alpha,
|
* after compositing with the prior frame.
|
*/
|
bool hasAlpha() const { return fHasAlpha; }
|
|
/**
|
* Cache whether the finished frame has alpha.
|
*/
|
void setHasAlpha(bool alpha) { fHasAlpha = alpha; }
|
|
/**
|
* Whether enough of the frame has been read to determine
|
* fRequiredFrame and fHasAlpha.
|
*/
|
bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }
|
|
/**
|
* The frame this one depends on.
|
*
|
* Must not be called until fRequiredFrame has been set properly.
|
*/
|
int getRequiredFrame() const {
|
SkASSERT(this->reachedStartOfData());
|
return fRequiredFrame;
|
}
|
|
/**
|
* Set the frame that this frame depends on.
|
*/
|
void setRequiredFrame(int req) { fRequiredFrame = req; }
|
|
/**
|
* Set the rectangle that is updated by this frame.
|
*/
|
void setXYWH(int x, int y, int width, int height) {
|
fRect.setXYWH(x, y, width, height);
|
}
|
|
/**
|
* The rectangle that is updated by this frame.
|
*/
|
SkIRect frameRect() const { return fRect; }
|
|
int xOffset() const { return fRect.x(); }
|
int yOffset() const { return fRect.y(); }
|
int width() const { return fRect.width(); }
|
int height() const { return fRect.height(); }
|
|
SkCodecAnimation::DisposalMethod getDisposalMethod() const {
|
return fDisposalMethod;
|
}
|
|
void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
|
fDisposalMethod = disposalMethod;
|
}
|
|
/**
|
* Set the duration (in ms) to show this frame.
|
*/
|
void setDuration(int duration) {
|
fDuration = duration;
|
}
|
|
/**
|
* Duration in ms to show this frame.
|
*/
|
int getDuration() const {
|
return fDuration;
|
}
|
|
void setBlend(SkCodecAnimation::Blend blend) {
|
fBlend = blend;
|
}
|
|
SkCodecAnimation::Blend getBlend() const {
|
return fBlend;
|
}
|
|
protected:
|
virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;
|
|
private:
|
static constexpr int kUninitialized = -2;
|
|
const int fId;
|
bool fHasAlpha;
|
int fRequiredFrame;
|
SkIRect fRect;
|
SkCodecAnimation::DisposalMethod fDisposalMethod;
|
int fDuration;
|
SkCodecAnimation::Blend fBlend;
|
};
|
|
/**
|
* Base class for an object which holds the SkFrames of an
|
* image sequence.
|
*/
|
class SkFrameHolder : public SkNoncopyable {
|
public:
|
SkFrameHolder()
|
: fScreenWidth(0)
|
, fScreenHeight(0)
|
{}
|
|
virtual ~SkFrameHolder() {}
|
|
/**
|
* Size of the image. Each frame will be contained in
|
* these dimensions (possibly after clipping).
|
*/
|
int screenWidth() const { return fScreenWidth; }
|
int screenHeight() const { return fScreenHeight; }
|
|
/**
|
* Compute the opacity and required frame, based on
|
* the frame's reportedAlpha and how it blends
|
* with prior frames.
|
*/
|
void setAlphaAndRequiredFrame(SkFrame*);
|
|
/**
|
* Return the frame with frameId i.
|
*/
|
const SkFrame* getFrame(int i) const {
|
return this->onGetFrame(i);
|
}
|
|
protected:
|
int fScreenWidth;
|
int fScreenHeight;
|
|
virtual const SkFrame* onGetFrame(int i) const = 0;
|
};
|
|
#endif // SkFrameHolder_DEFINED
|