mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-22 12:09:50 +08:00
#127 pdf/a-1a compliance
adds struct tree and markinfo dictionaries to support pdf/a-1a compliance.
This commit is contained in:
@@ -522,6 +522,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanGeneratePdfA1AFile()
|
||||||
|
{
|
||||||
|
var builder = new PdfDocumentBuilder
|
||||||
|
{
|
||||||
|
ArchiveStandard = PdfAStandard.A1A
|
||||||
|
};
|
||||||
|
|
||||||
|
var page = builder.AddPage(PageSize.A4);
|
||||||
|
|
||||||
|
var font = builder.AddTrueTypeFont(TrueTypeTestHelper.GetFileBytes("Roboto-Regular.ttf"));
|
||||||
|
|
||||||
|
page.AddText("Howdy PDF/A-1A!", 10, new PdfPoint(25, 700), font);
|
||||||
|
|
||||||
|
var bytes = builder.Build();
|
||||||
|
|
||||||
|
WriteFile(nameof(CanGeneratePdfA1AFile), bytes);
|
||||||
|
|
||||||
|
using (var pdf = PdfDocument.Open(bytes, ParsingOptions.LenientParsingOff))
|
||||||
|
{
|
||||||
|
Assert.Equal(1, pdf.NumberOfPages);
|
||||||
|
|
||||||
|
Assert.True(pdf.TryGetXmpMetadata(out var xmp));
|
||||||
|
|
||||||
|
Assert.NotNull(xmp.GetXDocument());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void WriteFile(string name, byte[] bytes)
|
private static void WriteFile(string name, byte[] bytes)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -334,6 +334,7 @@
|
|||||||
public static readonly NameToken Mac = new NameToken("Mac");
|
public static readonly NameToken Mac = new NameToken("Mac");
|
||||||
public static readonly NameToken MacExpertEncoding = new NameToken("MacExpertEncoding");
|
public static readonly NameToken MacExpertEncoding = new NameToken("MacExpertEncoding");
|
||||||
public static readonly NameToken MacRomanEncoding = new NameToken("MacRomanEncoding");
|
public static readonly NameToken MacRomanEncoding = new NameToken("MacRomanEncoding");
|
||||||
|
public static readonly NameToken Marked = new NameToken("Marked");
|
||||||
public static readonly NameToken MarkInfo = new NameToken("MarkInfo");
|
public static readonly NameToken MarkInfo = new NameToken("MarkInfo");
|
||||||
public static readonly NameToken Mask = new NameToken("Mask");
|
public static readonly NameToken Mask = new NameToken("Mask");
|
||||||
public static readonly NameToken Matrix = new NameToken("Matrix");
|
public static readonly NameToken Matrix = new NameToken("Matrix");
|
||||||
|
35
src/UglyToad.PdfPig/Writer/PdfA1ARuleBuilder.cs
Normal file
35
src/UglyToad.PdfPig/Writer/PdfA1ARuleBuilder.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
|
||||||
|
namespace UglyToad.PdfPig.Writer
|
||||||
|
{
|
||||||
|
internal static class PdfA1ARuleBuilder
|
||||||
|
{
|
||||||
|
public static void Obey(Dictionary<NameToken, IToken> catalog)
|
||||||
|
{
|
||||||
|
var structTreeRoot = GenerateStructTree();
|
||||||
|
|
||||||
|
catalog[NameToken.StructTreeRoot] = structTreeRoot;
|
||||||
|
|
||||||
|
var markInfoDictionary = new DictionaryToken(new Dictionary<NameToken, IToken>
|
||||||
|
{
|
||||||
|
{NameToken.Marked, BooleanToken.True}
|
||||||
|
});
|
||||||
|
|
||||||
|
catalog[NameToken.MarkInfo] = markInfoDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DictionaryToken GenerateStructTree()
|
||||||
|
{
|
||||||
|
var rootDictionary = new Dictionary<NameToken, IToken>
|
||||||
|
{
|
||||||
|
{NameToken.Type, NameToken.StructTreeRoot}
|
||||||
|
};
|
||||||
|
|
||||||
|
var structTreeRoot = new DictionaryToken(rootDictionary);
|
||||||
|
|
||||||
|
return structTreeRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/UglyToad.PdfPig/Writer/PdfA1BRuleBuilder.cs
Normal file
21
src/UglyToad.PdfPig/Writer/PdfA1BRuleBuilder.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
using UglyToad.PdfPig.Writer.Colors;
|
||||||
|
using UglyToad.PdfPig.Writer.Xmp;
|
||||||
|
|
||||||
|
namespace UglyToad.PdfPig.Writer
|
||||||
|
{
|
||||||
|
internal static class PdfA1BRuleBuilder
|
||||||
|
{
|
||||||
|
public static void Obey(Dictionary<NameToken, IToken> catalog, Func<IToken, ObjectToken> writerFunc,
|
||||||
|
PdfDocumentBuilder.DocumentInformationBuilder documentInformationBuilder,
|
||||||
|
PdfAStandard archiveStandard)
|
||||||
|
{
|
||||||
|
catalog[NameToken.OutputIntents] = OutputIntentsFactory.GetOutputIntentsArray(writerFunc);
|
||||||
|
var xmpStream = XmpWriter.GenerateXmpStream(documentInformationBuilder, 1.7m, archiveStandard);
|
||||||
|
var xmpObj = writerFunc(xmpStream);
|
||||||
|
catalog[NameToken.Metadata] = new IndirectReferenceToken(xmpObj.Number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -12,6 +12,10 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compliance with PDF/A1-B. Level B (basic) conformance are standards necessary for the reliable reproduction of a document's visual appearance.
|
/// Compliance with PDF/A1-B. Level B (basic) conformance are standards necessary for the reliable reproduction of a document's visual appearance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
A1B = 1
|
A1B = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Compliance with PDF/A1-A. Level A (accessible) conformance are PDF/A1-B standards in addition to features intended to improve a document's accessibility.
|
||||||
|
/// </summary>
|
||||||
|
A1A = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -13,8 +13,6 @@ namespace UglyToad.PdfPig.Writer
|
|||||||
using PdfPig.Fonts.Standard14Fonts;
|
using PdfPig.Fonts.Standard14Fonts;
|
||||||
using PdfPig.Fonts.TrueType.Parser;
|
using PdfPig.Fonts.TrueType.Parser;
|
||||||
using Tokens;
|
using Tokens;
|
||||||
using Colors;
|
|
||||||
using Xmp;
|
|
||||||
|
|
||||||
using Util.JetBrains.Annotations;
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
@@ -343,10 +341,16 @@ namespace UglyToad.PdfPig.Writer
|
|||||||
|
|
||||||
if (ArchiveStandard != PdfAStandard.None)
|
if (ArchiveStandard != PdfAStandard.None)
|
||||||
{
|
{
|
||||||
catalogDictionary[NameToken.OutputIntents] = OutputIntentsFactory.GetOutputIntentsArray(x => context.WriteObject(memory, x));
|
Func<IToken, ObjectToken> writerFunc = x => context.WriteObject(memory, x);
|
||||||
var xmpStream = XmpWriter.GenerateXmpStream(DocumentInformation, 1.7m, ArchiveStandard);
|
|
||||||
var xmpObj = context.WriteObject(memory, xmpStream);
|
PdfA1BRuleBuilder.Obey(catalogDictionary, writerFunc, DocumentInformation, ArchiveStandard);
|
||||||
catalogDictionary[NameToken.Metadata] = new IndirectReferenceToken(xmpObj.Number);
|
|
||||||
|
switch (ArchiveStandard)
|
||||||
|
{
|
||||||
|
case PdfAStandard.A1A:
|
||||||
|
PdfA1ARuleBuilder.Obey(catalogDictionary);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var catalog = new DictionaryToken(catalogDictionary);
|
var catalog = new DictionaryToken(catalogDictionary);
|
||||||
|
@@ -135,6 +135,10 @@ namespace UglyToad.PdfPig.Writer.Xmp
|
|||||||
part = 1;
|
part = 1;
|
||||||
conformance = "B";
|
conformance = "B";
|
||||||
break;
|
break;
|
||||||
|
case PdfAStandard.A1A:
|
||||||
|
part = 1;
|
||||||
|
conformance = "A";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(standard), standard, null);
|
throw new ArgumentOutOfRangeException(nameof(standard), standard, null);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user