Support for common radial gradient fills. (#152)

* Support for common radial gradient fills.

* CR feedback.
This commit is contained in:
Simeon 2019-09-09 09:56:47 -07:00 коммит произвёл GitHub
Родитель b6b29b22e4
Коммит 6e94ea343d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 144 добавлений и 24 удалений

Просмотреть файл

@ -415,8 +415,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie
return GetCompositionPathGeometry((Wd.CompositionPathGeometry)obj);
case Wd.CompositionObjectType.CompositionPropertySet:
return GetCompositionPropertySet((Wd.CompositionPropertySet)obj);
/*case Wd.CompositionObjectType.CompositionRadialGradientBrush:
return GetCompositionRadialGradientBrush((Wd.CompositionRadialGradientBrush)obj);*/
case Wd.CompositionObjectType.CompositionRadialGradientBrush:
return GetCompositionRadialGradientBrush((Wd.CompositionRadialGradientBrush)obj);
case Wd.CompositionObjectType.CompositionRectangleGeometry:
return GetCompositionRectangleGeometry((Wd.CompositionRectangleGeometry)obj);
case Wd.CompositionObjectType.CompositionRoundedRectangleGeometry:
@ -1299,8 +1299,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie
case Wd.CompositionObjectType.CompositionLinearGradientBrush:
return GetCompositionLinearGradientBrush((Wd.CompositionLinearGradientBrush)obj);
case Wd.CompositionObjectType.CompositionRadialGradientBrush:
// TODO - handle versioning - RadialGradientBrush was not added until 1903
// return GetCompositionRadialGradientBrush((Wd.CompositionRadialGradientBrush)obj);
return GetCompositionRadialGradientBrush((Wd.CompositionRadialGradientBrush)obj);
default:
throw new InvalidOperationException();
}

Просмотреть файл

@ -1058,29 +1058,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
var popped = stack.Peek();
switch (popped.ContentType)
{
case ShapeContentType.RadialGradientFill:
_owner._issues.GradientFillIsNotSupported();
{
// We don't yet support gradient fill, but we can at least
// draw something. Use data from the first gradient stop as the fill.
var rgf = (RadialGradientFill)popped;
var rgfArgs = default(ShapeLayerContent.ShapeLayerContentArgs);
rgfArgs.BlendMode = rgf.BlendMode;
Fill = new SolidColorFill(
in rgfArgs,
ShapeFill.PathFillType.EvenOdd,
rgf.OpacityPercent,
new Animatable<Color>(rgf.ColorStops.InitialValue.Items[0].Color, null));
}
break;
case ShapeContentType.LinearGradientStroke:
case ShapeContentType.RadialGradientStroke:
_owner._issues.GradientStrokeIsNotSupported();
break;
case ShapeContentType.LinearGradientFill:
case ShapeContentType.RadialGradientFill:
case ShapeContentType.SolidColorFill:
Fill = ComposeFills(Fill, (ShapeFill)popped);
break;
@ -2545,7 +2529,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
case ShapeFill.ShapeFillKind.LinearGradient:
return TranslateLinearGradientFill(context, (LinearGradientFill)shapeFill, opacityPercent);
case ShapeFill.ShapeFillKind.RadialGradient:
/*return TranslateRadialGradientFill(context, (RadialGradientFill)shapeFill, opacityPercent);*/
return TranslateRadialGradientFill(context, (RadialGradientFill)shapeFill, opacityPercent);
default:
throw new InvalidOperationException();
}
@ -2561,7 +2545,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
opacityPercent);
}
CompositionLinearGradientBrush TranslateLinearGradientFill(TranslationContext context, LinearGradientFill shapeFill, TrimmedAnimatable<double> opacityPercent)
CompositionLinearGradientBrush TranslateLinearGradientFill(
TranslationContext context,
LinearGradientFill shapeFill,
TrimmedAnimatable<double> opacityPercent)
{
var colorStops = context.TrimAnimatable(shapeFill.ColorStops);
var opacityPercentStops = context.TrimAnimatable(shapeFill.OpacityPercentStops);
@ -2662,6 +2649,116 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.LottieToWinComp
return result;
}
CompositionRadialGradientBrush TranslateRadialGradientFill(
TranslationContext context,
RadialGradientFill shapeFill,
TrimmedAnimatable<double> opacityPercent)
{
var colorStops = context.TrimAnimatable(shapeFill.ColorStops);
var opacityPercentStops = context.TrimAnimatable(shapeFill.OpacityPercentStops);
if (colorStops.InitialValue.Items.IsEmpty)
{
// If there are no color stops then we can't create a brush.
return null;
}
if (opacityPercent.IsAnimated)
{
// We don't yet support animated opacity with RadialGradientFill.
_issues.GradientFillIsNotSupported();
}
if (!opacityPercentStops.InitialValue.Items.IsEmpty)
{
// We don't yet support opacity stops.
_issues.GradientFillIsNotSupported();
}
var opacityPercentValue = opacityPercent.InitialValue;
var result = _c.CreateRadialGradientBrush();
// BodyMovin specifies start and end points in absolute values.
result.MappingMode = CompositionMappingMode.Absolute;
var startPoint = context.TrimAnimatable(shapeFill.StartPoint);
var endPoint = context.TrimAnimatable(shapeFill.EndPoint);
if (startPoint.IsAnimated)
{
ApplyVector2KeyFrameAnimation(context, startPoint, result, nameof(result.EllipseCenter));
}
else
{
result.EllipseCenter = Vector2(startPoint.InitialValue);
}
if (endPoint.IsAnimated)
{
// We don't yet support animated EndPoint.
_issues.GradientFillIsNotSupported();
}
result.EllipseRadius = new Sn.Vector2(Sn.Vector2.Distance(Vector2(startPoint.InitialValue), Vector2(endPoint.InitialValue)));
if (shapeFill.HighlightLength != null &&
(shapeFill.HighlightLength.InitialValue != 0 || shapeFill.HighlightLength.IsAnimated))
{
// We don't yet support animated HighlightLength.
_issues.GradientFillIsNotSupported();
}
var brushStops = result.ColorStops;
if (colorStops.IsAnimated)
{
// Lottie represents animation of stops as a sequence of lists of stops.
// WinComp uses a single list of stops where each stop is animated.
var stopsCount = colorStops.InitialValue.Items.Length;
var keyframesCount = colorStops.KeyFrames.Length;
var colorStopKeyFrames = colorStops.KeyFrames.ToArray();
// Create the Composition stops and animate them.
for (var i = 0; i < stopsCount; i++)
{
var gradientStop = _c.CreateColorGradientStop();
brushStops.Add(gradientStop);
// Extract the key frames for this stop.
var colorKeyFrames = ExtractKeyFramesFromGradientStopKeyFrames(
colorStopKeyFrames,
i,
gs => MultiplyColorByOpacityPercent(gs.Color, opacityPercentValue)).ToArray();
ApplyColorKeyFrameAnimation(
context,
new TrimmedAnimatable<Color>(context, colorKeyFrames[0].Value, colorKeyFrames),
gradientStop,
nameof(gradientStop.Color));
var offsetKeyFrames = ExtractKeyFramesFromGradientStopKeyFrames(colorStopKeyFrames, i, gs => gs.Offset).ToArray();
ApplyScalarKeyFrameAnimation(
context,
new TrimmedAnimatable<double>(context, offsetKeyFrames[0].Value, offsetKeyFrames),
gradientStop,
nameof(gradientStop.Offset));
}
}
else
{
foreach (var stop in colorStops.InitialValue.Items)
{
var offset = stop.Offset;
var color = MultiplyColorByOpacityPercent(stop.Color, opacityPercentValue);
brushStops.Add(_c.CreateColorGradientStop(Float(offset), color));
}
}
return result;
}
static IEnumerable<KeyFrame<TKeyFrame>> ExtractKeyFramesFromGradientStopKeyFrames<TStop, TKeyFrame>(
KeyFrame<Sequence<TStop>>[] stops,
int stopIndex,

Просмотреть файл

@ -847,7 +847,28 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.UIData.CodeGen
bool GenerateCompositionRadialGradientBrushFactory(CodeBuilder builder, CompositionRadialGradientBrush obj, ObjectData node)
{
throw new NotImplementedException();
WriteObjectFactoryStart(builder, node);
WriteCreateAssignment(builder, node, $"_c{Deref}CreateRadialGradientBrush()");
InitializeCompositionGradientBrush(builder, obj, node);
if (obj.EllipseCenter.HasValue)
{
builder.WriteLine($"result{Deref}EllipseCenter = {Vector2(obj.EllipseCenter.Value)};");
}
if (obj.EllipseRadius.HasValue)
{
builder.WriteLine($"result{Deref}EllipseRadius = {Vector2(obj.EllipseRadius.Value)};");
}
if (obj.GradientOriginOffset.HasValue)
{
builder.WriteLine($"result{Deref}GradientOriginOffset = {Vector2(obj.GradientOriginOffset.Value)};");
}
StartAnimations(builder, obj, node);
WriteObjectFactoryEnd(builder);
return true;
}
bool GenerateLinearEasingFunctionFactory(CodeBuilder builder, LinearEasingFunction obj, ObjectData node)

Просмотреть файл

@ -15,10 +15,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Lottie.WinCompData
{
}
// Default is 0.5, 0.5
public Vector2? EllipseCenter { get; set; }
// Default is 0.5, 0.5
public Vector2? EllipseRadius { get; set; }
// Default is 0, 0
public Vector2? GradientOriginOffset { get; set; }
/// <inheritdoc/>