Browse Source

Fixed occasional rendering artifacts at the container’s top or bottom when text spans multiple pages, and optimized text rendering for lengthy text elements. #1208

Marcin Ziąbek 9 months ago
parent
commit
7098536e07

+ 1 - 1
Source/QuestPDF.UnitTests/TestEngine/MockCanvas.cs

@@ -23,7 +23,7 @@ namespace QuestPDF.UnitTests.TestEngine
 
 
         public void DrawFilledRectangle(Position vector, Size size, Color color) => DrawRectFunc(vector, size, color);
         public void DrawFilledRectangle(Position vector, Size size, Color color) => DrawRectFunc(vector, size, color);
         public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
         public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
-        public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
+        public void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo) => throw new NotImplementedException();
         public void DrawImage(SkImage image, Size size) => DrawImageFunc(image, Position.Zero, size);
         public void DrawImage(SkImage image, Size size) => DrawImageFunc(image, Position.Zero, size);
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();
         public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();

+ 1 - 1
Source/QuestPDF.UnitTests/TestEngine/OperationRecordingCanvas.cs

@@ -20,7 +20,7 @@ namespace QuestPDF.UnitTests.TestEngine
 
 
         public void DrawFilledRectangle(Position vector, Size size, Color color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
         public void DrawFilledRectangle(Position vector, Size size, Color color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
         public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
         public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
-        public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
+        public void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo) => throw new NotImplementedException();
         public void DrawImage(SkImage image, Size size) => Operations.Add(new CanvasDrawImageOperation(Position.Zero, size));
         public void DrawImage(SkImage image, Size size) => Operations.Add(new CanvasDrawImageOperation(Position.Zero, size));
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();
         public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();

+ 1 - 1
Source/QuestPDF/Drawing/FreeCanvas.cs

@@ -64,7 +64,7 @@ namespace QuestPDF.Drawing
             
             
         }
         }
         
         
-        public void DrawParagraph(SkParagraph paragraph)
+        public void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo)
         {
         {
             
             
         }
         }

+ 2 - 2
Source/QuestPDF/Drawing/ProxyCanvas.cs

@@ -33,9 +33,9 @@ internal sealed class ProxyCanvas : ICanvas
         Target.DrawStrokeRectangle(vector, size, strokeWidth, color);
         Target.DrawStrokeRectangle(vector, size, strokeWidth, color);
     }
     }
 
 
-    public void DrawParagraph(SkParagraph paragraph)
+    public void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo)
     {
     {
-        Target.DrawParagraph(paragraph);
+        Target.DrawParagraph(paragraph, lineFrom, lineTo);
     }
     }
 
 
     public void DrawImage(SkImage image, Size size)
     public void DrawImage(SkImage image, Size size)

+ 2 - 2
Source/QuestPDF/Drawing/SkiaCanvasBase.cs

@@ -86,9 +86,9 @@ namespace QuestPDF.Drawing
             Canvas.DrawStrokeRectangle(position, strokeWidth, color);
             Canvas.DrawStrokeRectangle(position, strokeWidth, color);
         }
         }
 
 
-        public void DrawParagraph(SkParagraph paragraph)
+        public void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo)
         {
         {
-            Canvas.DrawParagraph(paragraph);
+            Canvas.DrawParagraph(paragraph, lineFrom, lineTo);
         }
         }
 
 
         public void DrawImage(SkImage image, Size size)
         public void DrawImage(SkImage image, Size size)

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

@@ -185,11 +185,14 @@ namespace QuestPDF.Elements.Text
                 if (takesMultiplePages)
                 if (takesMultiplePages)
                 {
                 {
                     Canvas.Save();
                     Canvas.Save();
-                    Canvas.ClipRectangle(new SkRect(0, 0, availableSpace.Width, takenHeight));
                     Canvas.Translate(new Position(0, -CurrentTopOffset));
                     Canvas.Translate(new Position(0, -CurrentTopOffset));
                 }
                 }
+
+                Canvas.DrawParagraph(Paragraph, CurrentLineIndex, CurrentLineIndex + linesToDraw - 1);
+                
+                if (takesMultiplePages)
+                    Canvas.ClipRectangle(new SkRect(0, CurrentTopOffset, availableSpace.Width, takenHeight + CurrentTopOffset));
                 
                 
-                Canvas.DrawParagraph(Paragraph);
                 DrawInjectedElements();
                 DrawInjectedElements();
                 DrawHyperlinks();
                 DrawHyperlinks();
                 DrawSectionLinks();
                 DrawSectionLinks();
