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 QuestPDF.Drawing.Exceptions;
 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]
         public void Exception()
         {
@@ -47,5 +63,43 @@ namespace QuestPDF.Examples
                     .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 => { });
                 });
         }
+        
+        [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.Text;
 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]
         public void TextDirectionality()
         {

+ 2 - 7
QuestPDF/Elements/DynamicImage.cs

@@ -24,13 +24,8 @@ namespace QuestPDF.Elements
             if (imageData == null)
                 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;
                     
                     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)
                         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
         private TableCell[][] CellsCache { get; set; }
         private int MaxRow { get; set; }
+        private int MaxRowSpan { get; set; }
         
         internal override IEnumerable<Element?> GetChildren()
         {
@@ -64,6 +65,7 @@ namespace QuestPDF.Elements.Table
             if (Cells.Count == 0)
             {
                 MaxRow = 0;
+                MaxRowSpan = 1;
                 CellsCache = Array.Empty<TableCell[]>();
                 
                 return;
@@ -74,6 +76,7 @@ namespace QuestPDF.Elements.Table
                 .ToDictionary(x => x.Key, x => x.OrderBy(x => x.Column).ToArray());
 
             MaxRow = groups.Max(x => x.Key);
+            MaxRowSpan = Cells.Max(x => x.RowSpan);
 
             CellsCache = Enumerable
                 .Range(0, MaxRow + 1)
@@ -211,9 +214,9 @@ namespace QuestPDF.Elements.Table
                         
                         currentRow = cell.Row;
                     }
-
+                    
                     // cell visibility optimizations
-                    if (cell.Row > maxRenderingRow)
+                    if (cell.Row > maxRenderingRow + MaxRowSpan)
                         break;
 
                     // calculate cell position / size
@@ -230,14 +233,14 @@ namespace QuestPDF.Elements.Table
                     {
                         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
                     if (cellSize.Type == SpacePlanType.Wrap)
                     {
                         maxRenderingRow = Math.Min(maxRenderingRow, cell.Row - 1);
                         continue;
                     }
-                    
+
                     // update position of the last row that cell occupies
                     var bottomRow = cell.Row + cell.RowSpan - 1;
                     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)
             {
-                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)
                     {
@@ -130,19 +134,25 @@ namespace QuestPDF.Elements.Text
                     }
                     
                     var textRuns = textBlockSpan.Text.SplitWithFontFallback(textBlockSpan.Style);
-
+                    
                     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
                 {
-                    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 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 ();
         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.
 
-## 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. 
 
@@ -47,6 +47,7 @@ Special thanks to all companies that decided to sponsor QuestPDF development. Th
 | 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="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)
 
@@ -62,14 +63,14 @@ Install-Package QuestPDF
 dotnet add package QuestPDF
 
 // 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/)
 
 ## 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.
 
 
@@ -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.
 
 
-[![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.
 
 ## 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!
 
-[![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%">