RenderImage should handle the case of a null image

When given a null image, RenderImage should be as small as possible (isntead of
being NaNxNaN).

Also, plumb ImageFit and ImageRepeat through the various image widgets.
diff --git a/packages/flutter/lib/rendering/box.dart b/packages/flutter/lib/rendering/box.dart
index 820127e..fbd93de 100644
--- a/packages/flutter/lib/rendering/box.dart
+++ b/packages/flutter/lib/rendering/box.dart
@@ -1347,7 +1347,7 @@
       height: _height
     ).apply(constraints);
 
-    if (constraints.isTight)
+    if (constraints.isTight || _image == null)
       return constraints.smallest;
 
     // This algorithm attempts to find a size for the RenderImage that fits in
@@ -1360,8 +1360,10 @@
     //  - The RenderImage's dimension are maximal subject to being smaller than
     //    the intrinsic size of the image.
 
-    double width = _image == null ? 0.0 : _image.width.toDouble();
-    double height = _image == null ? 0.0 : _image.height.toDouble();
+    double width = _image.width.toDouble();
+    double height = _image.height.toDouble();
+    assert(width > 0.0);
+    assert(height > 0.0);
     double aspectRatio = width / height;
 
     if (width > constraints.maxWidth) {
@@ -1384,7 +1386,6 @@
       width = height * aspectRatio;
     }
 
-    assert(width != null && height != null);
     return constraints.constrain(new Size(width, height));
   }
 
diff --git a/packages/flutter/lib/widgets/basic.dart b/packages/flutter/lib/widgets/basic.dart
index 8a4864e..6c78f88 100644
--- a/packages/flutter/lib/widgets/basic.dart
+++ b/packages/flutter/lib/widgets/basic.dart
@@ -523,14 +523,30 @@
 }
 
 class Image extends LeafRenderObjectWrapper {
-  Image({ Key key, this.image, this.width, this.height, this.colorFilter }) : super(key: key);
+  Image({
+    Key key,
+    this.image,
+    this.width,
+    this.height,
+    this.colorFilter,
+    this.fit: ImageFit.scaleDown,
+    this.repeat: ImageRepeat.noRepeat
+  }) : super(key: key);
 
   final sky.Image image;
   final double width;
   final double height;
   final sky.ColorFilter colorFilter;
+  final ImageFit fit;
+  final ImageRepeat repeat;
 
-  RenderImage createNode() => new RenderImage(image: image, width: width, height: height, colorFilter: colorFilter);
+  RenderImage createNode() => new RenderImage(
+    image: image,
+    width: width,
+    height: height,
+    colorFilter: colorFilter,
+    fit: fit,
+    repeat: repeat);
   RenderImage get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
@@ -539,16 +555,28 @@
     renderObject.width = width;
     renderObject.height = height;
     renderObject.colorFilter = colorFilter;
+    renderObject.fit = fit;
+    renderObject.repeat = repeat;
   }
 }
 
 class ImageListener extends StatefulComponent {
-  ImageListener({ Key key, this.image, this.width, this.height, this.colorFilter }) : super(key: key);
+  ImageListener({
+    Key key,
+    this.image,
+    this.width,
+    this.height,
+    this.colorFilter,
+    this.fit: ImageFit.scaleDown,
+    this.repeat: ImageRepeat.noRepeat
+  }) : super(key: key);
 
   ImageResource image;
   double width;
   double height;
   sky.ColorFilter colorFilter;
+  ImageFit fit;
+  ImageRepeat repeat;
 
   sky.Image _resolvedImage;
 
@@ -578,6 +606,8 @@
     width = source.width;
     height = source.height;
     colorFilter = source.colorFilter;
+    fit = source.fit;
+    repeat = source.repeat;
     if (needToUpdateListeners)
       image.addListener(_handleImageChanged);
   }
@@ -587,44 +617,71 @@
       image: _resolvedImage,
       width: width,
       height: height,
-      colorFilter: colorFilter
+      colorFilter: colorFilter,
+      fit: fit,
+      repeat: repeat
     );
   }
 }
 
 class NetworkImage extends Component {
-  NetworkImage({ Key key, this.src, this.width, this.height, this.colorFilter }) : super(key: key);
+  NetworkImage({
+    Key key,
+    this.src,
+    this.width,
+    this.height,
+    this.colorFilter,
+    this.fit: ImageFit.scaleDown,
+    this.repeat: ImageRepeat.noRepeat
+  }) : super(key: key);
 
   final String src;
   final double width;
   final double height;
   final sky.ColorFilter colorFilter;
+  final ImageFit fit;
+  final ImageRepeat repeat;
 
   Widget build() {
     return new ImageListener(
       image: image_cache.load(src),
       width: width,
       height: height,
-      colorFilter: colorFilter
+      colorFilter: colorFilter,
+      fit: fit,
+      repeat: repeat
     );
   }
 }
 
 class AssetImage extends Component {
-  AssetImage({ Key key, this.name, this.bundle, this.width, this.height, this.colorFilter }) : super(key: key);
+  AssetImage({
+    Key key,
+    this.name,
+    this.bundle,
+    this.width,
+    this.height,
+    this.colorFilter,
+    this.fit: ImageFit.scaleDown,
+    this.repeat: ImageRepeat.noRepeat
+  }) : super(key: key);
 
   final String name;
   final AssetBundle bundle;
   final double width;
   final double height;
   final sky.ColorFilter colorFilter;
+  final ImageFit fit;
+  final ImageRepeat repeat;
 
   Widget build() {
     return new ImageListener(
       image: bundle.loadImage(name),
       width: width,
       height: height,
-      colorFilter: colorFilter
+      colorFilter: colorFilter,
+      fit: fit,
+      repeat: repeat
     );
   }
 }