Skip to content

Instantly share code, notes, and snippets.

@bjoerntx
Created December 19, 2023 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bjoerntx/a2441d1e21adab0b276990ebbd295353 to your computer and use it in GitHub Desktop.
Save bjoerntx/a2441d1e21adab0b276990ebbd295353 to your computer and use it in GitHub Desktop.
using System;
using System.Drawing;
using System.IO;
using System.Text;
using System.Xml;
using TXTextControl;
public static class SignatureBoxManager
{
public static string AddSignatureBox(TextControl textControl, Size size, int page, SignatureLocation signatureLocation, SignerData signerData, SignatureStyle signatureStyle)
{
SignatureField field = new SignatureField(size, "sign1", 1);
field.SignerData = signerData;
var pageBounds = textControl.GetPages()[1].TextBounds;
var frameLocation = GetFrameLocation(signatureLocation, size, pageBounds);
textControl.SignatureFields.Add(field, 1, frameLocation, FrameInsertionMode.AboveTheText);
var stamp = Encoding.ASCII.GetBytes(GetSvgFromImage(size, signatureStyle.SvgImage, signerData, DateTime.Now.ToString(signatureStyle.DateFormat), signatureStyle));
using (MemoryStream ms = new MemoryStream(stamp, 0, stamp.Length, writable: false, publiclyVisible: true))
{
field.Image = new SignatureImage(ms);
}
return field.Name;
}
private static Point GetFrameLocation(SignatureLocation location, Size size, Rectangle pageBounds)
{
switch (location)
{
case SignatureLocation.TopRight:
return new Point(pageBounds.Right - size.Width, pageBounds.Top - 1440);
case SignatureLocation.BottomLeft:
return new Point(pageBounds.Left, pageBounds.Bottom - size.Height);
case SignatureLocation.BottomRight:
return new Point(pageBounds.Right - size.Width, pageBounds.Bottom - size.Height);
default:
return new Point(pageBounds.Left, pageBounds.Top - 1440);
}
}
private static string GetSvgFromImage(Size size, string svgImage, SignerData signerData, string date, SignatureStyle style)
{
var sizeInPixels = new Size(size.Width / 15, size.Height / 15);
var imageWidth = sizeInPixels.Width / 2;
var fontSize = sizeInPixels.Width / 20;
var signature = new Signature(svgImage, sizeInPixels);
var svg = new StringBuilder();
svg.Append("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"");
svg.Append(sizeInPixels.Width);
svg.Append("\" height=\"");
svg.Append(sizeInPixels.Height);
svg.Append("\">");
svg.Append("<g transform=\"scale(" + signature.ScalingFactor / 2 + ") translate(0 0)\"");
svg.Append(">");
svg.Append(svgImage);
svg.Append("</g>");
var textPositions = new[] { fontSize, fontSize * 2, fontSize * 3, fontSize * 4 };
foreach (var position in textPositions)
{
svg.Append($"<text x=\"{sizeInPixels.Width / 2}\" y=\"{position}\" font-family=\"{style.DetailsFont.FontFamily.Name}\" font-size=\"{fontSize}\" fill=\"red\">");
if (position == fontSize)
svg.Append("Digitally signed by");
else if (position == fontSize * 2)
svg.Append(signerData.Name);
else if (position == fontSize * 3)
svg.Append(signerData.Address);
else if (position == fontSize * 4)
svg.Append(date);
svg.Append("</text>");
}
svg.Append("</svg>");
return svg.ToString();
}
}
public enum SignatureLocation
{
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
public class SignatureStyle
{
public SignatureStyle() { }
public string SvgImage { get; set; }
public bool ShowDate { get; set; } = true;
public bool ShowLocation { get; set; } = true;
public string DateFormat { get; set; } = "MM/dd/yyyy";
public Font DetailsFont { get; set; } = new Font("Arial", 12);
}
internal class Signature
{
private Size m_size;
private Size m_distinationSize;
private string m_signatureSVG;
private float m_scalingFactor = 1.0f;
public Signature(string signatureSVG, Size destinationSize)
{
m_signatureSVG = signatureSVG;
m_distinationSize = destinationSize;
m_size = GetSignatureSize();
m_scalingFactor = CalculateScaling();
}
public Size Size { get { return m_size; } }
public float ScalingFactor { get { return m_scalingFactor; } }
private Size GetSignatureSize()
{
XmlDocument input = new XmlDocument();
input.LoadXml(m_signatureSVG);
XmlNodeList childNodes = input.GetElementsByTagName("svg");
// find width or viewbox
if (childNodes[0].Attributes["width"] != null)
{
return new Size(
int.Parse(childNodes[0].Attributes["width"].Value),
int.Parse(childNodes[0].Attributes["height"].Value));
}
else if (childNodes[0].Attributes["viewBox"] != null)
{
var viewBox = childNodes[0].Attributes["viewBox"].Value.Split(' ');
return new Size(
int.Parse(viewBox[2]),
int.Parse(viewBox[3]));
}
return new Size(100, 100);
}
private float CalculateScaling()
{
float scalingFactor = 1;
if (m_size.Width > m_distinationSize.Width)
{
scalingFactor = (float)m_distinationSize.Width / (float)m_size.Width;
}
return scalingFactor;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment