using System; using System.Collections; using System.Text; using System.Collections.Generic; using System.Xml.Serialization; 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.Support; using Microsoft.Win32; using System.Text.RegularExpressions; using System.Xml; using System.IO; using Volian.Base.Library; namespace Volian.Svg.Library { public static class VolianPdf { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public static int PageCount(string fileName) { PdfReader pdfr = new PdfReader(fileName); int retval = pdfr.NumberOfPages; pdfr.Close(); return retval; } // keep for debug //private static List _RegFonts = new List(); public static iTextSharp.text.Font GetFont(string fontName, int size, int style) { //if (!_RegFonts.Contains(fontName)) //{ //_MyLog.WarnFormat("Registering Font {0}", fontName); //_RegFonts.Add(fontName); //} // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(fontName); return iTextSharp.text.FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, size / 2, style); } public static iTextSharp.text.Font GetFont(System.Drawing.Font font) // fontName, int size, int style) { // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(font.Name); int style = (font.Bold ? iTextSharp.text.Font.BOLD : 0) + (font.Italic ? iTextSharp.text.Font.ITALIC : 0); return iTextSharp.text.FontFactory.GetFont(font.Name, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, font.Size, style); } } internal static class SvgITextLibrary { public static void StrokeAndFill(PdfContentByte cb, bool stroke, bool fill) { switch ((stroke ? 1 : 0) + (fill ? 2 : 0)) { case 0: // No Stroke or Fill break; case 1: // Stroke cb.Stroke(); break; case 2: // Fill cb.Fill(); break; case 3: // Stroke and Fill cb.FillStroke(); break; } } } public abstract partial class SvgPart { public abstract void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent); public abstract void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent); } public partial class SvgPartInheritance : SvgPart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { } } // TODO: Pages // TODO: Page Background public delegate string SvgProcessTextEvent(object sender, SvgProcessTextArgs args); public class SvgProcessTextArgs { private string _MyText; public string MyText { get { return _MyText; } } private SvgText _MySvgText; public SvgText MySvgText { get { return _MySvgText; } set { _MySvgText = value; } } private SvgScale _MySvgScale; public SvgScale MySvgScale { get { return _MySvgScale; } set { _MySvgScale = value; } } public SvgProcessTextArgs(string myText, SvgText mySvgText, SvgScale mySvgScale) { _MyText = myText; _MySvgText = mySvgText; _MySvgScale = mySvgScale; } } public partial class Svg : SvgGroup { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public void DrawMacro(string macroDef, float x, float y, PdfContentByte cb) { _MyContentByte = cb; SvgMeasurement X = new SvgMeasurement(x, E_MeasurementUnits.PT); SvgMeasurement Y = new SvgMeasurement(Height.GetSizeInPoints(72) - y, E_MeasurementUnits.PT); if (!this.LookUp.ContainsKey(macroDef)) return; // AEP - DU1 (missing C22 macro for AEP) SvgGroup macro = this[macroDef] as SvgGroup; macro.SvgParts.Draw(cb, MyScale.AdjustOrigin(X, Y), this,this); } public event SvgProcessTextEvent ProcessText; internal string OnProcessText(string myText, SvgText mySvgText, SvgScale scale) { if (ProcessText != null) return ProcessText(this, new SvgProcessTextArgs(myText, mySvgText, scale)); return myText; } private Dictionary _Templates; public PdfTemplate GetTemplate(string name, PdfContentByte cb) { if (!_Templates.ContainsKey(name)) { PdfTemplate tmp = cb.CreateTemplate(100, 100); _Templates.Add(name, tmp); } return _Templates[name]; } public static void FixBoundingBox(PdfTemplate tmp, float xll, float yll, float xul, float yul) { float left = tmp.BoundingBox.Left; float bottom = tmp.BoundingBox.Bottom; float right = tmp.BoundingBox.Right; float top = tmp.BoundingBox.Top; left = (xll < xul ? (xll < left ? xll : left) : (xul < left ? xul : left)); right = (xll > xul ? (xll > right ? xll : right) : (xul > right ? xul : right)); bottom = (yll < yul ? (yll < bottom ? yll : bottom) : (yul < bottom ? yul : bottom)); top = (yll > yul ? (yll > top ? yll : top) : (yul > top ? yul : top)); tmp.BoundingBox = new iTextSharp.text.Rectangle(xll, yll, xul, yul); } private PdfContentByte _MyContentByte; [XmlIgnore] public PdfContentByte MyContentByte { get { return _MyContentByte; } set { _MyContentByte = value; } } private float _LeftMargin = 0; public float LeftMargin { get { return _LeftMargin; } set { _LeftMargin = value; } } private float _TopMargin = 0; public float TopMargin { get { return _TopMargin; } set { _TopMargin = value; } } private SvgScale _MyScale; public SvgScale MyScale { get { if (_MyScale == null) { _MyScale = new SvgScale(72, new System.Drawing.RectangleF(0, 0, _MyContentByte.PdfWriter.PageSize.Width, _MyContentByte.PdfWriter.PageSize.Height), _Width, _Height, _ViewBox); _MyScale.XLowerLimit -= _LeftMargin; _MyScale.YLowerLimit -= _TopMargin; } return _MyScale; } } public void Draw(PdfContentByte cb) { //myPdf.Clear(); _MyContentByte = cb; _Templates = new Dictionary(); //RegisterFonts(); SvgParts.Draw(cb, MyScale, this, this); //72 - Points } public static iTextSharp.text.Font GetFont(string fontName) { // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(fontName); return FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 10); } public static iTextSharp.text.Font GetFont(string fontName, float size, int style, System.Drawing.Color color) { // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(fontName); return FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, size, style, new iTextSharp.text.Color(color)); } //private static string _FontFolder = null; //public static string FontFolder //{ // get // { // if (_FontFolder == null) // { // _FontFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts); // if (_FontFolder == null) _FontFolder = (String)Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Explorer").OpenSubKey("Shell Folders").GetValue("Fontz"); // _MyLog.WarnFormat("FontFolder set to {0}", _FontFolder); // } // return _FontFolder; // } //} private static int _StackTraceSkip = 1; private static DateTime _LastTime = DateTime.Now; private static DateTime _StartTime = DateTime.Now; public static void ResetWhen() { _StartTime = _LastTime = DateTime.Now; } public static void WhenAndWhere() { DateTime thisTime = DateTime.Now; System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(_StackTraceSkip, true); Console.WriteLine("{0:000000},{1:000000},'{2}',{3},'{4}'", TimeSpan.FromTicks(thisTime.Ticks - _StartTime.Ticks).TotalMilliseconds, TimeSpan.FromTicks(thisTime.Ticks - _LastTime.Ticks).TotalMilliseconds, sf.GetMethod().Name, sf.GetFileLineNumber() ,sf.GetFileName()); _LastTime = thisTime; } } public partial class SvgArc : SvgShapePart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { cb.SaveState(); SetupInheritance(myParent.MyInheritedSettings); if (FillColor != System.Drawing.Color.Transparent) cb.SetColorFill(new Color(FillColor)); if (OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty) { cb.SetLineWidth(scale.M(OutlineWidth)); cb.SetColorStroke(new Color(OutlineColor)); } cb.Ellipse(scale.X(CX - Radius), scale.Y(cb, CY - Radius), scale.M(Radius * 2), scale.M(Radius * 2)); SvgITextLibrary.StrokeAndFill(cb, (OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty), (FillColor != System.Drawing.Color.Transparent)); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { tmp.SaveState(); SetupInheritance(myParent.MyInheritedSettings); if (FillColor != System.Drawing.Color.Transparent) tmp.SetColorFill(new Color(FillColor)); if (OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty) { tmp.SetLineWidth(scale.M(OutlineWidth)); tmp.SetColorStroke(new Color(OutlineColor)); } tmp.Ellipse(scale.X(CX - Radius), scale.Y(CY - Radius), scale.M(Radius * 2), scale.M(Radius * 2)); SvgITextLibrary.StrokeAndFill(tmp, (OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty), (FillColor != System.Drawing.Color.Transparent)); tmp.RestoreState(); } } public partial class SvgCircle : SvgShapePart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); cb.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) cb.SetColorFill(new Color(FillColor)); if (stroke) { cb.SetLineWidth(scale.M(OutlineWidth)); cb.SetColorStroke(new Color(OutlineColor)); } float x1 = scale.X(CX - Radius); float y1 = scale.Y(cb, CY - Radius); float x2 = scale.X(CX + Radius); float y2 = scale.Y(cb, CY + Radius); cb.Ellipse(x1, y1, x2, y2); SvgITextLibrary.StrokeAndFill(cb, stroke, fill); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); tmp.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) tmp.SetColorFill(new Color(FillColor)); if (stroke) { tmp.SetLineWidth(scale.M(OutlineWidth)); tmp.SetColorStroke(new Color(OutlineColor)); } tmp.Ellipse(scale.X(CX - Radius), scale.Y(CY - Radius), scale.X(CX + Radius), scale.Y(CY + Radius)); SvgITextLibrary.StrokeAndFill(tmp, stroke, fill); tmp.RestoreState(); Svg.FixBoundingBox(tmp, scale.X(CX - Radius), scale.Y(CY - Radius), scale.X(CX + Radius), scale.Y(CY + Radius)); } } public partial class SvgDefine : SvgGroup { public override void Draw(PdfContentByte cb, SvgScale myScale, Svg mySvg, SvgPartInheritance myParent) { // TODO: Could I try creating a template // Don't draw // SvgParts.Draw(cb, myScale, mySvg, myParent); PdfTemplate tmp = null; if (ID != "") tmp = mySvg.GetTemplate(ID, cb); // the size will be adjusted as items are added. SvgParts.Draw(tmp, myScale, mySvg, myParent); } public override void Draw(PdfTemplate tmp, SvgScale myScale, Svg mySvg, SvgPartInheritance myParent) { // TODO: Could I try creating a template // Don't draw // SvgParts.Draw(cb, myScale, mySvg, myParent); //PdfTemplate tmp2 = mySvg.GetTemplate(ID); // the size will be adjusted as items are added. //SvgParts.Draw(tmp2, myScale, mySvg, myParent); } } public partial class SvgUse : SvgPartInheritance { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static List _MissingMacros = new List(); public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { // TODO: Could I use the template SetupInheritance(myParent.MyInheritedSettings); if (mySvg.LookUp.ContainsKey(_UseID)) mySvg[_UseID].Draw(cb, scale.AdjustOrigin(X, Y), mySvg, this); else { if (!_MissingMacros.Contains(_UseID)) { _MissingMacros.Add(_UseID); _MyLog.WarnFormat("Missing Macro '{0}'", _UseID); } } //cb.AddTemplate(mySvg.GetTemplate(_UseID.Substring(1),cb), scale.X(X), scale.Y(cb, Y)); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { // TODO: Could I use the template SetupInheritance(myParent.MyInheritedSettings); //mySvg[_UseID.Substring(1)].Draw(tmp, scale.AdjustOrigin(X, Y), mySvg, this); mySvg[_UseID].Draw(tmp, scale.AdjustOrigin(X, Y), mySvg, this); } } public partial class SvgEllipse : SvgShapePart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); cb.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) cb.SetColorFill(new Color(FillColor)); if (stroke) { cb.SetLineWidth(scale.M(OutlineWidth)); cb.SetColorStroke(new Color(OutlineColor)); } cb.Ellipse(scale.X(CX - RX), scale.Y(cb, CY - RY), scale.X(CX + RX), scale.Y(cb, CY + RY)); SvgITextLibrary.StrokeAndFill(cb, stroke, fill); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); tmp.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) tmp.SetColorFill(new Color(FillColor)); if (stroke) { tmp.SetLineWidth(scale.M(OutlineWidth)); tmp.SetColorStroke(new Color(OutlineColor)); } tmp.Ellipse(scale.X(CX - RX), scale.Y(CY - RY), scale.X(CX + RX), scale.Y(CY + RY)); SvgITextLibrary.StrokeAndFill(tmp, stroke, fill); tmp.RestoreState(); } } public partial class SvgGroup : SvgPartInheritance { public override void Draw(PdfContentByte cb, SvgScale myScale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); _SvgParts.Draw(cb, myScale, mySvg, this); } public override void Draw(PdfTemplate tmp, SvgScale myScale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); if (ID != "") tmp = mySvg.GetTemplate(ID, mySvg.MyContentByte); // the size will be adjusted as items are added. SvgParts.Draw(tmp, myScale, mySvg, this); } } public partial class SvgImage : SvgPart { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); cb.SaveState(); iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(ImagePath); if (Height.Value != 0) img.ScaleAbsoluteHeight(scale.M(Height)); if (Width.Value != 0) img.ScaleAbsoluteWidth(scale.M(Width)); img.SetAbsolutePosition(scale.X(X), scale.Y(cb, Y) - scale.M(img.ScaledHeight)); // The next three lines set the image opacity for testing //PdfGState gState = new PdfGState(); //gState.FillOpacity = .2f; //cb.SetGState(gState); cb.AddImage(img); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); tmp.SaveState(); try { if (ImagePath != null) { iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(ImagePath); img.ScaleAbsolute(scale.M(Width), scale.M(Height)); img.SetAbsolutePosition(scale.X(X), scale.Y(Y) - scale.M(img.ScaledHeight)); tmp.AddImage(img); } } catch (Exception ex) { //_MyLog.WarnFormat("SvgImage.Draw '{0}' {1} - {2}", ImagePath, ex.GetType().Name, ex.Message); } tmp.RestoreState(); } } public partial class SvgLine : SvgLinePart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); cb.SaveState(); bool stroke = LineColor != System.Drawing.Color.Empty; if (stroke) { cb.SetLineWidth(LineWidth.Value); cb.SetColorStroke(new Color(LineColor)); } cb.SetLineCap(PdfContentByte.LINE_CAP_ROUND); if (myParent is SvgGroup && (myParent as SvgGroup).Description.ToUpper() == "ABSOLUTE") { cb.MoveTo(scale.AbsX(X1), scale.AbsY(cb, Y1)); cb.LineTo(scale.AbsX(X2), scale.AbsY(cb, Y2)); } else { cb.MoveTo(scale.X(X1), scale.Y(cb, Y1)); cb.LineTo(scale.X(X2), scale.Y(cb, Y2)); } cb.Stroke(); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); tmp.SaveState(); bool stroke = LineColor != System.Drawing.Color.Empty; if (stroke) { tmp.SetLineWidth(scale.M(LineWidth)); tmp.SetColorStroke(new Color(LineColor)); } tmp.MoveTo(scale.X(X1), scale.Y(Y1)); tmp.LineTo(scale.X(X2), scale.Y(Y2)); tmp.Stroke(); tmp.RestoreState(); Svg.FixBoundingBox(tmp, scale.X(X1), scale.Y(Y1), scale.X(X2), scale.Y(Y2)); } } public partial class SvgParts : CollectionBase { public void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { foreach (SvgPart svgPart in List) svgPart.Draw(cb, scale, mySvg, myParent); } public void Draw(PdfTemplate tmp, SvgScale myScale, Svg mySvg, SvgPartInheritance myParent) { foreach (SvgPart svgPart in List) svgPart.Draw(tmp, myScale, mySvg, myParent); } } public partial class SvgRectangle : SvgShapePart { public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); cb.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) cb.SetColorFill(new Color(FillColor)); if (stroke) { cb.SetLineWidth(scale.M(OutlineWidth)); cb.SetColorStroke(new Color(OutlineColor)); } if (myParent is SvgGroup && (myParent as SvgGroup).Description.ToUpper() == "ABSOLUTE") cb.RoundRectangle(scale.AbsX(X), scale.AbsY(cb, Y), scale.M(Width), -scale.M(Height), .005F); else cb.RoundRectangle(scale.X(X), scale.Y(cb, Y), scale.M(Width), -scale.M(Height), .005F); SvgITextLibrary.StrokeAndFill(cb, stroke, fill); cb.RestoreState(); } public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { SetupInheritance(myParent.MyInheritedSettings); if (ID != "") tmp = mySvg.GetTemplate(ID, mySvg.MyContentByte); // the size will be adjusted as items are added. tmp.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; if (fill) tmp.SetColorFill(new Color(FillColor)); if (stroke) { tmp.SetLineWidth(scale.M(OutlineWidth)); tmp.SetColorStroke(new Color(OutlineColor)); } tmp.Rectangle(scale.X(X), scale.Y(Y), scale.M(Width), -scale.M(Height)); SvgITextLibrary.StrokeAndFill(tmp, stroke, fill); Svg.FixBoundingBox(tmp, scale.X(X), scale.Y(Y), scale.X(X) + scale.M(Width), scale.Y(Y) - scale.M(Height)); tmp.RestoreState(); } } public partial class SvgText : SvgShapePart { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static string ReplaceSpecialCharacter(Match m) { int i = int.Parse(m.ToString().Substring(2, m.ToString().Length - 3)); char c = (char)i; return c.ToString(); } private static string ReplaceHexCharacter(Match m) { int i = int.Parse(m.ToString().Substring(2, 2), System.Globalization.NumberStyles.HexNumber); char c = (char)i; return c.ToString(); } public int Align { get { switch (Justify) { case SvgJustify.Left: return Element.ALIGN_LEFT; break; case SvgJustify.Center: return Element.ALIGN_CENTER; break; case SvgJustify.Right: return Element.ALIGN_RIGHT; break; } return Element.ALIGN_LEFT; } } 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(); // Draw's using PdfContentByte are for drawing PageList items. public override void Draw(PdfContentByte cb, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { string text = mySvg.OnProcessText(Text, this, scale); if (text == string.Empty) return; // Replace hard hyphen with hyphen when printing pagelist items // this will enable the hyphens to be found in a PDF search if(text.Contains("\\u8209?")) text = text.Replace("\\u8209?", "-"); // Replace symbol backslash with a text backslash when printing pagelist items // this will enable the backslash to be found in a PDF search if (text.Contains("\\u9586?")) text = text.Replace("\\u9586?", "\\"); SetupInheritance(myParent.MyInheritedSettings); float yScale = (myParent is SvgGroup && (myParent as SvgGroup).Description.ToUpper() == "ABSOLUTE") ? scale.AbsY(cb, Y): scale.Y(cb, Y); cb.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; // Strip out inline commands that are overridden by the fontStyle if (Font.Bold) text = StripCommands(text, @"\\b0", @"\\b"); if (Font.Italic) text = StripCommands(text, @"\\i0", @"\\i"); if (Font.Underline) text = StripCommands(text, @"\\ulnone", @"\\ul0", @"\\ul"); float fontSize = scale.M(new SvgMeasurement(Font.SizeInPoints, E_MeasurementUnits.PT)); int fontStyle = (Font.Bold ? iTextSharp.text.Font.BOLD : 0) + (Font.Italic ? iTextSharp.text.Font.ITALIC : 0); // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(Font.Name); iTextSharp.text.Font font = FontFactory.GetFont(Font.Name, BaseFont.IDENTITY_H,BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); Phrase ph = BuildPhrase(text, fontSize, fontStyle, font); ColumnText ct = new ColumnText(cb); float x = (myParent is SvgGroup && (myParent as SvgGroup).Description.ToUpper() == "ABSOLUTE") ? scale.AbsX(X): scale.X(X); float w = 0; // chk.GetWidthPoint(); // Change the chunks to only split on spaces rather than spaces and hyphens foreach (Chunk chk in ph.Chunks) { w += chk.GetWidthPoint(); // Change the chunks to only split on spaces rather than spaces and hyphens if (chk.Attributes == null || !chk.Attributes.ContainsKey("NoSplit")) { if (chk.Attributes == null) chk.Attributes = new Hashtable(); chk.SetSplitCharacter(mySplitter); chk.Attributes.Add("NoSplit", false); } } switch (Justify) { //case SvgJustify.Left: // x = x; // break; case SvgJustify.Center: x-=w/2; break; case SvgJustify.Right: x-=w; break; } float y = yScale; float xRight = x + w; float Offset = 0; if (Font.Underline) { foreach (Chunk chk in ph.Chunks) chk.SetUnderline(new Color(FillColor), 0, 0.047F, 0, -.1373F, PdfContentByte.LINE_CAP_ROUND); } // The following line was changed so that a 6.5 size font would print, i.e. the 2 was changed to a 3 to make the // 6.5 size work. ct.SetSimpleColumn(x, y + ph.Leading + Offset, xRight + 1F, y + ph.Leading + Offset - 3 * font.Size);//2 * font.Size); ct.AddElement(ph); cb.SaveState(); cb.SetColorFill(new Color(FillColor)); ct.Go(); cb.RestoreState(); } // F2021-053: Do replace words for Page List items. Format flags to use for compressing and locating sub/super scripts public static bool CompressSuper = false; public static bool CompressSub = false; public static bool CompressPropSubSup = false; private Phrase BuildPhrase(string text, float fontSize, int fontStyle, iTextSharp.text.Font font) { //if (text == "Caution") //{ // if (iTextSharp.text.FontFactory.IsRegistered("VolianScript")) // Console.WriteLine("Is Registered"); // Console.WriteLine("stop"); //} bool fontUnderline = false; float fontTextRise = 0; text = Regex.Replace(text, @"\\[Uu][0-9]+[?]", new MatchEvaluator(ReplaceSpecialCharacter)); text = Regex.Replace(text, @"\\'[0-9a-fA-F][0-9a-fA-F]", new MatchEvaluator(ReplaceHexCharacter)); text += " "; //if (text.Contains("\\")) -- these 2 lines made \ul and \ulnone in page list text not get resolved and would then print //text = text.Replace("\\", ((char)9586).ToString()); // B2016-155 convert backslash char to the unicode symbol - to allow processing rtf commands \ul, \up, \dn, etc. // B2016-167: handle backslashes but don't do if the backslash is an underline rtf command int stindx = text.IndexOf("\\"); while (stindx != -1) { if ((stindx + 2 < text.Length - 1 && text.ToUpper().IndexOf("UL", stindx + 1) == stindx + 1) || //don't replace it // B2020-041: PSI (this happened for all pagelist items) print doesn't resolve super/sub script, bold, italics: (stindx + 2 < text.Length - 1 && text.ToUpper().IndexOf("UP", stindx + 1) == stindx + 1) || (stindx + 1 < text.Length - 1 && text.ToUpper().IndexOf("B", stindx + 1) == stindx + 1) || (stindx + 2 < text.Length - 1 && text.ToUpper().IndexOf("B0", stindx + 1) == stindx + 1) || (stindx + 2 < text.Length - 1 && text.ToUpper().IndexOf("DN", stindx + 1) == stindx + 1) || (stindx + 1 < text.Length - 1 && text.ToUpper().IndexOf("I", stindx + 1) == stindx + 1) || (stindx + 2 < text.Length - 1 && text.ToUpper().IndexOf("I0", stindx + 1) == stindx + 1)) stindx = text.IndexOf("\\", stindx + 1); else { text = text.Remove(stindx,1); text = text.Insert(stindx, ((char)9586).ToString()); stindx = text.IndexOf("\\",stindx); } } Phrase ph = new Phrase(); while (text.Length > 0) { string next = ""; Match m = Regex.Match(text, @"\\[^ ]*?[ $]"); if (m.Success) { // text is portion of text and next is remaining portion to process next next = text.Substring(m.Index + m.Length); text = text.Substring(0, m.Index); } else if (text[text.Length - 1] == ' ') text = text.Substring(0, text.Length - 1); // B2016-155 convert the backslash symbol back to the backslash character since we look for specific rft commands below foreach (Chunk chk in BuildPartialPhrase(text.Replace(((char)9586).ToString(),"\\"), fontSize, fontStyle, font).Chunks) { if (fontUnderline) chk.SetUnderline(font.Color, 0, 0.05F, 0, -.131F, PdfContentByte.LINE_CAP_ROUND); if (fontTextRise != 0) chk.SetTextRise(fontTextRise * chk.Font.Size); ph.Add(chk); } if (m.Success) { // bold, underline, italics, subscript, superscript if (m.Value.Contains(@"\ulnone") || m.Value.Contains(@"\ul0")) // off fontUnderline = false; else if (m.Value.Contains(@"\ul")) fontUnderline = true; if (m.Value.Contains(@"\up0") || m.Value.Contains(@"\dn0")) { fontTextRise = 0; // B2021-133 need to reset the font size after doing a compressed super or sub script if (CompressSuper || CompressPropSubSup || CompressSub) font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); ; } else if (m.Value.Contains(@"\up")) { fontTextRise = .25F; // F2021-053: Do replace words for Page List items. size and locate superscript if (CompressSuper || CompressPropSubSup) { font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize * .75f, fontStyle, new Color(FillColor)); ; fontTextRise = .33F; } } else if (m.Value.Contains(@"\dn")) { fontTextRise = -.25F; // F2021-053: Do replace words for Page List items. size subscript if (CompressSub || CompressPropSubSup) font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize * .75f, fontStyle, new Color(FillColor)); ; } if (m.Value.Contains(@"\b0")) { fontStyle ^= iTextSharp.text.Font.BOLD; font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); } else if (m.Value.Contains(@"\b")) { fontStyle |= iTextSharp.text.Font.BOLD; font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); } if (m.Value.Contains(@"\i0")) { fontStyle ^= iTextSharp.text.Font.ITALIC; font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); } else if (m.Value.Contains(@"\i")) { fontStyle |= iTextSharp.text.Font.ITALIC; font = FontFactory.GetFont(font.Familyname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor)); } } text = next; } return ph; } private Phrase BuildPartialPhrase(string text, float fontSize, int fontStyle, iTextSharp.text.Font font) { iTextSharp.text.pdf.FontSelector fs = new FontSelector(); fs.AddFont(font); if (font.BaseFont != null && font.BaseFont.GetWidthPoint("m", 12) == font.BaseFont.GetWidthPoint(".", 12)) { // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont("VESymbFix"); fs.AddFont(FontFactory.GetFont("VESymbFix", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor))); } else { // C2017-036 get best available proportional font for symbols // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(Volian.Base.Library.vlnFont.ProportionalSymbolFont); fs.AddFont(FontFactory.GetFont(Volian.Base.Library.vlnFont.ProportionalSymbolFont, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, fontSize, fontStyle, new Color(FillColor))); } Phrase ph = fs.Process(text); return ph; } private string StripCommands(string text, params string [] rtfCommands) { foreach (string rtfCommand in rtfCommands) { // remove rtf command preceeded by another rtf command with previous // rtf ending with a space, i.e. "\ulnone\b0 " removing the "b0", leaves " " // * - as many as there are, ? - minimum number that results in a match text = Regex.Replace(text, @"(\\[^ ]*?)" + rtfCommand + " ", "$1 "); // remove rtf command follwed by a space text = Regex.Replace(text, rtfCommand + " ", ""); // remove just the rtf command text = Regex.Replace(text, rtfCommand, ""); } return text; } // Draw's using PdfTemplate are for drawing SVG (16-bit genmac). public override void Draw(PdfTemplate tmp, SvgScale scale, Svg mySvg, SvgPartInheritance myParent) { string text = mySvg.OnProcessText(Text, this, scale); if (text == string.Empty) return; SetupInheritance(myParent.MyInheritedSettings); float yScale = -scale.Y(Y); tmp.SaveState(); bool fill = FillColor != System.Drawing.Color.Transparent; bool stroke = OutlineWidth.Value != 0F && OutlineColor != System.Drawing.Color.Empty; tmp.BeginText(); if (fill) tmp.SetColorFill(new Color(FillColor)); if (stroke) { tmp.SetLineWidth(scale.M(OutlineWidth)); tmp.SetColorStroke(new Color(OutlineColor)); } iTextSharp.text.Font font = Svg.GetFont(Font.Name); BaseFont baseFont = font.BaseFont; if (baseFont == null) { // B2019-116 Use Volian.Base.Library.VlnItextFont // This is a generic class for dealing with iTextSharp Fonts // Code moved and consolidated from Volian.Print.Library, Volian PDF.Library and VG VlnItextFont.RegisterFont(Font.Name); font = Svg.GetFont(Font.Name); baseFont = font.BaseFont; if(baseFont==null) _MyLog.WarnFormat("Missing Font {0}", Font.Name); } tmp.MoveText(scale.X(X), yScale); tmp.SetFontAndSize(baseFont, scale.M(new SvgMeasurement(Font.SizeInPoints, E_MeasurementUnits.PT))); switch ((stroke ? 1 : 0) + (fill ? 2 : 0)) { case 0: // No Stroke or Fill tmp.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_INVISIBLE); break; case 1: // Stroke tmp.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_STROKE); break; case 2: // Fill tmp.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL); break; case 3: // Stroke and Fill tmp.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE); break; } tmp.ShowTextKerned(text); tmp.EndText(); tmp.RestoreState(); } } public class SvgPageTotal { public SvgPageTotal(System.Drawing.Font myFont, PdfContentByte cb) { _MyFont = myFont; _MyTemplate = cb.CreateTemplate(100, 100); _MyTemplate.BoundingBox= new Rectangle(-20, -20, 100, 100); } private int _PageCount=1; private System.Drawing.Font _MyFont; private PdfTemplate _MyTemplate; public PdfTemplate MyTemplate { get { return _MyTemplate; } } public void Draw() { // Output Page Count _MyTemplate.BeginText(); iTextSharp.text.Font font = Svg.GetFont(_MyFont.Name); BaseFont baseFont = font.BaseFont; _MyTemplate.SetFontAndSize(baseFont,_MyFont.Size); _MyTemplate.SetTextMatrix(0, 0); _MyTemplate.ShowText(_PageCount.ToString()); _MyTemplate.EndText(); } } public class SvgPageHelper : PdfPageEventHelper { private bool _SpecialCAS; // B2023-005: CAS page, rotate watermark public bool SpecialCAS { get { return _SpecialCAS; } set { _SpecialCAS = value; } } private bool _IsLandscape; public bool IsLandscape { get { return _IsLandscape; } set { _IsLandscape = value; } } // B2019-145: added the following property so that the code would know that an adjustment should be made to print the watermark // in landscape mode. Note that 'IsLandscape' could not be used because it also does the pagelist items. private bool _IsWatermarkLandscape; public bool IsWatermarkLandscape { get { return _IsWatermarkLandscape; } set { _IsWatermarkLandscape = value; } } // B2018-124 we no longer need is list was not hanling "Information Only" water mark //private List _AllowedWatermarks = new List(); //public List AllowedWatermarks //{ // get { return _AllowedWatermarks; } // set { _AllowedWatermarks = value; } //} private Svg _MySvg; public Svg MySvg { get { return _MySvg; } set { _MySvg = value; } } private PdfLayer _PageListLayer; public PdfLayer PageListLayer { get { return _PageListLayer; } set { _PageListLayer = value; } } private PdfLayer _WatermarkLayer; public PdfLayer WatermarkLayer { get { return _WatermarkLayer; } set { _WatermarkLayer = value; } } private string _Watermark=string.Empty; public string Watermark { get { return _Watermark; } set { _Watermark = value; } } private string _WatermarkColor = "BLUE"; public string WatermarkColor { get { return _WatermarkColor; } set { _WatermarkColor = value; } } private PdfLayer _PROMSVersionLayer; //C2018-009 print PROMS version public PdfLayer PROMSVersionLayer { get { return _PROMSVersionLayer; } set { _PROMSVersionLayer = value; } } private string _PROMSVersion = string.Empty; public string PROMSVersion { get { return _PROMSVersion; } set { _PROMSVersion = value; } } private bool _DoZoomOMatic = false; public bool DoZoomOMatic { get { return _DoZoomOMatic; } set { _DoZoomOMatic = value; } } private int _CurrentPageNumber = 0; public int CurrentPageNumber { get { return _CurrentPageNumber; } set { _CurrentPageNumber = value; } } private int _CurrentPageNumberNoFoldouts = 0; public int CurrentPageNumberNoFoldouts { get { return _CurrentPageNumberNoFoldouts; } set { _CurrentPageNumberNoFoldouts = value; } } private int _CurrentTOCPageNumber = 0; public int CurrentTOCPageNumber { get { return _CurrentTOCPageNumber; } set { _CurrentTOCPageNumber = value; } } private bool _OnFoldoutPage = false; public bool OnFoldoutPage { get { return _OnFoldoutPage; } set { _OnFoldoutPage = value; } } private bool _CreatingFoldoutPage = false; public bool CreatingFoldoutPage { get { return _CreatingFoldoutPage; } set { _CreatingFoldoutPage = value; } } private bool _CreatingSupInfoPage = false; public bool CreatingSupInfoPage { get { return _CreatingSupInfoPage; } set { _CreatingSupInfoPage = value; } } public SvgPageHelper(Svg mySvg) { _MySvg = mySvg; } public SvgPageHelper() { } private int _BGPageOffset = 0; public int BackgroundPageOffset { get { return _BGPageOffset; } set { _BGPageOffset = value; } } protected virtual string ReplacePageListToken(Match match) { return string.Empty; } public override void OnOpenDocument(PdfWriter writer, Document document) { //base.OnOpenDocument(writer, document); //tmpTotal = writer.DirectContent.CreateTemplate(100, 100); //tmpTotal.BoundingBox = new Rectangle(-20, -20, 100, 100); //PdfContentByte cb = writer.DirectContent; } public override void OnEndPage(PdfWriter writer, Document document) { if (!OnFoldoutPage) { base.OnEndPage(writer, document); // note that pagelist items are not done for Foldout & SupInfo (facing pages) - they get merged onto pages that have this if (!CreatingFoldoutPage && !CreatingSupInfoPage) { DrawBackground(writer.DirectContentUnder); DrawPageList(writer.DirectContent); DrawWatermark(writer.DirectContent); DrawPROMSVersion(writer.DirectContent); //C2018-009 print PROMS version if (DoZoomOMatic) DrawZoomOMatic(writer.DirectContent); } CurrentPageNumber++; CurrentPageNumberNoFoldouts++; } else { // note that pagelist items are not done for Foldout & SupInfo (facing pages) - they get merged onto pages that have this if (!CreatingFoldoutPage && !CreatingSupInfoPage) { DrawBackground(writer.DirectContentUnder); DrawPageList(writer.DirectContent); DrawWatermark(writer.DirectContent); DrawPROMSVersion(writer.DirectContent); //C2018-009 print PROMS version if (DoZoomOMatic) DrawZoomOMatic(writer.DirectContent); CurrentPageNumber++; } } } private PdfReader _BackgroundReader = null; public PdfReader BackgroundReader { get { if (_BackgroundReader == null && _BackgroundFile != null && File.Exists(_BackgroundFile)) _BackgroundReader = new PdfReader(_BackgroundFile); return _BackgroundReader; } } public bool Back32BitPROMS { get { if (BackgroundReader == null) return false; return BackgroundReader.Info["Producer"].ToString().StartsWith("iTextSharp"); } } private string _BackgroundFile = null; public string BackgroundFile { get { return _BackgroundFile; } set { _BackgroundFile = value; } } private PdfLayer _BackgroundLayer = null; public PdfLayer BackgroundLayer { get { return _BackgroundLayer; } set { _BackgroundLayer = value; } } private System.Drawing.PointF _BackgroundOffset = new System.Drawing.PointF(0, 0); public System.Drawing.PointF BackgroundOffset { get { return _BackgroundOffset; } set { _BackgroundOffset = value; } } public int BackgroundPageCount { get { return BackgroundReader == null ? 0 : BackgroundReader.NumberOfPages; } } private PdfImportedPage GetBackgroundPage(PdfContentByte cb) { if (BackgroundReader == null) return null; int page = cb.PdfWriter.CurrentPageNumber + BackgroundPageOffset; if (page < 1 || page > BackgroundPageCount) return null; return cb.PdfWriter.GetImportedPage(BackgroundReader, page); } private void DrawBackground(PdfContentByte cb) { PdfImportedPage backgroundPage = GetBackgroundPage(cb); if (backgroundPage == null) return; if(BackgroundLayer != null) cb.BeginLayer(BackgroundLayer); iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(backgroundPage); image.SetAbsolutePosition(BackgroundOffset.X,BackgroundOffset.Y); cb.AddImage(image); if (BackgroundLayer != null) cb.EndLayer(); } private void DrawZoomOMatic(PdfContentByte cb) { cb.SaveState(); ZoomOMatic(cb, 36); cb.RestoreState(); } private bool _AllowAllWatermarks = false; public bool AllowAllWatermarks { get { return _AllowAllWatermarks; } set { _AllowAllWatermarks = value; } } //C2022-004 This will return the system drawing color from either the color name or ARGB values public System.Drawing.Color GetWatermarkColor(string colorDescription) { System.Drawing.Color systemColor; if (colorDescription.StartsWith("[A=")) // if color is ARGB representation, parse out the values { // initialize the ARGB value to white int Alpha = 255; int Red = 255; int Green = 255; int Blue = 255; // The color is formatted as ARGB in a string (i.e. "[A=255, R=157, G=187, B=97]") in the format file string argbColor = colorDescription.Replace("[", "").Replace("]", "").Replace(" ", ""); // remove starting and ending square brackets // split the string on the commas and find each ARGB value string[] argbSplit = argbColor.Split(','); foreach (string s in argbSplit) { if (s[0] == 'A') Alpha = Convert.ToInt32(s.Substring(2)); else if (s[0] == 'R') Red = Convert.ToInt32(s.Substring(2)); else if (s[0] == 'G') Green = Convert.ToInt32(s.Substring(2)); else if (s[0] == 'B') Blue = Convert.ToInt32(s.Substring(2)); } systemColor = System.Drawing.Color.FromArgb(Alpha, Red, Green, Blue); } else systemColor = System.Drawing.Color.FromName(colorDescription); // get from color name that was passed in return systemColor; } private void DrawWatermark(PdfContentByte cb) { if (Watermark == null || Watermark.ToLower().Contains("none") || Watermark == "") return; //if (!AllowAllWatermarks && !AllowedWatermarks.Contains(Watermark)) return; -- B2018-124 not needed anymore with above if statement - this does not hanle "Information Only" cb.SaveState(); if (_WatermarkLayer != null) cb.BeginLayer(_WatermarkLayer); // B2023-005: Beaver Valley, second page of CAS page is a 'foldout' on large paper - need to rotate the // watermark if (SpecialCAS) { double a = -180 * (Math.PI / 180); System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix((float)Math.Cos(a), (float)Math.Sin(a), (float)-Math.Sin(a), (float)Math.Cos(a), cb.PdfDocument.PageSize.Width, cb.PdfDocument.PageSize.Height); cb.Transform(myMatrix); } else if (IsLandscape || IsWatermarkLandscape) // B2019-145: Added for printing landscape watermark on step section pages. { // The watermark needs to be rotated back for landscape pagelist - B2016-191 //double a = -33 * (Math.PI / 180); //System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix((float)Math.Cos(a), (float)Math.Sin(a), (float)-Math.Sin(a), (float)Math.Cos(a), -60, 320); double a = -90 * (Math.PI / 180); System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix((float)Math.Cos(a), (float)Math.Sin(a), (float)-Math.Sin(a), (float)Math.Cos(a), 0, cb.PdfDocument.PageSize.Height); cb.Transform(myMatrix); } SvgWatermark myWatermark = new SvgWatermark(cb, Watermark, GetWatermarkColor(WatermarkColor), .15F); //myWatermark.SetSquareDotPattern(.7F); myWatermark.Draw(); if (_WatermarkLayer != null) cb.EndLayer(); cb.RestoreState(); } //C2018-009 print PROMS version private void DrawPROMSVersion(PdfContentByte cb) { cb.SaveState(); string text = PROMSVersion; float textBase =cb.PdfDocument.Top + 19; float textLeft = cb.PdfDocument.Right - 15; if (_PROMSVersionLayer != null) cb.BeginLayer(_PROMSVersionLayer); cb.BeginText(); cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED), 6f); cb.SetTextMatrix(textLeft, textBase); cb.SetColorFill(new iTextSharp.text.Color(System.Drawing.Color.Indigo)); cb.ShowText(text); cb.EndText(); if (_PROMSVersionLayer != null) cb.EndLayer(); cb.RestoreState(); } private void DrawPageList(PdfContentByte cb) { if (_MySvg != null) { cb.SaveState(); if (_PageListLayer != null) cb.BeginLayer(_PageListLayer); // Do anything needed to finish off the page //System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(); //myMatrix.Rotate(90); // Rotate the Pagelist items by 90 Degrees. //// Translate by the Height of the page. //myMatrix.Translate(cb.PdfDocument.PageSize.Height, 0, System.Drawing.Drawing2D.MatrixOrder.Append); //// This was for fun //// myMatrix.Scale(.75F, .75F, System.Drawing.Drawing2D.MatrixOrder.Append); //cb.Transform(myMatrix); //// You can look at the value of the Matrix at this point, to create the matrix directly like I did below //OR // Rotate 90 Degrees and Translate by the Height of the Page if (IsLandscape) { System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(0, 1, -1, 0, cb.PdfDocument.PageSize.Height, 0); cb.Transform(myMatrix); } _MySvg.Draw(cb); if (_PageListLayer != null) cb.EndLayer(); cb.RestoreState(); } } private void ZoomOMatic(PdfContentByte cb, float size) { for (float xx = 0; xx < cb.PdfDocument.PageSize.Width; xx += size) { for (float yy = 0; yy < cb.PdfDocument.PageSize.Height; yy += size) { PdfDestination dest = new PdfDestination(PdfDestination.FITR, xx - 1.5F * size, yy - 1.5F * size, xx + 1.5F * size, yy + 1.5F * size); cb.SetAction(PdfAction.GotoLocalPage(cb.PdfWriter.CurrentPageNumber, dest, cb.PdfWriter), xx - size, yy - size, xx + size, yy + size); } } } public override void OnStartPage(PdfWriter writer, Document document) { //base.OnStartPage(writer, document); } public override void OnCloseDocument(PdfWriter writer, Document document) { // Build Templates for Page Count } } public class SvgWatermark { private PdfContentByte _ContentByte; private string _Text; private System.Drawing.Color _Color; private PdfPatternPainter _PatternPainter; private BaseFont _Basefont; private float _Fontsize; private float _XOffset; private float _YOffset; private float _TextAngle; private float _Opacity; public SvgWatermark(PdfContentByte contentByte, string text, System.Drawing.Color color, float opacity) { _ContentByte = contentByte; _Text = text; //float radius = .5F; //float space = 3; // B2021-081: Blue was too intense with an alpha of 255 Read was too light with an alpha of 96 if (color != System.Drawing.Color.Red) _Color = System.Drawing.Color.FromArgb(96, color); else _Color = color; // C2021-019: save color for color override _Opacity = opacity; //SetDotPattern(radius, space); //SetTextLayout(); } #region commentedout //private void SetTextLayout() //{ // Rectangle pageSize = _ContentByte.PdfWriter.PageSize; // Get page size // _Basefont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, BaseFont.EMBEDDED); // float hgtA = _Basefont.GetAscentPoint(_Text, 12); // //float hgtD = basefont.GetDescentPoint(text,20); // float wid = _Basefont.GetWidthPointKerned(_Text, 12); // //Console.WriteLine("{0} {1} {2}",hgtA,hgtD,wid); // float rho = wid / hgtA; // float x2 = (rho * pageSize.Height - pageSize.Width) / (rho * rho - 1); // float y1 = x2 * rho; // float y2 = pageSize.Height - y1; // float x1 = pageSize.Width - x2; // _XOffset = x2 + x1 / 2; // _YOffset = y1 / 2; // _TextAngle = CalcAngle(y1, x1); // _Fontsize = (float)(10 * Math.Sqrt(x2 * x2 + y2 * y2) / hgtA); //} //public void SetDotPattern(float radius, float space) //{ // _PatternPainter = _ContentByte.CreatePattern(radius * 2, radius * 2, radius * 2 + space, radius * 2 + space); // PdfGState gState = new PdfGState(); // gState.FillOpacity = _Opacity; // _PatternPainter.SetGState(gState); // _PatternPainter.SetColorFill(_Color); // _PatternPainter.Circle(radius, radius, radius); // _PatternPainter.Fill(); //} //public void SetSquareDotPattern(float radius) //{ // _PatternPainter = _ContentByte.CreatePattern(radius * 4, radius * 2, radius * 4, radius * 2); // PdfGState gState = new PdfGState(); // gState.FillOpacity = .5f * _Opacity; // _PatternPainter.SetGState(gState); // _PatternPainter.SetColorFill(_Color); // _PatternPainter.Rectangle(0, 0, radius, radius); // _PatternPainter.Rectangle(radius * 2, radius, radius, radius); // _PatternPainter.Fill(); //} //public void SetHashPattern(float thickness, float size) //{ // _PatternPainter = _ContentByte.CreatePattern(size, size, size, size); // PdfGState gState = new PdfGState(); // gState.FillOpacity = _Opacity; // gState.StrokeOpacity = _Opacity; // _PatternPainter.SetGState(gState); // _PatternPainter.SetLineWidth(.01F); // _PatternPainter.SetColorStroke(_Color); // Set color // _PatternPainter.MoveTo(0, 0); // _PatternPainter.LineTo(size, size); // _PatternPainter.MoveTo(size, 0); // _PatternPainter.LineTo(0, size); // _PatternPainter.Stroke(); //} //public void SetTextPattern(float fontSize, float space) //{ // float hgtA = _Basefont.GetAscentPoint(_Text, fontSize) + _Basefont.GetDescentPoint(_Text, fontSize); // float wid = _Basefont.GetWidthPointKerned(_Text, fontSize); // _PatternPainter = _ContentByte.CreatePattern(wid, hgtA, wid + space, hgtA + space); // _PatternPainter.SetFontAndSize(_Basefont, fontSize); // _PatternPainter.BoundingBox = new Rectangle(-20, -20, 100, 100); // _PatternPainter.BeginText(); // PdfGState gs1 = new PdfGState(); // gs1.FillOpacity = _Opacity; // _PatternPainter.SetGState(gs1); // _PatternPainter.SetColorFill(_Color); // Set color // _PatternPainter.ShowText(_Text); // _PatternPainter.EndText(); //} //public void SetTextPattern2(float fontSize) //{ // BaseFont _Basefont2 = BaseFont.CreateFont(BaseFont.HELVETICA, Encoding.ASCII.EncodingName, BaseFont.EMBEDDED); // float hgtA = _Basefont2.GetAscentPoint(_Text, fontSize); // float wid = _Basefont2.GetWidthPointKerned(_Text, fontSize); // _PatternPainter = _ContentByte.CreatePattern(wid * 2, hgtA * 2, wid * 2, hgtA * 2); // _PatternPainter.SetFontAndSize(_Basefont2, fontSize); // _PatternPainter.BoundingBox = new Rectangle(-20, -20, 100, 100); // _PatternPainter.BeginText(); // PdfGState gs1 = new PdfGState(); // gs1.FillOpacity = _Opacity; // _PatternPainter.SetGState(gs1); // _PatternPainter.SetColorFill(_Color); // Set color // _PatternPainter.ShowText(_Text); // _PatternPainter.ShowTextAligned(PdfContentByte.ALIGN_LEFT, _Text, wid, hgtA, 0); // _PatternPainter.EndText(); //} #endregion public void Draw() { _ContentByte.SaveState(); //_ContentByte.BeginText(); //_ContentByte.SetPatternFill(_PatternPainter); //_ContentByte.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE); //_ContentByte.SetLineWidth(.5F); //_ContentByte.SetFontAndSize(_Basefont, _Fontsize);// Set font and size //_ContentByte.SetColorStroke(_Color); //PdfGState gs2 = new PdfGState(); //gs2.StrokeOpacity = _Opacity; //_ContentByte.SetGState(gs2); //_ContentByte.ShowTextAlignedKerned(PdfContentByte.ALIGN_CENTER, _Text, _XOffset, _YOffset, _TextAngle);// Draw the text //_ContentByte.EndText(); _ContentByte.AddImage(WatermarkImage); _ContentByte.RestoreState(); } //private float CalcAngle(float opposite, float adjacent) //{ // return (float)(Math.Atan2(opposite, adjacent) * (180 / Math.PI)); //} private Image _WatermarkImage; public Image WatermarkImage { get { if (_WatermarkImage == null) { float fntSize = 200; System.Drawing.Font fnt = new System.Drawing.Font("Arial", fntSize); string msg = _Text; System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath(); gp.AddString(msg, fnt.FontFamily, 0, fntSize, new System.Drawing.Point(0, 0), System.Drawing.StringFormat.GenericTypographic); System.Drawing.RectangleF bnds = gp.GetBounds(); gp.Reset(); int height = (int)bnds.Height; int width = (int)bnds.Width; System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width + 2, height + 2); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp)) { g.FillRectangle(System.Drawing.Brushes.Transparent, 0, 0, width, height); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gp.AddString(msg, fnt.FontFamily, 0, fntSize, new System.Drawing.PointF(-bnds.X, -bnds.Y), System.Drawing.StringFormat.GenericTypographic); // C2021-019: allow setting of watermark color System.Drawing.Drawing2D.HatchBrush aHatchBrush = new System.Drawing.Drawing2D.HatchBrush(System.Drawing.Drawing2D.HatchStyle.Percent25, _Color, System.Drawing.Color.Transparent); g.FillPath(aHatchBrush, gp); g.DrawPath(new System.Drawing.Pen(_Color), gp); //g.DrawRectangle(System.Drawing.Pens.Cyan, 0, 0, bnds.Width, bnds.Height); } _WatermarkImage = iTextSharp.text.Image.GetInstance(bmp, System.Drawing.Imaging.ImageFormat.Png); _WatermarkImage.SetAbsolutePosition(72, 72); float H = _ContentByte.PdfWriter.PageSize.Height - 144; float W = _ContentByte.PdfWriter.PageSize.Width - 144; float ratio = bnds.Width / bnds.Height; float W2 = (H - W / ratio) / (ratio - 1 / ratio); float W1 = W - W2; float H1 = (float)(Math.Sqrt(-4 * (W1 * W2) + H * H) + H) / 2; float H2 = H - H1; float Theta = (float)Math.Atan(H1 / W1); float h = H2 / (float)Math.Cos(Theta); float w = H1 / (float)Math.Sin(Theta); // C2022-004 if the watermark is only one character, don't rotate and scale if (msg.Length > 2) { _WatermarkImage.Rotation = Theta; // 3.141592653F / 4; _WatermarkImage.ScaleAbsolute(w, h); } else _WatermarkImage.ScaleAbsolute(W, H);// C2022-004 if the watermark is only one character, scale with respect to page size } return _WatermarkImage; } } } public enum SvgWatermarkFill { Dots = 1, Text1 = 2, Text2 = 3, Hash = 4 } }