PdfA.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 System.Text;
  9. using GrapeCity.Documents.Text;
  10. using GrapeCity.Documents.Common;
  11. using GrapeCity.Documents.Drawing;
  12. using GrapeCity.Documents.Pdf;
  13. using GrapeCity.Documents.Pdf.Structure;
  14. using GrapeCity.Documents.Pdf.MarkedContent;
  15. using GrapeCity.Documents.Pdf.Graphics;
  16. using GrapeCity.Documents.Pdf.Annotations;
  17. using GCTEXT = GrapeCity.Documents.Text;
  18. using GCDRAW = GrapeCity.Documents.Drawing;
  19.  
  20. namespace DsPdfWeb.Demos.Basics
  21. {
  22. // This sample shows how to create a PDF/A-3u compliant document.
  23. public class PdfA
  24. {
  25. public int CreatePDF(Stream stream)
  26. {
  27. var doc = new GcPdfDocument();
  28. var date = new DateTime(1961, 4, 12, 6, 7, 0, DateTimeKind.Utc);
  29.  
  30. // Mark the document as PDF/A-3u conformant:
  31. doc.ConformanceLevel = PdfAConformanceLevel.PdfA3u;
  32.  
  33. var fnt = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "arial.ttf"));
  34. var gap = 36;
  35.  
  36. // PDF/A-3a requires all content to be tagged so create and populate StructElement when rendering:
  37. var sePart = new StructElement("Part");
  38. doc.StructTreeRoot.Children.Add(sePart);
  39.  
  40. TextLayout tl = null;
  41. // Add 3 pages with sample content tagged according to PDF/A rules:
  42. for (int pageNo = 1; pageNo <= 3; ++pageNo)
  43. {
  44. // add page
  45. var page = doc.Pages.Add();
  46. var g = page.Graphics;
  47. float y = 72;
  48. if (doc.Pages.Count == 1)
  49. {
  50. // Create paragraph element:
  51. var seParagraph = new StructElement("P") { DefaultPage = page };
  52. // Add it to Part element:
  53. sePart.Children.Add(seParagraph);
  54.  
  55. tl = g.CreateTextLayout();
  56. tl.MarginAll = 72;
  57. tl.MaxWidth = page.Size.Width;
  58.  
  59. tl.DefaultFormat.Font = fnt;
  60. tl.DefaultFormat.FontBold = true;
  61. tl.DefaultFormat.FontSize = 20;
  62. tl.Append("PDF/A-3A Document");
  63.  
  64. // PerformLayout is done automatically in a new TextLayout or after a Clear():
  65. //tl.PerformLayout(true);
  66.  
  67. // Draw TextLayout within tagged content:
  68. g.BeginMarkedContent(new TagMcid("P", 0));
  69. g.DrawTextLayout(tl, PointF.Empty);
  70. g.EndMarkedContent();
  71.  
  72. y = tl.ContentRectangle.Bottom + gap;
  73.  
  74. seParagraph.ContentItems.Add(new McidContentItemLink(0));
  75. }
  76.  
  77. // Add some sample paragraphs tagged according to PDF/A rules:
  78. for (int i = 1; i <= 3; ++i)
  79. {
  80. // Create paragraph element:
  81. var seParagraph = new StructElement("P") { DefaultPage = page };
  82. // Add it to Part element:
  83. sePart.Children.Add(seParagraph);
  84.  
  85. var sb = new StringBuilder();
  86. sb.Append(string.Format("Paragraph {0} on page {1}: ", i, pageNo));
  87. sb.Append(Common.Util.LoremIpsum(1, 2, 4, 5, 10));
  88. var para = sb.ToString();
  89.  
  90. tl.Clear();
  91. tl.DefaultFormat.FontSize = 14;
  92. tl.DefaultFormat.FontBold = false;
  93. tl.MarginTop = y;
  94. tl.Append(para);
  95.  
  96. // Draw TextLayout within tagged content:
  97. g.BeginMarkedContent(new TagMcid("P", i));
  98. g.DrawTextLayout(tl, PointF.Empty);
  99. g.EndMarkedContent();
  100.  
  101. y += tl.ContentHeight + gap;
  102.  
  103. // Add content item to paragraph StructElement:
  104. seParagraph.ContentItems.Add(new McidContentItemLink(i));
  105.  
  106. // PDF/A-3 allows embedding files into document, but they should be associated with some document element
  107. // add embedded file associated with seParagraph:
  108. var ef1 = EmbeddedFileStream.FromBytes(doc, Encoding.UTF8.GetBytes(para));
  109. // ModificationDate and MimeType should be specified in case of PDF/A:
  110. ef1.ModificationDate = date;
  111. ef1.MimeType = "text/plain";
  112. var fn = string.Format("Page{0}_Paragraph{1}.txt", pageNo, i);
  113. var fs1 = FileSpecification.FromEmbeddedStream(fn, ef1);
  114. // UnicodeFile.FileName should be specified for PDF/A compliance:
  115. fs1.UnicodeFile.FileName = fs1.File.FileName;
  116. // Relationship should be specified in case of PDF/A:
  117. fs1.Relationship = AFRelationship.Unspecified;
  118. doc.EmbeddedFiles.Add(fn, fs1);
  119. seParagraph.AssociatedFiles.Add(fs1);
  120. }
  121. }
  122.  
  123. // PDF/A-3 allows transparency drawing in PDF file, add some:
  124. var gpage = doc.Pages[0].Graphics;
  125. gpage.FillRectangle(new RectangleF(20, 20, 200, 200), Color.FromArgb(40, Color.Red));
  126.  
  127. // PDF/A-3 allows using FormXObjects, add one with transparency:
  128. var r = new RectangleF(0, 0, 144, 72);
  129. var fxo = new FormXObject(doc, r);
  130. var gfxo = fxo.Graphics;
  131. gfxo.FillRectangle(r, Color.FromArgb(40, Color.Violet));
  132. var tf = new TextFormat()
  133. {
  134. Font = fnt,
  135. FontSize = 16,
  136. ForeColor = Color.FromArgb(100, Color.Black),
  137. };
  138. gfxo.DrawString("FormXObject", tf, r, TextAlignment.Center, ParagraphAlignment.Center);
  139. gfxo.DrawRectangle(r, Color.Blue, 3);
  140. gpage.DrawForm(fxo, new RectangleF(300, 250, r.Width, r.Height), null, ImageAlign.ScaleImage);
  141.  
  142. // PDF/A-3 allows using embedded files, but each embedded file must be associated with a document's element:
  143. var ef = EmbeddedFileStream.FromFile(doc, Path.Combine("Resources", "WordDocs", "ProcurementLetter.docx"));
  144. // ModificationDate and MimeType should be specified for EmbeddedFile in PDF/A:
  145. ef.ModificationDate = date;
  146. ef.MimeType = "application/msword";
  147. var fs = FileSpecification.FromEmbeddedFile(ef);
  148. fs.UnicodeFile.FileName = fs.File.FileName;
  149. fs.Relationship = AFRelationship.Unspecified;
  150. doc.EmbeddedFiles.Add("ProcurementLetter.docx", fs);
  151. // Associate embedded file with the document:
  152. doc.AssociatedFiles.Add(fs);
  153.  
  154. // Add an attachment associated with an annotation:
  155. var sa = new StampAnnotation()
  156. {
  157. UserName = "Minerva",
  158. Font = fnt,
  159. Rect = new RectangleF(300, 36, 220, 72),
  160. };
  161. sa.Flags |= AnnotationFlags.Print;
  162. // Use a FormXObject to represent the stamp annotation:
  163. var stampFxo = new FormXObject(doc, new RectangleF(PointF.Empty, sa.Rect.Size));
  164. var gstampFxo = stampFxo.Graphics;
  165. gstampFxo.FillRectangle(stampFxo.Bounds, Color.FromArgb(40, Color.Green));
  166. gstampFxo.DrawString("Stamp Annotation\nassociated with minerva.jpg", tf, stampFxo.Bounds, TextAlignment.Center, ParagraphAlignment.Center);
  167. gstampFxo.DrawRectangle(stampFxo.Bounds, Color.Green, 3);
  168. //
  169. sa.AppearanceStreams.Normal.Default = stampFxo;
  170. doc.Pages[0].Annotations.Add(sa);
  171. ef = EmbeddedFileStream.FromFile(doc, Path.Combine("Resources", "Images", "minerva.jpg"));
  172. ef.ModificationDate = date;
  173. ef.MimeType = "image/jpeg";
  174. fs = FileSpecification.FromEmbeddedFile(ef);
  175. fs.UnicodeFile.FileName = fs.File.FileName;
  176. fs.Relationship = AFRelationship.Unspecified;
  177. doc.EmbeddedFiles.Add("minerva.jpg", fs);
  178. sa.AssociatedFiles.Add(fs);
  179.  
  180. // Mark the document as conforming to Tagged PDF conventions (required for PDF/A):
  181. doc.MarkInfo.Marked = true;
  182.  
  183. // Metadata.CreatorTool and DocumentInfo.Creator should be the same for a PDF/A document:
  184. doc.Metadata.CreatorTool = doc.DocumentInfo.Creator;
  185. // A title should be specified for PDF/A document:
  186. doc.Metadata.Title = "DsPdf Document";
  187. doc.ViewerPreferences.DisplayDocTitle = true;
  188.  
  189. // Done:
  190. doc.Save(stream);
  191. return doc.Pages.Count;
  192. }
  193. }
  194. }
  195.