From 58007fc64cfc17540ed5e687efaf043cd7d4ce23 Mon Sep 17 00:00:00 2001 From: Bruno Leroux Date: Fri, 17 Jun 2022 08:16:06 +0200 Subject: [PATCH] Fix debugPaintSize throws 'Null Check error' (#106108) --- packages/flutter/lib/src/rendering/box.dart | 1 + .../flutter/lib/src/rendering/proxy_box.dart | 24 ++++-- .../test/rendering/proxy_box_test.dart | 76 +++++++++++++++++++ 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index e60dd60db694..d9b5b699c883 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -2738,6 +2738,7 @@ abstract class RenderBox extends RenderObject { /// /// Called for every [RenderBox] when [debugPaintSizeEnabled] is true. @protected + @visibleForTesting void debugPaintSize(PaintingContext context, Offset offset) { assert(() { final Paint paint = Paint() diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 22f138dd0c39..001bf45679c1 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -1580,8 +1580,10 @@ class RenderClipRect extends _RenderCustomClip { assert(() { if (child != null) { super.debugPaintSize(context, offset); - context.canvas.drawRect(_clip!.shift(offset), _debugPaint!); - _debugText!.paint(context.canvas, offset + Offset(_clip!.width / 8.0, -_debugText!.text!.style!.fontSize! * 1.1)); + if (clipBehavior != Clip.none) { + context.canvas.drawRect(_clip!.shift(offset), _debugPaint!); + _debugText!.paint(context.canvas, offset + Offset(_clip!.width / 8.0, -_debugText!.text!.style!.fontSize! * 1.1)); + } } return true; }()); @@ -1687,8 +1689,10 @@ class RenderClipRRect extends _RenderCustomClip { assert(() { if (child != null) { super.debugPaintSize(context, offset); - context.canvas.drawRRect(_clip!.shift(offset), _debugPaint!); - _debugText!.paint(context.canvas, offset + Offset(_clip!.tlRadiusX, -_debugText!.text!.style!.fontSize! * 1.1)); + if (clipBehavior != Clip.none) { + context.canvas.drawRRect(_clip!.shift(offset), _debugPaint!); + _debugText!.paint(context.canvas, offset + Offset(_clip!.tlRadiusX, -_debugText!.text!.style!.fontSize! * 1.1)); + } } return true; }()); @@ -1773,8 +1777,10 @@ class RenderClipOval extends _RenderCustomClip { assert(() { if (child != null) { super.debugPaintSize(context, offset); - context.canvas.drawPath(_getClipPath(_clip!).shift(offset), _debugPaint!); - _debugText!.paint(context.canvas, offset + Offset((_clip!.width - _debugText!.width) / 2.0, -_debugText!.text!.style!.fontSize! * 1.1)); + if (clipBehavior != Clip.none) { + context.canvas.drawPath(_getClipPath(_clip!).shift(offset), _debugPaint!); + _debugText!.paint(context.canvas, offset + Offset((_clip!.width - _debugText!.width) / 2.0, -_debugText!.text!.style!.fontSize! * 1.1)); + } } return true; }()); @@ -1851,8 +1857,10 @@ class RenderClipPath extends _RenderCustomClip { assert(() { if (child != null) { super.debugPaintSize(context, offset); - context.canvas.drawPath(_clip!.shift(offset), _debugPaint!); - _debugText!.paint(context.canvas, offset); + if (clipBehavior != Clip.none) { + context.canvas.drawPath(_clip!.shift(offset), _debugPaint!); + _debugText!.paint(context.canvas, offset); + } } return true; }()); diff --git a/packages/flutter/test/rendering/proxy_box_test.dart b/packages/flutter/test/rendering/proxy_box_test.dart index 8495ec2cad08..25498b522371 100644 --- a/packages/flutter/test/rendering/proxy_box_test.dart +++ b/packages/flutter/test/rendering/proxy_box_test.dart @@ -9,6 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'mock_canvas.dart'; import 'rendering_tester.dart'; void main() { @@ -770,6 +771,81 @@ void main() { Offset.zero & renderClipRect.size, ); }); + + // Simulate painting a RenderBox as if 'debugPaintSizeEnabled == true' + Function(PaintingContext, Offset) debugPaint(RenderBox renderBox) { + layout(renderBox); + pumpFrame(phase: EnginePhase.compositingBits); + return (PaintingContext context, Offset offset) { + renderBox.paint(context, offset); + renderBox.debugPaintSize(context, offset); + }; + } + + test('RenderClipPath.debugPaintSize draws a path and a debug text when clipBehavior is not Clip.none', () { + Function(PaintingContext, Offset) debugPaintClipRect(Clip clip) { + final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200)); + final RenderClipPath renderClipPath = RenderClipPath(clipBehavior: clip, child: child); + return debugPaint(renderClipPath); + } + + // RenderClipPath.debugPaintSize draws when clipBehavior is not Clip.none + expect(debugPaintClipRect(Clip.hardEdge), paintsExactlyCountTimes(#drawPath, 1)); + expect(debugPaintClipRect(Clip.hardEdge), paintsExactlyCountTimes(#drawParagraph, 1)); + + // RenderClipPath.debugPaintSize does not draw when clipBehavior is Clip.none + // Regression test for https://github.com/flutter/flutter/issues/105969 + expect(debugPaintClipRect(Clip.none), paintsExactlyCountTimes(#drawPath, 0)); + expect(debugPaintClipRect(Clip.none), paintsExactlyCountTimes(#drawParagraph, 0)); + }); + + test('RenderClipRect.debugPaintSize draws a rect and a debug text when clipBehavior is not Clip.none', () { + Function(PaintingContext, Offset) debugPaintClipRect(Clip clip) { + final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200)); + final RenderClipRect renderClipRect = RenderClipRect(clipBehavior: clip, child: child); + return debugPaint(renderClipRect); + } + + // RenderClipRect.debugPaintSize draws when clipBehavior is not Clip.none + expect(debugPaintClipRect(Clip.hardEdge), paintsExactlyCountTimes(#drawRect, 1)); + expect(debugPaintClipRect(Clip.hardEdge), paintsExactlyCountTimes(#drawParagraph, 1)); + + // RenderClipRect.debugPaintSize does not draw when clipBehavior is Clip.none + expect(debugPaintClipRect(Clip.none), paintsExactlyCountTimes(#drawRect, 0)); + expect(debugPaintClipRect(Clip.none), paintsExactlyCountTimes(#drawParagraph, 0)); + }); + + test('RenderClipRRect.debugPaintSize draws a rounded rect and a debug text when clipBehavior is not Clip.none', () { + Function(PaintingContext, Offset) debugPaintClipRRect(Clip clip) { + final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200)); + final RenderClipRRect renderClipRRect = RenderClipRRect(clipBehavior: clip, child: child); + return debugPaint(renderClipRRect); + } + + // RenderClipRRect.debugPaintSize draws when clipBehavior is not Clip.none + expect(debugPaintClipRRect(Clip.hardEdge), paintsExactlyCountTimes(#drawRRect, 1)); + expect(debugPaintClipRRect(Clip.hardEdge), paintsExactlyCountTimes(#drawParagraph, 1)); + + // RenderClipRRect.debugPaintSize does not draw when clipBehavior is Clip.none + expect(debugPaintClipRRect(Clip.none), paintsExactlyCountTimes(#drawRRect, 0)); + expect(debugPaintClipRRect(Clip.none), paintsExactlyCountTimes(#drawParagraph, 0)); + }); + + test('RenderClipOval.debugPaintSize draws a path and a debug text when clipBehavior is not Clip.none', () { + Function(PaintingContext, Offset) debugPaintClipOval(Clip clip) { + final RenderBox child = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 200, height: 200)); + final RenderClipOval renderClipOval = RenderClipOval(clipBehavior: clip, child: child); + return debugPaint(renderClipOval); + } + + // RenderClipOval.debugPaintSize draws when clipBehavior is not Clip.none + expect(debugPaintClipOval(Clip.hardEdge), paintsExactlyCountTimes(#drawPath, 1)); + expect(debugPaintClipOval(Clip.hardEdge), paintsExactlyCountTimes(#drawParagraph, 1)); + + // RenderClipOval.debugPaintSize does not draw when clipBehavior is Clip.none + expect(debugPaintClipOval(Clip.none), paintsExactlyCountTimes(#drawPath, 0)); + expect(debugPaintClipOval(Clip.none), paintsExactlyCountTimes(#drawParagraph, 0)); + }); } class _TestRectClipper extends CustomClipper {