Browse Source

Feature: layout-issue debugging feature provides more details regarding reasons of the SpacePlan.Wrap operation (#936)

* Layout debugging enhancement: providing reason of the wrap operation

* Revert changes to ReportSample

* Layout Debugging Wrap Reason: updated tests

* Layout Debugging Wrap Reason: code refactoring
Marcin Ziąbek 1 year ago
parent
commit
60d916fc1d
45 changed files with 202 additions and 133 deletions
  1. 3 3
      Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs
  2. 1 1
      Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs
  3. 1 0
      Source/QuestPDF.UnitTests/AlignmentTests.cs
  4. 4 4
      Source/QuestPDF.UnitTests/AspectRatioTests.cs
  5. 5 5
      Source/QuestPDF.UnitTests/ColumnTests.cs
  6. 6 6
      Source/QuestPDF.UnitTests/ConstrainedTests.cs
  7. 8 8
      Source/QuestPDF.UnitTests/DecorationTests.cs
  8. 3 3
      Source/QuestPDF.UnitTests/EnsureSpaceTests.cs
  9. 2 2
      Source/QuestPDF.UnitTests/ExtendTests.cs
  10. 4 4
      Source/QuestPDF.UnitTests/LayersTests.cs
  11. 4 4
      Source/QuestPDF.UnitTests/PaddingTests.cs
  12. 2 2
      Source/QuestPDF.UnitTests/ScaleTests.cs
  13. 3 3
      Source/QuestPDF.UnitTests/ShowEntireTests.cs
  14. 2 2
      Source/QuestPDF.UnitTests/SimpleRotateTests.cs
  15. 2 2
      Source/QuestPDF.UnitTests/TestEngine/SimpleContainerTests.cs
  16. 1 0
      Source/QuestPDF.UnitTests/TestEngine/TestPlan.cs
  17. 3 3
      Source/QuestPDF.UnitTests/UnconstrainedTests.cs
  18. 4 1
      Source/QuestPDF/Drawing/Proxy/LayoutDebugging.cs
  19. 1 1
      Source/QuestPDF/Drawing/Proxy/OverflowDebuggingProxy.cs
  20. 8 6
      Source/QuestPDF/Drawing/SpacePlan.cs
  21. 3 3
      Source/QuestPDF/Elements/AspectRatio.cs
  22. 6 3
      Source/QuestPDF/Elements/Column.cs
  23. 3 3
      Source/QuestPDF/Elements/Constrained.cs
  24. 55 24
      Source/QuestPDF/Elements/Decoration.cs
  25. 1 1
      Source/QuestPDF/Elements/DynamicImage.cs
  26. 1 1
      Source/QuestPDF/Elements/DynamicSvgImage.cs
  27. 1 1
      Source/QuestPDF/Elements/Empty.cs
  28. 1 1
      Source/QuestPDF/Elements/EnsureSpace.cs
  29. 1 1
      Source/QuestPDF/Elements/Image.cs
  30. 1 1
      Source/QuestPDF/Elements/Inlined.cs
  31. 6 1
      Source/QuestPDF/Elements/Layers.cs
  32. 1 1
      Source/QuestPDF/Elements/LayoutOverflowVisualization.cs
  33. 19 7
      Source/QuestPDF/Elements/Line.cs
  34. 2 2
      Source/QuestPDF/Elements/Padding.cs
  35. 1 1
      Source/QuestPDF/Elements/PageBreak.cs
  36. 6 3
      Source/QuestPDF/Elements/Row.cs
  37. 6 6
      Source/QuestPDF/Elements/ScaleToFit.cs
  38. 8 5
      Source/QuestPDF/Elements/ShowEntire.cs
  39. 1 1
      Source/QuestPDF/Elements/SkipOnce.cs
  40. 1 1
      Source/QuestPDF/Elements/StopPaging.cs
  41. 1 1
      Source/QuestPDF/Elements/SvgImage.cs
  42. 1 1
      Source/QuestPDF/Elements/SvgPath.cs
  43. 2 2
      Source/QuestPDF/Elements/Table/Table.cs
  44. 1 1
      Source/QuestPDF/Elements/Text/TextBlock.cs
  45. 6 1
      Source/QuestPDF/Infrastructure/ContainerElement.cs

+ 3 - 3
Source/QuestPDF.LayoutTests/TestEngine/MockChild.cs

@@ -26,10 +26,10 @@ internal class ElementMock : Element
     internal override SpacePlan Measure(Size availableSpace)
     internal override SpacePlan Measure(Size availableSpace)
     {
     {
         if (TotalWidth > availableSpace.Width)
         if (TotalWidth > availableSpace.Width)
-            return SpacePlan.Wrap();
-        
+            return SpacePlan.Wrap("The content requires more horizontal space than available.");
+
         if (availableSpace.Height < Size.Epsilon)
         if (availableSpace.Height < Size.Epsilon)
-            return SpacePlan.Wrap();
+            return SpacePlan.Wrap("The content requires more vertical space than available.");
 
 
         var remainingHeight = TotalHeight - HeightOffset;
         var remainingHeight = TotalHeight - HeightOffset;
 
 

+ 1 - 1
Source/QuestPDF.LayoutTests/TestEngine/WrapChild.cs

@@ -8,7 +8,7 @@ internal class WrapChild : Element
 {
 {
     internal override SpacePlan Measure(Size availableSpace)
     internal override SpacePlan Measure(Size availableSpace)
     {
     {
-        return SpacePlan.Wrap();
+        return SpacePlan.Wrap("This element is used only for testing purposes and does not fit on any space by design.");
     }
     }
 
 
     internal override void Draw(Size availableSpace)
     internal override void Draw(Size availableSpace)

+ 1 - 0
Source/QuestPDF.UnitTests/AlignmentTests.cs

@@ -11,6 +11,7 @@ namespace QuestPDF.UnitTests
     {
     {
         [Test]
         [Test]
         public void Measure() => SimpleContainerTests.Measure<Alignment>();
         public void Measure() => SimpleContainerTests.Measure<Alignment>();
+        
         [Test]
         [Test]
         public void Draw_HorizontalCenter_VerticalCenter()
         public void Draw_HorizontalCenter_VerticalCenter()
         {
         {

+ 4 - 4
Source/QuestPDF.UnitTests/AspectRatioTests.cs

@@ -53,8 +53,8 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(400, 201))
                 .MeasureElement(new Size(400, 201))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]
@@ -85,7 +85,7 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(400, 199))
                 .MeasureElement(new Size(400, 199))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("To preserve the target aspect ratio, the content requires more vertical space than available."));
         }
         }
         
         
         [Test]
         [Test]
@@ -116,7 +116,7 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(399, 200))
                 .MeasureElement(new Size(399, 200))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("To preserve the target aspect ratio, the content requires more horizontal space than available."));
         }
         }
         
         
         [Test]
         [Test]

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

