PDF/UA (Universal Accessibility)
DynamicPDF Core Suite for .NET can create PDF/UA compatible PDF documents. The goal of the PDF/UA standard is to allow universally accessible information contained within a PDF document. Accessible PDF documents must meet specific technical criteria that allow them to be used by people with disabilities. The PDF/UA standard addresses these needs by ensuring PDF documents are accessible to all.
Rules to Follow for PDF/UA
Creating a PDF/UA compliant document requires that:
- PDF content must be e-tagged,
- tags added in logical reading order,
- the document must have a title in metadata,
- the document must have a title displayable in the PDF reader displaying the PDF,
- JavaScript must be accessible,
- security settings must not prevent accessibility,
- fonts must be embedded in the PDF document, and
- non-text contents must have alternate text.
You can verify your PDF document is accessible by testing it in veraPDF, and open source industry supported PDF/A validation tool maintained by the Open Preservation Foundation (www.verpdf.org).
Example
The example below uses several concepts to create a PDF/UA compatible document, including structuring and adding tags, fonts, and XMP metadata. It uses the StructureElement class combined with the AttributeObject class to create a PDF/UA compliant PDF. It adds the relevant TagOptions to a Document instances Tag property. Adds the document's font as an OpentTypeFont. And then adds XMPMetadata.
The following example illustrates creating a PDF/UA compatible document.
// Create a PDF Document
Document document = new Document();
// Set the TagOptions to document
document.Tag = new TagOptions();
// Create StructureElement objects and set Order etc.
StructureElement structureDocument = new StructureElement(TagType.Document);
StructureElement structureHeading = new StructureElement(TagType.Heading);
StructureElement structureForm = new StructureElement(TagType.Form);
structureForm.Order = 2;
structureHeading.Parent = structureDocument;
structureForm.Parent = structureDocument;
// Create AttributeObject objects with tag order and parents.
AttributeObject attrObjLayout = new AttributeObject(AttributeOwner.Layout);
attrObjLayout.SetPlacement(Placement.Block);
structureForm.AttributeLists.Add(attrObjLayout);
StructureElement structureForm2 = new StructureElement(TagType.Form);
structureForm2.Order = 4;
structureForm2.Parent = structureDocument;
structureForm2.AttributeLists.Add(attrObjLayout);
StructureElement structureParagraph = new StructureElement(TagType.Paragraph);
structureParagraph.Order = 1;
structureParagraph.Parent = structureDocument;
StructureElement element5 = new StructureElement(TagType.Paragraph);
element5.Parent = structureDocument;
element5.Order = 3;
// Set Document Language
document.Language = "en-us";
document.ViewerPreferences.DisplayDocTitle = true;
// Create a Page
Page page = new Page();
// Create a Label and set Tag
ceTe.DynamicPDF.PageElements.Label lblEnterName = new ceTe.DynamicPDF.PageElements.Label("Name : ", 0, 100, 100, 50);
lblEnterName.Tag = structureParagraph;
ceTe.DynamicPDF.PageElements.Label lblAge = new ceTe.DynamicPDF.PageElements.Label("Age : ", 0, 200, 100, 50);
lblAge.Tag = element5;
// Create a TextField and set Tag
ceTe.DynamicPDF.PageElements.Forms.TextField txtField1 = new ceTe.DynamicPDF.PageElements.Forms.TextField("txtFieldName", 100, 100, 100, 50);
ceTe.DynamicPDF.PageElements.Forms.TextField txtField2 = new ceTe.DynamicPDF.PageElements.Forms.TextField("txtFieldName", 100, 200, 100, 50);
txtField1.Tag = structureForm;
txtField2.Tag = structureForm2;
// Create an OpenTypeFont object with Embed option and ToolTip
OpenTypeFont font = new OpenTypeFont("times.ttf");
font.Embed = true;
font.Subset = false;
lblEnterName.Font = font;
lblAge.Font = font;
txtField1.Font = font;
txtField1.ToolTip = "Name";
txtField2.Font = font;
txtField2.ToolTip = "age";
// Add the Elements to the Page
page.Elements.Add(lblEnterName);
page.Elements.Add(txtField1);
page.Elements.Add(lblAge);
page.Elements.Add(txtField2);
// Add Page to the Document
document.Pages.Add(page);
// Create an Xmp Metadata
XmpMetadata xmp = new XmpMetadata();
// Create a PdfUASchema and add to XMP matadata
PdfUASchema customSchema = new PdfUASchema();
xmp.AddSchema(customSchema);
// Create DublinCoreSchema and set properties
DublinCoreSchema dc = xmp.DublinCore;
dc.Title.AddLang("en-us", "XMP");
dc.Title.DefaultText = "Title Text";
// Adding the XmpMatadata to the document
document.XmpMetadata = xmp;
// Save the PDF
document.Draw(outputPath);
' Create a PDF Document
Dim MyDocument As Document = New Document
' Set the TagOptions to document
MyDocument.Tag = New TagOptions
' Create StructureElement objects and set Order etc.
Dim structureDocument As StructureElement = New StructureElement(TagType.Document)
Dim structureHeading As StructureElement = New StructureElement(TagType.Heading)
Dim structureForm As StructureElement = New StructureElement(TagType.Form)
structureForm.Order = 2
structureHeading.Parent = structureDocument
structureForm.Parent = structureDocument
' Create AttributeObject objects with tag order and parents.
Dim attrObjLayout As AttributeObject = New AttributeObject(AttributeOwner.Layout)
attrObjLayout.SetPlacement(Placement.Block)
structureForm.AttributeLists.Add(attrObjLayout)
Dim structureForm2 As StructureElement = New StructureElement(TagType.Form)
structureForm2.Order = 4
structureForm2.Parent = structureDocument
structureForm2.AttributeLists.Add(attrObjLayout)
Dim structureParagraph As StructureElement = New StructureElement(TagType.Paragraph)
structureParagraph.Order = 1
structureParagraph.Parent = structureDocument
Dim structureParagraph2 As StructureElement = New StructureElement(TagType.Paragraph)
structureParagraph2.Parent = structureDocument
structureParagraph2.Order = 3
' Set Document Language
MyDocument.Language = "en-us"
MyDocument.ViewerPreferences.DisplayDocTitle = True
' Create a Page
Dim MyPage As Page = New Page
' Create a Label and set Tag
Dim lblEnterName As ceTe.DynamicPDF.PageElements.Label = New ceTe.DynamicPDF.PageElements.Label("Name : ", 0, 100, 100, 50)
lblEnterName.Tag = structureParagraph
Dim lblAge As ceTe.DynamicPDF.PageElements.Label = New ceTe.DynamicPDF.PageElements.Label("Age : ", 0, 200, 100, 50)
lblAge.Tag = structureParagraph2
' Create a TextField and set Tag
Dim txtField1 As ceTe.DynamicPDF.PageElements.Forms.TextField = New ceTe.DynamicPDF.PageElements.Forms.TextField("txtFieldName1", 100, 100, 100, 50)
Dim txtField2 As ceTe.DynamicPDF.PageElements.Forms.TextField = New ceTe.DynamicPDF.PageElements.Forms.TextField("txtFieldName2", 100, 200, 100, 50)
txtField1.Tag = structureForm
txtField2.Tag = structureForm2
' Create an OpenTypeFont object with Embed option and ToolTip
Dim font As OpenTypeFont = New OpenTypeFont("times.ttf")
font.Embed = True
font.Subset = False
lblEnterName.Font = font
lblAge.Font = font
txtField1.Font = font
txtField1.ToolTip = "Name"
txtField2.Font = font
txtField2.ToolTip = "age"
' Add the Elements to the Page
MyPage.Elements.Add(lblEnterName)
MyPage.Elements.Add(txtField1)
MyPage.Elements.Add(lblAge)
MyPage.Elements.Add(txtField2)
' Add Page to the Document
MyDocument.Pages.Add(MyPage)
' Create an Xmp Metadata
Dim Xmp As XmpMetadata = New XmpMetadata()
' Create a PdfUASchema and add to XMP matadata
Dim customSchema As PdfUASchema = New PdfUASchema()
Xmp.AddSchema(customSchema)
' Create DublinCoreSchema and set properties
Dim dublinCoreSchema As DublinCoreSchema = Xmp.DublinCore
dublinCoreSchema.Title.AddLang("en-us", "XMP")
dublinCoreSchema.Title.DefaultText = "Title Text"
' Adding the XmpMatadata to the document
MyDocument.XmpMetadata = Xmp
' Save the PDF
MyDocument.Draw(outputPath)
Figure 1. PDF/UA accessible PDF document.