Flutter Engine
The Flutter Engine
Composition.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 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
9
20#include "src/utils/SkJSON.h"
21
22#include <algorithm>
23#include <utility>
24
25namespace skottie {
26namespace internal {
27
28AnimationBuilder::ScopedAssetRef::ScopedAssetRef(const AnimationBuilder* abuilder,
29 const skjson::ObjectValue& jlayer) {
30 const auto refId = ParseDefault<SkString>(jlayer["refId"], SkString());
31 if (refId.isEmpty()) {
32 abuilder->log(Logger::Level::kError, nullptr, "Layer missing refId.");
33 return;
34 }
35
36 const auto* asset_info = abuilder->fAssets.find(refId);
37 if (!asset_info) {
38 abuilder->log(Logger::Level::kError, nullptr, "Asset not found: '%s'.", refId.c_str());
39 return;
40 }
41
42 if (asset_info->fIsAttaching) {
43 abuilder->log(Logger::Level::kError, nullptr,
44 "Asset cycle detected for: '%s'", refId.c_str());
45 return;
46 }
47
48 asset_info->fIsAttaching = true;
49
50 fInfo = asset_info;
51}
52
54 const SkSize& size,
55 const skjson::ObjectValue& jcomp)
56 : fSize(size) {
57
58 // Optional motion blur params.
59 if (const skjson::ObjectValue* jmb = jcomp["mb"]) {
60 static constexpr size_t kMaxSamplesPerFrame = 64;
61 fMotionBlurSamples = std::min(ParseDefault<size_t>((*jmb)["spf"], 1ul),
62 kMaxSamplesPerFrame);
63 fMotionBlurAngle = SkTPin(ParseDefault((*jmb)["sa"], 0.0f), 0.0f, 720.0f);
64 fMotionBlurPhase = SkTPin(ParseDefault((*jmb)["sp"], 0.0f), -360.0f, 360.0f);
65 }
66
67 int camera_builder_index = -1;
68
69 // Prepare layer builders.
70 if (const skjson::ArrayValue* jlayers = jcomp["layers"]) {
71 fLayerBuilders.reserve(SkToInt(jlayers->size()));
72 for (const skjson::ObjectValue* jlayer : *jlayers) {
73 if (!jlayer) continue;
74
75 const auto lbuilder_index = fLayerBuilders.size();
76 fLayerBuilders.emplace_back(*jlayer, fSize);
77 const auto& lbuilder = fLayerBuilders.back();
78
79 fLayerIndexMap.set(lbuilder.index(), lbuilder_index);
80
81 // Keep track of the camera builder.
82 if (lbuilder.isCamera()) {
83 // We only support one (first) camera for now.
84 if (camera_builder_index < 0) {
85 camera_builder_index = SkToInt(lbuilder_index);
86 } else {
87 abuilder.log(Logger::Level::kWarning, jlayer,
88 "Ignoring duplicate camera layer.");
89 }
90 }
91 }
92 }
93
94 // Attach a camera transform upfront, if needed (required to build
95 // all other 3D transform chains).
96 if (camera_builder_index >= 0) {
97 // Explicit camera.
98 fCameraTransform = fLayerBuilders[camera_builder_index].buildTransform(abuilder, this);
99 } else if (ParseDefault<int>(jcomp["ddd"], 0) && !fSize.isEmpty()) {
100 // Default/implicit camera when 3D layers are present.
101 fCameraTransform = CameraAdaper::DefaultCameraTransform(fSize);
102 }
103}
104
106
108 if (layer_index < 0) {
109 return nullptr;
110 }
111
112 if (const auto* idx = fLayerIndexMap.find(layer_index)) {
113 return &fLayerBuilders[SkToInt(*idx)];
114 }
115
116 return nullptr;
117}
118
120 // First pass - transitively attach layer transform chains.
121 for (auto& lbuilder : fLayerBuilders) {
122 lbuilder.buildTransform(abuilder, this);
123 }
124
125 // Second pass - attach actual layer contents and finalize the layer render tree.
126 std::vector<sk_sp<sksg::RenderNode>> layers;
127 layers.reserve(fLayerBuilders.size());
128
129 LayerBuilder* prev_layer = nullptr;
130 for (auto& lbuilder : fLayerBuilders) {
131 if (auto layer = lbuilder.buildRenderTree(abuilder, this, prev_layer)) {
132 layers.push_back(std::move(layer));
133 }
134 prev_layer = &lbuilder;
135 }
136
137 if (layers.empty()) {
138 return nullptr;
139 }
140
141 if (layers.size() == 1) {
142 return std::move(layers[0]);
143 }
144
145 // Layers are painted in bottom->top order.
146 std::reverse(layers.begin(), layers.end());
147 layers.shrink_to_fit();
148
149 return sksg::Group::Make(std::move(layers));
150}
151
152} // namespace internal
153} // namespace skottie
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
constexpr int SkToInt(S x)
Definition: SkTo.h:29
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487
void log(Logger::Level, const skjson::Value *, const char fmt[],...) const SK_PRINTF_LIKE(4
Definition: Skottie.cpp:71
static sk_sp< sksg::Transform > DefaultCameraTransform(const SkSize &viewport_size)
Definition: Camera.cpp:110
CompositionBuilder(const AnimationBuilder &, const SkSize &, const skjson::ObjectValue &)
Definition: Composition.cpp:53
sk_sp< sksg::RenderNode > build(const AnimationBuilder &)
LayerBuilder * layerBuilder(int layer_index)
static sk_sp< Group > Make()
Definition: SkSGGroup.h:31
static float min(float r, float g, float b)
Definition: hsl.cpp:48
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
T ParseDefault(const skjson::Value &v, const T &defaultValue)
Definition: SkottieJson.h:23
Definition: SkSize.h:52
bool isEmpty() const
Definition: SkSize.h:71