Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:math' as math; | 5 import 'dart:math' as math; |
| 6 import 'dart:sky' as sky; | 6 import 'dart:sky' as sky; |
| 7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; | 7 import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; |
| 8 | 8 |
| 9 import '../base/hit_test.dart'; | 9 import '../base/hit_test.dart'; |
| 10 import '../base/node.dart'; | 10 import '../base/node.dart'; |
| 11 import '../base/scheduler.dart' as scheduler; | 11 import '../base/scheduler.dart' as scheduler; |
| 12 | 12 |
| 13 export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; | 13 export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; |
| 14 export '../base/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; | 14 export '../base/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; |
| 15 | 15 |
| 16 | 16 |
| 17 class ParentData { | 17 class ParentData { |
| 18 void detach() { | 18 void detach() { |
| 19 detachSiblings(); | 19 detachSiblings(); |
| 20 } | 20 } |
| 21 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart | 21 void detachSiblings() { } // workaround for lack of inter-class mixins in Dart |
| 22 void merge(ParentData other) { | 22 void merge(ParentData other) { |
| 23 // override this in subclasses to merge in data from other into this | 23 // override this in subclasses to merge in data from other into this |
| 24 assert(other.runtimeType == this.runtimeType); | 24 assert(other.runtimeType == this.runtimeType); |
| 25 } | 25 } |
| 26 String toString() => '<none>'; | 26 String toString() => '<none>'; |
| 27 } | 27 } |
| 28 | 28 |
| 29 class PaintingCanvas extends sky.Canvas { | 29 class PaintingCanvas extends sky.Canvas { |
| 30 PaintingCanvas(sky.PictureRecorder recorder, Size bounds) : super(recorder, bo unds); | 30 PaintingCanvas(sky.PictureRecorder recorder, Rect bounds) : super(recorder, bo unds); |
| 31 | 31 |
| 32 List<RenderObject> _descendentsWithPaintingCanvases = new List<RenderObject>() ; // used by RenderObject._updatePaintingCanvas() to find out which RenderObject s to ask to paint | |
| 32 void paintChild(RenderObject child, Point point) { | 33 void paintChild(RenderObject child, Point point) { |
| 33 child.paint(this, point.toOffset()); | 34 if (child.createNewDisplayList) { |
| 35 assert(!_descendentsWithPaintingCanvases.contains(child)); | |
| 36 _descendentsWithPaintingCanvases.add(child); | |
| 37 drawPaintingNode(child._paintingNode, point); | |
| 38 } else { | |
| 39 child._paintOnCanvas(this, point.toOffset()); | |
| 40 } | |
| 34 } | 41 } |
| 35 } | 42 } |
| 36 | 43 |
| 37 abstract class Constraints { | 44 abstract class Constraints { |
| 38 const Constraints(); | 45 const Constraints(); |
| 39 bool get isTight; | 46 bool get isTight; |
| 40 } | 47 } |
| 41 | 48 |
| 42 abstract class RenderObject extends AbstractNode implements HitTestTarget { | 49 abstract class RenderObject extends AbstractNode implements HitTestTarget { |
| 43 | 50 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 _cleanRelayoutSubtreeRootChildren(); | 139 _cleanRelayoutSubtreeRootChildren(); |
| 133 } | 140 } |
| 134 } | 141 } |
| 135 void _cleanRelayoutSubtreeRootChildren() { } // workaround for lack of inter-c lass mixins in Dart | 142 void _cleanRelayoutSubtreeRootChildren() { } // workaround for lack of inter-c lass mixins in Dart |
| 136 void scheduleInitialLayout() { | 143 void scheduleInitialLayout() { |
| 137 assert(attached); | 144 assert(attached); |
| 138 assert(parent == null); | 145 assert(parent == null); |
| 139 assert(_relayoutSubtreeRoot == null); | 146 assert(_relayoutSubtreeRoot == null); |
| 140 _relayoutSubtreeRoot = this; | 147 _relayoutSubtreeRoot = this; |
| 141 _nodesNeedingLayout.add(this); | 148 _nodesNeedingLayout.add(this); |
| 149 _nodesNeedingPaint.add(this); | |
| 142 scheduler.ensureVisualUpdate(); | 150 scheduler.ensureVisualUpdate(); |
| 143 } | 151 } |
| 144 static void flushLayout() { | 152 static void flushLayout() { |
| 145 sky.tracing.begin('RenderObject.flushLayout'); | 153 sky.tracing.begin('RenderObject.flushLayout'); |
| 146 _debugDoingLayout = true; | 154 _debugDoingLayout = true; |
| 147 try { | 155 try { |
| 148 List<RenderObject> dirtyNodes = _nodesNeedingLayout; | 156 List<RenderObject> dirtyNodes = _nodesNeedingLayout; |
| 149 _nodesNeedingLayout = new List<RenderObject>(); | 157 _nodesNeedingLayout = new List<RenderObject>(); |
| 150 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { | 158 dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { |
| 151 if (node._needsLayout && node.attached) | 159 if (node._needsLayout && node.attached) |
| 152 node.layoutWithoutResize(); | 160 node.layoutWithoutResize(); |
| 153 }); | 161 }); |
| 154 } finally { | 162 } finally { |
| 155 _debugDoingLayout = false; | 163 _debugDoingLayout = false; |
| 156 sky.tracing.end('RenderObject.flushLayout'); | 164 sky.tracing.end('RenderObject.flushLayout'); |
| 157 } | 165 } |
| 158 } | 166 } |
| 159 void layoutWithoutResize() { | 167 void layoutWithoutResize() { |
| 160 try { | 168 try { |
| 161 assert(_relayoutSubtreeRoot == this); | 169 assert(_relayoutSubtreeRoot == this); |
| 162 _debugCanParentUseSize = false; | 170 _debugCanParentUseSize = false; |
| 163 _debugDoingThisLayout = true; | 171 _debugDoingThisLayout = true; |
| 164 RenderObject debugPreviousActiveLayout = _debugActiveLayout; | 172 RenderObject debugPreviousActiveLayout = _debugActiveLayout; |
| 165 _debugActiveLayout = this; | 173 _debugActiveLayout = this; |
| 166 performLayout(); | 174 performLayout(); |
| 167 _debugActiveLayout = debugPreviousActiveLayout; | 175 _debugActiveLayout = debugPreviousActiveLayout; |
| 168 _debugDoingThisLayout = false; | 176 _debugDoingThisLayout = false; |
| 169 _debugCanParentUseSize = null; | 177 _debugCanParentUseSize = null; |
| 170 } catch (e, stack) { | 178 } catch (e) { |
| 171 print('Exception raised during layout:\n${e}\nContext:\n${this}'); | 179 print('Exception raised during layout:\n${e}\nContext:\n${this}'); |
| 172 print(stack); | |
| 173 return; | 180 return; |
| 174 } | 181 } |
| 175 _needsLayout = false; | 182 _needsLayout = false; |
| 176 markNeedsPaint(); | 183 markNeedsPaint(); |
| 177 } | 184 } |
| 178 void layout(Constraints constraints, { bool parentUsesSize: false }) { | 185 void layout(Constraints constraints, { bool parentUsesSize: false }) { |
| 179 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer | 186 final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer |
| 180 RenderObject relayoutSubtreeRoot; | 187 RenderObject relayoutSubtreeRoot; |
| 181 if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! Re nderObject) | 188 if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! Re nderObject) |
| 182 relayoutSubtreeRoot = this; | 189 relayoutSubtreeRoot = this; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 | 239 |
| 233 void rotate({ | 240 void rotate({ |
| 234 int oldAngle, // 0..3 | 241 int oldAngle, // 0..3 |
| 235 int newAngle, // 0..3 | 242 int newAngle, // 0..3 |
| 236 Duration time | 243 Duration time |
| 237 }) { } | 244 }) { } |
| 238 | 245 |
| 239 | 246 |
| 240 // PAINTING | 247 // PAINTING |
| 241 | 248 |
| 242 static bool debugDoingPaint = false; | 249 static List<RenderObject> _nodesNeedingPaint = new List<RenderObject>(); |
| 250 static bool _debugDoingPaint = false; | |
| 251 static bool get debugDoingPaint => _debugDoingPaint; | |
| 252 static void set debugDoingPaint(bool debug) { | |
| 253 _debugDoingPaint = debug; | |
| 254 } | |
| 255 | |
| 256 final sky.PaintingNode _paintingNode = new sky.PaintingNode(); // only set if createNewDisplayList is true | |
|
abarth-chromium
2015/07/07 21:22:29
I'd remove this comment and add assert(createNewDi
| |
| 257 sky.PaintingNode get paintingNode => _paintingNode; | |
| 258 bool _needsPaint = true; | |
| 259 bool get needsPaint => _needsPaint; | |
| 260 bool get createNewDisplayList => false; | |
| 261 | |
| 243 void markNeedsPaint() { | 262 void markNeedsPaint() { |
| 244 assert(!debugDoingPaint); | 263 assert(!debugDoingPaint); |
| 245 scheduler.ensureVisualUpdate(); | 264 if (_needsPaint) return; |
| 265 if (createNewDisplayList) { | |
| 266 _needsPaint = true; | |
| 267 _nodesNeedingPaint.add(this); | |
| 268 scheduler.ensureVisualUpdate(); | |
| 269 } else if (parent != null) { | |
|
abarth-chromium
2015/07/07 21:22:29
Can we make this if check into an assert? The onl
| |
| 270 if (parent is RenderObject) { | |
| 271 (parent as RenderObject).markNeedsPaint(); // TODO(ianh): remove the cas t once the analyzer is cleverer | |
| 272 } | |
| 273 } | |
| 246 } | 274 } |
| 275 | |
| 276 static void flushPaint() { | |
| 277 try { | |
| 278 _debugDoingPaint = true; | |
| 279 List<RenderObject> dirtyNodes = _nodesNeedingPaint; | |
| 280 _nodesNeedingPaint = new List<RenderObject>(); | |
| 281 for (RenderObject node in dirtyNodes..sort((a, b) => a.depth - b.depth)) { | |
| 282 if (node._needsPaint && node.attached) | |
| 283 node._updatePaintingCanvas(); | |
| 284 }; | |
| 285 assert(_nodesNeedingPaint.length == 0); | |
| 286 } catch (e) { | |
| 287 print('Exception raised during flushPaint:\n${e}'); | |
| 288 } finally { | |
| 289 _debugDoingPaint = false; | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 void _updatePaintingCanvas() { | |
| 294 assert(!_needsLayout); | |
| 295 assert(createNewDisplayList); | |
| 296 sky.PictureRecorder recorder = new sky.PictureRecorder(); | |
| 297 PaintingCanvas canvas = new PaintingCanvas(recorder, paintBounds); | |
| 298 _needsPaint = false; | |
| 299 try { | |
| 300 _paintOnCanvas(canvas, Offset.zero); | |
| 301 } catch (e) { | |
| 302 print('Exception raised during _updatePaintingCanvas:\n${e}\nContext:\n${t his}'); | |
| 303 return; | |
| 304 } | |
| 305 assert(!_needsLayout); // check that the paint() method didn't mark us dirty again | |
| 306 assert(!_needsPaint); // check that the paint() method didn't mark us dirty again | |
| 307 _paintingNode.setBackingDrawable(recorder.endRecordingAsDrawable()); | |
| 308 | |
| 309 if (canvas._descendentsWithPaintingCanvases != null) { | |
| 310 for (RenderObject node in canvas._descendentsWithPaintingCanvases) { | |
| 311 assert(node.attached == attached); | |
| 312 if (node._needsPaint) | |
| 313 node._updatePaintingCanvas(); | |
| 314 }; | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 void _paintOnCanvas(PaintingCanvas canvas, Offset offset) { | |
| 319 _needsPaint = false; | |
| 320 paint(canvas, offset); | |
| 321 assert(!_needsPaint); | |
| 322 } | |
| 323 | |
| 324 Rect get paintBounds; | |
| 325 | |
| 247 void paint(PaintingCanvas canvas, Offset offset) { } | 326 void paint(PaintingCanvas canvas, Offset offset) { } |
| 248 | 327 |
| 249 | 328 |
| 250 // EVENTS | 329 // EVENTS |
| 251 | 330 |
| 252 void handleEvent(sky.Event event, HitTestEntry entry) { | 331 void handleEvent(sky.Event event, HitTestEntry entry) { |
| 253 // override this if you have a client, to hand it to the client | 332 // override this if you have a client, to hand it to the client |
| 254 // override this if you want to do anything with the event | 333 // override this if you want to do anything with the event |
| 255 } | 334 } |
| 256 | 335 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 int count = 1; | 609 int count = 1; |
| 531 ChildType child = _firstChild; | 610 ChildType child = _firstChild; |
| 532 while (child != null) { | 611 while (child != null) { |
| 533 result += '${prefix}child ${count}: ${child.toString(prefix)}'; | 612 result += '${prefix}child ${count}: ${child.toString(prefix)}'; |
| 534 count += 1; | 613 count += 1; |
| 535 child = child.parentData.nextSibling; | 614 child = child.parentData.nextSibling; |
| 536 } | 615 } |
| 537 return result; | 616 return result; |
| 538 } | 617 } |
| 539 } | 618 } |
| OLD | NEW |