using System; using System.Collections.Generic; using System.Text; using System.Drawing; using iTextSharp.text.pdf; using iTextSharp.text; using VEPROMS.CSLA.Library; namespace Volian.Print.Library { public partial class vlnTab : vlnText { /// /// Used to Align Tabs for numeric tabs that can go to 2 digits /// private float? _TabAlign; public float TabAlign // Offset to Last printable character { get { if (_TabAlign == null) { _TabAlign = 0; if (Text != null && (!MyParent.MyItemInfo.IsStep || !MyParent.MyItemInfo.FormatStepData.TabData.NoTabAlign)) { while (_TabAlign < Text.Length && Text[(int)_TabAlign] == ' ') _TabAlign++; if (_TabAlign < Text.Length) { if ("0123456789".Contains(Text[(int)_TabAlign].ToString())) { while (_TabAlign < Text.Length && "0123456789".Contains(Text[(int)_TabAlign].ToString())) _TabAlign++; _TabAlign--; } } else _TabAlign = 0; } } return (float)_TabAlign * MyFont.CharsToTwips; } } private float? _TabOffset; public float TabOffset // Offset to first printable character { get { if (_TabOffset == null) { _TabOffset = 0; if (Text != null) { while (_TabOffset= Text.Length) _TabOffset = 0; return (float)_TabOffset * MyFont.CharsToTwips; } } private vlnMacro _MyMacro; public vlnMacro MyMacro { get { return _MyMacro; } set { _MyMacro = value; } } private string symblsStr = "\u25CF\u0394"; // string of possible symbol character in a tab // add symbol characters as needed // "\u25CF" - solid bullet // \x0394 - delta private System.Drawing.FontStyle GetSysFontStyle(VE_Font f) { if (f.Style == E_Style.Italics) return System.Drawing.FontStyle.Italic; return FontStyle.Regular; } public float GetTextWidth(VE_Font vefont, string txt) { return GetTextWidth(vefont, txt, SymbolFontName); } private float GetTextWidth(VE_Font vefont, string txt, string symblFontName) { // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //System.Drawing.Font font = new System.Drawing.Font(vefont.Family, (float)vefont.Size, GetSysFontStyle(vefont)); //System.Drawing.Font symbFont = new System.Drawing.Font(symblFontName, (float)vefont.Size); System.Drawing.Font font = VE_Font.GetWinSysFont(vefont.Family, (float)vefont.Size, GetSysFontStyle(vefont)); System.Drawing.Font symbFont = VE_Font.GetWinSysFont(symblFontName, (float)vefont.Size); iTextSharp.text.Font iFont = Volian.Svg.Library.VolianPdf.GetFont(font); iTextSharp.text.Font iSymblFont = Volian.Svg.Library.VolianPdf.GetFont(symbFont); float w = 0; foreach (char c in txt) { int idx = symblsStr.IndexOf(c); if (idx >= 0) // symbol character - use symbol font to find its width w += iSymblFont.BaseFont.GetWidthPointKerned(symblsStr[idx].ToString(), (float)vefont.Size); else w += iFont.BaseFont.GetWidthPointKerned(c.ToString(), (float)vefont.Size); } //float w = iFont.BaseFont.GetWidthPointKerned(Text.Replace("\u25CF","@"), (float)vefont.Size); return w; } bool _ScriptCaution = false; public bool ScriptCaution { get { return _ScriptCaution; } set { _ScriptCaution = value; } } bool _SeparateBullet = false; public bool SeparateBullet { get { return _SeparateBullet; } set { _SeparateBullet = value; } } private string _SymbolFontName; public string SymbolFontName { get { return _SymbolFontName; } set { _SymbolFontName = value; } } public vlnTab(PdfContentByte cb, vlnParagraph myparent, string origTab, string cleanTab, float xoffset, float yoffset, VE_Font vFont, bool doSectTab, string symblFontName, bool removedUnderline) { SymbolFontName = symblFontName; bool alignAsIfBulleted = false; ScriptCaution = (origTab.Contains("Caution") && vFont.Family == "VolianScript"); MyContentByte = cb; MyParent = myparent; YOffset = yoffset; Text = cleanTab; MyFont = vFont; // C2018-024 I in Arial font changed to I in TimesNewRoman if (myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ChangeFontUpperCaseIinArial && cleanTab.StartsWith("I.")) vFont = new VE_Font("Times New Roman", (int)vFont.Size, (E_Style)vFont.Style, (float)vFont.CPI); // BGE has a format flag to increase size of font, if top level: if (doSectTab && myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.SectionNumber.Level0Big && myparent.MyItemInfo.MyParent.IsProcedure) vFont = new VE_Font(vFont.Family, 14, (E_Style)vFont.Style | E_Style.Bold, 8); float CCCs = GetTextWidth(MyFont, "CCCCCCCCCC", symblFontName); float IIIs = GetTextWidth(MyFont, "iiiiiiiiii", symblFontName); string origTab1 = origTab; if (ScriptCaution) { Text = origTab.Replace("Caution ", "\uF043\uF061\uF069\uF06E\uF06F\uF074\uF075\uF020\uF020"); Width = 90; } else if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0) //if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0) Width = (float)myparent.MyItemInfo.FormatStepData.TabData.IdentWidth; else if (CCCs != IIIs) { float tPtPerChar = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TabPtsPerChar ?? 6; Width = (tPtPerChar == 0 ? 6 : tPtPerChar) * origTab.Length; // Check the following, it may be needed for FPL: //origTab1 = origTab1.TrimStart(" ".ToCharArray()); // 6 = number of points per character. 4 characters between end of tab and beginning of text // origTab1.Trim... is number of non-space characters of the tab string. //Width = 6 * (4 + origTab1.Trim(" ".ToCharArray()).Length); } else Width = GetTextWidth(MyFont, (Text != null ? Text : origTab), symblFontName); //MyFont.CharsToTwips * (Text != null ? Text.Length : origTab.Length); // Pairie Island (NSP) Caution and Note tabs use a larger font // When using a bullet, we need to use the font size of the Caution/Note text instead of the tab. // To do this we set the TabData.Bullet.Separate to true (currently - 4/26/2013 - only NSP uses this). // Because of the different font sizes, when the Caution/Note did have have a bullet, the positioning // was off by the lenght of IdentB (the bullet string), thus the "alignAsIfBulleted" bool if ((myparent.MyItemInfo.FormatStepData != null) && myparent.MyItemInfo.FormatStepData.TabData.Bullet.Separate) if (myparent.MyItemInfo.MyPrevious != null || myparent.MyItemInfo.NextItem != null) SeparateBullet = true; else alignAsIfBulleted = true; if (origTab.Contains(@"{!")) { int mindx = origTab.IndexOf(@"{!"); int meindx = origTab.IndexOf(@"}", mindx); string macro = origTab.Substring(mindx, meindx - mindx + 1); // Width for placement of macro should be position in the string where the macro was located. float lwidth = MyFont.CharsToTwips * (origTab.Length - meindx - 1); MyMacro = new vlnMacro(xoffset - lwidth, yoffset, macro.Substring(2, macro.Length - 3)); xoffset += myparent.MyItemInfo.FormatStepData.TabData.MacroTabAdjust ?? 0; origTab = origTab.Replace(macro, ""); cleanTab = origTab; if (CCCs != IIIs) { float? tPtPerChar1 = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TabPtsPerChar; if (tPtPerChar1 != null) Width = (float)tPtPerChar1 * origTab.Length; else if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0) Width = (float)myparent.MyItemInfo.FormatStepData.TabData.IdentWidth; else { origTab = origTab + " "; origTab = origTab.TrimStart(" ".ToCharArray()); if (mindx > 2) // ouch! Width = 6f * (origTab.Length - 1); // FPL (macro is after {numeric}) FPL is good with genmac output! else Width = 3 + (6f * origTab.Length); // NSP (macro is before {numeric}) } } else Width = GetTextWidth(MyFont, (cleanTab != null ? cleanTab : origTab), symblFontName);//MyFont.CharsToTwips * (cleanTab != null ? cleanTab.Length : origTab.Length); } else { origTab = origTab1; } // if this tab was underlined, we may need to add partial underlining back in, if it was // removed when the bullet was added. This handles the case where the bullet was appended // to the tab, for example "NOTE: o". if (removedUnderline) { int sep = origTab.IndexOfAny(". ".ToCharArray()); string prefix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b\ul " : @"\ul "; string suffix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b0\ulnone " : @"\ulnone "; //origTab = @"\ul " + origTab.Substring(0, sep-1) + @"\ulnone" + origTab.Substring(sep-1); //origTab = @"\ul " + origTab.Substring(0, sep) + @"\ulnone" + origTab.Substring(sep); origTab = prefix + origTab.Substring(0, sep) + suffix + origTab.Substring(sep); } UnderlineTerminateList utl = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.UnderlineTerminateList; // if this tab is underlined, the underlining should not underline the ':'. Check for "NOTE:" // or "CAUTION:", i.e. only underline up to ':' if (myparent.MyItemInfo.IsStep && ((myparent.MyItemInfo.FormatStepData.AlwaysTab || myparent.MyItemInfo.MyPrevious == null) && ((vFont.Style & E_Style.Underline) > 0) && (origTab.ToUpper().Contains("NOTE:") || origTab.ToUpper().Contains("CAUTION:")))) { FontStyle style = FontStyle.Regular; if ((vFont.Style & E_Style.Bold) > 0) style |= FontStyle.Bold; if ((vFont.Style & E_Style.Italics) > 0) style |= FontStyle.Italic; // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //vFont.WindowsFont = new System.Drawing.Font(vFont.Family, (float)vFont.Size, style); vFont.WindowsFont = VE_Font.GetWinSysFont(vFont.Family, (float)vFont.Size, style); int indxC = origTab.IndexOf(":"); origTab = @"\ul " + origTab.Substring(0, indxC) + @"\ulnone" + origTab.Substring(indxC); } else if (utl != null && utl.Count > 0 && ((vFont.Style & E_Style.Underline) > 0)) { foreach (UnderlineTerminate ut in utl) { if (origTab.Contains(ut.Text)) { FontStyle style = FontStyle.Regular; if ((vFont.Style & E_Style.Bold) > 0) style |= FontStyle.Bold; if ((vFont.Style & E_Style.Italics) > 0) style |= FontStyle.Italic; // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //vFont.WindowsFont = new System.Drawing.Font(vFont.Family, (float)vFont.Size, style); vFont.WindowsFont = VE_Font.GetWinSysFont(vFont.Family, (float)vFont.Size, style); int indxC = origTab.IndexOf(ut.Text); string prefix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b\ul " : @"\ul "; string suffix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b0\ulnone " : @"\ulnone "; //origTab = @"\ul " + origTab.Substring(0, indxC) + @"\ulnone " + origTab.Substring(indxC); origTab = prefix + origTab.Substring(0, indxC) + suffix + origTab.Substring(indxC); break; } } } Rtf = GetRtf(origTab, vFont); Rtf = Rtf.Replace("\u0394", @"\f1\u916?\f0 "); // delta 0x0394 if (ScriptCaution) { Rtf = GetRtf("\u25CFCaution ", vFont); Rtf = Rtf.Replace("\u25CF", @"\f1\fs20 \u9679?\f0\par\f0\fs64 "); // bullet 25CF // jsj- force bullet size (is different than tab text) if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.MyPrevious != null) Rtf = Rtf.Replace("Caution ", @"\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?"); else { if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.NextItem == null) Rtf = Rtf.Replace(@"\u9679?", ""); Rtf = Rtf.Replace("Caution ", @"\u61507?\u61537?\u61557?\u61556?\u61545?\u61551?\u61550?\u61472?\u61472?"); } } else { if (SeparateBullet) Rtf = Rtf.Replace("\u25CF", ""); else Rtf = Rtf.Replace("\u25CF", @"\f1\u9679?\f0 "); // bullet 25CF // jsj- add space after \f0 //Rtf = Rtf.Replace("\u25CF", @"\f1\fs18\b0\i0 \u9679?\f0 "); // bullet 25CF // jsj- add space after \f0 if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.MyPrevious != null && (!myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.OnlyBulletSameCautionNoteType || (myparent.MyItemInfo.MyPrevious.MyContent.Type == myparent.MyItemInfo.MyContent.Type))) { //if (scriptCaution) // Rtf = Rtf.Replace("CAUTION ", @"\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?"); Rtf = Rtf.Replace("Caution:", " "); Rtf = Rtf.Replace("Note:", " "); Rtf = Rtf.Replace("CAUTION:", " "); Rtf = Rtf.Replace("NOTE:", " "); Rtf = Rtf.Replace("Caution", " "); Rtf = Rtf.Replace("Note", " "); Rtf = Rtf.Replace("CAUTION", " "); Rtf = Rtf.Replace("NOTE", " "); } } //if (ScriptCaution && Rtf.Contains("Caution")) //{ // // NSP script caution // iTextSharp.text.Font myfont = pdf.GetFont(vFont.Family, 28, 0, iTextSharp.text.Color.BLACK); // if (!myfont.BaseFont.CharExists(0x43)) // Capital 'C' exists as text // { // //VE_Font vf = new VE_Font("VolianScript", 28, E_Style.Italics, 12); // // Capital 'C' exists as Symbol // Rtf = Rtf.Replace("Caution ", @"\u61507?\u61537?\u61557?\u61556?\u61545?\u61551?\u61550?\u61472?\u61472?"); // } //} // do positioning based on whether format has locations for section 'header'. If it's not centered, treat // it's location more like a 'tab'. if (doSectTab) { XOffset = xoffset; // the width was just a little small, so it was wrapping - but only if there were no spaces at end // so use this condition to do minimal impact (WCN1 format, for section tabs with three places, i.e. 6.1.2 if (!cleanTab.EndsWith(" ")) Width += .1f; } else { // if using a proportional font and the tab font/size is different than the text font/size if (CCCs != IIIs && (MyFont.Family != myparent.MyItemInfo.FormatStepData.Font.Family || MyFont.Size != myparent.MyItemInfo.FormatStepData.Font.Size)) { // This is needed for Prairie Island (NSP) Caution/Note tabs to consistantly position // them at the same horizontal (column) position on the page string txt = Text; if (alignAsIfBulleted) txt += myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.IdentB; // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //System.Drawing.Font font = new System.Drawing.Font(MyFont.Family, (float)MyFont.Size); System.Drawing.Font font = VE_Font.GetWinSysFont(MyFont.Family, (float)MyFont.Size); iTextSharp.text.Font iFont = Volian.Svg.Library.VolianPdf.GetFont(font); float w = iFont.BaseFont.GetWidthPointKerned(txt, (float)MyFont.Size); Width = w; } XOffset = xoffset - Width; } } public override float ToPdf(PdfContentByte cb, float yPageStart, ref float yTopMargin, ref float yBottomMargin) { // Don't print a Tab if the text contains a Grid if (MyParent.MyItemInfo.MyContent.MyGrid != null) return yPageStart; if (MyParent.MyItemInfo.FormatStepData != null && MyParent.MyItemInfo.FormatStepData.StepPrintData != null) XOffset += (float)(MyParent.MyItemInfo.FormatStepData.StepPrintData.PosAdjust ?? 0); float yLocation = CalculateYOffset(yPageStart, yTopMargin); Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, "", yBottomMargin); return yPageStart; } } }