Available for: UI for ASP.NET MVC | UI for ASP.NET AJAX | UI for Blazor | UI for WPF | UI for WinForms | UI for Silverlight | UI for Xamarin | UI for WinUI | UI for ASP.NET Core | UI for .NET MAUI

New to Telerik Document Processing? Download free 30-day trial

Tagged PDF Q3 2025 (or newer)

Related Feature: Accessibility Support

RadPdfProcessing provides support for a Tagged PDF. It is a stylized use of PDF which defines a set of standard structure types and attributes that allow page content (text, graphics, and images) to be extracted and reused for other purposes. It is intended to be used by tools that perform operations like:

  • Making content accessible to users with visual impairments
  • Simple extraction of text and graphics
  • Automatic reflow of text and associated graphics to fit a page of a different size than was assumed for the original layout
  • Processing text for such purposes as searching, indexing, and spell-checking
  • Conversion to other common file formats with document structure and basic styling information preserved

Tagging Strategy

Represents the strategy for handling tagging in PDF documents. The available options are:

In .NET Standard/.NET (Target OS: None) environments, fonts beyond the 14 standard ones require a FontsProvider implementation to be resolved correctly.

  • UseExisting - Specifies whether the document should not be tagged on export automatically and the existing StructureTree will be used. The default option.

  • Build - Specifies whether the document should be automatically tagged on export and a new StructureTree should be created.

Tagging Document Elements

The following sections demonstrate how to tag the different elements of a RadFixedDocument:

Tagging a TextFragment

RadFixedDocument fixedDocument = new RadFixedDocument();
fixedDocument.DocumentInfo.Title = "Test PDF Document";
fixedDocument.ViewerPreferences.ShouldDisplayDocumentTitle = true;
byte[] textFile =  File.ReadAllBytes(@"Pdf Files\PdfA2A.pdf");  
fixedDocument.EmbeddedFiles.Add("PdfA2A.pdf", textFile); 
// Important: To comply with PDF/A or PDF/UA the attached file must be PDF/A compliant as well

RadFixedPage firstPage = fixedDocument.Pages.AddPage();

MarkedContent paragraphContainer1 = firstPage.Content.AddMarkedContent();
Telerik.Windows.Documents.Fixed.Model.Text.TextFragment textFragment1 = paragraphContainer1.Content.AddTextFragment("Text fragment 1");
FontsRepository.TryCreateFont(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, out FontBase arialFont);
textFragment1.Font = arialFont;
textFragment1.Position.Translate(20, 20);

MarkedContent paragraphContainer2 = firstPage.Content.AddMarkedContent();
Telerik.Windows.Documents.Fixed.Model.Text.TextFragment textFragment2 = paragraphContainer2.Content.AddTextFragment("Fragmento de texto 2");
textFragment2.Font = arialFont;
textFragment2.Position.Translate(20, 100);

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement paragraphElement1 = sectionElement.ChildElements.AddStructureElement("CustomParagraph", StructureTagType.Paragraph);
StructureElement paragraphElement2 = sectionElement.ChildElements.AddStructureElement(StructureTagType.Paragraph);
paragraphContainer1.StructureTag = paragraphElement1;
paragraphElement1.AlternateDescription = "Standard Paragraph in English";
paragraphContainer2.StructureTag = paragraphElement2;
paragraphElement2.Language = "ES";
paragraphElement2.AlternateDescription = "Custom Paragraph in Spanish";

Tagging an Annotation

RadFixedDocument fixedDocument = new RadFixedDocument();
RadFixedPage firstPage = fixedDocument.Pages.AddPage();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement paragraphElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Paragraph);

TextAnnotation annotation = firstPage.Annotations.AddText(new Rect(200, 100, 200, 200));
annotation.Contents = "This is a TextAnnotation";
annotation.Opacity = 0.5;
annotation.Color = new RgbColor(255, 0, 0);
StructureElement annotStruct = paragraphElement.ChildElements.AddStructureElement(StructureTagType.Annotation);
annotation.StructureTag = annotStruct;
RadFixedDocument fixedDocument = new RadFixedDocument();
StructureElement documentStructureElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionStructureElement = documentStructureElement.ChildElements.AddStructureElement(StructureTagType.Section);
FixedContentEditor editor = new FixedContentEditor(fixedDocument.Pages.AddPage());
Block block = new Block();

using (block.SaveTextProperties())
{
    block.GraphicProperties.FillColor = new RgbColor(255, 5, 99, 193);
    string text = " Getting Started with RadPdfProcessing ";
    StructureElement paragraphStructureElement = sectionStructureElement.ChildElements.AddStructureElement(StructureTagType.Paragraph);
    StructureElement linkStructureElement = paragraphStructureElement.ChildElements.AddStructureElement(StructureTagType.Link);
    block.InsertMarkedContentStart(linkStructureElement);
    block.InsertHyperlinkStart(new Uri("https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/getting-started"));
    block.InsertText(text);
    block.InsertHyperlinkEnd();
    block.InsertMarkedContentEnd(); 
}

Tagging a Table

RadFixedDocument fixedDocument = new RadFixedDocument();
RadFixedPage firstPage = fixedDocument.Pages.AddPage();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement tableElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Table);

Telerik.Windows.Documents.Fixed.Model.Editing.Tables.Table table = new Telerik.Windows.Documents.Fixed.Model.Editing.Tables.Table();
table.StructureTag = tableElement;
Border redBorder = new Border(2, new RgbColor(255, 0, 0));
table.DefaultCellProperties.Borders = new Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableCellBorders(redBorder);
table.DefaultCellProperties.Padding = new Thickness(20, 10, 20, 10);
table.DefaultCellProperties.Background = new RgbColor(0, 255, 0);

Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableRow firstRow = table.Rows.AddTableRow();
firstRow.Cells.AddTableCell().Blocks.AddBlock().InsertText("First cell");

Telerik.Windows.Documents.Fixed.Model.Editing.Tables.TableRow secondRow = table.Rows.AddTableRow();
secondRow.Cells.AddTableCell().Blocks.AddBlock().InsertText("Second cell");

FixedContentEditor editor = new FixedContentEditor(firstPage);

editor.Position.Translate(10, 200);
editor.DrawTable(table);

Tagging a List

RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement listElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.List);

using (RadFixedDocumentEditor editor = new RadFixedDocumentEditor(fixedDocument))
{
    List list = editor.Lists.AddList(ListTemplateType.NumberedDefault);
    list.StructureTag = listElement;
    editor.ParagraphProperties.ListId = list.Id;

    for (int listLevel = 0; listLevel < list.Levels.Count; listLevel++)
    {
        editor.ParagraphProperties.ListLevel = listLevel;
        editor.InsertParagraph();
        editor.InsertRun(string.Format("List level {0}", listLevel));
    }
}

Advanced Example

RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement figureElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Figure);
StructureElement paragraphElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Paragraph);
StructureElement paragraph2Element = sectionElement.ChildElements.AddStructureElement(StructureTagType.Paragraph);
StructureElement multipleFigureElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Figure);

RadFixedPage page = new RadFixedPage();
fixedDocument.Pages.Add(page);
FixedContentEditor pageEditor = new FixedContentEditor(page);

// Artifact for background
pageEditor.InsertMarkedContentStart();
pageEditor.SaveGraphicProperties();
pageEditor.GraphicProperties.FillColor = new RgbColor(250, 250, 250);
pageEditor.DrawRectangle(new Rect(0, 0, 500, 1000));
pageEditor.RestoreGraphicProperties();
pageEditor.InsertMarkedContentEnd();

// Structured content until the end
figureElement.AlternateDescription = "Image";
pageEditor.InsertMarkedContentStart(figureElement);
pageEditor.DrawImage(new FileStream(@"image.jpg", FileMode.Open), new Size(118, 28));
pageEditor.InsertMarkedContentEnd();

pageEditor.Position.Translate(0, 40);
paragraphElement.AlternateDescription = "Paragraph with text";
pageEditor.InsertMarkedContentStart(paragraphElement);
pageEditor.DrawText("First text fragment.", new Size(300, 10));
pageEditor.InsertMarkedContentEnd();

