MarcinZiabek 3 years ago
parent
commit
657bbe2aac

+ 15 - 4
QuestPDF/Drawing/DocumentGenerator.cs

@@ -17,19 +17,30 @@ namespace QuestPDF.Drawing
     {
         internal static void GeneratePdf(Stream stream, IDocument document)
         {
+            CheckIfStreamIsCompatible(stream);
+            
             var metadata = document.GetMetadata();
-            var writeOnlyStream = new WriteOnlyStream(stream);
-            var canvas = new PdfCanvas(writeOnlyStream, metadata);
+            var canvas = new PdfCanvas(stream, metadata);
             RenderDocument(canvas, document);
         }
         
         internal static void GenerateXps(Stream stream, IDocument document)
         {
+            CheckIfStreamIsCompatible(stream);
+            
             var metadata = document.GetMetadata();
-            var writeOnlyStream = new WriteOnlyStream(stream);
-            var canvas = new XpsCanvas(writeOnlyStream, metadata);
+            var canvas = new XpsCanvas(stream, metadata);
             RenderDocument(canvas, document);
         }
+
+        private static void CheckIfStreamIsCompatible(Stream stream)
+        {
+            if (!stream.CanWrite)
+                throw new ArgumentException("The library requires a Stream object with the 'write' capability available (the CanWrite flag). Please consider using the MemoryStream class.");
+            
+            if (!stream.CanSeek)
+                throw new ArgumentException("The library requires a Stream object with the 'seek' capability available (the CanSeek flag). Please consider using the MemoryStream class.");
+        }
         
         internal static ICollection<byte[]> GenerateImages(IDocument document)
         {

+ 4 - 4
QuestPDF/Drawing/SkiaDocumentCanvasBase.cs

@@ -6,16 +6,16 @@ namespace QuestPDF.Drawing
 {
     internal class SkiaDocumentCanvasBase : SkiaCanvasBase
     {
-        private SKDocument Document { get; }
+        private SKDocument? Document { get; }
 
-        public SkiaDocumentCanvasBase(SKDocument document)
+        protected SkiaDocumentCanvasBase(SKDocument document)
         {
             Document = document;
         }
 
         ~SkiaDocumentCanvasBase()
         {
-            Document.Dispose();
+            Document?.Dispose();
         }
         
         public override void BeginDocument()
@@ -25,7 +25,7 @@ namespace QuestPDF.Drawing
 
         public override void EndDocument()
         {
-            Canvas.Dispose();
+            Canvas?.Dispose();
             
             Document.Close();
             Document.Dispose();

+ 2 - 2
QuestPDF/Elements/Line.cs

@@ -25,8 +25,8 @@ namespace QuestPDF.Elements
         {
             return Type switch
             {
-                LineType.Vertical when availableSpace.Width >= Size => SpacePlan.FullRender(Size, 0),
-                LineType.Horizontal when availableSpace.Height >= Size => SpacePlan.FullRender(0, Size),
+                LineType.Vertical when availableSpace.Width + Infrastructure.Size.Epsilon >= Size => SpacePlan.FullRender(Size, 0),
+                LineType.Horizontal when availableSpace.Height + Infrastructure.Size.Epsilon >= Size => SpacePlan.FullRender(0, Size),
                 _ => SpacePlan.Wrap()
             };
         }

+ 4 - 2
QuestPDF/Elements/ScaleToFit.cs

@@ -17,8 +17,10 @@ namespace QuestPDF.Elements
             if (perfectScale == null)
                 return SpacePlan.Wrap();
 
-            var targetSpace = ScaleSize(availableSpace, perfectScale.Value);
-            return SpacePlan.FullRender(targetSpace);
+            var scaledSpace = ScaleSize(availableSpace, 1 / perfectScale.Value);
+            var childSizeInScale = Child.Measure(scaledSpace);
+            var childSizeInOriginalScale = ScaleSize(childSizeInScale, perfectScale.Value);
+            return SpacePlan.FullRender(childSizeInOriginalScale);
         }
         
         internal override void Draw(Size availableSpace)

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

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using QuestPDF.Drawing;
 using QuestPDF.Elements.Text.Calculation;
 using QuestPDF.Infrastructure;
@@ -11,8 +12,7 @@ namespace QuestPDF.Elements.Text.Items
         public string Text { get; set; }
         public TextStyle Style { get; set; } = new TextStyle();
 
-        private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache =
-            new Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?>();
+        private Dictionary<(int startIndex, float availableWidth), TextMeasurementResult?> MeasureCache = new ();
 
         public virtual TextMeasurementResult? Measure(TextMeasurementRequest request)
         {
@@ -54,7 +54,7 @@ namespace QuestPDF.Elements.Text.Items
             // start breaking text from requested position
             var text = Text.Substring(startIndex);
             
-            var textLength = (int)paint.BreakText(text, request.AvailableWidth);
+            var textLength = (int)paint.BreakText(text, request.AvailableWidth + Size.Epsilon);
 
             if (textLength <= 0)
                 return null;

+ 2 - 2
QuestPDF/Fluent/GenerateExtensions.cs

@@ -29,6 +29,8 @@ namespace QuestPDF.Fluent
         }
         
         #endregion
+
+        #region XPS
         
         public static byte[] GenerateXps(this IDocument document)
         {
@@ -48,8 +50,6 @@ namespace QuestPDF.Fluent
             DocumentGenerator.GenerateXps(stream, document);
         }
         
-        #region XPS
-        
         #endregion
 
         #region Images

+ 0 - 56
QuestPDF/Helpers/WriteOnlyStream.cs

@@ -1,56 +0,0 @@
-using System;
-using System.IO;
-
-namespace QuestPDF.Helpers
-{
-    /// <summary>
-    /// SkiaSharp calls the Position property when generating target document file.
-    /// If the output stream does not support the Position property, the NullReferenceException is thrown.
-    /// This wrapper fixes this issue by providing cached Position value (always the end of the stream / current length).
-    /// Example stream affected: HttpContext.Response.Body
-    /// </summary>
-    internal class WriteOnlyStream : Stream
-    {
-        private readonly Stream InnerStream;
-        private long StreamLength { get; set; }
-
-        public WriteOnlyStream(Stream stream)
-        {            
-            if (!stream.CanWrite)
-                throw new NotSupportedException("Stream cannot be written");
-
-            InnerStream = stream;
-        }
-
-        public override bool CanRead => false;
-
-        public override bool CanSeek => false;
-
-        public override bool CanWrite => true;
-
-        public override long Length => StreamLength;
-
-        public override long Position
-        { 
-            get => StreamLength; 
-            set => throw new NotImplementedException(); 
-        }
-
-        public override void Flush() => InnerStream.Flush();
-
-        public override int Read(byte[] buffer, int offset, int count) 
-            => throw new NotImplementedException();
-
-        public override long Seek(long offset, SeekOrigin origin) 
-            => throw new NotImplementedException();
-
-        public override void SetLength(long value) 
-            => throw new NotImplementedException();
-
-        public override void Write(byte[] buffer, int offset, int count)
-        {
-            InnerStream.Write(buffer, offset, count);
-            StreamLength += count;
-        }
-    }
-}

+ 1 - 1
QuestPDF/QuestPDF.csproj

@@ -4,7 +4,7 @@
         <Authors>MarcinZiabek</Authors>
         <Company>CodeFlint</Company>
         <PackageId>QuestPDF</PackageId>
-        <Version>2022.2.3</Version>
+        <Version>2022.2.4</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.</PackageDescription>
         <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
         <LangVersion>9</LangVersion>