2876 lines
137 KiB
C#

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;
using JR.Utils.GUI.Forms;
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,
LoadVlnParagraph
}
public class PromsPrinter
{
public bool NeedSupInfoBreak = false;
public E_SupInfoPrintType SupInfoPrintType = E_SupInfoPrintType.None;
// used to link supinfo steps in pdf
public int SupInfoPdfPageCount = -1;
private Dictionary<int, int> _SupInfoPdfPage;
public Dictionary<int, int> SupInfoPdfPage
{
get { return _SupInfoPdfPage; }
set { _SupInfoPdfPage = value; }
}
private bool _DoingFacingPage = false; // used to flag actual pdf generation of facing page within final print (so no section titles get printed)
public bool DoingFacingPage
{
get { return _DoingFacingPage; }
set { _DoingFacingPage = value; }
}
// used to save word sections with resolved ROs (for export file generated from approve)
private Dictionary<int, byte[]> _DocReplace;
public Dictionary<int, byte[]> DocReplace
{
get { return _DocReplace; }
set { _DocReplace = value; }
}
private bool _SaveLinks = false;
public bool SaveLinks
{
get { return _SaveLinks; }
set { _SaveLinks = value; }
}
// C2021-010: Remove trailing returns/spaces & manual page breaks & allow save.
// Use these 2 lists to track the items that will need to be saved after removing trailing newlines/spaces or
// manual page breaks, if the user selects to do that.
private List<int> _RemoveTrailingHardReturnsAndSpaces = null;
public List<int> RemoveTrailingHardReturnsAndSpaces
{
get { return _RemoveTrailingHardReturnsAndSpaces; }
set { _RemoveTrailingHardReturnsAndSpaces = value; }
}
private List<int> _RemoveManualPageBreaks = null;
public List<int> RemoveManualPageBreaks
{
get { return _RemoveManualPageBreaks; }
set { _RemoveManualPageBreaks = value; }
}
private string _Prefix = ""; // RHM20150506 Multiline ItemID TextBox
public string Prefix
{
get { return _Prefix; }
set { _Prefix = value; }
}
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public event PromsPrinterStatusEvent StatusChanged;
internal void OnStatusChanged(object sender, PromsPrintStatusArgs args)
{
if (StatusChanged != null)
StatusChanged(sender, args);
}
internal void OnStatusChanged(string myStatus, PromsPrinterStatusType type)
{
OnStatusChanged(this, new PromsPrintStatusArgs(myStatus, type));
}
public void OnStatusChanged(string msg)
{
OnStatusChanged(this, new PromsPrintStatusArgs(msg, PromsPrinterStatusType.General));
}
internal void OnStatusChanged(string myStatus, PromsPrinterStatusType type, int progress)
{
OnStatusChanged(this, new PromsPrintStatusArgs(myStatus, type, progress));
}
private string _Rev;
private ItemInfo _MyItem;
public ItemInfo MyItem
{
get { return _MyItem; }
set { _MyItem = value; }
}
private string _Watermark;
private string _WatermarkColor;
//C2018-009 print PROMS version
private string _PromsVersion = "";
public string PromsVersion
{
get { return _PromsVersion; }
set { _PromsVersion = value; }
}
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; }
}
private bool _InsertBlankPages;
public bool InsertBlankPages
{
get { return _InsertBlankPages; }
set { _InsertBlankPages = value; }
}
private bool _BatchPrint = true; // flags that a batch-type print is occurring, i.e. AllProcedures or Automatic testing
public bool BatchPrint
{
get { return _BatchPrint; }
set { _BatchPrint = value; }
}
// B2020-159: When printing, if forced pagination errors occurred (see Pagination.cs), put up a dialog with
// the places they occurred. Do not do this is running baseline/automatic print testing.
private static List<string> _ForcedPaginations = null;
public static List<string> ForcedPaginations
{
get { return PromsPrinter._ForcedPaginations; }
set { PromsPrinter._ForcedPaginations = value; }
}
public static DialogResult ReportForcedPaginations()
{
if (ForcedPaginations != null && ForcedPaginations.Count > 0)
{
string pnProbl = null;
foreach (string pstr in ForcedPaginations)
pnProbl = pnProbl + "\r\n" + pstr;
Clipboard.SetText(pnProbl);
return FlexibleMessageBox.Show(
"PROMS has identified location(s) in the PDF file that was created that may not have paginated correctly."
+ "\r\nOn or around the following pages should be reviewed to ensure that the procedure is correct."
+ "\r\nVerify that there is no missing text on the page(s) designated."
+ "\r\nIf not correct, the procedure writer will have to modify the procedure content or add hard returns."
+ "\r\nContact Volian if assistance is needed."
+ "\r\nThe following list was placed on the Windows Clipboard."
+ "\r\n\r\nPDF File\t\tSection/Step\t\t\tPDF Page No.\r\n" + pnProbl,
"Forced Pagination", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
return DialogResult.OK;
}
private static List<string> _TransPageNumProblems = null;
public static List<string> TransPageNumProblems
{
get { return PromsPrinter._TransPageNumProblems; }
set { PromsPrinter._TransPageNumProblems = value; }
}
public static void ClearTransPageNumProblems()
{
_TransPageNumProblems = null;
}
public static DialogResult ReportTransPageNumProblems()
{
if (TransPageNumProblems != null && TransPageNumProblems.Count > 0)
{
string pnProbl = null;
foreach (string pstr in TransPageNumProblems)
pnProbl = pnProbl + "\r\n" + pstr;
Clipboard.SetText(pnProbl);
return FlexibleMessageBox.Show("The following list was placed on the Windows Clipboard."
+ "\r\nIt shows the page numbers of the locations that are referenced by transitions."
+ "\r\nThis list, along with the PDF, can help you to determine the cause of the inconsistent page numbers."
+ "\r\n\r\nDo you want to also review the PDF output prior to the second pass printing?"
// C2017-018 Output Column Headers for Inconsistent Page Transitions
+ "\r\n\r\nItemID\tTransition Destination\tPage Pass 1\t Page Pass 2\r\n\r\n" + pnProbl,
"Inconsistent Transition Page Numbers", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
}
return DialogResult.No;
}
private ReaderHelper _MyReaderHelper;
public ReaderHelper MyReaderHelper
{
get { return _MyReaderHelper; }
set { _MyReaderHelper = value; }
}
private string _BlankPageText; // C2019-004: Allow user to define duplex blank page text
public string BlankPageText
{
get { return _BlankPageText; }
set { _BlankPageText = value; }
}
// use DidAll & MergeNotIncuded to know that printing all (not single) was done. Used w/ merge code to know when to return, i.e. not include in merged pdf
private bool _DidAll;
public bool DidAll // value passed in from frmPdfStatusForm
{
get { return _DidAll; }
set { _DidAll = value; }
}
private bool _MergeNotIncluded;
public bool MergeNotIncluded
{
get { return _MergeNotIncluded; }
set { _MergeNotIncluded = value; }
}
private MergedPdf _MergedPdf;
public MergedPdf MergedPdf
{
get { return _MergedPdf; }
set { _MergedPdf = value; }
}
public PromsPrinter(ItemInfo myItem, string rev, string watermark, bool debugOutput, bool origPgBrk, string backgroundFolder, bool openPDF, bool overWrite,
ChangeBarDefinition cbd, String pdfFile, bool insertBlankPages, bool batchPrint, string prefix, bool saveLinks, int removeTrailngHardReturnsAndManualPageBreaks, string blankPageText, bool didAll, MergedPdf mergedPdf, string watermarkColor)
{
Prefix = prefix; // RHM20150506 Multiline ItemID TextBox
_MyItem = myItem;
_Rev = rev;
_Watermark = watermark;
_WatermarkColor = watermarkColor;
_DebugOutput = debugOutput;
_BackgroundFolder = backgroundFolder;
_OpenPDF = openPDF;
_OverWrite = overWrite;
_MyChangeBarDefinition = cbd;
_PDFFile = pdfFile;
_OriginalPageBreak = origPgBrk;
_InsertBlankPages = insertBlankPages;
_BatchPrint = batchPrint;
_MyReaderHelper = new ReaderHelper(this);
_SaveLinks = saveLinks;
// C2021-010: Remove trailing returns/spaces & manual page breaks & allow save.
if (removeTrailngHardReturnsAndManualPageBreaks == 1 || removeTrailngHardReturnsAndManualPageBreaks == 3 ) RemoveTrailingHardReturnsAndSpaces = new List<int>();
if (removeTrailngHardReturnsAndManualPageBreaks == 2 || removeTrailngHardReturnsAndManualPageBreaks == 3) RemoveManualPageBreaks = new List<int>();
_BlankPageText = blankPageText;
_DidAll = didAll;
_MergeNotIncluded = false;
_MergedPdf = mergedPdf;
//_MyReaderHelper.LoadTree(myItem);
}
// Pass 1 PDF Name
private string _BeforePageNumberPdf = null;
public string BeforePageNumberPdf
{
get { return _BeforePageNumberPdf; }
set { _BeforePageNumberPdf = value; }
}
// Pass 2 PDF Name
private string _BeforePageNumber2Pdf = null;
public string BeforePageNumber2Pdf
{
get { return _BeforePageNumber2Pdf; }
set { _BeforePageNumber2Pdf = value; }
}
// B2019-152: MergedLandscapePages is a dictionary whose key is the pdf file name & values are all of the page numbers
// in that pdf that should have landscaped page numbers. These are added when the page is finished (onEndPage)
public static Dictionary<string, List<int>> MergedLandscapePages = null;
public string Print(string pdfFolder, bool makePlacekeeper, bool makeContinuousActionSummary)
{
if (_MyItem is ProcedureInfo)
{
ProcedureConfig pcfg = (ProcedureConfig)(_MyItem as ProcedureInfo).MyConfig;
if (DidAll && pcfg.Print_NotInMergeAll) // will be merging a pdf, so don't print this procedure if user set that on procedure propertures
{
_MergeNotIncluded = true;
return null;
}
// B2017-186 First do Procedures that don't have page number transitions
if (!(_MyItem.ActiveFormat.PlantFormat.FormatData.TransData.UseTransitionModifier ||
_MyItem.ActiveFormat.PlantFormat.FormatData.TransData.UseSpecificTransitionModifier))
{
// B2017-186 Do Facing Page SAMGs
if ((_MyItem as ProcedureInfo).ProcHasSupInfoData)
{
// Use two passes to print facing page supplemental information for SAMGs
// First pass gets pagination for the step sections and stores the associated supplemental information ids in
// the list StepSectPageBreaksForSupInfo off of the section object
// Second pass prints the supplemental information pdfs using the list generated in the first pass to know where to do the
// supplemental information page breaks & then merges in those pages when printing the step sections.
SectionInfo.ResetLookupStepSectPageBreaks(); // B2017-192: Reset lists for tracking page breaks
SectionInfo.ResetLookupStepSectPageBreaksForSupInfo();
SupInfoPrintType = E_SupInfoPrintType.DoPageBreaks;
string retstr = Print(_MyItem as ProcedureInfo, pdfFolder, false, false);
if (retstr == null) return null;
SupInfoPrintType = E_SupInfoPrintType.Merge;
string tmps = Print(_MyItem as ProcedureInfo, pdfFolder, false, false);
if (!BatchPrint && ForcedPaginations != null && ForcedPaginations.Count > 0) // B2020-159: Forced Pagination Reporting
{
ReportForcedPaginations();
ForcedPaginations.Clear();
}
return tmps;
}
else // B2017-186 Neither Facing Pages or Page Number Transitions
{
string tmpss = Print(_MyItem as ProcedureInfo, pdfFolder, makePlacekeeper, makeContinuousActionSummary);
if (!BatchPrint && ForcedPaginations != null && ForcedPaginations.Count > 0) // B2020-159: Forced Pagination Reporting
{
ReportForcedPaginations();
ForcedPaginations.Clear();
}
return tmpss;
}
}
else // B2017-186 Page Number Transitions
{
string retstr;
// if the plant uses transition modifiers and/or page num in transition format,
// need to do two passes. First pass, sets the pagenumbers for each item,
// 2nd pass fills in the page numbers in transitions.
DirectoryInfo di = new DirectoryInfo(pdfFolder + @"\PageNumberPass1");
if (!di.Exists) di.Create();
if ((_MyItem as ProcedureInfo).ProcHasSupInfoData)// B2017-186 Adds Facing Page Code to Page Number Transition Code
{
// Use two passes to print facing page supplemental information for SAMGs
// First pass gets pagination for the step sections and stores the associated supplemental information ids in
// the list StepSectPageBreaksForSupInfo off of the section object
// Second pass prints the supplemental information pdfs using the list generated in the first pass to know where to do the
// supplemental information page breaks & then merges in those pages when printing the step sections.
SupInfoPrintType = E_SupInfoPrintType.DoPageBreaks;
retstr = Print(_MyItem as ProcedureInfo, pdfFolder, false, false);
if (retstr == null) return null;
SupInfoPrintType = E_SupInfoPrintType.Merge;
}
retstr = Print(_MyItem as ProcedureInfo, pdfFolder + @"\PageNumberPass1", false, false);
if (retstr == null) return null;
BeforePageNumberPdf = retstr;
BeforePageNumber2Pdf = null; // C2017-018 Initialize Pass 2 PDF Name
ProcedureInfo.RefreshPageNumTransitions(_MyItem as ProcedureInfo);
_MyReaderHelper = new ReaderHelper(this);
retstr = Print(_MyItem as ProcedureInfo, pdfFolder, makePlacekeeper, makeContinuousActionSummary);
if (! BatchPrint && ForcedPaginations != null && ForcedPaginations.Count > 0) // B2020-159: Forced Pagination Reporting
{
ReportForcedPaginations();
ForcedPaginations.Clear();
}
if (TransPageNumProblems.Count > 0)
{
if (BatchPrint || (MessageBox.Show("Page Number Transitions may be fixed if a second pass is performed. Do you want to perform a second pass?", "Page Number Transition Errors", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes))
{
DirectoryInfo di1 = new DirectoryInfo(pdfFolder + @"\PageNumberPass2");
if (!di1.Exists) di1.Create();
FileInfo fi = new FileInfo(retstr);
// Save Pass 2 PDF Name
FileInfo fidest = new FileInfo(BeforePageNumber2Pdf = di1.FullName + @"\" + fi.Name);
if (fidest.Exists) fidest.Delete();
try
{
fi.MoveTo(di1.FullName + @"\" + fi.Name);
}
catch (Exception ex)
{
_MyLog.ErrorFormat("{0} During Save {1}", ex.GetType().FullName, ex.Message);
}
ClearTransPageNumProblems();
RefreshPageNumber(_MyItem);
ProcedureInfo.RefreshPageNumTransitions(_MyItem as ProcedureInfo);
_MyReaderHelper = new ReaderHelper(this);
retstr = Print(_MyItem as ProcedureInfo, pdfFolder, makePlacekeeper, makeContinuousActionSummary);
}
}
return retstr;
}
}
return "";
}
private void RefreshPageNumber(ItemInfo _MyItem)
{
// set all page numbers for all items under the passed in procedure item
_MyItem.PageNumber = _MyItem.PageNumberNextPass;
if (_MyItem.MyContent.ContentPartCount > 0)
{
foreach (PartInfo pi in _MyItem.MyContent.ContentParts)
{
foreach (ItemInfo ii in pi.MyItems)
RefreshPageNumber(ii);
}
}
}
internal string BuildMSWordPDF(SectionInfo section)
{
DateTime tStart = DateTime.Now;
string MSWordFile = null;
if (section.MyContent.ContentEntryCount == 1)
{
MSWordToPDF.DocReplace = DocReplace;
MSWordFile = MSWordToPDF.GetDocPdf(section, PrintOverride.TextColor);
MSWordToPDF.DocReplace = null;
GC.Collect(); // memory garbage collection
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)
{
if (cb.PdfDocument.PageSize.Height > cb.PdfDocument.PageSize.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 PdfLayer _PROMSVersionLayer; //C2018-009 print PROMS version
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);
_PROMSVersionLayer = new PdfLayer("PROMS Version", cb.PdfWriter); //C2018-009 print PROMS version
_PROMSVersionLayer.SetPrint("PROMS Version", true);
}
}
public static int ProcPageCount = -1; // Used to count page numbers in each pdf. This will be used if/when pdfs are merged together.
private void CloseDocument(string fileName)
{
int profileDepth = ProfileTimer.Push(">>>> CloseDocument");
try
{
ProcPageCount = MyContentByte.PdfWriter.CurrentPageNumber - 1;
MyContentByte.PdfDocument.Close();
MyContentByte = null;
}
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);
ProfileTimer.Pop(profileDepth);
}
private PdfContentByte _MyContentByte = null;
public PdfContentByte MyContentByte
{
get { return _MyContentByte; }
set
{
_MyContentByte = value;
if(value != null)MyReaderHelper.LoadTree(MyItem);
}
}
public void NewPage()
{
string path = Volian.Base.Library.vlnStackTrace.StackToStringLocal(2, 1);
NewPage(false);
}
public void NewPage(bool sectionChange)
{
// the first time we come in here we already printed the first page.
// we are now setting up the page size for the next page
iTextSharp.text.Rectangle rct = MyReaderHelper.MyPromsPrinter.MyContentByte.PdfDocument.PageSize;
// B2019-166 Only check for Word margins if the section changed
// - was getting next section's page margins prematurely (while still processing the a multi-page section)
// - this was changing the margins/orientation of other pages in the same Word section.
if (_MyHelper != null && sectionChange)
{
SectionInfo currentSection = _MyHelper.MySection;
SectionInfo nextSection = GetNextSection(currentSection); // _MyHelper.MySection.NextItem as SectionInfo;
//SectionConfig sc = (nextSection ?? currentSection).MyConfig as SectionConfig;
// If we are changing to a different section, then get the config from the nextSection
// else we are still printing in the same section so get the config from the current section
SectionConfig sc = ((!sectionChange || nextSection == null)? currentSection.MyConfig : nextSection.MyConfig) as SectionConfig;
bool wordMargins = (sc != null && sc.Section_WordMargin == "Y");
if (wordMargins)
{
if (nextSection != null && (sectionChange) && !nextSection.IsStepSection) //change to a word section
{
LastWordSection = nextSection;
_PageCountOfWordSection = 1;
MyReaderHelper.MySectionInfo = LastWordSection;
//ShowNeedForPageSize();
rct = MyReaderHelper.GetSize(LastWordSection, 1);
}
else if (!currentSection.IsStepSection) //current section is a word section
{
if (currentSection != LastWordSection)
{
LastWordSection = currentSection;
_PageCountOfWordSection = 1;
}
else
if (!_MyHelper.OnBlankPage) _PageCountOfWordSection++; // B2018-049: supplemental printing throws off page sizes
MyReaderHelper.MySectionInfo = LastWordSection;
//ShowNeedForPageSize();
rct = MyReaderHelper.GetSize(LastWordSection, _PageCountOfWordSection);
}
}
else // don't use Word margins
{
rct = PDFPageSize.UsePaperSize(MyItem.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
}
// C2018-004 create meta file for baseline compares
if (currentSection.IsStepSection)
Volian.Base.Library.BaselineMetaFile.WriteLine("{0}", rct);
else
Volian.Base.Library.BaselineMetaFile.WriteLine("UseWordMargins={0} {1} ", (wordMargins)?"Y":"N", rct);
//Console.WriteLine("\"{0}\"\t\"{1}\"\t\"{2}\"\t\"{3}\"\t{4}"
// , currentSection == null ? "" : currentSection.DisplayNumber + " " + currentSection.DisplayText
// , nextSection == null ? "" : nextSection.DisplayNumber + " " + nextSection.DisplayText
// , sectionChange, wordMargins,_PageCountOfWordSection);
}
// Bug Fix: B2016-135 when using a large page size word section, that large page size was being used for the foldout page
// save this for the next section which will be the large page size word section.
// Bug Fix: B2018-049 supplemental printing throws off page sizes (need to do same thing as fix for foldouts)
// Bug Fix: B2019-165 (Byron/Braidwood) also don't do this if the current section has Don't Include Duplex Foldout checkbox checked (automation tab of section properties)
if ((_MyFoldoutReader.Count > 0) && (_MyHelper != null && !((_MyHelper.MySection.MyConfig as SectionConfig).Section_DontIncludeDuplexFoldout) || (_MyHelper != null && _MyHelper.MySection != null && _MyHelper.MySection.MyProcedure.ProcHasSupInfoData)))
MyContentByte.PdfDocument.SetPageSize(NxtRCT);
else
MyContentByte.PdfDocument.SetPageSize(rct);
NxtRCT = rct;
MyContentByte.PdfDocument.NewPage();
}
private static bool _BaselineTesting = false; // Is the baseline being run (/P Commandline Parameter)
public static bool BaselineTesting
{
get { return PromsPrinter._BaselineTesting; }
set { PromsPrinter._BaselineTesting = value; }
}
private iTextSharp.text.Rectangle NxtRCT = PageSize.LETTER;
private SectionInfo GetNextSection(SectionInfo currentSection)
{
if (currentSection.Sections != null)
return currentSection.Sections[0].GetSectionInfo();
if (currentSection.NextItem != null)
return currentSection.NextItem.GetSectionInfo();
ItemInfo parent = currentSection.ActiveParent as ItemInfo;
while (parent != null && parent.NextItem == null)
parent = parent.ActiveParent as ItemInfo;
if (parent == null) return null;
return parent.NextItem.GetSectionInfo();
}
private SectionInfo _PreviousWordSection = null;
public SectionInfo PreviousWordSection
{
get { return _PreviousWordSection; }
set { _PreviousWordSection = value; }
}
private SectionInfo _LastWordSection = null;
public SectionInfo LastWordSection
{
get { return _LastWordSection; }
set
{
PreviousWordSection = _LastWordSection;
_LastWordSection = value;
}
}
private int _PageCountOfWordSection = 0;
//private void ShowNeedForPageSize()
//{
// if(PreviousWordSection != null && PreviousWordSection != LastWordSection)
// Console.WriteLine("Switch From {0}.{1} ",PreviousWordSection.DisplayNumber,PreviousWordSection.DisplayText);
// Console.WriteLine("To {0}.{1} Page: {2}",LastWordSection.DisplayNumber,LastWordSection.DisplayText,_PageCountOfWordSection);
// PreviousWordSection = LastWordSection;
//}
private PdfContentByte OpenDoc(string outputFileName, iTextSharp.text.Rectangle rect)
{
PdfWriter writer=null;
iTextSharp.text.Document document = new iTextSharp.text.Document(rect);
try
{
writer = PdfWriter.GetInstance(document, new FileStream(outputFileName, FileMode.Create));
// PDFA1B does not allow layers, so this is disabled for now
// If enabled, CreateLayers will need to be skipped.
//writer.PDFXConformance = PdfWriter.PDFA1B;
}
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 MyContentByte = 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;
}
MyContentByte = writer.DirectContent;
return MyContentByte;
}
//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<PdfReader> _MyFoldoutReader = null;
public static List<PdfReader> MyFoldoutReader
{
get { return PromsPrinter._MyFoldoutReader; }
set { PromsPrinter._MyFoldoutReader = value; }
}
private static List<SectionInfo> _MyFoldoutSection = null;
private string Print(ProcedureInfo myProcedure, string pdfFolder, bool makePlacekeeper, bool makeContinuousActionSummary)
{
if (_ForcedPaginations != null) _ForcedPaginations.Clear();
int profileDepth = ProfileTimer.Push(">>>> PromsPrinter.Print");
if (_TransPageNumProblems == null) _TransPageNumProblems = new List<string>();
if (_MyFoldoutReader != null) _MyFoldoutReader.Clear();
else _MyFoldoutReader = new List<PdfReader>();
if (_MyFoldoutSection != null) _MyFoldoutSection.Clear();
else _MyFoldoutSection = new List<SectionInfo>();
VlnItextFont.RegisterFontFolder(); //B2019-174 register the font folder so that symbols will display on auto TOC
if (myProcedure.Sections != null)
{
int cnt = 0;
foreach (SectionInfo mySection in myProcedure.Sections)
{
//C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box
if ((myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.SectionLevelFoldouts && (mySection.MyConfig as SectionConfig).Section_IsFoldout == "Y")
|| (myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.AlternateFloatingFoldout && (mySection.MyConfig as SectionConfig).Section_IsFoldout == "Y"))
{
// 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", false, false);
_MyFoldoutReader.Add(foldoutPdf != null ? new PdfReader(foldoutPdf) : null);
cnt++;
}
}
}
OnStatusChanged("Print " + myProcedure.DisplayNumber, PromsPrinterStatusType.Start);
string outputFileName = pdfFolder + "\\" + Prefix + PDFFile; // RHM20150506 Multiline ItemID TextBox
if (!OverWrite && File.Exists(outputFileName))
{
if (MessageBox.Show(outputFileName + " exists. Overwrite file?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No)
{
ProfileTimer.Pop(profileDepth);
return null;
}
}
string retval = PrintProcedureOrFoldout(myProcedure, null, outputFileName, makePlacekeeper, makeContinuousActionSummary);
ProfileTimer.Pop(profileDepth);
return retval;
}
// 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.MyConfig as SectionConfig).Section_IsFoldout == "Y")) //C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box
{
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 _WatermarkOverrideColor = "BLUE"; // C2021-019: Override watermark color
public string WatermarkOverrideColor
{
get { return _WatermarkOverrideColor; }
set { _WatermarkOverrideColor = value; }
}
//private PdfReader readerWord;
private string PrintProcedureOrFoldout(ProcedureInfo myProcedure, SectionInfo myFoldoutSection, string outputFileName, bool makePlacekeeper, bool makeContinuousActionSummary)
{
int profileDepth = ProfileTimer.Push(">>>> PrintProcedureOrFoldout");
Rtf2Pdf.TextAtCounter = 0;
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);
iTextSharp.text.Rectangle rct = PDFPageSize.UsePaperSize(myProcedure.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
if (myProcedure.Sections != null && !myProcedure.Sections[0].IsStepSection && !doingFoldout) // B2019-166 also don't do this if doing a foldout else it will use the margins set in word
{
SectionInfo si = myProcedure.Sections[0] as SectionInfo;
SectionConfig sc = si.MyConfig as SectionConfig;
bool wordMargins = (sc != null && sc.Section_WordMargin == "Y");
if (wordMargins)
{
string pdfFile =BuildMSWordPDF(si);
try
{
PdfReader reader = new PdfReader(pdfFile);
rct = reader.GetPageSizeWithRotation(1);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.GetType().FullName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
_MyLog.Warn(string.Format("Error of ReadPDf [{0}],{1}.{2}",si.ItemID,si.DisplayNumber,si.DisplayText),ex);
throw new Exception("Error in readPDF", ex);
}
}
}
PdfContentByte cb = OpenDoc(outputFileName, rct);
if (cb == null)
{
ProfileTimer.Pop(profileDepth);
return null;
}
SetupProperties(cb.PdfDocument, myProcedure);
OnStatusChanged("Before NewPage", PromsPrinterStatusType.Before);
NewPage(); // Start of print
//_MyLog.InfoFormat("NewPage 1 {0}", cb.PdfWriter.CurrentPageNumber);
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);
ProfileTimer.Pop(profileDepth);
return null;
}
OnStatusChanged(myProcedure.DisplayNumber, PromsPrinterStatusType.ProgressSetup, myProcedure.Sections.Count);
int progress = 0;
int finalMessageSectionID = GetFinalMessageSectionID(myProcedure, doingFoldout);
string LastFmtName = null;
int lastDocStyle = -1;
bool firstStepSec = true;
// C2021-019: Override the watermark color, stored in the PSI - color list set as combobox in PSI with list of colors
ProcedureConfig pc = myProcedure.MyConfig as ProcedureConfig;
WatermarkOverrideColor = _WatermarkColor;
if (pc != null)
{
string clr = pc.GetValue("PSI", "WATERMARKOVERRIDECLR");
if (clr != null && clr != "") WatermarkOverrideColor = clr.ToUpper().Contains("DEFAULT") ? "BLUE" : clr;
}
foreach (SectionInfo mySection in myProcedure.Sections)
{
// B2020-115 Calculate maximum available space on a page for figures
vlnParagraph.hMax = ((float)mySection.MyDocStyle.Layout.PageLength);
vlnParagraph.wMax = ((float) mySection.MyDocStyle.Layout.PageWidth)- ((float) mySection.MyDocStyle.Layout.LeftMargin - 12);
NeedSupInfoBreak = true;
bool isFoldoutSection = (mySection.MyConfig as SectionConfig).Section_IsFoldout == "Y"; //C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box
if (((isFoldoutSection && myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.SectionLevelFoldouts)
|| (myProcedure.ActiveFormat.PlantFormat.FormatData.PrintData.AlternateFloatingFoldout && isFoldoutSection))
!= 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;
PrintOverride.CompressPropSubSup = mySection.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.CompressPropSubSup;
OnStatusChanged((mySection.DisplayNumber ?? "") == "" ? mySection.DisplayText : mySection.DisplayNumber, PromsPrinterStatusType.Progress, progress++);
// Set up Helper for the particular Section
if (_MyHelper == null)
{
LastFmtName = mySection.ActiveFormat.Name;
lastDocStyle = (int)mySection.MyDocStyle.Index;
string hlsText = "";
int hlsItemId = 0;
if (mySection.IsStepSection && mySection.Steps != null && mySection.Steps.Count > 0)
{
hlsItemId = mySection.Steps[0].ItemID;
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, hlsItemId);
_MyHelper.AllowAllWatermarks = AllowAllWatermarks;
_MyHelper.MyPdfWriter = cb.PdfWriter;
_MyHelper.CreatingFoldoutPage = doingFoldout;
_MyHelper.CreatingSupInfoPage = false;
_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.Trim();//CreateFileName(myProcedure.DisplayNumber);
FileInfo VEPromsFile = new FileInfo(procedureFileName);
if (VEPromsFile.Exists && !doingFoldout)
{
_MyHelper.BackgroundFile = procedureFileName;
float x = 0;
float y = 0;
if (!(mySection.ActiveFormat.Name.ToUpper().StartsWith("WST") || _MyHelper.Back32BitPROMS)) // compare folder contains PROMS generated PDF
{
// X value below = 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:
// These values adjust if overlay is 16bit versus 32bit. This is
// used so that the comparison is an exact match. Use 0,0 if comparing to another 32bit
// pdf, i.e. won't process the following 2 lines of code.
x = 2 * 72F / (float)myProcedure.ActiveFormat.PlantFormat.FormatData.Font.CPI;
y = -9.5F;
}
x += 72F * VlnSettings.GetCommandFloat("X", 0);
y -= 72F * VlnSettings.GetCommandFloat("Y", 0);
_MyHelper.BackgroundOffset = new PointF(x,y);
_MyHelper.BackgroundPageOffset = 0;
}
_MyHelper.WatermarkLayer = _WatermarkLayer;
_MyHelper.PageListLayer = _PagelistLayer;
_MyHelper.TextLayer = _TextLayer;
_MyHelper.BackgroundLayer = _BackgroundLayer;
_MyHelper.DebugLayer = _DebugLayer;
_MyHelper.PROMSVersionLayer = _PROMSVersionLayer; //C2018-009 print PROMS version
}
_MyHelper.Rev = _Rev;
_MyHelper.Watermark = _Watermark;
// C2019-039 Remove automatic zoom on Overlay PDFs
//_MyHelper.DoZoomOMatic = DebugOutput;
_MyHelper.OriginalPageBreak = OriginalPageBreak;
_MyHelper.PROMSVersion = _PromsVersion; //C2018-009 print PROMS version
_MyHelper.WatermarkColor = WatermarkOverrideColor; // C2021-019: save the override for the watermark color
OnStatusChanged("After Set PageEvent", PromsPrinterStatusType.SetPageEvent);
}
else
{
//added by jcb to reset mygaps when changing a section. found old section gaps were carrying over to new section
_MyHelper.MyGaps.Clear();
//Console.WriteLine("'{0}' PromsPrinter", mySection.DisplayText);
// if pagination is separate or we've changed the format, we have not done the first page
// (if this format has the useonfirst page docstyle flag)
if (LastFmtName != mySection.ActiveFormat.Name || lastDocStyle != (int)mySection.MyDocStyle.Index || mySection.SectionConfig.Section_Pagination == SectionConfig.SectionPagination.Separate)
{
_MyHelper.DidFirstPageDocStyle = false;
lastDocStyle = (int)mySection.MyDocStyle.Index;
LastFmtName = mySection.ActiveFormat.Name;
}
if (!mySection.IsStepSection) _MyHelper.PageBookmarks.Add((ItemInfo)mySection, ((mySection.DisplayNumber ?? "") == "" ? "" : mySection.DisplayNumber + " - ") + mySection.DisplayText, null);
_MyHelper.MySection = mySection;
//OnStatusChanged("After Set Svg", PromsPrinterStatusType.SetSVG);
}
// if this format uses phonelists, see if this section has one. We need to know the number
//of lines to adjust the pagelength for pagination and printing.
_MyHelper.PhoneListHeight = 0;
if (mySection.ActiveFormat.PlantFormat.FormatData.SectData.PrintPhoneList)
{
// get config for section
SectionConfig sc = mySection.MyConfig as SectionConfig;
if (sc.Section_PhoneList != null && sc.Section_PhoneList == "Y")
{
DocVersionConfig dvc = mySection.MyDocVersion.MyConfig as DocVersionConfig;
if (dvc != null)
{
string phlist = dvc.Print_PhoneList;
if (phlist != null && phlist != "")
{
// count lines:
int cl = 0;
int indx = phlist.IndexOf("\n");
while (indx > 0)
{
cl++;
if (indx + 1 > phlist.Length)
indx = -1;
else
indx = phlist.IndexOf("\n", indx + 1);
}
if (cl == 0) cl = 1; // phone list is a single line without an ending newline
_MyHelper.PhoneListHeight = cl * vlnPrintObject.SixLinesPerInch;
}
}
}
}
_MyHelper.FinalMessageSectionID = finalMessageSectionID; // set VlnSvgPageHelper with the finalMessageSectionID
if (mySection.IsAutoTOCSection)
{
if (((cb.PdfWriter.CurrentPageNumber % 2 == 0 && !_MyHelper.CreatingFoldoutPage) || myProcedure.ProcHasSupInfoData) && InsertBlankPages) // Bug Fix: B2016-181 - add blank page if page count is even
{
InsertBlankPage(cb);
}
GenerateTOC(mySection, myProcedure, cb, _TextLayer);
// B2020-102: extra page printing after auto TOC for summer. Retested for Farley and was successful also
// F2018-033: Farley Auto TOC. If doing foldouts or supinfo facing pages, add a blank page after also:
//if (myProcedure.ProcHasSupInfoData && InsertBlankPages) // Bug Fix: B2016-181 - add blank page if page count is even
//{
// InsertBlankPage(cb);
//}
}
else
{
if (mySection.IsStepSection)
{
if (mySection.Steps != null && mySection.Steps.Count > 0)
{
// get first step to send to floating foldout indx.&& MyItemInfo.FoldoutIndex>-1)
ItemInfo firstStep = mySection.Steps[0];
// B2019-165 Don't print the duplex foldout (on the back of the page) if the Don't Include Duplex Foldout check box was checked in section properties
if (firstStep.FoldoutIndex() > -1 && (mySection.MyPrevious == null || !((mySection.MyPrevious.MyConfig as SectionConfig).Section_DontIncludeDuplexFoldout)))
DoFoldoutPage(cb, "Beginning of Step Section", _TextLayer, _MyHelper, firstStep.FoldoutIndex(), InsertBlankPages);
else if (!_MyHelper.CreatingFoldoutPage && _MyFoldoutReader.Count > 0 && InsertBlankPages)
{
// if it is continuous pagination, don't do blank page - not sure if this is correct place for this:
if (mySection.SectionConfig.Section_Pagination == SectionConfig.SectionPagination.Separate)
{
// only insert a blank page if this section does not have a foldout (but the procedure as a whole does)
// and the checkbox on the print dialog to add blank pages is checked
InsertBlankPage(cb);
//_MyLog.InfoFormat("NewPage Begin Step Sect blank {0}", cb.PdfWriter.CurrentPageNumber);
}
}
else
{
// If the procedure has supplemental facing pages, but this section does not & it's the first section,
// need a blank 'facing page'. Sections after the first will get blank 'facing page' in print's pagination logic
if (SupInfoPrintType==E_SupInfoPrintType.Merge && !mySection.HasSupInfoSteps && firstStepSec && InsertBlankPages)
{
InsertBlankPage(cb);
}
}
}
firstStepSec = false;
CreateStepPdf(mySection, cb);
}
else
{
CreateWordDocPdf(cb, mySection);
}
}
_MyHelper.PrintedSectionPage = 0;
}
if (_MyHelper != null && _MyHelper.BackgroundFile != null)
{
_MyHelper.MySvg = null;
while (cb.PdfWriter.CurrentPageNumber <= _MyHelper.BackgroundPageCount)
{
iTextSharp.text.Font font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 30, iTextSharp.text.Font.NORMAL, new iTextSharp.text.Color(PrintOverride.TextColor));
PrintTextMessage(cb, "No Proms Output", _TextLayer, font);
NewPage();
//_MyLog.InfoFormat("NewPage 2 {0}", cb.PdfWriter.CurrentPageNumber);
if (DebugPagination.IsOpen) DebugPagination.WriteLine("{0:D6},'{1}'",
_MyHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "No PROMS Output");
//C2018-015 add debug pagination to meta file
if (BaselineMetaFile.IsOpen) BaselineMetaFile.WriteLine("!! {0:D6},'{1}'",
_MyHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "No PROMS Output");
}
}
OnStatusChanged(myProcedure.DisplayNumber + " PDF Creation Completed", PromsPrinterStatusType.Progress, progress);
if (DebugPagination.IsOpen) DebugPagination.TotalPages += cb.PdfWriter.CurrentPageNumber;
CloseDocument(outputFileName);
if (_MyHelper != null && makePlacekeeper)
{
// Setting the default font to Arial since that is what Calvert is currently using for their Placekeeper pages
VE_Font pkFont = new VE_Font("Arial", 11, E_Style.None, 12); // default font info.
// Ideally, we should grab the font from the DocStyle used for the Placekeeper.
// Note that Calvert has two Placekeeper docSyles (EOPs and AOPs) in the same format.
// Both Placekeeper DocStyles use Arial 11 pt font, so there is no need to grab it from the format file.
//foreach (DocStyle ds in _MyHelper.MySection.ActiveFormat.PlantFormat.DocStyles.DocStyleList)
//{ // note that this will get the last Placekeeper font setting
// if (ds.StructureStyle.Style == E_DocStructStyle.Placekeeper)
// pkFont = ds.Font;
//}
if (_MyHelper.MyPlacekeepers.Count > 0)
MyPlacekeeper = new Placekeeper(_MyHelper.MyPlacekeepers, pkFont);
}
// Generate the Continuous Action Summary
if (_MyHelper != null && makeContinuousActionSummary)
{
// Set the font for the Continue Action Summary
VE_Font pkFont = myProcedure.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.ContinuousActionSummaryData.Font; // uses font defined in the format or uses what is definced in BaseAll format
if (_MyHelper.MyContActSteps.Count > 0)
MyContActSummary = new ContinuousActionSummary(_MyHelper.MyContActSteps, pkFont);
}
_MyHelper = null;
ProfileTimer.Pop(profileDepth);
return outputFileName;
}
public void InsertBlankPage(PdfContentByte cb)
{
_MyHelper.OnBlankPage = true;
string baselinemsg = "==Insert Blank Page==";
if (_BlankPageText != null && _BlankPageText != "") // C2019-004: Allow user to define duplex blank page text
{
string bsfontfamily = MyItem.ActiveFormat.PlantFormat.FormatData.StepDataList[0].Font.Family;
int bsfontsize = 26;
iTextSharp.text.Font font = FontFactory.GetFont(bsfontfamily, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, bsfontsize, iTextSharp.text.Font.NORMAL, new iTextSharp.text.Color(PrintOverride.TextColor));
PrintTextMessage(cb, _BlankPageText, _TextLayer, font);
// B2019-019: Add the blank page message to the baseline output file.
baselinemsg = string.Format("==Insert Blank Page With Message \"{0}\"==", _BlankPageText);
}
else
cb.PdfDocument.Add(new iTextSharp.text.Table(1));
NewPage();
Volian.Base.Library.BaselineMetaFile.WriteLine(baselinemsg);
}
private void SetupProperties(PdfDocument document, ProcedureInfo myProcedure)
{
document.AddTitle(string.Format("{0} {1}",myProcedure.DisplayNumber,myProcedure.DisplayText));
document.AddSubject(myProcedure.SearchDVPath);
document.AddCreator(string.Format("{0} {1}",Application.ProductName, Application.ProductVersion));
document.AddAuthor(Volian.Base.Library.VlnSettings.UserID);
}
private Placekeeper _MyPlacekeeper = null;
public Placekeeper MyPlacekeeper
{
get { return _MyPlacekeeper; }
set { _MyPlacekeeper = value; }
}
private ContinuousActionSummary _MyContActSummary = null;
public ContinuousActionSummary MyContActSummary
{
get { return _MyContActSummary; }
set { _MyContActSummary = value; }
}
public void CreateWordDocPdf(PdfContentByte cb, SectionInfo mySection)
{
if (mySection.PageNumber == -1) // If page num transition goes to a section, need the pagenumber of section.
{
if ((mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DontCountFoldoutPgs) == E_DocStructStyle.DontCountFoldoutPgs)
mySection.PageNumber = _MyHelper.CurrentPageNumberNoFoldouts;
else
mySection.PageNumber = _MyHelper.CurrentPageNumber;
}
else
{
if ((mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DontCountFoldoutPgs) == E_DocStructStyle.DontCountFoldoutPgs)
mySection.PageNumberNextPass = _MyHelper.CurrentPageNumberNoFoldouts;
else
mySection.PageNumberNextPass = _MyHelper.CurrentPageNumber;
}
int profileDepth = ProfileTimer.Push(">>>> CreateWordDocPdf");
if (_MyHelper.MySection != mySection) // C2018-004 create meta file for baseline compares - assigning MySection again will reprocess the Page List
_MyHelper.MySection = mySection;
try
{
OnStatusChanged("Get Section", PromsPrinterStatusType.GetSection);
int sectPageCount = 0;
float locEndOfWordDoc = 0;
float pdfSize = 0;
using (PdfInfo myPdf = PdfInfo.Get(mySection,false))
{
if (myPdf == null) // B2017-218 Handle invalid word sections
{
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED), 20);
cb.SetTextMatrix(cb.PdfDocument.Left+200,cb.PdfDocument.Bottom+cb.PdfDocument.Top / 2);
cb.ShowText("Word Section Invalid");
// C2018-004 create meta file for baseline compares
Volian.Base.Library.BaselineMetaFile.WriteLine("!!Word Section Invalid: ID {0} \"{1}\" \"{2}\"",mySection.ItemID, mySection.DisplayNumber, mySection.DisplayText);
}
else
{
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;
bool resetSvgForCont = true;
for (int ii = 0; ii < sectPageCount; ii++)
{
int pageNumber = 1 + ii;
bool didFoldout = false;
if (((mySection.MyDocStyle.StructureStyle.Style ?? 0) & E_DocStructStyle.UseSectionFoldout) != 0)
{
// B2022-009: if doing a foldout & this is a landscape section, turn landscape off for the foldout
if (mySection.MyDocStyle.LandscapePageList) _MyHelper.IsLandscape = false;
didFoldout = true;
DoFoldoutPage(cb, "Word Document", _TextLayer, _MyHelper, 0, false);
if (mySection.MyDocStyle.LandscapePageList) _MyHelper.IsLandscape = true; // B2022-009: turn landscape back on for the foldout
}
if (this.MyReaderHelper != null)
{
bool doimport2 = true;
PdfImportedPage fgPage = null;
try
{
fgPage = this.MyReaderHelper.GetPage(mySection, ii + 1);
}
catch (Exception ex)
{
Console.WriteLine(ex);
doimport2 = false;
}
OnStatusChanged("Read MSWord", PromsPrinterStatusType.ReadMSWord);
if (doimport2)
{
if (((!didFoldout && _MyFoldoutReader.Count > 0) || mySection.MyProcedure.ProcHasSupInfoData) && cb.PdfWriter.CurrentPageNumber > 1 && InsertBlankPages)
{
// only insert a blank page if this section does not have a foldout (but the procedure as a whole does)
// and the checkbox on the print dialog to add blank pages is checked
InsertBlankPage(cb);
//_MyLog.InfoFormat("NewPage 3 blank {0}", cb.PdfWriter.CurrentPageNumber);
}
float yoff = 0;
if (_MyHelper.DidFirstPageDocStyle) yoff = origYoff - (float)mySection.MyDocStyle.Layout.TopMargin;
// C2018-004 create meta file for baseline compares
Volian.Base.Library.BaselineMetaFile.WriteLine("WD Height={0} Width={1} scPgCnt={2} locEnd={3} pdfSz={4} xOff={5} yOff={6} ScPgNum {7}", fgPage.Height, fgPage.Width, sectPageCount, locEndOfWordDoc, pdfSize, (float)(mySection.MyDocStyle.Layout.MSWordXAdj ?? 0.0), (float)(mySection.MyDocStyle.Layout.MSWordYAdj ?? 0.0) + yoff, pageNumber);
AddImportedPageToLayer(cb.PdfWriter.DirectContent, _MSWordLayer, fgPage, (float)(mySection.MyDocStyle.Layout.MSWordXAdj ?? 0), (float)(mySection.MyDocStyle.Layout.MSWordYAdj ?? 0) + yoff);
// B2019-102 Handle PDF Destinations for Word Sections
if (ii == 0 && _MyHelper.MyPromsPrinter.SaveLinks)
{
ColumnText ct = new ColumnText(cb);
iTextSharp.text.Font font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 12, iTextSharp.text.Font.NORMAL, new iTextSharp.text.Color(PrintOverride.TextColor));
Chunk chk = new Chunk(mySection.DisplayNumber, font);
chk.SetLocalDestination(string.Format("ItemID={0}", mySection.ItemID));
//Console.WriteLine("++++ ItemID={0}", mySection.ItemID);
//float x1 = cb.PdfDocument.PageSize.Width / 2;
//float y1 = cb.PdfDocument.PageSize.Height ; // 1.8f;
float height = 12 * 1.5F;
// B2019-102 Locate the chunk below the bottom of the page
ct.SetSimpleColumn(0, -height, chk.GetWidthPoint() * 1.01F, -2*height );
ct.AddElement(new Phrase(chk));
cb.SetColorFill(new iTextSharp.text.Color(PrintOverride.TextColor));
int status = ct.Go();
if(status > 1)
_MyLog.WarnFormat("\r\n.-.-.-. Failed to add a PDF destination for {0}", mySection.ShortPath);
}
if(DebugPagination.IsOpen) 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));
// F2022-017: For Word Document sections, allow the message to have the '{Section Number}' token that
// gets resolved by the section's DisplayNumber.
string myMsg = mySection.MyDocStyle.End.FixedMessage;
if (myMsg.Contains("{Section Number}")) myMsg = myMsg.Replace("{Section Number}", mySection.DisplayNumber).Trim();
iTextSharp.text.Paragraph para = new Paragraph(myMsg, fnt);
float wtpm = (float)mySection.MyDocStyle.Layout.PageWidth - (float)mySection.MyDocStyle.Layout.LeftMargin;
float centerpos = (float)mySection.MyDocStyle.Layout.LeftMargin + (wtpm - (myMsg.Length * (float)mySection.MyDocStyle.End.Font.CharsToTwips)) / 2;
float yBottomMargin = Math.Max(0, (float)mySection.MyDocStyle.Layout.TopMargin - (float)mySection.MyDocStyle.Layout.PageLength - 2 * vlnPrintObject.SixLinesPerInch);
float adjMsgY = 0;
if ((float)mySection.MyDocStyle.End.Flag < 0) // Adjust this many lines down the page.
{
adjMsgY = (float)(-(float)mySection.MyDocStyle.End.Flag * vlnPrintObject.SixLinesPerInch);
if (ylocation - adjMsgY > mySection.MyDocStyle.Layout.FooterLength) ylocation = ylocation - adjMsgY;
}
bool landscape = (mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_WordContentLandscaped) == E_DocStructStyle.DSS_WordContentLandscaped;
if (landscape)
{
cb.SaveState();
System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(0, 1, -1, 0, cb.PdfDocument.PageSize.Height, 0);
cb.Transform(myMatrix);
}
Rtf2Pdf.TextAt(cb, para, centerpos, ylocation + 6, 200, 12, "", yBottomMargin);
if (landscape) cb.RestoreState();
}
}
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;
NewPage(ii == sectPageCount-1); // Word Document
//_MyLog.InfoFormat("NewPage 3 {0}", cb.PdfWriter.CurrentPageNumber);
// 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;
// Calvert has a case in their stp landscape word docs where a ' (Continued)' message
// appears in their pagelist item for printing the section title, {ATTACHTITLECONT} pagelist
// However, other sections use this token, but do NOT have the continue message - so
// the docstyle was added to flag the difference between them (STP-Landscape Attachments has it,
// STP-Attachments do not)
if (resetSvgForCont && (mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListAddSectCont) == E_DocStructStyle.DSS_PageListAddSectCont)
{
_MyHelper.ResetSvg();
resetSvgForCont = false; // only need to reset it once (for all pages after 1st page)
}
//DebugPagination.WriteLine("CreateWordDocPdf");
if ((mySection.MyDocStyle.StructureStyle.Where & E_DocStyleUse.UseOnFirstPage) > 0)
_MyHelper.MySection = mySection; // this resets the docstyle/pagestyle in pagehelper
OnStatusChanged("After NewPage", PromsPrinterStatusType.NewPage);
}
}
catch (Exception ex)
{
NewPage(); // can we put out 'error on page'?
_MyLog.InfoFormat("NewPage error on page {0}", cb.PdfWriter.CurrentPageNumber);
}
finally
{
_MyHelper.IsLandscape = false; // reset landscape mode to false
}
ProfileTimer.Pop(profileDepth);
}
// B2019-152: AddMergedLandscapePage adds entries to the dictionary that keeps track of what pages in a pdf are landscape
// so that if merge is done, the pages that are landscaped can have landscaped page numbers placed on them
public static void AddMergedLandscapePage(VlnSvgPageHelper _MyHelper, string PDFFile)
{
string tmp = PDFFile.Substring(0,PDFFile.IndexOf(".pdf"));
if (MergedLandscapePages == null) MergedLandscapePages = new Dictionary<string, List<int>>();
if (MergedLandscapePages.ContainsKey(tmp))
MergedLandscapePages[tmp].Add(_MyHelper.CurrentPageNumber);
else
{
// Create the list & add this to dictionary, pdf file with page list.
List<int> children = new List<int>();
children.Add(_MyHelper.CurrentPageNumber);
MergedLandscapePages.Add(tmp, children);
}
}
private void GenerateTOC(SectionInfo tocSection, ProcedureInfo myProcedure, PdfContentByte cb, PdfLayer textLayer)
{
iTextSharp.text.pdf.PdfWriter writer = cb.PdfWriter;
float _PointsPerPage = PDFPageSize.PaperSizePoints(myProcedure.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
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);
ItemInfo procItem = myProcedure;
lastyLocation = 0;
AddSectionToTOC(tocSection, procItem, tOfC, cb, yTopMargin, 0, false); // add all of the marked sections and sub-sections to the table of contents
if (textLayer != null) cb.EndLayer();
NewPage();
//_MyLog.InfoFormat("NewPage 4 {0}", cb.PdfWriter.CurrentPageNumber);
_NoBreakYOffset = 0;
}
float lastyLocation = 0;
private string GetRtfToC(string txt, TableOfContentsData tOfCData)
{
return GetRtfToC(txt, tOfCData, null);
}
private string GetRtfToC(string txt, TableOfContentsData tOfCData, VE_Font overrideFont)
{
StringBuilder _RtfSB = new StringBuilder();
VEPROMS.CSLA.Library.DisplayText toctxt = new VEPROMS.CSLA.Library.DisplayText(txt, tOfCData.Font, false);
System.Drawing.Font myFont = toctxt.TextFont.WindowsFont;
if (overrideFont != null)
{
toctxt = new VEPROMS.CSLA.Library.DisplayText(txt, overrideFont, false);
myFont = overrideFont.WindowsFont;//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, bool didSubSecLineSpacing)
{
// 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;
string lastTOCGroupHeading = "";
bool firstGroupHeading = true;
if (ii.Sections != null)
{
int sectCnt = 0; // keep count of which section/sub-section we are processing
bool doSubY = false;
int level = 0;
// C2018-004 create meta file for baseline compares
Volian.Base.Library.BaselineMetaFile.WriteLine("TOC Ystart {0} LeftMar {1} ScNmPos {2} ScTtlPos {3} ScPgPos {4}", yPageStart, leftMargin, secNumPos, secTitlePos, secPagePos);
bool inGroup = false;
foreach (SectionInfo mySection in ii.Sections)
{
sectCnt++;
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")))
{
// 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:
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;
int startIndentAfterLevel = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCStartIndentAfterLevel ?? 2; //
level = level <= startIndentAfterLevel ? 0 : level - startIndentAfterLevel;
float indentOffset = (level * (secTitlePos - secNumPos));
if (didSubSecLineSpacing && sectCnt == 1 && indentOffset > 0) // processing first sub-section and we are indenting B2016-205
{
// processed last sub-section so use the main section line spacing (most times is double spaced)
yLocation -= (float)(tOfC.TofCLineSpacingSub ?? 1) * vlnPrintObject.SixLinesPerInch;
yLocation += (float)(tOfC.TofCLineSpacing ?? 1) * vlnPrintObject.SixLinesPerInch;
}
// The Group Title logic was added for V.C. Summer and Farley(new writer guide format)
// It allows the user to enter a Table of Contents Grouping Title on the Section Property (under automation)
// The grouping title will print if the same title wasn't last printed
string tocGrpHeading = sc.Section_TOC_Group_Title; // returns a "" if no title was entered
float yBottomMargin = yPageStart - (float)tocSection.MyDocStyle.Layout.PageLength + (2 * vlnPrintObject.SixLinesPerInch);
bool doGroupHeading = false;
if (tocGrpHeading != lastTOCGroupHeading && tocGrpHeading.Length > 0)
{
doGroupHeading = true;
inGroup = true;
// B2020-033: for single spacing, add an extra line before a grouping title:
float tmpspc = (float)(tOfC.TofCLineSpacing ?? 1);
if (lastTOCGroupHeading != "" || (firstGroupHeading && tmpspc==1))
{
yLocation += vlnPrintObject.SixLinesPerInch;
firstGroupHeading = false;
}
lastTOCGroupHeading = tocGrpHeading;
}
// 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.
bool didGrp = false;
string tmptxt = mySection.MyContent.Number == null || mySection.MyContent.Number == "" ? " " : mySection.DisplayNumber;// B2017-019 - process "<u>" in section number
if (tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCRemoveGrpNameInSects
&& tocGrpHeading.Length > 0 && tmptxt.ToUpper().Contains(tocGrpHeading))
{
tmptxt = tmptxt.Replace(tocGrpHeading, "");
didGrp = true;
}
if (tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCRemoveGrpNameInSects
&& lastTOCGroupHeading.Length > 0 && tmptxt.ToUpper().Contains(lastTOCGroupHeading))
{
tmptxt = tmptxt.Replace(lastTOCGroupHeading, "");
didGrp = true;
}
string rtfText = GetRtfToC(tmptxt, tOfC);
Paragraph myparagraphSecNum = vlnPrintObject.RtfToParagraph(rtfText);
float width = 0;
foreach (Chunk chkt in myparagraphSecNum.Chunks)
width += chkt.GetWidthPoint();
float numwidth = width;
Rtf2Pdf.Offset = new PointF(0, 2.5F);
// 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;
// logic put in for V.C. Summer who wants to their auto table of contents to print "OPERATOR ACTIONS" (set in the format) instead of "Procedure Steps"
// - note that Summer didn't want to change the section title because they want transition to say "procedure step" for the section title. 03/08/2016
string tocSecTitle = mySection.FormattedDisplayText;// B2017-019 - process "<u>" in section title
tocSecTitle= ConvertSpecialChars(tocSecTitle, ii.ActiveFormat.PlantFormat.FormatData); // B2019-172 process symbol characters
if (tocSecTitle.ToUpper() == "PROCEDURE STEPS" && tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCProcedureStepsTitle != "")
tocSecTitle = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCProcedureStepsTitle;
// Do the title first since it may wrap to 2nd line and this is an issue for
// doing a pagebreak, i.e. may cause a page break when the number on a single line
// would not.
//if (tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData
if (level == 0 && tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCUnderlineFirstLevelTitle)
{
VE_Font ovrFont = new VE_Font(tOfC.Font.Family, (int)tOfC.Font.Size,(E_Style)tOfC.Font.Style | E_Style.Underline, (float)tOfC.Font.CPI);
rtfText = GetRtfToC(tocSecTitle, tOfC, ovrFont);
}
else
rtfText = GetRtfToC(tocSecTitle, tOfC);
Paragraph myparagraphSecTitle = vlnPrintObject.RtfToParagraph(rtfText); // section title
width = secPagePos - adjSecTitlePos - ((tOfC.TofCPageNumAlign.ToUpper() == "RIGHT") ? 18 : 6);// B2021-109 proper adjustment of section title width - copied from leader dots lenth calcuation below
float savTitleWid = width;
// for South Texas Table of Contents
// if there is no section number (we put a blank in tmptxt) then move the section title over to the section number position
if (doGroupHeading) // see if the group title and the first item under it will fit on the page B2016-216
{
VE_Font grpingFont = new VE_Font(tOfC.Font.Family, (int)tOfC.Font.Size, (E_Style)tOfC.Font.Style | E_Style.Underline, (float)tOfC.Font.CPI);
string rtfGrpingText = GetRtfToC(tocGrpHeading, tOfC, grpingFont);
Paragraph myparagraphGrpTitle = vlnPrintObject.RtfToParagraph(rtfGrpingText);
float w = secPagePos - 6;
// F2018-033: Farley Auto TOC. If line spacing is less than 0, then spacing is double spaced if on section items (such as
// Purpose, Proc Steps; and spacing is single spaced if within groups. If not less than 0, just use what is in format file.
int lnaftergroup = 1;
float lnsp = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCLineSpacing ?? 0;
if (lnsp < 0) lnaftergroup = ((tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCLineSpacingSub ?? 0) > 0) ? 1 : 2;
float yLocAfterGrpTitleAndFirstItem = yLocation + (lnaftergroup * vlnPrintObject.SixLinesPerInch) + vlnPrintObject.GetHeight(cb, myparagraphGrpTitle, string.Empty, w, false) + vlnPrintObject.GetHeight(cb, myparagraphSecTitle, string.Empty, savTitleWid, false);
// if group heading and first item under it does not fit on the page, do a page break
if ((yPageStart - yLocAfterGrpTitleAndFirstItem) < yBottomMargin)
{
NewPage();
_MyHelper.ResetSvg(); // needed to reset so that PSNotFirst pagelist justify flag gets used for BGE
yLocation = lastyLocation = 0;
}
//if (yLocation > 0) yLocation += vlnPrintObject.SixLinesPerInch;// commented out for B2016-200 // for two blank line between last TOC title and the new grouping title
float rtnval = Rtf2Pdf.TextAt(cb, myparagraphGrpTitle, leftMargin + secNumPos, yPageStart - yLocation, w, height, "", yBottomMargin); // print the Group Title
yLocation += vlnPrintObject.SixLinesPerInch; // for two blank line between last TOC title and the new grouping title - added for B2016-200
if (lnsp > -1) yLocation += (lnaftergroup * vlnPrintObject.SixLinesPerInch); // new line
}
// Print the section title
float retval = Rtf2Pdf.TextAt(cb, myparagraphSecTitle, leftMargin + ((tOfC.TofCSecNumPos == tOfC.TofCSecTitlePos && tmptxt.Equals(" "))? secNumPos : adjSecTitlePos), yPageStart - yLocation, width, height, "", yBottomMargin);
if (retval == 0) // couldn't fit, flags need for a page break.
{
NewPage();
_MyHelper.ResetSvg(); // needed to reset so that PSNotFirst pagelist justify flag gets used for BGE
yLocation = lastyLocation = 0;
retval = Rtf2Pdf.TextAt(cb, myparagraphSecTitle, leftMargin + adjSecTitlePos, yPageStart - yLocation, width, height, "", yBottomMargin);
}
float ttlRetval = retval;
float savTitleFillWidth = Rtf2Pdf.FillWidth;
// Now do the section number. Retval is the ylocation on page after the text
// is put out.
retval = Rtf2Pdf.TextAt(cb, myparagraphSecNum, leftMargin + secNumPos + indentOffset, yPageStart - yLocation, numwidth * 1.3F, height, "", yBottomMargin);
//float lSpace = (float)(tOfC.TofCLineSpacing ?? 1) * vlnPrintObject.SixLinesPerInch;
// adjust ylocation for pagenumber - the ylocation will get reset if the
// section title split on 2 lines and the page number needs to be on the 2nd line.
// Only do this if the title is not empty (the code was meant for if title spans more than a line)
if (retval != ttlRetval && mySection.MyContent.Text != null && mySection.MyContent.Text != "") yLocation += (retval - ttlRetval);
// retval = the minimum (further down the page) between section number and
// title - this accounts for multi line title.
retval = Math.Min(retval, ttlRetval);
lastyLocation = retval;
// check that the page number should be in the TOC (some BGE sections do not have the page number)
if (!((mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DontNumberInTOC) == E_DocStructStyle.DontNumberInTOC))
{
// add a template for the page number:
// 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 myparagraphSecTitle.Chunks)
width += chkt.GetWidthPoint();
// get height - if two lines high, need width of 2nd line for adding
// space characters
float heightTtl = vlnPrintObject.GetHeight(cb, myparagraphSecTitle, string.Empty, savTitleWid, false);
string spaceStr = "";
float startSpace = 0;
// the '6's in the next few code lines & in the 'while' loop below allows the placement of the dots (or other space character)
// to be not too close to section title & page number.
if (heightTtl > vlnPrintObject.SixLinesPerInch)
{
// this title is 2 or more lines, find start of leader dots by determining length of text
// on 2nd line (the savTitleFillWidth is the widest line of the split title)
float secondLineWidth = width - savTitleFillWidth;
startSpace = leftMargin + adjSecTitlePos + secondLineWidth + 6;
}
else
startSpace = leftMargin + adjSecTitlePos + width + 6;
// If the page number is Right justified, need less space characters ('.') so that page number
// doesn't have the last space character overwriting the 1st digit:
int endJust = (tOfC.TofCPageNumAlign.ToUpper() == "RIGHT") ? 18 : 6;
float endSpace = leftMargin + secPagePos - endJust;
float numSpace = endSpace - startSpace;
rtfText = GetRtfToC(tOfC.TofCSpaceChar, tOfC);
Paragraph tmpmyparagraph = vlnPrintObject.RtfToParagraph(rtfText);
float spacchrwid = 0;
foreach (Chunk chkt in tmpmyparagraph.Chunks)
spacchrwid += chkt.GetWidthPoint();
while (numSpace > 6)
{
spaceStr = spaceStr + tOfC.TofCSpaceChar;
numSpace -= spacchrwid;
}
rtfText = GetRtfToC(spaceStr, tOfC); // out the leader dots
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, key);
}
//If the format wants single spacing within subsections (2nd level and lower), then need to figure out
// spacing (vcb1 table of contents)
//bool dosuby = (((tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCLineSpacingSub ?? 1) > 0)
// && (mySection.MyParent.IsSection && ((mySection.Sections != null && mySection.Sections.Count > 0) || (level > 0 && mySection.NextItem != null))))
// || didGrp;
doSubY = (((tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCLineSpacingSub ?? 1) > 0)
&& (mySection.MyParent.IsSection && (/* mySection.Sections == null && */ sectCnt < ii.Sections.Count))) // B2016-205
|| didGrp;
//float spc = (float)(tOfC.TofCLineSpacing ?? 1);
if (doSubY)
{
float spcs = (float)(tOfC.TofCLineSpacingSub ?? 1);
if (spcs == -1) // F2018-033: Allow for single & double spacing for Farley (if in group or not)
{
if (inGroup) // Do not require a title to be placed on each section in group for Farley. If in group from above, single space
spcs = 1;
else
spcs = 2;
}
yLocation += (spcs * vlnPrintObject.SixLinesPerInch);
}
else
{
float spc = (float)(tOfC.TofCLineSpacing ?? 1);
if (spc == -1) // F2018-033: Allow for single & double spacing for Farley (if in group or not)
{
if (inGroup) // Do not require a title to be placed on each section in group for Farley. If in group from above, single space
spc = 1;
else
spc = 2;
}
yLocation += (spc * vlnPrintObject.SixLinesPerInch);
}
// C2021-015: Barakah High Level Steps in Table of Contents - check to see if we need to add the high level steps on
// table of contents for this section, format flag & section has steps:
if (mySection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCAllowHLS &&
mySection.IsStepSection && mySection.Steps != null && mySection.Steps.Count > 0)
yLocation = AddHLSToTOC(tocSection, mySection, tOfC, cb, yPageStart, yLocation, doSubY, level + 1, adjSecTitlePos);
}
float savYLoc = yLocation;
yLocation = AddSectionToTOC(tocSection, mySection, tOfC, cb, yPageStart, yLocation, doSubY);
if (savYLoc == yLocation) // nothing was outputted i.e. the subsections are not included on the TOC // B2016-205
{
if (doSubY && sectCnt == ii.Sections.Count)
{
// processed last sub-section so use the main section line spacing (most times is double spaced)
yLocation -= (float)(tOfC.TofCLineSpacingSub ?? 1) * vlnPrintObject.SixLinesPerInch;
yLocation += (float)(tOfC.TofCLineSpacing ?? 1) * vlnPrintObject.SixLinesPerInch;
}
}
}
}
return yLocation;
}
// C2021-015: Barakah High Level Steps in Table of Contents
private float AddHLSToTOC(SectionInfo tocSection, ItemInfo ii, TableOfContentsData tOfC, PdfContentByte cb, float yPageStart, float yLocation, bool didSubSecLineSpacing, int level, float parTitleXOff)
{
// if section is not in TOC, don't add the HLSs
SectionConfig sc = ii.ActiveSection.MyConfig as SectionConfig;
if (!((ii.ActiveSection.MyDocStyle != null && ii.ActiveSection.MyDocStyle.IncludeInTOC && (sc == null || sc.Section_TOC != "Y"))
|| ((ii.ActiveSection.MyDocStyle == null || !ii.ActiveSection.MyDocStyle.IncludeInTOC) && (sc != null && sc.Section_TOC == "Y"))))
return yLocation;
float xAdjNumber = -6 + 1.2F;
float xAdjTitle = .8F + 1.2F;
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 stepNumPos = (float)tOfC.TofCSecNumPos + xAdjNumber;
float stepTitlePos = (float)tOfC.TofCSecTitlePos + xAdjTitle;
float stepPagePos = (float)tOfC.TofCPageNumPos + xAdjNumber;
float height = tOfC.Font.WindowsFont.Size * 1.5F;
// C2018-004 create meta file for baseline compares
Volian.Base.Library.BaselineMetaFile.WriteLine("TOC Ystart {0} LeftMar {1} ScNmPos {2} ScTtlPos {3} ScPgPos {4}", yPageStart, leftMargin, stepNumPos, stepTitlePos, stepPagePos);
int tofCNumLevels = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCNumLevels ?? 0;
if (tofCNumLevels > 0 && level > tofCNumLevels) return yLocation; // don't go down more than number of levels as defined in format
// figure out whether to indent. If not, set indentOffset to 0, otherwise indent number to where parent's text was (input parTitleXOff)
int startIndentAfterLevel = tocSection.ActiveFormat.PlantFormat.FormatData.SectData.AccSectionData.TableOfContentsData.TofCStartIndentAfterLevel ?? 2; //
level = level <= startIndentAfterLevel ? 0 : level - startIndentAfterLevel;
// The parTitleXOff is passed in, it is the xoffset for the title of the section. This is where the number should
// start, if indenting. Without this, the xoffset was not correct:
float indentOffset = level == 0 ? 0 : parTitleXOff;
float numwidth = 0;
foreach (ItemInfo hls in ii.Steps) // Ouput each HLS that has config flag to include it.
{
StepConfig stc = hls.MyConfig as StepConfig;
if (stc != null && stc.Step_IncludeInTOC)
{
float yBottomMargin = yPageStart - (float)tocSection.MyDocStyle.Layout.PageLength + (2 * vlnPrintObject.SixLinesPerInch);
// need to do the step number, title & page number. Page number has to be put on at end after number of page is known, so use a Template.
string tmptxt = hls.MyTab.CleanText;
if (tmptxt == null || tmptxt == "") tmptxt = " "; // if no number set to blanks. Without this, low level printing gets confused
string rtfText = GetRtfToC(tmptxt, tOfC);
Paragraph myparagraphStepNum = vlnPrintObject.RtfToParagraph(rtfText);
float width = 0;
foreach (Chunk chkt in myparagraphStepNum.Chunks)
width += chkt.GetWidthPoint();
if (numwidth == 0) numwidth = width; // keep same xoffset for step text unless overwriting by number (see below)
Rtf2Pdf.Offset = new PointF(0, 2.5F);
// if the starting column of text would be in 'middle of' the number, just put it
// a few spaces after the number. The '182' below represents 2 chars.
float adjStepTitlePos = indentOffset + numwidth + 6;
if (width + indentOffset > adjStepTitlePos)
{
adjStepTitlePos = numwidth + 12 + indentOffset;
numwidth = width;
}
string tocStepTitle = hls.FormattedDisplayText;
tocStepTitle = ConvertSpecialChars(tocStepTitle, ii.ActiveFormat.PlantFormat.FormatData); // B2019-172 process symbol characters
rtfText = GetRtfToC(tocStepTitle, tOfC);
Paragraph myparagraphStepTitle = vlnPrintObject.RtfToParagraph(rtfText);
width = stepPagePos - adjStepTitlePos - ((tOfC.TofCPageNumAlign.ToUpper() == "RIGHT") ? 18 : 6);// B2021-109 proper adjustment of section title width - copied from leader dots lenth calcuation below
float savTitleWid = width;
// Print the step text
float retval = Rtf2Pdf.TextAt(cb, myparagraphStepTitle, leftMargin + ((tOfC.TofCSecNumPos == tOfC.TofCSecTitlePos && tmptxt.Equals(" ")) ? stepNumPos : adjStepTitlePos), yPageStart - yLocation, width, height, "", yBottomMargin);
if (retval == 0) // couldn't fit, flags need for a page break.
{
NewPage();
_MyHelper.ResetSvg(); // needed to reset so that PSNotFirst pagelist justify flag gets used for BGE
yLocation = lastyLocation = 0;
retval = Rtf2Pdf.TextAt(cb, myparagraphStepTitle, leftMargin + adjStepTitlePos, yPageStart - yLocation, width, height, "", yBottomMargin);
}
float ttlRetval = retval;
float savTitleFillWidth = Rtf2Pdf.FillWidth;
// Now do the step number. Retval is the ylocation on page after the text is put out
retval = Rtf2Pdf.TextAt(cb, myparagraphStepNum, leftMargin + indentOffset, yPageStart - yLocation, numwidth * 1.3F, height, "", yBottomMargin);
if (retval != ttlRetval) yLocation += (retval - ttlRetval);
// retval = the minimum (further down the page) between step number & text - accounts for multi line step
retval = Math.Min(retval, ttlRetval);
lastyLocation = retval;
// add a template for the page number:
// 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 myparagraphStepTitle.Chunks)
width += chkt.GetWidthPoint();
// get height - if two lines high, need width of 2nd line for adding
// space characters
float heightTtl = vlnPrintObject.GetHeight(cb, myparagraphStepTitle, string.Empty, savTitleWid, false);
string spaceStr = "";
float startSpace = 0;
// the '6's in the next few code lines & in the 'while' loop below allows the placement of the dots (or other space character)
// to be not too close to section title & page number.
if (heightTtl > vlnPrintObject.SixLinesPerInch)
{
// this title is 2 or more lines, find start of leader dots by determining length of text
// on 2nd line (the savTitleFillWidth is the widest line of the split title)
float secondLineWidth = width - savTitleFillWidth;
startSpace = leftMargin + adjStepTitlePos + secondLineWidth + 6;
}
else
startSpace = leftMargin + adjStepTitlePos + width + 6;
// If the page number is Right justified, need less space characters ('.') so that page number
// doesn't have the last space character overwriting the 1st digit:
int endJust = (tOfC.TofCPageNumAlign.ToUpper() == "RIGHT") ? 18 : 6;
float endSpace = leftMargin + stepPagePos - endJust;
float numSpace = endSpace - startSpace;
rtfText = GetRtfToC(tOfC.TofCSpaceChar, tOfC);
Paragraph tmpmyparagraph = vlnPrintObject.RtfToParagraph(rtfText);
float spacchrwid = 0;
foreach (Chunk chkt in tmpmyparagraph.Chunks)
spacchrwid += chkt.GetWidthPoint();
while (numSpace > 6)
{
spaceStr = spaceStr + tOfC.TofCSpaceChar;
numSpace -= spacchrwid;
}
rtfText = GetRtfToC(spaceStr, tOfC); // out the leader dots
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" + hls.ItemID.ToString();
if (ii.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 + stepPagePos, yPageStart - yLocation, width, height, "", yBottomMargin);
}
else
AddTemplateTOCPageCounts(tOfC, yLocation, yPageStartAdj, leftMargin, stepPagePos, height, key);
float spc = (float)(tOfC.TofCLineSpacing ?? 1);
yLocation += (spc * vlnPrintObject.SixLinesPerInch);
}
}
return yLocation;
}
//B2019-172 This will add the RTF font commands around the symbol characters
// This was copied for DisplaySearch and modified - added the FormatData parameter
private string ConvertSpecialChars(string str, FormatData fmtData)
{
string rtnVal = str;
rtnVal = rtnVal.Replace("\u00A0", @"\u160?"); //convert \u00A0 to a hard space (\u00A0 shows as a blank in the search text field)
rtnVal = rtnVal.Replace("\n", @"\line "); //B2018-020 SQL content record has "\line " for the hard return
// Bug fix B2014-057
// if we are searching for a symbol character in all procedure sets MyDocVersion is null
// when MyDocVersion is null, get the symbol list directly from the PROMS base format (BaseAll.xml)
if (fmtData != null && fmtData.SymbolList != null)
{
SymbolList sl = fmtData.SymbolList;
if (sl != null)
{
foreach (Symbol sym in sl)
{
string rplace = string.Format(sym.Unicode < 256 ? @"\'{0:X2}" : @"\u{0}?", sym.Unicode); // bug fix B2014-057 we were not including the ? in the replace
rtnVal = rtnVal.Replace(((char)sym.Unicode).ToString(), rplace);
}
}
}
return rtnVal;
}
private void AddTemplateTOCPageCounts(TableOfContentsData tOfC, float yLocation, float yPageStartAdj, float leftMargin, float secPagePos, float height, string key)
{
PdfTemplate tmp = _MyHelper.MyTOCPageCounts.AddToTemplateList(key, _MyHelper.MyPdfWriter, "{TOCPAGE}", tOfC.Font.WindowsFont, (tOfC.TofCPageNumAlign.ToUpper() == "RIGHT") ? Element.ALIGN_RIGHT : Element.ALIGN_LEFT, PrintOverride.TextColor);
_MyHelper.MyPdfContentByte.AddTemplate(tmp, leftMargin + secPagePos, (yPageStartAdj - yLocation) - height / 2);
}
//private string GetRtfPlacekeeper(string txt, PlacekeeperData pkCData)
//{
// StringBuilder _RtfSB = new StringBuilder();
// Volian.Controls.Library.DisplayText pktxt = new Volian.Controls.Library.DisplayText(txt, pkCData.Font, false);
// System.Drawing.Font myFont = pktxt.TextFont.WindowsFont;
// _RtfSB.Append(vlnPrintObject.AddFontTable(myFont));
// _RtfSB.Append(pktxt.StartText);
// _RtfSB.Append("}");
// return _RtfSB.ToString();
//}
//private float AddSectionToPK(SectionInfo pkSection, ItemInfo ii, PlacekeeperData pkData, PdfContentByte cb, float yPageStart, float yLocation)
//{
// SectionConfig pkSC = pkSection.MyConfig as SectionConfig;
// if (pkSC.Section_Placekeeper != "Y") return yLocation; // automatic generation of Placekeeper turned off
// 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)pkSection.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.ItemID != pkSection.ItemID && sc != null && sc.Section_Placekeeper == "Y")
// {
// // Look at each step in the section and build a Placekeeper for those steps that are marked
// // 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 = GetRtfPlacekeeper(tmptxt, pkData);//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)pkSection.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 = pkSection.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));
// // 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;
// //float retval = Rtf2Pdf.TextAt(cb, myparagrapht, leftMargin + adjSecTitlePos, yPageStart - yLocation, width, height, "", yBottomMargin);
// //float ttlRetval = retval;
// //if (retval == 0)
// //{
// // cb.PdfDocument.NewPage();
// // //_MyLog.InfoFormat("NewPage 5 {0}", cb.PdfWriter.CurrentPageNumber);
// // yLocation = lastyLocation = 0;
// // retval = Rtf2Pdf.TextAt(cb, myparagrapht, leftMargin + adjSecTitlePos, yPageStart - yLocation, width, height, "", yBottomMargin);
// // ttlRetval = retval;
// //}
// //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();
// // //_MyLog.InfoFormat("NewPage 5 {0}", cb.PdfWriter.CurrentPageNumber);
// // yLocation = lastyLocation = 0;
// // retval = Rtf2Pdf.TextAt(cb, myparagraphn, leftMargin + secNumPos + indentOffset, yPageStart - yLocation, width * 1.3F, height, "", yBottomMargin);
// //}
// //retval = Math.Min(retval, ttlRetval);
// //float lSpace = (tOfC.TofCLineSpacing == 2) ? 2 * vlnPrintObject.SixLinesPerInch : vlnPrintObject.SixLinesPerInch;
// //if (lastyLocation != 0 && ((lastyLocation - retval) > lSpace))
// // yLocation += (lastyLocation - retval - lSpace);
// //lastyLocation = retval;
// //// check that the page number should be in the TOC (some BGE sections do not have the page number)
// //if (!((mySection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DontNumberInTOC) == E_DocStructStyle.DontNumberInTOC))
// //{
// // // add a template for the page number:
// // // 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 AddTemplatePKPageCounts(TableOfContentsData tOfC, float yLocation, float yPageStartAdj, float leftMargin, float secPagePos, float height, SectionInfo mySection)
//{
// string key = "PK" + 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, iTextSharp.text.Font font)
{
if (textLayer != null) cb.BeginLayer(textLayer);
float fontSize = font.Size;
ColumnText ct = new ColumnText(cb);
//iTextSharp.text.Font font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize,iTextSharp.text.Font.NORMAL, 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; // 1.8f;
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)
{
int profileDepth = ProfileTimer.Push(">>>> CreateStepPdf");
//PrintTimer pt = new PrintTimer();
iTextSharp.text.pdf.PdfWriter writer = cb.PdfWriter;
ItemInfo myItemInfo = section as ItemInfo;
if (SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks)
{
section.StepSectPageBreaksForSupInfo.Clear();
section.StepSectPageBreaks.Clear();
}
// 792: 72 * 11 inches - TopRow - Top is high value for 8.5x11 paper, 842 for A4 paper
float _PointsPerPage = PDFPageSize.PaperSizePoints(myItemInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
float yTopMargin = _PointsPerPage - (float)myItemInfo.MyDocStyle.Layout.TopMargin;
yTopMargin -= _MyHelper.AdjustTopMarginForMultiLinePageListItems;
// the following line was modified to comment out the - 2 * SixLinesPerInch. this fixed a pagination problem with WCN EMG E-3.
// The change mentioned above caused the bottom message to print without a line separating it from step text (if the text was long
// enough to go to the bottom of page). A fix for this problem, B2017-103, is to use a format variable to define
// how many lines will go above the continue message. It was done this way so that it fixes the format/data that the problem
// was found in, i.e. Ginna Rev2 SAMG, SAG-3 step 7. This change won't affect other plants/formats but if the problem occurs
// the format value can be used to adjust the location of bottom message. However, this could adversely affect pagination and
// each plant/format needs to be done on a case by base basis.
float yBottomMargin = Math.Max(0, yTopMargin - (float)myItemInfo.MyDocStyle.Layout.PageLength - (myItemInfo.MyDocStyle.Continue.Bottom.LocAdj==null?0:(int)myItemInfo.MyDocStyle.Continue.Bottom.LocAdj));
vlnParagraph.PathPrefix = myItemInfo.Path;
//Rtf2Pdf.PdfDebug = true;
Rtf2Pdf.Offset = new PointF(0, 2.5F);
if (section.MyDocStyle.LandscapePageList)
{
if ((section.MyConfig as SectionConfig).Section_Pagination == SectionConfig.SectionPagination.Separate)
{
System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(0, 1, -1, 0, cb.PdfDocument.PageSize.Height, 0);
cb.Transform(myMatrix);
_MyHelper.IsWatermarkLandscape = true; // B2019-145: watermark on landscape page
}
}
else
_MyHelper.IsLandscape = false;
_MyHelper.ChangeBarDefinition = MyChangeBarDefinition;
//pt.Description = "vlnParagrph";
vlnParagraph myParagraph = new vlnParagraph(null, cb, myItemInfo, (float)myItemInfo.MyDocStyle.Layout.LeftMargin, _NoBreakYOffset, 0, myItemInfo.ColumnMode, myItemInfo.ActiveFormat, null, null, 0, true, this);
//pt.Description = "After vlnParagrph";
//if (myParagraph.MyItemInfo.InList(15906))
//{
// CPSGen myGen = new CPSGen(myParagraph);
// myGen.Generate("TestCPSGEN.xml");
//}
float localYPageStart = 0;
float yPageStart = yTopMargin;
if (myItemInfo.HasChildren || myItemInfo.MyDocVersion.DocVersionConfig.SelectedSlave > 0 || (myItemInfo.ActiveFormat.PlantFormat.FormatData.Express && myItemInfo.MyDocStyle.OptionalSectionContent))
{
// if there is supplemental information associated with this section... generate the pdf. This pdf will be used to place
// supplemental information on facing pages
// B2017-267 Put in the DocStyle setting "AdjustTopMarginOnStepContinuePages" for Farley who uses the "PSOnlyFirst" in some of their pagelists so that a section title is printed only on the first page of the section.
// This will adjust the top margin when the section title is not printed on the other pages.
yTopMargin += myItemInfo.MyDocStyle.AdjustTopMarginOnStepContinuePages;
if (SupInfoPrintType == E_SupInfoPrintType.Merge && myParagraph.SupInfoSection != null && myParagraph.SupInfoSection.ChildrenBelow != null && myParagraph.SupInfoSection.ChildrenBelow.Count > 0)
GenerateSuppInfoPdf(myParagraph.SupInfoSection, yTopMargin, yBottomMargin);
localYPageStart = myParagraph.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin);
if (myParagraph.MyPlaceKeeper != null)
_MyHelper.MyPlacekeepers.Add(myParagraph.MyPlaceKeeper); // add this step text to the PlaceKeeper (Calvert Cliffs)
if (myParagraph.MyContAct != null)
_MyHelper.MyContActSteps.Add(myParagraph.MyContAct); // add this step to the Continuous Action Summary
}
else if (!myItemInfo.MyDocStyle.OptionalSectionContent)
{
SectionInfo si = myItemInfo.ActiveSection as SectionInfo;
if (si.IsSeparatePagination()) // Don't output this message for continuous sections
{
// This was causing overlap of this message with previous sections
iTextSharp.text.Font font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 30, iTextSharp.text.Font.NORMAL, new iTextSharp.text.Color(PrintOverride.TextColor));
PrintTextMessage(cb, "No Section Content", _TextLayer, font);
}
}
SectionConfig.SectionPagination sp = SectionConfig.SectionPagination.Separate; // always the default
ItemInfo nxtItem = section.NextItem;
if (nxtItem != null)
{
// 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 && nxtItem.IsStepSection)
{
SectionInfo si = nxtItem as SectionInfo;
// B2017-201 if si is null we need to get it via the ItemID
if (si == null)
si = SectionInfo.Get(nxtItem.ItemID); //ActiveSection as SectionInfo;
SectionConfig sc = si.SectionConfig;
try
{
if (sc != null) sp = sc.Section_Pagination;
}
catch (Exception ex)
{
sp = SectionConfig.SectionPagination.Separate;
}
}
}
if (sp == SectionConfig.SectionPagination.Separate)
{
if (section.MyDocStyle.LandscapePageList)
{
_MyHelper.IsLandscape = false;
}
NewPage(true); // end of step section
//_MyLog.InfoFormat("NewPage 6 {0}", cb.PdfWriter.CurrentPageNumber);
_NoBreakYOffset = 0;
yPageStart = yTopMargin;
}
else
{
if (nxtItem != null && nxtItem.MyPrevious != null && nxtItem.ActiveFormat.PlantFormat.FormatData.SectData.SectionHeader.Level0Big)
localYPageStart -= 12;
if (_MyHelper.BottomMessage != null && _MyHelper.BottomMessage.Count != 0)
{
_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);
//pt.Description = "End";
ProfileTimer.Pop(profileDepth);
_MyHelper.IsWatermarkLandscape = false;
}
private void GenerateSuppInfoPdf(vlnParagraph vlnParagraph, float yTopMargin, float yBottomMargin)
{
ReaderHelper savMyReaderHelper = MyReaderHelper;
PdfContentByte savMyContentByte = MyContentByte;
VlnSvgPageHelper savMyHelper = _MyHelper;
if (SupInfoPdfPage == null) SupInfoPdfPage = new Dictionary<int, int>();
else SupInfoPdfPage.Clear();
string SupInfoPdfName = Volian.Base.Library.VlnSettings.TemporaryFolder + @"\SupInfo" + vlnParagraph.MyItemInfo.ItemID.ToString() + @".pdf";
iTextSharp.text.Rectangle pageSize = PDFPageSize.UsePaperSize(MyItem.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
PdfContentByte cb = OpenDoc(SupInfoPdfName, pageSize);
if (cb == null) return;
VlnSvgPageHelper myPageHelper = new VlnSvgPageHelper(vlnParagraph.MyItemInfo as SectionInfo, this, null, 0);
cb.PdfWriter.PageEvent = myPageHelper;
myPageHelper.AllowAllWatermarks = AllowAllWatermarks;
myPageHelper.MyPdfWriter = cb.PdfWriter;
myPageHelper.CreatingFoldoutPage = false;
myPageHelper.CreatingSupInfoPage = true;
myPageHelper.MyPdfContentByte = cb;
myPageHelper.ChangeBarDefinition = MyChangeBarDefinition;
float yPageStart = yTopMargin;
vlnParagraph._yPageStartForSupInfo = yTopMargin;
SupInfoAjustGroupings(vlnParagraph,cb);
SupInfoPrintType = E_SupInfoPrintType.SupInfoPdfPrint;
vlnParagraph.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin);
SupInfoPrintType = E_SupInfoPrintType.Merge;
try
{
cb.PdfDocument.Close();
cb = null;
}
catch (Exception ex)
{
Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message);
}
_MyHelper = savMyHelper;
MyContentByte = savMyContentByte;
MyReaderHelper = savMyReaderHelper;
}
#region ShrinkSupInfoGroupAtATime
private Dictionary<float, float> _AdjustForParagraphShrinkage;
private float _LastOffset;
private float _LastBottom;
/// <summary>
/// Adjust the font size so that the Supplemental Information will fit on a single page.
/// </summary>
/// <param name="vlnParagraph">supinfo paragraphs</param>
/// <param name="cb">pdfcontentbyte</param>
private void SupInfoAjustGroupings(vlnParagraph vlnParagraph, PdfContentByte cb)
{
// Get groups of SupInfo paragraphs
List<List<vlnParagraph>> supInfoGroups = FindSupInfoGroups(vlnParagraph);
float pageLength = (float)vlnParagraph.MyItemInfo.MyDocStyle.Layout.PageLength;
// Process Each Group of SupInfo paragraphs
foreach (List<vlnParagraph> grp in supInfoGroups)
{
// Initialize font decrement
float decrement = 2f;
float fontSize = grp[0].IParagraph.Leading; // current font size
float mpglen = MeasureSupInfoGroupLength(grp, cb,pageLength); // Measure the length of the group of supinfo paragraphs
// If the group does not fit on a page then reduce the font size
if (mpglen > pageLength)
{
float newFontSize=fontSize;
// reduce the font size by _Decrement until the entire grouping fits on one page
while (mpglen > pageLength) // While the measured supinfo group length is greatere than the page length
{
newFontSize = fontSize - decrement;
float scaler = newFontSize / fontSize;// Calculate the reduction
ReduceSupInfoGroupFontSize(grp, scaler, cb); // Apply the smaller font size
fontSize = newFontSize; // adjust the base font size
mpglen = MeasureSupInfoGroupLength(grp, cb, pageLength);// Measure the length of the group of supinfo paragraphs
}
// Binary Search to find proper font size within .1
while (decrement > .1f)
{
decrement = decrement / 2f; //Reduce the decrement by half
if (mpglen > pageLength) // If the measured length is too big
newFontSize -= decrement;// Reduce the font size
else
newFontSize += decrement;//Otherwise increase the font size
float scaler = newFontSize / fontSize;// Calculate the reduction
ReduceSupInfoGroupFontSize(grp, scaler, cb);// apply the new font size
fontSize = newFontSize;// adjust the base font size
mpglen = MeasureSupInfoGroupLength(grp, cb, pageLength);// Measure the length of the group of supinfo paragraphs
}
if (mpglen > pageLength) //If the measured lenght is greater than the page length reduce the font size
{
newFontSize -= decrement;// Reduce the font size
float scaler = newFontSize / fontSize;// Calculate the reduction
ReduceSupInfoGroupFontSize(grp, scaler, cb);// apply the new font size
fontSize = newFontSize;// adjust the base font size
mpglen = MeasureSupInfoGroupLength(grp, cb, pageLength);// Measure the length of the group of supinfo paragraphs
}
}
}
}
/// <summary>
/// Method to apply a multiplier to the font size to a group of supinfo paragraphs
/// </summary>
/// <param name="grp">group of SupInfo paragraphs</param>
/// <param name="scaler">multiplier for font size</param>
/// <param name="cb">The PDFContentByte which is needed to calculate the adjusted the paragraph height</param>
private void ReduceSupInfoGroupFontSize(List<vlnParagraph> grp, float scaler, PdfContentByte cb)
{
foreach (vlnParagraph pg in grp) // For each paragraph and children apply the scaler
{
// When adjusting the font size if the change causes the paragraph to change due to the number of characters
// per line these changes will impact the paragraphs below the affected paragraph
// This is kept in a dictionary. The key is the vertical offset to the affected paragraph.
// The value is the impact on the paragraph height.
_AdjustForParagraphShrinkage = new Dictionary<float, float>();
// Apply the scaler to each paragraph
ReduceSupInfoGroupFontSize(pg, scaler, cb);
}
}
/// <summary>
/// Method to apply a multiplier to the font size to a supinfo paragraph and children
/// </summary>
/// <param name="pg">supinfo paragraph</param>
/// <param name="scaler">font multiplier</param>
/// <param name="cb">pdfcontentbyte</param>
private void ReduceSupInfoGroupFontSize(vlnParagraph pg, float scaler, PdfContentByte cb)
{
float hBefore = pg.Height;// Save initial paragraph height
AdjustSupInfoTable(pg, scaler,cb);
NewSupInfoFixChunks(pg, scaler);// Apply multiplier to font size
pg.IParagraph.Leading = scaler * pg.IParagraph.Leading; // Adjust leading (line spacing)
// B2017-112: Don't do the font size change if images.
// B2017-116: Don;t do the font size change for RTF Raw
if (pg.ImageText == null && !pg.MyItemInfo.IsRtfRaw)
{
float hAfter = pg.GetParagraphHeight(cb, pg.IParagraph, "", pg.Width); // Calculate new paragraph height
pg.Height = hAfter; // Save new Height;
pg.YBottomMost += hAfter - hBefore; // Adjust YbottomMost for font size and leading
float hleading = hBefore * scaler; // Calcuate leading change
// If the change in font size effects the paragraph height due to word wrapping save the impact to adjust
// Offsets below
if ((hleading > hAfter + 1 && scaler < 1f) || (hleading < hAfter + 1 && scaler > 1f))
{
if (!_AdjustForParagraphShrinkage.ContainsKey(pg.YOffset))
{
_AdjustForParagraphShrinkage.Add(pg.YOffset, hleading - hAfter);
}
}
}
else // Adjust the Image Size B2017-112 And B2017-116
{
pg.ImageScaler *= scaler;
pg.Height *= scaler;
pg.Width *= scaler;
}
float yoBefore = pg.YOffset;// Save the offset before
float yoAfter = pg.YOffset = NewSupInfoFixOffset(pg, scaler);// Calculate the offset after
pg.YBottomMost += yoAfter - yoBefore;// Adjust YbottomMost for changes to yOffset
foreach (vlnParagraph cpg in pg.ChildrenAbove)// Process Children Above
ReduceSupInfoGroupFontSize(cpg, scaler, cb);
foreach (vlnParagraph cpg in pg.ChildrenBelow)// Process Children Below
ReduceSupInfoGroupFontSize(cpg, scaler, cb);
foreach (vlnParagraph cpg in pg.ChildrenLeft)// Process Children Left
ReduceSupInfoGroupFontSize(cpg, scaler, cb);
foreach (vlnParagraph cpg in pg.ChildrenRight)// Process Children Right
ReduceSupInfoGroupFontSize(cpg, scaler, cb);
foreach (vlnPrintObject po in pg.PartsAbove) // Process Parts Above (headers)
NewSupInfoFixParts(po, scaler);
foreach (vlnPrintObject po in pg.PartsBelow) // Process Parts Below (unknown)
NewSupInfoFixParts(po, scaler);
foreach (vlnPrintObject po in pg.PartsLeft) // Process Parts Left (Tabs)
NewSupInfoFixParts(po, scaler);
foreach (vlnPrintObject po in pg.PartsRight) // Process Parts Right (unknown)
NewSupInfoFixParts(po, scaler);
}
/// <summary>
/// Adjust the Table Fonts to shrink the sup info text
/// </summary>
/// <param name="pg">vlnParagraph potentially containing a vlnTable</param>
/// <param name="scaler">multiplier</param>
/// <param name="cb">pdfContentByte</param>
private void AdjustSupInfoTable(vlnParagraph pg, float scaler, PdfContentByte cb)
{
// Adjust the table if it exists
if (pg.MyGrid != null)
{
// Create lists of heights before and after shrinking sup info
Dictionary<int, float> beforeRowHeight = new Dictionary<int, float>();
Dictionary<int, float> afterRowHeight = new Dictionary<int, float>();
for (int i = 0; i < pg.MyGrid.RowTop.GetLength(0)-1; i++)
{
beforeRowHeight.Add(i, scaler * (pg.MyGrid.RowTop[i+1] - pg.MyGrid.RowTop[i]));
afterRowHeight.Add(i, 0);
}
// Adjust font size for each cell.
foreach (vlnCell cell in pg.MyGrid.MyCells)
{
float x = cell.MyTable.ColLeft[cell.c1];
float w = cell.MyTable.ColLeft[cell.c2 + 1] - x;
float hBefore = scaler * pg.GetParagraphHeight(cb,cell.MyPara,"",w);
foreach (Chunk chk in cell.MyPara.Chunks)
chk.Font.Size = scaler * chk.Font.Size;
float hAfter = 1.075F * pg.GetParagraphHeight(cb,cell.MyPara,"",w);// 1.075 is a magic number that worked for Ginna. Otherwise decenders overlapped the bottom line of the cell.
cell.HContent = hAfter;
// Save tthe height after adjusting the font size to account for changes in word wrap.
afterRowHeight[cell.r1]=Math.Max(hAfter,afterRowHeight[cell.r1]);
}
for (int i = 0; i < pg.MyGrid.RowTop.GetLength(0)-1; i++)
{
pg.MyGrid.RowTop[i+1] = scaler * pg.MyGrid.RowTop[i+1];// Adjust for leading
pg.MyGrid.RowTop[i+1] += (afterRowHeight[i]-beforeRowHeight[i]); //Adjust for word wrapping
}
}
}
/// <summary>
/// Adjust YOffset for Print Objects
/// </summary>
/// <param name="vpo">Print Object (tab, paragraph, etc.)</param>
/// <param name="scaler">multiplier</param>
/// <returns></returns>
private float NewSupInfoFixOffset(vlnPrintObject vpo, float scaler)
{
float fixOffSet = 0;
// determine impact of paragraphs above due to word-wrap
foreach (float off in _AdjustForParagraphShrinkage.Keys)
if (off < vpo.YOffset)
fixOffSet += _AdjustForParagraphShrinkage[off];
// combine this impact with the scaler on the YOffset
return scaler * vpo.YOffset - fixOffSet;
}
/// <summary>
/// Adjust Font Size and offset for Parts
/// </summary>
/// <param name="po">PrintObject</param>
/// <param name="scaler">Multiplier</param>
private void NewSupInfoFixParts(vlnPrintObject po, float scaler)
{
if (po.IParagraph == null) return; // B2017-132 check for NULL reference (happend printing Bryon SAMGS with sup info pages)
// Adjust the font size by the multiplier
foreach (Chunk chk in po.IParagraph.Chunks)
chk.Font.Size = scaler * chk.Font.Size;
po.IParagraph.Leading = scaler * po.IParagraph.Leading;// Apply the multiplier to the leading (line spacing)
po.YOffset = NewSupInfoFixOffset(po,scaler);// Adjust the YOffset
}
/// <summary>
/// Adjust the Font Size
/// </summary>
/// <param name="vlnParagraph">Paragraph</param>
/// <param name="scaler">Multiplier</param>
private void NewSupInfoFixChunks(vlnParagraph vlnParagraph, float scaler)
{
// Adjust the font size by the multiplier
foreach (Chunk chk in vlnParagraph.IParagraph.Chunks)
chk.Font.Size = scaler * chk.Font.Size;
}
/// <summary>
/// Measure the Length of the Group
/// </summary>
/// <param name="grp">Group of SupInfo Paragraphs</param>
/// <param name="cb">pdfContentByte</param>
/// <param name="pagelength">Page Length</param>
/// <returns>Length</returns>
private float MeasureSupInfoGroupLength(List<vlnParagraph> grp, PdfContentByte cb, float pagelength)
{
_LastBottom = 0;
_LastOffset = 12;// 24; // account for the Sup Info header (two lines)
float fontSize = grp[0].IParagraph.Leading; // current font size
// For each SupInfo Paragraph calculate length
foreach (vlnParagraph pg in grp)
{
MeasureSupInfoGroupLength(pg, cb);// Measure a SupInfo Paragraph and children
_LastOffset += _LastBottom;
_LastBottom = 0;
}
//Console.WriteLine("MeasureSupInfoGroupLength {0} {1} {2} {3}", grp[0].MyItemInfo.ItemID, _LastOffset, fontSize, pagelength);
return _LastOffset;
}
/// <summary>
/// Measure the height of a supinfo paragraph and children
/// </summary>
/// <param name="pg">SupInfo paragraph</param>
/// <param name="cb">pdfContentByte</param>
private void MeasureSupInfoGroupLength(vlnParagraph pg, PdfContentByte cb)
{
_LastBottom = pg.YBottomMost;
foreach (vlnParagraph cpg in pg.ChildrenAbove) // Measure Children Above
MeasureSupInfoGroupLength(cpg, cb);
foreach (vlnParagraph cpg in pg.ChildrenBelow) // Measure Children Below
MeasureSupInfoGroupLength(cpg, cb);
foreach (vlnParagraph cpg in pg.ChildrenLeft) // Measure Children Left
MeasureSupInfoGroupLength(cpg, cb);
foreach (vlnParagraph cpg in pg.ChildrenRight) // Measure Children Right
MeasureSupInfoGroupLength(cpg, cb);
}
/// <summary>
/// Find Groups of SupInfo Paragraphs
/// </summary>
/// <param name="vlnParagraph">SupInfo Paragraph</param>
/// <returns>List of supinfo paragraph groups</returns>
private List<List<vlnParagraph>> FindSupInfoGroups(vlnParagraph vlnParagraph)
{
List<List<vlnParagraph>> supInfoGroups;
supInfoGroups = new List<List<vlnParagraph>>();
foreach (vlnParagraph pg in vlnParagraph.ChildrenBelow)
{
SectionInfo supInfoSect = (pg.MyItemInfo.ActiveSection != null) ? pg.MyItemInfo.ActiveSection as SectionInfo : null;
if (supInfoSect != null && supInfoSect.StepSectPageBreaksForSupInfo != null && supInfoSect.StepSectPageBreaksForSupInfo.Contains(pg.MyItemInfo.ItemID)) // C2018-003 fixed use of getting the active section
supInfoGroups.Add(new List<vlnParagraph>()); // add a grouping since a page break exists
if (supInfoGroups.Count == 0)
{
supInfoGroups.Add(new List<vlnParagraph>()); // add a grouping since a page break exists
_MyLog.WarnFormat("SupInfo Print Groups: {0}, {1}", pg.MyItemInfo.ItemID, pg.MyItemInfo.ShortPath);
}
supInfoGroups[supInfoGroups.Count - 1].Add(pg); // add paragraph to the last grouping
}
return supInfoGroups;
}
#endregion //ShrinkSupInfoGroupAtATime
public void DoSupInfoPage(PdfContentByte cb, string str, PdfLayer textLayer, VlnSvgPageHelper myPageHelper, int itemid, bool insertBlankPages)
{
// see if the ID is in the facing page pdf - if so, get the page:
if (SupInfoPdfPage == null || SupInfoPdfPage.Count < 1) return;
int getpage = 0;
if (SupInfoPdfPage.ContainsKey(itemid)) getpage = SupInfoPdfPage[itemid];
if (getpage < 0)
{
InsertBlankPage(cb);
return;
}
PdfImportedPage sipage = null;
try
{
string SupInfoPdfName = Volian.Base.Library.VlnSettings.TemporaryFolder + @"\SupInfo" + myPageHelper.MySection.ItemID.ToString() + @".pdf";
PdfReader pdfreader = new PdfReader(SupInfoPdfName);
sipage = cb.PdfWriter.GetImportedPage(pdfreader, getpage+1);
AddImportedPageToLayer(cb.PdfWriter.DirectContent, textLayer, sipage, 0, 0);
DoingFacingPage = true;
myPageHelper.ResetSvg();
NewPage();
DoingFacingPage = false;
myPageHelper.ResetSvg();
pdfreader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void DoFoldoutPage(PdfContentByte cb, string str, PdfLayer textLayer, VlnSvgPageHelper myPageHelper, int foldoutindx, bool insertBlankPages)
{
if (_MyFoldoutSection == null || _MyFoldoutSection.Count==0) return;
// if the very first page to be output is a 'foldout', treat this as a special case, since
// if duplex printing is on, the foldout should always be on the left side, i.e. or behind
// the document text. The option PROMS provides is to either:
// 1) Skip doing the foldout before the first page, if the 'InsertBlankPages' isn't set, by not checking
// the checkbox on the print dialog.
// 2) Insert a blank page as the first page, if the 'InsertBlankPages' is set.
if (!myPageHelper.PrintedAPage && !insertBlankPages) return;
if (!myPageHelper.PrintedAPage)
{
// only insert a blank page if this is the very first page printed & section has a foldout
// and the checkbox on the print dialog to add blank pages is checked. This will put out a blank page as
// as the first page so that duplex printing is correct for this condition.
InsertBlankPage(cb);
}
SectionInfo saveSect = myPageHelper.MySection;
myPageHelper.MySection = _MyFoldoutSection[foldoutindx];
myPageHelper.OnFoldoutPage = true;
if (_MyFoldoutReader != null)
{
bool doimport2 = true;
PdfImportedPage fgPage = null;
try
{ // read saved foldout page
fgPage = cb.PdfWriter.GetImportedPage(_MyFoldoutReader[foldoutindx],1);
}
catch (Exception ex)
{
Console.WriteLine(ex);
doimport2 = false;
}
if (doimport2)
{// put the saved foldout page into the PDF
AddImportedPageToLayer(cb.PdfWriter.DirectContent, textLayer, fgPage, 0, 0);
foreach (iTextSharp.text.pdf.PdfAnnotation.PdfImportedLink il in _MyFoldoutReader[foldoutindx].GetLinks(1))
{
if(!il.IsInternal() )
cb.PdfWriter.AddAnnotation(il.CreateAnnotation(cb.PdfWriter));
}
if (DebugPagination.IsOpen) DebugPagination.WriteLine("{0:D6},'{1}',{2}",
myPageHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "Foldout", 1);
//if (BaselineMetaFile.IsOpen) BaselineMetaFile.WriteLine("!! {0:D6},'{1}',{2}",
//myPageHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, "Foldout", 1);
}
}
//_MyLog.InfoFormat("DoFoldoutPage {0}", cb.PdfWriter.CurrentPageNumber);
//PrintTextMessage(cb, "Foldout for: " + str, textLayer);
NewPage();// Temporary for foldout/16bit-32bit page alignment
//_MyLog.InfoFormat("NewPage 8 {0}", cb.PdfWriter.CurrentPageNumber);
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();
}
// C2021-010: Remove trailing returns/spaces & manual page breaks & allow save.
public void SavePaginationFixes()
{
// If manual page breaks were removed (during pagination), save those
if (RemoveManualPageBreaks != null && RemoveManualPageBreaks.Count > 0)
{
foreach (int iid in RemoveManualPageBreaks)
{
ItemInfo ii = ItemInfo.Get(iid);
StepConfig sc = ii.MyConfig as StepConfig;
if (sc != null)
{
using (Item itm = Item.Get(iid))
{
if (!HasManPagAnnot(ii, "Removed Manual Page Break")) VEPROMS.CSLA.Library.Annotation.MakeAnnotation(itm, AnnotationType.GetByNameOrCreate("Manual Pagination Issues"), null, "Removed Manual Page Break", null);
sc.Step_NewManualPagebreak = false; // reset the flag that was set in the config
itm.MyContent.Config = sc.ToString();
itm.MyContent.DTS = DateTime.Now;
itm.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
itm.MyContent.Save();
}
}
}
}
// If trailing newlines and/or spages were removed, save those
if (RemoveTrailingHardReturnsAndSpaces != null && RemoveTrailingHardReturnsAndSpaces.Count > 0)
{
foreach (int iid in RemoveTrailingHardReturnsAndSpaces)
{
// first check if it exists, if the step was empty, it may have been deleted.
ItemInfo iitmp = ItemInfo.Get(iid);
if (iitmp != null)
{
string annot = "Removed Trailing Newlines and Spaces";
if (RemoveManualPageBreaks != null && RemoveManualPageBreaks.Contains(iid)) annot = "Removed Trailing Newlines, Spaces and ManualPageBreak";
string tmp = Regex.Replace(iitmp.MyContent.Text, "(\\\\line|\r|\n|\\\\u160\\?| )+$", "");
// if the step ends up empty, set the text to a space (if null or "") step gets deleted.
// B2021-028: removed code that set a step config item flagging an empty step. This had been put in to print
// the same way before save but that printing was wrong and was fixed for this bug.
if (tmp == null || tmp == "")
{
tmp = " ";
annot = "Empty step. Consider deleting to restore standard pagination.";
}
bool alreadyHasAnnot = HasManPagAnnot(iitmp, annot); // don't add annotation if it exists.
using (Item itm = Item.Get(iid))
{
if (!alreadyHasAnnot) VEPROMS.CSLA.Library.Annotation.MakeAnnotation(itm, AnnotationType.GetByNameOrCreate("Manual Pagination Issues"), null, annot, null);
itm.MyContent.Text = tmp;
itm.MyContent.DTS = DateTime.Now;
itm.MyContent.UserID = Volian.Base.Library.VlnSettings.UserID;
itm.MyContent.Save();
}
}
}
}
}
private bool HasManPagAnnot(ItemInfo iitmp, string annotstr)
{
if (iitmp.ItemAnnotations != null && iitmp.ItemAnnotationCount > 0)
{
// check each annotation to see if this manual pagination issue exists - so it won't get added again.
foreach (AnnotationInfo ai in iitmp.ItemAnnotations)
{
if (ai.MyAnnotationType.Name.StartsWith("Manual Pagination Issues"))
if (ai.SearchText.StartsWith(annotstr)) return true;
}
}
return false;
}
}
public class ReaderHelper
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<string, PdfImportedPage> dicPage = new Dictionary<string, PdfImportedPage>();
private Dictionary<string, iTextSharp.text.Rectangle> dicSize = new Dictionary<string, iTextSharp.text.Rectangle>();
private PromsPrinter _MyPromsPrinter;
public PromsPrinter MyPromsPrinter
{
get { return _MyPromsPrinter; }
set { _MyPromsPrinter = value; }
}
private SectionInfo _MySectionInfo;
public SectionInfo MySectionInfo
{
get { return _MySectionInfo; }
set
{
if (_MySectionInfo == null || value.ItemID != _MySectionInfo.ItemID)
{
_MySectionInfo = value;
//MyPdfFile = _MyPromsPrinter.BuildMSWordPDF(MySectionInfo);
//try
//{
// MyReader = MyPdfFile != null ? new PdfReader(MyPdfFile) : null;
// string key = string.Empty;
// for (int i = 1; i <= MyReader.NumberOfPages; i++)
// {
// key = string.Format("{0}.{1}", MySectionInfo.ItemID, i);
// dicPage.Add(key, MyPromsPrinter.MyContentByte.PdfWriter.GetImportedPage(MyReader, i));
// dicSize.Add(key, MyReader.GetPageSizeWithRotation(i));
// }
//}
//catch (Exception ex)
//{
// MyReader = null;
//}
}
}
}
private string _MyPdfFile;
public string MyPdfFile
{
get { return _MyPdfFile; }
set { _MyPdfFile = value; }
}
private int _DocID;
public int DocID
{
get { return _DocID; }
set { _DocID = value; }
}
private PdfReader _MyReader;
public PdfReader MyReader
{
get { return _MyReader; }
set { _MyReader = value; }
}
public ReaderHelper(PromsPrinter pp)
{
MyPromsPrinter = pp;
//this.LoadTree(pp.MyItem);
}
public PdfImportedPage GetPage(SectionInfo sectInfo, int pageNumber)
{
string key = string.Format("{0}.{1}", sectInfo.ItemID, pageNumber);
return dicPage[key];
}
public iTextSharp.text.Rectangle GetSize(SectionInfo sectInfo, int pageNumber)
{
string key = string.Format("{0}.{1}", sectInfo.ItemID, pageNumber);
if(dicSize.ContainsKey(key))
return dicSize[key];
return PDFPageSize.UsePaperSize(sectInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files
}
public void LoadTree(ItemInfo ii)
{
dicPage = new Dictionary<string, PdfImportedPage>();
dicSize = new Dictionary<string, iTextSharp.text.Rectangle>();
LoadSectionTree(ii);
}
private void LoadSectionTree(ItemInfo ii)
{
if (ii.Sections == null) return; // B2021-067 crash on null reference
foreach (SectionInfo si in ii.Sections)
{
if (si.IsStepSection)
{
if(si.Sections != null)LoadSectionTree(si);
}
else
{
MyPdfFile = _MyPromsPrinter.BuildMSWordPDF(si);
if (MyPdfFile != null)
{
try
{
FileInfo fi = new FileInfo(MyPdfFile);
if (fi.Length == 0 ) // B2017-218 Handle invalid word sections
{
if(!PromsPrinter.BaselineTesting) //B2018-071 Output a message box unless baseline testing is being performed.
MessageBox.Show(si.DisplayNumber + " " + si.DisplayText + " is not valid", "Invalid Word Section", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
MyReader = MyPdfFile != null ? new PdfReader(MyPdfFile) : null;
string key = string.Empty;
for (int i = 1; i <= MyReader.NumberOfPages; i++)
{
key = string.Format("{0}.{1}", si.ItemID, i);
dicPage.Add(key, MyPromsPrinter.MyContentByte.PdfWriter.GetImportedPage(MyReader, i));
iTextSharp.text.Rectangle rectgl = MyReader.GetPageSizeWithRotation(i);
// If the word page is set to landscape, but the document style is not landscape, then flip the height and width (put back to portrait)
if (!((si.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_WordContentLandscaped) == E_DocStructStyle.DSS_WordContentLandscaped) && rectgl.Height < rectgl.Width)
rectgl = new iTextSharp.text.Rectangle(rectgl.Height, rectgl.Width);
dicSize.Add(key, rectgl);
//dicSize.Add(key, MyReader.GetPageSizeWithRotation(i));
}
}
catch (Exception ex)
{
if (_MyPromsPrinter.DocReplace == null)
MessageBox.Show(ex.Message, ex.GetType().FullName, MessageBoxButtons.OK, MessageBoxIcon.Error);
_MyLog.Warn(string.Format("Error in LoadSectionTree [{0}],{1}.{2}", si.ItemID, si.DisplayNumber, si.DisplayText), ex);
}
}
}
}
}
}
//public class PrintTimer
//{
// private DateTime _StartTime = DateTime.Now;
// public DateTime StartTime
// {
// get { return _StartTime; }
// set { _StartTime = value; }
// }
// private string _Description = "Start";
// public string Description
// {
// get { return _Description; }
// set
// {
// DateTime dtNext = DateTime.Now;
// //Console.WriteLine("{0},'{1}'", TimeSpan.FromTicks(dtNext.Ticks - LastTime.Ticks).TotalSeconds, Description);
// _Description = value;
// _LastTime = dtNext;
// }
// }
// private DateTime _LastTime = DateTime.Now;
// public DateTime LastTime
// {
// get { return _LastTime; }
// set { _LastTime = value; }
// }
//}
}