diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index e4b183b104..4544d4f4f8 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -1264,9 +1264,43 @@ class RenderCustomPaint extends RenderProxyBox { } void _paintWithPainter(Canvas canvas, Offset offset, CustomPainter painter) { + int debugPreviousCanvasSaveCount; + canvas.save(); + assert(() { debugPreviousCanvasSaveCount = canvas.getSaveCount(); return true; }); canvas.translate(offset.dx, offset.dy); painter.paint(canvas, size); - canvas.translate(-offset.dx, -offset.dy); + assert(() { + // This isn't perfect. For example, we can't catch the case of + // someone first restoring, then setting a transform or whatnot, + // then saving. + // If this becomes a real problem, we could add logic to the + // Canvas class to lock the canvas at a particular save count + // such that restore() fails if it would take the lock count + // below that number. + int debugNewCanvasSaveCount = canvas.getSaveCount(); + if (debugNewCanvasSaveCount > debugPreviousCanvasSaveCount) { + throw new RenderingError( + 'The $painter custom painter called canvas.save() or canvas.saveLayer() at least ' + '${debugNewCanvasSaveCount - debugPreviousCanvasSaveCount} more ' + 'time${debugNewCanvasSaveCount - debugPreviousCanvasSaveCount == 1 ? '' : 's' } ' + 'than it called canvas.restore().\n' + 'This leaves the canvas in an inconsistent state and will probably result in a broken display.\n' + 'You must pair each call to save()/saveLayer() with a later matching call to restore().' + ); + } + if (debugNewCanvasSaveCount < debugPreviousCanvasSaveCount) { + throw new RenderingError( + 'The $painter custom painter called canvas.restore() ' + '${debugPreviousCanvasSaveCount - debugNewCanvasSaveCount} more ' + 'time${debugPreviousCanvasSaveCount - debugNewCanvasSaveCount == 1 ? '' : 's' } ' + 'than it called canvas.save() or canvas.saveLayer().\n' + 'This leaves the canvas in an inconsistent state and will result in a broken display.\n' + 'You should only call restore() if you first called save() or saveLayer().' + ); + } + return debugNewCanvasSaveCount == debugPreviousCanvasSaveCount; + }); + canvas.restore(); } void paint(PaintingContext context, Offset offset) { diff --git a/packages/flutter/lib/src/widgets/checked_mode_banner.dart b/packages/flutter/lib/src/widgets/checked_mode_banner.dart index e5e0faa43d..c92318f8dc 100644 --- a/packages/flutter/lib/src/widgets/checked_mode_banner.dart +++ b/packages/flutter/lib/src/widgets/checked_mode_banner.dart @@ -15,7 +15,7 @@ class _CheckedModeBannerPainter extends CustomPainter { static const kHeight = 12.0; // height of banner static const kTextAlign = const Offset(0.0, -3.0); // offset to move text up static const kFontSize = kHeight * 0.85; - static const kShadowBlur = 8.0; // shadow blur sigma + static const kShadowBlur = 4.0; // shadow blur sigma static final Rect kRect = new Rect.fromLTWH(-kOffset, kOffset-kHeight, kOffset * 2.0, kHeight); static const TextStyle kTextStyles = const TextStyle( color: const Color(0xFFFFFFFF),