WPF - загрузить шрифт из потока?

У меня есть MemoryStream с содержимым файла шрифтов (.ttf), и я хотел бы иметь возможность создать объект FontFamily WPF из этого потока БЕЗ записи содержимого потока на диск. Я знаю, что это возможно с помощью System.Drawing.FontFamily, но я не могу понять, как это сделать с помощью System.Windows.Media.FontFamily.

Примечание: у меня будет только поток, поэтому я не могу упаковать его как ресурс в приложении и из-за проблем с правами доступа к диску не смогу записать файл шрифта на диск для справки в качестве содержимого.

ОБНОВЛЕНИЕ:

Документы API < / a> как описать, как можно использовать ресурс приложения, хотя мне не ясно, является ли он встроенным ресурсом в сборке или файлом на диске.

Вы можете использовать базовое значение URI при ссылке на шрифт, который упакован как часть приложения. Например, базовым значением URI может быть URI pack: // application, который позволяет ссылаться на шрифты, упакованные как ресурсы приложения. В следующем примере кода показана ссылка на шрифт, состоящая из базового значения URI и относительного значения URI.


person viggity    schedule 04.09.2008    source источник
comment
Не уверен, что вы можете это сделать, Бернард :-) DirectWrite (который является базовой используемой технологией) поддерживает его, но WPF (который не обновлялся много с 15 лет) в значительной степени жестко кодирует тот факт, что он загружает шрифты из Windows или папки / файл. Следуйте за источником: referenceource.microsoft.com / # PresentationCore / Core / CSharp /   -  person Simon Mourier    schedule 06.01.2021
comment
Спасибо @SimonMourier: Я добавил информацию о формате URI pack: //. Если при этом используются встроенные ресурсы, можно ли расширить загрузку файла для поддержки потока? Я попытался спуститься на кролика целиком, но не смог найти четкого ответа в referenceource.microsoft.com/#WindowsBase/Base/System/IO/.   -  person Bernard Vander Beken    schedule 07.01.2021
comment
Дополнительная информация о формате пакета docs.microsoft.com/en-us/dotnet/desktop/wpf/app-development/   -  person Bernard Vander Beken    schedule 07.01.2021
comment
Я пробовал это stackoverflow.com/a/16459015/403671, но он не работает, не срабатывает. Различные параметры Uri здесь поддерживаются только с протоколом pack или file: //.   -  person Simon Mourier    schedule 07.01.2021
comment
Если вы не возражаете, я спрошу, откуда MemoryStream? Может есть другой подход?   -  person Keith Stein    schedule 10.01.2021
comment
OP запросил MemoryStream, для моего случая использования любое представление в памяти работоспособно, включая массив байтов. Пока не требуется доступ к файловой системе.   -  person Bernard Vander Beken    schedule 11.01.2021


Ответы (2)


Лучший подход, который я мог придумать, - это сохранить oldFont во временном каталоге и немедленно загрузить его с помощью конструктора newFont, который принимает uri.

person kobi7    schedule 07.09.2011

Аналогичный вопрос существует здесь, который содержит предполагаемое решение путем преобразования System.Drawing.FontFamily в семейство шрифтов WPF, все в памяти без какого-либо файлового ввода-вывода:

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);
}

Кажется, здесь используется _2 _ (^), чтобы добавить System.Drawing.Font, созданный из MemoryStream, а затем использовать Families[0].Name этого шрифта для передачи в конструктор System.Windows.Media.FontFamily. Я предполагаю, что имя семейства тогда будет URI для экземпляра этого шрифта в PrivateFontCollection, но вам, вероятно, придется его попробовать.

person Patrick Klug    schedule 11.01.2021