diff options
Diffstat (limited to 'gfx/thebes/gfxDWriteFontList.cpp')
-rw-r--r-- | gfx/thebes/gfxDWriteFontList.cpp | 1813 |
1 files changed, 0 insertions, 1813 deletions
diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp deleted file mode 100644 index c08ca8265..000000000 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ /dev/null @@ -1,1813 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/ArrayUtils.h" -#include "mozilla/MemoryReporting.h" - -#include "gfxDWriteFontList.h" -#include "gfxDWriteFonts.h" -#include "nsUnicharUtils.h" -#include "nsILocaleService.h" -#include "nsServiceManagerUtils.h" -#include "nsCharSeparatedTokenizer.h" -#include "mozilla/Preferences.h" -#include "mozilla/Sprintf.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsISimpleEnumerator.h" -#include "GeckoProfiler.h" - -#include "gfxGDIFontList.h" - -#include "nsIWindowsRegKey.h" - -#include "harfbuzz/hb.h" - -using namespace mozilla; - -#define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ - LogLevel::Debug, args) -#define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \ - gfxPlatform::GetLog(eGfxLog_fontlist), \ - LogLevel::Debug) - -#define LOG_FONTINIT(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \ - LogLevel::Debug, args) -#define LOG_FONTINIT_ENABLED() MOZ_LOG_TEST( \ - gfxPlatform::GetLog(eGfxLog_fontinit), \ - LogLevel::Debug) - -#define LOG_CMAPDATA_ENABLED() MOZ_LOG_TEST( \ - gfxPlatform::GetLog(eGfxLog_cmapdata), \ - LogLevel::Debug) - -static __inline void -BuildKeyNameFromFontName(nsAString &aName) -{ - if (aName.Length() >= LF_FACESIZE) - aName.Truncate(LF_FACESIZE - 1); - ToLowerCase(aName); -} - -//////////////////////////////////////////////////////////////////////////////// -// gfxDWriteFontFamily - -gfxDWriteFontFamily::~gfxDWriteFontFamily() -{ -} - -static HRESULT -GetDirectWriteFontName(IDWriteFont *aFont, nsAString& aFontName) -{ - HRESULT hr; - - RefPtr<IDWriteLocalizedStrings> names; - hr = aFont->GetFaceNames(getter_AddRefs(names)); - if (FAILED(hr)) { - return hr; - } - - BOOL exists; - AutoTArray<wchar_t,32> faceName; - UINT32 englishIdx = 0; - hr = names->FindLocaleName(L"en-us", &englishIdx, &exists); - if (FAILED(hr)) { - return hr; - } - - if (!exists) { - // No english found, use whatever is first in the list. - englishIdx = 0; - } - UINT32 length; - hr = names->GetStringLength(englishIdx, &length); - if (FAILED(hr)) { - return hr; - } - faceName.SetLength(length + 1); - hr = names->GetString(englishIdx, faceName.Elements(), length + 1); - if (FAILED(hr)) { - return hr; - } - - aFontName.Assign(faceName.Elements()); - return S_OK; -} - -#define FULLNAME_ID DWRITE_INFORMATIONAL_STRING_FULL_NAME -#define PSNAME_ID DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME - -// for use in reading postscript or fullname -static HRESULT -GetDirectWriteFaceName(IDWriteFont *aFont, - DWRITE_INFORMATIONAL_STRING_ID aWhichName, - nsAString& aFontName) -{ - HRESULT hr; - - BOOL exists; - RefPtr<IDWriteLocalizedStrings> infostrings; - hr = aFont->GetInformationalStrings(aWhichName, getter_AddRefs(infostrings), &exists); - if (FAILED(hr) || !exists) { - return E_FAIL; - } - - AutoTArray<wchar_t,32> faceName; - UINT32 englishIdx = 0; - hr = infostrings->FindLocaleName(L"en-us", &englishIdx, &exists); - if (FAILED(hr)) { - return hr; - } - - if (!exists) { - // No english found, use whatever is first in the list. - englishIdx = 0; - } - UINT32 length; - hr = infostrings->GetStringLength(englishIdx, &length); - if (FAILED(hr)) { - return hr; - } - faceName.SetLength(length + 1); - hr = infostrings->GetString(englishIdx, faceName.Elements(), length + 1); - if (FAILED(hr)) { - return hr; - } - - aFontName.Assign(faceName.Elements()); - return S_OK; -} - -void -gfxDWriteFontFamily::FindStyleVariations(FontInfoData *aFontInfoData) -{ - HRESULT hr; - if (mHasStyles) { - return; - } - mHasStyles = true; - - gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList(); - - bool skipFaceNames = mFaceNamesInitialized || - !fp->NeedFullnamePostscriptNames(); - bool fontInfoShouldHaveFaceNames = !mFaceNamesInitialized && - fp->NeedFullnamePostscriptNames() && - aFontInfoData; - - for (UINT32 i = 0; i < mDWFamily->GetFontCount(); i++) { - RefPtr<IDWriteFont> font; - hr = mDWFamily->GetFont(i, getter_AddRefs(font)); - if (FAILED(hr)) { - // This should never happen. - NS_WARNING("Failed to get existing font from family."); - continue; - } - - if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { - // We don't want these in the font list; we'll apply simulations - // on the fly when appropriate. - continue; - } - - // name - nsString fullID(mName); - nsAutoString faceName; - hr = GetDirectWriteFontName(font, faceName); - if (FAILED(hr)) { - continue; - } - fullID.Append(' '); - fullID.Append(faceName); - - gfxDWriteFontEntry *fe = new gfxDWriteFontEntry(fullID, font); - fe->SetForceGDIClassic(mForceGDIClassic); - AddFontEntry(fe); - - // postscript/fullname if needed - nsAutoString psname, fullname; - if (fontInfoShouldHaveFaceNames) { - aFontInfoData->GetFaceNames(fe->Name(), fullname, psname); - if (!fullname.IsEmpty()) { - fp->AddFullname(fe, fullname); - } - if (!psname.IsEmpty()) { - fp->AddPostscriptName(fe, psname); - } - } else if (!skipFaceNames) { - hr = GetDirectWriteFaceName(font, PSNAME_ID, psname); - if (FAILED(hr)) { - skipFaceNames = true; - } else if (psname.Length() > 0) { - fp->AddPostscriptName(fe, psname); - } - - hr = GetDirectWriteFaceName(font, FULLNAME_ID, fullname); - if (FAILED(hr)) { - skipFaceNames = true; - } else if (fullname.Length() > 0) { - fp->AddFullname(fe, fullname); - } - } - - if (LOG_FONTLIST_ENABLED()) { - LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" - " with style: %s weight: %d stretch: %d psname: %s fullname: %s", - NS_ConvertUTF16toUTF8(fe->Name()).get(), - NS_ConvertUTF16toUTF8(Name()).get(), - (fe->IsItalic()) ? - "italic" : (fe->IsOblique() ? "oblique" : "normal"), - fe->Weight(), fe->Stretch(), - NS_ConvertUTF16toUTF8(psname).get(), - NS_ConvertUTF16toUTF8(fullname).get())); - } - } - - // assume that if no error, all postscript/fullnames were initialized - if (!skipFaceNames) { - mFaceNamesInitialized = true; - } - - if (!mAvailableFonts.Length()) { - NS_WARNING("Family with no font faces in it."); - } - - if (mIsBadUnderlineFamily) { - SetBadUnderlineFonts(); - } -} - -void -gfxDWriteFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList, - bool aNeedFullnamePostscriptNames, - FontInfoData *aFontInfoData) -{ - // if all needed names have already been read, skip - if (mOtherFamilyNamesInitialized && - (mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) { - return; - } - - // If we've been passed a FontInfoData, we skip the DWrite implementation - // here and fall back to the generic code which will use that info. - if (!aFontInfoData) { - // DirectWrite version of this will try to read - // postscript/fullnames via DirectWrite API - FindStyleVariations(); - } - - // fallback to looking up via name table - if (!mOtherFamilyNamesInitialized || !mFaceNamesInitialized) { - gfxFontFamily::ReadFaceNames(aPlatformFontList, - aNeedFullnamePostscriptNames, - aFontInfoData); - } -} - -void -gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName) -{ - aLocalizedName.AssignLiteral("Unknown Font"); - HRESULT hr; - nsresult rv; - nsCOMPtr<nsILocaleService> ls = do_GetService(NS_LOCALESERVICE_CONTRACTID, - &rv); - nsCOMPtr<nsILocale> locale; - rv = ls->GetApplicationLocale(getter_AddRefs(locale)); - nsString localeName; - if (NS_SUCCEEDED(rv)) { - rv = locale->GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), - localeName); - } - if (NS_FAILED(rv)) { - localeName.AssignLiteral("en-us"); - } - - RefPtr<IDWriteLocalizedStrings> names; - - hr = mDWFamily->GetFamilyNames(getter_AddRefs(names)); - if (FAILED(hr)) { - return; - } - UINT32 idx = 0; - BOOL exists; - hr = names->FindLocaleName(localeName.get(), - &idx, - &exists); - if (FAILED(hr)) { - return; - } - if (!exists) { - // Use english is localized is not found. - hr = names->FindLocaleName(L"en-us", &idx, &exists); - if (FAILED(hr)) { - return; - } - if (!exists) { - // Use 0 index if english is not found. - idx = 0; - } - } - AutoTArray<WCHAR, 32> famName; - UINT32 length; - - hr = names->GetStringLength(idx, &length); - if (FAILED(hr)) { - return; - } - - if (!famName.SetLength(length + 1, fallible)) { - // Eeep - running out of memory. Unlikely to end well. - return; - } - - hr = names->GetString(idx, famName.Elements(), length + 1); - if (FAILED(hr)) { - return; - } - - aLocalizedName = nsDependentString(famName.Elements()); -} - -void -gfxDWriteFontFamily::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - gfxFontFamily::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); - // TODO: - // This doesn't currently account for |mDWFamily| -} - -void -gfxDWriteFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - aSizes->mFontListSize += aMallocSizeOf(this); - AddSizeOfExcludingThis(aMallocSizeOf, aSizes); -} - -//////////////////////////////////////////////////////////////////////////////// -// gfxDWriteFontEntry - -gfxDWriteFontEntry::~gfxDWriteFontEntry() -{ -} - -bool -gfxDWriteFontEntry::IsSymbolFont() -{ - if (mFont) { - return mFont->IsSymbolFont(); - } else { - return false; - } -} - -static bool -UsingArabicOrHebrewScriptSystemLocale() -{ - LANGID langid = PRIMARYLANGID(::GetSystemDefaultLangID()); - switch (langid) { - case LANG_ARABIC: - case LANG_DARI: - case LANG_PASHTO: - case LANG_PERSIAN: - case LANG_SINDHI: - case LANG_UIGHUR: - case LANG_URDU: - case LANG_HEBREW: - return true; - default: - return false; - } -} - -nsresult -gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag, - nsTArray<uint8_t> &aBuffer) -{ - gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList(); - const uint32_t tagBE = NativeEndian::swapToBigEndian(aTableTag); - - // Don't use GDI table loading for symbol fonts or for - // italic fonts in Arabic-script system locales because of - // potential cmap discrepancies, see bug 629386. - // Ditto for Hebrew, bug 837498. - if (mFont && pFontList->UseGDIFontTableAccess() && - !(mStyle && UsingArabicOrHebrewScriptSystemLocale()) && - !mFont->IsSymbolFont()) - { - LOGFONTW logfont = { 0 }; - if (InitLogFont(mFont, &logfont)) { - AutoDC dc; - AutoSelectFont font(dc.GetDC(), &logfont); - if (font.IsValid()) { - uint32_t tableSize = - ::GetFontData(dc.GetDC(), tagBE, 0, nullptr, 0); - if (tableSize != GDI_ERROR) { - if (aBuffer.SetLength(tableSize, fallible)) { - ::GetFontData(dc.GetDC(), tagBE, 0, - aBuffer.Elements(), aBuffer.Length()); - return NS_OK; - } - return NS_ERROR_OUT_OF_MEMORY; - } - } - } - } - - RefPtr<IDWriteFontFace> fontFace; - nsresult rv = CreateFontFace(getter_AddRefs(fontFace)); - if (NS_FAILED(rv)) { - return rv; - } - - uint8_t *tableData; - uint32_t len; - void *tableContext = nullptr; - BOOL exists; - HRESULT hr = - fontFace->TryGetFontTable(tagBE, (const void**)&tableData, &len, - &tableContext, &exists); - if (FAILED(hr) || !exists) { - return NS_ERROR_FAILURE; - } - - if (aBuffer.SetLength(len, fallible)) { - memcpy(aBuffer.Elements(), tableData, len); - rv = NS_OK; - } else { - rv = NS_ERROR_OUT_OF_MEMORY; - } - - if (tableContext) { - fontFace->ReleaseFontTable(&tableContext); - } - - return rv; -} - -// Access to font tables packaged in hb_blob_t form - -// object attached to the Harfbuzz blob, used to release -// the table when the blob is destroyed -class FontTableRec { -public: - FontTableRec(IDWriteFontFace *aFontFace, void *aContext) - : mFontFace(aFontFace), mContext(aContext) - { - MOZ_COUNT_CTOR(FontTableRec); - } - - ~FontTableRec() { - MOZ_COUNT_DTOR(FontTableRec); - mFontFace->ReleaseFontTable(mContext); - } - -private: - RefPtr<IDWriteFontFace> mFontFace; - void *mContext; -}; - -static void -DestroyBlobFunc(void* aUserData) -{ - FontTableRec *ftr = static_cast<FontTableRec*>(aUserData); - delete ftr; -} - -hb_blob_t * -gfxDWriteFontEntry::GetFontTable(uint32_t aTag) -{ - // try to avoid potentially expensive DWrite call if we haven't actually - // created the font face yet, by using the gfxFontEntry method that will - // use CopyFontTable and then cache the data - if (!mFontFace) { - return gfxFontEntry::GetFontTable(aTag); - } - - const void *data; - UINT32 size; - void *context; - BOOL exists; - HRESULT hr = mFontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTag), - &data, &size, &context, &exists); - if (SUCCEEDED(hr) && exists) { - FontTableRec *ftr = new FontTableRec(mFontFace, context); - return hb_blob_create(static_cast<const char*>(data), size, - HB_MEMORY_MODE_READONLY, - ftr, DestroyBlobFunc); - } - - return nullptr; -} - -nsresult -gfxDWriteFontEntry::ReadCMAP(FontInfoData *aFontInfoData) -{ - PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS); - - // attempt this once, if errors occur leave a blank cmap - if (mCharacterMap) { - return NS_OK; - } - - RefPtr<gfxCharacterMap> charmap; - nsresult rv; - bool symbolFont; - - if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData, - mUVSOffset, - symbolFont))) { - rv = NS_OK; - } else { - uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p'); - charmap = new gfxCharacterMap(); - AutoTable cmapTable(this, kCMAP); - - if (cmapTable) { - bool unicodeFont = false, symbolFont = false; // currently ignored - uint32_t cmapLen; - const uint8_t* cmapData = - reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable, - &cmapLen)); - rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, - *charmap, mUVSOffset, - unicodeFont, symbolFont); - } else { - rv = NS_ERROR_NOT_AVAILABLE; - } - } - - mHasCmapTable = NS_SUCCEEDED(rv); - if (mHasCmapTable) { - // Bug 969504: exclude U+25B6 from Segoe UI family, because it's used - // by sites to represent a "Play" icon, but the glyph in Segoe UI Light - // and Semibold on Windows 7 is too thin. (Ditto for leftward U+25C0.) - // Fallback to Segoe UI Symbol is preferred. - if (FamilyName().EqualsLiteral("Segoe UI")) { - charmap->clear(0x25b6); - charmap->clear(0x25c0); - } - gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); - mCharacterMap = pfl->FindCharMap(charmap); - } else { - // if error occurred, initialize to null cmap - mCharacterMap = new gfxCharacterMap(); - } - - LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", - NS_ConvertUTF16toUTF8(mName).get(), - charmap->SizeOfIncludingThis(moz_malloc_size_of), - charmap->mHash, mCharacterMap == charmap ? " new" : "")); - if (LOG_CMAPDATA_ENABLED()) { - char prefix[256]; - SprintfLiteral(prefix, "(cmapdata) name: %.220s", - NS_ConvertUTF16toUTF8(mName).get()); - charmap->Dump(prefix, eGfxLog_cmapdata); - } - - return rv; -} - -gfxFont * -gfxDWriteFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, - bool aNeedsBold) -{ - return new gfxDWriteFont(this, aFontStyle, aNeedsBold); -} - -nsresult -gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace, - DWRITE_FONT_SIMULATIONS aSimulations) -{ - // initialize mFontFace if this hasn't been done before - if (!mFontFace) { - HRESULT hr; - if (mFont) { - hr = mFont->CreateFontFace(getter_AddRefs(mFontFace)); - } else if (mFontFile) { - IDWriteFontFile *fontFile = mFontFile.get(); - hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> - CreateFontFace(mFaceType, - 1, - &fontFile, - 0, - DWRITE_FONT_SIMULATIONS_NONE, - getter_AddRefs(mFontFace)); - } else { - NS_NOTREACHED("invalid font entry"); - return NS_ERROR_FAILURE; - } - if (FAILED(hr)) { - return NS_ERROR_FAILURE; - } - } - - // check whether we need to add a DWrite simulated style - if ((aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) && - !(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) { - // if so, we need to return not mFontFace itself but a version that - // has the Bold simulation - unfortunately, DWrite doesn't provide - // a simple API for this - UINT32 numberOfFiles = 0; - if (FAILED(mFontFace->GetFiles(&numberOfFiles, nullptr))) { - return NS_ERROR_FAILURE; - } - AutoTArray<IDWriteFontFile*,1> files; - files.AppendElements(numberOfFiles); - if (FAILED(mFontFace->GetFiles(&numberOfFiles, files.Elements()))) { - return NS_ERROR_FAILURE; - } - HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> - CreateFontFace(mFontFace->GetType(), - numberOfFiles, - files.Elements(), - mFontFace->GetIndex(), - aSimulations, - aFontFace); - for (UINT32 i = 0; i < numberOfFiles; ++i) { - files[i]->Release(); - } - return FAILED(hr) ? NS_ERROR_FAILURE : NS_OK; - } - - // no simulation: we can just add a reference to mFontFace and return that - *aFontFace = mFontFace; - (*aFontFace)->AddRef(); - return NS_OK; -} - -bool -gfxDWriteFontEntry::InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont) -{ - HRESULT hr; - - BOOL isInSystemCollection; - IDWriteGdiInterop *gdi = - gfxDWriteFontList::PlatformFontList()->GetGDIInterop(); - hr = gdi->ConvertFontToLOGFONT(aFont, aLogFont, &isInSystemCollection); - // If the font is not in the system collection, GDI will be unable to - // select it and load its tables, so we return false here to indicate - // failure, and let CopyFontTable fall back to DWrite native methods. - return (SUCCEEDED(hr) && isInSystemCollection); -} - -bool -gfxDWriteFontEntry::IsCJKFont() -{ - if (mIsCJK != UNINITIALIZED_VALUE) { - return mIsCJK; - } - - mIsCJK = false; - - const uint32_t kOS2Tag = TRUETYPE_TAG('O','S','/','2'); - AutoTArray<uint8_t, 128> buffer; - if (CopyFontTable(kOS2Tag, buffer) != NS_OK) { - return mIsCJK; - } - - // ulCodePageRange bit definitions for the CJK codepages, - // from http://www.microsoft.com/typography/otspec/os2.htm#cpr - const uint32_t CJK_CODEPAGE_BITS = - (1 << 17) | // codepage 932 - JIS/Japan - (1 << 18) | // codepage 936 - Chinese (simplified) - (1 << 19) | // codepage 949 - Korean Wansung - (1 << 20) | // codepage 950 - Chinese (traditional) - (1 << 21); // codepage 1361 - Korean Johab - - if (buffer.Length() >= offsetof(OS2Table, sxHeight)) { - const OS2Table* os2 = - reinterpret_cast<const OS2Table*>(buffer.Elements()); - if ((uint32_t(os2->codePageRange1) & CJK_CODEPAGE_BITS) != 0) { - mIsCJK = true; - } - } - - return mIsCJK; -} - -void -gfxDWriteFontEntry::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - gfxFontEntry::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); - // TODO: - // This doesn't currently account for the |mFont| and |mFontFile| members -} - -void -gfxDWriteFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - aSizes->mFontListSize += aMallocSizeOf(this); - AddSizeOfExcludingThis(aMallocSizeOf, aSizes); -} - -//////////////////////////////////////////////////////////////////////////////// -// gfxDWriteFontList - -gfxDWriteFontList::gfxDWriteFontList() - : mForceGDIClassicMaxFontSize(0.0) -{ -} - -// bug 602792 - CJK systems default to large CJK fonts which cause excessive -// I/O strain during cold startup due to dwrite caching bugs. Default to -// Arial to avoid this. - -gfxFontFamily * -gfxDWriteFontList::GetDefaultFontForPlatform(const gfxFontStyle *aStyle) -{ - nsAutoString resolvedName; - - // try Arial first - gfxFontFamily *ff; - if ((ff = FindFamily(NS_LITERAL_STRING("Arial")))) { - return ff; - } - - // otherwise, use local default - NONCLIENTMETRICSW ncm; - ncm.cbSize = sizeof(ncm); - BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, - sizeof(ncm), &ncm, 0); - - if (status) { - ff = FindFamily(nsDependentString(ncm.lfMessageFont.lfFaceName)); - if (ff) { - return ff; - } - } - - return nullptr; -} - -gfxFontEntry * -gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle) -{ - gfxFontEntry *lookup; - - lookup = LookupInFaceNameLists(aFontName); - if (!lookup) { - return nullptr; - } - - gfxDWriteFontEntry* dwriteLookup = static_cast<gfxDWriteFontEntry*>(lookup); - gfxDWriteFontEntry *fe = - new gfxDWriteFontEntry(lookup->Name(), - dwriteLookup->mFont, - aWeight, - aStretch, - aStyle); - fe->SetForceGDIClassic(dwriteLookup->GetForceGDIClassic()); - return fe; -} - -gfxFontEntry * -gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle, - const uint8_t* aFontData, - uint32_t aLength) -{ - nsresult rv; - nsAutoString uniqueName; - rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); - if (NS_FAILED(rv)) { - free((void*)aFontData); - return nullptr; - } - - FallibleTArray<uint8_t> newFontData; - - rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData); - free((void*)aFontData); - - if (NS_FAILED(rv)) { - return nullptr; - } - - RefPtr<IDWriteFontFileStream> fontFileStream; - RefPtr<IDWriteFontFile> fontFile; - HRESULT hr = - gfxDWriteFontFileLoader::CreateCustomFontFile(newFontData, - getter_AddRefs(fontFile), - getter_AddRefs(fontFileStream)); - - if (FAILED(hr)) { - NS_WARNING("Failed to create custom font file reference."); - return nullptr; - } - - BOOL isSupported; - DWRITE_FONT_FILE_TYPE fileType; - UINT32 numFaces; - - gfxDWriteFontEntry *entry = - new gfxDWriteFontEntry(uniqueName, - fontFile, - fontFileStream, - aWeight, - aStretch, - aStyle); - - fontFile->Analyze(&isSupported, &fileType, &entry->mFaceType, &numFaces); - if (!isSupported || numFaces > 1) { - // We don't know how to deal with 0 faces either. - delete entry; - return nullptr; - } - - return entry; -} - -enum DWriteInitError { - errGDIInterop = 1, - errSystemFontCollection = 2, - errNoFonts = 3 -}; - -nsresult -gfxDWriteFontList::InitFontListForPlatform() -{ - LARGE_INTEGER frequency; // ticks per second - LARGE_INTEGER t1, t2, t3, t4, t5; // ticks - double elapsedTime, upTime; - char nowTime[256], nowDate[256]; - - if (LOG_FONTINIT_ENABLED()) { - GetTimeFormatA(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, - nullptr, nullptr, nowTime, 256); - GetDateFormatA(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256); - upTime = (double) GetTickCount(); - } - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter(&t1); // start - - HRESULT hr; - mGDIFontTableAccess = - Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", - false); - - mFontSubstitutes.Clear(); - mNonExistingFonts.Clear(); - - hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> - GetGdiInterop(getter_AddRefs(mGDIInterop)); - if (FAILED(hr)) { - return NS_ERROR_FAILURE; - } - - QueryPerformanceCounter(&t2); // base-class/interop initialization - - RefPtr<IDWriteFactory> factory = - gfxWindowsPlatform::GetPlatform()->GetDWriteFactory(); - - hr = factory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); - NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); - - if (FAILED(hr)) { - return NS_ERROR_FAILURE; - } - - QueryPerformanceCounter(&t3); // system font collection - - GetFontsFromCollection(mSystemFonts); - - // if no fonts found, something is out of whack, bail and use GDI backend - NS_ASSERTION(mFontFamilies.Count() != 0, - "no fonts found in the system fontlist -- holy crap batman!"); - if (mFontFamilies.Count() == 0) { - return NS_ERROR_FAILURE; - } - - QueryPerformanceCounter(&t4); // iterate over system fonts - - mBundledFonts = CreateBundledFontsCollection(factory); - if (mBundledFonts) { - GetFontsFromCollection(mBundledFonts); - } - - mOtherFamilyNamesInitialized = true; - GetFontSubstitutes(); - - // bug 642093 - DirectWrite does not support old bitmap (.fon) - // font files, but a few of these such as "Courier" and "MS Sans Serif" - // are frequently specified in shoddy CSS, without appropriate fallbacks. - // By mapping these to TrueType equivalents, we provide better consistency - // with both pre-DW systems and with IE9, which appears to do the same. - GetDirectWriteSubstitutes(); - - // bug 551313 - DirectWrite creates a Gill Sans family out of - // poorly named members of the Gill Sans MT family containing - // only Ultra Bold weights. This causes big problems for pages - // using Gill Sans which is usually only available on OSX - - nsAutoString nameGillSans(L"Gill Sans"); - nsAutoString nameGillSansMT(L"Gill Sans MT"); - BuildKeyNameFromFontName(nameGillSans); - BuildKeyNameFromFontName(nameGillSansMT); - - gfxFontFamily *gillSansFamily = mFontFamilies.GetWeak(nameGillSans); - gfxFontFamily *gillSansMTFamily = mFontFamilies.GetWeak(nameGillSansMT); - - if (gillSansFamily && gillSansMTFamily) { - gillSansFamily->FindStyleVariations(); - nsTArray<RefPtr<gfxFontEntry> >& faces = gillSansFamily->GetFontList(); - uint32_t i; - - bool allUltraBold = true; - for (i = 0; i < faces.Length(); i++) { - // does the face have 'Ultra Bold' in the name? - if (faces[i]->Name().Find(NS_LITERAL_STRING("Ultra Bold")) == -1) { - allUltraBold = false; - break; - } - } - - // if all the Gill Sans faces are Ultra Bold ==> move faces - // for Gill Sans into Gill Sans MT family - if (allUltraBold) { - - // add faces to Gill Sans MT - for (i = 0; i < faces.Length(); i++) { - // change the entry's family name to match its adoptive family - faces[i]->mFamilyName = gillSansMTFamily->Name(); - gillSansMTFamily->AddFontEntry(faces[i]); - - if (LOG_FONTLIST_ENABLED()) { - gfxFontEntry *fe = faces[i]; - LOG_FONTLIST(("(fontlist) moved (%s) to family (%s)" - " with style: %s weight: %d stretch: %d", - NS_ConvertUTF16toUTF8(fe->Name()).get(), - NS_ConvertUTF16toUTF8(gillSansMTFamily->Name()).get(), - (fe->IsItalic()) ? - "italic" : (fe->IsOblique() ? "oblique" : "normal"), - fe->Weight(), fe->Stretch())); - } - } - - // remove Gills Sans - mFontFamilies.Remove(nameGillSans); - } - } - - nsAdoptingCString classicFamilies = - Preferences::GetCString("gfx.font_rendering.cleartype_params.force_gdi_classic_for_families"); - if (classicFamilies) { - nsCCharSeparatedTokenizer tokenizer(classicFamilies, ','); - while (tokenizer.hasMoreTokens()) { - NS_ConvertUTF8toUTF16 name(tokenizer.nextToken()); - BuildKeyNameFromFontName(name); - gfxFontFamily *family = mFontFamilies.GetWeak(name); - if (family) { - static_cast<gfxDWriteFontFamily*>(family)->SetForceGDIClassic(true); - } - } - } - mForceGDIClassicMaxFontSize = - Preferences::GetInt("gfx.font_rendering.cleartype_params.force_gdi_classic_max_size", - mForceGDIClassicMaxFontSize); - - GetPrefsAndStartLoader(); - - QueryPerformanceCounter(&t5); // misc initialization - - if (LOG_FONTINIT_ENABLED()) { - // determine dwrite version - nsAutoString dwriteVers; - gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", dwriteVers); - LOG_FONTINIT(("(fontinit) Start: %s %s\n", nowDate, nowTime)); - LOG_FONTINIT(("(fontinit) Uptime: %9.3f s\n", upTime/1000)); - LOG_FONTINIT(("(fontinit) dwrite version: %s\n", - NS_ConvertUTF16toUTF8(dwriteVers).get())); - } - - elapsedTime = (t5.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; - LOG_FONTINIT(( - "(fontinit) Total time in InitFontList: %9.3f ms (families: %d, %s)\n", - elapsedTime, mSystemFonts->GetFontFamilyCount(), - (mGDIFontTableAccess ? "gdi table access" : "dwrite table access"))); - - elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; - LOG_FONTINIT(("(fontinit) --- base/interop obj initialization init: %9.3f ms\n", elapsedTime)); - - elapsedTime = (t3.QuadPart - t2.QuadPart) * 1000.0 / frequency.QuadPart; - LOG_FONTINIT(("(fontinit) --- GetSystemFontCollection: %9.3f ms\n", elapsedTime)); - - elapsedTime = (t4.QuadPart - t3.QuadPart) * 1000.0 / frequency.QuadPart; - LOG_FONTINIT(("(fontinit) --- iterate over families: %9.3f ms\n", elapsedTime)); - - elapsedTime = (t5.QuadPart - t4.QuadPart) * 1000.0 / frequency.QuadPart; - LOG_FONTINIT(("(fontinit) --- misc initialization: %9.3f ms\n", elapsedTime)); - - return NS_OK; -} - -void -gfxDWriteFontList::GetFontsFromCollection(IDWriteFontCollection* aCollection) -{ - for (UINT32 i = 0; i < aCollection->GetFontFamilyCount(); i++) { - RefPtr<IDWriteFontFamily> family; - aCollection->GetFontFamily(i, getter_AddRefs(family)); - - RefPtr<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; - } - - AutoTArray<WCHAR, 32> enName; - UINT32 length; - - hr = names->GetStringLength(englishIdx, &length); - if (FAILED(hr)) { - continue; - } - - if (!enName.SetLength(length + 1, fallible)) { - // 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); - - RefPtr<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; - AutoTArray<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, fallible)) { - 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) -{ - int32_t comma = aName.FindChar(char16_t(',')); - if (comma >= 0) - aName.Truncate(comma); -} - -#define MAX_VALUE_NAME 512 -#define MAX_VALUE_DATA 512 - -nsresult -gfxDWriteFontList::GetFontSubstitutes() -{ - HKEY hKey; - DWORD i, rv, lenAlias, lenActual, valueType; - WCHAR aliasName[MAX_VALUE_NAME]; - WCHAR actualName[MAX_VALUE_DATA]; - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", - 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - return NS_ERROR_FAILURE; - } - - for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) { - aliasName[0] = 0; - lenAlias = ArrayLength(aliasName); - actualName[0] = 0; - lenActual = sizeof(actualName); - rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, nullptr, &valueType, - (LPBYTE)actualName, &lenActual); - - if (rv != ERROR_SUCCESS || valueType != REG_SZ || lenAlias == 0) { - continue; - } - - if (aliasName[0] == WCHAR('@')) { - continue; - } - - nsAutoString substituteName((char16_t*) aliasName); - nsAutoString actualFontName((char16_t*) actualName); - RemoveCharsetFromFontSubstitute(substituteName); - BuildKeyNameFromFontName(substituteName); - RemoveCharsetFromFontSubstitute(actualFontName); - BuildKeyNameFromFontName(actualFontName); - gfxFontFamily *ff; - if (!actualFontName.IsEmpty() && - (ff = mFontFamilies.GetWeak(actualFontName))) { - mFontSubstitutes.Put(substituteName, ff); - } else { - mNonExistingFonts.AppendElement(substituteName); - } - } - return NS_OK; -} - -struct FontSubstitution { - const WCHAR* aliasName; - const WCHAR* actualName; -}; - -static const FontSubstitution sDirectWriteSubs[] = { - { L"MS Sans Serif", L"Microsoft Sans Serif" }, - { L"MS Serif", L"Times New Roman" }, - { L"Courier", L"Courier New" }, - { L"Small Fonts", L"Arial" }, - { L"Roman", L"Times New Roman" }, - { L"Script", L"Mistral" } -}; - -void -gfxDWriteFontList::GetDirectWriteSubstitutes() -{ - for (uint32_t i = 0; i < ArrayLength(sDirectWriteSubs); ++i) { - const FontSubstitution& sub(sDirectWriteSubs[i]); - nsAutoString substituteName((char16_t*)sub.aliasName); - BuildKeyNameFromFontName(substituteName); - if (nullptr != mFontFamilies.GetWeak(substituteName)) { - // don't do the substitution if user actually has a usable font - // with this name installed - continue; - } - nsAutoString actualFontName((char16_t*)sub.actualName); - BuildKeyNameFromFontName(actualFontName); - gfxFontFamily *ff; - if (nullptr != (ff = mFontFamilies.GetWeak(actualFontName))) { - mFontSubstitutes.Put(substituteName, ff); - } else { - mNonExistingFonts.AppendElement(substituteName); - } - } -} - -bool -gfxDWriteFontList::GetStandardFamilyName(const nsAString& aFontName, - nsAString& aFamilyName) -{ - gfxFontFamily *family = FindFamily(aFontName); - if (family) { - family->LocalizedName(aFamilyName); - return true; - } - - return false; -} - -bool -gfxDWriteFontList::FindAndAddFamilies(const nsAString& aFamily, - nsTArray<gfxFontFamily*>* aOutput, - gfxFontStyle* aStyle, - gfxFloat aDevToCssSize) -{ - nsAutoString keyName(aFamily); - BuildKeyNameFromFontName(keyName); - - gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName); - if (ff) { - aOutput->AppendElement(ff); - return true; - } - - if (mNonExistingFonts.Contains(keyName)) { - return false; - } - - return gfxPlatformFontList::FindAndAddFamilies(aFamily, aOutput, aStyle, - aDevToCssSize); -} - -void -gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); - - aSizes->mFontListSize += - SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf); - - aSizes->mFontListSize += - mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf); - for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) { - aSizes->mFontListSize += - mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf); - } -} - -void -gfxDWriteFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const -{ - aSizes->mFontListSize += aMallocSizeOf(this); - AddSizeOfExcludingThis(aMallocSizeOf, aSizes); -} - -static HRESULT GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName) -{ - HRESULT hr; - RefPtr<IDWriteFontFamily> family; - - // clean out previous value - aFamilyName.Truncate(); - - hr = aFont->GetFontFamily(getter_AddRefs(family)); - if (FAILED(hr)) { - return hr; - } - - RefPtr<IDWriteLocalizedStrings> familyNames; - - hr = family->GetFamilyNames(getter_AddRefs(familyNames)); - if (FAILED(hr)) { - return hr; - } - - UINT32 index = 0; - BOOL exists = false; - - hr = familyNames->FindLocaleName(L"en-us", &index, &exists); - if (FAILED(hr)) { - return hr; - } - - // If the specified locale doesn't exist, select the first on the list. - if (!exists) { - index = 0; - } - - AutoTArray<WCHAR, 32> name; - UINT32 length; - - hr = familyNames->GetStringLength(index, &length); - if (FAILED(hr)) { - return hr; - } - - if (!name.SetLength(length + 1, fallible)) { - return E_FAIL; - } - hr = familyNames->GetString(index, name.Elements(), length + 1); - if (FAILED(hr)) { - return hr; - } - - aFamilyName.Assign(name.Elements()); - return S_OK; -} - -// bug 705594 - the method below doesn't actually do any "drawing", it's only -// used to invoke the DirectWrite layout engine to determine the fallback font -// for a given character. - -IFACEMETHODIMP DWriteFontFallbackRenderer::DrawGlyphRun( - void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - DWRITE_MEASURING_MODE measuringMode, - DWRITE_GLYPH_RUN const* glyphRun, - DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, - IUnknown* clientDrawingEffect - ) -{ - if (!mSystemFonts) { - return E_FAIL; - } - - HRESULT hr = S_OK; - - RefPtr<IDWriteFont> font; - hr = mSystemFonts->GetFontFromFontFace(glyphRun->fontFace, - getter_AddRefs(font)); - if (FAILED(hr)) { - return hr; - } - - // copy the family name - hr = GetFamilyName(font, mFamilyName); - if (FAILED(hr)) { - return hr; - } - - // Arial is used as the default fallback font - // so if it matches ==> no font found - if (mFamilyName.EqualsLiteral("Arial")) { - mFamilyName.Truncate(); - return E_FAIL; - } - return hr; -} - -gfxFontEntry* -gfxDWriteFontList::PlatformGlobalFontFallback(const uint32_t aCh, - Script aRunScript, - const gfxFontStyle* aMatchStyle, - gfxFontFamily** aMatchedFamily) -{ - HRESULT hr; - - RefPtr<IDWriteFactory> dwFactory = - gfxWindowsPlatform::GetPlatform()->GetDWriteFactory(); - if (!dwFactory) { - return nullptr; - } - - // initialize fallback renderer - if (!mFallbackRenderer) { - mFallbackRenderer = new DWriteFontFallbackRenderer(dwFactory); - } - - // initialize text format - if (!mFallbackFormat) { - hr = dwFactory->CreateTextFormat(L"Arial", nullptr, - DWRITE_FONT_WEIGHT_REGULAR, - DWRITE_FONT_STYLE_NORMAL, - DWRITE_FONT_STRETCH_NORMAL, - 72.0f, L"en-us", - getter_AddRefs(mFallbackFormat)); - if (FAILED(hr)) { - return nullptr; - } - } - - // set up string with fallback character - wchar_t str[16]; - uint32_t strLen; - - if (IS_IN_BMP(aCh)) { - str[0] = static_cast<wchar_t> (aCh); - str[1] = 0; - strLen = 1; - } else { - str[0] = static_cast<wchar_t> (H_SURROGATE(aCh)); - str[1] = static_cast<wchar_t> (L_SURROGATE(aCh)); - str[2] = 0; - strLen = 2; - } - - // set up layout - RefPtr<IDWriteTextLayout> fallbackLayout; - - hr = dwFactory->CreateTextLayout(str, strLen, mFallbackFormat, - 200.0f, 200.0f, - getter_AddRefs(fallbackLayout)); - if (FAILED(hr)) { - return nullptr; - } - - // call the draw method to invoke the DirectWrite layout functions - // which determine the fallback font - hr = fallbackLayout->Draw(nullptr, mFallbackRenderer, 50.0f, 50.0f); - if (FAILED(hr)) { - return nullptr; - } - - gfxFontFamily *family = FindFamily(mFallbackRenderer->FallbackFamilyName()); - if (family) { - gfxFontEntry *fontEntry; - bool needsBold; // ignored in the system fallback case - fontEntry = family->FindFontForStyle(*aMatchStyle, needsBold); - if (fontEntry && fontEntry->HasCharacter(aCh)) { - *aMatchedFamily = family; - return fontEntry; - } - } - - return nullptr; -} - -// used to load system-wide font info on off-main thread -class DirectWriteFontInfo : public FontInfoData { -public: - DirectWriteFontInfo(bool aLoadOtherNames, - bool aLoadFaceNames, - bool aLoadCmaps, - IDWriteFontCollection* aSystemFonts - , IDWriteFontCollection* aBundledFonts - ) : - FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps) - , mSystemFonts(aSystemFonts) - , mBundledFonts(aBundledFonts) - {} - - virtual ~DirectWriteFontInfo() {} - - // loads font data for all members of a given family - virtual void LoadFontFamilyData(const nsAString& aFamilyName); - -private: - RefPtr<IDWriteFontCollection> mSystemFonts; - RefPtr<IDWriteFontCollection> mBundledFonts; -}; - -void -DirectWriteFontInfo::LoadFontFamilyData(const nsAString& aFamilyName) -{ - // lookup the family - AutoTArray<wchar_t, 32> famName; - - uint32_t len = aFamilyName.Length(); - if(!famName.SetLength(len + 1, fallible)) { - return; - } - memcpy(famName.Elements(), aFamilyName.BeginReading(), len * sizeof(char16_t)); - famName[len] = 0; - - HRESULT hr; - BOOL exists = false; - - uint32_t index; - RefPtr<IDWriteFontFamily> family; - hr = mSystemFonts->FindFamilyName(famName.Elements(), &index, &exists); - if (SUCCEEDED(hr) && exists) { - mSystemFonts->GetFontFamily(index, getter_AddRefs(family)); - if (!family) { - return; - } - } - - if (!family && mBundledFonts) { - hr = mBundledFonts->FindFamilyName(famName.Elements(), &index, &exists); - if (SUCCEEDED(hr) && exists) { - mBundledFonts->GetFontFamily(index, getter_AddRefs(family)); - } - } - - if (!family) { - return; - } - - // later versions of DirectWrite support querying the fullname/psname - bool loadFaceNamesUsingDirectWrite = mLoadFaceNames; - - for (uint32_t i = 0; i < family->GetFontCount(); i++) { - // get the font - RefPtr<IDWriteFont> dwFont; - hr = family->GetFont(i, getter_AddRefs(dwFont)); - if (FAILED(hr)) { - // This should never happen. - NS_WARNING("Failed to get existing font from family."); - continue; - } - - if (dwFont->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { - // We don't want these in the font list; we'll apply simulations - // on the fly when appropriate. - continue; - } - - mLoadStats.fonts++; - - // get the name of the face - nsString fullID(aFamilyName); - nsAutoString fontName; - hr = GetDirectWriteFontName(dwFont, fontName); - if (FAILED(hr)) { - continue; - } - fullID.Append(' '); - fullID.Append(fontName); - - FontFaceData fontData; - bool haveData = true; - RefPtr<IDWriteFontFace> dwFontFace; - - if (mLoadFaceNames) { - // try to load using DirectWrite first - if (loadFaceNamesUsingDirectWrite) { - hr = GetDirectWriteFaceName(dwFont, PSNAME_ID, fontData.mPostscriptName); - if (FAILED(hr)) { - loadFaceNamesUsingDirectWrite = false; - } - hr = GetDirectWriteFaceName(dwFont, FULLNAME_ID, fontData.mFullName); - if (FAILED(hr)) { - loadFaceNamesUsingDirectWrite = false; - } - } - - // if DirectWrite read fails, load directly from name table - if (!loadFaceNamesUsingDirectWrite) { - hr = dwFont->CreateFontFace(getter_AddRefs(dwFontFace)); - if (SUCCEEDED(hr)) { - uint32_t kNAME = - NativeEndian::swapToBigEndian(TRUETYPE_TAG('n','a','m','e')); - const char *nameData; - BOOL exists; - void* ctx; - uint32_t nameSize; - - hr = dwFontFace->TryGetFontTable( - kNAME, - (const void**)&nameData, &nameSize, &ctx, &exists); - - if (SUCCEEDED(hr) && nameData && nameSize > 0) { - gfxFontUtils::ReadCanonicalName(nameData, nameSize, - gfxFontUtils::NAME_ID_FULL, - fontData.mFullName); - gfxFontUtils::ReadCanonicalName(nameData, nameSize, - gfxFontUtils::NAME_ID_POSTSCRIPT, - fontData.mPostscriptName); - dwFontFace->ReleaseFontTable(ctx); - } - } - } - - haveData = !fontData.mPostscriptName.IsEmpty() || - !fontData.mFullName.IsEmpty(); - if (haveData) { - mLoadStats.facenames++; - } - } - - // cmaps - if (mLoadCmaps) { - if (!dwFontFace) { - hr = dwFont->CreateFontFace(getter_AddRefs(dwFontFace)); - if (!SUCCEEDED(hr)) { - continue; - } - } - - uint32_t kCMAP = - NativeEndian::swapToBigEndian(TRUETYPE_TAG('c','m','a','p')); - const uint8_t *cmapData; - BOOL exists; - void* ctx; - uint32_t cmapSize; - - hr = dwFontFace->TryGetFontTable(kCMAP, - (const void**)&cmapData, &cmapSize, &ctx, &exists); - - if (SUCCEEDED(hr)) { - bool cmapLoaded = false; - bool unicodeFont = false, symbolFont = false; - RefPtr<gfxCharacterMap> charmap = new gfxCharacterMap(); - uint32_t offset; - - if (cmapData && - cmapSize > 0 && - NS_SUCCEEDED( - gfxFontUtils::ReadCMAP(cmapData, cmapSize, *charmap, - offset, unicodeFont, symbolFont))) { - fontData.mCharacterMap = charmap; - fontData.mUVSOffset = offset; - fontData.mSymbolFont = symbolFont; - cmapLoaded = true; - mLoadStats.cmaps++; - } - dwFontFace->ReleaseFontTable(ctx); - haveData = haveData || cmapLoaded; - } - } - - // if have data, load - if (haveData) { - mFontFaceData.Put(fullID, fontData); - } - } -} - -already_AddRefed<FontInfoData> -gfxDWriteFontList::CreateFontInfoData() -{ - bool loadCmaps = !UsesSystemFallback() || - gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); - - RefPtr<DirectWriteFontInfo> fi = - new DirectWriteFontInfo(false, NeedFullnamePostscriptNames(), loadCmaps, - mSystemFonts - , mBundledFonts - ); - - return fi.forget(); -} - - - -#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() = delete; - BundledFontFileEnumerator(const BundledFontFileEnumerator&) = delete; - BundledFontFileEnumerator& operator=(const BundledFontFileEnumerator&) = delete; - virtual ~BundledFontFileEnumerator() {} - - RefPtr<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&) = delete; - BundledFontLoader& operator=(const BundledFontLoader&) = delete; - virtual ~BundledFontLoader() { } -}; - -IFACEMETHODIMP -BundledFontLoader::CreateEnumeratorFromKey( - IDWriteFactory *aFactory, - const void *aCollectionKey, - UINT32 aCollectionKeySize, - IDWriteFontFileEnumerator **aFontFileEnumerator) -{ - nsIFile *fontDir = *(nsIFile**)aCollectionKey; - *aFontFileEnumerator = new BundledFontFileEnumerator(aFactory, fontDir); - NS_ADDREF(*aFontFileEnumerator); - 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; - } - - RefPtr<BundledFontLoader> loader = new BundledFontLoader(); - if (FAILED(aFactory->RegisterFontCollectionLoader(loader))) { - return nullptr; - } - - const void *key = localDir.get(); - RefPtr<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(); - } -} - |