SignatureAppearance.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using GrapeCity.Documents.Drawing;
  9. using GrapeCity.Documents.Pdf;
  10. using GrapeCity.Documents.Pdf.AcroForms;
  11. using GrapeCity.Documents.Pdf.Graphics;
  12. using GrapeCity.Documents.Text;
  13. using System.Security.Cryptography.X509Certificates;
  14. using GCTEXT = GrapeCity.Documents.Text;
  15. using GCDRAW = GrapeCity.Documents.Drawing;
  16.  
  17. namespace DsPdfWeb.Demos
  18. {
  19. // This sample demonstrates how to create and sign a PDF with a .pfx file,
  20. // specifying a custom AppearanceStream to represent the signature.
  21. // This sample is similar to SignDoc, except that it adds the AppearanceStream.
  22. public class SignatureAppearance
  23. {
  24. public int CreatePDF(Stream stream)
  25. {
  26. var doc = new GcPdfDocument();
  27. var page = doc.NewPage();
  28. var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
  29. page.Graphics.DrawString("Hello, World!\n" +
  30. "Signed by DsPdfWeb SignatureAppearance sample.",
  31. tf, new PointF(72, 72));
  32.  
  33. // Init a test certificate:
  34. var pfxPath = Path.Combine("Resources", "Misc", "DsPdfTest.pfx");
  35. var cert = new X509Certificate2(File.ReadAllBytes(pfxPath), "qq",
  36. X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
  37. var sp = new SignatureProperties()
  38. {
  39. SignatureBuilder = new Pkcs7SignatureBuilder()
  40. {
  41. CertificateChain = new X509Certificate2[] { cert }
  42. },
  43. Location = "DsPdfWeb Demo Browser",
  44. SignerName = "DsPdfWeb",
  45. SigningDateTime = Common.Util.TimeNow(),
  46. };
  47.  
  48. // Create a signature field to hold the signature:
  49. var sf = new SignatureField();
  50. // Add the signature field to the document:
  51. doc.AcroForm.Fields.Add(sf);
  52. // Connect the signature field and signature props:
  53. sp.SignatureField = sf;
  54.  
  55. // Set up the signature field:
  56. sf.Widget.Rect = new RectangleF(page.Size.Width - 72 * 4, 72 * 2, 72 * 3, 72);
  57. sf.Widget.Page = page;
  58. // Widget visual props will be overridden by sf.Widget.AppearanceStreams.Normal.Default set below:
  59. sf.Widget.BackColor = Color.PeachPuff;
  60. sf.Widget.Border = new GrapeCity.Documents.Pdf.Annotations.Border()
  61. {
  62. Color = Color.SaddleBrown,
  63. Width = 3,
  64. };
  65. sf.Widget.ButtonAppearance.Caption = $"Signer: {sp.SignerName}\r\nLocation: {sp.Location}";
  66. // Create custom signature appearance stream:
  67. var rc = new RectangleF(PointF.Empty, sf.Widget.Rect.Size);
  68. var fxo = new FormXObject(doc, rc);
  69. rc.Inflate(-4, -4);
  70. fxo.Graphics.FillEllipse(rc, Color.CornflowerBlue);
  71. fxo.Graphics.DrawEllipse(rc, new GCDRAW.Pen(Color.RoyalBlue, 3));
  72. rc.Inflate(-5, -5);
  73. fxo.Graphics.DrawEllipse(rc, new GCDRAW.Pen(Color.LightSteelBlue, 1));
  74. fxo.Graphics.DrawString($"Signed by {sp.SignerName}\non {Common.Util.TimeNow():yyyy-MM-dd}.",
  75. new TextFormat()
  76. {
  77. FontName = "Times New Roman",
  78. FontSize = 14,
  79. FontItalic = true,
  80. ForeColor = Color.Navy
  81. },
  82. fxo.Bounds,
  83. TextAlignment.Center, ParagraphAlignment.Center, false);
  84. sf.Widget.AppearanceStreams.Normal.Default = fxo;
  85.  
  86. // Reset signature appearance so that the widget appearance stream is used:
  87. sp.SignatureAppearance = null;
  88.  
  89. // Sign and save the document:
  90. // NOTES:
  91. // - Signing and saving is an atomic operation, the two cannot be separated.
  92. // - The stream passed to the Sign() method must be readable.
  93. doc.Sign(sp, stream);
  94.  
  95. // Done (the generated and signed docment has already been saved to 'stream').
  96. return doc.Pages.Count;
  97. }
  98. }
  99. }
  100.