Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MSKPPlayer.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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 MSKPPlayer_DEFINED
9#define MSKPPlayer_DEFINED
10
12#include "include/core/SkSize.h"
13
14#include <memory>
15#include <unordered_map>
16#include <vector>
17
18class SkCanvas;
19class SkImage;
21class SkSurface;
22
23/**
24 * Plays frames/pages of a MSKP to a canvas. This class uses the term "frame" as though the MSKP
25 * contains an animation, though it could indeed contain pages of a static document.
26 */
28public:
30
31 /** Make a player from a MSKP stream, or null if stream can't be read as MSKP. */
32 static std::unique_ptr<MSKPPlayer> Make(SkStreamSeekable* stream);
33
34 /** Maximum width and height across all frames. */
35 SkISize maxDimensions() const { return fMaxDimensions; }
36
37 /** Total number of frames. */
38 int numFrames() const { return static_cast<int>(fRootLayers.size()); }
39
40 /** Size of an individual frame. */
41 SkISize frameDimensions(int i) const;
42
43 /**
44 * Plays a frame into the passed canvas. Frames can be randomly accessed. Offscreen layers are
45 * incrementally updated from their current state to the state required for the frame
46 * (redrawing from scratch if their current state is ahead of the passed frame index).
47 */
48 bool playFrame(SkCanvas* canvas, int i);
49
50 /** Destroys any cached offscreen layers. */
51 void resetLayers();
52
53 /**
54 * Forces all offscreen layers to re-render the next time they're required for a frame but
55 * preserves the backing stores for them if already allocated.
56 */
57 void rewindLayers();
58
59 /**
60 * Creates backing stores for any offscreen layers using the passed canvas's makeSurface().
61 * Existing layers that match the canvas's recording context are not reallocated or rewound.
62 */
64
65 /**
66 * A set of IDs of offscreen layers in no particular order. If frame value >= 0 is specified
67 * then the layer set is filtered to layers used by that frame (or empty if >= numFrames). If
68 * < 0 then gathers all the layers across all frames.
69 */
70 std::vector<int> layerIDs(int frame = -1) const;
71
72 /**
73 * Gets the contents of an offscreen layer. It's contents will depend on current playback state
74 * (playFrame(), updateFrameLayers(), resetLayers()). If the layer currently has no backing
75 * store because it hasn't been drawn or resetLayers() was called then this will return nullptr.
76 * Layer contents are not affected by rewindLayers() as that simply lazily redraws the frame
77 * contents the next time it is required by playFrame*() or updateFrameLayers().
78 */
79 sk_sp<SkImage> layerSnapshot(int layerID) const;
80
81private:
82 MSKPPlayer() = default;
83 // noncopyable, nonmoveable.
84 MSKPPlayer(const MSKPPlayer&) = delete;
85 MSKPPlayer(MSKPPlayer&&) = delete;
86 MSKPPlayer& operator=(const MSKPPlayer&) = delete;
87 MSKPPlayer& operator=(MSKPPlayer&&) = delete;
88
89 // Cmds are used to draw content to the frame root layer and to offscreen layers.
90 struct Cmd;
91 // Draws a SkPicture.
92 struct PicCmd;
93 // Draws another layer. Stores the ID of the layer to draw and what command index on that
94 // layer should be current when the layer is drawn. The layer contents are updated to the
95 // stored command index before the layer is drawn.
96 struct DrawLayerCmd;
97
98 // The commands for a root/offscreen layer and dimensions of the layer.
99 struct LayerCmds {
100 LayerCmds() = default;
101 LayerCmds(LayerCmds&&) = default;
102 SkISize fDimensions;
103 std::vector<std::unique_ptr<Cmd>> fCmds;
104 };
105
106 // Playback state of layer: the last command index drawn to it and the SkSurface with contents.
107 struct LayerState {
108 size_t fCurrCmd = -1;
109 sk_sp<SkSurface> fSurface;
110 };
111
112 static sk_sp<SkSurface> MakeSurfaceForLayer(const LayerCmds&, SkCanvas* rootCanvas);
113
114 void collectReferencedLayers(const LayerCmds& layer, std::vector<int>*) const;
115
116 // MSKP layer ID -> LayerCmds
117 using LayerMap = std::unordered_map<int, LayerCmds>;
118 // MSKP layer ID -> LayerState
119 using LayerStateMap = std::unordered_map<int, LayerState>;
120
121 /**
122 * A SkCanvas that consumes the SkPicture and records Cmds into a Layer. It will spawn
123 * additional Layers and record nested SkPictures into those using additional CmdRecordCanvas
124 * CmdRecordCanvas instances. It needs access to fOffscreenLayers to create and update LayerCmds
125 * structs for offscreen layers.
126 */
127 class CmdRecordCanvas;
128
129 SkISize fMaxDimensions = {0, 0}; // Max dimensions across all frames.
130 LayerMap fOffscreenLayers; // All the offscreen layers for all frames.
131 LayerStateMap fOffscreenLayerStates; // Current surfaces and command idx for offscreen
132 // layers
133 std::vector<LayerCmds> fRootLayers; // One root layer for each frame.
134};
135
136#endif
int numFrames() const
Definition MSKPPlayer.h:38
void rewindLayers()
std::vector< int > layerIDs(int frame=-1) const
sk_sp< SkImage > layerSnapshot(int layerID) const
static std::unique_ptr< MSKPPlayer > Make(SkStreamSeekable *stream)
void resetLayers()
bool playFrame(SkCanvas *canvas, int i)
SkISize frameDimensions(int i) const
SkISize maxDimensions() const
Definition MSKPPlayer.h:35
void allocateLayers(SkCanvas *)
double frame
Definition examples.cpp:31