using System; using System.Xml; using System.Linq; using System.Text; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using SharpVectors.Dom.Svg; using SharpVectors.Dom.Css; using SharpVectors.Renderers.Utils; namespace SharpVectors.Renderers.Wpf { public sealed class WpfGradientFill : WpfFill { #region Private Fields private SvgGradientElement _gradientElement; #endregion #region Constructors and Destructor public WpfGradientFill(SvgGradientElement gradientElement) { _gradientElement = gradientElement; } #endregion #region Public Methods public override Brush GetBrush(WpfDrawingContext context) { if (_gradientElement is SvgLinearGradientElement) { return GetLinearGradientBrush((SvgLinearGradientElement)_gradientElement); } else if (_gradientElement is SvgRadialGradientElement) { return GetRadialGradientBrush((SvgRadialGradientElement)_gradientElement); } else { return new SolidColorBrush(Colors.Black); } } #endregion #region Private Methods private LinearGradientBrush GetLinearGradientBrush(SvgLinearGradientElement res) { double x1 = res.X1.AnimVal.Value; double x2 = res.X2.AnimVal.Value; double y1 = res.Y1.AnimVal.Value; double y2 = res.Y2.AnimVal.Value; GradientStopCollection gradientStops = GetGradientStops(res.Stops); LinearGradientBrush brush = new LinearGradientBrush(gradientStops, new Point(x1, y1), new Point(x2, y2)); SvgSpreadMethod spreadMethod = SvgSpreadMethod.None; if (res.SpreadMethod != null) { spreadMethod = (SvgSpreadMethod)res.SpreadMethod.AnimVal; if (spreadMethod != SvgSpreadMethod.None) { brush.SpreadMethod = WpfConvert.ToSpreadMethod(spreadMethod); } } if (res.GradientUnits != null) { SvgUnitType mappingMode = (SvgUnitType)res.GradientUnits.AnimVal; if (mappingMode == SvgUnitType.ObjectBoundingBox) { brush.MappingMode = BrushMappingMode.RelativeToBoundingBox; } else if (mappingMode == SvgUnitType.UserSpaceOnUse) { brush.MappingMode = BrushMappingMode.Absolute; } } MatrixTransform transform = GetTransformMatrix(res); if (transform != null && !transform.Matrix.IsIdentity) { brush.Transform = transform; } //else //{ // float fLeft = (float)res.X1.AnimVal.Value; // float fRight = (float)res.X2.AnimVal.Value; // float fTop = (float)res.Y1.AnimVal.Value; // float fBottom = (float)res.Y2.AnimVal.Value; // if (fTop == fBottom) // { // //mode = LinearGradientMode.Horizontal; // } // else // { // if (fLeft == fRight) // { // //mode = LinearGradientMode.Vertical; // } // else // { // if (fLeft < fRight) // { // //mode = LinearGradientMode.ForwardDiagonal; // brush.Transform = new RotateTransform(45, 0, 0); // //brush.EndPoint = new Point(x1, y1 + 1); // } // else // { // //mode = LinearGradientMode.BackwardDiagonal; // brush.Transform = new RotateTransform(-45); // } // } // } //} string colorInterpolation = res.GetPropertyValue("color-interpolation"); if (!String.IsNullOrEmpty(colorInterpolation)) { if (colorInterpolation == "linearRGB") { brush.ColorInterpolationMode = ColorInterpolationMode.ScRgbLinearInterpolation; } else { brush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; } } return brush; } private RadialGradientBrush GetRadialGradientBrush(SvgRadialGradientElement res) { double centerX = res.Cx.AnimVal.Value; double centerY = res.Cy.AnimVal.Value; double focusX = res.Fx.AnimVal.Value; double focusY = res.Fy.AnimVal.Value; double radius = res.R.AnimVal.Value; GradientStopCollection gradientStops = GetGradientStops(res.Stops); RadialGradientBrush brush = new RadialGradientBrush(gradientStops); brush.RadiusX = radius; brush.RadiusY = radius; brush.Center = new Point(centerX, centerY); brush.GradientOrigin = new Point(focusX, focusY); if (res.SpreadMethod != null) { SvgSpreadMethod spreadMethod = (SvgSpreadMethod)res.SpreadMethod.AnimVal; if (spreadMethod != SvgSpreadMethod.None) { brush.SpreadMethod = WpfConvert.ToSpreadMethod(spreadMethod); } } if (res.GradientUnits != null) { SvgUnitType mappingMode = (SvgUnitType)res.GradientUnits.AnimVal; if (mappingMode == SvgUnitType.ObjectBoundingBox) { brush.MappingMode = BrushMappingMode.RelativeToBoundingBox; } else if (mappingMode == SvgUnitType.UserSpaceOnUse) { brush.MappingMode = BrushMappingMode.Absolute; } } MatrixTransform transform = GetTransformMatrix(res); if (transform != null && !transform.Matrix.IsIdentity) { brush.Transform = transform; } string colorInterpolation = res.GetPropertyValue("color-interpolation"); if (!String.IsNullOrEmpty(colorInterpolation)) { if (colorInterpolation == "linearRGB") { brush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; } else { brush.ColorInterpolationMode = ColorInterpolationMode.ScRgbLinearInterpolation; } } return brush; } private MatrixTransform GetTransformMatrix(SvgGradientElement gradientElement) { SvgMatrix svgMatrix = ((SvgTransformList)gradientElement.GradientTransform.AnimVal).TotalMatrix; MatrixTransform transformMatrix = new MatrixTransform(svgMatrix.A, svgMatrix.B, svgMatrix.C, svgMatrix.D, svgMatrix.E, svgMatrix.F); return transformMatrix; } private GradientStopCollection GetGradientStops(XmlNodeList stops) { int itemCount = stops.Count; GradientStopCollection gradientStops = new GradientStopCollection(itemCount); double lastOffset = 0; for (int i = 0; i < itemCount; i++) { SvgStopElement stop = (SvgStopElement)stops.Item(i); string prop = stop.GetPropertyValue("stop-color"); WpfSvgColor svgColor = new WpfSvgColor(stop, "stop-color"); double offset = stop.Offset.AnimVal; offset /= 100; offset = Math.Max(lastOffset, offset); gradientStops.Add(new GradientStop(svgColor.Color, offset)); lastOffset = offset; } if (itemCount == 0) { gradientStops.Add(new GradientStop(Colors.Black, 0)); gradientStops.Add(new GradientStop(Colors.Black, 1)); } return gradientStops; } #endregion } }