提交 a525f84b 编写于 作者: A Adam Barth

Merge pull request #672 from abarth/render_image_fit

Apply ImageFit and ImageRepeat to RenderImage
......@@ -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 BackgroundRepeat { repeat, repeatX, repeatY, noRepeat }
enum ImageFit { fill, contain, cover, none, scaleDown }
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';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册