YamlObject FromOpacityGradientStop(OpacityGradientStop value) { var result = new YamlMap { { nameof(value.Opacity), Scalar(value.Opacity) }, { nameof(value.Offset), Scalar(value.Offset) }, }; return(result); }
static YamlObject FromOpacityGradientStop(OpacityGradientStop value) { var result = new YamlMap { { "OpacityPercent", value.OpacityPercent }, { "Offset", value.Offset }, }; return(result); }
/// <summary> /// Converts a list of <see cref="GradientStop"/>s into an equivalent list of /// <see cref="ColorGradientStop"/> of the same length, but with the opacity from any /// <see cref="OpacityGradientStop"/>s multiplied into the alpha channel of the /// <see cref="ColorGradientStop"/>s. /// The color and opacity values are calculated by interpolating from the surrounding stops. /// The result is ordered by offset. /// </summary> /// <returns>A list of <see cref="ColorGradientStop"/>s ordered by offset.</returns> public static IEnumerable <ColorGradientStop> Optimize(IEnumerable <GradientStop> stops) { // Order the stops. This is necessary because we will be searching forward in offset to find // the next stop of a particular type to use for interpolating colors and opacities. // If a color stop is at the same offset as an opacity stop, put the color stop first. var orderedStops = stops.OrderBy(s => s.Offset).ThenBy(s => s.Kind == GradientStop.GradientStopKind.Color ? 0 : 1).ToArray(); OpacityGradientStop previousOpacityStop = null; OpacityGradientStop nextOpacityStop = null; ColorGradientStop previousColorStop = null; ColorGradientStop nextColorStop = null; var foundLastColorStop = false; var foundLastOpacityStop = false; // Convert GradientStops into ColorGradientStops by interpolating the color or opacity values from // the surrounding GradientStops. for (var i = 0; i < orderedStops.Length; i++) { var currentStop = orderedStops[i]; // The stop is either an OpacityGradientStop or a ColorGradientStop. Convert to a ColorGradientStop // by interpolating the color or opacity as necessary. Color color; Opacity opacity; if (currentStop.Kind == GradientStop.GradientStopKind.Color) { // The stop is a ColorGradientStop. Get the color value directly from the stop, // and interpolate the opacity value from the surrounding OpacityGradientStops. var currentColorStop = previousColorStop = (ColorGradientStop)currentStop; color = currentColorStop.Color; // Invalidate nextColorStop to force a search for the next color stop. nextColorStop = null; // If there's an opacity stop at the same offset, it will be the next stop in the list. if (i + 1 < orderedStops.Length && orderedStops[i + 1].Offset == currentStop.Offset && orderedStops[i + 1].Kind == GradientStop.GradientStopKind.Opacity) { opacity = ((OpacityGradientStop)orderedStops[i + 1]).Opacity; } else { // Find the next opacity stop, if there is one. if (nextOpacityStop is null && !foundLastOpacityStop) { nextOpacityStop = (OpacityGradientStop)FindNextStopOfKind( orderedStops, i + 1, GradientStop.GradientStopKind.Opacity); if (nextOpacityStop is null) { // Indicate that we should not search again. foundLastOpacityStop = true; } } // Interpolate the opacity value from the surrounding stops. if (previousOpacityStop is null) { // There is no previous opacity stop. Use the next opacity // stop if there is one, or Opaque if there are no opacity stops. opacity = nextOpacityStop?.Opacity ?? Opacity.Opaque; } else { // If there's a following opacity stop, interpolate between previous // and next, otherwise continue using the previous opacity. opacity = nextOpacityStop is null ? previousOpacityStop.Opacity : InterpolateOpacity(previousOpacityStop, nextOpacityStop, currentStop.Offset); } } } else { // The stop is an OpacityGradientStop. Get the opacity value directly from the stop, // and interpolate the color value from the surrounding ColorStops. var currentOpacityStop = previousOpacityStop = (OpacityGradientStop)currentStop; opacity = previousOpacityStop.Opacity; // Invalidate nextOpacityStop to force a search for the next opacity stop. nextOpacityStop = null; // If there's a color stop at the same offset, it will be the previous stop in the list. if (i > 0 && orderedStops[i - 1].Offset == currentStop.Offset && orderedStops[i - 1].Kind == GradientStop.GradientStopKind.Color) { color = ((ColorGradientStop)orderedStops[i - 1]).Color; } else { // Find the next color stop, if there is one. if (nextColorStop is null && !foundLastColorStop) { nextColorStop = (ColorGradientStop)FindNextStopOfKind( orderedStops, i + 1, GradientStop.GradientStopKind.Color); if (nextColorStop is null) { // Indicate that we should not search again. foundLastColorStop = true; } } // Interpolate the color value from the surrounding stops. if (previousColorStop is null) { // There is no previous color. Use the next color, or black if there are no // colors. There should always be at least one color, so black is arbitrary. color = nextColorStop?.Color ?? Color.Black; } else { // If there's a following color stop, interpolate between previous // and next, otherwise continue using the previous color. color = nextColorStop is null ? previousColorStop.Color : InterpolateColor(previousColorStop, nextColorStop, currentStop.Offset); } } } yield return(new ColorGradientStop(currentStop.Offset, color * opacity)); } }