Skip to content

Commit 8432ee2

Browse files
author
Simeon
authored
Handle rounded rectangles more accurately (#288)
* Rename to match After Effects and some initial refactoring. * Correctly support roundness where size and roundness are not animated. * Handle non-static rounded rectangles better. * Also fixes a misunderstanding with how animations are stopped in Composition.
1 parent 2968252 commit 8432ee2

File tree

9 files changed

+216
-130
lines changed

9 files changed

+216
-130
lines changed

source/LottieData/Polystar.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public Polystar(
1818
Animatable<double> rotation,
1919
Animatable<double> innerRadius,
2020
Animatable<double> outerRadius,
21-
Animatable<double> innerRoundedness,
22-
Animatable<double> outerRoundedness)
21+
Animatable<double> innerRoundness,
22+
Animatable<double> outerRoundness)
2323
: base(in args, drawingDirection)
2424
{
2525
StarType = starType;
@@ -28,8 +28,8 @@ public Polystar(
2828
Rotation = rotation;
2929
InnerRadius = innerRadius;
3030
OuterRadius = outerRadius;
31-
InnerRoundedness = innerRoundedness;
32-
OuterRoundedness = outerRoundedness;
31+
InnerRoundness = innerRoundness;
32+
OuterRoundness = outerRoundness;
3333
}
3434

3535
internal PolyStarType StarType { get; }
@@ -44,9 +44,9 @@ public Polystar(
4444

4545
internal Animatable<double> OuterRadius { get; }
4646

47-
internal Animatable<double> InnerRoundedness { get; }
47+
internal Animatable<double> InnerRoundness { get; }
4848

49-
internal Animatable<double> OuterRoundedness { get; }
49+
internal Animatable<double> OuterRoundness { get; }
5050

5151
/// <inheritdoc/>
5252
public override ShapeContentType ContentType => ShapeContentType.Polystar;

source/LottieData/Rectangle.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,22 @@ public Rectangle(
1414
DrawingDirection drawingDirection,
1515
IAnimatableVector3 position,
1616
IAnimatableVector3 size,
17-
Animatable<double> cornerRadius)
17+
Animatable<double> roundness)
1818
: base(in args, drawingDirection)
1919
{
2020
Position = position;
2121
Size = size;
22-
CornerRadius = cornerRadius;
22+
Roundness = roundness;
2323
}
2424

25-
public Animatable<double> CornerRadius { get; }
25+
/// <summary>
26+
/// Determines how round the corners of the rectangle are. If the rectangle
27+
/// is a square and the roundness is equal to half of the width then the
28+
/// rectangle will be rendered as a circle. Once the roundness value reaches
29+
/// half of the minimum of the shortest dimension, increasing it has no
30+
/// further effect.
31+
/// </summary>
32+
public Animatable<double> Roundness { get; }
2633

2734
public IAnimatableVector3 Size { get; }
2835

source/LottieData/RoundedCorner.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ public RoundedCorner(
1717
Radius = radius;
1818
}
1919

20+
/// <summary>
21+
/// The radius of the rounding.
22+
/// </summary>
23+
/// <remarks>
24+
/// If the shape to which this applies is a rectangle, the rounding will
25+
/// only apply if the rectangle has a 0 roundness value. Once the radius
26+
/// value reaches half of the largest dimension of the rectangle, the
27+
/// result will be equivalent to an ellipse of the same size, and
28+
/// increasing the radius further will have no further effect.
29+
/// </remarks>
2030
public Animatable<double> Radius { get; }
2131

2232
/// <inheritdoc/>

source/LottieData/Serialization/LottieCompositionXmlSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ IEnumerable<XObject> GetContents()
616616

617617
yield return FromAnimatable(nameof(content.Size), content.Size);
618618
yield return FromAnimatable(nameof(content.Position), content.Position);
619-
yield return FromAnimatable(nameof(content.CornerRadius), content.CornerRadius);
619+
yield return FromAnimatable(nameof(content.Roundness), content.Roundness);
620620
}
621621
}
622622

source/LottieData/Serialization/LottieCompositionYamlSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ YamlObject FromRectangle(Rectangle content, YamlMap superclassContent)
644644
var result = superclassContent;
645645
result.Add(nameof(content.Size), FromAnimatable(content.Size));
646646
result.Add(nameof(content.Position), FromAnimatable(content.Position));
647-
result.Add(nameof(content.CornerRadius), FromAnimatable(content.CornerRadius));
647+
result.Add(nameof(content.Roundness), FromAnimatable(content.Roundness));
648648
return result;
649649
}
650650

