Add PaintingContext which has-a sky.Canvas instead of is-a sky.Canvas

We'll need this for compositing because we need to switch out the sky.Canvas
when we switch compositing layers.
diff --git a/examples/game/lib/sprite_box.dart b/examples/game/lib/sprite_box.dart
index 62532f2..a18f3a8 100644
--- a/examples/game/lib/sprite_box.dart
+++ b/examples/game/lib/sprite_box.dart
@@ -321,7 +321,8 @@
     _rootNode._invalidateToBoxTransformMatrix();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
+    final PaintingCanvas canvas = context.canvas;
     canvas.save();
 
     // Move to correct coordinate space before drawing
diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart
index a91914c..3d6375b 100644
--- a/examples/rendering/sector_layout.dart
+++ b/examples/rendering/sector_layout.dart
@@ -129,7 +129,7 @@
   }
 
   // offset must point to the center of the circle
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     assert(deltaRadius != null);
     assert(deltaTheta != null);
     assert(parentData is SectorParentData);
@@ -138,6 +138,7 @@
       return;
 
     if (_decoration.backgroundColor != null) {
+      final PaintingCanvas canvas = context.canvas;
       Paint paint = new Paint()..color = _decoration.backgroundColor;
       Path path = new Path();
       double outerRadius = (parentData.radius + deltaRadius);
@@ -266,13 +267,13 @@
 
   // offset must point to the center of our circle
   // each sector then knows how to paint itself at its location
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     // TODO(ianh): avoid code duplication
-    super.paint(canvas, offset);
+    super.paint(context, offset);
     RenderSector child = firstChild;
     while (child != null) {
       assert(child.parentData is SectorChildListParentData);
-      canvas.paintChild(child, offset.toPoint());
+      context.paintChild(child, offset.toPoint());
       child = child.parentData.nextSibling;
     }
   }
@@ -371,13 +372,13 @@
 
   // offset must point to the center of our circle
   // each sector then knows how to paint itself at its location
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     // TODO(ianh): avoid code duplication
-    super.paint(canvas, offset);
+    super.paint(context, offset);
     RenderSector child = firstChild;
     while (child != null) {
       assert(child.parentData is SectorChildListParentData);
-      canvas.paintChild(child, offset.toPoint());
+      context.paintChild(child, offset.toPoint());
       child = child.parentData.nextSibling;
     }
   }
@@ -464,12 +465,12 @@
     }
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    super.paint(canvas, offset);
+  void paint(PaintingContext context, Offset offset) {
+    super.paint(context, offset);
     if (child != null) {
       Rect bounds = offset & size;
       // we move the offset to the center of the circle for the RenderSectors
-      canvas.paintChild(child, bounds.center);
+      context.paintChild(child, bounds.center);
     }
   }
 
diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart
index ea4d836..d94333b 100644
--- a/examples/rendering/touch_demo.dart
+++ b/examples/rendering/touch_demo.dart
@@ -33,8 +33,8 @@
     radius = 5 + (95 * event.pressure);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    canvas.drawCircle(position + offset, radius, _paint);
+  void paint(PaintingContext context, Offset offset) {
+    context.canvas.drawCircle(position + offset, radius, _paint);
   }
 }
 
@@ -70,7 +70,8 @@
     size = constraints.biggest;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
+    final PaintingCanvas canvas = context.canvas;
     Paint white = new Paint()
         ..color = const Color(0xFFFFFFFF);
     canvas.drawRect(offset & size, white);
diff --git a/sky/packages/sky/lib/rendering/auto_layout.dart b/sky/packages/sky/lib/rendering/auto_layout.dart
index 1942760..82ea255 100644
--- a/sky/packages/sky/lib/rendering/auto_layout.dart
+++ b/sky/packages/sky/lib/rendering/auto_layout.dart
@@ -216,8 +216,8 @@
     defaultHitTestChildren(result, position: position);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    defaultPaint(canvas, offset);
+  void paint(PaintingContext context, Offset offset) {
+    defaultPaint(context, offset);
   }
 
   List<al.Constraint> _constructImplicitConstraints() {
diff --git a/sky/packages/sky/lib/rendering/block.dart b/sky/packages/sky/lib/rendering/block.dart
index 1fe9b4e..d5f3497 100644
--- a/sky/packages/sky/lib/rendering/block.dart
+++ b/sky/packages/sky/lib/rendering/block.dart
@@ -156,8 +156,8 @@
     assert(!size.isInfinite);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    defaultPaint(canvas, offset);
+  void paint(PaintingContext context, Offset offset) {
+    defaultPaint(context, offset);
   }
 
   void hitTestChildren(HitTestResult result, { Point position }) {
@@ -242,11 +242,11 @@
     super.performLayout();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    canvas.save();
-    canvas.clipRect(offset & size);
-    defaultPaint(canvas, offset.translate(0.0, startOffset));
-    canvas.restore();
+  void paint(PaintingContext context, Offset offset) {
+    context.canvas.save();
+    context.canvas.clipRect(offset & size);
+    defaultPaint(context, offset.translate(0.0, startOffset));
+    context.canvas.restore();
   }
 
   void applyPaintTransform(Matrix4 transform) {
diff --git a/sky/packages/sky/lib/rendering/box.dart b/sky/packages/sky/lib/rendering/box.dart
index c106892..e7ad244 100644
--- a/sky/packages/sky/lib/rendering/box.dart
+++ b/sky/packages/sky/lib/rendering/box.dart
@@ -491,20 +491,20 @@
   }
 
   Rect get paintBounds => Point.origin & size;
-  void debugPaint(PaintingCanvas canvas, Offset offset) {
+  void debugPaint(PaintingContext context, Offset offset) {
     if (debugPaintSizeEnabled)
-      debugPaintSize(canvas, offset);
+      debugPaintSize(context, offset);
     if (debugPaintBaselinesEnabled)
-      debugPaintBaselines(canvas, offset);
+      debugPaintBaselines(context, offset);
   }
-  void debugPaintSize(PaintingCanvas canvas, Offset offset) {
+  void debugPaintSize(PaintingContext context, Offset offset) {
     Paint paint = new Paint();
     paint.setStyle(sky.PaintingStyle.stroke);
     paint.strokeWidth = 1.0;
     paint.color = debugPaintSizeColor;
-    canvas.drawRect(offset & size, paint);
+    context.canvas.drawRect(offset & size, paint);
   }
-  void debugPaintBaselines(PaintingCanvas canvas, Offset offset) {
+  void debugPaintBaselines(PaintingContext context, Offset offset) {
     Paint paint = new Paint();
     paint.setStyle(sky.PaintingStyle.stroke);
     paint.strokeWidth = 0.25;
@@ -516,7 +516,7 @@
       path = new Path();
       path.moveTo(offset.dx, offset.dy + baselineI);
       path.lineTo(offset.dx + size.width, offset.dy + baselineI);
-      canvas.drawPath(path, paint);
+      context.canvas.drawPath(path, paint);
     }
     // alphabetic baseline
     double baselineA = getDistanceToBaseline(TextBaseline.alphabetic, onlyReal: true);
@@ -525,7 +525,7 @@
       path = new Path();
       path.moveTo(offset.dx, offset.dy + baselineA);
       path.lineTo(offset.dx + size.width, offset.dy + baselineA);
-      canvas.drawPath(path, paint);
+      context.canvas.drawPath(path, paint);
     }
   }
 
@@ -586,9 +586,9 @@
       super.hitTestChildren(result, position: position);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null)
-      canvas.paintChild(child, offset.toPoint());
+      context.paintChild(child, offset.toPoint());
   }
 }
 
@@ -812,7 +812,7 @@
     return _cachedPaint;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
       int a = _alpha;
 
@@ -820,13 +820,13 @@
         return;
 
       if (a == 255) {
-        canvas.paintChild(child, offset.toPoint());
+        context.paintChild(child, offset.toPoint());
         return;
       }
 
