1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 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 "include/core/SkBlendMode.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPictureRecorder.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTPin.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/Adapter.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottiePriv.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottieValue.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/effects/Effects.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGNode.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGRenderNode.h"
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
35*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
36*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
37*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
38*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker namespace skjson {
41*c8dee2aaSAndroid Build Coastguard Worker class ArrayValue;
42*c8dee2aaSAndroid Build Coastguard Worker }
43*c8dee2aaSAndroid Build Coastguard Worker namespace sksg {
44*c8dee2aaSAndroid Build Coastguard Worker class InvalidationController;
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker namespace skottie {
48*c8dee2aaSAndroid Build Coastguard Worker namespace internal {
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker namespace {
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker // AE motion tile effect semantics
53*c8dee2aaSAndroid Build Coastguard Worker // (https://helpx.adobe.com/after-effects/using/stylize-effects.html#motion_tile_effect):
54*c8dee2aaSAndroid Build Coastguard Worker //
55*c8dee2aaSAndroid Build Coastguard Worker // - the full content of the layer is mapped to a tile: tile_center, tile_width, tile_height
56*c8dee2aaSAndroid Build Coastguard Worker //
57*c8dee2aaSAndroid Build Coastguard Worker // - tiles are repeated in both dimensions to fill the output area: output_width, output_height
58*c8dee2aaSAndroid Build Coastguard Worker //
59*c8dee2aaSAndroid Build Coastguard Worker // - tiling mode is either kRepeat (default) or kMirror (when mirror_edges == true)
60*c8dee2aaSAndroid Build Coastguard Worker //
61*c8dee2aaSAndroid Build Coastguard Worker // - for a non-zero phase, alternating vertical columns (every other column) are offset by
62*c8dee2aaSAndroid Build Coastguard Worker // the specified amount
63*c8dee2aaSAndroid Build Coastguard Worker //
64*c8dee2aaSAndroid Build Coastguard Worker // - when horizontal_phase is true, the phase is applied to horizontal rows instead of columns
65*c8dee2aaSAndroid Build Coastguard Worker //
66*c8dee2aaSAndroid Build Coastguard Worker class TileRenderNode final : public sksg::CustomRenderNode {
67*c8dee2aaSAndroid Build Coastguard Worker public:
TileRenderNode(const SkSize & size,sk_sp<sksg::RenderNode> layer)68*c8dee2aaSAndroid Build Coastguard Worker TileRenderNode(const SkSize& size, sk_sp<sksg::RenderNode> layer)
69*c8dee2aaSAndroid Build Coastguard Worker : INHERITED({std::move(layer)})
70*c8dee2aaSAndroid Build Coastguard Worker , fLayerSize(size) {}
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(TileCenter , SkPoint , fTileCenter )
73*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(TileWidth , SkScalar, fTileW )
74*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(TileHeight , SkScalar, fTileH )
75*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(OutputWidth , SkScalar, fOutputW )
76*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(OutputHeight , SkScalar, fOutputH )
77*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(Phase , SkScalar, fPhase )
78*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(MirrorEdges , bool , fMirrorEdges )
79*c8dee2aaSAndroid Build Coastguard Worker SG_ATTRIBUTE(HorizontalPhase, bool , fHorizontalPhase)
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker protected:
onNodeAt(const SkPoint &) const82*c8dee2aaSAndroid Build Coastguard Worker const RenderNode* onNodeAt(const SkPoint&) const override { return nullptr; } // no hit-testing
83*c8dee2aaSAndroid Build Coastguard Worker
onRevalidate(sksg::InvalidationController * ic,const SkMatrix & ctm)84*c8dee2aaSAndroid Build Coastguard Worker SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
85*c8dee2aaSAndroid Build Coastguard Worker // Re-record the layer picture if needed.
86*c8dee2aaSAndroid Build Coastguard Worker if (!fLayerPicture || this->hasChildrenInval()) {
87*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->children().size() == 1ul);
88*c8dee2aaSAndroid Build Coastguard Worker const auto& layer = this->children()[0];
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker layer->revalidate(ic, ctm);
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
93*c8dee2aaSAndroid Build Coastguard Worker layer->render(recorder.beginRecording(fLayerSize.width(), fLayerSize.height()));
94*c8dee2aaSAndroid Build Coastguard Worker fLayerPicture = recorder.finishRecordingAsPicture();
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker // tileW and tileH use layer size percentage units.
98*c8dee2aaSAndroid Build Coastguard Worker const auto tileW = SkTPin(fTileW, 0.0f, 100.0f) * 0.01f * fLayerSize.width(),
99*c8dee2aaSAndroid Build Coastguard Worker tileH = SkTPin(fTileH, 0.0f, 100.0f) * 0.01f * fLayerSize.height();
100*c8dee2aaSAndroid Build Coastguard Worker const auto tile_size = SkSize::Make(std::max(tileW, 1.0f),
101*c8dee2aaSAndroid Build Coastguard Worker std::max(tileH, 1.0f));
102*c8dee2aaSAndroid Build Coastguard Worker const auto tile = SkRect::MakeXYWH(fTileCenter.fX - 0.5f * tile_size.width(),
103*c8dee2aaSAndroid Build Coastguard Worker fTileCenter.fY - 0.5f * tile_size.height(),
104*c8dee2aaSAndroid Build Coastguard Worker tile_size.width(),
105*c8dee2aaSAndroid Build Coastguard Worker tile_size.height());
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker const auto layerShaderMatrix = SkMatrix::RectToRect(
108*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeWH(fLayerSize.width(), fLayerSize.height()), tile);
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker const auto tm = fMirrorEdges ? SkTileMode::kMirror : SkTileMode::kRepeat;
111*c8dee2aaSAndroid Build Coastguard Worker auto layer_shader = fLayerPicture->makeShader(tm, tm, SkFilterMode::kLinear,
112*c8dee2aaSAndroid Build Coastguard Worker &layerShaderMatrix, nullptr);
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker if (fPhase && layer_shader && tile.isFinite()) {
115*c8dee2aaSAndroid Build Coastguard Worker // To implement AE phase semantics, we construct a mask shader for the pass-through
116*c8dee2aaSAndroid Build Coastguard Worker // rows/columns. We then draw the layer content through this mask, and then again
117*c8dee2aaSAndroid Build Coastguard Worker // through the inverse mask with a phase shift.
118*c8dee2aaSAndroid Build Coastguard Worker const auto phase_vec = fHorizontalPhase
119*c8dee2aaSAndroid Build Coastguard Worker ? SkVector::Make(tile.width(), 0)
120*c8dee2aaSAndroid Build Coastguard Worker : SkVector::Make(0, tile.height());
121*c8dee2aaSAndroid Build Coastguard Worker const auto phase_shift = SkVector::Make(phase_vec.fX, phase_vec.fY)
122*c8dee2aaSAndroid Build Coastguard Worker * std::fmod(fPhase * (1/360.0f), 1);
123*c8dee2aaSAndroid Build Coastguard Worker const auto phase_shader_matrix = SkMatrix::Translate(phase_shift.x(), phase_shift.y());
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker // The mask is generated using a step gradient shader, spanning 2 x tile width/height,
126*c8dee2aaSAndroid Build Coastguard Worker // and perpendicular to the phase vector.
127*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkColor colors[] = { 0xffffffff, 0x00000000 };
128*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar pos[] = { 0.5f, 0.5f };
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {{ tile.x(), tile.y() },
131*c8dee2aaSAndroid Build Coastguard Worker { tile.x() + 2 * (tile.width() - phase_vec.fX),
132*c8dee2aaSAndroid Build Coastguard Worker tile.y() + 2 * (tile.height() - phase_vec.fY) }};
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Worker auto mask_shader = SkGradientShader::MakeLinear(pts, colors, pos,
135*c8dee2aaSAndroid Build Coastguard Worker std::size(colors),
136*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat);
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker // First drawing pass: in-place masked layer content.
139*c8dee2aaSAndroid Build Coastguard Worker fMainPassShader = SkShaders::Blend(SkBlendMode::kSrcIn , mask_shader, layer_shader);
140*c8dee2aaSAndroid Build Coastguard Worker // Second pass: phased-shifted layer content, with an inverse mask.
141*c8dee2aaSAndroid Build Coastguard Worker fPhasePassShader = SkShaders::Blend(SkBlendMode::kSrcOut, mask_shader, layer_shader)
142*c8dee2aaSAndroid Build Coastguard Worker ->makeWithLocalMatrix(phase_shader_matrix);
143*c8dee2aaSAndroid Build Coastguard Worker } else {
144*c8dee2aaSAndroid Build Coastguard Worker fMainPassShader = std::move(layer_shader);
145*c8dee2aaSAndroid Build Coastguard Worker fPhasePassShader = nullptr;
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker // outputW and outputH also use layer size percentage units.
149*c8dee2aaSAndroid Build Coastguard Worker const auto outputW = fOutputW * 0.01f * fLayerSize.width(),
150*c8dee2aaSAndroid Build Coastguard Worker outputH = fOutputH * 0.01f * fLayerSize.height();
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker return SkRect::MakeXYWH((fLayerSize.width() - outputW) * 0.5f,
153*c8dee2aaSAndroid Build Coastguard Worker (fLayerSize.height() - outputH) * 0.5f,
154*c8dee2aaSAndroid Build Coastguard Worker outputW, outputH);
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
onRender(SkCanvas * canvas,const RenderContext * ctx) const157*c8dee2aaSAndroid Build Coastguard Worker void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
158*c8dee2aaSAndroid Build Coastguard Worker // AE allow one of the tile dimensions to collapse, but not both.
159*c8dee2aaSAndroid Build Coastguard Worker if (this->bounds().isEmpty() || (fTileW <= 0 && fTileH <= 0)) {
160*c8dee2aaSAndroid Build Coastguard Worker return;
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
164*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker if (ctx) {
167*c8dee2aaSAndroid Build Coastguard Worker // apply any pending paint effects via the shader paint
168*c8dee2aaSAndroid Build Coastguard Worker ctx->modulatePaint(canvas->getLocalToDeviceAs3x3(), &paint);
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(fMainPassShader);
172*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(this->bounds(), paint);
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker if (fPhasePassShader) {
175*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(fPhasePassShader);
176*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(this->bounds(), paint);
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker private:
181*c8dee2aaSAndroid Build Coastguard Worker const SkSize fLayerSize;
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker SkPoint fTileCenter = { 0, 0 };
184*c8dee2aaSAndroid Build Coastguard Worker SkScalar fTileW = 1,
185*c8dee2aaSAndroid Build Coastguard Worker fTileH = 1,
186*c8dee2aaSAndroid Build Coastguard Worker fOutputW = 1,
187*c8dee2aaSAndroid Build Coastguard Worker fOutputH = 1,
188*c8dee2aaSAndroid Build Coastguard Worker fPhase = 0;
189*c8dee2aaSAndroid Build Coastguard Worker bool fMirrorEdges = false;
190*c8dee2aaSAndroid Build Coastguard Worker bool fHorizontalPhase = false;
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker // These are computed/cached on revalidation.
193*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> fLayerPicture; // cached picture for layer content
194*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fMainPassShader, // shader for the main tile(s)
195*c8dee2aaSAndroid Build Coastguard Worker fPhasePassShader; // shader for the phased tile(s)
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = sksg::CustomRenderNode;
198*c8dee2aaSAndroid Build Coastguard Worker };
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker class MotionTileAdapter final : public DiscardableAdapterBase<MotionTileAdapter, TileRenderNode> {
201*c8dee2aaSAndroid Build Coastguard Worker public:
MotionTileAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder & abuilder,const SkSize & layer_size)202*c8dee2aaSAndroid Build Coastguard Worker MotionTileAdapter(const skjson::ArrayValue& jprops,
203*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer,
204*c8dee2aaSAndroid Build Coastguard Worker const AnimationBuilder& abuilder,
205*c8dee2aaSAndroid Build Coastguard Worker const SkSize& layer_size)
206*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(sk_make_sp<TileRenderNode>(layer_size, std::move(layer))) {
207*c8dee2aaSAndroid Build Coastguard Worker
208*c8dee2aaSAndroid Build Coastguard Worker enum : size_t {
209*c8dee2aaSAndroid Build Coastguard Worker kTileCenter_Index = 0,
210*c8dee2aaSAndroid Build Coastguard Worker kTileWidth_Index = 1,
211*c8dee2aaSAndroid Build Coastguard Worker kTileHeight_Index = 2,
212*c8dee2aaSAndroid Build Coastguard Worker kOutputWidth_Index = 3,
213*c8dee2aaSAndroid Build Coastguard Worker kOutputHeight_Index = 4,
214*c8dee2aaSAndroid Build Coastguard Worker kMirrorEdges_Index = 5,
215*c8dee2aaSAndroid Build Coastguard Worker kPhase_Index = 6,
216*c8dee2aaSAndroid Build Coastguard Worker kHorizontalPhaseShift_Index = 7,
217*c8dee2aaSAndroid Build Coastguard Worker };
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard Worker EffectBinder(jprops, abuilder, this)
220*c8dee2aaSAndroid Build Coastguard Worker .bind( kTileCenter_Index, fTileCenter )
221*c8dee2aaSAndroid Build Coastguard Worker .bind( kTileWidth_Index, fTileW )
222*c8dee2aaSAndroid Build Coastguard Worker .bind( kTileHeight_Index, fTileH )
223*c8dee2aaSAndroid Build Coastguard Worker .bind( kOutputWidth_Index, fOutputW )
224*c8dee2aaSAndroid Build Coastguard Worker .bind( kOutputHeight_Index, fOutputH )
225*c8dee2aaSAndroid Build Coastguard Worker .bind( kMirrorEdges_Index, fMirrorEdges )
226*c8dee2aaSAndroid Build Coastguard Worker .bind( kPhase_Index, fPhase )
227*c8dee2aaSAndroid Build Coastguard Worker .bind(kHorizontalPhaseShift_Index, fHorizontalPhase);
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker
230*c8dee2aaSAndroid Build Coastguard Worker private:
onSync()231*c8dee2aaSAndroid Build Coastguard Worker void onSync() override {
232*c8dee2aaSAndroid Build Coastguard Worker const auto& tiler = this->node();
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker tiler->setTileCenter({fTileCenter.x, fTileCenter.y});
235*c8dee2aaSAndroid Build Coastguard Worker tiler->setTileWidth (fTileW);
236*c8dee2aaSAndroid Build Coastguard Worker tiler->setTileHeight(fTileH);
237*c8dee2aaSAndroid Build Coastguard Worker tiler->setOutputWidth (fOutputW);
238*c8dee2aaSAndroid Build Coastguard Worker tiler->setOutputHeight(fOutputH);
239*c8dee2aaSAndroid Build Coastguard Worker tiler->setPhase(fPhase);
240*c8dee2aaSAndroid Build Coastguard Worker tiler->setMirrorEdges(SkToBool(fMirrorEdges));
241*c8dee2aaSAndroid Build Coastguard Worker tiler->setHorizontalPhase(SkToBool(fHorizontalPhase));
242*c8dee2aaSAndroid Build Coastguard Worker }
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker Vec2Value fTileCenter = {0,0};
245*c8dee2aaSAndroid Build Coastguard Worker ScalarValue fTileW = 1,
246*c8dee2aaSAndroid Build Coastguard Worker fTileH = 1,
247*c8dee2aaSAndroid Build Coastguard Worker fOutputW = 1,
248*c8dee2aaSAndroid Build Coastguard Worker fOutputH = 1,
249*c8dee2aaSAndroid Build Coastguard Worker fMirrorEdges = 0,
250*c8dee2aaSAndroid Build Coastguard Worker fPhase = 0,
251*c8dee2aaSAndroid Build Coastguard Worker fHorizontalPhase = 0;
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = DiscardableAdapterBase<MotionTileAdapter, TileRenderNode>;
254*c8dee2aaSAndroid Build Coastguard Worker };
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker } // namespace
257*c8dee2aaSAndroid Build Coastguard Worker
attachMotionTileEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const258*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> EffectBuilder::attachMotionTileEffect(const skjson::ArrayValue& jprops,
259*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer) const {
260*c8dee2aaSAndroid Build Coastguard Worker return fBuilder->attachDiscardableAdapter<MotionTileAdapter>(jprops,
261*c8dee2aaSAndroid Build Coastguard Worker std::move(layer),
262*c8dee2aaSAndroid Build Coastguard Worker *fBuilder,
263*c8dee2aaSAndroid Build Coastguard Worker fLayerSize);
264*c8dee2aaSAndroid Build Coastguard Worker }
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker } // namespace internal
267*c8dee2aaSAndroid Build Coastguard Worker } // namespace skottie
268