From ebf032b82a069531d75e240ef5d529d0c9b440d7 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Fri, 20 Nov 2015 09:36:29 -0800 Subject: [PATCH] Avoid using transforms when simple offsets will do. --- packages/flutter/lib/painting.dart | 1 + .../flutter/lib/src/painting/transforms.dart | 40 ++++++++++++++++++ .../flutter/lib/src/rendering/proxy_box.dart | 10 ++++- .../painting/transform_utilities_test.dart | 42 +++++++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 packages/flutter/lib/src/painting/transforms.dart create mode 100644 packages/unit/test/painting/transform_utilities_test.dart diff --git a/packages/flutter/lib/painting.dart b/packages/flutter/lib/painting.dart index a0b7ef87e53..c0d1407a2bd 100644 --- a/packages/flutter/lib/painting.dart +++ b/packages/flutter/lib/painting.dart @@ -18,3 +18,4 @@ export 'src/painting/colors.dart'; export 'src/painting/shadows.dart'; export 'src/painting/text_painter.dart'; export 'src/painting/text_style.dart'; +export 'src/painting/transforms.dart'; diff --git a/packages/flutter/lib/src/painting/transforms.dart b/packages/flutter/lib/src/painting/transforms.dart new file mode 100644 index 00000000000..bc80bc204bb --- /dev/null +++ b/packages/flutter/lib/src/painting/transforms.dart @@ -0,0 +1,40 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:vector_math/vector_math_64.dart'; + +import 'basic_types.dart'; + +class MatrixUtils { + MatrixUtils._(); + + /// If the given transform is nothing but a 2D translation, then returns that + /// translation as an Offset. + /// + /// Otherwise, returns null. + static Offset getAsTranslation(Matrix4 transform) { + Float64List values = transform.storage; + // values are stored in column-major order + if (values[0] == 1.0 && + values[1] == 0.0 && + values[2] == 0.0 && + values[3] == 0.0 && + values[4] == 0.0 && + values[5] == 1.0 && + values[6] == 0.0 && + values[7] == 0.0 && + values[8] == 0.0 && + values[9] == 0.0 && + values[10] == 1.0 && + values[11] == 0.0 && + values[14] == 0.0 && + values[15] == 1.0) { + return new Offset(values[12], values[13]); + } + return null; + } + +} \ No newline at end of file diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index e4948fb48db..78c3ca468bd 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -865,8 +865,14 @@ class RenderTransform extends RenderProxyBox { } void paint(PaintingContext context, Offset offset) { - if (child != null) - context.pushTransform(needsCompositing, offset, _effectiveTransform, super.paint); + if (child != null) { + Matrix4 transform = _effectiveTransform; + Offset childOffset = MatrixUtils.getAsTranslation(transform); + if (childOffset == null) + context.pushTransform(needsCompositing, offset, transform, super.paint); + else + super.paint(context, offset + childOffset); + } } void applyPaintTransform(Matrix4 transform) { diff --git a/packages/unit/test/painting/transform_utilities_test.dart b/packages/unit/test/painting/transform_utilities_test.dart new file mode 100644 index 00000000000..53a76a6cec0 --- /dev/null +++ b/packages/unit/test/painting/transform_utilities_test.dart @@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/painting.dart'; +import 'package:test/test.dart'; +import 'package:vector_math/vector_math_64.dart'; + +void main() { + test("MatrixUtils.getAsTranslation()", () { + Matrix4 test; + test = new Matrix4.identity(); + expect(MatrixUtils.getAsTranslation(test), equals(Offset.zero)); + test = new Matrix4.zero(); + expect(MatrixUtils.getAsTranslation(test), isNull); + test = new Matrix4.rotationX(1.0); + expect(MatrixUtils.getAsTranslation(test), isNull); + test = new Matrix4.rotationZ(1.0); + expect(MatrixUtils.getAsTranslation(test), isNull); + test = new Matrix4.translationValues(1.0, 2.0, 0.0); + expect(MatrixUtils.getAsTranslation(test), equals(const Offset(1.0, 2.0))); + test = new Matrix4.translationValues(1.0, 2.0, 3.0); + expect(MatrixUtils.getAsTranslation(test), isNull); + + test = new Matrix4.identity(); + expect(MatrixUtils.getAsTranslation(test), equals(Offset.zero)); + test.rotateX(2.0); + expect(MatrixUtils.getAsTranslation(test), isNull); + + test = new Matrix4.identity(); + expect(MatrixUtils.getAsTranslation(test), equals(Offset.zero)); + test.scale(2.0); + expect(MatrixUtils.getAsTranslation(test), isNull); + + test = new Matrix4.identity(); + expect(MatrixUtils.getAsTranslation(test), equals(Offset.zero)); + test.translate(2.0, -2.0); + expect(MatrixUtils.getAsTranslation(test), equals(const Offset(2.0, -2.0))); + test.translate(4.0, 8.0); + expect(MatrixUtils.getAsTranslation(test), equals(const Offset(6.0, 6.0))); + }); +}