From d1364643db2ae66214cce3d066ee758b0f9b5d09 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Thu, 10 Dec 2015 20:13:08 -0800 Subject: [PATCH] applyPaintTransform() improvements Previously, applyPaintTransform() had to know how it was positioned in its parent, even though that's really the parent's responsibility. Now, applyPaintTransform() is given a child and applies the transform that it would give the child during paint. This makes it possible for applyPaintTransform() to work across coordinate system boundaries (e.g. box to sector, or view to box -- previously, view to box only worked because we explicitly skipped that step -- since view doesn't actually apply a transform, it doesn't really matter). --- .../flutter/lib/src/material/material.dart | 9 ++-- packages/flutter/lib/src/rendering/block.dart | 4 +- packages/flutter/lib/src/rendering/box.dart | 44 ++++++++++--------- .../flutter/lib/src/rendering/object.dart | 8 ++-- .../flutter/lib/src/rendering/proxy_box.dart | 4 +- .../flutter/lib/src/rendering/viewport.dart | 4 +- 6 files changed, 40 insertions(+), 33 deletions(-) diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index de3b8909c8..922d75ffdf 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -298,17 +298,18 @@ abstract class InkFeature { assert(referenceBox.attached); assert(!_debugDisposed); // find the chain of renderers from us to the feature's referenceBox - List descendants = []; + List descendants = [referenceBox]; RenderBox node = referenceBox; while (node != renderer) { - descendants.add(node); node = node.parent; assert(node != null); + descendants.add(node); } // determine the transform that gets our coordinate system to be like theirs Matrix4 transform = new Matrix4.identity(); - for (RenderBox descendant in descendants.reversed) - descendant.applyPaintTransform(transform); + assert(descendants.length >= 2); + for (int index = descendants.length - 1; index > 0; index -= 1) + descendants[index].applyPaintTransform(descendants[index - 1], transform); paintFeature(canvas, transform); } diff --git a/packages/flutter/lib/src/rendering/block.dart b/packages/flutter/lib/src/rendering/block.dart index a1c4e33772..96edfa31e3 100644 --- a/packages/flutter/lib/src/rendering/block.dart +++ b/packages/flutter/lib/src/rendering/block.dart @@ -420,12 +420,12 @@ class RenderBlockViewport extends RenderBlockBase { context.pushClipRect(needsCompositing, offset, Point.origin & size, _paintContents); } - void applyPaintTransform(Matrix4 transform) { - super.applyPaintTransform(transform); + void applyPaintTransform(RenderBox child, Matrix4 transform) { if (isVertical) transform.translate(0.0, startOffset); else transform.translate(startOffset, 0.0); + super.applyPaintTransform(child, transform); } bool hitTestChildren(HitTestResult result, { Point position }) { diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index ced458e548..4c57d4332e 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -609,49 +609,53 @@ abstract class RenderBox extends RenderObject { /// visually "on top" (i.e., paints later). bool hitTestChildren(HitTestResult result, { Point position }) => false; - /// Multiply the transform from the parent's coordinate system to this box's - /// coordinate system into the given transform - /// - /// This function is used to convert coordinate systems between boxes. - /// Subclasses that apply transforms during painting should override this - /// function to factor those transforms into the calculation. - void applyPaintTransform(Matrix4 transform) { - if (parentData is BoxParentData) { - Point position = (parentData as BoxParentData).position; - transform.translate(position.x, position.y); - } - } - static Point _transformPoint(Matrix4 transform, Point point) { Vector3 position3 = new Vector3(point.x, point.y, 0.0); Vector3 transformed3 = transform.transform3(position3); return new Point(transformed3.x, transformed3.y); } + /// Multiply the transform from the parent's coordinate system to this box's + /// coordinate system into the given transform. + /// + /// This function is used to convert coordinate systems between boxes. + /// Subclasses that apply transforms during painting should override this + /// function to factor those transforms into the calculation. + /// + /// The RenderBox implementation takes care of adjusting the matrix for the + /// position of the given child. + void applyPaintTransform(RenderObject child, Matrix4 transform) { + assert(child.parent == this); + BoxParentData childParentData = child.parentData; + Point position = childParentData.position; + transform.translate(position.x, position.y); + } + /// Convert the given point from the global coodinate system to the local /// coordinate system for this box Point globalToLocal(Point point) { assert(attached); Matrix4 transform = new Matrix4.identity(); RenderObject renderer = this; - while (renderer != null) { - renderer.applyPaintTransform(transform); - renderer = renderer.parent; + while (renderer.parent is RenderObject) { + RenderObject rendererParent = renderer.parent; + rendererParent.applyPaintTransform(renderer, transform); + renderer = rendererParent; } /* double det = */ transform.invert(); // TODO(abarth): Check the determinant for degeneracy. return _transformPoint(transform, point); } - /// Convert the given point from the local coordiante system for this box to - /// the global coordinate sytem + /// Convert the given point from the local coordinate system for this box to + /// the global coordinate system. Point localToGlobal(Point point) { List renderers = []; for (RenderObject renderer = this; renderer != null; renderer = renderer.parent) renderers.add(renderer); Matrix4 transform = new Matrix4.identity(); - for (RenderObject renderer in renderers.reversed) - renderer.applyPaintTransform(transform); + for (int index = renderers.length - 1; index > 0; index -= 1) + renderers[index].applyPaintTransform(renderers[index - 1], transform); return _transformPoint(transform, point); } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 176e009d1a..2a52f6ca01 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -1036,12 +1036,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// be recorded on separate compositing layers. void paint(PaintingContext context, Offset offset) { } - /// If this render object applies a transform before painting, apply that - /// transform to the given matrix + /// Applies the transform that would be applied when painting the given child + /// to the given matrix. /// /// Used by coordinate conversion functions to translate coordinates local to /// one render object into coordinates local to another render object. - void applyPaintTransform(Matrix4 transform) { } + void applyPaintTransform(RenderObject child, Matrix4 transform) { + assert(child.parent == this); + } // EVENTS diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index bbb60e033f..87b4e0667e 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -974,9 +974,9 @@ class RenderTransform extends RenderProxyBox { } } - void applyPaintTransform(Matrix4 transform) { - super.applyPaintTransform(transform); + void applyPaintTransform(RenderBox child, Matrix4 transform) { transform.multiply(_effectiveTransform); + super.applyPaintTransform(child, transform); } void debugDescribeSettings(List settings) { diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index eee9cb65ed..b3cfa192f5 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -164,9 +164,9 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin