This commit is contained in:
2021-05-25 17:00:45 +05:00
parent e2fcfed44c
commit ec2dac13d8
1172 changed files with 5636 additions and 5839 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
#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.Diagnostics;
using System.Collections.Generic;
using PdfSharp.Fonts.OpenType;
using PdfSharp.Pdf.Internal;
namespace PdfSharp.Fonts
{
/// <summary>
/// Helper class that determines the characters used in a particular font.
/// </summary>
internal class CMapInfo
{
public CMapInfo(OpenTypeDescriptor descriptor)
{
Debug.Assert(descriptor != null);
_descriptor = descriptor;
}
internal OpenTypeDescriptor _descriptor;
/// <summary>
/// Adds the characters of the specified string to the hashtable.
/// </summary>
public void AddChars(string text)
{
if (text != null)
{
bool symbol = _descriptor.FontFace.cmap.symbol;
int length = text.Length;
for (int idx = 0; idx < length; idx++)
{
char ch = text[idx];
if (!CharacterToGlyphIndex.ContainsKey(ch))
{
char ch2 = ch;
if (symbol)
{
// Remap ch for symbol fonts.
ch2 = (char)(ch | (_descriptor.FontFace.os2.usFirstCharIndex & 0xFF00)); // @@@ refactor
}
int glyphIndex = _descriptor.CharCodeToGlyphIndex(ch2);
CharacterToGlyphIndex.Add(ch, glyphIndex);
GlyphIndices[glyphIndex] = null;
MinChar = (char)Math.Min(MinChar, ch);
MaxChar = (char)Math.Max(MaxChar, ch);
}
}
}
}
/// <summary>
/// Adds the glyphIndices to the hashtable.
/// </summary>
public void AddGlyphIndices(string glyphIndices)
{
if (glyphIndices != null)
{
int length = glyphIndices.Length;
for (int idx = 0; idx < length; idx++)
{
int glyphIndex = glyphIndices[idx];
GlyphIndices[glyphIndex] = null;
}
}
}
/// <summary>
/// Adds a ANSI characters.
/// </summary>
internal void AddAnsiChars()
{
byte[] ansi = new byte[256 - 32];
for (int idx = 0; idx < 256 - 32; idx++)
ansi[idx] = (byte)(idx + 32);
#if EDF_CORE
string text = null; // PdfEncoders.WinAnsiEncoding.GetString(ansi, 0, ansi.Length);
#else
string text = PdfEncoders.WinAnsiEncoding.GetString(ansi, 0, ansi.Length);
#endif
AddChars(text);
}
internal bool Contains(char ch)
{
return CharacterToGlyphIndex.ContainsKey(ch);
}
public char[] Chars
{
get
{
char[] chars = new char[CharacterToGlyphIndex.Count];
CharacterToGlyphIndex.Keys.CopyTo(chars, 0);
Array.Sort(chars);
return chars;
}
}
public int[] GetGlyphIndices()
{
int[] indices = new int[GlyphIndices.Count];
GlyphIndices.Keys.CopyTo(indices, 0);
Array.Sort(indices);
return indices;
}
public char MinChar = char.MaxValue;
public char MaxChar = char.MinValue;
public Dictionary<char, int> CharacterToGlyphIndex = new Dictionary<char, int>();
public Dictionary<int, object> GlyphIndices = new Dictionary<int, object>();
}
}

View File

@@ -0,0 +1,174 @@
#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 PdfSharp.Drawing;
using PdfSharp.Fonts.OpenType;
using PdfSharp.Internal;
namespace PdfSharp.Fonts
{
/// <summary>
/// Global table of OpenType font descriptor objects.
/// </summary>
internal sealed class FontDescriptorCache
{
FontDescriptorCache()
{
_cache = new Dictionary<string, FontDescriptor>();
}
///// <summary>
///// Gets the FontDescriptor identified by the specified FontSelector. If no such object
///// exists, a new FontDescriptor is created and added to the stock.
///// </summary>
//public static FontDescriptor GetOrCreateDescriptor_DEL-ETE(string familyName, XFontStyle stlye, OpenTypeFontface fontface)
//{
// //FontSelector1 selector = new FontSelector1(familyName, stlye);
// string fontDescriptorKey = null; // FontDescriptor.ComputeKey(familyName, stlye);
// try
// {
// Lock.EnterFontFactory();
// FontDescriptor descriptor;
// if (!Singleton._cache.TryGetValue(fontDescriptorKey, out descriptor))
// {
// descriptor = new OpenTypeDescriptor(fontDescriptorKey, familyName, stlye, fontface, null);
// Singleton._cache.Add(fontDescriptorKey, descriptor);
// }
// return descriptor;
// }
// finally { Lock.ExitFontFactory(); }
//}
/// <summary>
/// Gets the FontDescriptor identified by the specified XFont. If no such object
/// exists, a new FontDescriptor is created and added to the cache.
/// </summary>
public static FontDescriptor GetOrCreateDescriptorFor(XFont font)
{
if (font == null)
throw new ArgumentNullException("font");
//FontSelector1 selector = new FontSelector1(font);
string fontDescriptorKey = FontDescriptor.ComputeKey(font);
try
{
Lock.EnterFontFactory();
FontDescriptor descriptor;
if (!Singleton._cache.TryGetValue(fontDescriptorKey, out descriptor))
{
descriptor = new OpenTypeDescriptor(fontDescriptorKey, font);
Singleton._cache.Add(fontDescriptorKey, descriptor);
}
return descriptor;
}
finally { Lock.ExitFontFactory(); }
}
/// <summary>
/// Gets the FontDescriptor identified by the specified FontSelector. If no such object
/// exists, a new FontDescriptor is created and added to the stock.
/// </summary>
public static FontDescriptor GetOrCreateDescriptor(string fontFamilyName, XFontStyle style)
{
if (string.IsNullOrEmpty(fontFamilyName))
throw new ArgumentNullException("fontFamilyName");
//FontSelector1 selector = new FontSelector1(fontFamilyName, style);
string fontDescriptorKey = FontDescriptor.ComputeKey(fontFamilyName, style);
try
{
Lock.EnterFontFactory();
FontDescriptor descriptor;
if (!Singleton._cache.TryGetValue(fontDescriptorKey, out descriptor))
{
XFont font = new XFont(fontFamilyName, 10, style);
descriptor = GetOrCreateDescriptorFor(font);
if (Singleton._cache.ContainsKey(fontDescriptorKey))
Singleton.GetType();
else
Singleton._cache.Add(fontDescriptorKey, descriptor);
}
return descriptor;
}
finally { Lock.ExitFontFactory(); }
}
public static FontDescriptor GetOrCreateDescriptor(string idName, byte[] fontData)
{
//FontSelector1 selector = new FontSelector1(idName);
string fontDescriptorKey = FontDescriptor.ComputeKey(idName);
try
{
Lock.EnterFontFactory();
FontDescriptor descriptor;
if (!Singleton._cache.TryGetValue(fontDescriptorKey, out descriptor))
{
descriptor = GetOrCreateOpenTypeDescriptor(fontDescriptorKey, idName, fontData);
Singleton._cache.Add(fontDescriptorKey, descriptor);
}
return descriptor;
}
finally { Lock.ExitFontFactory(); }
}
static OpenTypeDescriptor GetOrCreateOpenTypeDescriptor(string fontDescriptorKey, string idName, byte[] fontData)
{
return new OpenTypeDescriptor(fontDescriptorKey, idName, fontData);
}
/// <summary>
/// Gets the singleton.
/// </summary>
static FontDescriptorCache Singleton
{
get
{
if (_singleton == null)
{
try
{
Lock.EnterFontFactory();
if (_singleton == null)
_singleton = new FontDescriptorCache();
}
finally { Lock.ExitFontFactory(); }
}
return _singleton;
}
}
static volatile FontDescriptorCache _singleton;
/// <summary>
/// Maps font font descriptor key to font descriptor.
/// </summary>
readonly Dictionary<string, FontDescriptor> _cache;
}
}

View File

@@ -0,0 +1,450 @@
#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.Diagnostics;
using System.Collections.Generic;
using System.Text;
#if CORE || GDI
using System.Drawing;
using GdiFontFamily = System.Drawing.FontFamily;
using GdiFont = System.Drawing.Font;
#endif
#if WPF
using System.Windows;
using System.Windows.Media;
using System.Windows.Resources;
using WpfFontFamily = System.Windows.Media.FontFamily;
using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface;
using WpfTypeface = System.Windows.Media.Typeface;
#endif
using PdfSharp.Drawing;
using PdfSharp.Fonts.OpenType;
using PdfSharp.Internal;
#pragma warning disable 1591
// ReSharper disable RedundantNameQualifier
namespace PdfSharp.Fonts
{
/// <summary>
/// Provides functionality to map a fontface request to a physical font.
/// </summary>
internal static class FontFactory
{
//// Suffix for internal face names to indicate that the font data comes from the platform
//// and not from the users font resolver.
//public const string PlatformTag = "platform:";
/// <summary>
/// Converts specified information about a required typeface into a specific font.
/// </summary>
/// <param name="familyName">Name of the font family.</param>
/// <param name="fontResolvingOptions">The font resolving options.</param>
/// <param name="typefaceKey">Typeface key if already known by caller, null otherwise.</param>
/// <returns>
/// Information about the typeface, or null if no typeface can be found.
/// </returns>
public static FontResolverInfo ResolveTypeface(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey)
{
if (string.IsNullOrEmpty(typefaceKey))
typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions);
try
{
Lock.EnterFontFactory();
// Was this typeface requested before?
FontResolverInfo fontResolverInfo;
if (FontResolverInfosByName.TryGetValue(typefaceKey, out fontResolverInfo))
return fontResolverInfo;
// Case: This typeface was not yet resolved before.
// Is there a custom font resolver available?
IFontResolver customFontResolver = GlobalFontSettings.FontResolver;
if (customFontResolver != null)
{
// Case: Use custom font resolver.
fontResolverInfo = customFontResolver.ResolveTypeface(familyName, fontResolvingOptions.IsBold, fontResolvingOptions.IsItalic);
// If resolved by custom font resolver register info and font source.
if (fontResolverInfo != null && !(fontResolverInfo is PlatformFontResolverInfo))
{
// OverrideStyleSimulations is true only for internal quality tests.
if (fontResolvingOptions.OverrideStyleSimulations)
{
// Override style simulation returned by custom font resolver.
fontResolverInfo = new FontResolverInfo(fontResolverInfo.FaceName, fontResolvingOptions.MustSimulateBold, fontResolvingOptions.MustSimulateItalic, fontResolverInfo.CollectionNumber);
}
string resolverInfoKey = fontResolverInfo.Key;
FontResolverInfo existingFontResolverInfo;
if (FontResolverInfosByName.TryGetValue(resolverInfoKey, out existingFontResolverInfo))
{
// Case: A new typeface was resolved with the same info as a previous one.
// Discard new object an reuse previous one.
fontResolverInfo = existingFontResolverInfo;
// Associate with typeface key.
FontResolverInfosByName.Add(typefaceKey, fontResolverInfo);
#if DEBUG
// The font source should exist.
Debug.Assert(FontSourcesByName.ContainsKey(fontResolverInfo.FaceName));
#endif
}
else
{
// Case: No such font resolver info exists.
// Add to both dictionaries.
FontResolverInfosByName.Add(typefaceKey, fontResolverInfo);
Debug.Assert(resolverInfoKey == fontResolverInfo.Key);
FontResolverInfosByName.Add(resolverInfoKey, fontResolverInfo);
// Create font source if not yet exists.
XFontSource previousFontSource;
if (FontSourcesByName.TryGetValue(fontResolverInfo.FaceName, out previousFontSource))
{
// Case: The font source exists, because a previous font resolver info comes
// with the same face name, but was different in style simulation flags.
// Nothing to do.
}
else
{
// Case: Get font from custom font resolver and create font source.
byte[] bytes = customFontResolver.GetFont(fontResolverInfo.FaceName);
XFontSource fontSource = XFontSource.GetOrCreateFrom(bytes);
// Add font source's font resolver name if it is different to the face name.
if (string.Compare(fontResolverInfo.FaceName, fontSource.FontName, StringComparison.OrdinalIgnoreCase) != 0)
FontSourcesByName.Add(fontResolverInfo.FaceName, fontSource);
}
}
}
}
else
{
// Case: There was no custom font resolver set.
// Use platform font resolver.
// If it was successful resolver info and font source are cached
// automatically by PlatformFontResolver.ResolveTypeface.
fontResolverInfo = PlatformFontResolver.ResolveTypeface(familyName, fontResolvingOptions, typefaceKey);
}
// Return value is null if the typeface could not be resolved.
// In this case PDFsharp stops.
return fontResolverInfo;
}
finally { Lock.ExitFontFactory(); }
}
#if GDI
/// <summary>
/// Registers the font face.
/// </summary>
public static XFontSource RegisterFontFace(byte[] fontBytes)
{
try
{
Lock.EnterFontFactory();
ulong key = FontHelper.CalcChecksum(fontBytes);
XFontSource fontSource;
if (FontSourcesByKey.TryGetValue(key, out fontSource))
{
throw new InvalidOperationException("Font face already registered.");
}
fontSource = XFontSource.GetOrCreateFrom(fontBytes);
Debug.Assert(FontSourcesByKey.ContainsKey(key));
Debug.Assert(fontSource.Fontface != null);
//fontSource.Fontface = new OpenTypeFontface(fontSource);
//FontSourcesByKey.Add(checksum, fontSource);
//FontSourcesByFontName.Add(fontSource.FontName, fontSource);
XGlyphTypeface glyphTypeface = new XGlyphTypeface(fontSource);
FontSourcesByName.Add(glyphTypeface.Key, fontSource);
GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface);
return fontSource;
}
finally { Lock.ExitFontFactory(); }
}
#endif
/// <summary>
/// Gets the bytes of a physical font with specified face name.
/// </summary>
public static XFontSource GetFontSourceByFontName(string fontName)
{
XFontSource fontSource;
if (FontSourcesByName.TryGetValue(fontName, out fontSource))
return fontSource;
Debug.Assert(false, string.Format("An XFontSource with the name '{0}' does not exists.", fontName));
return null;
}
/// <summary>
/// Gets the bytes of a physical font with specified face name.
/// </summary>
public static XFontSource GetFontSourceByTypefaceKey(string typefaceKey)
{
XFontSource fontSource;
if (FontSourcesByName.TryGetValue(typefaceKey, out fontSource))
return fontSource;
Debug.Assert(false, string.Format("An XFontSource with the typeface key '{0}' does not exists.", typefaceKey));
return null;
}
public static bool TryGetFontSourceByKey(ulong key, out XFontSource fontSource)
{
return FontSourcesByKey.TryGetValue(key, out fontSource);
}
/// <summary>
/// Gets a value indicating whether at least one font source was created.
/// </summary>
public static bool HasFontSources
{
get { return FontSourcesByName.Count > 0; }
}
public static bool TryGetFontResolverInfoByTypefaceKey(string typeFaceKey, out FontResolverInfo info)
{
return FontResolverInfosByName.TryGetValue(typeFaceKey, out info);
}
public static bool TryGetFontSourceByTypefaceKey(string typefaceKey, out XFontSource source)
{
return FontSourcesByName.TryGetValue(typefaceKey, out source);
}
//public static bool TryGetFontSourceByFaceName(string faceName, out XFontSource source)
//{
// return FontSourcesByName.TryGetValue(faceName, out source);
//}
internal static void CacheFontResolverInfo(string typefaceKey, FontResolverInfo fontResolverInfo)
{
FontResolverInfo existingfFontResolverInfo;
// Check whether identical font is already registered.
if (FontResolverInfosByName.TryGetValue(typefaceKey, out existingfFontResolverInfo))
{
// Should never come here.
throw new InvalidOperationException(string.Format("A font file with different content already exists with the specified face name '{0}'.", typefaceKey));
}
if (FontResolverInfosByName.TryGetValue(fontResolverInfo.Key, out existingfFontResolverInfo))
{
// Should never come here.
throw new InvalidOperationException(string.Format("A font resolver already exists with the specified key '{0}'.", fontResolverInfo.Key));
}
// Add to both dictionaries.
FontResolverInfosByName.Add(typefaceKey, fontResolverInfo);
FontResolverInfosByName.Add(fontResolverInfo.Key, fontResolverInfo);
}
/// <summary>
/// Caches a font source under its face name and its key.
/// </summary>
public static XFontSource CacheFontSource(XFontSource fontSource)
{
try
{
Lock.EnterFontFactory();
// Check whether an identical font source with a different face name already exists.
XFontSource existingFontSource;
if (FontSourcesByKey.TryGetValue(fontSource.Key, out existingFontSource))
{
#if DEBUG
// Fonts have same length and check sum. Now check byte by byte identity.
int length = fontSource.Bytes.Length;
for (int idx = 0; idx < length; idx++)
{
if (existingFontSource.Bytes[idx] != fontSource.Bytes[idx])
{
//Debug.Assert(false,"Two fonts with identical checksum found.");
break;
//goto FontsAreNotIdentical;
}
}
Debug.Assert(existingFontSource.Fontface != null);
#endif
return existingFontSource;
//FontsAreNotIdentical:
//// Incredible rare case: Two different fonts have the same size and check sum.
//// Give the new one a new key until it do not clash with an existing one.
//while (FontSourcesByKey.ContainsKey(fontSource.Key))
// fontSource.IncrementKey();
}
OpenTypeFontface fontface = fontSource.Fontface;
if (fontface == null)
{
// Create OpenType fontface for this font source.
fontSource.Fontface = new OpenTypeFontface(fontSource);
}
FontSourcesByKey.Add(fontSource.Key, fontSource);
FontSourcesByName.Add(fontSource.FontName, fontSource);
return fontSource;
}
finally { Lock.ExitFontFactory(); }
}
/// <summary>
/// Caches a font source under its face name and its key.
/// </summary>
public static XFontSource CacheNewFontSource(string typefaceKey, XFontSource fontSource)
{
// Debug.Assert(!FontSourcesByFaceName.ContainsKey(fontSource.FaceName));
// Check whether an identical font source with a different face name already exists.
XFontSource existingFontSource;
if (FontSourcesByKey.TryGetValue(fontSource.Key, out existingFontSource))
{
//// Fonts have same length and check sum. Now check byte by byte identity.
//int length = fontSource.Bytes.Length;
//for (int idx = 0; idx < length; idx++)
//{
// if (existingFontSource.Bytes[idx] != fontSource.Bytes[idx])
// {
// goto FontsAreNotIdentical;
// }
//}
return existingFontSource;
////// The bytes are really identical. Register font source again with the new face name
////// but return the existing one to save memory.
////FontSourcesByFaceName.Add(fontSource.FaceName, existingFontSource);
////return existingFontSource;
//FontsAreNotIdentical:
//// Incredible rare case: Two different fonts have the same size and check sum.
//// Give the new one a new key until it do not clash with an existing one.
//while (FontSourcesByKey.ContainsKey(fontSource.Key))
// fontSource.IncrementKey();
}
OpenTypeFontface fontface = fontSource.Fontface;
if (fontface == null)
{
fontface = new OpenTypeFontface(fontSource);
fontSource.Fontface = fontface; // Also sets the font name in fontSource
}
FontSourcesByName.Add(typefaceKey, fontSource);
FontSourcesByName.Add(fontSource.FontName, fontSource);
FontSourcesByKey.Add(fontSource.Key, fontSource);
return fontSource;
}
public static void CacheExistingFontSourceWithNewTypefaceKey(string typefaceKey, XFontSource fontSource)
{
try
{
Lock.EnterFontFactory();
FontSourcesByName.Add(typefaceKey, fontSource);
}
finally { Lock.ExitFontFactory(); }
}
internal static string GetFontCachesState()
{
StringBuilder state = new StringBuilder();
string[] keys;
int count;
// FontResolverInfo by name.
state.Append("====================\n");
state.Append("Font resolver info by name\n");
Dictionary<string, FontResolverInfo>.KeyCollection keyCollection = FontResolverInfosByName.Keys;
count = keyCollection.Count;
keys = new string[count];
keyCollection.CopyTo(keys, 0);
Array.Sort(keys, StringComparer.OrdinalIgnoreCase);
foreach (string key in keys)
state.AppendFormat(" {0}: {1}\n", key, FontResolverInfosByName[key].DebuggerDisplay);
state.Append("\n");
// FontSource by key.
state.Append("Font source by key and name\n");
Dictionary<ulong, XFontSource>.KeyCollection fontSourceKeys = FontSourcesByKey.Keys;
count = fontSourceKeys.Count;
ulong[] ulKeys = new ulong[count];
fontSourceKeys.CopyTo(ulKeys, 0);
Array.Sort(ulKeys, delegate (ulong x, ulong y) { return x == y ? 0 : (x > y ? 1 : -1); });
foreach (ulong ul in ulKeys)
state.AppendFormat(" {0}: {1}\n", ul, FontSourcesByKey[ul].DebuggerDisplay);
Dictionary<string, XFontSource>.KeyCollection fontSourceNames = FontSourcesByName.Keys;
count = fontSourceNames.Count;
keys = new string[count];
fontSourceNames.CopyTo(keys, 0);
Array.Sort(keys, StringComparer.OrdinalIgnoreCase);
foreach (string key in keys)
state.AppendFormat(" {0}: {1}\n", key, FontSourcesByName[key].DebuggerDisplay);
state.Append("--------------------\n\n");
// FontFamilyInternal by name.
state.Append(FontFamilyCache.GetCacheState());
// XGlyphTypeface by name.
state.Append(GlyphTypefaceCache.GetCacheState());
// OpenTypeFontface by name.
state.Append(OpenTypeFontfaceCache.GetCacheState());
return state.ToString();
}
// TODO: Move to ctor
/// <summary>
/// Maps font typeface key to font resolver info.
/// </summary>
//static readonly Dictionary<string, FontResolverInfo> FontResolverInfosByTypefaceKey = new Dictionary<string, FontResolverInfo>(StringComparer.OrdinalIgnoreCase);
static readonly Dictionary<string, FontResolverInfo> FontResolverInfosByName = new Dictionary<string, FontResolverInfo>(StringComparer.OrdinalIgnoreCase);
///// <summary>
///// Maps font resolver info key to font resolver info.
///// </summary>
//static readonly Dictionary<string, FontResolverInfo> FontResolverInfosByKey = new Dictionary<string, FontResolverInfo>();
/// <summary>
/// Maps typeface key or font name to font source.
/// </summary>
//static readonly Dictionary<string, XFontSource> FontSourcesByTypefaceKey = new Dictionary<string, XFontSource>(StringComparer.OrdinalIgnoreCase);
static readonly Dictionary<string, XFontSource> FontSourcesByName = new Dictionary<string, XFontSource>(StringComparer.OrdinalIgnoreCase);
///// <summary>
///// Maps font name to font source.
///// </summary>
//static readonly Dictionary<string, XFontSource> FontSourcesByFontName = new Dictionary<string, XFontSource>();
/// <summary>
/// Maps font source key to font source.
/// </summary>
static readonly Dictionary<ulong, XFontSource> FontSourcesByKey = new Dictionary<ulong, XFontSource>();
}
}

View File

@@ -0,0 +1,211 @@
#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.Diagnostics;
using System.Globalization;
using PdfSharp.Drawing;
#if CORE
using System.Drawing;
#endif
#if GDI
using System.Drawing;
#endif
#if WPF
using System.Windows.Media;
#endif
namespace PdfSharp.Fonts
{
// The English terms font, font family, typeface, glyph etc. are sometimes confusingly used.
// Here a short clarification by Wikipedia.
//
// Wikipedia EN -> DE
// Font -> Schriftschnitt
// Computer font -> Font (Informationstechnik)
// Typeface (Font family) -> Schriftart / Schriftfamilie
// Glyph -> Glyphe
//
// It seems that typeface and font family are synonyms in English.
// In WPF a family name is used as a term for a bunch of fonts that share the same
// characteristics, like Univers or Times New Roman.
// In WPF a fontface describes a request of a font of a particular font family, e.g.
// Univers medium bold italic.
// In WPF a glyph typeface is the result of requesting a typeface, i.e. a physical font
// plus the information whether bold and/or italic should be simulated.
//
// Wikipedia DE -> EN
// Schriftart -> Typeface
// Schriftschnitt -> Font
// Schriftfamilie -> ~ (means Font family)
// Schriftsippe -> Font superfamily
// Font -> Computer font
//
// http://en.wikipedia.org/wiki/Font
// http://en.wikipedia.org/wiki/Computer_font
// http://en.wikipedia.org/wiki/Typeface
// http://en.wikipedia.org/wiki/Glyph
// http://en.wikipedia.org/wiki/Typographic_unit
//
// FaceName: A unique and only internally used name of a glyph typeface. In other words the name of the font data that represents a specific font.
//
//
/// <summary>
/// Describes the physical font that must be used to render a particular XFont.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay}")]
public class FontResolverInfo
{
private const string KeyPrefix = "frik:"; // Font Resolver Info Key
/// <summary>
/// Initializes a new instance of the <see cref="FontResolverInfo"/> struct.
/// </summary>
/// <param name="faceName">The name that uniquely identifies the fontface.</param>
public FontResolverInfo(string faceName) :
this(faceName, false, false, 0)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="FontResolverInfo"/> struct.
/// </summary>
/// <param name="faceName">The name that uniquely identifies the fontface.</param>
/// <param name="mustSimulateBold">Set to <c>true</c> to simulate bold when rendered. Not implemented and must be false.</param>
/// <param name="mustSimulateItalic">Set to <c>true</c> to simulate italic when rendered.</param>
/// <param name="collectionNumber">Index of the font in a true type font collection.
/// Not yet implemented and must be zero.
/// </param>
internal FontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic, int collectionNumber)
{
if (String.IsNullOrEmpty(faceName))
throw new ArgumentNullException("faceName");
if (collectionNumber != 0)
throw new NotImplementedException("collectionNumber is not yet implemented and must be 0.");
_faceName = faceName;
_mustSimulateBold = mustSimulateBold;
_mustSimulateItalic = mustSimulateItalic;
_collectionNumber = collectionNumber;
}
/// <summary>
/// Initializes a new instance of the <see cref="FontResolverInfo"/> struct.
/// </summary>
/// <param name="faceName">The name that uniquely identifies the fontface.</param>
/// <param name="mustSimulateBold">Set to <c>true</c> to simulate bold when rendered. Not implemented and must be false.</param>
/// <param name="mustSimulateItalic">Set to <c>true</c> to simulate italic when rendered.</param>
public FontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic)
: this(faceName, mustSimulateBold, mustSimulateItalic, 0)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="FontResolverInfo" /> struct.
/// </summary>
/// <param name="faceName">The name that uniquely identifies the fontface.</param>
/// <param name="styleSimulations">The style simulation flags.</param>
public FontResolverInfo(string faceName, XStyleSimulations styleSimulations)
: this(faceName,
(styleSimulations & XStyleSimulations.BoldSimulation) == XStyleSimulations.BoldSimulation,
(styleSimulations & XStyleSimulations.ItalicSimulation) == XStyleSimulations.ItalicSimulation, 0)
{ }
/// <summary>
/// Gets the key for this object.
/// </summary>
internal string Key
{
get
{
return _key ?? (_key = KeyPrefix + _faceName.ToLowerInvariant()
+ '/' + (_mustSimulateBold ? "b+" : "b-") + (_mustSimulateItalic ? "i+" : "i-"));
}
}
string _key;
/// <summary>
/// A name that uniquely identifies the font (not the family), e.g. the file name of the font. PDFsharp does not use this
/// name internally, but passes it to the GetFont function of the IFontResolver interface to retrieve the font data.
/// </summary>
public string FaceName
{
get { return _faceName; }
}
readonly string _faceName;
/// <summary>
/// Indicates whether bold must be simulated. Bold simulation is not implemented in PDFsharp.
/// </summary>
public bool MustSimulateBold
{
get { return _mustSimulateBold; }
}
readonly bool _mustSimulateBold;
/// <summary>
/// Indicates whether italic must be simulated.
/// </summary>
public bool MustSimulateItalic
{
get { return _mustSimulateItalic; }
}
readonly bool _mustSimulateItalic;
/// <summary>
/// Gets the style simulation flags.
/// </summary>
public XStyleSimulations StyleSimulations
{
get { return (_mustSimulateBold ? XStyleSimulations.BoldSimulation : 0) | (_mustSimulateItalic ? XStyleSimulations.ItalicSimulation : 0); }
}
/// <summary>
/// The number of the font in a Truetype font collection file. The number of the first font is 0.
/// NOT YET IMPLEMENTED. Must be zero.
/// </summary>
internal int CollectionNumber // TODO : Find a better name.
{
get { return _collectionNumber; }
}
readonly int _collectionNumber;
/// <summary>
/// Gets the DebuggerDisplayAttribute text.
/// </summary>
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "FontResolverInfo: '{0}',{1}{2}", FaceName,
MustSimulateBold ? " simulate Bold" : "",
MustSimulateItalic ? " simulate Italic" : "");
}
}
}
}

