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