Index: sky/sdk/lib/framework/layout2.dart |
diff --git a/sky/sdk/lib/framework/layout2.dart b/sky/sdk/lib/framework/layout2.dart |
index e3773e2bcc67bea48bdb19bafce41577409a2637..5837577113eb2105f6ec7a31d0b58664dc80a9f2 100644 |
--- a/sky/sdk/lib/framework/layout2.dart |
+++ b/sky/sdk/lib/framework/layout2.dart |
@@ -32,14 +32,27 @@ double clamp({double min: 0.0, double value: 0.0, double max: double.INFINITY}) |
class RenderNodeDisplayList extends sky.PictureRecorder { |
RenderNodeDisplayList(double width, double height) : super(width, height); |
+ List<RenderNode> _children; // used by _doPaint() to find out which RenderNodes to ask to paint |
void paintChild(RenderNode child, double x, double y) { |
- save(); |
- translate(x, y); |
- child.paint(this); |
- restore(); |
+ if (child.createNewDisplayList) { |
+ if (_children == null) |
+ _children = new List<RenderNode>(); |
+ assert(!_children.contains(child)); |
+ _children.add(child); |
+ drawPaintNode(child._paintNode, transform: new Matrix.translate(x, y)); |
+ } else { |
+ save(); |
+ translate(x, y); |
+ child.paint(this); |
+ restore(); |
+ } |
} |
} |
+class PaintOptions { |
+ Matrix transform = Matrix.IDENTITY; |
+} |
+ |
abstract class RenderNode extends AbstractNode { |
// LAYOUT |
@@ -222,15 +235,57 @@ abstract class RenderNode extends AbstractNode { |
// PAINTING |
+ static List<RenderNode> _nodesNeedingPaint = new List<RenderNode>(); |
static bool _debugDoingPaint = false; |
+ PaintNode _paintNode; // only set if createNewDisplayList is true |
+ bool _needsPaint = true; |
+ bool get needsPaint => _needsPaint; |
+ bool get createNewDisplayList => false; |
void markNeedsPaint() { |
assert(!_debugDoingPaint); |
- var ancestor = this; |
- while (ancestor.parent != null) |
- ancestor = ancestor.parent; |
- assert(ancestor is Screen); |
- ancestor.paintFrame(); |
+ if (_needsPaint) return; |
+ if (createNewDisplayList) { |
+ _needsPaint = true; |
+ _nodesNeedingPaint.add(this); |
+ } else { |
+ assert(parent != null); |
+ parent.markNeedsPaint(); |
+ } |
+ } |
+ static void flushPaint() { |
+ List<RenderNode> dirtyNodes = _nodesNeedingPaint; |
+ _nodesNeedingPaint = new List<RenderNode>(); |
+ dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { |
+ if (node._needsPaint && node.attached) |
+ node._doPaint(); |
+ }); |
} |
+ void _doPaint() { |
+ assert(!_needsLayout); |
+ assert(createNewDisplayList); |
+ RenderNodeDisplayList newDisplayList = new RenderNodeDisplayList(); |
+ _needsPaint = false; |
+ try { |
+ paint(newDisplayList); |
+ } catch (e, stack) { |
+ print('Exception raised during paint of ${this}: ${e}'); |
+ print(stack); |
+ return; |
+ } |
+ 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 |
+ _paintNode.setDisplayList(newDisplayList); |
+ if (newDisplayList._children != null) |
+ newDisplayList._children.forEach((node) { |
+ assert(node.attached == attached); |
+ if (node._needsPaint) |
+ node._doPaint(); |
+ }); |
+ } |
+ |
+ PaintOptions paintOptions; |
+ // only set this to a subclass of PaintOptions that this class of RenderNode knows how to deal with |
+ |
void paint(RenderNodeDisplayList canvas) { } |
} |