Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
skottie::internal::LayerBuilder Class Referencefinal

#include <Layer.h>

Public Member Functions

 LayerBuilder (const skjson::ObjectValue &jlayer, const SkSize &comp_size)
 
 LayerBuilder (const LayerBuilder &)=default
 
 ~LayerBuilder ()
 
int index () const
 
bool isCamera () const
 
sk_sp< sksg::TransformbuildTransform (const AnimationBuilder &, CompositionBuilder *)
 
sk_sp< sksg::RenderNodebuildRenderTree (const AnimationBuilder &, CompositionBuilder *, const LayerBuilder *prev_layer)
 
const sk_sp< sksg::RenderNode > & contentTree () const
 
const SkSizesize () const
 

Detailed Description

Definition at line 31 of file Layer.h.

Constructor & Destructor Documentation

◆ LayerBuilder() [1/2]

skottie::internal::LayerBuilder::LayerBuilder ( const skjson::ObjectValue jlayer,
const SkSize comp_size 
)

Definition at line 329 of file Layer.cpp.

330 : fJlayer(jlayer)
331 , fIndex (ParseDefault<int>(jlayer["ind" ], -1))
332 , fParentIndex(ParseDefault<int>(jlayer["parent"], -1))
333 , fType (ParseDefault<int>(jlayer["ty" ], -1))
334 , fAutoOrient (ParseDefault<int>(jlayer["ao" ], 0))
335 , fInfo{comp_size,
336 ParseDefault<float>(jlayer["ip"], 0.0f),
337 ParseDefault<float>(jlayer["op"], 0.0f)}
338{
339
340 if (this->isCamera() || ParseDefault<int>(jlayer["ddd"], 0)) {
341 fFlags |= Flags::kIs3D;
342 }
343}

◆ LayerBuilder() [2/2]

skottie::internal::LayerBuilder::LayerBuilder ( const LayerBuilder )
default

◆ ~LayerBuilder()

skottie::internal::LayerBuilder::~LayerBuilder ( )
default

Member Function Documentation

◆ buildRenderTree()

sk_sp< sksg::RenderNode > skottie::internal::LayerBuilder::buildRenderTree ( const AnimationBuilder abuilder,
CompositionBuilder cbuilder,
const LayerBuilder prev_layer 
)

Definition at line 431 of file Layer.cpp.

