Browse Source

Column: simplified implementation and improved performance

Marcin Ziąbek 1 year ago
parent
commit
d64d75fddc

+ 5 - 11
Source/QuestPDF.UnitTests/ColumnTests.cs

@@ -17,14 +17,8 @@ namespace QuestPDF.UnitTests
             {
             {
                 Items =
                 Items =
                 {
                 {
-                    new ColumnItem
-                    {
-                        Child = testPlan.CreateChild("first")
-                    },
-                    new ColumnItem
-                    {
-                        Child = testPlan.CreateChild("second")
-                    }
+                    testPlan.CreateChild("first"),
+                    testPlan.CreateChild("second")
                 }
                 }
             };
             };
         }
         }
@@ -32,7 +26,7 @@ namespace QuestPDF.UnitTests
         private Column CreateColumnWithTwoItemsWhereFirstIsFullyRendered(TestPlan testPlan)
         private Column CreateColumnWithTwoItemsWhereFirstIsFullyRendered(TestPlan testPlan)
         {
         {
             var column = CreateColumnWithTwoItems(testPlan);
             var column = CreateColumnWithTwoItems(testPlan);
-            column.Items.First().IsRendered = true;
+            column.CurrentRenderingIndex = 1;
             return column;
             return column;
         }
         }
         
         
@@ -176,7 +170,7 @@ namespace QuestPDF.UnitTests
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectChildDraw("second", new Size(400, 300))
                 .ExpectChildDraw("second", new Size(400, 300))
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectCanvasTranslate(0, 0)
-                .CheckState<Column>(x => x.Items.First().IsRendered)
+                .CheckState<Column>(x => x.CurrentRenderingIndex > 0)
                 .CheckDrawResult();
                 .CheckDrawResult();
         }
         }
         
         
@@ -191,7 +185,7 @@ namespace QuestPDF.UnitTests
                 .ExpectChildDraw("second", new Size(400, 300))
                 .ExpectChildDraw("second", new Size(400, 300))
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectCanvasTranslate(0, 0)
                 .CheckDrawResult()
                 .CheckDrawResult()
-                .CheckState<Column>(x => !x.Items.First().IsRendered);
+                .CheckState<Column>(x => x.CurrentRenderingIndex == 0);
         }
         }
         
         
         #endregion
         #endregion

+ 19 - 21
Source/QuestPDF/Elements/Column.cs

@@ -6,26 +6,23 @@ using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Elements
 namespace QuestPDF.Elements
 {
 {
-    internal sealed class ColumnItem : Container
-    {
-        public bool IsRendered { get; set; }
-    }
-
     internal sealed class ColumnItemRenderingCommand
     internal sealed class ColumnItemRenderingCommand
     {
     {
-        public ColumnItem ColumnItem { get; set; }
+        public Element Element { get; set; }
         public SpacePlan Measurement { get; set; }
         public SpacePlan Measurement { get; set; }
         public Position Offset { get; set; }
         public Position Offset { get; set; }
     }
     }
 
 
     internal sealed class Column : Element, ICacheable, IStateResettable
     internal sealed class Column : Element, ICacheable, IStateResettable
     {
     {
-        internal List<ColumnItem> Items { get; } = new();
+        internal List<Element> Items { get; } = new();
         internal float Spacing { get; set; }
         internal float Spacing { get; set; }
+        
+        internal int CurrentRenderingIndex { get; set; }
 
 
         public void ResetState()
         public void ResetState()
         {
         {
-            Items.ForEach(x => x.IsRendered = false);
+            CurrentRenderingIndex = 0;
         }
         }
         
         
         internal override IEnumerable<Element?> GetChildren()
         internal override IEnumerable<Element?> GetChildren()
@@ -35,7 +32,8 @@ namespace QuestPDF.Elements
         
         
         internal override void CreateProxy(Func<Element?, Element?> create)
         internal override void CreateProxy(Func<Element?, Element?> create)
         {
         {
-            Items.ForEach(x => x.Child = create(x.Child));
+            for (var i = 0; i < Items.Count; i++)
+                Items[i] = create(Items[i]);
         }
         }
 
 
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
@@ -43,6 +41,9 @@ namespace QuestPDF.Elements
             if (!Items.Any())
             if (!Items.Any())
                 return SpacePlan.FullRender(Size.Zero);
                 return SpacePlan.FullRender(Size.Zero);
             
             
+            if (CurrentRenderingIndex == Items.Count)
+                return SpacePlan.FullRender(Size.Zero);
+            
             var renderingCommands = PlanLayout(availableSpace);
             var renderingCommands = PlanLayout(availableSpace);
 
 
             if (!renderingCommands.Any())
             if (!renderingCommands.Any())
@@ -55,7 +56,7 @@ namespace QuestPDF.Elements
             if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
             if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
                 return SpacePlan.Wrap();
                 return SpacePlan.Wrap();
             
             
-            var totalRenderedItems = Items.Count(x => x.IsRendered) + renderingCommands.Count(x => x.Measurement.Type == SpacePlanType.FullRender);
+            var totalRenderedItems = CurrentRenderingIndex + renderingCommands.Count(x => x.Measurement.Type is SpacePlanType.FullRender);
             var willBeFullyRendered = totalRenderedItems == Items.Count;
             var willBeFullyRendered = totalRenderedItems == Items.Count;
 
 
             return willBeFullyRendered
             return willBeFullyRendered
@@ -69,31 +70,28 @@ namespace QuestPDF.Elements
 
 
             foreach (var command in renderingCommands)
             foreach (var command in renderingCommands)
             {
             {
-                if (command.Measurement.Type == SpacePlanType.FullRender)
-                    command.ColumnItem.IsRendered = true;
-
                 var targetSize = new Size(availableSpace.Width, command.Measurement.Height);
                 var targetSize = new Size(availableSpace.Width, command.Measurement.Height);
 
 
                 Canvas.Translate(command.Offset);
                 Canvas.Translate(command.Offset);
-                command.ColumnItem.Draw(targetSize);
+                command.Element.Draw(targetSize);
                 Canvas.Translate(command.Offset.Reverse());
                 Canvas.Translate(command.Offset.Reverse());
             }
             }
             
             
-            if (Items.All(x => x.IsRendered))
+            var fullyRenderedItems = renderingCommands.Count(x => x.Measurement.Type is SpacePlanType.FullRender);
+            CurrentRenderingIndex += fullyRenderedItems;
+            
+            if (CurrentRenderingIndex == Items.Count)
                 ResetState();
                 ResetState();
         }
         }
 
 
-        private ICollection<ColumnItemRenderingCommand> PlanLayout(Size availableSpace)
+        private List<ColumnItemRenderingCommand> PlanLayout(Size availableSpace)
         {
         {
             var topOffset = 0f;
             var topOffset = 0f;
             var targetWidth = 0f;
             var targetWidth = 0f;
             var commands = new List<ColumnItemRenderingCommand>();
             var commands = new List<ColumnItemRenderingCommand>();
 
 
-            foreach (var item in Items)
+            foreach (var item in Items.Skip(CurrentRenderingIndex))
             {
             {
-                if (item.IsRendered)
-                    continue;
-
                 var availableHeight = availableSpace.Height - topOffset;
                 var availableHeight = availableSpace.Height - topOffset;
 
 
                 var itemSpace = availableHeight > 0
                 var itemSpace = availableHeight > 0
@@ -114,7 +112,7 @@ namespace QuestPDF.Elements
                 
                 
                 commands.Add(new ColumnItemRenderingCommand
                 commands.Add(new ColumnItemRenderingCommand
                 {
                 {
-                    ColumnItem = item,
+                    Element = item,
                     Measurement = measurement,
                     Measurement = measurement,
                     Offset = new Position(0, topOffset)
                     Offset = new Position(0, topOffset)
                 });
                 });

+ 1 - 6
Source/QuestPDF/Fluent/ColumnExtensions.cs

@@ -23,12 +23,7 @@ namespace QuestPDF.Fluent
         public IContainer Item()
         public IContainer Item()
         {
         {
             var container = new Container();
             var container = new Container();
-            
-            Column.Items.Add(new ColumnItem
-            {
-                Child = container
-            });
-            
+            Column.Items.Add(container);
             return container;
             return container;
         }
         }
     }
     }