From cdc2aefc69cc7aecca2836ac4804ca2e077ff72d Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 8 Mar 2016 11:01:48 -0800 Subject: [PATCH] ImageFit.cover doesn't respect alignment We need to apply the alignment to the source rect because the ouput rect fills the destination rect. Fixes #1514 --- .../flutter/lib/src/painting/box_painter.dart | 20 ++++---- packages/flutter/lib/src/rendering/image.dart | 3 +- .../test/painting/paint_image_test.dart | 49 +++++++++++++++++++ 3 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 packages/flutter/test/painting/paint_image_test.dart diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index d833a3e61ae..440d9f9a103 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -492,8 +492,7 @@ void paintImage({ ImageFit fit, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, - double alignX, - double alignY + FractionalOffset alignment }) { assert(canvas != null); assert(image != null); @@ -508,6 +507,7 @@ void paintImage({ outputSize -= sliceBorder; inputSize -= sliceBorder; } + Point sourcePosition = Point.origin; Size sourceSize; Size destinationSize; fit ??= centerSlice == null ? ImageFit.scaleDown : ImageFit.fill; @@ -525,10 +525,13 @@ void paintImage({ destinationSize = new Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width); break; case ImageFit.cover: - if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) + if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) { sourceSize = new Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width); - else + sourcePosition = new Point(0.0, (inputSize.height - sourceSize.height) * (alignment?.dy ?? 0.5)); + } else { sourceSize = new Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height); + sourcePosition = new Point((inputSize.width - sourceSize.width) * (alignment?.dx ?? 0.5), 0.0); + } destinationSize = outputSize; break; case ImageFit.none: @@ -566,8 +569,8 @@ void paintImage({ // to nearest-neighbor. paint.filterQuality = FilterQuality.low; } - double dx = (outputSize.width - destinationSize.width) * (alignX ?? 0.5); - double dy = (outputSize.height - destinationSize.height) * (alignY ?? 0.5); + double dx = (outputSize.width - destinationSize.width) * (alignment?.dx ?? 0.5); + double dy = (outputSize.height - destinationSize.height) * (alignment?.dy ?? 0.5); Point destinationPosition = rect.topLeft + new Offset(dx, dy); Rect destinationRect = destinationPosition & destinationSize; if (repeat != ImageRepeat.noRepeat) { @@ -575,7 +578,7 @@ void paintImage({ canvas.clipRect(rect); } if (centerSlice == null) { - Rect sourceRect = Point.origin & sourceSize; + Rect sourceRect = sourcePosition & sourceSize; for (Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) canvas.drawImageRect(image, sourceRect, tileRect, paint); } else { @@ -1035,8 +1038,7 @@ class _BoxDecorationPainter extends BoxPainter { rect: rect, image: image, colorFilter: backgroundImage.colorFilter, - alignX: backgroundImage.alignment?.dx, - alignY: backgroundImage.alignment?.dy, + alignment: backgroundImage.alignment, fit: backgroundImage.fit, repeat: backgroundImage.repeat ); diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index e4306b7a68d..8ac1bfb85e4 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -242,8 +242,7 @@ class RenderImage extends RenderBox { image: _image, colorFilter: _colorFilter, fit: _fit, - alignX: _alignment?.dx, - alignY: _alignment?.dy, + alignment: _alignment, centerSlice: _centerSlice, repeat: _repeat ); diff --git a/packages/flutter/test/painting/paint_image_test.dart b/packages/flutter/test/painting/paint_image_test.dart new file mode 100644 index 00000000000..078d30e5220 --- /dev/null +++ b/packages/flutter/test/painting/paint_image_test.dart @@ -0,0 +1,49 @@ +// 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:ui' as ui; + +import 'package:flutter/painting.dart'; + +import 'package:test/test.dart'; + +class TestImage implements ui.Image { + TestImage({ this.width, this.height }); + + final int width; + final int height; + + void dispose() { } +} + +class TestCanvas implements Canvas { + final List invocations = []; + + void noSuchMethod(Invocation invocation) { + invocations.add(invocation); + } +} + +void main() { + test("Cover and align", () { + TestImage image = new TestImage(width: 300, height: 300); + TestCanvas canvas = new TestCanvas(); + paintImage( + canvas: canvas, + rect: new Rect.fromLTWH(50.0, 75.0, 200.0, 100.0), + image: image, + fit: ImageFit.cover, + alignment: new FractionalOffset(0.0, 0.5) + ); + + Invocation command = canvas.invocations.firstWhere((Invocation invocation) { + return invocation.memberName == #drawImageRect; + }); + + expect(command, isNotNull); + expect(command.positionalArguments[0], equals(image)); + expect(command.positionalArguments[1], equals(new Rect.fromLTWH(0.0, 75.0, 300.0, 150.0))); + expect(command.positionalArguments[2], equals(new Rect.fromLTWH(50.0, 75.0, 200.0, 100.0))); + }); +}