Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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)
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: