Home | History | Annotate | Download | only in codec
      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:
     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 
     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      */
     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      */
     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      */
     68     bool hasAlpha() const { return fHasAlpha; }
     69 
     70     /**
     71      *  Cache whether the finished frame has alpha.
     72      */
     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      */
     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      */
     86     int getRequiredFrame() const {
     87         SkASSERT(this->reachedStartOfData());
     88         return fRequiredFrame;
     89     }
     90 
     91     /**
     92      *  Set the frame that this frame depends on.
     93      */
     94     void setRequiredFrame(int req) { fRequiredFrame = req; }
     95 
     96     /**
     97      *  Set the rectangle that is updated by this frame.
     98      */
     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      */
    106     SkIRect frameRect() const { return fRect; }
    107 
    108     int xOffset() const { return fRect.x(); }
    109     int yOffset() const { return fRect.y(); }
    110     int width()   const { return fRect.width(); }
    111     int height()  const { return fRect.height(); }
    112 
    113     SkCodecAnimation::DisposalMethod getDisposalMethod() const {
    114         return fDisposalMethod;
    115     }
    116 
    117     void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
    118         fDisposalMethod = disposalMethod;
    119     }
    120 
    121     /**
    122      * Set the duration (in ms) to show this frame.
    123      */
    124     void setDuration(int duration) {
    125         fDuration = duration;
    126     }
    127 
    128     /**
    129      *  Duration in ms to show this frame.
    130      */
    131     int getDuration() const {
    132         return fDuration;
    133     }
    134 
    135     void setBlend(SkCodecAnimation::Blend blend) {
    136         fBlend = blend;
    137     }
    138 
    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:
    164     SkFrameHolder()
    165         : fScreenWidth(0)
    166         , fScreenHeight(0)
    167     {}
    168 
    169     virtual ~SkFrameHolder() {}
    170 
    171     /**
    172      *  Size of the image. Each frame will be contained in
    173      *  these dimensions (possibly after clipping).
    174      */
    175     int screenWidth() const { return fScreenWidth; }
    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      */
    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