-      canvas.saveLayer(null, _paint);
-      canvas.paintChild(child, offset.toPoint());
-      canvas.restore();
+      context.canvas.saveLayer(null, _paint);
+      context.paintChild(child, offset.toPoint());
+      context.canvas.restore();
     }
   }
 }
@@ -868,11 +868,11 @@
     return _cachedPaint;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
-      canvas.saveLayer(offset & size, _paint);
-      canvas.paintChild(child, offset.toPoint());
-      canvas.restore();
+      context.canvas.saveLayer(offset & size, _paint);
+      context.paintChild(child, offset.toPoint());
+      context.canvas.restore();
     }
   }
 }
@@ -880,12 +880,12 @@
 class RenderClipRect extends RenderProxyBox {
   RenderClipRect({ RenderBox child }) : super(child);
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
-      canvas.save();
-      canvas.clipRect(offset & size);
-      canvas.paintChild(child, offset.toPoint());
-      canvas.restore();
+      context.canvas.save();
+      context.canvas.clipRect(offset & size);
+      context.paintChild(child, offset.toPoint());
+      context.canvas.restore();
     }
   }
 }
@@ -919,14 +919,14 @@
 
   final Paint _paint = new Paint()..isAntiAlias = false;
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
       Rect rect = offset & size;
-      canvas.saveLayer(rect, _paint);
+      context.canvas.saveLayer(rect, _paint);
       sky.RRect rrect = new sky.RRect()..setRectXY(rect, xRadius, yRadius);
-      canvas.clipRRect(rrect);
-      canvas.paintChild(child, offset.toPoint());
-      canvas.restore();
+      context.canvas.clipRRect(rrect);
+      context.paintChild(child, offset.toPoint());
+      context.canvas.restore();
     }
   }
 }
@@ -947,13 +947,13 @@
     return _cachedPath;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
       Rect rect = offset & size;
-      canvas.saveLayer(rect, _paint);
-      canvas.clipPath(_getPath(rect));
-      canvas.paintChild(child, offset.toPoint());
-      canvas.restore();
+      context.canvas.saveLayer(rect, _paint);
+      context.canvas.clipPath(_getPath(rect));
+      context.paintChild(child, offset.toPoint());
+      context.canvas.restore();
     }
   }
 }
@@ -1004,9 +1004,9 @@
     return result;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null)
-      canvas.paintChild(child, child.parentData.position + offset);
+      context.paintChild(child, child.parentData.position + offset);
   }
 
   void hitTestChildren(HitTestResult result, { Point position }) {
@@ -1297,18 +1297,18 @@
                       dyInDevicePixels / devicePixelRatio);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null) {
       Offset roundedScrollOffset = _scrollOffsetRoundedToIntegerDevicePixels;
       bool _needsClip = offset < Offset.zero ||
                         !(offset & size).contains(((offset - roundedScrollOffset) & child.size).bottomRight);
       if (_needsClip) {
-        canvas.save();
-        canvas.clipRect(offset & size);
+        context.canvas.save();
+        context.canvas.clipRect(offset & size);
       }
-      canvas.paintChild(child, (offset - roundedScrollOffset).toPoint());
+      context.paintChild(child, (offset - roundedScrollOffset).toPoint());
       if (_needsClip)
-        canvas.restore();
+        context.canvas.restore();
     }
   }
 
@@ -1452,10 +1452,11 @@
     size = _sizeForConstraints(constraints);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (_image == null)
       return;
     bool needsScale = size.width != _image.width || size.height != _image.height;
+    final PaintingCanvas canvas = context.canvas;
     if (needsScale) {
       double widthScale = size.width / _image.width;
       double heightScale = size.height / _image.height;
@@ -1518,11 +1519,11 @@
     super.detach();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     assert(size.width != null);
     assert(size.height != null);
-    _painter.paint(canvas, offset & size);
-    super.paint(canvas, offset);
+    _painter.paint(context.canvas, offset & size);
+    super.paint(context, offset);
   }
 
   String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}decoration:\n${_painter.decoration.toString(prefix + "  ")}\n';
@@ -1588,12 +1589,12 @@
     return super.hitTest(result, position: transformed);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
