private void AddAnnotation(object sender, RoutedEventArgs e)
        {
            // add annotation based on button's tag value.
            Button button     = (Button)sender;
            string actionName = button.Tag as string;

            if (this.document != null && this.document.NativePage != null && this.document.Page != null)
            {
                if (actionName == "star")
                {
                    Annotation starAnnotation = new RubberStampAnnotation(new Boundary(10, 400, 50, 440),
                                                                          AnnotationFlags.Default);
                    FixedContent fixedContent = new FixedContent("ap01", new Boundary(0, 0, 40, 40));
                    fixedContent.Content.AppendImage("star", 0, 0, 40, 40);
                    starAnnotation.Appearance.Normal = fixedContent;
                    this.document.NativePage.Annotations.Add(starAnnotation);

                    this.document.PageViewModel.Annotations.Add(new StarAnnotationViewModel(starAnnotation,
                                                                                            this.document.Page));
                }
                else if (actionName == "smile")
                {
                    Annotation starAnnotation = new RubberStampAnnotation(new Boundary(60, 400, 100, 440),
                                                                          AnnotationFlags.Default);
                    FixedContent fixedContent = new FixedContent("ap01", new Boundary(0, 0, 40, 40));
                    fixedContent.Content.AppendImage("smile", 0, 0, 40, 40);
                    starAnnotation.Appearance.Normal = fixedContent;
                    this.document.NativePage.Annotations.Add(starAnnotation);

                    this.document.PageViewModel.Annotations.Add(new SmileAnnotationViewModel(starAnnotation,
                                                                                             this.document.Page));
                }
                else if (actionName == "text")
                {
                    FreeTextAnnotation textAnnotation = new FreeTextAnnotation(new Boundary(60, 400, 260, 500));

                    string sampleText = "sample text";

                    textAnnotation.Appearance.Normal = AnnotationsHelper.CreateNormalAppearance(sampleText, 200, 100);

                    // set properties affecting default appearance to be used as fallback
                    textAnnotation.FontSize     = 12;
                    textAnnotation.BorderEffect = new AnnotationBorderEffect(AnnotationBorderEffectStyle.NoEffect, 0);
                    textAnnotation.Contents     = sampleText;
                    // text and border color
                    textAnnotation.TextColor = RgbColors.White.Components;
                    // set  background here if needed
                    textAnnotation.Color = RgbColors.Green.Components;

                    this.document.NativePage.Annotations.Add(textAnnotation);

                    this.document.PageViewModel.Annotations.Add(new TextAnnotationViewModel(textAnnotation,
                                                                                            this.document.Page));
                }
            }
        }
        /// <summary>
        /// Adds a watermark on all pages of the specified document.
        /// </summary>
        /// <param name="doc">Document to process.</param>
        /// <param name="imageDataStream">Stream containing image data to be used as watermark. Caller is reposible for closing it.</param>
        /// <param name="outputStream">Output stream, optional. If not set, incremental save will be performed. Caller is responsible for closing it.</param>
        public static void Watermark(this FixedDocument doc, Stream imageDataStream, Stream outputStream = null)
        {
            if (doc == null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            if (imageDataStream == null)
            {
                throw new ArgumentNullException(nameof(imageDataStream));
            }

            // create and register image resource
            string imageResourceId = Guid.NewGuid().ToString("N");
            Image  imageResource   = new Image(imageResourceId, imageDataStream);

            doc.ResourceManager.RegisterResource(imageResource);

            // register watermark XObject it will be referenced in all watermark annotations
            FixedContent watermarkContent = new FixedContent(Guid.NewGuid().ToString("N"),
                                                             new Boundary(imageResource.Width, imageResource.Height));

            watermarkContent.Content.AppendImage(imageResourceId, 0, 0, imageResource.Width, imageResource.Height);
            doc.ResourceManager.RegisterResource(watermarkContent);

            // add annotations to every page
            foreach (Page page in doc.Pages)
            {
                WatermarkAnnotation watermarkAnnotation = CreateWatermarkAnnotation(page.Boundary.MediaBox, watermarkContent);
                doc.ResourceManager.RegisterResource(watermarkAnnotation.Watermark);
                page.Annotations.Add(watermarkAnnotation);
            }

            // save to specified file or do an incremental update
            if (outputStream != null)
            {
                doc.Save(outputStream);
            }
            else
            {
                doc.Save();
            }
        }
        /// <summary>
        /// Creates a fixed content object that contains
        /// drawing instructions for normal annotation state.
        /// </summary>
        public static FixedContent CreateNormalAppearance(string text, double width,
                                                          double height)
        {
            // create fixed content object, set its unique ID using guid.
            // this object will be implicitly added to page resources using this ID.
            FixedContent fixedContent = new FixedContent(Guid.NewGuid().ToString("N"), new Boundary(0, 0, width, height));

            // use text block from flow layout API subset,
            // to quickly draw text in a fixed content container.
            Apitron.PDF.Kit.FlowLayout.Content.TextBlock textBlock = new Apitron.PDF.Kit.FlowLayout.Content.TextBlock(text);
            textBlock.Font       = new Font(StandardFonts.Helvetica, 12);
            textBlock.Display    = Display.Block;
            textBlock.Color      = RgbColors.White;
            textBlock.Width      = width;
            textBlock.Height     = height;
            textBlock.Background = RgbColors.Green;

            fixedContent.Content.AppendContentElement(textBlock, width, height);
            return(fixedContent);
        }
        /// <summary>
        /// Creates watermark annotations object referencing specified XObject.
        /// </summary>
        /// <param name="pageBoundary">Targer page boundary.</param>
        /// <param name="watermarkXobject">XObject containing visual content for the watermark.</param>
        /// <param name="rotated">Indicates that watermark object should be rotated and aligned between the lower left and upper right corners.</param>
        /// <returns>Initialized watermarp annotation.</returns>
        private static WatermarkAnnotation CreateWatermarkAnnotation(Boundary pageBoundary,
                                                                     FixedContent watermarkXobject, bool rotated = false)
        {
            // create watermark content XObject and reference existing "real" watermark XObject containing content
            FixedContent watermarkStub = new FixedContent(Guid.NewGuid().ToString("N"), pageBoundary);

            if (rotated)
            {
                // calculate rotation angle
                double alpha = Math.Atan(watermarkStub.Boundary.Height / watermarkStub.Boundary.Width);
                double beta  = Math.PI / 2.0 - alpha;

                double centeringDelta = watermarkXobject.Boundary.Height * Math.Cos(beta);

                double rotatedWidth  = watermarkXobject.Boundary.Width * Math.Cos(alpha) + centeringDelta;
                double rotatedHeight = watermarkXobject.Boundary.Width * Math.Sin(alpha) + watermarkXobject.Boundary.Height * Math.Sin(beta);

                watermarkStub.Content.SaveGraphicsState();
                watermarkStub.Content.Translate(centeringDelta + (watermarkStub.Boundary.Width - rotatedWidth) / 2.0,
                                                (watermarkStub.Boundary.Height - rotatedHeight) / 2.0);
                watermarkStub.Content.SetRotate(alpha);
                watermarkStub.Content.AppendXObject(watermarkXobject.ID, 0, 0);
                watermarkStub.Content.RestoreGraphicsState();
            }
            else
            {
                watermarkStub.Content.AppendXObject(watermarkXobject.ID, (watermarkStub.Boundary.Width - watermarkXobject.Boundary.Width) / 2.0,
                                                    (watermarkStub.Boundary.Height - watermarkXobject.Boundary.Height) / 2.0);
                watermarkStub.Content.RestoreGraphicsState();
            }

            // create annotation and wire its visual part
            WatermarkAnnotation annotation = new WatermarkAnnotation(pageBoundary);

            annotation.Watermark = watermarkStub;

            return(annotation);
        }
        /// <summary>
        /// Adds a watermark to all pages of the specified document.
        /// </summary>
        /// <param name="doc">Document to process.</param>
        /// <param name="watermarkText">Watermark text.</param>
        /// <param name="outputStream">Output stream, optional. If not set, incremental save will be performed.</param>
        public static void WatermarkText(this FixedDocument doc, string watermarkText, Stream outputStream = null)
        {
            if (doc == null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            if (string.IsNullOrEmpty(watermarkText))
            {
                throw new ArgumentException("Value cannot be null or empty.", nameof(watermarkText));
            }


            // register graphics state that sets transparency level for content
            GraphicsState gsTransparency = new GraphicsState("gsTransparency");

            gsTransparency.CurrentNonStrokingAlpha = 0.3;
            gsTransparency.CurrentStrokingAlpha    = 0.3;
            doc.ResourceManager.RegisterResource(gsTransparency);

            // create watermark content template using given text
            double fontSizeInPoints = 20;
            double padding          = 10;
            double borderThickness  = 2;

            double totalAddedSpace = (padding + borderThickness) * 2;

            TextBlock watermarkTextBlock = new TextBlock(watermarkText)
            {
                Font         = new Font("Times New Roman", fontSizeInPoints),
                Color        = RgbColors.Red,
                Padding      = new Thickness(padding),
                BorderColor  = RgbColors.Red,
                Border       = new Border(borderThickness),
                BorderRadius = 5,
                Background   = RgbColors.Pink
            };

            double textBlockWidth  = watermarkTextBlock.Measure(doc.ResourceManager) + totalAddedSpace;
            double textBlockHeight = fontSizeInPoints + totalAddedSpace + 10;

            FixedContent watermarkContent = new FixedContent(Guid.NewGuid().ToString("N"), new Boundary(textBlockWidth, textBlockHeight));

            watermarkContent.Content.SetGraphicsState(gsTransparency.ID);
            watermarkContent.Content.AppendContentElement(watermarkTextBlock, textBlockWidth, textBlockHeight);

            // register watermark XObject it will be referenced in all watermark annotations
            doc.ResourceManager.RegisterResource(watermarkContent);

            // add annotations to every page
            foreach (Page page in doc.Pages)
            {
                WatermarkAnnotation watermarkAnnotation = CreateWatermarkAnnotation(page.Boundary.MediaBox, watermarkContent, true);
                doc.ResourceManager.RegisterResource(watermarkAnnotation.Watermark);
                page.Annotations.Add(watermarkAnnotation);
            }

            // save to specified file or do an incremental update
            if (outputStream != null)
            {
                doc.Save(outputStream);
            }
            else
            {
                doc.Save();
            }
        }
        /// <summary>
        /// Signs the range of document pages using given certificate and signature image.
        /// </summary>
        /// <param name="doc">Document to sign.</param>
        /// <param name="signingCertificate">Signing certificate's data stream.</param>
        /// <param name="certPassword">Certificate's password.</param>
        /// <param name="signatureText">The text of the signature.</param>
        /// <param name="signatureBoundary">Visual signature boundaries.</param>
        /// <param name="signaturePageIndexStart">The index of the first page to sign.</param>
        /// <param name="signaturePageIndexEnd">The index of the last page to sign.</param>
        /// <param name="outputStream">Output stream, optional. If not set, incremental save will be performed.</param>
        /// <returns>Identifier assigned to the created signature field. Using this id you can find this field in doc's AcroForm dictionary.</returns>
        public static string Sign(this FixedDocument doc, Stream signingCertificate,
                                  string certPassword, string signatureText, Boundary signatureBoundary,
                                  int signaturePageIndexStart = 0, int signaturePageIndexEnd = 0, Stream outputStream = null)
        {
            if (doc == null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            if (signingCertificate == null)
            {
                throw new ArgumentNullException(nameof(signingCertificate));
            }

            if (certPassword == null)
            {
                throw new ArgumentNullException(nameof(certPassword));
            }

            if (signatureBoundary == null)
            {
                throw new ArgumentNullException(nameof(signatureBoundary));
            }

            if (signaturePageIndexStart < 0 || signaturePageIndexStart > doc.Pages.Count - 1)
            {
                throw new ArgumentOutOfRangeException(nameof(signaturePageIndexStart));
            }

            if (signaturePageIndexEnd < signaturePageIndexStart || signaturePageIndexEnd > doc.Pages.Count - 1)
            {
                throw new ArgumentOutOfRangeException(nameof(signaturePageIndexEnd));
            }

            // create textual resource
            FixedContent signatureTextXObject = new FixedContent(Guid.NewGuid().ToString("N"), new Boundary(0, 0, signatureBoundary.Width, signatureBoundary.Height));

            Section section = new Section();

            if (!string.IsNullOrEmpty(signatureText))
            {
                var newLineString = "<br/>";
                signatureText = signatureText.Replace("\r\n", newLineString)
                                .Replace("\n", newLineString)
                                .Replace("\r", newLineString);

                foreach (ContentElement contentElement in ContentElement.FromMarkup(signatureText))
                {
                    contentElement.Font = new Font("TimesNewRoman", 12);
                    section.Add(contentElement);
                }

                signatureTextXObject.Content.AppendContentElement(section, signatureBoundary.Width, signatureBoundary.Height);
            }

            doc.ResourceManager.RegisterResource(signatureTextXObject);

            string signatureFieldId = Guid.NewGuid().ToString("N");

            // create signature field and initialize it using a stored
            // password protected certificate
            SignatureField signatureField = new SignatureField(signatureFieldId);

            signatureField.Signature = Signature.Create(new Pkcs12Store(signingCertificate, certPassword));

            // add signature field to a document
            doc.AcroForm.Fields.Add(signatureField);

            // create signature view using the image resource
            SignatureFieldView signatureView = new SignatureFieldView(signatureField, signatureBoundary);

            signatureView.ViewSettings.Graphic           = Graphic.XObject;
            signatureView.ViewSettings.GraphicResourceID = signatureTextXObject.ID;
            signatureView.ViewSettings.Description       = Description.None;

            // add view to pages' annotations
            for (int i = signaturePageIndexStart; i <= signaturePageIndexEnd; ++i)
            {
                doc.Pages[i].Annotations.Add(signatureView);
            }

            // save to specified file or do an incremental update
            if (outputStream != null)
            {
                doc.Save(outputStream);
            }
            else
            {
                doc.Save();
            }

            return(signatureFieldId);
        }