Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

### [3.2.13-rc.14] - 2026-02-11
- Upgraded `MuPDF.NativeAssets` to 1.27.2 and refreshed generated MuPDF bindings for Windows and Linux.
- Implemented `IDisposable` on core types (`Document`, `Page`, `TextPage`, `Story`, `DocumentWriter`, `DisplayList`, `Font`, `GraftMap`, `DeviceWrapper`, `Outline`) and made `Document.Dispose()` idempotent.
- Hardened native resource handling (e.g. `Document.Convert2Pdf`, `Pixmap.InvertIrect`) to be exception-safe, fixed `Pixmap.InvertIrect` null/stencil handling, and added tests for table extraction and disposal patterns.

### [3.2.13-rc.6] - 2025-12-26
- Fixed the issues in `ResolveNames` method.
- Fixed the issues in `DrawShape`
Expand Down
20 changes: 20 additions & 0 deletions Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,30 @@ static void Main(string[] args)
TestTable();
TestGetText();
TestMarkdownReader();
TestRecompressJBIG2();

return;
}

static void TestRecompressJBIG2()
{
Console.WriteLine("\n=== TestJBIG2 =======================");

string testFilePath = Path.GetFullPath("../../../TestDocuments/Jbig2.pdf");

Document doc = new Document(testFilePath);

PdfImageRewriterOptions opts = new PdfImageRewriterOptions();

opts.bitonal_image_recompress_method = mupdf.mupdf.FZ_RECOMPRESS_FAX;
opts.recompress_when = mupdf.mupdf.FZ_RECOMPRESS_WHEN_ALWAYS;

doc.RewriteImage(options: opts);

doc.Save(@"e:\TestRecompressJBIG2.pdf");
doc.Close();
}

static void TestMarkdownReader()
{
Console.WriteLine("\n=== TestMarkdownReader =======================");
Expand Down
Binary file added Demo/TestDocuments/Jbig2.pdf
Binary file not shown.
119 changes: 119 additions & 0 deletions MuPDF.NET.Test/DisposePatternTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using System.IO;
using NUnit.Framework;
using MuPDF.NET;

namespace MuPDF.NET.Test
{
public class DisposePatternTest
{
private const string TocPath = "../../../resources/toc.pdf";

[Test]
public void Document_Dispose_MultipleTimes_DoesNotThrow()
{
var doc = new Document(TocPath);

doc.Dispose();

Assert.DoesNotThrow(() => doc.Dispose());
}

[Test]
public void Page_Dispose_MultipleTimes_DoesNotThrow()
{
var doc = new Document(TocPath);
var page = doc[0];

page.Dispose();

Assert.DoesNotThrow(() => page.Dispose());

doc.Dispose();
}

[Test]
public void TextPage_Dispose_MultipleTimes_DoesNotThrow()
{
var doc = new Document(TocPath);
var page = doc[0];
var textPage = page.GetTextPage();

textPage.Dispose();

Assert.DoesNotThrow(() => textPage.Dispose());

page.Dispose();
doc.Dispose();
}

[Test]
public void Story_Dispose_MultipleTimes_DoesNotThrow()
{
var story = new Story("<p>Hello</p>");

story.Dispose();

Assert.DoesNotThrow(() => story.Dispose());
}

[Test]
public void DisplayList_Dispose_MultipleTimes_DoesNotThrow()
{
var rect = new Rect(0, 0, 100, 100);
var dl = new DisplayList(rect);

dl.Dispose();

Assert.DoesNotThrow(() => dl.Dispose());
}

[Test]
public void DocumentWriter_Dispose_MultipleTimes_DoesNotThrow()
{
string path = Path.GetTempFileName();

try
{
var writer = new DocumentWriter(path);

writer.Dispose();

Assert.DoesNotThrow(() => writer.Dispose());
}
finally
{
if (File.Exists(path))
File.Delete(path);
}
}

[Test]
public void Font_Dispose_MultipleTimes_DoesNotThrow()
{
var font = new Font();

font.Dispose();

Assert.DoesNotThrow(() => font.Dispose());
}

[Test]
public void GraftMap_Dispose_MultipleTimes_DoesNotThrow()
{
var doc = new Document(TocPath);
var map = new GraftMap(doc);

map.Dispose();

Assert.DoesNotThrow(() => map.Dispose());

doc.Dispose();
}

// Outline is constructed internally from native MuPDF outline structures and
// not exposed as a public constructor. Its disposal semantics are exercised
// indirectly via Document/Document.GetToc tests, so we skip a direct idempotency test.
}
}

Binary file modified MuPDF.NET.Test/resources/test_1645_expected.pdf
Binary file not shown.
5 changes: 3 additions & 2 deletions MuPDF.NET/DeviceWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using mupdf;
using mupdf;
using System;

namespace MuPDF.NET
{
public class DeviceWrapper
public class DeviceWrapper : IDisposable
{
static DeviceWrapper()
{
Expand Down
5 changes: 3 additions & 2 deletions MuPDF.NET/DisplayList.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using mupdf;
using mupdf;
using System;

namespace MuPDF.NET
{
public class DisplayList
public class DisplayList : IDisposable
{

static DisplayList()
Expand Down
Loading