Handle negative and zero sizes. (#11827)

diff --git a/packages/flutter/lib/src/painting/box_fit.dart b/packages/flutter/lib/src/painting/box_fit.dart
index 99ec3f3..d2bb9ba 100644
--- a/packages/flutter/lib/src/painting/box_fit.dart
+++ b/packages/flutter/lib/src/painting/box_fit.dart
@@ -125,6 +125,9 @@
 ///  * [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 23ddcb7..2a79542 100644
--- a/packages/flutter/lib/src/painting/box_painter.dart
+++ b/packages/flutter/lib/src/painting/box_painter.dart
@@ -1212,7 +1212,7 @@
 ///  * `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 @@
 }) {
   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 78207e2..d647613 100644
--- a/packages/flutter/lib/src/painting/flutter_logo.dart
+++ b/packages/flutter/lib/src/painting/flutter_logo.dart
@@ -375,6 +375,8 @@
   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 1faa3db..9b6d0cc 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -1860,6 +1860,8 @@
 
   @override
   bool hitTest(HitTestResult result, { Offset position }) {
+    if (size.isEmpty)
+      return false;
     _updatePaintData();
     Matrix4 inverse;
     try {
@@ -1875,8 +1877,12 @@
 
   @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 1767cab..3830d00 100644
--- a/packages/flutter/test/painting/box_fit_test.dart
+++ b/packages/flutter/test/painting/box_fit_test.dart
@@ -25,5 +25,49 @@
     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 2e587a4..32b0ebd 100644
--- a/packages/flutter/test/painting/decoration_test.dart
+++ b/packages/flutter/test/painting/decoration_test.dart
@@ -213,14 +213,14 @@
     final BoxDecoration boxDecoration = new BoxDecoration(image: backgroundImage);
     final BoxPainter boxPainter = boxDecoration.createBoxPainter(() { assert(false); });
     final TestCanvas canvas = new TestCanvas(<Invocation>[]);
-    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<TestImage>());
     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<Paint>());
     expect(call.positionalArguments[3].isAntiAlias, false);
     expect(call.positionalArguments[3].colorFilter, colorFilter);