| 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) { }
|
|
|
| }
|
|
|