View File

@@ -0,0 +1,89 @@
#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
#if GDI
using System.Drawing;
using System.Drawing.Text;
#endif
#if WPF
using System.Windows.Media;
#endif
using PdfSharp.Drawing;
namespace PdfSharp.Fonts
{
/// <summary>
/// Parameters that affect font selection.
/// </summary>
class FontResolvingOptions
{
public FontResolvingOptions(XFontStyle fontStyle)
{
FontStyle = fontStyle;
}
public FontResolvingOptions(XFontStyle fontStyle, XStyleSimulations styleSimulations)
{
FontStyle = fontStyle;
OverrideStyleSimulations = true;
StyleSimulations = styleSimulations;
}
public bool IsBold
{
get { return (FontStyle & XFontStyle.Bold) == XFontStyle.Bold; }
}
public bool IsItalic
{
get { return (FontStyle & XFontStyle.Italic) == XFontStyle.Italic; }
}
public bool IsBoldItalic
{
get { return (FontStyle & XFontStyle.BoldItalic) == XFontStyle.BoldItalic; }
}
public bool MustSimulateBold
{
get { return (StyleSimulations & XStyleSimulations.BoldSimulation) == XStyleSimulations.BoldSimulation; }
}
public bool MustSimulateItalic
{
get { return (StyleSimulations & XStyleSimulations.ItalicSimulation) == XStyleSimulations.ItalicSimulation; }
}
public XFontStyle FontStyle;
public bool OverrideStyleSimulations;
public XStyleSimulations StyleSimulations;
}
}

