Unverified Commit 9ffa1c51 authored by liyuqian's avatar liyuqian Committed by GitHub

Add Clip enum to Material and related widgets (#18576)

See details in our proposal for this breaking API change and #18057. This PR setup all code paths to allow the change but doesn't change the clip behavior by itself. We'll change `defaultClipBehavior` from `Clip.antiAlias` to `Clip.none` in the following PR to change the clip behavior and update tests.
parent ad163749
...@@ -28,6 +28,7 @@ export 'src/painting/box_decoration.dart'; ...@@ -28,6 +28,7 @@ export 'src/painting/box_decoration.dart';
export 'src/painting/box_fit.dart'; export 'src/painting/box_fit.dart';
export 'src/painting/box_shadow.dart'; export 'src/painting/box_shadow.dart';
export 'src/painting/circle_border.dart'; export 'src/painting/circle_border.dart';
export 'src/painting/clip.dart';
export 'src/painting/colors.dart'; export 'src/painting/colors.dart';
export 'src/painting/debug.dart'; export 'src/painting/debug.dart';
export 'src/painting/decoration.dart'; export 'src/painting/decoration.dart';
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' show Clip, defaultClipBehavior; // ignore: deprecated_member_use
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -87,8 +89,9 @@ abstract class MaterialInkController { ...@@ -87,8 +89,9 @@ abstract class MaterialInkController {
/// ///
/// The Material widget is responsible for: /// The Material widget is responsible for:
/// ///
/// 1. Clipping: Material clips its widget sub-tree to the shape specified by /// 1. Clipping: If [clipBehavior] is not [Clip.none], Material clips its widget
/// [shape], [type], and [borderRadius]. /// sub-tree to the shape specified by [shape], [type], and [borderRadius].
/// By default, [clipBehavior] is [Clip.none] for performance considerations.
/// 2. Elevation: Material elevates its widget sub-tree on the Z axis by /// 2. Elevation: Material elevates its widget sub-tree on the Z axis by
/// [elevation] pixels, and draws the appropriate shadow. /// [elevation] pixels, and draws the appropriate shadow.
/// 3. Ink effects: Material shows ink effects implemented by [InkFeature]s /// 3. Ink effects: Material shows ink effects implemented by [InkFeature]s
...@@ -171,6 +174,7 @@ class Material extends StatefulWidget { ...@@ -171,6 +174,7 @@ class Material extends StatefulWidget {
this.textStyle, this.textStyle,
this.borderRadius, this.borderRadius,
this.shape, this.shape,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
this.animationDuration = kThemeChangeDuration, this.animationDuration = kThemeChangeDuration,
this.child, this.child,
}) : assert(type != null), }) : assert(type != null),
...@@ -179,6 +183,7 @@ class Material extends StatefulWidget { ...@@ -179,6 +183,7 @@ class Material extends StatefulWidget {
assert(!(shape != null && borderRadius != null)), assert(!(shape != null && borderRadius != null)),
assert(animationDuration != null), assert(animationDuration != null),
assert(!(identical(type, MaterialType.circle) && (borderRadius != null || shape != null))), assert(!(identical(type, MaterialType.circle) && (borderRadius != null || shape != null))),
assert(clipBehavior != null),
super(key: key); super(key: key);
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
...@@ -226,6 +231,14 @@ class Material extends StatefulWidget { ...@@ -226,6 +231,14 @@ class Material extends StatefulWidget {
/// zero. /// zero.
final ShapeBorder shape; final ShapeBorder shape;
/// {@template flutter.widgets.Clip}
/// The content will be clipped (or not) according to this option.
///
/// See the enum [Clip] for details of all possible options and their common
/// use cases.
/// {@endtemplate}
final Clip clipBehavior;
/// Defines the duration of animated changes for [shape], [elevation], /// Defines the duration of animated changes for [shape], [elevation],
/// and [shadowColor]. /// and [shadowColor].
/// ///
...@@ -329,6 +342,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -329,6 +342,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
curve: Curves.fastOutSlowIn, curve: Curves.fastOutSlowIn,
duration: widget.animationDuration, duration: widget.animationDuration,
shape: BoxShape.rectangle, shape: BoxShape.rectangle,
clipBehavior: widget.clipBehavior,
borderRadius: BorderRadius.zero, borderRadius: BorderRadius.zero,
elevation: widget.elevation, elevation: widget.elevation,
color: backgroundColor, color: backgroundColor,
...@@ -341,12 +355,13 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -341,12 +355,13 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
final ShapeBorder shape = _getShape(); final ShapeBorder shape = _getShape();
if (widget.type == MaterialType.transparency) if (widget.type == MaterialType.transparency)
return _transparentInterior(shape: shape, contents: contents); return _transparentInterior(shape: shape, clipBehavior: widget.clipBehavior, contents: contents);
return new _MaterialInterior( return new _MaterialInterior(
curve: Curves.fastOutSlowIn, curve: Curves.fastOutSlowIn,
duration: widget.animationDuration, duration: widget.animationDuration,
shape: shape, shape: shape,
clipBehavior: widget.clipBehavior,
elevation: widget.elevation, elevation: widget.elevation,
color: backgroundColor, color: backgroundColor,
shadowColor: widget.shadowColor, shadowColor: widget.shadowColor,
...@@ -354,7 +369,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -354,7 +369,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
); );
} }
static Widget _transparentInterior({ShapeBorder shape, Widget contents}) { static Widget _transparentInterior({ShapeBorder shape, Clip clipBehavior, Widget contents}) {
return new ClipPath( return new ClipPath(
child: new _ShapeBorderPaint( child: new _ShapeBorderPaint(
child: contents, child: contents,
...@@ -363,6 +378,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -363,6 +378,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
clipper: new ShapeBorderClipper( clipper: new ShapeBorderClipper(
shape: shape, shape: shape,
), ),
clipBehavior: clipBehavior,
); );
} }
...@@ -582,6 +598,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget { ...@@ -582,6 +598,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
Key key, Key key,
@required this.child, @required this.child,
@required this.shape, @required this.shape,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
@required this.elevation, @required this.elevation,
@required this.color, @required this.color,
@required this.shadowColor, @required this.shadowColor,
...@@ -589,6 +606,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget { ...@@ -589,6 +606,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
@required Duration duration, @required Duration duration,
}) : assert(child != null), }) : assert(child != null),
assert(shape != null), assert(shape != null),
assert(clipBehavior != null),
assert(elevation != null), assert(elevation != null),
assert(color != null), assert(color != null),
assert(shadowColor != null), assert(shadowColor != null),
...@@ -605,6 +623,9 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget { ...@@ -605,6 +623,9 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
/// determines the physical shape. /// determines the physical shape.
final ShapeBorder shape; final ShapeBorder shape;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// The target z-coordinate at which to place this physical object. /// The target z-coordinate at which to place this physical object.
final double elevation; final double elevation;
...@@ -651,6 +672,7 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior> ...@@ -651,6 +672,7 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
shape: shape, shape: shape,
textDirection: Directionality.of(context) textDirection: Directionality.of(context)
), ),
clipBehavior: widget.clipBehavior,
elevation: _elevation.evaluate(animation), elevation: _elevation.evaluate(animation),
color: widget.color, color: widget.color,
shadowColor: _shadowColor.evaluate(animation), shadowColor: _shadowColor.evaluate(animation),
......
// Copyright 2018 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 'dart:ui' show Canvas, Clip, Path, Paint, Rect, RRect;
/// Clip utilities used by [PaintingContext] and [TestRecordingPaintingContext].
abstract class ClipContext {
/// The canvas on which to paint.
Canvas get canvas;
void _clipAndPaint(void canvasClipCall(bool doAntiAlias), Clip clipBehavior, Rect bounds, void painter()) {
assert(canvasClipCall != null);
canvas.save();
switch (clipBehavior) {
case Clip.none:
break;
case Clip.hardEdge:
canvasClipCall(false);
break;
case Clip.antiAlias:
canvasClipCall(true);
break;
case Clip.antiAliasWithSaveLayer:
canvasClipCall(true);
canvas.saveLayer(bounds, new Paint());
break;
}
painter();
if (clipBehavior == Clip.antiAliasWithSaveLayer) {
canvas.restore();
}
canvas.restore();
}
/// Clip [canvas] with [Path] according to [Clip] and then paint. [canvas] is
/// restored to the pre-clip status afterwards.
///
/// `bounds` is the saveLayer bounds used for [Clip.antiAliasWithSaveLayer].
void clipPathAndPaint(Path path, Clip clipBehavior, Rect bounds, void painter()) {
_clipAndPaint((bool doAntiAias) => canvas.clipPath(path, doAntiAlias: doAntiAias), clipBehavior, bounds, painter);
}
/// Clip [canvas] with [Path] according to [RRect] and then paint. [canvas] is
/// restored to the pre-clip status afterwards.
///
/// `bounds` is the saveLayer bounds used for [Clip.antiAliasWithSaveLayer].
void clipRRectAndPaint(RRect rrect, Clip clipBehavior, Rect bounds, void painter()) {
_clipAndPaint((bool doAntiAias) => canvas.clipRRect(rrect, doAntiAlias: doAntiAias), clipBehavior, bounds, painter);
}
/// Clip [canvas] with [Path] according to [Rect] and then paint. [canvas] is
/// restored to the pre-clip status afterwards.
///
/// `bounds` is the saveLayer bounds used for [Clip.antiAliasWithSaveLayer].
void clipRectAndPaint(Rect rect, Clip clipBehavior, Rect bounds, void painter()) {
_clipAndPaint((bool doAntiAias) => canvas.clipRect(rect, doAntiAlias: doAntiAias), clipBehavior, bounds, painter);
}
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'dart:ui' as ui show Image, ImageFilter, Picture, Scene, SceneBuilder; import 'dart:ui' as ui show Image, ImageFilter, Picture, Scene, SceneBuilder;
import 'dart:ui' show Offset; import 'dart:ui' show Clip, Offset, defaultClipBehavior; // ignore: deprecated_member_use
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
...@@ -605,7 +605,8 @@ class ClipRectLayer extends ContainerLayer { ...@@ -605,7 +605,8 @@ class ClipRectLayer extends ContainerLayer {
/// ///
/// The [clipRect] property must be non-null before the compositing phase of /// The [clipRect] property must be non-null before the compositing phase of
/// the pipeline. /// the pipeline.
ClipRectLayer({ this.clipRect }); ClipRectLayer({ this.clipRect, Clip clipBehavior = Clip.antiAlias }) :
_clipBehavior = clipBehavior, assert(clipBehavior != null), assert(clipBehavior != Clip.none);
/// The rectangle to clip in the parent's coordinate system. /// The rectangle to clip in the parent's coordinate system.
/// ///
...@@ -613,6 +614,15 @@ class ClipRectLayer extends ContainerLayer { ...@@ -613,6 +614,15 @@ class ClipRectLayer extends ContainerLayer {
/// (as described at [Layer]). /// (as described at [Layer]).
Rect clipRect; Rect clipRect;
/// {@macro flutter.clipper.clipBehavior}
Clip get clipBehavior => _clipBehavior;
Clip _clipBehavior;
set clipBehavior(Clip value) {
assert(value != null);
assert(value != Clip.none);
_clipBehavior = value;
}
@override @override
S find<S>(Offset regionOffset) { S find<S>(Offset regionOffset) {
if (!clipRect.contains(regionOffset)) if (!clipRect.contains(regionOffset))
...@@ -628,7 +638,7 @@ class ClipRectLayer extends ContainerLayer { ...@@ -628,7 +638,7 @@ class ClipRectLayer extends ContainerLayer {
return true; return true;
}()); }());
if (enabled) if (enabled)
builder.pushClipRect(clipRect.shift(layerOffset)); builder.pushClipRect(clipRect.shift(layerOffset), clipBehavior: clipBehavior);
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
if (enabled) if (enabled)
builder.pop(); builder.pop();
...@@ -651,7 +661,8 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -651,7 +661,8 @@ class ClipRRectLayer extends ContainerLayer {
/// ///
/// The [clipRRect] property must be non-null before the compositing phase of /// The [clipRRect] property must be non-null before the compositing phase of
/// the pipeline. /// the pipeline.
ClipRRectLayer({ this.clipRRect }); ClipRRectLayer({ this.clipRRect, Clip clipBehavior = Clip.antiAlias }) :
_clipBehavior = clipBehavior, assert(clipBehavior != null), assert(clipBehavior != Clip.none);
/// The rounded-rect to clip in the parent's coordinate system. /// The rounded-rect to clip in the parent's coordinate system.
/// ///
...@@ -659,6 +670,15 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -659,6 +670,15 @@ class ClipRRectLayer extends ContainerLayer {
/// (as described at [Layer]). /// (as described at [Layer]).
RRect clipRRect; RRect clipRRect;
/// {@macro flutter.clipper.clipBehavior}
Clip get clipBehavior => _clipBehavior;
Clip _clipBehavior;
set clipBehavior(Clip value) {
assert(value != null);
assert(value != Clip.none);
_clipBehavior = value;
}
@override @override
S find<S>(Offset regionOffset) { S find<S>(Offset regionOffset) {
if (!clipRRect.contains(regionOffset)) if (!clipRRect.contains(regionOffset))
...@@ -674,7 +694,7 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -674,7 +694,7 @@ class ClipRRectLayer extends ContainerLayer {
return true; return true;
}()); }());
if (enabled) if (enabled)
builder.pushClipRRect(clipRRect.shift(layerOffset)); builder.pushClipRRect(clipRRect.shift(layerOffset), clipBehavior: clipBehavior);
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
if (enabled) if (enabled)
builder.pop(); builder.pop();
...@@ -697,7 +717,8 @@ class ClipPathLayer extends ContainerLayer { ...@@ -697,7 +717,8 @@ class ClipPathLayer extends ContainerLayer {
/// ///
/// The [clipPath] property must be non-null before the compositing phase of /// The [clipPath] property must be non-null before the compositing phase of
/// the pipeline. /// the pipeline.
ClipPathLayer({ this.clipPath }); ClipPathLayer({ this.clipPath, Clip clipBehavior = Clip.antiAlias }) :
_clipBehavior = clipBehavior, assert(clipBehavior != null), assert(clipBehavior != Clip.none);
/// The path to clip in the parent's coordinate system. /// The path to clip in the parent's coordinate system.
/// ///
...@@ -705,6 +726,15 @@ class ClipPathLayer extends ContainerLayer { ...@@ -705,6 +726,15 @@ class ClipPathLayer extends ContainerLayer {
/// (as described at [Layer]). /// (as described at [Layer]).
Path clipPath; Path clipPath;
/// {@macro flutter.clipper.clipBehavior}
Clip get clipBehavior => _clipBehavior;
Clip _clipBehavior;
set clipBehavior(Clip value) {
assert(value != null);
assert(value != Clip.none);
_clipBehavior = value;
}
@override @override
S find<S>(Offset regionOffset) { S find<S>(Offset regionOffset) {
if (!clipPath.contains(regionOffset)) if (!clipPath.contains(regionOffset))
...@@ -720,7 +750,7 @@ class ClipPathLayer extends ContainerLayer { ...@@ -720,7 +750,7 @@ class ClipPathLayer extends ContainerLayer {
return true; return true;
}()); }());
if (enabled) if (enabled)
builder.pushClipPath(clipPath.shift(layerOffset)); builder.pushClipPath(clipPath.shift(layerOffset), clipBehavior: clipBehavior);
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
if (enabled) if (enabled)
builder.pop(); builder.pop();
...@@ -925,10 +955,12 @@ class PhysicalModelLayer extends ContainerLayer { ...@@ -925,10 +955,12 @@ class PhysicalModelLayer extends ContainerLayer {
/// The [clipPath], [elevation], and [color] arguments must not be null. /// The [clipPath], [elevation], and [color] arguments must not be null.
PhysicalModelLayer({ PhysicalModelLayer({
@required this.clipPath, @required this.clipPath,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
@required this.elevation, @required this.elevation,
@required this.color, @required this.color,
@required this.shadowColor, @required this.shadowColor,
}) : assert(clipPath != null), }) : assert(clipPath != null),
assert(clipBehavior != null),
assert(elevation != null), assert(elevation != null),
assert(color != null), assert(color != null),
assert(shadowColor != null); assert(shadowColor != null);
...@@ -939,6 +971,9 @@ class PhysicalModelLayer extends ContainerLayer { ...@@ -939,6 +971,9 @@ class PhysicalModelLayer extends ContainerLayer {
/// (as described at [Layer]). /// (as described at [Layer]).
Path clipPath; Path clipPath;
/// {@macro flutter.widgets.Clip}
Clip clipBehavior;
/// The z-coordinate at which to place this physical object. /// The z-coordinate at which to place this physical object.
/// ///
/// The scene must be explicitly recomposited after this property is changed /// The scene must be explicitly recomposited after this property is changed
...@@ -980,6 +1015,7 @@ class PhysicalModelLayer extends ContainerLayer { ...@@ -980,6 +1015,7 @@ class PhysicalModelLayer extends ContainerLayer {
elevation: elevation, elevation: elevation,
color: color, color: color,
shadowColor: shadowColor, shadowColor: shadowColor,
clipBehavior: clipBehavior,
); );
} }
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:developer'; import 'dart:developer';
import 'dart:ui' as ui show PictureRecorder; import 'dart:ui' as ui show PictureRecorder;
import 'dart:ui' show Clip;
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -59,7 +60,7 @@ typedef void PaintingContextCallback(PaintingContext context, Offset offset); ...@@ -59,7 +60,7 @@ typedef void PaintingContextCallback(PaintingContext context, Offset offset);
/// ///
/// New [PaintingContext] objects are created automatically when using /// New [PaintingContext] objects are created automatically when using
/// [PaintingContext.repaintCompositedChild] and [pushLayer]. /// [PaintingContext.repaintCompositedChild] and [pushLayer].
class PaintingContext { class PaintingContext extends ClipContext {
PaintingContext._(this._containerLayer, this.estimatedBounds) PaintingContext._(this._containerLayer, this.estimatedBounds)
: assert(_containerLayer != null), : assert(_containerLayer != null),
assert(estimatedBounds != null); assert(estimatedBounds != null);
...@@ -195,6 +196,7 @@ class PaintingContext { ...@@ -195,6 +196,7 @@ class PaintingContext {
/// The current canvas can change whenever you paint a child using this /// The current canvas can change whenever you paint a child using this
/// context, which means it's fragile to hold a reference to the canvas /// context, which means it's fragile to hold a reference to the canvas
/// returned by this getter. /// returned by this getter.
@override
Canvas get canvas { Canvas get canvas {
if (_canvas == null) if (_canvas == null)
_startRecording(); _startRecording();
...@@ -315,17 +317,13 @@ class PaintingContext { ...@@ -315,17 +317,13 @@ class PaintingContext {
/// clip the painting done by [painter]. /// clip the painting done by [painter].
/// * `painter` is a callback that will paint with the [clipRect] applied. This /// * `painter` is a callback that will paint with the [clipRect] applied. This
/// function calls the [painter] synchronously. /// function calls the [painter] synchronously.
void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter) { /// * `clipBehavior` controls how the rectangle is clipped.
void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
final Rect offsetClipRect = clipRect.shift(offset); final Rect offsetClipRect = clipRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
pushLayer(new ClipRectLayer(clipRect: offsetClipRect), painter, offset, childPaintBounds: offsetClipRect); pushLayer(new ClipRectLayer(clipRect: offsetClipRect, clipBehavior: clipBehavior), painter, offset, childPaintBounds: offsetClipRect);
} else { } else {
canvas clipRectAndPaint(offsetClipRect, clipBehavior, offsetClipRect, () => painter(this, offset));
..save()
..clipRect(offsetClipRect);
painter(this, offset);
canvas
..restore();
} }
} }
...@@ -341,18 +339,16 @@ class PaintingContext { ...@@ -341,18 +339,16 @@ class PaintingContext {
/// to use to clip the painting done by `painter`. /// to use to clip the painting done by `painter`.
/// * `painter` is a callback that will paint with the `clipRRect` applied. This /// * `painter` is a callback that will paint with the `clipRRect` applied. This
/// function calls the `painter` synchronously. /// function calls the `painter` synchronously.
void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter) { /// * `clipBehavior` controls how the path is clipped.
// ignore: deprecated_member_use
void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
assert(clipBehavior != null);
final Rect offsetBounds = bounds.shift(offset); final Rect offsetBounds = bounds.shift(offset);
final RRect offsetClipRRect = clipRRect.shift(offset); final RRect offsetClipRRect = clipRRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
pushLayer(new ClipRRectLayer(clipRRect: offsetClipRRect), painter, offset, childPaintBounds: offsetBounds); pushLayer(new ClipRRectLayer(clipRRect: offsetClipRRect, clipBehavior: clipBehavior), painter, offset, childPaintBounds: offsetBounds);
} else { } else {
canvas clipRRectAndPaint(offsetClipRRect, clipBehavior, offsetBounds, () => painter(this, offset));
..save()
..clipRRect(offsetClipRRect);
painter(this, offset);
canvas
..restore();
} }
} }
...@@ -368,18 +364,16 @@ class PaintingContext { ...@@ -368,18 +364,16 @@ class PaintingContext {
/// clip the painting done by `painter`. /// clip the painting done by `painter`.
/// * `painter` is a callback that will paint with the `clipPath` applied. This /// * `painter` is a callback that will paint with the `clipPath` applied. This
/// function calls the `painter` synchronously. /// function calls the `painter` synchronously.
void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter) { /// * `clipBehavior` controls how the rounded rectangle is clipped.
// ignore: deprecated_member_use
void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
assert(clipBehavior != null);
final Rect offsetBounds = bounds.shift(offset); final Rect offsetBounds = bounds.shift(offset);
final Path offsetClipPath = clipPath.shift(offset); final Path offsetClipPath = clipPath.shift(offset);
if (needsCompositing) { if (needsCompositing) {
pushLayer(new ClipPathLayer(clipPath: offsetClipPath), painter, offset, childPaintBounds: offsetBounds); pushLayer(new ClipPathLayer(clipPath: offsetClipPath, clipBehavior: clipBehavior), painter, offset, childPaintBounds: offsetBounds);
} else { } else {
canvas clipPathAndPaint(offsetClipPath, clipBehavior, offsetBounds, () => painter(this, offset));
..save()
..clipPath(clipPath.shift(offset));
painter(this, offset);
canvas
..restore();
} }
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui show ImageFilter, Gradient, Image; import 'dart:ui' as ui show ImageFilter, Gradient, Image;
import 'dart:ui' show Clip, defaultClipBehavior; // ignore: deprecated_member_use
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -1116,8 +1117,9 @@ class ShapeBorderClipper extends CustomClipper<Path> { ...@@ -1116,8 +1117,9 @@ class ShapeBorderClipper extends CustomClipper<Path> {
abstract class _RenderCustomClip<T> extends RenderProxyBox { abstract class _RenderCustomClip<T> extends RenderProxyBox {
_RenderCustomClip({ _RenderCustomClip({
RenderBox child, RenderBox child,
CustomClipper<T> clipper CustomClipper<T> clipper,
}) : _clipper = clipper, super(child); this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
}) : _clipper = clipper, assert(clipBehavior != null), assert(clipBehavior != Clip.none), super(child);
/// If non-null, determines which clip to use on the child. /// If non-null, determines which clip to use on the child.
CustomClipper<T> get clipper => _clipper; CustomClipper<T> get clipper => _clipper;
...@@ -1160,6 +1162,13 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox { ...@@ -1160,6 +1162,13 @@ abstract class _RenderCustomClip<T> extends RenderProxyBox {
T get _defaultClip; T get _defaultClip;
T _clip; T _clip;
/// {@template flutter.clipper.clipBehavior}
/// Controls how to clip (default to [Clip.antiAlias]).
///
/// [Clip.none] is not allowed here.
/// {@endtemplate}
final Clip clipBehavior;
@override @override
void performLayout() { void performLayout() {
final Size oldSize = hasSize ? size : null; final Size oldSize = hasSize ? size : null;
...@@ -1220,8 +1229,9 @@ class RenderClipRect extends _RenderCustomClip<Rect> { ...@@ -1220,8 +1229,9 @@ class RenderClipRect extends _RenderCustomClip<Rect> {
/// the child. /// the child.
RenderClipRect({ RenderClipRect({
RenderBox child, RenderBox child,
CustomClipper<Rect> clipper CustomClipper<Rect> clipper,
}) : super(child: child, clipper: clipper); Clip clipBehavior = Clip.antiAlias,
}) : super(child: child, clipper: clipper, clipBehavior: clipBehavior);
@override @override
Rect get _defaultClip => Offset.zero & size; Rect get _defaultClip => Offset.zero & size;
...@@ -1241,7 +1251,7 @@ class RenderClipRect extends _RenderCustomClip<Rect> { ...@@ -1241,7 +1251,7 @@ class RenderClipRect extends _RenderCustomClip<Rect> {
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { if (child != null) {
_updateClip(); _updateClip();
context.pushClipRect(needsCompositing, offset, _clip, super.paint); context.pushClipRect(needsCompositing, offset, _clip, super.paint, clipBehavior: clipBehavior);
} }
} }
...@@ -1274,7 +1284,8 @@ class RenderClipRRect extends _RenderCustomClip<RRect> { ...@@ -1274,7 +1284,8 @@ class RenderClipRRect extends _RenderCustomClip<RRect> {
RenderBox child, RenderBox child,
BorderRadius borderRadius = BorderRadius.zero, BorderRadius borderRadius = BorderRadius.zero,
CustomClipper<RRect> clipper, CustomClipper<RRect> clipper,
}) : _borderRadius = borderRadius, super(child: child, clipper: clipper) { Clip clipBehavior = Clip.antiAlias,
}) : _borderRadius = borderRadius, super(child: child, clipper: clipper, clipBehavior: clipBehavior) {
assert(_borderRadius != null || clipper != null); assert(_borderRadius != null || clipper != null);
} }
...@@ -1312,7 +1323,7 @@ class RenderClipRRect extends _RenderCustomClip<RRect> { ...@@ -1312,7 +1323,7 @@ class RenderClipRRect extends _RenderCustomClip<RRect> {
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { if (child != null) {
_updateClip(); _updateClip();
context.pushClipRRect(needsCompositing, offset, _clip.outerRect, _clip, super.paint); context.pushClipRRect(needsCompositing, offset, _clip.outerRect, _clip, super.paint, clipBehavior: clipBehavior);
} }
} }
...@@ -1341,8 +1352,9 @@ class RenderClipOval extends _RenderCustomClip<Rect> { ...@@ -1341,8 +1352,9 @@ class RenderClipOval extends _RenderCustomClip<Rect> {
/// position of the child. /// position of the child.
RenderClipOval({ RenderClipOval({
RenderBox child, RenderBox child,
CustomClipper<Rect> clipper CustomClipper<Rect> clipper,
}) : super(child: child, clipper: clipper); Clip clipBehavior = Clip.antiAlias,
}) : super(child: child, clipper: clipper, clipBehavior: clipBehavior);
Rect _cachedRect; Rect _cachedRect;
Path _cachedPath; Path _cachedPath;
...@@ -1376,7 +1388,7 @@ class RenderClipOval extends _RenderCustomClip<Rect> { ...@@ -1376,7 +1388,7 @@ class RenderClipOval extends _RenderCustomClip<Rect> {
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { if (child != null) {
_updateClip(); _updateClip();
context.pushClipPath(needsCompositing, offset, _clip, _getClipPath(_clip), super.paint); context.pushClipPath(needsCompositing, offset, _clip, _getClipPath(_clip), super.paint, clipBehavior: clipBehavior);
} }
} }
...@@ -1413,8 +1425,9 @@ class RenderClipPath extends _RenderCustomClip<Path> { ...@@ -1413,8 +1425,9 @@ class RenderClipPath extends _RenderCustomClip<Path> {
/// efficiently. /// efficiently.
RenderClipPath({ RenderClipPath({
RenderBox child, RenderBox child,
CustomClipper<Path> clipper CustomClipper<Path> clipper,
}) : super(child: child, clipper: clipper); Clip clipBehavior = Clip.antiAlias,
}) : super(child: child, clipper: clipper, clipBehavior: clipBehavior);
@override @override
Path get _defaultClip => new Path()..addRect(Offset.zero & size); Path get _defaultClip => new Path()..addRect(Offset.zero & size);
...@@ -1434,7 +1447,7 @@ class RenderClipPath extends _RenderCustomClip<Path> { ...@@ -1434,7 +1447,7 @@ class RenderClipPath extends _RenderCustomClip<Path> {
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { if (child != null) {
_updateClip(); _updateClip();
context.pushClipPath(needsCompositing, offset, Offset.zero & size, _clip, super.paint); context.pushClipPath(needsCompositing, offset, Offset.zero & size, _clip, super.paint, clipBehavior: clipBehavior);
} }
} }
...@@ -1462,14 +1475,16 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> { ...@@ -1462,14 +1475,16 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> {
@required double elevation, @required double elevation,
@required Color color, @required Color color,
@required Color shadowColor, @required Color shadowColor,
Clip clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
CustomClipper<T> clipper, CustomClipper<T> clipper,
}) : assert(elevation != null), }) : assert(elevation != null),
assert(color != null), assert(color != null),
assert(shadowColor != null), assert(shadowColor != null),
assert(clipBehavior != null),
_elevation = elevation, _elevation = elevation,
_color = color, _color = color,
_shadowColor = shadowColor, _shadowColor = shadowColor,
super(child: child, clipper: clipper); super(child: child, clipBehavior: clipBehavior, clipper: clipper);
/// The z-coordinate at which to place this material. /// The z-coordinate at which to place this material.
/// ///
...@@ -1539,17 +1554,20 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> { ...@@ -1539,17 +1554,20 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> {
RenderPhysicalModel({ RenderPhysicalModel({
RenderBox child, RenderBox child,
BoxShape shape = BoxShape.rectangle, BoxShape shape = BoxShape.rectangle,
Clip clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
BorderRadius borderRadius, BorderRadius borderRadius,
double elevation = 0.0, double elevation = 0.0,
@required Color color, @required Color color,
Color shadowColor = const Color(0xFF000000), Color shadowColor = const Color(0xFF000000),
}) : assert(shape != null), }) : assert(shape != null),
assert(clipBehavior != null),
assert(elevation != null), assert(elevation != null),
assert(color != null), assert(color != null),
assert(shadowColor != null), assert(shadowColor != null),
_shape = shape, _shape = shape,
_borderRadius = borderRadius, _borderRadius = borderRadius,
super( super(
clipBehavior: clipBehavior,
child: child, child: child,
elevation: elevation, elevation: elevation,
color: color, color: color,
...@@ -1638,6 +1656,7 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> { ...@@ -1638,6 +1656,7 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> {
if (needsCompositing) { if (needsCompositing) {
final PhysicalModelLayer physicalModel = new PhysicalModelLayer( final PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetRRectAsPath, clipPath: offsetRRectAsPath,
clipBehavior: clipBehavior,
elevation: paintShadows ? elevation : 0.0, elevation: paintShadows ? elevation : 0.0,
color: color, color: color,
shadowColor: shadowColor, shadowColor: shadowColor,
...@@ -1662,10 +1681,7 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> { ...@@ -1662,10 +1681,7 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase<RRect> {
); );
} }
canvas.drawRRect(offsetRRect, new Paint()..color = color); canvas.drawRRect(offsetRRect, new Paint()..color = color);
canvas.save(); context.clipRRectAndPaint(offsetRRect, clipBehavior, offsetBounds, () => super.paint(context, offset));
canvas.clipRRect(offsetRRect);
super.paint(context, offset);
canvas.restore();
assert(context.canvas == canvas, 'canvas changed even though needsCompositing was false'); assert(context.canvas == canvas, 'canvas changed even though needsCompositing was false');
} }
} }
...@@ -1697,6 +1713,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -1697,6 +1713,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
RenderPhysicalShape({ RenderPhysicalShape({
RenderBox child, RenderBox child,
@required CustomClipper<Path> clipper, @required CustomClipper<Path> clipper,
Clip clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
double elevation = 0.0, double elevation = 0.0,
@required Color color, @required Color color,
Color shadowColor = const Color(0xFF000000), Color shadowColor = const Color(0xFF000000),
...@@ -1710,6 +1727,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -1710,6 +1727,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
color: color, color: color,
shadowColor: shadowColor, shadowColor: shadowColor,
clipper: clipper, clipper: clipper,
clipBehavior: clipBehavior
); );
@override @override
...@@ -1751,6 +1769,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -1751,6 +1769,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
if (needsCompositing) { if (needsCompositing) {
final PhysicalModelLayer physicalModel = new PhysicalModelLayer( final PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetPath, clipPath: offsetPath,
clipBehavior: clipBehavior,
elevation: paintShadows ? elevation : 0.0, elevation: paintShadows ? elevation : 0.0,
color: color, color: color,
shadowColor: shadowColor, shadowColor: shadowColor,
...@@ -1775,10 +1794,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> { ...@@ -1775,10 +1794,7 @@ class RenderPhysicalShape extends _RenderPhysicalModelBase<Path> {
); );
} }
canvas.drawPath(offsetPath, new Paint()..color = color..style = PaintingStyle.fill); canvas.drawPath(offsetPath, new Paint()..color = color..style = PaintingStyle.fill);
canvas.save(); context.clipPathAndPaint(offsetPath, clipBehavior, offsetBounds, () => super.paint(context, offset));
canvas.clipPath(offsetPath);
super.paint(context, offset);
canvas.restore();
assert(context.canvas == canvas, 'canvas changed even though needsCompositing was false'); assert(context.canvas == canvas, 'canvas changed even though needsCompositing was false');
} }
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui show Image, ImageFilter; import 'dart:ui' as ui show Image, ImageFilter;
import 'dart:ui' show Clip, defaultClipBehavior; // ignore: deprecated_member_use
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -476,13 +477,16 @@ class ClipRect extends SingleChildRenderObjectWidget { ...@@ -476,13 +477,16 @@ class ClipRect extends SingleChildRenderObjectWidget {
/// ///
/// If [clipper] is null, the clip will match the layout size and position of /// If [clipper] is null, the clip will match the layout size and position of
/// the child. /// the child.
const ClipRect({ Key key, this.clipper, Widget child }) : super(key: key, child: child); const ClipRect({ Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
final CustomClipper<Rect> clipper; final CustomClipper<Rect> clipper;
/// {@macro flutter.widget.clipper.clipBehavior}
final Clip clipBehavior;
@override @override
RenderClipRect createRenderObject(BuildContext context) => new RenderClipRect(clipper: clipper); RenderClipRect createRenderObject(BuildContext context) => new RenderClipRect(clipper: clipper, clipBehavior: clipBehavior);
@override @override
void updateRenderObject(BuildContext context, RenderClipRect renderObject) { void updateRenderObject(BuildContext context, RenderClipRect renderObject) {
...@@ -524,8 +528,10 @@ class ClipRRect extends SingleChildRenderObjectWidget { ...@@ -524,8 +528,10 @@ class ClipRRect extends SingleChildRenderObjectWidget {
Key key, Key key,
this.borderRadius, this.borderRadius,
this.clipper, this.clipper,
this.clipBehavior = Clip.antiAlias,
Widget child, Widget child,
}) : assert(borderRadius != null || clipper != null), }) : assert(borderRadius != null || clipper != null),
assert(clipBehavior != null),
super(key: key, child: child); super(key: key, child: child);
/// The border radius of the rounded corners. /// The border radius of the rounded corners.
...@@ -539,8 +545,11 @@ class ClipRRect extends SingleChildRenderObjectWidget { ...@@ -539,8 +545,11 @@ class ClipRRect extends SingleChildRenderObjectWidget {
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
final CustomClipper<RRect> clipper; final CustomClipper<RRect> clipper;
/// {@macro flutter.widget.clipper.clipBehavior}
final Clip clipBehavior;
@override @override
RenderClipRRect createRenderObject(BuildContext context) => new RenderClipRRect(borderRadius: borderRadius, clipper: clipper); RenderClipRRect createRenderObject(BuildContext context) => new RenderClipRRect(borderRadius: borderRadius, clipper: clipper, clipBehavior: clipBehavior);
@override @override
void updateRenderObject(BuildContext context, RenderClipRRect renderObject) { void updateRenderObject(BuildContext context, RenderClipRRect renderObject) {
...@@ -575,7 +584,7 @@ class ClipOval extends SingleChildRenderObjectWidget { ...@@ -575,7 +584,7 @@ class ClipOval extends SingleChildRenderObjectWidget {
/// ///
/// If [clipper] is null, the oval will be inscribed into the layout size and /// If [clipper] is null, the oval will be inscribed into the layout size and
/// position of the child. /// position of the child.
const ClipOval({ Key key, this.clipper, Widget child }) : super(key: key, child: child); const ClipOval({ Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
/// ///
...@@ -588,8 +597,11 @@ class ClipOval extends SingleChildRenderObjectWidget { ...@@ -588,8 +597,11 @@ class ClipOval extends SingleChildRenderObjectWidget {
/// object) instead. /// object) instead.
final CustomClipper<Rect> clipper; final CustomClipper<Rect> clipper;
/// {@macro flutter.widget.clipper.clipBehavior}
final Clip clipBehavior;
@override @override
RenderClipOval createRenderObject(BuildContext context) => new RenderClipOval(clipper: clipper); RenderClipOval createRenderObject(BuildContext context) => new RenderClipOval(clipper: clipper, clipBehavior: clipBehavior);
@override @override
void updateRenderObject(BuildContext context, RenderClipOval renderObject) { void updateRenderObject(BuildContext context, RenderClipOval renderObject) {
...@@ -627,7 +639,7 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -627,7 +639,7 @@ class ClipPath extends SingleChildRenderObjectWidget {
/// size and location of the child. However, rather than use this default, /// size and location of the child. However, rather than use this default,
/// consider using a [ClipRect], which can achieve the same effect more /// consider using a [ClipRect], which can achieve the same effect more
/// efficiently. /// efficiently.
const ClipPath({ Key key, this.clipper, Widget child }) : super(key: key, child: child); const ClipPath({ Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child }) : super(key: key, child: child);
/// If non-null, determines which clip to use. /// If non-null, determines which clip to use.
/// ///
...@@ -636,8 +648,11 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -636,8 +648,11 @@ class ClipPath extends SingleChildRenderObjectWidget {
/// efficient way of obtaining that effect. /// efficient way of obtaining that effect.
final CustomClipper<Path> clipper; final CustomClipper<Path> clipper;
/// {@macro flutter.widget.clipper.clipBehavior}
final Clip clipBehavior;
@override @override
RenderClipPath createRenderObject(BuildContext context) => new RenderClipPath(clipper: clipper); RenderClipPath createRenderObject(BuildContext context) => new RenderClipPath(clipper: clipper, clipBehavior: clipBehavior);
@override @override
void updateRenderObject(BuildContext context, RenderClipPath renderObject) { void updateRenderObject(BuildContext context, RenderClipPath renderObject) {
...@@ -677,6 +692,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget { ...@@ -677,6 +692,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget {
const PhysicalModel({ const PhysicalModel({
Key key, Key key,
this.shape = BoxShape.rectangle, this.shape = BoxShape.rectangle,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
this.borderRadius, this.borderRadius,
this.elevation = 0.0, this.elevation = 0.0,
@required this.color, @required this.color,
...@@ -691,6 +707,9 @@ class PhysicalModel extends SingleChildRenderObjectWidget { ...@@ -691,6 +707,9 @@ class PhysicalModel extends SingleChildRenderObjectWidget {
/// The type of shape. /// The type of shape.
final BoxShape shape; final BoxShape shape;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// The border radius of the rounded corners. /// The border radius of the rounded corners.
/// ///
/// Values are clamped so that horizontal and vertical radii sums do not /// Values are clamped so that horizontal and vertical radii sums do not
...@@ -712,6 +731,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget { ...@@ -712,6 +731,7 @@ class PhysicalModel extends SingleChildRenderObjectWidget {
RenderPhysicalModel createRenderObject(BuildContext context) { RenderPhysicalModel createRenderObject(BuildContext context) {
return new RenderPhysicalModel( return new RenderPhysicalModel(
shape: shape, shape: shape,
clipBehavior: clipBehavior,
borderRadius: borderRadius, borderRadius: borderRadius,
elevation: elevation, color: color, elevation: elevation, color: color,
shadowColor: shadowColor, shadowColor: shadowColor,
...@@ -760,11 +780,13 @@ class PhysicalShape extends SingleChildRenderObjectWidget { ...@@ -760,11 +780,13 @@ class PhysicalShape extends SingleChildRenderObjectWidget {
const PhysicalShape({ const PhysicalShape({
Key key, Key key,
@required this.clipper, @required this.clipper,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
this.elevation = 0.0, this.elevation = 0.0,
@required this.color, @required this.color,
this.shadowColor = const Color(0xFF000000), this.shadowColor = const Color(0xFF000000),
Widget child, Widget child,
}) : assert(clipper != null), }) : assert(clipper != null),
assert(clipBehavior != null),
assert(elevation != null), assert(elevation != null),
assert(color != null), assert(color != null),
assert(shadowColor != null), assert(shadowColor != null),
...@@ -777,6 +799,9 @@ class PhysicalShape extends SingleChildRenderObjectWidget { ...@@ -777,6 +799,9 @@ class PhysicalShape extends SingleChildRenderObjectWidget {
/// shape for use with this widget. /// shape for use with this widget.
final CustomClipper<Path> clipper; final CustomClipper<Path> clipper;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// The z-coordinate at which to place this physical object. /// The z-coordinate at which to place this physical object.
final double elevation; final double elevation;
...@@ -790,6 +815,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget { ...@@ -790,6 +815,7 @@ class PhysicalShape extends SingleChildRenderObjectWidget {
RenderPhysicalShape createRenderObject(BuildContext context) { RenderPhysicalShape createRenderObject(BuildContext context) {
return new RenderPhysicalShape( return new RenderPhysicalShape(
clipper: clipper, clipper: clipper,
clipBehavior: clipBehavior,
elevation: elevation, elevation: elevation,
color: color, color: color,
shadowColor: shadowColor shadowColor: shadowColor
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' show Clip, defaultClipBehavior; // ignore: deprecated_member_use
import 'package:flutter/animation.dart'; import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -1181,6 +1183,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget { ...@@ -1181,6 +1183,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget {
Key key, Key key,
@required this.child, @required this.child,
@required this.shape, @required this.shape,
this.clipBehavior = defaultClipBehavior, // ignore: deprecated_member_use
this.borderRadius = BorderRadius.zero, this.borderRadius = BorderRadius.zero,
@required this.elevation, @required this.elevation,
@required this.color, @required this.color,
...@@ -1191,6 +1194,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget { ...@@ -1191,6 +1194,7 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget {
@required Duration duration, @required Duration duration,
}) : assert(child != null), }) : assert(child != null),
assert(shape != null), assert(shape != null),
assert(clipBehavior != null),
assert(borderRadius != null), assert(borderRadius != null),
assert(elevation != null), assert(elevation != null),
assert(color != null), assert(color != null),
...@@ -1209,6 +1213,9 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget { ...@@ -1209,6 +1213,9 @@ class AnimatedPhysicalModel extends ImplicitlyAnimatedWidget {
/// This property is not animated. /// This property is not animated.
final BoxShape shape; final BoxShape shape;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// The target border radius of the rounded corners for a rectangle shape. /// The target border radius of the rounded corners for a rectangle shape.
final BorderRadius borderRadius; final BorderRadius borderRadius;
...@@ -1262,6 +1269,7 @@ class _AnimatedPhysicalModelState extends AnimatedWidgetBaseState<AnimatedPhysic ...@@ -1262,6 +1269,7 @@ class _AnimatedPhysicalModelState extends AnimatedWidgetBaseState<AnimatedPhysic
return new PhysicalModel( return new PhysicalModel(
child: widget.child, child: widget.child,
shape: widget.shape, shape: widget.shape,
clipBehavior: widget.clipBehavior,
borderRadius: _borderRadius.evaluate(animation), borderRadius: _borderRadius.evaluate(animation),
elevation: _elevation.evaluate(animation), elevation: _elevation.evaluate(animation),
color: widget.animateColor ? _color.evaluate(animation) : widget.color, color: widget.animateColor ? _color.evaluate(animation) : widget.color,
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' show Clip;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -90,7 +92,7 @@ class TestRecordingCanvas implements Canvas { ...@@ -90,7 +92,7 @@ class TestRecordingCanvas implements Canvas {
} }
/// A [PaintingContext] for tests that use [TestRecordingCanvas]. /// A [PaintingContext] for tests that use [TestRecordingCanvas].
class TestRecordingPaintingContext implements PaintingContext { class TestRecordingPaintingContext extends ClipContext implements PaintingContext {
/// Creates a [PaintingContext] for tests that use [TestRecordingCanvas]. /// Creates a [PaintingContext] for tests that use [TestRecordingCanvas].
TestRecordingPaintingContext(this.canvas); TestRecordingPaintingContext(this.canvas);
...@@ -103,28 +105,19 @@ class TestRecordingPaintingContext implements PaintingContext { ...@@ -103,28 +105,19 @@ class TestRecordingPaintingContext implements PaintingContext {
} }
@override @override
void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter) { void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
canvas.save(); clipRectAndPaint(clipRect.shift(offset), clipBehavior, clipRect.shift(offset), () => painter(this, offset));
canvas.clipRect(clipRect.shift(offset));
painter(this, offset);
canvas.restore();
} }
@override @override
void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter) { void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, RRect clipRRect, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
canvas.save(); assert(clipBehavior != null);
canvas.clipRRect(clipRRect.shift(offset)); clipRRectAndPaint(clipRRect.shift(offset), clipBehavior, bounds.shift(offset), () => painter(this, offset));
painter(this, offset);
canvas.restore();
} }
@override @override
void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter) { void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter, {Clip clipBehavior = Clip.antiAlias}) {
canvas clipPathAndPaint(clipPath.shift(offset), clipBehavior, bounds.shift(offset), () => painter(this, offset));
..save()
..clipPath(clipPath.shift(offset));
painter(this, offset);
canvas.restore();
} }
@override @override
......
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