-    canvas.save();
-    canvas.translate(offset.dx, offset.dy);
-    canvas.concat(_transform.storage);
-    super.paint(canvas, Offset.zero);
-    canvas.restore();
+  void paint(PaintingContext context, Offset offset) {
+    context.canvas.save();
+    context.canvas.translate(offset.dx, offset.dy);
+    context.canvas.concat(_transform.storage);
+    super.paint(context, Offset.zero);
+    context.canvas.restore();
   }
 
   void applyPaintTransform(Matrix4 transform) {
@@ -1656,12 +1657,14 @@
     super.attach();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     assert(_callback != null);
-    canvas.translate(offset.dx, offset.dy);
-    _callback(canvas, size);
-    super.paint(canvas, Offset.zero);
-    canvas.translate(-offset.dx, -offset.dy);
+    context.canvas.translate(offset.dx, offset.dy);
+    _callback(context.canvas, size);
+    // TODO(abarth): We should translate back before calling super because in
+    // the future, super.paint might switch our compositing layer.
+    super.paint(context, Offset.zero);
+    context.canvas.translate(-offset.dx, -offset.dy);
   }
 }
 
@@ -1735,9 +1738,9 @@
     return true;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (child != null)
-      canvas.paintChild(child, offset.toPoint());
+      context.paintChild(child, offset.toPoint());
   }
 
   void paintFrame() {
@@ -1747,9 +1750,10 @@
       sky.PictureRecorder recorder = new sky.PictureRecorder();
       Rect cullRect = Point.origin & (size * devicePixelRatio);
       PaintingCanvas canvas = new PaintingCanvas(recorder, cullRect);
+      PaintingContext context = new PaintingContext(canvas);
       canvas.drawColor(const Color(0xFF000000), sky.TransferMode.src);
       canvas.scale(devicePixelRatio, devicePixelRatio);
-      canvas.paintChild(child, Point.origin);
+      context.paintChild(child, Point.origin);
       sky.view.picture = recorder.endRecording();
     } finally {
       sky.tracing.end('RenderView.paintFrame');
@@ -1817,11 +1821,11 @@
     }
   }
 
-  void defaultPaint(PaintingCanvas canvas, Offset offset) {
+  void defaultPaint(PaintingContext context, Offset offset) {
     RenderBox child = firstChild;
     while (child != null) {
       assert(child.parentData is ParentDataType);
-      canvas.paintChild(child, child.parentData.position + offset);
+      context.paintChild(child, child.parentData.position + offset);
       child = child.parentData.nextSibling;
     }
   }
diff --git a/sky/packages/sky/lib/rendering/flex.dart b/sky/packages/sky/lib/rendering/flex.dart
index 5bc9d03..b8d87f4 100644
--- a/sky/packages/sky/lib/rendering/flex.dart
+++ b/sky/packages/sky/lib/rendering/flex.dart
@@ -449,19 +449,19 @@
     defaultHitTestChildren(result, position: position);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (_overflow > 0) {
-      canvas.save();
-      canvas.clipRect(offset & size);
-      defaultPaint(canvas, offset);
-      canvas.restore();
+      context.canvas.save();
+      context.canvas.clipRect(offset & size);
+      defaultPaint(context, offset);
+      context.canvas.restore();
     } else {
-      defaultPaint(canvas, offset);
+      defaultPaint(context, offset);
     }
   }
 
-  void debugPaintSize(PaintingCanvas canvas, Offset offset) {
-    super.debugPaintSize(canvas, offset);
+  void debugPaintSize(PaintingContext context, Offset offset) {
+    super.debugPaintSize(context, offset);
     if (_overflow <= 0)
       return;
 
@@ -479,6 +479,6 @@
                        new Size(size.width, _overflow);
         break;
     }
-    canvas.drawRect(overflowRect, paint);
+    context.canvas.drawRect(overflowRect, paint);
   }
 }
diff --git a/sky/packages/sky/lib/rendering/object.dart b/sky/packages/sky/lib/rendering/object.dart
index cfa42e7..4f06c5e 100644
--- a/sky/packages/sky/lib/rendering/object.dart
+++ b/sky/packages/sky/lib/rendering/object.dart
@@ -29,15 +29,21 @@
 
 class PaintingCanvas extends sky.Canvas {
   PaintingCanvas(sky.PictureRecorder recorder, Rect bounds) : super(recorder, bounds);
+}
+
+class PaintingContext {
+  final PaintingCanvas canvas;
+
+  PaintingContext(this.canvas);
 
   List<RenderObject> _descendentsWithPaintingCanvases = new List<RenderObject>(); // used by RenderObject._updatePaintingCanvas() to find out which RenderObjects to ask to paint
   void paintChild(RenderObject child, Point point) {
     if (child.createNewDisplayList) {
       assert(!_descendentsWithPaintingCanvases.contains(child));
       _descendentsWithPaintingCanvases.add(child);
-      drawPaintingNode(child._paintingNode, point);
+      canvas.drawPaintingNode(child._paintingNode, point);
     } else {
-      child._paintOnCanvas(this, point.toOffset());
+      child._paintWithContext(this, point.toOffset());
     }
   }
 }
@@ -362,10 +368,11 @@
     assert(!_needsLayout);
     assert(createNewDisplayList);
     sky.PictureRecorder recorder = new sky.PictureRecorder();
-    PaintingCanvas canvas = new PaintingCanvas(recorder, paintBounds);
+    sky.Canvas canvas = new sky.Canvas(recorder, paintBounds);
+    PaintingContext context = new PaintingContext(canvas);
     _needsPaint = false;
     try {
-      _paintOnCanvas(canvas, Offset.zero);
+      _paintWithContext(context, Offset.zero);
     } catch (e) {
       print('Exception raised during _updatePaintingCanvas:\n${e}\nContext:\n${this}');
       if (inDebugBuild)
@@ -375,8 +382,8 @@
     assert(!_needsLayout); // check that the paint() method didn't mark us dirty again
     assert(!_needsPaint); // check that the paint() method didn't mark us dirty again
     _paintingNode.setBackingDrawable(recorder.endRecordingAsDrawable());
-    if (canvas._descendentsWithPaintingCanvases != null) {
-      for (RenderObject node in canvas._descendentsWithPaintingCanvases) {
+    if (context._descendentsWithPaintingCanvases != null) {
+      for (RenderObject node in context._descendentsWithPaintingCanvases) {
         assert(node.attached == attached);
         if (node._needsPaint)
           node._updatePaintingCanvas();
@@ -384,7 +391,7 @@
     }
   }
 
-  void _paintOnCanvas(PaintingCanvas canvas, Offset offset) {
+  void _paintWithContext(PaintingContext context, Offset offset) {
     _needsPaint = false;
     assert(!_debugDoingThisPaint);
     RenderObject debugLastActivePaint;
@@ -392,17 +399,17 @@
       _debugDoingThisPaint = true;
       debugLastActivePaint = _debugActivePaint;
       _debugActivePaint = this;
-      debugPaint(canvas, offset);
+      debugPaint(context, offset);
       if (debugPaintBoundsEnabled) {
-        canvas.save();
-        canvas.clipRect(paintBounds.shift(offset));
+        context.canvas.save();
+        context.canvas.clipRect(paintBounds.shift(offset));
       }
       return true;
     });
-    paint(canvas, offset);
+    paint(context, offset);
     assert(() {
       if (debugPaintBoundsEnabled)
-        canvas.restore();
+        context.canvas.restore();
       _debugActivePaint = debugLastActivePaint;
       _debugDoingThisPaint = false;
       return true;
@@ -412,8 +419,8 @@
 
   bool get createNewDisplayList => false;
   Rect get paintBounds;
-  void debugPaint(PaintingCanvas canvas, Offset offset) { }
-  void paint(PaintingCanvas canvas, Offset offset) { }
+  void debugPaint(PaintingContext context, Offset offset) { }
+  void paint(PaintingContext context, Offset offset) { }
 
   void applyPaintTransform(Matrix4 transform) { }
 
diff --git a/sky/packages/sky/lib/rendering/paragraph.dart b/sky/packages/sky/lib/rendering/paragraph.dart
index ac64d59..7b8838b 100644
--- a/sky/packages/sky/lib/rendering/paragraph.dart
+++ b/sky/packages/sky/lib/rendering/paragraph.dart
@@ -181,7 +181,7 @@
                                           _applyFloatingPointHack(root.height)));
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     // Ideally we could compute the min/max intrinsic width/height with a
     // non-destructive operation. However, currently, computing these values
     // will destroy state inside the layout root. If that happens, we need to
@@ -192,9 +192,9 @@
     // TODO(ianh): Make LayoutRoot support a paint offset so we don't
     // need to translate for each span of text.
     _layout(constraints);
-    canvas.translate(offset.dx, offset.dy);
-    _layoutRoot.paint(canvas);
-    canvas.translate(-offset.dx, -offset.dy);
+    context.canvas.translate(offset.dx, offset.dy);
+    _layoutRoot.paint(context.canvas);
+    context.canvas.translate(-offset.dx, -offset.dy);
   }
 
   // we should probably expose a way to do precise (inter-glpyh) hit testing
diff --git a/sky/packages/sky/lib/rendering/stack.dart b/sky/packages/sky/lib/rendering/stack.dart
index 8b7a2b7..4a01dae 100644
--- a/sky/packages/sky/lib/rendering/stack.dart
+++ b/sky/packages/sky/lib/rendering/stack.dart
@@ -201,14 +201,14 @@
     defaultHitTestChildren(result, position: position);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (_hasVisualOverflow) {
-      canvas.save();
-      canvas.clipRect(offset & size);
-      defaultPaint(canvas, offset);
-      canvas.restore();
+      context.canvas.save();
+      context.canvas.clipRect(offset & size);
+      defaultPaint(context, offset);
+      context.canvas.restore();
     } else {
-      defaultPaint(canvas, offset);
+      defaultPaint(context, offset);
     }
   }
 }
