Guest User

Using PoDoFo to fill a acroform

a guest
Jun 27th, 2014
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.49 KB | None | 0 0
  1. // dennis.jenkins.75 .at. gmail.com
  2.  
  3. // http://www.mail-archive.com/[email protected]/msg00963.html
  4. // https://podofo.svn.sourceforge.net/svnroot/podofo/podofo/trunk/test/FormTest/FormTest.cpp
  5. // http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
  6.  
  7. #include <iostream>
  8. #include <podofo/podofo.h>
  9.  
  10. #define CP() do { std::cerr << "CheckPoint, line " << __LINE__ << "\n"; } while (0)
  11.  
  12. using namespace PoDoFo;
  13.  
  14. static bool verbose = false;
  15.  
  16. static const char   *GetFieldTypeName (EPdfField eType)
  17. {
  18.     switch (eType)
  19.     {
  20.         case ePdfField_PushButton: return "pushbutton";
  21.         case ePdfField_CheckBox: return "checkbox";
  22.         case ePdfField_RadioButton: return "radiobutton";
  23.         case ePdfField_TextField: return "textfield";
  24.         case ePdfField_ComboBox: return "combobox";
  25.         case ePdfField_ListBox: return "listbox";
  26.         case ePdfField_Signature: return "signature";
  27.         case ePdfField_Unknown: return "unknown";
  28.         default: return "??";
  29.     }
  30.  
  31.     return NULL;
  32. }
  33.  
  34. static void DumpPdfForm (const char *filename)
  35. {
  36.     PdfMemDocument      doc (filename);
  37.     PdfPage         *pPage = NULL;
  38.  
  39.     for (int iPage = 0; iPage < doc.GetPageCount(); ++iPage)
  40.     {
  41.         pPage = doc.GetPage (iPage);
  42.  
  43.         std::cout << filename << ":  page: " << iPage + 1 << "  fields: " << pPage->GetNumFields() << "\n";
  44.  
  45.         for (int iField = 0; iField < pPage->GetNumFields(); ++iField)
  46.         {
  47.             PdfField    field = pPage->GetField (iField);
  48.  
  49.             if (verbose)
  50.             {
  51.                 std::cout <<
  52.                     "  field: " << iField + 1 <<
  53.                     ", name: " << field.GetFieldName().GetString() <<
  54.                     ", type: " << GetFieldTypeName (field.GetType()) <<
  55.                     "\n";
  56.             }
  57.         }
  58.     }
  59. }
  60.  
  61. void    ListAnnotations (const char *filename, int nPage)
  62. {
  63.     PdfMemDocument doc (filename);
  64.     PdfPage *pPage = doc.GetPage (nPage);
  65.  
  66.     printf ("index   GetType()  HasKey('FT')\n");
  67.  
  68.     int nAnnots = pPage->GetNumAnnots();
  69.     for (int i = 0; i < nAnnots; i++) {
  70.         const PdfAnnotation* pAnnot = const_cast<PdfPage*>(pPage)->GetAnnotation (i);
  71.  
  72.         bool b = pAnnot->GetObject()->GetDictionary().HasKey (PdfName ("FT"));
  73.  
  74.         printf ("%5d          %2d          %1d\n", i, pAnnot->GetType(), b);
  75.     }
  76. }
  77.  
  78. // See section 12.7.3.3 (page 434) of ISO-32000-1:2008.
  79. // Need to construct an appearance stream for each form field,
  80. // or configure document to generated one dynamically.
  81.  
  82. // See section 12.7.4.3 (page 444) of ISO-32000-1:2008.
  83. // Shows a correct "Appearance Stream" for a text field.
  84.  
  85. // We can always directly hack the dictionary:
  86. //    PdfAnnotation::GetObject()->GetDictionary()
  87.  
  88. static void HackPdfFormDocument (PdfDocument &doc)
  89. {
  90. // http://www.mail-archive.com/[email protected]/msg01155.html
  91. // Stolen from PdfAcroForm::Init()
  92. //  doc.GetAcroForm()->Init (PdfAcroForm::ePdfAcroFormDefaultAppearance_BlackText12pt);
  93.  
  94.     PdfObject *pObj = doc.GetAcroForm()->GetObject();
  95.  
  96.     pObj->GetDictionary().AddKey (PdfName ("NeedAppearances"), PdfVariant (true));
  97.  
  98.     if (!pObj->GetDictionary().HasKey("DA"))
  99.     {
  100.         PdfFont     *pFont = doc.CreateFont ("Arial");
  101.         PdfObject   *pResource = NULL;
  102.         PdfObject   *pFontDict = NULL;
  103.  
  104. // Create "DR" key.
  105.         if (!pObj->GetDictionary().HasKey (PdfName ("DR")))
  106.         {
  107.             pObj->GetDictionary().AddKey (PdfName ("DR"), PdfDictionary());
  108.         }
  109.         pResource = pObj->GetDictionary().GetKey( PdfName("DR") );
  110.  
  111.         if (!pResource->GetDictionary().HasKey( PdfName ("Font")))
  112.         {
  113.             pResource->GetDictionary().AddKey (PdfName ("Font"), PdfDictionary());
  114.         }
  115.         pFontDict = pResource->GetDictionary().GetKey( PdfName("Font") );
  116.  
  117.         pFontDict->GetDictionary().AddKey( pFont->GetIdentifier(), pFont->GetObject()->Reference() );
  118.  
  119. // Create "DA" key.
  120.         std::ostringstream oss;
  121.         PdfLocaleImbue (oss);
  122.         oss << "0 0 0 rg /" << pFont->GetIdentifier().GetName() << " 12 Tf";
  123.         pObj->GetDictionary().AddKey( PdfName("DA"), PdfString( oss.str() ) );
  124.     }
  125. }
  126.  
  127. static void HackPdfForm (const char *in_fn, const char *out_fn)
  128. {
  129.     PdfMemDocument      doc (in_fn);
  130.     PdfPage         *pPage = NULL;
  131. //  PdfFont         *pFont = doc.CreateFont ("Arial");
  132.  
  133.     HackPdfFormDocument (doc);
  134.  
  135.     for (int iPage = 0; iPage < doc.GetPageCount(); ++iPage)
  136.     {
  137.         pPage = doc.GetPage (iPage);
  138.  
  139.         if (verbose)
  140.         {
  141.             std::cout << "  page: " << iPage + 1 << "  fields: " << pPage->GetNumFields() << "\n";
  142.         }
  143.  
  144.         for (int iField = 0; iField < pPage->GetNumFields(); ++iField)
  145.         {
  146.             PdfField    field = pPage->GetField (iField);
  147.  
  148.             if (verbose)
  149.             {
  150.                 std::cout <<
  151.                     "  field: " << iField + 1 <<
  152.                     ", name: " << field.GetFieldName().GetString() <<
  153.                     ", type: " << GetFieldTypeName (field.GetType()) <<
  154.                     "\n";
  155.             }
  156.  
  157.             if (field.GetType() == ePdfField_TextField)
  158.             {
  159.                 char tmp[32];
  160.                 snprintf (tmp, sizeof(tmp), "%d", iField);
  161.  
  162.                 auto *tf = reinterpret_cast<PdfTextField*>(&field);
  163.                 tf->SetText (tmp);
  164.                 tf->SetBackgroundColor (1.0, 0.0, 0.0);
  165.             } else if (field.GetType() == ePdfField_CheckBox) {
  166.                 auto *cb = reinterpret_cast<PdfCheckBox*>(&field);
  167.                 cb->SetChecked (true);
  168. //              cb->SetAppearanceChecked ();
  169.             }
  170.         }
  171.     }
  172.  
  173.     doc.Write (out_fn);
  174. }
  175.  
  176.  
  177. int main (int argc, char *argv[])
  178. {
  179.     try
  180.     {
  181.         PdfError::EnableDebug (false);
  182.  
  183.         if (argc == 2)
  184.         {
  185.             DumpPdfForm (argv[1]);
  186. //          ListAnnotations (argv[1], 0);
  187.         }
  188.         else if (argc == 3)
  189.         {
  190.             HackPdfForm (argv[1], argv[2]);
  191.         }
  192.         else
  193.         {
  194.             std::cerr << "Usage:\n";
  195.             std::cerr << "  " << argv[0] << " src.pdf\n";
  196.             std::cerr << "  " << argv[0] << " src.pdf dest.pdf\n";
  197.             return -1;
  198.         }
  199.     }
  200.  
  201.     catch (const PdfError &err)
  202.     {
  203.         err.PrintErrorMsg();
  204.         return err.GetError();
  205.     }
  206.  
  207.     return 0;
  208. }
Advertisement
Add Comment
Please, Sign In to add comment