670 lines
27 KiB
C#
670 lines
27 KiB
C#
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("<special {0}>", 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("<START]")) chkStart = _MyParagraph.Chunks.Count;
|
|
if (visualText.Text.Contains("[END>"))
|
|
{
|
|
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)
|
|
{
|
|
chk.SetRemoteGoto(_Ti.MyItemToID.MyProcedure.DisplayNumber.Replace("/", "_") + ".pdf", 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
|
|
}
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="visualText"></param>
|
|
/// <param name="txt"></param>
|
|
/// <param name="font"></param>
|
|
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("<Image>"));
|
|
//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
|
|
|
|
}
|
|
}
|