@@ -165,7 +165,7 @@ mixin RenderVisibilityDetectorBase on RenderObject {
165165 }
166166
167167 VisibilityInfo _determineVisibility (ContainerLayer ? layer, Rect bounds) {
168- if (_disposed || layer? .attached == false || ! attached) {
168+ if (_disposed || layer == null || layer .attached == false || ! attached) {
169169 // layer is detached and thus invisible.
170170 return VisibilityInfo (
171171 key: key,
@@ -174,39 +174,50 @@ mixin RenderVisibilityDetectorBase on RenderObject {
174174 }
175175 final transform = Matrix4 .identity ();
176176
177- // Create a list of RenderObjects from this to the root, excluding the root
177+ // Check if any ancestors decided to skip painting this RenderObject.
178+ if (parent != null ) {
179+ RenderObject ancestor = parent! as RenderObject ;
180+ RenderObject child = this ;
181+ while (ancestor.parent != null ) {
182+ if (! ancestor.paintsChild (child)) {
183+ return VisibilityInfo (key: key, size: bounds.size);
184+ }
185+ child = ancestor;
186+ ancestor = ancestor.parent! as RenderObject ;
187+ }
188+ }
189+
190+ // Create a list of Layers from layer to the root, excluding the root
178191 // since that has the DPR transform and we want to work with logical pixels.
179- // Cannot use the layer tree since some ancestor render object may have
180- // directly transformed/clipped the canvas. If there is some way to figure
181- // out how to get the RenderObjects below [layer], could take advantage of
182- // the usually shallower height of the layer tree compared to the render
183- // tree. Alternatively, if the canvas itself exposed the current matrix/clip
184- // we could use that.
185- RenderObject ? ancestor = parent as RenderObject ? ;
186-
187- final List <RenderObject > ancestors = < RenderObject > [];
188- ancestors.add (this );
189- RenderObject child = this ;
192+ // Add one extra leaf layer so that we can apply the transform of `layer`
193+ // to the matrix.
194+ ContainerLayer ? ancestor = layer;
195+ final List <ContainerLayer > ancestors = < ContainerLayer > [ContainerLayer ()];
190196 while (ancestor != null && ancestor.parent != null ) {
191- if (! ancestor.paintsChild (child)) {
192- return VisibilityInfo (key: key, size: bounds.size);
193- }
194197 ancestors.add (ancestor);
195- child = ancestor;
196- ancestor = ancestor.parent as RenderObject ? ;
198+ ancestor = ancestor.parent;
197199 }
198200
199- // Determine the transform and clip from first child of root down to
200- // this.
201201 Rect clip = Rect .largest;
202202 for (int index = ancestors.length - 1 ; index > 0 ; index -= 1 ) {
203203 final parent = ancestors[index];
204204 final child = ancestors[index - 1 ];
205- Rect ? parentClip = parent.describeApproximatePaintClip (child );
205+ Rect ? parentClip = parent.describeClipBounds ( );
206206 if (parentClip != null ) {
207207 clip = clip.intersect (MatrixUtils .transformRect (transform, parentClip));
208208 }
209- parent.applyPaintTransform (child, transform);
209+ parent.applyTransform (child, transform);
210+ }
211+
212+ // Apply whatever transform/clip was on the canvas when painting.
213+ if (_lastPaintClipBounds != null ) {
214+ clip = clip.intersect (MatrixUtils .transformRect (
215+ transform,
216+ _lastPaintClipBounds! ,
217+ ));
218+ }
219+ if (_lastPaintTransform != null ) {
220+ transform.multiply (_lastPaintTransform! );
210221 }
211222 return VisibilityInfo .fromRects (
212223 key: key,
@@ -219,9 +230,17 @@ mixin RenderVisibilityDetectorBase on RenderObject {
219230 /// clients about visibility.
220231 Rect get bounds;
221232
233+ Matrix4 ? _lastPaintTransform;
234+ Rect ? _lastPaintClipBounds;
235+
222236 @override
223237 void paint (PaintingContext context, Offset offset) {
224238 if (onVisibilityChanged != null ) {
239+ _lastPaintClipBounds = context.canvas.getLocalClipBounds ();
240+ _lastPaintTransform =
241+ Matrix4 .fromFloat64List (context.canvas.getTransform ())
242+ ..translate (offset.dx, offset.dy, 0 );
243+
225244 _compositionCallbackCanceller? .call ();
226245 _compositionCallbackCanceller =
227246 context.addCompositionCallback ((Layer layer) {
0 commit comments