diff --git a/sky/packages/sky/lib/widgets/checkbox.dart b/sky/packages/sky/lib/widgets/checkbox.dart
index d560aaf..d9a050b 100644
--- a/sky/packages/sky/lib/widgets/checkbox.dart
+++ b/sky/packages/sky/lib/widgets/checkbox.dart
@@ -101,7 +101,8 @@
     markNeedsPaint();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
+    final PaintingCanvas canvas = context.canvas;
     // Choose a color between grey and the theme color
     sky.Paint paint = new sky.Paint()
       ..strokeWidth = 2.0
diff --git a/sky/packages/sky/lib/widgets/ink_well.dart b/sky/packages/sky/lib/widgets/ink_well.dart
index eb39a0f..906f781 100644
--- a/sky/packages/sky/lib/widgets/ink_well.dart
+++ b/sky/packages/sky/lib/widgets/ink_well.dart
@@ -113,8 +113,9 @@
     markNeedsPaint();
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (!_splashes.isEmpty) {
+      final PaintingCanvas canvas = context.canvas;
       canvas.save();
       canvas.translate(offset.dx, offset.dy);
       canvas.clipRect(Point.origin & size);
@@ -122,7 +123,7 @@
         splash.paint(canvas);
       canvas.restore();
     }
-    super.paint(canvas, offset);
+    super.paint(context, offset);
   }
 }
 
diff --git a/sky/packages/sky/lib/widgets/scaffold.dart b/sky/packages/sky/lib/widgets/scaffold.dart
index 79ab95d..10d205c 100644
--- a/sky/packages/sky/lib/widgets/scaffold.dart
+++ b/sky/packages/sky/lib/widgets/scaffold.dart
@@ -141,12 +141,12 @@
     }
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     for (ScaffoldSlots slot in ScaffoldSlots.values) {
       RenderBox box = _slots[slot];
       if (box != null) {
         assert(box.parentData is BoxParentData);
-        canvas.paintChild(box, box.parentData.position + offset);
+        context.paintChild(box, box.parentData.position + offset);
       }
     }
   }
