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
This commit is contained in:
Adam Barth 2016-03-08 11:01:48 -08:00
parent eba2d44f3a
commit cdc2aefc69
3 changed files with 61 additions and 11 deletions

View file

@ -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
);

View file

@ -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
);

View file

@ -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<Invocation> invocations = <Invocation>[];
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)));
});
}