MarkedContent markedContent = new MarkedContent();
paragraph2Element.AlternateDescription = "Paragraph with text";
markedContent.StructureTag = paragraph2Element;
TextFragment secondTextFragment = markedContent.Content.AddTextFragment("Second text Fragment");
pageEditor.Position.Translate(0, 70);
pageEditor.Draw(markedContent);

pageEditor.Position.Translate(0, 90);
multipleFigureElement.AlternateDescription = "Multiple figures";
pageEditor.InsertMarkedContentStart(multipleFigureElement);
pageEditor.DrawCircle(new Point(10, 10), 10);
pageEditor.Position.Translate(0, 120);
pageEditor.DrawRectangle(new Rect(0, 0, 100, 50));
pageEditor.Position.Translate(0, 210);
pageEditor.DrawLine(new Point(0, 0), new Point(100, 100));
pageEditor.InsertMarkedContentEnd();

Auto-Tagging

RadFixedDocument fixedDocument = new RadFixedDocument(autoTag: true);
fixedDocument.Language = "en-Us";

RadFixedPage page = new RadFixedPage();
fixedDocument.Pages.Add(page);
FixedContentEditor pageEditor = new FixedContentEditor(page, autoTag: true);

// Artifact for background
pageEditor.SaveGraphicProperties();
pageEditor.GraphicProperties.FillColor = new RgbColor(250, 250, 250);
pageEditor.DrawRectangle(new Rect(0, 0, 500, 1000));
pageEditor.RestoreGraphicProperties();

// Structured content until the end
pageEditor.DrawImage(new FileStream(@"profile_pic_cropped.jpg", FileMode.Open), new Size(118, 28));

pageEditor.Position.Translate(0, 40);
pageEditor.DrawText("First text fragment.", new Size(300, 10));

MarkedContent markedContent = new MarkedContent();
TextFragment secondTextFragment = markedContent.Content.AddTextFragment("Second text Fragment");
pageEditor.Position.Translate(0, 70);
pageEditor.Draw(markedContent);

pageEditor.Position.Translate(0, 90);
pageEditor.DrawCircle(new Point(10, 10), 10);
pageEditor.Position.Translate(0, 120);
pageEditor.DrawRectangle(new Rect(0, 0, 100, 50));
pageEditor.Position.Translate(0, 210);
pageEditor.DrawLine(new Point(0, 0), new Point(100, 100));

Tagging a Form Field

RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement formElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Form);

RadFixedPage page = fixedDocument.Pages.AddPage();

TextBoxField textField = new TextBoxField("SampleTextBox")
{
    MaxLengthOfInputCharacters = 500,
    IsMultiline = true,
    IsPassword = false,
    IsFileSelect = false,
    ShouldSpellCheck = true,
    AllowScroll = true,
    Value = "Sample content",
    // Required for Accessibility
    UserInterfaceName = "SampleTextBox Alternate name"
};

textField.StructureTag = formElement;
fixedDocument.AcroForm.FormFields.Add(textField);

VariableContentWidget widget1 = textField.Widgets.AddWidget();
widget1.Rect = new Rect(0, 0, 250, 50);
widget1.RecalculateContent();

VariableContentWidget widget2 = textField.Widgets.AddWidget();
widget2.Rect = new Rect(0, 200, 100, 100);
widget2.RecalculateContent();

page.Annotations.Add(widget1);
page.Annotations.Add(widget2);

Tagging a FormField using FixedContentEditor

RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement formElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Form);

RadFixedPage page = new RadFixedPage();
fixedDocument.Pages.Add(page);
FixedContentEditor pageEditor = new FixedContentEditor(page, autoTag: true);

PushButtonField pushButton = new PushButtonField("button");
pushButton.StructureTag = formElement;
fixedDocument.AcroForm.FormFields.Add(pushButton);

pageEditor.Position.Translate(20, 450);
pageEditor.DrawWidget(pushButton, new Size(100, 20));

Auto-Tagging a FormField using FixedContentEditor

RadFixedDocument fixedDocument = new RadFixedDocument(autoTag: true);

RadFixedPage page = new RadFixedPage();
fixedDocument.Pages.Add(page);
FixedContentEditor pageEditor = new FixedContentEditor(page, autoTag: true);

PushButtonField pushButton = new PushButtonField("button");
fixedDocument.AcroForm.FormFields.Add(pushButton);

