2
0
Эх сурвалжийг харах

Fixed: layout overflow marker shown on incorrect pages + code refactoring

Marcin Ziąbek 2 жил өмнө
parent
commit
598f7385c5

+ 25 - 22
Source/QuestPDF/Drawing/DocumentGenerator.cs

@@ -193,8 +193,6 @@ namespace QuestPDF.Drawing
             content.InjectDependencies(pageContext, canvas);
             content.VisitChildren(x => (x as IStateResettable)?.ResetState());
 
-            LayoutOverflowPageMarker? layoutOverflowPageMarker = null;
-            
             while(true)
             {
                 var spacePlan = content.Measure(Size.Max);
@@ -227,12 +225,6 @@ namespace QuestPDF.Drawing
 
                 if (pageContext.CurrentPage >= Settings.DocumentLayoutExceptionThreshold)
                 {
-                    if (Settings.EnableDebugging)
-                    {
-                        ApplyLayoutDebugging();
-                        continue;
-                    }
-                    
                     canvas.EndDocument();
                     ThrowLayoutException();
                 }
@@ -241,27 +233,19 @@ namespace QuestPDF.Drawing
                     break;
             }
 
+            if (Settings.EnableDebugging)
+            {
+                ConfigureLayoutOverflowMarker();
+            }
+
             void ApplyLayoutDebugging()
             {
-                if (layoutOverflowPageMarker == null)
-                {
-                    layoutOverflowPageMarker = new LayoutOverflowPageMarker();
-                    
-                    content.CreateProxy(child =>
-                    {
-                        layoutOverflowPageMarker.Child = child;
-                        return layoutOverflowPageMarker;
-                    });
-                }
-                
-                layoutOverflowPageMarker.PageNumbersWithLayoutIssues.Add(pageContext.CurrentPage);
-                
                 content.RemoveExistingProxies();
 
                 content.ApplyLayoutOverflowDetection();
                 content.Measure(Size.Max);
 
-                var overflowState = content.ExtractProxyOfType<OverflowDebuggingProxy>();
+                var overflowState = content.ExtractElementsOfType<OverflowDebuggingProxy>().FirstOrDefault();
                 overflowState.ApplyLayoutOverflowVisualization();
                 
                 content.ApplyContentDirection();
@@ -269,6 +253,25 @@ namespace QuestPDF.Drawing
 
                 content.RemoveExistingProxies();
             }
+
+            void ConfigureLayoutOverflowMarker()
+            {
+                var layoutOverflowPageMarker = new LayoutOverflowPageMarker();
+                    
+                content.CreateProxy(child =>
+                {
+                    layoutOverflowPageMarker.Child = child;
+                    return layoutOverflowPageMarker;
+                });
+
+                var pageNumbersWithLayoutIssues = content
+                    .ExtractElementsOfType<LayoutOverflowVisualization>()
+                    .SelectMany(x => x.Flatten())
+                    .SelectMany(x => x.Value.VisibleOnPageNumbers)
+                    .Distinct();
+
+                layoutOverflowPageMarker.PageNumbersWithLayoutIssues = new HashSet<int>(pageNumbersWithLayoutIssues);
+            }
             
             void ThrowLayoutException()
             {

+ 20 - 16
Source/QuestPDF/Drawing/Proxy/TreeTraversal.cs

@@ -17,26 +17,30 @@ internal class TreeNode<T>
 
 internal static class TreeTraversal
 {
-    public static TreeNode<T> ExtractProxyOfType<T>(this Element root) where T : ElementProxy
+    public static IEnumerable<TreeNode<T>> ExtractElementsOfType<T>(this Element element) where T : Element
     {
-        return Traverse(root).FirstOrDefault();
-
-        IEnumerable<TreeNode<T>> Traverse(Element element)
+        if (element is T proxy)
         {
-            if (element is T proxy)
-            {
-                var result = new TreeNode<T>(proxy);
+            var result = new TreeNode<T>(proxy);
                 
-                foreach (var treeNode in proxy.Child!.GetChildren().SelectMany(Traverse))
-                    result.Children.Add(treeNode);
+            foreach (var treeNode in proxy.GetChildren().SelectMany(ExtractElementsOfType<T>))
+                result.Children.Add(treeNode);
                 
-                yield return result;
-            }
-            else
-            {
-                foreach (var treeNode in element.GetChildren().SelectMany(Traverse))
-                    yield return treeNode;
-            }
+            yield return result;
+        }
+        else
+        {
+            foreach (var treeNode in element.GetChildren().SelectMany(ExtractElementsOfType<T>))
+                yield return treeNode;
         }
     }
+    
+    public static IEnumerable<TreeNode<T>> Flatten<T>(this TreeNode<T> element) where T : Element
+    {
+        yield return element;
+
+        foreach (var child in element.Children)
+            foreach (var innerChild in Flatten(child))
+                yield return innerChild;
+    }
 }

+ 1 - 1
Source/QuestPDF/Drawing/SpacePlan.cs

@@ -16,7 +16,7 @@ namespace QuestPDF.Drawing
             Height = height;
         }
 
-        internal static SpacePlan Wrap() => new SpacePlan(SpacePlanType.Wrap, 0, 0);
+        internal static SpacePlan  Wrap() => new SpacePlan(SpacePlanType.Wrap, 0, 0);
         
         internal static SpacePlan PartialRender(float width, float height) => new SpacePlan(SpacePlanType.PartialRender, width, height);
 

+ 6 - 4
Source/QuestPDF/Elements/LayoutOverflowPageMarker.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using QuestPDF.Drawing;
+using QuestPDF.Fluent;
 using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using SkiaSharp;
@@ -9,11 +10,12 @@ namespace QuestPDF.Elements;
 
 internal class LayoutOverflowPageMarker : ContainerElement
 {
-    public HashSet<int> PageNumbersWithLayoutIssues { get; } = new();
+    public HashSet<int> PageNumbersWithLayoutIssues { get; set; } = new();
     
     private const string LineColor = Colors.Red.Medium;
-    private const float BorderThickness = 16f;
-    
+    private const byte LineOpacity = 64;
+    private const float BorderThickness = 24f;
+
     internal override void Draw(Size availableSpace)
     {
         Child?.Draw(availableSpace);
@@ -32,7 +34,7 @@ internal class LayoutOverflowPageMarker : ContainerElement
         using var indicatorPaint = new SKPaint
         {
             StrokeWidth = BorderThickness * 2, // half of the width will be outside of the page area
-            Color = SKColor.Parse(LineColor).WithAlpha(128),
+            Color = SKColor.Parse(LineColor).WithAlpha(LineOpacity),
             IsStroke = true
         };
         

+ 4 - 0
Source/QuestPDF/Elements/LayoutOverflowVisualization.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using QuestPDF.Drawing;
 using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
@@ -17,6 +18,7 @@ internal class LayoutOverflowVisualization : ContainerElement, IContentDirection
     private const byte AreaOpacity = 64;
 
     public ContentDirection ContentDirection { get; set; }
+    public ICollection<int> VisibleOnPageNumbers { get; set; } = new List<int>();
 
     internal override SpacePlan Measure(Size availableSpace)
     {
@@ -30,6 +32,8 @@ internal class LayoutOverflowVisualization : ContainerElement, IContentDirection
         
     internal override void Draw(Size availableSpace)
     {
+        VisibleOnPageNumbers.Add(PageContext.CurrentPage);
+        
         // measure content area
         var childSize = base.Measure(availableSpace);