Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Unified Diff: sky/sdk/lib/painting/box_painter.dart

Issue 1217623002: Support for background images on cards, style demo home (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/sdk/home.dart ('k') | sky/sdk/lib/rendering/box.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/sdk/lib/painting/box_painter.dart
diff --git a/sky/sdk/lib/painting/box_painter.dart b/sky/sdk/lib/painting/box_painter.dart
index e77d7b9ac3884bc60d9440cab6c42b301e957d70..6f3a9d6e4995a4720473d53c84ac01c96d20af4e 100644
--- a/sky/sdk/lib/painting/box_painter.dart
+++ b/sky/sdk/lib/painting/box_painter.dart
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dart:math' as math;
import 'dart:sky' as sky;
import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
import 'shadows.dart';
+import 'package:sky/mojo/net/image_cache.dart' as image_cache;
class BorderSide {
const BorderSide({
@@ -120,12 +122,60 @@ class RadialGradient extends Gradient {
final sky.TileMode tileMode;
}
+enum BackgroundFit { fill, contain, cover, none, scaleDown }
+
+enum BackgroundRepeat { repeat, repeatX, repeatY, noRepeat }
+
+// TODO(jackson): We should abstract this out into a separate class
+// that handles the image caching and so forth, which has callbacks
+// for "size changed" and "image changed". This would also enable us
+// to do animated images.
+
+class BackgroundImage {
+ final String src;
+ final BackgroundFit fit;
+ final BackgroundRepeat repeat;
+ BackgroundImage({
+ this.src,
+ this.fit: BackgroundFit.scaleDown,
+ this.repeat: BackgroundRepeat.noRepeat
+ }) {
+ image_cache.load(src, (image) {
+ if (image == null)
+ return;
+ _image = image;
+ _size = new Size(image.width.toDouble(), image.height.toDouble());
+ for (Function listener in _listeners) {
+ listener();
+ }
+ });
+ }
+
+ sky.Image _image;
+ sky.Image get image => _image;
+
+ Size _size;
+
+ final List<Function> _listeners = new List<Function>();
+
+ void addChangeListener(Function listener) {
+ _listeners.add(listener);
+ }
+
+ void removeChangeListener(Function listener) {
+ _listeners.remove(listener);
+ }
+
+ String toString() => 'BackgroundImage($src, $fit, $repeat)';
+}
+
enum Shape { rectangle, circle }
// This must be immutable, because we won't notice when it changes
class BoxDecoration {
const BoxDecoration({
- this.backgroundColor, // null = don't draw background
+ this.backgroundColor, // null = don't draw background color
+ this.backgroundImage, // null = don't draw background image
this.border, // null = don't draw border
this.borderRadius, // null = use more efficient background drawing; note that this must be null for circles
this.boxShadow, // null = don't draw shadows
@@ -134,6 +184,7 @@ class BoxDecoration {
});
final Color backgroundColor;
+ final BackgroundImage backgroundImage;
final double borderRadius;
final Border border;
final List<BoxShadow> boxShadow;
@@ -144,6 +195,8 @@ class BoxDecoration {
List<String> result = [];
if (backgroundColor != null)
result.add('${prefix}backgroundColor: $backgroundColor');
+ if (backgroundImage != null)
+ result.add('${prefix}backgroundImage: $backgroundImage');
if (border != null)
result.add('${prefix}border: $border');
if (borderRadius != null)
@@ -199,7 +252,7 @@ class BoxPainter {
return _cachedBackgroundPaint;
}
- void paint(sky.Canvas canvas, Rect rect) {
+ void _paintBackgroundColor(sky.Canvas canvas, Rect rect) {
if (_decoration.backgroundColor != null || _decoration.boxShadow != null ||
_decoration.gradient != null) {
switch (_decoration.shape) {
@@ -217,54 +270,113 @@ class BoxPainter {
break;
}
}
+ }
- if (_decoration.border != null) {
- assert(_decoration.borderRadius == null); // TODO(abarth): Implement borders with border radius.
- assert(_decoration.shape == Shape.rectangle); // TODO(ianh): Implement borders on circles.
+ void _paintBackgroundImage(sky.Canvas canvas, Rect rect) {
+ if (_decoration.backgroundImage == null)
+ return;
+ sky.Image image = _decoration.backgroundImage.image;
+ if (image != null) {
+ Size bounds = rect.size;
+ Size imageSize = _decoration.backgroundImage._size;
+ Size src;
+ Size dst;
+ switch(_decoration.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;
+ }
+ canvas.drawImageRect(image, Point.origin & src, rect.topLeft & dst, new Paint());
+ }
+ }
- assert(_decoration.border.top != null);
- assert(_decoration.border.right != null);
- assert(_decoration.border.bottom != null);
- assert(_decoration.border.left != null);
+ void _paintBorder(sky.Canvas canvas, Rect rect) {
+ if (_decoration.border == null)
+ return;
- Paint paint = new Paint();
- Path path;
-
- paint.color = _decoration.border.top.color;
- path = new Path();
- path.moveTo(rect.left, rect.top);
- path.lineTo(rect.left + _decoration.border.left.width, rect.top + _decoration.border.top.width);
- path.lineTo(rect.right - _decoration.border.right.width, rect.top + _decoration.border.top.width);
- path.lineTo(rect.right, rect.top);
- path.close();
- canvas.drawPath(path, paint);
-
- paint.color = _decoration.border.right.color;
- path = new Path();
- path.moveTo(rect.right, rect.top);
- path.lineTo(rect.right - _decoration.border.right.width, rect.top + _decoration.border.top.width);
- path.lineTo(rect.right - _decoration.border.right.width, rect.bottom - _decoration.border.bottom.width);
- path.lineTo(rect.right, rect.bottom);
- path.close();
- canvas.drawPath(path, paint);
-
- paint.color = _decoration.border.bottom.color;
- path = new Path();
- path.moveTo(rect.right, rect.bottom);
- path.lineTo(rect.right - _decoration.border.right.width, rect.bottom - _decoration.border.bottom.width);
- path.lineTo(rect.left + _decoration.border.left.width, rect.bottom - _decoration.border.bottom.width);
- path.lineTo(rect.left, rect.bottom);
- path.close();
- canvas.drawPath(path, paint);
-
- paint.color = _decoration.border.left.color;
- path = new Path();
- path.moveTo(rect.left, rect.bottom);
- path.lineTo(rect.left + _decoration.border.left.width, rect.bottom - _decoration.border.bottom.width);
- path.lineTo(rect.left + _decoration.border.left.width, rect.top + _decoration.border.top.width);
- path.lineTo(rect.left, rect.top);
- path.close();
- canvas.drawPath(path, paint);
- }
+ assert(_decoration.borderRadius == null); // TODO(abarth): Implement borders with border radius.
+ assert(_decoration.shape == Shape.rectangle); // TODO(ianh): Implement borders on circles.
+
+ assert(_decoration.border.top != null);
+ assert(_decoration.border.right != null);
+ assert(_decoration.border.bottom != null);
+ assert(_decoration.border.left != null);
+
+ Paint paint = new Paint();
+ Path path;
+
+ paint.color = _decoration.border.top.color;
+ path = new Path();
+ path.moveTo(rect.left, rect.top);
+ path.lineTo(rect.left + _decoration.border.left.width, rect.top + _decoration.border.top.width);
+ path.lineTo(rect.right - _decoration.border.right.width, rect.top + _decoration.border.top.width);
+ path.lineTo(rect.right, rect.top);
+ path.close();
+ canvas.drawPath(path, paint);
+
+ paint.color = _decoration.border.right.color;
+ path = new Path();
+ path.moveTo(rect.right, rect.top);
+ path.lineTo(rect.right - _decoration.border.right.width, rect.top + _decoration.border.top.width);
+ path.lineTo(rect.right - _decoration.border.right.width, rect.bottom - _decoration.border.bottom.width);
+ path.lineTo(rect.right, rect.bottom);
+ path.close();
+ canvas.drawPath(path, paint);
+
+ paint.color = _decoration.border.bottom.color;
+ path = new Path();
+ path.moveTo(rect.right, rect.bottom);
+ path.lineTo(rect.right - _decoration.border.right.width, rect.bottom - _decoration.border.bottom.width);
+ path.lineTo(rect.left + _decoration.border.left.width, rect.bottom - _decoration.border.bottom.width);
+ path.lineTo(rect.left, rect.bottom);
+ path.close();
+ canvas.drawPath(path, paint);
+
+ paint.color = _decoration.border.left.color;
+ path = new Path();
+ path.moveTo(rect.left, rect.bottom);
+ path.lineTo(rect.left + _decoration.border.left.width, rect.bottom - _decoration.border.bottom.width);
+ path.lineTo(rect.left + _decoration.border.left.width, rect.top + _decoration.border.top.width);
+ path.lineTo(rect.left, rect.top);
+ path.close();
+ canvas.drawPath(path, paint);
+ }
+
+ void paint(sky.Canvas canvas, Rect rect) {
+ _paintBackgroundColor(canvas, rect);
+ _paintBackgroundImage(canvas, rect);
+ _paintBorder(canvas, rect);
}
}
« no previous file with comments | « sky/sdk/home.dart ('k') | sky/sdk/lib/rendering/box.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698