如何从 windows OS 下载但尚未安装的字体文件中获取 IDWriteFont 对象

How to get the IDWriteFont object from the font file downloaded in windows OS and not installed yet

您好,我正在使用 DWrite APIs 通过 DWrite APIs 获取系统字体元数据。我正在执行以下操作。

    HR(DWriteCreateFactory(
        DWRITE_FACTORY_TYPE_SHARED,
        __uuidof(IDWriteFactory),
        reinterpret_cast<IUnknown **>(&factory)));

    // Get the system font collection.
    IDWriteFontCollection *collection = NULL;
    HR(factory->GetSystemFontCollection(&collection, TRUE));

    // Get the number of font families in the collection.
    int familyCount = collection->GetFontFamilyCount();

    // track unique font Ids we've already added
    // using a set so we don't get any duplicates.
    for (int i = 0; i < familyCount; i++)
    {
        IDWriteFontFamily *family = NULL;

        // Get the font family.
        HR(collection->GetFontFamily(i, &family));
        int fontCount = family->GetFontCount();

        for (int j = 0; j < fontCount; j++)
        {
            IDWriteFont *font = NULL;
            HR(family->GetFont(j, &font));
            fontMetaDataPtr* result = resultFromFont(font);
        }
    }

这将给我所有已安装字体的信息。现在我需要获取我下载的新字体的信息,但是 DWrite 中没有 API,我可以在其中使用字体文件路径 ex 获取 IDWriteFont *font 对象。 "C:\Downloads\Fonts.ttf"

你能分享任何工作示例吗?

我尝试了以下代码,但它没有用,因为它看起来像是临时安装字体而不是更新集合。

int result = AddFontResourceW(wideFontFilePath.c_str());
if (result > 0) {
    IDWriteFactory *factory = NULL;
    HR(DWriteCreateFactory(
    DWRITE_FACTORY_TYPE_SHARED,
    __uuidof(IDWriteFactory),
    reinterpret_cast<IUnknown **>(&factory)));

    // Get the system font collection.
    IDWriteFontCollection *collection = NULL;
    HR(factory->GetSystemFontCollection(&collection, TRUE));

    IDWriteFontFile *fontFile = NULL;
    // Get the system font collection.
    
    HR(factory->CreateFontFileReference(utf8ToUtf16(fontfile.c_str()), NULL, &fontFile));
    if (fontFile) {
        BOOL isSupported;
        DWRITE_FONT_FILE_TYPE fileType;
        DWRITE_FONT_FACE_TYPE fontFaceType;
        UINT32 numFaces;
        IDWriteFontFace* fontFace = NULL;
        fontFile->Analyze(&isSupported, &fileType, &fontFaceType, &numFaces);
        factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
        IDWriteFont *font = NULL;
        collection->GetFontFromFontFace(fontFace, &font);
        fontMetaDataPtr* result = resultFromFont(font);
    }
 }
 result = RemoveFontResourceW(wideFontFilePath.c_str());

我找到了解决此问题的方法

HR(DWriteCreateFactory(
        DWRITE_FACTORY_TYPE_SHARED,
        __uuidof(IDWriteFactory3),
        reinterpret_cast<IUnknown **>(&factory)));

    HR(factory->CreateFontSetBuilder(&fontSetBuilder));
    HR(factory->CreateFontFileReference(utf8ToUtf16(fontFilePath.c_str()), NULL, &fontFile));

    if (fontFile) {
        
        fontFile->Analyze(&isSupported, &fileType, &fontFaceType, &numberOfFonts);
        // If there are more than 1 fonts are there, then we are taking only first index of the font
        // TODO: need to check for multiple fonts
        IDWriteFontFaceReference* fontFaceReference;
        factory->CreateFontFaceReference(fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontFaceReference);
        fontSetBuilder->AddFontFaceReference(fontFaceReference);
        
        IDWriteFontSet* customFontSet;
        fontSetBuilder->CreateFontSet(&customFontSet);
        UINT32 fontCnt = customFontSet->GetFontCount();
        if (fontCnt > 1) {
            // TODO: need to check for multiple fonts
        }
        string postscriptName = getStringFromFontSet(customFontSet, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME);
   }

像这样使用 IDWriteFontSet and DWRITE_FONT_PROPERTY_ID enum from dwrite_3.h 帮助我找到了解决方案。