aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkFrameHolder.h
blob: ab308b39dbc57e7c689eee2af5e2bbb3433689c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkFrameHolder_DEFINED
#define SkFrameHolder_DEFINED

#include "SkTypes.h"
#include "SkCodecAnimation.h"
#include "SkCodecAnimationPriv.h"
#include "SkRect.h"

/**
 *  Base class for a single frame of an animated image.
 *
 *  Separate from SkCodec::FrameInfo, which is a pared down
 *  interface that only contains the info the client needs.
 */
class SkFrame : public SkNoncopyable {
public:
    SkFrame(int id)
        : fId(id)
        , fHasAlpha(false)
        , fRequiredFrame(kUninitialized)
        , fDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep)
        , fDuration(0)
        , fBlend(SkCodecAnimation::Blend::kPriorFrame)
    {
        fRect.setEmpty();
    }

    virtual ~SkFrame() {}

    /**
     *  0-based index of the frame in the image sequence.
     */
    int frameId() const { return fId; }

    /**
     *  How this frame reports its alpha.
     *
     *  This only considers the rectangle of this frame, and
     *  considers it to have alpha even if it is opaque once
     *  blended with the frame behind it.
     */
    SkEncodedInfo::Alpha reportedAlpha() const {
        return this->onReportedAlpha();
    }

    /**
     *  Cached value representing whether the frame has alpha,
     *  after compositing with the prior frame.
     */
    bool hasAlpha() const { return fHasAlpha; }

    /**
     *  Cache whether the finished frame has alpha.
     */
    void setHasAlpha(bool alpha) { fHasAlpha = alpha; }

    /**
     *  Whether enough of the frame has been read to determine
     *  fRequiredFrame and fHasAlpha.
     */
    bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }

    /**
     *  The frame this one depends on.
     *
     *  Must not be called until fRequiredFrame has been set properly.
     */
    int getRequiredFrame() const {
        SkASSERT(this->reachedStartOfData());
        return fRequiredFrame;
    }

    /**
     *  Set the frame that this frame depends on.
     */
    void setRequiredFrame(int req) { fRequiredFrame = req; }

    /**
     *  Set the rectangle that is updated by this frame.
     */
    void setXYWH(int x, int y, int width, int height) {
        fRect.setXYWH(x, y, width, height);
    }

    /**
     *  The rectangle that is updated by this frame.
     */
    SkIRect frameRect() const { return fRect; }

    int xOffset() const { return fRect.x(); }
    int yOffset() const { return fRect.y(); }
    int width()   const { return fRect.width(); }
    int height()  const { return fRect.height(); }

    SkCodecAnimation::DisposalMethod getDisposalMethod() const {
        return fDisposalMethod;
    }

    void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
        fDisposalMethod = disposalMethod;
    }

    /**
     * Set the duration (in ms) to show this frame.
     */
    void setDuration(int duration) {
        fDuration = duration;
    }

    /**
     *  Duration in ms to show this frame.
     */
    int getDuration() const {
        return fDuration;
    }

    void setBlend(SkCodecAnimation::Blend blend) {
        fBlend = blend;
    }

    SkCodecAnimation::Blend getBlend() const {
        return fBlend;
    }

protected:
    virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;

private:
    static constexpr int kUninitialized = -2;

    const int                           fId;
    bool                                fHasAlpha;
    int                                 fRequiredFrame;
    SkIRect                             fRect;
    SkCodecAnimation::DisposalMethod    fDisposalMethod;
    int                                 fDuration;
    SkCodecAnimation::Blend             fBlend;
};

/**
 *  Base class for an object which holds the SkFrames of an
 *  image sequence.
 */
class SkFrameHolder : public SkNoncopyable {
public:
    SkFrameHolder()
        : fScreenWidth(0)
        , fScreenHeight(0)
    {}

    virtual ~SkFrameHolder() {}

    /**
     *  Size of the image. Each frame will be contained in
     *  these dimensions (possibly after clipping).
     */
    int screenWidth() const { return fScreenWidth; }
    int screenHeight() const { return fScreenHeight; }

    /**
     *  Compute the opacity and required frame, based on
     *  the frame's reportedAlpha and how it blends
     *  with prior frames.
     */
    void setAlphaAndRequiredFrame(SkFrame*);

    /**
     *  Return the frame with frameId i.
     */
    const SkFrame* getFrame(int i) const {
        return this->onGetFrame(i);
    }

protected:
    int fScreenWidth;
    int fScreenHeight;

    virtual const SkFrame* onGetFrame(int i) const = 0;
};

#endif // SkFrameHolder_DEFINED