View File

@@ -0,0 +1,176 @@
#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.IO;
namespace PdfSharp.Fonts
{
/// <summary>
/// Represents a writer for generation of font file streams.
/// </summary>
internal class FontWriter
{
/// <summary>
/// Initializes a new instance of the <see cref="FontWriter"/> class.
/// Data is written in Motorola format (big-endian).
/// </summary>
public FontWriter(Stream stream)
{
_stream = stream;
}
/// <summary>
/// Closes the writer and, if specified, the underlying stream.
/// </summary>
public void Close(bool closeUnderlyingStream)
{
if (_stream != null && closeUnderlyingStream)
{
#if !UWP
_stream.Close();
#endif
_stream.Dispose();
}
_stream = null;
}
/// <summary>
/// Closes the writer and the underlying stream.
/// </summary>
public void Close()
{
Close(true);
}
/// <summary>
/// Gets or sets the position within the stream.
/// </summary>
public int Position
{
get { return (int)_stream.Position; }
set { _stream.Position = value; }
}
/// <summary>
/// Writes the specified value to the font stream.
/// </summary>
public void WriteByte(byte value)
{
_stream.WriteByte(value);
}
/// <summary>
/// Writes the specified value to the font stream.
/// </summary>
public void WriteByte(int value)
{
_stream.WriteByte((byte)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteShort(short value)
{
_stream.WriteByte((byte)(value >> 8));
_stream.WriteByte((byte)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteShort(int value)
{
WriteShort((short)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteUShort(ushort value)
{
_stream.WriteByte((byte)(value >> 8));
_stream.WriteByte((byte)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteUShort(int value)
{
WriteUShort((ushort)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteInt(int value)
{
_stream.WriteByte((byte)(value >> 24));
_stream.WriteByte((byte)(value >> 16));
_stream.WriteByte((byte)(value >> 8));
_stream.WriteByte((byte)value);
}
/// <summary>
/// Writes the specified value to the font stream using big-endian.
/// </summary>
public void WriteUInt(uint value)
{
_stream.WriteByte((byte)(value >> 24));
_stream.WriteByte((byte)(value >> 16));
_stream.WriteByte((byte)(value >> 8));
_stream.WriteByte((byte)value);
}
//public short ReadFWord()
//public ushort ReadUFWord()
//public long ReadLongDate()
//public string ReadString(int size)
public void Write(byte[] buffer)
{
_stream.Write(buffer, 0, buffer.Length);
}
public void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}
/// <summary>
/// Gets the underlying stream.
/// </summary>
internal Stream Stream
{
get { return _stream; }
}
Stream _stream;
}
}

View File

@@ -0,0 +1,116 @@
#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 PdfSharp.Internal;
using PdfSharp.Pdf;
namespace PdfSharp.Fonts
{
/// <summary>
/// Provides functionality to specify information about the handling of fonts in the current application domain.
/// </summary>
public static class GlobalFontSettings
{
/// <summary>
/// The name of the default font.
/// </summary>
public const string DefaultFontName = "PlatformDefault";
/// <summary>
/// Gets or sets the global font resolver for the current application domain.
/// This static function must be called only once and before any font operation was executed by PDFsharp.
/// If this is not easily to obtain, e.g. because your code is running on a web server, you must provide the
/// same instance of your font resolver in every subsequent setting of this property.
/// In a web application set the font resolver in Global.asax.
/// </summary>
public static IFontResolver FontResolver
{
get { return _fontResolver; }
set
{
// Cannot remove font resolver.
if (value == null)
throw new ArgumentNullException();
try
{
Lock.EnterFontFactory();
// Ignore multiple setting e.g. in a web application.
if (ReferenceEquals(_fontResolver, value))
return;
if (FontFactory.HasFontSources)
throw new InvalidOperationException("Must not change font resolver after is was once used.");
_fontResolver = value;
}
finally { Lock.ExitFontFactory(); }
}
}
static IFontResolver _fontResolver;
/// <summary>
/// Gets or sets the default font encoding used for XFont objects where encoding is not explicitly specified.
/// If it is not set, the default value is PdfFontEncoding.Unicode.
/// If you are sure your document contains only Windows-1252 characters (see https://en.wikipedia.org/wiki/Windows-1252)
/// set default encoding to PdfFontEncodingj.Windows1252.
/// Must be set only once per app domain.
/// </summary>
public static PdfFontEncoding DefaultFontEncoding
{
get
{
if (!_fontEncodingInitialized)
DefaultFontEncoding = PdfFontEncoding.Unicode;
return _fontEncoding;
}
set
{
try
{
Lock.EnterFontFactory();
if (_fontEncodingInitialized)
{
// Ignore multiple setting e.g. in a web application.
if (_fontEncoding == value)
return;
throw new InvalidOperationException("Must not change DefaultFontEncoding after is was set once.");
}
_fontEncoding = value;
_fontEncodingInitialized = true;
}
finally { Lock.ExitFontFactory(); }
}
}
static PdfFontEncoding _fontEncoding;
static bool _fontEncodingInitialized;
}
}

View File

@@ -0,0 +1,54 @@
#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
namespace PdfSharp.Fonts
{
/// <summary>
/// Provides functionality that converts a requested typeface into a physical font.
/// </summary>
public interface IFontResolver
{
/// <summary>
/// Converts specified information about a required typeface into a specific font.
/// </summary>
/// <param name="familyName">Name of the font family.</param>
/// <param name="isBold">Set to <c>true</c> when a bold fontface is required.</param>
/// <param name="isItalic">Set to <c>true</c> when an italic fontface is required.</param>
/// <returns>Information about the physical font, or null if the request cannot be satisfied.</returns>
FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic);
//FontResolverInfo ResolveTypeface(Typeface); TODO in PDFsharp 2.0
/// <summary>
/// Gets the bytes of a physical font with specified face name.
/// </summary>
/// <param name="faceName">A face name previously retrieved by ResolveTypeface.</param>
byte[] GetFont(string faceName);
}
}

View File

@@ -0,0 +1,337 @@
#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.Diagnostics;
#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;
#endif
#if WPF
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using WpfFontFamily = System.Windows.Media.FontFamily;
using WpfTypeface = System.Windows.Media.Typeface;
using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface;
using WpfStyleSimulations = System.Windows.Media.StyleSimulations;
#endif
using PdfSharp.Drawing;
#pragma warning disable 1591
// ReSharper disable RedundantNameQualifier
namespace PdfSharp.Fonts
{
/// <summary>
/// Default platform specific font resolving.
/// </summary>
public static class PlatformFontResolver
{
/// <summary>
/// Resolves the typeface by generating a font resolver info.
/// </summary>
/// <param name="familyName">Name of the font family.</param>
/// <param name="isBold">Indicates whether a bold font is requested.</param>
/// <param name="isItalic">Indicates whether an italic font is requested.</param>
public static FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
FontResolvingOptions fontResolvingOptions = new FontResolvingOptions(FontHelper.CreateStyle(isBold, isItalic));
return ResolveTypeface(familyName, fontResolvingOptions, XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions));
}
/// <summary>
/// Internal implementation.
/// </summary>
internal static FontResolverInfo ResolveTypeface(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey)
{
// Internally we often have the typeface key already.
if (string.IsNullOrEmpty(typefaceKey))
typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions);
// The user may call ResolveTypeface anytime from anywhere, so check cache in FontFactory in the first place.
FontResolverInfo fontResolverInfo;
if (FontFactory.TryGetFontResolverInfoByTypefaceKey(typefaceKey, out fontResolverInfo))
return fontResolverInfo;
// Let the platform create the requested font source and save both PlattformResolverInfo
// and XFontSource in FontFactory cache.
// It is possible that we already have the correct font source. E.g. we already have the regular typeface in cache
// and looking now for the italic typeface, but no such font exists. In this case we get the regular font source
// and cache again it with the italic typeface key. Furthermore in glyph typeface style simulation for italic is set.
#if (CORE || GDI) && !WPF
GdiFont gdiFont;
XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, out gdiFont, typefaceKey);
#endif
#if WPF && !SILVERLIGHT
WpfFontFamily wpfFontFamily;
WpfTypeface wpfTypeface;
WpfGlyphTypeface wpfGlyphTypeface;
XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, out wpfFontFamily, out wpfTypeface, out wpfGlyphTypeface, typefaceKey);
#endif
#if SILVERLIGHT
//GlyphTypeface wpfGlyphTypeface;
XFontSource fontSource = null;//CreateFontSource(familyName, isBold, isItalic, out wpfGlyphTypeface, typefaceKey);
#endif
#if NETFX_CORE || UWP
//GlyphTypeface wpfGlyphTypeface;
XFontSource fontSource = null;//CreateFontSource(familyName, isBold, isItalic, out wpfGlyphTypeface, typefaceKey);
#endif
// If no such font exists return null. PDFsharp will fail.
if (fontSource == null)
return null;
//#if (CORE || GDI) && !WPF
// // TODO: Support style simulation for GDI+ platform fonts.
// fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, false, false, gdiFont);
//#endif
if (fontResolvingOptions.OverrideStyleSimulations)
{
#if (CORE || GDI) && !WPF
// TODO: Support style simulation for GDI+ platform fonts.
fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, fontResolvingOptions.MustSimulateBold, fontResolvingOptions.MustSimulateItalic, gdiFont);
#endif
#if WPF && !SILVERLIGHT
fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, fontResolvingOptions.MustSimulateBold, fontResolvingOptions.MustSimulateItalic,
wpfFontFamily, wpfTypeface, wpfGlyphTypeface);
#endif
}
else
{
#if (CORE || GDI) && !WPF
bool mustSimulateBold = gdiFont.Bold && !fontSource.Fontface.os2.IsBold;
bool mustSimulateItalic = gdiFont.Italic && !fontSource.Fontface.os2.IsItalic;
fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, mustSimulateBold, mustSimulateItalic, gdiFont);
#endif
#if WPF && !SILVERLIGHT
// WPF knows what styles have to be simulated.
bool mustSimulateBold = (wpfGlyphTypeface.StyleSimulations & WpfStyleSimulations.BoldSimulation) == WpfStyleSimulations.BoldSimulation;
bool mustSimulateItalic = (wpfGlyphTypeface.StyleSimulations & WpfStyleSimulations.ItalicSimulation) == WpfStyleSimulations.ItalicSimulation;
// Weird behavior of WPF is fixed here in case we request a bold italic typeface.
// If only italic is available, bold is simulated based on italic.
// If only bold is available, italic is simulated based on bold.
// But if both bold and italic is available, italic face is used and bold is simulated.
// The latter case is reversed here, i.e. bold face is used and italic is simulated.
if (fontResolvingOptions.IsBoldItalic && mustSimulateBold && !mustSimulateItalic)
{
// Try to get the bold typeface.
string typefaceKeyBold = XGlyphTypeface.ComputeKey(familyName, true, false);
FontResolverInfo infoBold = ResolveTypeface(familyName,
new FontResolvingOptions(FontHelper.CreateStyle(true, false)), typefaceKeyBold);
// Use it if it does not base on simulation.
if (infoBold != null && infoBold.StyleSimulations == XStyleSimulations.None)
{
// Use existing bold typeface and simulate italic.
fontResolverInfo = new PlatformFontResolverInfo(typefaceKeyBold, false, true,
wpfFontFamily, wpfTypeface, wpfGlyphTypeface);
}
else
{
// Simulate both.
fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, true, true,
wpfFontFamily, wpfTypeface, wpfGlyphTypeface);
}
}
else
{
fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, mustSimulateBold, mustSimulateItalic,
wpfFontFamily, wpfTypeface, wpfGlyphTypeface);
}
#endif
}
#if SILVERLIGHT
fontResolverInfo = null; //new PlattformResolverInfo(typefaceKey, false, false, wpfGlyphTypeface);
#endif
FontFactory.CacheFontResolverInfo(typefaceKey, fontResolverInfo);
// Register font data under the platform specific face name.
// Already done in CreateFontSource.
// FontFactory.CacheNewFontSource(typefaceKey, fontSource);
return fontResolverInfo;
}
#if (CORE_WITH_GDI || GDI) && !WPF
/// <summary>
/// Create a GDI+ font and use its handle to retrieve font data using native calls.
/// </summary>
internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, out GdiFont font, string typefaceKey)
{
if (string.IsNullOrEmpty(typefaceKey))
typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions);
#if true_
if (familyName == "Cambria")
Debug-Break.Break();
#endif
GdiFontStyle gdiStyle = (GdiFontStyle)(fontResolvingOptions.FontStyle & XFontStyle.BoldItalic);
// Create a 10 point GDI+ font as an exemplar.
XFontSource fontSource;
font = FontHelper.CreateFont(familyName, 10, gdiStyle, out fontSource);
if (fontSource != null)
{
Debug.Assert(font != null);
// Case: Font was created by a GDI+ private font collection.
#if true
#if DEBUG
XFontSource existingFontSource;
Debug.Assert(FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out existingFontSource) &&
ReferenceEquals(fontSource, existingFontSource));
#endif
#else
// Win32 API cannot get font data from fonts created by private font collection,
// because this is handled internally in GDI+.
// Therefore the font source was created when the private font is added to the private font collection.
if (!FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out fontSource))
{
// Simplify styles.
// (The code is written for clarity - do not rearrange for optimization)
if (font.Bold && font.Italic)
{
if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, true, false), out fontSource))
{
// Use bold font.
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
}
else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, true), out fontSource))
{
// Use italic font.
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
}
else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource))
{
// Use regular font.
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
}
}
else if (font.Bold || font.Italic)
{
// Use regular font.
if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource))
{
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
}
}
else
{
if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource))
{
// Should never come here...
FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource);
}
}
}
#endif
}
else
{
// Get or create the font source and cache it under the specified typeface key.
fontSource = XFontSource.GetOrCreateFromGdi(typefaceKey, font);
}
return fontSource;
}
#endif
#if WPF && !SILVERLIGHT
/// <summary>
/// Create a WPF GlyphTypeface and retrieve font data from it.
/// </summary>
internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions,
out WpfFontFamily wpfFontFamily, out WpfTypeface wpfTypeface, out WpfGlyphTypeface wpfGlyphTypeface, string typefaceKey)
{
if (string.IsNullOrEmpty(typefaceKey))
typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions);
XFontStyle style = fontResolvingOptions.FontStyle;
#if DEBUG
if (StringComparer.OrdinalIgnoreCase.Compare(familyName, "Segoe UI Semilight") == 0
&& (style & XFontStyle.BoldItalic) == XFontStyle.Italic)
familyName.GetType();
#endif
// Use WPF technique to create font data.
wpfTypeface = XPrivateFontCollection.TryCreateTypeface(familyName, style, out wpfFontFamily);
#if DEBUG__
if (wpfTypeface != null)
{
WpfGlyphTypeface glyphTypeface;
ICollection<WpfTypeface> list = wpfFontFamily.GetTypefaces();
foreach (WpfTypeface tf in list)
{
if (!tf.TryGetGlyphTypeface(out glyphTypeface))
Debug-Break.Break();
}
//if (!WpfTypeface.TryGetGlyphTypeface(out glyphTypeface))
// throw new InvalidOperationException(PSSR.CannotGetGlyphTypeface(familyName));
}
#endif
if (wpfFontFamily == null)
wpfFontFamily = new WpfFontFamily(familyName);
if (wpfTypeface == null)
wpfTypeface = FontHelper.CreateTypeface(wpfFontFamily, style);
// Let WPF choose the right glyph typeface.
if (!wpfTypeface.TryGetGlyphTypeface(out wpfGlyphTypeface))
throw new InvalidOperationException(PSSR.CannotGetGlyphTypeface(familyName));
// Get or create the font source and cache it under the specified typeface key.
XFontSource fontSource = XFontSource.GetOrCreateFromWpf(typefaceKey, wpfGlyphTypeface);
return fontSource;
}
#endif
#if SILVERLIGHT
/// <summary>
/// Silverlight has no access to the bytes of its fonts and therefore return null.
/// </summary>
internal static XFontSource CreateFontSource(string familyName, bool isBold, bool isItalic)
{
// PDFsharp does not provide a default font because this would blow up the assembly
// unnecessarily if the font is not needed. Provide your own font resolver to generate
// PDF files containing text.
return null;
}
#endif
#if NETFX_CORE
internal static XFontSource CreateFontSource(string familyName, bool isBold, bool isItalic, string typefaceKey)
{
throw new NotImplementedException();
}
#endif
}
}

