title: How to prevent replacement annotation from changing position and text size?
body: <p>I'm using iTextSharp to replace Typewriter annotations with Textboxes that have the same content and position, but some of the resulting Textboxes end up in different positions with different text sizes, despite seemingly having exactly the same data in their <code>hashMap</code>. </p>
  
  <p>The problem is that when I create these new annotations on <a href="https://www.dropbox.com/s/hyfgqh4fsbalezs/Before%20Conversion%20Dummy.pdf?dl=0" rel="nofollow noreferrer">this sample PDF</a>, and then view the PDF in Adobe Acrobat XI, the new Textboxes have the following problems:</p>
  
  <ul>
  <li><p>They have moved from their original positions (adjacent to the arrows) to lower on the page</p></li>
  <li><p>The text has changed in size</p></li>
  <li><p>There is no <strong>Properties</strong> available when the new Textbox is right-clicked</p></li>
  </ul>
  
  <p>I suspect that all 3 problems are due to a single underlying issue with how I'm creating the new Textbox.</p>
  
  <p>When I check the <code>/Rect</code> key in the <code>hashMap</code> for <code>annot</code>, it has the same rectangle coordinates in the same order as the original <code>freeTextAnnot</code>, so I don't understand why some of the annotations end up displaced.</p>
  
  <p>Here's my code for creating the new Textboxes with the existing Typewriter annotation data.  Note that you'll need to set <code>inputPath</code> and <code>outputPath</code> to the actual location of the PDF and its destination path:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using iTextSharp;
  using iTextSharp.text.pdf;
  using System.IO;
  
  namespace PDFConverterTester
  {
      public class PdfModifierTester
      {
          public void testWithPaths()
          {
              //set to location of test PDF
              string inputPath = @"C:\InputPath\Before Conversion Dummy.pdf";
              //set to destination of new PDF
              string outputPath = @"C:\OutputPath\Before Conversion Dummy.pdf";
              test(inputPath, outputPath);
          }
  
          public void test(string inputPath, string outputPath)
          {
              PdfReader pdfReader = new PdfReader(inputPath);
              PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(outputPath, FileMode.Create));
              //get the PdfDictionary of the 1st page
              PdfDictionary pageDict = pdfReader.GetPageN(1);
              //get annotation array
              PdfArray annotArray = pageDict.GetAsArray(PdfName.ANNOTS);
              //iterate through annotation array
              int size = annotArray.Size;
              for (int i = size - 1; i &gt;= 0; i--)
              {
                  PdfDictionary dict = annotArray.GetAsDict(i);
                  PdfName ITName = dict.GetAsName(new PdfName("IT"));
                  if (ITName != null)
                  {
                      if (ITName.Equals(new PdfName("FreeTextTypewriter")))
                      {
                          PdfAnnotation annot = copyToNewAnnotation_SSCCE(dict,pdfStamper);
                          pdfStamper.AddAnnotation(annot, 1);
                          annotArray.Remove(i);
                      }
                  }
              }
              pdfStamper.Close();
              pdfReader.Close();
          }
  
          private PdfAnnotation copyToNewAnnotation_SSCCE(PdfDictionary freeTextAnnot,PdfStamper pdfStamper)
          {
  
              //need Rectangle for CreateFreeText()
              iTextSharp.text.Rectangle rect;
              PdfArray rectArray = freeTextAnnot.GetAsArray(PdfName.RECT);
              if (rectArray == null)
              {
                  rect = null;
              }
              else
              {
                  rect = new iTextSharp.text.Rectangle(getFloat(rectArray, 0),
                                                                            getFloat(rectArray, 1),
                                                                            getFloat(rectArray, 2),
                                                                            getFloat(rectArray, 3));
              }
              //create new annotation
              PdfContentByte pcb = new PdfContentByte(pdfStamper.Writer);
              PdfAnnotation annot = PdfAnnotation.CreateFreeText(pdfStamper.Writer, rect, "", pcb);
              //make array of all possible PdfName keys in dictionary for freeTextAnnot
              string pdfNames = "AP,BS,C,CA,CL,CONTENTS,CREATIONDATE,DA,DS,F,IT,LE,M,NM,P,POPUP,Q,RC,RD,ROTATE,SUBJ,SUBTYPE,T,TYPE";
              string[] pdfNameArray = pdfNames.Split(',');
              //iterate through key array copying key-value pairs to new annotation
              foreach (string pdfName in pdfNameArray)
              {
                  //get value for this PdfName
                  PdfName key = new PdfName(pdfName);
                  PdfObject obj = freeTextAnnot.Get(key);
                  //if returned value is null, maybe key is case-sensitive
                  if (obj == null)
                  {
                      //try with first letter only capitalized, e.g. "Contents" instead of "CONTENTS"
                      string firstCappdfName = char.ToUpper(pdfName[0]) + pdfName.Substring(1);
                      key = new PdfName(firstCappdfName);
                      obj = freeTextAnnot.Get(key);
                  }
                  //set key-value pair in new annotation
                  annot.Put(key, obj);
              }
              //change annotation type to Textbox
              annot.Put(PdfName.SUBTYPE, PdfName.FREETEXT);
              annot.Put(new PdfName("Subj"), new PdfString("Textbox"));
  
              //set a default blank border
              annot.Put(PdfName.BORDER, new PdfBorderArray(0, 0, 0));
  
              return annot;
  
  
          }
  
          private float getFloat(PdfArray arr, int index)
          {
              return float.Parse(arr[index].ToString());
          }
      }
  }
  </code></pre>
  
  <p>EDIT: It seems that part of the problem may be in the call to <code>pdfStamper.AddAnnotation(annot,1)</code>, because <code>annot</code>'s values for the <code>/Rect</code> key change after this call is made. E.g.:</p>
  
  <p>before <code>AddAnnotation()</code> call: </p>
  
  <pre><code>{[2401, 408.56, 2445.64, 693]}
  </code></pre>
  
  <p>after call:</p>
  
  <pre><code>{[1899, 2445.64, 2183.44, 2401]}
  </code></pre>
  
  <p>So maybe the following code from <code>PdfStamper.AddAnnotation()</code> (<a href="https://github.com/itext/itextsharp/blob/develop/src/core/iTextSharp/text/pdf/PdfStamperImp.cs" rel="nofollow noreferrer">link to source</a>), lines 1463-1493, is responsible, I'm currently investigating this possibility:</p>
  
  <pre><code>if (!annot.IsUsed()) {
                          PdfRectangle rect = (PdfRectangle)annot.Get(PdfName.RECT);
                          if (rect != null &amp;&amp; (rect.Left != 0 || rect.Right != 0 || rect.Top != 0 || rect.Bottom != 0)) {
                              int rotation = reader.GetPageRotation(pageN);
                              Rectangle pageSize = reader.GetPageSizeWithRotation(pageN);
                              switch (rotation) {
                                  case 90:
                                      annot.Put(PdfName.RECT, new PdfRectangle(
                                          pageSize.Top - rect.Top,
                                          rect.Right,
                                          pageSize.Top - rect.Bottom,
                                          rect.Left));
                                      break;
                                  case 180:
                                      annot.Put(PdfName.RECT, new PdfRectangle(
                                          pageSize.Right - rect.Left,
                                          pageSize.Top - rect.Bottom,
                                          pageSize.Right - rect.Right,
                                          pageSize.Top - rect.Top));
                                      break;
                                  case 270:
                                      annot.Put(PdfName.RECT, new PdfRectangle(
                                          rect.Bottom,
                                          pageSize.Right - rect.Left,
                                          rect.Top,
                                          pageSize.Right - rect.Right));
                                      break;
                              }
                          }
                      }
                  }
  </code></pre>