using System; using System.Collections.Generic; using System.Text; using VEPROMS.CSLA.Library; using Volian.Svg.Library; using iTextSharp.text.factories; using iTextSharp.text; using iTextSharp.text.pdf; using System.Text.RegularExpressions; using System.IO; using System.Xml; using System.Windows.Forms; using LBWordLibrary; using System.Drawing; using System.Drawing.Imaging; using Volian.Controls.Library; using Volian.Base.Library; namespace Volian.Print.Library { public delegate void PromsPrinterStatusEvent(object sender,PromsPrintStatusArgs args); public class PromsPrintStatusArgs { private string _MyStatus; public string MyStatus { get { return _MyStatus; } } private DateTime _When = DateTime.Now; public DateTime When { get { return _When; } } private PromsPrinterStatusType _Type; public PromsPrinterStatusType Type { get { return _Type; } set { _Type = value; } } private int _Progress = 0; public int Progress { get { return _Progress; } set { _Progress = value; } } public PromsPrintStatusArgs(string myStatus, PromsPrinterStatusType type) { _MyStatus = myStatus; _Type = type; } public PromsPrintStatusArgs(string myStatus, PromsPrinterStatusType type, int progress) { _MyStatus = myStatus; _Type = type; _Progress = progress; } } public enum PromsPrinterStatusType { Start, General, MSWordToPDF, PageList, Watermark, Read16, Merge16, Open16, ReadMSWord, MergeMSWord, OpenMSWord, OpenPDF, Merge, Total, CloseDocument, NewPage, BuildSVG, SetSVG, SetPageEvent, GetSection, Before, BuildStep, Progress, ProgressSetup } public class PromsPrinter { public event PromsPrinterStatusEvent StatusChanged; private void OnStatusChanged(object sender, PromsPrintStatusArgs args) { if (StatusChanged != null) StatusChanged(sender, args); } private void OnStatusChanged(string myStatus, PromsPrinterStatusType type) { OnStatusChanged(this, new PromsPrintStatusArgs(myStatus, type)); } private void OnStatusChanged(string myStatus, PromsPrinterStatusType type, int progress) { OnStatusChanged(this, new PromsPrintStatusArgs(myStatus, type, progress)); } private string _Rev; private ItemInfo _MyItem; private string _Watermark; private string _PDFFile; public string PDFFile { get { return _PDFFile; } set { _PDFFile = value; } } private bool _DebugOutput; public bool DebugOutput { get { return _DebugOutput; } set { _DebugOutput = value; } } private string _BackgroundFolder; public string BackgroundFolder { get { return _BackgroundFolder; } set { _BackgroundFolder = value; } } private bool _OpenPDF; public bool OpenPDF { get { return _OpenPDF; } set { _OpenPDF = value; } } private bool _OverWrite; public bool OverWrite { get { return _OverWrite; } set { _OverWrite = value; } } private ChangeBarDefinition _MyChangeBarDefinition; public ChangeBarDefinition MyChangeBarDefinition { get { return _MyChangeBarDefinition; } set { _MyChangeBarDefinition = value; } } private bool _OriginalPageBreak; // use 16bit page breaks. public bool OriginalPageBreak { get { return _OriginalPageBreak; } set { _OriginalPageBreak = value; } } public PromsPrinter(ItemInfo myItem, string rev, string watermark, bool debugOutput, bool origPgBrk, string backgroundFolder, bool openPDF, bool overWrite, ChangeBarDefinition cbd, String pdfFile) { _MyItem = myItem; _Rev = rev; _Watermark = watermark; _DebugOutput = debugOutput; _BackgroundFolder = backgroundFolder; _OpenPDF = openPDF; _OverWrite = overWrite; _MyChangeBarDefinition = cbd; _PDFFile = pdfFile; _OriginalPageBreak = origPgBrk; } public string Print(string pdfFolder) { if (_MyItem is ProcedureInfo) return Print(_MyItem as ProcedureInfo, pdfFolder); return ""; } private string BuildMSWordPDF(SectionInfo section) { DateTime tStart = DateTime.Now; string MSWordFile = null; if (section.MyContent.ContentEntryCount == 1) { MSWordFile = MSWordToPDF.GetDocPdf(section, PrintOverride.TextColor); OnStatusChanged("MSWord converted to PDF " + MSWordFile, PromsPrinterStatusType.MSWordToPDF); } return MSWordFile; } private static void AddImportedPageToLayer(PdfContentByte cb, PdfLayer layer, PdfImportedPage page, float xOff, float yOff) { cb.BeginLayer(layer); iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(page); // the following checks if the content of page is landscape and rotates because we're printing on // a portrait page. If, at some point, we print a total landscape page, not a mix, this will need // re-evaluated. if (page.Height < page.Width) image.RotationDegrees = 90F; image.SetAbsolutePosition(xOff, yOff); cb.AddImage(image); cb.EndLayer(); } private PdfLayer _TextLayer; private PdfLayer _BackgroundLayer; private PdfLayer _MSWordLayer; private PdfLayer _PagelistLayer; private PdfLayer _DebugLayer; private PdfLayer _WatermarkLayer; private void CreateLayers(PdfContentByte cb) { if (DebugOutput) { _BackgroundLayer = new PdfLayer("16-Bit", cb.PdfWriter); _MSWordLayer = new PdfLayer("32-Bit MSWord", cb.PdfWriter); _PagelistLayer = new PdfLayer("32-Bit Pagelist", cb.PdfWriter); _TextLayer = new PdfLayer("32-Bit Text", cb.PdfWriter); _DebugLayer = new PdfLayer("Debug", cb.PdfWriter); _WatermarkLayer = new PdfLayer("Watermark", cb.PdfWriter); _WatermarkLayer.SetPrint("Watermark", true); } } private void CloseDocument(PdfContentByte cb, string fileName) { try { cb.PdfDocument.Close(); } catch (Exception ex) { Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message); } OnStatusChanged("CloseDocument", PromsPrinterStatusType.CloseDocument); if (OpenPDF) System.Diagnostics.Process.Start(fileName); OnStatusChanged("OpenPDF", PromsPrinterStatusType.OpenPDF); } private PdfContentByte OpenDoc(string outputFileName) { PdfWriter writer=null; iTextSharp.text.Document document = new iTextSharp.text.Document(PageSize.LETTER); try { writer = PdfWriter.GetInstance(document, new FileStream(outputFileName, FileMode.Create)); } catch (Exception ex) { StringBuilder sb = new StringBuilder(); sb.AppendLine("Could not create"); sb.AppendLine(); sb.AppendLine(outputFileName + "."); sb.AppendLine(); sb.AppendLine("If it is open, close and retry."); MessageBox.Show(sb.ToString(), "Error on CreatePdf", MessageBoxButtons.OK, MessageBoxIcon.Warning); //MessageBox.Show("Could not create " + outputFileName + ". If it is open, close and retry.", "Error on CreatePdf"); return null; } document.Open(); // Create Layers CreateLayers(writer.DirectContent); MSWordToPDF.DebugStatus = DebugOutput ? 1 : 0; PrintOverride.Reset(); if (DebugOutput) { PrintOverride.TextColor = System.Drawing.Color.Red; PrintOverride.SvgColor = System.Drawing.Color.LawnGreen; PrintOverride.BoxColor = System.Drawing.Color.Red; PrintOverride.ChangeBarColor = System.Drawing.Color.Red; PrintOverride.DebugColor = System.Drawing.Color.CadetBlue; } return writer.DirectContent; } //private string CreateFileName(string procNumber, string sectNumber, string sectTitle) //{ // return FixFileName(procNumber + "_" + ((sectNumber ?? "") != "" ? sectNumber : sectTitle)); //} //private string CreateFileName(string procNumber) //{ // return FixFileName(procNumber); //} //private string FixFileName(string name) //{ // return Regex.Replace(name, "[ .,/]", "_") + ".pdf"; //} int _StepPageNumber = 0; private VlnSvgPageHelper _MyHelper = null; //private static PdfReader _MyFoldoutReader = null; //private static SectionInfo _MyFoldoutSection = null; private static List _MyFoldoutReader = null; private static List _MyFoldoutSection = null; private string Print(ProcedureInfo myProcedure, string pdfFolder) { if (_MyFoldoutReader != null) _MyFoldoutReader.Clear(); else _MyFoldoutReader = new List(); if (_MyFoldoutSection != null) _MyFoldoutSection.Clear(); else _MyFoldoutSection = new List(); if (myProcedure.Sections != null) { int cnt = 0; foreach (SectionInfo mySection in myProcedure.Sections) { if ((myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.SectionLevelFoldouts && mySection.MyContent.Number.ToUpper() == "FOLDOUT") || (myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.AlternateFloatingFoldout && mySection.MyContent.Text.ToUpper().Contains("FOLDOUT"))) { // if floating foldouts, need a list of sections & foldoutreaders. Just do first for now. _MyFoldoutSection.Add(mySection); string foldoutPdf = PrintProcedureOrFoldout(myProcedure, mySection, Volian.Base.Library.VlnSettings.TemporaryFolder + @"\Foldout" + cnt.ToString() + @".pdf"); _MyFoldoutReader.Add(foldoutPdf != null ? new PdfReader(foldoutPdf) : null); cnt++; } } } OnStatusChanged("Print " + myProcedure.DisplayNumber, PromsPrinterStatusType.Start); string outputFileName = pdfFolder + "\\" + PDFFile; if (!OverWrite && File.Exists(outputFileName)) { if (MessageBox.Show(outputFileName + " exists. Overwrite file?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No) return null; } return PrintProcedureOrFoldout(myProcedure, null, outputFileName); } // See if the last non Foldout Section has a Final Message. private int GetFinalMessageSectionID(ProcedureInfo myProcedure, bool doingFoldout) { if (!doingFoldout) { // Work backwards because we don't want to include any foldouts. Find the last section that is not // a foldout. If it has a final message, this is the 'last section' and should have a final message. // If it doesn't have a final message, then none should be printed. int cntSect = myProcedure.Sections.Count; for (int i = cntSect - 1; i >= 0; i--) { SectionInfo mySection = myProcedure.Sections[i] as SectionInfo; if (!mySection.DisplayText.ToUpper().Contains("FOLDOUT")) { if (mySection.MyDocStyle.Final != null && mySection.MyDocStyle.Final.Message != null && mySection.MyDocStyle.Final.Message.Length > 0) return mySection.ItemID; else return -1; } } } return -1; } private bool _AllowAllWatermarks = false; public bool AllowAllWatermarks { get { return _AllowAllWatermarks; } set { _AllowAllWatermarks = value; } } private string PrintProcedureOrFoldout(ProcedureInfo myProcedure, SectionInfo myFoldoutSection, string outputFileName) { bool doingFoldout = myFoldoutSection != null; // The following line accounts for 16bit OverrideLeftMargin when the 'Absolute' attribute is used in the genmac. // We don't want to use the OverrideLeftMargin when 'Absolute' is used in the genmac. // It's set here because the Volian.Svg.Library cannot call back to Volian.Print.Library to get this value. Svg.Library.Svg.AbsoluteOffset = new PointF(2 * 72F / (float)myProcedure.ActiveFormat.PlantFormat.FormatData.Font.CPI, -9.5F); // Create an MSWord Pdf // Setup a pdf Document for printing OnStatusChanged("Before OpenDoc", PromsPrinterStatusType.Before); PdfContentByte cb = OpenDoc(outputFileName); if (cb == null) return null; OnStatusChanged("Before NewPage", PromsPrinterStatusType.Before); cb.PdfDocument.NewPage(); // Start of print OnStatusChanged("After NewPage", PromsPrinterStatusType.NewPage); if (myProcedure.Sections == null) { MessageBox.Show("This procedure has no content and will not be printed.", "Empty Procedure", MessageBoxButtons.OK, MessageBoxIcon.Information); return null; } OnStatusChanged(myProcedure.DisplayNumber, PromsPrinterStatusType.ProgressSetup, myProcedure.Sections.Count); int progress = 0; int finalMessageSectionID = GetFinalMessageSectionID(myProcedure, doingFoldout); foreach (SectionInfo mySection in myProcedure.Sections) { if (((mySection.MyContent.Number.ToUpper() == "FOLDOUT" && myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.SectionLevelFoldouts) || (myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.AlternateFloatingFoldout && mySection.MyContent.Text.ToUpper().Contains("FOLDOUT"))) != doingFoldout) continue; if (myFoldoutSection != null && myFoldoutSection.ItemID != mySection.ItemID) continue; PrintOverride.CompressSuper = mySection.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.CompressHPSuper; PrintOverride.CompressSub = mySection.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.CompressHPSub; OnStatusChanged((mySection.DisplayNumber ?? "") == "" ? mySection.DisplayText : mySection.DisplayNumber, PromsPrinterStatusType.Progress, progress++); // Set up Helper for the particular Section if (_MyHelper == null) { string hlsText = ""; if (mySection.IsStepSection && mySection.Steps.Count > 0) hlsText = mySection.Steps[0].DisplayText; // save the High level step text for use in the page list cb.PdfWriter.PageEvent = _MyHelper = new VlnSvgPageHelper(mySection, this, hlsText); _MyHelper.AllowAllWatermarks = AllowAllWatermarks; _MyHelper.MyPdfWriter = cb.PdfWriter; _MyHelper.CreatingFoldoutPage = doingFoldout; _MyHelper.MyPdfContentByte = cb; if (!mySection.IsStepSection) _MyHelper.PageBookmarks.Add((ItemInfo)mySection, ((mySection.DisplayNumber ?? "") == "" ? "" : mySection.DisplayNumber + " - ") + mySection.DisplayText, null); if (DebugOutput) { // 16-bit background string procedureFileName = BackgroundFolder + "\\" + PDFFile;//CreateFileName(myProcedure.DisplayNumber); FileInfo VEPromsFile = new FileInfo(procedureFileName); if (VEPromsFile.Exists && !doingFoldout) { _MyHelper.BackgroundFile = procedureFileName; // X argument below: accounts for 16-bit pdf OverrideLeftMargin = -2 characters at the plant format's default Font's // characters per inch. // 16bit OverrideLeftMargin, defined as -2 in driver\drvin.rtf, - override took 2 characters out, so we're adding it back in: if (mySection.ActiveFormat.Name.ToUpper().StartsWith("WST") || _MyHelper.Back32BitPROMS) // compare folder contains PROMS generated PDF _MyHelper.BackgroundOffset = new PointF(0, 0); else _MyHelper.BackgroundOffset = new PointF(2 * 72F / (float)myProcedure.ActiveFormat.PlantFormat.FormatData.Font.CPI, -9.5F); _MyHelper.BackgroundPageOffset = 0; } _MyHelper.WatermarkLayer = _WatermarkLayer; _MyHelper.PageListLayer = _PagelistLayer; _MyHelper.TextLayer = _TextLayer; _MyHelper.BackgroundLayer = _BackgroundLayer; _MyHelper.DebugLayer = _DebugLayer; } _MyHelper.Rev = _Rev; _MyHelper.Watermark = _Watermark; _MyHelper.DoZoomOMatic = DebugOutput; _MyHelper.OriginalPageBreak = OriginalPageBreak; OnStatusChanged("After Set PageEvent", PromsPrinterStatusType.SetPageEvent); } else { //Console.WriteLine("'{0}' PromsPrinter", mySection.DisplayText); if (mySection.SectionConfig.Section_Pagination == SectionConfig.SectionPagination.Separate) _MyHelper.DidFirstPageDocStyle = false; if (!mySection.IsStepSection) _MyHelper.PageBookmarks.Add((ItemInfo)mySection, ((mySection.DisplayNumber ?? "") == "" ? "" : mySection.DisplayNumber + " - ") + mySection.DisplayText, null); _MyHelper.MySection = mySection; OnStatusChanged("After Set Svg", PromsPrinterStatusType.SetSVG); } PdfReader readerWord = null; string myPdfFile = null; _MyHelper.FinalMessageSectionID = finalMessageSectionID; // set VlnSvgPageHelper with the finalMessageSectionID //SectionConfig sc = mySection.MyConfig as SectionConfig; if (mySection.IsAutoTOCSection) GenerateTOC(mySection, myProcedure, cb, _TextLayer); else { if (mySection.IsStepSection) { if (mySection.Steps != null && mySection.Steps.Count > 0) { // get first step to send to floading foldout indx.&& MyItemInfo.FoldoutIndex>-1) ItemInfo firstStep = mySection.Steps[0]; if (firstStep.FoldoutIndex() > -1) DoFoldoutPage(cb, "Beginning of Step Section", _TextLayer, _MyHelper, firstStep.FoldoutIndex()); } CreateStepPdf(mySection, cb); } else CreateWordDocPdf(cb, mySection, ref readerWord, ref myPdfFile); } } if (_MyHelper != null && _MyHelper.BackgroundFile != null) { _MyHelper.MySvg = null; while (cb.PdfWriter.CurrentPageNumber <= _MyHelper.BackgroundPageCount) { PrintTextMessage(cb, "No Proms Output", _TextLayer); cb.PdfDocument.NewPage(); // only have 16bit pages left (for DebugMode) DebugPagination.WriteLine("{0:D6},'{1}'", _MyHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "No PROMS Output"); } } OnStatusChanged(myProcedure.DisplayNumber + " PDF Creation Completed", PromsPrinterStatusType.Progress, progress); DebugPagination.TotalPages += cb.PdfWriter.CurrentPageNumber; CloseDocument(cb, outputFileName); _MyHelper = null; return outputFileName; } public void CreateWordDocPdf(PdfContentByte cb, SectionInfo mySection, ref PdfReader readerWord, ref string myPdfFile) { _MyHelper.MySection = mySection; myPdfFile = BuildMSWordPDF(mySection); try { readerWord = myPdfFile != null ? new PdfReader(myPdfFile) : null; OnStatusChanged("Get Section", PromsPrinterStatusType.GetSection); int sectPageCount = 0; float locEndOfWordDoc = 0; float pdfSize = 0; using (PdfInfo myPdf = PdfInfo.Get(mySection)) { sectPageCount = (int)(Math.Ceiling(myPdf.PageCount)); locEndOfWordDoc = (float)(myPdf.PageCount - (sectPageCount - 1)) * 100; pdfSize = (float)myPdf.PageCount; } string tocKey = string.Format("TOC{0}", mySection.ItemID); if (_MyHelper.MyTOCPageCounts.ContainsKey(tocKey)) { PageCount pc = _MyHelper.MyTOCPageCounts[tocKey]; // add 1 because have not hit end page yet. pc.Total = _MyHelper.CurrentTOCPageNumber + 1; pc.DrawTemplates(); } else { // see if this section will be added to the table of content. This is for sections that // precede tha actual Automated TOC section. SectionConfig sc = mySection.MyConfig as SectionConfig; if (sc != null && sc.Section_TOC == "Y") { string tockey = "TOC" + mySection.ItemID.ToString(); if (!_MyHelper.MyTOCPageNums.ContainsKey(tockey)) // increment the CurrentTOCPageNumber by 1 since we haven't hit an // endpage yet, and that's what increments it to the current page number. _MyHelper.MyTOCPageNums.Add(tockey, _MyHelper.CurrentTOCPageNumber + 1); } } float origYoff = (float)mySection.MyDocStyle.Layout.TopMargin; for (int ii = 0; ii < sectPageCount; ii++) { int pageNumber = 1 + ii; if (((mySection.MyDocStyle.StructureStyle.Style ?? 0) & E_DocStructStyle.UseSectionFoldout) != 0) DoFoldoutPage(cb, "Word Document", _TextLayer, _MyHelper, 0); if (readerWord != null) { bool doimport2 = true; PdfImportedPage fgPage = null; try { fgPage = cb.PdfWriter.GetImportedPage(readerWord, ii + 1); } catch (Exception ex) { Console.WriteLine(ex); doimport2 = false; } OnStatusChanged("Read MSWord", PromsPrinterStatusType.ReadMSWord); if (doimport2) { float yoff = 0; if (_MyHelper.DidFirstPageDocStyle) yoff = origYoff - (float)mySection.MyDocStyle.Layout.TopMargin; AddImportedPageToLayer(cb.PdfWriter.DirectContent, _MSWordLayer, fgPage, (float)(mySection.MyDocStyle.Layout.MSWordXAdj??0), (float)(mySection.MyDocStyle.Layout.MSWordYAdj??0)+yoff); DebugPagination.WriteLine("{0:D6},'{1}',{2}", _MyHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, mySection.ShortPath,pageNumber); } if (ii == sectPageCount - 1) { // if there's and end message, add it to the appropriate location on the last page of // the word document: if ((mySection.MyDocStyle.End.Message ?? "") != "") { float ylocation = cb.PdfDocument.PageSize.Height - ((float)mySection.MyDocStyle.Layout.TopMargin + locEndOfWordDoc * 72); // 72 - pts per inch. iTextSharp.text.Font fnt = VolianPdf.GetFont(mySection.MyDocStyle.End.Font.WindowsFont); fnt.Color = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Black)); iTextSharp.text.Paragraph para = new Paragraph(mySection.MyDocStyle.End.FixedMessage, fnt); float wtpm = (float)mySection.MyDocStyle.Layout.PageWidth - (float)mySection.MyDocStyle.Layout.LeftMargin; float centerpos = (float)mySection.MyDocStyle.Layout.LeftMargin + (wtpm - (mySection.MyDocStyle.End.Message.Length * mySection.MyDocStyle.End.Font.CharsToTwips)) / 2; float yBottomMargin = Math.Max(0, (float)mySection.MyDocStyle.Layout.TopMargin - (float)mySection.MyDocStyle.Layout.PageLength - 2 * vlnPrintObject.SixLinesPerInch); Rtf2Pdf.TextAt(cb, para, centerpos, ylocation + 6, 100, 12, "", yBottomMargin); } } OnStatusChanged("Merge MSWord", PromsPrinterStatusType.MergeMSWord); } OnStatusChanged("Before NewPage", PromsPrinterStatusType.Before); if (mySection.MyDocStyle.LandscapePageList)// && mySection.MyDocStyle.Layout.PageWidth > mySection.MyDocStyle.Layout.PageLength) _MyHelper.IsLandscape = true; else _MyHelper.IsLandscape = false; cb.PdfDocument.NewPage(); // Word Document // if this document style has another style that is for pages other than first, we need to // reset the document style off of this section AND reset docstyle values used. _MyHelper.DidFirstPageDocStyle = true; DebugPagination.WriteLine("CreateWordDocPdf"); if ((mySection.MyDocStyle.StructureStyle.Where & E_DocStyleUse.UseOnFirstPage) > 0) _MyHelper.MySection = mySection; // this resets the docstyle/pagestyle if pagehelper OnStatusChanged("After NewPage", PromsPrinterStatusType.NewPage); } } catch (Exception ex) { cb.PdfDocument.NewPage(); // can we put out 'error on page'? } } private void GenerateTOC(SectionInfo tocSection, ProcedureInfo myProcedure, PdfContentByte cb, PdfLayer textLayer) { iTextSharp.text.pdf.PdfWriter writer = cb.PdfWriter; float _PointsPerPage = 792; float yTopMargin = _PointsPerPage - (float)tocSection.MyDocStyle.Layout.TopMargin; float yBottomMargin = Math.Max(0, yTopMargin - (float)tocSection.MyDocStyle.Layout.PageLength); // - 2 * vlnPrintObject.SixLinesPerInch); if (textLayer != null) cb.BeginLayer(textLayer); TableOfContentsData tOfC = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData; ItemInfo procItem = ItemInfo.Get(myProcedure.ItemID); lastyLocation = 0; AddSectionToTOC(tocSection, procItem, tOfC, cb, yTopMargin, 0); if (textLayer != null) cb.EndLayer(); cb.PdfDocument.NewPage(); _NoBreakYOffset = 0; } float lastyLocation = 0; private string GetRtfToC(string txt, TableOfContentsData tOfCData) { StringBuilder _RtfSB = new StringBuilder(); Volian.Controls.Library.DisplayText toctxt = new Volian.Controls.Library.DisplayText(txt, tOfCData.Font, false); System.Drawing.Font myFont = toctxt.TextFont.WindowsFont; _RtfSB.Append(vlnPrintObject.AddFontTable(myFont)); _RtfSB.Append(toctxt.StartText); _RtfSB.Append("}"); return _RtfSB.ToString(); } private float AddSectionToTOC(SectionInfo tocSection, ItemInfo ii, TableOfContentsData tOfC, PdfContentByte cb, float yPageStart, float yLocation) { // The following adjustments are for WCN1: // for xAdjNumber: 6 is for 1 char less in 16bit (\promsnt\exe\print\tabocont.c, method 'howMany'. // 1.2 is a tweak to get output to match between 16 & 32 bit. // for xAdjTitle: .8 & 1.2 are both tweaks to get output to match. // for xAdjTitleIndent: 6 is for 1 char less. 2.4 is a tweak float xAdjNumber = -6 + 1.2F; float xAdjTitle = .8F + 1.2F; float xAdjTitleIndent = -6 + 2.4F; float yadj = 0.5F; // tweak to get 16 & 32 bit output to match. float yPageStartAdj = yPageStart - yadj; float leftMargin = (float)tocSection.MyDocStyle.Layout.LeftMargin; float secNumPos = (float)tOfC.TofCSecNumPos + xAdjNumber; float secTitlePos = (float)tOfC.TofCSecTitlePos + xAdjTitle; float secPagePos = (float)tOfC.TofCPageNumPos + xAdjNumber; float height = tOfC.Font.WindowsFont.Size * 1.5F; if (ii.Sections != null) { foreach (SectionInfo mySection in ii.Sections) { SectionConfig sc = mySection.MyConfig as SectionConfig; if ((mySection.MyDocStyle != null && mySection.MyDocStyle.IncludeInTOC && (sc == null || sc.Section_TOC != "Y")) || ((mySection.MyDocStyle == null || !mySection.MyDocStyle.IncludeInTOC) && (sc != null && sc.Section_TOC == "Y"))) { // need to do the section number, section title & page number. Page number // has to be put on at end after number of page is known, so use a Template. string tmptxt = mySection.MyContent.Number == null || mySection.MyContent.Number == "" ? " " : mySection.MyContent.Number; string rtfText = GetRtfToC(tmptxt, tOfC); Paragraph myparagraphn = vlnPrintObject.RtfToParagraph(rtfText); float width = 0; foreach (Chunk chkt in myparagraphn.Chunks) width += chkt.GetWidthPoint(); float numwidth = width; float yBottomMargin = yPageStart - (float)tocSection.MyDocStyle.Layout.PageLength + (2 * vlnPrintObject.SixLinesPerInch); Rtf2Pdf.Offset = new PointF(0, 2.5F); // for indenting of subsections, count up tree. Only start indenting // at third level, i.e. not indent on 1.0 and 1.1, but indent on 1.1.1: int level = 0; ItemInfo iilvl = mySection as ItemInfo; while (!iilvl.IsProcedure) { level++; iilvl = iilvl.MyParent; } // check what level the plant wants the auto ToC indented: int tofCNumLevels = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCNumLevels ?? 0; if (tofCNumLevels > 0 && level > tofCNumLevels) return yLocation; level = level <= 2 ? 0 : level - 2; // no indenting until third level float indentOffset = (level * (secTitlePos - secNumPos)); float retval = Rtf2Pdf.TextAt(cb, myparagraphn, leftMargin + secNumPos + indentOffset, yPageStart - yLocation, width * 1.3F, height, "", yBottomMargin); if (retval == 0) // do a newpage, it couldn't fit on current page. { cb.PdfDocument.NewPage(); yLocation = 0; retval = Rtf2Pdf.TextAt(cb, myparagraphn, leftMargin + secNumPos + indentOffset, yPageStart - yLocation, width * 1.3F, height, "", yBottomMargin); } // if the starting column of text would be in 'middle of' the number, just put it // a few spaces after the number. The '18' below represents 3 chars. float adjSecTitlePos = secTitlePos + indentOffset + (level * 6); if (secNumPos + numwidth + indentOffset > secTitlePos + indentOffset) adjSecTitlePos = secNumPos + numwidth + 18 - xAdjTitleIndent + indentOffset; rtfText = GetRtfToC(mySection.MyContent.Text, tOfC); Paragraph myparagrapht = vlnPrintObject.RtfToParagraph(rtfText); width = secPagePos - adjSecTitlePos - 6; retval = Rtf2Pdf.TextAt(cb, myparagrapht, leftMargin + adjSecTitlePos, yPageStart - yLocation, width, height, "", yBottomMargin); // add a template for the page number: if (lastyLocation != 0 && ((lastyLocation - retval) > vlnPrintObject.SixLinesPerInch)) yLocation += (lastyLocation - retval - vlnPrintObject.SixLinesPerInch); lastyLocation = retval; // if the space character is not null & is not a space, the we've got to put out // these between the section title & the page number if (tOfC.TofCSpaceChar != null && tOfC.TofCSpaceChar != "" && tOfC.TofCSpaceChar != " ") { width = 0; foreach (Chunk chkt in myparagrapht.Chunks) width += chkt.GetWidthPoint(); float startSpace = leftMargin + adjSecTitlePos + width; float endSpace = leftMargin + secPagePos; float numSpace = endSpace - startSpace; string spaceStr = ""; rtfText = GetRtfToC(tOfC.TofCSpaceChar, tOfC); Paragraph tmpmyparagraph = vlnPrintObject.RtfToParagraph(rtfText); float spacchrwid = 0; foreach (Chunk chkt in tmpmyparagraph.Chunks) spacchrwid += chkt.GetWidthPoint(); while (numSpace > 0) { spaceStr = spaceStr + tOfC.TofCSpaceChar; numSpace -= spacchrwid; } rtfText = GetRtfToC(spaceStr, tOfC); Paragraph myparagraphs = vlnPrintObject.RtfToParagraph(rtfText); retval = Rtf2Pdf.TextAt(cb, myparagraphs, startSpace, yPageStart - yLocation, endSpace - startSpace, height, "", yBottomMargin); } // if in the pre-table of content list, just put the page number out as text. // otherwise, add a template _MyHelper.MyTOCPageCounts string key = "TOC" + mySection.ItemID.ToString(); if (mySection.IsAutoTOCSection || _MyHelper.MyTOCPageNums.ContainsKey(key)) { string pnum = _MyHelper.MyTOCPageNums.ContainsKey(key) ? _MyHelper.MyTOCPageNums[key].ToString() : (_MyHelper.CurrentTOCPageNumber + 1).ToString(); rtfText = GetRtfToC(pnum, tOfC); Paragraph myparagraphp = vlnPrintObject.RtfToParagraph(rtfText); width = pnum.Length * 6; retval = Rtf2Pdf.TextAt(cb, myparagraphp, leftMargin + secPagePos, yPageStart - yLocation, width, height, "", yBottomMargin); } else AddTemplateTOCPageCounts(tOfC, yLocation, yPageStartAdj, leftMargin, secPagePos, height, mySection); yLocation += vlnPrintObject.SixLinesPerInch; } yLocation = AddSectionToTOC(tocSection, mySection, tOfC, cb, yPageStart, yLocation); } } return yLocation; } private void AddTemplateTOCPageCounts(TableOfContentsData tOfC, float yLocation, float yPageStartAdj, float leftMargin, float secPagePos, float height, SectionInfo mySection) { string key = "TOC" + mySection.ItemID.ToString(); PdfTemplate tmp = _MyHelper.MyTOCPageCounts.AddToTemplateList(key, _MyHelper.MyPdfWriter, "{TOCPAGE}", tOfC.Font.WindowsFont, Element.ALIGN_LEFT, PrintOverride.TextColor); _MyHelper.MyPdfContentByte.AddTemplate(tmp, leftMargin + secPagePos, (yPageStartAdj - yLocation) - height / 2); } private static void PrintTextMessage(PdfContentByte cb, string message, PdfLayer textLayer) { if (textLayer != null) cb.BeginLayer(textLayer); float fontSize = 30; ColumnText ct = new ColumnText(cb); iTextSharp.text.Font font = FontFactory.GetFont("Arial", fontSize, new iTextSharp.text.Color(PrintOverride.TextColor)); Chunk chk = new Chunk(message, font); float xCenter = cb.PdfDocument.PageSize.Width / 2; float yCenter = cb.PdfDocument.PageSize.Height / 2; float width = chk.GetWidthPoint() * 1.01F; float height = fontSize * 1.5F; ct.SetSimpleColumn(xCenter - width / 2, yCenter - height / 2, xCenter + width / 2, yCenter + height / 2); Phrase ph = new Phrase(chk); ct.AddElement(ph); cb.SetColorFill(new iTextSharp.text.Color(PrintOverride.TextColor)); ct.Go(); if (textLayer != null) cb.EndLayer(); } private float _NoBreakYOffset = 0; private float _NoBreakYPageStart = 0; private void CreateStepPdf(SectionInfo section, PdfContentByte cb) { iTextSharp.text.pdf.PdfWriter writer = cb.PdfWriter; ItemInfo myItemInfo = section as ItemInfo; // 792: 72 * 11 inches - TopRow - Top is high value float _PointsPerPage = 792; float yTopMargin = _PointsPerPage - (float)myItemInfo.MyDocStyle.Layout.TopMargin; // the following line was modified to comment out the - 2 * SixLinesPerInch. this fixed a pagination problem with WCN EMG E-3. float yBottomMargin = Math.Max(0, yTopMargin - (float)myItemInfo.MyDocStyle.Layout.PageLength); // - 2 * vlnPrintObject.SixLinesPerInch); vlnParagraph.Prefix = myItemInfo.Path; Rtf2Pdf.PdfDebug = true; Rtf2Pdf.Offset = new PointF(0, 2.5F); _MyHelper.ChangeBarDefinition = MyChangeBarDefinition; vlnParagraph myParagraph = new vlnParagraph(null, cb, myItemInfo, (float)myItemInfo.MyDocStyle.Layout.LeftMargin, _NoBreakYOffset, 0, myItemInfo.ColumnMode, myItemInfo.ActiveFormat, null, null); float localYPageStart = 0; float yPageStart = yTopMargin; if (myItemInfo.HasChildren) localYPageStart = myParagraph.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); else if(!myItemInfo.MyDocStyle.OptionalSectionContent) PrintTextMessage(cb, "No Section Content", _TextLayer); SectionConfig.SectionPagination sp = SectionConfig.SectionPagination.Separate; // always the default if ( section.NextItemCount > 0) { SectionInfo tmpii = SectionInfo.Get(section.NextItem.ItemID); // if this section & the next section are not accessory pages, see if there is continuous pagination, // i.e. no page break between them. if (section.IsStepSection && tmpii.IsStepSection) { SectionConfig sc = tmpii.SectionConfig; try { if (sc != null) sp = sc.Section_Pagination; } catch (Exception ex) { sp = SectionConfig.SectionPagination.Separate; } } } if (sp == SectionConfig.SectionPagination.Separate) { cb.PdfDocument.NewPage(); // end of step section _NoBreakYOffset = 0; yPageStart = yTopMargin; } else { if (_MyHelper.BottomMessage != null) { _MyHelper.DrawBottomMessage(cb); localYPageStart += 12; myParagraph.YBottomMost += 24; // two lines. } float tmplocal = localYPageStart; _NoBreakYOffset = myParagraph.YBottomMost; float yOffset = localYPageStart - yTopMargin; _NoBreakYOffset -= yOffset; yPageStart = localYPageStart; Volian.Base.Library.DebugText.WriteLine("NOBREAK:{0},'{1}','{2}','{3}','{4}','{5}'", section.ItemID, tmplocal, yTopMargin, localYPageStart, _NoBreakYOffset, myParagraph.YBottomMost); } OnStatusChanged("StepSection converted to PDF " + section.ShortPath, PromsPrinterStatusType.BuildStep); } public static void DoFoldoutPage(PdfContentByte cb, string str, PdfLayer textLayer) { cb.Circle(400, 100, 50); PrintTextMessage(cb, "Foldout for: " + str, textLayer); cb.PdfDocument.NewPage(); // Temporary for foldout/16bit-32bit page alignment } public static void DoFoldoutPage(PdfContentByte cb, string str, PdfLayer textLayer, VlnSvgPageHelper myPageHelper, int foldoutindx) { if (_MyFoldoutSection == null || _MyFoldoutSection.Count==0) return; SectionInfo saveSect = myPageHelper.MySection; myPageHelper.MySection = _MyFoldoutSection[foldoutindx]; myPageHelper.OnFoldoutPage = true; if (_MyFoldoutReader != null) { bool doimport2 = true; PdfImportedPage fgPage = null; try { fgPage = cb.PdfWriter.GetImportedPage(_MyFoldoutReader[foldoutindx],1); } catch (Exception ex) { Console.WriteLine(ex); doimport2 = false; } if (doimport2) { AddImportedPageToLayer(cb.PdfWriter.DirectContent, textLayer, fgPage, 0, 0); DebugPagination.WriteLine("{0:D6},'{1}',{2}", myPageHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "Foldout", 1); } } //PrintTextMessage(cb, "Foldout for: " + str, textLayer); cb.PdfDocument.NewPage(); // Temporary for foldout/16bit-32bit page alignment myPageHelper.MySection = saveSect; myPageHelper.OnFoldoutPage = false; } public static byte[] WatermarkPDF(byte[] buffer, string watermark) { PdfReader reader = new PdfReader(buffer); MemoryStream ms = new MemoryStream(); PdfStamper stamper = new PdfStamper(reader, ms); PdfLayer layer = new PdfLayer("Watermark", stamper.Writer); layer.SetPrint("Print", true); for (int i = 1; i <= reader.NumberOfPages; i++) { PdfContentByte cb = stamper.GetUnderContent(i); cb.SaveState(); cb.BeginLayer(layer); SvgWatermark wm = new SvgWatermark(cb, watermark, System.Drawing.Color.Blue, .15F); wm.SetSquareDotPattern(.7F); //wm.SetTextPattern(8, 3); //wm.SetTextPattern2(8); //wm.SetHashPattern(1, 6); //wm.SetDotPattern(5, 2); wm.Draw(); cb.EndLayer(); cb.RestoreState(); } stamper.Close(); /* cb.SaveState(); if (_WatermarkLayer != null) cb.BeginLayer(_WatermarkLayer); SvgWatermark myWatermark = new SvgWatermark(cb, Watermark, System.Drawing.Color.Blue, .15F); myWatermark.SetSquareDotPattern(.7F); myWatermark.Draw(); if (_WatermarkLayer != null) cb.EndLayer(); cb.RestoreState(); */ return ms.ToArray(); } } }