• 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 "SkTypes.h"
12 #include "SkCodecAnimation.h"
13 #include "SkCodecAnimationPriv.h"
14 #include "SkRect.h"
15 
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  */
22 class SkFrame : public SkNoncopyable {
23 public:
SkFrame(int id)24     SkFrame(int id)
25         : fId(id)
26         , fHasAlpha(false)
27         , fRequiredFrame(kUninitialized)
28         , fDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep)
29         , fDuration(0)
30         , fBlend(SkCodecAnimation::Blend::kPriorFrame)
31     {
32         fRect.setEmpty();
33     }
34 
~SkFrame()35     virtual ~SkFrame() {}
36 
37     /**
38      * 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     /**
49      *  0-based index of the frame in the image sequence.
50      */
frameId()51     int frameId() const { return fId; }
52 
53     /**
54      *  How this frame reports its alpha.
55      *
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      */
reportedAlpha()60     SkEncodedInfo::Alpha reportedAlpha() const {
61         return this->onReportedAlpha();
62     }
63 
64     /**
65      *  Cached value representing whether the frame has alpha,
66      *  after compositing with the prior frame.
67      */
hasAlpha()68     bool hasAlpha() const { return fHasAlpha; }
69 
70     /**
71      *  Cache whether the finished frame has alpha.
72      */
setHasAlpha(bool alpha)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      */
reachedStartOfData()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      */
getRequiredFrame()86     int getRequiredFrame() const {
87         SkASSERT(this->reachedStartOfData());
88         return fRequiredFrame;
89     }
90 
91     /**
92      *  Set the frame that this frame depends on.
93      */
setRequiredFrame(int req)94     void setRequiredFrame(int req) { fRequiredFrame = req; }
95 
96     /**
97      *  Set the rectangle that is updated by this frame.
98      */
setXYWH(int x,int y,int width,int height)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      */
frameRect()106     SkIRect frameRect() const { return fRect; }
107 
xOffset()108     int xOffset() const { return fRect.x(); }
yOffset()109     int yOffset() const { return fRect.y(); }
width()110     int width()   const { return fRect.width(); }
height()111     int height()  const { return fRect.height(); }
112 
getDisposalMethod()113     SkCodecAnimation::DisposalMethod getDisposalMethod() const {
114         return fDisposalMethod;
115     }
116 
setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod)117     void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
118         fDisposalMethod = disposalMethod;
119     }
120 
121     /**
122      * Set the duration (in ms) to show this frame.
123      */
setDuration(int duration)124     void setDuration(int duration) {
125         fDuration = duration;
126     }
127 
128     /**
129      *  Duration in ms to show this frame.
130      */
getDuration()131     int getDuration() const {
132         return fDuration;
133     }
134 
setBlend(SkCodecAnimation::Blend blend)135     void setBlend(SkCodecAnimation::Blend blend) {
136         fBlend = blend;
137     }
138 
getBlend()139     SkCodecAnimation::Blend getBlend() const {
140         return fBlend;
141     }
142 
143 protected:
144     virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;
145 
146 private:
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  */
162 class SkFrameHolder : public SkNoncopyable {
163 public:
SkFrameHolder()164     SkFrameHolder()
165         : fScreenWidth(0)
166         , fScreenHeight(0)
167     {}
168 
~SkFrameHolder()169     virtual ~SkFrameHolder() {}
170 
171     /**
172      *  Size of the image. Each frame will be contained in
173      *  these dimensions (possibly after clipping).
174      */
screenWidth()175     int screenWidth() const { return fScreenWidth; }
screenHeight()176     int screenHeight() const { return fScreenHeight; }
177 
178     /**
179      *  Compute the opacity and required frame, based on
180      *  the frame's reportedAlpha and how it blends
181      *  with prior frames.
182      */
183     void setAlphaAndRequiredFrame(SkFrame*);
184 
185     /**
186      *  Return the frame with frameId i.
187      */
getFrame(int i)188     const SkFrame* getFrame(int i) const {
189         return this->onGetFrame(i);
190     }
191 
192 protected:
193     int fScreenWidth;
194     int fScreenHeight;
195 
196     virtual const SkFrame* onGetFrame(int i) const = 0;
197 };
198 
199 #endif // SkFrameHolder_DEFINED
200