Browse Source

Implemented measurement cache proxy

Marcin Ziąbek 4 years ago
parent
commit
814d325376

+ 52 - 0
QuestPDF/Drawing/CacheProxy.cs

@@ -0,0 +1,52 @@
+using System;
+using QuestPDF.Drawing.SpacePlan;
+using QuestPDF.Infrastructure;
+using IContainer = System.ComponentModel.IContainer;
+
+namespace QuestPDF.Drawing
+{
+    internal class ElementProxy : ContainerElement
+    {
+        
+    }
+    
+    internal class CacheProxy : ElementProxy
+    {
+        public Size? AvailableSpace { get; set; }
+        public ISpacePlan? MeasurementResult { get; set; }
+        
+        internal override ISpacePlan Measure(Size availableSpace)
+        {
+            if (MeasurementResult != null &&
+                AvailableSpace != null &&
+                IsClose(AvailableSpace.Width, availableSpace.Width) &&
+                IsClose(AvailableSpace.Height, availableSpace.Height))
+            {
+                return MeasurementResult;
+            }
+
+            AvailableSpace = availableSpace;
+            MeasurementResult = Child?.Measure(availableSpace) ?? new FullRender(Size.Zero);
+
+            return MeasurementResult;
+        }
+
+        internal override void Draw(Size availableSpace)
+        {
+            AvailableSpace = null;
+            MeasurementResult = null;
+            
+            base.Draw(availableSpace);
+        }
+
+        private bool IsClose(float x, float y)
+        {
+            return Math.Abs(x - y) < Size.Epsilon;
+        }
+    }
+
+    internal class DebugProxy : ElementProxy
+    {
+        
+    }
+}

+ 10 - 0
QuestPDF/Drawing/DocumentGenerator.cs

@@ -40,6 +40,8 @@ namespace QuestPDF.Drawing
             var metadata = document.GetMetadata();
             var pageContext = new PageContext();
 
+            ApplyElementProxy<CacheProxy>(content);
+            
             RenderPass(pageContext, new FreeCanvas(), content, metadata);
             RenderPass(pageContext, canvas, content, metadata);
         }
@@ -89,5 +91,13 @@ namespace QuestPDF.Drawing
             
             canvas.EndDocument();
         }
+
+        private static void ApplyElementProxy<TProxy>(Container content) where TProxy : ElementProxy, new()
+        {
+            content.HandleVisitor(x => x.CreateProxy(y => new TProxy()
+            {
+                Child = y
+            }));
+        }
     }
 }

+ 6 - 0
QuestPDF/Elements/Decoration.cs

@@ -25,6 +25,12 @@ namespace QuestPDF.Elements
             base.HandleVisitor(visit);
         }
 
+        internal override void CreateProxy(Func<Element, Element> create)
+        {
+            DecorationElement = create(DecorationElement);
+            ContentElement = create(ContentElement);
+        }
+
         internal override ISpacePlan Measure(Size availableSpace)
         {
             var decorationMeasure = DecorationElement?.Measure(availableSpace);

+ 6 - 0
QuestPDF/Elements/Row.cs

@@ -48,6 +48,12 @@ namespace QuestPDF.Elements
             base.HandleVisitor(visit);
         }
 
+        internal override void CreateProxy(Func<Element?, Element?> create)
+        {
+            Left = create(Left);
+            Right = create(Right);
+        }
+        
         internal override ISpacePlan Measure(Size availableSpace)
         {
             var leftMeasurement = Left.Measure(new Size(availableSpace.Width, availableSpace.Height)) as Size;

+ 6 - 0
QuestPDF/Elements/Stack.cs

@@ -30,6 +30,12 @@ namespace QuestPDF.Elements
             IsFirstRendered = false;
         }
 
+        internal override void CreateProxy(Func<Element?, Element?> create)
+        {
+            First = create(First);
+            Second = create(Second);
+        }
+        
         internal override ISpacePlan Measure(Size availableSpace)
         {
             var firstElement = IsFirstRendered ? Empty.Instance : First;

+ 6 - 1
QuestPDF/Infrastructure/ContainerElement.cs

@@ -16,8 +16,13 @@ namespace QuestPDF.Infrastructure
 
         internal override void HandleVisitor(Action<Element?> visit)
         {
-            base.HandleVisitor(visit);
             Child?.HandleVisitor(visit);
+            base.HandleVisitor(visit);
+        }
+
+        internal override void CreateProxy(Func<Element?, Element?> create)
+        {
+            Child = create(Child);
         }
 
         internal override ISpacePlan Measure(Size availableSpace)

+ 5 - 0
QuestPDF/Infrastructure/Element.cs

@@ -19,6 +19,11 @@ namespace QuestPDF.Infrastructure
             PageContext = pageContext;
             Canvas = canvas;
         }
+
+        internal virtual void CreateProxy(Func<Element?, Element?> create)
+        {
+            
+        }
         
         internal abstract ISpacePlan Measure(Size availableSpace);
         internal abstract void Draw(Size availableSpace);