PDFsharp & MigraDoc Foundation
https://forum.pdfsharp.net/

Embedded Custom Font Issue via SQL Server 2005 Agent
https://forum.pdfsharp.net/viewtopic.php?f=2&t=1745
Page 1 of 1

Author:  BDRichardson [ Thu Aug 18, 2011 2:59 pm ]
Post subject:  Embedded Custom Font Issue via SQL Server 2005 Agent

Hi,

I think I have identified an issue where a custom embedded font is not rendered correctly using PdfSharp via SQL Server 2005 Agent.

Unfortunately, the decision to use an Integration Services package scheduled by SQL Agent is out of my control. Basically, I am attempting to schedule an Integration Services package, which simply contains a Script object to invoke code from a .NET assembly in conjunction with the PdfSharp assembly. Everything works perfectly on both my development environment, and on the server where it will reside, except for when I attempt to execute the package via SQL Server Management Studio. No errors are raised, and everything seems fine except that the text content is no longer rendered using the custom font, and text that should be right (far) aligned is no longer so.

I have done the following:
Installed the custom font on the server.
Successfully registered all assemblies within the GAC.
Ensured the Proxy account for the SQL Agent Job is a domain account with local administrator rights to the server, and is a member of the System Administators role within SQL Server.
The Proxy has privileges to the appropriate sub-systems within SQL Server.

I have executed the package using DTExec from the command prompt using the same account as described above, and everything works perfectly. The problem just seems to be with executing the package through SQL Agent where problems are introduced with the fonts. I am sure that there are not any permission (both code trust or otherwise) issues since the assemblies have permissions for partial trusted callers. 'Process Monitor' reports that successful access has been made to the font (TTF) files.

I am suspecting that there must a security and/or policy restriction being enforced when executing the package via SQL Agent, which is not being enforced when executing it by an interactive command prompt.

Is anyone able make any suggestions as to what additional security checks I can make?

Any assistance would be greatly appreciated.

