using System; using System.Collections.Generic; using System.Text; using C1.Win.C1FlexGrid; using System.IO; using Itenso.Rtf; using Itenso.Rtf.Parser; using Itenso.Rtf.Interpreter; using Itenso.Rtf.Support; using Volian.Print.Library; using Volian.Controls.Library; using iTextSharp.text; using iTextSharp.text.pdf; using VEPROMS.CSLA.Library; using System.Text.RegularExpressions; namespace Volian.Print.Library { #region Settings // RHM20150429 - Table Scrunch public partial class vlnTable { private string _DebugInfo = null; // RHM20150429 - Table Scrunch public string DebugInfo { get { return _DebugInfo; } set { _DebugInfo = value; } } private int _ItemID = 0; public int ItemID { get { return _ItemID; } set { _ItemID = value; } } private bool _ShowDetails = false; public bool ShowDetails { get { return _ShowDetails; } set { _ShowDetails = value; } } private bool _IsTooBig = false; public bool IsTooBig { get { return _IsTooBig; } set { _IsTooBig = value; } } } public partial class vlnCells { private static float YAdjust_HContent = 4; // 4 private float YAdjust_SpacingAfter { get { return 8-8*MyTable.Adjustment;//0; // 8 } } } public partial class vlnCell { public bool ShowDetails { get { return MyTable.ShowDetails; } } private static float YAdjust_h = 0; // 0 private float YAdjust_TextLocation { get { return 4 - 4 * MyTable.Adjustment; ;//0; // 4 } } } //public partial class vlnTable //{ // private static float YAdjust_RowTop = 0;//8; // 0 //} //public partial class vlnCells //{ // private static float YAdjust_HContent = 4; // 4 // private static float YAdjust_SpacingAfter = 8;//0; // 8 //} //public partial class vlnCell //{ // private static float YAdjust_h = 0; // 0 // private static float YAdjust_TextLocation = 4;//0; // 4 //} #endregion public partial class vlnTable { #region Properties private float[] _HContents;// RHM20150525 - Table Scrunch public float[] HContents { get { return _HContents; } set { _HContents = value; } } private float[] _RowTop; public float[] RowTop { get { return _RowTop; } set { _RowTop = value; } } private float[] _ColLeft; public float[] ColLeft { get { return _ColLeft; } set { _ColLeft = value; } } private VlnFlexGrid _MyFlexGrid; public VlnFlexGrid MyFlexGrid { get { return _MyFlexGrid; } set { _MyFlexGrid = value; } } private VlnBorders _MyBorders; public VlnBorders MyBorders { get { return _MyBorders; } set { _MyBorders = value; } } private iTextSharp.text.pdf.PdfContentByte _MyContentByte; public iTextSharp.text.pdf.PdfContentByte MyContentByte { get { return _MyContentByte; } set { _MyContentByte = value; } } private vlnCells _MyCells; public vlnCells MyCells { get { return _MyCells; } set { _MyCells = value; } } public float Height { get { return RowTop[RowTop.Length - 1]; } } public float Width { get { return ColLeft[ColLeft.Length - 1]; } } private static float _XOffset = -1; // This moves the borders with respect to the text public static float XOffset { get { return vlnTable._XOffset; } set { vlnTable._XOffset = value; } } private static float _YOffset = 0; // This moves the borders with respect to the text public static float YOffset { get { return vlnTable._YOffset; } set { vlnTable._YOffset = value; } } private static float _LineThicknessForThin = .9F; public static float LineThicknessForThin { get { return vlnTable._LineThicknessForThin; } set { vlnTable._LineThicknessForThin = value; } } private static float _LineThicknessForThick = 1.8F; public static float LineThicknessForThick { get { return vlnTable._LineThicknessForThick; } set { vlnTable._LineThicknessForThick = value; } } private static float _LineThicknessForDouble = .6F; public static float LineThicknessForDouble { get { return vlnTable._LineThicknessForDouble; } set { vlnTable._LineThicknessForDouble = value; } } public static float DoubleLineOffset { get { return (LineThicknessForThick - LineThicknessForDouble) / 2; }//LineThicknessForThick - 2 * LineThicknessForDouble; } } private float _TotalContentHeight = 0;// RHM20150525 - Table Scrunc public float TotalContentHeight { get { if (_TotalContentHeight == 0) { foreach (float h in HContents) _TotalContentHeight += h; } return _TotalContentHeight; } } public float SpaceAvailable// RHM20150525 - Table Scrunc { get { return TotalContentHeight ==0 ? 0 : RowTop[RowTop.Length - 1] - TotalContentHeight; } } private float _TooBig;// RHM20150525 - Table Scrunc public float TooBig { get { return _TooBig; } set { _TooBig = value; //_Adjustment = Math.Min(1F, (_TooBig / (RowTop.Length - 1)) / 12); //if (ShowDetails) Console.WriteLine("TooBig\t{0}\t{1}", value, _Adjustment); //if(ShowDetails) Console.WriteLine("Before RowTop={0}", RowTop[RowTop.Length-1] ); float extra=(TooBig < SpaceAvailable)?(SpaceAvailable - TooBig) / HContents.Length:0; for (int r = 0; r < RowTop.Length - 1; r++) RowTop[r + 1] = RowTop[r] + HContents[r] + extra; //if(ShowDetails) Console.WriteLine("After RowTop={0}", RowTop[RowTop.Length-1] ); } } private float _Adjustment = 0;// RHM20150525 - Table Scrunc public float Adjustment { get { return _Adjustment; } set { _Adjustment = value; } } //private float _YAdjust_RowTop = 0;//8; // 0 public float YAdjust_RowTop { get { return _Adjustment * 12; } } private void DrawRuler(PdfContentByte cb, float x, float yTop, float height)// RHM20150525 - Table Scrunc { VlnSvgPageHelper myPageHelper = cb.PdfWriter.PageEvent as VlnSvgPageHelper; if (myPageHelper.DebugLayer != null) { cb.BeginLayer(myPageHelper.DebugLayer); cb.SaveState(); cb.SetLineWidth(.1F); cb.SetColorStroke(new Color(System.Drawing.Color.Orange)); float yBottom = yTop - height; cb.MoveTo(x, yTop); cb.LineTo(x, yBottom); int i = 0; for (float y = yTop; y >= yBottom; y -= 10) { float w = 10; if (i % 10 == 0) w = 30; else if (i % 5 == 0) w = 20; cb.SetLineWidth(w / 30); i++; cb.MoveTo(x + w, y); cb.LineTo(x, y); cb.Stroke(); } i = 0; cb.Stroke(); cb.RestoreState(); cb.EndLayer(); } } private void ShowRowTops(string location)// RHM20150525 - Table Scrunc { if (!ShowDetails) return; StringBuilder sb = new StringBuilder(); for (int i = 0; i < RowTop.Length; i++) sb.Append("\t" + RowTop[i].ToString()); Console.WriteLine(location + "\t" + sb.ToString()); } private void EndSetup()// RHM20150525 - Table Scrunc { if (ShowDetails) ShowRowTops("vlnTable.ctor.2"); if (ShowDetails) Console.WriteLine("^^^^^^vlnTable============{0}===============", ItemID); } private void SetupDebug(VlnFlexGrid myFlexGrid)// RHM20150525 - Table Scrunc { //ShowDetails = myFlexGrid.GetMyItemInfo().InList(38329); //if(ShowDetails) Console.WriteLine("vvvvvvlnTable============{0}===============", ItemID); ItemInfo myItemInfo = myFlexGrid.GetMyItemInfo(); ItemID = myItemInfo.ItemID; DebugInfo = string.Format("DebugID = {0}, ID={1} Type={2} TypeName='{3}' StepLevel={4} ShortPath={5} Width={6} Left={7} YOffset={8}", 0, myItemInfo.ItemID, myItemInfo.FormatStepType, myItemInfo.FormatStepData == null ? "NoStepData" : myItemInfo.FormatStepData.Type, myItemInfo.StepLevel, myItemInfo.ShortPath, Width, XOffset, YOffset); } #endregion #region Constructors public vlnTable(VlnFlexGrid myFlexGrid, iTextSharp.text.pdf.PdfContentByte myContentByte) { MyFlexGrid = myFlexGrid; MyContentByte = myContentByte; InitializeSizes(); SetupDebug(myFlexGrid);// RHM20150525 - Table Scrunc MyCells = new vlnCells(this, MyFlexGrid, MyContentByte); EndSetup();// RHM20150525 - Table Scrunc } #endregion #region Private Methods private void InitializeSizes() { RowTop = new float[MyFlexGrid.Rows.Count + 1]; HContents = new float[MyFlexGrid.Rows.Count];// RHM20150525 - Table Scrunc RowTop[0] = 0; for (int r = 0; r < MyFlexGrid.Rows.Count; r++) RowTop[r + 1] = RowTop[r] + 72 * (MyFlexGrid.Rows[r].Height == -1 ? MyFlexGrid.Rows.DefaultSize : MyFlexGrid.Rows[r].Height) / (float)MyFlexGrid.DPI; ColLeft = new float[MyFlexGrid.Cols.Count + 1]; ColLeft[0] = 0; for (int c = 0; c < MyFlexGrid.Cols.Count; c++) ColLeft[c + 1] = 2 + ColLeft[c] + 72 * (MyFlexGrid.Cols[c].Width == -1 // RHM20150429 - Table Scrunch ? MyFlexGrid.Cols.DefaultSize : MyFlexGrid.Cols[c].Width) / (float)MyFlexGrid.DPI; } #endregion #region Public Methods public void AdjustRowTop(int row1, int row2, float hNew) { float hAdjust = hNew - (RowTop[row2 + 1] - RowTop[row1]); for (int r = row2; r < MyFlexGrid.Rows.Count; r++) RowTop[r + 1] += hAdjust; } public void ToPdf(iTextSharp.text.pdf.ColumnText myColumnText, float left, float top) { //ZoomGrid(myColumnText, left, top); if(ShowDetails) Console.WriteLine("vvvvvvToPdf============{0}===============", ItemID);// RHM20150525 - Table Scrunc ShowRowTops("ToPDF1"); PdfContentByte cb = myColumnText.Canvas; // RHM20150429 - Table Scrunch VlnSvgPageHelper myPageHelper = cb.PdfWriter.PageEvent as VlnSvgPageHelper; string myLPI = myPageHelper.YMultiplier == 1.0F ? ",6LPI" : ",7LPI"; Rtf2Pdf.DrawPdfDebug(myColumnText.Canvas, left-2, top+1, left + Width, top-myPageHelper.YMultiplier *(Height+1), DebugInfo+", Height= " + (myPageHelper.YMultiplier * Height).ToString() + myLPI, 0); PdfLayer textLayer = myPageHelper == null ? null : myPageHelper.TextLayer; // RHM20150429 - Table Scrunch if (textLayer != null) cb.BeginLayer(textLayer); myPageHelper.AddGap(top, top - Height, left, left + Width); MyCells.ToPdf(myColumnText, left, top); DrawRuler(myColumnText.Canvas, left + Width, top, myPageHelper.YMultiplier * (Height + 1)); // RHM20150429 - Table Scrunch if (textLayer != null) cb.EndLayer(); ShowRowTops("ToPDF2"); if (ShowDetails) Console.WriteLine("^^^^^^ToPdf============{0}===============", ItemID); } private void ZoomGrid(iTextSharp.text.pdf.ColumnText myColumnText, float left, float top) { PdfDestination dest = new PdfDestination(PdfDestination.FITR, left - 4, top - Height - 4, left + Width, top + 4); myColumnText.Canvas.SetAction(PdfAction.GotoLocalPage(myColumnText.Canvas.PdfWriter.CurrentPageNumber, dest, myColumnText.Canvas.PdfWriter), left, top - Height, left + Width, top); } #endregion } public partial class vlnCells : List // RHM20150429 - Table Scrunch { #region Properties private VlnFlexGrid _MyFlexGrid; public VlnFlexGrid MyFlexGrid { get { return _MyFlexGrid; } set { _MyFlexGrid = value; } } private vlnTable _MyTable; public vlnTable MyTable { get { return _MyTable; } set { _MyTable = value; } } public bool ShowDetails// RHM20150525 - Table Scrunc { get { return MyTable.ShowDetails; }} private iTextSharp.text.pdf.PdfContentByte _MyContentByte; public iTextSharp.text.pdf.PdfContentByte MyContentByte { get { return _MyContentByte; } set { _MyContentByte = value; } } #endregion #region Constructors public vlnCells(vlnTable myTable, VlnFlexGrid myFlexGrid, iTextSharp.text.pdf.PdfContentByte myContentByte) { MyTable = myTable; MyFlexGrid = myFlexGrid; MyContentByte = myContentByte; SetupCells(); foreach(vlnCell cell in this) { myTable.MyBorders = VlnBorders.Get(myFlexGrid.MyBorders.ConvertToString()); GridLinePattern glp = cell.AboveLeftSide; glp = cell.AboveRightSide; glp = cell.BelowLeftSide; glp = cell.BelowRightSide; glp = cell.RightOfBottomSide; glp = cell.RightOfTopSide; object ta = cell.TextAlign; } } #endregion #region Private Methods private void SetupCells() { // Create a ColumnText to determine the cell heights iTextSharp.text.pdf.ColumnText myColumnText1 = new iTextSharp.text.pdf.ColumnText(MyContentByte); // Walk through for (int r = 0; r < MyFlexGrid.Rows.Count; r++) { float hMax = 12; // RHM20150429 - Table Scrunch for (int c = 0; c < MyFlexGrid.Cols.Count; c++) { CellRange cr = MyFlexGrid.GetMergedRange(r, c); if (cr.r1 == r && cr.c1 == c) { float w = MyTable.ColLeft[cr.c2 + 1] - MyTable.ColLeft[cr.c1]; float h = MyTable.RowTop[cr.r2 + 1] - MyTable.RowTop[cr.r1]; string str = MyFlexGrid.GetCellRTFString(r, c) ?? string.Empty; if (str.Contains(@"\cf")) { str = System.Text.RegularExpressions.Regex.Replace(str, @"\\cf[0-9]\\", @"\"); str = System.Text.RegularExpressions.Regex.Replace(str, @"\\cf[0-9] ", @""); } // the FreeMono font is used for the editor, but VESymbFix is used for printing // The font spefication is embeded in the table text so we need to change the font reference from // FreeMono to VESymbFix before we print the table if (str.ToUpper().Contains("FREEMONO")) str = str.Replace("FreeMono", "VESymbFix"); DisplayText dt = new DisplayText(MyFlexGrid.GetMyItemInfo(), str, false); str = dt.StartText; str = PreProcessRTF(w, str); // If the font is not proportional, pass the symbol font through to RtfToParagraph. It is needed // in underlying code to set the chunk's font if the first character of a cell is a hardspace. Without // this, pdfs were using the Helvetica font, which is a default itextsharp font. ItemInfo ii = MyFlexGrid.GetMyItemInfo(); iTextSharp.text.Font ff = null; if (!ii.FormatStepData.Font.FontIsProportional()) ff = Volian.Svg.Library.VolianPdf.GetFont("VESymbFix", (int)ii.FormatStepData.Font.Size, (int)ii.FormatStepData.Font.WindowsFont.Style); iTextSharp.text.Paragraph myPara = RtfToParagraph(str, ff); myColumnText1.SetSimpleColumn(0, 0, w-2, MyContentByte.PdfDocument.PageSize.Top); // Padding = 4 if (str.Contains(@"\'05")) { // if there is a hanging indent, the iTextSharp paragraph properties must be set // to print the indent. Replace the indent 'token' with a non-used symbol, this will // create a chunk with that symbol. Then loop through all of the chunks until we find // this symbol, adding up the widths to that point. This width is the value that // needs to be used to set the indent. // Notes: // A hard return will reset the chkW (indent width) back to zero. // We jump out of the processing loop after the first indent token is found and ignor any other ones float chkW = CalculateHangingIndent(str); myPara.IndentationLeft = chkW; myPara.FirstLineIndent = -chkW; } Match match = Regex.Match(str, @"\\fi([-0-9]*) ?\\li([0-9]*)"); if (match.Success) { float fi = float.Parse(match.Groups[1].Value) / 20; // 72 is dots per inch & 96 is standard DPI (120 is KBR's machine) float li = float.Parse(match.Groups[2].Value) / 20; // if there is a hanging indent, the iTextSharp paragraph properties must be set // to print the indent. myPara.IndentationLeft = li; myPara.FirstLineIndent = fi; } // RHM 20120925 - Line spacing should be 6 lines per inch. In order to get a valid value // for TotalLeading you have to set MultipliedLeading first: myPara.MultipliedLeading = 1.0f; // once there is valid value for TotalLeading (from previous line), you can use it to // calculate a MultipliedLeading to give 6 LPI (12 points) myPara.MultipliedLeading = 12.0f / myPara.TotalLeading; myPara.SpacingAfter = 8; // RHM 20120925 - Add a line to properly space text from lines. if(Rtf2Pdf.GetTableScrunchingStatus(TableScrunching.Phase2)) // RHM20150429 - Table Scrunch myPara.SpacingAfter = 0;// YAdjust_SpacingAfter; // RHM 20120925 - Add a line to properly space text from lines. FixHyphens(myPara, MyTable); if (Rtf2Pdf.GetTableScrunchingStatus(TableScrunching.Phase3)) TrimNewlines(myPara); // RHM20150429 - Table Scrunch myColumnText1.AddElement(myPara); //myColumnText1.Canvas.SetColorFill(PrintOverride.OverrideTextColor(System.Drawing.Color.Black)); float posBefore = myColumnText1.YLine; int status = myColumnText1.Go(true); float posAfter = myColumnText1.YLine; float hContent = 4 + posBefore - posAfter; if (Rtf2Pdf.GetTableScrunchingStatus(TableScrunching.Phase4))// RHM20150525 - Table Scrunc { hContent = 0 + posBefore - posAfter;//YAdjust_HContent + posBefore - posAfter; // if (myPara.Chunks.Count > 0 && myPara.Chunks[myPara.Chunks.Count - 1] == "\n") // hContent -= 12; } //if(ShowDetails) Console.WriteLine("{0}\t{1}\t{2}",r,c, hContent/12); if (cr.r1 == cr.r2) hMax = Math.Max(hMax, hContent); else hMax = Math.Max(hMax, hContent - (cr.r2 - cr.r1) * _SixLinesPerInch); if (hContent > h) { // RHM20150429 - Table Scrunch //if (ShowDetails) Console.WriteLine("Less {0},{1},{2},{3},{4},{5}", r, c, posBefore, posAfter, hContent, hMax); MyTable.AdjustRowTop(cr.r1, cr.r2, hContent); } // RHM20150429 - Table Scrunch if (Rtf2Pdf.GetTableScrunchingStatus(TableScrunching.Phase5)) { //if (ShowDetails) Console.WriteLine("Greater{0},{1},{2},{3},{4},{5}", r, c, posBefore, posAfter, hContent, hMax); //if (c == MyFlexGrid.Cols.Count - 1) //MyTable.AdjustRowTop(cr.r1, cr.r2, hMax + 6); MyTable.HContents[cr.r2] = hMax+2; } Add(new vlnCell(cr.r1, cr.c1, cr.r2, cr.c2, MyTable, myPara,hContent)); } } } } private void ShowChunks(System.Collections.ArrayList chunks) // RHM20150429 - Table Scrunch { StringBuilder sb = new StringBuilder(); foreach (Chunk chk in chunks) { sb.Append(BuildChunks(chk.Content)); } //if (ShowDetails) Console.WriteLine("Chunks = '{0}'", sb.ToString()); } private string BuildChunks(string str) { StringBuilder sb = new StringBuilder(); foreach(char c in str) { if (((int)c) < 0x20 || ((int)c) > 0x7F) sb.Append(string.Format("<{0:X4}>",(int)c)); else sb.Append(c); } return "{" + sb.ToString() + "}"; } private void TrimNewlines(Paragraph myPara) { while (myPara.Count > 0 && ParaEndsWithNewLine(myPara)) myPara.RemoveAt(myPara.Count - 1); } private bool ParaEndsWithNewLine(Paragraph myPara) { Chunk chk = myPara[myPara.Count - 1] as Chunk; if (chk == null) return false; if (chk.Content == "\n") return true; return false; } public class VlnSplitCharacter : ISplitCharacter { public bool IsSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) { return (cc[current] == ' '); } public bool IsSplitCharacter(char c) { return (c == ' '); } } public static VlnSplitCharacter mySplitter = new VlnSplitCharacter(); internal static void FixHyphens(Paragraph myPara, vlnTable myTable) { // Find chunk with hardhyphen // If a hard hyphen is found, the remove it and add a dash (keyboard minus sign) to the beginning // of the text that follows it. int hype=-1; Font fnt = null; while ((hype = GetHyphen(myPara)) > -1) { fnt = null; if (hype > 0) { Chunk chk1 = (Chunk)myPara[hype - 1]; if (hype > 1 && chk1.Content.Equals("\n")) chk1 = (Chunk)myPara[hype - 2]; fnt = chk1.Font; // use the font of the text that follows the hyphen (dash) } else if (hype < myPara.Count - 1) { Chunk chk2 = (Chunk)myPara[hype + 1]; if (hype != 0 && !chk2.Content.Equals("\n")) fnt = chk2.Font; // use the font of the text that follows the hyphen (dash) } if (fnt == null) { // if there was no text following the hypen, then use the font defined for tables in the plant's format VEPROMS.CSLA.Library.VE_Font vfnt = myTable.MyFlexGrid.GetMyItemInfo().FormatStepData.Font; System.Drawing.Font ffont = new System.Drawing.Font(vfnt.Family, (float)vfnt.Size); fnt = Volian.Svg.Library.VolianPdf.GetFont(ffont); fnt.SetStyle(myPara.Font.Style); fnt.SetColor(myPara.Font.Color.R,myPara.Font.Color.G,myPara.Font.Color.B); } Chunk chk = (Chunk)myPara[hype]; // THIS CODE IS USED FOR DEBUGGING //if (!fnt.Familyname.StartsWith("L")) //{ // Console.WriteLine("font = {0}", makeitpretty(fnt)); // Console.WriteLine("Hype = {0}\r\n{1}",hype, myPara.Content); // if (hype > 0) // { // Chunk chk3 = (Chunk)myPara[hype - 1]; // Console.WriteLine("before '{0}'", chk3.Content); // } // Chunk chk4 = (Chunk)myPara[hype]; // Console.WriteLine("during '{0}'", chk4.Content); // if (hype < myPara.Count -1) // { // Chunk chk5 = (Chunk)myPara[hype + 1]; // Console.WriteLine("after '{0}'", chk5.Content); // } //} string prefix = ""; if (chk.Content == "\u2011" && hype < (myPara.Count - 1)) { myPara.RemoveAt(hype);// Remove standalone hyphen chk = (Chunk)myPara[hype]; prefix = "-"; } myPara.RemoveAt(hype); myPara.Insert(hype, new Chunk(prefix + chk.Content.Replace("\u2011", "-"), fnt)); } } // THIS FUNCTION IS USED FOR DEBUGGING private static string makeitpretty(Font fnt) { return string.Format("font {0}, size {1}, style {2}", fnt.Familyname, fnt.Size, fnt.Style); } private static int GetHyphen(Paragraph myPara) { int index=0; foreach (Chunk chk in myPara.Chunks) if (chk.Content.Contains("\u2011")) return index; else index++; return -1; } public static float CalculateHangingIndent(string rtf) { float chkW = 0; // **** This is intened to be a temporary fix for V.C.Summer **** // Two procedures would not print: A-2 SAG in Summer's SAMG set, and SAG-3 in Summer's PWOG DAMG set. // These procedures have tables with hanging indents and use the Letter Gothic Tall font. // It appears that the font information for the hanging indent character is not included in the RTF // for those table cells. // This piece of code checks for the existance of a font definition of \f1 which is need for the \u9999? indent character // If the a font definition of \f1 is not found then the indent character is removed. This will allow the procedure to print // but the text in that table cell will not be indented. - jsj 10/10/2014 //IRtfDocument rtfDoc2 = RtfInterpreterTool.BuildDoc(rtf.Replace(@"\'05", @"\f1 \u9999? \f0 ")); IRtfDocument rtfDoc2 = null; //if (rtf.Contains(@"\f1\fnil\fcharset0 ")) // rtfDoc2 = RtfInterpreterTool.BuildDoc(rtf.Replace(@"\'05", @"\f1 \u9999? \f0 ")); //else //{ // first add the symbol font and then surround the indent as above. rtfDoc2 = RtfInterpreterTool.BuildDoc(rtf.Replace(@"\'05", @"\par\u9999?\par")); //} Rtf2iTextSharp rtf2IText2 = new Rtf2iTextSharp(rtfDoc2); iTextSharp.text.Paragraph para2 = rtf2IText2.Convert(); for (int ic = 0; ic < para2.Chunks.Count; ic++) { Chunk chk = para2.Chunks[ic] as Chunk; if (chk.Content[0] == 9999) break; if (chk.Content.Contains("\u270f")) { int i = chk.Content.IndexOf('\u270F'); int n = chk.Content.Length; chkW += chk.GetWidthPoint() * i / (n - i); break; } if (chk.Content.Contains("\n")) { if (ic < para2.Chunks.Count - 2 && (para2.Chunks[ic + 1] as Chunk).Content.StartsWith("\u270f")) return chkW; chkW = 0; //hard return - reset chkW (indent start) } chkW += chk.GetWidthPoint(); } return chkW; } private static StepRTB _StatRTB = new StepRTB(); private string PreProcessRTF(float w, string str) { _StatRTB.Text = string.Empty; _StatRTB.Width = (int)w; _StatRTB.Font = MyFlexGrid.Font; if (str.StartsWith(@"{\rtf")) { // The 'Replace(@" \ulnone", @"\u160?\ulnone")' was added so that data in VEWCNSUR_MTC // tables would print. There were a number of tables, for example in STN NB-115/8.1.6, // that had a series of spaces underlined and these spaces were not underlined in the // generated pdf. It seems that there is a problem somewhere in the rtb -> itextsharp // level. This fixed the immediate problem. If there is 'b0' (bold off) after the // space before the 'ulnone' the following won't work. Also, this change was not // made in the non-table code. If the problem occurs there, it should be added. _StatRTB.Rtf = Regex.Replace(str.Replace(@"\~", @"\u160?"), @"(?|---> LineAhead | v lineToRight Case 2: Line being drawn left: lineToRight ^ | LineAhead <-----|<--- Line Being Drawn | v lineToLeft Case 3: Line being drawn up: lineAhead ^ | lineToLeft <-----|----> lineToRight ^ | | Line Being Drawn Case 4: Line being drawn down: Line Begin Drawn | | v lineToRight <-----|----> lineToLeft | | v lineAhead * */ #endregion #region Border Intersection Methods private static float DoubleIntersectionLeft(GridLinePattern lineToLeft, GridLinePattern lineToRight, GridLinePattern lineAhead) { if (lineToLeft == GridLinePattern.Double) return -DoubleLineOffset; if (lineToRight == GridLinePattern.Double || lineAhead == GridLinePattern.Double) return DoubleLineOffset; if (lineToLeft == GridLinePattern.Thick || lineToRight == GridLinePattern.Thick) return DoubleUnderThick; if (VlnBorders.LineWidth(lineToLeft) == 1 || VlnBorders.LineWidth(lineToRight) == 1) return DoubleUnderThin; return 0; } private static float DoubleIntersectionRight(GridLinePattern lineToLeft, GridLinePattern lineToRight, GridLinePattern lineAhead) { if (lineToRight == GridLinePattern.Double) return -DoubleLineOffset; if (lineToLeft == GridLinePattern.Double || lineAhead == GridLinePattern.Double) return DoubleLineOffset; if (lineToLeft == GridLinePattern.Thick || lineToRight == GridLinePattern.Thick) return DoubleUnderThick; if (VlnBorders.LineWidth(lineToLeft) == 1 || VlnBorders.LineWidth(lineToRight) == 1) return DoubleUnderThin; return 0; } private static float ThinIntersection(GridLinePattern lineToLeft, GridLinePattern lineToRight, GridLinePattern lineAhead) { if (lineToLeft == GridLinePattern.Double && lineToRight == GridLinePattern.Double) return -ThinUnderDouble; if (lineToLeft == GridLinePattern.Double || lineToRight == GridLinePattern.Double) { if (lineAhead == GridLinePattern.Double) return -ThinUnderDouble; return ThinOverDouble; } if (lineToLeft == GridLinePattern.Thick || lineToRight == GridLinePattern.Thick) return ThinOverThick; return 0; } private static float ThickIntersection(GridLinePattern lineToLeft, GridLinePattern lineToRight, GridLinePattern lineAhead) { if (lineToLeft == GridLinePattern.Double && lineToRight == GridLinePattern.Double) { if (lineAhead == GridLinePattern.Thick) return ThickOverDouble; return -ThickUnderDouble; } if ( lineToLeft == GridLinePattern.Double || lineToRight == GridLinePattern.Double) { if (lineAhead == GridLinePattern.Double) { if (lineToLeft == GridLinePattern.Thick || lineToRight == GridLinePattern.Thick) return ThickOverDouble; return -ThickUnderDouble; } return ThickOverDouble; } if (VlnBorders.LineWidth(lineToLeft) == 1 && VlnBorders.LineWidth(lineToRight) == 1) return ThickOverThin; return 0; } #endregion #region Basic Border Methods private static void DrawLine(PdfContentByte cb, float lineThickness, float xStart, float yStart, float xEnd, float yEnd) { cb.SetLineWidth(lineThickness); cb.MoveTo(xStart, yStart); cb.LineTo(xEnd, yEnd); } private static void SetLinePattern(PdfContentByte cb, GridLinePattern linePattern) { if (linePattern == GridLinePattern.Dotted) { cb.SetLineDash(0, 2, 0); cb.SetLineCap(PdfContentByte.LINE_CAP_ROUND); } else if (linePattern == GridLinePattern.Dashed) cb.SetLineDash(4, 4, 0); } private static void SetLineColor(PdfContentByte cb, int row, int col, string side) { iTextSharp.text.Color lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Black)); //switch (side) //{ // case "Top": // if (col == 0) lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Blue)); // else lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Cyan)); // break; // case "Left": // if (row == 0) lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Red)); // else lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Magenta)); // break; // case "Bottom": // if (col == 0) lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Green)); // else lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Cyan)); // break; // case "Right": // if (row == 0) lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Orange)); // else lineColor = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Magenta)); // break; //} cb.SetColorStroke(lineColor); } private static void InitializeLineStyle(PdfContentByte cb) { cb.SetLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); // Extend the line by half of it's thickness cb.SetLineDash(0);// Solid Line } #endregion #region Debug Methods private static void SetOpacity(PdfContentByte cb, float opacity) { PdfGState gs = new PdfGState(); gs.StrokeOpacity = opacity; cb.SetGState(gs); } private static void ZoomToCell(iTextSharp.text.pdf.ColumnText myColumnText, float xLeft, float yTop, float xRight, float yBottom) { PdfDestination dest = new PdfDestination(PdfDestination.FITR, xLeft - 4, yBottom , xRight, yTop + 4); myColumnText.Canvas.SetAction(PdfAction.GotoLocalPage(myColumnText.Canvas.PdfWriter.CurrentPageNumber, dest, myColumnText.Canvas.PdfWriter), xLeft, yBottom, xRight, yTop); } #endregion #region Old Border Methods //private void DrawLeftLine(PdfContentByte cb, float xLeft, float yTop, float yBottom) //{ // if (c1 == 0 && LineLeft != GridLinePattern.None) // { // InitializeLineStyle(cb); // SetLineColor(cb, r1, c1, "Left"); // if (LineLeft == GridLinePattern.Double) // { // //Left Line // float dyTop = DoubleIntersectionLeft(LineTopLeft, LineTop, LineLeftAbove); // float dyBottom = -DoubleIntersectionRight(LineBottom, LineBottomLeft, LineLeftBelow); // DrawLine(cb, LineThicknessForDouble, xLeft - DoubleLineOffset, yTop + dyTop, xLeft - DoubleLineOffset, yBottom + dyBottom); // //Right Line // dyTop = DoubleIntersectionRight(LineTopLeft, LineTop, LineLeftAbove); // dyBottom = -DoubleIntersectionLeft(LineBottom, LineBottomLeft, LineLeftBelow); // DrawLine(cb, LineThicknessForDouble, xLeft + DoubleLineOffset, yTop + dyTop, xLeft + DoubleLineOffset, yBottom + dyBottom); // } // else if (LineLeft != GridLinePattern.Thick) // { // SetLinePattern(cb, LineLeft); // float dyTop = ThinIntersection(LineTopLeft, LineTop, LineLeftAbove); // float dyBottom = -ThinIntersection(LineBottom, LineBottomLeft, LineLeftBelow); // DrawLine(cb, LineThicknessForThin, xLeft, yTop + dyTop, xLeft, yBottom + dyBottom); // } // else // { // float dyTop = ThickIntersection(LineTopLeft, LineTop, LineLeftAbove); // float dyBottom = -ThickIntersection(LineBottom, LineBottomLeft, LineLeftBelow); // DrawLine(cb, LineThicknessForThick, xLeft, yTop + dyTop, xLeft, yBottom + dyBottom); // } // cb.Stroke(); // } //} //private void DrawRightLine(PdfContentByte cb, float xRight, float yTop, float yBottom) //{ // if (LineRight != GridLinePattern.None) // { // InitializeLineStyle(cb); // SetLineColor(cb, r1, c1, "Right"); // if (LineRight == GridLinePattern.Double) // { // //Left Line // float dyTop = DoubleIntersectionLeft(LineTop, LineTopRight, LineRightAbove); // float dyBottom = -DoubleIntersectionRight(LineBottomRight, LineBottom, LineRightBelow); // DrawLine(cb, LineThicknessForDouble, xRight - DoubleLineOffset, yTop + dyTop, xRight - DoubleLineOffset, yBottom + dyBottom); // //Right Line // dyTop = DoubleIntersectionRight(LineTop, LineTopRight, LineRightAbove); // dyBottom = -DoubleIntersectionLeft(LineBottomRight, LineBottom, LineRightBelow); // DrawLine(cb, LineThicknessForDouble, xRight + DoubleLineOffset, yTop + dyTop, xRight + DoubleLineOffset, yBottom + dyBottom); // } // else if (LineRight != GridLinePattern.Thick) // { // float dyTop = ThinIntersection(LineTop, LineTopRight, LineRightAbove); // float dyBottom = -ThinIntersection(LineBottomRight, LineBottom, LineRightBelow); // SetLinePattern(cb, LineRight); // DrawLine(cb, LineThicknessForThin, xRight, yTop + dyTop, xRight, yBottom + dyBottom); // } // else // { // float dyTop = ThickIntersection(LineTop, LineTopRight, LineRightAbove); // float dyBottom = -ThickIntersection(LineBottomRight, LineBottom, LineRightBelow); // DrawLine(cb, LineThicknessForThick, xRight, yTop + dyTop, xRight, yBottom + dyBottom); // } // cb.Stroke(); // } //} //private void DrawTopLine(PdfContentByte cb, float xLeft, float xRight, float yTop) //{ // if (r1 == 0 && TopSide != GridLinePattern.None) // { // InitializeLineStyle(cb); // SetLineColor(cb, r1, c1, "Top"); // if (TopSide == GridLinePattern.Double) // { // // Top Line // float dxLeft = -DoubleIntersectionRight(LeftSide, AboveLeftSide, LeftOfTopSide); // float dxRight = DoubleIntersectionLeft(AboveRightSide, RightSide, RightOfTopSide); // DrawLine(cb, LineThicknessForDouble, xLeft + dxLeft, yTop + DoubleLineOffset, xRight + dxRight, yTop + DoubleLineOffset); // // Bottom Line // dxLeft = -DoubleIntersectionLeft(LeftSide, AboveLeftSide, LeftOfTopSide); // dxRight = DoubleIntersectionRight(AboveRightSide, RightSide, RightOfTopSide); // DrawLine(cb, LineThicknessForDouble, xLeft + dxLeft, yTop - DoubleLineOffset, xRight + dxRight, yTop - DoubleLineOffset); // } // else if (TopSide != GridLinePattern.Thick) // { // SetLinePattern(cb, TopSide); // float dxLeft = -ThinIntersection(LeftSide, AboveLeftSide, LeftOfTopSide); // float dxRight = ThinIntersection(AboveRightSide, RightSide, RightOfTopSide); // DrawLine(cb, LineThicknessForThin, xLeft + dxLeft, yTop, xRight + dxRight, yTop); // } // else // { // float dxLeft = -ThickIntersection(LeftSide, AboveLeftSide, LeftOfTopSide); // float dxRight = ThickIntersection(AboveRightSide, RightSide, RightOfTopSide); // if (c1 == 0) // Console.WriteLine("'{0}','{1}','{2}',{3},{4}", LeftSide, AboveLeftSide, LeftOfTopSide, dxLeft, ThickOverThin); // DrawLine(cb, LineThicknessForThick, xLeft + dxLeft, yTop, xRight + dxRight, yTop); // } // cb.Stroke(); // } //} //private void DrawBottomLine(PdfContentByte cb, float xLeft, float xRight, float yBottom) //{ // if (BottomSide != GridLinePattern.None) // { // InitializeLineStyle(cb); // SetLineColor(cb, r1, c1, "Bottom"); // if (BottomSide == GridLinePattern.Double) // { // // Top Line // float dxLeft = -DoubleIntersectionRight(BelowLeftSide, LeftSide, LeftOfBottomSide); // float dxRight = DoubleIntersectionLeft(RightSide, BelowRightSide, RightOfBottomSide); // DrawLine(cb, LineThicknessForDouble, xLeft + dxLeft, yBottom + DoubleLineOffset, xRight + dxRight, yBottom + DoubleLineOffset);// Top Line // // Bottom Line // dxLeft = -DoubleIntersectionLeft(BelowLeftSide, LeftSide, LeftOfBottomSide); // dxRight = DoubleIntersectionRight(RightSide, BelowRightSide, RightOfBottomSide); // DrawLine(cb, LineThicknessForDouble, xLeft + dxLeft, yBottom - DoubleLineOffset, xRight + dxRight, yBottom - DoubleLineOffset);//Bottom Line // } // else if (BottomSide != GridLinePattern.Thick) // Bottom line is thin. Determine if intersecting with double: // { // SetLinePattern(cb, BottomSide); // float dxLeft = -ThinIntersection(BelowLeftSide, LeftSide, LeftOfBottomSide); // float dxRight = ThinIntersection(RightSide, BelowRightSide, RightOfBottomSide); // DrawLine(cb, LineThicknessForThin, xLeft + dxLeft, yBottom, xRight + dxRight, yBottom); // } // else // { // float dxLeft = -ThickIntersection(BelowLeftSide, LeftSide, LeftOfBottomSide); // float dxRight = ThickIntersection(RightSide, BelowRightSide, RightOfBottomSide); // DrawLine(cb, LineThicknessForThick, xLeft + dxLeft, yBottom, xRight + dxRight, yBottom); // } // cb.Stroke(); // } //} #endregion } }