433 {
434 const AnimationBuilder::AutoPropertyTracker apt(&abuilder, fJlayer, PropertyObserver::NodeType::LAYER);
435
436 using LayerBuilder =
437 sk_sp<sksg::RenderNode> (AnimationBuilder::*)(const skjson::ObjectValue&,
438 AnimationBuilder::LayerInfo*) const;
439
440 // AE is annoyingly inconsistent in how effects interact with layer transforms: depending on
441 // the layer type, effects are applied before or after the content is transformed.
442 //
443 // Empirically, pre-rendered layers (for some loose meaning of "pre-rendered") are in the
444 // former category (effects are subject to transformation), while the remaining types are in
445 // the latter.
446 enum : uint32_t {
447 kTransformEffects = 0x01, // The layer transform also applies to its effects.
448 kForceSeek = 0x02, // Dispatch all seek() events even when the layer is inactive.
449 };
450
451 static constexpr struct {
452 LayerBuilder fBuilder;
453 uint32_t fFlags;
454 } gLayerBuildInfo[] = {
455 { &AnimationBuilder::attachPrecompLayer, kTransformEffects }, // 'ty': 0 -> precomp
456 { &AnimationBuilder::attachSolidLayer , kTransformEffects }, // 'ty': 1 -> solid
457 { &AnimationBuilder::attachFootageLayer, kTransformEffects }, // 'ty': 2 -> image
458 { &AnimationBuilder::attachNullLayer , 0 }, // 'ty': 3 -> null
459 { &AnimationBuilder::attachShapeLayer , 0 }, // 'ty': 4 -> shape
460 { &AnimationBuilder::attachTextLayer , 0 }, // 'ty': 5 -> text
461 { &AnimationBuilder::attachAudioLayer , kForceSeek }, // 'ty': 6 -> audio
462 { nullptr , 0 }, // 'ty': 7 -> pholderVideo
463 { nullptr , 0 }, // 'ty': 8 -> imageSeq
464 { &AnimationBuilder::attachFootageLayer, kTransformEffects }, // 'ty': 9 -> video
465 { nullptr , 0 }, // 'ty': 10 -> pholderStill
466 { nullptr , 0 }, // 'ty': 11 -> guide
467 { nullptr , 0 }, // 'ty': 12 -> adjustment
468 { &AnimationBuilder::attachNullLayer , 0 }, // 'ty': 13 -> camera
469 { nullptr , 0 }, // 'ty': 14 -> light
470 };
471
472 if (fType < 0 || static_cast<size_t>(fType) >= std::size(gLayerBuildInfo)) {
473 return nullptr;
474 }
475
476 const auto& build_info = gLayerBuildInfo[fType];
477
478 // Switch to the layer animator scope (which at this point holds transform-only animators).
479 AnimationBuilder::AutoScope ascope(&abuilder, std::move(fLayerScope));
480
481 // Potentially null.
483
484 // Build the layer content fragment.
485 if (build_info.fBuilder) {
486 layer = (abuilder.*(build_info.fBuilder))(fJlayer, &fInfo);
487 }
488
489 // Clip layers with explicit dimensions.
490 float w = 0, h = 0;
491 if (::skottie::Parse<float>(fJlayer["w"], &w) && ::skottie::Parse<float>(fJlayer["h"], &h)) {
492 layer = sksg::ClipEffect::Make(std::move(layer),
494#ifdef SK_LEGACY_SKOTTIE_CLIPPING
495 /*aa=*/true, /*force_clip=*/false);
496#else
497 /*aa=*/true, /*force_clip=*/true);
498#endif
499 }
500
501 // Optional layer mask.
502 layer = AttachMask(fJlayer["masksProperties"], &abuilder, std::move(layer));
503
504 // Does the transform apply to effects also?
505 // (AE quirk: it doesn't - except for solid layers)
506 const auto transform_effects = (build_info.fFlags & kTransformEffects);
507
508 // Attach the transform before effects, when needed.
509 if (fLayerTransform && !transform_effects) {
510 layer = sksg::TransformEffect::Make(std::move(layer), fLayerTransform);
511 }
512
513 // Optional layer effects.
514 if (const skjson::ArrayValue* jeffects = fJlayer["ef"]) {
515 layer = EffectBuilder(&abuilder, fInfo.fSize, cbuilder)
516 .attachEffects(*jeffects, std::move(layer));
517 }
518
519 // Attach the transform after effects, when needed.
520 if (fLayerTransform && transform_effects) {
521 layer = sksg::TransformEffect::Make(std::move(layer), std::move(fLayerTransform));
522 }
523
524 // Optional layer styles.
525 if (const skjson::ArrayValue* jstyles = fJlayer["sy"]) {
526 layer = EffectBuilder(&abuilder, fInfo.fSize, cbuilder)
527 .attachStyles(*jstyles, std::move(layer));
528 }
529
530 // Optional layer opacity.
531 // TODO: de-dupe this "ks" lookup with matrix above.
532 if (const skjson::ObjectValue* jtransform = fJlayer["ks"]) {
533 layer = abuilder.attachOpacity(*jtransform, std::move(layer));
534 }
535
536 // Stash the content tree in case it is needed for later mattes.
537 fContentTree = layer;
538 if (ParseDefault<bool>(fJlayer["hd"], false)) {
539 layer = nullptr;
540 }
541
542 const auto has_animators = !abuilder.fCurrentAnimatorScope->empty();
543 const auto force_seek_count = build_info.fFlags & kForceSeek
544 ? abuilder.fCurrentAnimatorScope->size()
545 : fTransformAnimatorCount;
546
547 sk_sp<Animator> controller = sk_make_sp<LayerController>(ascope.release(),
548 layer,
549 force_seek_count,
550 fInfo.fInPoint,
551 fInfo.fOutPoint);
552
553 // Optional motion blur.
554 if (layer && has_animators && this->hasMotionBlur(cbuilder)) {
555 // Wrap both the layer node and the controller.
556 auto motion_blur = MotionBlurEffect::Make(std::move(controller), std::move(layer),
557 cbuilder->fMotionBlurSamples,
558 cbuilder->fMotionBlurAngle,
559 cbuilder->fMotionBlurPhase);
560 controller = sk_make_sp<MotionBlurController>(motion_blur);
561 layer = std::move(motion_blur);
562 }
563
564 abuilder.fCurrentAnimatorScope->push_back(std::move(controller));
565
566 if (ParseDefault<bool>(fJlayer["td"], false)) {
567 // |layer| is a track matte. We apply it as a mask to the next layer.
568 return nullptr;
569 }
570
571 // Optional matte.
572 const auto matte_mode = prev_layer
573 ? ParseDefault<size_t>(fJlayer["tt"], 0)
574 : 0;
575 if (matte_mode > 0) {
576 static constexpr sksg::MaskEffect::Mode gMatteModes[] = {
581 };
582
583 if (matte_mode <= std::size(gMatteModes)) {
584 // The current layer is masked with the previous layer *content*.
585 layer = sksg::MaskEffect::Make(std::move(layer),
586 prev_layer->fContentTree,
587 gMatteModes[matte_mode - 1]);
588 } else {
589 abuilder.log(Logger::Level::kError, nullptr,
590 "Unknown track matte mode: %zu\n", matte_mode);
591 }
592 }
593
594 // Finally, attach an optional blend mode.
595 // NB: blend modes are never applied to matte sources (layer content only).
596 return abuilder.attachBlendMode(fJlayer, std::move(layer));
597}
LayerBuilder(const skjson::ObjectValue &jlayer, const SkSize &comp_size)
Definition: Layer.cpp:329
static sk_sp< MotionBlurEffect > Make(sk_sp< Animator > animator, sk_sp< sksg::RenderNode > child, size_t samples_per_frame, float shutter_angle, float shutter_phase)
static sk_sp< ClipEffect > Make(sk_sp< RenderNode > child, sk_sp< GeometryNode > clip, bool aa=false, bool force_clip=false)
static sk_sp< MaskEffect > Make(sk_sp< RenderNode > child, sk_sp< RenderNode > mask, Mode mode=Mode::kAlphaNormal)
static sk_sp< Rect > Make()
Definition: SkSGRect.h:36
static sk_sp< TransformEffect > Make(sk_sp< RenderNode > child, sk_sp< Transform > transform)
Definition: SkSGTransform.h:97
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
SkScalar w
SkScalar h
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609