source/LottieReader/Serialization/ShapeLayerContents.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,23 +326,23 @@ Polystar ReadPolystar(
326326
var position = ReadAnimatableVector3(obj.ObjectPropertyOrNull("p"));
327327
var rotation = ReadAnimatableFloat(obj.ObjectPropertyOrNull("r"));
328328
var outerRadius = ReadAnimatableFloat(obj.ObjectPropertyOrNull("or"));
329-
var outerRoundedness = ReadAnimatableFloat(obj.ObjectPropertyOrNull("os"));
329+
var outerRoundness = ReadAnimatableFloat(obj.ObjectPropertyOrNull("os"));
330330

331331
var polystarType = SyToPolystarType(obj.DoublePropertyOrNull("sy")) ?? Polystar.PolyStarType.Polygon;
332332

333333
Animatable<double> innerRadius;
334-
Animatable<double> innerRoundedness;
334+
Animatable<double> innerRoundness;
335335

336336
switch (polystarType)
337337
{
338338
case Polystar.PolyStarType.Star:
339339
innerRadius = ReadAnimatableFloat(obj.ObjectPropertyOrNull("ir"));
340-
innerRoundedness = ReadAnimatableFloat(obj.ObjectPropertyOrNull("is"));
340+
innerRoundness = ReadAnimatableFloat(obj.ObjectPropertyOrNull("is"));
341341
break;
342342

343343
default:
344344
innerRadius = null;
345-
innerRoundedness = null;
345+
innerRoundness = null;
346346
break;
347347
}
348348

@@ -356,8 +356,8 @@ Polystar ReadPolystar(
356356
rotation,
357357
innerRadius,
358358
outerRadius,
359-
innerRoundedness,
360-
outerRoundedness);
359+
innerRoundness,
360+
outerRoundness);
361361
}
362362

363363
Rectangle ReadRectangle(
@@ -370,10 +370,10 @@ Rectangle ReadRectangle(
370370
var drawingDirection = DToDrawingDirection(obj.DoublePropertyOrNull("d"));
371371
var position = ReadAnimatableVector3(obj.ObjectPropertyOrNull("p"));
372372
var size = ReadAnimatableVector3(obj.ObjectPropertyOrNull("s"));
373-
var cornerRadius = ReadAnimatableFloat(obj.ObjectPropertyOrNull("r"));
373+
var roundness = ReadAnimatableFloat(obj.ObjectPropertyOrNull("r"));
374374

375375
obj.AssertAllPropertiesRead();
376-
return new Rectangle(in shapeLayerContentArgs, drawingDirection, position, size, cornerRadius);
376+
return new Rectangle(in shapeLayerContentArgs, drawingDirection, position, size, roundness);
377377
}
378378

379379
Path ReadPath(

source/LottieToWinComp/ExpressionFactory.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static class ExpressionFactory
2727
internal static readonly Vector2 MyPosition = MyVector2("Position");
2828
internal static readonly Vector2 MySize = MyVector2("Size");
2929
internal static readonly Matrix3x2 MyTransformMatrix = MyMatrix3x2("TransformMatrix");
30+
static readonly Scalar MyRoundness = MyScalar("Roundness");
3031
static readonly Scalar MyTStart = MyScalar("TStart");
3132
static readonly Scalar MyTEnd = MyScalar("TEnd");
3233

@@ -67,6 +68,15 @@ internal static Color ColorMultipliedByPreMultipliedOpacities(Wui.Color color, S
6768

6869
internal static Scalar RootScalar(string propertyName) => Scalar(RootProperty(propertyName));
6970

71+
internal static Vector2 ConstrainedCornerRadiusScalar(double roundness)
72+
=> Vector2(Min(roundness, Min(MySize.X, MySize.Y) / 2), Min(roundness, Min(MySize.X, MySize.Y) / 2));
73+
74+
internal static Vector2 ConstrainedCornerRadiusScalar()
75+
=> Vector2(Min(MyRoundness, Min(MySize.X, MySize.Y) / 2), Min(MyRoundness, Min(MySize.X, MySize.Y) / 2));
76+
77+
internal static Vector2 ConstrainedCornerRadiusScalar(Sn.Vector2 size)
78+
=> Vector2(Min(MyRoundness, Math.Min(size.X, size.Y) / 2), Min(MyRoundness, Math.Min(size.X, size.Y) / 2));
79+
7080
// The value of a Color property stored as a Vector4 on the theming property set.
7181
static Vector4 ThemedColor4Property(string propertyName) => Vector4(ThemeProperty(propertyName));
7282

0 commit comments

Comments
 (0)