загрузить шрифт ttf с помощью Windows API - PullRequest
2 голосов
/ 22 апреля 2011

С помощью CreateFont можно указать имя шрифта и множество других свойств.Однако, что если у меня есть файл font.ttf, и я хочу, чтобы этот конкретный шрифт загружался окнами?Как мне указать этот конкретный файл для использования?

Ответы [ 4 ]

3 голосов
/ 29 августа 2014

По общему признанию, это скорее косвенно, но вы можете использовать взаимодействие GDI с DWrite при работе в Windows 7+.

#include <Windows.h>
#include <WindowsX.h>
#include <DWrite.h>

...

// Make the font file visible to GDI.
AddFontResourceEx(fontFileName, FR_PRIVATE, 0);
if (SUCCEEDED(GetLogFontFromFileName(fontFileName, &logFont)))
{
    logFont.lfHeight = -long(desiredPpem);
    HFONT hf = CreateFontIndirect(&logFont);
    HFONT oldFont = SelectFont(hdc, hf);
    ...
    // Do stuff...
    ...
    SelectFont(hdc, oldFont);
}
RemoveFontResource(fontFileName);

....

HRESULT GetLogFontFromFileName(_In_z_ wchar const* fontFileName, _Out_ LOGFONT* logFont)
{
    // DWrite objects
    ComPtr<IDWriteFactory> dwriteFactory;
    ComPtr<IDWriteFontFace> fontFace;
    ComPtr<IDWriteFontFile> fontFile;
    ComPtr<IDWriteGdiInterop> gdiInterop;

    // Set up our DWrite factory and interop interface.
    IFR(DWriteCreateFactory(
        DWRITE_FACTORY_TYPE_SHARED,
        __uuidof(IDWriteFactory),
        reinterpret_cast<IUnknown**>(&dwriteFactory)
        );
    IFR(g_dwriteFactory->GetGdiInterop(&gdiInterop));

    // Open the file and determine the font type.
    IFR(g_dwriteFactory->CreateFontFileReference(fontFileName, nullptr, &fontFile));
    BOOL isSupportedFontType = false;
    DWRITE_FONT_FILE_TYPE fontFileType;
    DWRITE_FONT_FACE_TYPE fontFaceType;
    UINT32 numberOfFaces = 0;
    IFR(fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces));

    if (!isSupportedFontType)
        return DWRITE_E_FILEFORMAT;

    // Set up a font face from the array of font files (just one)
    ComPtr<IDWriteFontFile> fontFileArray[] = {fontFile};
    IFR(g_dwriteFactory->CreateFontFace(
        fontFaceType,
        ARRAYSIZE(fontFileArray), // file count
        &fontFileArray[0], // or GetAddressOf if WRL ComPtr
        0, // faceIndex
        DWRITE_FONT_SIMULATIONS_NONE,
        &fontFace
        );

    // Get the necessary logical font information.
    IFR(gdiInterop->ConvertFontFaceToLOGFONT(fontFace, OUT logFont));

    return S_OK;
}

Где IFR - это просто макрос ошибки, который возвращает FAILED HRESULT, а ComPtr - этокласс интеллектуального указателя помощника (замените его собственным или ATL CComPtr, WinRT ComPtr, VS2013 _com_ptr_t ...).

3 голосов
/ 22 апреля 2011

Я уверен, что вы не можете.Все запросы на шрифты проходят через сопоставитель шрифтов, и он выбирает файл шрифта, который ближе всего соответствует заданным вами спецификациям.Хотя я не уверен, что в действительности это так, он может по крайней мере теоретически использовать (например) данные из двух совершенно разных файлов шрифтов для создания одного логического шрифта.

2 голосов
/ 23 апреля 2011

Одна возможность - EnumFonts(), сохранить результаты.Затем добавьте свой личный шрифт с помощью AddFontResourceEx() и EnumFonts() снова, разница в том, что вы добавили.Обратите внимание, что TTF и растровые шрифты перечисляются по-разному, но для этого теста это не должно иметь значения.

Если вы используете растровые шрифты, они могут быть легко проанализированы (.FNT и .FON).TTF, который вам, вероятно, придется построить (или заимствовать, как другой комментатор предложил FreeType) парсер для извлечения таблицы «name» из файла TTF.

Это похоже на большую работу для шрифта, который выКонтролируете или снабжаете своим приложением.

Мы используем AddFontResourceEx () для добавления частного шрифта, но так как мы контролируем добавляемый шрифт, мы просто жестко закодируем имя шрифта, переданное CreateFontIndirect(), чтобы соответствовать.

1 голос
/ 22 апреля 2011

Если вам не нужна установка шрифта, вы можете сделать это с помощью AddFontResource, тогда вы можете получить связь между физическим .TTF и его логическим / семейным именем, посмотрев на сопоставления в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts.

Я упомянул PrivateFontCollection в моем комментарии, потому что я думал, что вы хотите сделать это временно;Вы можете загрузить TTF в PFC с помощью PrivateFontCollection::AddFontFile, получить новый объект FontFamily из коллекции и экзамена GetFamilyName.(Я сделал то же самое с реализацией .net этого, но не с необработанным API)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...