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 vlnBox : vlnPrintObject { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private int _LineType; /* how to represent?? */ private System.Drawing.Color _Color; public System.Drawing.Color Color { get { return _Color; } set { _Color = value; } } private Box _MyBox; public Box MyBox { get { return _MyBox; } set { _MyBox = value; } } // the following two fields are used if 'boxed' step, thus // no 'Box' was defined in format file. public override float Height { get { if (_Height == 0) _Height = GetParagraphHeight(MyContentByte, IParagraph,string.Empty, Width); return _Height; } set { _Height = value; } } public string DefBox = null; public float DefEnd = 0; private bool _ContainsPageBreak = false; public bool ContainsPageBreak { get { return _ContainsPageBreak; } set { _ContainsPageBreak = value; } } private bool _DoubleBoxHls = false; // BGE double lined box around HLS public bool DoubleBoxHls { get { return _DoubleBoxHls; } set { _DoubleBoxHls = value; } } public const string DOUBLEboxHLS = "DoubleBox"; //private bool _DoBottom = true; public vlnBox() { } public vlnBox(vlnParagraph paragraph) { } public const string BoxThin = "\x2510.\x2500.\x250c.\x2502. . .\x2518.\x2514. .\x2500. . "; const string BoxThick = "\x2584.\x2584.\x2584.\x2588. . .\x2580.\x2580. .\x2580. . "; const string BoxDouble = "\x2557.\x2550.\x2554.\x2551. . .\x255D.\x255A. .\x2550. . "; const string BoxFPLNote = "\x2557.\x2550\xad.\x2554\xad.\x2551. . .\x255d.\x255a\xad. .\x2550\xad. . "; const string BoxFPLCaution = "\x2588.\x2580.\x2588.\x2588. . .\x2588.\x2588. .\x2584. . "; const string BoxAsterisk = " *.* .* . . . . *.* . .* . . "; const string BoxAsteriskWithSides1 = " *.* .* .* . . . *.* . .* . . "; // ip2 const string BoxAsteriskWithSides2 = " *. *.*.*. . . *.*. . *. . "; // ip3 const string BoxAsteriskWithSides3 = "*.*.*.*.*.*.*.*.*.*.*.*"; //byr const string BoxAsteriskWithSides4 = "*.*.*.*.*.*.*.*. .*. . "; // wep2 const string BoxAsteriskWithSides5 = "*.*.*.*. . .*.*. .*.*.*"; // WEP2 (Point Beach) const string BoxAsteriskTopBottom = "*.*.*. . . .*.*. .*. . "; // fnp const string BoxLineTopBottom = "\x2500.\x2500.\x2500. . . .\x2500.\x2500. .\x2500. . "; // fnp const string BoxAsteriskTopBotton2 = " .*. . . . . . . .*. . "; // Robinson (CPL) public vlnBox MyParentBox { get { // B2018-096 AEP 082.002CD Note Box overlapping Step Box vlnParagraph parent = MyParent.MyParent; if(parent == null) return null; if (parent.MyItemInfo.FormatStepData != null && !parent.MyItemInfo.FormatStepData.BoxIt) return null; if (parent.PartsContainer == null) return null; foreach(vlnPrintObject obj in parent.PartsContainer) if (obj is vlnBox) return(obj as vlnBox); return null; } } public override float ToPdf(PdfContentByte cb, float yPageStart, ref float yTopMargin, ref float yBottomMargin) { if (MyBox == null) return yPageStart; cb.SaveState(); VlnSvgPageHelper _MyPageHelper = cb.PdfWriter.PageEvent as VlnSvgPageHelper; PdfLayer textLayer = _MyPageHelper == null ? null : _MyPageHelper.TextLayer; if (textLayer != null) cb.BeginLayer(textLayer); MyContentByte = cb; //Console.WriteLine("'{0}','{1}'", CharToAsc(MyBox.BoxStyle), MyParent.MyItemInfo.ShortPath); float top = CalculateYOffset(yPageStart, yTopMargin) - (7*MyPageHelper.YMultiplier); float bottom = top - (Height * MyPageHelper.YMultiplier); float left = (float)((MyBox.Start ?? 0) + MyParent.MyItemInfo.MyDocStyle.Layout.LeftMargin); float myBoxLeftAdj = 0; if (MyParent.MyItemInfo.ActiveFormat.MyStepSectionLayoutData.BoxLeftAdj != null) myBoxLeftAdj = float.Parse(MyParent.MyItemInfo.ActiveFormat.MyStepSectionLayoutData.BoxLeftAdj); left += myBoxLeftAdj; float right = (float)MyParent.MyItemInfo.MyDocStyle.Layout.LeftMargin + (float)(MyBox.End ?? DefEnd); if (MyParentBox != null)// B2018-096 AEP 082.002CD Note Box overlapping Step Box right = (float)MyParent.MyItemInfo.MyDocStyle.Layout.LeftMargin + MyParentBox.DefEnd - SixLinesPerInch/2; right += myBoxLeftAdj; iTextSharp.text.Color boxColor = new iTextSharp.text.Color(PrintOverride.OverrideBoxColor(System.Drawing.Color.Black)); cb.SetColorStroke(boxColor); float gapTopBox = top; float gapBottomBox = top - Height; if (MyParent.MyItemInfo.MyDocStyle.CenterLineYTop!=null && DefBox == vlnBox.DOUBLEboxHLS) { // For top box, if at top of page, the first gap begins at the centerlineYTop, otherwise it starts where // the box is drawn, with an adjustment to allow for the first line of text & the extra line above the box gapTopBox = (top + 3*SixLinesPerInch > (float)MyParent.MyItemInfo.MyDocStyle.CenterLineYTop) ? (float)MyParent.MyItemInfo.MyDocStyle.CenterLineYTop : top + 1.3f * vlnPrintObject.SixLinesPerInch; // The bottom gap must be moved down just a little to account for the double box (bottom line of box) gapBottomBox -= 3.2f; } if (MyParent.MyItemInfo.MyDocStyle.CenterLineYTop!=null)_MyPageHelper.MyGaps.Add(gapTopBox, gapBottomBox); // F2021-026: Barakah single column thick double box around Warnings if (DefBox == null && MyBox.ThickDouble) { Volian.Base.Library.BaselineMetaFile.WriteLine("BXDblThick Lf={0} Rt={1} Tp={2} Bt={3}", left, (float)MyParent.MyItemInfo.MyDocStyle.Layout.PageWidth, top, bottom); DrawDoubleHlsBoxThick(cb, top, bottom, left, (float)MyParent.MyItemInfo.MyDocStyle.Layout.PageWidth); } else if (DefBox != null && DefBox != vlnBox.DOUBLEboxHLS) { cb.SetLineWidth(.6F); float lheight = Height; if (top > yTopMargin) { lheight -= (top - yTopMargin); } if (bottom < yBottomMargin) { lheight += (bottom - yBottomMargin); bottom = yBottomMargin; } // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX Lf={0} Bt={1} W={2} H={3}", left, bottom, right - left, lheight * MyPageHelper. YMultiplier); cb.Rectangle(left, bottom, right - left, lheight * MyPageHelper.YMultiplier); } else if (DefBox == vlnBox.DOUBLEboxHLS) { // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXHLS Lf={0} Rt={1} Tp={2} Bt={3}", left, (float)MyParent.MyItemInfo.MyDocStyle.Layout.PageWidth,top, bottom); DrawDoubleHlsBox(cb, top, bottom, left, (float)MyParent.MyItemInfo.MyDocStyle.Layout.PageWidth); } else { const float llxOffset = 3; float lineThickness = 0; switch (MyBox.BoxStyle) { case BoxThin: lineThickness = .6F; cb.SetLineWidth(lineThickness); // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXThin Lf={0} Bt={1} W={2} H={3}", left + llxOffset, bottom + (lineThickness / 2), right - left, (Height - lineThickness) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset, bottom + (lineThickness / 2), right - left, (Height - lineThickness) * MyPageHelper.YMultiplier); break; case BoxThick: lineThickness = 6; cb.SetLineWidth(lineThickness); // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXThick Lf={0} Bt={1} W={2} H={3}", left + llxOffset, bottom + (lineThickness / 2), right - left, (Height - lineThickness) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset, bottom + (lineThickness / 2), right - left, (Height - lineThickness) * MyPageHelper.YMultiplier); break; case BoxDouble: if (MyBox.NumLines == 3) { lineThickness = .6F; cb.SetLineWidth(lineThickness / 2F); // outer rectangle (rectangle's are defined as x,y,w,h) // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX3lns1 Lf={0} Bt={1} W={2} H={3}", left + llxOffset - lineThickness * 1.5F, bottom - lineThickness, right - left + lineThickness * 3, (Height + lineThickness * 2) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset - lineThickness * 1.5F, bottom - lineThickness, right - left + lineThickness * 3, (Height + lineThickness * 2) * MyPageHelper.YMultiplier); // inner rectangle // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX3lns2 Lf={0} Bt={1} W={2} H={3}", left + llxOffset + lineThickness, bottom + lineThickness * 1.5F, right - left - lineThickness * 2, (Height - lineThickness * 3) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset + lineThickness, bottom + lineThickness * 1.5F, right - left - lineThickness * 2, (Height - lineThickness * 3) * MyPageHelper.YMultiplier); // outer outer most // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX3lns3 Lf={0} Bt={1} W={2} H={3}", left + llxOffset - lineThickness * 4F, bottom - lineThickness * 3.5F, right - left + lineThickness * 8, (Height + lineThickness * 7) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset - lineThickness * 4F, bottom - lineThickness * 3.5F, right - left + lineThickness * 8, (Height + lineThickness * 7) * MyPageHelper.YMultiplier); break; } lineThickness = .6F; cb.SetLineWidth(lineThickness); // outer rectangle (rectangle's are defined as x,y,w,h) // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX2lns1 Lf={0} Bt={1} W={2} H={3}", left + llxOffset - lineThickness * 1.5F, bottom - lineThickness, right - left + lineThickness * 3, (Height + lineThickness * 2) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset - lineThickness * 1.5F, bottom - lineThickness, right - left + lineThickness * 3, (Height + lineThickness * 2) * MyPageHelper.YMultiplier); // inner rectangle // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BX2lns2 Lf={0} Bt={1} W={2} H={3}", left + llxOffset + lineThickness, bottom + lineThickness * 1.5F, right - left - lineThickness * 2, (Height - lineThickness * 3) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset + lineThickness, bottom + lineThickness * 1.5F, right - left - lineThickness * 2, (Height - lineThickness * 3) * MyPageHelper.YMultiplier); break; case BoxFPLNote: lineThickness = 2; cb.SetLineWidth(lineThickness); float[] linePattern = { 6, 1.75F, 2.5F, 1.75F }; cb.SetLineDash(linePattern,3); // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXFPLNt Lf={0} Bt={1} W={2} H={3}", left + llxOffset, bottom + (lineThickness / 2) - 1, right - left, (2 + Height - lineThickness) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset, bottom + (lineThickness / 2) -1, right - left, (2 + Height - lineThickness) * MyPageHelper.YMultiplier); break; case BoxFPLCaution: lineThickness = 3; cb.SetLineWidth(lineThickness); // use a Y adjustment (top & bottom) to make the caution box match the 16bit output. // F2021-038: SHE/SHEA format - Less space between text and bottom line of Caution Box float YbxAdjust = (MyParent.MyItemInfo.IsStep && MyParent.MyItemInfo.FormatStepData.NoYBxAdjust) ? 0 : 6.5F; // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXFPLCn Lf={0} Bt={1} W={2} H={3}", left + llxOffset, bottom - YbxAdjust + (lineThickness / 2), right - left, (Height - lineThickness + 2 * YbxAdjust) * MyPageHelper.YMultiplier); cb.Rectangle(left + llxOffset, bottom - YbxAdjust + (lineThickness / 2), right - left, (Height - lineThickness + 2*YbxAdjust) * MyPageHelper.YMultiplier); break; case BoxAsterisk: case BoxAsteriskTopBottom: case BoxAsteriskTopBotton2: DrawAsteriskTopBottom(cb, yPageStart, yTopMargin, yBottomMargin, ref top, ref bottom, left, MyBox.Font); break; case BoxLineTopBottom: // fnp note box lineThickness = .6f; cb.SetLineWidth(lineThickness); // C2018-004 create meta file for baseline compares Volian.Base.Library.BaselineMetaFile.WriteLine("BXFNPNt Lf={0} Rt={1} Tp={2} Bt={3}", left + llxOffset, right, top, bottom); cb.MoveTo(left + llxOffset, bottom); cb.LineTo(right, bottom); cb.MoveTo(left + llxOffset, top); cb.LineTo(right, top); break; case BoxAsteriskWithSides1: case BoxAsteriskWithSides3: case BoxAsteriskWithSides4: case BoxAsteriskWithSides5: DrawAsteriskTopBottom(cb, yPageStart, yTopMargin, yBottomMargin, ref top, ref bottom, left, MyBox.Font); DrawAsteriskSide(cb, yPageStart, yTopMargin, yBottomMargin, top, bottom, left, right, MyBox.Font); break; case BoxAsteriskWithSides2: // special processing for IP3's box DrawAsteriskTopBottomHLS(cb, yPageStart, yTopMargin, yBottomMargin, ref top, ref bottom, left, MyBox.Font); DrawAsteriskSideHLS(cb, yPageStart, yTopMargin, yBottomMargin, top, bottom, left, right, MyBox.Font); break; default: // For other than thick, thin and double. if (!_UnimplementedBoxStyles.Contains(MyBox.BoxStyle)) { _UnimplementedBoxStyles.Add(MyBox.BoxStyle); _MyLog.InfoFormat("Unimplemented Box Style {0} {1}", ShowBoxStyle(MyBox.BoxStyle), MyParent.MyItemInfo.ShortPath); //Console.WriteLine("Unimplemented Box Style {0} {1}", ShowBoxStyle(MyBox.BoxStyle), MyParent.MyItemInfo.ShortPath); } break; //throw new Exception("Missing vlnBox handler"); } } cb.Stroke(); if (textLayer != null) cb.EndLayer(); cb.RestoreState(); return yPageStart; } private static void DrawDoubleHlsBox(PdfContentByte cb, float top, float bottom, float left, float right) { float lineThickness = .6f; float lnOff = 1.3f * vlnPrintObject.SixLinesPerInch; cb.SetLineWidth(lineThickness); // top (double line) cb.MoveTo(left, top + lnOff); cb.LineTo(right, top + lnOff); cb.MoveTo(left + 3.6f, top + lnOff - 3); cb.LineTo(right - 3.6f, top + lnOff - 3); // bottom (double line) cb.MoveTo(left, bottom - 2f); cb.LineTo(right, bottom - 2f); cb.MoveTo(left + 3.6f, bottom+1f); cb.LineTo(right - 3.6f, bottom+1f); // sides cb.MoveTo(left + 3.6f, top + lnOff - 3); cb.LineTo(left + 3.6f, bottom +1f); cb.MoveTo(right - 3.6f, top + lnOff - 3); cb.LineTo(right - 3.6f, bottom +1f); } // F2021-026: Barakah single column thick double box around Warnings // F2021-081: Barakah thick double box, adjust to add more space between boxes // F2022-012: Barakah move the top 2 lines down slightly so they don't overlap INIT underline if at top of page. private static void DrawDoubleHlsBoxThick(PdfContentByte cb, float top, float bottom, float left, float right) { float lineThickness = 3; float lnOff = 1f * vlnPrintObject.SixLinesPerInch; cb.SetLineWidth(lineThickness); // top (double line) cb.MoveTo(left-2.5f, top + lnOff-4); // outer (lower y moves up page) cb.LineTo(right+2.5f, top + lnOff-4); cb.MoveTo(left + 4.5f, top + lnOff - 11); // inner cb.LineTo(right - 4.5f, top + lnOff - 11); // bottom (double line) cb.MoveTo(left-2.5f, bottom - 6); cb.LineTo(right+2.5f, bottom - 6); cb.MoveTo(left + 4.5f, bottom+ 1); cb.LineTo(right - 4.5f, bottom+ 1); // sides cb.MoveTo(left + 4.5f, top + lnOff - 9.5f); // inner box cb.LineTo(left + 4.5f, bottom - 0.5f); cb.MoveTo(right - 4.5f, top + lnOff - 9.5f); cb.LineTo(right - 4.5f, bottom - 0.5f); cb.MoveTo(left - 2.5f, top + lnOff-2.5f); // outer box cb.LineTo(left-2.5f, bottom - 7.5f); cb.MoveTo(right + 2.5f, top + lnOff -2.5f); cb.LineTo(right+2.5f, bottom - 7.5f); } private void DrawAsteriskTopBottom(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin, ref float top, ref float bottom, float left, VE_Font vef) { // this box is not drawn, it is a series of asterisks drawn above and below text. // For this box, there are no vertical edges (RGE uses this box type) top = CalculateYOffset(yPageStart, yTopMargin); // Bug fix B2013-091 // added YMultiplier to handle compress pages // bottom row of asterisks was in non-compressed line location bottom = top - (Height * MyPageHelper.YMultiplier); // create a new font without any styles such as underline. E_Style es = ((vef.Style & E_Style.Bold) == E_Style.Bold) ? E_Style.Bold : E_Style.None; // if the box has a font, use it - otherwise use this item info's font VE_Font vf = null; bool UseBoxFont = false; try { UseBoxFont = MyParent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox; } catch // done this way in case one of the format properties is null in the previous statement, UseBoxFont will be false. { } if (UseBoxFont) vf = new VE_Font(vef.Family, (int)vef.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); else vf = new VE_Font(MyParent.MyItemInfo.FormatStepData.Font.Family, (int)MyParent.MyItemInfo.FormatStepData.Font.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); // To find the length of the line, account for the length of the upper right corner also (BXURC) int urcLen = MyBox.BXHorz[MyBox.BXHorz.Length - 1] == ' ' && MyBox.BXURC[0] == ' ' ? 1 : MyBox.BXURC.Length; float endHorz = (float)MyBox.End - (float)MyBox.Start - (float)(urcLen * (72 / vf.CPI)); float bxHorzTextWidth = GetTextWidth(vf, MyBox.BXHorz); // get the width of the BXHorz string // Do the top line first: StringBuilder sb = new StringBuilder(); sb.Append(MyBox.BXULC); float size = GetTextWidth(vf, MyBox.BXULC); //(float)(MyBox.BXULC.Length * (72 / vf.CPI)); string bxstr = null; if (!ContainsPageBreak) // Only do top line if there is no page break. { while (size < endHorz) { sb.Append(MyBox.BXHorz); size = size + bxHorzTextWidth; //(float)(MyBox.BXHorz.Length * (72 / vf.CPI)); } // Tack on the right upper corner. For some formats, the upper right corner in the // had the first character as a space, this would put two spaces in a row at the // end of the string, so remove the space before tacking on the upper right corner: bxstr = sb.ToString(); if (bxstr[bxstr.Length - 1] == ' ' && MyBox.BXURC[0] == ' ') bxstr = bxstr.TrimEnd(); bxstr = bxstr + MyBox.BXURC; size = size + GetTextWidth(vf, MyBox.BXURC);//(float)((MyBox.BXURC.Length) * (72 / vf.CPI)); Rtf = GetRtf(bxstr, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. Rtf2Pdf.TextAt(cb, IParagraph, left, top, size + 10, 100, "", yBottomMargin); } // Handle the bottom line now: if (bottom < yBottomMargin) return; // Box goes off page, i.e. page break, don't do bottom sb.Remove(0, sb.Length); sb.Append(MyBox.BXLLC); size = GetTextWidth(vf, MyBox.BXLLC); //(float)(MyBox.BXLLC.Length * (72 / vf.CPI)); while (size < endHorz) { sb.Append(MyBox.BXHorz); size = size + bxHorzTextWidth;//(float)(MyBox.BXHorz.Length * (72 / vf.CPI)); } bxstr = sb.ToString().TrimEnd() + MyBox.BXLRC; size = size + GetTextWidth(vf, MyBox.BXLRC); //(float)((MyBox.BXLRC.Length) * (72 / vf.CPI)); Rtf = GetRtf(bxstr, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. Rtf2Pdf.TextAt(cb, IParagraph, left, bottom, size + 10, 100, "", yBottomMargin); } 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; } private float GetTextWidth(VE_Font vefont, string txt) { string symblFontName = (vefont.FontIsProportional()) ? Volian.Base.Library.vlnFont.ProportionalSymbolFont : "VESymbFix"; // C2017-036 get best available proportional font for symbols // 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 //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; } private void DrawAsteriskSide(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin, float top, float bottom, float left, float right, VE_Font vef) { // set the top & bottom of sides. If there is a page break in the middle of box, adjust these. // The vlnBox property, ContainsPageBreak, flags that a break occurred. if (!ContainsPageBreak) // if no page break, just use top as is. { top = CalculateYOffset(yPageStart, yTopMargin); bottom = top - (Height * MyPageHelper.YMultiplier); } else { // to calculate the bottom, don't adjust the top yet. top = CalculateYOffset(yPageStart, yTopMargin); bottom = top - (Height * MyPageHelper.YMultiplier); top = yTopMargin; // reset top to top margin since there was a page break. } // Check that the bottom is within the bottom margin, if this step spans more than one page, // stop the side asterisks at the bottom margin. (pagination puts inserts a page break here) if (bottom < yBottomMargin) bottom = yBottomMargin; float height = (SixLinesPerInch * MyPageHelper.YMultiplier) + 4; // just add a little on so that height is a little bigger than character // create a new font without any styles such as underline. E_Style es = ((vef.Style & E_Style.Bold) == E_Style.Bold) ? E_Style.Bold : E_Style.None; // if the box has a font, use it - otherwise use this item info's font VE_Font vf = null; bool UseBoxFont = false; try { UseBoxFont = MyParent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox; } catch // done this way in case one of the format properties is null in the previous statement, UseBoxFont will be false. { } if (UseBoxFont) vf = new VE_Font(vef.Family, (int)vef.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); else vf = new VE_Font(MyParent.MyItemInfo.FormatStepData.Font.Family, (int)MyParent.MyItemInfo.FormatStepData.Font.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); // Left side first: Rtf = GetRtf(MyBox.BXVert, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. // start down one line because the top/bottom code draws the corner float vertDiff = top - (SixLinesPerInch * MyPageHelper.YMultiplier); float width = (float)(MyBox.BXVert.Length * (72 / vf.CPI)); while (vertDiff > bottom) { Rtf2Pdf.TextAt(cb, IParagraph, left, vertDiff, width, height, "", yBottomMargin); vertDiff -= (SixLinesPerInch * MyPageHelper.YMultiplier); } // right side: vertDiff = top - (SixLinesPerInch * MyPageHelper.YMultiplier); Rtf = GetRtf(MyBox.BXVert.TrimEnd(), vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. while (vertDiff > bottom) { Rtf2Pdf.TextAt(cb, IParagraph, right, vertDiff, width, height, "", yBottomMargin); vertDiff -= (SixLinesPerInch * MyPageHelper.YMultiplier); } } private string ShowBoxStyle(string str) { StringBuilder sb = new StringBuilder(); foreach (Char c in str) { if (c >= ' ' && c < 128) sb.Append(c); else sb.Append(string.Format("x{0:X0000}", (int)c)); } return sb.ToString(); } private static List _UnimplementedBoxStyles = new List(); private string CharToAsc(string p) { StringBuilder sb = new StringBuilder(); foreach (char c in p) { if (c >= ' ' && c < 127) sb.Append(c); else sb.Append(string.Format("\\x{0:x}", (int)c)); } return sb.ToString(); } private void DrawAsteriskTopBottomHLS(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin, ref float top, ref float bottom, float left, VE_Font vef) { // this box is not drawn, it is a series of asterisks drawn above and below text. top = CalculateYOffset(yPageStart, yTopMargin); if (MyPageHelper.YMultiplier != 1) top += 2; float ytmpbottom1 = yPageStart - (MyParent.YBottomForBox > 0 ? MyParent.YBottomForBox : MyParent.YBottomMost); if (MyPageHelper.YMultiplier != 1) { ytmpbottom1 = (-1 + yTopMargin - (yTopMargin - ytmpbottom1) * MyPageHelper.YMultiplier) + 2; } bottom = ytmpbottom1; // create a new font without any styles such as underline. E_Style es = ((vef.Style & E_Style.Bold) == E_Style.Bold) ? E_Style.Bold : E_Style.None; // if the box has a font, use it - otherwise use this item info's font VE_Font vf = null; bool UseBoxFont = false; try { UseBoxFont = MyParent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox; } catch // done this way in case one of the format properties is null in the previous statement, UseBoxFont will be false. { } if (UseBoxFont) vf = new VE_Font(vef.Family, (int)vef.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); else vf = new VE_Font(MyParent.MyItemInfo.FormatStepData.Font.Family, (int)MyParent.MyItemInfo.FormatStepData.Font.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); // To find the length of the line, account for the length of the upper right corner also (BXURC) int urcLen = MyBox.BXHorz[MyBox.BXHorz.Length - 1] == ' ' && MyBox.BXURC[0] == ' ' ? 1 : MyBox.BXURC.Length; float endHorz = (float)MyBox.End - (float)MyBox.Start - (float)(urcLen * (72 / vf.CPI)); float bxHorzTextWidth = GetTextWidth(vf, MyBox.BXHorz); // get the width of the BXHorz string // Do the top line first: StringBuilder sb = new StringBuilder(); sb.Append(MyBox.BXULC); float size = GetTextWidth(vf, MyBox.BXULC); //(float)(MyBox.BXULC.Length * (72 / vf.CPI)); string bxstr = null; if (!ContainsPageBreak) // Only do top line if there is no page break. { while (size < endHorz) { sb.Append(MyBox.BXHorz); size = size + bxHorzTextWidth; //(float)(MyBox.BXHorz.Length * (72 / vf.CPI)); } // Tack on the right upper corner. For some formats, the upper right corner in the // had the first character as a space, this would put two spaces in a row at the // end of the string, so remove the space before tacking on the upper right corner: bxstr = sb.ToString(); if (bxstr[bxstr.Length - 1] == ' ' && MyBox.BXURC[0] == ' ') bxstr = bxstr.TrimEnd(); bxstr = bxstr + MyBox.BXURC; size = size + GetTextWidth(vf, MyBox.BXURC);//(float)((MyBox.BXURC.Length) * (72 / vf.CPI)); Rtf = GetRtf(bxstr, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. Rtf2Pdf.TextAt(cb, IParagraph, left, top, size + 10, 100, "", yBottomMargin); } // Handle the bottom line now: if (bottom < yBottomMargin) return; // Box goes off page, i.e. page break, don't do bottom sb.Remove(0, sb.Length); sb.Append(MyBox.BXLLC); size = GetTextWidth(vf, MyBox.BXLLC); //(float)(MyBox.BXLLC.Length * (72 / vf.CPI)); while (size < endHorz) { sb.Append(MyBox.BXHorz); size = size + bxHorzTextWidth;//(float)(MyBox.BXHorz.Length * (72 / vf.CPI)); } bxstr = sb.ToString().TrimEnd() + MyBox.BXLRC; size = size + GetTextWidth(vf, MyBox.BXLRC); //(float)((MyBox.BXLRC.Length) * (72 / vf.CPI)); Rtf = GetRtf(bxstr, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. Rtf2Pdf.TextAt(cb, IParagraph, left, bottom, size + 10, 100, "", yBottomMargin); } private void DrawAsteriskSideHLS(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin, float top, float bottom, float left, float right, VE_Font vef) { // set the top & bottom of sides. If there is a page break in the middle of box, adjust these. // The vlnBox property, ContainsPageBreak, flags that a break occurred. float yOffBreak = 0; if (!ContainsPageBreak) { top = CalculateYOffset(yPageStart, yTopMargin); if (MyPageHelper.YMultiplier != 1) top += 2; // if this broke, the bottom is defined where the parabreak occurred. yOffBreak = MyPageHelper.ParaBreaks.Count > 0 ? MyPageHelper.ParaBreaks[0].YOffset : 0; if (yOffBreak > 0) bottom = (yPageStart - yOffBreak) * MyPageHelper.YMultiplier; else { float ytmpbottom = yPageStart - (MyParent.YBottomForBox > 0 ? MyParent.YBottomForBox : MyParent.YBottomMost); if (MyPageHelper.YMultiplier != 1) { ytmpbottom = -1 + yTopMargin - (yTopMargin - ytmpbottom) * MyPageHelper.YMultiplier; } bottom = ytmpbottom; } } else { top = CalculateYOffset(yPageStart, yTopMargin); yOffBreak = MyPageHelper.ParaBreaks.Count > 0 ? MyPageHelper.ParaBreaks[0].YOffset : 0; if (yOffBreak > 0) bottom = (yPageStart - yOffBreak) * MyPageHelper.YMultiplier; else { float ytmpbottom1 = yPageStart - (MyParent.YBottomForBox > 0 ? MyParent.YBottomForBox : MyParent.YBottomMost); if (MyPageHelper.YMultiplier != 1) { ytmpbottom1 = -1 + yTopMargin - (yTopMargin - ytmpbottom1) * MyPageHelper.YMultiplier; } bottom = ytmpbottom1; } top = yTopMargin; // reset top to top margin since there was a page break. } // Check that the bottom is within the bottom margin, if this step spans more than one page, // stop the side asterisks at the bottom margin. (pagination puts inserts a page break here) if (bottom < yBottomMargin) bottom = yBottomMargin; float height = (SixLinesPerInch * MyPageHelper.YMultiplier) + 4; // just add a little on so that height is a little bigger than character // create a new font without any styles such as underline. E_Style es = ((vef.Style & E_Style.Bold) == E_Style.Bold) ? E_Style.Bold : E_Style.None; // if the box has a font, use it - otherwise use this item info's font VE_Font vf = null; bool UseBoxFont = false; try { UseBoxFont = MyParent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox; } catch // done this way in case one of the format properties is null in the previous statement, UseBoxFont will be false. { } if (UseBoxFont) vf = new VE_Font(vef.Family, (int)vef.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); else vf = new VE_Font(MyParent.MyItemInfo.FormatStepData.Font.Family, (int)MyParent.MyItemInfo.FormatStepData.Font.Size, es, (float)MyParent.MyItemInfo.FormatStepData.Font.CPI); // Left side first: Rtf = GetRtf(MyBox.BXVert, vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. // start down one line because the top/bottom code draws the corner float vertDiff = top - (SixLinesPerInch * MyPageHelper.YMultiplier); float width = (float)(MyBox.BXVert.Length * (72 / vf.CPI)); while (vertDiff > bottom) { Rtf2Pdf.TextAt(cb, IParagraph, left, vertDiff, width, height, "", yBottomMargin); vertDiff -= (SixLinesPerInch * MyPageHelper.YMultiplier); } // right side: vertDiff = top - (SixLinesPerInch * MyPageHelper.YMultiplier); Rtf = GetRtf(MyBox.BXVert.TrimEnd(), vf); IParagraph = null; // set to null so that next access of IParagraph sets the Rtf. while (vertDiff > bottom) { Rtf2Pdf.TextAt(cb, IParagraph, right, vertDiff, width, height, "", yBottomMargin); vertDiff -= (SixLinesPerInch * MyPageHelper.YMultiplier); } } } }