Browse Source

Svg now renders layer properly

flabbet 11 months ago
parent
commit
d08813de02

+ 40 - 0
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -135,6 +135,46 @@ public class DocumentRenderer
             return new EmptyChunk();
         }
     }
+    
+    public Texture? RenderLayer(Guid nodeId, ChunkResolution resolution, KeyFrameTime frameTime)
+    {
+        var node = Document.FindNode(nodeId);
+        
+        if (node is null)
+        {
+            return null;
+        }
+        
+        VecI sizeInChunks = Document.Size / resolution.PixelSize();
+        
+        sizeInChunks = new VecI(
+            Math.Max(1, sizeInChunks.X),
+            Math.Max(1, sizeInChunks.Y));
+        
+        VecI size = new VecI(
+            Math.Min(Document.Size.X, resolution.PixelSize() * sizeInChunks.X),
+            Math.Min(Document.Size.Y, resolution.PixelSize() * sizeInChunks.Y));
+        
+        Texture texture = new(size);
+        
+        for (int x = 0; x < sizeInChunks.X; x++)
+        {
+            for (int y = 0; y < sizeInChunks.Y; y++)
+            {
+                VecI chunkPos = new(x, y);
+                OneOf<Chunk, EmptyChunk> chunk = RenderChunk(chunkPos, resolution, node, frameTime);
+                if (chunk.IsT0)
+                {
+                    VecI pos = chunkPos * resolution.PixelSize(); 
+                    texture.DrawingSurface.Canvas.DrawSurface(
+                        chunk.AsT0.Surface.DrawingSurface,
+                        pos.X, pos.Y, null);
+                }
+            }
+        }
+        
+        return texture;
+    }
 
     private static OneOf<Chunk, EmptyChunk> RenderChunkOnGraph(VecI chunkPos, ChunkResolution resolution,
         RectI? globalClippingRect,

+ 3 - 2
src/PixiEditor.SVG/Elements/SvgImage.cs

@@ -9,9 +9,10 @@ public class SvgImage : SvgElement
     
     public SvgProperty<SvgNumericUnit> Width { get; } = new("width");
     public SvgProperty<SvgNumericUnit> Height { get; } = new("height");
-    
+        
     public SvgProperty<SvgStringUnit> Href { get; } = new("xlink:href");
-    
+    public SvgProperty<SvgLinkUnit> Mask { get; } = new("mask");
+
     public SvgImage() : base("image")
     {
         RequiredNamespaces.Add("xlink", "http://www.w3.org/1999/xlink");

+ 14 - 0
src/PixiEditor.SVG/Elements/SvgMask.cs

@@ -0,0 +1,14 @@
+using PixiEditor.SVG.Features;
+using PixiEditor.SVG.Units;
+
+namespace PixiEditor.SVG.Elements;
+
+public class SvgMask() : SvgElement("mask"), IElementContainer
+{
+    public SvgProperty<SvgNumericUnit> X { get; } = new("x");
+    public SvgProperty<SvgNumericUnit> Y { get; } = new("y");
+    
+    public SvgProperty<SvgNumericUnit> Width { get; } = new("width");
+    public SvgProperty<SvgNumericUnit> Height { get; } = new("height");
+    public List<SvgElement> Children { get; } = new();
+}

+ 2 - 0
src/PixiEditor.SVG/SvgElement.cs

@@ -1,10 +1,12 @@
 using System.Text;
 using PixiEditor.SVG.Features;
+using PixiEditor.SVG.Units;
 
 namespace PixiEditor.SVG;
 
 public class SvgElement(string tagName)
 {
+    public SvgProperty<SvgStringUnit> Id { get; } = new("id");
     public Dictionary<string, string> RequiredNamespaces { get; } = new();
     public string TagName { get; } = tagName;
 

+ 1 - 1
src/PixiEditor.SVG/SvgProperty.cs

@@ -13,7 +13,7 @@ public abstract class SvgProperty
     public ISvgUnit? Unit { get; set; }
 }
 
-public class SvgProperty<T> : SvgProperty where T : ISvgUnit
+public class SvgProperty<T> : SvgProperty where T : struct, ISvgUnit
 {
     public new T? Unit
     {

+ 20 - 0
src/PixiEditor.SVG/Units/SvgLinkUnit.cs

@@ -0,0 +1,20 @@
+using PixiEditor.SVG.Elements;
+
+namespace PixiEditor.SVG.Units;
+
+public struct SvgLinkUnit : ISvgUnit
+{
+    public string? ObjectReference { get; set; } 
+    public string ToXml()
+    {
+        return ObjectReference != null ? $"url(#{ObjectReference}" : string.Empty;
+    }
+
+    public static SvgLinkUnit FromElement(SvgElement element)
+    {
+        return new SvgLinkUnit
+        {
+            ObjectReference = element.Id.Unit?.Value
+        };
+    }
+}

+ 34 - 9
src/PixiEditor/ViewModels/Document/DocumentViewModel.Serialization.cs

@@ -1,5 +1,6 @@
 using System.Collections;
-using System.Drawing;
+using System.Diagnostics.CodeAnalysis;
+using Avalonia.Threading;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
 using Microsoft.Extensions.DependencyInjection;
@@ -10,8 +11,10 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
+using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Extensions.CommonApi.Palettes;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Handlers;
@@ -28,6 +31,8 @@ using PixiEditor.SVG.Elements;
 using PixiEditor.SVG.Features;
 using PixiEditor.SVG.Units;
 using PixiEditor.ViewModels.Document.Nodes;
+using BlendMode = PixiEditor.DrawingApi.Core.Surfaces.BlendMode;
+using Color = System.Drawing.Color;
 using IKeyFrameChildrenContainer = PixiEditor.ChangeableDocument.Changeables.Interfaces.IKeyFrameChildrenContainer;
 using KeyFrameData = PixiEditor.Parser.KeyFrameData;
 using PixiDocument = PixiEditor.Parser.Document;
@@ -111,17 +116,36 @@ internal partial class DocumentViewModel
 
         if (tightBounds == null || tightBounds.Value.IsZeroArea) return;
 
+        Image toSave = null;
+        DrawingBackendApi.Current.RenderingServer.Invoke(() =>
+        {
+            using Texture rendered = Renderer.RenderLayer(imageNode.Id, ChunkResolution.Full, atTime.Frame);
+            
+            using Surface surface = new Surface(rendered.Size);
+            surface.DrawingSurface.Canvas.DrawImage(rendered.DrawingSurface.Snapshot(), 0, 0);
+
+            toSave = surface.DrawingSurface.Snapshot((RectI)tightBounds.Value);
+        });
+
+        //var imgToSerialize = imageNode.GetLayerImageAtFrame(atTime.Frame);
+        var image = CreateImageElement(resizeFactor, tightBounds.Value, toSave);
+
+        elementContainer.Children.Add(image);
+    }
+
+    private static SvgImage CreateImageElement(VecD resizeFactor, RectD tightBounds,
+        Image toSerialize)
+    {
         SvgImage image = new SvgImage();
 
-        RectI bounds = (RectI)tightBounds.Value;
+        RectI bounds = (RectI)tightBounds;
 
         using Surface surface = new Surface(bounds.Size);
-        imageNode.GetLayerImageAtFrame(atTime.Frame).DrawMostUpToDateRegionOn(
-            (RectI)tightBounds.Value, ChunkResolution.Full, surface.DrawingSurface, VecI.Zero);
+        surface.DrawingSurface.Canvas.DrawImage(toSerialize, 0, 0);
 
         byte[] targetBytes;
 
-        RectD targetBounds = tightBounds.Value;
+        RectD targetBounds = tightBounds;
 
         if (!resizeFactor.AlmostEquals(new VecD(1, 1)))
         {
@@ -129,12 +153,14 @@ internal partial class DocumentViewModel
             using var resized = surface.Resize(newSize, ResizeMethod.NearestNeighbor);
             using var snapshot = resized.DrawingSurface.Snapshot();
             targetBytes = snapshot.Encode().AsSpan().ToArray();
-            
-            targetBounds = new RectD(targetBounds.X * resizeFactor.X, targetBounds.Y * resizeFactor.Y, newSize.X, newSize.Y);
+
+            targetBounds = new RectD(targetBounds.X * resizeFactor.X, targetBounds.Y * resizeFactor.Y, newSize.X,
+                newSize.Y);
         }
         else
         {
             using var snapshot = surface.DrawingSurface.Snapshot();
+
             targetBytes = snapshot.Encode().AsSpan().ToArray();
         }
 
@@ -143,8 +169,7 @@ internal partial class DocumentViewModel
         image.Width.Unit = SvgNumericUnit.FromUserUnits(targetBounds.Width);
         image.Height.Unit = SvgNumericUnit.FromUserUnits(targetBounds.Height);
         image.Href.Unit = new SvgStringUnit($"data:image/png;base64,{Convert.ToBase64String(targetBytes)}");
-
-        elementContainer.Children.Add(image);
+        return image;
     }
 
     private static void AddNodes(IReadOnlyNodeGraph graph, NodeGraph targetGraph,