diff --git a/modules/juce_graphics/native/juce_DirectX_windows.cpp b/modules/juce_graphics/native/juce_DirectX_windows.cpp index 1aa24923c0..5042422183 100644 --- a/modules/juce_graphics/native/juce_DirectX_windows.cpp +++ b/modules/juce_graphics/native/juce_DirectX_windows.cpp @@ -1010,6 +1010,12 @@ public: Uuid getUuid() const { return uuid; } + Span asSpan() const&& = delete; + Span asSpan() const& + { + return { static_cast (block->getData()), block->getSize() }; + } + private: std::shared_ptr block; Uuid uuid; @@ -1061,20 +1067,54 @@ DirectWriteCustomFontCollectionLoader::DirectWriteCustomFontCollectionLoader (ID DirectWriteCustomFontCollectionLoader::~DirectWriteCustomFontCollectionLoader() { - for (const auto& loader : fileLoaders) + for (auto& loader : loaders) factory.UnregisterFontFileLoader (loader); } +auto DirectWriteCustomFontCollectionLoader::findLoaderForUuid (const Uuid& uuid) const -> ComSmartPtr +{ + const auto compareUuidAndLoader = [] (ComSmartPtr loader, const Uuid& comparisonUuid) + { + return loader->getUuid() < comparisonUuid; + }; + + const auto iter = std::lower_bound (loaders.begin(), loaders.end(), uuid, compareUuidAndLoader); + + if (iter == loaders.end() || iter->get()->getUuid() != uuid) + return {}; + + return *iter; +} + Uuid DirectWriteCustomFontCollectionLoader::addRawFontData (Span blob) { + const std::string_view blobAsString (reinterpret_cast (blob.data()), blob.size()); + const auto hashValue = std::hash{} (blobAsString); + auto& uuids = uuidsForHash[hashValue]; + + for (const auto& uuid : uuids) + { + const auto matchingLoader = findLoaderForUuid (uuid); + + if (matchingLoader == nullptr) + continue; + + const auto loaderData = matchingLoader->asSpan(); + + if (! std::equal (blob.begin(), blob.end(), loaderData.begin(), loaderData.end())) + continue; + + return matchingLoader->getUuid(); + } + ComSmartPtr loader { new MemoryFontFileLoader { { blob.data(), blob.size() } }, IncrementRef::no }; - factory.RegisterFontFileLoader (loader); - fileLoaders.push_back (loader); - - return fileLoaders.back()->getUuid(); + const auto compareUuids = [] (const auto& a, const auto& b) { return a->getUuid() < b->getUuid(); }; + OrderedContainerHelpers::insertOrAssign (loaders, loader, compareUuids); + uuids.push_back (loader->getUuid()); + return loader->getUuid(); } HRESULT WINAPI DirectWriteCustomFontCollectionLoader::CreateEnumeratorFromKey (IDWriteFactory* factoryIn, @@ -1087,16 +1127,13 @@ HRESULT WINAPI DirectWriteCustomFontCollectionLoader::CreateEnumeratorFromKey (I const Uuid requestedCollectionKey { static_cast (collectionKey) }; - for (const auto& loader : fileLoaders) - { - if (loader->getUuid() != requestedCollectionKey) - continue; + const auto matchingLoader = findLoaderForUuid (requestedCollectionKey); - *fontFileEnumerator = new FontFileEnumerator { *factoryIn, loader }; - return S_OK; - } + if (matchingLoader == nullptr) + return E_INVALIDARG; - return E_INVALIDARG; + *fontFileEnumerator = new FontFileEnumerator { *factoryIn, matchingLoader }; + return S_OK; } //============================================================================== @@ -1119,8 +1156,8 @@ Direct2DFactories::Direct2DFactories() JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token") d2d1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED, - __uuidof (ID2D1Factory), - &options, + __uuidof (ID2D1Factory), + &options, (void**) result.resetAndGetPointerAddress()); JUCE_END_IGNORE_WARNINGS_GCC_LIKE diff --git a/modules/juce_graphics/native/juce_DirectX_windows.h b/modules/juce_graphics/native/juce_DirectX_windows.h index c7c35847fd..e44f51067b 100644 --- a/modules/juce_graphics/native/juce_DirectX_windows.h +++ b/modules/juce_graphics/native/juce_DirectX_windows.h @@ -399,8 +399,15 @@ private: class MemoryFontFileLoader; class FontFileEnumerator; + ComSmartPtr findLoaderForUuid (const Uuid&) const; + IDWriteFactory& factory; - std::vector> fileLoaders; + + // Allows lookup of Uuids of all loaders with data matching a particular hash + std::map> uuidsForHash; + + // Sorted by Uuid + std::vector> loaders; }; //==============================================================================