Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<NoWarn>CS1591;CS0649;CA1416;NU1608;NU1109</NoWarn>
<Version>5.27.0</Version>
<Version>5.28.0</Version>
<LangVersion>preview</LangVersion>
<AssemblyVersion>1.0.0</AssemblyVersion>
<PackageTags>Aspose, Verify</PackageTags>
Expand Down
36 changes: 34 additions & 2 deletions src/Verify.Aspose/VerifyAsposeSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace VerifyTestsAspose;
namespace VerifyTestsAspose;

public static class VerifyAsposeSettings
{
Expand Down Expand Up @@ -67,4 +67,36 @@ internal static PngDevice GetPdfPngDevice(this IReadOnlyDictionary<string, objec
var func = (Func<Aspose.Pdf.Page, PngDevice>) value;
return func(page);
}
}

/// <summary>
/// Snapshots the pdf bytes exactly as produced, skipping the normalization that neutralizes the
/// trailer <c>/ID</c>, the <c>/CreationDate</c> and <c>/ModDate</c>, and the XMP dates and
/// identifiers. Use it when the producer already emits byte-deterministic documents, since
/// normalizing them again copies the whole buffer, rescans it, and — when the XMP packet is
/// canonicalized — rebuilds it and repairs the cross-reference table, all to change nothing.
/// </summary>
/// <remarks>
/// Only skip this when the producer is genuinely deterministic. Without it a freshly generated
/// pdf carries a wall-clock <c>/CreationDate</c> and a fresh <c>/ID</c>, so the snapshot differs
/// on every run.
/// <para>
/// The XMP canonicalization is worth calling out because it is the pass that changes bytes for
/// an already-deterministic producer: it collapses the packet's whitespace, so enabling or
/// disabling this setting on an existing suite shifts the stored <c>.verified.pdf</c> even
/// though nothing about the document changed. Expect to re-accept those snapshots once.
/// </para>
/// </remarks>
public static void SkipPdfNormalization(this VerifySettings settings) =>
settings.Context["VerifyAsposeSkipPdfNormalization"] = true;

/// <inheritdoc cref="SkipPdfNormalization(VerifySettings)"/>
public static SettingsTask SkipPdfNormalization(this SettingsTask settings)
{
settings.CurrentSettings.SkipPdfNormalization();
return settings;
}

internal static bool NormalizePdf(this IReadOnlyDictionary<string, object> settings) =>
!settings.TryGetValue("VerifyAsposeSkipPdfNormalization", out var value) ||
value is not true;
}
7 changes: 4 additions & 3 deletions src/Verify.Aspose/VerifyAspose_Pdf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static ConversionResult ConvertPdf(string? name, Document document, IReadOnlyDic
// Building the deterministic pdf is expensive, so skip it when the pdf target is excluded.
if (!settings.IsTargetExcluded("pdf"))
{
targets.Add(BuildPdfTarget(document));
targets.Add(BuildPdfTarget(document, settings.NormalizePdf()));
}

targets.AddRange(GetPdfStreams(name, document, settings));
Expand All @@ -145,11 +145,12 @@ static ConversionResult ConvertPdf(string? name, Document document, IReadOnlyDic
// The pdf snapshot is always the full document, regardless of PagesToInclude: PagesToInclude
// only trims the rendered png pages in GetPdfStreams. Mirrors BuildXlsxTarget/BuildDocxTarget,
// which do the same for the OOXML formats via DeterministicPackage.
static Target BuildPdfTarget(Document document)
static Target BuildPdfTarget(Document document, bool normalize)
{
using var source = new MemoryStream();
document.Save(source);
var resultStream = PdfNormalizer.Normalize(source);
source.Position = 0;
var resultStream = normalize ? PdfNormalizer.Normalize(source) : new MemoryStream(source.ToArray());

return new("pdf", resultStream, performConversion: false)
{
Expand Down
Loading