Commit d15907b5 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Uniform rectangular borders were drawing in the wrong place. (#12179)

I inflated instead of deflating. Oops.
parent 1a62c28b
......@@ -398,7 +398,7 @@ class Border {
..color = top.color
..strokeWidth = width
..style = PaintingStyle.stroke;
canvas.drawRect(rect.inflate(width / 2.0), paint);
canvas.drawRect(rect.deflate(width / 2.0), paint);
}
@override
......
......@@ -176,6 +176,24 @@ abstract class PaintPattern {
/// arguments as they were seen by the method.
void rrect({ RRect rrect, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style });
/// Indicates that a rounded rectangle outline is expected next.
///
/// The next call to [Canvas.drawRRect] is examined. Any arguments that are
/// passed to this method are compared to the actual [Canvas.drawRRect] call's
/// arguments and any mismatches result in failure.
///
/// If no call to [Canvas.drawRRect] was made, then this results in failure.
///
/// Any calls made between the last matched call (if any) and the
/// [Canvas.drawRRect] call are ignored.
///
/// The [Paint]-related arguments (`color`, `strokeWidth`, `hasMaskFilter`,
/// `style`) are compared against the state of the [Paint] object after the
/// painting has completed, not at the time of the call. If the same [Paint]
/// object is reused multiple times, then this may not match the actual
/// arguments as they were seen by the method.
void drrect({ RRect outer, RRect inner, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style });
/// Indicates that a circle is expected next.
///
/// The next circle is examined. Any arguments that are passed to this method
......@@ -424,6 +442,11 @@ class _TestRecordingCanvasPatternMatcher extends _TestRecordingCanvasMatcher imp
_predicates.add(new _RRectPaintPredicate(rrect: rrect, color: color, strokeWidth: strokeWidth, hasMaskFilter: hasMaskFilter, style: style));
}
@override
void drrect({ RRect outer, RRect inner, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) {
_predicates.add(new _DRRectPaintPredicate(outer: outer, inner: inner, color: color, strokeWidth: strokeWidth, hasMaskFilter: hasMaskFilter, style: style));
}
@override
void circle({ double x, double y, double radius, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) {
_predicates.add(new _CirclePaintPredicate(x: x, y: y, radius: radius, color: color, strokeWidth: strokeWidth, hasMaskFilter: hasMaskFilter, style: style));
......@@ -631,6 +654,51 @@ class _OneParameterPaintPredicate<T> extends _DrawCommandPaintPredicate {
}
}
class _TwoParameterPaintPredicate<T1, T2> extends _DrawCommandPaintPredicate {
_TwoParameterPaintPredicate(Symbol symbol, String name, {
@required this.expected1,
@required this.expected2,
@required Color color,
@required double strokeWidth,
@required bool hasMaskFilter,
@required PaintingStyle style
}) : super(
symbol, name, 3, 2, color: color, strokeWidth: strokeWidth, hasMaskFilter: hasMaskFilter, style: style);
final T1 expected1;
final T2 expected2;
@override
void verifyArguments(List<dynamic> arguments) {
super.verifyArguments(arguments);
final T1 actual1 = arguments[0];
if (expected1 != null && actual1 != expected1)
throw 'It called $methodName with its first argument (a $T1), $actual1, which was not exactly the expected $T1 ($expected1).';
final T2 actual2 = arguments[1];
if (expected2 != null && actual2 != expected2)
throw 'It called $methodName with its second argument (a $T2), $actual2, which was not exactly the expected $T2 ($expected2).';
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (expected1 != null) {
if (expected1.toString().contains(T1.toString())) {
description.add('$expected1');
} else {
description.add('$T1: $expected1');
}
}
if (expected2 != null) {
if (expected2.toString().contains(T2.toString())) {
description.add('$expected2');
} else {
description.add('$T2: $expected2');
}
}
}
}
class _RectPaintPredicate extends _OneParameterPaintPredicate<Rect> {
_RectPaintPredicate({ Rect rect, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) : super(
......@@ -656,6 +724,19 @@ class _RRectPaintPredicate extends _OneParameterPaintPredicate<RRect> {
);
}
class _DRRectPaintPredicate extends _TwoParameterPaintPredicate<RRect, RRect> {
_DRRectPaintPredicate({ RRect inner, RRect outer, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) : super(
#drawDRRect,
'a rounded rectangle outline',
expected1: outer,
expected2: inner,
color: color,
strokeWidth: strokeWidth,
hasMaskFilter: hasMaskFilter,
style: style,
);
}
class _CirclePaintPredicate extends _DrawCommandPaintPredicate {
_CirclePaintPredicate({ this.x, this.y, this.radius, Color color, double strokeWidth, bool hasMaskFilter, PaintingStyle style }) : super(
#drawCircle, 'a circle', 3, 2, color: color, strokeWidth: strokeWidth, hasMaskFilter: hasMaskFilter, style: style
......
......@@ -89,6 +89,99 @@ void main() {
..path()); // all appear to have the same settings here (that of the last call).
});
testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/12165
await tester.pumpWidget(
new Column(
children: <Widget>[
new Container(
// There's not currently a way to verify that this paints the same size as the others,
// so the pattern below just asserts that there's four paths but doesn't check the geometry.
width: 100.0,
height: 100.0,
decoration: const BoxDecoration(
border: const Border(
top: const BorderSide(
width: 10.0,
color: const Color(0xFFEEEEEE),
),
left: const BorderSide(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
right: const BorderSide(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
bottom: const BorderSide(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
),
),
),
new Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
border: new Border.all(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
),
),
new Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
border: new Border.all(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
borderRadius: const BorderRadius.only(
topRight: const Radius.circular(10.0),
),
),
),
new Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
border: new Border.all(
width: 10.0,
color: const Color(0xFFFFFFFF),
),
shape: BoxShape.circle,
),
),
],
),
);
expect(find.byType(Column), paints
..path()
..path()
..path()
..path()
..rect(rect: new Rect.fromLTRB(355.0, 105.0, 445.0, 195.0))
..drrect(
outer: new RRect.fromLTRBAndCorners(
350.0, 200.0, 450.0, 300.0,
topLeft: Radius.zero,
topRight: const Radius.circular(10.0),
bottomRight: Radius.zero,
bottomLeft: Radius.zero,
),
inner: new RRect.fromLTRBAndCorners(
360.0, 210.0, 440.0, 290.0,
topLeft: const Radius.circular(-10.0),
topRight: Radius.zero,
bottomRight: const Radius.circular(-10.0),
bottomLeft: const Radius.circular(-10.0),
),
)
..circle(x: 400.0, y: 350.0, radius: 45.0)
);
});
testWidgets('Can hit test on BoxDecoration', (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment