/// <summary> /// Initializes a new instance of the <see cref="FontData"/> class. /// </summary> public FontData(XFont font, XPdfFontOptions options) { #if GDI && !WPF CreateGdiFontImage(font, options, font.privateFontCollection); #endif #if WPF && !GDI CreateWpfFontData(font, options); #endif #if WPF && GDI System.Drawing.Font gdiFont = font.RealizeGdiFont(); if (font.font != null) { CreateGdiFontImage(font, options, font.privateFontCollection); } else if (font.typeface != null) { CreateWpfFontData(font, options); } #endif if (this.data == null) { throw new InvalidOperationException("Cannot allocate font image."); } Read(); }
/// <summary> /// Create the font image using GDI+ functionality. /// </summary> void CreateGdiFontImage(XFont font, XPdfFontOptions options, XPrivateFontCollection privateFontCollection) { System.Drawing.Font gdiFont = font.RealizeGdiFont(); NativeMethods.LOGFONT logFont; #if DEBUG_ logFont = new NativeMethods.LOGFONT(); gdiFont.ToLogFont(logFont); Debug.WriteLine("FontData: " + logFont.lfFaceName); #endif this.data = null; if (privateFontCollection != null) { //XPrivateFont privateFont = privateFontCollection.FindFont(logFont.lfFaceName, logFont.lfWeight >= 700, logFont.lfItalic > 0); XPrivateFont privateFont = privateFontCollection.FindFont(font.Name, font.Bold, font.Italic); if (privateFont != null) { int size = privateFont.GetFontData(ref this.data, 0); if (size > 0) { this.data = new byte[size]; privateFont.GetFontData(ref this.data, size); } } } if (this.data == null) { int error; IntPtr hfont = gdiFont.ToHfont(); IntPtr hdc = NativeMethods.GetDC(IntPtr.Zero); error = Marshal.GetLastWin32Error(); IntPtr oldFont = NativeMethods.SelectObject(hdc, hfont); error = Marshal.GetLastWin32Error(); // size is exactly the size of the font file. int size = NativeMethods.GetFontData(hdc, 0, 0, null, 0); error = Marshal.GetLastWin32Error(); if (size > 0) { this.data = new byte[size]; int effectiveSize = NativeMethods.GetFontData(hdc, 0, 0, this.data, this.data.Length); Debug.Assert(size == effectiveSize); NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); error.GetType(); } else { // Sometimes size is -1 (GDI_ERROR), but I cannot determine why. It happens only with the font 'Symbol'. // The issue occurs the first time in early 2005, when I start writing PDFsharp. I could not fix it and after // some code refactoring the problem disappears. // There was never a report from anyone about this issue. // Now I get it again (while debugging QBX 2006). Maybe it is a problem with my PC at my home office. // As a work-around I create a new font handle with a different height value. This works. Maybe the // font file gets locked somewhere. Very very strange. // IF SOMEONE ELSE COMES HERE PLEASE LET ME KNOW! // Clean up old handles NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); // Try again with new font handle logFont = new NativeMethods.LOGFONT(); gdiFont.ToLogFont(logFont); logFont.lfHeight += 1; // force new handle IntPtr hfont2 = NativeMethods.CreateFontIndirect(logFont); hdc = NativeMethods.GetDC(IntPtr.Zero); error = Marshal.GetLastWin32Error(); oldFont = NativeMethods.SelectObject(hdc, hfont2); error = Marshal.GetLastWin32Error(); // size is exactly the size of the font file. size = NativeMethods.GetFontData(hdc, 0, 0, null, 0); error = Marshal.GetLastWin32Error(); if (size > 0) { this.data = new byte[size]; int effectiveSize = NativeMethods.GetFontData(hdc, 0, 0, this.data, this.data.Length); Debug.Assert(size == effectiveSize); } NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); NativeMethods.DeleteObject(hfont2); error.GetType(); } } if (this.data == null) { throw new InvalidOperationException("Internal error. Font data could not retrieved."); } }
/// <summary> /// Create the font image using GDI+ functionality. /// </summary> void CreateGdiFontImage(XFont font, XPdfFontOptions options /*, XPrivateFontCollection privateFontCollection*/) { System.Drawing.Font gdiFont = font.RealizeGdiFont(); #if DEBUG_ logFont = new NativeMethods.LOGFONT(); gdiFont.ToLogFont(logFont); Debug.WriteLine("FontData: " + logFont.lfFaceName); #endif this.data = null; // PFC //if (privateFontCollection != null) //{ // //XPrivateFont privateFont = privateFontCollection.FindFont(logFont.lfFaceName, logFont.lfWeight >= 700, logFont.lfItalic > 0); // XGlyphTypeface privateFont = privateFontCollection.FindFont(font.Name, font.Bold, font.Italic); // if (privateFont != null) // { // //////int size = privateFont.GetData(ref this.data); // //////if (size > 0) // //////{ // ////// this.data = new byte[size]; // ////// privateFont.GetData(ref this.data, size); // //////} // } //} if (this.data == null) { var assembly = FontDataConfig.ResourceAssembly; var name = string.Format("{0}.FontHacks.{1}{2}{3}.fontdat", assembly != null ? assembly.GetName().Name : string.Empty, font.Name, font.Bold ? ".Bold" : string.Empty, font.Italic ? ".Italic" : string.Empty); if (assembly != null && new List <string>(assembly.GetManifestResourceNames()).Contains(name)) { System.Diagnostics.Debug.WriteLine("*** Reading fontdata from Resource"); using (var s = assembly.GetManifestResourceStream(name)) { this.data = new byte[s.Length]; s.Read(this.data, 0, (int)s.Length); } } else { System.Diagnostics.Debug.WriteLine("*** Reading fontdata from GDI+"); int error; IntPtr hfont = gdiFont.ToHfont(); using (var dcBmp = new Bitmap(100, 100)) using (var dc = Graphics.FromImage(dcBmp)) { IntPtr hdc = dc.GetHdc(); error = Marshal.GetLastWin32Error(); IntPtr oldFont = NativeMethods.SelectObject(hdc, hfont); error = Marshal.GetLastWin32Error(); // size is exactly the size of the font file. int size = NativeMethods.GetFontData(hdc, 0, 0, null, 0); error = Marshal.GetLastWin32Error(); if (size > 0) { this.data = new byte[size]; int effectiveSize = NativeMethods.GetFontData(hdc, 0, 0, this.data, this.data.Length); Debug.Assert(size == effectiveSize); if (FontDataConfig.SaveFont) { FileExtensions.WriteFileBytes(this.data, string.Format("..\\..\\FontHacks\\{0}{1}{2}.fontdat", font.Name, font.Bold ? ".Bold" : string.Empty, font.Italic ? ".Italic" : string.Empty)); } NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); error.GetType(); } else { // Sometimes size is -1 (GDI_ERROR), but I cannot determine why. It happens only with the font 'Symbol'. // The issue occurs the first time in early 2005, when I start writing PDFsharp. I could not fix it and after // some code refactoring the problem disappears. // There was never a report from anyone about this issue. // Now I get it again (while debugging QBX 2006). Maybe it is a problem with my PC at my home office. // As a work-around I create a new font handle with a different height value. This works. Maybe the // font file gets locked somewhere. Very very strange. // IF SOMEONE ELSE COMES HERE PLEASE LET ME KNOW! // Clean up old handles NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); // Try again with new font handle var logFont = new NativeMethods.LOGFONT(); gdiFont.ToLogFont(logFont); logFont.lfHeight += 1; // force new handle IntPtr hfont2 = NativeMethods.CreateFontIndirect(logFont); hdc = NativeMethods.GetDC(IntPtr.Zero); error = Marshal.GetLastWin32Error(); oldFont = NativeMethods.SelectObject(hdc, hfont2); error = Marshal.GetLastWin32Error(); // size is exactly the size of the font file. size = NativeMethods.GetFontData(hdc, 0, 0, null, 0); error = Marshal.GetLastWin32Error(); if (size > 0) { this.data = new byte[size]; int effectiveSize = NativeMethods.GetFontData(hdc, 0, 0, this.data, this.data.Length); Debug.Assert(size == effectiveSize); } NativeMethods.SelectObject(hdc, oldFont); NativeMethods.ReleaseDC(IntPtr.Zero, hdc); NativeMethods.DeleteObject(hfont2); error.GetType(); } } } if (this.data == null) { throw new InvalidOperationException("Internal error. Font data could not retrieved."); } } }