diff --git a/sky/engine/core/painting/Canvas.cpp b/sky/engine/core/painting/Canvas.cpp index f7deed3a27b0df8678ca4e074f8fd4aab536a9a9..4624833ca7fc5bcc93b6b25a4daa5f9fb0cec54a 100644 --- a/sky/engine/core/painting/Canvas.cpp +++ b/sky/engine/core/painting/Canvas.cpp @@ -190,6 +190,16 @@ void Canvas::drawRRect(const RRect* rrect, const Paint* paint) m_canvas->drawRRect(rrect->rrect(), paint->paint()); } +void Canvas::drawDRRect(const RRect* outer, const RRect* inner, const Paint* paint) +{ + if (!m_canvas) + return; + ASSERT(outer); + ASSERT(inner); + ASSERT(paint); + m_canvas->drawDRRect(outer->rrect(), inner->rrect(), paint->paint()); +} + void Canvas::drawOval(const Rect& rect, const Paint* paint) { if (!m_canvas) diff --git a/sky/engine/core/painting/Canvas.h b/sky/engine/core/painting/Canvas.h index 75a144bc4ec55812f58c56364b944218fea43ac9..e580725a7a45ee5b1dc0933ebbfd317a8b282993 100644 --- a/sky/engine/core/painting/Canvas.h +++ b/sky/engine/core/painting/Canvas.h @@ -81,6 +81,7 @@ public: void drawPaint(const Paint* paint); void drawRect(const Rect& rect, const Paint* paint); void drawRRect(const RRect* rrect, const Paint* paint); + void drawDRRect(const RRect* outer, const RRect* inner, const Paint* paint); void drawOval(const Rect& rect, const Paint* paint); void drawCircle(const Point& c, float radius, const Paint* paint); void drawPath(const CanvasPath* path, const Paint* paint); diff --git a/sky/engine/core/painting/Canvas.idl b/sky/engine/core/painting/Canvas.idl index 83f75743d9f60e214407a32e53f0480c890533e4..942dcaf03613c5bc790c14e79150b84ef894c6b4 100644 --- a/sky/engine/core/painting/Canvas.idl +++ b/sky/engine/core/painting/Canvas.idl @@ -29,6 +29,7 @@ void drawPaint(Paint paint); void drawRect(Rect rect, Paint paint); void drawRRect(RRect rrect, Paint paint); + void drawDRRect(RRect outer, RRect inner, Paint paint); void drawOval(Rect rect, Paint paint); void drawCircle(Point c, float radius, Paint paint); void drawPath(Path path, Paint paint); diff --git a/sky/engine/core/painting/Rect.dart b/sky/engine/core/painting/Rect.dart index 8a82e69a5666da44193f868ccba392882c6e41de..270e22fb4e0d9adcb62e5dbcd8d0287a38321ace 100644 --- a/sky/engine/core/painting/Rect.dart +++ b/sky/engine/core/painting/Rect.dart @@ -36,6 +36,9 @@ class Rect { Rect inflate(double delta) { return new Rect.fromLTRB(left - delta, top - delta, right + delta, bottom + delta); } + Rect deflate(double delta) { + return inflate(-delta); + } double get width => right - left; double get height => bottom - top; diff --git a/sky/packages/sky/example/widgets/block_viewport.dart b/sky/packages/sky/example/widgets/block_viewport.dart index cba6f19c69cf621c0c81c81dc85b47c368550e16..54c5ea7f197f6ac7e9b9cd022a32fee20cb2fd83 100644 --- a/sky/packages/sky/example/widgets/block_viewport.dart +++ b/sky/packages/sky/example/widgets/block_viewport.dart @@ -91,7 +91,7 @@ class BlockViewportApp extends App { child: new Container( margin: new EdgeDims.all(8.0), decoration: new BoxDecoration( - border: new Border.all(new BorderSide(color: new Color(0xFF000000))) + border: new Border.all(color: new Color(0xFF000000)) ), padding: new EdgeDims.all(16.0), child: new BlockViewport( diff --git a/sky/packages/sky/example/widgets/sector.dart b/sky/packages/sky/example/widgets/sector.dart index 8a5948d8ac532189ba6be21448879d0d650ac6ce..492e7430899a80a5f56a26624e1d75f368d2b7dd 100644 --- a/sky/packages/sky/example/widgets/sector.dart +++ b/sky/packages/sky/example/widgets/sector.dart @@ -114,7 +114,7 @@ class SectorApp extends App { child: new Container( margin: new EdgeDims.all(8.0), decoration: new BoxDecoration( - border: new Border.all(new BorderSide(color: new Color(0xFF000000))) + border: new Border.all(color: new Color(0xFF000000)) ), padding: new EdgeDims.all(8.0), child: new WidgetToRenderBoxAdapter(sectors) diff --git a/sky/packages/sky/lib/painting/box_painter.dart b/sky/packages/sky/lib/painting/box_painter.dart index 33039ca75c1f2571b3ebb46c6f30e9fb2630325f..1bec305d844ba4b96541876d69f29ad487c9e9d0 100644 --- a/sky/packages/sky/lib/painting/box_painter.dart +++ b/sky/packages/sky/lib/painting/box_painter.dart @@ -37,11 +37,13 @@ class Border { this.left: BorderSide.none }); - const Border.all(BorderSide side) : - top = side, - right = side, - bottom = side, - left = side; + factory Border.all({ + Color color: const Color(0xFF000000), + double width: 1.0 + }) { + BorderSide side = new BorderSide(color: color, width: width); + return new Border(top: side, right: side, bottom: side, left: side); + } final BorderSide top; final BorderSide right; @@ -323,6 +325,25 @@ class BoxPainter { return _cachedBackgroundPaint; } + bool get _hasUniformBorder { + Color color = _decoration.border.top.color; + bool hasUniformColor = + _decoration.border.right.color == color && + _decoration.border.bottom.color == color && + _decoration.border.left.color == color; + + if (!hasUniformColor) + return false; + + double width = _decoration.border.top.width; + bool hasUniformWidth = + _decoration.border.right.width == width && + _decoration.border.bottom.width == width && + _decoration.border.left.width == width; + + return hasUniformWidth; + } + void _paintBackgroundColor(sky.Canvas canvas, Rect rect) { if (_decoration.backgroundColor != null || _decoration.boxShadow != null || _decoration.gradient != null) { @@ -397,8 +418,13 @@ class BoxPainter { if (_decoration.border == null) return; - assert(_decoration.borderRadius == null); // TODO(abarth): Implement borders with border radius. - assert(_decoration.shape == Shape.rectangle); // TODO(ianh): Implement borders on circles. + if (_hasUniformBorder && _decoration.borderRadius != null) { + _paintBorderWithRadius(canvas, rect); + return; + } + + assert(_decoration.borderRadius == null); // TODO(abarth): Support non-uniform rounded borders. + assert(_decoration.shape == Shape.rectangle); // TODO(ianh): Support borders on circles. assert(_decoration.border.top != null); assert(_decoration.border.right != null); @@ -445,6 +471,17 @@ class BoxPainter { canvas.drawPath(path, paint); } + void _paintBorderWithRadius(sky.Canvas canvas, Rect rect) { + assert(_hasUniformBorder); + Color color = _decoration.border.top.color; + double width = _decoration.border.top.width; + double radius = _decoration.borderRadius; + + sky.RRect outer = new sky.RRect()..setRectXY(rect, radius, radius); + sky.RRect inner = new sky.RRect()..setRectXY(rect.deflate(width), radius - width, radius - width); + canvas.drawDRRect(outer, inner, new Paint()..color = color); + } + void paint(sky.Canvas canvas, Rect rect) { _paintBackgroundColor(canvas, rect); _paintBackgroundImage(canvas, rect); diff --git a/sky/tests/resources/display_list.dart b/sky/tests/resources/display_list.dart index 41517b9d39710eb7df43bb193c3769557030fcc5..6bd3e67b4c89e6fe51333af47997484f342ce447 100644 --- a/sky/tests/resources/display_list.dart +++ b/sky/tests/resources/display_list.dart @@ -90,6 +90,10 @@ class TestPaintingCanvas extends PaintingCanvas { log("drawRRect($rrect, $paint)"); } + void drawDRRect(sky.RRect outer, sky.RRect inner, Paint paint) { + log("drawDRRect($outer, $inner, $paint)"); + } + void drawOval(Rect rect, Paint paint) { log("drawOval($rect, $paint)"); } diff --git a/sky/tests/widgets/rounded_border-expected.txt b/sky/tests/widgets/rounded_border-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..643038852bccc8b44cfe2d5fc6254d40388d62b4 --- /dev/null +++ b/sky/tests/widgets/rounded_border-expected.txt @@ -0,0 +1,18 @@ +TestRenderView enabled + +PAINT FOR FRAME #1 ---------------------------------------------- +1 | TestPaintingCanvas() constructor: 800.0 x 600.0 +------------------------------------------------------------------------ + +PAINT FOR FRAME #2 ---------------------------------------------- +2 | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | paintChild RenderPositionedBox at Point(0.0, 0.0) +2 | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | paintChild RenderConstrainedBox at Point(350.0, 250.0) +2 | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | paintChild RenderDecoratedBox at Point(350.0, 250.0) +2 | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | drawRRect(Instance of 'RRect', Paint(color:Color(0xff0000ff))) +2 | | | | drawDRRect(Instance of 'RRect', Instance of 'RRect', Paint(color:Color(0x7fff0000))) +------------------------------------------------------------------------ +PAINTED 2 FRAMES diff --git a/sky/tests/widgets/rounded_border.dart b/sky/tests/widgets/rounded_border.dart new file mode 100644 index 0000000000000000000000000000000000000000..c091d13eb1a63721ab640f14fa090befce4f51df --- /dev/null +++ b/sky/tests/widgets/rounded_border.dart @@ -0,0 +1,30 @@ +// 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 'package:sky/widgets/basic.dart'; + +import '../resources/display_list.dart'; + +main() async { + WidgetTester tester = new WidgetTester(); + + await tester.test(() { + return new Center( + child: new Container( + width: 100.0, + height: 100.0, + decoration: new BoxDecoration( + backgroundColor: new Color(0xFF0000FF), + borderRadius: 20.0, + border: new Border.all( + color: const Color(0x7FFF0000), + width: 10.0 + ) + ) + ) + ); + }); + + tester.endTest(); +}