@@ -642,10 +642,17 @@ internal ShapeLayerTranslator(ShapeLayerContext context)
642642 _context = context ;
643643 }
644644
645+ // Indicates if we can translate shape layer as a single composition shape (GetShapeRoot).
646+ // Otherwise we should use extra parent Visual (GetVisualRoot).
647+ //
648+ // Note: We can apply Masks and effects only to Visual node.
649+ // Also we can reduce number of expression animations if we apply opacity directly to visual node
650+ // instead of pushing it down to color fill that will produce color expression animation.
645651 internal override bool IsShape =>
646652 ! _context . Layer . Masks . Any ( ) &&
647653 _context . Effects . DropShadowEffect is null &&
648- _context . Effects . GaussianBlurEffect is null ;
654+ _context . Effects . GaussianBlurEffect is null &&
655+ _context . Layer . Transform . Opacity . IsAlways ( Opacity . Opaque ) ;
649656
650657 internal override CompositionShape ? GetShapeRoot ( TranslationContext context )
651658 {
@@ -668,6 +675,9 @@ _context.Effects.DropShadowEffect is null &&
668675
669676 // Update the opacity from the transform. This is necessary to push the opacity
670677 // to the leaves (because CompositionShape does not support opacity).
678+ // Note: this is no longer used because we will not call GetShapeRoot if layer transform has
679+ // animated opacity, instead we will call GetVisualRoot. But let's keep it here
680+ // just in case we will change the logic of IsShape flag.
671681 shapeContext . UpdateOpacityFromTransform ( _context , _context . Layer . Transform ) ;
672682 contentsNode . Shapes . Add ( TranslateShapeLayerContents ( shapeContext , _context . Layer . Contents ) ) ;
673683
0 commit comments