@@ -596,7 +599,7 @@ namespace QuestPDF.Elements.Text
                     var textStyle = TextStyleManager.GetTextStyle(textStyleId).GetSkTextStyle();
                     var textStyle = TextStyleManager.GetTextStyle(textStyleId).GetSkTextStyle();
                     builder.AddText("\u00A0", textStyle); // non-breaking space
                     builder.AddText("\u00A0", textStyle); // non-breaking space
 
 
-                    var paragraph = builder.CreateParagraph();
+                    using var paragraph = builder.CreateParagraph();
                     paragraph.PlanLayout(1000);
                     paragraph.PlanLayout(1000);
                     return paragraph.GetLineMetrics().First().Height;
                     return paragraph.GetLineMetrics().First().Height;
                 }
                 }

+ 1 - 1
Source/QuestPDF/Infrastructure/ICanvas.cs

@@ -12,7 +12,7 @@ namespace QuestPDF.Infrastructure
         
         
         void DrawFilledRectangle(Position vector, Size size, Color color);
         void DrawFilledRectangle(Position vector, Size size, Color color);
         void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color);
         void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color);
-        void DrawParagraph(SkParagraph paragraph);
+        void DrawParagraph(SkParagraph paragraph, int lineFrom, int lineTo);
         void DrawImage(SkImage image, Size size);
         void DrawImage(SkImage image, Size size);
         void DrawPicture(SkPicture picture);
         void DrawPicture(SkPicture picture);
         void DrawSvgPath(string path, Color color);
         void DrawSvgPath(string path, Color color);

BIN
Source/QuestPDF/Runtimes/linux-arm64/native/libQuestPdfSkia.so


BIN
Source/QuestPDF/Runtimes/linux-musl-x64/native/libQuestPdfSkia.so


BIN
Source/QuestPDF/Runtimes/linux-x64/native/libQuestPdfSkia.so


BIN
Source/QuestPDF/Runtimes/osx-arm64/native/libQuestPdfSkia.dylib


BIN
Source/QuestPDF/Runtimes/osx-x64/native/libQuestPdfSkia.dylib


BIN
Source/QuestPDF/Runtimes/win-x64/native/QuestPdfSkia.dll


BIN
Source/QuestPDF/Runtimes/win-x86/native/QuestPdfSkia.dll


+ 3 - 3
Source/QuestPDF/Skia/SkCanvas.cs

@@ -68,9 +68,9 @@ internal sealed class SkCanvas : IDisposable
         API.canvas_draw_picture(Instance, picture.Instance);
         API.canvas_draw_picture(Instance, picture.Instance);
     }
     }
     
     
-    public void DrawParagraph(SkParagraph paragraph)
+    public void DrawParagraph(SkParagraph paragraph, int? lineFrom = null, int? lineTo = null)
     {
     {
-        API.canvas_draw_paragraph(Instance, paragraph.Instance);
+        API.canvas_draw_paragraph(Instance, paragraph.Instance, lineFrom ?? 0, lineTo ?? int.MaxValue);
     }
     }
     
     
     public void DrawSvgPath(string svg, uint color)
     public void DrawSvgPath(string svg, uint color)
@@ -184,7 +184,7 @@ internal sealed class SkCanvas : IDisposable
         public static extern void canvas_draw_stroke_rectangle(IntPtr canvas, SkRect position, float strokeWidth, uint color);
         public static extern void canvas_draw_stroke_rectangle(IntPtr canvas, SkRect position, float strokeWidth, uint color);
         
         
         [DllImport(SkiaAPI.LibraryName, CallingConvention = CallingConvention.Cdecl)]
         [DllImport(SkiaAPI.LibraryName, CallingConvention = CallingConvention.Cdecl)]
-        public static extern void canvas_draw_paragraph(IntPtr canvas, IntPtr paragraph);
+        public static extern void canvas_draw_paragraph(IntPtr canvas, IntPtr paragraph, int lineFrom, int lineTo);
         
         
         [DllImport(SkiaAPI.LibraryName, CallingConvention = CallingConvention.Cdecl)]
         [DllImport(SkiaAPI.LibraryName, CallingConvention = CallingConvention.Cdecl)]
         public static extern void canvas_draw_svg_path(IntPtr canvas, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaller))] string svg, uint color);
         public static extern void canvas_draw_svg_path(IntPtr canvas, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8StringMarshaller))] string svg, uint color);