Docotic.Pdf Library Help > Samples > Pages and Navigation > Copy text, paths and images

This sample shows how to copy page objects (text, paths and images) to a new document.

Use PdfDocument.CopyPage method to copy full page content and associated resources (fonts, images) to a new document. Then use PdfPage.GetObjects() method to get all text, paths and images drawn on the page. Copy required objects to a new page. At the end, remove original page from the result document.

Copying of page objects is useful when you want to remove or replace some content (e.g. text) from the page.

C#
using System;
using System.Diagnostics;

using BitMiracle.Docotic.Pdf;

namespace BitMiracle.Docotic.Pdf.Samples
{
    public static class CopyPageObjects
    {
        public static void Main()
        {
            // NOTE: 
            // When used in trial mode, the library imposes some restrictions.
            // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            // for more information.

            const string PathToFile = "CopyPageObjects.pdf";

            using (var pdf = new PdfDocument(@"Sample Data/BRAILLE CODES WITH TRANSLATION.pdf"))
            {
                using (PdfDocument copy = pdf.CopyPages(0, 1))
                {
                    PdfPage sourcePage = copy.Pages[0];
                    PdfPage copyPage = copy.AddPage();

                    copyPage.Rotation = sourcePage.Rotation;
                    copyPage.MediaBox = sourcePage.MediaBox;
                    if (sourcePage.CropBox != sourcePage.MediaBox)
                        copyPage.CropBox = sourcePage.CropBox;

                    PdfFont universalFont = copy.AddFont("Arial");

                    PdfCanvas target = copyPage.Canvas;
                    foreach (PdfPageObject obj in sourcePage.GetObjects())
                    {
                        target.SaveState();
                        setClipRegion(target, obj.ClipRegion);

                        if (obj.Type == PdfPageObjectType.Path)
                        {
                            PdfPath path = (PdfPath)obj;
                            target.Transform(path.TransformationMatrix);
                            setBrushAndPen(target, path);

                            appendPath(target, path);
                            drawPath(target, path);
                        }
                        else if (obj.Type == PdfPageObjectType.Image)
                        {
                            PdfPaintedImage image = (PdfPaintedImage)obj;
                            target.TranslateTransform(image.Position.X, image.Position.Y);
                            target.Transform(image.TransformationMatrix);

                            target.Brush.Color = new PdfRgbColor(255, 255, 255);
                            target.DrawImage(image.Image, 0, 0, 0);
                        }
                        else if (obj.Type == PdfPageObjectType.Text)
                        {
                            PdfTextData text = (PdfTextData)obj;
                            drawText(target, text, universalFont, copy);
                        }

                        target.RestoreState();
                    }

                    foreach (PdfFont font in copy.Fonts)
                        font.RemoveUnusedGlyphs();

                    copy.RemovePage(0);

                    copy.Save(PathToFile);
                }
            }

            Process.Start(PathToFile);
        }

        private static void setClipRegion(PdfCanvas canvas, PdfClipRegion clipRegion)
        {
            if (clipRegion.IntersectedPaths.Count == 0)
                return;

            PdfMatrix transformationBefore = canvas.TransformationMatrix;
            try
            {
                foreach (PdfPath clipPath in clipRegion.IntersectedPaths)
                {
                    canvas.ResetTransform();
                    canvas.Transform(clipPath.TransformationMatrix);
                    appendPath(canvas, clipPath);
                    canvas.SetClip(clipPath.ClipMode.Value);
                }
            }
            finally
            {
                canvas.ResetTransform();
                canvas.Transform(transformationBefore);
            }
        }

        private static void setBrushAndPen(PdfCanvas target, PdfPath path)
        {
            if (path.PaintMode == PdfDrawMode.Fill || path.PaintMode == PdfDrawMode.FillAndStroke)
            {
                target.Brush.Opacity = path.Brush.Opacity;

                PdfColor color = path.Brush.Color;
                if (color != null)
                    target.Brush.Color = path.Brush.Color;
            }

            if (path.PaintMode == PdfDrawMode.Stroke || path.PaintMode == PdfDrawMode.FillAndStroke)
            {
                target.Pen.Opacity = path.Pen.Opacity;

                PdfColor color = path.Pen.Color;
                if (color != null)
                    target.Pen.Color = path.Pen.Color;
            }
        }

        private static void appendPath(PdfCanvas target, PdfPath path)
        {
            foreach (PdfSubpath subpath in path.Subpaths)
            {
                foreach (PdfPathSegment segment in subpath.Segments)
                {
                    switch (segment.Type)
                    {
                        case PdfPathSegmentType.Point:
                            target.CurrentPosition = ((PdfPointSegment)segment).Value;
                            break;

                        case PdfPathSegmentType.Line:
                            PdfLineSegment line = (PdfLineSegment)segment;
                            target.CurrentPosition = line.Start;
                            target.AppendLineTo(line.End);
                            break;

                        case PdfPathSegmentType.Bezier:
                            PdfBezierSegment bezier = (PdfBezierSegment)segment;
                            target.CurrentPosition = bezier.Start;
                            target.AppendCurveTo(bezier.FirstControl, bezier.SecondControl, bezier.End);
                            break;

                        case PdfPathSegmentType.Rectangle:
                            target.AppendRectangle(((PdfRectangleSegment)segment).Bounds);
                            break;

                        case PdfPathSegmentType.CloseSubpath:
                            target.ClosePath();
                            break;
                    }
                }
            }
        }

        private static void drawPath(PdfCanvas target, PdfPath path)
        {
            switch (path.PaintMode)
            {
                case PdfDrawMode.Fill:
                    target.FillPath(path.FillMode.Value);
                    break;

                case PdfDrawMode.FillAndStroke:
                    target.FillAndStrokePath(path.FillMode.Value);
                    break;

                case PdfDrawMode.Stroke:
                    target.StrokePath();
                    break;

                default:
                    target.ResetPath();
                    break;
            }
        }

        private static void drawText(PdfCanvas target, PdfTextData td, PdfFont fallback, PdfDocument pdf)
        {
            target.TextRenderingMode = td.RenderingMode;
            target.Brush.Color = td.Brush.Color;
            target.Brush.Opacity = td.Brush.Opacity;

            target.Pen.Color = td.Pen.Color;
            target.Pen.Opacity = td.Pen.Opacity;
            target.Pen.Width = td.Pen.Width;

            target.TextPosition = PdfPoint.Empty;
            target.FontSize = td.FontSize;
            target.Font = td.Font;
            target.TranslateTransform(td.Position.X, td.Position.Y);
            target.Transform(td.TransformationMatrix);

            // Currently, Docotic.Pdf does not completely support drawing of 
            // text with all types of fonts existing in PDF documents. Let's use
            // some system font as a workaround in such cases.
            try
            {
                target.DrawString(td.Text);
            }
            catch (PdfException)
            {
                // Clean font names like "Arial,Black"
                string sanitizedFontName = td.Font.Name;
                int commaIndex = sanitizedFontName.LastIndexOf(",", StringComparison.Ordinal);
                if (commaIndex >= 0)
                    sanitizedFontName = sanitizedFontName.Remove(commaIndex);

                target.Font = pdf.AddFont(sanitizedFontName, td.Font.Bold, td.Font.Italic, false, false) ?? fallback;
                target.DrawString(td.Text);
            }
        }
    }
}
VB
Imports System
Imports System.Diagnostics

Imports BitMiracle.Docotic.Pdf

Namespace BitMiracle.Docotic.Pdf.Samples
    Public NotInheritable Class CopyPageObjects
        Public Shared Sub Main()
            ' NOTE: 
            ' When used in trial mode, the library imposes some restrictions.
            ' Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            ' for more information.

            Const PathToFile As String = "CopyPageObjects.pdf"

            Using pdf = New PdfDocument("Sample Data/BRAILLE CODES WITH TRANSLATION.pdf")
                Using copy As PdfDocument = pdf.CopyPages(0, 1)
                    Dim sourcePage As PdfPage = copy.Pages(0)
                    Dim copyPage As PdfPage = copy.AddPage()

                    copyPage.Rotation = sourcePage.Rotation
                    copyPage.MediaBox = sourcePage.MediaBox
                    If sourcePage.CropBox <> sourcePage.MediaBox Then
                        copyPage.CropBox = sourcePage.CropBox
                    End If

                    Dim universalFont As PdfFont = copy.AddFont("Arial")

                    Dim target As PdfCanvas = copyPage.Canvas
                    For Each obj As PdfPageObject In sourcePage.GetObjects()
                        target.SaveState()
                        setClipRegion(target, obj.ClipRegion)

                        If obj.Type = PdfPageObjectType.Path Then
                            Dim path As PdfPath = DirectCast(obj, PdfPath)
                            target.Transform(path.TransformationMatrix)
                            setBrushAndPen(target, path)

                            appendPath(target, path)
                            drawPath(target, path)
                        ElseIf obj.Type = PdfPageObjectType.Image Then
                            Dim image As PdfPaintedImage = DirectCast(obj, PdfPaintedImage)
                            target.TranslateTransform(image.Position.X, image.Position.Y)
                            target.Transform(image.TransformationMatrix)

                            target.Brush.Color = New PdfRgbColor(255, 255, 255)
                            target.DrawImage(image.Image, 0, 0, 0)
                        ElseIf obj.Type = PdfPageObjectType.Text Then
                            Dim text As PdfTextData = DirectCast(obj, PdfTextData)
                            drawText(target, text, universalFont, copy)
                        End If

                        target.RestoreState()
                    Next

                    For Each font As PdfFont In copy.Fonts
                        font.RemoveUnusedGlyphs()
                    Next

                    copy.RemovePage(0)

                    copy.Save(PathToFile)
                End Using
            End Using

            Process.Start(PathToFile)
        End Sub

        Private Shared Sub setClipRegion(canvas As PdfCanvas, clipRegion As PdfClipRegion)
            If clipRegion.IntersectedPaths.Count = 0 Then
                Return
            End If

            Dim transformationBefore As PdfMatrix = canvas.TransformationMatrix
            Try
                For Each clipPath As PdfPath In clipRegion.IntersectedPaths
                    canvas.ResetTransform()
                    canvas.Transform(clipPath.TransformationMatrix)
                    appendPath(canvas, clipPath)
                    canvas.SetClip(clipPath.ClipMode.Value)
                Next
            Finally
                canvas.ResetTransform()
                canvas.Transform(transformationBefore)
            End Try
        End Sub

        Private Shared Sub setBrushAndPen(target As PdfCanvas, path As PdfPath)
            If path.PaintMode = PdfDrawMode.Fill OrElse path.PaintMode = PdfDrawMode.FillAndStroke Then
                target.Brush.Opacity = path.Brush.Opacity

                Dim color As PdfColor = path.Brush.Color
                If color IsNot Nothing Then
                    target.Brush.Color = path.Brush.Color
                End If
            End If

            If path.PaintMode = PdfDrawMode.Stroke OrElse path.PaintMode = PdfDrawMode.FillAndStroke Then
                target.Pen.Opacity = path.Pen.Opacity

                Dim color As PdfColor = path.Pen.Color
                If color IsNot Nothing Then
                    target.Pen.Color = path.Pen.Color
                End If
            End If
        End Sub

        Private Shared Sub appendPath(target As PdfCanvas, path As PdfPath)
            For Each subpath As PdfSubpath In path.Subpaths
                For Each segment As PdfPathSegment In subpath.Segments
                    Select Case segment.Type
                        Case PdfPathSegmentType.Point
                            target.CurrentPosition = DirectCast(segment, PdfPointSegment).Value
                            Exit Select

                        Case PdfPathSegmentType.Line
                            Dim line As PdfLineSegment = DirectCast(segment, PdfLineSegment)
                            target.CurrentPosition = line.Start
                            target.AppendLineTo(line.[End])
                            Exit Select

                        Case PdfPathSegmentType.Bezier
                            Dim bezier As PdfBezierSegment = DirectCast(segment, PdfBezierSegment)
                            target.CurrentPosition = bezier.Start
                            target.AppendCurveTo(bezier.FirstControl, bezier.SecondControl, bezier.[End])
                            Exit Select

                        Case PdfPathSegmentType.Rectangle
                            target.AppendRectangle(DirectCast(segment, PdfRectangleSegment).Bounds)
                            Exit Select

                        Case PdfPathSegmentType.CloseSubpath
                            target.ClosePath()
                            Exit Select
                    End Select
                Next
            Next
        End Sub

        Private Shared Sub drawPath(target As PdfCanvas, path As PdfPath)
            Select Case path.PaintMode
                Case PdfDrawMode.Fill
                    target.FillPath(path.FillMode.Value)
                    Exit Select

                Case PdfDrawMode.FillAndStroke
                    target.FillAndStrokePath(path.FillMode.Value)
                    Exit Select

                Case PdfDrawMode.Stroke
                    target.StrokePath()
                    Exit Select
                Case Else

                    target.ResetPath()
                    Exit Select
            End Select
        End Sub

        Private Shared Sub drawText(target As PdfCanvas, td As PdfTextData, fallback As PdfFont, pdf As PdfDocument)
            target.TextRenderingMode = td.RenderingMode
            target.Brush.Color = td.Brush.Color
            target.Brush.Opacity = td.Brush.Opacity

            target.Pen.Color = td.Pen.Color
            target.Pen.Opacity = td.Pen.Opacity
            target.Pen.Width = td.Pen.Width

            target.TextPosition = PdfPoint.Empty
            target.FontSize = td.FontSize
            target.Font = td.Font
            target.TranslateTransform(td.Position.X, td.Position.Y)
            target.Transform(td.TransformationMatrix)

            ' Currently, Docotic.Pdf does not completely support drawing of 
            ' text with all types of fonts existing in PDF documents. Let's use
            ' some system font as a workaround in such cases.
            Try
                target.DrawString(td.Text)
            Catch generatedExceptionName As PdfException
                ' Clean font names like "Arial,Black"
                Dim sanitizedFontName As String = td.Font.Name
                Dim commaIndex As Integer = sanitizedFontName.LastIndexOf(",", StringComparison.Ordinal)
                If commaIndex >= 0 Then
                    sanitizedFontName = sanitizedFontName.Remove(commaIndex)
                End If

                target.Font = If(pdf.AddFont(sanitizedFontName, td.Font.Bold, td.Font.Italic, False, False), fallback)
                target.DrawString(td.Text)
            End Try
        End Sub
    End Class
End Namespace