1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxDWriteFontList.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1743 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 +#include "mozilla/MemoryReporting.h" 1.11 + 1.12 +#ifdef MOZ_LOGGING 1.13 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.14 +#endif /* MOZ_LOGGING */ 1.15 + 1.16 +#include "gfxDWriteFontList.h" 1.17 +#include "gfxDWriteFonts.h" 1.18 +#include "nsUnicharUtils.h" 1.19 +#include "nsILocaleService.h" 1.20 +#include "nsServiceManagerUtils.h" 1.21 +#include "nsCharSeparatedTokenizer.h" 1.22 +#include "mozilla/Preferences.h" 1.23 +#include "mozilla/Telemetry.h" 1.24 + 1.25 +#include "gfxGDIFontList.h" 1.26 + 1.27 +#include "nsIWindowsRegKey.h" 1.28 + 1.29 +#include "harfbuzz/hb.h" 1.30 + 1.31 +using namespace mozilla; 1.32 + 1.33 +#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.34 + PR_LOG_DEBUG, args) 1.35 +#define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \ 1.36 + gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.37 + PR_LOG_DEBUG) 1.38 + 1.39 +#define LOG_FONTINIT(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \ 1.40 + PR_LOG_DEBUG, args) 1.41 +#define LOG_FONTINIT_ENABLED() PR_LOG_TEST( \ 1.42 + gfxPlatform::GetLog(eGfxLog_fontinit), \ 1.43 + PR_LOG_DEBUG) 1.44 + 1.45 +#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \ 1.46 + gfxPlatform::GetLog(eGfxLog_cmapdata), \ 1.47 + PR_LOG_DEBUG) 1.48 + 1.49 +static __inline void 1.50 +BuildKeyNameFromFontName(nsAString &aName) 1.51 +{ 1.52 + if (aName.Length() >= LF_FACESIZE) 1.53 + aName.Truncate(LF_FACESIZE - 1); 1.54 + ToLowerCase(aName); 1.55 +} 1.56 + 1.57 +//////////////////////////////////////////////////////////////////////////////// 1.58 +// gfxDWriteFontFamily 1.59 + 1.60 +gfxDWriteFontFamily::~gfxDWriteFontFamily() 1.61 +{ 1.62 +} 1.63 + 1.64 +static HRESULT 1.65 +GetDirectWriteFontName(IDWriteFont *aFont, nsAString& aFontName) 1.66 +{ 1.67 + HRESULT hr; 1.68 + 1.69 + nsRefPtr<IDWriteLocalizedStrings> names; 1.70 + hr = aFont->GetFaceNames(getter_AddRefs(names)); 1.71 + if (FAILED(hr)) { 1.72 + return hr; 1.73 + } 1.74 + 1.75 + BOOL exists; 1.76 + nsAutoTArray<wchar_t,32> faceName; 1.77 + UINT32 englishIdx = 0; 1.78 + hr = names->FindLocaleName(L"en-us", &englishIdx, &exists); 1.79 + if (FAILED(hr)) { 1.80 + return hr; 1.81 + } 1.82 + 1.83 + if (!exists) { 1.84 + // No english found, use whatever is first in the list. 1.85 + englishIdx = 0; 1.86 + } 1.87 + UINT32 length; 1.88 + hr = names->GetStringLength(englishIdx, &length); 1.89 + if (FAILED(hr)) { 1.90 + return hr; 1.91 + } 1.92 + faceName.SetLength(length + 1); 1.93 + hr = names->GetString(englishIdx, faceName.Elements(), length + 1); 1.94 + if (FAILED(hr)) { 1.95 + return hr; 1.96 + } 1.97 + 1.98 + aFontName.Assign(faceName.Elements()); 1.99 + return S_OK; 1.100 +} 1.101 + 1.102 +// These strings are only defined in Win SDK 8+, so use #ifdef for now 1.103 +#if MOZ_WINSDK_TARGETVER > 0x08000000 1.104 +#define FULLNAME_ID DWRITE_INFORMATIONAL_STRING_FULL_NAME 1.105 +#define PSNAME_ID DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME 1.106 +#else 1.107 +#define FULLNAME_ID DWRITE_INFORMATIONAL_STRING_ID(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT + 1) 1.108 +#define PSNAME_ID DWRITE_INFORMATIONAL_STRING_ID(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT + 2) 1.109 +#endif 1.110 + 1.111 +// for use in reading postscript or fullname 1.112 +static HRESULT 1.113 +GetDirectWriteFaceName(IDWriteFont *aFont, 1.114 + DWRITE_INFORMATIONAL_STRING_ID aWhichName, 1.115 + nsAString& aFontName) 1.116 +{ 1.117 + HRESULT hr; 1.118 + 1.119 + BOOL exists; 1.120 + nsRefPtr<IDWriteLocalizedStrings> infostrings; 1.121 + hr = aFont->GetInformationalStrings(aWhichName, getter_AddRefs(infostrings), &exists); 1.122 + if (FAILED(hr) || !exists) { 1.123 + return E_FAIL; 1.124 + } 1.125 + 1.126 + nsAutoTArray<wchar_t,32> faceName; 1.127 + UINT32 englishIdx = 0; 1.128 + hr = infostrings->FindLocaleName(L"en-us", &englishIdx, &exists); 1.129 + if (FAILED(hr)) { 1.130 + return hr; 1.131 + } 1.132 + 1.133 + if (!exists) { 1.134 + // No english found, use whatever is first in the list. 1.135 + englishIdx = 0; 1.136 + } 1.137 + UINT32 length; 1.138 + hr = infostrings->GetStringLength(englishIdx, &length); 1.139 + if (FAILED(hr)) { 1.140 + return hr; 1.141 + } 1.142 + faceName.SetLength(length + 1); 1.143 + hr = infostrings->GetString(englishIdx, faceName.Elements(), length + 1); 1.144 + if (FAILED(hr)) { 1.145 + return hr; 1.146 + } 1.147 + 1.148 + aFontName.Assign(faceName.Elements()); 1.149 + return S_OK; 1.150 +} 1.151 + 1.152 +void 1.153 +gfxDWriteFontFamily::FindStyleVariations(FontInfoData *aFontInfoData) 1.154 +{ 1.155 + HRESULT hr; 1.156 + if (mHasStyles) { 1.157 + return; 1.158 + } 1.159 + mHasStyles = true; 1.160 + 1.161 + gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList(); 1.162 + 1.163 + bool skipFaceNames = mFaceNamesInitialized || 1.164 + !fp->NeedFullnamePostscriptNames(); 1.165 + bool fontInfoShouldHaveFaceNames = !mFaceNamesInitialized && 1.166 + fp->NeedFullnamePostscriptNames() && 1.167 + aFontInfoData; 1.168 + 1.169 + for (UINT32 i = 0; i < mDWFamily->GetFontCount(); i++) { 1.170 + nsRefPtr<IDWriteFont> font; 1.171 + hr = mDWFamily->GetFont(i, getter_AddRefs(font)); 1.172 + if (FAILED(hr)) { 1.173 + // This should never happen. 1.174 + NS_WARNING("Failed to get existing font from family."); 1.175 + continue; 1.176 + } 1.177 + 1.178 + if (font->GetSimulations() & DWRITE_FONT_SIMULATIONS_OBLIQUE) { 1.179 + // We don't want these. 1.180 + continue; 1.181 + } 1.182 + 1.183 + // name 1.184 + nsString fullID(mName); 1.185 + nsAutoString faceName; 1.186 + hr = GetDirectWriteFontName(font, faceName); 1.187 + if (FAILED(hr)) { 1.188 + continue; 1.189 + } 1.190 + fullID.Append(NS_LITERAL_STRING(" ")); 1.191 + fullID.Append(faceName); 1.192 + 1.193 + gfxDWriteFontEntry *fe = new gfxDWriteFontEntry(fullID, font); 1.194 + fe->SetForceGDIClassic(mForceGDIClassic); 1.195 + AddFontEntry(fe); 1.196 + 1.197 + // postscript/fullname if needed 1.198 + nsAutoString psname, fullname; 1.199 + if (fontInfoShouldHaveFaceNames) { 1.200 + aFontInfoData->GetFaceNames(fe->Name(), fullname, psname); 1.201 + if (!fullname.IsEmpty()) { 1.202 + fp->AddFullname(fe, fullname); 1.203 + } 1.204 + if (!psname.IsEmpty()) { 1.205 + fp->AddPostscriptName(fe, psname); 1.206 + } 1.207 + } else if (!skipFaceNames) { 1.208 + hr = GetDirectWriteFaceName(font, PSNAME_ID, psname); 1.209 + if (FAILED(hr)) { 1.210 + skipFaceNames = true; 1.211 + } else if (psname.Length() > 0) { 1.212 + fp->AddPostscriptName(fe, psname); 1.213 + } 1.214 + 1.215 + hr = GetDirectWriteFaceName(font, FULLNAME_ID, fullname); 1.216 + if (FAILED(hr)) { 1.217 + skipFaceNames = true; 1.218 + } else if (fullname.Length() > 0) { 1.219 + fp->AddFullname(fe, fullname); 1.220 + } 1.221 + } 1.222 + 1.223 +#ifdef PR_LOGGING 1.224 + if (LOG_FONTLIST_ENABLED()) { 1.225 + LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" 1.226 + " with style: %s weight: %d stretch: %d psname: %s fullname: %s", 1.227 + NS_ConvertUTF16toUTF8(fe->Name()).get(), 1.228 + NS_ConvertUTF16toUTF8(Name()).get(), 1.229 + (fe->IsItalic()) ? "italic" : "normal", 1.230 + fe->Weight(), fe->Stretch(), 1.231 + NS_ConvertUTF16toUTF8(psname).get(), 1.232 + NS_ConvertUTF16toUTF8(fullname).get())); 1.233 + } 1.234 +#endif 1.235 + } 1.236 + 1.237 + // assume that if no error, all postscript/fullnames were initialized 1.238 + if (!skipFaceNames) { 1.239 + mFaceNamesInitialized = true; 1.240 + } 1.241 + 1.242 + if (!mAvailableFonts.Length()) { 1.243 + NS_WARNING("Family with no font faces in it."); 1.244 + } 1.245 + 1.246 + if (mIsBadUnderlineFamily) { 1.247 + SetBadUnderlineFonts(); 1.248 + } 1.249 +} 1.250 + 1.251 +void 1.252 +gfxDWriteFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList, 1.253 + bool aNeedFullnamePostscriptNames) 1.254 +{ 1.255 + // if all needed names have already been read, skip 1.256 + if (mOtherFamilyNamesInitialized && 1.257 + (mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) { 1.258 + return; 1.259 + } 1.260 + 1.261 + // DirectWrite version of this will try to read 1.262 + // postscript/fullnames via DirectWrite API 1.263 + FindStyleVariations(); 1.264 + 1.265 + // fallback to looking up via name table 1.266 + if (!mOtherFamilyNamesInitialized || !mFaceNamesInitialized) { 1.267 + gfxFontFamily::ReadFaceNames(aPlatformFontList, 1.268 + aNeedFullnamePostscriptNames); 1.269 + } 1.270 +} 1.271 + 1.272 +void 1.273 +gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName) 1.274 +{ 1.275 + aLocalizedName.AssignLiteral("Unknown Font"); 1.276 + HRESULT hr; 1.277 + nsresult rv; 1.278 + nsCOMPtr<nsILocaleService> ls = do_GetService(NS_LOCALESERVICE_CONTRACTID, 1.279 + &rv); 1.280 + nsCOMPtr<nsILocale> locale; 1.281 + rv = ls->GetApplicationLocale(getter_AddRefs(locale)); 1.282 + nsString localeName; 1.283 + if (NS_SUCCEEDED(rv)) { 1.284 + rv = locale->GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), 1.285 + localeName); 1.286 + } 1.287 + if (NS_FAILED(rv)) { 1.288 + localeName.AssignLiteral("en-us"); 1.289 + } 1.290 + 1.291 + nsRefPtr<IDWriteLocalizedStrings> names; 1.292 + 1.293 + hr = mDWFamily->GetFamilyNames(getter_AddRefs(names)); 1.294 + if (FAILED(hr)) { 1.295 + return; 1.296 + } 1.297 + UINT32 idx = 0; 1.298 + BOOL exists; 1.299 + hr = names->FindLocaleName(localeName.get(), 1.300 + &idx, 1.301 + &exists); 1.302 + if (FAILED(hr)) { 1.303 + return; 1.304 + } 1.305 + if (!exists) { 1.306 + // Use english is localized is not found. 1.307 + hr = names->FindLocaleName(L"en-us", &idx, &exists); 1.308 + if (FAILED(hr)) { 1.309 + return; 1.310 + } 1.311 + if (!exists) { 1.312 + // Use 0 index if english is not found. 1.313 + idx = 0; 1.314 + } 1.315 + } 1.316 + AutoFallibleTArray<WCHAR, 32> famName; 1.317 + UINT32 length; 1.318 + 1.319 + hr = names->GetStringLength(idx, &length); 1.320 + if (FAILED(hr)) { 1.321 + return; 1.322 + } 1.323 + 1.324 + if (!famName.SetLength(length + 1)) { 1.325 + // Eeep - running out of memory. Unlikely to end well. 1.326 + return; 1.327 + } 1.328 + 1.329 + hr = names->GetString(idx, famName.Elements(), length + 1); 1.330 + if (FAILED(hr)) { 1.331 + return; 1.332 + } 1.333 + 1.334 + aLocalizedName = nsDependentString(famName.Elements()); 1.335 +} 1.336 + 1.337 +void 1.338 +gfxDWriteFontFamily::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, 1.339 + FontListSizes* aSizes) const 1.340 +{ 1.341 + gfxFontFamily::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.342 + // TODO: 1.343 + // This doesn't currently account for |mDWFamily| 1.344 +} 1.345 + 1.346 +void 1.347 +gfxDWriteFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.348 + FontListSizes* aSizes) const 1.349 +{ 1.350 + aSizes->mFontListSize += aMallocSizeOf(this); 1.351 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.352 +} 1.353 + 1.354 +//////////////////////////////////////////////////////////////////////////////// 1.355 +// gfxDWriteFontEntry 1.356 + 1.357 +gfxDWriteFontEntry::~gfxDWriteFontEntry() 1.358 +{ 1.359 +} 1.360 + 1.361 +bool 1.362 +gfxDWriteFontEntry::IsSymbolFont() 1.363 +{ 1.364 + if (mFont) { 1.365 + return mFont->IsSymbolFont(); 1.366 + } else { 1.367 + return false; 1.368 + } 1.369 +} 1.370 + 1.371 +static bool 1.372 +UsingArabicOrHebrewScriptSystemLocale() 1.373 +{ 1.374 + LANGID langid = PRIMARYLANGID(::GetSystemDefaultLangID()); 1.375 + switch (langid) { 1.376 + case LANG_ARABIC: 1.377 + case LANG_DARI: 1.378 + case LANG_PASHTO: 1.379 + case LANG_PERSIAN: 1.380 + case LANG_SINDHI: 1.381 + case LANG_UIGHUR: 1.382 + case LANG_URDU: 1.383 + case LANG_HEBREW: 1.384 + return true; 1.385 + default: 1.386 + return false; 1.387 + } 1.388 +} 1.389 + 1.390 +nsresult 1.391 +gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag, 1.392 + FallibleTArray<uint8_t> &aBuffer) 1.393 +{ 1.394 + gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList(); 1.395 + 1.396 + // Don't use GDI table loading for symbol fonts or for 1.397 + // italic fonts in Arabic-script system locales because of 1.398 + // potential cmap discrepancies, see bug 629386. 1.399 + // Ditto for Hebrew, bug 837498. 1.400 + if (mFont && pFontList->UseGDIFontTableAccess() && 1.401 + !(mItalic && UsingArabicOrHebrewScriptSystemLocale()) && 1.402 + !mFont->IsSymbolFont()) 1.403 + { 1.404 + LOGFONTW logfont = { 0 }; 1.405 + if (!InitLogFont(mFont, &logfont)) 1.406 + return NS_ERROR_FAILURE; 1.407 + 1.408 + AutoDC dc; 1.409 + AutoSelectFont font(dc.GetDC(), &logfont); 1.410 + if (font.IsValid()) { 1.411 + uint32_t tableSize = 1.412 + ::GetFontData(dc.GetDC(), 1.413 + NativeEndian::swapToBigEndian(aTableTag), 0, 1.414 + nullptr, 0); 1.415 + if (tableSize != GDI_ERROR) { 1.416 + if (aBuffer.SetLength(tableSize)) { 1.417 + ::GetFontData(dc.GetDC(), 1.418 + NativeEndian::swapToBigEndian(aTableTag), 0, 1.419 + aBuffer.Elements(), aBuffer.Length()); 1.420 + return NS_OK; 1.421 + } 1.422 + return NS_ERROR_OUT_OF_MEMORY; 1.423 + } 1.424 + } 1.425 + return NS_ERROR_FAILURE; 1.426 + } 1.427 + 1.428 + nsRefPtr<IDWriteFontFace> fontFace; 1.429 + nsresult rv = CreateFontFace(getter_AddRefs(fontFace)); 1.430 + if (NS_FAILED(rv)) { 1.431 + return rv; 1.432 + } 1.433 + 1.434 + uint8_t *tableData; 1.435 + uint32_t len; 1.436 + void *tableContext = nullptr; 1.437 + BOOL exists; 1.438 + HRESULT hr = 1.439 + fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag), 1.440 + (const void**)&tableData, &len, 1.441 + &tableContext, &exists); 1.442 + if (FAILED(hr) || !exists) { 1.443 + return NS_ERROR_FAILURE; 1.444 + } 1.445 + 1.446 + if (aBuffer.SetLength(len)) { 1.447 + memcpy(aBuffer.Elements(), tableData, len); 1.448 + rv = NS_OK; 1.449 + } else { 1.450 + rv = NS_ERROR_OUT_OF_MEMORY; 1.451 + } 1.452 + 1.453 + if (tableContext) { 1.454 + fontFace->ReleaseFontTable(&tableContext); 1.455 + } 1.456 + 1.457 + return rv; 1.458 +} 1.459 + 1.460 +// Access to font tables packaged in hb_blob_t form 1.461 + 1.462 +// object attached to the Harfbuzz blob, used to release 1.463 +// the table when the blob is destroyed 1.464 +class FontTableRec { 1.465 +public: 1.466 + FontTableRec(IDWriteFontFace *aFontFace, void *aContext) 1.467 + : mFontFace(aFontFace), mContext(aContext) 1.468 + { } 1.469 + 1.470 + ~FontTableRec() { 1.471 + mFontFace->ReleaseFontTable(mContext); 1.472 + } 1.473 + 1.474 +private: 1.475 + nsRefPtr<IDWriteFontFace> mFontFace; 1.476 + void *mContext; 1.477 +}; 1.478 + 1.479 +static void 1.480 +DestroyBlobFunc(void* aUserData) 1.481 +{ 1.482 + FontTableRec *ftr = static_cast<FontTableRec*>(aUserData); 1.483 + delete ftr; 1.484 +} 1.485 + 1.486 +hb_blob_t * 1.487 +gfxDWriteFontEntry::GetFontTable(uint32_t aTag) 1.488 +{ 1.489 + // try to avoid potentially expensive DWrite call if we haven't actually 1.490 + // created the font face yet, by using the gfxFontEntry method that will 1.491 + // use CopyFontTable and then cache the data 1.492 + if (!mFontFace) { 1.493 + return gfxFontEntry::GetFontTable(aTag); 1.494 + } 1.495 + 1.496 + const void *data; 1.497 + UINT32 size; 1.498 + void *context; 1.499 + BOOL exists; 1.500 + HRESULT hr = mFontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTag), 1.501 + &data, &size, &context, &exists); 1.502 + if (SUCCEEDED(hr) && exists) { 1.503 + FontTableRec *ftr = new FontTableRec(mFontFace, context); 1.504 + return hb_blob_create(static_cast<const char*>(data), size, 1.505 + HB_MEMORY_MODE_READONLY, 1.506 + ftr, DestroyBlobFunc); 1.507 + } 1.508 + 1.509 + return nullptr; 1.510 +} 1.511 + 1.512 +nsresult 1.513 +gfxDWriteFontEntry::ReadCMAP(FontInfoData *aFontInfoData) 1.514 +{ 1.515 + // attempt this once, if errors occur leave a blank cmap 1.516 + if (mCharacterMap) { 1.517 + return NS_OK; 1.518 + } 1.519 + 1.520 + nsRefPtr<gfxCharacterMap> charmap; 1.521 + nsresult rv; 1.522 + bool symbolFont; 1.523 + 1.524 + if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData, 1.525 + mUVSOffset, 1.526 + symbolFont))) { 1.527 + rv = NS_OK; 1.528 + } else { 1.529 + uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p'); 1.530 + charmap = new gfxCharacterMap(); 1.531 + AutoTable cmapTable(this, kCMAP); 1.532 + 1.533 + if (cmapTable) { 1.534 + bool unicodeFont = false, symbolFont = false; // currently ignored 1.535 + uint32_t cmapLen; 1.536 + const uint8_t* cmapData = 1.537 + reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable, 1.538 + &cmapLen)); 1.539 + rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, 1.540 + *charmap, mUVSOffset, 1.541 + unicodeFont, symbolFont); 1.542 + } else { 1.543 + rv = NS_ERROR_NOT_AVAILABLE; 1.544 + } 1.545 + } 1.546 + 1.547 + mHasCmapTable = NS_SUCCEEDED(rv); 1.548 + if (mHasCmapTable) { 1.549 + // Bug 969504: exclude U+25B6 from Segoe UI family, because it's used 1.550 + // by sites to represent a "Play" icon, but the glyph in Segoe UI Light 1.551 + // and Semibold on Windows 7 is too thin. (Ditto for leftward U+25C0.) 1.552 + // Fallback to Segoe UI Symbol is preferred. 1.553 + if (FamilyName().EqualsLiteral("Segoe UI")) { 1.554 + charmap->clear(0x25b6); 1.555 + charmap->clear(0x25c0); 1.556 + } 1.557 + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); 1.558 + mCharacterMap = pfl->FindCharMap(charmap); 1.559 + } else { 1.560 + // if error occurred, initialize to null cmap 1.561 + mCharacterMap = new gfxCharacterMap(); 1.562 + } 1.563 + 1.564 +#ifdef PR_LOGGING 1.565 + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", 1.566 + NS_ConvertUTF16toUTF8(mName).get(), 1.567 + charmap->SizeOfIncludingThis(moz_malloc_size_of), 1.568 + charmap->mHash, mCharacterMap == charmap ? " new" : "")); 1.569 + if (LOG_CMAPDATA_ENABLED()) { 1.570 + char prefix[256]; 1.571 + sprintf(prefix, "(cmapdata) name: %.220s", 1.572 + NS_ConvertUTF16toUTF8(mName).get()); 1.573 + charmap->Dump(prefix, eGfxLog_cmapdata); 1.574 + } 1.575 +#endif 1.576 + 1.577 + return rv; 1.578 +} 1.579 + 1.580 +gfxFont * 1.581 +gfxDWriteFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, 1.582 + bool aNeedsBold) 1.583 +{ 1.584 + return new gfxDWriteFont(this, aFontStyle, aNeedsBold); 1.585 +} 1.586 + 1.587 +nsresult 1.588 +gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace, 1.589 + DWRITE_FONT_SIMULATIONS aSimulations) 1.590 +{ 1.591 + // initialize mFontFace if this hasn't been done before 1.592 + if (!mFontFace) { 1.593 + HRESULT hr; 1.594 + if (mFont) { 1.595 + hr = mFont->CreateFontFace(getter_AddRefs(mFontFace)); 1.596 + } else if (mFontFile) { 1.597 + IDWriteFontFile *fontFile = mFontFile.get(); 1.598 + hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.599 + CreateFontFace(mFaceType, 1.600 + 1, 1.601 + &fontFile, 1.602 + 0, 1.603 + DWRITE_FONT_SIMULATIONS_NONE, 1.604 + getter_AddRefs(mFontFace)); 1.605 + } else { 1.606 + NS_NOTREACHED("invalid font entry"); 1.607 + return NS_ERROR_FAILURE; 1.608 + } 1.609 + if (FAILED(hr)) { 1.610 + return NS_ERROR_FAILURE; 1.611 + } 1.612 + } 1.613 + 1.614 + // check whether we need to add a DWrite simulated style 1.615 + if ((aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) && 1.616 + !(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) { 1.617 + // if so, we need to return not mFontFace itself but a version that 1.618 + // has the Bold simulation - unfortunately, DWrite doesn't provide 1.619 + // a simple API for this 1.620 + UINT32 numberOfFiles = 0; 1.621 + if (FAILED(mFontFace->GetFiles(&numberOfFiles, nullptr))) { 1.622 + return NS_ERROR_FAILURE; 1.623 + } 1.624 + nsAutoTArray<IDWriteFontFile*,1> files; 1.625 + files.AppendElements(numberOfFiles); 1.626 + if (FAILED(mFontFace->GetFiles(&numberOfFiles, files.Elements()))) { 1.627 + return NS_ERROR_FAILURE; 1.628 + } 1.629 + HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.630 + CreateFontFace(mFontFace->GetType(), 1.631 + numberOfFiles, 1.632 + files.Elements(), 1.633 + mFontFace->GetIndex(), 1.634 + aSimulations, 1.635 + aFontFace); 1.636 + for (UINT32 i = 0; i < numberOfFiles; ++i) { 1.637 + files[i]->Release(); 1.638 + } 1.639 + return FAILED(hr) ? NS_ERROR_FAILURE : NS_OK; 1.640 + } 1.641 + 1.642 + // no simulation: we can just add a reference to mFontFace and return that 1.643 + *aFontFace = mFontFace; 1.644 + (*aFontFace)->AddRef(); 1.645 + return NS_OK; 1.646 +} 1.647 + 1.648 +bool 1.649 +gfxDWriteFontEntry::InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont) 1.650 +{ 1.651 + HRESULT hr; 1.652 + 1.653 + BOOL isInSystemCollection; 1.654 + IDWriteGdiInterop *gdi = 1.655 + gfxDWriteFontList::PlatformFontList()->GetGDIInterop(); 1.656 + hr = gdi->ConvertFontToLOGFONT(aFont, aLogFont, &isInSystemCollection); 1.657 + return (FAILED(hr) ? false : true); 1.658 +} 1.659 + 1.660 +bool 1.661 +gfxDWriteFontEntry::IsCJKFont() 1.662 +{ 1.663 + if (mIsCJK != UNINITIALIZED_VALUE) { 1.664 + return mIsCJK; 1.665 + } 1.666 + 1.667 + mIsCJK = false; 1.668 + 1.669 + const uint32_t kOS2Tag = TRUETYPE_TAG('O','S','/','2'); 1.670 + AutoFallibleTArray<uint8_t,128> buffer; 1.671 + if (CopyFontTable(kOS2Tag, buffer) != NS_OK) { 1.672 + return mIsCJK; 1.673 + } 1.674 + 1.675 + // ulCodePageRange bit definitions for the CJK codepages, 1.676 + // from http://www.microsoft.com/typography/otspec/os2.htm#cpr 1.677 + const uint32_t CJK_CODEPAGE_BITS = 1.678 + (1 << 17) | // codepage 932 - JIS/Japan 1.679 + (1 << 18) | // codepage 936 - Chinese (simplified) 1.680 + (1 << 19) | // codepage 949 - Korean Wansung 1.681 + (1 << 20) | // codepage 950 - Chinese (traditional) 1.682 + (1 << 21); // codepage 1361 - Korean Johab 1.683 + 1.684 + if (buffer.Length() >= offsetof(OS2Table, sxHeight)) { 1.685 + const OS2Table* os2 = 1.686 + reinterpret_cast<const OS2Table*>(buffer.Elements()); 1.687 + if ((uint32_t(os2->codePageRange1) & CJK_CODEPAGE_BITS) != 0) { 1.688 + mIsCJK = true; 1.689 + } 1.690 + } 1.691 + 1.692 + return mIsCJK; 1.693 +} 1.694 + 1.695 +void 1.696 +gfxDWriteFontEntry::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, 1.697 + FontListSizes* aSizes) const 1.698 +{ 1.699 + gfxFontEntry::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.700 + // TODO: 1.701 + // This doesn't currently account for the |mFont| and |mFontFile| members 1.702 +} 1.703 + 1.704 +void 1.705 +gfxDWriteFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.706 + FontListSizes* aSizes) const 1.707 +{ 1.708 + aSizes->mFontListSize += aMallocSizeOf(this); 1.709 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.710 +} 1.711 + 1.712 +//////////////////////////////////////////////////////////////////////////////// 1.713 +// gfxDWriteFontList 1.714 + 1.715 +gfxDWriteFontList::gfxDWriteFontList() 1.716 + : mInitialized(false), mForceGDIClassicMaxFontSize(0.0) 1.717 +{ 1.718 +} 1.719 + 1.720 +// bug 602792 - CJK systems default to large CJK fonts which cause excessive 1.721 +// I/O strain during cold startup due to dwrite caching bugs. Default to 1.722 +// Arial to avoid this. 1.723 + 1.724 +gfxFontFamily * 1.725 +gfxDWriteFontList::GetDefaultFont(const gfxFontStyle *aStyle) 1.726 +{ 1.727 + nsAutoString resolvedName; 1.728 + 1.729 + // try Arial first 1.730 + if (ResolveFontName(NS_LITERAL_STRING("Arial"), resolvedName)) { 1.731 + return FindFamily(resolvedName); 1.732 + } 1.733 + 1.734 + // otherwise, use local default 1.735 + NONCLIENTMETRICSW ncm; 1.736 + ncm.cbSize = sizeof(ncm); 1.737 + BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 1.738 + sizeof(ncm), &ncm, 0); 1.739 + if (status) { 1.740 + if (ResolveFontName(nsDependentString(ncm.lfMessageFont.lfFaceName), 1.741 + resolvedName)) { 1.742 + return FindFamily(resolvedName); 1.743 + } 1.744 + } 1.745 + 1.746 + return nullptr; 1.747 +} 1.748 + 1.749 +gfxFontEntry * 1.750 +gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, 1.751 + const nsAString& aFullname) 1.752 +{ 1.753 + gfxFontEntry *lookup; 1.754 + 1.755 + lookup = LookupInFaceNameLists(aFullname); 1.756 + if (!lookup) { 1.757 + return nullptr; 1.758 + } 1.759 + 1.760 + gfxDWriteFontEntry* dwriteLookup = static_cast<gfxDWriteFontEntry*>(lookup); 1.761 + gfxDWriteFontEntry *fe = 1.762 + new gfxDWriteFontEntry(lookup->Name(), 1.763 + dwriteLookup->mFont, 1.764 + aProxyEntry->Weight(), 1.765 + aProxyEntry->Stretch(), 1.766 + aProxyEntry->IsItalic()); 1.767 + fe->SetForceGDIClassic(dwriteLookup->GetForceGDIClassic()); 1.768 + return fe; 1.769 +} 1.770 + 1.771 +gfxFontEntry * 1.772 +gfxDWriteFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 1.773 + const uint8_t *aFontData, 1.774 + uint32_t aLength) 1.775 +{ 1.776 + nsresult rv; 1.777 + nsAutoString uniqueName; 1.778 + rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); 1.779 + if (NS_FAILED(rv)) { 1.780 + NS_Free((void*)aFontData); 1.781 + return nullptr; 1.782 + } 1.783 + 1.784 + FallibleTArray<uint8_t> newFontData; 1.785 + 1.786 + rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData); 1.787 + NS_Free((void*)aFontData); 1.788 + 1.789 + if (NS_FAILED(rv)) { 1.790 + return nullptr; 1.791 + } 1.792 + 1.793 + nsRefPtr<IDWriteFontFile> fontFile; 1.794 + HRESULT hr; 1.795 + 1.796 + /** 1.797 + * We pass in a pointer to a structure containing a pointer to the array 1.798 + * containing the font data and a unique identifier. DWrite will 1.799 + * internally copy what is at that pointer, and pass that to 1.800 + * CreateStreamFromKey. The array will be empty when the function 1.801 + * succesfully returns since it swaps out the data. 1.802 + */ 1.803 + ffReferenceKey key; 1.804 + key.mArray = &newFontData; 1.805 + nsCOMPtr<nsIUUIDGenerator> uuidgen = 1.806 + do_GetService("@mozilla.org/uuid-generator;1"); 1.807 + if (!uuidgen) { 1.808 + return nullptr; 1.809 + } 1.810 + 1.811 + rv = uuidgen->GenerateUUIDInPlace(&key.mGUID); 1.812 + 1.813 + if (NS_FAILED(rv)) { 1.814 + return nullptr; 1.815 + } 1.816 + 1.817 + hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.818 + CreateCustomFontFileReference(&key, 1.819 + sizeof(key), 1.820 + gfxDWriteFontFileLoader::Instance(), 1.821 + getter_AddRefs(fontFile)); 1.822 + 1.823 + if (FAILED(hr)) { 1.824 + NS_WARNING("Failed to create custom font file reference."); 1.825 + return nullptr; 1.826 + } 1.827 + 1.828 + BOOL isSupported; 1.829 + DWRITE_FONT_FILE_TYPE fileType; 1.830 + UINT32 numFaces; 1.831 + 1.832 + gfxDWriteFontEntry *entry = 1.833 + new gfxDWriteFontEntry(uniqueName, 1.834 + fontFile, 1.835 + aProxyEntry->Weight(), 1.836 + aProxyEntry->Stretch(), 1.837 + aProxyEntry->IsItalic()); 1.838 + 1.839 + fontFile->Analyze(&isSupported, &fileType, &entry->mFaceType, &numFaces); 1.840 + if (!isSupported || numFaces > 1) { 1.841 + // We don't know how to deal with 0 faces either. 1.842 + delete entry; 1.843 + return nullptr; 1.844 + } 1.845 + 1.846 + return entry; 1.847 +} 1.848 + 1.849 +#ifdef DEBUG_DWRITE_STARTUP 1.850 + 1.851 +#define LOGREGISTRY(msg) LogRegistryEvent(msg) 1.852 + 1.853 +// for use when monitoring process 1.854 +static void LogRegistryEvent(const wchar_t *msg) 1.855 +{ 1.856 + HKEY dummyKey; 1.857 + HRESULT hr; 1.858 + wchar_t buf[512]; 1.859 + 1.860 + wsprintfW(buf, L" log %s", msg); 1.861 + hr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey); 1.862 + if (SUCCEEDED(hr)) { 1.863 + RegCloseKey(dummyKey); 1.864 + } 1.865 +} 1.866 +#else 1.867 + 1.868 +#define LOGREGISTRY(msg) 1.869 + 1.870 +#endif 1.871 + 1.872 +nsresult 1.873 +gfxDWriteFontList::InitFontList() 1.874 +{ 1.875 + LOGREGISTRY(L"InitFontList start"); 1.876 + 1.877 + mInitialized = false; 1.878 + 1.879 + LARGE_INTEGER frequency; // ticks per second 1.880 + LARGE_INTEGER t1, t2, t3; // ticks 1.881 + double elapsedTime, upTime; 1.882 + char nowTime[256], nowDate[256]; 1.883 + 1.884 + if (LOG_FONTINIT_ENABLED()) { 1.885 + GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, 1.886 + nullptr, nullptr, nowTime, 256); 1.887 + GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256); 1.888 + } 1.889 + upTime = (double) GetTickCount(); 1.890 + QueryPerformanceFrequency(&frequency); 1.891 + QueryPerformanceCounter(&t1); 1.892 + 1.893 + HRESULT hr; 1.894 + gfxFontCache *fc = gfxFontCache::GetCache(); 1.895 + if (fc) { 1.896 + fc->AgeAllGenerations(); 1.897 + } 1.898 + 1.899 + mGDIFontTableAccess = Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", false); 1.900 + 1.901 + gfxPlatformFontList::InitFontList(); 1.902 + 1.903 + mFontSubstitutes.Clear(); 1.904 + mNonExistingFonts.Clear(); 1.905 + 1.906 + QueryPerformanceCounter(&t2); 1.907 + 1.908 + hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.909 + GetGdiInterop(getter_AddRefs(mGDIInterop)); 1.910 + if (FAILED(hr)) { 1.911 + return NS_ERROR_FAILURE; 1.912 + } 1.913 + 1.914 + LOGREGISTRY(L"InitFontList end"); 1.915 + 1.916 + QueryPerformanceCounter(&t3); 1.917 + 1.918 + if (LOG_FONTINIT_ENABLED()) { 1.919 + // determine dwrite version 1.920 + nsAutoString dwriteVers; 1.921 + gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", dwriteVers); 1.922 + LOG_FONTINIT(("InitFontList\n")); 1.923 + LOG_FONTINIT(("Start: %s %s\n", nowDate, nowTime)); 1.924 + LOG_FONTINIT(("Uptime: %9.3f s\n", upTime/1000)); 1.925 + LOG_FONTINIT(("dwrite version: %s\n", 1.926 + NS_ConvertUTF16toUTF8(dwriteVers).get())); 1.927 + } 1.928 + 1.929 + elapsedTime = (t3.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; 1.930 + Telemetry::Accumulate(Telemetry::DWRITEFONT_INITFONTLIST_TOTAL, elapsedTime); 1.931 + LOG_FONTINIT(("Total time in InitFontList: %9.3f ms\n", elapsedTime)); 1.932 + elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; 1.933 + Telemetry::Accumulate(Telemetry::DWRITEFONT_INITFONTLIST_INIT, elapsedTime); 1.934 + LOG_FONTINIT((" --- gfxPlatformFontList init: %9.3f ms\n", elapsedTime)); 1.935 + elapsedTime = (t3.QuadPart - t2.QuadPart) * 1000.0 / frequency.QuadPart; 1.936 + Telemetry::Accumulate(Telemetry::DWRITEFONT_INITFONTLIST_GDI, elapsedTime); 1.937 + LOG_FONTINIT((" --- GdiInterop object: %9.3f ms\n", elapsedTime)); 1.938 + 1.939 + return NS_OK; 1.940 +} 1.941 + 1.942 +nsresult 1.943 +gfxDWriteFontList::DelayedInitFontList() 1.944 +{ 1.945 + LOGREGISTRY(L"DelayedInitFontList start"); 1.946 + 1.947 + LARGE_INTEGER frequency; // ticks per second 1.948 + LARGE_INTEGER t1, t2, t3; // ticks 1.949 + double elapsedTime, upTime; 1.950 + char nowTime[256], nowDate[256]; 1.951 + 1.952 + if (LOG_FONTINIT_ENABLED()) { 1.953 + GetTimeFormat(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, 1.954 + nullptr, nullptr, nowTime, 256); 1.955 + GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256); 1.956 + } 1.957 + 1.958 + upTime = (double) GetTickCount(); 1.959 + QueryPerformanceFrequency(&frequency); 1.960 + QueryPerformanceCounter(&t1); 1.961 + 1.962 + HRESULT hr; 1.963 + 1.964 + LOGREGISTRY(L"calling GetSystemFontCollection"); 1.965 + nsRefPtr<IDWriteFontCollection> systemFonts; 1.966 + hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.967 + GetSystemFontCollection(getter_AddRefs(systemFonts)); 1.968 + NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); 1.969 + LOGREGISTRY(L"GetSystemFontCollection done"); 1.970 + 1.971 + if (FAILED(hr)) { 1.972 + return NS_ERROR_FAILURE; 1.973 + } 1.974 + 1.975 + QueryPerformanceCounter(&t2); 1.976 + 1.977 + for (UINT32 i = 0; i < systemFonts->GetFontFamilyCount(); i++) { 1.978 + nsRefPtr<IDWriteFontFamily> family; 1.979 + systemFonts->GetFontFamily(i, getter_AddRefs(family)); 1.980 + 1.981 + nsRefPtr<IDWriteLocalizedStrings> names; 1.982 + hr = family->GetFamilyNames(getter_AddRefs(names)); 1.983 + if (FAILED(hr)) { 1.984 + continue; 1.985 + } 1.986 + 1.987 + UINT32 englishIdx = 0; 1.988 + 1.989 + BOOL exists; 1.990 + hr = names->FindLocaleName(L"en-us", &englishIdx, &exists); 1.991 + if (FAILED(hr)) { 1.992 + continue; 1.993 + } 1.994 + if (!exists) { 1.995 + // Use 0 index if english is not found. 1.996 + englishIdx = 0; 1.997 + } 1.998 + 1.999 + AutoFallibleTArray<WCHAR, 32> enName; 1.1000 + UINT32 length; 1.1001 + 1.1002 + hr = names->GetStringLength(englishIdx, &length); 1.1003 + if (FAILED(hr)) { 1.1004 + continue; 1.1005 + } 1.1006 + 1.1007 + if (!enName.SetLength(length + 1)) { 1.1008 + // Eeep - running out of memory. Unlikely to end well. 1.1009 + continue; 1.1010 + } 1.1011 + 1.1012 + hr = names->GetString(englishIdx, enName.Elements(), length + 1); 1.1013 + if (FAILED(hr)) { 1.1014 + continue; 1.1015 + } 1.1016 + 1.1017 + nsAutoString name(enName.Elements()); 1.1018 + BuildKeyNameFromFontName(name); 1.1019 + 1.1020 + nsRefPtr<gfxFontFamily> fam; 1.1021 + 1.1022 + if (mFontFamilies.GetWeak(name)) { 1.1023 + continue; 1.1024 + } 1.1025 + 1.1026 + nsDependentString familyName(enName.Elements()); 1.1027 + 1.1028 + fam = new gfxDWriteFontFamily(familyName, family); 1.1029 + if (!fam) { 1.1030 + continue; 1.1031 + } 1.1032 + 1.1033 + if (mBadUnderlineFamilyNames.Contains(name)) { 1.1034 + fam->SetBadUnderlineFamily(); 1.1035 + } 1.1036 + mFontFamilies.Put(name, fam); 1.1037 + 1.1038 + // now add other family name localizations, if present 1.1039 + uint32_t nameCount = names->GetCount(); 1.1040 + uint32_t nameIndex; 1.1041 + 1.1042 + for (nameIndex = 0; nameIndex < nameCount; nameIndex++) { 1.1043 + UINT32 nameLen; 1.1044 + AutoFallibleTArray<WCHAR, 32> localizedName; 1.1045 + 1.1046 + // only add other names 1.1047 + if (nameIndex == englishIdx) { 1.1048 + continue; 1.1049 + } 1.1050 + 1.1051 + hr = names->GetStringLength(nameIndex, &nameLen); 1.1052 + if (FAILED(hr)) { 1.1053 + continue; 1.1054 + } 1.1055 + 1.1056 + if (!localizedName.SetLength(nameLen + 1)) { 1.1057 + continue; 1.1058 + } 1.1059 + 1.1060 + hr = names->GetString(nameIndex, localizedName.Elements(), 1.1061 + nameLen + 1); 1.1062 + if (FAILED(hr)) { 1.1063 + continue; 1.1064 + } 1.1065 + 1.1066 + nsDependentString locName(localizedName.Elements()); 1.1067 + 1.1068 + if (!familyName.Equals(locName)) { 1.1069 + AddOtherFamilyName(fam, locName); 1.1070 + } 1.1071 + 1.1072 + } 1.1073 + 1.1074 + // at this point, all family names have been read in 1.1075 + fam->SetOtherFamilyNamesInitialized(); 1.1076 + } 1.1077 + 1.1078 + mOtherFamilyNamesInitialized = true; 1.1079 + GetFontSubstitutes(); 1.1080 + 1.1081 + // bug 642093 - DirectWrite does not support old bitmap (.fon) 1.1082 + // font files, but a few of these such as "Courier" and "MS Sans Serif" 1.1083 + // are frequently specified in shoddy CSS, without appropriate fallbacks. 1.1084 + // By mapping these to TrueType equivalents, we provide better consistency 1.1085 + // with both pre-DW systems and with IE9, which appears to do the same. 1.1086 + GetDirectWriteSubstitutes(); 1.1087 + 1.1088 + // bug 551313 - DirectWrite creates a Gill Sans family out of 1.1089 + // poorly named members of the Gill Sans MT family containing 1.1090 + // only Ultra Bold weights. This causes big problems for pages 1.1091 + // using Gill Sans which is usually only available on OSX 1.1092 + 1.1093 + nsAutoString nameGillSans(L"Gill Sans"); 1.1094 + nsAutoString nameGillSansMT(L"Gill Sans MT"); 1.1095 + BuildKeyNameFromFontName(nameGillSans); 1.1096 + BuildKeyNameFromFontName(nameGillSansMT); 1.1097 + 1.1098 + gfxFontFamily *gillSansFamily = mFontFamilies.GetWeak(nameGillSans); 1.1099 + gfxFontFamily *gillSansMTFamily = mFontFamilies.GetWeak(nameGillSansMT); 1.1100 + 1.1101 + if (gillSansFamily && gillSansMTFamily) { 1.1102 + gillSansFamily->FindStyleVariations(); 1.1103 + nsTArray<nsRefPtr<gfxFontEntry> >& faces = gillSansFamily->GetFontList(); 1.1104 + uint32_t i; 1.1105 + 1.1106 + bool allUltraBold = true; 1.1107 + for (i = 0; i < faces.Length(); i++) { 1.1108 + // does the face have 'Ultra Bold' in the name? 1.1109 + if (faces[i]->Name().Find(NS_LITERAL_STRING("Ultra Bold")) == -1) { 1.1110 + allUltraBold = false; 1.1111 + break; 1.1112 + } 1.1113 + } 1.1114 + 1.1115 + // if all the Gill Sans faces are Ultra Bold ==> move faces 1.1116 + // for Gill Sans into Gill Sans MT family 1.1117 + if (allUltraBold) { 1.1118 + 1.1119 + // add faces to Gill Sans MT 1.1120 + for (i = 0; i < faces.Length(); i++) { 1.1121 + gillSansMTFamily->AddFontEntry(faces[i]); 1.1122 + 1.1123 +#ifdef PR_LOGGING 1.1124 + if (LOG_FONTLIST_ENABLED()) { 1.1125 + gfxFontEntry *fe = faces[i]; 1.1126 + LOG_FONTLIST(("(fontlist) moved (%s) to family (%s)" 1.1127 + " with style: %s weight: %d stretch: %d", 1.1128 + NS_ConvertUTF16toUTF8(fe->Name()).get(), 1.1129 + NS_ConvertUTF16toUTF8(gillSansMTFamily->Name()).get(), 1.1130 + (fe->IsItalic()) ? "italic" : "normal", 1.1131 + fe->Weight(), fe->Stretch())); 1.1132 + } 1.1133 +#endif 1.1134 + } 1.1135 + 1.1136 + // remove Gills Sans 1.1137 + mFontFamilies.Remove(nameGillSans); 1.1138 + } 1.1139 + } 1.1140 + 1.1141 + nsAdoptingCString classicFamilies = 1.1142 + Preferences::GetCString("gfx.font_rendering.cleartype_params.force_gdi_classic_for_families"); 1.1143 + if (classicFamilies) { 1.1144 + nsCCharSeparatedTokenizer tokenizer(classicFamilies, ','); 1.1145 + while (tokenizer.hasMoreTokens()) { 1.1146 + NS_ConvertUTF8toUTF16 name(tokenizer.nextToken()); 1.1147 + BuildKeyNameFromFontName(name); 1.1148 + gfxFontFamily *family = mFontFamilies.GetWeak(name); 1.1149 + if (family) { 1.1150 + static_cast<gfxDWriteFontFamily*>(family)->SetForceGDIClassic(true); 1.1151 + } 1.1152 + } 1.1153 + } 1.1154 + mForceGDIClassicMaxFontSize = 1.1155 + Preferences::GetInt("gfx.font_rendering.cleartype_params.force_gdi_classic_max_size", 1.1156 + mForceGDIClassicMaxFontSize); 1.1157 + 1.1158 + GetPrefsAndStartLoader(); 1.1159 + 1.1160 + LOGREGISTRY(L"DelayedInitFontList end"); 1.1161 + 1.1162 + QueryPerformanceCounter(&t3); 1.1163 + 1.1164 + if (LOG_FONTINIT_ENABLED()) { 1.1165 + // determine dwrite version 1.1166 + nsAutoString dwriteVers; 1.1167 + gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", dwriteVers); 1.1168 + LOG_FONTINIT(("DelayedInitFontList\n")); 1.1169 + LOG_FONTINIT(("Start: %s %s\n", nowDate, nowTime)); 1.1170 + LOG_FONTINIT(("Uptime: %9.3f s\n", upTime/1000)); 1.1171 + LOG_FONTINIT(("dwrite version: %s\n", 1.1172 + NS_ConvertUTF16toUTF8(dwriteVers).get())); 1.1173 + } 1.1174 + 1.1175 + elapsedTime = (t3.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; 1.1176 + Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_TOTAL, elapsedTime); 1.1177 + Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COUNT, 1.1178 + systemFonts->GetFontFamilyCount()); 1.1179 + Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_GDI_TABLE, mGDIFontTableAccess); 1.1180 + LOG_FONTINIT(( 1.1181 + "Total time in DelayedInitFontList: %9.3f ms (families: %d, %s)\n", 1.1182 + elapsedTime, systemFonts->GetFontFamilyCount(), 1.1183 + (mGDIFontTableAccess ? "gdi table access" : "dwrite table access"))); 1.1184 + 1.1185 + elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; 1.1186 + Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_COLLECT, elapsedTime); 1.1187 + LOG_FONTINIT((" --- GetSystemFontCollection: %9.3f ms\n", elapsedTime)); 1.1188 + 1.1189 + elapsedTime = (t3.QuadPart - t2.QuadPart) * 1000.0 / frequency.QuadPart; 1.1190 + Telemetry::Accumulate(Telemetry::DWRITEFONT_DELAYEDINITFONTLIST_ITERATE, elapsedTime); 1.1191 + LOG_FONTINIT((" --- iterate over families: %9.3f ms\n", elapsedTime)); 1.1192 + 1.1193 + return NS_OK; 1.1194 +} 1.1195 + 1.1196 +static void 1.1197 +RemoveCharsetFromFontSubstitute(nsAString &aName) 1.1198 +{ 1.1199 + int32_t comma = aName.FindChar(char16_t(',')); 1.1200 + if (comma >= 0) 1.1201 + aName.Truncate(comma); 1.1202 +} 1.1203 + 1.1204 +#define MAX_VALUE_NAME 512 1.1205 +#define MAX_VALUE_DATA 512 1.1206 + 1.1207 +nsresult 1.1208 +gfxDWriteFontList::GetFontSubstitutes() 1.1209 +{ 1.1210 + HKEY hKey; 1.1211 + DWORD i, rv, lenAlias, lenActual, valueType; 1.1212 + WCHAR aliasName[MAX_VALUE_NAME]; 1.1213 + WCHAR actualName[MAX_VALUE_DATA]; 1.1214 + 1.1215 + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1.1216 + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", 1.1217 + 0, KEY_READ, &hKey) != ERROR_SUCCESS) 1.1218 + { 1.1219 + return NS_ERROR_FAILURE; 1.1220 + } 1.1221 + 1.1222 + for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) { 1.1223 + aliasName[0] = 0; 1.1224 + lenAlias = ArrayLength(aliasName); 1.1225 + actualName[0] = 0; 1.1226 + lenActual = sizeof(actualName); 1.1227 + rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, nullptr, &valueType, 1.1228 + (LPBYTE)actualName, &lenActual); 1.1229 + 1.1230 + if (rv != ERROR_SUCCESS || valueType != REG_SZ || lenAlias == 0) { 1.1231 + continue; 1.1232 + } 1.1233 + 1.1234 + if (aliasName[0] == WCHAR('@')) { 1.1235 + continue; 1.1236 + } 1.1237 + 1.1238 + nsAutoString substituteName((char16_t*) aliasName); 1.1239 + nsAutoString actualFontName((char16_t*) actualName); 1.1240 + RemoveCharsetFromFontSubstitute(substituteName); 1.1241 + BuildKeyNameFromFontName(substituteName); 1.1242 + RemoveCharsetFromFontSubstitute(actualFontName); 1.1243 + BuildKeyNameFromFontName(actualFontName); 1.1244 + gfxFontFamily *ff; 1.1245 + if (!actualFontName.IsEmpty() && 1.1246 + (ff = mFontFamilies.GetWeak(actualFontName))) { 1.1247 + mFontSubstitutes.Put(substituteName, ff); 1.1248 + } else { 1.1249 + mNonExistingFonts.AppendElement(substituteName); 1.1250 + } 1.1251 + } 1.1252 + return NS_OK; 1.1253 +} 1.1254 + 1.1255 +struct FontSubstitution { 1.1256 + const WCHAR* aliasName; 1.1257 + const WCHAR* actualName; 1.1258 +}; 1.1259 + 1.1260 +static const FontSubstitution sDirectWriteSubs[] = { 1.1261 + { L"MS Sans Serif", L"Microsoft Sans Serif" }, 1.1262 + { L"MS Serif", L"Times New Roman" }, 1.1263 + { L"Courier", L"Courier New" }, 1.1264 + { L"Small Fonts", L"Arial" }, 1.1265 + { L"Roman", L"Times New Roman" }, 1.1266 + { L"Script", L"Mistral" } 1.1267 +}; 1.1268 + 1.1269 +void 1.1270 +gfxDWriteFontList::GetDirectWriteSubstitutes() 1.1271 +{ 1.1272 + for (uint32_t i = 0; i < ArrayLength(sDirectWriteSubs); ++i) { 1.1273 + const FontSubstitution& sub(sDirectWriteSubs[i]); 1.1274 + nsAutoString substituteName((char16_t*)sub.aliasName); 1.1275 + BuildKeyNameFromFontName(substituteName); 1.1276 + if (nullptr != mFontFamilies.GetWeak(substituteName)) { 1.1277 + // don't do the substitution if user actually has a usable font 1.1278 + // with this name installed 1.1279 + continue; 1.1280 + } 1.1281 + nsAutoString actualFontName((char16_t*)sub.actualName); 1.1282 + BuildKeyNameFromFontName(actualFontName); 1.1283 + gfxFontFamily *ff; 1.1284 + if (nullptr != (ff = mFontFamilies.GetWeak(actualFontName))) { 1.1285 + mFontSubstitutes.Put(substituteName, ff); 1.1286 + } else { 1.1287 + mNonExistingFonts.AppendElement(substituteName); 1.1288 + } 1.1289 + } 1.1290 +} 1.1291 + 1.1292 +bool 1.1293 +gfxDWriteFontList::GetStandardFamilyName(const nsAString& aFontName, 1.1294 + nsAString& aFamilyName) 1.1295 +{ 1.1296 + gfxFontFamily *family = FindFamily(aFontName); 1.1297 + if (family) { 1.1298 + family->LocalizedName(aFamilyName); 1.1299 + return true; 1.1300 + } 1.1301 + 1.1302 + return false; 1.1303 +} 1.1304 + 1.1305 +gfxFontFamily* gfxDWriteFontList::FindFamily(const nsAString& aFamily) 1.1306 +{ 1.1307 + if (!mInitialized) { 1.1308 + mInitialized = true; 1.1309 + DelayedInitFontList(); 1.1310 + } 1.1311 + 1.1312 + return gfxPlatformFontList::FindFamily(aFamily); 1.1313 +} 1.1314 + 1.1315 +void 1.1316 +gfxDWriteFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 1.1317 +{ 1.1318 + if (!mInitialized) { 1.1319 + mInitialized = true; 1.1320 + DelayedInitFontList(); 1.1321 + } 1.1322 + 1.1323 + return gfxPlatformFontList::GetFontFamilyList(aFamilyArray); 1.1324 +} 1.1325 + 1.1326 +bool 1.1327 +gfxDWriteFontList::ResolveFontName(const nsAString& aFontName, 1.1328 + nsAString& aResolvedFontName) 1.1329 +{ 1.1330 + if (!mInitialized) { 1.1331 + mInitialized = true; 1.1332 + DelayedInitFontList(); 1.1333 + } 1.1334 + 1.1335 + nsAutoString keyName(aFontName); 1.1336 + BuildKeyNameFromFontName(keyName); 1.1337 + 1.1338 + gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName); 1.1339 + if (ff) { 1.1340 + aResolvedFontName = ff->Name(); 1.1341 + return true; 1.1342 + } 1.1343 + 1.1344 + if (mNonExistingFonts.Contains(keyName)) { 1.1345 + return false; 1.1346 + } 1.1347 + 1.1348 + return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName); 1.1349 +} 1.1350 + 1.1351 +void 1.1352 +gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, 1.1353 + FontListSizes* aSizes) const 1.1354 +{ 1.1355 + gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.1356 + 1.1357 + aSizes->mFontListSize += 1.1358 + mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, 1.1359 + aMallocSizeOf); 1.1360 + 1.1361 + aSizes->mFontListSize += 1.1362 + mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf); 1.1363 + for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) { 1.1364 + aSizes->mFontListSize += 1.1365 + mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.1366 + } 1.1367 +} 1.1368 + 1.1369 +void 1.1370 +gfxDWriteFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.1371 + FontListSizes* aSizes) const 1.1372 +{ 1.1373 + aSizes->mFontListSize += aMallocSizeOf(this); 1.1374 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.1375 +} 1.1376 + 1.1377 +static HRESULT GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName) 1.1378 +{ 1.1379 + HRESULT hr; 1.1380 + nsRefPtr<IDWriteFontFamily> family; 1.1381 + 1.1382 + // clean out previous value 1.1383 + aFamilyName.Truncate(); 1.1384 + 1.1385 + hr = aFont->GetFontFamily(getter_AddRefs(family)); 1.1386 + if (FAILED(hr)) { 1.1387 + return hr; 1.1388 + } 1.1389 + 1.1390 + nsRefPtr<IDWriteLocalizedStrings> familyNames; 1.1391 + 1.1392 + hr = family->GetFamilyNames(getter_AddRefs(familyNames)); 1.1393 + if (FAILED(hr)) { 1.1394 + return hr; 1.1395 + } 1.1396 + 1.1397 + UINT32 index = 0; 1.1398 + BOOL exists = false; 1.1399 + 1.1400 + hr = familyNames->FindLocaleName(L"en-us", &index, &exists); 1.1401 + if (FAILED(hr)) { 1.1402 + return hr; 1.1403 + } 1.1404 + 1.1405 + // If the specified locale doesn't exist, select the first on the list. 1.1406 + if (!exists) { 1.1407 + index = 0; 1.1408 + } 1.1409 + 1.1410 + AutoFallibleTArray<WCHAR, 32> name; 1.1411 + UINT32 length; 1.1412 + 1.1413 + hr = familyNames->GetStringLength(index, &length); 1.1414 + if (FAILED(hr)) { 1.1415 + return hr; 1.1416 + } 1.1417 + 1.1418 + if (!name.SetLength(length + 1)) { 1.1419 + return E_FAIL; 1.1420 + } 1.1421 + hr = familyNames->GetString(index, name.Elements(), length + 1); 1.1422 + if (FAILED(hr)) { 1.1423 + return hr; 1.1424 + } 1.1425 + 1.1426 + aFamilyName.Assign(name.Elements()); 1.1427 + return S_OK; 1.1428 +} 1.1429 + 1.1430 +// bug 705594 - the method below doesn't actually do any "drawing", it's only 1.1431 +// used to invoke the DirectWrite layout engine to determine the fallback font 1.1432 +// for a given character. 1.1433 + 1.1434 +IFACEMETHODIMP FontFallbackRenderer::DrawGlyphRun( 1.1435 + void* clientDrawingContext, 1.1436 + FLOAT baselineOriginX, 1.1437 + FLOAT baselineOriginY, 1.1438 + DWRITE_MEASURING_MODE measuringMode, 1.1439 + DWRITE_GLYPH_RUN const* glyphRun, 1.1440 + DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 1.1441 + IUnknown* clientDrawingEffect 1.1442 + ) 1.1443 +{ 1.1444 + if (!mSystemFonts) { 1.1445 + return E_FAIL; 1.1446 + } 1.1447 + 1.1448 + HRESULT hr = S_OK; 1.1449 + 1.1450 + nsRefPtr<IDWriteFont> font; 1.1451 + hr = mSystemFonts->GetFontFromFontFace(glyphRun->fontFace, 1.1452 + getter_AddRefs(font)); 1.1453 + if (FAILED(hr)) { 1.1454 + return hr; 1.1455 + } 1.1456 + 1.1457 + // copy the family name 1.1458 + hr = GetFamilyName(font, mFamilyName); 1.1459 + if (FAILED(hr)) { 1.1460 + return hr; 1.1461 + } 1.1462 + 1.1463 + // Arial is used as the default fallback font 1.1464 + // so if it matches ==> no font found 1.1465 + if (mFamilyName.EqualsLiteral("Arial")) { 1.1466 + mFamilyName.Truncate(); 1.1467 + return E_FAIL; 1.1468 + } 1.1469 + return hr; 1.1470 +} 1.1471 + 1.1472 +gfxFontEntry* 1.1473 +gfxDWriteFontList::GlobalFontFallback(const uint32_t aCh, 1.1474 + int32_t aRunScript, 1.1475 + const gfxFontStyle* aMatchStyle, 1.1476 + uint32_t& aCmapCount, 1.1477 + gfxFontFamily** aMatchedFamily) 1.1478 +{ 1.1479 + bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.1480 + 1.1481 + if (useCmaps) { 1.1482 + return gfxPlatformFontList::GlobalFontFallback(aCh, 1.1483 + aRunScript, 1.1484 + aMatchStyle, 1.1485 + aCmapCount, 1.1486 + aMatchedFamily); 1.1487 + } 1.1488 + 1.1489 + HRESULT hr; 1.1490 + 1.1491 + nsRefPtr<IDWriteFactory> dwFactory = 1.1492 + gfxWindowsPlatform::GetPlatform()->GetDWriteFactory(); 1.1493 + if (!dwFactory) { 1.1494 + return nullptr; 1.1495 + } 1.1496 + 1.1497 + // initialize fallback renderer 1.1498 + if (!mFallbackRenderer) { 1.1499 + mFallbackRenderer = new FontFallbackRenderer(dwFactory); 1.1500 + } 1.1501 + 1.1502 + // initialize text format 1.1503 + if (!mFallbackFormat) { 1.1504 + hr = dwFactory->CreateTextFormat(L"Arial", nullptr, 1.1505 + DWRITE_FONT_WEIGHT_REGULAR, 1.1506 + DWRITE_FONT_STYLE_NORMAL, 1.1507 + DWRITE_FONT_STRETCH_NORMAL, 1.1508 + 72.0f, L"en-us", 1.1509 + getter_AddRefs(mFallbackFormat)); 1.1510 + if (FAILED(hr)) { 1.1511 + return nullptr; 1.1512 + } 1.1513 + } 1.1514 + 1.1515 + // set up string with fallback character 1.1516 + wchar_t str[16]; 1.1517 + uint32_t strLen; 1.1518 + 1.1519 + if (IS_IN_BMP(aCh)) { 1.1520 + str[0] = static_cast<wchar_t> (aCh); 1.1521 + str[1] = 0; 1.1522 + strLen = 1; 1.1523 + } else { 1.1524 + str[0] = static_cast<wchar_t> (H_SURROGATE(aCh)); 1.1525 + str[1] = static_cast<wchar_t> (L_SURROGATE(aCh)); 1.1526 + str[2] = 0; 1.1527 + strLen = 2; 1.1528 + } 1.1529 + 1.1530 + // set up layout 1.1531 + nsRefPtr<IDWriteTextLayout> fallbackLayout; 1.1532 + 1.1533 + hr = dwFactory->CreateTextLayout(str, strLen, mFallbackFormat, 1.1534 + 200.0f, 200.0f, 1.1535 + getter_AddRefs(fallbackLayout)); 1.1536 + if (FAILED(hr)) { 1.1537 + return nullptr; 1.1538 + } 1.1539 + 1.1540 + // call the draw method to invoke the DirectWrite layout functions 1.1541 + // which determine the fallback font 1.1542 + hr = fallbackLayout->Draw(nullptr, mFallbackRenderer, 50.0f, 50.0f); 1.1543 + if (FAILED(hr)) { 1.1544 + return nullptr; 1.1545 + } 1.1546 + 1.1547 + gfxFontFamily *family = FindFamily(mFallbackRenderer->FallbackFamilyName()); 1.1548 + if (family) { 1.1549 + gfxFontEntry *fontEntry; 1.1550 + bool needsBold; // ignored in the system fallback case 1.1551 + fontEntry = family->FindFontForStyle(*aMatchStyle, needsBold); 1.1552 + if (fontEntry && fontEntry->TestCharacterMap(aCh)) { 1.1553 + *aMatchedFamily = family; 1.1554 + return fontEntry; 1.1555 + } 1.1556 + Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, true); 1.1557 + } 1.1558 + 1.1559 + return nullptr; 1.1560 +} 1.1561 + 1.1562 +// used to load system-wide font info on off-main thread 1.1563 +class DirectWriteFontInfo : public FontInfoData { 1.1564 +public: 1.1565 + DirectWriteFontInfo(bool aLoadOtherNames, 1.1566 + bool aLoadFaceNames, 1.1567 + bool aLoadCmaps) : 1.1568 + FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps) 1.1569 + {} 1.1570 + 1.1571 + virtual ~DirectWriteFontInfo() {} 1.1572 + 1.1573 + // loads font data for all members of a given family 1.1574 + virtual void LoadFontFamilyData(const nsAString& aFamilyName); 1.1575 + 1.1576 + nsRefPtr<IDWriteFontCollection> mSystemFonts; 1.1577 +}; 1.1578 + 1.1579 +void 1.1580 +DirectWriteFontInfo::LoadFontFamilyData(const nsAString& aFamilyName) 1.1581 +{ 1.1582 + // lookup the family 1.1583 + nsAutoTArray<wchar_t, 32> famName; 1.1584 + 1.1585 + uint32_t len = aFamilyName.Length(); 1.1586 + famName.SetLength(len + 1); 1.1587 + memcpy(famName.Elements(), aFamilyName.BeginReading(), len * sizeof(char16_t)); 1.1588 + famName[len] = 0; 1.1589 + 1.1590 + HRESULT hr; 1.1591 + BOOL exists = false; 1.1592 + 1.1593 + uint32_t index; 1.1594 + hr = mSystemFonts->FindFamilyName(famName.Elements(), &index, &exists); 1.1595 + if (FAILED(hr) || !exists) { 1.1596 + return; 1.1597 + } 1.1598 + 1.1599 + nsRefPtr<IDWriteFontFamily> family; 1.1600 + mSystemFonts->GetFontFamily(index, getter_AddRefs(family)); 1.1601 + if (!family) { 1.1602 + return; 1.1603 + } 1.1604 + 1.1605 + // later versions of DirectWrite support querying the fullname/psname 1.1606 + bool loadFaceNamesUsingDirectWrite = mLoadFaceNames; 1.1607 + 1.1608 + for (uint32_t i = 0; i < family->GetFontCount(); i++) { 1.1609 + // get the font 1.1610 + nsRefPtr<IDWriteFont> dwFont; 1.1611 + hr = family->GetFont(i, getter_AddRefs(dwFont)); 1.1612 + if (FAILED(hr)) { 1.1613 + // This should never happen. 1.1614 + NS_WARNING("Failed to get existing font from family."); 1.1615 + continue; 1.1616 + } 1.1617 + 1.1618 + if (dwFont->GetSimulations() & DWRITE_FONT_SIMULATIONS_OBLIQUE) { 1.1619 + // We don't want these. 1.1620 + continue; 1.1621 + } 1.1622 + 1.1623 + mLoadStats.fonts++; 1.1624 + 1.1625 + // get the name of the face 1.1626 + nsString fullID(aFamilyName); 1.1627 + nsAutoString fontName; 1.1628 + hr = GetDirectWriteFontName(dwFont, fontName); 1.1629 + if (FAILED(hr)) { 1.1630 + continue; 1.1631 + } 1.1632 + fullID.Append(NS_LITERAL_STRING(" ")); 1.1633 + fullID.Append(fontName); 1.1634 + 1.1635 + FontFaceData fontData; 1.1636 + bool haveData = true; 1.1637 + nsRefPtr<IDWriteFontFace> dwFontFace; 1.1638 + 1.1639 + if (mLoadFaceNames) { 1.1640 + // try to load using DirectWrite first 1.1641 + if (loadFaceNamesUsingDirectWrite) { 1.1642 + hr = GetDirectWriteFaceName(dwFont, PSNAME_ID, fontData.mPostscriptName); 1.1643 + if (FAILED(hr)) { 1.1644 + loadFaceNamesUsingDirectWrite = false; 1.1645 + } 1.1646 + hr = GetDirectWriteFaceName(dwFont, FULLNAME_ID, fontData.mFullName); 1.1647 + if (FAILED(hr)) { 1.1648 + loadFaceNamesUsingDirectWrite = false; 1.1649 + } 1.1650 + } 1.1651 + 1.1652 + // if DirectWrite read fails, load directly from name table 1.1653 + if (!loadFaceNamesUsingDirectWrite) { 1.1654 + hr = dwFont->CreateFontFace(getter_AddRefs(dwFontFace)); 1.1655 + if (SUCCEEDED(hr)) { 1.1656 + uint32_t kNAME = 1.1657 + NativeEndian::swapToBigEndian(TRUETYPE_TAG('n','a','m','e')); 1.1658 + const char *nameData; 1.1659 + BOOL exists; 1.1660 + void* ctx; 1.1661 + uint32_t nameSize; 1.1662 + 1.1663 + hr = dwFontFace->TryGetFontTable( 1.1664 + kNAME, 1.1665 + (const void**)&nameData, &nameSize, &ctx, &exists); 1.1666 + 1.1667 + if (SUCCEEDED(hr) && nameData && nameSize > 0) { 1.1668 + gfxFontUtils::ReadCanonicalName(nameData, nameSize, 1.1669 + gfxFontUtils::NAME_ID_FULL, 1.1670 + fontData.mFullName); 1.1671 + gfxFontUtils::ReadCanonicalName(nameData, nameSize, 1.1672 + gfxFontUtils::NAME_ID_POSTSCRIPT, 1.1673 + fontData.mPostscriptName); 1.1674 + dwFontFace->ReleaseFontTable(ctx); 1.1675 + } 1.1676 + } 1.1677 + } 1.1678 + 1.1679 + haveData = !fontData.mPostscriptName.IsEmpty() || 1.1680 + !fontData.mFullName.IsEmpty(); 1.1681 + if (haveData) { 1.1682 + mLoadStats.facenames++; 1.1683 + } 1.1684 + } 1.1685 + 1.1686 + // cmaps 1.1687 + if (mLoadCmaps) { 1.1688 + if (!dwFontFace) { 1.1689 + hr = dwFont->CreateFontFace(getter_AddRefs(dwFontFace)); 1.1690 + if (!SUCCEEDED(hr)) { 1.1691 + continue; 1.1692 + } 1.1693 + } 1.1694 + 1.1695 + uint32_t kCMAP = 1.1696 + NativeEndian::swapToBigEndian(TRUETYPE_TAG('c','m','a','p')); 1.1697 + const uint8_t *cmapData; 1.1698 + BOOL exists; 1.1699 + void* ctx; 1.1700 + uint32_t cmapSize; 1.1701 + 1.1702 + hr = dwFontFace->TryGetFontTable(kCMAP, 1.1703 + (const void**)&cmapData, &cmapSize, &ctx, &exists); 1.1704 + 1.1705 + if (SUCCEEDED(hr)) { 1.1706 + bool cmapLoaded = false; 1.1707 + bool unicodeFont = false, symbolFont = false; 1.1708 + nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap(); 1.1709 + uint32_t offset; 1.1710 + 1.1711 + if (cmapData && 1.1712 + cmapSize > 0 && 1.1713 + NS_SUCCEEDED( 1.1714 + gfxFontUtils::ReadCMAP(cmapData, cmapSize, *charmap, 1.1715 + offset, unicodeFont, symbolFont))) { 1.1716 + fontData.mCharacterMap = charmap; 1.1717 + fontData.mUVSOffset = offset; 1.1718 + fontData.mSymbolFont = symbolFont; 1.1719 + cmapLoaded = true; 1.1720 + mLoadStats.cmaps++; 1.1721 + } 1.1722 + dwFontFace->ReleaseFontTable(ctx); 1.1723 + haveData = haveData || cmapLoaded; 1.1724 + } 1.1725 + } 1.1726 + 1.1727 + // if have data, load 1.1728 + if (haveData) { 1.1729 + mFontFaceData.Put(fullID, fontData); 1.1730 + } 1.1731 + } 1.1732 +} 1.1733 + 1.1734 +already_AddRefed<FontInfoData> 1.1735 +gfxDWriteFontList::CreateFontInfoData() 1.1736 +{ 1.1737 + bool loadCmaps = !UsesSystemFallback() || 1.1738 + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.1739 + 1.1740 + nsRefPtr<DirectWriteFontInfo> fi = 1.1741 + new DirectWriteFontInfo(false, NeedFullnamePostscriptNames(), loadCmaps); 1.1742 + gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()-> 1.1743 + GetSystemFontCollection(getter_AddRefs(fi->mSystemFonts)); 1.1744 + 1.1745 + return fi.forget(); 1.1746 +}