◆ buildTransform()

sk_sp< sksg::Transform > skottie::internal::LayerBuilder::buildTransform ( const AnimationBuilder abuilder,
CompositionBuilder cbuilder 
)

Definition at line 353 of file Layer.cpp.

354 {
355 // Depending on the leaf node type, we treat the whole transform chain as either 2D or 3D.
356 const auto transform_chain_type = this->is3D() ? TransformType::k3D
357 : TransformType::k2D;
358 fLayerTransform = this->getTransform(abuilder, cbuilder, transform_chain_type);
359
360 return fLayerTransform;
361}

◆ contentTree()

const sk_sp< sksg::RenderNode > & skottie::internal::LayerBuilder::contentTree ( ) const
inline

Definition at line 48 of file Layer.h.

48{ return fContentTree; }

◆ index()

int skottie::internal::LayerBuilder::index ( ) const
inline

Definition at line 37 of file Layer.h.

37{ return fIndex; }

◆ isCamera()

bool skottie::internal::LayerBuilder::isCamera ( ) const

Definition at line 347 of file Layer.cpp.

347 {
348 static constexpr int kCameraLayerType = 13;
349
350 return fType == kCameraLayerType;
351}

◆ size()

const SkSize & skottie::internal::LayerBuilder::size ( ) const
inline

Definition at line 50 of file Layer.h.

50{ return fInfo.fSize; }

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