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