mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #672 from abarth/render_image_fit
Apply ImageFit and ImageRepeat to RenderImage
This commit is contained in:
commit
39ca4fa1ce
@ -73,7 +73,7 @@ List<SkyDemo> demos = [
|
||||
decoration: new BoxDecoration(
|
||||
backgroundImage: new BackgroundImage(
|
||||
image: _bundle.loadImage('assets/stocks_thumbnail.png'),
|
||||
fit: BackgroundFit.cover
|
||||
fit: ImageFit.cover
|
||||
)
|
||||
)
|
||||
),
|
||||
@ -86,7 +86,7 @@ List<SkyDemo> demos = [
|
||||
decoration: new BoxDecoration(
|
||||
backgroundImage: new BackgroundImage(
|
||||
image: _bundle.loadImage('assets/game_thumbnail.png'),
|
||||
fit: BackgroundFit.cover
|
||||
fit: ImageFit.cover
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
@ -167,21 +167,77 @@ class RadialGradient extends Gradient {
|
||||
}
|
||||
}
|
||||
|
||||
enum BackgroundFit { fill, contain, cover, none, scaleDown }
|
||||
enum ImageFit { fill, contain, cover, none, scaleDown }
|
||||
|
||||
enum BackgroundRepeat { repeat, repeatX, repeatY, noRepeat }
|
||||
enum ImageRepeat { repeat, repeatX, repeatY, noRepeat }
|
||||
|
||||
void paintImage({
|
||||
sky.Canvas canvas,
|
||||
Rect rect,
|
||||
sky.Image image,
|
||||
sky.ColorFilter colorFilter,
|
||||
fit: ImageFit.scaleDown,
|
||||
repeat: ImageRepeat.noRepeat
|
||||
}) {
|
||||
Size bounds = rect.size;
|
||||
Size imageSize = new Size(image.width.toDouble(), image.height.toDouble());
|
||||
Size src;
|
||||
Size dst;
|
||||
switch(fit) {
|
||||
case ImageFit.fill:
|
||||
src = imageSize;
|
||||
dst = bounds;
|
||||
break;
|
||||
case ImageFit.contain:
|
||||
src = imageSize;
|
||||
if (bounds.width / bounds.height > src.width / src.height) {
|
||||
dst = new Size(bounds.width, src.height * bounds.width / src.width);
|
||||
} else {
|
||||
dst = new Size(src.width * bounds.height / src.height, bounds.height);
|
||||
}
|
||||
break;
|
||||
case ImageFit.cover:
|
||||
if (bounds.width / bounds.height > imageSize.width / imageSize.height) {
|
||||
src = new Size(imageSize.width, imageSize.width * bounds.height / bounds.width);
|
||||
} else {
|
||||
src = new Size(imageSize.height * bounds.width / bounds.height, imageSize.height);
|
||||
}
|
||||
dst = bounds;
|
||||
break;
|
||||
case ImageFit.none:
|
||||
src = new Size(math.min(imageSize.width, bounds.width),
|
||||
math.min(imageSize.height, bounds.height));
|
||||
dst = src;
|
||||
break;
|
||||
case ImageFit.scaleDown:
|
||||
src = imageSize;
|
||||
dst = bounds;
|
||||
if (src.height > dst.height) {
|
||||
dst = new Size(src.width * dst.height / src.height, src.height);
|
||||
}
|
||||
if (src.width > dst.width) {
|
||||
dst = new Size(dst.width, src.height * dst.width / src.width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO(abarth): Implement |repeat|.
|
||||
Paint paint = new Paint();
|
||||
if (colorFilter != null)
|
||||
paint.setColorFilter(colorFilter);
|
||||
canvas.drawImageRect(image, Point.origin & src, rect.topLeft & dst, paint);
|
||||
}
|
||||
|
||||
typedef void BackgroundImageChangeListener();
|
||||
|
||||
class BackgroundImage {
|
||||
final BackgroundFit fit;
|
||||
final BackgroundRepeat repeat;
|
||||
final ImageFit fit;
|
||||
final ImageRepeat repeat;
|
||||
final sky.ColorFilter colorFilter;
|
||||
|
||||
BackgroundImage({
|
||||
ImageResource image,
|
||||
this.fit: BackgroundFit.scaleDown,
|
||||
this.repeat: BackgroundRepeat.noRepeat,
|
||||
this.fit: ImageFit.scaleDown,
|
||||
this.repeat: ImageRepeat.noRepeat,
|
||||
this.colorFilter
|
||||
}) : _imageResource = image;
|
||||
|
||||
@ -189,7 +245,6 @@ class BackgroundImage {
|
||||
sky.Image get image => _image;
|
||||
|
||||
ImageResource _imageResource;
|
||||
Size _size;
|
||||
|
||||
final List<BackgroundImageChangeListener> _listeners =
|
||||
new List<BackgroundImageChangeListener>();
|
||||
@ -215,7 +270,6 @@ class BackgroundImage {
|
||||
if (resolvedImage == null)
|
||||
return;
|
||||
_image = resolvedImage;
|
||||
_size = new Size(resolvedImage.width.toDouble(), resolvedImage.height.toDouble());
|
||||
final List<BackgroundImageChangeListener> localListeners =
|
||||
new List<BackgroundImageChangeListener>.from(_listeners);
|
||||
for (BackgroundImageChangeListener listener in localListeners) {
|
||||
@ -386,53 +440,16 @@ class BoxPainter {
|
||||
if (backgroundImage == null)
|
||||
return;
|
||||
sky.Image image = backgroundImage.image;
|
||||
if (image != null) {
|
||||
Size bounds = rect.size;
|
||||
Size imageSize = backgroundImage._size;
|
||||
Size src;
|
||||
Size dst;
|
||||
switch(backgroundImage.fit) {
|
||||
case BackgroundFit.fill:
|
||||
src = imageSize;
|
||||
dst = bounds;
|
||||
break;
|
||||
case BackgroundFit.contain:
|
||||
src = imageSize;
|
||||
if (bounds.width / bounds.height > src.width / src.height) {
|
||||
dst = new Size(bounds.width, src.height * bounds.width / src.width);
|
||||
} else {
|
||||
dst = new Size(src.width * bounds.height / src.height, bounds.height);
|
||||
}
|
||||
break;
|
||||
case BackgroundFit.cover:
|
||||
if (bounds.width / bounds.height > imageSize.width / imageSize.height) {
|
||||
src = new Size(imageSize.width, imageSize.width * bounds.height / bounds.width);
|
||||
} else {
|
||||
src = new Size(imageSize.height * bounds.width / bounds.height, imageSize.height);
|
||||
}
|
||||
dst = bounds;
|
||||
break;
|
||||
case BackgroundFit.none:
|
||||
src = new Size(math.min(imageSize.width, bounds.width),
|
||||
math.min(imageSize.height, bounds.height));
|
||||
dst = src;
|
||||
break;
|
||||
case BackgroundFit.scaleDown:
|
||||
src = imageSize;
|
||||
dst = bounds;
|
||||
if (src.height > dst.height) {
|
||||
dst = new Size(src.width * dst.height / src.height, src.height);
|
||||
}
|
||||
if (src.width > dst.width) {
|
||||
dst = new Size(dst.width, src.height * dst.width / src.width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Paint paint = new Paint();
|
||||
if (backgroundImage.colorFilter != null)
|
||||
paint.setColorFilter(backgroundImage.colorFilter);
|
||||
canvas.drawImageRect(image, Point.origin & src, rect.topLeft & dst, paint);
|
||||
}
|
||||
if (image == null)
|
||||
return;
|
||||
paintImage(
|
||||
canvas: canvas,
|
||||
rect: rect,
|
||||
image: image,
|
||||
colorFilter: backgroundImage.colorFilter,
|
||||
fit: backgroundImage.fit,
|
||||
repeat: backgroundImage.repeat
|
||||
);
|
||||
}
|
||||
|
||||
void _paintBorder(sky.Canvas canvas, Rect rect) {
|
||||
|
||||
@ -1324,12 +1324,19 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
|
||||
}
|
||||
|
||||
class RenderImage extends RenderBox {
|
||||
|
||||
RenderImage({ sky.Image image, double width, double height, sky.ColorFilter colorFilter })
|
||||
: _image = image,
|
||||
RenderImage({
|
||||
sky.Image image,
|
||||
double width,
|
||||
double height,
|
||||
sky.ColorFilter colorFilter,
|
||||
fit: ImageFit.scaleDown,
|
||||
repeat: ImageRepeat.noRepeat
|
||||
}) : _image = image,
|
||||
_width = width,
|
||||
_height = height,
|
||||
_colorFilter = colorFilter;
|
||||
_colorFilter = colorFilter,
|
||||
_fit = fit,
|
||||
_repeat = repeat;
|
||||
|
||||
sky.Image _image;
|
||||
sky.Image get image => _image;
|
||||
@ -1366,18 +1373,25 @@ class RenderImage extends RenderBox {
|
||||
if (value == _colorFilter)
|
||||
return;
|
||||
_colorFilter = value;
|
||||
_cachedPaint = null;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Paint _cachedPaint;
|
||||
Paint get _paint {
|
||||
if (_cachedPaint == null) {
|
||||
_cachedPaint = new Paint();
|
||||
if (colorFilter != null)
|
||||
_cachedPaint.setColorFilter(colorFilter);
|
||||
}
|
||||
return _cachedPaint;
|
||||
ImageFit _fit;
|
||||
ImageFit get fit => _fit;
|
||||
void set fit (ImageFit value) {
|
||||
if (value == _fit)
|
||||
return;
|
||||
_fit = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
ImageRepeat _repeat;
|
||||
ImageRepeat get repeat => _repeat;
|
||||
void set repeat (ImageRepeat value) {
|
||||
if (value == _repeat)
|
||||
return;
|
||||
_repeat = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Size _sizeForConstraints(BoxConstraints constraints) {
|
||||
@ -1452,19 +1466,14 @@ class RenderImage extends RenderBox {
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (_image == null)
|
||||
return;
|
||||
bool needsScale = size.width != _image.width || size.height != _image.height;
|
||||
final PaintingCanvas canvas = context.canvas;
|
||||
if (needsScale) {
|
||||
double widthScale = size.width / _image.width;
|
||||
double heightScale = size.height / _image.height;
|
||||
canvas.save();
|
||||
canvas.translate(offset.dx, offset.dy);
|
||||
canvas.scale(widthScale, heightScale);
|
||||
offset = Offset.zero;
|
||||
}
|
||||
canvas.drawImage(_image, offset.toPoint(), _paint);
|
||||
if (needsScale)
|
||||
canvas.restore();
|
||||
paintImage(
|
||||
canvas: context.canvas,
|
||||
rect: offset & size,
|
||||
image: _image,
|
||||
colorFilter: _colorFilter,
|
||||
fit: _fit,
|
||||
repeat: _repeat
|
||||
);
|
||||
}
|
||||
|
||||
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}width: ${width}\n${prefix}height: ${height}\n';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user