Browse Source

Merge branch 'main' into feature-merge-documents

Marcin Ziąbek 2 years ago
parent
commit
e9a1ec23e9

+ 1 - 1
.github/workflows/qodana.yml

@@ -18,4 +18,4 @@ jobs:
       - name: 'Qodana Scan'
       - name: 'Qodana Scan'
         uses: JetBrains/qodana-action@main
         uses: JetBrains/qodana-action@main
         env:
         env:
-          QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
+          QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

+ 1 - 2
README.md

@@ -56,8 +56,7 @@ Choosing a project dependency could be difficult. We need to ensure stability an
 
 
 ⭐ Please give this repository a star. It takes seconds and help thousands of developers! ⭐
 ⭐ Please give this repository a star. It takes seconds and help thousands of developers! ⭐
 
 
-<img src="https://user-images.githubusercontent.com/9263853/236193691-efb9cff8-e919-4826-9720-dcfb492980ae.png" width="800" />
-
+<img src="https://github.com/QuestPDF/QuestPDF/assets/9263853/fd16701c-d74c-41ba-a549-fb731c492fe4" width="800" />
 
 
 ## Please share with the community
 ## Please share with the community
 
 

+ 68 - 0
Source/QuestPDF.Examples/BorderExamples.cs

@@ -0,0 +1,68 @@
+using NUnit.Framework;
+using QuestPDF.Examples.Engine;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
+
+namespace QuestPDF.Examples
+{
+    public class BorderExamples
+    {
+        [Test]
+        public void Border_Simple()
+        {
+            RenderingTest
+                .Create()
+                .PageSize(200, 150)
+                .ProduceImages()
+                .ShowResults()
+                .Render(container =>
+                {
+                    container
+                        .Padding(25)
+                        
+                        .BorderLeft(6)
+                        .BorderTop(9)
+                        .BorderRight(12)
+                        .BorderBottom(15)
+                        .BorderColor(Colors.Green.Darken3)
+                        
+                        .Background(Colors.Grey.Lighten2)
+                        
+                        .AlignCenter()
+                        .AlignMiddle()
+                        .Text("Text")
+                        .FontSize(20);
+                });
+        }
+        
+        [Test]
+        public void Border_DifferentColors()
+        {
+            RenderingTest
+                .Create()
+                .PageSize(200, 150)
+                .ProduceImages()
+                .ShowResults()
+                .Render(container =>
+                {
+                    container
+                        .Padding(25)
+                        
+                        .BorderTop(5)
+                        .BorderColor(Colors.Blue.Darken1)
+                        
+                        .Container()
+                        
+                        .BorderBottom(5)
+                        .BorderColor(Colors.Green.Darken1)
+                        
+                        .Background(Colors.Grey.Lighten2)
+                        
+                        .AlignCenter()
+                        .AlignMiddle()
+                        .Text("Text")
+                        .FontSize(20);
+                });
+        }
+    }
+}

+ 27 - 0
Source/QuestPDF.UnitTests/ImageTests.cs

@@ -6,6 +6,7 @@ using System.Threading;
 using FluentAssertions;
 using FluentAssertions;
 using NUnit.Framework;
 using NUnit.Framework;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
+using QuestPDF.Drawing.Exceptions;
 using QuestPDF.Elements;
 using QuestPDF.Elements;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
 using QuestPDF.Helpers;
 using QuestPDF.Helpers;
@@ -63,6 +64,32 @@ namespace QuestPDF.UnitTests
                 .CheckMeasureResult(SpacePlan.FullRender(300, 100));;
                 .CheckMeasureResult(SpacePlan.FullRender(300, 100));;
         }
         }
         
         
+        [Test]
+        public void ImageObject_ThrowsEncodingException_WhenImageDataIsIncorrect()
+        {
+            Func<Infrastructure.Image> action = () => Infrastructure.Image.FromBinaryData(new byte[] { 1, 2, 3 });
+            action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot decode the provided image.");
+        }
+        
+        [Test]
+        public void ImageObject_ThrowsEncodingException_WhenStreamIsIncorrect()
+        {
+            Func<Infrastructure.Image> action = () =>
+            {
+                using var stream = new MemoryStream(new byte[] { 1, 2, 3 });
+                return Infrastructure.Image.FromStream(stream);
+            };
+
+            action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot decode the provided image.");
+        }
+        
+        [Test]
+        public void ImageObject_ThrowsFileNotFoundException_FileIsNotFound()
+        {
+            Func<Infrastructure.Image> action = () => Infrastructure.Image.FromFile("non-existing-file.jpg");
+            action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot load provided image, file not found: *");
+        }
+
         [Test]
         [Test]
         public void UsingSharedImageShouldNotDrasticallyIncreaseDocumentSize()
         public void UsingSharedImageShouldNotDrasticallyIncreaseDocumentSize()
         {
         {

+ 1 - 1
Source/QuestPDF/Fluent/ImageExtensions.cs

@@ -125,7 +125,7 @@ namespace QuestPDF.Fluent
             return parent.Image(image);
             return parent.Image(image);
         }
         }
         
         
-        internal static ImageDescriptor Image(this IContainer parent, Infrastructure.Image image)
+        public static ImageDescriptor Image(this IContainer parent, Infrastructure.Image image)
         {
         {
             if (image == null)
             if (image == null)
                 throw new DocumentComposeException("Cannot load or decode provided image.");
                 throw new DocumentComposeException("Cannot load or decode provided image.");

+ 11 - 6
Source/QuestPDF/Helpers/Helpers.cs

@@ -87,6 +87,15 @@ namespace QuestPDF.Helpers
             };
             };
         }
         }
         
         
+        internal static SKImage ScaleImage(this SKImage image, ImageSize targetResolution)
+        {
+            var imageInfo = new SKImageInfo(targetResolution.Width, targetResolution.Height, image.Info.ColorType, image.Info.AlphaType, image.Info.ColorSpace);
+            
+            using var bitmap = SKBitmap.FromImage(image);
+            using var resultBitmap = bitmap.Resize(imageInfo, SKFilterQuality.Medium);
+            return SKImage.FromBitmap(resultBitmap);
+        }
+        
         internal static SKImage CompressImage(this SKImage image, ImageCompressionQuality compressionQuality)
         internal static SKImage CompressImage(this SKImage image, ImageCompressionQuality compressionQuality)
         {
         {
             var targetFormat = image.Info.IsOpaque 
             var targetFormat = image.Info.IsOpaque 
@@ -105,12 +114,8 @@ namespace QuestPDF.Helpers
             if (image.Width == targetResolution.Width && image.Height == targetResolution.Height)
             if (image.Width == targetResolution.Width && image.Height == targetResolution.Height)
                 return CompressImage(image, compressionQuality);
                 return CompressImage(image, compressionQuality);
             
             
-            var imageInfo = new SKImageInfo(targetResolution.Width, targetResolution.Height, image.Info.ColorType, image.Info.AlphaType, image.Info.ColorSpace);
-            
-            using var resultImage = SKImage.Create(imageInfo);
-            image.ScalePixels(resultImage.PeekPixels(), SKFilterQuality.Medium);
-            
-            return CompressImage(resultImage, compressionQuality);
+            using var scaledImage = image.ScaleImage(targetResolution);
+            return CompressImage(scaledImage, compressionQuality);
         }
         }
 
 
         internal static SKImage GetImageWithSmallerSize(SKImage one, SKImage second)
         internal static SKImage GetImageWithSmallerSize(SKImage one, SKImage second)

+ 23 - 10
Source/QuestPDF/Infrastructure/Image.cs

@@ -54,31 +54,44 @@ namespace QuestPDF.Infrastructure
 
 
         #region public constructors
         #region public constructors
 
 
+        private const string CannotDecodeExceptionMessage = "Cannot decode the provided image.";
+        
         internal static Image FromSkImage(SKImage image)
         internal static Image FromSkImage(SKImage image)
         {
         {
-            return CreateImage(image);
+            return new Image(image);
         }
         }
 
 
         public static Image FromBinaryData(byte[] imageData)
         public static Image FromBinaryData(byte[] imageData)
         {
         {
-            return CreateImage(SKImage.FromEncodedData(imageData));
+            var image = SKImage.FromEncodedData(imageData);
+            
+            if (image == null)
+                throw new DocumentComposeException(CannotDecodeExceptionMessage);
+            
+            return new Image(image);
         }
         }
 
 
         public static Image FromFile(string filePath)
         public static Image FromFile(string filePath)
         {
         {
-            return CreateImage(SKImage.FromEncodedData(filePath));
-        }
+            var image = SKImage.FromEncodedData(filePath);
 
 
-        public static Image FromStream(Stream fileStream)
-        {
-            return CreateImage(SKImage.FromEncodedData(fileStream));
+            if (image == null)
+            {
+                throw File.Exists(filePath) 
+                    ? new DocumentComposeException(CannotDecodeExceptionMessage)
+                    : new DocumentComposeException($"Cannot load provided image, file not found: ${filePath}");
+            }
+            
+            return new Image(image);
         }
         }
 
 
-        private static Image CreateImage(SKImage? image)
+        public static Image FromStream(Stream fileStream)
         {
         {
+            var image = SKImage.FromEncodedData(fileStream);
+            
             if (image == null)
             if (image == null)
-                throw new DocumentComposeException("Cannot load or decode provided image.");
-
+                throw new DocumentComposeException(CannotDecodeExceptionMessage);
+            
             return new Image(image);
             return new Image(image);
         }
         }
 
 

+ 1 - 1
Source/QuestPDF/QuestPDF.csproj

@@ -3,7 +3,7 @@
         <Authors>MarcinZiabek</Authors>
         <Authors>MarcinZiabek</Authors>
         <Company>CodeFlint</Company>
         <Company>CodeFlint</Company>
         <PackageId>QuestPDF</PackageId>
         <PackageId>QuestPDF</PackageId>
-        <Version>2023.5.1</Version>
+        <Version>2023.5.3</Version>
         <PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API. Easily generate PDF reports, invoices, exports, etc.</PackageDescription>
         <PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API. Easily generate PDF reports, invoices, exports, etc.</PackageDescription>
         <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
         <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
         <LangVersion>9</LangVersion>
         <LangVersion>9</LangVersion>

+ 6 - 1
Source/QuestPDF/Resources/ReleaseNotes.txt

@@ -11,4 +11,9 @@ Version 2023.5.1
 - Adjusted and simplified the Image and SharedImage APIs,
 - Adjusted and simplified the Image and SharedImage APIs,
 - Improved image generation performance,
 - Improved image generation performance,
 - Provided the ability to configure the image generation process: image format, compression quality and raster DPI.
 - Provided the ability to configure the image generation process: image format, compression quality and raster DPI.
- 
+
+Version 2023.5.2
+- Adjusted accessibility of the Image API method. 
+
+Version 2023.5.3
+- Fixed: image scaling may cause a rare bug that terminates an entire application when under a high memory pressure.