Browse Source

Removed legacy layout debugging feature

Marcin Ziąbek 2 years ago
parent
commit
19716d3f41

+ 21 - 44
Source/QuestPDF/Drawing/DocumentGenerator.cs

@@ -107,23 +107,19 @@ namespace QuestPDF.Drawing
         private static void RenderSingleDocument<TCanvas>(TCanvas canvas, IDocument document, DocumentSettings settings)
             where TCanvas : ICanvas, IRenderingCanvas
         {
-            const int documentId = 0;
-            
-            var debuggingState = new DebuggingState();
             var useOriginalImages = canvas is ImageCanvas;
 
-            var content = ConfigureContent(document, settings, debuggingState, documentId, useOriginalImages);
+            var content = ConfigureContent(document, settings, useOriginalImages);
 
             var pageContext = new PageContext();
-            RenderPass(pageContext, new FreeCanvas(), content, debuggingState);
+            RenderPass(pageContext, new FreeCanvas(), content);
             pageContext.ResetPageNumber();
-            RenderPass(pageContext, canvas, content, debuggingState);
+            RenderPass(pageContext, canvas, content);
         }
         
         private static void RenderMergedDocument<TCanvas>(TCanvas canvas, MergedDocument document, DocumentSettings settings)
             where TCanvas : ICanvas, IRenderingCanvas
         {
-            var debuggingState = new DebuggingState();
             var useOriginalImages = canvas is ImageCanvas;
             
             var documentParts = Enumerable
@@ -131,7 +127,7 @@ namespace QuestPDF.Drawing
                 .Select(index => new
                 {
                     DocumentId = index,
-                    Content = ConfigureContent(document.Documents[index], settings, debuggingState, index, useOriginalImages)
+                    Content = ConfigureContent(document.Documents[index], settings, useOriginalImages)
                 })
                 .ToList();
 
@@ -142,7 +138,7 @@ namespace QuestPDF.Drawing
                 foreach (var documentPart in documentParts)
                 {
                     documentPageContext.SetDocumentId(documentPart.DocumentId);
-                    RenderPass(documentPageContext, new FreeCanvas(), documentPart.Content, debuggingState);
+                    RenderPass(documentPageContext, new FreeCanvas(), documentPart.Content);
                 }
                 
                 documentPageContext.ResetPageNumber();
@@ -150,7 +146,7 @@ namespace QuestPDF.Drawing
                 foreach (var documentPart in documentParts)
                 {
                     documentPageContext.SetDocumentId(documentPart.DocumentId);
-                    RenderPass(documentPageContext, canvas, documentPart.Content, debuggingState);   
+                    RenderPass(documentPageContext, canvas, documentPart.Content);   
                 }
             }
             else
@@ -160,14 +156,14 @@ namespace QuestPDF.Drawing
                     var pageContext = new PageContext();
                     pageContext.SetDocumentId(documentPart.DocumentId);
                     
-                    RenderPass(pageContext, new FreeCanvas(), documentPart.Content, debuggingState);
+                    RenderPass(pageContext, new FreeCanvas(), documentPart.Content);
                     pageContext.ResetPageNumber();
-                    RenderPass(pageContext, canvas, documentPart.Content, debuggingState);
+                    RenderPass(pageContext, canvas, documentPart.Content);
                 }
             }
         }
 
-        private static Container ConfigureContent(IDocument document, DocumentSettings settings, DebuggingState debuggingState, int documentIndex, bool useOriginalImages)
+        private static Container ConfigureContent(IDocument document, DocumentSettings settings, bool useOriginalImages)
         {
             var container = new DocumentContainer();
             document.Compose(container);
@@ -180,14 +176,11 @@ namespace QuestPDF.Drawing
                     
             if (Settings.EnableCaching)
                 content.ApplyCaching();
-
-            if (Settings.EnableDebugging)
-                content.ApplyDebugging(debuggingState);
-
+            
             return content;
         }
 
-        private static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, ContainerElement content, DebuggingState? debuggingState)
+        private static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, ContainerElement content)
             where TCanvas : ICanvas, IRenderingCanvas
         {
             content.InjectDependencies(pageContext, canvas);
@@ -223,12 +216,6 @@ namespace QuestPDF.Drawing
 
                 canvas.EndPage();
 
-                if (pageContext.CurrentPage >= Settings.DocumentLayoutExceptionThreshold)
-                {
-                    canvas.EndDocument();
-                    ThrowLayoutException();
-                }
-                
                 if (spacePlan.Type == SpacePlanType.FullRender)
                     break;
             }
@@ -275,16 +262,17 @@ namespace QuestPDF.Drawing
             
             void ThrowLayoutException()
             {
-                var message = 
-                    $"Composed layout generates infinite document. This may happen in two cases. " +
-                    $"1) Your document and its layout configuration is correct but the content takes more than {Settings.DocumentLayoutExceptionThreshold} pages. " +
-                    $"In this case, please increase the value {nameof(QuestPDF)}.{nameof(Settings)}.{nameof(Settings.DocumentLayoutExceptionThreshold)} static property. " +
-                    $"2) The layout configuration of your document is invalid. Some of the elements require more space than is provided." +
-                    $"Please analyze your documents structure to detect this element and fix its size constraints.";
-                
-                var elementTrace = debuggingState?.BuildTrace() ?? "Debug trace is available only in the DEBUG mode.";
+                var newLine = Environment.NewLine;
+                var newParagraph = newLine + newLine;
+                    
+                var message =
+                    $"The provided document content contains conflicting size constraints. " +
+                    $"For example, some elements may require more space than is available. {newParagraph}" +
+                    $"To quickly determine the place where the problem is likely occurring, please generate the document with the attached debugger. " +
+                    $"The library will generate a PDF document with visually annotated places where layout constraints are invalid. {newParagraph}" +
+                    $"Alternatively, if you don’t want to or cannot attach the debugger, you can set the {nameof(QuestPDF)}.{nameof(Settings)}.{nameof(Settings.EnableDebugging)} flag to true.";
                 
-                throw new DocumentLayoutException(message, elementTrace);
+                throw new DocumentLayoutException(message);
             }
         }
 
@@ -309,17 +297,6 @@ namespace QuestPDF.Drawing
             });
         }
 
-        private static void ApplyDebugging(this Container content, DebuggingState? debuggingState)
-        {
-            if (debuggingState == null)
-                return;
-            
-            content.VisitChildren(x =>
-            {
-                x.CreateProxy(y => new DebuggingProxy(debuggingState, y));
-            });
-        }
-        
         internal static void ApplyContentDirection(this Element? content, ContentDirection? direction = null)
         {
             if (content == null)

+ 2 - 4
Source/QuestPDF/Drawing/Exceptions/DocumentLayoutException.cs

@@ -4,11 +4,9 @@ namespace QuestPDF.Drawing.Exceptions
 {
     public class DocumentLayoutException : Exception
     {
-        public string? ElementTrace { get; }
-
-        internal DocumentLayoutException(string message, string? elementTrace = null) : base(message)
+        internal DocumentLayoutException(string message) : base(message)
         {
-            ElementTrace = elementTrace;
+            
         }
     }
 }

+ 0 - 14
Source/QuestPDF/Drawing/Proxy/DebugStackItem.cs

@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Drawing.Proxy
-{
-    internal class DebugStackItem
-    {
-        public IElement Element { get; internal set; }
-        public Size AvailableSpace { get; internal set; }
-        public SpacePlan SpacePlan { get; internal set; }
-
-        public ICollection<DebugStackItem> Stack { get; internal set; } = new List<DebugStackItem>();
-    }
-}

+ 0 - 24
Source/QuestPDF/Drawing/Proxy/DebuggingProxy.cs

@@ -1,24 +0,0 @@
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Drawing.Proxy
-{
-    internal class DebuggingProxy : ElementProxy
-    {
-        private DebuggingState DebuggingState { get; }
-
-        public DebuggingProxy(DebuggingState debuggingState, Element child)
-        {
-            DebuggingState = debuggingState;
-            Child = child;
-        }
-        
-        internal override SpacePlan Measure(Size availableSpace)
-        {
-            DebuggingState.RegisterMeasure(Child, availableSpace);
-            var spacePlan = base.Measure(availableSpace);
-            DebuggingState.RegisterMeasureResult(Child, spacePlan);
-
-            return spacePlan;
-        }
-    }
-}

+ 0 - 133
Source/QuestPDF/Drawing/Proxy/DebuggingState.cs

@@ -1,133 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using QuestPDF.Elements;
-using QuestPDF.Helpers;
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Drawing.Proxy
-{
-    internal class DebuggingState
-    {
-        private DebugStackItem? Root { get; set; }
-        private Stack<DebugStackItem> Stack { get; set; }
-
-        public DebuggingState()
-        {
-            Reset();
-        }
-        
-        public void Reset()
-        {
-            Root = null;
-            Stack = new Stack<DebugStackItem>();
-        }
-        
-        public void RegisterMeasure(IElement element, Size availableSpace)
-        {
-            if (element.GetType() == typeof(Container))
-                return;
-            
-            var item = new DebugStackItem
-            {
-                Element = element,
-                AvailableSpace = availableSpace
-            };
-
-            Root ??= item;
-            
-            if (Stack.Any())
-                Stack.Peek().Stack.Add(item);
-
-            Stack.Push(item);
-        }
-
-        public void RegisterMeasureResult(IElement element, SpacePlan spacePlan)
-        {
-            if (element.GetType() == typeof(Container))
-                return;
-            
-            var item = Stack.Pop();
-
-            if (item.Element != element)
-                throw new Exception();
-            
-            item.SpacePlan = spacePlan;
-        }
-        
-        public string BuildTrace()
-        {
-            if (Root == null)
-                return null;
-            
-            var builder = new StringBuilder();
-            var nestingLevel = 0;
-
-            Traverse(Root);
-            return builder.ToString();
-
-            void Traverse(DebugStackItem item)
-            {
-                var indent = new string(' ', nestingLevel * 4);
-                var title = item.Element.GetType().Name;
-
-                if (item.Element is DebugPointer debugPointer)
-                {
-                    title = debugPointer.Target;
-                    title += debugPointer.Highlight ? " 🌟" : string.Empty;
-                }
-                
-                if (item.SpacePlan.Type != SpacePlanType.FullRender)
-                    title = "🔥 " + title;
-
-                builder.AppendLine(indent + title);
-                builder.AppendLine(indent + new string('-', title.Length));
-                
-                builder.AppendLine(indent + "Available space: " + item.AvailableSpace);
-                builder.AppendLine(indent + "Requested space: " + item.SpacePlan);
-                
-                foreach (var configuration in GetElementConfiguration(item.Element))
-                    builder.AppendLine(indent + configuration);
-
-                builder.AppendLine();
-                
-                nestingLevel++;
-                item.Stack.ToList().ForEach(Traverse);
-                nestingLevel--;
-            }
-
-            static IEnumerable<string> GetElementConfiguration(IElement element)
-            {
-                if (element is DebugPointer)
-                    return Enumerable.Empty<string>();
-                
-                return element
-                    .GetType()
-                    .GetProperties()
-                    .Select(x => new
-                    {
-                        Property = x.Name.PrettifyName(),
-                        Value = x.GetValue(element)
-                    })
-                    .Where(x => !(x.Value is IElement))
-                    .Where(x => x.Value is string || !(x.Value is IEnumerable))
-                    .Where(x => !(x.Value is TextStyle))
-                    .Select(x => $"{x.Property}: {FormatValue(x.Value)}");
-
-                string FormatValue(object value)
-                {
-                    const int maxLength = 100;
-                    
-                    var text = value?.ToString() ?? "-";
-
-                    if (text.Length < maxLength)
-                        return text;
-
-                    return text.AsSpan(0, maxLength).ToString() + "...";
-                }
-            }
-        }
-    }
-}

+ 5 - 11
Source/QuestPDF/Settings.cs

@@ -1,4 +1,5 @@
-using QuestPDF.Infrastructure;
+using System;
+using QuestPDF.Infrastructure;
 
 namespace QuestPDF
 {
@@ -10,13 +11,7 @@ namespace QuestPDF
         /// </summary>
         public static LicenseType? License { get; set; }
         
-        /// <summary>
-        /// This value represents the maximum number of pages that the library produces.
-        /// This is useful when layout constraints are too strong, e.g. one element does not fit in another.
-        /// In such cases, the library would produce document of infinite length, consuming all available resources.
-        /// To break the algorithm and save the environment, the library breaks the rendering process after reaching specified length of document.
-        /// If your content requires generating longer documents, please assign the most reasonable value.
-        /// </summary>
+        [Obsolete("This setting is ignored since the 2023.10 version. The new infinite layout detection algorithm works automatically. You can safely remove this setting from your codebase.")]
         public static int DocumentLayoutExceptionThreshold { get; set; } = 250;
         
         /// <summary>
@@ -28,10 +23,9 @@ namespace QuestPDF
         
         /// <summary>
         /// This flag generates additional document elements to improve layout debugging experience.
-        /// When the DocumentLayoutException is thrown, the library is able to provide additional execution context.
-        /// It includes layout calculation results and path to the problematic area.
+        /// When the provided content contains size constraints impossible to meet, the library generates special visual annotations to help determining the root cause.
         /// </summary>
-        /// <remarks>By default, this flag is enabled only when the debugger IS attached.</remarks>
+        /// <remarks>By default, this flag is enabled only when the debugger IS attached.</remarks>  
         public static bool EnableDebugging { get; set; } = System.Diagnostics.Debugger.IsAttached;
         
         /// <summary>