Merge pull request #663 from abarth/fix_rotate

Don't corrupt drawing when rotating
diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart
index bc78445..d18fe06 100644
--- a/examples/game/lib/main.dart
+++ b/examples/game/lib/main.dart
@@ -48,8 +48,8 @@
 
   _app = new GameDemoApp();
 
-  _sounds["explosion"] = new SoundEffect('https://github.com/slembcke/GalacticGuardian.spritebuilder/raw/GDC/Packages/SpriteBuilder%20Resources.sbpack/TempSounds/Explosion.wav');
-  _sounds["laser"] = new SoundEffect('https://github.com/slembcke/GalacticGuardian.spritebuilder/raw/GDC/Packages/SpriteBuilder%20Resources.sbpack/TempSounds/Laser.wav');
+  _sounds["explosion"] = new SoundEffect(_bundle.load('assets/explosion.wav'));
+  _sounds["laser"] = new SoundEffect(_bundle.load('assets/laser.wav'));
 
   await _sounds["explosion"].load();
   await _sounds["laser"].load();
diff --git a/examples/game/lib/sound.dart b/examples/game/lib/sound.dart
index 5e50e7f..b217090 100644
--- a/examples/game/lib/sound.dart
+++ b/examples/game/lib/sound.dart
@@ -6,16 +6,15 @@
 typedef void SoundEffectStreamCallback(SoundEffectStream);
 
 class SoundEffect {
-  SoundEffect(this._url);
+  SoundEffect(this._pipeFuture);
 
   // TODO: Remove load method from SoundEffect
   Future load() async {
-    UrlResponse response = await fetchUrl(_url);
-    _data = response.body;
+    _data = await _pipeFuture;
   }
 
-  String _url;
-  Object _data;
+  Future<MojoDataPipeConsumer> _pipeFuture;
+  MojoDataPipeConsumer _data;
 }
 
 class SoundEffectStream {
diff --git a/examples/game/lib/sound_manager.dart b/examples/game/lib/sound_manager.dart
index 90c03a9..311da05 100644
--- a/examples/game/lib/sound_manager.dart
+++ b/examples/game/lib/sound_manager.dart
@@ -54,7 +54,6 @@
 
   static void purgeSharedInstance() {
     if (_sharedSoundManager == null) return;
-    _sharedSoundManager._running = false;
     _sharedSoundManager = null;
   }
 
@@ -72,7 +71,6 @@
   bool enableBackgroundMusic;
   bool enableSoundEffects;
 
-  bool _running = true;
   int _lastTimeStamp;
 
   void playEvent(SoundEvent evt, [double volume = 1.0, double pitch = 1.0, double pan = 0.0]) {
diff --git a/examples/game/lib/sprites.dart b/examples/game/lib/sprites.dart
index 6522290..8735554 100644
--- a/examples/game/lib/sprites.dart
+++ b/examples/game/lib/sprites.dart
@@ -10,6 +10,7 @@
 import 'dart:typed_data';
 import 'dart:sky';
 
+import 'package:mojo/core.dart';
 import 'package:mojo/mojo/url_response.mojom.dart';
 import 'package:sky/animation/curves.dart';
 import 'package:sky/base/scheduler.dart' as scheduler;
diff --git a/examples/raw/hello_world.dart b/examples/raw/hello_world.dart
index c9ed52a..ee4669c 100644
--- a/examples/raw/hello_world.dart
+++ b/examples/raw/hello_world.dart
@@ -8,7 +8,7 @@
   Size size = new Size(view.width, view.height);
 
   PictureRecorder recorder = new PictureRecorder();
-  final double devicePixelRatio = sky.view.devicePixelRatio;
+  final double devicePixelRatio = view.devicePixelRatio;
   Canvas canvas = new Canvas(recorder, Point.origin & (size * devicePixelRatio));
   canvas.scale(devicePixelRatio, devicePixelRatio);
   double radius = size.shortestSide * 0.45;
diff --git a/examples/raw/painting_node.dart b/examples/raw/painting_node.dart
index 2a7e67f..3cfa950 100644
--- a/examples/raw/painting_node.dart
+++ b/examples/raw/painting_node.dart
@@ -21,7 +21,7 @@
     paintingNode = new PaintingNode();
     Paint innerPaint = new Paint()..color = new Color.fromARGB(a, 255 - r, 255 - g, 255 - b);
     PictureRecorder innerRecorder = new PictureRecorder();
-    Canvas innerCanvas = new Canvas(innerRecorder, Point.origin & bounds);
+    Canvas innerCanvas = new Canvas(innerRecorder, Point.origin & size);
     innerCanvas.drawCircle(size.center(Point.origin), radius * 0.5, innerPaint);
 
     paintingNode.setBackingDrawable(innerRecorder.endRecordingAsDrawable());
diff --git a/examples/raw/shadow.dart b/examples/raw/shadow.dart
index 2907a3c..c301beb 100644
--- a/examples/raw/shadow.dart
+++ b/examples/raw/shadow.dart
@@ -21,11 +21,11 @@
           ..setPaintBits(PaintBits.all)
           ..setOffset(const Offset(5.0, 5.0))
           ..setColorMode(TransferMode.src),
-        (Paint layerPaint) {
-      layerPaint.color = const Color.fromARGB(128, 55, 55, 55);
-      layerPaint.setMaskFilter(
-          new MaskFilter.blur(BlurStyle.normal, 5.0, highQuality: true));
-    })
+        new Paint()
+          ..color = const Color.fromARGB(128, 55, 55, 55)
+          ..setMaskFilter(
+            new MaskFilter.blur(BlurStyle.normal, 5.0, highQuality: true))
+    )
     // Main layer.
     ..addLayerOnTop(new DrawLooperLayerInfo(), new Paint());
   paint.setDrawLooper(builder.build());
