winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Fonts.cpp (6758B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include <AppInstallerStrings.h>
      5 #include <winget/Fonts.h>
      6 #include <winget/Locale.h>
      7 
      8 namespace AppInstaller::Fonts
      9 {
     10     namespace
     11     {
     12         std::vector<std::filesystem::path> GetFontFilePaths(const wil::com_ptr<IDWriteFontFace>& fontFace)
     13         {
     14             UINT32 fileCount = 0;
     15             THROW_IF_FAILED(fontFace->GetFiles(&fileCount, nullptr));
     16 
     17             static_assert(sizeof(wil::com_ptr<IDWriteFontFile>) == sizeof(IDWriteFontFile*));
     18             std::vector<wil::com_ptr<IDWriteFontFile>> fontFiles;
     19             fontFiles.resize(fileCount);
     20 
     21             THROW_IF_FAILED(fontFace->GetFiles(&fileCount, fontFiles[0].addressof()));
     22 
     23             std::vector<std::filesystem::path> filePaths;
     24             for (UINT32 i = 0; i < fileCount; ++i) {
     25                 wil::com_ptr<IDWriteFontFileLoader> loader;
     26                 THROW_IF_FAILED(fontFiles[i]->GetLoader(loader.addressof()));
     27 
     28                 const void* fontFileReferenceKey;
     29                 UINT32 fontFileReferenceKeySize;
     30                 THROW_IF_FAILED(fontFiles[i]->GetReferenceKey(&fontFileReferenceKey, &fontFileReferenceKeySize));
     31 
     32                 if (const auto localLoader = loader.try_query<IDWriteLocalFontFileLoader>()) {
     33                     UINT32 pathLength;
     34                     THROW_IF_FAILED(localLoader->GetFilePathLengthFromKey(fontFileReferenceKey, fontFileReferenceKeySize, &pathLength));
     35                     pathLength += 1; // Account for the trailing null terminator during allocation.
     36 
     37                     std::wstring path;
     38                     path.resize(pathLength);
     39                     THROW_IF_FAILED(localLoader->GetFilePathFromKey(fontFileReferenceKey, fontFileReferenceKeySize, &path[0], pathLength));
     40                     path.resize(pathLength - 1); // Remove the null char.
     41                     filePaths.emplace_back(std::move(path));
     42                 }
     43             }
     44 
     45             return filePaths;
     46         }
     47     }
     48 
     49     FontCatalog::FontCatalog()
     50     {
     51         m_preferredLocales = AppInstaller::Locale::GetUserPreferredLanguagesUTF16();
     52     }
     53 
     54     std::vector<FontFamily> FontCatalog::GetInstalledFontFamilies(std::optional<std::wstring> familyName)
     55     {
     56         wil::com_ptr<IDWriteFactory7> factory;
     57         THROW_IF_FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), factory.put_unknown()));
     58 
     59         wil::com_ptr<IDWriteFontCollection> collection;
     60         THROW_IF_FAILED(factory->GetSystemFontCollection(collection.addressof(), FALSE));
     61 
     62         std::vector<FontFamily> installedFontFamilies;
     63 
     64         if (familyName.has_value())
     65         {
     66             UINT32 index;
     67             BOOL exists;
     68             THROW_IF_FAILED(collection->FindFamilyName(familyName.value().c_str(), &index, &exists));
     69 
     70             if (exists)
     71             {
     72                 installedFontFamilies.emplace_back(GetFontFamilyByIndex(collection, index));
     73             }
     74         }
     75         else
     76         {
     77             UINT32 familyCount = collection->GetFontFamilyCount();
     78 
     79             for (UINT32 index = 0; index < familyCount; index++)
     80             {
     81                 installedFontFamilies.emplace_back(GetFontFamilyByIndex(collection, index));
     82             }
     83         }
     84 
     85         return installedFontFamilies;
     86     }
     87 
     88     std::wstring FontCatalog::GetLocalizedStringFromFont(const wil::com_ptr<IDWriteLocalizedStrings>& localizedStringCollection)
     89     {
     90         UINT32 index = 0;
     91         BOOL exists = false;
     92 
     93         for (const auto& locale : m_preferredLocales)
     94         {
     95             if (SUCCEEDED_LOG(localizedStringCollection->FindLocaleName(locale.c_str(), &index, &exists)) && exists)
     96             {
     97                 break;
     98             }
     99         }
    100 
    101         // If the locale does not exist, resort to the default value at the 0 index.
    102         if (!exists)
    103         {
    104             index = 0;
    105         }
    106 
    107         UINT32 length = 0;
    108         THROW_IF_FAILED(localizedStringCollection->GetStringLength(index, &length));
    109         length += 1; // Account for the trailing null terminator during allocation.
    110 
    111         std::wstring localizedString;
    112         localizedString.resize(length);
    113         THROW_IF_FAILED(localizedStringCollection->GetString(index, &localizedString[0], length));
    114         localizedString.resize(length - 1); // Remove the null char.
    115         return localizedString;
    116     }
    117 
    118     std::wstring FontCatalog::GetFontFaceName(const wil::com_ptr<IDWriteFont>& font)
    119     {
    120         wil::com_ptr<IDWriteLocalizedStrings> faceNames;
    121         THROW_IF_FAILED(font->GetFaceNames(faceNames.addressof()));
    122         return GetLocalizedStringFromFont(faceNames);
    123     }
    124 
    125     std::wstring FontCatalog::GetFontFamilyName(const wil::com_ptr<IDWriteFontFamily>& fontFamily)
    126     {
    127         wil::com_ptr<IDWriteLocalizedStrings> familyNames;
    128         THROW_IF_FAILED(fontFamily->GetFamilyNames(familyNames.addressof()));
    129         return GetLocalizedStringFromFont(familyNames);
    130     }
    131 
    132     Utility::OpenTypeFontVersion FontCatalog::GetFontFaceVersion(const wil::com_ptr<IDWriteFont>& font)
    133     {
    134         wil::com_ptr<IDWriteLocalizedStrings> fontVersion;
    135         BOOL exists;
    136         THROW_IF_FAILED(font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS, fontVersion.addressof(), &exists));
    137         if (!exists)
    138         {
    139             return {};
    140         }
    141 
    142         std::string value = AppInstaller::Utility::ConvertToUTF8(GetLocalizedStringFromFont(fontVersion));
    143         Utility::OpenTypeFontVersion openTypeFontVersion{ value };
    144         return openTypeFontVersion;
    145     }
    146 
    147     FontFamily FontCatalog::GetFontFamilyByIndex(const wil::com_ptr<IDWriteFontCollection>& collection, UINT32 index)
    148     {
    149         wil::com_ptr<IDWriteFontFamily> family;
    150         THROW_IF_FAILED(collection->GetFontFamily(index, family.addressof()));
    151         std::wstring familyName = GetFontFamilyName(family);
    152 
    153         std::vector<FontFace> fontFaces;
    154         UINT32 fontCount = family->GetFontCount();
    155         for (UINT32 fontIndex = 0; fontIndex < fontCount; fontIndex++)
    156         {
    157             wil::com_ptr<IDWriteFont> font;
    158             THROW_IF_FAILED(family->GetFont(fontIndex, font.addressof()));
    159 
    160             wil::com_ptr<IDWriteFontFace> fontFace;
    161             THROW_IF_FAILED(font->CreateFontFace(fontFace.addressof()));
    162 
    163             FontFace fontFaceEntry;
    164             fontFaceEntry.Name = GetFontFaceName(font);
    165             fontFaceEntry.Version = GetFontFaceVersion(font);
    166             fontFaceEntry.FilePaths = GetFontFilePaths(fontFace);
    167             fontFaces.emplace_back(std::move(fontFaceEntry));
    168         }
    169 
    170         FontFamily fontFamily;
    171         fontFamily.Name = std::move(familyName);
    172         fontFamily.Faces = std::move(fontFaces);
    173         return fontFamily;
    174     }
    175 }