using System; using System.Collections.Generic; using System.Text; using iTextSharp.text; using iTextSharp.text.pdf; using iTextSharp.text.factories; using Itenso.Rtf; using Itenso.Rtf.Parser; using Itenso.Rtf.Interpreter; //using Itenso.Rtf.Model; using Itenso.Rtf.Support; using Microsoft.Win32; using Volian.Base.Library; using System.Text.RegularExpressions; using VEPROMS.CSLA.Library; namespace Volian.Print.Library { public partial class PrintOverride { public static bool CompressSub = false; public static bool CompressSuper = false; public static bool CompressPropSubSup = false; private static System.Drawing.Color _TextColor = System.Drawing.Color.Empty; public static System.Drawing.Color TextColor { get { return _TextColor; } set { _TextColor = value; } } public static System.Drawing.Color OverrideTextColor(System.Drawing.Color color) { if (_TextColor == System.Drawing.Color.Empty) return color; return _TextColor; } private static System.Drawing.Color _SvgColor = System.Drawing.Color.Empty; public static System.Drawing.Color SvgColor { get { return _SvgColor; } set { _SvgColor = value; Volian.Svg.Library.Svg.OverrideColor = value; } } public static System.Drawing.Color OverrideSvgColor(System.Drawing.Color color) { if (_SvgColor == System.Drawing.Color.Empty) return color; return _SvgColor; } private static System.Drawing.Color _BoxColor = System.Drawing.Color.Empty; public static System.Drawing.Color BoxColor { get { return _BoxColor; } set { _BoxColor = value; } } public static System.Drawing.Color OverrideBoxColor(System.Drawing.Color color) { if (_BoxColor == System.Drawing.Color.Empty) return color; return _BoxColor; } private static System.Drawing.Color _ChangeBarColor = System.Drawing.Color.Empty; public static System.Drawing.Color ChangeBarColor { get { return _ChangeBarColor; } set { _ChangeBarColor = value; } } public static System.Drawing.Color OverrideChangeBarColor(System.Drawing.Color color) { if (_ChangeBarColor == System.Drawing.Color.Empty) return color; return _ChangeBarColor; } private static System.Drawing.Color _DebugColor = System.Drawing.Color.Empty; public static System.Drawing.Color DebugColor { get { return _DebugColor; } set { _DebugColor = value; } } public static System.Drawing.Color OverrideDebugColor(System.Drawing.Color color) { if (_DebugColor == System.Drawing.Color.Empty) return color; return _DebugColor; } public static void Reset() { DebugColor = System.Drawing.Color.Empty; TextColor = System.Drawing.Color.Empty; SvgColor = System.Drawing.Color.Empty; BoxColor = System.Drawing.Color.Empty; ChangeBarColor = System.Drawing.Color.Empty; } } public class Rtf2iTextSharp : RtfVisualVisitorBase { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private bool _HasIndent = false; public bool HasIndent { get { return _HasIndent; } set { _HasIndent = value; } } private IRtfDocument _RtfDoc; private Paragraph _MyParagraph = new Paragraph(); private iTextSharp.text.Font _MyFont; // Allow for definition of a default font: if the font is not proportional, this gets set. // It is needed to set the chunk's font if the first character of a cell is a hardspace (or various // other special cases (see its use below). Without this, pdfs were using the Helvetica font, // which is a default itextsharp font (this was causing a problem for HLP, their pdfs could not // contain a Helvetica font when putting them in their production environment). private iTextSharp.text.Font _DefaultFont; public iTextSharp.text.Font DefaultFont { get { return _DefaultFont; } set { _DefaultFont = value; } } private string _MyDebugID = null; public string MyDebugID { get { return _MyDebugID; } set { _MyDebugID = value; } } public bool DoPdfLinks = false; // public Rtf2iTextSharp(IRtfDocument rtfDoc, Document doc, PdfWriter writer) public Rtf2iTextSharp(IRtfDocument rtfDoc) { if (rtfDoc == null) throw new ArgumentNullException("rtfDoc"); _RtfDoc = rtfDoc; } public Paragraph Convert() { int profileDepth = ProfileTimer.Push(">>>> Rtf2ITextSharp.Convert"); _MyParagraph.Clear(); _MyFont = null; foreach (IRtfVisual visual in _RtfDoc.VisualContent) { visual.Visit(this); } //_MyParagraph.SetLeading(0, 1); ProfileTimer.Pop(profileDepth); return _MyParagraph; } // ---------------------------------------------------------------------- private int _lastWasLineBreak = 0; // B2017-191 insert a NewLine when hard returns are used protected override void DoVisitBreak(IRtfVisualBreak visualBreak) { switch (visualBreak.BreakKind) { case RtfVisualBreakKind.Line: if (_lastWasLineBreak > 0) { _MyParagraph.Add(Chunk.NEWLINE); if (_lastWasLineBreak == 1) _MyParagraph.Add(Chunk.NEWLINE); // B2017-191 if this is the first hard return add an etra newline to create the first blank line } else { Chunk ck = HasIndent ? new Chunk("".PadLeft(200)) : new Chunk("".PadLeft(200)); _MyParagraph.Add(ck); } _lastWasLineBreak++; // B2017-191 hard return count break; case RtfVisualBreakKind.Page: _lastWasLineBreak = 0; // B2017-191 reset hard return count break; case RtfVisualBreakKind.Paragraph: Chunk ck1 = HasIndent ? new Chunk("".PadLeft(200)) : Chunk.NEWLINE; _MyParagraph.Add(ck1); _lastWasLineBreak = 0; // B2017-191 reset hard return count break; case RtfVisualBreakKind.Section: _lastWasLineBreak = 0; // B2017-191 reset hard return count break; default: _lastWasLineBreak = 0; // B2017-191 reset hard return count break; } //_MyParagraph.Add(string.Format("<{0}>", visualBreak.BreakKind.ToString())); } private void AddChunk(string str, iTextSharp.text.Font font) { if (font == null) _MyParagraph.Add(new Chunk(str)); else _MyParagraph.Add(new Chunk(str, font)); } protected override void DoVisitSpecial(IRtfVisualSpecialChar visualSpecialChar) { //_MyParagraph.Add(string.Format("", visualSpecialChar.CharKind.ToString())); iTextSharp.text.Font activeFont = _MyFont ?? DefaultFont; switch (visualSpecialChar.CharKind) { case RtfVisualSpecialCharKind.Bullet: AddChunk("\u2022", activeFont); break; case RtfVisualSpecialCharKind.EmDash: AddChunk("\u2014", activeFont); break; case RtfVisualSpecialCharKind.EmSpace: AddChunk("\u2003", activeFont); break; case RtfVisualSpecialCharKind.EnDash: AddChunk("\u2013", activeFont); break; case RtfVisualSpecialCharKind.EnSpace: AddChunk(" ", activeFont); break; case RtfVisualSpecialCharKind.LeftDoubleQuote: AddChunk("\u201C", activeFont); break; case RtfVisualSpecialCharKind.LeftSingleQuote: AddChunk("\u2018", activeFont); break; case RtfVisualSpecialCharKind.NonBreakingHyphen: AddChunk("\u2011", activeFont); break; case RtfVisualSpecialCharKind.NonBreakingSpace: //iTextSharp.text.Font font = Volian.Svg.Library.VolianPdf.GetFont(sdf); AddChunk("\u00A0", activeFont); break; case RtfVisualSpecialCharKind.OptionalHyphen: AddChunk("\u00AD", activeFont); break; case RtfVisualSpecialCharKind.ParagraphNumberBegin: break; case RtfVisualSpecialCharKind.ParagraphNumberEnd: break; case RtfVisualSpecialCharKind.QmSpace: break; case RtfVisualSpecialCharKind.RightDoubleQuote: AddChunk("\u201D", activeFont); break; case RtfVisualSpecialCharKind.RightSingleQuote: AddChunk("\u2019", activeFont); break; case RtfVisualSpecialCharKind.Tabulator: break; default: break; } _lastWasLineBreak = 0; // B2017-191 reset hard return count } private bool ContainsAllSymbols(string p) { foreach (char c in p) if (c <= '\x7F') return false; return true; } private bool ContainsAnySymbols(string p) { foreach (char c in p) if (c > '\x7F' && c != '\xA0' && c != '\xB0') return true; return false; } // The funcction below was used for the first few lines of DoVisitText which have been commented-out //private object FixText(string str) //{ // StringBuilder sb = new StringBuilder(); // foreach (char c in str) // if (c < ' ' || c > '\xFF') // sb.Append(string.Format("[{0}]", (int)c)); // else // sb.Append(c); // return sb.ToString(); //} // ParseLink & GetDefaultItemInfo (which used to be in vlnParagraph) support coding that was added to DoVisitText for // doing pdflink for each transition/ro in a step, see bug B2019-052 private RoUsageInfo _Roui = null; private TransitionInfo _Ti = null; private int _linkType = 0; // for the particular link, parse its text to see the type of link and its associated data, either transitioninfo or rousageinfo: public void ParseLink(string _LinkInfoText) { if (_LinkInfoText == null) return; // First parse the string if (_LinkInfoText.Contains(@"\v")) throw new Exception("LinkText.ParseLink found RTF token"); Match m = Regex.Match(_LinkInfoText, @"[#]Link:([A-Za-z]*):(.*)"); string _MyValue = m.Groups[1].Value; string _MyLink = "#Link:" + m.Groups[2].Value + ":" + m.Groups[3].Value; switch (m.Groups[1].Value) { case "ReferencedObject": _linkType = 1; string[] subs = m.Groups[2].Value.Split(" ".ToCharArray()); if (subs[0].IndexOf("CROUSGID") > -1) _Roui = null; else if (subs[0].IndexOf("NewID") > -1) _Roui = null; else { int roUsageid = int.Parse(subs[0]); _Roui = RoUsageInfo.Get(roUsageid); } break; case "Transition": case "TransitionRange": _linkType = 2; string[] subst = m.Groups[2].Value.Split(" ".ToCharArray()); if (subst[1].IndexOf("CTID") > -1) _Ti = null; else if (subst[1].IndexOf("NewID") > -1) _Ti = null; else { int transitionID = int.Parse(m.Groups[2].Value.Split(" ".ToCharArray())[1]); _Ti = TransitionInfo.Get(transitionID); } break; } } // GetDefaultItemInfo finds the item that a transition goes to. If it goes to procedure, go to default section's (or procedure // steps section if no default) first step (or go to default section if there are not steps). Also, go to step if there are // steps, else go to section. And last, if none of these can be found, just go to the item passed in. private ItemInfo GetDefaultItemInfo(ItemInfo myItemInfo) { if (myItemInfo.IsProcedure && myItemInfo.Sections != null) { SectionInfo siProcedureSteps = null; foreach (SectionInfo si in myItemInfo.Sections) { if (si.IsDefaultSection) { if (si.Steps != null) return si.Steps[0]; if (si.Sections != null) return si.Sections[0]; return si; } if (si.DisplayText.Contains("Procedure Step")) siProcedureSteps = si; } if (siProcedureSteps != null) { if (siProcedureSteps.Steps != null) return siProcedureSteps.Steps[0]; if (siProcedureSteps.Sections != null) return siProcedureSteps.Sections[0]; return siProcedureSteps; } } if (myItemInfo.IsSection) { if (myItemInfo.Steps != null) return myItemInfo.Steps[0]; if (myItemInfo.Sections != null) return myItemInfo.Sections[0]; } return myItemInfo; } private static int chkStart = -1; protected override void DoVisitText(IRtfVisualText visualText) { //Code to find text (non-symbol) being output with a symbol font //if(visualText.Format.Font.Name=="VESymbFix" && visualText.Text.Length > 1) //{ // string s = visualText.Text; // s=s.Replace("a","").Replace("b",""); // if(s!=visualText.Text) // Console.WriteLine("{0}-{1}-{2}-{3}", visualText.Format.Font.Name, (int)(visualText.Text[0]),visualText.Text.Length,FixText(visualText.Text)); //} int profileDepth = ProfileTimer.Push(">>>> DoVisitText"); if (visualText.Format.IsHidden) { // B2019-052: Hidden text contains the link text - so if doing the pdf links when printing, this can be used to determine how // to create the link. A given link may have multiple chunks though, if there are attribute changes, symbols, etc. This // code goes through all of the chunks of a link and sets attributes on each chunk so that the link goes to the correct // place (RO or Transition 'to'). Note that the pdf links were originally done in vlnparagraph.cs but only went to a single // link within a step. The code was moved here so that each ro and transition link within a step could have its on pdf link. if (DoPdfLinks) { // use the start and end tokens in the link text, these may span more than one chunk. if (visualText.Text.Contains("")) { string txt = visualText.Text; ParseLink(txt); // get the link data, ro or transition for (int i = chkStart; i < _MyParagraph.Chunks.Count; i++) { try { Chunk chk = _MyParagraph.Chunks[i] as Chunk; if (chk != null) { if (_linkType == 2 && _Ti != null) // transition { ItemInfo tiDefault = GetDefaultItemInfo(_Ti.MyItemToID); ItemInfo from = _Ti.MyContent.ContentItems[0]; if (_Ti.MyItemToID.MyProcedure.ItemID == from.MyProcedure.ItemID && !((from.ActiveSection.MyConfig as SectionConfig).Section_IsFoldout == "Y")) //C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box { // Local Go To // B2020-028, 029 and 030: all were related to print of supplemental information when printing with // pdf links. The pdf links in the temporary supinfo pdf caused a crash on save of file because they didn't exist. if (_Ti.MyItemToID.MyContent.Type > 9999 && !from.IsInSupInfo) // internal to this file { chk.SetLocalGoto(string.Format("ItemID={0}", tiDefault.ItemID)); chk.SetBackground(Color.CYAN); chk.SetBackground(new Color(System.Drawing.Color.LightCyan)); } } else if (_Ti != null && !from.IsInSupInfo) // Remote Go To. Added SupInfo check for B2020 bugs (see above) { // C2024-009 add PDF file prefix and suffix if available to the PDF file name in the transition reference. DocVersionConfig dvc = _Ti.MyItemToID.MyProcedure.MyDocVersion.DocVersionConfig; string remotePDFName = dvc.Print_PDFFilePrefix + _Ti.MyItemToID.MyProcedure.DisplayNumber.Replace("/", "_") + dvc.Print_PDFFileSuffix + ".pdf"; chk.SetRemoteGoto(remotePDFName, string.Format("ItemID={0}", tiDefault.ItemID)); chk.SetBackground(new Color(System.Drawing.Color.PeachPuff)); } } else if (_linkType == 1 && _Roui != null && !_Roui.MyContent.ContentItems[0].IsInSupInfo) // referenced object. Added SupInfo check for B2020 bugs (see above) { if (_Roui.ROID.Substring(0, 4) != "FFFF") { chk.SetRemoteGoto("completeroreport.pdf", string.Format("ROID={0}", _Roui.ROID.Substring(0, 12).ToUpper())); chk.SetBackground(new Color(System.Drawing.Color.LightGreen)); } } } } catch (Exception ex) { _MyLog.ErrorFormat("Error creating pdf links {0}", ex.Message); } } _Ti = null; _Roui = null; _linkType = 0; chkStart = -1; } } ProfileTimer.Pop(profileDepth); _lastWasLineBreak = 0; // B2017-191 reset hard return count return; } iTextSharp.text.Font font = Volian.Svg.Library.VolianPdf.GetFont(visualText.Format.Font.Name, visualText.Format.FontSize, (visualText.Format.IsBold ? iTextSharp.text.Font.BOLD : 0) + (visualText.Format.IsItalic ? iTextSharp.text.Font.ITALIC : 0)); font.Color = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(visualText.Format.ForegroundColor.AsDrawingColor)); // The following line of code was added to allow for comparisons between the 16bit and 32bit pdf files. Without // the size change, the overlays did not match up. It seems that the 16bit font size may be inaccurate // and the 16bit conversion to be pdf may be off. //if (font.Familyname.StartsWith("Arial") && font.Size == 11 && DoingComparison) font.Size = 11.15f; iTextSharp.text.pdf.FontSelector fs = new FontSelector(); // DEBUG //if (visualText.Format.Font.Name != "VESymbFix" && ContainsAnySymbols(visualText.Text)) //{ // Console.WriteLine("Font: {0} TEXT: {1}", visualText.Format.Font.Name, ShowSpecialCharacters(visualText.Text)); //} if (visualText.Format.Font.Name == "VESymbFix" && ContainsAllSymbols(visualText.Text)) { fs.AddFont(font); // if the symbol character cannot be found in VESymbFix then check/use the Consolas font // We are using the VESymbFix font first because not all of the symbols that we use are in the Consolas font // The Consolas font will give us other symbols that we don't have in VESymbFix (ex the Omega) fs.AddFont(FontFactory.GetFont("Consolas", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (visualText.Format.FontSize * 1.1F) / 2, (visualText.Format.IsBold ? iTextSharp.text.Font.BOLD : 0) + (visualText.Format.IsItalic ? iTextSharp.text.Font.ITALIC : 0), font.Color)); // added the FreeMono font because when were was a backslash symbol (\u9568?) it was not found and thus removed from the chunk B2014-108 backslash in table fs.AddFont(FontFactory.GetFont("FreeMono", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (visualText.Format.FontSize * 1.1F) / 2, (visualText.Format.IsBold ? iTextSharp.text.Font.BOLD : 0) + (visualText.Format.IsItalic ? iTextSharp.text.Font.ITALIC : 0), font.Color)); // B2021-038 add the Consolas and FreeMono without Bold or Italic - some symbols are not available as Bold or Italic fs.AddFont(FontFactory.GetFont("Consolas", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (visualText.Format.FontSize * 1.1F) / 2, 0, font.Color)); fs.AddFont(FontFactory.GetFont("FreeMono", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (visualText.Format.FontSize * 1.1F) / 2, 0, font.Color)); Phrase ph = fs.Process(visualText.Text); foreach (Chunk chk in ph.Chunks) { AdjustChunk(visualText, font, chk); _MyParagraph.Add(chk); } } // B2021-038 add the FreeSerif without Bold or Italic - some symbols are not available as Bold or Italic else if (visualText.Format.Font.Name == "FreeSerif" && ContainsAllSymbols(visualText.Text)) { fs.AddFont(font); fs.AddFont(FontFactory.GetFont("FreeSerif", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (visualText.Format.FontSize * 1.1F) / 2, 0, font.Color)); Phrase ph = fs.Process(visualText.Text); foreach (Chunk chk in ph.Chunks) { AdjustChunk(visualText, font, chk); _MyParagraph.Add(chk); } } else { // The bullet character for some unknown reason was entered in a text font rather than a symbol font // switch from x25cf ot x2022 moves to a valid bullet character in the text font // B2017-171 Mcguire reported their bullet substeps print a smaller bullet than before // B2017-238 V.C. Summer Bullets were not printing. Needed to check for Letter Gothic Tall font if (font.Familyname == "Prestige Elite Tall" || font.Familyname == "Letter Gothic Tall") ProcessMeans(visualText, visualText.Text.Replace("\u25cf", "\u2022"), font); else ProcessMeans(visualText, visualText.Text, font); } ProfileTimer.Pop(profileDepth); _lastWasLineBreak = 0; // B2017-191 reset hard return count } /// /// Method to process means from text. Draws a line above the content of the range included in the /// square brackets. [Mean X] /// Handles everything except font style changes within the expression. /// /// /// /// private void ProcessMeans(IRtfVisualText visualText, string txt,iTextSharp.text.Font font) { Match m = Regex.Match(txt, "(.*)[[]Mean (.+)[]](.*)", RegexOptions.IgnoreCase); Chunk chk; if (m.Groups.Count == 4) // If the text contains [Mean ...] then follow the code to add a line above the text. { //The first group is the text before the last [Mean ...] ProcessMeans(visualText, m.Groups[1].Value, font);// Recursively process the first group. // The second group is the text within the [Mean ...] range chk = new Chunk(m.Groups[2].Value, font); float offset = .8f;// This is just above the character. // If the content is lower case and does not have ascenders then move the line down. if (Regex.IsMatch(m.Groups[2].Value, "^[acgmnopqrsuvwxyz]+$")) offset = .6F; //PrintOverride.CompressPropSubSup = true; if (visualText.Format.SuperScript < 0)// Adjust line for subscript { offset -= .2f; if (PrintOverride.CompressPropSubSup) offset += .2f;// Adjust line for shrinking font } if (visualText.Format.SuperScript > 0)//Adjust line for superscript { offset += .3f; if (PrintOverride.CompressPropSubSup) offset += .2f;// Adjust line for shrinking font } // Draw the line chk.SetUnderline(font.Color, 0, .05F, 0, offset, PdfContentByte.LINE_CAP_ROUND); AdjustChunk(visualText, font, chk); _MyParagraph.Add(chk); // output the text following the [Mean ...] chk = new Chunk(m.Groups[3].Value, font); AdjustChunk(visualText, font, chk); _MyParagraph.Add(chk); } else { chk = new Chunk(txt, font); AdjustChunk(visualText, font, chk); _MyParagraph.Add(chk); } } private void AdjustChunk(IRtfVisualText visualText, iTextSharp.text.Font font, Chunk chk) { if (visualText.Format.BackgroundColor.AsDrawingColor.ToArgb() != System.Drawing.Color.White.ToArgb()) chk.SetBackground(new iTextSharp.text.Color(visualText.Format.BackgroundColor.AsDrawingColor)); if (visualText.Format.IsStrikeThrough) chk.SetUnderline(font.Color, 0, 0.05F, 0, .3F, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size if (visualText.Format.IsUnderline) if (visualText.Format.SuperScript < 0) { if (PrintOverride.CompressSub) { float yoffundx = (_MyParagraph.Leading < 12 && font.Size >= 12) ? -0.06F : -0.18F; chk.SetUnderline(font.Color, 0, 0.07F, 0, yoffundx, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size } else chk.SetUnderline(font.Color, 0, 0.05F, 0, -.381F, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size } else if (visualText.Format.SuperScript > 0 && PrintOverride.CompressSuper) { float yoffundx = (_MyParagraph.Leading < 12 && font.Size >= 12) ? -0.06F : -0.18F; chk.SetUnderline(font.Color, 0, 0.07F, 0, yoffundx, PdfContentByte.LINE_CAP_ROUND); } else { // If on a compressed printed step (Leading < 12) and a larger underlined font, then set the underlining // a little less far down the page. Without this, the underline was touching the 2nd line of text, if it existed. // Any plant that had compressed steps with the font size/underline would have this problem. An example // was Braidwood FSG-6, high level steps. float yoffund = (_MyParagraph.Leading < 12 && font.Size >= 12) ? -0.06F : -0.131F; if(chk.Font.BaseFont.PostscriptFontName.ToUpper().Contains("BOLD")) // C2021-052 make underline thicker if text is bolded chk.SetUnderline(font.Color, 0, 0.12F, 0, yoffund, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size else chk.SetUnderline(font.Color, 0, 0.05F, 0, yoffund, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size } if (visualText.Format.SuperScript > 0) { if (PrintOverride.CompressPropSubSup) { chk.SetTextRise(.33F * chk.Font.Size); chk.Font.Size *= .75f; } else { chk.SetTextRise(.25F * chk.Font.Size); if (PrintOverride.CompressSuper) chk.Font.Size = 9; } } else if (visualText.Format.SuperScript < 0) { if (PrintOverride.CompressPropSubSup) chk.Font.Size *= .75f; else { // if the subscript is not compressed or if it is compress but not underlined, then move it down if (!PrintOverride.CompressSub || !visualText.Format.IsUnderline) chk.SetTextRise(-.25F * chk.Font.Size); if (PrintOverride.CompressSub) chk.Font.Size = 9; } } else chk.SetTextRise(0); switch (visualText.Format.Alignment) { case RtfTextAlignment.Center: _MyParagraph.Alignment = Element.ALIGN_CENTER; break; case RtfTextAlignment.Justify: _MyParagraph.Alignment = Element.ALIGN_JUSTIFIED; break; case RtfTextAlignment.Left: _MyParagraph.Alignment = Element.ALIGN_LEFT; break; case RtfTextAlignment.Right: _MyParagraph.Alignment = Element.ALIGN_RIGHT; break; default: break; } if (_MyFont == null) { _MyFont = font; //B2021-055 If first character was a bold symbol, entire line was bold // Set the MyParagraph font to an not bolded version //B2021-058 Needed to double font size because GetFont will divide it to zero _MyParagraph.Font = Volian.Svg.Library.VolianPdf.GetFont(font.Familyname, (int)(font.Size * 2), 0); } } private string ShowSpecialCharacters(string p) { StringBuilder sb = new StringBuilder(); foreach (char c in p) { int i = (int)c; if (i < 20 || i > 127) sb.Append(string.Format("<{0:x}>", i)); else sb.Append(c); } return sb.ToString(); }// DoVisitText // ---------------------------------------------------------------------- protected override void DoVisitImage(IRtfVisualImage visualImage) { //_MyParagraph.Add(new Chunk("")); //DateTime dt1 = DateTime.Now; //System.Drawing.Image img2 = visualImage.ImageForDrawing; //Console.WriteLine("1 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); //img2.Save(@"c:\datacvrt\x.png"); System.IO.MemoryStream ms = new System.IO.MemoryStream(); //Console.WriteLine("2 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); //Console.WriteLine("Size {0}", visualImage.ImageForDrawing.Size); visualImage.ImageForDrawing.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); //Console.WriteLine("3 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); ms.Seek(0, System.IO.SeekOrigin.Begin); //Console.WriteLine("4 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(ms); //Console.WriteLine("5 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); _MyParagraph.Add(img); //Console.WriteLine("6 Time Span {0}", TimeSpan.FromTicks(DateTime.Now.Ticks - dt1.Ticks).TotalMilliseconds); _lastWasLineBreak = 0; // B2017-191 reset hard return count } // DoVisitImage } }