diff --git a/examples/raw/spinning_image.dart b/examples/raw/spinning_image.dart
index 8e5267b..d4a2239 100644
--- a/examples/raw/spinning_image.dart
+++ b/examples/raw/spinning_image.dart
@@ -20,7 +20,7 @@
   PictureRecorder recorder = new PictureRecorder();
   final double devicePixelRatio = view.devicePixelRatio;
   Canvas canvas = new Canvas(recorder, Point.origin & new Size(view.width * devicePixelRatio, view.height * devicePixelRatio));
-  cavnas.scale(devicePixelRatio, devicePixelRatio);
+  canvas.scale(devicePixelRatio, devicePixelRatio);
   canvas.translate(view.width / 2.0, view.height / 2.0);
   canvas.rotate(math.PI * delta / 1800);
   canvas.scale(0.2, 0.2);
@@ -61,7 +61,7 @@
   }
 
   if (event.type == "pointerup") {
-    image_cache.load(url2).then(handleImageLoad);
+    image_cache.load(url2).first.then(handleImageLoad);
     return true;
   }
 
@@ -69,7 +69,7 @@
 }
 
 void main() {
-  image_cache.load(url1).then(handleImageLoad);
+  image_cache.load(url1).first.then(handleImageLoad);
   view.setEventCallback(handleEvent);
   view.setFrameCallback(beginFrame);
 }
diff --git a/examples/rendering/align_items.dart b/examples/rendering/align_items.dart
index c8f6b24..817857d 100644
--- a/examples/rendering/align_items.dart
+++ b/examples/rendering/align_items.dart
@@ -18,25 +18,25 @@
 
   for(FlexAlignItems alignItems in FlexAlignItems.values) {
     TextStyle style = const TextStyle(color: const Color(0xFF000000));
-    RenderParagraph paragraph = new RenderParagraph(new RenderStyled(style, [new RenderText("${alignItems}")]));
+    RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, [new PlainTextSpan("${alignItems}")]));
     table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
     var row = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
 
     style = new TextStyle(fontSize: 15.0, color: const Color(0xFF000000));
     row.add(new RenderDecoratedBox(
       decoration: new BoxDecoration(backgroundColor: const Color(0x7FFFCCCC)),
-      child: new RenderParagraph(new RenderStyled(style, [new RenderText('foo foo foo')]))
+      child: new RenderParagraph(new StyledTextSpan(style, [new PlainTextSpan('foo foo foo')]))
     ));
     style = new TextStyle(fontSize: 10.0, color: const Color(0xFF000000));
     row.add(new RenderDecoratedBox(
       decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCFFCC)),
-      child: new RenderParagraph(new RenderStyled(style, [new RenderText('foo foo foo')]))
+      child: new RenderParagraph(new StyledTextSpan(style, [new PlainTextSpan('foo foo foo')]))
     ));
     var subrow = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
     style = new TextStyle(fontSize: 25.0, color: const Color(0xFF000000));
     subrow.add(new RenderDecoratedBox(
       decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCCCFF)),
-      child: new RenderParagraph(new RenderStyled(style, [new RenderText('foo foo foo foo')]))
+      child: new RenderParagraph(new StyledTextSpan(style, [new PlainTextSpan('foo foo foo foo')]))
     ));
     subrow.add(new RenderSolidColorBox(const Color(0x7FCCFFFF), desiredSize: new Size(30.0, 40.0)));
     row.add(subrow);
