Extract and Replace text with Images inside PDF using C# with Aspose.PDF

We are using Pdf library to generate some dynamic contracts, where the initial pdf has some text placeholders, then after collecting data form the user we generate the end contract.
While doing this, we discovered a very strange issue. See the code below.
Basically finding all the needed text using the Regex and TextAbsorber, then having the position of the fragments, I place an ImageStamp. What is strange is, the Signature field I can see it 3 times as needed, but the checkboxes only the last one. The funny thing is, if I reverse the order of the fields in the list, then I see the last Signature, and all checkboxes.
Can you please tell me what is wrong here?

For your convenience, I attached the full project.

Thank you.

AsposeReplaceTextWithImage.zip (70.3 KB)

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Aspose.Pdf;
using Aspose.Pdf.Text;

namespace AsposeReplaceTextWithImage
{
    class Program
    {
        static Random R = new Random();
        static void Main(string[] args)
        {
            List<Field> fields = new List<Field>()
            {
                new Field(){IsCustom = true, Name = "custom"},
                new Field(){IsSignature = true, Name = "t"},
                new Field(){IsCheckBox = true, Name = "c"}
            };

            Document pdfDocument = new Document(new FileStream("QC simple contract.pdf", FileMode.Open));
            int customCnt = 1;
            foreach (var field in fields)
            {
                var regex = CreateFieldRg(field.Name);
                var textFragmentAbsorber = new TextFragmentAbsorber(regex, new TextSearchOptions(true));
                foreach (var page in pdfDocument.Pages) page.Annotations.Clear();
                pdfDocument.Pages.Accept(textFragmentAbsorber);

                var textFragmentCollection = textFragmentAbsorber.TextFragments;
                foreach (var fragment in textFragmentCollection)
                {
                    if (field.IsCustom)
                    {
                        fragment.Text = $"Custom_{customCnt++}";
                    }
                    else if (field.IsSignature)
                    {
                        fragment.Text = GetEmptyTextToFitWidth(fragment);
                        var w = fragment.Rectangle.Width;
                        var h = fragment.Rectangle.Height;
                        var ms = new MemoryStream(File.ReadAllBytes("signature.png")); // in real project it comes from a web-request
                        var imageStamp = new ImageStamp(ms)
                        {
                            Background = false,
                            Width = w,
                            Height = h,
                            XIndent = fragment.Position.XIndent,
                            YIndent = fragment.Position.YIndent,
                            OutlineOpacity = 0.5,
                        };
                        fragment.Page.AddStamp(imageStamp);
                    }
                    else if (field.IsCheckBox)
                    {
                        fragment.Text = GetEmptyTextToFitWidth(fragment);
                        var w = Math.Min(fragment.Rectangle.Width, fragment.Rectangle.Height);
                        var bitmap = R.Next(4) == 2
                            ? File.ReadAllBytes("CheckBox-checked-512.png")
                            : File.ReadAllBytes("CheckBox-empty-512.png");
                        var ms = new MemoryStream(bitmap);
                        var imageStamp = new ImageStamp(ms)
                        {
                            Background = false,
                            Width = w,
                            Height = w,
                            XIndent = fragment.Position.XIndent,
                            YIndent = fragment.Position.YIndent,
                            OutlineOpacity = 0.5,
                        };
                        fragment.Page.AddStamp(imageStamp);
                    }
                }
            }

            pdfDocument.Save("result.pdf");
        }

        private static string GetEmptyTextToFitWidth(TextFragment textFragment)
        {
            var text = new string(' ', textFragment.Text.Length);
            var width = textFragment.TextState.Font.MeasureString(text, textFragment.TextState.FontSize);
            var widthCustom =
                textFragment.TextState.Font.MeasureString(textFragment.Text, textFragment.TextState.FontSize);
            if (width < widthCustom)
                while (width < widthCustom)
                {
                    text += " ";
                    width = textFragment.TextState.Font.MeasureString(text, textFragment.TextState.FontSize);
                }
            else
                while (text.Length > 0 && width > textFragment.Rectangle.Width)
                {
                    text = text.Remove(0, 1);
                    width = textFragment.TextState.Font.MeasureString(text, textFragment.TextState.FontSize);
                }

            return text;
        }

        private static Regex CreateFieldRg(string fieldName)
        {
            //return new Regex(@"<([\$\@])\s*(" + fieldName +  @")([0-9]*)\s*>", RegexOptions.IgnoreCase);
            return new Regex(@"<([\$\@]{1})\s*(" + fieldName + @")\s*>", RegexOptions.IgnoreCase);
        }
    }

    public class Field
    {
        public bool IsCustom { get; set; }

        public bool IsSignature { get; set; }

        public bool IsCheckBox { get; set; }

        public string Name { get; set; }
    }
}

@Lernair

Thanks for posting your inquiry.

We were able to observe similar behavior of the API in our environment and for the sake of investigation, we have logged a ticket as PDFNET-47949 in our issue tracking system. We will further look into details of it and keep you posted with the status of its rectification. Please be patient and spare us some time.

We are sorry for the incovenience.

Ok, Can you please credit our account for the use of your service until this issue is resolved? This is currently blocking us from using the software with our clients.

Thanks.

@Lernair

We would like to share with you that we replicated the issue with Aspose.PDF for .NET 20.4 and logged it under free support model where issues have low priority and are resolved on first come first serve basis. We speculate that issue could be resolved with some code reformations but it needs to be investigated in details.

In case the issue is resolved with a code snippet reform, you do not need to upgrade your license in order to use the fix. However, if its fix will be included in upcoming version which is not supported by your license, you will need to renew your subscription in order to use the latest version as per company policy.

Furthermore, you may also check our priority support option where issues have high precedence and tickets are resolved on an urgent basis. In case you have further concerns, please feel free to share.

Is there any status on this BUG reported? It’s currently blocking our development and it’s been 3 weeks without an update. Can you please give us an update and timeframe as to when it will be fixed?

Thanks

@Lernair

We are afraid that earlier logged ticket is not yet resolved due to other high priority issues in the queue. We regret that we are not in a position to share any reliable ETA for now. However, we have recorded your concerns and will surely consider them during ticket investigation. Will inform you as soon as we have some certain updates in this regard. Please spare us some time.

We are sorry for the inconvenience.

The issues you have found earlier (filed as PDFNET-47949) have been fixed in Aspose.PDF for .NET 22.7.