📄 fontcachewin.cpp
字号:
break; LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; memcpy(logFont.lfFaceName, linkedFonts->at(linkedFontIndex).characters(), linkedFonts->at(linkedFontIndex).length() * sizeof(WCHAR)); logFont.lfFaceName[linkedFonts->at(linkedFontIndex).length()] = 0; EnumFontFamiliesEx(hdc, &logFont, linkedFontEnumProc, reinterpret_cast<LPARAM>(&hfont), 0); linkedFontIndex++; } if (hfont) { if (!familyName.isEmpty()) { FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName); if (result) fontData = getCachedFontData(result); } SelectObject(hdc, oldFont); DeleteObject(hfont); } ReleaseDC(0, hdc); return fontData;}FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font){ return 0;}FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription){ // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. static AtomicString timesStr("Times New Roman"); return getCachedFontPlatformData(fontDescription, timesStr);}static LONG toGDIFontWeight(FontWeight fontWeight){ static LONG gdiFontWeights[] = { FW_THIN, // FontWeight100 FW_EXTRALIGHT, // FontWeight200 FW_LIGHT, // FontWeight300 FW_NORMAL, // FontWeight400 FW_MEDIUM, // FontWeight500 FW_SEMIBOLD, // FontWeight600 FW_BOLD, // FontWeight700 FW_EXTRABOLD, // FontWeight800 FW_HEAVY // FontWeight900 }; return gdiFontWeights[fontWeight];}static inline bool isGDIFontWeightBold(LONG gdiFontWeight){ return gdiFontWeight >= FW_SEMIBOLD;}static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family){ static AtomicString lucidaStr("Lucida Grande"); if (equalIgnoringCase(family, lucidaStr)) { if (gdiFontWeight == FW_NORMAL) return FW_MEDIUM; if (gdiFontWeight == FW_BOLD) return FW_SEMIBOLD; } return gdiFontWeight;}struct MatchImprovingProcData { MatchImprovingProcData(LONG desiredWeight, bool desiredItalic) : m_desiredWeight(desiredWeight) , m_desiredItalic(desiredItalic) , m_hasMatched(false) { } LONG m_desiredWeight; bool m_desiredItalic; bool m_hasMatched; LOGFONT m_chosen;};static int CALLBACK matchImprovingEnumProc(CONST LOGFONT* candidate, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam){ MatchImprovingProcData* matchData = reinterpret_cast<MatchImprovingProcData*>(lParam); if (!matchData->m_hasMatched) { matchData->m_hasMatched = true; matchData->m_chosen = *candidate; return 1; } if (!candidate->lfItalic != !matchData->m_chosen.lfItalic) { if (!candidate->lfItalic == !matchData->m_desiredItalic) matchData->m_chosen = *candidate; return 1; } unsigned chosenWeightDeltaMagnitude = abs(matchData->m_chosen.lfWeight - matchData->m_desiredWeight); unsigned candidateWeightDeltaMagnitude = abs(candidate->lfWeight - matchData->m_desiredWeight); // If both are the same distance from the desired weight, prefer the candidate if it is further from regular. if (chosenWeightDeltaMagnitude == candidateWeightDeltaMagnitude && abs(candidate->lfWeight - FW_NORMAL) > abs(matchData->m_chosen.lfWeight - FW_NORMAL)) { matchData->m_chosen = *candidate; return 1; } // Otherwise, prefer the one closer to the desired weight. if (candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude) matchData->m_chosen = *candidate; return 1;}static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool desiredItalic, int size){ HDC hdc = GetDC(0); LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; unsigned familyLength = min(family.length(), static_cast<unsigned>(LF_FACESIZE - 1)); memcpy(logFont.lfFaceName, family.characters(), familyLength * sizeof(UChar)); logFont.lfFaceName[familyLength] = 0; logFont.lfPitchAndFamily = 0; MatchImprovingProcData matchData(desiredWeight, desiredItalic); EnumFontFamiliesEx(hdc, &logFont, matchImprovingEnumProc, reinterpret_cast<LPARAM>(&matchData), 0); ReleaseDC(0, hdc); if (!matchData.m_hasMatched) return 0; matchData.m_chosen.lfHeight = -size; matchData.m_chosen.lfWidth = 0; matchData.m_chosen.lfEscapement = 0; matchData.m_chosen.lfOrientation = 0; matchData.m_chosen.lfUnderline = false; matchData.m_chosen.lfStrikeOut = false; matchData.m_chosen.lfCharSet = DEFAULT_CHARSET;#if PLATFORM(CG) || PLATFORM(CAIRO) matchData.m_chosen.lfOutPrecision = OUT_TT_ONLY_PRECIS;#else matchData.m_chosen.lfOutPrecision = OUT_TT_PRECIS;#endif matchData.m_chosen.lfQuality = DEFAULT_QUALITY; matchData.m_chosen.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; HFONT result = CreateFontIndirect(&matchData.m_chosen); if (!result) return 0; HDC dc = GetDC(0); SaveDC(dc); SelectObject(dc, result); WCHAR actualName[LF_FACESIZE]; GetTextFace(dc, LF_FACESIZE, actualName); RestoreDC(dc, -1); ReleaseDC(0, dc); if (wcsicmp(matchData.m_chosen.lfFaceName, actualName)) { DeleteObject(result); result = 0; } return result;}struct TraitsInFamilyProcData { TraitsInFamilyProcData(const AtomicString& familyName) : m_familyName(familyName) { } const AtomicString& m_familyName; HashSet<unsigned> m_traitsMasks;};static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam){ TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam); unsigned traitsMask = 0; traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask; traitsMask |= FontVariantNormalMask; LONG weight = adjustedGDIFontWeight(logFont->lfWeight, procData->m_familyName); traitsMask |= weight == FW_THIN ? FontWeight100Mask : weight == FW_EXTRALIGHT ? FontWeight200Mask : weight == FW_LIGHT ? FontWeight300Mask : weight == FW_NORMAL ? FontWeight400Mask : weight == FW_MEDIUM ? FontWeight500Mask : weight == FW_SEMIBOLD ? FontWeight600Mask : weight == FW_BOLD ? FontWeight700Mask : weight == FW_EXTRABOLD ? FontWeight800Mask : FontWeight900Mask; procData->m_traitsMasks.add(traitsMask); return 1;}void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks){ HDC hdc = GetDC(0); LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1)); memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar)); logFont.lfFaceName[familyLength] = 0; logFont.lfPitchAndFamily = 0; TraitsInFamilyProcData procData(familyName); EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0); copyToVector(procData.m_traitsMasks, traitsMasks); ReleaseDC(0, hdc);}FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family){ bool isLucidaGrande = false; static AtomicString lucidaStr("Lucida Grande"); if (equalIgnoringCase(family, lucidaStr)) isLucidaGrande = true; bool useGDI = fontDescription.renderingMode() == AlternateRenderingMode && !isLucidaGrande; // The logical size constant is 32. We do this for subpixel precision when rendering using Uniscribe. // This masks rounding errors related to the HFONT metrics being different from the CGFont metrics. // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't // look as nice. That may be solvable though. LONG weight = adjustedGDIFontWeight(toGDIFontWeight(fontDescription.weight()), family); HFONT hfont = createGDIFont(family, weight, fontDescription.italic(), fontDescription.computedPixelSize() * (useGDI ? 1 : 32)); if (!hfont) return 0; if (isLucidaGrande) useGDI = false; // Never use GDI for Lucida Grande. LOGFONT logFont; GetObject(hfont, sizeof(LOGFONT), &logFont); bool synthesizeBold = isGDIFontWeightBold(weight) && !isGDIFontWeightBold(logFont.lfWeight); bool synthesizeItalic = fontDescription.italic() && !logFont.lfItalic; FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(), synthesizeBold, synthesizeItalic, useGDI);#if PLATFORM(CG) bool fontCreationFailed = !result->cgFont();#elif PLATFORM(CAIRO) bool fontCreationFailed = !result->fontFace();#endif if (fontCreationFailed) { // The creation of the CGFontRef failed for some reason. We already asserted in debug builds, but to make // absolutely sure that we don't use this font, go ahead and return 0 so that we can fall back to the next // font. delete result; DeleteObject(hfont); return 0; } return result;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -