Browse Source

Merge branch 'main' into content-direction

Marcin Ziąbek 3 years ago
parent
commit
af60d84abe

+ 55 - 1
QuestPDF.Examples/ImageExamples.cs

@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
 using NUnit.Framework;
 using NUnit.Framework;
 using QuestPDF.Drawing.Exceptions;
 using QuestPDF.Drawing.Exceptions;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Examples.Engine;
@@ -34,6 +35,21 @@ namespace QuestPDF.Examples
                 });
                 });
         }
         }
         
         
+        [Test]
+        public void DynamicImage()
+        {
+            RenderingTest
+                .Create()
+                .PageSize(450, 350)
+                .ProducePdf()
+                .ShowResults()
+                .Render(page =>
+                {
+                    page.Padding(25)
+                        .Image(Placeholders.Image);
+                });
+        }
+        
         [Test]
         [Test]
         public void Exception()
         public void Exception()
         {
         {
@@ -47,5 +63,43 @@ namespace QuestPDF.Examples
                     .Render(page => page.Image("non_existent.png"));
                     .Render(page => page.Image("non_existent.png"));
             });
             });
         }
         }
+        
+        [Test]
+        public void ReusingTheSameImageFileShouldBePossible()
+        {
+            var fileName = Path.GetTempFileName() + ".jpg";
+            
+            try
+            {
+                var image = Placeholders.Image(300, 100);
+                
+                using var file = File.Create(fileName);
+                file.Write(image);
+                file.Dispose();
+                
+                RenderingTest
+                    .Create()
+                    .ProducePdf()
+                    .PageSize(PageSizes.A4)
+                    .ShowResults()
+                    .Render(container =>
+                    {
+                        container
+                            .Padding(20)
+                            .Column(column =>
+                            {
+                                column.Spacing(20);
+                                
+                                column.Item().Image(fileName);
+                                column.Item().Image(fileName);
+                                column.Item().Image(fileName);
+                            });
+                    });
+            }
+            finally
+            {
+                File.Delete(fileName);
+            }
+        }
     }
     }
 }
 }

+ 36 - 0
QuestPDF.Examples/RowExamples.cs

@@ -105,5 +105,41 @@ namespace QuestPDF.Examples
                         .Row(row => { });
                         .Row(row => { });
                 });
                 });
         }
         }
+        
+        [Test]
+        public void RowElementForRelativeHeightDivision()
+        {
+            RenderingTest
+                .Create()
+                .ProduceImages()
+                .ShowResults()
+                .MaxPages(100)
+                .PageSize(250, 400)
+                .Render(container =>
+                {
+                    container
+                        .Padding(25)
+                        .AlignLeft()
+                        .RotateRight()
+                        .Row(row =>
+                        {
+                            row.Spacing(20);
+
+                            row.RelativeItem(1).Element(Content);
+                            row.RelativeItem(2).Element(Content);
+                            row.RelativeItem(3).Element(Content);
+
+                            void Content(IContainer container)
+                            {
+                                container
+                                    .RotateLeft()
+                                    .Border(1)
+                                    .Background(Placeholders.BackgroundColor())
+                                    .Padding(5)
+                                    .Text(Placeholders.Label());
+                            }
+                        });
+                });
+        }
     }
     }
 }
 }

+ 33 - 1
QuestPDF.Examples/TextExamples.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
 using NUnit.Framework;
 using NUnit.Framework;
@@ -658,6 +658,38 @@ namespace QuestPDF.Examples
                 });
                 });
         }
         }
         
         
+        [Test]
+        public void WordWrappingStability()
+        {
+            // instruction: check if any characters repeat when performing the word-wrapping algorithm
+            
+            RenderingTest
+                .Create()
+                .PageSize(PageSizes.A4)
+                .ProducePdf()
+                .ShowResults()
+                .Render(container =>
+                {
+                    var text = "Lorem ipsum dolor sit amet consectetuer";
+                    
+                    container
+                        .Padding(20)
+                        .Column(column =>
+                        {
+                            column.Spacing(10);
+
+                            foreach (var width in Enumerable.Range(25, 200))
+                            {
+                                column
+                                    .Item()
+                                    .MaxWidth(width)
+                                    .Background(Colors.Grey.Lighten3)
+                                    .Text(text);
+                            }
+                        });
+                });
+        }
+        
         [Test]
         [Test]
         public void TextDirectionality()
         public void TextDirectionality()
         {
         {

+ 2 - 7
QuestPDF/Elements/DynamicImage.cs

@@ -24,13 +24,8 @@ namespace QuestPDF.Elements
             if (imageData == null)
             if (imageData == null)
                 return;
                 return;
 
 
-            var imageElement = new Image
-            {
-                InternalImage = SKImage.FromEncodedData(imageData)
-            };
-            
-            imageElement.InjectDependencies(PageContext, Canvas);
-            imageElement.Draw(availableSpace);
+            using var image = SKImage.FromEncodedData(imageData);
+            Canvas.DrawImage(image, Position.Zero, availableSpace);
         }
         }
     }
     }
 }
 }

+ 1 - 1
QuestPDF/Elements/Inlined.cs

@@ -228,7 +228,7 @@ namespace QuestPDF.Elements
                         break;
                         break;
                     
                     
                     var element = queue.Peek();
                     var element = queue.Peek();
-                    var size = element.Measure(Size.Max);
+                    var size = element.Measure(new Size(availableSize.Width, Size.Max.Height));
                     
                     
                     if (size.Type == SpacePlanType.Wrap)
                     if (size.Type == SpacePlanType.Wrap)
                         break;
                         break;

+ 7 - 4
QuestPDF/Elements/Table/Table.cs

@@ -27,6 +27,7 @@ namespace QuestPDF.Elements.Table
         // inner table: list of all cells that ends at the corresponding row
         // inner table: list of all cells that ends at the corresponding row
         private TableCell[][] CellsCache { get; set; }
         private TableCell[][] CellsCache { get; set; }
         private int MaxRow { get; set; }
         private int MaxRow { get; set; }
+        private int MaxRowSpan { get; set; }
         
         
         internal override IEnumerable<Element?> GetChildren()
         internal override IEnumerable<Element?> GetChildren()
         {
         {
@@ -64,6 +65,7 @@ namespace QuestPDF.Elements.Table
             if (Cells.Count == 0)
             if (Cells.Count == 0)
             {
             {
                 MaxRow = 0;
                 MaxRow = 0;
+                MaxRowSpan = 1;
                 CellsCache = Array.Empty<TableCell[]>();
                 CellsCache = Array.Empty<TableCell[]>();
                 
                 
                 return;
                 return;
@@ -74,6 +76,7 @@ namespace QuestPDF.Elements.Table
                 .ToDictionary(x => x.Key, x => x.OrderBy(x => x.Column).ToArray());
                 .ToDictionary(x => x.Key, x => x.OrderBy(x => x.Column).ToArray());
 
 
             MaxRow = groups.Max(x => x.Key);
             MaxRow = groups.Max(x => x.Key);
+            MaxRowSpan = Cells.Max(x => x.RowSpan);
 
 
             CellsCache = Enumerable
             CellsCache = Enumerable
                 .Range(0, MaxRow + 1)
                 .Range(0, MaxRow + 1)
@@ -211,9 +214,9 @@ namespace QuestPDF.Elements.Table
                         
                         
                         currentRow = cell.Row;
                         currentRow = cell.Row;
                     }
                     }
-
+                    
                     // cell visibility optimizations
                     // cell visibility optimizations
-                    if (cell.Row > maxRenderingRow)
+                    if (cell.Row > maxRenderingRow + MaxRowSpan)
                         break;
                         break;
 
 
                     // calculate cell position / size
                     // calculate cell position / size
@@ -230,14 +233,14 @@ namespace QuestPDF.Elements.Table
                     {
                     {
                         maxRenderingRow = Math.Min(maxRenderingRow, cell.Row + cell.RowSpan - 1);
                         maxRenderingRow = Math.Min(maxRenderingRow, cell.Row + cell.RowSpan - 1);
                     }
                     }
-                    
+
                     // corner case: if cell within the row want to wrap to the next page, do not attempt to render this row
                     // corner case: if cell within the row want to wrap to the next page, do not attempt to render this row
                     if (cellSize.Type == SpacePlanType.Wrap)
                     if (cellSize.Type == SpacePlanType.Wrap)
                     {
                     {
                         maxRenderingRow = Math.Min(maxRenderingRow, cell.Row - 1);
                         maxRenderingRow = Math.Min(maxRenderingRow, cell.Row - 1);
                         continue;
                         continue;
                     }
                     }
-                    
+
                     // update position of the last row that cell occupies
                     // update position of the last row that cell occupies
                     var bottomRow = cell.Row + cell.RowSpan - 1;
                     var bottomRow = cell.Row + cell.RowSpan - 1;
                     rowBottomOffsets[bottomRow] = Math.Max(rowBottomOffsets[bottomRow], topOffset + cellSize.Height);
                     rowBottomOffsets[bottomRow] = Math.Max(rowBottomOffsets[bottomRow], topOffset + cellSize.Height);

+ 16 - 6
QuestPDF/Elements/Text/FontFallback.cs

@@ -121,7 +121,11 @@ namespace QuestPDF.Elements.Text
         {
         {
             foreach (var textBlockItem in textBlockItems)
             foreach (var textBlockItem in textBlockItems)
             {
             {
-                if (textBlockItem is TextBlockSpan textBlockSpan and not TextBlockPageNumber)
+                if (textBlockItem is TextBlockPageNumber or TextBlockElement)
+                {
+                    yield return textBlockItem;
+                }
+                else if (textBlockItem is TextBlockSpan textBlockSpan)
                 {
                 {
                     if (!Settings.CheckIfAllTextGlyphsAreAvailable && textBlockSpan.Style.Fallback == null)
                     if (!Settings.CheckIfAllTextGlyphsAreAvailable && textBlockSpan.Style.Fallback == null)
                     {
                     {
@@ -130,19 +134,25 @@ namespace QuestPDF.Elements.Text
                     }
                     }
                     
                     
                     var textRuns = textBlockSpan.Text.SplitWithFontFallback(textBlockSpan.Style);
                     var textRuns = textBlockSpan.Text.SplitWithFontFallback(textBlockSpan.Style);
-
+                    
                     foreach (var textRun in textRuns)
                     foreach (var textRun in textRuns)
                     {
                     {
-                        yield return new TextBlockSpan
+                        var newElement = textBlockSpan switch
                         {
                         {
-                            Text = textRun.Content,
-                            Style = textRun.Style
+                            TextBlockHyperlink hyperlink => new TextBlockHyperlink { Url = hyperlink.Url },
+                            TextBlockSectionLink sectionLink => new TextBlockSectionLink { SectionName = sectionLink.SectionName },
+                            TextBlockSpan => new TextBlockSpan()
                         };
                         };
+
+                        newElement.Text = textRun.Content;
+                        newElement.Style = textRun.Style;
+
+                        yield return newElement;
                     }
                     }
                 }
                 }
                 else
                 else
                 {
                 {
-                    yield return textBlockItem;
+                    throw new NotSupportedException();
                 }
                 }
             }
             }
         }
         }

+ 1 - 1
QuestPDF/Elements/Text/Items/TextBlockSpan.cs

@@ -15,7 +15,7 @@ namespace QuestPDF.Elements.Text.Items
     {
     {
         public string Text { get; set; }
         public string Text { get; set; }
         public TextStyle Style { get; set; } = TextStyle.Default;
         public TextStyle Style { get; set; } = TextStyle.Default;
-        public TextShapingResult? TextShapingResult { get; set; }
+        private TextShapingResult? TextShapingResult { get; set; }
 
 
         private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache = new ();
         private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache = new ();
         protected virtual bool EnableTextCache => true; 
         protected virtual bool EnableTextCache => true; 

+ 6 - 5
readme.md

@@ -17,7 +17,7 @@ It offers a layouting engine designed with a full paging support in mind. The do
 
 
 Unlike other libraries, it does not rely on the HTML-to-PDF conversion which in many cases is not reliable. Instead, it implements its own layouting engine that is optimized to cover all paging-related requirements.
 Unlike other libraries, it does not rely on the HTML-to-PDF conversion which in many cases is not reliable. Instead, it implements its own layouting engine that is optimized to cover all paging-related requirements.
 
 
-## Please show the value
+## Please help by giving a star
 
 
 Choosing a project dependency could be difficult. We need to ensure stability and maintainability of our projects. Surveys show that GitHub stars count play an important factor when assessing library quality. 
 Choosing a project dependency could be difficult. We need to ensure stability and maintainability of our projects. Surveys show that GitHub stars count play an important factor when assessing library quality. 
 
 
@@ -47,6 +47,7 @@ Special thanks to all companies that decided to sponsor QuestPDF development. Th
 | Company                                                                              | Description                                                                                                                     |
 | Company                                                                              | Description                                                                                                                     |
 |--------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
 |--------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
 | <img src="Resources/jetbrains-logo.svg" width="100px"> | [JetBrains](https://www.jetbrains.com/) supports this project as part of the OSS Power-Ups program. Thank you!<br/>100$ / month |
 | <img src="Resources/jetbrains-logo.svg" width="100px"> | [JetBrains](https://www.jetbrains.com/) supports this project as part of the OSS Power-Ups program. Thank you!<br/>100$ / month |
+| <img src="https://avatars.githubusercontent.com/u/2712328?v=4" width="100px"> | [Mark Gould](https://github.com/markgould) supports this project. Thank you!<br/>100$ / month |
 
 
 [![Sponsor project](https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F%20sponsor-QuestPDF-red)](https://github.com/sponsors/QuestPDF)
 [![Sponsor project](https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F%20sponsor-QuestPDF-red)](https://github.com/sponsors/QuestPDF)
 
 
@@ -62,14 +63,14 @@ Install-Package QuestPDF
 dotnet add package QuestPDF
 dotnet add package QuestPDF
 
 
 // Package reference in .csproj file
 // Package reference in .csproj file
-<PackageReference Include="QuestPDF" Version="2022.6.0" />
+<PackageReference Include="QuestPDF" Version="2022.9.0" />
 ```
 ```
 
 
 [![Nuget version](https://img.shields.io/badge/package%20details-QuestPDF-blue?logo=nuget)](https://www.nuget.org/packages/QuestPDF/)
 [![Nuget version](https://img.shields.io/badge/package%20details-QuestPDF-blue?logo=nuget)](https://www.nuget.org/packages/QuestPDF/)
 
 
 ## Documentation
 ## Documentation
 
 
-[![Getting started tutorial]( https://img.shields.io/badge/%F0%9F%9A%80%20read-getting%20started-blue)](https://www.questpdf.com/getting-started.html)
+[![Getting started tutorial]( https://img.shields.io/badge/%F0%9F%9A%80%20read-getting%20started-blue)](https://www.questpdf.com/getting-started)
 A short and easy to follow tutorial showing how to design an invoice document under 200 lines of code.
 A short and easy to follow tutorial showing how to design an invoice document under 200 lines of code.
 
 
 
 
@@ -77,14 +78,14 @@ A short and easy to follow tutorial showing how to design an invoice document un
 A detailed description of behavior of all available components and how to use them with C# Fluent API.
 A detailed description of behavior of all available components and how to use them with C# Fluent API.
 
 
 
 
-[![Patterns and Practices](https://img.shields.io/badge/%E2%9C%A8%20read-patterns%20and%20practices-blue)](https://www.questpdf.com/design-patterns.html)
+[![Patterns and Practices](https://img.shields.io/badge/%E2%9C%A8%20read-patterns%20and%20practices-blue)](https://www.questpdf.com/design-patterns)
 Everything that may help you designing great reports and create reusable code that is easy to maintain.
 Everything that may help you designing great reports and create reusable code that is easy to maintain.
 
 
 ## QuestPDF Previewer
 ## QuestPDF Previewer
 
 
 The QuestPDF Previewer is a tool designed to simplify and speed up your development lifecycle. First, it shows a preview of your document. But the real magic starts with the hot-reload capability! It observes your code and updates the preview every time you change the implementation. Get real-time results without the need of code recompilation. Save time and enjoy the task!
 The QuestPDF Previewer is a tool designed to simplify and speed up your development lifecycle. First, it shows a preview of your document. But the real magic starts with the hot-reload capability! It observes your code and updates the preview every time you change the implementation. Get real-time results without the need of code recompilation. Save time and enjoy the task!
 
 
-[![Learn more](https://img.shields.io/badge/%F0%9F%93%96%20Previewer-learn%20more-blue)](https://www.questpdf.com/document-previewer.html)
+[![Learn more](https://img.shields.io/badge/%F0%9F%93%96%20Previewer-learn%20more-blue)](https://www.questpdf.com/document-previewer)
 
 
 
 
 <img src="https://github.com/QuestPDF/QuestPDF-Documentation/blob/main/docs/public/previewer/animation.gif?raw=true" width="100%">
 <img src="https://github.com/QuestPDF/QuestPDF-Documentation/blob/main/docs/public/previewer/animation.gif?raw=true" width="100%">