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