diff --git a/samples/AvalonDraw/MainWindow.axaml b/samples/AvalonDraw/MainWindow.axaml index db8d916719..e112c4030c 100644 --- a/samples/AvalonDraw/MainWindow.axaml +++ b/samples/AvalonDraw/MainWindow.axaml @@ -40,6 +40,7 @@ + diff --git a/samples/AvalonDraw/MainWindow.axaml.cs b/samples/AvalonDraw/MainWindow.axaml.cs index 14cf5cc85e..10470792b8 100644 --- a/samples/AvalonDraw/MainWindow.axaml.cs +++ b/samples/AvalonDraw/MainWindow.axaml.cs @@ -421,6 +421,39 @@ private async void ExportElementMenuItem_Click(object? sender, RoutedEventArgs e SK.SKColorType.Rgba8888, SK.SKAlphaType.Premul, SvgView.SkSvg.Settings.Srgb); } + private async void PlaceImageMenuItem_Click(object? sender, RoutedEventArgs e) + { + if (_document is null) + return; + var dialog = new OpenFileDialog + { + Filters = new() + { + new FileDialogFilter { Name = "Images", Extensions = { "png", "jpg", "jpeg", "bmp" } }, + new FileDialogFilter { Name = "All", Extensions = { "*" } } + } + }; + var result = await dialog.ShowAsync(this); + var file = result?.FirstOrDefault(); + if (string.IsNullOrEmpty(file)) + return; + byte[] data; + try + { + data = await File.ReadAllBytesAsync(file); + } + catch + { + return; + } + var ext = Path.GetExtension(file).Trim('.').ToLowerInvariant(); + if (ext == "jpg") + ext = "jpeg"; + var href = $"data:image/{ext};base64,{Convert.ToBase64String(data)}"; + _toolService.ImageHref = href; + _toolService.SetTool(Tool.Image); + } + private void Window_OnDragOver(object? sender, DragEventArgs e) { if (e.Data.Contains(DataFormats.FileNames)) @@ -557,7 +590,7 @@ private async void SvgView_OnPointerPressed(object? sender, PointerPressedEventA if ((_toolService.CurrentTool == Tool.Line || _toolService.CurrentTool == Tool.Rect || _toolService.CurrentTool == Tool.Circle || _toolService.CurrentTool == Tool.Ellipse || _toolService.CurrentTool == Tool.Text || _toolService.CurrentTool == Tool.TextPath || _toolService.CurrentTool == Tool.TextArea || - _toolService.CurrentTool == Tool.Symbol || + _toolService.CurrentTool == Tool.Symbol || _toolService.CurrentTool == Tool.Image || _toolService.CurrentTool == Tool.PathLine || _toolService.CurrentTool == Tool.PathCubic || _toolService.CurrentTool == Tool.PathQuadratic || _toolService.CurrentTool == Tool.PathArc || _toolService.CurrentTool == Tool.PathMove) && e.GetCurrentPoint(SvgView).Properties.IsLeftButtonPressed) { diff --git a/samples/AvalonDraw/Services/ToolService.cs b/samples/AvalonDraw/Services/ToolService.cs index ed5c8b9a2c..2ea66e1bcf 100644 --- a/samples/AvalonDraw/Services/ToolService.cs +++ b/samples/AvalonDraw/Services/ToolService.cs @@ -28,7 +28,8 @@ public enum Tool PathQuadratic, PathArc, PathMove, - Symbol + Symbol, + Image } public Tool CurrentTool { get; private set; } = Tool.Select; @@ -46,6 +47,7 @@ public void SetTool(Tool tool) public string? SymbolId { get; set; } public string? ReferenceId { get; set; } + public string? ImageHref { get; set; } public SvgVisualElement? CreateElement(Tool tool, SvgElement parent, ShimSkiaSharp.SKPoint start) { @@ -130,6 +132,14 @@ public void SetTool(Tool tool) X = new SvgUnit(SvgUnitType.User, start.X), Y = new SvgUnit(SvgUnitType.User, start.Y) }, + Tool.Image when !string.IsNullOrEmpty(ImageHref) => new SvgImage + { + X = new SvgUnit(SvgUnitType.User, start.X), + Y = new SvgUnit(SvgUnitType.User, start.Y), + Width = new SvgUnit(SvgUnitType.User, 0), + Height = new SvgUnit(SvgUnitType.User, 0), + Href = ImageHref + }, _ => null! }; } @@ -179,20 +189,42 @@ public void UpdateElement(SvgVisualElement element, Tool tool, ShimSkiaSharp.SKP var h = Math.Abs(current.Y - start.Y); if (snapToGrid) { - x = snap(x); y = snap(y); w = snap(w); h = snap(h); + x = snap(x); + y = snap(y); + w = snap(w); + h = snap(h); } r.X = new SvgUnit(r.X.Type, x); r.Y = new SvgUnit(r.Y.Type, y); r.Width = new SvgUnit(r.Width.Type, w); r.Height = new SvgUnit(r.Height.Type, h); break; + case Tool.Image when element is SvgImage img: + var ix = Math.Min(start.X, current.X); + var iy = Math.Min(start.Y, current.Y); + var iw = Math.Abs(current.X - start.X); + var ih = Math.Abs(current.Y - start.Y); + if (snapToGrid) + { + ix = snap(ix); + iy = snap(iy); + iw = snap(iw); + ih = snap(ih); + } + img.X = new SvgUnit(img.X.Type, ix); + img.Y = new SvgUnit(img.Y.Type, iy); + img.Width = new SvgUnit(img.Width.Type, iw); + img.Height = new SvgUnit(img.Height.Type, ih); + break; case Tool.Circle when element is SvgCircle c: var cx = (start.X + current.X) / 2f; var cy = (start.Y + current.Y) / 2f; var rv = Math.Max(Math.Abs(current.X - start.X), Math.Abs(current.Y - start.Y)) / 2f; if (snapToGrid) { - cx = snap(cx); cy = snap(cy); rv = snap(rv); + cx = snap(cx); + cy = snap(cy); + rv = snap(rv); } c.CenterX = new SvgUnit(c.CenterX.Type, cx); c.CenterY = new SvgUnit(c.CenterY.Type, cy); @@ -205,7 +237,10 @@ public void UpdateElement(SvgVisualElement element, Tool tool, ShimSkiaSharp.SKP var ry = Math.Abs(current.Y - start.Y) / 2f; if (snapToGrid) { - ecx = snap(ecx); ecy = snap(ecy); rx = snap(rx); ry = snap(ry); + ecx = snap(ecx); + ecy = snap(ecy); + rx = snap(rx); + ry = snap(ry); } el.CenterX = new SvgUnit(el.CenterX.Type, ecx); el.CenterY = new SvgUnit(el.CenterY.Type, ecy);