mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
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:
parent
eba2d44f3a
commit
cdc2aefc69
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
49
packages/flutter/test/painting/paint_image_test.dart
Normal file
49
packages/flutter/test/painting/paint_image_test.dart
Normal 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)));
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue