Browse Source

VisitChildren -> GetChildren traversal refactorization

Marcin Ziąbek 4 years ago
parent
commit
eb297177ea

+ 2 - 1
QuestPDF.ReportSample/PerformanceTests.cs

@@ -11,6 +11,7 @@ using NUnit.Framework;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing.Proxy;
 using QuestPDF.Drawing.Proxy;
 using QuestPDF.Elements;
 using QuestPDF.Elements;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 using QuestPDF.ReportSample.Layouts;
 using QuestPDF.ReportSample.Layouts;
 
 
@@ -55,7 +56,7 @@ namespace QuestPDF.ReportSample
             var sw = new Stopwatch();
             var sw = new Stopwatch();
             sw.Start();
             sw.Start();
 
 
-            Content.HandleVisitor(x =>
+            Content.VisitChildren(x =>
             {
             {
                 if (x is ICacheable)
                 if (x is ICacheable)
                     x.CreateProxy(y => new CacheProxy(y));
                     x.CreateProxy(y => new CacheProxy(y));

+ 6 - 6
QuestPDF.UnitTests/TestEngine/TestPlan.cs

@@ -213,7 +213,7 @@ namespace QuestPDF.UnitTests.TestEngine
         
         
         public TestPlan CheckMeasureResult(SpacePlan expected)
         public TestPlan CheckMeasureResult(SpacePlan expected)
         {
         {
-            Element.HandleVisitor(x => x?.Initialize(null, Canvas));
+            Element.VisitChildren(x => x?.Initialize(null, Canvas));
             
             
             var actual = Element.Measure(OperationInput);
             var actual = Element.Measure(OperationInput);
             
             
@@ -228,7 +228,7 @@ namespace QuestPDF.UnitTests.TestEngine
         
         
         public TestPlan CheckDrawResult()
         public TestPlan CheckDrawResult()
         {
         {
-            Element.HandleVisitor(x => x?.Initialize(null, Canvas));
+            Element.VisitChildren(x => x?.Initialize(null, Canvas));
             Element.Draw(OperationInput);
             Element.Draw(OperationInput);
             return this;
             return this;
         }
         }
@@ -271,10 +271,10 @@ namespace QuestPDF.UnitTests.TestEngine
             availableSpace ??= new Size(400, 300);
             availableSpace ??= new Size(400, 300);
             
             
             var canvas = new FreeCanvas();
             var canvas = new FreeCanvas();
-            value.HandleVisitor(x => x.Initialize(null, canvas));
+            value.VisitChildren(x => x.Initialize(null, canvas));
             var valueMeasure = value.Measure(availableSpace.Value);
             var valueMeasure = value.Measure(availableSpace.Value);
             
             
-            expected.HandleVisitor(x => x.Initialize(null, canvas));
+            expected.VisitChildren(x => x.Initialize(null, canvas));
             var expectedMeasure = expected.Measure(availableSpace.Value);
             var expectedMeasure = expected.Measure(availableSpace.Value);
             
             
             valueMeasure.Should().BeEquivalentTo(expectedMeasure);
             valueMeasure.Should().BeEquivalentTo(expectedMeasure);
@@ -285,11 +285,11 @@ namespace QuestPDF.UnitTests.TestEngine
             availableSpace ??= new Size(400, 300);
             availableSpace ??= new Size(400, 300);
             
             
             var valueCanvas = new OperationRecordingCanvas();
             var valueCanvas = new OperationRecordingCanvas();
-            value.HandleVisitor(x => x.Initialize(null, valueCanvas));
+            value.VisitChildren(x => x.Initialize(null, valueCanvas));
             value.Draw(availableSpace.Value);
             value.Draw(availableSpace.Value);
             
             
             var expectedCanvas = new OperationRecordingCanvas();
             var expectedCanvas = new OperationRecordingCanvas();
-            expected.HandleVisitor(x => x.Initialize(null, expectedCanvas));
+            expected.VisitChildren(x => x.Initialize(null, expectedCanvas));
             expected.Draw(availableSpace.Value);
             expected.Draw(availableSpace.Value);
             
             
             valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);
             valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);

+ 32 - 17
QuestPDF/Drawing/DocumentGenerator.cs

@@ -7,6 +7,8 @@ using QuestPDF.Drawing.Proxy;
 using QuestPDF.Elements;
 using QuestPDF.Elements;
 using QuestPDF.Elements.Text;
 using QuestPDF.Elements.Text;
 using QuestPDF.Elements.Text.Items;
 using QuestPDF.Elements.Text.Items;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Drawing
 namespace QuestPDF.Drawing
@@ -42,6 +44,7 @@ namespace QuestPDF.Drawing
             var container = new DocumentContainer();
             var container = new DocumentContainer();
             document.Compose(container);
             document.Compose(container);
             var content = container.Compose();
             var content = container.Compose();
+            ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
             
             
             var metadata = document.GetMetadata();
             var metadata = document.GetMetadata();
             var pageContext = new PageContext();
             var pageContext = new PageContext();
@@ -58,8 +61,8 @@ namespace QuestPDF.Drawing
         internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DocumentMetadata documentMetadata, DebuggingState? debuggingState)
         internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DocumentMetadata documentMetadata, DebuggingState? debuggingState)
             where TCanvas : ICanvas, IRenderingCanvas
             where TCanvas : ICanvas, IRenderingCanvas
         {
         {
-            content.HandleVisitor(x => x?.Initialize(pageContext, canvas));
-            content.HandleVisitor(x => (x as IStateResettable)?.ResetState());
+            content.VisitChildren(x => x?.Initialize(pageContext, canvas));
+            content.VisitChildren(x => (x as IStateResettable)?.ResetState());
             
             
             canvas.BeginDocument();
             canvas.BeginDocument();
 
 
@@ -122,7 +125,7 @@ namespace QuestPDF.Drawing
 
 
         private static void ApplyCaching(Container content)
         private static void ApplyCaching(Container content)
         {
         {
-            content.HandleVisitor(x =>
+            content.VisitChildren(x =>
             {
             {
                 if (x is ICacheable)
                 if (x is ICacheable)
                     x.CreateProxy(y => new CacheProxy(y));
                     x.CreateProxy(y => new CacheProxy(y));
@@ -133,7 +136,7 @@ namespace QuestPDF.Drawing
         {
         {
             var debuggingState = new DebuggingState();
             var debuggingState = new DebuggingState();
 
 
-            content.HandleVisitor(x =>
+            content.VisitChildren(x =>
             {
             {
                 x.CreateProxy(y => new DebuggingProxy(debuggingState, y));
                 x.CreateProxy(y => new DebuggingProxy(debuggingState, y));
             });
             });
@@ -141,26 +144,38 @@ namespace QuestPDF.Drawing
             return debuggingState;
             return debuggingState;
         }
         }
 
 
-        internal static void ApplyDefaultTextStyle(this Element content, TextStyle documentDefaultTextStyle)
+        private static void ApplyDefaultTextStyle(this Element? content, TextStyle documentDefaultTextStyle)
         {
         {
-            documentDefaultTextStyle.ApplyGlobalStyle(TextStyle.LibraryDefault);
+            if (content == null)
+                return;
             
             
-            content.HandleVisitor(element =>
+            if (content is TextBlock textBlock)
             {
             {
-                var text = element as TextBlock;
-                
-                if (text == null)
-                    return;
-
-                foreach (var child in text.Children)
+                foreach (var textBlockItem in textBlock.Items)
                 {
                 {
-                    if (child is TextBlockSpan textSpan)
+                    if (textBlockItem is TextBlockSpan textSpan)
+                    {
                         textSpan.Style.ApplyGlobalStyle(documentDefaultTextStyle);
                         textSpan.Style.ApplyGlobalStyle(documentDefaultTextStyle);
-
-                    if (child is TextBlockElement textElement)
+                    }
+                    else if (textBlockItem is TextBlockElement textElement)
+                    {
                         ApplyDefaultTextStyle(textElement.Element, documentDefaultTextStyle);
                         ApplyDefaultTextStyle(textElement.Element, documentDefaultTextStyle);
+                    }
                 }
                 }
-            });
+                
+                return;
+            }
+
+            var targetTextStyle = documentDefaultTextStyle;
+            
+            if (content is DefaultTextStyle defaultTextStyleElement)
+            {
+                defaultTextStyleElement.TextStyle.ApplyParentStyle(documentDefaultTextStyle);
+                targetTextStyle = defaultTextStyleElement.TextStyle;
+            }
+            
+            foreach (var child in content.GetChildren())
+                ApplyDefaultTextStyle(child, targetTextStyle);
         }
         }
     }
     }
 }
 }

+ 4 - 5
QuestPDF/Elements/Decoration.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Collections.Generic;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
@@ -17,12 +18,10 @@ namespace QuestPDF.Elements
         public Element ContentElement { get; set; } = Empty.Instance;
         public Element ContentElement { get; set; } = Empty.Instance;
         public DecorationType Type { get; set; }
         public DecorationType Type { get; set; }
 
 
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            DecorationElement?.HandleVisitor(visit);
-            ContentElement?.HandleVisitor(visit);
-            
-            base.HandleVisitor(visit);
+            yield return DecorationElement;
+            yield return ContentElement;
         }
         }
 
 
         internal override void CreateProxy(Func<Element, Element> create)
         internal override void CreateProxy(Func<Element, Element> create)

+ 10 - 0
QuestPDF/Elements/DefaultTextStyle.cs

@@ -0,0 +1,10 @@
+using QuestPDF.Drawing;
+using QuestPDF.Infrastructure;
+
+namespace QuestPDF.Elements
+{
+    internal class DefaultTextStyle : ContainerElement
+    {
+        public TextStyle TextStyle { get; set; } = TextStyle.Default;
+    }
+}

+ 3 - 4
QuestPDF/Elements/Inlined.cs

@@ -44,12 +44,11 @@ namespace QuestPDF.Elements
             ChildrenQueue = new Queue<InlinedElement>(Elements);
             ChildrenQueue = new Queue<InlinedElement>(Elements);
         }
         }
         
         
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            Elements.ForEach(x => x.HandleVisitor(visit));
-            base.HandleVisitor(visit);
+            return Elements;
         }
         }
-
+        
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
             if (!ChildrenQueue.Any())
             if (!ChildrenQueue.Any())

+ 3 - 4
QuestPDF/Elements/Layers.cs

@@ -15,12 +15,11 @@ namespace QuestPDF.Elements
     {
     {
         public List<Layer> Children { get; set; } = new List<Layer>();
         public List<Layer> Children { get; set; } = new List<Layer>();
         
         
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            Children.ForEach(x => x.HandleVisitor(visit));
-            base.HandleVisitor(visit);
+            return Children;
         }
         }
-
+        
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
             return Children
             return Children

+ 14 - 17
QuestPDF/Elements/Row.cs

@@ -38,14 +38,12 @@ namespace QuestPDF.Elements
             IsRightRendered = false;
             IsRightRendered = false;
         }
         }
         
         
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            Left.HandleVisitor(visit);
-            Right.HandleVisitor(visit);
-            
-            base.HandleVisitor(visit);
+            yield return Left;
+            yield return Right;
         }
         }
-
+        
         internal override void CreateProxy(Func<Element?, Element?> create)
         internal override void CreateProxy(Func<Element?, Element?> create)
         {
         {
             Left = create(Left);
             Left = create(Left);
@@ -99,16 +97,15 @@ namespace QuestPDF.Elements
     {
     {
         public float Spacing { get; set; } = 0;
         public float Spacing { get; set; } = 0;
         
         
-        public ICollection<RowElement> Children { get; internal set; } = new List<RowElement>();
+        public ICollection<RowElement> Items { get; internal set; } = new List<RowElement>();
         private Element? RootElement { get; set; }
         private Element? RootElement { get; set; }
-        
-        internal override void HandleVisitor(Action<Element?> visit)
+
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
             if (RootElement == null)
             if (RootElement == null)
                 ComposeTree();
                 ComposeTree();
-            
-            RootElement.HandleVisitor(visit);
-            base.HandleVisitor(visit);
+
+            return Items;
         }
         }
 
 
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
@@ -127,20 +124,20 @@ namespace QuestPDF.Elements
         
         
         private void ComposeTree()
         private void ComposeTree()
         {
         {
-            Children = AddSpacing(Children, Spacing);
+            Items = AddSpacing(Items, Spacing);
             
             
-            var elements = Children.Cast<Element>().ToArray();
+            var elements = Items.Cast<Element>().ToArray();
             RootElement = BuildTree(elements);
             RootElement = BuildTree(elements);
         }
         }
 
 
         private void UpdateElementsWidth(float availableWidth)
         private void UpdateElementsWidth(float availableWidth)
         {
         {
-            var constantWidth = Children.Sum(x => x.ConstantSize);
-            var relativeWidth = Children.Sum(x => x.RelativeSize);
+            var constantWidth = Items.Sum(x => x.ConstantSize);
+            var relativeWidth = Items.Sum(x => x.RelativeSize);
 
 
             var widthPerRelativeUnit = (relativeWidth > 0) ? (availableWidth - constantWidth) / relativeWidth : 0;
             var widthPerRelativeUnit = (relativeWidth > 0) ? (availableWidth - constantWidth) / relativeWidth : 0;
             
             
-            foreach (var row in Children)
+            foreach (var row in Items)
             {
             {
                 row.SetWidth(row.ConstantSize + row.RelativeSize * widthPerRelativeUnit);
                 row.SetWidth(row.ConstantSize + row.RelativeSize * widthPerRelativeUnit);
             }
             }

+ 6 - 8
QuestPDF/Elements/Stack.cs

@@ -16,14 +16,12 @@ namespace QuestPDF.Elements
 
 
         internal bool IsFirstRendered { get; set; } = false;
         internal bool IsFirstRendered { get; set; } = false;
 
 
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            First?.HandleVisitor(visit);
-            Second?.HandleVisitor(visit);
-            
-            base.HandleVisitor(visit);
+            yield return First;
+            yield return Second;
         }
         }
-        
+
         public void ResetState()
         public void ResetState()
         {
         {
             IsFirstRendered = false;
             IsFirstRendered = false;
@@ -97,12 +95,12 @@ namespace QuestPDF.Elements
     
     
     internal class Stack : IComponent
     internal class Stack : IComponent
     {
     {
-        public ICollection<Element> Children { get; } = new List<Element>();
+        public ICollection<Element> Items { get; } = new List<Element>();
         public float Spacing { get; set; } = 0;
         public float Spacing { get; set; } = 0;
         
         
         public void Compose(IContainer container)
         public void Compose(IContainer container)
         {
         {
-            var elements = AddSpacing(Spacing, Children);
+            var elements = AddSpacing(Spacing, Items);
 
 
             container
             container
                 .PaddingBottom(-Spacing)    
                 .PaddingBottom(-Spacing)    

+ 15 - 16
QuestPDF/Elements/Table/Table.cs

@@ -12,51 +12,50 @@ namespace QuestPDF.Elements.Table
     internal class Table : Element, IStateResettable
     internal class Table : Element, IStateResettable
     {
     {
         public List<TableColumnDefinition> Columns { get; } = new List<TableColumnDefinition>();
         public List<TableColumnDefinition> Columns { get; } = new List<TableColumnDefinition>();
-        public List<TableCell> Children { get; } = new List<TableCell>();
+        public List<TableCell> Cells { get; } = new List<TableCell>();
         public bool ExtendLastCellsToTableBottom { get; set; }
         public bool ExtendLastCellsToTableBottom { get; set; }
         
         
         // cache for efficient cell finding
         // cache for efficient cell finding
         // index of first array - number of row
         // index of first array - number of row
         // nested array - collection of all cells starting at given row
         // nested array - collection of all cells starting at given row
-        private TableCell[][] OrderedChildren { get; set; }
+        private TableCell[][] OrderedCells { get; set; }
         
         
         private int StartingRowsCount { get; set; }
         private int StartingRowsCount { get; set; }
         private int RowsCount { get; set; }
         private int RowsCount { get; set; }
         private int CurrentRow { get; set; }
         private int CurrentRow { get; set; }
         
         
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            Children.ToList().ForEach(x => x.HandleVisitor(visit));
-            base.HandleVisitor(visit);
+            return Cells;
         }
         }
-        
+
         public void ResetState()
         public void ResetState()
         {
         {
             if (StartingRowsCount == default)
             if (StartingRowsCount == default)
-                StartingRowsCount = Children.Select(x => x.Row).DefaultIfEmpty(0).Max();
+                StartingRowsCount = Cells.Select(x => x.Row).DefaultIfEmpty(0).Max();
             
             
             if (RowsCount == default)
             if (RowsCount == default)
-                RowsCount = Children.Select(x => x.Row + x.RowSpan - 1).DefaultIfEmpty(0).Max();
+                RowsCount = Cells.Select(x => x.Row + x.RowSpan - 1).DefaultIfEmpty(0).Max();
 
 
-            if (OrderedChildren == default)
+            if (OrderedCells == default)
             {
             {
-                var groups = Children
+                var groups = Cells
                     .GroupBy(x => x.Row)
                     .GroupBy(x => x.Row)
                     .ToDictionary(x => x.Key, x => x.OrderBy(y => y.Column).ToArray());
                     .ToDictionary(x => x.Key, x => x.OrderBy(y => y.Column).ToArray());
             
             
-                OrderedChildren = Enumerable
+                OrderedCells = Enumerable
                     .Range(0, RowsCount + 1)
                     .Range(0, RowsCount + 1)
                     .Select(x => groups.TryGetValue(x, out var output) ? output : Array.Empty<TableCell>())
                     .Select(x => groups.TryGetValue(x, out var output) ? output : Array.Empty<TableCell>())
                     .ToArray();   
                     .ToArray();   
             }
             }
 
 
-            Children.ForEach(x => x.IsRendered = false);
+            Cells.ForEach(x => x.IsRendered = false);
             CurrentRow = 1;
             CurrentRow = 1;
         }
         }
         
         
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)
         {
         {
-            if (!Children.Any())
+            if (!Cells.Any())
                 return SpacePlan.FullRender(Size.Zero);
                 return SpacePlan.FullRender(Size.Zero);
             
             
             UpdateColumnsWidth(availableSpace.Width);
             UpdateColumnsWidth(availableSpace.Width);
@@ -149,16 +148,16 @@ namespace QuestPDF.Elements.Table
             {
             {
                 var rowBottomOffsets = new DynamicDictionary<int, float>();
                 var rowBottomOffsets = new DynamicDictionary<int, float>();
                 
                 
-                var childrenToTry = Enumerable
+                var cellsToTry = Enumerable
                     .Range(CurrentRow, RowsCount - CurrentRow + 1)
                     .Range(CurrentRow, RowsCount - CurrentRow + 1)
-                    .SelectMany(x => OrderedChildren[x]);
+                    .SelectMany(x => OrderedCells[x]);
             
             
                 var currentRow = CurrentRow;
                 var currentRow = CurrentRow;
                 var maxRenderingRow = RowsCount;
                 var maxRenderingRow = RowsCount;
                 
                 
                 var commands = new List<TableCellRenderingCommand>();
                 var commands = new List<TableCellRenderingCommand>();
                 
                 
-                foreach (var cell in childrenToTry)
+                foreach (var cell in cellsToTry)
                 {
                 {
                     // update position of previous row
                     // update position of previous row
                     if (cell.Row > currentRow)
                     if (cell.Row > currentRow)

+ 1 - 1
QuestPDF/Elements/Table/TableLayoutPlanner.cs

@@ -9,7 +9,7 @@ namespace QuestPDF.Elements.Table
     {
     {
         public static void PlanCellPositions(this Table table)
         public static void PlanCellPositions(this Table table)
         {
         {
-            PlanCellPositions(table.Columns.Count, table.Children);
+            PlanCellPositions(table.Columns.Count, table.Cells);
         }
         }
         
         
         private static void PlanCellPositions(int columnsCount, ICollection<TableCell> cells)
         private static void PlanCellPositions(int columnsCount, ICollection<TableCell> cells)

+ 1 - 1
QuestPDF/Elements/Table/TableLayoutValidator.cs

@@ -10,7 +10,7 @@ namespace QuestPDF.Elements.Table
     {
     {
         public static void ValidateCellPositions(this Table table)
         public static void ValidateCellPositions(this Table table)
         {
         {
-            ValidateCellPositions(table.Columns.Count, table.Children);
+            ValidateCellPositions(table.Columns.Count, table.Cells);
         }
         }
         
         
         private static void ValidateCellPositions(int columnsCount, ICollection<TableCell> cells)
         private static void ValidateCellPositions(int columnsCount, ICollection<TableCell> cells)

+ 5 - 4
QuestPDF/Elements/Text/Items/TextBlockElement.cs

@@ -1,5 +1,6 @@
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
 using QuestPDF.Elements.Text.Calculation;
 using QuestPDF.Elements.Text.Calculation;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Elements.Text.Items
 namespace QuestPDF.Elements.Text.Items
@@ -10,8 +11,8 @@ namespace QuestPDF.Elements.Text.Items
         
         
         public TextMeasurementResult? Measure(TextMeasurementRequest request)
         public TextMeasurementResult? Measure(TextMeasurementRequest request)
         {
         {
-            Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
-            Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
+            Element.VisitChildren(x => (x as IStateResettable)?.ResetState());
+            Element.VisitChildren(x => x.Initialize(request.PageContext, request.Canvas));
 
 
             var measurement = Element.Measure(new Size(request.AvailableWidth, Size.Max.Height));
             var measurement = Element.Measure(new Size(request.AvailableWidth, Size.Max.Height));
 
 
@@ -35,8 +36,8 @@ namespace QuestPDF.Elements.Text.Items
 
 
         public void Draw(TextDrawingRequest request)
         public void Draw(TextDrawingRequest request)
         {
         {
-            Element.HandleVisitor(x => (x as IStateResettable)?.ResetState());
-            Element.HandleVisitor(x => x.Initialize(request.PageContext, request.Canvas));
+            Element.VisitChildren(x => (x as IStateResettable)?.ResetState());
+            Element.VisitChildren(x => x.Initialize(request.PageContext, request.Canvas));
             
             
             request.Canvas.Translate(new Position(0, request.TotalAscent));
             request.Canvas.Translate(new Position(0, request.TotalAscent));
             Element.Draw(new Size(request.TextSize.Width, -request.TotalAscent));
             Element.Draw(new Size(request.TextSize.Width, -request.TotalAscent));

+ 3 - 3
QuestPDF/Elements/Text/TextBlock.cs

@@ -11,16 +11,16 @@ namespace QuestPDF.Elements.Text
     internal class TextBlock : Element, IStateResettable
     internal class TextBlock : Element, IStateResettable
     {
     {
         public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
         public HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;
-        public List<ITextBlockItem> Children { get; set; } = new List<ITextBlockItem>();
+        public List<ITextBlockItem> Items { get; set; } = new List<ITextBlockItem>();
 
 
-        public string Text => string.Join(" ", Children.Where(x => x is TextBlockSpan).Cast<TextBlockSpan>().Select(x => x.Text));
+        public string Text => string.Join(" ", Items.Where(x => x is TextBlockSpan).Cast<TextBlockSpan>().Select(x => x.Text));
         
         
         private Queue<ITextBlockItem> RenderingQueue { get; set; }
         private Queue<ITextBlockItem> RenderingQueue { get; set; }
         private int CurrentElementIndex { get; set; }
         private int CurrentElementIndex { get; set; }
 
 
         public void ResetState()
         public void ResetState()
         {
         {
-            RenderingQueue = new Queue<ITextBlockItem>(Children);
+            RenderingQueue = new Queue<ITextBlockItem>(Items);
             CurrentElementIndex = 0;
             CurrentElementIndex = 0;
         }
         }
 
 

+ 1 - 1
QuestPDF/Fluent/RowExtensions.cs

@@ -27,7 +27,7 @@ namespace QuestPDF.Fluent
         {
         {
             var element = new RowElement(constantWidth, relativeWidth);
             var element = new RowElement(constantWidth, relativeWidth);
             
             
-            Row.Children.Add(element);
+            Row.Items.Add(element);
             return element;
             return element;
         }
         }
     }
     }

+ 1 - 1
QuestPDF/Fluent/StackExtensions.cs

@@ -16,7 +16,7 @@ namespace QuestPDF.Fluent
         public IContainer Item()
         public IContainer Item()
         {
         {
             var container = new Container();
             var container = new Container();
-            Stack.Children.Add(container);
+            Stack.Items.Add(container);
             return container;
             return container;
         }
         }
     }
     }

+ 2 - 2
QuestPDF/Fluent/TableExtensions.cs

@@ -61,13 +61,13 @@ namespace QuestPDF.Fluent
         public ITableCellContainer Cell()
         public ITableCellContainer Cell()
         {
         {
             var cell = new TableCell();
             var cell = new TableCell();
-            Table.Children.Add(cell);
+            Table.Cells.Add(cell);
             return cell;
             return cell;
         }
         }
 
 
         internal void ApplyDefaultCellStyle()
         internal void ApplyDefaultCellStyle()
         {
         {
-            foreach (var cell in Table.Children)
+            foreach (var cell in Table.Cells)
             {
             {
                 var container = new Container();
                 var container = new Container();
                 DefaultCellStyleFunc(container).Element(cell.Child);
                 DefaultCellStyleFunc(container).Element(cell.Child);

+ 3 - 6
QuestPDF/Fluent/TextExtensions.cs

@@ -47,7 +47,7 @@ namespace QuestPDF.Fluent
             if (!TextBlocks.Any())
             if (!TextBlocks.Any())
                 TextBlocks.Add(new TextBlock());
                 TextBlocks.Add(new TextBlock());
             
             
-            TextBlocks.Last().Children.Add(item);
+            TextBlocks.Last().Items.Add(item);
         }
         }
         
         
         public void Span(string? text, TextStyle? style = null)
         public void Span(string? text, TextStyle? style = null)
@@ -73,7 +73,7 @@ namespace QuestPDF.Fluent
                 .Skip(1)
                 .Skip(1)
                 .Select(x => new TextBlock
                 .Select(x => new TextBlock
                 {   
                 {   
-                    Children = new List<ITextBlockItem> { x }
+                    Items = new List<ITextBlockItem> { x }
                 })
                 })
                 .ToList()
                 .ToList()
                 .ForEach(TextBlocks.Add);
                 .ForEach(TextBlocks.Add);
@@ -173,11 +173,8 @@ namespace QuestPDF.Fluent
         internal void Compose(IContainer container)
         internal void Compose(IContainer container)
         {
         {
             TextBlocks.ToList().ForEach(x => x.Alignment = Alignment);
             TextBlocks.ToList().ForEach(x => x.Alignment = Alignment);
-            
-            foreach (var textBlockSpan in TextBlocks.SelectMany(x => x.Children).Where(x => x is TextBlockSpan).Cast<TextBlockSpan>())
-                textBlockSpan.Style.ApplyParentStyle(DefaultStyle);
 
 
-            container.Stack(stack =>
+            container.DefaultTextStyle(DefaultStyle).Stack(stack =>
             {
             {
                 stack.Spacing(Spacing);
                 stack.Spacing(Spacing);
 
 

+ 10 - 0
QuestPDF/Helpers/Helpers.cs

@@ -1,8 +1,10 @@
 using System;
 using System;
 using System.IO;
 using System.IO;
+using System.Linq;
 using System.Linq.Expressions;
 using System.Linq.Expressions;
 using System.Reflection;
 using System.Reflection;
 using System.Text.RegularExpressions;
 using System.Text.RegularExpressions;
+using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Helpers
 namespace QuestPDF.Helpers
 {
 {
@@ -41,5 +43,13 @@ namespace QuestPDF.Helpers
         {
         {
             return Regex.Replace(text, @"([a-z])([A-Z])", "$1 $2");
             return Regex.Replace(text, @"([a-z])([A-Z])", "$1 $2");
         }
         }
+
+        internal static void VisitChildren(this Element? element, Action<Element?> handler)
+        {
+            handler(element);
+
+            foreach (var child in element.GetChildren().Where(x => x != null))
+                VisitChildren(child, handler);
+        }
     }
     }
 }
 }

+ 3 - 3
QuestPDF/Infrastructure/ContainerElement.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Collections.Generic;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
 using QuestPDF.Elements;
 using QuestPDF.Elements;
 
 
@@ -14,10 +15,9 @@ namespace QuestPDF.Infrastructure
             set => Child = value as Element;
             set => Child = value as Element;
         }
         }
 
 
-        internal override void HandleVisitor(Action<Element?> visit)
+        internal override IEnumerable<Element?> GetChildren()
         {
         {
-            Child?.HandleVisitor(visit);
-            base.HandleVisitor(visit);
+            yield return Child;
         }
         }
 
 
         internal override void CreateProxy(Func<Element?, Element?> create)
         internal override void CreateProxy(Func<Element?, Element?> create)

+ 2 - 2
QuestPDF/Infrastructure/Element.cs

@@ -10,9 +10,9 @@ namespace QuestPDF.Infrastructure
         internal IPageContext PageContext { get; set; }
         internal IPageContext PageContext { get; set; }
         internal ICanvas Canvas { get; set; }
         internal ICanvas Canvas { get; set; }
         
         
-        internal virtual void HandleVisitor(Action<Element?> visit)
+        internal virtual IEnumerable<Element?> GetChildren()
         {
         {
-            visit(this);
+            yield break;
         }
         }
 
 
         internal void Initialize(IPageContext pageContext, ICanvas canvas)
         internal void Initialize(IPageContext pageContext, ICanvas canvas)