diff --git a/sky/packages/sky/lib/widgets/switch.dart b/sky/packages/sky/lib/widgets/switch.dart
index e2ce9d9..c6f8521 100644
--- a/sky/packages/sky/lib/widgets/switch.dart
+++ b/sky/packages/sky/lib/widgets/switch.dart
@@ -117,7 +117,8 @@
     _radialReaction = null;
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
+    final PaintingCanvas canvas = context.canvas;
     sky.Color thumbColor = _kThumbOffColor;
     sky.Color trackColor = _kTrackOffColor;
     if (value) {
diff --git a/sky/packages/sky/lib/widgets/tabs.dart b/sky/packages/sky/lib/widgets/tabs.dart
index 090c519..6811c21 100644
--- a/sky/packages/sky/lib/widgets/tabs.dart
+++ b/sky/packages/sky/lib/widgets/tabs.dart
@@ -246,21 +246,21 @@
     canvas.drawRect(rect, new Paint()..color = indicatorColor);
   }
 
-  void paint(PaintingCanvas canvas, Offset offset) {
+  void paint(PaintingContext context, Offset offset) {
     if (backgroundColor != null) {
       double width = layoutWidths != null
         ? layoutWidths.reduce((sum, width) => sum + width)
         : size.width;
       Rect rect = offset & new Size(width, size.height);
-      canvas.drawRect(rect, new Paint()..color = backgroundColor);
+      context.canvas.drawRect(rect, new Paint()..color = backgroundColor);
     }
     int index = 0;
     RenderBox child = firstChild;
     while (child != null) {
       assert(child.parentData is TabBarParentData);
-      canvas.paintChild(child, child.parentData.position + offset);
+      context.paintChild(child, child.parentData.position + offset);
       if (index++ == selectedIndex)
-        _paintIndicator(canvas, child, offset);
+        _paintIndicator(context.canvas, child, offset);
       child = child.parentData.nextSibling;
     }
   }
diff --git a/sky/tests/resources/display_list.dart b/sky/tests/resources/display_list.dart
index 6bd3e67..570d767 100644
--- a/sky/tests/resources/display_list.dart
+++ b/sky/tests/resources/display_list.dart
@@ -113,10 +113,15 @@
   void drawImageRect(sky.Image image, sky.Rect src, sky.Rect dst, Paint paint) {
     log("drawImageRect($image, $src, $dst, paint)");
   }
+}
+
+class TestPaintingContext extends PaintingContext {
+  TestPaintingContext(TestPaintingCanvas canvas) : super(canvas);
 
   void paintChild(RenderObject child, Point position) {
-    log("paintChild ${child.runtimeType} at $position");
-    child.paint(new TestPaintingCanvas(new sky.PictureRecorder(), size, logger, indent: "$indent  |"), position.toOffset());
+    canvas.log("paintChild ${child.runtimeType} at $position");
+    TestPaintingCanvas childCanvas = new TestPaintingCanvas(new sky.PictureRecorder(), canvas.size, canvas.logger, indent: "${canvas.indent}  |");
+    child.paint(new TestPaintingContext(childCanvas), position.toOffset());
   }
 }
 
@@ -142,9 +147,11 @@
     frame += 1;
     lastPaint = '';
     log("PAINT FOR FRAME #${frame} ----------------------------------------------");
-    var recorder = new sky.PictureRecorder();
-    var canvas = new TestPaintingCanvas(recorder, rootConstraints.size, log, indent: "${frame} |");
-    paint(canvas, Offset.zero);
+    sky.PictureRecorder recorder = new sky.PictureRecorder();
+    TestPaintingCanvas canvas = new TestPaintingCanvas(recorder, rootConstraints.size, log, indent: "${frame} |");
+    TestPaintingContext context = new TestPaintingContext(canvas);
+
+    paint(context, Offset.zero);
     recorder.endRecording();
     log("------------------------------------------------------------------------");
     RenderObject.debugDoingPaint = false;