c++directwrite

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


Hi I am using DWrite APIs to get the system fonts metadata using DWrite APIs. I am doing the following.

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

This will give me the information of the all the installed fonts. Now I need to get the information for the new fonts which I have downloaded, but there is no API in DWrite in which I can get IDWriteFont *font Object using font file path ex. "C:\Downloads\Fonts.ttf"

Can you share any working example for this.

I tried following code but it didn't work as it looks like font installing temporary not updating the collection.

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

Solution

  • I found a work around for this problem

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

    like this using IDWriteFontSet and DWRITE_FONT_PROPERTY_ID enum from dwrite_3.h helped me to get my solution.