• 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      *  0-based index of the frame in the image sequence.
39      */
frameId()40     int frameId() const { return fId; }
41 
42     /**
43      *  How this frame reports its alpha.
44      *
45      *  This only considers the rectangle of this frame, and
46      *  considers it to have alpha even if it is opaque once
47      *  blended with the frame behind it.
48      */
reportedAlpha()49     SkEncodedInfo::Alpha reportedAlpha() const {
50         return this->onReportedAlpha();
51     }
52 
53     /**
54      *  Cached value representing whether the frame has alpha,
55      *  after compositing with the prior frame.
56      */
hasAlpha()57     bool hasAlpha() const { return fHasAlpha; }
58 
59     /**
60      *  Cache whether the finished frame has alpha.
61      */
setHasAlpha(bool alpha)62     void setHasAlpha(bool alpha) { fHasAlpha = alpha; }
63 
64     /**
65      *  Whether enough of the frame has been read to determine
66      *  fRequiredFrame and fHasAlpha.
67      */
reachedStartOfData()68     bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }
69 
70     /**
71      *  The frame this one depends on.
72      *
73      *  Must not be called until fRequiredFrame has been set properly.
74      */
getRequiredFrame()75     int getRequiredFrame() const {
76         SkASSERT(this->reachedStartOfData());
77         return fRequiredFrame;
78     }
79 
80     /**
81      *  Set the frame that this frame depends on.
82      */
setRequiredFrame(int req)83     void setRequiredFrame(int req) { fRequiredFrame = req; }
84 
85     /**
86      *  Set the rectangle that is updated by this frame.
87      */
setXYWH(int x,int y,int width,int height)88     void setXYWH(int x, int y, int width, int height) {
89         fRect.setXYWH(x, y, width, height);
90     }
91 
92     /**
93      *  The rectangle that is updated by this frame.
94      */
frameRect()95     SkIRect frameRect() const { return fRect; }
96 
xOffset()97     int xOffset() const { return fRect.x(); }
yOffset()98     int yOffset() const { return fRect.y(); }
width()99     int width()   const { return fRect.width(); }
height()100     int height()  const { return fRect.height(); }
101 
getDisposalMethod()102     SkCodecAnimation::DisposalMethod getDisposalMethod() const {
103         return fDisposalMethod;
104     }
105 
setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod)106     void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
107         fDisposalMethod = disposalMethod;
108     }
109 
110     /**
111      * Set the duration (in ms) to show this frame.
112      */
setDuration(int duration)113     void setDuration(int duration) {
114         fDuration = duration;
115     }
116 
117     /**
118      *  Duration in ms to show this frame.
119      */
getDuration()120     int getDuration() const {
121         return fDuration;
122     }
123 
setBlend(SkCodecAnimation::Blend blend)124     void setBlend(SkCodecAnimation::Blend blend) {
125         fBlend = blend;
126     }
127 
getBlend()128     SkCodecAnimation::Blend getBlend() const {
129         return fBlend;
130     }
131 
132 protected:
133     virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;
134 
135 private:
136     static constexpr int kUninitialized = -2;
137 
138     const int                           fId;
139     bool                                fHasAlpha;
140     int                                 fRequiredFrame;
141     SkIRect                             fRect;
142     SkCodecAnimation::DisposalMethod    fDisposalMethod;
143     int                                 fDuration;
144     SkCodecAnimation::Blend             fBlend;
145 };
146 
147 /**
148  *  Base class for an object which holds the SkFrames of an
149  *  image sequence.
150  */
151 class SkFrameHolder : public SkNoncopyable {
152 public:
SkFrameHolder()153     SkFrameHolder()
154         : fScreenWidth(0)
155         , fScreenHeight(0)
156     {}
157 
~SkFrameHolder()158     virtual ~SkFrameHolder() {}
159 
160     /**
161      *  Size of the image. Each frame will be contained in
162      *  these dimensions (possibly after clipping).
163      */
screenWidth()164     int screenWidth() const { return fScreenWidth; }
screenHeight()165     int screenHeight() const { return fScreenHeight; }
166 
167     /**
168      *  Compute the opacity and required frame, based on
169      *  the frame's reportedAlpha and how it blends
170      *  with prior frames.
171      */
172     void setAlphaAndRequiredFrame(SkFrame*);
173 
174     /**
175      *  Return the frame with frameId i.
176      */
getFrame(int i)177     const SkFrame* getFrame(int i) const {
178         return this->onGetFrame(i);
179     }
180 
181 protected:
182     int fScreenWidth;
183     int fScreenHeight;
184 
185     virtual const SkFrame* onGetFrame(int i) const = 0;
186 };
187 
188 #endif // SkFrameHolder_DEFINED
189