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.
This commit is contained in:
parent
ad163749b7
commit
9ffa1c5174
@ -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 @@
|
|||||||
// 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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
clipper: new ShapeBorderClipper(
|
clipper: new ShapeBorderClipper(
|
||||||
shape: shape,
|
shape: shape,
|
||||||
),
|
),
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
|||||||
@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 {
|
|||||||
/// 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>
|
|||||||
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),
|
||||||
|
59
packages/flutter/lib/src/painting/clip.dart
Normal file
59
packages/flutter/lib/src/painting/clip.dart
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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 @@
|
|||||||
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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
/// (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 {
|
|||||||
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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
/// (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 {
|
|||||||
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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
/// (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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
/// (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 {
|
|||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
color: color,
|
color: color,
|
||||||
shadowColor: shadowColor,
|
shadowColor: shadowColor,
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
addChildrenToScene(builder, layerOffset);
|
addChildrenToScene(builder, layerOffset);
|
||||||
|
@ -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);
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
/// 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 @@
|
|||||||
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> {
|
|||||||
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 {
|
|||||||
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> {
|
|||||||
/// 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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
/// 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> {
|
|||||||
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> {
|
|||||||
/// 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> {
|
|||||||
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> {
|
|||||||
@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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
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> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
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 @@
|
|||||||
// 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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
///
|
///
|
||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
/// 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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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 @@
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
@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 {
|
|||||||
/// 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
|
|||||||
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 @@
|
|||||||
// 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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user