Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | List of all members
MSKPPlayer Class Reference

#include <MSKPPlayer.h>

Classes

struct  Cmd
 
class  CmdRecordCanvas
 
struct  DrawLayerCmd
 
struct  PicCmd
 

Public Member Functions

 ~MSKPPlayer ()
 
SkISize maxDimensions () const
 
int numFrames () const
 
SkISize frameDimensions (int i) const
 
bool playFrame (SkCanvas *canvas, int i)
 
void resetLayers ()
 
void rewindLayers ()
 
void allocateLayers (SkCanvas *)
 
std::vector< intlayerIDs (int frame=-1) const
 
sk_sp< SkImagelayerSnapshot (int layerID) const
 

Static Public Member Functions

static std::unique_ptr< MSKPPlayerMake (SkStreamSeekable *stream)
 

Detailed Description

Plays frames/pages of a MSKP to a canvas. This class uses the term "frame" as though the MSKP contains an animation, though it could indeed contain pages of a static document.

Definition at line 27 of file MSKPPlayer.h.

Constructor & Destructor Documentation

◆ ~MSKPPlayer()

MSKPPlayer::~MSKPPlayer ( )
default

Member Function Documentation

◆ allocateLayers()

void MSKPPlayer::allocateLayers ( SkCanvas canvas)

Creates backing stores for any offscreen layers using the passed canvas's makeSurface(). Existing layers that match the canvas's recording context are not reallocated or rewound.

Definition at line 467 of file MSKPPlayer.cpp.

467 {
468 // Iterate over layers not states as states are lazily created in playback but here we want to
469 // create any that don't already exist.
470 for (auto& [id, layer] : fOffscreenLayers) {
471 LayerState& state = fOffscreenLayerStates[id];
472 if (!state.fSurface || state.fSurface->recordingContext() != canvas->recordingContext()) {
473 state.fCurrCmd = -1;
474 state.fSurface = MakeSurfaceForLayer(fOffscreenLayers[id], canvas);
475 }
476 }
477}
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
AtkStateType state
const uintptr_t id

◆ frameDimensions()

SkISize MSKPPlayer::frameDimensions ( int  i) const

Size of an individual frame.

Definition at line 417 of file MSKPPlayer.cpp.

417 {
418 if (i < 0 || i >= this->numFrames()) {
419 return {-1, -1};
420 }
421 return fRootLayers[i].fDimensions;
422}
int numFrames() const
Definition: MSKPPlayer.h:38

◆ layerIDs()

std::vector< int > MSKPPlayer::layerIDs ( int  frame = -1) const

A set of IDs of offscreen layers in no particular order. If frame value >= 0 is specified then the layer set is filtered to layers used by that frame (or empty if >= numFrames). If < 0 then gathers all the layers across all frames.

Definition at line 479 of file MSKPPlayer.cpp.

479 {
480 std::vector<int> result;
481 if (frame < 0) {
482 result.reserve(fOffscreenLayers.size());
483 for (auto& [id, _] : fOffscreenLayers) {
484 result.push_back(id);
485 }
486 return result;
487 }
488 if (frame < static_cast<int>(fRootLayers.size())) {
489 this->collectReferencedLayers(fRootLayers[frame], &result);
490 }
491 return result;
492}
double frame
Definition: examples.cpp:31
GAsyncResult * result

◆ layerSnapshot()

sk_sp< SkImage > MSKPPlayer::layerSnapshot ( int  layerID) const

Gets the contents of an offscreen layer. It's contents will depend on current playback state (playFrame(), updateFrameLayers(), resetLayers()). If the layer currently has no backing store because it hasn't been drawn or resetLayers() was called then this will return nullptr. Layer contents are not affected by rewindLayers() as that simply lazily redraws the frame contents the next time it is required by playFrame*() or updateFrameLayers().

Definition at line 494 of file MSKPPlayer.cpp.

494 {
495 auto iter = fOffscreenLayerStates.find(layerID);
496 if (iter == fOffscreenLayerStates.end() || !iter->second.fSurface) {
497 return nullptr;
498 }
499 return iter->second.fSurface->makeImageSnapshot();
500}

◆ Make()

std::unique_ptr< MSKPPlayer > MSKPPlayer::Make ( SkStreamSeekable stream)
static

Make a player from a MSKP stream, or null if stream can't be read as MSKP.

Definition at line 386 of file MSKPPlayer.cpp.

386 {
387 auto deserialContext = std::make_unique<SkSharingDeserialContext>();
388 SkDeserialProcs procs;
390 procs.fImageCtx = deserialContext.get();
391
393 if (!pageCount) {
394 return nullptr;
395 }
396 std::vector<SkDocumentPage> pages(pageCount);
397 if (!SkMultiPictureDocument::Read(stream, pages.data(), pageCount, &procs)) {
398 return nullptr;
399 }
400 std::unique_ptr<MSKPPlayer> result(new MSKPPlayer);
401 result->fRootLayers.reserve(pages.size());
402 for (const auto& page : pages) {
403 SkISize dims = {SkScalarCeilToInt(page.fSize.width()),
404 SkScalarCeilToInt(page.fSize.height())};
405 result->fRootLayers.emplace_back();
406 result->fRootLayers.back().fDimensions = dims;
407 result->fMaxDimensions.fWidth = std::max(dims.width() , result->fMaxDimensions.width() );
408 result->fMaxDimensions.fHeight = std::max(dims.height(), result->fMaxDimensions.height());
409 CmdRecordCanvas sc(&result->fRootLayers.back(), &result->fOffscreenLayers);
410 page.fPicture->playback(&sc);
411 }
412 return result;
413}
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SK_API bool Read(SkStreamSeekable *src, SkDocumentPage *dstArray, int dstArrayCount, const SkDeserialProcs *=nullptr)
SK_API int ReadPageCount(SkStreamSeekable *src)
SkDeserialImageProc fImageProc
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
static sk_sp< SkImage > deserializeImage(const void *data, size_t length, void *ctx)

◆ maxDimensions()

SkISize MSKPPlayer::maxDimensions ( ) const
inline

Maximum width and height across all frames.

Definition at line 35 of file MSKPPlayer.h.

35{ return fMaxDimensions; }

◆ numFrames()

int MSKPPlayer::numFrames ( ) const
inline

Total number of frames.

Definition at line 38 of file MSKPPlayer.h.

38{ return static_cast<int>(fRootLayers.size()); }

◆ playFrame()

bool MSKPPlayer::playFrame ( SkCanvas canvas,
int  i 
)

Plays a frame into the passed canvas. Frames can be randomly accessed. Offscreen layers are incrementally updated from their current state to the state required for the frame (redrawing from scratch if their current state is ahead of the passed frame index).

Definition at line 424 of file MSKPPlayer.cpp.

424 {
425 if (i < 0 || i >= this->numFrames()) {
426 return false;
427 }
428
429 // Find the first offscreen layer that has a valid surface. If it's recording context
430 // differs from the passed canvas's then reset all the layers. Playback will
431 // automatically allocate new surfaces for offscreen layers as they're encountered.
432 for (const auto& ols : fOffscreenLayerStates) {
433 const LayerState& state = ols.second;
434 if (state.fSurface) {
435 if (state.fSurface->recordingContext() != canvas->recordingContext()) {
436 this->resetLayers();
437 }
438 break;
439 }
440 }
441
442 // Replay all the commands for this frame to the caller's canvas.
443 const LayerCmds& layer = fRootLayers[i];
444 for (const auto& cmd : layer.fCmds) {
445 cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
446 }
447 return true;
448}
void resetLayers()
Definition: MSKPPlayer.cpp:459

◆ resetLayers()

void MSKPPlayer::resetLayers ( )

Destroys any cached offscreen layers.

Definition at line 459 of file MSKPPlayer.cpp.

459{ fOffscreenLayerStates.clear(); }

◆ rewindLayers()

void MSKPPlayer::rewindLayers ( )

Forces all offscreen layers to re-render the next time they're required for a frame but preserves the backing stores for them if already allocated.

Definition at line 461 of file MSKPPlayer.cpp.

461 {
462 for (auto& [id, state] : fOffscreenLayerStates) {
463 state.fCurrCmd = -1;
464 }
465}

The documentation for this class was generated from the following files: