Răsfoiți Sursa

Decoration: improved implementation, fixed unit tests

MarcinZiabek 3 ani în urmă
părinte
comite
2ca6d1cb47
2 a modificat fișierele cu 96 adăugiri și 83 ștergeri
  1. 76 73
      QuestPDF.UnitTests/DecorationTests.cs
  2. 20 10
      QuestPDF/Elements/Decoration.cs

+ 76 - 73
QuestPDF.UnitTests/DecorationTests.cs

@@ -9,125 +9,128 @@ namespace QuestPDF.UnitTests
     [TestFixture]
     public class DecorationTests
     {
+        private Decoration CreateDecoration(TestPlan testPlan)
+        {
+            return new Decoration
+            {
+                Before = testPlan.CreateChild("before"),
+                Content = testPlan.CreateChild("content"),
+                After = testPlan.CreateChild("after"),
+            };
+        }
+        
         #region Measure
 
         [Test]
-        public void Measure_ReturnsWrap_WhenDecorationReturnsWrap()
+        public void Measure_ReturnsWrap_WhenBeforeReturnsWrap()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .CheckMeasureResult(SpacePlan.Wrap());
         }
         
         [Test]
-        public void Measure_ReturnsWrap_WhenDecorationReturnsPartialRender()
+        public void Measure_ReturnsWrap_WhenContentReturnsWrap()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.PartialRender(300, 200))
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap())
                 .CheckMeasureResult(SpacePlan.Wrap());
         }
         
         [Test]
-        public void Measure_ReturnsWrap_WhenContentReturnsWrap()
+        public void Measure_ReturnsWrap_WhenAfterReturnsWrap()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
-                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap())
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .CheckMeasureResult(SpacePlan.Wrap());
         }
         
         [Test]
-        public void Measure_ReturnsPartialRender_WhenContentReturnsPartialRender()
+        public void Measure_ReturnsWrap_WhenBeforeReturnsPartialRender()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
-                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(200, 150))
-                .CheckMeasureResult(SpacePlan.PartialRender(400, 250));
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.PartialRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
+                .CheckMeasureResult(SpacePlan.Wrap());
         }
         
         [Test]
-        public void Measure_ReturnsFullRender_WhenContentReturnsFullRender()
+        public void Measure_ReturnsWrap_WhenAfterReturnsPartialRender()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
-                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(200, 150))
-                .CheckMeasureResult(SpacePlan.FullRender(400, 250));
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.PartialRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
+                .CheckMeasureResult(SpacePlan.Wrap());
         }
         
-        #endregion
-        
-        #region Draw
+        [Test]
+        public void Measure_ReturnsWrap_WhenContentReturnsPartialRender()
+        {
+            TestPlan
+                .For(CreateDecoration)
+                .MeasureElement(new Size(400, 300))
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(150, 100))
+                .CheckMeasureResult(SpacePlan.PartialRender(150, 200));
+        }
         
         [Test]
-        public void Draw_Prepend()
+        public void Measure_ReturnsWrap_WhenContentReturnsFullRender()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Prepend,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
-                .DrawElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
-                .ExpectChildDraw("decoration", new Size(400, 100))
-                .ExpectCanvasTranslate(0, 100)
-                .ExpectChildDraw("content", new Size(400, 200))
-                .ExpectCanvasTranslate(0, -100)
-                .CheckDrawResult();
+                .For(CreateDecoration)
+                .MeasureElement(new Size(400, 300))
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
+                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(150, 100))
+                .CheckMeasureResult(SpacePlan.FullRender(150, 200));
         }
+
+        #endregion
+        
+        #region Draw
         
         [Test]
         public void Draw_Append()
         {
             TestPlan
-                .For(x => new BinaryDecoration
-                {
-                    Type = DecorationType.Append,
-                    DecorationElement = x.CreateChild("decoration"),
-                    ContentElement = x.CreateChild("content")
-                })
+                .For(CreateDecoration)
                 .DrawElement(new Size(400, 300))
-                .ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
-                .ExpectChildDraw("content", new Size(400, 200))
-                .ExpectCanvasTranslate(0, 200)
-                .ExpectChildDraw("decoration", new Size(400, 100))
-                .ExpectCanvasTranslate(0, -200)
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(200, 40))
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(200, 60))
+                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(300, 100))
+                
+                .ExpectCanvasTranslate(0, 0)
+                .ExpectChildDraw("before", new Size(300, 40))
+                .ExpectCanvasTranslate(0, 0)
+                
+                .ExpectCanvasTranslate(0, 40)
+                .ExpectChildDraw("content", new Size(300, 100))
+                .ExpectCanvasTranslate(0, -40)
+                
+                .ExpectCanvasTranslate(0, 140)
+                .ExpectChildDraw("after", new Size(300, 60))
+                .ExpectCanvasTranslate(0, -140)
+
                 .CheckDrawResult();
         }
 

+ 20 - 10
QuestPDF/Elements/Decoration.cs

@@ -11,7 +11,6 @@ namespace QuestPDF.Elements
     {
         public Element Element { get; set; }
         public SpacePlan Measurement { get; set; }
-        public Size Size { get; set; }
         public Position Offset { get; set; }
     }
     
@@ -42,8 +41,8 @@ namespace QuestPDF.Elements
             if (renderingCommands.Any(x => x.Measurement.Type == SpacePlanType.Wrap))
                 return SpacePlan.Wrap();
 
-            var width = renderingCommands.Max(x => x.Size.Width);
-            var height = renderingCommands.Sum(x => x.Size.Height);
+            var width = renderingCommands.Max(x => x.Measurement.Width);
+            var height = renderingCommands.Sum(x => x.Measurement.Height);
             var size = new Size(width, height);
             
             if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
@@ -58,18 +57,32 @@ namespace QuestPDF.Elements
 
         internal override void Draw(Size availableSpace)
         {
-            foreach (var command in PlanLayout(availableSpace))
+            var renderingCommands = PlanLayout(availableSpace).ToList();
+            var width = renderingCommands.Max(x => x.Measurement.Width);
+            
+            foreach (var command in renderingCommands)
             {
+                var elementSize = new Size(width, command.Measurement.Height);
+                
                 Canvas.Translate(command.Offset);
-                command.Element.Draw(command.Size);
+                command.Element.Draw(elementSize);
                 Canvas.Translate(command.Offset.Reverse());
             }
         }
 
         private IEnumerable<DecorationItemRenderingCommand> PlanLayout(Size availableSpace)
         {
-            var beforeMeasurement = Before.Measure(availableSpace);
-            var afterMeasurement = After.Measure(availableSpace);
+            SpacePlan GetDecorationMeasurement(Element element)
+            {
+                var measurement = element.Measure(availableSpace);
+                
+                return measurement.Type == SpacePlanType.FullRender 
+                    ? measurement 
+                    : SpacePlan.Wrap();
+            }
+            
+            var beforeMeasurement = GetDecorationMeasurement(Before);
+            var afterMeasurement = GetDecorationMeasurement(After);
             
             var contentSpace = new Size(availableSpace.Width, availableSpace.Height - beforeMeasurement.Height - afterMeasurement.Height);
             var contentMeasurement = Content.Measure(contentSpace);
@@ -78,7 +91,6 @@ namespace QuestPDF.Elements
             {
                 Element = Before,
                 Measurement = beforeMeasurement,
-                Size = new Size(availableSpace.Width, beforeMeasurement.Height),
                 Offset = Position.Zero
             };
             
@@ -86,7 +98,6 @@ namespace QuestPDF.Elements
             {
                 Element = Content,
                 Measurement = contentMeasurement,
-                Size = new Size(availableSpace.Width, contentMeasurement.Height),
                 Offset = new Position(0, beforeMeasurement.Height)
             };
 
@@ -94,7 +105,6 @@ namespace QuestPDF.Elements
             {
                 Element = After,
                 Measurement = afterMeasurement,
-                Size = new Size(availableSpace.Width, afterMeasurement.Height),
                 Offset = new Position(0, beforeMeasurement.Height + contentMeasurement.Height)
             };
         }