Add OpenNest.Reporting (net8.0, PDFsharp-MigraDoc 6.2.4) with a detached report snapshot and a PDF writer for an empty/demand-only job or a single plate layout: Letter portrait summary with vector part thumbnails and a landscape plate page with a vector sheet diagram, both with Page X of Y. - Snapshot uses reference identity for document-local R### IDs, recounts nested quantities from placements x copies with checked wide integers, excludes cutoffs from accounting, and retains no live domain objects. - Geometry keeps Cut/Display material paths, drops rapid/scribe/lead paths, preserves native arcs, holes and intentional tab gaps, and rejects malformed programs with plate/part identification. - Open contours and cutoffs are stroked per contour so PDFsharp cannot join a tab gap to the next contour. - Bundled DejaVu Sans via a custom resolver (including MigraDoc's error font); unsupported text fails with the field and code point. - Layouts beyond this slice (multiple plates, page overflow, labels that do not fit) fail with NotSupportedException before the destination is replaced; output is rendered to a temporary sibling and moved atomically.
48 lines
1.6 KiB
C#
48 lines
1.6 KiB
C#
using OpenNest.Reporting;
|
|
using PdfSharp.Drawing;
|
|
using PdfSharp.Fonts;
|
|
using PdfSharp.Pdf;
|
|
|
|
namespace OpenNest.Tests.Reporting;
|
|
|
|
public class ReportFontsTests
|
|
{
|
|
[Fact]
|
|
public void BundledFontsEmbedWithoutSystemFontResolutionAcrossRepeatedExports()
|
|
{
|
|
ReportFonts.Initialize();
|
|
var resolver = GlobalFontSettings.FontResolver;
|
|
for (var i = 0; i < 2; i++)
|
|
{
|
|
ReportFonts.Initialize();
|
|
Assert.Same(resolver, GlobalFontSettings.FontResolver);
|
|
using var doc = new PdfDocument();
|
|
var page = doc.AddPage();
|
|
using (var gfx = XGraphics.FromPdfPage(page))
|
|
{
|
|
gfx.DrawString("Résumé Ø TEST DATA", new XFont(ReportFonts.Family, 10), XBrushes.Black, 20, 20);
|
|
gfx.DrawString("Bold", new XFont(ReportFonts.Family, 10, XFontStyleEx.Bold), XBrushes.Black, 20, 40);
|
|
}
|
|
using var stream = new MemoryStream();
|
|
doc.Save(stream, false);
|
|
Assert.True(stream.Length > 1000);
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("ASCII, 0.25 in; R001\nRésumé Ø Æ")]
|
|
[InlineData("")]
|
|
public void SupportedTextPasses(string text) => ReportFonts.ValidateText(text, "part R001");
|
|
|
|
[Theory]
|
|
[InlineData("中文")]
|
|
[InlineData("bad\u0000text")]
|
|
[InlineData("hidden\u00ADhyphen")]
|
|
public void UnsupportedTextHasAnIdentifiedErrorInsteadOfMissingGlyphs(string text)
|
|
{
|
|
var error = Assert.Throws<InvalidOperationException>(() => ReportFonts.ValidateText(text, "part R001"));
|
|
Assert.Contains("part R001", error.Message);
|
|
Assert.Contains("U+", error.Message);
|
|
}
|
|
}
|