Author:  BDRichardson [ Tue Aug 23, 2011 10:42 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

Further to my investigation, when the CreateGdiFontImage method within the PdfSharp.Fonts.OpenType.FontData class is invoked, it would appear that the PdfSharp.Internal.NativeMethods.GetFontData method is invoked but returns '-1'. This implies that the call failed to determine the size of the font file. Immediately after, the Marshal.GetLastWin32Error() method is invoked and returns error code 127. From my investigation so far, I believe error code 127 equates to 'The specified procedure could not be found' (ERROR_PROC_NOT_FOUND).

I am suspecting that code access security is preventing the GetFontData method being invoked from GDI32.dll, but have not yet proved it. The font I am attempting to load the information from is True Type.

Author:  BDRichardson [ Tue Aug 23, 2011 2:50 pm ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

I think I am getting closer to the problem. For the assembly to be available to SQL Agent, it has to be registered in the GAC. However, the GDI32.dll is not registered in the GAC. Thus the problem. I believe managed assemblies are not able to access unmanaged assemblies which are not registered in the GAC.

Author:  BDRichardson [ Fri Aug 26, 2011 12:25 pm ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

I have come to the conclusion that native unmanaged assemblies may only be reference by an assembly, which is registered in then GAC, if the unmanaged assemblies are also registered in the GAC by embedding them within the managed assembly.

Unfortunately, in this case, it is not possible since there are so many dependencies of the GDI32.dll, and the only feasible means of overcoming this issue was to embed the necessary font information within the managed assembly.

Author:  ozbobwa [ Wed Mar 11, 2015 8:10 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

@THHO I'm giving up and finding an alternative PDF creator - unless the missing sample is provided on (http://www.pdfsharp.net/wiki/PrivateFonts-sample.ashx) soon.

On the web there is no simple way to use PdfSharp of MigraPdf. Embedding Font's as embedded resources on the Project that references has a Nuget reference to "PDFsharp-MigraDoc-gdi" doesn't work.

I get the following error:
[InvalidOperationException: Cannot retrieve font data.]
PdfSharp.Fonts.FontResolverBase.GetFontData(Byte[]& data, String familyName, Boolean isBold, Boolean isItalic) +311
PdfSharp.Fonts.FontResolverBase.ResolveTypeface(String familyName, Boolean isBold, Boolean isItalic) +124
PdfSharp.Fonts.DefaultFontResolver.ResolveTypeface(String typefaceName, Boolean isBold, Boolean isItalic) +17
PdfSharp.Fonts.GlobalFontSettings.ResolveFont(XFont font) +75
PdfSharp.Fonts.OpenType.OpenTypeFontface..ctor(XFont font, XPdfFontOptions options) +68
PdfSharp.Fonts.OpenType.OpenTypeDescriptor..ctor(XFont font, XPdfFontOptions options) +97
PdfSharp.Fonts.FontDescriptorStock.CreateOpenTypeDescriptor(XFont font) +134
PdfSharp.Fonts.FontDescriptorStock.CreateDescriptor(XFont font) +126
PdfSharp.Drawing.XFont.get_Metrics() +34
PdfSharp.Drawing.XFont.Initialize() +170
PdfSharp.Drawing.XFont..ctor(String familyName, Double emSize, XFontStyle style) +51
PdfSharp.Drawing.XGraphicsPath.AddString(String s, XFontFamily family, XFontStyle style, Double emSize, XRect layoutRect, XStringFormat format) +143
PdfSharpMigraDocTest.getClock.DrawText(XGraphics gfx, XPen pen, XBrush brush) in c:\Dev\qwe\Spikes\PDF\PdfSharpMigraDocTest\getClock.aspx.cs:78

I am tempted to give '
System.Windows.Media.FontFamily fontFamily = new System.Windows.Media.FontFamily(baseUri, familyName);
fontFamilies.Add(key, fontFamily);'
a go if it existed in MigraPDF but sadly not, or if the URI for my font was obtainable.
Maybe the Uri for local nonGAC registered DLL embedded fonts is per <http://stackoverflow.com/questions/350027/setting-wpf-image-source-in-code> : i.e. new Uri("pack://application:,,,/AssemblyName;component/Resources/Verdana.ttf");

Author:  Thomas Hoevel [ Wed Mar 11, 2015 9:16 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

ozbobwa wrote:
@THHO I'm giving up and finding an alternative PDF creator - unless the missing sample is provided on (http://www.pdfsharp.net/wiki/PrivateFonts-sample.ashx) soon.
It works with version 1.32. There is no sample for version 1.50 beta yet.
If you need it now, use version 1.32 (from NuGet or Codeplex or Sourceforge).

Author:  ozbobwa [ Wed Mar 11, 2015 1:13 pm ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

Thanks for the reply. I'm still unsure of where to put the Font files and what the Uri should be on a webserver.

Author:  Thomas Hoevel [ Wed Mar 11, 2015 3:16 pm ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

When you add the fonts as resources to your project, then the URI on the server will be the same as in the test environment. This makes testing and deployment easier.

Author:  ozbobwa [ Thu Mar 12, 2015 1:14 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

Can you provide an example of a Uri to a font file?

Author:  Thomas Hoevel [ Thu Mar 12, 2015 8:46 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

Download the source code package 1.32 from CodePlex and you will find a sample for the WPF build that works with fonts embedded as resources.
http://pdfsharp.codeplex.com/releases

Things will be slightly different with PDFsharp 1.50, but we haven't published a sample yet.

Author:  ozbobwa [ Mon Mar 16, 2015 4:35 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

AFter much testing with all your version (1.32, 1.50 from nuget and then the source code from your downloads).

The error message from Asp.Net hosted pages, rendering private font collections comes down to this:
[InvalidOperationException: Internal error. Font data could not retrieved.]
PdfSharp.Fonts.OpenType.FontData.CreateGdiFontImage(XFont font, XPdfFontOptions options) +452

While debugging your source code line by line the error comes because the Memory Pointer for the private font is '3221225506' as a uInt from Gdi32 on the webserver, causing a Memory Fault as it's too big for a Font allocation.

Locally it's all fine, the code being that works locally on all versions:
1. include the font and path to the font in the project and class
2.


Code:
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System;

namespace Migra13TestWeb
{
   public partial class index : System.Web.UI.Page
   {
      protected void Page_Load(object sender, EventArgs e)
      {
         // Create new PDF document
         var clock = new CreateClock13(Server.MapPath("~"));
         System.IO.MemoryStream stream = clock.RenderClockAsStream();

         Response.Clear();
         Response.ContentType = "application/pdf";
         Response.AddHeader("content-length", stream.Length.ToString());
         Response.BinaryWrite(stream.ToArray());
         Response.Flush();

         stream.Close();

         Response.End();
      }
   }

   public class CreateClock13
   {
      private DateTime Time;
      private PdfPage page;
      private XGraphics gfx;
      private XFont fontVerdana;
      private XFontFamily fontVerdanaFamily;
      XPdfFontOptions options;
      private string _localPath;

      public CreateClock13(string localPath)
      {
         _localPath = localPath;
         // Set font embedding to Always
         options = new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.Always);

      }

      private byte[] FileToByteArray(string fileName)
      {
         byte[] fileContent = null;
         System.IO.FileStream fs = new System.IO.FileStream(_localPath + fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
         System.IO.BinaryReader binaryReader = new System.IO.BinaryReader(fs);

         long byteLength = new System.IO.FileInfo(_localPath + fileName).Length;
         fileContent = binaryReader.ReadBytes((Int32)byteLength);
         fs.Close();
         fs.Dispose();
         binaryReader.Close();
         return fileContent;
      }

      public System.IO.MemoryStream RenderClockAsStream()
      {
         PdfDocument document = new PdfDocument();

         byte[] fontStreamBytes = FileToByteArray(@"bin\Font\verdana.ttf");

         //var xpfc = new XPrivateFontCollection();
         //xpfc.AddFont(fontStreamBytes, "Verdana");
         //PdfSharp.Drawing.XPrivateFontCollection.SetGlobalFontCollection(xpfc);


         XPrivateFontCollection globalFontCollection = XPrivateFontCollection.Global;
         globalFontCollection.AddFont(fontStreamBytes, "Verdana");
         PdfSharp.Drawing.XPrivateFontCollection.SetGlobalFontCollection(globalFontCollection);

         this.Time = document.Info.CreationDate;
         document.Info.Title = "PDFsharp Clock Demo";
         document.Info.Author = "Stefan Lange";
         document.Info.Subject = "Server Time: " + this.Time.ToString("F", System.Globalization.CultureInfo.InvariantCulture);

         // Create new page
         page = document.AddPage();
         page.Width = XUnit.FromMillimeter(210);
         page.Height = XUnit.FromMillimeter(297);

         // Create graphics object and draw clock
         gfx = XGraphics.FromPdfPage(page);

         // HACKĀ²
         gfx.MUH = PdfFontEncoding.Unicode;
         gfx.MFEH = PdfFontEmbedding.Default;

         XFont font = new XFont("Verdana", 13, XFontStyle.Bold);

         gfx.DrawString("The following paragraph was rendered using MigraDoc:", font, XBrushes.Black,
           new XRect(100, 100, page.Width - 200, 300), XStringFormats.Center);

         Document doc = new Document();
         Section sec = doc.AddSection();
         // Add a single paragraph with some text and format information.
         Paragraph para = sec.AddParagraph();
         para.Format.Alignment = ParagraphAlignment.Justify;
         para.Format.Font.Name = "Verdana";
         para.Format.Font.Size = 12;
         para.Format.Font.Color = MigraDoc.DocumentObjectModel.Colors.DarkGray;
         para.Format.Font.Color = MigraDoc.DocumentObjectModel.Colors.DarkGray;
         para.AddText("Duisism odigna acipsum delesenisl ");

         // Create a renderer and prepare (=layout) the document
         MigraDoc.Rendering.DocumentRenderer docRenderer = new DocumentRenderer(doc);
         docRenderer.PrepareDocument();

         // Render the paragraph. You can render tables or shapes the same way.
         docRenderer.RenderObject(gfx, XUnit.FromCentimeter(5), XUnit.FromCentimeter(10), "12cm", para);
   
         var stream = new System.IO.MemoryStream();
         document.Save(stream, false);
         return stream;
      }
   }
}

Author:  Thomas Hoevel [ Mon Mar 16, 2015 9:12 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

ozbobwa wrote:
AFter much testing with all your version (1.32, 1.50 from nuget and then the source code from your downloads).

The error message from Asp.Net hosted pages, rendering private font collections comes down to this:
[InvalidOperationException: Internal error. Font data could not retrieved.]
PdfSharp.Fonts.OpenType.FontData.CreateGdiFontImage(XFont font, XPdfFontOptions options) +452
You obviously are using the GDI+ build of PDFsharp 1.32. Private fonts do not work with the GDI+ build 1.32, so please try the WPF build.

PDFsharp 1.50 requires a different technique to use private fonts.
viewtopic.php?p=8961#p8961

Author:  ozbobwa [ Tue Mar 17, 2015 7:32 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

Hi Thomas
I will give that a go. Thank you.
I thought that only GDI would work on WebServers because of the inclusion of the WPF dlls. Is that correct?

Author:  Thomas Hoevel [ Tue Mar 17, 2015 11:05 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

ozbobwa wrote:
I thought that only GDI would work on WebServers because of the inclusion of the WPF dlls. Is that correct?
I don't know.
There are so many server versions and .NET versions around.

Trying the WPF build 1.32 is a small change. Trying 1.50 beta requires more changes.

Author:  stroup [ Mon Jun 22, 2015 11:46 am ]
Post subject:  Re: Embedded Custom Font Issue via SQL Server 2005 Agent

I got private font's working in the 1.32gdi with a bit of wrangling but I've not tried embedding them, I've got them as loose files.

When initiating my code I build my private font family, you'll have to excuse the vb ;)

At the class level I have

Code:
 Private _privatefontfamily As System.Drawing.Text.PrivateFontCollection
    Private _xfontoptions As New Drawing.XPdfFontOptions(Pdf.PdfFontEncoding.Unicode, Pdf.PdfFontEmbedding.Always)

Then on initialising

Code:
       _privatefontfamily = New System.Drawing.Text.PrivateFontCollection

        _privatefontfamily.AddFontfile(System.IO.Path.Combine(ResourcePath, "fonts", "Frutiger Black.ttf"))
        _privatefontfamily.AddFontFile(System.IO.Path.Combine(ResourcePath, "fonts", "HelveticaLTStd-Bold.ttf"))
        _privatefontfamily.AddFontFile(System.IO.Path.Combine(ResourcePath, "fonts", "HelveticaLTStd-Roman.ttf"))



Then when I want to use one of them I run another routine

Code:
    Public Function FontFamily(ByVal name As String) As FontFamily
        For Each fontfam As FontFamily In _privatefontfamily.Families
            If fontfam.Name.ToUpper.Equals(name.ToUpper) Then Return fontfam
        Next
        Return New FontFamily("Arial")
    End Function


obviously this could be changed to then check the local resources if it isn't in the gdi private fonts.

Then when using the font I just use

Code:
New Drawing.XFont(FontFamily("Frutiger"), 19, Drawing.XFontStyle.Bold, _xfontoptions)


In the few pieces I've generated it's worked ok, obviously the problem will happen when a font can't be embedded but then that will happen anyway. Sadly it only works with ttf fonts which are becoming increasingly difficult to get from suppliers so eventually I'll have to switch to wpf.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/