/// <summary> /// Generate the XAML Path source code for a visual /// </summary> private static void GeneratePathGroup(GraphicVisual visual, StringBuilder result, int level, GeometryGeneratorType geometryGeneratorType) { switch (visual) { case GraphicGroup group: { var tag = "Grid"; var indentTag = SourceFormatterHelper.GetTagIndent(level); result.Append($"{indentTag}<{tag}"); bool tagIndent = false; if (!DoubleUtilities.IsEqual(group.Opacity, 1.0)) { tagIndent = true; string opac = string.Format(CultureInfo.InvariantCulture, " Opacity=\"{0}\"", DoubleUtilities.FormatString(group.Opacity)); result.Append(opac); } if (group.Clip != null) { if (tagIndent) { var indentProperty = SourceFormatterHelper.GetPropertyIndent(level, tag); result.AppendLine(); result.Append(indentProperty); } else { result.Append(" "); } result.Append(string.Format("Clip=\"")); var stream = StreamSourceGenerator.GenerateStreamGeometry(group.Clip); result.Append(stream); result.Append("\""); } result.AppendLine(">"); foreach (var childVisual in group.Children) { GeneratePathGroup(childVisual, result, level + 1, geometryGeneratorType); } result.AppendLine($"{indentTag}</{tag}>"); break; } case GraphicPath graphicPath: { result.AppendLine(GeneratePath(graphicPath, false, level, geometryGeneratorType)); break; } } }
/// <summary> /// Generate the XAML source code (a <Path/> for a single graphic path /// </summary> private static string GeneratePath(GraphicPath graphicPath, bool stretch, int level, GeometryGeneratorType geometryGeneratorType) { var tag = "Path"; var indentTag = SourceFormatterHelper.GetTagIndent(level); var indentProperty = SourceFormatterHelper.GetPropertyIndent(level, tag); StringBuilder result = new StringBuilder(); string stretchParam = stretch ? "Uniform" : "None"; result.Append($"{indentTag}<{tag} Stretch=\"{stretchParam}\""); bool fillColorInExtendedProperties = false; bool strokeColorInExtendedProperties = false; if (graphicPath.FillBrush != null) { if (graphicPath.FillBrush is GraphicSolidColorBrush solidFillColor) { result.AppendLine(); Color color = solidFillColor.Color; result.Append(indentProperty); result.Append(string.Format("Fill=\"{0}\"", SourceFormatterHelper.FormatColorParamter(color))); } else { fillColorInExtendedProperties = true; } } if (graphicPath.StrokeBrush != null) { if (graphicPath.StrokeBrush is GraphicSolidColorBrush solidStrokeColor) { result.AppendLine(); Color color = solidStrokeColor.Color; result.Append(indentProperty); result.Append(string.Format("Stroke=\"{0}\" ", SourceFormatterHelper.FormatColorParamter(color))); } else { strokeColorInExtendedProperties = true; } result.AppendLine(); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "StrokeThickness=\"{0}\" ", DoubleUtilities.FormatString(graphicPath.StrokeThickness))); if (graphicPath.StrokeLineCap != GraphicLineCap.Flat) { result.AppendLine(); result.Append(indentProperty); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "StrokeStartLineCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "StrokeEndLineCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); } if (graphicPath.StrokeDashes != null) { if (graphicPath.StrokeLineCap != GraphicLineCap.Flat) { result.AppendLine(); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "StrokeDashCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); } result.AppendLine(); result.Append(indentProperty); result.Append("StrokeDashArray=\""); for (int i = 0; i < graphicPath.StrokeDashes.Count; i++) { if (i != 0) { result.Append(" "); } result.Append(DoubleUtilities.FormatString(graphicPath.StrokeDashes[i])); } result.AppendLine("\""); if (!DoubleUtilities.IsZero(graphicPath.StrokeDashOffset)) { result.AppendLine(); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "StrokeDashOffset=\"{0}\"", DoubleUtilities.FormatString(graphicPath.StrokeDashOffset))); } } if (graphicPath.StrokeLineJoin != GraphicLineJoin.Miter) { result.AppendLine(); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "StrokeLineJoin=\"{0}\" ", Converter.ConvertToWpf(graphicPath.StrokeLineJoin).ToString())); } else if (!DoubleUtilities.IsEqual(graphicPath.StrokeMiterLimit, 10)) { result.AppendLine(); result.Append(indentProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "MiterLimit=\"{0}\"", DoubleUtilities.FormatString(graphicPath.StrokeMiterLimit))); } } if (geometryGeneratorType == GeometryGeneratorType.Stream) { result.AppendLine(); result.Append(indentProperty); result.Append("Data=\""); result.Append(StreamSourceGenerator.GenerateStreamGeometry(graphicPath.Geometry)); result.Append("\""); } if (geometryGeneratorType == GeometryGeneratorType.PathGeometry || fillColorInExtendedProperties || strokeColorInExtendedProperties) { result.AppendLine(">"); if (geometryGeneratorType == GeometryGeneratorType.PathGeometry) { var indent1 = SourceFormatterHelper.GetTagIndent(level + 1); result.Append(indent1); result.AppendLine("<Path.Data>"); PathGeometrySourceGenerator.GeneratePathGeometry(result, graphicPath.Geometry, level + 2); result.Append(indent1); result.AppendLine("</Path.Data>"); } if (fillColorInExtendedProperties) { BrushSourceGenerator.GenerateBrush(result, graphicPath.FillBrush, "Path.Fill", level + 1); } if (strokeColorInExtendedProperties) { BrushSourceGenerator.GenerateBrush(result, graphicPath.StrokeBrush, "Path.Stroke", level + 1); } result.Append(indentTag); result.Append($"</{tag}>"); } else { result.Append(" />"); } return(result.ToString()); }
/// <summary> /// Generate the source code for a complex brush /// </summary> public static void GenerateBrush(StringBuilder result, GraphicBrush graphicBrush, string element, int level) { var indentTag = SourceFormatterHelper.GetTagIndent(level); var indent1Tag = SourceFormatterHelper.GetTagIndent(level + 1); var indent2Tag = SourceFormatterHelper.GetTagIndent(level + 2); result.AppendLine(string.Format("{0}<{1}>", indentTag, element)); switch (graphicBrush) { case GraphicLinearGradientBrush linearGradientBrush: { var tag = "LinearGradientBrush"; var indentProperty = SourceFormatterHelper.GetPropertyIndent(level + 1, tag); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}<{1} StartPoint=\"{2}\"", indent1Tag, tag, SourceFormatterHelper.FormatPointParamter(linearGradientBrush.StartPoint))); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}EndPoint=\"{1}\"", indentProperty, SourceFormatterHelper.FormatPointParamter(linearGradientBrush.EndPoint))); if (linearGradientBrush.MappingMode != GraphicBrushMappingMode.RelativeToBoundingBox) { result.AppendLine(); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}MappingMode=\"{1}\"", indentProperty, Converter.ConvertToWpf(linearGradientBrush.MappingMode).ToString())); } result.AppendLine(">"); GenerateGradientStops(result, indent2Tag, linearGradientBrush.GradientStops); result.AppendLine(string.Format("{0}</{1}>", indent1Tag, tag)); break; } case GraphicRadialGradientBrush radialGradientBrush: { var tag = "RadialGradientBrush"; var indentProperty = SourceFormatterHelper.GetPropertyIndent(level + 1, tag); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}<{1} GradientOrigin=\"{2}\"", indent1Tag, tag, SourceFormatterHelper.FormatPointParamter(radialGradientBrush.StartPoint))); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}Center=\"{1}\"", indentProperty, SourceFormatterHelper.FormatPointParamter(radialGradientBrush.EndPoint))); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}RadiusX=\"{1}\"", indentProperty, DoubleUtilities.FormatString(radialGradientBrush.RadiusX))); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}RadiusY=\"{1}\"", indentProperty, DoubleUtilities.FormatString(radialGradientBrush.RadiusY))); if (radialGradientBrush.MappingMode != GraphicBrushMappingMode.RelativeToBoundingBox) { result.AppendLine(); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}MappingMode=\"{1}\"", indentProperty, Converter.ConvertToWpf(radialGradientBrush.MappingMode).ToString())); } result.AppendLine(">"); GenerateGradientStops(result, indent2Tag, radialGradientBrush.GradientStops); result.AppendLine(string.Format("{0}</{1}>", indent1Tag, tag)); break; } default: { result.AppendLine(string.Format("{0}<SolidColorBrush Color=\"#FFB0B0B0\" />", indent1Tag)); break; } } result.AppendLine(string.Format("{0}</{1}>", indentTag, element)); }
/// <summary> /// Generate the pen for a GeometryDrawing /// </summary> private static void GeneratePen(StringBuilder result, GraphicPath graphicPath, int level) { if (graphicPath.StrokeBrush != null) { var indent1 = SourceFormatterHelper.GetTagIndent(level); var indent2 = SourceFormatterHelper.GetTagIndent(level + 1); bool strokeColorInExtendedProperties = false; result.Append(indent1); result.AppendLine("<GeometryDrawing.Pen>"); var tag = "Pen"; var indentPenProperty = SourceFormatterHelper.GetPropertyIndent(level + 1, tag); result.Append(indent2); result.Append(string.Format(CultureInfo.InvariantCulture, "<{0} Thickness=\"{1}\"", tag, DoubleUtilities.FormatString(graphicPath.StrokeThickness))); if (graphicPath.StrokeLineCap != GraphicLineCap.Flat) { result.AppendLine(); result.Append(indentPenProperty); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "StartLineCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); result.Append(indentPenProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "EndLineCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); } if (graphicPath.StrokeDashes != null) { if (graphicPath.StrokeLineCap != GraphicLineCap.Square) { result.AppendLine(); result.Append(indentPenProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "DashCap=\"{0}\" ", Converter.ConvertToWPF(graphicPath.StrokeLineCap).ToString())); } } if (graphicPath.StrokeLineJoin != GraphicLineJoin.Miter) { result.AppendLine(); result.Append(indentPenProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "LineJoin=\"{0}\" ", Converter.ConvertToWpf(graphicPath.StrokeLineJoin).ToString())); } else if (!DoubleUtilities.IsEqual(graphicPath.StrokeMiterLimit, 10)) { result.AppendLine(); result.Append(indentPenProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "MiterLimit=\"{0}\"", DoubleUtilities.FormatString(graphicPath.StrokeMiterLimit))); } if (graphicPath.StrokeBrush is GraphicSolidColorBrush strokeColor) { result.AppendLine(); Color color = strokeColor.Color; result.Append(indentPenProperty); result.Append(string.Format("Brush=\"{0}\"", SourceFormatterHelper.FormatColorParamter(color))); } else { strokeColorInExtendedProperties = true; } if (strokeColorInExtendedProperties || graphicPath.StrokeDashes != null) { result.AppendLine(">"); if (graphicPath.StrokeDashes != null) { var indent3 = SourceFormatterHelper.GetTagIndent(level + 2); var indent4 = SourceFormatterHelper.GetTagIndent(level + 3); var tagDashStyle = "DashStyle"; result.Append(indent3); result.AppendLine($"<Pen.{tagDashStyle}>"); result.Append(indent4); result.Append($"<{tagDashStyle} Dashes=\""); for (int i = 0; i < graphicPath.StrokeDashes.Count; i++) { if (i != 0) { result.Append(" "); } result.Append(DoubleUtilities.FormatString(graphicPath.StrokeDashes[i])); } result.Append("\""); if (!DoubleUtilities.IsZero(graphicPath.StrokeDashOffset)) { var indentDashStyleProperty = SourceFormatterHelper.GetPropertyIndent(level + 3, tagDashStyle); result.AppendLine(); result.Append(indentDashStyleProperty); result.Append(string.Format(CultureInfo.InvariantCulture, "Offset=\"{0}\"", DoubleUtilities.FormatString(graphicPath.StrokeDashOffset))); } result.AppendLine("/>"); result.Append(indent3); result.AppendLine($"</Pen.{tagDashStyle}>"); } if (strokeColorInExtendedProperties) { BrushSourceGenerator.GenerateBrush(result, graphicPath.StrokeBrush, "Pen.Brush", level + 3); } result.AppendLine($"{indent2}</{tag}>"); } else { result.AppendLine(" />"); } result.Append(indent1); result.AppendLine("</GeometryDrawing.Pen>"); } }
/// <summary> /// Generate path /// </summary> private static void GeneratePath(GraphicPath graphicPath, StringBuilder result, int level, GeometryGeneratorType geometryGeneratorType) { var tag = "GeometryDrawing"; var indentTag = SourceFormatterHelper.GetTagIndent(level); var indentProperty = SourceFormatterHelper.GetPropertyIndent(level, tag); result.Append($"{indentTag}<{tag}"); bool fillColorInExtendedProperties = false; bool firstAttributSet = false; if (graphicPath.FillBrush != null) { if (graphicPath.FillBrush is GraphicSolidColorBrush solidFillColor) { firstAttributSet = true; Color color = solidFillColor.Color; var brush = string.Format(" Brush=\"{0}\"", SourceFormatterHelper.FormatColorParamter(color)); result.Append(brush); } else { fillColorInExtendedProperties = true; } } if (geometryGeneratorType == GeometryGeneratorType.Stream) { if (firstAttributSet) { result.AppendLine(); result.Append(indentProperty); } else { result.Append(" "); } result.Append(string.Format("Geometry=\"")); var stream = StreamSourceGenerator.GenerateStreamGeometry(graphicPath.Geometry); result.Append(stream); result.Append("\""); } if (geometryGeneratorType == GeometryGeneratorType.PathGeometry || fillColorInExtendedProperties || graphicPath.StrokeBrush != null) { result.AppendLine(">"); if (geometryGeneratorType == GeometryGeneratorType.PathGeometry) { var indent1 = SourceFormatterHelper.GetTagIndent(level + 1); result.Append(indent1); result.AppendLine("<GeometryDrawing.Geometry>"); PathGeometrySourceGenerator.GeneratePathGeometry(result, graphicPath.Geometry, level + 2); result.Append(indent1); result.AppendLine("</GeometryDrawing.Geometry>"); } if (fillColorInExtendedProperties) { BrushSourceGenerator.GenerateBrush(result, graphicPath.FillBrush, "GeometryDrawing.Brush", level + 1); } if (graphicPath.StrokeBrush != null) { GeneratePen(result, graphicPath, level + 1); } result.Append(indentTag); result.AppendLine("</GeometryDrawing>"); } else { result.AppendLine("/>"); } }
/// <summary> /// Generate the XAML source code for a PathGeometry plus an optional xKey attribute /// </summary> private static void GeneratePathGeometry(StringBuilder result, GraphicPathGeometry geometry, int level, string xKey) { bool finalizeLastFigure = false; var indent = SourceFormatterHelper.GetTagIndent(level); var indent1 = SourceFormatterHelper.GetTagIndent(level + 1); var indent2 = SourceFormatterHelper.GetTagIndent(level + 2); var pathGeometryTag = "PathGeometry"; string fillRule = string.Empty; switch (geometry.FillRule) { case GraphicFillRule.EvenOdd: fillRule = "EvenOdd"; break; case GraphicFillRule.NoneZero: fillRule = "Nonzero"; break; } if (string.IsNullOrEmpty(xKey)) { result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}<{1} FillRule=\"{2}\">", indent, pathGeometryTag, fillRule)); } else { var indentPathGeometryProperty = SourceFormatterHelper.GetPropertyIndent(level, pathGeometryTag); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}<{1} x:Key=\"{2}\"", indent, pathGeometryTag, xKey)); result.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}FillRule=\"{1}\">", indentPathGeometryProperty, fillRule)); } var pathFigureTag = "PathFigure"; foreach (var segment in geometry.Segments) { switch (segment) { case GraphicMoveSegment graphicMove: { if (finalizeLastFigure) { result.Append(indent1); result.AppendLine("</PathFigure>"); } var indentPathFigureProperty = SourceFormatterHelper.GetPropertyIndent(level + 1, pathFigureTag); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}<{1} IsClosed=", indent1, pathFigureTag)); SourceFormatterHelper.AppendXamlBool(result, graphicMove.IsClosed); result.AppendLine(); result.Append(indentPathFigureProperty); result.Append("StartPoint="); SourceFormatterHelper.AppendXamlPoint(result, graphicMove.StartPoint.X, graphicMove.StartPoint.Y); result.AppendLine(">"); finalizeLastFigure = true; break; } case GraphicLineSegment graphicLineTo: { result.Append(indent2); result.Append("<LineSegment Point="); SourceFormatterHelper.AppendXamlPoint(result, graphicLineTo.To); result.AppendLine(" />"); break; } case GraphicCubicBezierSegment graphicCubicBezier: { var tag = "BezierSegment"; var indentProperty = SourceFormatterHelper.GetPropertyIndent(level + 2, tag); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}<{1} Point1=", indent2, tag)); SourceFormatterHelper.AppendXamlPoint(result, graphicCubicBezier.ControlPoint1); result.AppendLine(); result.Append(indentProperty); result.Append("Point2="); SourceFormatterHelper.AppendXamlPoint(result, graphicCubicBezier.ControlPoint2); result.AppendLine(); result.Append(indentProperty); result.Append("Point3="); SourceFormatterHelper.AppendXamlPoint(result, graphicCubicBezier.EndPoint); result.AppendLine(" />"); break; } case GraphicQuadraticBezierSegment graphicQuadraticBezier: { var tag = "QuadraticBezierSegment"; var indentProperty = SourceFormatterHelper.GetPropertyIndent(level + 2, tag); result.Append(string.Format(CultureInfo.InvariantCulture, "{0}<{1} Point1=", indent2, tag)); SourceFormatterHelper.AppendXamlPoint(result, graphicQuadraticBezier.ControlPoint); result.AppendLine(); result.Append(indentProperty); result.Append("Point2="); SourceFormatterHelper.AppendXamlPoint(result, graphicQuadraticBezier.EndPoint); result.AppendLine(" />"); break; } default: break; } } if (finalizeLastFigure) { result.Append(indent1); result.AppendLine($"</{pathFigureTag}>"); } result.AppendLine($"{indent}</{pathGeometryTag}>"); }