I am using itextsharp to programmatically generate replies to PDF annotations. Everything seems fine, except that the generated replies do not get sorted in chronologic order in Acrobat DC. It appears above manually-created replies, even though it has a later timestamp. Please see image below, showing how it appears on Acrobat DC.
Auto generated reply appearing above manual replies despite having a later timestamp:
The following is my code:
PdfArray originalRect = originalAnnot.GetAsArray(PdfName.RECT);
Rectangle replyRect = new Rectangle(
originalRect.GetAsNumber(0).FloatValue, originalRect.GetAsNumber(1).FloatValue,
originalRect.GetAsNumber(2).FloatValue, originalRect.GetAsNumber(3).FloatValue
);
PdfAnnotation replySticky = PdfAnnotation.CreateText(stamper.Writer, replyRect, author, change.ReplyToAdd, true, "Comment");
replySticky.Put(PdfName.IRT, annots.getAsIndirectObject(i));
replySticky.Put(PdfName.CREATIONDATE, new PdfDate(DateTime.Now));
replySticky.Put(PdfName.M, new PdfDate(DateTime.Now));
replySticky.Put(PdfName.AUTHOR, new PdfString(author));
replySticky.Put(PdfName.NM, new PdfString(Guid.NewGuid().ToString()));
replySticky.Put(new PdfName("Subj"), new PdfString("Sticky Note"));
PdfNumber n = originalAnnot.GetAsNumber(PdfName.F);
replySticky.Put(PdfName.F, new PdfNumber(n.IntValue | PdfAnnotation.FLAGS_HIDDEN));
stamper.AddAnnotation(replySticky, page);
Am I missing some attribute that determines display order in Acrobat? Thanks!
Updated: There is a question on how I am getting the value for originalAnnot. Before writing to the PDF, I will retrieve all existing annotations, and store them in a dictionary, using a key that is a combination of the page number and the NM value of the annotation. Here is the code fragment:
Dictionary<string, Annotation> annotationMap = new Dictionary<string, Annotation>();
pdfReader = new PdfReader(inputPath, password);
// First pass to read annotations
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
//get the PdfDictionary of the 1st page
PdfDictionary pageDict = pdfReader.GetPageN(page);
//get annotation array
PdfArray annotArray = pageDict.GetAsArray(PdfName.ANNOTS);
if (annotArray == null)
{
continue;
}
//iterate through annotation array
int size = annotArray.Size;
for (int i = 0; i < size; i++)
{
PdfDictionary dict = annotArray.GetAsDict(i);
string name = getStringFromPDFString(dict.GetAsString(PdfName.NM));
string author = getStringFromPDFString(dict.GetAsString(PdfName.T));
if (name != string.Empty && author != string.Empty)
{
string contents = getStringFromPDFString(dict.GetAsString(PdfName.CONTENTS));
string subType = getSubType((PdfName)dict.GetAsName(PdfName.SUBTYPE));
string moddate = getStringFromPDFString(dict.GetAsString(PdfName.M));
string state = getStringFromPDFString(dict.GetAsString(PdfName.STATE));
string inreplyto = getStringFromPDFString(pdfDictionary.GetAsString(PdfName.NM));
string key = string.Format("{0}={1}", page, name);
if (annotationMap.ContainsKey(key))
{
Console.WriteLine(string.Format("Annotation with duplicate key {0} ignored", key));
continue;
}
string context = string.Empty;
string highlightedtext = getHighlightText(dict, page, pdfReader, out context);
Annotation ann = new Annotation(name, moddate, subType, author, page, inputPath, contents, inreplyto, state, context, highlightedtext, dict, annotArray.GetAsIndirectObject(i));
annotationMap.Add(ann.Identifier, ann);
}
} // Each annotation
} // Each page