View File

@@ -0,0 +1,101 @@
#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
#if CORE || GDI
using System.Drawing;
using GdiFont = System.Drawing.Font;
#endif
#if WPF
using System.Windows.Media;
using WpfFontFamily = System.Windows.Media.FontFamily;
using WpfTypeface = System.Windows.Media.Typeface;
using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface;
#endif
namespace PdfSharp.Fonts
{
/// <summary>
/// Represents a font resolver info created by the platform font resolver.
/// </summary>
internal class PlatformFontResolverInfo : FontResolverInfo
{
#if CORE || GDI
public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic, GdiFont gdiFont)
: base(faceName, mustSimulateBold, mustSimulateItalic)
{
_gdiFont = gdiFont;
}
#endif
#if WPF
public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic, WpfFontFamily wpfFontFamily,
WpfTypeface wpfTypeface, WpfGlyphTypeface wpfGlyphTypeface)
: base(faceName, mustSimulateBold, mustSimulateItalic)
{
_wpfFontFamily = wpfFontFamily;
_wpfTypeface = wpfTypeface;
_wpfGlyphTypeface = wpfGlyphTypeface;
}
#endif
#if CORE || GDI
public Font GdiFont
{
get { return _gdiFont; }
}
readonly Font _gdiFont;
#endif
#if WPF
public WpfFontFamily WpfFontFamily
{
get { return _wpfFontFamily; }
}
readonly WpfFontFamily _wpfFontFamily;
public WpfTypeface WpfTypeface
{
get { return _wpfTypeface; }
}
readonly WpfTypeface _wpfTypeface;
public WpfGlyphTypeface WpfGlyphTypeface
{
get { return _wpfGlyphTypeface; }
}
readonly WpfGlyphTypeface _wpfGlyphTypeface;
#endif
#if NETFX_CORE || UWP
public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic)
: base(faceName, mustSimulateBold, mustSimulateItalic)
{
//_gdiFont = gdiFont;
}
#endif
}
}