diff --git a/packages/flutter/lib/src/painting/box_fit.dart b/packages/flutter/lib/src/painting/box_fit.dart index 99ec3f3147..d2bb9ba727 100644 --- a/packages/flutter/lib/src/painting/box_fit.dart +++ b/packages/flutter/lib/src/painting/box_fit.dart @@ -125,6 +125,9 @@ class FittedSizes { /// * [DecoratedBox], [BoxDecoration], and [DecorationImage], which together /// provide access to [paintImage] at the widgets layer. FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) { + if (inputSize.height <= 0.0 || inputSize.width <= 0.0 || outputSize.height <= 0.0 || outputSize.width <= 0.0) + return const FittedSizes(Size.zero, Size.zero); + Size sourceSize, destinationSize; switch (fit) { case BoxFit.fill: diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 23ddcb7097..2a79542af8 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -1212,7 +1212,7 @@ Iterable _generateImageTileRects(Rect outputRect, Rect fundamentalRect, Im /// * `canvas`: The canvas onto which the image will be painted. /// * `rect`: The region of the canvas into which the image will be painted. /// The image might not fill the entire rectangle (e.g., depending on the -/// `fit`). +/// `fit`). If `rect` is empty, nothing is painted. /// * `image`: The image to paint onto the canvas. /// * `colorFilter`: If non-null, the color filter to apply when painting the /// image. @@ -1251,6 +1251,8 @@ void paintImage({ }) { assert(canvas != null); assert(image != null); + if (rect.isEmpty) + return; Size outputSize = rect.size; Size inputSize = new Size(image.width.toDouble(), image.height.toDouble()); Offset sliceBorder; diff --git a/packages/flutter/lib/src/painting/flutter_logo.dart b/packages/flutter/lib/src/painting/flutter_logo.dart index 78207e2b1e..d647613357 100644 --- a/packages/flutter/lib/src/painting/flutter_logo.dart +++ b/packages/flutter/lib/src/painting/flutter_logo.dart @@ -375,6 +375,8 @@ class _FlutterLogoPainter extends BoxPainter { void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { offset += _config.margin.topLeft; final Size canvasSize = _config.margin.deflateSize(configuration.size); + if (canvasSize.isEmpty) + return; Size logoSize; if (_config._position > 0.0) { // horizontal style diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 1faa3db98b..9b6d0ccad7 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -1860,6 +1860,8 @@ class RenderFittedBox extends RenderProxyBox { @override bool hitTest(HitTestResult result, { Offset position }) { + if (size.isEmpty) + return false; _updatePaintData(); Matrix4 inverse; try { @@ -1875,8 +1877,12 @@ class RenderFittedBox extends RenderProxyBox { @override void applyPaintTransform(RenderBox child, Matrix4 transform) { - _updatePaintData(); - transform.multiply(_transform); + if (size.isEmpty) { + transform.setZero(); + } else { + _updatePaintData(); + transform.multiply(_transform); + } } @override diff --git a/packages/flutter/test/painting/box_fit_test.dart b/packages/flutter/test/painting/box_fit_test.dart index 1767cab64b..3830d00051 100644 --- a/packages/flutter/test/painting/box_fit_test.dart +++ b/packages/flutter/test/painting/box_fit_test.dart @@ -25,5 +25,49 @@ void main() { result = applyBoxFit(BoxFit.fitHeight, const Size(400.0, 2000.0), const Size(100.0, 1000.0)); expect(result.source, equals(const Size(200.0, 2000.0))); expect(result.destination, equals(const Size(100.0, 1000.0))); + + _testZeroAndNegativeSizes(BoxFit.fill); + _testZeroAndNegativeSizes(BoxFit.contain); + _testZeroAndNegativeSizes(BoxFit.cover); + _testZeroAndNegativeSizes(BoxFit.fitWidth); + _testZeroAndNegativeSizes(BoxFit.fitHeight); + _testZeroAndNegativeSizes(BoxFit.none); + _testZeroAndNegativeSizes(BoxFit.scaleDown); }); } + +void _testZeroAndNegativeSizes(BoxFit fit) { + FittedSizes result; + + result = applyBoxFit(fit, const Size(-400.0, 2000.0), const Size(100.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, -2000.0), const Size(100.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, 2000.0), const Size(-100.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, 2000.0), const Size(100.0, -1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(0.0, 2000.0), const Size(100.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, 0.0), const Size(100.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, 2000.0), const Size(0.0, 1000.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); + + result = applyBoxFit(fit, const Size(400.0, 2000.0), const Size(100.0, 0.0)); + expect(result.source, equals(Size.zero)); + expect(result.destination, equals(Size.zero)); +} diff --git a/packages/flutter/test/painting/decoration_test.dart b/packages/flutter/test/painting/decoration_test.dart index 2e587a4506..32b0ebd821 100644 --- a/packages/flutter/test/painting/decoration_test.dart +++ b/packages/flutter/test/painting/decoration_test.dart @@ -213,14 +213,14 @@ void main() { final BoxDecoration boxDecoration = new BoxDecoration(image: backgroundImage); final BoxPainter boxPainter = boxDecoration.createBoxPainter(() { assert(false); }); final TestCanvas canvas = new TestCanvas([]); - boxPainter.paint(canvas, Offset.zero, const ImageConfiguration(size: const Size(10.0, 10.0))); + boxPainter.paint(canvas, Offset.zero, const ImageConfiguration(size: const Size(100.0, 100.0))); final Invocation call = canvas.invocations.singleWhere((Invocation call) => call.memberName == #drawImageNine); expect(call.isMethod, isTrue); expect(call.positionalArguments, hasLength(4)); expect(call.positionalArguments[0], const isInstanceOf()); expect(call.positionalArguments[1], new Rect.fromLTRB(10.0, 20.0, 40.0, 60.0)); - expect(call.positionalArguments[2], new Rect.fromLTRB(0.0, 0.0, 32.5, 10.0)); + expect(call.positionalArguments[2], new Rect.fromLTRB(0.0, 0.0, 100.0, 100.0)); expect(call.positionalArguments[3], const isInstanceOf()); expect(call.positionalArguments[3].isAntiAlias, false); expect(call.positionalArguments[3].colorFilter, colorFilter);