public static void SignPDFSynfusion(SignatureInfo signInfo, byte[] inDocByte, Cert objCert, string customSignatureDetails, out byte[] outDocPdf)
{
// Dimensions and positions for the signature field
double signatureFieldWidth; // Width of the signature field
double signatureFieldHeight;
double signaturePositionLeft;
double signaturePositionTop;
// Getting TimeStamp Details from Database..
TimeStampSettings objTimeStampSettings = new TimeStampSettings();
TimeStampInfo objTimeStampInfo = (TimeStampInfo)objTimeStampSettings.GetTimeStamp();
PfxSettings objPfxSettings = new PfxSettings();
// Params to take account in the input
bool displaySignature = Convert.ToBoolean(HttpContext.Current.Session["showSign"]);
bool needTimeStamp = false;
string TsaServerUrl = "";
string TsaServerUser = "";
string TsaServerPassword = "";
string strPasswrd = string.Empty;
double imageWidth = 0;
if (objTimeStampInfo != null)
{
needTimeStamp = (bool)objTimeStampInfo.TimeStampNeeded;
TsaServerUrl = objTimeStampInfo.TimeStampUrl;
if ((bool)objTimeStampInfo.AuthNeeded)
{
TsaServerUser = objTimeStampInfo.UserName;
strPasswrd = SecurQueryString.decryptQueryString(objTimeStampInfo.Password);
TsaServerPassword = strPasswrd;
}
}
// Load the certificate
X509Certificate2 certificate = new X509Certificate2(objCert.CertArray, objCert.Password);
// Create a SignatureField and assign the digital signature to it
SignatureField pdfSignature = new SignatureField("SignatureField");
pdfSignature.Signature = new Telerik.Windows.Documents.Fixed.Model.DigitalSignatures.Signature(certificate);
// Set signature details
string strNotAvailable = HttpContext.GetGlobalResourceObject("GlobalResources", "lblNotAvlbl").ToString();
pdfSignature.Signature.Properties.Reason = strNotAvailable;
pdfSignature.Signature.Properties.ContactInfo = strNotAvailable;
pdfSignature.Signature.Properties.Location = strNotAvailable;
// Create a new form to place the signature field
Form pdfForm = new Form();
pdfForm.FormSource = new FormSource();
// Load the existing PDF from the byte array using PdfFormatProvider
using (MemoryStream inputStream = new MemoryStream(inDocByte))
{
// Create PdfFormatProvider and load the existing document
PdfFormatProvider provider = new PdfFormatProvider();
RadFixedDocument document = provider.Import(inputStream);
int pageNo = (signInfo.DigitalSignPage() == 0 ? 1 : document.Pages.Count);
try
{
if (needTimeStamp)
{
//.TimeStampServer = new TimeStampServer(new Uri(TsaServerUrl), TsaServerUser, TsaServerPassword);
}
}
catch (Exception ex)
{ }
// Path to the image (ensure this is correct)
System.Drawing.Image signatureImage = null;
if (signInfo.DigitalSignMode() == 2 && HttpContext.Current.Session["imagesyncfusion"] != null)
{
signatureImage = (System.Drawing.Image)HttpContext.Current.Session["imagesyncfusion"];
}
//var signatureImage = (System.Drawing.Image)HttpContext.Current.Session["imagesyncfusion"];
if (signInfo.UseDigitalSign())
{
if ((signInfo.DigitalSignMode() == 1) || (signInfo.DigitalSignMode() == 2))
{
signaturePositionLeft = (double)signInfo.DigitalSignLeftInPoints();
signaturePositionTop = (double)signInfo.DigitalSignTopInPoints();
signatureFieldWidth = (double)signInfo.DigitalSignWidthInPoints();
signatureFieldHeight = (double)signInfo.DigitalSignHeightInPoints();
RadFixedPage radFixedPage = document.Pages[pageNo - 1];
if (!string.IsNullOrEmpty(customSignatureDetails))
{
//Movable case:
signatureFieldWidth = signaturePositionLeft + (double)signInfo.DigitalSignWidthInPoints();
signatureFieldHeight = signaturePositionTop + (double)signInfo.DigitalSignHeightInPoints();
string[] separator = new string[] { "!_!" };
string[] offsetArray = customSignatureDetails.Split(separator, StringSplitOptions.RemoveEmptyEntries);
if (offsetArray.Length >= 9)
{
float offsetLeft = returnFloatWithCultureValue(offsetArray[0]);
float offsetTop = returnFloatWithCultureValue(offsetArray[1]);
float docHeight = returnFloatWithCultureValue(offsetArray[2]);
float greenDivHeight = returnFloatWithCultureValue(offsetArray[3]);
float greenDivWidth = returnFloatWithCultureValue(offsetArray[4]);
float dpi_x = returnFloatWithCultureValue(offsetArray[6]);
float dpi_y = returnFloatWithCultureValue(offsetArray[7]);
pageNo = int.Parse(offsetArray[8]);
// Calculate positions for drawing the text div;
signaturePositionLeft = (offsetLeft / dpi_x) * 72;
signaturePositionTop = (offsetTop / dpi_y) * 72;
signatureFieldWidth = (greenDivWidth / dpi_y) * 72;
signatureFieldHeight = (greenDivHeight / dpi_x) * 72;
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
}
else
{
//Non-movable case:
radFixedPage = document.Pages[pageNo - 1];
Tuple<double, double> k = null;
if (signatureImage != null)
{
k = calculateAspectRatioFit(signatureImage.Width, signatureImage.Height, signatureFieldWidth, signatureFieldHeight);
signatureFieldWidth = k.Item1;
signatureFieldHeight = k.Item2;
}
signaturePositionLeft = radFixedPage.Size.Height - (double)(signatureFieldWidth + signatureFieldHeight + 1);
signaturePositionTop = signaturePositionTop + 1; // +1 For border size
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
FixedContentEditor editor = new FixedContentEditor(pdfForm.FormSource);
// Drawing the image at the starting position (left side of the signature field)
imageWidth = signatureFieldWidth / 2; // Half the width for the image
double imageHeight = signatureFieldHeight; // Use full height of the signature field
if (signatureImage == null)
{
}
else
{
// Create a memory stream to hold the image
using (MemoryStream ms = new MemoryStream())
{
// Save the image to the memory stream
signatureImage.Save(ms, signatureImage.RawFormat);
// Reset the stream position to the beginning
ms.Position = 0;
// Pass the memory stream to the DrawImage method
editor.DrawImage(ms, new Telerik.Documents.Primitives.Size(imageWidth, imageHeight));
}
}
string textToDraw = $"Digitally signed by {certificate.FriendlyName} \nDate: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss zzz")} \nReason: {pdfSignature.Signature.Properties.Reason} \nLocation: {pdfSignature.Signature.Properties.Location}";
// Set the width of the text area (remaining space after the image)
double textWidth = signatureFieldWidth - imageWidth;
double dsd = CalculateFontSize(textWidth, signatureFieldHeight, textToDraw);
// Now, draw the text next to the image (on the right side), within the remaining space
Telerik.Windows.Documents.Fixed.Model.Editing.Block textBlock = new Telerik.Windows.Documents.Fixed.Model.Editing.Block();
double textPositionLeft = signaturePositionLeft + imageWidth; // Adding a 5px gap after the image
textBlock.TextProperties.FontSize = 8;
textBlock.InsertText($"Digitally signed by {certificate.FriendlyName}");
textBlock.InsertText($" Date: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss zzz")}");
textBlock.InsertText($" Reason: {pdfSignature.Signature.Properties.Reason}");
textBlock.InsertText($" Location: {pdfSignature.Signature.Properties.Location}");
Rect boundingRect = new Rect(textPositionLeft - 8, signaturePositionTop - 12, textWidth, signatureFieldHeight);
textBlock.Draw(editor, boundingRect);
// Create the SignatureWidget and position it on the PDF page
SignatureWidget signatureWidget = pdfSignature.Widgets.AddWidget();
signatureWidget.Content.NormalContentSource = pdfForm.FormSource;
signatureWidget.Rect = new Rect(signaturePositionLeft, signaturePositionTop, signatureFieldWidth, signatureFieldHeight);
signatureWidget.RecalculateContent();
// Add content from the form to the page at the specified position
RadFixedPage pdfPage = document.Pages[0]; // Assuming you're adding it to the first page
FixedContentEditor pageEditor = new FixedContentEditor(pdfPage);
pageEditor.Position.Translate(signaturePositionLeft, signaturePositionTop);
pageEditor.DrawForm(pdfForm.FormSource);
// Add the signature field to the document's AcroForm
document.AcroForm.FormFields.Add(pdfSignature);
}
}
// Use MemoryStream to capture the PDF output and return as a byte array
using (MemoryStream memoryStream = new MemoryStream())
{
// Export the document to the memory stream as a PDF
Telerik.Documents.ImageUtils.ImagePropertiesResolver defaultImagePropertiesResolver = new Telerik.Documents.ImageUtils.ImagePropertiesResolver();
Telerik.Windows.Documents.Extensibility.FixedExtensibilityManager.ImagePropertiesResolver = defaultImagePropertiesResolver;
var settings = new PdfExportSettings();
settings.ImageQuality = ImageQuality.High;
provider.ExportSettings = settings;
provider.Export(document, memoryStream);
// Return the byte array of the PDF
outDocPdf = memoryStream.ToArray();
//return memoryStream.ToArray(); // Return the byte array of the signed PDF
}
}
}
private static double CalculateFontSize(double textWidth, double signatureFieldHeight, string text)
{
// Start with a base font size for better precision
double baseFontSize = 12.0; // Starting font size
// Calculate width scale factor to adjust the font size based on text length
double widthScaleFactor = textWidth / text.Length;
double widthFontSize = baseFontSize * widthScaleFactor;
// Calculate height scale factor to adjust the font size based on the number of lines
int numLines = text.Split('\n').Length;
double heightScaleFactor = signatureFieldHeight / (numLines * baseFontSize);
double heightFontSize = baseFontSize * heightScaleFactor;
// Return the smaller font size to fit both dimensions
return Math.Min(widthFontSize, heightFontSize);
}
public static Tuple<double, double> calculateAspectRatioFit(double srcWidth, double srcHeight, double maxWidth, double maxHeight)
{
var ratio = Math.Min(maxWidth / srcWidth, maxHeight / srcHeight);
return new Tuple<double, double>(srcWidth * ratio, srcHeight * ratio);
}
{
// Dimensions and positions for the signature field
double signatureFieldWidth; // Width of the signature field
double signatureFieldHeight;
double signaturePositionLeft;
double signaturePositionTop;
// Getting TimeStamp Details from Database..
TimeStampSettings objTimeStampSettings = new TimeStampSettings();
TimeStampInfo objTimeStampInfo = (TimeStampInfo)objTimeStampSettings.GetTimeStamp();
PfxSettings objPfxSettings = new PfxSettings();
// Params to take account in the input
bool displaySignature = Convert.ToBoolean(HttpContext.Current.Session["showSign"]);
bool needTimeStamp = false;
string TsaServerUrl = "";
string TsaServerUser = "";
string TsaServerPassword = "";
string strPasswrd = string.Empty;
double imageWidth = 0;
if (objTimeStampInfo != null)
{
needTimeStamp = (bool)objTimeStampInfo.TimeStampNeeded;
TsaServerUrl = objTimeStampInfo.TimeStampUrl;
if ((bool)objTimeStampInfo.AuthNeeded)
{
TsaServerUser = objTimeStampInfo.UserName;
strPasswrd = SecurQueryString.decryptQueryString(objTimeStampInfo.Password);
TsaServerPassword = strPasswrd;
}
}
// Load the certificate
X509Certificate2 certificate = new X509Certificate2(objCert.CertArray, objCert.Password);
// Create a SignatureField and assign the digital signature to it
SignatureField pdfSignature = new SignatureField("SignatureField");
pdfSignature.Signature = new Telerik.Windows.Documents.Fixed.Model.DigitalSignatures.Signature(certificate);
// Set signature details
string strNotAvailable = HttpContext.GetGlobalResourceObject("GlobalResources", "lblNotAvlbl").ToString();
pdfSignature.Signature.Properties.Reason = strNotAvailable;
pdfSignature.Signature.Properties.ContactInfo = strNotAvailable;
pdfSignature.Signature.Properties.Location = strNotAvailable;
// Create a new form to place the signature field
Form pdfForm = new Form();
pdfForm.FormSource = new FormSource();
// Load the existing PDF from the byte array using PdfFormatProvider
using (MemoryStream inputStream = new MemoryStream(inDocByte))
{
// Create PdfFormatProvider and load the existing document
PdfFormatProvider provider = new PdfFormatProvider();
RadFixedDocument document = provider.Import(inputStream);
int pageNo = (signInfo.DigitalSignPage() == 0 ? 1 : document.Pages.Count);
try
{
if (needTimeStamp)
{
//.TimeStampServer = new TimeStampServer(new Uri(TsaServerUrl), TsaServerUser, TsaServerPassword);
}
}
catch (Exception ex)
{ }
// Path to the image (ensure this is correct)
System.Drawing.Image signatureImage = null;
if (signInfo.DigitalSignMode() == 2 && HttpContext.Current.Session["imagesyncfusion"] != null)
{
signatureImage = (System.Drawing.Image)HttpContext.Current.Session["imagesyncfusion"];
}
//var signatureImage = (System.Drawing.Image)HttpContext.Current.Session["imagesyncfusion"];
if (signInfo.UseDigitalSign())
{
if ((signInfo.DigitalSignMode() == 1) || (signInfo.DigitalSignMode() == 2))
{
signaturePositionLeft = (double)signInfo.DigitalSignLeftInPoints();
signaturePositionTop = (double)signInfo.DigitalSignTopInPoints();
signatureFieldWidth = (double)signInfo.DigitalSignWidthInPoints();
signatureFieldHeight = (double)signInfo.DigitalSignHeightInPoints();
RadFixedPage radFixedPage = document.Pages[pageNo - 1];
if (!string.IsNullOrEmpty(customSignatureDetails))
{
//Movable case:
signatureFieldWidth = signaturePositionLeft + (double)signInfo.DigitalSignWidthInPoints();
signatureFieldHeight = signaturePositionTop + (double)signInfo.DigitalSignHeightInPoints();
string[] separator = new string[] { "!_!" };
string[] offsetArray = customSignatureDetails.Split(separator, StringSplitOptions.RemoveEmptyEntries);
if (offsetArray.Length >= 9)
{
float offsetLeft = returnFloatWithCultureValue(offsetArray[0]);
float offsetTop = returnFloatWithCultureValue(offsetArray[1]);
float docHeight = returnFloatWithCultureValue(offsetArray[2]);
float greenDivHeight = returnFloatWithCultureValue(offsetArray[3]);
float greenDivWidth = returnFloatWithCultureValue(offsetArray[4]);
float dpi_x = returnFloatWithCultureValue(offsetArray[6]);
float dpi_y = returnFloatWithCultureValue(offsetArray[7]);
pageNo = int.Parse(offsetArray[8]);
// Calculate positions for drawing the text div;
signaturePositionLeft = (offsetLeft / dpi_x) * 72;
signaturePositionTop = (offsetTop / dpi_y) * 72;
signatureFieldWidth = (greenDivWidth / dpi_y) * 72;
signatureFieldHeight = (greenDivHeight / dpi_x) * 72;
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
}
else
{
//Non-movable case:
radFixedPage = document.Pages[pageNo - 1];
Tuple<double, double> k = null;
if (signatureImage != null)
{
k = calculateAspectRatioFit(signatureImage.Width, signatureImage.Height, signatureFieldWidth, signatureFieldHeight);
signatureFieldWidth = k.Item1;
signatureFieldHeight = k.Item2;
}
signaturePositionLeft = radFixedPage.Size.Height - (double)(signatureFieldWidth + signatureFieldHeight + 1);
signaturePositionTop = signaturePositionTop + 1; // +1 For border size
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
FixedContentEditor editor = new FixedContentEditor(pdfForm.FormSource);
// Drawing the image at the starting position (left side of the signature field)
imageWidth = signatureFieldWidth / 2; // Half the width for the image
double imageHeight = signatureFieldHeight; // Use full height of the signature field
if (signatureImage == null)
{
}
else
{
// Create a memory stream to hold the image
using (MemoryStream ms = new MemoryStream())
{
// Save the image to the memory stream
signatureImage.Save(ms, signatureImage.RawFormat);
// Reset the stream position to the beginning
ms.Position = 0;
// Pass the memory stream to the DrawImage method
editor.DrawImage(ms, new Telerik.Documents.Primitives.Size(imageWidth, imageHeight));
}
}
string textToDraw = $"Digitally signed by {certificate.FriendlyName} \nDate: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss zzz")} \nReason: {pdfSignature.Signature.Properties.Reason} \nLocation: {pdfSignature.Signature.Properties.Location}";
// Set the width of the text area (remaining space after the image)
double textWidth = signatureFieldWidth - imageWidth;
double dsd = CalculateFontSize(textWidth, signatureFieldHeight, textToDraw);
// Now, draw the text next to the image (on the right side), within the remaining space
Telerik.Windows.Documents.Fixed.Model.Editing.Block textBlock = new Telerik.Windows.Documents.Fixed.Model.Editing.Block();
double textPositionLeft = signaturePositionLeft + imageWidth; // Adding a 5px gap after the image
textBlock.TextProperties.FontSize = 8;
textBlock.InsertText($"Digitally signed by {certificate.FriendlyName}");
textBlock.InsertText($" Date: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss zzz")}");
textBlock.InsertText($" Reason: {pdfSignature.Signature.Properties.Reason}");
textBlock.InsertText($" Location: {pdfSignature.Signature.Properties.Location}");
Rect boundingRect = new Rect(textPositionLeft - 8, signaturePositionTop - 12, textWidth, signatureFieldHeight);
textBlock.Draw(editor, boundingRect);
// Create the SignatureWidget and position it on the PDF page
SignatureWidget signatureWidget = pdfSignature.Widgets.AddWidget();
signatureWidget.Content.NormalContentSource = pdfForm.FormSource;
signatureWidget.Rect = new Rect(signaturePositionLeft, signaturePositionTop, signatureFieldWidth, signatureFieldHeight);
signatureWidget.RecalculateContent();
// Add content from the form to the page at the specified position
RadFixedPage pdfPage = document.Pages[0]; // Assuming you're adding it to the first page
FixedContentEditor pageEditor = new FixedContentEditor(pdfPage);
pageEditor.Position.Translate(signaturePositionLeft, signaturePositionTop);
pageEditor.DrawForm(pdfForm.FormSource);
// Add the signature field to the document's AcroForm
document.AcroForm.FormFields.Add(pdfSignature);
}
}
// Use MemoryStream to capture the PDF output and return as a byte array
using (MemoryStream memoryStream = new MemoryStream())
{
// Export the document to the memory stream as a PDF
Telerik.Documents.ImageUtils.ImagePropertiesResolver defaultImagePropertiesResolver = new Telerik.Documents.ImageUtils.ImagePropertiesResolver();
Telerik.Windows.Documents.Extensibility.FixedExtensibilityManager.ImagePropertiesResolver = defaultImagePropertiesResolver;
var settings = new PdfExportSettings();
settings.ImageQuality = ImageQuality.High;
provider.ExportSettings = settings;
provider.Export(document, memoryStream);
// Return the byte array of the PDF
outDocPdf = memoryStream.ToArray();
//return memoryStream.ToArray(); // Return the byte array of the signed PDF
}
}
}
private static double CalculateFontSize(double textWidth, double signatureFieldHeight, string text)
{
// Start with a base font size for better precision
double baseFontSize = 12.0; // Starting font size
// Calculate width scale factor to adjust the font size based on text length
double widthScaleFactor = textWidth / text.Length;
double widthFontSize = baseFontSize * widthScaleFactor;
// Calculate height scale factor to adjust the font size based on the number of lines
int numLines = text.Split('\n').Length;
double heightScaleFactor = signatureFieldHeight / (numLines * baseFontSize);
double heightFontSize = baseFontSize * heightScaleFactor;
// Return the smaller font size to fit both dimensions
return Math.Min(widthFontSize, heightFontSize);
}
public static Tuple<double, double> calculateAspectRatioFit(double srcWidth, double srcHeight, double maxWidth, double maxHeight)
{
var ratio = Math.Min(maxWidth / srcWidth, maxHeight / srcHeight);
return new Tuple<double, double>(srcWidth * ratio, srcHeight * ratio);
}
Hello Vaibhav,
I am sorry to hear you are experiencing unexpected results. The provided code snippet is much appreciated and I would gladly like to help you with this case however without having the full context of this scenario at my disposal, my assistance can be very limited.
As I do not currently have access to the complete implementation, it would require additional time to refactor this snippet into a runnable project. Even with that effort, I cannot guarantee that the behavior and results on my end will match the ones you’re observing.
To ensure we are aligned and I can assist you effectively, could you please address as many of the following points as possible:
With this additional information, I’ll be able to better understand your situation and work toward a resolution more efficiently.
Also, in order for me to get a better context and understanding of the scenario, would you be able to share with us a runnable sample project that implements the provided code snippet?
Having this at my disposal will be much appreciated as it will really speed up the investigation process as I try to achieve the same results on my end, examine the issue further, and try to identify the cause. I assure you I will get back to you with details and feedback as soon as possible.
Please keep in mind that this is a public Q&A Forum and anything shared here will be made public. If you have any concerns about that please let me know.
Thank you in advance for your cooperation.
Regards,
Yoan
I have already sent you code snippets,
- The required resources?
- Are you processing an already existing document or creating a new one? => Existing one
- Does the file already contain a signature field or is a brand new one being created? => new signature field
- The expected final results. => inside the signature field the image and text should be draw with specified position and height and width will come from parameter name customSignatureDetails this parameter hold the position,height and width of signature field
- The Document Processing version that is referenced in the project. => 2024.4.1106.20
- A description of the setbacks and unexpected results you are encountering. =>image are shown perfectly but text is not visible or display but when i debug the application text is shown in the document but text is not show in the signature field
- Any missing class implementations, method definitions, or configurations referenced in the snippet.
- Any specific input values or conditions under which the issue arises.
public static void SignPDFSynfusion(SignatureInfo signInfo, byte[] inDocByte, Cert objCert, string customSignatureDetails, out byte[] outDocPdf)Below is the method
{
#region Old code conversion from Syncfusion to Telerik
// Initialize necessary objects
TimeStampSettings objTimeStampSettings = new TimeStampSettings();
TimeStampInfo objTimeStampInfo = (TimeStampInfo)objTimeStampSettings.GetTimeStamp();
PfxSettings objPfxSettings = new PfxSettings();
// Params to take account in the input
bool displaySignature = Convert.ToBoolean(HttpContext.Current.Session["showSign"]);
bool needTimeStamp = false;
string TsaServerUrl = "";
string TsaServerUser = "";
string TsaServerPassword = "";
string strPasswrd = string.Empty;
double imageWidth = 0;
if (objTimeStampInfo != null)
{
needTimeStamp = (bool)objTimeStampInfo.TimeStampNeeded;
TsaServerUrl = objTimeStampInfo.TimeStampUrl;
if ((bool)objTimeStampInfo.AuthNeeded)
{
TsaServerUser = objTimeStampInfo.UserName;
strPasswrd = SecurQueryString.decryptQueryString(objTimeStampInfo.Password);
TsaServerPassword = strPasswrd;
}
}
// Load the certificate
X509Certificate2 certificate = new X509Certificate2(objCert.CertArray, objCert.Password);
// Create a SignatureField and assign the digital signature to it
SignatureField pdfSignature = new SignatureField("SignatureField");
pdfSignature.Signature = new Telerik.Windows.Documents.Fixed.Model.DigitalSignatures.Signature(certificate);
// Set signature details
string strNotAvailable = HttpContext.GetGlobalResourceObject("GlobalResources", "lblNotAvlbl").ToString();
pdfSignature.Signature.Properties.Reason = strNotAvailable;
pdfSignature.Signature.Properties.ContactInfo = strNotAvailable;
pdfSignature.Signature.Properties.Location = strNotAvailable;
// Create a new form to place the signature field
Form pdfForm = new Form();
pdfForm.FormSource = new FormSource();
FixedContentEditor editor = new FixedContentEditor(pdfForm.FormSource);
// Load the existing PDF from the byte array using PdfFormatProvider
using (MemoryStream inputStream = new MemoryStream(inDocByte))
{
// Create PdfFormatProvider and load the existing document
PdfFormatProvider provider = new PdfFormatProvider();
RadFixedDocument document = provider.Import(inputStream);
int pageNo = (signInfo.DigitalSignPage() == 0 ? 1 : document.Pages.Count);
// Path to the image (ensure this is correct)
System.Drawing.Image signatureImage = null;
if (signInfo.DigitalSignMode() == 2 && HttpContext.Current.Session["imagesyncfusion"] != null)
{
signatureImage = (System.Drawing.Image)HttpContext.Current.Session["imagesyncfusion"];
}
// Check if digital signature is needed
if (signInfo.UseDigitalSign())
{
if ((signInfo.DigitalSignMode() == 1) || (signInfo.DigitalSignMode() == 2))
{
double signaturePositionLeft = (double)signInfo.DigitalSignLeftInPoints();
double signaturePositionTop = (double)signInfo.DigitalSignTopInPoints();
double signatureFieldWidth = (double)signInfo.DigitalSignWidthInPoints();
double signatureFieldHeight = (double)signInfo.DigitalSignHeightInPoints();
RadFixedPage radFixedPage = document.Pages[pageNo - 1];
if (!string.IsNullOrEmpty(customSignatureDetails))
{
// Movable signature case: Adjust the signature field based on custom details
signatureFieldWidth = signaturePositionLeft + (double)signInfo.DigitalSignWidthInPoints();
signatureFieldHeight = signaturePositionTop + (double)signInfo.DigitalSignHeightInPoints();
string[] separator = new string[] { "!_!" };
string[] offsetArray = customSignatureDetails.Split(separator, StringSplitOptions.RemoveEmptyEntries);
if (offsetArray.Length >= 9)
{
float offsetLeft = returnFloatWithCultureValue(offsetArray[0]);
float offsetTop = returnFloatWithCultureValue(offsetArray[1]);
float docHeight = returnFloatWithCultureValue(offsetArray[2]);
float greenDivHeight = returnFloatWithCultureValue(offsetArray[3]);
float greenDivWidth = returnFloatWithCultureValue(offsetArray[4]);
float dpi_x = returnFloatWithCultureValue(offsetArray[6]);
float dpi_y = returnFloatWithCultureValue(offsetArray[7]);
pageNo = int.Parse(offsetArray[8]);
// Calculate positions for drawing the text div;
signaturePositionLeft = (offsetLeft / dpi_x) * 72;
signaturePositionTop = (offsetTop / dpi_y) * 72;
signatureFieldWidth = (greenDivWidth / dpi_y) * 72;
signatureFieldHeight = (greenDivHeight / dpi_x) * 72;
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
}
else
{
// Non-movable case: Place the signature field in a fixed location
radFixedPage = document.Pages[pageNo - 1];
Tuple<double, double> k = null;
if (signatureImage != null)
{
k = calculateAspectRatioFit(signatureImage.Width, signatureImage.Height, signatureFieldWidth, signatureFieldHeight);
signatureFieldWidth = k.Item1;
signatureFieldHeight = k.Item2;
}
signaturePositionLeft = radFixedPage.Size.Height - (double)(signatureFieldWidth + signatureFieldHeight + 1);
signaturePositionTop = signaturePositionTop + 1; // +1 For border size
pdfForm.FormSource.Size = new Telerik.Documents.Primitives.Size(signatureFieldWidth, signatureFieldHeight);
}
// Drawing the image at the starting position (left side of the signature field)
imageWidth = signatureFieldWidth / 2; // Half the width for the image
double imageHeight = signatureFieldHeight; // Use full height of the signature field
if (signatureImage != null)
{
using (MemoryStream ms = new MemoryStream())
{
signatureImage.Save(ms, signatureImage.RawFormat);
ms.Position = 0;
editor.DrawImage(ms, new Telerik.Documents.Primitives.Size(imageWidth, imageHeight));
}
}
// Prepare text to draw beside the signature image
string textToDraw = $"Digitally signed by {certificate.FriendlyName} \nDate: {DateTime.Now:yyyy.MM.dd HH:mm:ss zzz} \nReason: {pdfSignature.Signature.Properties.Reason} \nLocation: {pdfSignature.Signature.Properties.Location}";
// Set text width and calculate font size
double textWidth = signatureFieldWidth - imageWidth;
double fontSize = CalculateFontSize(textWidth - 23, signatureFieldHeight, textToDraw);
// Define the position for the text and draw it
Telerik.Windows.Documents.Fixed.Model.Editing.Block textBlock = new Telerik.Windows.Documents.Fixed.Model.Editing.Block();
double textPositionLeft = signaturePositionLeft + imageWidth; // Adding a 5px gap after the image
textBlock.TextProperties.FontSize = fontSize;
textBlock.InsertText($"Digitally signed by {certificate.FriendlyName}");
textBlock.InsertText($" Date: {DateTime.Now:yyyy.MM.dd HH:mm:ss zzz}");
textBlock.InsertText($" Reason: {pdfSignature.Signature.Properties.Reason}");
textBlock.InsertText($" Location: {pdfSignature.Signature.Properties.Location}");
Rect boundingRect = new Rect(textPositionLeft - 8, signaturePositionTop - 12, textWidth, signatureFieldHeight);
textBlock.Draw(editor, boundingRect);
//editor.DrawBlock(textBlock);
// Create the SignatureWidget and position it on the PDF page
SignatureWidget signatureWidget = pdfSignature.Widgets.AddWidget();
signatureWidget.Content.NormalContentSource = pdfForm.FormSource;
signatureWidget.Rect = new Rect(signaturePositionLeft, signaturePositionTop, signatureFieldWidth, signatureFieldHeight);
signatureWidget.RecalculateContent();
// Add signature widget to the page and draw the content
RadFixedPage pdfPage = document.Pages[pageNo - 1];
pdfPage.Annotations.Add(signatureWidget);
FixedContentEditor pageEditor = new FixedContentEditor(pdfPage);
pageEditor.Position.Translate(signaturePositionLeft, signaturePositionTop);
pageEditor.DrawForm(pdfForm.FormSource);
// Add the signature field to the document's AcroForm
document.AcroForm.FormFields.Add(pdfSignature);
}
}
// Export the document to a byte array and return
using (MemoryStream memoryStream = new MemoryStream())
{
Telerik.Documents.ImageUtils.ImagePropertiesResolver defaultImagePropertiesResolver = new Telerik.Documents.ImageUtils.ImagePropertiesResolver();
Telerik.Windows.Documents.Extensibility.FixedExtensibilityManager.ImagePropertiesResolver = defaultImagePropertiesResolver;
PdfExportSettings settings = new PdfExportSettings() { ImageQuality = ImageQuality.High };
provider.ExportSettings = settings;
provider.Export(document, memoryStream);
outDocPdf = memoryStream.ToArray();
}
}
#endregion
}
Hello Vaibhav,
Thank you for taking the time to address my questions so thoroughly. Your detailed responses have been incredibly helpful in narrowing down the scope of the issue.
Possible Cause #1
Based on the description of the observed results I understand that the signature text does not appear at all in the signature field. If that is the case then one reason for this could be that the text is unable to fit in the field and goes out of bounds due to unexpected calculations. Another cause could be the order of inserting elements, which can cause them to overlap.
Possible Cause #2
Also, correct me if I am wrong, but due to the implementation of the ImagePropertiesResolver I have come to the conclusion that the project is using the .NET Standard version of Document Processing. If that is the case, then it is important to mention that the PdfProcessing library has certain limitations in the .NET Standard environment that one should be aware of. More specifically in this case - the Fonts.
Any calculations by the library are based on the used fonts in the document which is why the library needs to have access to the specific font data, otherwise, the application will fall back to another default font (e.g. Helvetica) and the results will be different as opposed to when using the font used in the file.
The .NET Framework version of PdfProcessing comes with out-of-the-box functionality to read fonts, however, the .NET Standard version does not have such capabilities.
To allow the library to create and use fonts, you need to manually provide an implementation that can serve as a workaround - implement a FontsProvider or manually register the fonts.
Request
While I greatly appreciate the code snippet and information you’ve shared, I still lack the full context to reproduce the behavior on my end and confirm my theory. Specifically, certain key variables and inputs - such as the customSignatureDetails parameter, which is critical for performing the calculations, and some API that does not seem to be Telerik-related (e.g. TimeStampSettings, PfxSettings, DigitalSignPage). These and some other gaps prevent me from replicating the exact environment and understanding how these inputs interact in your project.
I must apologize if my earlier response was somehow unclear, however, in order for me to continue the investigation and ensure that I can assist you more effectively, would it be possible for you to share a runnable sample project that implements the provided code snippet and the unexpected result document you are describing? A complete project along with the output file will allow me to fully replicate the scenario, observe the same results, and pinpoint the root cause of the text not appearing within the signature field as expected.
I understand that preparing a sample project might take additional time, and I sincerely appreciate your patience and cooperation in this matter. Please let me know if you have any concerns or questions about sharing resources, and I’ll be happy to guide you further.
Regards,
Yoan