@@ -38,8 +38,8 @@ namespace QuestPDF.UnitTests
             TestPlan
             TestPlan
                 .For(CreateColumnWithTwoItems)
                 .For(CreateColumnWithTwoItems)
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("The available space is not sufficient for even partially rendering a single item."));
         }
         }
         
         
         [Test]
         [Test]
@@ -59,7 +59,7 @@ namespace QuestPDF.UnitTests
                 .For(CreateColumnWithTwoItems)
                 .For(CreateColumnWithTwoItems)
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
                 .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
                 .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
-                .ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
+                .ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap("Mock"))
                 .CheckMeasureResult(SpacePlan.PartialRender(200, 100));
                 .CheckMeasureResult(SpacePlan.PartialRender(200, 100));
         }
         }
         
         
@@ -95,7 +95,7 @@ namespace QuestPDF.UnitTests
             TestPlan
             TestPlan
                 .For(CreateColumnWithTwoItems)
                 .For(CreateColumnWithTwoItems)
                 .DrawElement(new Size(400, 300))
                 .DrawElement(new Size(400, 300))
-                .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap("Mock"))
                 .CheckDrawResult();
                 .CheckDrawResult();
         }
         }
         
         
@@ -119,7 +119,7 @@ namespace QuestPDF.UnitTests
                 .For(CreateColumnWithTwoItems)
                 .For(CreateColumnWithTwoItems)
                 .DrawElement(new Size(400, 300))
                 .DrawElement(new Size(400, 300))
                 .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
                 .ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
-                .ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
+                .ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap("Mock"))
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectChildDraw("first", new Size(400, 100))
                 .ExpectChildDraw("first", new Size(400, 100))
                 .ExpectCanvasTranslate(0, 0)
                 .ExpectCanvasTranslate(0, 0)

+ 6 - 6
Source/QuestPDF.UnitTests/ConstrainedTests.cs

@@ -20,7 +20,7 @@ namespace QuestPDF.UnitTests
                     MinHeight = 100
                     MinHeight = 100
                 })
                 })
                 .MeasureElement(new Size(400, 50))
                 .MeasureElement(new Size(400, 50))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("The available vertical space is less than the minimum height."));
         }
         }
         
         
         [Test]
         [Test]
@@ -91,8 +91,8 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(400, 200))
                 .MeasureElement(new Size(400, 200))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         #endregion
         #endregion
@@ -108,7 +108,7 @@ namespace QuestPDF.UnitTests
                     MinWidth = 100
                     MinWidth = 100
                 })
                 })
                 .MeasureElement(new Size(50, 400))
                 .MeasureElement(new Size(50, 400))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("The available horizontal space is less than the minimum width."));
         }
         }
         
         
         [Test]
         [Test]
@@ -179,8 +179,8 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(200, 400))
                 .MeasureElement(new Size(200, 400))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .ExpectChildMeasure(new Size(100, 400), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(100, 400), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         #endregion
         #endregion

+ 8 - 8
Source/QuestPDF.UnitTests/DecorationTests.cs

@@ -27,10 +27,10 @@ namespace QuestPDF.UnitTests
             TestPlan
             TestPlan
                 .For(CreateDecoration)
                 .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.Wrap("Mock"))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("Decoration slot (before or after) does not fit fully on the page."));
         }
         }
         
         
         [Test]
         [Test]
@@ -41,8 +41,8 @@ namespace QuestPDF.UnitTests
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("after", 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());
+                .ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("The primary content does not fit on the page."));
         }
         }
         
         
         [Test]
         [Test]
@@ -52,9 +52,9 @@ namespace QuestPDF.UnitTests
                 .For(CreateDecoration)
                 .For(CreateDecoration)
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
-                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.Wrap())
+                .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.Wrap("Mock"))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("Decoration slot (before or after) does not fit fully on the page."));
         }
         }
         
         
         [Test]
         [Test]
@@ -66,7 +66,7 @@ namespace QuestPDF.UnitTests
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.PartialRender(100, 50))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.PartialRender(100, 50))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("Decoration slot (before or after) does not fit fully on the page."));
         }
         }
         
         
         [Test]
         [Test]
@@ -78,7 +78,7 @@ namespace QuestPDF.UnitTests
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("before", new Size(400, 300), SpacePlan.FullRender(100, 50))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.PartialRender(100, 50))
                 .ExpectChildMeasure("after", new Size(400, 300), SpacePlan.PartialRender(100, 50))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
                 .ExpectChildMeasure("content", new Size(400, 250), SpacePlan.FullRender(100, 100))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("Decoration slot (before or after) does not fit fully on the page."));
         }
         }
         
         
         [Test]
         [Test]

+ 3 - 3
Source/QuestPDF.UnitTests/EnsureSpaceTests.cs

@@ -19,8 +19,8 @@ namespace QuestPDF.UnitTests
                     MinHeight = 200
                     MinHeight = 200
                 })
                 })
                 .MeasureElement(new Size(400, 100))
                 .MeasureElement(new Size(400, 100))
-                .ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]
@@ -34,7 +34,7 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(400, 100))
                 .MeasureElement(new Size(400, 100))
                 .ExpectChildMeasure(new Size(400, 100), SpacePlan.PartialRender(300, 50))
                 .ExpectChildMeasure(new Size(400, 100), SpacePlan.PartialRender(300, 50))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("The available vertical space is smaller than requested in the constraint."));
         }
         }
         
         
         [Test]
         [Test]

+ 2 - 2
Source/QuestPDF.UnitTests/ExtendTests.cs

