xref: /aosp_15_r20/external/skia/modules/skottie/src/SlotManager.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/SlotManager.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/SkottieProperty.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottiePriv.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/animator/Animator.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/text/TextAdapter.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skresources/include/SkResources.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker class skottie::SlotManager::ImageAssetProxy final : public skresources::ImageAsset {
23*c8dee2aaSAndroid Build Coastguard Worker public:
ImageAssetProxy(sk_sp<skresources::ImageAsset> asset)24*c8dee2aaSAndroid Build Coastguard Worker     explicit ImageAssetProxy(sk_sp<skresources::ImageAsset> asset)
25*c8dee2aaSAndroid Build Coastguard Worker     : fImageAsset(std::move(asset)) {}
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker     // always returns true to force the FootageLayer to always redraw in case asset is swapped
isMultiFrame()28*c8dee2aaSAndroid Build Coastguard Worker     bool isMultiFrame() override { return true; }
29*c8dee2aaSAndroid Build Coastguard Worker 
getFrameData(float t)30*c8dee2aaSAndroid Build Coastguard Worker     FrameData getFrameData(float t) override {
31*c8dee2aaSAndroid Build Coastguard Worker         if (fImageAsset) {
32*c8dee2aaSAndroid Build Coastguard Worker             return fImageAsset->getFrameData(t);
33*c8dee2aaSAndroid Build Coastguard Worker         }
34*c8dee2aaSAndroid Build Coastguard Worker         return {nullptr , SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest),
35*c8dee2aaSAndroid Build Coastguard Worker             SkMatrix::I(), SizeFit::kCenter};
36*c8dee2aaSAndroid Build Coastguard Worker     }
37*c8dee2aaSAndroid Build Coastguard Worker 
setImageAsset(sk_sp<skresources::ImageAsset> asset)38*c8dee2aaSAndroid Build Coastguard Worker     void setImageAsset (sk_sp<skresources::ImageAsset> asset) {
39*c8dee2aaSAndroid Build Coastguard Worker         fImageAsset = std::move(asset);
40*c8dee2aaSAndroid Build Coastguard Worker     }
41*c8dee2aaSAndroid Build Coastguard Worker 
getImageAsset() const42*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const skresources::ImageAsset> getImageAsset() const {
43*c8dee2aaSAndroid Build Coastguard Worker         return fImageAsset;
44*c8dee2aaSAndroid Build Coastguard Worker     }
45*c8dee2aaSAndroid Build Coastguard Worker private:
46*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skresources::ImageAsset> fImageAsset;
47*c8dee2aaSAndroid Build Coastguard Worker };
48*c8dee2aaSAndroid Build Coastguard Worker 
SlotManager(sk_sp<skottie::internal::SceneGraphRevalidator> revalidator)49*c8dee2aaSAndroid Build Coastguard Worker skottie::SlotManager::SlotManager(sk_sp<skottie::internal::SceneGraphRevalidator> revalidator)
50*c8dee2aaSAndroid Build Coastguard Worker         : fRevalidator(std::move(revalidator)) {}
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker skottie::SlotManager::~SlotManager() = default;
53*c8dee2aaSAndroid Build Coastguard Worker 
setColorSlot(const SlotID & slotID,SkColor c)54*c8dee2aaSAndroid Build Coastguard Worker bool skottie::SlotManager::setColorSlot(const SlotID& slotID, SkColor c) {
55*c8dee2aaSAndroid Build Coastguard Worker     auto c4f = SkColor4f::FromColor(c);
56*c8dee2aaSAndroid Build Coastguard Worker     ColorValue v{c4f.fR, c4f.fG, c4f.fB, c4f.fA};
57*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fColorMap.find(slotID);
58*c8dee2aaSAndroid Build Coastguard Worker     if (valueGroup) {
59*c8dee2aaSAndroid Build Coastguard Worker         for (auto& cPair : *valueGroup) {
60*c8dee2aaSAndroid Build Coastguard Worker             *(cPair.value) = v;
61*c8dee2aaSAndroid Build Coastguard Worker             cPair.adapter->onSync();
62*c8dee2aaSAndroid Build Coastguard Worker         }
63*c8dee2aaSAndroid Build Coastguard Worker         fRevalidator->revalidate();
64*c8dee2aaSAndroid Build Coastguard Worker         return true;
65*c8dee2aaSAndroid Build Coastguard Worker     }
66*c8dee2aaSAndroid Build Coastguard Worker     return false;
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker 
setImageSlot(const SlotID & slotID,const sk_sp<skresources::ImageAsset> & i)69*c8dee2aaSAndroid Build Coastguard Worker bool skottie::SlotManager::setImageSlot(const SlotID& slotID,
70*c8dee2aaSAndroid Build Coastguard Worker                                         const sk_sp<skresources::ImageAsset>& i) {
71*c8dee2aaSAndroid Build Coastguard Worker     const auto imageGroup = fImageMap.find(slotID);
72*c8dee2aaSAndroid Build Coastguard Worker     if (imageGroup) {
73*c8dee2aaSAndroid Build Coastguard Worker         for (auto& imageAsset : *imageGroup) {
74*c8dee2aaSAndroid Build Coastguard Worker             imageAsset->setImageAsset(i);
75*c8dee2aaSAndroid Build Coastguard Worker         }
76*c8dee2aaSAndroid Build Coastguard Worker         fRevalidator->revalidate();
77*c8dee2aaSAndroid Build Coastguard Worker         return true;
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker     return false;
80*c8dee2aaSAndroid Build Coastguard Worker }
81*c8dee2aaSAndroid Build Coastguard Worker 
setScalarSlot(const SlotID & slotID,float s)82*c8dee2aaSAndroid Build Coastguard Worker bool skottie::SlotManager::setScalarSlot(const SlotID& slotID, float s) {
83*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fScalarMap.find(slotID);
84*c8dee2aaSAndroid Build Coastguard Worker     if (valueGroup) {
85*c8dee2aaSAndroid Build Coastguard Worker         for (auto& sPair : *valueGroup) {
86*c8dee2aaSAndroid Build Coastguard Worker             *(sPair.value) = s;
87*c8dee2aaSAndroid Build Coastguard Worker             sPair.adapter->onSync();
88*c8dee2aaSAndroid Build Coastguard Worker         }
89*c8dee2aaSAndroid Build Coastguard Worker         fRevalidator->revalidate();
90*c8dee2aaSAndroid Build Coastguard Worker         return true;
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker     return false;
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker 
setVec2Slot(const SlotID & slotID,SkV2 v)95*c8dee2aaSAndroid Build Coastguard Worker bool skottie::SlotManager::setVec2Slot(const SlotID& slotID, SkV2 v) {
96*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fVec2Map.find(slotID);
97*c8dee2aaSAndroid Build Coastguard Worker     if (valueGroup) {
98*c8dee2aaSAndroid Build Coastguard Worker         for (auto& vPair : *valueGroup) {
99*c8dee2aaSAndroid Build Coastguard Worker             *(vPair.value) = v;
100*c8dee2aaSAndroid Build Coastguard Worker             vPair.adapter->onSync();
101*c8dee2aaSAndroid Build Coastguard Worker         }
102*c8dee2aaSAndroid Build Coastguard Worker         fRevalidator->revalidate();
103*c8dee2aaSAndroid Build Coastguard Worker         return true;
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker     return false;
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker 
setTextSlot(const SlotID & slotID,const TextPropertyValue & t)108*c8dee2aaSAndroid Build Coastguard Worker bool skottie::SlotManager::setTextSlot(const SlotID& slotID, const TextPropertyValue& t) {
109*c8dee2aaSAndroid Build Coastguard Worker     const auto adapterGroup = fTextMap.find(slotID);
110*c8dee2aaSAndroid Build Coastguard Worker     if (adapterGroup) {
111*c8dee2aaSAndroid Build Coastguard Worker         for (auto& textAdapter : *adapterGroup) {
112*c8dee2aaSAndroid Build Coastguard Worker             textAdapter->setText(t);
113*c8dee2aaSAndroid Build Coastguard Worker         }
114*c8dee2aaSAndroid Build Coastguard Worker         fRevalidator->revalidate();
115*c8dee2aaSAndroid Build Coastguard Worker         return true;
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker     return false;
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker 
getColorSlot(const SlotID & slotID) const120*c8dee2aaSAndroid Build Coastguard Worker std::optional<SkColor> skottie::SlotManager::getColorSlot(const SlotID& slotID) const {
121*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fColorMap.find(slotID);
122*c8dee2aaSAndroid Build Coastguard Worker     return valueGroup && !valueGroup->empty() ? std::optional<SkColor>(*(valueGroup->at(0).value))
123*c8dee2aaSAndroid Build Coastguard Worker                                               : std::nullopt;
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker 
getImageSlot(const SlotID & slotID) const126*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const skresources::ImageAsset> skottie::SlotManager::getImageSlot(
127*c8dee2aaSAndroid Build Coastguard Worker         const SlotID& slotID) const {
128*c8dee2aaSAndroid Build Coastguard Worker     const auto imageGroup = fImageMap.find(slotID);
129*c8dee2aaSAndroid Build Coastguard Worker     return imageGroup && !imageGroup->empty() ? imageGroup->at(0)->getImageAsset() : nullptr;
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker 
getScalarSlot(const SlotID & slotID) const132*c8dee2aaSAndroid Build Coastguard Worker std::optional<float> skottie::SlotManager::getScalarSlot(const SlotID& slotID) const {
133*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fScalarMap.find(slotID);
134*c8dee2aaSAndroid Build Coastguard Worker     return valueGroup && !valueGroup->empty() ? std::optional<float>(*(valueGroup->at(0).value))
135*c8dee2aaSAndroid Build Coastguard Worker                                               : std::nullopt;
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker 
getVec2Slot(const SlotID & slotID) const138*c8dee2aaSAndroid Build Coastguard Worker std::optional<SkV2> skottie::SlotManager::getVec2Slot(const SlotID& slotID) const {
139*c8dee2aaSAndroid Build Coastguard Worker     const auto valueGroup = fVec2Map.find(slotID);
140*c8dee2aaSAndroid Build Coastguard Worker     return valueGroup && !valueGroup->empty() ? std::optional<SkV2>(*(valueGroup->at(0).value))
141*c8dee2aaSAndroid Build Coastguard Worker                                               : std::nullopt;
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker 
getTextSlot(const SlotID & slotID) const144*c8dee2aaSAndroid Build Coastguard Worker std::optional<skottie::TextPropertyValue> skottie::SlotManager::getTextSlot(
145*c8dee2aaSAndroid Build Coastguard Worker         const SlotID& slotID) const {
146*c8dee2aaSAndroid Build Coastguard Worker     const auto adapterGroup = fTextMap.find(slotID);
147*c8dee2aaSAndroid Build Coastguard Worker     return adapterGroup && !adapterGroup->empty() ?
148*c8dee2aaSAndroid Build Coastguard Worker            std::optional<TextPropertyValue>(adapterGroup->at(0)->getText()) :
149*c8dee2aaSAndroid Build Coastguard Worker            std::nullopt;
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker 
trackColorValue(const SlotID & slotID,ColorValue * colorValue,sk_sp<internal::AnimatablePropertyContainer> adapter)152*c8dee2aaSAndroid Build Coastguard Worker void skottie::SlotManager::trackColorValue(const SlotID& slotID, ColorValue* colorValue,
153*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<internal::AnimatablePropertyContainer> adapter) {
154*c8dee2aaSAndroid Build Coastguard Worker     fColorMap[slotID].push_back({colorValue, std::move(adapter)});
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker 
trackImageValue(const SlotID & slotID,sk_sp<skresources::ImageAsset> imageAsset)157*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skresources::ImageAsset> skottie::SlotManager::trackImageValue(const SlotID& slotID,
158*c8dee2aaSAndroid Build Coastguard Worker                                                                      sk_sp<skresources::ImageAsset>
159*c8dee2aaSAndroid Build Coastguard Worker                                                                         imageAsset) {
160*c8dee2aaSAndroid Build Coastguard Worker     auto proxy = sk_make_sp<ImageAssetProxy>(std::move(imageAsset));
161*c8dee2aaSAndroid Build Coastguard Worker     fImageMap[slotID].push_back(proxy);
162*c8dee2aaSAndroid Build Coastguard Worker     return proxy;
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker 
trackScalarValue(const SlotID & slotID,ScalarValue * scalarValue,sk_sp<internal::AnimatablePropertyContainer> adapter)165*c8dee2aaSAndroid Build Coastguard Worker void skottie::SlotManager::trackScalarValue(const SlotID& slotID, ScalarValue* scalarValue,
166*c8dee2aaSAndroid Build Coastguard Worker                                             sk_sp<internal::AnimatablePropertyContainer> adapter) {
167*c8dee2aaSAndroid Build Coastguard Worker     fScalarMap[slotID].push_back({scalarValue, std::move(adapter)});
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker 
trackVec2Value(const SlotID & slotID,Vec2Value * vec2Value,sk_sp<internal::AnimatablePropertyContainer> adapter)170*c8dee2aaSAndroid Build Coastguard Worker void skottie::SlotManager::trackVec2Value(const SlotID& slotID, Vec2Value* vec2Value,
171*c8dee2aaSAndroid Build Coastguard Worker                                           sk_sp<internal::AnimatablePropertyContainer> adapter) {
172*c8dee2aaSAndroid Build Coastguard Worker     fVec2Map[slotID].push_back({vec2Value, std::move(adapter)});
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker 
trackTextValue(const SlotID & slotID,sk_sp<internal::TextAdapter> adapter)175*c8dee2aaSAndroid Build Coastguard Worker void skottie::SlotManager::trackTextValue(const SlotID& slotID,
176*c8dee2aaSAndroid Build Coastguard Worker                                           sk_sp<internal::TextAdapter> adapter) {
177*c8dee2aaSAndroid Build Coastguard Worker     fTextMap[slotID].push_back(std::move(adapter));
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker 
getSlotInfo() const180*c8dee2aaSAndroid Build Coastguard Worker skottie::SlotManager::SlotInfo skottie::SlotManager::getSlotInfo() const {
181*c8dee2aaSAndroid Build Coastguard Worker     SlotInfo sInfo;
182*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& c : fColorMap) {
183*c8dee2aaSAndroid Build Coastguard Worker         sInfo.fColorSlotIDs.push_back(c.first);
184*c8dee2aaSAndroid Build Coastguard Worker     }
185*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& s : fScalarMap) {
186*c8dee2aaSAndroid Build Coastguard Worker         sInfo.fScalarSlotIDs.push_back(s.first);
187*c8dee2aaSAndroid Build Coastguard Worker     }
188*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& v : fVec2Map) {
189*c8dee2aaSAndroid Build Coastguard Worker         sInfo.fVec2SlotIDs.push_back(v.first);
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& i : fImageMap) {
192*c8dee2aaSAndroid Build Coastguard Worker         sInfo.fImageSlotIDs.push_back(i.first);
193*c8dee2aaSAndroid Build Coastguard Worker     }
194*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& t : fTextMap) {
195*c8dee2aaSAndroid Build Coastguard Worker         sInfo.fTextSlotIDs.push_back(t.first);
196*c8dee2aaSAndroid Build Coastguard Worker     }
197*c8dee2aaSAndroid Build Coastguard Worker     return sInfo;
198*c8dee2aaSAndroid Build Coastguard Worker }
199