PdfA4.vb
''
'' This code is part of Document Solutions for PDF .NET demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports System.Text
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Common
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.Structure
Imports GrapeCity.Documents.Pdf.MarkedContent
Imports GrapeCity.Documents.Pdf.Graphics
Imports GrapeCity.Documents.Pdf.Annotations
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This sample shows how to create a PDF/A-4f compliant document.
Public Class PdfA4
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim thedate = 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"

        Dim fnt = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf"))
        Dim gap = 36

        '' PDF/A-4 requires all content to be tagged, so create and populate StructElements when rendering:
        Dim sePart = New StructElement("Part")
        doc.StructTreeRoot.Children.Add(sePart)

        Dim tl As TextLayout = Nothing
        '' Add 3 pages with sample content tagged according to PDF/A rules:
        For pageNo = 1 To 3
            Dim page = doc.Pages.Add()
            Dim g = page.Graphics
            Dim y = 72.0F
            If doc.Pages.Count = 1 Then
                '' Create paragraph element and add it to the Part element:
                Dim seParagraph = New StructElement("P") With {.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))
            End If

            '' Add some sample paragraphs tagged according to PDF/A rules:
            For i = 1 To 3
                Dim seParagraph = New StructElement("P") With {.DefaultPage = page}
                sePart.Children.Add(seParagraph)

                Dim sb = New StringBuilder()
                sb.Append($"Paragraph {i} on page {pageNo}. ")
                sb.Append(Util.LoremIpsum(1, 2, 4, 5, 10))
                Dim 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))
            Next
        Next

        '' PDF/A-4 allows transparency drawing in the PDF file, add some:
        Dim 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:
        Dim r = New RectangleF(0, 0, 144, 72)
        Dim fxo = New FormXObject(doc, r)
        Dim gfxo = fxo.Graphics
        gfxo.FillRectangle(r, Color.FromArgb(40, Color.Violet))
        Dim tf = New TextFormat() With
            {
                .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), Nothing, ImageAlign.ScaleImage)

        '' PDF/A-4f allows embedding arbitrary files, but each one must be associated with a document element:
        Dim ef = EmbeddedFileStream.FromFile(doc, Path.Combine("Resources", "WordDocs", "ProcurementLetter.docx"))
        '' ModificationDate and MimeType should be specified for EmbeddedFile in PDF/A:
        ef.ModificationDate = thedate
        ef.MimeType = "application/msword"
        Dim 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:
        Dim sa = New StampAnnotation() With
            {
                .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 = sa.Flags Or AnnotationFlags.Print
        '' Use a FormXObject to represent the stamp annotation:
        Dim stampFxo = New FormXObject(doc, New RectangleF(PointF.Empty, sa.Rect.Size))
        Dim 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 = thedate
        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 = Nothing

        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class