1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxGDIFontList.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1094 @@ 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/DebugOnly.h" 1.10 +#include <algorithm> 1.11 + 1.12 +#ifdef MOZ_LOGGING 1.13 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.14 +#endif 1.15 +#include "prlog.h" 1.16 + 1.17 +#include "gfxGDIFontList.h" 1.18 +#include "gfxWindowsPlatform.h" 1.19 +#include "gfxUserFontSet.h" 1.20 +#include "gfxFontUtils.h" 1.21 +#include "gfxGDIFont.h" 1.22 + 1.23 +#include "nsServiceManagerUtils.h" 1.24 +#include "nsTArray.h" 1.25 +#include "nsUnicharUtils.h" 1.26 + 1.27 +#include "nsDirectoryServiceUtils.h" 1.28 +#include "nsDirectoryServiceDefs.h" 1.29 +#include "nsAppDirectoryServiceDefs.h" 1.30 +#include "nsISimpleEnumerator.h" 1.31 +#include "nsIWindowsRegKey.h" 1.32 +#include "gfxFontConstants.h" 1.33 + 1.34 +#include "mozilla/MemoryReporting.h" 1.35 +#include "mozilla/Telemetry.h" 1.36 +#include "mozilla/WindowsVersion.h" 1.37 + 1.38 +#include <usp10.h> 1.39 + 1.40 +using namespace mozilla; 1.41 + 1.42 +#define ROUND(x) floor((x) + 0.5) 1.43 + 1.44 + 1.45 +#ifndef CLEARTYPE_QUALITY 1.46 +#define CLEARTYPE_QUALITY 5 1.47 +#endif 1.48 + 1.49 +#ifdef PR_LOGGING 1.50 +#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.51 + PR_LOG_DEBUG, args) 1.52 +#define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \ 1.53 + gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.54 + PR_LOG_DEBUG) 1.55 + 1.56 +#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \ 1.57 + gfxPlatform::GetLog(eGfxLog_cmapdata), \ 1.58 + PR_LOG_DEBUG) 1.59 + 1.60 +#endif // PR_LOGGING 1.61 + 1.62 +static __inline void 1.63 +BuildKeyNameFromFontName(nsAString &aName) 1.64 +{ 1.65 + if (aName.Length() >= LF_FACESIZE) 1.66 + aName.Truncate(LF_FACESIZE - 1); 1.67 + ToLowerCase(aName); 1.68 +} 1.69 + 1.70 +// Implementation of gfxPlatformFontList for Win32 GDI, 1.71 +// using GDI font enumeration APIs to get the list of fonts 1.72 + 1.73 +class WinUserFontData : public gfxUserFontData { 1.74 +public: 1.75 + WinUserFontData(HANDLE aFontRef) 1.76 + : mFontRef(aFontRef) 1.77 + { } 1.78 + 1.79 + virtual ~WinUserFontData() 1.80 + { 1.81 + DebugOnly<BOOL> success; 1.82 + success = RemoveFontMemResourceEx(mFontRef); 1.83 +#if DEBUG 1.84 + if (!success) { 1.85 + char buf[256]; 1.86 + sprintf(buf, "error deleting font handle (%p) - RemoveFontMemResourceEx failed", mFontRef); 1.87 + NS_ASSERTION(success, buf); 1.88 + } 1.89 +#endif 1.90 + } 1.91 + 1.92 + HANDLE mFontRef; 1.93 +}; 1.94 + 1.95 +BYTE 1.96 +FontTypeToOutPrecision(uint8_t fontType) 1.97 +{ 1.98 + BYTE ret; 1.99 + switch (fontType) { 1.100 + case GFX_FONT_TYPE_TT_OPENTYPE: 1.101 + case GFX_FONT_TYPE_TRUETYPE: 1.102 + ret = OUT_TT_ONLY_PRECIS; 1.103 + break; 1.104 + case GFX_FONT_TYPE_PS_OPENTYPE: 1.105 + ret = OUT_PS_ONLY_PRECIS; 1.106 + break; 1.107 + case GFX_FONT_TYPE_TYPE1: 1.108 + ret = OUT_OUTLINE_PRECIS; 1.109 + break; 1.110 + case GFX_FONT_TYPE_RASTER: 1.111 + ret = OUT_RASTER_PRECIS; 1.112 + break; 1.113 + case GFX_FONT_TYPE_DEVICE: 1.114 + ret = OUT_DEVICE_PRECIS; 1.115 + break; 1.116 + default: 1.117 + ret = OUT_DEFAULT_PRECIS; 1.118 + } 1.119 + return ret; 1.120 +} 1.121 + 1.122 +/*************************************************************** 1.123 + * 1.124 + * GDIFontEntry 1.125 + * 1.126 + */ 1.127 + 1.128 +GDIFontEntry::GDIFontEntry(const nsAString& aFaceName, 1.129 + gfxWindowsFontType aFontType, 1.130 + bool aItalic, uint16_t aWeight, int16_t aStretch, 1.131 + gfxUserFontData *aUserFontData, 1.132 + bool aFamilyHasItalicFace) 1.133 + : gfxFontEntry(aFaceName), 1.134 + mWindowsFamily(0), mWindowsPitch(0), 1.135 + mFontType(aFontType), 1.136 + mForceGDI(false), 1.137 + mFamilyHasItalicFace(aFamilyHasItalicFace), 1.138 + mCharset(), mUnicodeRanges() 1.139 +{ 1.140 + mUserFontData = aUserFontData; 1.141 + mItalic = aItalic; 1.142 + mWeight = aWeight; 1.143 + mStretch = aStretch; 1.144 + if (IsType1()) 1.145 + mForceGDI = true; 1.146 + mIsUserFont = aUserFontData != nullptr; 1.147 + 1.148 + InitLogFont(aFaceName, aFontType); 1.149 +} 1.150 + 1.151 +nsresult 1.152 +GDIFontEntry::ReadCMAP(FontInfoData *aFontInfoData) 1.153 +{ 1.154 + // attempt this once, if errors occur leave a blank cmap 1.155 + if (mCharacterMap) { 1.156 + return NS_OK; 1.157 + } 1.158 + 1.159 + // skip non-SFNT fonts completely 1.160 + if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE && 1.161 + mFontType != GFX_FONT_TYPE_TT_OPENTYPE && 1.162 + mFontType != GFX_FONT_TYPE_TRUETYPE) 1.163 + { 1.164 + mCharacterMap = new gfxCharacterMap(); 1.165 + mCharacterMap->mBuildOnTheFly = true; 1.166 + return NS_ERROR_FAILURE; 1.167 + } 1.168 + 1.169 + nsRefPtr<gfxCharacterMap> charmap; 1.170 + nsresult rv; 1.171 + bool unicodeFont = false, symbolFont = false; 1.172 + 1.173 + if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData, 1.174 + mUVSOffset, 1.175 + symbolFont))) { 1.176 + mSymbolFont = symbolFont; 1.177 + rv = NS_OK; 1.178 + } else { 1.179 + uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p'); 1.180 + charmap = new gfxCharacterMap(); 1.181 + AutoFallibleTArray<uint8_t,16384> cmap; 1.182 + rv = CopyFontTable(kCMAP, cmap); 1.183 + 1.184 + if (NS_SUCCEEDED(rv)) { 1.185 + rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), 1.186 + *charmap, mUVSOffset, 1.187 + unicodeFont, symbolFont); 1.188 + } 1.189 + mSymbolFont = symbolFont; 1.190 + } 1.191 + 1.192 + mHasCmapTable = NS_SUCCEEDED(rv); 1.193 + if (mHasCmapTable) { 1.194 + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); 1.195 + mCharacterMap = pfl->FindCharMap(charmap); 1.196 + } else { 1.197 + // if error occurred, initialize to null cmap 1.198 + mCharacterMap = new gfxCharacterMap(); 1.199 + // For fonts where we failed to read the character map, 1.200 + // we can take a slow path to look up glyphs character by character 1.201 + mCharacterMap->mBuildOnTheFly = true; 1.202 + } 1.203 + 1.204 +#ifdef PR_LOGGING 1.205 + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", 1.206 + NS_ConvertUTF16toUTF8(mName).get(), 1.207 + charmap->SizeOfIncludingThis(moz_malloc_size_of), 1.208 + charmap->mHash, mCharacterMap == charmap ? " new" : "")); 1.209 + if (LOG_CMAPDATA_ENABLED()) { 1.210 + char prefix[256]; 1.211 + sprintf(prefix, "(cmapdata) name: %.220s", 1.212 + NS_ConvertUTF16toUTF8(mName).get()); 1.213 + charmap->Dump(prefix, eGfxLog_cmapdata); 1.214 + } 1.215 +#endif 1.216 + 1.217 + return rv; 1.218 +} 1.219 + 1.220 +bool 1.221 +GDIFontEntry::IsSymbolFont() 1.222 +{ 1.223 + // initialize cmap first 1.224 + HasCmapTable(); 1.225 + return mSymbolFont; 1.226 +} 1.227 + 1.228 +gfxFont * 1.229 +GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold) 1.230 +{ 1.231 + bool isXP = !IsVistaOrLater(); 1.232 + 1.233 + bool useClearType = isXP && !aFontStyle->systemFont && 1.234 + (gfxWindowsPlatform::GetPlatform()->UseClearTypeAlways() || 1.235 + (mIsUserFont && !mIsLocalUserFont && 1.236 + gfxWindowsPlatform::GetPlatform()->UseClearTypeForDownloadableFonts())); 1.237 + 1.238 + return new gfxGDIFont(this, aFontStyle, aNeedsBold, 1.239 + (useClearType ? gfxFont::kAntialiasSubpixel 1.240 + : gfxFont::kAntialiasDefault)); 1.241 +} 1.242 + 1.243 +nsresult 1.244 +GDIFontEntry::CopyFontTable(uint32_t aTableTag, 1.245 + FallibleTArray<uint8_t>& aBuffer) 1.246 +{ 1.247 + if (!IsTrueType()) { 1.248 + return NS_ERROR_FAILURE; 1.249 + } 1.250 + 1.251 + AutoDC dc; 1.252 + AutoSelectFont font(dc.GetDC(), &mLogFont); 1.253 + if (font.IsValid()) { 1.254 + uint32_t tableSize = 1.255 + ::GetFontData(dc.GetDC(), 1.256 + NativeEndian::swapToBigEndian(aTableTag), 1.257 + 0, nullptr, 0); 1.258 + if (tableSize != GDI_ERROR) { 1.259 + if (aBuffer.SetLength(tableSize)) { 1.260 + ::GetFontData(dc.GetDC(), 1.261 + NativeEndian::swapToBigEndian(aTableTag), 0, 1.262 + aBuffer.Elements(), tableSize); 1.263 + return NS_OK; 1.264 + } 1.265 + return NS_ERROR_OUT_OF_MEMORY; 1.266 + } 1.267 + } 1.268 + return NS_ERROR_FAILURE; 1.269 +} 1.270 + 1.271 +void 1.272 +GDIFontEntry::FillLogFont(LOGFONTW *aLogFont, 1.273 + uint16_t aWeight, gfxFloat aSize, 1.274 + bool aUseCleartype) 1.275 +{ 1.276 + memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW)); 1.277 + 1.278 + aLogFont->lfHeight = (LONG)-ROUND(aSize); 1.279 + 1.280 + if (aLogFont->lfHeight == 0) { 1.281 + aLogFont->lfHeight = -1; 1.282 + } 1.283 + 1.284 + // If a non-zero weight is passed in, use this to override the original 1.285 + // weight in the entry's logfont. This is used to control synthetic bolding 1.286 + // for installed families with no bold face, and for downloaded fonts 1.287 + // (but NOT for local user fonts, because it could cause a different, 1.288 + // glyph-incompatible face to be used) 1.289 + if (aWeight) { 1.290 + aLogFont->lfWeight = aWeight; 1.291 + } 1.292 + 1.293 + // for non-local() user fonts, we never want to apply italics here; 1.294 + // if the face is described as italic, we should use it as-is, 1.295 + // and if it's not, but then the element is styled italic, we'll use 1.296 + // a cairo transform to create fake italic (oblique) 1.297 + if (IsUserFont() && !IsLocalUserFont()) { 1.298 + aLogFont->lfItalic = 0; 1.299 + } 1.300 + 1.301 + aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY); 1.302 +} 1.303 + 1.304 +#define MISSING_GLYPH 0x1F // glyph index returned for missing characters 1.305 + // on WinXP with .fon fonts, but not Type1 (.pfb) 1.306 + 1.307 +bool 1.308 +GDIFontEntry::TestCharacterMap(uint32_t aCh) 1.309 +{ 1.310 + if (!mCharacterMap) { 1.311 + ReadCMAP(); 1.312 + NS_ASSERTION(mCharacterMap, "failed to initialize a character map"); 1.313 + } 1.314 + 1.315 + if (mCharacterMap->mBuildOnTheFly) { 1.316 + if (aCh > 0xFFFF) 1.317 + return false; 1.318 + 1.319 + // previous code was using the group style 1.320 + gfxFontStyle fakeStyle; 1.321 + if (mItalic) 1.322 + fakeStyle.style = NS_FONT_STYLE_ITALIC; 1.323 + fakeStyle.weight = mWeight * 100; 1.324 + 1.325 + nsRefPtr<gfxFont> tempFont = FindOrMakeFont(&fakeStyle, false); 1.326 + if (!tempFont || !tempFont->Valid()) 1.327 + return false; 1.328 + gfxGDIFont *font = static_cast<gfxGDIFont*>(tempFont.get()); 1.329 + 1.330 + HDC dc = GetDC((HWND)nullptr); 1.331 + SetGraphicsMode(dc, GM_ADVANCED); 1.332 + HFONT hfont = font->GetHFONT(); 1.333 + HFONT oldFont = (HFONT)SelectObject(dc, hfont); 1.334 + 1.335 + wchar_t str[1] = { aCh }; 1.336 + WORD glyph[1]; 1.337 + 1.338 + bool hasGlyph = false; 1.339 + 1.340 + // Bug 573038 - in some cases GetGlyphIndicesW returns 0xFFFF for a 1.341 + // missing glyph or 0x1F in other cases to indicate the "invalid" 1.342 + // glyph. Map both cases to "not found" 1.343 + if (IsType1() || mForceGDI) { 1.344 + // Type1 fonts and uniscribe APIs don't get along. 1.345 + // ScriptGetCMap will return E_HANDLE 1.346 + DWORD ret = GetGlyphIndicesW(dc, str, 1, 1.347 + glyph, GGI_MARK_NONEXISTING_GLYPHS); 1.348 + if (ret != GDI_ERROR 1.349 + && glyph[0] != 0xFFFF 1.350 + && (IsType1() || glyph[0] != MISSING_GLYPH)) 1.351 + { 1.352 + hasGlyph = true; 1.353 + } 1.354 + } else { 1.355 + // ScriptGetCMap works better than GetGlyphIndicesW 1.356 + // for things like bitmap/vector fonts 1.357 + SCRIPT_CACHE sc = nullptr; 1.358 + HRESULT rv = ScriptGetCMap(dc, &sc, str, 1, 0, glyph); 1.359 + if (rv == S_OK) 1.360 + hasGlyph = true; 1.361 + } 1.362 + 1.363 + SelectObject(dc, oldFont); 1.364 + ReleaseDC(nullptr, dc); 1.365 + 1.366 + if (hasGlyph) { 1.367 + mCharacterMap->set(aCh); 1.368 + return true; 1.369 + } 1.370 + } else { 1.371 + // font had a cmap so simply check that 1.372 + return mCharacterMap->test(aCh); 1.373 + } 1.374 + 1.375 + return false; 1.376 +} 1.377 + 1.378 +void 1.379 +GDIFontEntry::InitLogFont(const nsAString& aName, 1.380 + gfxWindowsFontType aFontType) 1.381 +{ 1.382 +#define CLIP_TURNOFF_FONTASSOCIATION 0x40 1.383 + 1.384 + mLogFont.lfHeight = -1; 1.385 + 1.386 + // Fill in logFont structure 1.387 + mLogFont.lfWidth = 0; 1.388 + mLogFont.lfEscapement = 0; 1.389 + mLogFont.lfOrientation = 0; 1.390 + mLogFont.lfUnderline = FALSE; 1.391 + mLogFont.lfStrikeOut = FALSE; 1.392 + mLogFont.lfCharSet = DEFAULT_CHARSET; 1.393 + mLogFont.lfOutPrecision = FontTypeToOutPrecision(aFontType); 1.394 + mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION; 1.395 + mLogFont.lfQuality = DEFAULT_QUALITY; 1.396 + mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; 1.397 + // always force lfItalic if we want it. Font selection code will 1.398 + // do its best to give us an italic font entry, but if no face exists 1.399 + // it may give us a regular one based on weight. Windows should 1.400 + // do fake italic for us in that case. 1.401 + mLogFont.lfItalic = mItalic; 1.402 + mLogFont.lfWeight = mWeight; 1.403 + 1.404 + int len = std::min<int>(aName.Length(), LF_FACESIZE - 1); 1.405 + memcpy(&mLogFont.lfFaceName, aName.BeginReading(), len * sizeof(char16_t)); 1.406 + mLogFont.lfFaceName[len] = '\0'; 1.407 +} 1.408 + 1.409 +GDIFontEntry* 1.410 +GDIFontEntry::CreateFontEntry(const nsAString& aName, 1.411 + gfxWindowsFontType aFontType, bool aItalic, 1.412 + uint16_t aWeight, int16_t aStretch, 1.413 + gfxUserFontData* aUserFontData, 1.414 + bool aFamilyHasItalicFace) 1.415 +{ 1.416 + // jtdfix - need to set charset, unicode ranges, pitch/family 1.417 + 1.418 + GDIFontEntry *fe = new GDIFontEntry(aName, aFontType, aItalic, 1.419 + aWeight, aStretch, aUserFontData, 1.420 + aFamilyHasItalicFace); 1.421 + 1.422 + return fe; 1.423 +} 1.424 + 1.425 +void 1.426 +GDIFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.427 + FontListSizes* aSizes) const 1.428 +{ 1.429 + aSizes->mFontListSize += aMallocSizeOf(this); 1.430 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.431 +} 1.432 + 1.433 +/*************************************************************** 1.434 + * 1.435 + * GDIFontFamily 1.436 + * 1.437 + */ 1.438 + 1.439 +int CALLBACK 1.440 +GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe, 1.441 + const NEWTEXTMETRICEXW *nmetrics, 1.442 + DWORD fontType, LPARAM data) 1.443 +{ 1.444 + const NEWTEXTMETRICW& metrics = nmetrics->ntmTm; 1.445 + LOGFONTW logFont = lpelfe->elfLogFont; 1.446 + GDIFontFamily *ff = reinterpret_cast<GDIFontFamily*>(data); 1.447 + 1.448 + // Some fonts claim to support things > 900, but we don't so clamp the sizes 1.449 + logFont.lfWeight = clamped(logFont.lfWeight, LONG(100), LONG(900)); 1.450 + 1.451 + gfxWindowsFontType feType = GDIFontEntry::DetermineFontType(metrics, fontType); 1.452 + 1.453 + GDIFontEntry *fe = nullptr; 1.454 + for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) { 1.455 + fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get()); 1.456 + if (feType > fe->mFontType) { 1.457 + // if the new type is better than the old one, remove the old entries 1.458 + ff->mAvailableFonts.RemoveElementAt(i); 1.459 + --i; 1.460 + } else if (feType < fe->mFontType) { 1.461 + // otherwise if the new type is worse, skip it 1.462 + return 1; 1.463 + } 1.464 + } 1.465 + 1.466 + for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) { 1.467 + fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get()); 1.468 + // check if we already know about this face 1.469 + if (fe->mWeight == logFont.lfWeight && 1.470 + fe->mItalic == (logFont.lfItalic == 0xFF)) { 1.471 + // update the charset bit here since this could be different 1.472 + fe->mCharset.set(metrics.tmCharSet); 1.473 + return 1; 1.474 + } 1.475 + } 1.476 + 1.477 + // We can't set the hasItalicFace flag correctly here, 1.478 + // because we might not have seen the family's italic face(s) yet. 1.479 + // So we'll set that flag for all members after loading all the faces. 1.480 + fe = GDIFontEntry::CreateFontEntry(nsDependentString(lpelfe->elfFullName), 1.481 + feType, (logFont.lfItalic == 0xFF), 1.482 + (uint16_t) (logFont.lfWeight), 0, 1.483 + nullptr, false); 1.484 + if (!fe) 1.485 + return 1; 1.486 + 1.487 + ff->AddFontEntry(fe); 1.488 + 1.489 + // mark the charset bit 1.490 + fe->mCharset.set(metrics.tmCharSet); 1.491 + 1.492 + fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0; 1.493 + fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F; 1.494 + 1.495 + if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 && 1.496 + nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 && 1.497 + nmetrics->ntmFontSig.fsUsb[2] != 0x00000000 && 1.498 + nmetrics->ntmFontSig.fsUsb[3] != 0x00000000) { 1.499 + 1.500 + // set the unicode ranges 1.501 + uint32_t x = 0; 1.502 + for (uint32_t i = 0; i < 4; ++i) { 1.503 + DWORD range = nmetrics->ntmFontSig.fsUsb[i]; 1.504 + for (uint32_t k = 0; k < 32; ++k) { 1.505 + fe->mUnicodeRanges.set(x++, (range & (1 << k)) != 0); 1.506 + } 1.507 + } 1.508 + } 1.509 + 1.510 +#ifdef PR_LOGGING 1.511 + if (LOG_FONTLIST_ENABLED()) { 1.512 + LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" 1.513 + " with style: %s weight: %d stretch: %d", 1.514 + NS_ConvertUTF16toUTF8(fe->Name()).get(), 1.515 + NS_ConvertUTF16toUTF8(ff->Name()).get(), 1.516 + (logFont.lfItalic == 0xff) ? "italic" : "normal", 1.517 + logFont.lfWeight, fe->Stretch())); 1.518 + } 1.519 +#endif 1.520 + return 1; 1.521 +} 1.522 + 1.523 +void 1.524 +GDIFontFamily::FindStyleVariations(FontInfoData *aFontInfoData) 1.525 +{ 1.526 + if (mHasStyles) 1.527 + return; 1.528 + mHasStyles = true; 1.529 + 1.530 + HDC hdc = GetDC(nullptr); 1.531 + SetGraphicsMode(hdc, GM_ADVANCED); 1.532 + 1.533 + LOGFONTW logFont; 1.534 + memset(&logFont, 0, sizeof(LOGFONTW)); 1.535 + logFont.lfCharSet = DEFAULT_CHARSET; 1.536 + logFont.lfPitchAndFamily = 0; 1.537 + uint32_t l = std::min<uint32_t>(mName.Length(), LF_FACESIZE - 1); 1.538 + memcpy(logFont.lfFaceName, mName.get(), l * sizeof(char16_t)); 1.539 + 1.540 + EnumFontFamiliesExW(hdc, &logFont, 1.541 + (FONTENUMPROCW)GDIFontFamily::FamilyAddStylesProc, 1.542 + (LPARAM)this, 0); 1.543 +#ifdef PR_LOGGING 1.544 + if (LOG_FONTLIST_ENABLED() && mAvailableFonts.Length() == 0) { 1.545 + LOG_FONTLIST(("(fontlist) no styles available in family \"%s\"", 1.546 + NS_ConvertUTF16toUTF8(mName).get())); 1.547 + } 1.548 +#endif 1.549 + 1.550 + ReleaseDC(nullptr, hdc); 1.551 + 1.552 + if (mIsBadUnderlineFamily) { 1.553 + SetBadUnderlineFonts(); 1.554 + } 1.555 + 1.556 + // check for existence of italic face(s); if present, set the 1.557 + // FamilyHasItalic flag on all faces so that we'll know *not* 1.558 + // to use GDI's fake-italic effect with them 1.559 + size_t count = mAvailableFonts.Length(); 1.560 + for (size_t i = 0; i < count; ++i) { 1.561 + if (mAvailableFonts[i]->IsItalic()) { 1.562 + for (uint32_t j = 0; j < count; ++j) { 1.563 + static_cast<GDIFontEntry*>(mAvailableFonts[j].get())-> 1.564 + mFamilyHasItalicFace = true; 1.565 + } 1.566 + break; 1.567 + } 1.568 + } 1.569 +} 1.570 + 1.571 +/*************************************************************** 1.572 + * 1.573 + * gfxGDIFontList 1.574 + * 1.575 + */ 1.576 + 1.577 +gfxGDIFontList::gfxGDIFontList() 1.578 + : mFontSubstitutes(50) 1.579 +{ 1.580 +} 1.581 + 1.582 +static void 1.583 +RemoveCharsetFromFontSubstitute(nsAString &aName) 1.584 +{ 1.585 + int32_t comma = aName.FindChar(char16_t(',')); 1.586 + if (comma >= 0) 1.587 + aName.Truncate(comma); 1.588 +} 1.589 + 1.590 +#define MAX_VALUE_NAME 512 1.591 +#define MAX_VALUE_DATA 512 1.592 + 1.593 +nsresult 1.594 +gfxGDIFontList::GetFontSubstitutes() 1.595 +{ 1.596 + HKEY hKey; 1.597 + DWORD i, rv, lenAlias, lenActual, valueType; 1.598 + WCHAR aliasName[MAX_VALUE_NAME]; 1.599 + WCHAR actualName[MAX_VALUE_DATA]; 1.600 + 1.601 + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1.602 + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", 1.603 + 0, KEY_READ, &hKey) != ERROR_SUCCESS) 1.604 + { 1.605 + return NS_ERROR_FAILURE; 1.606 + } 1.607 + 1.608 + for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) { 1.609 + aliasName[0] = 0; 1.610 + lenAlias = ArrayLength(aliasName); 1.611 + actualName[0] = 0; 1.612 + lenActual = sizeof(actualName); 1.613 + rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, nullptr, &valueType, 1.614 + (LPBYTE)actualName, &lenActual); 1.615 + 1.616 + if (rv != ERROR_SUCCESS || valueType != REG_SZ || lenAlias == 0) { 1.617 + continue; 1.618 + } 1.619 + 1.620 + if (aliasName[0] == WCHAR('@')) { 1.621 + continue; 1.622 + } 1.623 + 1.624 + nsAutoString substituteName((char16_t*) aliasName); 1.625 + nsAutoString actualFontName((char16_t*) actualName); 1.626 + RemoveCharsetFromFontSubstitute(substituteName); 1.627 + BuildKeyNameFromFontName(substituteName); 1.628 + RemoveCharsetFromFontSubstitute(actualFontName); 1.629 + BuildKeyNameFromFontName(actualFontName); 1.630 + gfxFontFamily *ff; 1.631 + if (!actualFontName.IsEmpty() && 1.632 + (ff = mFontFamilies.GetWeak(actualFontName))) { 1.633 + mFontSubstitutes.Put(substituteName, ff); 1.634 + } else { 1.635 + mNonExistingFonts.AppendElement(substituteName); 1.636 + } 1.637 + } 1.638 + 1.639 + // "Courier" on a default Windows install is an ugly bitmap font. 1.640 + // If there is no substitution for Courier in the registry 1.641 + // substitute "Courier" with "Courier New". 1.642 + nsAutoString substituteName; 1.643 + substituteName.AssignLiteral("Courier"); 1.644 + BuildKeyNameFromFontName(substituteName); 1.645 + if (!mFontSubstitutes.GetWeak(substituteName)) { 1.646 + gfxFontFamily *ff; 1.647 + nsAutoString actualFontName; 1.648 + actualFontName.AssignLiteral("Courier New"); 1.649 + BuildKeyNameFromFontName(actualFontName); 1.650 + ff = mFontFamilies.GetWeak(actualFontName); 1.651 + if (ff) { 1.652 + mFontSubstitutes.Put(substituteName, ff); 1.653 + } 1.654 + } 1.655 + return NS_OK; 1.656 +} 1.657 + 1.658 +nsresult 1.659 +gfxGDIFontList::InitFontList() 1.660 +{ 1.661 + Telemetry::AutoTimer<Telemetry::GDI_INITFONTLIST_TOTAL> timer; 1.662 + gfxFontCache *fc = gfxFontCache::GetCache(); 1.663 + if (fc) 1.664 + fc->AgeAllGenerations(); 1.665 + 1.666 + // reset font lists 1.667 + gfxPlatformFontList::InitFontList(); 1.668 + 1.669 + mFontSubstitutes.Clear(); 1.670 + mNonExistingFonts.Clear(); 1.671 + 1.672 + // iterate over available families 1.673 + LOGFONTW logfont; 1.674 + memset(&logfont, 0, sizeof(logfont)); 1.675 + logfont.lfCharSet = DEFAULT_CHARSET; 1.676 + 1.677 + AutoDC hdc; 1.678 + int result = EnumFontFamiliesExW(hdc.GetDC(), &logfont, 1.679 + (FONTENUMPROCW)&EnumFontFamExProc, 1.680 + 0, 0); 1.681 + 1.682 + GetFontSubstitutes(); 1.683 + 1.684 + GetPrefsAndStartLoader(); 1.685 + 1.686 + return NS_OK; 1.687 +} 1.688 + 1.689 +int CALLBACK 1.690 +gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, 1.691 + NEWTEXTMETRICEXW *lpntme, 1.692 + DWORD fontType, 1.693 + LPARAM lParam) 1.694 +{ 1.695 + const LOGFONTW& lf = lpelfe->elfLogFont; 1.696 + 1.697 + if (lf.lfFaceName[0] == '@') { 1.698 + return 1; 1.699 + } 1.700 + 1.701 + nsAutoString name(lf.lfFaceName); 1.702 + BuildKeyNameFromFontName(name); 1.703 + 1.704 + gfxGDIFontList *fontList = PlatformFontList(); 1.705 + 1.706 + if (!fontList->mFontFamilies.GetWeak(name)) { 1.707 + nsDependentString faceName(lf.lfFaceName); 1.708 + nsRefPtr<gfxFontFamily> family = new GDIFontFamily(faceName); 1.709 + fontList->mFontFamilies.Put(name, family); 1.710 + 1.711 + // if locale is such that CJK font names are the default coming from 1.712 + // GDI, then if a family name is non-ASCII immediately read in other 1.713 + // family names. This assures that MS Gothic, MS Mincho are all found 1.714 + // before lookups begin. 1.715 + if (!IsASCII(faceName)) { 1.716 + family->ReadOtherFamilyNames(gfxPlatformFontList::PlatformFontList()); 1.717 + } 1.718 + 1.719 + if (fontList->mBadUnderlineFamilyNames.Contains(name)) 1.720 + family->SetBadUnderlineFamily(); 1.721 + } 1.722 + 1.723 + return 1; 1.724 +} 1.725 + 1.726 +gfxFontEntry* 1.727 +gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, 1.728 + const nsAString& aFullname) 1.729 +{ 1.730 + gfxFontEntry *lookup; 1.731 + 1.732 + lookup = LookupInFaceNameLists(aFullname); 1.733 + if (!lookup) { 1.734 + return nullptr; 1.735 + } 1.736 + 1.737 + bool isCFF = false; // jtdfix -- need to determine this 1.738 + 1.739 + // use the face name from the lookup font entry, which will be the localized 1.740 + // face name which GDI mapping tables use (e.g. with the system locale set to 1.741 + // Dutch, a fullname of 'Arial Bold' will find a font entry with the face name 1.742 + // 'Arial Vet' which can be used as a key in GDI font lookups). 1.743 + GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(lookup->Name(), 1.744 + gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, 1.745 + lookup->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL, 1.746 + lookup->mWeight, aProxyEntry->mStretch, nullptr, 1.747 + static_cast<GDIFontEntry*>(lookup)->mFamilyHasItalicFace); 1.748 + 1.749 + if (!fe) 1.750 + return nullptr; 1.751 + 1.752 + fe->mIsUserFont = true; 1.753 + fe->mIsLocalUserFont = true; 1.754 + 1.755 + // make the new font entry match the proxy entry style characteristics 1.756 + fe->mWeight = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight); 1.757 + fe->mItalic = aProxyEntry->mItalic; 1.758 + 1.759 + return fe; 1.760 +} 1.761 + 1.762 +gfxFontEntry* 1.763 +gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 1.764 + const uint8_t *aFontData, 1.765 + uint32_t aLength) 1.766 +{ 1.767 + // MakePlatformFont is responsible for deleting the font data with NS_Free 1.768 + // so we set up a stack object to ensure it is freed even if we take an 1.769 + // early exit 1.770 + struct FontDataDeleter { 1.771 + FontDataDeleter(const uint8_t *aFontData) 1.772 + : mFontData(aFontData) { } 1.773 + ~FontDataDeleter() { NS_Free((void*)mFontData); } 1.774 + const uint8_t *mFontData; 1.775 + }; 1.776 + FontDataDeleter autoDelete(aFontData); 1.777 + 1.778 + bool isCFF = gfxFontUtils::IsCffFont(aFontData); 1.779 + 1.780 + nsresult rv; 1.781 + HANDLE fontRef = nullptr; 1.782 + 1.783 + nsAutoString uniqueName; 1.784 + rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); 1.785 + if (NS_FAILED(rv)) 1.786 + return nullptr; 1.787 + 1.788 + FallibleTArray<uint8_t> newFontData; 1.789 + 1.790 + rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData); 1.791 + 1.792 + if (NS_FAILED(rv)) 1.793 + return nullptr; 1.794 + 1.795 + DWORD numFonts = 0; 1.796 + 1.797 + uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements()); 1.798 + uint32_t fontLength = newFontData.Length(); 1.799 + NS_ASSERTION(fontData, "null font data after renaming"); 1.800 + 1.801 + // http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx 1.802 + // "A font that is added by AddFontMemResourceEx is always private 1.803 + // to the process that made the call and is not enumerable." 1.804 + fontRef = AddFontMemResourceEx(fontData, fontLength, 1.805 + 0 /* reserved */, &numFonts); 1.806 + if (!fontRef) 1.807 + return nullptr; 1.808 + 1.809 + // only load fonts with a single face contained in the data 1.810 + // AddFontMemResourceEx generates an additional face name for 1.811 + // vertical text if the font supports vertical writing but since 1.812 + // the font is referenced via the name this can be ignored 1.813 + if (fontRef && numFonts > 2) { 1.814 + RemoveFontMemResourceEx(fontRef); 1.815 + return nullptr; 1.816 + } 1.817 + 1.818 + // make a new font entry using the unique name 1.819 + WinUserFontData *winUserFontData = new WinUserFontData(fontRef); 1.820 + uint16_t w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight); 1.821 + 1.822 + GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName, 1.823 + gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, 1.824 + uint32_t(aProxyEntry->mItalic ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL), 1.825 + w, aProxyEntry->mStretch, winUserFontData, false); 1.826 + 1.827 + if (!fe) 1.828 + return fe; 1.829 + 1.830 + fe->mIsUserFont = true; 1.831 + 1.832 + // Uniscribe doesn't place CFF fonts loaded privately 1.833 + // via AddFontMemResourceEx on XP/Vista 1.834 + if (isCFF && !IsWin7OrLater()) { 1.835 + fe->mForceGDI = true; 1.836 + } 1.837 + 1.838 + return fe; 1.839 +} 1.840 + 1.841 +gfxFontFamily* 1.842 +gfxGDIFontList::GetDefaultFont(const gfxFontStyle* aStyle) 1.843 +{ 1.844 + // this really shouldn't fail to find a font.... 1.845 + HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT); 1.846 + LOGFONTW logFont; 1.847 + if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) { 1.848 + nsAutoString resolvedName; 1.849 + if (ResolveFontName(nsDependentString(logFont.lfFaceName), resolvedName)) { 1.850 + return FindFamily(resolvedName); 1.851 + } 1.852 + } 1.853 + 1.854 + // ...but just in case, try another approach as well 1.855 + NONCLIENTMETRICSW ncm; 1.856 + ncm.cbSize = sizeof(ncm); 1.857 + BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 1.858 + sizeof(ncm), &ncm, 0); 1.859 + if (status) { 1.860 + nsAutoString resolvedName; 1.861 + if (ResolveFontName(nsDependentString(ncm.lfMessageFont.lfFaceName), resolvedName)) { 1.862 + return FindFamily(resolvedName); 1.863 + } 1.864 + } 1.865 + 1.866 + return nullptr; 1.867 +} 1.868 + 1.869 + 1.870 +bool 1.871 +gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName) 1.872 +{ 1.873 + nsAutoString keyName(aFontName); 1.874 + BuildKeyNameFromFontName(keyName); 1.875 + 1.876 + gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName); 1.877 + if (ff) { 1.878 + aResolvedFontName = ff->Name(); 1.879 + return true; 1.880 + } 1.881 + 1.882 + if (mNonExistingFonts.Contains(keyName)) 1.883 + return false; 1.884 + 1.885 + if (gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName)) 1.886 + return true; 1.887 + 1.888 + return false; 1.889 +} 1.890 + 1.891 +void 1.892 +gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, 1.893 + FontListSizes* aSizes) const 1.894 +{ 1.895 + gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.896 + aSizes->mFontListSize += 1.897 + mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, 1.898 + aMallocSizeOf); 1.899 + aSizes->mFontListSize += 1.900 + mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf); 1.901 + for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) { 1.902 + aSizes->mFontListSize += 1.903 + mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.904 + } 1.905 +} 1.906 + 1.907 +void 1.908 +gfxGDIFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.909 + FontListSizes* aSizes) const 1.910 +{ 1.911 + aSizes->mFontListSize += aMallocSizeOf(this); 1.912 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.913 +} 1.914 + 1.915 +// used to load system-wide font info on off-main thread 1.916 +class GDIFontInfo : public FontInfoData { 1.917 +public: 1.918 + GDIFontInfo(bool aLoadOtherNames, 1.919 + bool aLoadFaceNames, 1.920 + bool aLoadCmaps) : 1.921 + FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps) 1.922 + {} 1.923 + 1.924 + virtual ~GDIFontInfo() {} 1.925 + 1.926 + virtual void Load() { 1.927 + mHdc = GetDC(nullptr); 1.928 + SetGraphicsMode(mHdc, GM_ADVANCED); 1.929 + FontInfoData::Load(); 1.930 + ReleaseDC(nullptr, mHdc); 1.931 + } 1.932 + 1.933 + // loads font data for all members of a given family 1.934 + virtual void LoadFontFamilyData(const nsAString& aFamilyName); 1.935 + 1.936 + // callback for GDI EnumFontFamiliesExW call 1.937 + static int CALLBACK EnumerateFontsForFamily(const ENUMLOGFONTEXW *lpelfe, 1.938 + const NEWTEXTMETRICEXW *nmetrics, 1.939 + DWORD fontType, LPARAM data); 1.940 + 1.941 + HDC mHdc; 1.942 +}; 1.943 + 1.944 +struct EnumerateFontsForFamilyData { 1.945 + EnumerateFontsForFamilyData(const nsAString& aFamilyName, 1.946 + GDIFontInfo& aFontInfo) 1.947 + : mFamilyName(aFamilyName), mFontInfo(aFontInfo) 1.948 + {} 1.949 + 1.950 + nsString mFamilyName; 1.951 + nsTArray<nsString> mOtherFamilyNames; 1.952 + GDIFontInfo& mFontInfo; 1.953 + nsString mPreviousFontName; 1.954 +}; 1.955 + 1.956 +int CALLBACK GDIFontInfo::EnumerateFontsForFamily( 1.957 + const ENUMLOGFONTEXW *lpelfe, 1.958 + const NEWTEXTMETRICEXW *nmetrics, 1.959 + DWORD fontType, LPARAM data) 1.960 +{ 1.961 + EnumerateFontsForFamilyData *famData = 1.962 + reinterpret_cast<EnumerateFontsForFamilyData*>(data); 1.963 + HDC hdc = famData->mFontInfo.mHdc; 1.964 + LOGFONTW logFont = lpelfe->elfLogFont; 1.965 + const NEWTEXTMETRICW& metrics = nmetrics->ntmTm; 1.966 + 1.967 + AutoSelectFont font(hdc, &logFont); 1.968 + if (!font.IsValid()) { 1.969 + return 1; 1.970 + } 1.971 + 1.972 + FontFaceData fontData; 1.973 + nsDependentString fontName(lpelfe->elfFullName); 1.974 + 1.975 + // callback called for each style-charset so return if style already seen 1.976 + if (fontName.Equals(famData->mPreviousFontName)) { 1.977 + return 1; 1.978 + } 1.979 + famData->mPreviousFontName = fontName; 1.980 + famData->mFontInfo.mLoadStats.fonts++; 1.981 + 1.982 + // read name table info 1.983 + bool nameDataLoaded = false; 1.984 + if (famData->mFontInfo.mLoadFaceNames || famData->mFontInfo.mLoadOtherNames) { 1.985 + uint32_t kNAME = 1.986 + NativeEndian::swapToBigEndian(TRUETYPE_TAG('n','a','m','e')); 1.987 + uint32_t nameSize; 1.988 + AutoFallibleTArray<uint8_t, 1024> nameData; 1.989 + 1.990 + nameSize = ::GetFontData(hdc, kNAME, 0, nullptr, 0); 1.991 + if (nameSize != GDI_ERROR && 1.992 + nameSize > 0 && 1.993 + nameData.SetLength(nameSize)) { 1.994 + ::GetFontData(hdc, kNAME, 0, nameData.Elements(), nameSize); 1.995 + 1.996 + // face names 1.997 + if (famData->mFontInfo.mLoadFaceNames) { 1.998 + gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize, 1.999 + gfxFontUtils::NAME_ID_FULL, 1.1000 + fontData.mFullName); 1.1001 + gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize, 1.1002 + gfxFontUtils::NAME_ID_POSTSCRIPT, 1.1003 + fontData.mPostscriptName); 1.1004 + nameDataLoaded = true; 1.1005 + famData->mFontInfo.mLoadStats.facenames++; 1.1006 + } 1.1007 + 1.1008 + // other family names 1.1009 + if (famData->mFontInfo.mLoadOtherNames) { 1.1010 + gfxFontFamily::ReadOtherFamilyNamesForFace(famData->mFamilyName, 1.1011 + (const char*)(nameData.Elements()), 1.1012 + nameSize, 1.1013 + famData->mOtherFamilyNames, 1.1014 + false); 1.1015 + } 1.1016 + } 1.1017 + } 1.1018 + 1.1019 + // read cmap 1.1020 + bool cmapLoaded = false; 1.1021 + gfxWindowsFontType feType = 1.1022 + GDIFontEntry::DetermineFontType(metrics, fontType); 1.1023 + if (famData->mFontInfo.mLoadCmaps && 1.1024 + (feType == GFX_FONT_TYPE_PS_OPENTYPE || 1.1025 + feType == GFX_FONT_TYPE_TT_OPENTYPE || 1.1026 + feType == GFX_FONT_TYPE_TRUETYPE)) 1.1027 + { 1.1028 + uint32_t kCMAP = 1.1029 + NativeEndian::swapToBigEndian(TRUETYPE_TAG('c','m','a','p')); 1.1030 + uint32_t cmapSize; 1.1031 + AutoFallibleTArray<uint8_t, 1024> cmapData; 1.1032 + 1.1033 + cmapSize = ::GetFontData(hdc, kCMAP, 0, nullptr, 0); 1.1034 + if (cmapSize != GDI_ERROR && 1.1035 + cmapSize > 0 && 1.1036 + cmapData.SetLength(cmapSize)) { 1.1037 + ::GetFontData(hdc, kCMAP, 0, cmapData.Elements(), cmapSize); 1.1038 + bool cmapLoaded = false; 1.1039 + bool unicodeFont = false, symbolFont = false; 1.1040 + nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap(); 1.1041 + uint32_t offset; 1.1042 + 1.1043 + if (NS_SUCCEEDED(gfxFontUtils::ReadCMAP(cmapData.Elements(), 1.1044 + cmapSize, *charmap, 1.1045 + offset, unicodeFont, 1.1046 + symbolFont))) { 1.1047 + fontData.mCharacterMap = charmap; 1.1048 + fontData.mUVSOffset = offset; 1.1049 + fontData.mSymbolFont = symbolFont; 1.1050 + cmapLoaded = true; 1.1051 + famData->mFontInfo.mLoadStats.cmaps++; 1.1052 + } 1.1053 + } 1.1054 + } 1.1055 + 1.1056 + if (cmapLoaded || nameDataLoaded) { 1.1057 + famData->mFontInfo.mFontFaceData.Put(fontName, fontData); 1.1058 + } 1.1059 + 1.1060 + return 1; 1.1061 +} 1.1062 + 1.1063 +void 1.1064 +GDIFontInfo::LoadFontFamilyData(const nsAString& aFamilyName) 1.1065 +{ 1.1066 + // iterate over the family 1.1067 + LOGFONTW logFont; 1.1068 + memset(&logFont, 0, sizeof(LOGFONTW)); 1.1069 + logFont.lfCharSet = DEFAULT_CHARSET; 1.1070 + logFont.lfPitchAndFamily = 0; 1.1071 + uint32_t l = std::min<uint32_t>(aFamilyName.Length(), LF_FACESIZE - 1); 1.1072 + memcpy(logFont.lfFaceName, aFamilyName.BeginReading(), l * sizeof(char16_t)); 1.1073 + 1.1074 + EnumerateFontsForFamilyData data(aFamilyName, *this); 1.1075 + 1.1076 + EnumFontFamiliesExW(mHdc, &logFont, 1.1077 + (FONTENUMPROCW)GDIFontInfo::EnumerateFontsForFamily, 1.1078 + (LPARAM)(&data), 0); 1.1079 + 1.1080 + // if found other names, insert them 1.1081 + if (data.mOtherFamilyNames.Length() != 0) { 1.1082 + mOtherFamilyNames.Put(aFamilyName, data.mOtherFamilyNames); 1.1083 + mLoadStats.othernames += data.mOtherFamilyNames.Length(); 1.1084 + } 1.1085 +} 1.1086 + 1.1087 +already_AddRefed<FontInfoData> 1.1088 +gfxGDIFontList::CreateFontInfoData() 1.1089 +{ 1.1090 + bool loadCmaps = !UsesSystemFallback() || 1.1091 + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.1092 + 1.1093 + nsRefPtr<GDIFontInfo> fi = 1.1094 + new GDIFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps); 1.1095 + 1.1096 + return fi.forget(); 1.1097 +}