Test
This commit is contained in:
441
PrintPDF/PdfSharp/Drawing/XPrivateFontCollection.cs
Normal file
441
PrintPDF/PdfSharp/Drawing/XPrivateFontCollection.cs
Normal file
@@ -0,0 +1,441 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using PdfSharp.Fonts;
|
||||
#if CORE || GDI
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using GdiFontFamily = System.Drawing.FontFamily;
|
||||
using GdiFont = System.Drawing.Font;
|
||||
using GdiFontStyle = System.Drawing.FontStyle;
|
||||
using GdiPrivateFontCollection = System.Drawing.Text.PrivateFontCollection;
|
||||
#endif
|
||||
#if WPF
|
||||
using System.Windows.Markup;
|
||||
using WpfFonts = System.Windows.Media.Fonts;
|
||||
using WpfFontFamily = System.Windows.Media.FontFamily;
|
||||
using WpfTypeface = System.Windows.Media.Typeface;
|
||||
using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface;
|
||||
#endif
|
||||
|
||||
namespace PdfSharp.Drawing
|
||||
{
|
||||
#if true
|
||||
///<summary>
|
||||
/// Makes fonts that are not installed on the system available within the current application domain.<br/>
|
||||
/// In Silverlight required for all fonts used in PDF documents.
|
||||
/// </summary>
|
||||
public sealed class XPrivateFontCollection
|
||||
{
|
||||
// This one is global and can only grow. It is not possible to remove fonts that have been added.
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XPrivateFontCollection"/> class.
|
||||
/// </summary>
|
||||
XPrivateFontCollection()
|
||||
{
|
||||
// HACK: Use one global PrivateFontCollection in GDI+
|
||||
}
|
||||
|
||||
#if GDI
|
||||
//internal PrivateFontCollection PrivateFontCollection
|
||||
//{
|
||||
// get { return privateFontCollection; }
|
||||
// set { privateFontCollection = value; }
|
||||
//}
|
||||
|
||||
GdiPrivateFontCollection GetPrivateFontCollection()
|
||||
{
|
||||
// Create only if really needed.
|
||||
if (_privateFontCollection == null)
|
||||
_privateFontCollection = new GdiPrivateFontCollection();
|
||||
return _privateFontCollection;
|
||||
}
|
||||
|
||||
// PrivateFontCollection of GDI+
|
||||
private GdiPrivateFontCollection _privateFontCollection;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the global font collection.
|
||||
/// </summary>
|
||||
internal static XPrivateFontCollection Singleton
|
||||
{
|
||||
get { return _singleton; }
|
||||
}
|
||||
internal static XPrivateFontCollection _singleton = new XPrivateFontCollection();
|
||||
|
||||
#if GDI
|
||||
/// <summary>
|
||||
/// Adds the font data to the font collections.
|
||||
/// </summary>
|
||||
[Obsolete("Use Add(Stream stream)")]
|
||||
public void AddFont(byte[] data, string familyName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(familyName))
|
||||
throw new ArgumentNullException("familyName");
|
||||
|
||||
//if (glyphTypeface == null)
|
||||
// throw new ArgumentNullException("glyphTypeface");
|
||||
|
||||
// Add to GDI+ PrivateFontCollection
|
||||
int length = data.Length;
|
||||
|
||||
// Copy data without unsafe code
|
||||
IntPtr ip = Marshal.AllocCoTaskMem(length);
|
||||
Marshal.Copy(data, 0, ip, length);
|
||||
GetPrivateFontCollection().AddMemoryFont(ip, length);
|
||||
// Do not free the memory here, AddMemoryFont stores a pointer, not a copy!
|
||||
//Marshal.FreeCoTaskMem(ip);
|
||||
//privateFonts.Add(glyphTypeface);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified font data to the global PrivateFontCollection.
|
||||
/// Family name and style are automatically retrieved from the font.
|
||||
/// </summary>
|
||||
#if GDI
|
||||
[Obsolete("Use Add(Stream stream)")]
|
||||
#else
|
||||
[Obsolete("Use the GDI build of PDFsharp and use Add(Stream stream)")]
|
||||
#endif
|
||||
public static void AddFont(string filename)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//XGlyphTypeface glyphTypeface = new XGlyphTypeface(filename);
|
||||
//Global.AddGlyphTypeface(glyphTypeface);
|
||||
}
|
||||
|
||||
#if GDI
|
||||
/// <summary>
|
||||
/// Adds the specified font data to the global PrivateFontCollection.
|
||||
/// Family name and style are automatically retrieved from the font.
|
||||
/// </summary>
|
||||
[Obsolete("Use Add(stream).")]
|
||||
public static void AddFont(Stream stream)
|
||||
{
|
||||
Add(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified font data to the global PrivateFontCollection.
|
||||
/// Family name and style are automatically retrieved from the font.
|
||||
/// </summary>
|
||||
public static void Add(Stream stream)
|
||||
{
|
||||
int length = (int)stream.Length;
|
||||
byte[] bytes = new byte[length];
|
||||
stream.Read(bytes, 0, length);
|
||||
Add(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified font data to the global PrivateFontCollection.
|
||||
/// Family name and style are automatically retrieved from the font.
|
||||
/// </summary>
|
||||
public static void Add(byte[] font)
|
||||
{
|
||||
IntPtr unmanagedPointer = Marshal.AllocCoTaskMem(font.Length);
|
||||
Marshal.Copy(font, 0, unmanagedPointer, font.Length);
|
||||
Singleton.GetPrivateFontCollection().AddMemoryFont(unmanagedPointer, font.Length);
|
||||
// Do not free the memory here, AddMemoryFont stores a pointer, not a copy!
|
||||
//Marshal.FreeCoTaskMem(ip);
|
||||
|
||||
XFontSource fontSource = XFontSource.GetOrCreateFrom(font);
|
||||
|
||||
string familyName = fontSource.FontName;
|
||||
|
||||
if (familyName.EndsWith(" Regular", StringComparison.OrdinalIgnoreCase))
|
||||
familyName = familyName.Substring(0, familyName.Length - 8);
|
||||
|
||||
bool bold = fontSource.Fontface.os2.IsBold;
|
||||
bool italic = fontSource.Fontface.os2.IsItalic;
|
||||
IncompetentlyMakeAHackToFixAProblemYouWoldNeverHaveIfYouUseAFontResolver(fontSource, ref familyName, ref bold, ref italic);
|
||||
string key = MakeKey(familyName, bold, italic);
|
||||
Singleton._fontSources.Add(key, fontSource);
|
||||
|
||||
string typefaceKey = XGlyphTypeface.ComputeKey(familyName, bold, italic);
|
||||
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
|
||||
}
|
||||
|
||||
static void IncompetentlyMakeAHackToFixAProblemYouWoldNeverHaveIfYouUseAFontResolver(XFontSource fontSource,
|
||||
ref string familyName, ref bool bold, ref bool italic)
|
||||
{
|
||||
const string regularSuffix = " Regular";
|
||||
const string boldSuffix = " Bold";
|
||||
const string italicSuffix = " Italic";
|
||||
const string boldItalicSuffix = " Bold Italic";
|
||||
const string italicBoldSuffix = " Italic Bold";
|
||||
|
||||
if (familyName.EndsWith(regularSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
familyName = familyName.Substring(0, familyName.Length - regularSuffix.Length);
|
||||
Debug.Assert(!bold && !italic);
|
||||
bold = italic = false;
|
||||
}
|
||||
else if (familyName.EndsWith(boldItalicSuffix, StringComparison.OrdinalIgnoreCase) || familyName.EndsWith(italicBoldSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
familyName = familyName.Substring(0, familyName.Length - boldItalicSuffix.Length);
|
||||
Debug.Assert(bold && italic);
|
||||
bold = italic = true;
|
||||
}
|
||||
else if (familyName.EndsWith(boldSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
familyName = familyName.Substring(0, familyName.Length - boldSuffix.Length);
|
||||
Debug.Assert(bold && !italic);
|
||||
bold = true;
|
||||
italic = false;
|
||||
}
|
||||
else if (familyName.EndsWith(italicSuffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
familyName = familyName.Substring(0, familyName.Length - italicSuffix.Length);
|
||||
Debug.Assert(!bold && italic);
|
||||
bold = false;
|
||||
italic = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(!bold && !italic);
|
||||
bold = false;
|
||||
italic = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified font data to the global PrivateFontCollection.
|
||||
/// Family name and style are automatically retrieved from the font.
|
||||
/// </summary>
|
||||
#if GDI
|
||||
[Obsolete("Use Add(Stream stream)")]
|
||||
#else
|
||||
[Obsolete("Use the GDI build of PDFsharp and use Add(Stream stream)")]
|
||||
#endif
|
||||
public static void AddFont(Stream stream, string facename)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//XGlyphTypeface glyphTypeface = new XGlyphTypeface(stream, facename);
|
||||
//Global.AddGlyphTypeface(glyphTypeface);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Adds XGlyphTypeface to internal collection.
|
||||
// /// Family name and style are automatically retrieved from the font.
|
||||
// /// </summary>
|
||||
// void AddGlyphTypeface(XGlyphTypeface glyphTypeface)
|
||||
// {
|
||||
// string name = MakeName(glyphTypeface);
|
||||
// if (_typefaces.ContainsKey(name))
|
||||
// throw new InvalidOperationException(PSSR.FontAlreadyAdded(glyphTypeface.DisplayName));
|
||||
|
||||
// _typefaces.Add(name, glyphTypeface);
|
||||
// //Debug.WriteLine("Font added: " + name);
|
||||
|
||||
//#if GDI
|
||||
// // Add to GDI+ PrivateFontCollection singleton.
|
||||
// byte[] data = glyphTypeface.Fontface.FontSource.Bytes;
|
||||
// int length = data.Length;
|
||||
|
||||
// IntPtr ip = Marshal.AllocCoTaskMem(length);
|
||||
// Marshal.Copy(data, 0, ip, length);
|
||||
// _privateFontCollection.AddMemoryFont(ip, length);
|
||||
// // Do not free the memory here, AddMemoryFont stores a pointer, not a copy!
|
||||
// // Marshal.FreeCoTaskMem(ip);
|
||||
//#endif
|
||||
|
||||
//#if WPF
|
||||
//#endif
|
||||
// }
|
||||
|
||||
#if WPF
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the FontFamily class from the specified font family name and an optional base uniform resource identifier (URI) value.
|
||||
/// Sample: Add(new Uri("pack://application:,,,/"), "./myFonts/#FontFamilyName");)
|
||||
/// </summary>
|
||||
/// <param name="baseUri">Specifies the base URI that is used to resolve familyName.</param>
|
||||
/// <param name="familyName">The family name or names that comprise the new FontFamily. Multiple family names should be separated by commas.</param>
|
||||
public static void Add(Uri baseUri, string familyName)
|
||||
{
|
||||
Uri uri = new Uri("pack://application:,,,/");
|
||||
|
||||
// TODO: What means 'Multiple family names should be separated by commas.'?
|
||||
// does not work
|
||||
|
||||
|
||||
if (String.IsNullOrEmpty(familyName))
|
||||
throw new ArgumentNullException("familyName");
|
||||
|
||||
if (familyName.Contains(","))
|
||||
throw new NotImplementedException("Only one family name is supported.");
|
||||
|
||||
// Family name starts right of '#'.
|
||||
int idxHash = familyName.IndexOf('#');
|
||||
if (idxHash < 0)
|
||||
throw new ArgumentException("Family name must contain a '#'. Example './#MyFontFamilyName'", "familyName");
|
||||
|
||||
string key = familyName.Substring(idxHash + 1);
|
||||
if (String.IsNullOrEmpty(key))
|
||||
throw new ArgumentException("familyName has invalid format.");
|
||||
|
||||
if (Singleton._fontFamilies.ContainsKey(key))
|
||||
throw new ArgumentException("An entry with the specified family name already exists.");
|
||||
|
||||
#if !SILVERLIGHT
|
||||
#if DEBUG_
|
||||
foreach (WpfFontFamily fontFamily1 in WpfFonts.GetFontFamilies(baseUri, familyName))
|
||||
{
|
||||
ICollection<WpfTypeface> wpfTypefaces = fontFamily1.GetTypefaces();
|
||||
wpfTypefaces.GetType();
|
||||
}
|
||||
#endif
|
||||
// Create WPF font family.
|
||||
WpfFontFamily fontFamily = new WpfFontFamily(baseUri, familyName);
|
||||
//System.Windows.Media.FontFamily x;
|
||||
// Required for new Uri("pack://application:,,,/")
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
// new System.Windows.Application();
|
||||
|
||||
#else
|
||||
System.Windows.Media.FontFamily fontFamily = new System.Windows.Media.FontFamily(familyName);
|
||||
#endif
|
||||
|
||||
// Check whether font data really exists
|
||||
#if DEBUG && !SILVERLIGHT
|
||||
ICollection<WpfTypeface> list = fontFamily.GetTypefaces();
|
||||
foreach (WpfTypeface typeFace in list)
|
||||
{
|
||||
Debug.WriteLine(String.Format("{0}, {1}, {2}, {3}, {4}", familyName, typeFace.FaceNames[FontHelper.XmlLanguageEnUs], typeFace.Style, typeFace.Weight, typeFace.Stretch));
|
||||
WpfGlyphTypeface glyphTypeface;
|
||||
if (!typeFace.TryGetGlyphTypeface(out glyphTypeface))
|
||||
{
|
||||
Debug.WriteLine(" Glyph typeface does not exists.");
|
||||
//throw new ArgumentException("Font with the specified family name does not exist.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Singleton._fontFamilies.Add(key, fontFamily);
|
||||
}
|
||||
#endif
|
||||
|
||||
//internal static XGlyphTypeface TryGetXGlyphTypeface(string familyName, XFontStyle style)
|
||||
//{
|
||||
// string name = MakeName(familyName, style);
|
||||
|
||||
// XGlyphTypeface typeface;
|
||||
// _global._typefaces.TryGetValue(name, out typeface);
|
||||
// return typeface;
|
||||
//}
|
||||
|
||||
#if GDI
|
||||
internal static GdiFont TryCreateFont(string name, double size, GdiFontStyle style, out XFontSource fontSource)
|
||||
{
|
||||
fontSource = null;
|
||||
try
|
||||
{
|
||||
GdiPrivateFontCollection pfc = Singleton._privateFontCollection;
|
||||
if (pfc == null)
|
||||
return null;
|
||||
#if true
|
||||
string key = MakeKey(name, (XFontStyle)style);
|
||||
if (Singleton._fontSources.TryGetValue(key, out fontSource))
|
||||
{
|
||||
GdiFont font = new GdiFont(name, (float)size, style, GraphicsUnit.World);
|
||||
#if DEBUG_
|
||||
Debug.Assert(StringComparer.OrdinalIgnoreCase.Compare(name, font.Name) == 0);
|
||||
Debug.Assert(font.Bold == ((style & GdiFontStyle.Bold) != 0));
|
||||
Debug.Assert(font.Italic == ((style & GdiFontStyle.Italic) != 0));
|
||||
#endif
|
||||
return font;
|
||||
}
|
||||
return null;
|
||||
#else
|
||||
foreach (GdiFontFamily family in pfc.Families)
|
||||
{
|
||||
if (string.Compare(family.Name, name, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
GdiFont font = new GdiFont(family, (float)size, style, GraphicsUnit.World);
|
||||
if (string.Compare(font.Name, name, StringComparison.OrdinalIgnoreCase) != 0)
|
||||
{
|
||||
// Style simulation is not implemented in GDI+.
|
||||
// Use WPF build.
|
||||
}
|
||||
return font;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Ignore exception and return null.
|
||||
Debug.WriteLine(ex.ToString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WPF && !SILVERLIGHT
|
||||
internal static WpfTypeface TryCreateTypeface(string name, XFontStyle style, out WpfFontFamily fontFamily)
|
||||
{
|
||||
if (Singleton._fontFamilies.TryGetValue(name, out fontFamily))
|
||||
{
|
||||
WpfTypeface typeface = FontHelper.CreateTypeface(fontFamily, style);
|
||||
return typeface;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
static string MakeKey(string familyName, XFontStyle style)
|
||||
{
|
||||
return MakeKey(familyName, (style & XFontStyle.Bold) != 0, (style & XFontStyle.Italic) != 0);
|
||||
}
|
||||
|
||||
static string MakeKey(string familyName, bool bold, bool italic)
|
||||
{
|
||||
return familyName + "#" + (bold ? "b" : "") + (italic ? "i" : "");
|
||||
}
|
||||
|
||||
readonly Dictionary<string, XGlyphTypeface> _typefaces = new Dictionary<string, XGlyphTypeface>();
|
||||
#if GDI
|
||||
//List<XGlyphTypeface> privateFonts = new List<XGlyphTypeface>();
|
||||
readonly Dictionary<string, XFontSource> _fontSources = new Dictionary<string, XFontSource>(StringComparer.OrdinalIgnoreCase);
|
||||
#endif
|
||||
#if WPF
|
||||
readonly Dictionary<string, WpfFontFamily> _fontFamilies = new Dictionary<string, WpfFontFamily>(StringComparer.OrdinalIgnoreCase);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user