mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 998844 - part 5 - support bundled fonts on Windows/DWrite. r=bas
This commit is contained in:
parent
715446ecd5
commit
a8bff5f342
@ -18,6 +18,10 @@
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include "gfxGDIFontList.h"
|
||||
|
||||
@ -957,11 +961,11 @@ gfxDWriteFontList::DelayedInitFontList()
|
||||
QueryPerformanceCounter(&t1);
|
||||
|
||||
HRESULT hr;
|
||||
nsRefPtr<IDWriteFactory> factory =
|
||||
gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
|
||||
|
||||
LOGREGISTRY(L"calling GetSystemFontCollection");
|
||||
nsRefPtr<IDWriteFontCollection> systemFonts;
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
GetSystemFontCollection(getter_AddRefs(systemFonts));
|
||||
hr = factory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
|
||||
NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
|
||||
LOGREGISTRY(L"GetSystemFontCollection done");
|
||||
|
||||
@ -971,106 +975,14 @@ gfxDWriteFontList::DelayedInitFontList()
|
||||
|
||||
QueryPerformanceCounter(&t2);
|
||||
|
||||
for (UINT32 i = 0; i < systemFonts->GetFontFamilyCount(); i++) {
|
||||
nsRefPtr<IDWriteFontFamily> family;
|
||||
systemFonts->GetFontFamily(i, getter_AddRefs(family));
|
||||
GetFontsFromCollection(mSystemFonts);
|
||||
|
||||
nsRefPtr<IDWriteLocalizedStrings> names;
|
||||
hr = family->GetFamilyNames(getter_AddRefs(names));
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UINT32 englishIdx = 0;
|
||||
|
||||
BOOL exists;
|
||||
hr = names->FindLocaleName(L"en-us", &englishIdx, &exists);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
if (!exists) {
|
||||
// Use 0 index if english is not found.
|
||||
englishIdx = 0;
|
||||
}
|
||||
|
||||
AutoFallibleTArray<WCHAR, 32> enName;
|
||||
UINT32 length;
|
||||
|
||||
hr = names->GetStringLength(englishIdx, &length);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!enName.SetLength(length + 1)) {
|
||||
// Eeep - running out of memory. Unlikely to end well.
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetString(englishIdx, enName.Elements(), length + 1);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString name(enName.Elements());
|
||||
BuildKeyNameFromFontName(name);
|
||||
|
||||
nsRefPtr<gfxFontFamily> fam;
|
||||
|
||||
if (mFontFamilies.GetWeak(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsDependentString familyName(enName.Elements());
|
||||
|
||||
fam = new gfxDWriteFontFamily(familyName, family);
|
||||
if (!fam) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mBadUnderlineFamilyNames.Contains(name)) {
|
||||
fam->SetBadUnderlineFamily();
|
||||
}
|
||||
mFontFamilies.Put(name, fam);
|
||||
|
||||
// now add other family name localizations, if present
|
||||
uint32_t nameCount = names->GetCount();
|
||||
uint32_t nameIndex;
|
||||
|
||||
for (nameIndex = 0; nameIndex < nameCount; nameIndex++) {
|
||||
UINT32 nameLen;
|
||||
AutoFallibleTArray<WCHAR, 32> localizedName;
|
||||
|
||||
// only add other names
|
||||
if (nameIndex == englishIdx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetStringLength(nameIndex, &nameLen);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!localizedName.SetLength(nameLen + 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetString(nameIndex, localizedName.Elements(),
|
||||
nameLen + 1);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsDependentString locName(localizedName.Elements());
|
||||
|
||||
if (!familyName.Equals(locName)) {
|
||||
AddOtherFamilyName(fam, locName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// at this point, all family names have been read in
|
||||
fam->SetOtherFamilyNamesInitialized();
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
mBundledFonts = CreateBundledFontsCollection(factory);
|
||||
if (mBundledFonts) {
|
||||
GetFontsFromCollection(mBundledFonts);
|
||||
}
|
||||
#endif
|
||||
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
GetFontSubstitutes();
|
||||
@ -1172,11 +1084,11 @@ gfxDWriteFontList::DelayedInitFontList()
|
||||
elapsedTime = (t3.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
|
||||
Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_TOTAL, elapsedTime);
|
||||
Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COUNT,
|
||||
systemFonts->GetFontFamilyCount());
|
||||
mSystemFonts->GetFontFamilyCount());
|
||||
Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_GDI_TABLE, mGDIFontTableAccess);
|
||||
LOG_FONTINIT((
|
||||
"Total time in DelayedInitFontList: %9.3f ms (families: %d, %s)\n",
|
||||
elapsedTime, systemFonts->GetFontFamilyCount(),
|
||||
elapsedTime, mSystemFonts->GetFontFamilyCount(),
|
||||
(mGDIFontTableAccess ? "gdi table access" : "dwrite table access")));
|
||||
|
||||
elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
|
||||
@ -1190,6 +1102,111 @@ gfxDWriteFontList::DelayedInitFontList()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontList::GetFontsFromCollection(IDWriteFontCollection* aCollection)
|
||||
{
|
||||
for (UINT32 i = 0; i < aCollection->GetFontFamilyCount(); i++) {
|
||||
nsRefPtr<IDWriteFontFamily> family;
|
||||
aCollection->GetFontFamily(i, getter_AddRefs(family));
|
||||
|
||||
nsRefPtr<IDWriteLocalizedStrings> names;
|
||||
HRESULT hr = family->GetFamilyNames(getter_AddRefs(names));
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UINT32 englishIdx = 0;
|
||||
|
||||
BOOL exists;
|
||||
hr = names->FindLocaleName(L"en-us", &englishIdx, &exists);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
if (!exists) {
|
||||
// Use 0 index if english is not found.
|
||||
englishIdx = 0;
|
||||
}
|
||||
|
||||
AutoFallibleTArray<WCHAR, 32> enName;
|
||||
UINT32 length;
|
||||
|
||||
hr = names->GetStringLength(englishIdx, &length);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!enName.SetLength(length + 1)) {
|
||||
// Eeep - running out of memory. Unlikely to end well.
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetString(englishIdx, enName.Elements(), length + 1);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString name(enName.Elements());
|
||||
BuildKeyNameFromFontName(name);
|
||||
|
||||
nsRefPtr<gfxFontFamily> fam;
|
||||
|
||||
if (mFontFamilies.GetWeak(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsDependentString familyName(enName.Elements());
|
||||
|
||||
fam = new gfxDWriteFontFamily(familyName, family);
|
||||
if (!fam) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mBadUnderlineFamilyNames.Contains(name)) {
|
||||
fam->SetBadUnderlineFamily();
|
||||
}
|
||||
mFontFamilies.Put(name, fam);
|
||||
|
||||
// now add other family name localizations, if present
|
||||
uint32_t nameCount = names->GetCount();
|
||||
uint32_t nameIndex;
|
||||
|
||||
for (nameIndex = 0; nameIndex < nameCount; nameIndex++) {
|
||||
UINT32 nameLen;
|
||||
AutoFallibleTArray<WCHAR, 32> localizedName;
|
||||
|
||||
// only add other names
|
||||
if (nameIndex == englishIdx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetStringLength(nameIndex, &nameLen);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!localizedName.SetLength(nameLen + 1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = names->GetString(nameIndex, localizedName.Elements(),
|
||||
nameLen + 1);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsDependentString locName(localizedName.Elements());
|
||||
|
||||
if (!familyName.Equals(locName)) {
|
||||
AddOtherFamilyName(fam, locName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// at this point, all family names have been read in
|
||||
fam->SetOtherFamilyNamesInitialized();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveCharsetFromFontSubstitute(nsAString &aName)
|
||||
{
|
||||
@ -1561,8 +1578,17 @@ class DirectWriteFontInfo : public FontInfoData {
|
||||
public:
|
||||
DirectWriteFontInfo(bool aLoadOtherNames,
|
||||
bool aLoadFaceNames,
|
||||
bool aLoadCmaps) :
|
||||
bool aLoadCmaps,
|
||||
IDWriteFontCollection* aSystemFonts
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
, IDWriteFontCollection* aBundledFonts
|
||||
#endif
|
||||
) :
|
||||
FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps)
|
||||
, mSystemFonts(aSystemFonts)
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
, mBundledFonts(aBundledFonts)
|
||||
#endif
|
||||
{}
|
||||
|
||||
virtual ~DirectWriteFontInfo() {}
|
||||
@ -1570,7 +1596,11 @@ public:
|
||||
// loads font data for all members of a given family
|
||||
virtual void LoadFontFamilyData(const nsAString& aFamilyName);
|
||||
|
||||
private:
|
||||
nsRefPtr<IDWriteFontCollection> mSystemFonts;
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
nsRefPtr<IDWriteFontCollection> mBundledFonts;
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
@ -1588,13 +1618,24 @@ DirectWriteFontInfo::LoadFontFamilyData(const nsAString& aFamilyName)
|
||||
BOOL exists = false;
|
||||
|
||||
uint32_t index;
|
||||
nsRefPtr<IDWriteFontFamily> family;
|
||||
hr = mSystemFonts->FindFamilyName(famName.Elements(), &index, &exists);
|
||||
if (FAILED(hr) || !exists) {
|
||||
return;
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
mSystemFonts->GetFontFamily(index, getter_AddRefs(family));
|
||||
if (!family) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<IDWriteFontFamily> family;
|
||||
mSystemFonts->GetFontFamily(index, getter_AddRefs(family));
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
if (!family && mBundledFonts) {
|
||||
hr = mBundledFonts->FindFamilyName(famName.Elements(), &index, &exists);
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
mBundledFonts->GetFontFamily(index, getter_AddRefs(family));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!family) {
|
||||
return;
|
||||
}
|
||||
@ -1735,9 +1776,169 @@ gfxDWriteFontList::CreateFontInfoData()
|
||||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
||||
|
||||
nsRefPtr<DirectWriteFontInfo> fi =
|
||||
new DirectWriteFontInfo(false, NeedFullnamePostscriptNames(), loadCmaps);
|
||||
gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
GetSystemFontCollection(getter_AddRefs(fi->mSystemFonts));
|
||||
new DirectWriteFontInfo(false, NeedFullnamePostscriptNames(), loadCmaps,
|
||||
mSystemFonts
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
, mBundledFonts
|
||||
#endif
|
||||
);
|
||||
|
||||
return fi.forget();
|
||||
}
|
||||
|
||||
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
|
||||
#define IMPL_QI_FOR_DWRITE(_interface) \
|
||||
public: \
|
||||
IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject) \
|
||||
{ \
|
||||
if (__uuidof(_interface) == riid) { \
|
||||
*ppvObject = this; \
|
||||
} else if (__uuidof(IUnknown) == riid) { \
|
||||
*ppvObject = this; \
|
||||
} else { \
|
||||
*ppvObject = nullptr; \
|
||||
return E_NOINTERFACE; \
|
||||
} \
|
||||
this->AddRef(); \
|
||||
return S_OK; \
|
||||
}
|
||||
|
||||
class BundledFontFileEnumerator
|
||||
: public IDWriteFontFileEnumerator
|
||||
{
|
||||
IMPL_QI_FOR_DWRITE(IDWriteFontFileEnumerator)
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(BundledFontFileEnumerator)
|
||||
|
||||
public:
|
||||
BundledFontFileEnumerator(IDWriteFactory *aFactory,
|
||||
nsIFile *aFontDir);
|
||||
|
||||
IFACEMETHODIMP MoveNext(BOOL * hasCurrentFile);
|
||||
|
||||
IFACEMETHODIMP GetCurrentFontFile(IDWriteFontFile ** fontFile);
|
||||
|
||||
private:
|
||||
BundledFontFileEnumerator() MOZ_DELETE;
|
||||
BundledFontFileEnumerator(const BundledFontFileEnumerator&) MOZ_DELETE;
|
||||
BundledFontFileEnumerator& operator=(const BundledFontFileEnumerator&) MOZ_DELETE;
|
||||
|
||||
nsRefPtr<IDWriteFactory> mFactory;
|
||||
|
||||
nsCOMPtr<nsIFile> mFontDir;
|
||||
nsCOMPtr<nsISimpleEnumerator> mEntries;
|
||||
nsCOMPtr<nsISupports> mCurrent;
|
||||
};
|
||||
|
||||
BundledFontFileEnumerator::BundledFontFileEnumerator(IDWriteFactory *aFactory,
|
||||
nsIFile *aFontDir)
|
||||
: mFactory(aFactory)
|
||||
, mFontDir(aFontDir)
|
||||
{
|
||||
mFontDir->GetDirectoryEntries(getter_AddRefs(mEntries));
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
BundledFontFileEnumerator::MoveNext(BOOL * aHasCurrentFile)
|
||||
{
|
||||
bool hasMore = false;
|
||||
if (mEntries) {
|
||||
if (NS_SUCCEEDED(mEntries->HasMoreElements(&hasMore)) && hasMore) {
|
||||
if (NS_SUCCEEDED(mEntries->GetNext(getter_AddRefs(mCurrent)))) {
|
||||
hasMore = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*aHasCurrentFile = hasMore;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
BundledFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile ** aFontFile)
|
||||
{
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(mCurrent);
|
||||
if (!file) {
|
||||
return E_FAIL;
|
||||
}
|
||||
nsString path;
|
||||
if (NS_FAILED(file->GetPath(path))) {
|
||||
return E_FAIL;
|
||||
}
|
||||
return mFactory->CreateFontFileReference((const WCHAR*)path.get(),
|
||||
nullptr, aFontFile);
|
||||
}
|
||||
|
||||
class BundledFontLoader
|
||||
: public IDWriteFontCollectionLoader
|
||||
{
|
||||
IMPL_QI_FOR_DWRITE(IDWriteFontCollectionLoader)
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(BundledFontLoader)
|
||||
|
||||
public:
|
||||
BundledFontLoader()
|
||||
{
|
||||
}
|
||||
|
||||
IFACEMETHODIMP CreateEnumeratorFromKey(
|
||||
IDWriteFactory *aFactory,
|
||||
const void *aCollectionKey,
|
||||
UINT32 aCollectionKeySize,
|
||||
IDWriteFontFileEnumerator **aFontFileEnumerator);
|
||||
|
||||
private:
|
||||
BundledFontLoader(const BundledFontLoader&) MOZ_DELETE;
|
||||
BundledFontLoader& operator=(const BundledFontLoader&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
IFACEMETHODIMP
|
||||
BundledFontLoader::CreateEnumeratorFromKey(
|
||||
IDWriteFactory *aFactory,
|
||||
const void *aCollectionKey,
|
||||
UINT32 aCollectionKeySize,
|
||||
IDWriteFontFileEnumerator **aFontFileEnumerator)
|
||||
{
|
||||
nsIFile *fontDir = *(nsIFile**)aCollectionKey;
|
||||
*aFontFileEnumerator = new BundledFontFileEnumerator(aFactory, fontDir);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<IDWriteFontCollection>
|
||||
gfxDWriteFontList::CreateBundledFontsCollection(IDWriteFactory* aFactory)
|
||||
{
|
||||
nsCOMPtr<nsIFile> localDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(localDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("fonts")))) {
|
||||
return nullptr;
|
||||
}
|
||||
bool isDir;
|
||||
if (NS_FAILED(localDir->IsDirectory(&isDir)) || !isDir) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<BundledFontLoader> loader = new BundledFontLoader();
|
||||
if (FAILED(aFactory->RegisterFontCollectionLoader(loader))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void *key = localDir.get();
|
||||
nsRefPtr<IDWriteFontCollection> collection;
|
||||
HRESULT hr =
|
||||
aFactory->CreateCustomFontCollection(loader, &key, sizeof(key),
|
||||
getter_AddRefs(collection));
|
||||
|
||||
aFactory->UnregisterFontCollectionLoader(loader);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return collection.forget();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -390,6 +390,13 @@ private:
|
||||
|
||||
virtual bool UsesSystemFallback() { return true; }
|
||||
|
||||
void GetFontsFromCollection(IDWriteFontCollection* aCollection);
|
||||
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
already_AddRefed<IDWriteFontCollection>
|
||||
CreateBundledFontsCollection(IDWriteFactory* aFactory);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Fonts listed in the registry as substitutes but for which no actual
|
||||
* font family is found.
|
||||
@ -417,6 +424,11 @@ private:
|
||||
|
||||
nsRefPtr<FontFallbackRenderer> mFallbackRenderer;
|
||||
nsRefPtr<IDWriteTextFormat> mFallbackFormat;
|
||||
|
||||
nsRefPtr<IDWriteFontCollection> mSystemFonts;
|
||||
#ifdef MOZ_BUNDLED_FONTS
|
||||
nsRefPtr<IDWriteFontCollection> mBundledFonts;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user