Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit 6ce54e8

Browse files
author
Yuncong Zhang
committed
Implement ClipOval.
1 parent be59585 commit 6ce54e8

File tree

2 files changed

+116
-16
lines changed

2 files changed

+116
-16
lines changed

Runtime/rendering/proxy_box.cs

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,70 @@ protected override void debugPaintSize(PaintingContext context, Offset offset) {
983983
}
984984
}
985985

986+
public class RenderClipOval : _RenderCustomClip<Rect> {
987+
public RenderClipOval(
988+
RenderBox child = null,
989+
CustomClipper<Rect> clipper = null,
990+
Clip clipBehavior = Clip.antiAlias
991+
) : base(child: child, clipper: clipper, clipBehavior: clipBehavior) {
992+
D.assert(clipBehavior != Clip.none);
993+
}
994+
995+
Rect _cachedRect;
996+
Path _cachedPath;
997+
998+
Path _getClipPath(Rect rect) {
999+
if (rect != this._cachedRect) {
1000+
this._cachedRect = rect;
1001+
this._cachedPath = new Path();
1002+
this._cachedPath.addOval(this._cachedRect);
1003+
}
1004+
1005+
return this._cachedPath;
1006+
}
1007+
1008+
protected override Rect _defaultClip {
1009+
get { return Offset.zero & this.size; }
1010+
}
1011+
1012+
public override bool hitTest(HitTestResult result,
1013+
Offset position = null
1014+
) {
1015+
this._updateClip();
1016+
D.assert(this._clip != null);
1017+
Offset center = this._clip.center;
1018+
Offset offset = new Offset((position.dx - center.dx) / this._clip.width,
1019+
(position.dy - center.dy) / this._clip.height);
1020+
if (offset.distanceSquared > 0.25f) // x^2 + y^2 > r^2
1021+
{
1022+
return false;
1023+
}
1024+
1025+
return base.hitTest(result, position: position);
1026+
}
1027+
1028+
public override void paint(PaintingContext context, Offset offset) {
1029+
if (this.child != null) {
1030+
this._updateClip();
1031+
context.pushClipPath(this.needsCompositing, offset, this._clip, this._getClipPath(this._clip),
1032+
base.paint, clipBehavior: this.clipBehavior);
1033+
}
1034+
}
1035+
1036+
protected override void debugPaintSize(PaintingContext context, Offset offset) {
1037+
D.assert(() => {
1038+
if (this.child != null) {
1039+
base.debugPaintSize(context, offset);
1040+
context.canvas.drawPath(this._getClipPath(this._clip).shift(offset), this._debugPaint);
1041+
this._debugText.paint(context.canvas,
1042+
offset + new Offset((this._clip.width - this._debugText.width) / 2.0f,
1043+
-this._debugText.text.style.fontSize * 1.1f ?? 0.0f));
1044+
}
1045+
1046+
return true;
1047+
});
1048+
}
1049+
}
9861050

9871051
public class RenderClipPath : _RenderCustomClip<Path> {
9881052
public RenderClipPath(
@@ -1194,7 +1258,7 @@ public override bool hitTest(HitTestResult result, Offset position = null) {
11941258
return base.hitTest(result, position: position);
11951259
}
11961260

1197-
1261+
11981262
public override void paint(PaintingContext context, Offset offset) {
11991263
if (this.child != null) {
12001264
this._updateClip();
@@ -1282,7 +1346,7 @@ public override bool hitTest(HitTestResult result, Offset position = null) {
12821346
return base.hitTest(result, position: position);
12831347
}
12841348

1285-
1349+
12861350
public override void paint(PaintingContext context, Offset offset) {
12871351
if (this.child != null) {
12881352
this._updateClip();
@@ -1301,19 +1365,20 @@ public override void paint(PaintingContext context, Offset offset) {
13011365
}
13021366
else {
13031367
Canvas canvas = context.canvas;
1304-
if (this.elevation != 0.0) {
1305-
canvas.drawRect(
1306-
offsetBounds.inflate(20.0f),
1307-
_transparentPaint
1308-
);
1309-
1310-
canvas.drawShadow(
1311-
offsetPath,
1312-
this.shadowColor,
1313-
this.elevation,
1314-
this.color.alpha != 0xFF
1315-
);
1316-
}
1368+
if (this.elevation != 0.0) {
1369+
canvas.drawRect(
1370+
offsetBounds.inflate(20.0f),
1371+
_transparentPaint
1372+
);
1373+
1374+
canvas.drawShadow(
1375+
offsetPath,
1376+
this.shadowColor,
1377+
this.elevation,
1378+
this.color.alpha != 0xFF
1379+
);
1380+
}
1381+
13171382
Paint paint = new Paint {color = this.color, style = PaintingStyle.fill};
13181383
canvas.drawPath(offsetPath, paint);
13191384
context.clipPathAndPaint(offsetPath, this.clipBehavior,

Runtime/widgets/basic.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,41 @@ public override void debugFillProperties(DiagnosticPropertiesBuilder properties)
194194
}
195195
}
196196

197+
public class ClipOval : SingleChildRenderObjectWidget {
198+
public ClipOval(
199+
Key key = null,
200+
CustomClipper<Rect> clipper = null,
201+
Clip clipBehavior = Clip.antiAlias,
202+
Widget child = null) : base(key: key, child: child
203+
) {
204+
this.clipper = clipper;
205+
this.clipBehavior = clipBehavior;
206+
}
207+
208+
public readonly CustomClipper<Rect> clipper;
209+
210+
public readonly Clip clipBehavior;
211+
212+
public override RenderObject createRenderObject(BuildContext context) {
213+
return new RenderClipOval(clipper: this.clipper, clipBehavior: this.clipBehavior);
214+
}
215+
216+
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) {
217+
RenderClipOval renderObject = _renderObject as RenderClipOval;
218+
renderObject.clipper = this.clipper;
219+
}
220+
221+
public override void didUnmountRenderObject(RenderObject _renderObject) {
222+
RenderClipOval renderObject = _renderObject as RenderClipOval;
223+
renderObject.clipper = null;
224+
}
225+
226+
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
227+
base.debugFillProperties(properties);
228+
properties.add(new DiagnosticsProperty<CustomClipper<Rect>>("clipper", this.clipper, defaultValue: null));
229+
}
230+
}
231+
197232
public class ClipPath : SingleChildRenderObjectWidget {
198233
public ClipPath(
199234
Key key = null,
@@ -2161,4 +2196,4 @@ public override Widget build(BuildContext context) {
21612196
return this.builder(context);
21622197
}
21632198
}
2164-
}
2199+
}

0 commit comments

Comments
 (0)