diff --git a/examples/rendering/baseline.dart b/examples/rendering/baseline.dart
index 527d9cd..3d61016 100644
--- a/examples/rendering/baseline.dart
+++ b/examples/rendering/baseline.dart
@@ -13,19 +13,19 @@
 
 RenderBox getBox(double lh) {
   RenderParagraph paragraph = new RenderParagraph(
-    new RenderStyled(
+    new StyledTextSpan(
       new TextStyle(
         color: const Color(0xFF0000A0)
       ),
       [
-        new RenderText('test'),
-        new RenderStyled(
+        new PlainTextSpan('test'),
+        new StyledTextSpan(
           new TextStyle(
             fontFamily: 'serif',
             fontSize: 50.0,
             height: lh
           ),
-          [new RenderText('مرحبا Hello')]
+          [new PlainTextSpan('مرحبا Hello')]
         )
       ]
     )
diff --git a/examples/rendering/interactive_flex.dart b/examples/rendering/interactive_flex.dart
index 2f1b97c..462ea0b 100644
--- a/examples/rendering/interactive_flex.dart
+++ b/examples/rendering/interactive_flex.dart
@@ -65,7 +65,7 @@
 
   // Resizeable image
   image = new RenderImageGrow(null, new Size(100.0, null));
-  image_cache.load("https://www.dartlang.org/logos/dart-logo.png").then((Image dartLogo) {
+  image_cache.load("https://www.dartlang.org/logos/dart-logo.png").first.then((Image dartLogo) {
     image.image = dartLogo;
   });
 
@@ -84,9 +84,9 @@
 andouille leberkas capicola meatloaf. Chicken pig ball tip pork picanha bresaola
 alcatra. Pork pork belly alcatra, flank chuck drumstick biltong doner jowl.
 Pancetta meatball tongue tenderloin rump tail jowl boudin.""";
-  var text = new RenderStyled(
+  var text = new StyledTextSpan(
       new TextStyle(color:  const Color(0xFF009900)),
-      [new RenderText(meatyString)]);
+      [new PlainTextSpan(meatyString)]);
   padding = new RenderPadding(
       padding: const EdgeDims.all(10.0),
       child: new RenderParagraph(text));
diff --git a/examples/rendering/justify_content.dart b/examples/rendering/justify_content.dart
index 13e01d0..df3e186 100644
--- a/examples/rendering/justify_content.dart
+++ b/examples/rendering/justify_content.dart
@@ -21,7 +21,7 @@
   var table = new RenderFlex(direction: FlexDirection.vertical);
 
   void addRow(FlexJustifyContent justify) {
-    RenderParagraph paragraph = new RenderParagraph(new RenderStyled(style, [new RenderText("${justify}")]));
+    RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, [new PlainTextSpan("${justify}")]));
     table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
     var row = new RenderFlex(direction: FlexDirection.horizontal);
     row.add(new RenderSolidColorBox(const Color(0xFFFFCCCC), desiredSize: new Size(80.0, 60.0)));
diff --git a/examples/rendering/render_paragraph.dart b/examples/rendering/render_paragraph.dart
index 3227e90..58e390b 100644
--- a/examples/rendering/render_paragraph.dart
+++ b/examples/rendering/render_paragraph.dart
@@ -32,9 +32,9 @@
 alcatra. Pork pork belly alcatra, flank chuck drumstick biltong doner jowl.
 Pancetta meatball tongue tenderloin rump tail jowl boudin.""";
 
-  var text = new RenderStyled(
+  var text = new StyledTextSpan(
       new TextStyle(color:  const Color(0xFF009900)),
-      [new RenderText(meatyString)]);
+      [new PlainTextSpan(meatyString)]);
   child = new RenderDecoratedBox(
     decoration: new BoxDecoration(backgroundColor: const Color(0xFFFFFFFF)),
     child: new RenderParagraph(text)
diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart
index d94333b..33d745f 100644
--- a/examples/rendering/touch_demo.dart
+++ b/examples/rendering/touch_demo.dart
@@ -76,12 +76,12 @@
         ..color = const Color(0xFFFFFFFF);
     canvas.drawRect(offset & size, white);
     for (Dot dot in dots.values)
-      dot.paint(canvas, offset);
+      dot.paint(context, offset);
   }
 }
 
 void main() {
-  var paragraph = new RenderParagraph(new RenderText("Touch me!"));
+  var paragraph = new RenderParagraph(new PlainTextSpan("Touch me!"));
   var stack = new RenderStack(children: [
     new RenderTouchDemo(),
     paragraph,
diff --git a/examples/widgets/progress_indicator.dart b/examples/widgets/progress_indicator.dart
index df06c45..5d8d1a3 100644
--- a/examples/widgets/progress_indicator.dart
+++ b/examples/widgets/progress_indicator.dart
@@ -20,12 +20,12 @@
 
 class ProgressIndicatorApp extends App {
 
-  AnimationPerformance valueAnimation;
+  ValueAnimation<double> valueAnimation;
   Direction valueAnimationDirection = Direction.forward;
 
   void initState() {
     super.initState();
-    valueAnimation = new AnimationPerformance()
+    valueAnimation = new ValueAnimation<double>()
       ..duration = const Duration(milliseconds: 1500)
       ..variable = new AnimatedValue<double>(
         0.0,
@@ -59,17 +59,17 @@
         ),
         new LinearProgressIndicator(),
         new LinearProgressIndicator(),
-        new LinearProgressIndicator(value: valueAnimation.variable.value),
+        new LinearProgressIndicator(value: valueAnimation.value),
         new CircularProgressIndicator(),
         new SizedBox(
             width: 20.0,
             height: 20.0,
-            child: new CircularProgressIndicator(value: valueAnimation.variable.value)
+            child: new CircularProgressIndicator(value: valueAnimation.value)
         ),
         new SizedBox(
           width: 50.0,
           height: 30.0,
-          child: new CircularProgressIndicator(value: valueAnimation.variable.value)
+          child: new CircularProgressIndicator(value: valueAnimation.value)
         )
     ];
     return new Flex(
diff --git a/sky/engine/core/rendering/style/RenderStyle.cpp b/sky/engine/core/rendering/style/RenderStyle.cpp
index 80aa108..ff44d86 100644
--- a/sky/engine/core/rendering/style/RenderStyle.cpp
+++ b/sky/engine/core/rendering/style/RenderStyle.cpp
@@ -46,20 +46,6 @@
 
 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
 
-struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
-    void* dataRefs[7];
-
-    struct InheritedFlags {
-        unsigned m_bitfields;
-    } inherited_flags;
-
-    struct NonInheritedFlags {
-        unsigned m_bitfields[2];
-    } noninherited_flags;
-};
-
-COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
-
 inline RenderStyle* defaultStyle()
 {
     DEFINE_STATIC_REF(RenderStyle, s_defaultStyle, (RenderStyle::createDefaultStyle()));
diff --git a/sky/engine/platform/graphics/cpu/arm/filters/FECompositeArithmeticNEON.h b/sky/engine/platform/graphics/cpu/arm/filters/FECompositeArithmeticNEON.h
index e7e19c5..428d8f2 100644
--- a/sky/engine/platform/graphics/cpu/arm/filters/FECompositeArithmeticNEON.h
+++ b/sky/engine/platform/graphics/cpu/arm/filters/FECompositeArithmeticNEON.h
@@ -48,8 +48,9 @@
     uint32_t* destinationPixel = reinterpret_cast<uint32_t*>(destination);
     uint32_t* destinationEndPixel = destinationPixel + (pixelArrayLength >> 2);
 
+    uint32x2_t temporary1 = {0};
     while (destinationPixel < destinationEndPixel) {
-        uint32x2_t temporary1 = vset_lane_u32(*sourcePixel, temporary1, 0);
+        temporary1 = vset_lane_u32(*sourcePixel, temporary1, 0);
         uint16x4_t temporary2 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(temporary1)));
         float32x4_t sourcePixelAsFloat = vcvtq_f32_u32(vmovl_u16(temporary2));
 
diff --git a/sky/engine/platform/graphics/filters/FEComposite.cpp b/sky/engine/platform/graphics/filters/FEComposite.cpp
index 6893762..6bc0734 100644
--- a/sky/engine/platform/graphics/filters/FEComposite.cpp
+++ b/sky/engine/platform/graphics/filters/FEComposite.cpp
@@ -184,6 +184,7 @@
     }
 }
 
+#if !HAVE(ARM_NEON_INTRINSICS)
 static inline void arithmeticSoftware(unsigned char* source, unsigned char* destination, int pixelArrayLength, float k1, float k2, float k3, float k4)
 {
     float upperLimit = std::max(0.0f, k1) + std::max(0.0f, k2) + std::max(0.0f, k3) + k4;
@@ -215,6 +216,7 @@
             computeArithmeticPixels<0, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
     }
 }
+#endif  // !HAVE(ARM_NEON_INTRINSICS)
 
 inline void FEComposite::platformArithmeticSoftware(Uint8ClampedArray* source, Uint8ClampedArray* destination,
     float k1, float k2, float k3, float k4)
diff --git a/sky/packages/sky/lib/animation/README.md b/sky/packages/sky/lib/animation/README.md
index 3384c45..55f96ca 100644
--- a/sky/packages/sky/lib/animation/README.md
+++ b/sky/packages/sky/lib/animation/README.md
@@ -1,2 +1,2 @@
 This directory contains animation-related libraries that only depend
-on core Dart libraries and ../base/*.
+on core Dart libraries, the Newton Dart library, and ../base/*.
diff --git a/sky/packages/sky/lib/animation/animated_simulation.dart b/sky/packages/sky/lib/animation/animated_simulation.dart
index 4e492c4..b3278e2 100644
--- a/sky/packages/sky/lib/animation/animated_simulation.dart
+++ b/sky/packages/sky/lib/animation/animated_simulation.dart
@@ -33,11 +33,11 @@
       _animationId = null;
     }
 
+    // We take the _completer into a local variable so that !isTicking
+    // when we actually complete the future (isTicking uses _completer
+    // to determine its state).
     Completer localCompleter = _completer;
     _completer = null;
-
-    // We take the _completer into a local variable so that !isTicking when we
-    // actually complete the future.
     assert(!isTicking);
     localCompleter.complete();
   }
diff --git a/sky/packages/sky/lib/animation/forces.dart b/sky/packages/sky/lib/animation/forces.dart
index cf5f53a..6353c8a 100644
--- a/sky/packages/sky/lib/animation/forces.dart
+++ b/sky/packages/sky/lib/animation/forces.dart
@@ -10,27 +10,34 @@
 }
 
 class SpringForce extends Force {
-  SpringForce(this.spring, {this.left: 0.0, this.right: 1.0});
-
-  // We overshoot the target by this distance, but stop the simulation when
-  // the spring gets within this distance (regardless of how fast it's moving).
-  // This causes the spring to settle a bit faster than it otherwise would.
-  static final Tolerance tolerance =
-      new Tolerance(velocity: double.INFINITY, distance: 0.01);
+  SpringForce(this.spring, { this.left: 0.0, this.right: 1.0 });
 
   final SpringDescription spring;
+
   // Where to put the spring's resting point when releasing left or right,
   // respectively.
   final double left, right;
 
+  // We overshoot the target by this distance, but stop the simulation when
+  // the spring gets within this distance (regardless of how fast it's moving).
+  // This causes the spring to settle a bit faster than it otherwise would.
+  static final Tolerance tolerance = new Tolerance(
+    velocity: double.INFINITY,
+    distance: 0.01
+  );
+
   Simulation release(double position, double velocity) {
-    double target = velocity < 0.0 ?
-        this.left - tolerance.distance : this.right + tolerance.distance;
+    double target = velocity < 0.0 ? this.left - tolerance.distance
+                                   : this.right + tolerance.distance;
     return new SpringSimulation(spring, position, target, velocity)
       ..tolerance = tolerance;
   }
 }
 
-final SpringDescription _kDefaultSpringDesc =
-    new SpringDescription.withDampingRatio(mass: 1.0, springConstant: 500.0, ratio: 1.0);
+final SpringDescription _kDefaultSpringDesc = new SpringDescription.withDampingRatio(
+  mass: 1.0,
+  springConstant: 500.0,
+  ratio: 1.0
+);
+
 final SpringForce kDefaultSpringForce = new SpringForce(_kDefaultSpringDesc);
diff --git a/sky/packages/sky/lib/base/lerp.dart b/sky/packages/sky/lib/base/lerp.dart
index 80e2a2c..da5c144 100644
--- a/sky/packages/sky/lib/base/lerp.dart
+++ b/sky/packages/sky/lib/base/lerp.dart
@@ -26,10 +26,11 @@
   if (b == null)
     return _scaleAlpha(a, 1.0 - t);
   return new Color.fromARGB(
-      lerpNum(a.alpha, b.alpha, t).toInt(),
-      lerpNum(a.red, b.red, t).toInt(),
-      lerpNum(a.green, b.green, t).toInt(),
-      lerpNum(a.blue, b.blue, t).toInt());
+    lerpNum(a.alpha, b.alpha, t).toInt(),
+    lerpNum(a.red, b.red, t).toInt(),
+    lerpNum(a.green, b.green, t).toInt(),
+    lerpNum(a.blue, b.blue, t).toInt()
+  );
 }
 
 Offset lerpOffset(Offset a, Offset b, double t) {
@@ -55,5 +56,6 @@
     lerpNum(a.left, b.left, t),
     lerpNum(a.top, b.top, t),
     lerpNum(a.right, b.right, t),
-    lerpNum(a.bottom, b.bottom, t));
+    lerpNum(a.bottom, b.bottom, t)
+  );
 }
diff --git a/sky/packages/sky/lib/mojo/asset_bundle.dart b/sky/packages/sky/lib/mojo/asset_bundle.dart
index bb2ff84..7cce717 100644
--- a/sky/packages/sky/lib/mojo/asset_bundle.dart
+++ b/sky/packages/sky/lib/mojo/asset_bundle.dart
@@ -18,6 +18,7 @@
   void close();
   ImageResource loadImage(String key);
   Future<String> loadString(String key);
+  Future<core.MojoDataPipeConsumer> load(String key);
 }
 
 class NetworkAssetBundle extends AssetBundle {
@@ -27,13 +28,15 @@
 
   void close() { }
 
-  ImageResource loadImage(String key) {
-    return image_cache.load(_baseUrl.resolve(key).toString());
+  String _urlFromKey(String key) => _baseUrl.resolve(key).toString();
+
+  Future<core.MojoDataPipeConsumer> load(String key) async {
+    return (await fetchUrl(_urlFromKey(key))).body;
   }
 
-  Future<String> loadString(String key) {
-    return fetchString(_baseUrl.resolve(key).toString());
-  }
+  ImageResource loadImage(String key) => image_cache.load(_urlFromKey(key));
+
+  Future<String> loadString(String key) => fetchString(_urlFromKey(key));
 }
 
 Future _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async {
@@ -66,19 +69,23 @@
   ImageResource loadImage(String key) {
     return _imageCache.putIfAbsent(key, () {
       Completer<sky.Image> completer = new Completer<sky.Image>();
-      _bundle.ptr.getAsStream(key).then((response) {
-        new sky.ImageDecoder(response.assetData.handle.h, completer.complete);
+      load(key).then((assetData) {
+        new sky.ImageDecoder(assetData.handle.h, completer.complete);
       });
       return new ImageResource(completer.future);
     });
   }
 
   Future<String> _fetchString(String key) async {
-    core.MojoDataPipeConsumer pipe = (await _bundle.ptr.getAsStream(key)).assetData;
+    core.MojoDataPipeConsumer pipe = await load(key);
     ByteData data = await core.DataPipeDrainer.drainHandle(pipe);
     return new String.fromCharCodes(new Uint8List.view(data.buffer));
   }
 
+  Future<core.MojoDataPipeConsumer> load(String key) async {
+    return (await _bundle.ptr.getAsStream(key)).assetData;
+  }
+
   Future<String> loadString(String key) {
     return _stringCache.putIfAbsent(key, () => _fetchString(key));
   }
diff --git a/sky/packages/sky/lib/mojo/net/fetch.dart b/sky/packages/sky/lib/mojo/net/fetch.dart
index 56a3b22..042e527 100644
--- a/sky/packages/sky/lib/mojo/net/fetch.dart
+++ b/sky/packages/sky/lib/mojo/net/fetch.dart
@@ -12,6 +12,8 @@
 import 'package:mojo_services/mojo/url_loader.mojom.dart';
 import 'package:sky/mojo/shell.dart' as shell;
 
+export 'package:mojo/mojo/url_response.mojom.dart' show UrlResponse;
+
 NetworkServiceProxy _initNetworkService() {
   NetworkServiceProxy networkService = new NetworkServiceProxy.unbound();
   shell.requestService("mojo:authenticated_network_service", networkService);
diff --git a/sky/packages/sky/lib/painting/README.md b/sky/packages/sky/lib/painting/README.md
new file mode 100644
index 0000000..64967d7
--- /dev/null
+++ b/sky/packages/sky/lib/painting/README.md
@@ -0,0 +1,3 @@
+This directory contains painting-related libraries that only depend on
+core Dart libraries, ../base/*, and ../animation/*. Note that
+../animation/* depends on the Newton Dart library also.
diff --git a/sky/packages/sky/lib/painting/box_painter.dart b/sky/packages/sky/lib/painting/box_painter.dart
index 7cc5054..251aea7 100644
--- a/sky/packages/sky/lib/painting/box_painter.dart
+++ b/sky/packages/sky/lib/painting/box_painter.dart
@@ -91,9 +91,10 @@
   if (b == null)
     return a.scale(1.0 - t);
   return new BoxShadow(
-      color: lerpColor(a.color, b.color, t),
-      offset: lerpOffset(a.offset, b.offset, t),
-      blur: lerpNum(a.blur, b.blur, t));
+    color: lerpColor(a.color, b.color, t),
+    offset: lerpOffset(a.offset, b.offset, t),
+    blur: lerpNum(a.blur, b.blur, t)
+  );
 }
 
 List<BoxShadow> lerpListBoxShadow(List<BoxShadow> a, List<BoxShadow> b, double t) {
@@ -126,18 +127,19 @@
     this.tileMode: sky.TileMode.clamp
   });
 
-  String toString() =>
-      'LinearGradient($endPoints, $colors, $colorStops, $tileMode)';
-
-  sky.Shader createShader() {
-    return new sky.Gradient.linear(this.endPoints, this.colors, this.colorStops,
-                                   this.tileMode);
-  }
-
   final List<Point> endPoints;
   final List<Color> colors;
   final List<double> colorStops;
   final sky.TileMode tileMode;
+
+  sky.Shader createShader() {
+    return new sky.Gradient.linear(this.endPoints, this.colors,
+                                   this.colorStops, this.tileMode);
+  }
+
+  String toString() {
+    return 'LinearGradient($endPoints, $colors, $colorStops, $tileMode)';
+  }
 }
 
 class RadialGradient extends Gradient {
@@ -149,19 +151,20 @@
     this.tileMode: sky.TileMode.clamp
   });
 
-  String toString() =>
-      'RadialGradient($center, $radius, $colors, $colorStops, $tileMode)';
+  final Point center;
+  final double radius;
+  final List<Color> colors;
+  final List<double> colorStops;
+  final sky.TileMode tileMode;
 
   sky.Shader createShader() {
     return new sky.Gradient.radial(this.center, this.radius, this.colors,
                                    this.colorStops, this.tileMode);
   }
 
-  final Point center;
-  final double radius;
-  final List<Color> colors;
-  final List<double> colorStops;
-  final sky.TileMode tileMode;
+  String toString() {
+    return 'RadialGradient($center, $radius, $colors, $colorStops, $tileMode)';
+  }
 }
 
 enum BackgroundFit { fill, contain, cover, none, scaleDown }
@@ -358,7 +361,8 @@
   }
 
   void _paintBackgroundColor(sky.Canvas canvas, Rect rect) {
-    if (_decoration.backgroundColor != null || _decoration.boxShadow != null ||
+    if (_decoration.backgroundColor != null ||
+        _decoration.boxShadow != null ||
         _decoration.gradient != null) {
       switch (_decoration.shape) {
         case Shape.circle:
diff --git a/sky/packages/sky/lib/widgets/default_text_style.dart b/sky/packages/sky/lib/widgets/default_text_style.dart
index 9d810be..c4a763d 100644
--- a/sky/packages/sky/lib/widgets/default_text_style.dart
+++ b/sky/packages/sky/lib/widgets/default_text_style.dart
@@ -19,8 +19,8 @@
 
   final TextStyle style;
 
-  static TextStyle of(Component component) {
-    DefaultTextStyle result = component.inheritedOfType(DefaultTextStyle);
+  static TextStyle of(Widget widget) {
+    DefaultTextStyle result = widget.inheritedOfType(DefaultTextStyle);
     return result == null ? null : result.style;
   }
 
diff --git a/sky/packages/sky/lib/widgets/framework.dart b/sky/packages/sky/lib/widgets/framework.dart
index e4a0f98..8b15043 100644
--- a/sky/packages/sky/lib/widgets/framework.dart
+++ b/sky/packages/sky/lib/widgets/framework.dart
@@ -272,6 +272,27 @@
     return ancestor;
   }
 
+  Set<Type> _dependencies;
+  Inherited inheritedOfType(Type targetType) {
+    if (_dependencies == null)
+      _dependencies = new Set<Type>();
+    _dependencies.add(targetType);
+    Widget ancestor = parent;
+    while (ancestor != null && ancestor.runtimeType != targetType)
+      ancestor = ancestor.parent;
+    return ancestor;
+  }
+
+  void dependenciesChanged() {
+    // This is called if you've use inheritedOfType and the Inherited
+    // ancestor you were provided was changed. For a widget to use Inherited
+    // it needs an implementation of dependenciesChanged. If your widget extends
+    // Component or RenderObjectWrapper this is provided for you automatically.
+    // If you aren't able to extend one of those classes, you need to
+    // provide your own implementation of dependenciesChanged.
+    assert(false);
+  }
+
   void remove() {
     _renderObject = null;
     setParent(null);
@@ -453,10 +474,9 @@
   void notifyDescendants() {
     final Type ourRuntimeType = runtimeType;
     void notifyChildren(Widget child) {
-      if (child is Component &&
-          child._dependencies != null &&
+      if (child._dependencies != null &&
           child._dependencies.contains(ourRuntimeType))
-        child._dependenciesChanged();
+          child.dependenciesChanged();
       if (child.runtimeType != ourRuntimeType)
         child.walkChildren(notifyChildren);
     }
@@ -608,17 +628,7 @@
     _built.detachRoot();
   }
 
-  Set<Type> _dependencies;
-  Inherited inheritedOfType(Type targetType) {
-    if (_dependencies == null)
-      _dependencies = new Set<Type>();
-    _dependencies.add(targetType);
-    Widget ancestor = parent;
-    while (ancestor != null && ancestor.runtimeType != targetType)
-      ancestor = ancestor.parent;
-    return ancestor;
-  }
-  void _dependenciesChanged() {
+  void dependenciesChanged() {
     // called by Inherited.sync()
     _scheduleBuild();
   }
@@ -937,6 +947,11 @@
     }
   }
 
+  void dependenciesChanged() {
+    // called by Inherited.sync()
+    syncRenderObject(this);
+  }
+
   void remove() {
     assert(renderObject != null);
     _nodeMap.remove(renderObject);
diff --git a/sky/packages/sky/lib/widgets/switch.dart b/sky/packages/sky/lib/widgets/switch.dart
index ccdf435..573716d 100644
--- a/sky/packages/sky/lib/widgets/switch.dart
+++ b/sky/packages/sky/lib/widgets/switch.dart
@@ -30,47 +30,34 @@
 const Size _kSwitchSize = const Size(_kSwitchWidth + 2.0, _kSwitchHeight + 2.0);
 const double _kReactionRadius = _kSwitchWidth / 2.0;
 
-class Switch extends Component {
-  Switch({Key key, this.value, this.onChanged}) : super(key: key);
-
-  final bool value;
-  final ValueChanged onChanged;
-
-  Widget build() {
-    return new _SwitchWrapper(
-        value: value,
-        onChanged: onChanged,
-        thumbColor: Theme.of(this).accentColor);
-  }
-}
-
-// This wrapper class exists only because Switch needs to be a Component in
-// order to get an accent color from a Theme but Components do not know how to
-// host RenderObjects.
-class _SwitchWrapper extends LeafRenderObjectWrapper {
-  _SwitchWrapper({Key key, this.value, this.onChanged, this.thumbColor})
+class Switch extends LeafRenderObjectWrapper {
+  Switch({ Key key, this.value, this.onChanged })
       : super(key: key);
 
   final bool value;
   final ValueChanged onChanged;
-  final Color thumbColor;
 
   _RenderSwitch get renderObject => super.renderObject;
   _RenderSwitch createNode() => new _RenderSwitch(
-      value: value, thumbColor: thumbColor, onChanged: onChanged);
+    value: value,
+    thumbColor: null,
+    onChanged: onChanged
+  );
 
-  void syncRenderObject(_SwitchWrapper old) {
+  void syncRenderObject(Switch old) {
     super.syncRenderObject(old);
     renderObject.value = value;
     renderObject.onChanged = onChanged;
-    renderObject.thumbColor = thumbColor;
+    renderObject.thumbColor = Theme.of(this).accentColor;
   }
 }
 
 class _RenderSwitch extends RenderToggleable {
-  _RenderSwitch(
-      {bool value, Color thumbColor: _kThumbOffColor, ValueChanged onChanged})
-      : _thumbColor = thumbColor,
+  _RenderSwitch({
+    bool value,
+    Color thumbColor: _kThumbOffColor,
+    ValueChanged onChanged
+  }) : _thumbColor = thumbColor,
         super(value: value, onChanged: onChanged, size: _kSwitchSize) {}
 
   Color _thumbColor;
diff --git a/sky/packages/sky/lib/widgets/theme.dart b/sky/packages/sky/lib/widgets/theme.dart
index b84ff16..fb7cad8 100644
--- a/sky/packages/sky/lib/widgets/theme.dart
+++ b/sky/packages/sky/lib/widgets/theme.dart
@@ -23,8 +23,8 @@
 
   static final ThemeData _kFallbackTheme = new ThemeData.fallback();
 
-  static ThemeData of(Component component) {
-    Theme theme = component.inheritedOfType(Theme);
+  static ThemeData of(Widget widget) {
+    Theme theme = widget.inheritedOfType(Theme);
     return theme == null ? _kFallbackTheme : theme.data;
   }
 
diff --git a/sky/tools/shelldb b/sky/tools/shelldb
index 6283a8c..dd51c64 100755
--- a/sky/tools/shelldb
+++ b/sky/tools/shelldb
@@ -392,39 +392,6 @@
         pids.clear()
 
 
-class Analyze(object):
-    def add_subparser(self, subparsers):
-        analyze_parser = subparsers.add_parser('analyze',
-            help=('run the dart analyzer with sky url mappings'))
-        analyze_parser.add_argument('app_path', type=str)
-        analyze_parser.add_argument('--congratulate', action="store_true")
-        analyze_parser.set_defaults(func=self.run)
-
-    def run(self, args, pids):
-        build_dir = pids.get('build_dir')
-        if not build_dir:
-            logging.fatal("pids file missing build_dir. Try 'start' first.")
-            return 2
-        analyzer_path = os.path.join(SRC_ROOT, 'sky/tools/skyanalyzer')
-        analyzer_args = [
-            analyzer_path,
-            args.app_path
-        ]
-        if args.congratulate:
-          analyzer_args.append('--congratulate')
-        try:
-          output = subprocess.check_output(analyzer_args, stderr=subprocess.STDOUT)
-          result = 0
-        except subprocess.CalledProcessError as e:
-          output = e.output
-          result = e.returncode
-        lines = output.split('\n')
-        lines.pop()
-        for line in lines:
-          print >> sys.stderr, line
-        return result
-
-
 class StartTracing(object):
     def add_subparser(self, subparsers):
         start_tracing_parser = subparsers.add_parser('start_tracing',
@@ -480,7 +447,6 @@
             SetBuildDir(),
             StartSky(),
             StopSky(),
-            Analyze(),
             GDBAttach(),
             StartTracing(),
             StopTracing(),
diff --git a/sky/tools/skyanalyzer b/sky/tools/skyanalyzer
index 3d4da4b..ce09da5 100755
--- a/sky/tools/skyanalyzer
+++ b/sky/tools/skyanalyzer
@@ -31,9 +31,6 @@
   # Ignored because they don't affect Sky code
   re.compile(r'\[hint\] When compiled to JS, this test might return true when the left hand side is an int'),
 
-  # TODO: Remove once sdk-extensions are in place
-  re.compile(r'^\[error\] Native functions can only be declared in'),
-
   # TODO: Fix all the warnings in the mojo packages
   re.compile(r'.*dart-pub-cache.*\.mojom\.dart'),
   re.compile(r'.*dart-pub-cache.*/mojo-'),
@@ -42,10 +39,6 @@
   # TODO: Remove this once Sky no longer generates this warning.
   # dartbug.com/22836
   re.compile(r'.*cannot both be unnamed'),
-
-  # TODO: Remove this once Sky no longer generates this warning.
-  # dartbug.com/23606
-  re.compile(r'^\[warning] Missing concrete implementation of \'RenderObject.toString\''),
 ]
 
 def main():
@@ -56,7 +49,7 @@
 
     try:
       subprocess.check_output([
-          DARTANALYZER, "--package-warnings", args.app_path,
+          DARTANALYZER, "--package-warnings", os.path.abspath(args.app_path),
           "--package-root", os.path.join(WORKBENCH, "packages"),
           "--fatal-warnings"
       ], stderr=subprocess.STDOUT, cwd=WORKBENCH)
diff --git a/ui/gl/gl_surface_ios.h b/ui/gl/gl_surface_ios.h
index 3b1d317..55ecd76 100644
--- a/ui/gl/gl_surface_ios.h
+++ b/ui/gl/gl_surface_ios.h
@@ -28,6 +28,8 @@
   uint32_t depth_stencil_packed_buffer_;
   Size last_configured_size_;
   bool framebuffer_setup_complete_;
+
+  ~GLSurfaceIOS() override;
   void SetupFramebufferIfNecessary();
 
   DISALLOW_COPY_AND_ASSIGN(GLSurfaceIOS);
diff --git a/ui/gl/gl_surface_ios.mm b/ui/gl/gl_surface_ios.mm
index a65c666..0f8b1fc 100644
--- a/ui/gl/gl_surface_ios.mm
+++ b/ui/gl/gl_surface_ios.mm
@@ -30,6 +30,8 @@
       framebuffer_setup_complete_(false) {
 }
 
+GLSurfaceIOS::~GLSurfaceIOS() {}
+
 #ifndef NDEBUG
 static void GLSurfaceIOS_AssertFramebufferCompleteness(void) {
   GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);