PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Thu Jul 18, 2024 9:23 am

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Thu Aug 18, 2011 2:59 pm 
Offline

Joined: Thu Aug 18, 2011 2:39 pm
Posts: 4
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 23, 2011 10:42 am 
Offline

Joined: Thu Aug 18, 2011 2:39 pm
Posts: 4
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 23, 2011 2:50 pm 
Offline

Joined: Thu Aug 18, 2011 2:39 pm
Posts: 4
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.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 26, 2011 12:25 pm 
Offline

Joined: Thu Aug 18, 2011 2:39 pm
Posts: 4
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 11, 2015 8:10 am 
Offline

Joined: Tue Feb 17, 2015 2:58 am
Posts: 5
@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");


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 11, 2015 9:16 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3101
Location: Cologne, Germany
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).

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 11, 2015 1:13 pm 
Offline

Joined: Tue Feb 17, 2015 2:58 am
Posts: 5
Thanks for the reply. I'm still unsure of where to put the Font files and what the Uri should be on a webserver.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 11, 2015 3:16 pm 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3101
Location: Cologne, Germany
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.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 12, 2015 1:14 am 
Offline

Joined: Tue Feb 17, 2015 2:58 am
Posts: 5
Can you provide an example of a Uri to a font file?


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 12, 2015 8:46 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3101
Location: Cologne, Germany
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.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 16, 2015 4:35 am 
Offline

Joined: Tue Feb 17, 2015 2:58 am
Posts: 5
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;
      }
   }
}


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 16, 2015 9:12 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3101
Location: Cologne, Germany
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

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 17, 2015 7:32 am 
Offline

Joined: Tue Feb 17, 2015 2:58 am
Posts: 5
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?


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 17, 2015 11:05 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3101
Location: Cologne, Germany
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.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 22, 2015 11:46 am 
Offline

Joined: Thu Apr 01, 2010 12:44 pm
Posts: 4
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 40 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group