Flutter Engine
The Flutter Engine
SkottieViewController.mm
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3
5
10#include "src/base/SkTime.h"
11
12#include <cmath>
13
14////////////////////////////////////////////////////////////////////////////////
15
17public:
18 SkAnimationDraw() = default;
19 ~SkAnimationDraw() = default;
20
21 explicit operator bool() const { return fAnimation != nullptr; }
22
23 void draw(SkSize size, SkCanvas* canvas) {
24 if (size.width() != fSize.width() || size.height() != fSize.height()) {
25 // Cache the current matrix; change only if size changes.
26 if (fAnimationSize.width() > 0 && fAnimationSize.height() > 0) {
27 float scale = std::min(size.width() / fAnimationSize.width(),
28 size.height() / fAnimationSize.height());
29 fMatrix.setScaleTranslate(
30 scale, scale,
31 (size.width() - fAnimationSize.width() * scale) * 0.5f,
32 (size.height() - fAnimationSize.height() * scale) * 0.5f);
33 } else {
34 fMatrix = SkMatrix();
35 }
36 fSize = size;
37 }
38 canvas->concat(fMatrix);
39 SkRect rect = {0, 0, fAnimationSize.width(), fAnimationSize.height()};
41 fAnimation->render(canvas);
42 }
43
44 void load(const void* data, size_t length) {
46 fAnimation = builder.make((const char*)data, (size_t)length);
47 fSize = {0, 0};
48 fAnimationSize = fAnimation ? fAnimation->size() : SkSize{0, 0};
49 }
50
51 void seek(double time) { if (fAnimation) { fAnimation->seekFrameTime(time, nullptr); } }
52
53 float duration() { return fAnimation ? fAnimation->duration() : 0; }
54
55 SkSize size() { return fAnimationSize; }
56
57private:
58 sk_sp<skottie::Animation> fAnimation; // owner
59 SkSize fSize;
60 SkSize fAnimationSize;
61 SkMatrix fMatrix;
62
63 SkAnimationDraw(const SkAnimationDraw&) = delete;
64 SkAnimationDraw& operator=(const SkAnimationDraw&) = delete;
65};
66
67////////////////////////////////////////////////////////////////////////////////
68
70private:
71 double fStartTime = 0; // used when running
72 float fAnimationMoment = 0; // when paused.
73 float fDuration = 0;
74 bool fPaused = false;
75 bool fStopAtEnd = false;
76
77public:
78 void setStopAtEnd(bool s) { fStopAtEnd = s; }
79
80 float currentTime() {
81 if (0 == fDuration) {
82 return 0;
83 }
84 if (fPaused) {
85 return fAnimationMoment;
86 }
87 double time = 1e-9 * (SkTime::GetNSecs() - fStartTime);
88 if (fStopAtEnd && time >= fDuration) {
89 fPaused = true;
90 fAnimationMoment = fDuration;
91 return fAnimationMoment;
92 }
93 return std::fmod(time, fDuration);
94 }
95
96 void setDuration(float d) {
97 fDuration = d;
98 fStartTime = SkTime::GetNSecs();
99 fAnimationMoment = 0;
100 }
101
102 bool paused() const { return fPaused; }
103
104 float duration() const { return fDuration; }
105
106 void seek(float seconds) {
107 if (fPaused) {
108 fAnimationMoment = std::fmod(seconds, fDuration);
109 } else {
110 fStartTime = SkTime::GetNSecs() - 1e9 * seconds;
111 }
112 }
113
115 if (fPaused) {
116 double offset = (fAnimationMoment >= fDuration) ? 0 : -1e9 * fAnimationMoment;
117 fStartTime = SkTime::GetNSecs() + offset;
118 fPaused = false;
119 } else {
120 fAnimationMoment = this->currentTime();
121 fPaused = true;
122 }
123 }
124};
125
126////////////////////////////////////////////////////////////////////////////////
127
128@implementation SkottieViewController {
129 SkAnimationDraw fDraw;
131}
132
133- (bool)loadAnimation:(NSData*) data {
134 fDraw.load((const void*)[data bytes], (size_t)[data length]);
135 fClock.setDuration(fDraw.duration());
136 return (bool)fDraw;
137}
138
139- (void)setStopAtEnd:(bool)stop { fClock.setStopAtEnd(stop); }
140
141- (float)animationDurationSeconds { return fClock.duration(); }
142
143- (float)currentTime { return fDraw ? fClock.currentTime() : 0; }
144
145- (void)seek:(float)seconds {
146 if (fDraw) {
147 fClock.seek(seconds);
148 }
149}
150
151- (CGSize)size { return {(CGFloat)fDraw.size().width(), (CGFloat)fDraw.size().height()}; }
152
153- (bool)togglePaused {
155 return fClock.paused();
156}
157
158- (bool)isPaused { return fClock.paused(); }
159
160- (void)draw:(CGRect)rect toCanvas:(SkCanvas*)canvas atSize:(CGSize)size {
161 // TODO(halcanary): Use the rect and the InvalidationController to speed up rendering.
162 if (rect.size.width > 0 && rect.size.height > 0 && fDraw && canvas) {
163 if (!fClock.paused()) {
164 fDraw.seek(fClock.currentTime());
165 }
166 fDraw.draw(SkSize{(float)size.width, (float)size.height}, canvas);
167 }
168}
169
170@end
SkTimeKeeper fClock
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
void load(const void *data, size_t length)
void draw(SkSize size, SkCanvas *canvas)
~SkAnimationDraw()=default
void seek(double time)
SkAnimationDraw()=default
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
Definition: SkMatrix.h:1803
void seek(float seconds)
void setStopAtEnd(bool s)
void setDuration(float d)
float duration() const
const SkSize & size() const
Definition: Skottie.h:286
void seekFrameTime(double t, sksg::InvalidationController *=nullptr)
Definition: Skottie.cpp:530
double duration() const
Definition: Skottie.h:268
void render(SkCanvas *canvas, const SkRect *dst=nullptr) const
Definition: Skottie.cpp:482
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
struct MyStruct s
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
constexpr SkColor4f kWhite
Definition: SkColor.h:439
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
double GetNSecs()
Definition: SkTime.cpp:17
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static double time(int loops, Benchmark *bench, Target *target)
Definition: nanobench.cpp:394
const Scalar scale
SeparatedVector2 offset
Definition: SkSize.h:52
SkScalar width() const
Definition: SkSize.h:76
SkScalar height() const
Definition: SkSize.h:77
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63