blob: 7ac015ba0781a1e563af01d31052ebd83e7078a7 [file] [log] [blame]
Leon Scroggins III557fbbe2017-05-23 09:37:21 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkFrameHolder_DEFINED
9#define SkFrameHolder_DEFINED
10
11#include "SkTypes.h"
12#include "SkCodecAnimation.h"
Leon Scroggins III33deb7e2017-06-07 12:31:51 -040013#include "SkCodecAnimationPriv.h"
Hal Canary466c7d62017-07-03 15:11:49 -040014#include "SkRect.h"
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040015
16/**
17 * Base class for a single frame of an animated image.
18 *
19 * Separate from SkCodec::FrameInfo, which is a pared down
20 * interface that only contains the info the client needs.
21 */
22class SkFrame : public SkNoncopyable {
23public:
24 SkFrame(int id)
25 : fId(id)
26 , fHasAlpha(false)
27 , fRequiredFrame(kUninitialized)
Leon Scroggins III33deb7e2017-06-07 12:31:51 -040028 , fDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep)
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040029 , fDuration(0)
30 , fBlend(SkCodecAnimation::Blend::kPriorFrame)
31 {
32 fRect.setEmpty();
33 }
34
35 virtual ~SkFrame() {}
36
37 /**
Nigel Tao3cd0c242018-08-31 09:31:25 +100038 * An explicit move constructor, as
39 * https://en.cppreference.com/w/cpp/language/move_constructor says that
40 * there is no implicit move constructor if there are user-declared
41 * destructors, and we have one, immediately above.
42 *
43 * Without a move constructor, it is harder to use an SkFrame, or an
44 * SkFrame subclass, inside a std::vector.
45 */
46 SkFrame(SkFrame&&) = default;
47
48 /**
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040049 * 0-based index of the frame in the image sequence.
50 */
51 int frameId() const { return fId; }
52
53 /**
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -050054 * How this frame reports its alpha.
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040055 *
56 * This only considers the rectangle of this frame, and
57 * considers it to have alpha even if it is opaque once
58 * blended with the frame behind it.
59 */
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -050060 SkEncodedInfo::Alpha reportedAlpha() const {
61 return this->onReportedAlpha();
Leon Scroggins III557fbbe2017-05-23 09:37:21 -040062 }
63
64 /**
65 * Cached value representing whether the frame has alpha,
66 * after compositing with the prior frame.
67 */
68 bool hasAlpha() const { return fHasAlpha; }
69
70 /**
71 * Cache whether the finished frame has alpha.
72 */
73 void setHasAlpha(bool alpha) { fHasAlpha = alpha; }
74
75 /**
76 * Whether enough of the frame has been read to determine
77 * fRequiredFrame and fHasAlpha.
78 */
79 bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }
80
81 /**
82 * The frame this one depends on.
83 *
84 * Must not be called until fRequiredFrame has been set properly.
85 */
86 int getRequiredFrame() const {
87 SkASSERT(this->reachedStartOfData());
88 return fRequiredFrame;
89 }
90
91 /**
92 * Set the frame that this frame depends on.
93 */
94 void setRequiredFrame(int req) { fRequiredFrame = req; }
95
96 /**
97 * Set the rectangle that is updated by this frame.
98 */
99 void setXYWH(int x, int y, int width, int height) {
100 fRect.setXYWH(x, y, width, height);
101 }
102
103 /**
104 * The rectangle that is updated by this frame.
105 */
106 SkIRect frameRect() const { return fRect; }
107
108 int xOffset() const { return fRect.x(); }
109 int yOffset() const { return fRect.y(); }
110 int width() const { return fRect.width(); }
111 int height() const { return fRect.height(); }
112
113 SkCodecAnimation::DisposalMethod getDisposalMethod() const {
114 return fDisposalMethod;
115 }
116
117 void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
118 fDisposalMethod = disposalMethod;
119 }
120
121 /**
122 * Set the duration (in ms) to show this frame.
123 */
124 void setDuration(int duration) {
125 fDuration = duration;
126 }
127
128 /**
129 * Duration in ms to show this frame.
130 */
131 int getDuration() const {
132 return fDuration;
133 }
134
135 void setBlend(SkCodecAnimation::Blend blend) {
136 fBlend = blend;
137 }
138
139 SkCodecAnimation::Blend getBlend() const {
140 return fBlend;
141 }
142
143protected:
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -0500144 virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400145
146private:
147 static constexpr int kUninitialized = -2;
148
149 const int fId;
150 bool fHasAlpha;
151 int fRequiredFrame;
152 SkIRect fRect;
153 SkCodecAnimation::DisposalMethod fDisposalMethod;
154 int fDuration;
155 SkCodecAnimation::Blend fBlend;
156};
157
158/**
159 * Base class for an object which holds the SkFrames of an
160 * image sequence.
161 */
162class SkFrameHolder : public SkNoncopyable {
163public:
164 SkFrameHolder()
165 : fScreenWidth(0)
166 , fScreenHeight(0)
167 {}
168
169 virtual ~SkFrameHolder() {}
170
171 /**
172 * Size of the image. Each frame will be contained in
173 * these dimensions (possibly after clipping).
174 */
175 int screenWidth() const { return fScreenWidth; }
176 int screenHeight() const { return fScreenHeight; }
177
178 /**
179 * Compute the opacity and required frame, based on
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -0500180 * the frame's reportedAlpha and how it blends
Leon Scroggins III557fbbe2017-05-23 09:37:21 -0400181 * with prior frames.
182 */
183 void setAlphaAndRequiredFrame(SkFrame*);
184
185 /**
186 * Return the frame with frameId i.
187 */
188 const SkFrame* getFrame(int i) const {
189 return this->onGetFrame(i);
190 }
191
192protected:
193 int fScreenWidth;
194 int fScreenHeight;
195
196 virtual const SkFrame* onGetFrame(int i) const = 0;
197};
198
199#endif // SkFrameHolder_DEFINED