问题
I have a MemoryStream with the contents of a Font File (.ttf) and I would like to be able to create a FontFamily WPF object from that stream WITHOUT writing the contents of the stream to disk. I know this is possible with a System.Drawing.FontFamily but I cannot find out how to do it with System.Windows.Media.FontFamily.
Note: I will only have the stream, so I can't pack it as a resource in the application and because of disk permissions issues, will not be able to write the font file to disk for reference as "content"
UPDATE:
The API docs how describe how an application resource can be used, though it is not clear to me whether that is an Embedded resource in the assembly or a file on disk.
You can use a base URI value when you reference a font that is packaged as part of the application. For example, the base URI value can be a "pack://application" URI, which lets you reference fonts that are packaged as application resources. The following code example shows a font reference that is composed of a base URI value and a relative URI value.
回答1:
The best approach I could think of, was to save the oldFont to a temp directory, and immediately load it using the newFont constructor that accepts a uri.
回答2:
There is a similar question here, which contains a supposed solution by converting a System.Drawing.FontFamily to a WPF font family, all in memory without any file IO:
public static void Load(MemoryStream stream)
{
byte[] streamData = new byte[stream.Length];
stream.Read(streamData, 0, streamData.Length);
IntPtr data = Marshal.AllocCoTaskMem(streamData.Length); // Very important.
Marshal.Copy(streamData, 0, data, streamData.Length);
PrivateFontCollection pfc = new PrivateFontCollection();
pfc.AddMemoryFont(data, streamData.Length);
MemoryFonts.Add(pfc); // Your own collection of fonts here.
Marshal.FreeCoTaskMem(data); // Very important.
}
public static System.Windows.Media.FontFamily LoadFont(int fontId)
{
if (!Exists(fontId))
{
return null;
}
/*
NOTE:
This is basically how you convert a System.Drawing.FontFamily to System.Windows.Media.FontFamily, using PrivateFontCollection.
*/
return new System.Windows.Media.FontFamily(MemoryFonts[fontId].Families[0].Name);
}
This seems to use the System.Drawing.PrivateFontCollection
(^) to add a System.Drawing.Font
created from a MemoryStream
and then use the Families[0].Name
of that font to pass into the System.Windows.Media.FontFamily
constructor. I assume the family name would then be a URI to the instance of that font in the PrivateFontCollection but you'd probably have to try it out.
来源:https://stackoverflow.com/questions/44394/wpf-load-font-from-stream