pageEditor.Position.Translate(20, 450);
pageEditor.DrawWidget(pushButton, new Size(100, 20));

Tagging a Form

RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement figure1Element = sectionElement.ChildElements.AddStructureElement(StructureTagType.Figure);
figure1Element.AlternateDescription = "This is a figure 1."; // Required for Accessibility
StructureElement figure2Element = sectionElement.ChildElements.AddStructureElement(StructureTagType.Figure);
figure2Element.AlternateDescription = "This is a figure 2."; // Required for Accessibility
StructureElement figure3Element = sectionElement.ChildElements.AddStructureElement(StructureTagType.Figure);
figure2Element.AlternateDescription = "This is a figure 3."; // Required for Accessibility

RadFixedPage page = fixedDocument.Pages.AddPage();

FormSource formSource = new FormSource();
formSource.Size = new Size(200, 200);
MarkedContent markedContent = page.Content.AddMarkedContent(figure1Element); // Associate the marked content with the structure element
markedContent.Content.AddForm(formSource);

PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = pathGeometry.Figures.AddPathFigure();
pathFigure.StartPoint = new Point(5, 5);
LineSegment lineSegment = pathFigure.Segments.AddLineSegment();
lineSegment.Point = new Point(205, 5);
BezierSegment bezierSegment = pathFigure.Segments.AddBezierSegment();
bezierSegment.Point1 = new Point(105, 50);
bezierSegment.Point2 = new Point(130, 105);
bezierSegment.Point3 = new Point(100, 200);
pathFigure.IsClosed = true;

FixedContentEditor formEditor = new FixedContentEditor(formSource);
formEditor.DrawPath(pathGeometry);

FixedContentEditor pageEditor = new FixedContentEditor(page);
pageEditor.Position.Translate(0, 200);
pageEditor.InsertMarkedContentStart(figure2Element);
pageEditor.DrawForm(formSource);
pageEditor.InsertMarkedContentEnd();

pageEditor.Position.Translate(0, 400);
pageEditor.InsertMarkedContentStart(figure3Element);
Form form = new Form() { FormSource = formSource };
pageEditor.Draw(form);
pageEditor.InsertMarkedContentEnd();

Auto-Tagging a Form

RadFixedDocument fixedDocument = new RadFixedDocument(autoTag: true);

RadFixedPage page = fixedDocument.Pages.AddPage();

FormSource formSource = new FormSource();
formSource.Size = new Size(200, 200);

PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = pathGeometry.Figures.AddPathFigure();
pathFigure.StartPoint = new Point(5, 5);
LineSegment lineSegment = pathFigure.Segments.AddLineSegment();
lineSegment.Point = new Point(205, 5);
BezierSegment bezierSegment = pathFigure.Segments.AddBezierSegment();
bezierSegment.Point1 = new Point(105, 50);
bezierSegment.Point2 = new Point(130, 105);
bezierSegment.Point3 = new Point(100, 200);
pathFigure.IsClosed = true;

FixedContentEditor formEditor = new FixedContentEditor(formSource, autoTag: true);
formEditor.DrawPath(pathGeometry);

FixedContentEditor pageEditor = new FixedContentEditor(page, autoTag: true);
pageEditor.Position.Translate(0, 200);
pageEditor.DrawForm(formSource);

pageEditor.Position.Translate(0, 400);
Form form = new Form() { FormSource = formSource };
pageEditor.Draw(form);
RadFixedDocument fixedDocument = new RadFixedDocument();

StructureElement documentElement = fixedDocument.StructureTree.ChildElements.AddStructureElement(StructureTagType.Document);
StructureElement sectionElement = documentElement.ChildElements.AddStructureElement(StructureTagType.Section);
StructureElement linkElement = sectionElement.ChildElements.AddStructureElement(StructureTagType.Link);

RadFixedPage firstPage = fixedDocument.Pages.AddPage();
Location location = new Location();
location.Left = 225;
location.Top = 500;
location.Zoom = 4;
location.Page = firstPage;

Link link = firstPage.Annotations.AddLink(location);
link.Rect = new Rect(10, 10, 50, 50);

link.StructureTag = linkElement;

See Also

In this article