@@ -18,8 +18,8 @@ namespace QuestPDF.UnitTests
                     Child = x.CreateChild()
                     Child = x.CreateChild()
                 })
                 })
                 .MeasureElement(new Size(400, 200))
                 .MeasureElement(new Size(400, 200))
-                .ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]

+ 4 - 4
Source/QuestPDF.UnitTests/LayersTests.cs

@@ -45,8 +45,8 @@ namespace QuestPDF.UnitTests
             TestPlan
             TestPlan
                 .For(GetLayers)
                 .For(GetLayers)
                 .MeasureElement(new Size(800, 600))
                 .MeasureElement(new Size(800, 600))
-                .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("The content of the primary layer does not fit (even partially) the available space."));
         }
         }
 
 
         [Test]
         [Test]
@@ -101,7 +101,7 @@ namespace QuestPDF.UnitTests
                 
                 
                 .ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.PartialRender(100, 200))
                 .ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.PartialRender(100, 200))
                 .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
                 .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
-                .ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.Wrap())
+                .ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.Wrap("Mock"))
                 
                 
                 .ExpectChildDraw(BackgroundLayer, new Size(800, 600))
                 .ExpectChildDraw(BackgroundLayer, new Size(800, 600))
                 .ExpectChildDraw(MainLayer, new Size(800, 600))
                 .ExpectChildDraw(MainLayer, new Size(800, 600))
@@ -116,7 +116,7 @@ namespace QuestPDF.UnitTests
                 .For(GetLayers)
                 .For(GetLayers)
                 .MeasureElement(new Size(800, 600))
                 .MeasureElement(new Size(800, 600))
                 
                 
-                .ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.Wrap())
+                .ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.Wrap("Mock"))
                 .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
                 .ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
                 .ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.PartialRender(300, 400))
                 .ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.PartialRender(300, 400))
                 
                 

+ 4 - 4
Source/QuestPDF.UnitTests/PaddingTests.cs

@@ -39,7 +39,7 @@ namespace QuestPDF.UnitTests
                 .For(GetPadding)
                 .For(GetPadding)
                 .MeasureElement(new Size(50, 300))
                 .MeasureElement(new Size(50, 300))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("The available space is negative."));
         }
         }
         
         
         [Test]
         [Test]
@@ -49,7 +49,7 @@ namespace QuestPDF.UnitTests
                 .For(GetPadding)
                 .For(GetPadding)
                 .MeasureElement(new Size(20, 300))
                 .MeasureElement(new Size(20, 300))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
                 .ExpectChildMeasure(Size.Zero, SpacePlan.PartialRender(Size.Zero))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("The available space is negative."));
         }
         }
         
         
         [Test]
         [Test]
@@ -68,8 +68,8 @@ namespace QuestPDF.UnitTests
             TestPlan
             TestPlan
                 .For(GetPadding)
                 .For(GetPadding)
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure(new Size(340, 260), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(340, 260), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]

+ 2 - 2
Source/QuestPDF.UnitTests/ScaleTests.cs

@@ -22,8 +22,8 @@ namespace QuestPDF.UnitTests
                     ScaleY = 2
                     ScaleY = 2
                 })
                 })
                 .MeasureElement(new Size(900, 800))
                 .MeasureElement(new Size(900, 800))
-                .ExpectChildMeasure(new Size(300, 400), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(300, 400), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]

+ 3 - 3
Source/QuestPDF.UnitTests/ShowEntireTests.cs

@@ -18,8 +18,8 @@ namespace QuestPDF.UnitTests
                     Child = x.CreateChild()
                     Child = x.CreateChild()
                 })
                 })
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Child element does not fit (even partially) on the page."));
         }
         }
         
         
         [Test]
         [Test]
@@ -32,7 +32,7 @@ namespace QuestPDF.UnitTests
                 })
                 })
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
                 .ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(300, 200))
                 .ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(300, 200))
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .CheckMeasureResult(SpacePlan.Wrap("Child element fits only partially on the page."));
         }
         }
         
         
         [Test]
         [Test]

+ 2 - 2
Source/QuestPDF.UnitTests/SimpleRotateTests.cs

@@ -21,8 +21,8 @@ namespace QuestPDF.UnitTests
                     TurnCount = 0
                     TurnCount = 0
                 })
                 })
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]

+ 2 - 2
Source/QuestPDF.UnitTests/TestEngine/SimpleContainerTests.cs

@@ -22,8 +22,8 @@ namespace QuestPDF.UnitTests.TestEngine
                     Child = x.CreateChild()
                     Child = x.CreateChild()
                 })
                 })
                 .MeasureElement(new Size(400, 300))
                 .MeasureElement(new Size(400, 300))
-                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         private static void Measure_PartialRender<TElement>() where TElement : Element, IContainer, new()
         private static void Measure_PartialRender<TElement>() where TElement : Element, IContainer, new()

+ 1 - 0
Source/QuestPDF.UnitTests/TestEngine/TestPlan.cs

@@ -206,6 +206,7 @@ namespace QuestPDF.UnitTests.TestEngine
             ClassicAssert.AreEqual(expected.Width, actual.Width, "Measure: width");
             ClassicAssert.AreEqual(expected.Width, actual.Width, "Measure: width");
             ClassicAssert.AreEqual(expected.Height, actual.Height, "Measure: height");
             ClassicAssert.AreEqual(expected.Height, actual.Height, "Measure: height");
             ClassicAssert.AreEqual(expected.Type, actual.Type, "Measure: height");
             ClassicAssert.AreEqual(expected.Type, actual.Type, "Measure: height");
+            ClassicAssert.AreEqual(expected.WrapReason, actual.WrapReason, "Measure: wrap");
             
             
             return this;
             return this;
         }
         }

+ 3 - 3
Source/QuestPDF.UnitTests/UnconstrainedTests.cs

@@ -20,8 +20,8 @@ namespace QuestPDF.UnitTests
                     Child = x.CreateChild()
                     Child = x.CreateChild()
                 })
                 })
                 .MeasureElement(new Size(900, 800))
                 .MeasureElement(new Size(900, 800))
-                .ExpectChildMeasure(Size.Max, SpacePlan.Wrap())
-                .CheckMeasureResult(SpacePlan.Wrap());
+                .ExpectChildMeasure(Size.Max, SpacePlan.Wrap("Mock"))
+                .CheckMeasureResult(SpacePlan.Wrap("Forwarded from child"));
         }
         }
         
         
         [Test]
         [Test]
@@ -63,7 +63,7 @@ namespace QuestPDF.UnitTests
                     Child = x.CreateChild()
                     Child = x.CreateChild()
                 })
                 })
                 .DrawElement(new Size(900, 800))
                 .DrawElement(new Size(900, 800))
-                .ExpectChildMeasure(Size.Max, SpacePlan.Wrap())
+                .ExpectChildMeasure(Size.Max, SpacePlan.Wrap("Mock"))
                 .CheckDrawResult();
                 .CheckDrawResult();
         }
         }
         
         

+ 4 - 1
Source/QuestPDF/Drawing/Proxy/LayoutDebugging.cs

@@ -16,7 +16,7 @@ internal static class LayoutDebugging
         return TryVerticalOverflow()
         return TryVerticalOverflow()
                ?? TryHorizontalOverflow() 
                ?? TryHorizontalOverflow() 
                ?? TryUnconstrainedOverflow()
                ?? TryUnconstrainedOverflow()
-               ?? SpacePlan.Wrap();
+               ?? SpacePlan.Wrap("Extending the available space does not allow the child to fit on the page.");
 
 
         SpacePlan? TryOverflow(Size targetSpace)
         SpacePlan? TryOverflow(Size targetSpace)
         {
         {
@@ -244,6 +244,9 @@ internal static class LayoutDebugging
             
             
             yield return $"Available Space: {proxy.MeasurementSize}";
             yield return $"Available Space: {proxy.MeasurementSize}";
             yield return $"Space Plan: {proxy.SpacePlan}";
             yield return $"Space Plan: {proxy.SpacePlan}";
+
+            if (proxy.SpacePlan?.Type == SpacePlanType.Wrap)
+                yield return "Wrap Reason: " + (proxy.SpacePlan?.WrapReason ?? "Unknown");
             
             
             yield return new string('-', title.Length + 1);
             yield return new string('-', title.Length + 1);
             
             

+ 1 - 1
Source/QuestPDF/Drawing/Proxy/OverflowDebuggingProxy.cs

@@ -16,7 +16,7 @@ internal class OverflowDebuggingProxy : ElementProxy
 
 
     internal override SpacePlan Measure(Size availableSpace)
     internal override SpacePlan Measure(Size availableSpace)
     {
     {
-        var spacePlan = Child.Measure(availableSpace);
+        var spacePlan = base.Measure(availableSpace);
 
 
         if (IsMeasuring)
         if (IsMeasuring)
         {
         {

+ 8 - 6
Source/QuestPDF/Drawing/SpacePlan.cs

@@ -7,26 +7,28 @@ namespace QuestPDF.Drawing
         public readonly SpacePlanType Type;
         public readonly SpacePlanType Type;
         public readonly float Width;
         public readonly float Width;
         public readonly float Height;
         public readonly float Height;
+        public readonly string? WrapReason;
 
 
-        internal SpacePlan(SpacePlanType type, float width, float height)
+        internal SpacePlan(SpacePlanType type, float width, float height, string? wrapReason = null)
         {
         {
             Type = type;
             Type = type;
             Width = width;
             Width = width;
             Height = height;
             Height = height;
+            WrapReason = wrapReason;
         }
         }
 
 
-        internal static SpacePlan Empty() => new SpacePlan(SpacePlanType.Empty, 0, 0);
+        internal static SpacePlan Empty() => new(SpacePlanType.Empty, 0, 0);
         
         
-        internal static SpacePlan Wrap() => new SpacePlan(SpacePlanType.Wrap, 0, 0);
+        internal static SpacePlan Wrap(string reason) => new(SpacePlanType.Wrap, 0, 0, reason);
         
         
-        internal static SpacePlan PartialRender(float width, float height) => new SpacePlan(SpacePlanType.PartialRender, width, height);
+        internal static SpacePlan PartialRender(float width, float height) => new(SpacePlanType.PartialRender, width, height);
 
 
         internal static SpacePlan PartialRender(Size size) => PartialRender(size.Width, size.Height);
         internal static SpacePlan PartialRender(Size size) => PartialRender(size.Width, size.Height);
         
         
-        internal static SpacePlan FullRender(float width, float height) => new SpacePlan(SpacePlanType.FullRender, width, height);
+        internal static SpacePlan FullRender(float width, float height) => new(SpacePlanType.FullRender, width, height);
 
 
         internal static SpacePlan FullRender(Size size) => FullRender(size.Width, size.Height);
         internal static SpacePlan FullRender(Size size) => FullRender(size.Width, size.Height);
-
+        
         public override string ToString()
         public override string ToString()
         {
         {
             if (Type == SpacePlanType.Wrap)
             if (Type == SpacePlanType.Wrap)

+ 3 - 3
Source/QuestPDF/Elements/AspectRatio.cs

@@ -23,15 +23,15 @@ namespace QuestPDF.Elements
             var targetSize = GetTargetSize(availableSpace);
             var targetSize = GetTargetSize(availableSpace);
             
             
             if (targetSize.Height > availableSpace.Height + Size.Epsilon)
             if (targetSize.Height > availableSpace.Height + Size.Epsilon)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("To preserve the target aspect ratio, the content requires more vertical space than available.");
             
             
             if (targetSize.Width > availableSpace.Width + Size.Epsilon)
             if (targetSize.Width > availableSpace.Width + Size.Epsilon)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("To preserve the target aspect ratio, the content requires more horizontal space than available.");
 
 
             var childSize = base.Measure(targetSize);
             var childSize = base.Measure(targetSize);
 
 
             if (childSize.Type == SpacePlanType.Wrap)
             if (childSize.Type == SpacePlanType.Wrap)
-                return SpacePlan.Wrap();
+                return childSize;
 
 
             if (childSize.Type == SpacePlanType.PartialRender)
             if (childSize.Type == SpacePlanType.PartialRender)
                 return SpacePlan.PartialRender(targetSize);
                 return SpacePlan.PartialRender(targetSize);

+ 6 - 3
Source/QuestPDF/Elements/Column.cs

@@ -47,14 +47,17 @@ namespace QuestPDF.Elements
             var renderingCommands = PlanLayout(availableSpace);
             var renderingCommands = PlanLayout(availableSpace);
 
 
             if (!renderingCommands.Any())
             if (!renderingCommands.Any())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is not sufficient for even partially rendering a single item.");
 
 
             var width = renderingCommands.Max(x => x.Measurement.Width);
             var width = renderingCommands.Max(x => x.Measurement.Width);
             var height = renderingCommands.Last().Offset.Y + renderingCommands.Last().Measurement.Height;
             var height = renderingCommands.Last().Offset.Y + renderingCommands.Last().Measurement.Height;
             var size = new Size(width, height);
             var size = new Size(width, height);
             
             
-            if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
-                return SpacePlan.Wrap();
+            if (width > availableSpace.Width + Size.Epsilon)
+                return SpacePlan.Wrap("The content requires more horizontal space than available.");
+            
+            if (height > availableSpace.Height + Size.Epsilon)
+                return SpacePlan.Wrap("The content requires more vertical space than available.");
             
             
             var totalRenderedItems = CurrentRenderingIndex + renderingCommands.Count(x => x.Measurement.Type is SpacePlanType.Empty or SpacePlanType.FullRender);
             var totalRenderedItems = CurrentRenderingIndex + renderingCommands.Count(x => x.Measurement.Type is SpacePlanType.Empty or SpacePlanType.FullRender);
             var willBeFullyRendered = totalRenderedItems == Items.Count;
             var willBeFullyRendered = totalRenderedItems == Items.Count;

+ 3 - 3
Source/QuestPDF/Elements/Constrained.cs

@@ -23,10 +23,10 @@ namespace QuestPDF.Elements
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
             
             
             if (MinWidth > availableSpace.Width + Size.Epsilon)
             if (MinWidth > availableSpace.Width + Size.Epsilon)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available horizontal space is less than the minimum width.");
             
             
             if (MinHeight > availableSpace.Height + Size.Epsilon)
             if (MinHeight > availableSpace.Height + Size.Epsilon)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available vertical space is less than the minimum height.");
             
             
             var available = new Size(
             var available = new Size(
                 Min(MaxWidth, availableSpace.Width),
                 Min(MaxWidth, availableSpace.Width),
@@ -35,7 +35,7 @@ namespace QuestPDF.Elements
             var measurement = base.Measure(available);
             var measurement = base.Measure(available);
 
 
             if (measurement.Type == SpacePlanType.Wrap)
             if (measurement.Type == SpacePlanType.Wrap)
-                return SpacePlan.Wrap();
+                return measurement;
             
             
             var actualSize = new Size(
             var actualSize = new Size(
                 Max(MinWidth, measurement.Width),
                 Max(MinWidth, measurement.Width),

+ 55 - 24
Source/QuestPDF/Elements/Decoration.cs

@@ -6,11 +6,18 @@ using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Elements
 namespace QuestPDF.Elements
 {
 {
-    internal sealed class DecorationItemRenderingCommand
+    internal class DecorationElementLayout
     {
     {
-        public Element Element { get; set; }
-        public SpacePlan Measurement { get; set; }
-        public Position Offset { get; set; }
+        public ItemCommand Before { get; set; }
+        public ItemCommand Content { get; set; }
+        public ItemCommand After { get; set; }
+        
+        public struct ItemCommand
+        {
+            public Element Element;
+            public SpacePlan Measurement;
+            public Position Offset;
+        }
     }
     }
 
 
     internal sealed class Decoration : Element, IContentDirectionAware
     internal sealed class Decoration : Element, IContentDirectionAware
@@ -37,22 +44,38 @@ namespace QuestPDF.Elements
 
 
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            var renderingCommands = PlanLayout(availableSpace);
+            var layout = PlanLayout(availableSpace);
 
 
-            if (renderingCommands.Single(x => x.Element == Content).Measurement.Type == SpacePlanType.Empty)
+            if (layout.Content.Measurement.Type == SpacePlanType.Empty)
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
             
             
-            if (renderingCommands.Any(x => x.Measurement.Type == SpacePlanType.Wrap))
-                return SpacePlan.Wrap();
+            if (layout.Content.Measurement.Type == SpacePlanType.Wrap)
+                return SpacePlan.Wrap("The primary content does not fit on the page.");
 
 
-            var width = renderingCommands.Max(x => x.Measurement.Width);
-            var height = renderingCommands.Sum(x => x.Measurement.Height);
+            if (layout.Before.Measurement.Type == SpacePlanType.Wrap)
+                return layout.Before.Measurement;
+            
+            if (layout.After.Measurement.Type == SpacePlanType.Wrap)
+                return layout.After.Measurement;
+            
+            var itemMeasurements = new[]
+            {
+                layout.Before.Measurement,
+                layout.Content.Measurement,
+                layout.After.Measurement
+            };
+            
+            var width = itemMeasurements.Max(x => x.Width);
+            var height = itemMeasurements.Sum(x => x.Height);
             var size = new Size(width, height);
             var size = new Size(width, height);
             
             
-            if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
-                return SpacePlan.Wrap();
+            if (width > availableSpace.Width + Size.Epsilon)
+                return SpacePlan.Wrap("The content slot requires more horizontal space than available.");
             
             
-            var willBeFullyRendered = renderingCommands.All(x => x.Measurement.Type is SpacePlanType.Empty or SpacePlanType.FullRender);
+            if (height > availableSpace.Height + Size.Epsilon)
+                return SpacePlan.Wrap("The content slot requires more vertical space than available.");
+            
+            var willBeFullyRendered = itemMeasurements.All(x => x.Type is SpacePlanType.Empty or SpacePlanType.FullRender);
 
 
             return willBeFullyRendered
             return willBeFullyRendered
                 ? SpacePlan.FullRender(size)
                 ? SpacePlan.FullRender(size)
@@ -61,10 +84,18 @@ namespace QuestPDF.Elements
 
 
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
         {
         {
-            var renderingCommands = PlanLayout(availableSpace).ToList();
-            var width = renderingCommands.Max(x => x.Measurement.Width);
+            var layout = PlanLayout(availableSpace);
             
             
-            foreach (var command in renderingCommands)
+            var drawingCommands = new[]
+            {
+                layout.Before,
+                layout.Content,
+                layout.After
+            };
+            
+            var width = drawingCommands.Max(x => x.Measurement.Width);
+            
+            foreach (var command in drawingCommands)
             {
             {
                 var elementSize = new Size(width, command.Measurement.Height);
                 var elementSize = new Size(width, command.Measurement.Height);
                 
                 
@@ -78,14 +109,14 @@ namespace QuestPDF.Elements
             }
             }
         }
         }
 
 
-        private DecorationItemRenderingCommand[] PlanLayout(Size availableSpace)
+        private DecorationElementLayout PlanLayout(Size availableSpace)
         {
         {
             SpacePlan GetDecorationMeasurement(Element element)
             SpacePlan GetDecorationMeasurement(Element element)
             {
             {
                 var measurement = element.Measure(availableSpace);
                 var measurement = element.Measure(availableSpace);
 
 
                 if (measurement.Type is SpacePlanType.PartialRender or SpacePlanType.Wrap)
                 if (measurement.Type is SpacePlanType.PartialRender or SpacePlanType.Wrap)
-                    return SpacePlan.Wrap();
+                    return SpacePlan.Wrap("Decoration slot (before or after) does not fit fully on the page.");
 
 
                 return measurement;
                 return measurement;
             }
             }
@@ -96,26 +127,26 @@ namespace QuestPDF.Elements
             var contentSpace = new Size(availableSpace.Width, availableSpace.Height - beforeMeasurement.Height - afterMeasurement.Height);
             var contentSpace = new Size(availableSpace.Width, availableSpace.Height - beforeMeasurement.Height - afterMeasurement.Height);
             var contentMeasurement = Content.Measure(contentSpace);
             var contentMeasurement = Content.Measure(contentSpace);
 
 
-            return new[]
-            { 
-                new DecorationItemRenderingCommand
+            return new DecorationElementLayout
+            {
+                Before = new DecorationElementLayout.ItemCommand
                 {
                 {
                     Element = Before,
                     Element = Before,
                     Measurement = beforeMeasurement,
                     Measurement = beforeMeasurement,
                     Offset = Position.Zero
                     Offset = Position.Zero
                 },
                 },
-                new DecorationItemRenderingCommand
+                Content = new DecorationElementLayout.ItemCommand
                 {
                 {
                     Element = Content,
                     Element = Content,
                     Measurement = contentMeasurement,
                     Measurement = contentMeasurement,
                     Offset = new Position(0, beforeMeasurement.Height)
                     Offset = new Position(0, beforeMeasurement.Height)
                 },
                 },
-                new DecorationItemRenderingCommand
+                After = new DecorationElementLayout.ItemCommand
                 {
                 {
                     Element = After,
                     Element = After,
                     Measurement = afterMeasurement,
                     Measurement = afterMeasurement,
                     Offset = new Position(0, beforeMeasurement.Height + contentMeasurement.Height)
                     Offset = new Position(0, beforeMeasurement.Height + contentMeasurement.Height)
-                }
+                },
             };
             };
         }
         }
     }
     }

+ 1 - 1
Source/QuestPDF/Elements/DynamicImage.cs

@@ -51,7 +51,7 @@ namespace QuestPDF.Elements
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
 
 
             if (availableSpace.IsNegative())
             if (availableSpace.IsNegative())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is negative.");
         
         
             return SpacePlan.FullRender(availableSpace);
             return SpacePlan.FullRender(availableSpace);
         }
         }

+ 1 - 1
Source/QuestPDF/Elements/DynamicSvgImage.cs

@@ -33,7 +33,7 @@ internal class DynamicSvgImage : Element, IStateResettable
             return SpacePlan.Empty();
             return SpacePlan.Empty();
 
 
         if (availableSpace.IsNegative())
         if (availableSpace.IsNegative())
-            return SpacePlan.Wrap();
+            return SpacePlan.Wrap("The available space is negative.");
         
         
         return SpacePlan.FullRender(availableSpace);
         return SpacePlan.FullRender(availableSpace);
     }
     }

+ 1 - 1
Source/QuestPDF/Elements/Empty.cs

@@ -11,7 +11,7 @@ namespace QuestPDF.Elements
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
             return availableSpace.IsNegative() 
             return availableSpace.IsNegative() 
-                ? SpacePlan.Wrap() 
+                ? SpacePlan.Wrap("The available space is negative.") 
                 : SpacePlan.FullRender(0, 0);
                 : SpacePlan.FullRender(0, 0);
         }
         }
 
 

+ 1 - 1
Source/QuestPDF/Elements/EnsureSpace.cs

@@ -13,7 +13,7 @@ namespace QuestPDF.Elements
             var measurement = base.Measure(availableSpace);
             var measurement = base.Measure(availableSpace);
 
 
             if (measurement.Type == SpacePlanType.PartialRender && availableSpace.Height < MinHeight)
             if (measurement.Type == SpacePlanType.PartialRender && availableSpace.Height < MinHeight)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available vertical space is smaller than requested in the constraint.");
 
 
             return measurement;
             return measurement;
         }
         }

+ 1 - 1
Source/QuestPDF/Elements/Image.cs

@@ -26,7 +26,7 @@ namespace QuestPDF.Elements
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
 
 
             if (availableSpace.IsNegative())
             if (availableSpace.IsNegative())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is negative.");
         
         
             return SpacePlan.FullRender(Size.Zero);
             return SpacePlan.FullRender(Size.Zero);
         }
         }

+ 1 - 1
Source/QuestPDF/Elements/Inlined.cs

@@ -53,7 +53,7 @@ namespace QuestPDF.Elements
             var lines = Compose(availableSpace);
             var lines = Compose(availableSpace);
 
 
             if (!lines.Any())
             if (!lines.Any())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is not sufficient to fully render even a single item.");
 
 
             var lineSizes = lines
             var lineSizes = lines
                 .Select(line =>
                 .Select(line =>

+ 6 - 1
Source/QuestPDF/Elements/Layers.cs

@@ -21,9 +21,14 @@ namespace QuestPDF.Elements
         
         
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            return Children
+            var measurement = Children
                 .Single(x => x.IsPrimary)
                 .Single(x => x.IsPrimary)
                 .Measure(availableSpace);
                 .Measure(availableSpace);
+
+            if (measurement.Type == SpacePlanType.Wrap)
+                return SpacePlan.Wrap("The content of the primary layer does not fit (even partially) the available space.");
+
+            return measurement;
         }
         }
 
 
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)

+ 1 - 1
Source/QuestPDF/Elements/LayoutOverflowVisualization.cs

@@ -19,7 +19,7 @@ internal class LayoutOverflowVisualization : ContainerElement, IContentDirection
     internal override SpacePlan Measure(Size availableSpace)
     internal override SpacePlan Measure(Size availableSpace)
     {
     {
         if (Size.Equal(availableSpace, Size.Zero))
         if (Size.Equal(availableSpace, Size.Zero))
-            return SpacePlan.Wrap();
+            return SpacePlan.Wrap("There is no available space.");
         
         
         var childSize = base.Measure(availableSpace);
         var childSize = base.Measure(availableSpace);
         
         

+ 19 - 7
Source/QuestPDF/Elements/Line.cs

@@ -1,4 +1,5 @@
-using QuestPDF.Drawing;
+using System;
+using QuestPDF.Drawing;
 using QuestPDF.Helpers;
 using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 
 
@@ -34,14 +35,25 @@ namespace QuestPDF.Elements
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
             
             
             if (availableSpace.IsNegative())
             if (availableSpace.IsNegative())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is negative.");
+
+            if (Type == LineType.Vertical)
+            {
+                if (availableSpace.Width + Size.Epsilon < Thickness)
+                    return SpacePlan.Wrap("The line thickness is greater than the available horizontal space.");
+
+                return SpacePlan.FullRender(Thickness, 0);
+            }
             
             
-            return Type switch
+            if (Type == LineType.Horizontal)
             {
             {
-                LineType.Vertical when availableSpace.Width + Infrastructure.Size.Epsilon >= Thickness => SpacePlan.FullRender(Thickness, 0),
-                LineType.Horizontal when availableSpace.Height + Infrastructure.Size.Epsilon >= Thickness => SpacePlan.FullRender(0, Thickness),
-                _ => SpacePlan.Wrap()
-            };
+                if (availableSpace.Height + Size.Epsilon < Thickness)
+                    return SpacePlan.Wrap("The line thickness is greater than the available vertical space.");
+
+                return SpacePlan.FullRender(0, Thickness);
+            }
+
+            throw new NotSupportedException();
         }
         }
 
 
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)

+ 2 - 2
Source/QuestPDF/Elements/Padding.cs

@@ -16,8 +16,8 @@ namespace QuestPDF.Elements
         {
         {
             var internalSpace = InternalSpace(availableSpace);
             var internalSpace = InternalSpace(availableSpace);
 
 
-            if (internalSpace.Width < -Size.Epsilon || internalSpace.Height < -Size.Epsilon)
-                return Child.IsEmpty() ? SpacePlan.Empty() : SpacePlan.Wrap();
+            if (internalSpace.IsNegative())
+                return Child.IsEmpty() ? SpacePlan.Empty() : SpacePlan.Wrap("The available space is negative.");
             
             
             var measure = base.Measure(internalSpace);
             var measure = base.Measure(internalSpace);
 
 

+ 1 - 1
Source/QuestPDF/Elements/PageBreak.cs

@@ -16,7 +16,7 @@ namespace QuestPDF.Elements
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
             if (availableSpace.IsNegative())
             if (availableSpace.IsNegative())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is negative.");
 
 
             if (IsRendered)
             if (IsRendered)
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();

+ 6 - 3
Source/QuestPDF/Elements/Row.cs

@@ -64,14 +64,17 @@ namespace QuestPDF.Elements
             var renderingCommands = PlanLayout(availableSpace);
             var renderingCommands = PlanLayout(availableSpace);
 
 
             if (renderingCommands.Any(x => !x.RowItem.IsRendered && x.Measurement.Type == SpacePlanType.Wrap))
             if (renderingCommands.Any(x => !x.RowItem.IsRendered && x.Measurement.Type == SpacePlanType.Wrap))
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("One of the items does not fit (even partially) in the available space.");
 
 
             var width = renderingCommands.Last().Offset.X + renderingCommands.Last().Size.Width;
             var width = renderingCommands.Last().Offset.X + renderingCommands.Last().Size.Width;
             var height = renderingCommands.Max(x => x.Size.Height);
             var height = renderingCommands.Max(x => x.Size.Height);
             var size = new Size(width, height);
             var size = new Size(width, height);
 
 
-            if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
-                return SpacePlan.Wrap();
+            if (width > availableSpace.Width + Size.Epsilon)
+                return SpacePlan.Wrap("The content requires more horizontal space than available.");
+            
+            if (height > availableSpace.Height + Size.Epsilon)
+                return SpacePlan.Wrap("The content requires more vertical space than available.");
             
             
             if (renderingCommands.Any(x => !x.RowItem.IsRendered && x.Measurement.Type == SpacePlanType.PartialRender))
             if (renderingCommands.Any(x => !x.RowItem.IsRendered && x.Measurement.Type == SpacePlanType.PartialRender))
                 return SpacePlan.PartialRender(size);
                 return SpacePlan.PartialRender(size);

+ 6 - 6
Source/QuestPDF/Elements/ScaleToFit.cs

@@ -8,20 +8,20 @@ namespace QuestPDF.Elements
     {
     {
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            var perfectScale = FindPerfectScale(Child, availableSpace);
+            var perfectScale = FindPerfectScale(availableSpace);
 
 
             if (perfectScale == null)
             if (perfectScale == null)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("Cannot find the perfect scale to fit the child element in the available space.");
 
 
             var scaledSpace = ScaleSize(availableSpace, 1 / perfectScale.Value);
             var scaledSpace = ScaleSize(availableSpace, 1 / perfectScale.Value);
-            var childSizeInScale = Child.Measure(scaledSpace);
+            var childSizeInScale = base.Measure(scaledSpace);
             var childSizeInOriginalScale = ScaleSize(childSizeInScale, perfectScale.Value);
             var childSizeInOriginalScale = ScaleSize(childSizeInScale, perfectScale.Value);
             return SpacePlan.FullRender(childSizeInOriginalScale);
             return SpacePlan.FullRender(childSizeInOriginalScale);
         }
         }
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
         {
         {
-            var perfectScale = FindPerfectScale(Child, availableSpace);
+            var perfectScale = FindPerfectScale(availableSpace);
             
             
             if (!perfectScale.HasValue)
             if (!perfectScale.HasValue)
                 return;
                 return;
@@ -39,7 +39,7 @@ namespace QuestPDF.Elements
             return new Size(size.Width * factor, size.Height * factor);
             return new Size(size.Width * factor, size.Height * factor);
         }
         }
         
         
-        private static float? FindPerfectScale(Element child, Size availableSpace)
+        private float? FindPerfectScale(Size availableSpace)
         {
         {
             if (ChildFits(1))
             if (ChildFits(1))
                 return 1;
                 return 1;
@@ -69,7 +69,7 @@ namespace QuestPDF.Elements
             bool ChildFits(float scale)
             bool ChildFits(float scale)
             {
             {
                 var scaledSpace = ScaleSize(availableSpace, 1 / scale);
                 var scaledSpace = ScaleSize(availableSpace, 1 / scale);
-                return child.Measure(scaledSpace).Type is SpacePlanType.Empty or SpacePlanType.FullRender;
+                return base.Measure(scaledSpace).Type is SpacePlanType.Empty or SpacePlanType.FullRender;
             }
             }
         }
         }
     }
     }

+ 8 - 5
Source/QuestPDF/Elements/ShowEntire.cs

@@ -8,11 +8,14 @@ namespace QuestPDF.Elements
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
             var childMeasurement = base.Measure(availableSpace);
             var childMeasurement = base.Measure(availableSpace);
-
-            if (childMeasurement.Type is SpacePlanType.Empty or SpacePlanType.FullRender)
-                return childMeasurement;
-
-            return SpacePlan.Wrap();
+            
+            if (childMeasurement.Type is SpacePlanType.Wrap)
+                return SpacePlan.Wrap("Child element does not fit (even partially) on the page.");
+            
+            if (childMeasurement.Type is SpacePlanType.PartialRender)
+                return SpacePlan.Wrap("Child element fits only partially on the page.");
+            
+            return childMeasurement;
         }
         }
     }
     }
 }
 }

+ 1 - 1
Source/QuestPDF/Elements/SkipOnce.cs

@@ -18,7 +18,7 @@ namespace QuestPDF.Elements
             if (!FirstPageWasSkipped)
             if (!FirstPageWasSkipped)
                 return SpacePlan.Empty();
                 return SpacePlan.Empty();
 
 
-            return Child.Measure(availableSpace);
+            return base.Measure(availableSpace);
         }
         }
 
 
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)

+ 1 - 1
Source/QuestPDF/Elements/StopPaging.cs

@@ -8,7 +8,7 @@ namespace QuestPDF.Elements
     {
     {
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            var measurement = Child.Measure(availableSpace);
+            var measurement = base.Measure(availableSpace);
 
 
             return measurement.Type switch
             return measurement.Type switch
             {
             {

+ 1 - 1
Source/QuestPDF/Elements/SvgImage.cs

@@ -24,7 +24,7 @@ internal class SvgImage : Element, IStateResettable
             return SpacePlan.Empty();
             return SpacePlan.Empty();
 
 
         if (availableSpace.IsNegative())
         if (availableSpace.IsNegative())
-            return SpacePlan.Wrap();
+            return SpacePlan.Wrap("The available space is negative.");
         
         
         return SpacePlan.FullRender(Size.Zero);
         return SpacePlan.FullRender(Size.Zero);
     }
     }

+ 1 - 1
Source/QuestPDF/Elements/SvgPath.cs

@@ -23,7 +23,7 @@ internal class SvgPath : Element, IStateResettable
             return SpacePlan.Empty();
             return SpacePlan.Empty();
 
 
         if (availableSpace.IsNegative())
         if (availableSpace.IsNegative())
-            return SpacePlan.Wrap();
+            return SpacePlan.Wrap("The available space is negative.");
         
         
         return SpacePlan.FullRender(Size.Zero);
         return SpacePlan.FullRender(Size.Zero);
     }
     }

+ 2 - 2
Source/QuestPDF/Elements/Table/Table.cs

@@ -94,14 +94,14 @@ namespace QuestPDF.Elements.Table
             var renderingCommands = PlanLayout(availableSpace);
             var renderingCommands = PlanLayout(availableSpace);
 
 
             if (!renderingCommands.Any())
             if (!renderingCommands.Any())
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("Insufficient space to render (even partially) a single row.");
             
             
             var width = Columns.Sum(x => x.Width);
             var width = Columns.Sum(x => x.Width);
             var height = renderingCommands.Max(x => x.Offset.Y + x.Size.Height);
             var height = renderingCommands.Max(x => x.Offset.Y + x.Size.Height);
             var tableSize = new Size(width, height);
             var tableSize = new Size(width, height);
 
 
             if (tableSize.Width > availableSpace.Width + Size.Epsilon)
             if (tableSize.Width > availableSpace.Width + Size.Epsilon)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The content requires more horizontal space than available.");
 
 
             return CalculateCurrentRow(renderingCommands) > StartingRowsCount 
             return CalculateCurrentRow(renderingCommands) > StartingRowsCount 
                 ? SpacePlan.FullRender(tableSize) 
                 ? SpacePlan.FullRender(tableSize) 

+ 1 - 1
Source/QuestPDF/Elements/Text/TextBlock.cs

@@ -106,7 +106,7 @@ namespace QuestPDF.Elements.Text
             }
             }
 
 
             if (totalLines == 0)
             if (totalLines == 0)
-                return SpacePlan.Wrap();
+                return SpacePlan.Wrap("The available space is not sufficient to render even a single line of text.");
 
 
             var requiredArea = new Size(
             var requiredArea = new Size(
                 Math.Min(MaximumWidth, availableSpace.Width),
                 Math.Min(MaximumWidth, availableSpace.Width),

+ 6 - 1
Source/QuestPDF/Infrastructure/ContainerElement.cs

@@ -27,7 +27,12 @@ namespace QuestPDF.Infrastructure
 
 
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            return Child.Measure(availableSpace);
+            var measurement = Child.Measure(availableSpace);
+            
+            if (measurement.Type == SpacePlanType.Wrap)
+                return SpacePlan.Wrap("Forwarded from child");
+
+            return measurement;
         }
         }
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)