PdfA4.cs
C# VB
//// This code is part of Document Solutions for PDF .NET demos.// Copyright (c) MESCIUS inc. All rights reserved.//using System;using System.IO;using System.Drawing;using System.Text;using GrapeCity.Documents.Text;using GrapeCity.Documents.Drawing;using GrapeCity.Documents.Pdf;using GrapeCity.Documents.Pdf.Structure;using GrapeCity.Documents.Pdf.MarkedContent;using GrapeCity.Documents.Pdf.Graphics;using GrapeCity.Documents.Pdf.Annotations;using GCTEXT = GrapeCity.Documents.Text;using GCDRAW = GrapeCity.Documents.Drawing;
namespace DsPdfWeb.Demos.Basics{ // This sample shows how to create a PDF/A-4f compliant document. public class PdfA4 { public int CreatePDF(Stream stream) { var doc = new GcPdfDocument(); var date = new DateTime(1961, 4, 12, 6, 7, 0, DateTimeKind.Utc);
// PDF/A-4 is based on PDF 2.0: doc.PdfVersion = "2.0"; // Mark the document as PDF/A-4f conformant: doc.Metadata.PdfA = PdfAConformanceLevel.PdfA4f; // PDF/A-4 requires the "revision" year of the ISO 19005-4:2020 standard itself (not the document's date): doc.Metadata.PdfRev = "2020";
var fnt = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf")); var gap = 36;
// PDF/A-4 requires all content to be tagged, so create and populate StructElements when rendering: var sePart = new StructElement("Part"); doc.StructTreeRoot.Children.Add(sePart);
TextLayout tl = null; // Add 3 pages with sample content tagged according to PDF/A rules: for (int pageNo = 1; pageNo <= 3; ++pageNo) { var page = doc.Pages.Add(); var g = page.Graphics; float y = 72; if (doc.Pages.Count == 1) { // Create paragraph element and add it to the Part element: var seParagraph = new StructElement("P") { DefaultPage = page }; sePart.Children.Add(seParagraph);
tl = g.CreateTextLayout(); tl.MarginAll = 72; tl.MaxWidth = page.Size.Width;
tl.DefaultFormat.Font = fnt; tl.DefaultFormat.FontBold = true; tl.DefaultFormat.FontSize = 20; tl.Append("PDF/A-4 Document");
// Draw the TextLayout within tagged content: g.BeginMarkedContent(new TagMcid("P", 0)); g.DrawTextLayout(tl, PointF.Empty); g.EndMarkedContent();
y = tl.ContentRectangle.Bottom + gap;
seParagraph.ContentItems.Add(new McidContentItemLink(0)); }
// Add some sample paragraphs tagged according to PDF/A rules: for (int i = 1; i <= 3; ++i) { var seParagraph = new StructElement("P") { DefaultPage = page }; sePart.Children.Add(seParagraph);
var sb = new StringBuilder(); sb.Append($"Paragraph {i} on page {pageNo}. "); sb.Append(Common.Util.LoremIpsum(1, 2, 4, 5, 10)); var para = sb.ToString();
tl.Clear(); tl.DefaultFormat.FontSize = 14; tl.DefaultFormat.FontBold = false; tl.MarginTop = y; tl.Append(para);
g.BeginMarkedContent(new TagMcid("P", i)); g.DrawTextLayout(tl, PointF.Empty); g.EndMarkedContent();
y += tl.ContentHeight + gap;
seParagraph.ContentItems.Add(new McidContentItemLink(i)); } }
// PDF/A-4 allows transparency drawing in the PDF file, add some: var gpage = doc.Pages[0].Graphics; gpage.FillRectangle(new RectangleF(20, 20, 200, 200), Color.FromArgb(40, Color.Red));
// PDF/A-4 allows using FormXObjects, add one with transparency: var r = new RectangleF(0, 0, 144, 72); var fxo = new FormXObject(doc, r); var gfxo = fxo.Graphics; gfxo.FillRectangle(r, Color.FromArgb(40, Color.Violet)); var tf = new TextFormat() { Font = fnt, FontSize = 16, ForeColor = Color.FromArgb(100, Color.Black), }; gfxo.DrawString("FormXObject", tf, r, TextAlignment.Center, ParagraphAlignment.Center); gfxo.DrawRectangle(r, Color.Blue, 3); gpage.DrawForm(fxo, new RectangleF(300, 250, r.Width, r.Height), null, ImageAlign.ScaleImage);
// PDF/A-4f allows embedding arbitrary files, but each one must be associated with a document element: var ef = EmbeddedFileStream.FromFile(doc, Path.Combine("Resources", "WordDocs", "ProcurementLetter.docx")); // ModificationDate and MimeType should be specified for EmbeddedFile in PDF/A: ef.ModificationDate = date; ef.MimeType = "application/msword"; var fs = FileSpecification.FromEmbeddedFile(ef); fs.UnicodeFile.FileName = fs.File.FileName; fs.Relationship = AFRelationship.Unspecified; doc.EmbeddedFiles.Add("ProcurementLetter.docx", fs); // Associate embedded file with the document: doc.AssociatedFiles.Add(fs);
// Add a stamp annotation with an attachment of its own. // Note: RichMediaAnnotation is only allowed under PDF/A-4e, so a StampAnnotation is used here instead: var sa = new StampAnnotation() { UserName = "User", Font = fnt, Rect = new RectangleF(300, 36, 220, 72), }; // The Print flag must be set, as required by the PDF/A specification: sa.Flags |= AnnotationFlags.Print; // Use a FormXObject to represent the stamp annotation: var stampFxo = new FormXObject(doc, new RectangleF(PointF.Empty, sa.Rect.Size)); var gstampFxo = stampFxo.Graphics; gstampFxo.FillRectangle(stampFxo.Bounds, Color.FromArgb(40, Color.Green)); gstampFxo.DrawString("Stamp", tf, stampFxo.Bounds, TextAlignment.Center, ParagraphAlignment.Center); gstampFxo.DrawRectangle(stampFxo.Bounds, Color.Green, 3); sa.AppearanceStreams.Normal.Default = stampFxo; doc.Pages[0].Annotations.Add(sa); ef = EmbeddedFileStream.FromFile(doc, Path.Combine("Resources", "Images", "minerva.jpg")); ef.ModificationDate = date; ef.MimeType = "image/jpeg"; fs = FileSpecification.FromEmbeddedFile(ef); fs.UnicodeFile.FileName = fs.File.FileName; fs.Relationship = AFRelationship.Unspecified; doc.EmbeddedFiles.Add("minerva.jpg", fs); sa.AssociatedFiles.Add(fs);
// Mark the document as conforming to Tagged PDF conventions (required for PDF/A): doc.MarkInfo.Marked = true;
// Metadata.CreatorTool and DocumentInfo.Creator should be the same for a PDF/A document: doc.Metadata.CreatorTool = doc.DocumentInfo.Creator; // A title should be specified for a PDF/A document: doc.Metadata.Title = "PDF/A-4 compliant document"; doc.ViewerPreferences.DisplayDocTitle = true;
// PDF/A-4 does not allow a legacy DocumentInfo dictionary, so it must be removed // (do this last, since DocumentInfo.Creator was used above): doc.DocumentInfo = null;
doc.Save(stream); return doc.Pages.Count; } }}