diff --git a/src/SvgToXaml.Base/ViewModels/MainWindowViewModel.cs b/src/SvgToXaml.Base/ViewModels/MainWindowViewModel.cs index caf2fdd..740a47d 100644 --- a/src/SvgToXaml.Base/ViewModels/MainWindowViewModel.cs +++ b/src/SvgToXaml.Base/ViewModels/MainWindowViewModel.cs @@ -451,6 +451,7 @@ private async Task Clipboard(string? format) { UseCompatMode = Project.Settings.UseCompatMode, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; @@ -463,6 +464,7 @@ private async Task Clipboard(string? format) { UseCompatMode = Project.Settings.UseCompatMode, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; @@ -540,6 +542,7 @@ private async Task ToXaml(FileItemViewModel fileItemViewModel, bool enab UseCompatMode = Project.Settings.UseCompatMode, AddTransparentBackground = Project.Settings.AddTransparentBackground, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; @@ -553,6 +556,7 @@ private async Task ToXaml(FileItemViewModel fileItemViewModel, bool enab UseCompatMode = Project.Settings.UseCompatMode, AddTransparentBackground = Project.Settings.AddTransparentBackground, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; @@ -573,6 +577,7 @@ private async Task ToXamlStyles(List inputItems) { UseCompatMode = Project.Settings.UseCompatMode, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; @@ -638,6 +643,7 @@ public record PreviewItem(string Image, string TabControl); { UseCompatMode = Project.Settings.UseCompatMode, ReuseExistingResources = Project.Settings.ReuseExistingResources, + TransformGeometry = Project.Settings.TransformGeometry, Resources = Project.Settings.UseResources ? new ResourceDictionary() : null }; diff --git a/src/SvgToXaml.Base/ViewModels/ProjectViewModel.cs b/src/SvgToXaml.Base/ViewModels/ProjectViewModel.cs index 9a1107e..113016f 100644 --- a/src/SvgToXaml.Base/ViewModels/ProjectViewModel.cs +++ b/src/SvgToXaml.Base/ViewModels/ProjectViewModel.cs @@ -42,6 +42,7 @@ public ProjectViewModel() EnableGeneratePreview = true, UseResources = true, ReuseExistingResources = true, + TransformGeometry = true, UseCompatMode = false, AddTransparentBackground = true, IgnoreOpacity = false, diff --git a/src/SvgToXaml.Base/ViewModels/SettingsViewModel.cs b/src/SvgToXaml.Base/ViewModels/SettingsViewModel.cs index 6d57334..740f9a4 100644 --- a/src/SvgToXaml.Base/ViewModels/SettingsViewModel.cs +++ b/src/SvgToXaml.Base/ViewModels/SettingsViewModel.cs @@ -8,6 +8,7 @@ public class SettingsViewModel : ViewModelBase private bool _enableGeneratePreview; private bool _useResources; private bool _reuseExistingResources; + private bool _transformGeometry; private bool _useCompatMode; private bool _addTransparentBackground; private bool _ignoreOpacity; @@ -43,6 +44,13 @@ public bool ReuseExistingResources set => SetProperty(ref _reuseExistingResources, value); } + [JsonInclude] + public bool TransformGeometry + { + get => _transformGeometry; + set => SetProperty(ref _transformGeometry, value); + } + [JsonInclude] public bool UseCompatMode { diff --git a/src/SvgToXaml.Base/Views/SettingsView.axaml b/src/SvgToXaml.Base/Views/SettingsView.axaml index 85360ac..55e3bbf 100644 --- a/src/SvgToXaml.Base/Views/SettingsView.axaml +++ b/src/SvgToXaml.Base/Views/SettingsView.axaml @@ -37,6 +37,12 @@ HorizontalContentAlignment="Stretch" Margin="0" Padding="6"/> + Generate(solidColorBrush, context), - LinearGradientBrush linearGradientBrush => Generate(linearGradientBrush, context), - RadialGradientBrush radialGradientBrush => Generate(radialGradientBrush, context), - TwoPointConicalGradientBrush twoPointConicalGradientBrush => Generate(twoPointConicalGradientBrush, context), - PictureBrush pictureBrush => Generate(pictureBrush, context), + SolidColorBrush solidColorBrush => GenerateSolidColorBrush(solidColorBrush, settings), + LinearGradientBrush linearGradientBrush => GenerateLinearGradientBrush(linearGradientBrush, settings), + RadialGradientBrush radialGradientBrush => GenerateRadialGradientBrush(radialGradientBrush, settings), + TwoPointConicalGradientBrush twoPointConicalGradientBrush => GenerateTwoPointConicalGradientBrush(twoPointConicalGradientBrush, settings), + PictureBrush pictureBrush => GeneratePictureBrush(pictureBrush, settings), _ => "" }; } - public override string Generate(SolidColorBrush solidColorBrush, GeneratorContext context) + private string GenerateSolidColorBrush(SolidColorBrush solidColorBrush, XamlGeneratorSettings settings) { var sb = new StringBuilder(); sb.Append($"{context.NewLine}"); + sb.Append($"/>{settings.NewLine}"); return sb.ToString(); } - public override string Generate(LinearGradientBrush linearGradientBrush, GeneratorContext context) + private string GenerateLinearGradientBrush(LinearGradientBrush linearGradientBrush, XamlGeneratorSettings settings) { var sb = new StringBuilder(); @@ -182,42 +183,42 @@ public override string Generate(LinearGradientBrush linearGradientBrush, Generat sb.Append($" SpreadMethod=\"{ToGradientSpreadMethod(linearGradientBrush.Mode)}\""); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" MappingMode=\"Absolute\""); } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); if (linearGradientBrush.LocalMatrix is { }) { var localMatrix = linearGradientBrush.LocalMatrix.Value; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (linearGradientBrush.GradientStops.Count > 0) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); foreach (var stop in linearGradientBrush.GradientStops) { var color = ToHexColor(stop.Color); var offset = ToXamlString(stop.Offset); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); return sb.ToString(); } - public override string Generate(RadialGradientBrush radialGradientBrush, GeneratorContext context) + private string GenerateRadialGradientBrush(RadialGradientBrush radialGradientBrush, XamlGeneratorSettings settings) { var sb = new StringBuilder(); @@ -226,7 +227,7 @@ public override string Generate(RadialGradientBrush radialGradientBrush, Generat var center = radialGradientBrush.Center; var gradientOrigin = radialGradientBrush.Center; - if (!context.UseCompatMode) + if (!settings.UseCompatMode) { radius = radius / radialGradientBrush.Bounds.Width; } @@ -236,7 +237,7 @@ public override string Generate(RadialGradientBrush radialGradientBrush, Generat sb.Append($" Center=\"{ToPoint(center)}\""); sb.Append($" GradientOrigin=\"{ToPoint(gradientOrigin)}\""); - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" RadiusX=\"{ToXamlString(radius)}\""); sb.Append($" RadiusY=\"{ToXamlString(radius)}\""); @@ -246,7 +247,7 @@ public override string Generate(RadialGradientBrush radialGradientBrush, Generat sb.Append($" Radius=\"{ToXamlString(radius)}\""); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" MappingMode=\"Absolute\""); } @@ -256,37 +257,37 @@ public override string Generate(RadialGradientBrush radialGradientBrush, Generat sb.Append($" SpreadMethod=\"{ToGradientSpreadMethod(radialGradientBrush.Mode)}\""); } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); if (radialGradientBrush.LocalMatrix is { }) { var localMatrix = radialGradientBrush.LocalMatrix.Value; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (radialGradientBrush.GradientStops.Count > 0) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); foreach (var stop in radialGradientBrush.GradientStops) { var color = ToHexColor(stop.Color); var offset = ToXamlString(stop.Offset); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); return sb.ToString(); } - public override string Generate(TwoPointConicalGradientBrush twoPointConicalGradientBrush, GeneratorContext context) + private string GenerateTwoPointConicalGradientBrush(TwoPointConicalGradientBrush twoPointConicalGradientBrush, XamlGeneratorSettings settings) { var sb = new StringBuilder(); @@ -301,7 +302,7 @@ public override string Generate(TwoPointConicalGradientBrush twoPointConicalGrad var center = twoPointConicalGradientBrush.End; var gradientOrigin = twoPointConicalGradientBrush.Start; - if (!context.UseCompatMode) + if (!settings.UseCompatMode) { endRadius = endRadius / twoPointConicalGradientBrush.Bounds.Width; } @@ -311,7 +312,7 @@ public override string Generate(TwoPointConicalGradientBrush twoPointConicalGrad sb.Append($" Center=\"{ToPoint(center)}\""); sb.Append($" GradientOrigin=\"{ToPoint(gradientOrigin)}\""); - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" RadiusX=\"{ToXamlString(endRadius)}\""); sb.Append($" RadiusY=\"{ToXamlString(endRadius)}\""); @@ -321,7 +322,7 @@ public override string Generate(TwoPointConicalGradientBrush twoPointConicalGrad sb.Append($" Radius=\"{ToXamlString(endRadius)}\""); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" MappingMode=\"Absolute\""); } @@ -331,37 +332,37 @@ public override string Generate(TwoPointConicalGradientBrush twoPointConicalGrad sb.Append($" SpreadMethod=\"{ToGradientSpreadMethod(twoPointConicalGradientBrush.Mode)}\""); } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); if (twoPointConicalGradientBrush.LocalMatrix is { }) { var localMatrix = twoPointConicalGradientBrush.LocalMatrix.Value; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (twoPointConicalGradientBrush.GradientStops.Count > 0) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); foreach (var stop in twoPointConicalGradientBrush.GradientStops) { var color = ToHexColor(stop.Color); var offset = ToXamlString(stop.Offset); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); return sb.ToString(); } - public override string Generate(PictureBrush pictureBrush, GeneratorContext context) + private string GeneratePictureBrush(PictureBrush pictureBrush, XamlGeneratorSettings settings) { if (pictureBrush.Picture is null) { @@ -381,7 +382,7 @@ public override string Generate(PictureBrush pictureBrush, GeneratorContext cont sb.Append($" TileMode=\"{ToTileMode(pictureBrush.TileMode)}\""); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { if (!sourceRect.IsEmpty) { @@ -406,31 +407,31 @@ public override string Generate(PictureBrush pictureBrush, GeneratorContext cont } } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); if (pictureBrush.LocalMatrix is { }) { var localMatrix = pictureBrush.LocalMatrix.Value; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (pictureBrush.Picture is not null) { - sb.Append($" {context.NewLine}"); - sb.Append(Generate(pictureBrush.Picture, context with { WriteResources = false, AddTransparentBackground = false })); - sb.Append($"{context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append(GenerateImage(pictureBrush.Picture, settings with { WriteResources = false, AddTransparentBackground = false }, SkiaSharp.SKMatrix.CreateIdentity())); + sb.Append($"{settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); return sb.ToString(); } - public override string Generate(Pen pen, GeneratorContext context) + private string GeneratePen(Pen pen, XamlGeneratorSettings settings) { if (pen.Brush is null) { @@ -454,7 +455,7 @@ public override string Generate(Pen pen, GeneratorContext context) if (pen.StrokeCap != ShimSkiaSharp.SKStrokeCap.Butt) { - if (context.UseCompatMode) + if (settings.UseCompatMode) { sb.Append($" StartLineCap=\"{ToPenLineCap(pen.StrokeCap)}\""); sb.Append($" EndLineCap=\"{ToPenLineCap(pen.StrokeCap)}\""); @@ -465,7 +466,7 @@ public override string Generate(Pen pen, GeneratorContext context) } } - if (context.UseCompatMode) + if (settings.UseCompatMode) { if (pen.Dashes is { Intervals: { } }) { @@ -488,7 +489,7 @@ public override string Generate(Pen pen, GeneratorContext context) } } - if (context.UseCompatMode) + if (settings.UseCompatMode) { var miterLimit = pen.StrokeMiter; var strokeWidth = pen.StrokeWidth; @@ -522,11 +523,11 @@ public override string Generate(Pen pen, GeneratorContext context) if (pen.Brush is not SolidColorBrush || pen.Dashes is { Intervals: { } }) { - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); } else { - sb.Append($"/>{context.NewLine}"); + sb.Append($"/>{settings.NewLine}"); } if (pen.Dashes is { Intervals: { } }) @@ -540,38 +541,38 @@ public override string Generate(Pen pen, GeneratorContext context) var offset = pen.Dashes.Phase / pen.StrokeWidth; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (pen.Brush is not SolidColorBrush) { - sb.Append($" {context.NewLine}"); - sb.Append(Generate(pen.Brush, context)); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append(GenerateBrush(pen.Brush, settings)); + sb.Append($" {settings.NewLine}"); } if (pen.Brush is not SolidColorBrush || pen.Dashes is { Intervals: { } }) { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } return sb.ToString(); } - public override string Generate(Drawing drawing, GeneratorContext context) + private string GenerateDrawing(Drawing drawing, XamlGeneratorSettings settings, SkiaSharp.SKMatrix? matrix) { return drawing switch { - GeometryDrawing geometryDrawing => Generate(geometryDrawing, context), - DrawingGroup drawingGroup => Generate(drawingGroup, context), - DrawingImage drawingImage => Generate(drawingImage, context), + GeometryDrawing geometryDrawing => GenerateGeometryDrawing(geometryDrawing, settings, matrix), + DrawingGroup drawingGroup => GenerateDrawingGroup(drawingGroup, settings), + DrawingImage drawingImage => GenerateDrawingImage(drawingImage, settings, matrix), _ => "" }; } - public override string Generate(GeometryDrawing geometryDrawing, GeneratorContext context) + private string GenerateGeometryDrawing(GeometryDrawing geometryDrawing, XamlGeneratorSettings settings, SkiaSharp.SKMatrix? matrix) { if (geometryDrawing.Paint is null || geometryDrawing.Geometry is null) { @@ -585,7 +586,7 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex var isFilled = geometryDrawing.Brush is { }; var isStroked = geometryDrawing.Pen is { }; - if (isFilled && geometryDrawing.Brush is SolidColorBrush solidColorBrush && context.Resources is null) + if (isFilled && geometryDrawing.Brush is SolidColorBrush solidColorBrush && settings.Resources is null) { sb.Append($" Brush=\"{ToHexColor(solidColorBrush.Color)}\""); } @@ -593,18 +594,18 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex var brush = default(Brush); var pen = default(Pen); - if (isFilled && geometryDrawing.Brush is { } and not SolidColorBrush && context.Resources is null) + if (isFilled && geometryDrawing.Brush is { } and not SolidColorBrush && settings.Resources is null) { brush =geometryDrawing. Brush; } - if (isFilled && geometryDrawing.Paint is { } && context.Resources is { }) + if (isFilled && geometryDrawing.Paint is { } && settings.Resources is { }) { bool haveBrush = false; - if (context.ReuseExistingResources) + if (settings.ReuseExistingResources) { - var existingBrush = context.Resources.Brushes.FirstOrDefault(x => + var existingBrush = settings.Resources.Brushes.FirstOrDefault(x => { if (x.Value.Paint.Shader is { } && x.Value.Paint.Shader.Equals(geometryDrawing.Paint.Shader)) { @@ -616,7 +617,7 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex if (!string.IsNullOrEmpty(existingBrush.Key)) { - context.Resources.UseBrushes.Add(existingBrush.Value.Brush); + settings.Resources.UseBrushes.Add(existingBrush.Value.Brush); sb.Append($" Brush=\"{{DynamicResource {existingBrush.Key}}}\""); haveBrush = true; } @@ -624,9 +625,9 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex if (!haveBrush) { - if (geometryDrawing.Brush is { } && context.Resources is { } && geometryDrawing.Brush.Key is { }) + if (geometryDrawing.Brush is { } && settings.Resources is { } && geometryDrawing.Brush.Key is { }) { - context.Resources.UseBrushes.Add(geometryDrawing.Brush); + settings.Resources.UseBrushes.Add(geometryDrawing.Brush); sb.Append($" Brush=\"{{DynamicResource {geometryDrawing.Brush.Key}}}\""); haveBrush = true; } @@ -638,18 +639,18 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex } } - if (isStroked && geometryDrawing.Pen is { } && context.Resources is null) + if (isStroked && geometryDrawing.Pen is { } && settings.Resources is null) { pen = geometryDrawing.Pen; } - if (isStroked && geometryDrawing.Paint is { } && context.Resources is { }) + if (isStroked && geometryDrawing.Paint is { } && settings.Resources is { }) { bool havePen = false; - if (context.ReuseExistingResources) + if (settings.ReuseExistingResources) { - var existingPen = context.Resources.Pens.FirstOrDefault(x => + var existingPen = settings.Resources.Pens.FirstOrDefault(x => { if (x.Value.Paint.Shader is { } && x.Value.Paint.Shader.Equals(geometryDrawing.Paint.Shader) @@ -667,7 +668,7 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex if (!string.IsNullOrEmpty(existingPen.Key)) { - context.Resources.UsePens.Add(existingPen.Value.Pen); + settings.Resources.UsePens.Add(existingPen.Value.Pen); sb.Append($" Pen=\"{{DynamicResource {existingPen.Key}}}\""); havePen = true; } @@ -675,9 +676,9 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex if (!havePen) { - if (geometryDrawing.Pen is { } && context.Resources is { } && geometryDrawing.Pen.Key is { }) + if (geometryDrawing.Pen is { } && settings.Resources is { } && geometryDrawing.Pen.Key is { }) { - context.Resources.UsePens.Add(geometryDrawing.Pen); + settings.Resources.UsePens.Add(geometryDrawing.Pen); sb.Append($" Pen=\"{{DynamicResource {geometryDrawing.Pen.Key}}}\""); havePen = true; } @@ -691,41 +692,41 @@ public override string Generate(GeometryDrawing geometryDrawing, GeneratorContex if (geometryDrawing.Geometry is { }) { - sb.Append($" Geometry=\"{ToSvgPathData(geometryDrawing.Geometry)}\""); + sb.Append($" Geometry=\"{ToSvgPathData(geometryDrawing.Geometry, matrix ?? SkiaSharp.SKMatrix.CreateIdentity())}\""); } if (brush is { } || pen is { }) { - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); } else { - sb.Append($"/>{context.NewLine}"); + sb.Append($"/>{settings.NewLine}"); } if (brush is { }) { - sb.Append($" {context.NewLine}"); - sb.Append(Generate(brush, context)); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append(GenerateBrush(brush, settings)); + sb.Append($" {settings.NewLine}"); } if (pen is { }) { - sb.Append($" {context.NewLine}"); - sb.Append(Generate(pen, context)); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append(GeneratePen(pen, settings)); + sb.Append($" {settings.NewLine}"); } if (brush is { } || pen is { }) { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } return sb.ToString(); } - public override string Generate(DrawingGroup drawingGroup, GeneratorContext context) + public string GenerateDrawingGroup(DrawingGroup drawingGroup, XamlGeneratorSettings settings) { var sb = new StringBuilder(); @@ -736,34 +737,34 @@ public override string Generate(DrawingGroup drawingGroup, GeneratorContext cont sb.Append($" Opacity=\"{ToXamlString(drawingGroup.Opacity.Value)}\""); } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); if (drawingGroup.ClipGeometry is { }) { - var clipGeometry = ToSvgPathData(drawingGroup.ClipGeometry); + var clipGeometry = ToSvgPathData(drawingGroup.ClipGeometry, SkiaSharp.SKMatrix.CreateIdentity()); - sb.Append($" {context.NewLine}"); - sb.Append($" {clipGeometry}{context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {clipGeometry}{settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } - if (drawingGroup.Transform is { }) + if (drawingGroup.Transform is { } && !settings.TransformGeometry) { var matrix = drawingGroup.Transform.Value; - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } if (drawingGroup.OpacityMask is { }) { - sb.Append($"{context.NewLine}"); - sb.Append(Generate(drawingGroup.OpacityMask, context)); - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); + sb.Append(GenerateBrush(drawingGroup.OpacityMask, settings)); + sb.Append($"{settings.NewLine}"); } - if (context.AddTransparentBackground && drawingGroup.Picture is { }) + if (settings.AddTransparentBackground && drawingGroup.Picture is { }) { var left = drawingGroup.Picture.CullRect.Left; var top = drawingGroup.Picture.CullRect.Top; @@ -776,12 +777,12 @@ public override string Generate(DrawingGroup drawingGroup, GeneratorContext cont sb.Append($"L{ToXamlString(right)},{ToXamlString(bottom)}"); sb.Append($"L{ToXamlString(left)},{ToXamlString(bottom)}"); sb.Append($"z\" "); - sb.Append($"/>{context.NewLine}"); + sb.Append($"/>{settings.NewLine}"); } foreach (var child in drawingGroup.Children) { - sb.Append(Generate(child, context)); + sb.Append(GenerateDrawing(child, settings, settings.TransformGeometry ? drawingGroup.Transform : null)); } sb.Append($""); @@ -789,7 +790,7 @@ public override string Generate(DrawingGroup drawingGroup, GeneratorContext cont return sb.ToString(); } - public override string Generate(DrawingImage drawingImage, GeneratorContext context) + private string GenerateDrawingImage(DrawingImage drawingImage, XamlGeneratorSettings settings, SkiaSharp.SKMatrix? matrix) { if (drawingImage.Drawing is null) { @@ -798,76 +799,76 @@ public override string Generate(DrawingImage drawingImage, GeneratorContext cont var sb = new StringBuilder(); - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append(Generate(drawingImage.Drawing, context)); + sb.Append(GenerateDrawing(drawingImage.Drawing, settings, matrix)); - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); return sb.ToString(); } - public override string Generate(Resource resource, GeneratorContext context) + private string GenerateResource(Resource resource, XamlGeneratorSettings settings, SkiaSharp.SKMatrix? matrix) { return resource switch { - SolidColorBrush solidColorBrush => Generate(solidColorBrush, context), - LinearGradientBrush linearGradientBrush => Generate(linearGradientBrush, context), - RadialGradientBrush radialGradientBrush => Generate(radialGradientBrush, context), - TwoPointConicalGradientBrush twoPointConicalGradientBrush => Generate(twoPointConicalGradientBrush, context), - PictureBrush pictureBrush => Generate(pictureBrush, context), - Pen pen => Generate(pen, context), - GeometryDrawing geometryDrawing => Generate(geometryDrawing, context), - DrawingGroup drawingGroup => Generate(drawingGroup, context), - DrawingImage drawingImage => Generate(drawingImage, context), - Image image => Generate(image, context), + SolidColorBrush solidColorBrush => GenerateSolidColorBrush(solidColorBrush, settings), + LinearGradientBrush linearGradientBrush => GenerateLinearGradientBrush(linearGradientBrush, settings), + RadialGradientBrush radialGradientBrush => GenerateRadialGradientBrush(radialGradientBrush, settings), + TwoPointConicalGradientBrush twoPointConicalGradientBrush => GenerateTwoPointConicalGradientBrush(twoPointConicalGradientBrush, settings), + PictureBrush pictureBrush => GeneratePictureBrush(pictureBrush, settings), + Pen pen => GeneratePen(pen, settings), + GeometryDrawing geometryDrawing => GenerateGeometryDrawing(geometryDrawing, settings, matrix), + DrawingGroup drawingGroup => GenerateDrawingGroup(drawingGroup, settings), + DrawingImage drawingImage => GenerateDrawingImage(drawingImage, settings, matrix), + Image image => GenerateImage(image, settings, matrix), _ => "" }; } - public override string Generate(ResourceDictionary resourceDictionary, GeneratorContext context) + private string GenerateResourceDictionary(ResourceDictionary resourceDictionary, XamlGeneratorSettings settings) { var sb = new StringBuilder(); - if (context.ReuseExistingResources) + if (settings.ReuseExistingResources) { foreach (var resource in resourceDictionary.UseBrushes) { - sb.Append(Generate(resource, context)); + sb.Append(GenerateBrush(resource, settings)); } foreach (var resource in resourceDictionary.UsePens) { - sb.Append(Generate(resource, context)); + sb.Append(GeneratePen(resource, settings)); } } else { foreach (var resource in resourceDictionary.Brushes) { - sb.Append(Generate(resource.Value.Brush, context)); + sb.Append(GenerateBrush(resource.Value.Brush, settings)); } foreach (var resource in resourceDictionary.Pens) { - sb.Append(Generate(resource.Value.Pen, context)); + sb.Append(GeneratePen(resource.Value.Pen, settings)); } } return sb.ToString(); } - public override string Generate(Image image, GeneratorContext context) + public string GenerateImage(Image image, XamlGeneratorSettings settings, SkiaSharp.SKMatrix? matrix) { if (image.Source is null) { @@ -876,37 +877,37 @@ public override string Generate(Image image, GeneratorContext context) var sb = new StringBuilder(); - var content = Generate(image.Source, context); + var content = GenerateDrawingImage(image.Source, settings, matrix); sb.Append($" 0 || context.Resources.Pens.Count > 0) && context.WriteResources) + if (settings.Resources is { } && (settings.Resources.Brushes.Count > 0 || settings.Resources.Pens.Count > 0) && settings.WriteResources) { - // sb.Append(context.UseCompatMode + // sb.Append(settings.UseCompatMode // ? $" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"" // : $" xmlns=\"https://github.com/avaloniaui\""); // sb.Append($" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\""); } - sb.Append($">{context.NewLine}"); + sb.Append($">{settings.NewLine}"); - if (context.Resources is { } && (context.Resources.Brushes.Count > 0 || context.Resources.Pens.Count > 0) && context.WriteResources) + if (settings.Resources is { } && (settings.Resources.Brushes.Count > 0 || settings.Resources.Pens.Count > 0) && settings.WriteResources) { - sb.Append($"{context.NewLine}"); - sb.Append(Generate(context.Resources, context with { WriteResources = false, AddTransparentBackground = false })); - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); + sb.Append(GenerateResourceDictionary(settings.Resources, settings with { WriteResources = false, AddTransparentBackground = false })); + sb.Append($"{settings.NewLine}"); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } sb.Append(content); - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } sb.Append($""); @@ -914,7 +915,7 @@ public override string Generate(Image image, GeneratorContext context) return sb.ToString(); } - public override string Generate(Styles styles, GeneratorContext context) + public string GenerateStyles(Styles styles, XamlGeneratorSettings settings) { if (styles.Resources is null) { @@ -927,80 +928,80 @@ public override string Generate(Styles styles, GeneratorContext context) foreach (var result in styles.Resources) { - content.Append(Generate(result, context with { WriteResources = false, AddTransparentBackground = false })); - content.Append(context.NewLine); + content.Append(GenerateResource(result, settings with { WriteResources = false, AddTransparentBackground = false }, SkiaSharp.SKMatrix.CreateIdentity())); + content.Append(settings.NewLine); } - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } else { - sb.Append($"{context.NewLine}"); + sb.Append($"{settings.NewLine}"); } - if (styles.GeneratePreview && !context.UseCompatMode) + if (styles.GeneratePreview && !settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); foreach (var result in styles.Resources) { if (styles.GenerateImage) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } else { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); - if (context.UseCompatMode) + if (settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); } } - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); - sb.Append($" {context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); } - if (!context.UseCompatMode) + if (!settings.UseCompatMode) { - sb.Append($" {context.NewLine}"); - sb.Append($"{context.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($" {settings.NewLine}"); + sb.Append($"{settings.NewLine}"); } return sb.ToString(); diff --git a/src/SvgToXamlConverter/Generator/GeneratorContext.cs b/src/SvgToXamlConverter/Generator/XamlGeneratorSettings.cs similarity index 72% rename from src/SvgToXamlConverter/Generator/GeneratorContext.cs rename to src/SvgToXamlConverter/Generator/XamlGeneratorSettings.cs index bc1f8e6..6b68e8b 100644 --- a/src/SvgToXamlConverter/Generator/GeneratorContext.cs +++ b/src/SvgToXamlConverter/Generator/XamlGeneratorSettings.cs @@ -2,7 +2,7 @@ namespace SvgToXamlConverter.Generator; -public record GeneratorContext +public record XamlGeneratorSettings { public string NewLine { get; init; } = "\r\n"; @@ -12,7 +12,9 @@ public record GeneratorContext public bool ReuseExistingResources { get; init; } = false; - public bool WriteResources { get; init; } = false; + public bool TransformGeometry { get; init; } = true; + + public bool WriteResources { get; init; } = false; public ResourceDictionary? Resources { get; init; } } diff --git a/src/SvgToXamlConverter/Model/Drawing/GeometryDrawing.cs b/src/SvgToXamlConverter/Model/Drawing/GeometryDrawing.cs index fd0e38c..3ab2087 100644 --- a/src/SvgToXamlConverter/Model/Drawing/GeometryDrawing.cs +++ b/src/SvgToXamlConverter/Model/Drawing/GeometryDrawing.cs @@ -13,7 +13,10 @@ public record GeometryDrawing : Drawing public Pen? Pen { get; } - public GeometryDrawing(ShimSkiaSharp.SKPaint? paint = null, SkiaSharp.SKPath? geometry = null, ResourceDictionary? resources = null) + public GeometryDrawing( + ShimSkiaSharp.SKPaint? paint = null, + SkiaSharp.SKPath? geometry = null, + ResourceDictionary? resources = null) { Paint = paint; Geometry = geometry; @@ -49,4 +52,4 @@ public GeometryDrawing(ShimSkiaSharp.SKPaint? paint = null, SkiaSharp.SKPath? ge } } } -} \ No newline at end of file +} diff --git a/src/SvgToXamlConverter/SvgToXamlConverter.cs b/src/SvgToXamlConverter/SvgToXamlConverter.cs index 201ce5a..837e811 100644 --- a/src/SvgToXamlConverter/SvgToXamlConverter.cs +++ b/src/SvgToXamlConverter/SvgToXamlConverter.cs @@ -22,23 +22,26 @@ public class SvgToXamlConverter public bool ReuseExistingResources { get; set; } + public bool TransformGeometry { get; set; } + public ResourceDictionary? Resources { get; set; } public string ToXamlDrawingGroup(ShimSkiaSharp.SKPicture? skPicture, string? key = null) { var drawingGroup = new DrawingGroup(skPicture, Resources, key); - var context = new GeneratorContext + var context = new XamlGeneratorSettings { NewLine = NewLine, UseCompatMode = UseCompatMode, AddTransparentBackground = AddTransparentBackground, ReuseExistingResources = ReuseExistingResources, + TransformGeometry = TransformGeometry, WriteResources = false, Resources = Resources }; - return new XamlGenerator().Generate(drawingGroup, context); + return new XamlGenerator().GenerateDrawingGroup(drawingGroup, context); } public string ToXamlImage(ShimSkiaSharp.SKPicture? skPicture, string? key = null) @@ -47,17 +50,18 @@ public string ToXamlImage(ShimSkiaSharp.SKPicture? skPicture, string? key = null var drawingImage = new DrawingImage(drawingGroup); var image = new Image(drawingImage, key); - var context = new GeneratorContext + var context = new XamlGeneratorSettings { NewLine = NewLine, UseCompatMode = UseCompatMode, AddTransparentBackground = AddTransparentBackground, ReuseExistingResources = ReuseExistingResources, + TransformGeometry = TransformGeometry, WriteResources = true, Resources = Resources }; - return new XamlGenerator().Generate(image, context); + return new XamlGenerator().GenerateImage(image, context, null); } public string ToXamlStyles(List inputItems, bool generateImage = false, bool generatePreview = true) @@ -98,17 +102,18 @@ public string ToXamlStyles(List inputItems, bool generateImage = fals var resources = results.Select(x => x.Resource).ToList(); var styles = new Styles(resources, generateImage, generatePreview); - var context = new GeneratorContext + var context = new XamlGeneratorSettings { NewLine = NewLine, UseCompatMode = UseCompatMode, AddTransparentBackground = AddTransparentBackground, ReuseExistingResources = ReuseExistingResources, + TransformGeometry = TransformGeometry, WriteResources = false, Resources = Resources }; - return new XamlGenerator().Generate(styles, context); + return new XamlGenerator().GenerateStyles(styles, context); } public virtual string CreateKey(string path) diff --git a/src/svgxaml/Program.cs b/src/svgxaml/Program.cs index 6d158ad..bb9ce5a 100644 --- a/src/svgxaml/Program.cs +++ b/src/svgxaml/Program.cs @@ -33,6 +33,7 @@ { UseCompatMode = false, ReuseExistingResources = false, + TransformGeometry = false, Resources = null }; @@ -63,6 +64,7 @@ { UseCompatMode = false, ReuseExistingResources = false, + TransformGeometry = false, Resources = null };