Browse Source

Added text node and vector data

flabbet 6 months ago
parent
commit
b3b69452b3

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit 7fe29ad3ea438046a66b300e85608af3c8544309
+Subproject commit 049b8297bb5dbbdc0439f5286bc52dcdcdab522a

+ 100 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/TextVectorData.cs

@@ -0,0 +1,100 @@
+using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Text;
+using Drawie.Backend.Core.Vector;
+using Drawie.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+
+public class TextVectorData : ShapeVectorData
+{
+    public string Text { get; set; }
+    public VecD Position { get; set; }
+    public Font Font { get; set; }
+
+    public override RectD GeometryAABB => new RectD(Position.X, Position.Y, Font.MeasureText(Text), Font.Size);
+
+    public override ShapeCorners TransformationCorners =>
+        new ShapeCorners(GeometryAABB).WithMatrix(TransformationMatrix);
+
+    public override RectD VisualAABB => GeometryAABB;
+    public VectorPath? Path { get; set; }
+
+    public override VectorPath ToPath()
+    {
+        return Font.GetTextPath(Text);
+    }
+
+    public override void RasterizeGeometry(Canvas canvas)
+    {
+        Rasterize(canvas, false);
+    }
+
+    public override void RasterizeTransformed(Canvas canvas)
+    {
+        Rasterize(canvas, true);
+    }
+
+    private void Rasterize(Canvas canvas, bool applyTransform)
+    {
+        int num = 0;
+        if (applyTransform)
+        {
+            num = canvas.Save();
+            ApplyTransformTo(canvas);
+        }
+
+        using Paint paint = new Paint() { IsAntiAliased = true, };
+
+        if (Fill && FillColor.A > 0)
+        {
+            paint.Color = FillColor;
+            paint.Style = PaintStyle.Fill;
+
+            if (Path == null)
+            {
+                canvas.DrawText(Text, Position, Font, paint);
+            }
+            else
+            {
+                canvas.DrawTextOnPath(Path, Text, Position, Font, paint);
+            }
+        }
+
+        if (StrokeWidth > 0)
+        {
+            paint.Color = StrokeColor;
+            paint.Style = PaintStyle.Stroke;
+            paint.StrokeWidth = StrokeWidth;
+
+            if (Path == null)
+            {
+                canvas.DrawText(Text, Position, Font, paint);
+            }
+            else
+            {
+                canvas.DrawTextOnPath(Path, Text, Position, Font, paint);
+            }
+        }
+
+        if (applyTransform)
+        {
+            canvas.RestoreToCount(num);
+        }
+    }
+
+    public override bool IsValid()
+    {
+        return !string.IsNullOrEmpty(Text);
+    }
+
+    public override int GetCacheHash()
+    {
+        return HashCode.Combine(Text, Position, Font, StrokeColor, FillColor, StrokeWidth, TransformationMatrix);
+    }
+
+    public override int CalculateHash()
+    {
+        return GetCacheHash();
+    }
+}

+ 82 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/TextNode.cs

@@ -0,0 +1,82 @@
+using Drawie.Backend.Core.Text;
+using Drawie.Backend.Core.Vector;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+using PixiEditor.ChangeableDocument.Rendering;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes;
+
+[NodeInfo("Text")]
+public class TextNode : ShapeNode<TextVectorData>
+{
+    public InputProperty<string> Text { get; }
+    public InputProperty<VecD> TextPosition { get; }
+    public InputProperty<string> FontFamily { get; }
+    public InputProperty<double> FontSize { get; }
+    public InputProperty<ShapeVectorData> OnPathData { get; }
+    
+    private string lastText = "";
+    private VecD lastPosition = new VecD();
+    private string lastFontFamily = "";
+    private double lastFontSize = 12d;
+    private VectorPath? lastPath;
+
+    private TextVectorData? cachedData;
+    public TextNode()
+    {
+        Text = CreateInput("Text", "TEXT", "");
+        TextPosition = CreateInput("Position", "POSITION", new VecD());
+        FontFamily = CreateInput("FontFamily", "FONT_FAMILY", "");
+        FontSize = CreateInput("FontSize", "FONT_SIZE", 12d);
+        OnPathData = CreateInput<ShapeVectorData>("PathToDrawOn", "ON_PATH_DATA", null);
+    }
+    
+    protected override TextVectorData? GetShapeData(RenderContext context)
+    {
+        string text = Text.Value;
+        VecD position = TextPosition.Value;
+        string fontFamily = FontFamily.Value;
+        double fontSize = FontSize.Value;
+        VectorPath? path = OnPathData.Value?.ToPath();
+        
+        if (text == lastText && position == lastPosition && fontFamily == lastFontFamily && fontSize == lastFontSize && path == lastPath)
+        {
+            return cachedData;
+        }
+        
+        lastText = text;
+        lastPosition = position;
+        lastFontFamily = fontFamily;
+        lastFontSize = fontSize;
+        lastPath = path;
+
+        Font font = Font.FromFamilyName(fontFamily);
+        if(font == null)
+        {
+            font = Font.CreateDefault();
+        }
+        
+        font.Size = fontSize;
+        
+        cachedData = new TextVectorData()
+        {
+            Text = text,
+            Position = position,
+            Font = font,
+            Path = path,
+        };
+        
+        return cachedData;
+    }
+
+    public override Node CreateCopy()
+    {
+        return new TextNode();
+    }
+
+    public override void Dispose()
+    {
+        base.Dispose();
+        cachedData?.Font.Dispose();
+    }
+}

+ 7 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -17,6 +17,7 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("VectorLayer")]
 public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorNode, IRasterizable
 {
+    public OutputProperty<ShapeVectorData> Shape { get; }
     public Matrix3X3 TransformationMatrix
     {
         get => ShapeData?.TransformationMatrix ?? Matrix3X3.Identity;
@@ -31,7 +32,11 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         }
     }
 
-    public ShapeVectorData? ShapeData { get; set; }
+    public ShapeVectorData? ShapeData
+    {
+        get => Shape.Value;
+        set => Shape.Value = value;
+    }
     IReadOnlyShapeVectorData IReadOnlyVectorNode.ShapeData => ShapeData;
 
 
@@ -43,6 +48,7 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
     public VectorLayerNode()
     {
         AllowHighDpiRendering = true;
+        Shape = CreateOutput<ShapeVectorData>("Shape", "SHAPE", null);
     }
     
     protected override VecI GetTargetSize(RenderContext ctx)

+ 9 - 0
src/PixiEditor/ViewModels/Document/Nodes/Shapes/TextNodeViewModel.cs

@@ -0,0 +1,9 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Shapes;
+
+[NodeViewModel("TEXT_NODE", "SHAPE", "\ue90d")]
+internal class TextNodeViewModel : NodeViewModel<TextNode>
+{
+}

+ 3 - 3
src/PixiEditor/Views/Overlays/Drawables/InfoBox.cs

@@ -39,15 +39,15 @@ public class InfoBox
     public void DrawInfo(Canvas context, string text, VecD pointerPos)
     {
         const float padding = 10;
-        font.FontSize = 14 / ZoomScale;
+        font.Size = 14 / ZoomScale;
 
         double widthTextSize = font.MeasureText(text);
 
         VecD aboveCursor = pointerPos + new VecD(0, -20 / ZoomScale);
         float rectWidth = (float)widthTextSize + (padding * 2 / (float)ZoomScale);
-        float rectHeight = (float)font.FontSize + padding / (float)ZoomScale;
+        float rectHeight = (float)font.Size + padding / (float)ZoomScale;
         float x = (float)aboveCursor.X - rectWidth / 2;
-        float y = (float)aboveCursor.Y - ((float)font.FontSize) - (padding / 4) / (float)ZoomScale;
+        float y = (float)aboveCursor.Y - ((float)font.Size) - (padding / 4) / (float)ZoomScale;
         
         context.DrawRoundRect(x, y, rectWidth, rectHeight, 5 / (float)ZoomScale,
             5 / (float)ZoomScale, backgroundPen);

+ 1 - 1
src/PixiEditor/Views/Overlays/Handles/IconGlyph.cs

@@ -37,6 +37,6 @@ public class IconGlyph : HandleGlyph
     protected override RectD GetBounds()
     {
         double measure = targetFont.MeasureText(Icon);
-        return new RectD(0, 0, measure, targetFont.FontSize);
+        return new RectD(0, 0, measure, targetFont.Size);
     }
 }

+ 3 - 3
src/PixiEditor/Views/Overlays/SymmetryOverlay/SymmetryOverlay.cs

@@ -222,12 +222,12 @@ internal class SymmetryOverlay : Overlay
 
         using Font font = Font.CreateDefault(14f / (float)ZoomScale);
         
-        if (Size.Y < font.FontSize * 2.5 || horizontalAxisY == (int)Size.Y && upper || horizontalAxisY == 0 && !upper)
+        if (Size.Y < font.Size * 2.5 || horizontalAxisY == (int)Size.Y && upper || horizontalAxisY == 0 && !upper)
         {
             return;
         }
 
-        double textY = horizontalAxisY / 2.0 - font.FontSize / 2;
+        double textY = horizontalAxisY / 2.0 - font.Size / 2;
 
         if (upper)
         {
@@ -263,7 +263,7 @@ internal class SymmetryOverlay : Overlay
             textX += Size.X / 2;
         }
 
-        double textY = RulerOffset * PenThickness - ((drawBottom ? 5 : 2 + font.FontSize) * PenThickness) + yOffset;
+        double textY = RulerOffset * PenThickness - ((drawBottom ? 5 : 2 + font.Size) * PenThickness) + yOffset;
         drawingContext.DrawText(text, new VecD(textX, textY), TextAlign.Center, font, textPaint);
     }