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