Browse Source

Fixed a rare memory leak issue occurring on certain CPU architectures

Marcin Ziąbek 1 year ago
parent
commit
496ac02466

+ 7 - 7
Source/QuestPDF/Elements/Text/SkParagraphBuilderPoolManager.cs

@@ -7,29 +7,29 @@ namespace QuestPDF.Elements.Text;
 
 
 internal static class SkParagraphBuilderPoolManager
 internal static class SkParagraphBuilderPoolManager
 {
 {
-    private static ConcurrentDictionary<ParagraphStyleConfiguration, ConcurrentBag<SkParagraphBuilder>> ObjectPool { get; } = new();
+    private static ConcurrentDictionary<ParagraphStyle, ConcurrentBag<SkParagraphBuilder>> ObjectPool { get; } = new();
 
 
-    public static SkParagraphBuilder Get(ParagraphStyleConfiguration configuration)
+    public static SkParagraphBuilder Get(ParagraphStyle style)
     {
     {
-        var specificPool = GetPool(configuration);
+        var specificPool = GetPool(style);
         
         
         if (specificPool.TryTake(out var builder))
         if (specificPool.TryTake(out var builder))
             return builder;
             return builder;
         
         
         var fontCollection = SkFontCollection.Create(FontManager.TypefaceProvider, FontManager.CurrentFontManager);
         var fontCollection = SkFontCollection.Create(FontManager.TypefaceProvider, FontManager.CurrentFontManager);
-        return SkParagraphBuilder.Create(configuration, fontCollection);
+        return SkParagraphBuilder.Create(style, fontCollection);
     }
     }
 
 
     public static void Return(SkParagraphBuilder builder)
     public static void Return(SkParagraphBuilder builder)
     {
     {
         builder.Reset();
         builder.Reset();
         
         
-        var specificPool = GetPool(builder.Configuration);
+        var specificPool = GetPool(builder.Style);
         specificPool.Add(builder);
         specificPool.Add(builder);
     }
     }
 
 
-    private static ConcurrentBag<SkParagraphBuilder> GetPool(ParagraphStyleConfiguration configuration)
+    private static ConcurrentBag<SkParagraphBuilder> GetPool(ParagraphStyle style)
     {
     {
-        return ObjectPool.GetOrAdd(configuration, _ => new ConcurrentBag<SkParagraphBuilder>());
+        return ObjectPool.GetOrAdd(style, _ => new ConcurrentBag<SkParagraphBuilder>());
     }
     }
 }
 }

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

@@ -271,16 +271,14 @@ namespace QuestPDF.Elements.Text
 
 
         private void BuildParagraph()
         private void BuildParagraph()
         {
         {
-            using var clampLinesEllipsis = new SkText(LineClampEllipsis);
-            
             Alignment ??= TextHorizontalAlignment.Start;
             Alignment ??= TextHorizontalAlignment.Start;
             
             
-            var paragraphStyle = new ParagraphStyleConfiguration
+            var paragraphStyle = new ParagraphStyle
             {
             {
                 Alignment = MapAlignment(Alignment.Value),
                 Alignment = MapAlignment(Alignment.Value),
                 Direction = MapDirection(ContentDirection),
                 Direction = MapDirection(ContentDirection),
                 MaxLinesVisible = LineClamp ?? 1_000_000,
                 MaxLinesVisible = LineClamp ?? 1_000_000,
-                LineClampEllipsis = clampLinesEllipsis.Instance
+                LineClampEllipsis = LineClampEllipsis
             };
             };
             
             
             var builder = SkParagraphBuilderPoolManager.Get(paragraphStyle);
             var builder = SkParagraphBuilderPoolManager.Get(paragraphStyle);
@@ -559,10 +557,12 @@ namespace QuestPDF.Elements.Text
             
             
             static float Measure(int textStyleId)
             static float Measure(int textStyleId)
             {
             {
-                var paragraphStyle = new ParagraphStyleConfiguration
+                var paragraphStyle = new ParagraphStyle
                 {
                 {
                     Alignment = ParagraphStyleConfiguration.TextAlign.Start,
                     Alignment = ParagraphStyleConfiguration.TextAlign.Start,
-                    Direction = ParagraphStyleConfiguration.TextDirection.Ltr
+                    Direction = ParagraphStyleConfiguration.TextDirection.Ltr,
+                    MaxLinesVisible = 1_000_000,
+                    LineClampEllipsis = string.Empty
                 };
                 };
             
             
                 var builder = SkParagraphBuilderPoolManager.Get(paragraphStyle);
                 var builder = SkParagraphBuilderPoolManager.Get(paragraphStyle);

+ 5 - 0
Source/QuestPDF/Resources/ReleaseNotes.txt

@@ -11,3 +11,8 @@ Version 2024.10.1
 - Companion App: Improved support for documents with multiple page configurations.
 - Companion App: Improved support for documents with multiple page configurations.
 - Font discovery: Fixed file-access related exceptions.
 - Font discovery: Fixed file-access related exceptions.
 - Font discovery: Improved default file path for font discovery.
 - Font discovery: Improved default file path for font discovery.
+
+
+Version 2024.10.2
+- Fixed parsing of color values from both strings and uint.
+- Fixed a rare memory leak issue occurring on certain CPU architectures.

+ 21 - 3
Source/QuestPDF/Skia/Text/SkParagraphBuilder.cs

@@ -82,21 +82,39 @@ internal struct SkPlaceholderStyle
     }
     }
 }
 }
 
 
+record ParagraphStyle
+{
+    public ParagraphStyleConfiguration.TextAlign Alignment { get; init; }
+    public ParagraphStyleConfiguration.TextDirection Direction { get; init; }
+    public int MaxLinesVisible { get; init; }
+    public string LineClampEllipsis { get; init; }
+}
+
 internal sealed class SkParagraphBuilder : IDisposable
 internal sealed class SkParagraphBuilder : IDisposable
 {
 {
     public IntPtr Instance { get; private set; }
     public IntPtr Instance { get; private set; }
     
     
-    public ParagraphStyleConfiguration Configuration { get; private set; }
+    public ParagraphStyle Style { get; private set; }
 
 
-    public static SkParagraphBuilder Create(ParagraphStyleConfiguration paragraphStyleConfiguration, SkFontCollection fontCollection)
+    public static SkParagraphBuilder Create(ParagraphStyle style, SkFontCollection fontCollection)
     {
     {
+        using var clampLinesEllipsis = new SkText(style.LineClampEllipsis);
+
+        var paragraphStyleConfiguration = new ParagraphStyleConfiguration
+        {
+            Alignment = style.Alignment,
+            Direction = style.Direction,
+            MaxLinesVisible = style.MaxLinesVisible,
+            LineClampEllipsis = clampLinesEllipsis.Instance
+        };
+        
         var instance = API.paragraph_builder_create(paragraphStyleConfiguration, fontCollection.Instance);
         var instance = API.paragraph_builder_create(paragraphStyleConfiguration, fontCollection.Instance);
         SkiaAPI.EnsureNotNull(instance);
         SkiaAPI.EnsureNotNull(instance);
         
         
         return new SkParagraphBuilder
         return new SkParagraphBuilder
         {
         {
             Instance = instance,
             Instance = instance,
-            Configuration = paragraphStyleConfiguration
+            Style = style
         };
         };
     }
     }