📄 fontcachechromiumwin.cpp
字号:
HDC hdc = GetDC(0); HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont)); int count = GetFontUnicodeRanges(hdc, 0); if (count == 0 && ChromiumBridge::ensureFontLoaded(hfont)) count = GetFontUnicodeRanges(hdc, 0); if (count == 0) { ASSERT_NOT_REACHED(); SelectObject(hdc, oldFont); ReleaseDC(0, hdc); return true; } static Vector<char, 512> glyphsetBuffer; glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0)); GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data()); // In addition, refering to the OS/2 table and converting the codepage list // to the coverage map might be faster. count = GetFontUnicodeRanges(hdc, glyphset); ASSERT(count > 0); SelectObject(hdc, oldFont); ReleaseDC(0, hdc); // FIXME: consider doing either of the following two: // 1) port back ICU 4.0's faster look-up code for UnicodeSet // 2) port Mozilla's CompressedCharMap or gfxSparseBitset unsigned i = 0; UnicodeSet* cmap = new UnicodeSet; while (i < glyphset->cRanges) { WCHAR start = glyphset->ranges[i].wcLow; cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1); i++; } cmap->freeze(); // We don't lowercase |family| because all of them are under our control // and they're already lowercased. fontCmapCache->set(family, cmap); return cmap->contains(character);}// Given the desired base font, this will create a SimpleFontData for a specific// font that can be used to render the given range of characters.const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length){ // FIXME: Consider passing fontDescription.dominantScript() // to GetFallbackFamily here. FontDescription fontDescription = font.fontDescription(); UChar32 c; UScriptCode script; const wchar_t* family = getFallbackFamily(characters, length, fontDescription.genericFamily(), &c, &script); FontPlatformData* data = 0; if (family) data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)), false); // Last resort font list : PanUnicode. CJK fonts have a pretty // large repertoire. Eventually, we need to scan all the fonts // on the system to have a Firefox-like coverage. // Make sure that all of them are lowercased. const static wchar_t* const cjkFonts[] = { L"arial unicode ms", L"ms pgothic", L"simsun", L"gulim", L"pmingliu", L"wenquanyi zen hei", // partial CJK Ext. A coverage but more // widely known to Chinese users. L"ar pl shanheisun uni", L"ar pl zenkai uni", L"han nom a", // Complete CJK Ext. A coverage L"code2000", // Complete CJK Ext. A coverage // CJK Ext. B fonts are not listed here because it's of no use // with our current non-BMP character handling because we use // Uniscribe for it and that code path does not go through here. }; const static wchar_t* const commonFonts[] = { L"tahoma", L"arial unicode ms", L"lucida sans unicode", L"microsoft sans serif", L"palatino linotype", // Four fonts below (and code2000 at the end) are not from MS, but // once installed, cover a very wide range of characters. L"freeserif", L"freesans", L"gentium", L"gentiumalt", L"ms pgothic", L"simsun", L"gulim", L"pmingliu", L"code2000", }; const wchar_t* const* panUniFonts = 0; int numFonts = 0; if (script == USCRIPT_HAN) { panUniFonts = cjkFonts; numFonts = ARRAYSIZE(cjkFonts); } else { panUniFonts = commonFonts; numFonts = ARRAYSIZE(commonFonts); } // Font returned from GetFallbackFamily may not cover |characters| // because it's based on script to font mapping. This problem is // critical enough for non-Latin scripts (especially Han) to // warrant an additional (real coverage) check with fontCotainsCharacter. int i; for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) { family = panUniFonts[i]; data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family))); } // When i-th font (0-base) in |panUniFonts| contains a character and // we get out of the loop, |i| will be |i + 1|. That is, if only the // last font in the array covers the character, |i| will be numFonts. // So, we have to use '<=" rather than '<' to see if we found a font // covering the character. if (i <= numFonts) return getCachedFontData(data); return 0;}FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font){ return 0;}FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description){ FontDescription::GenericFamilyType generic = description.genericFamily(); // FIXME: Mapping webkit generic to GenericFamilyType needs to // be more intelligent. // This spot rarely gets reached. GetFontDataForCharacters() gets hit a lot // more often (see FIXME comment there). const wchar_t* family = getFontFamilyForScript(description.dominantScript(), generic); if (family) return getCachedFontPlatformData(description, AtomicString(family, wcslen(family))); // 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"); static AtomicString courierStr("Courier New"); static AtomicString arialStr("Arial"); AtomicString& fontStr = timesStr; if (generic == FontDescription::SansSerifFamily) fontStr = arialStr; else if (generic == FontDescription::MonospaceFamily) fontStr = courierStr; return getCachedFontPlatformData(description, fontStr);}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];}// FIXME: This may not be the best place to put this functionAtomicString FontCache::getGenericFontForScript(UScriptCode script, const FontDescription& description){ const wchar_t* scriptFont = getFontFamilyForScript( script, description.genericFamily()); return scriptFont ? AtomicString(scriptFont, wcslen(scriptFont)) : emptyAtom;}static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont){ // The size here looks unusual. The negative number is intentional. // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be // some kind of artifact of their CG backend, or something. winfont->lfHeight = -fontDescription.computedPixelSize(); winfont->lfWidth = 0; winfont->lfEscapement = 0; winfont->lfOrientation = 0; winfont->lfUnderline = false; winfont->lfStrikeOut = false; winfont->lfCharSet = DEFAULT_CHARSET; winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS; winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings. winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; winfont->lfItalic = fontDescription.italic(); winfont->lfWeight = toGDIFontWeight(fontDescription.weight());}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 = logFont->lfWeight; 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){ LOGFONT winfont = {0}; FillLogFont(fontDescription, &winfont); // Windows will always give us a valid pointer here, even if the face name // is non-existent. We have to double-check and see if the family name was // really used. String winName; HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName); if (!hfont) return 0; // FIXME: Do we need to use predefined fonts "guaranteed" to exist // when we're running in layout-test mode? if (!equalIgnoringCase(family, winName)) { // For CJK fonts with both English and native names, // GetTextFace returns a native name under the font's "locale" // and an English name under other locales regardless of // lfFaceName field of LOGFONT. As a result, we need to check // if a font has an alternate name. If there is, we need to // compare it with what's requested in the first place. String altName; if (!LookupAltName(family, altName) || !equalIgnoringCase(altName, winName)) { DeleteObject(hfont); return 0; } } return new FontPlatformData(hfont, fontDescription.computedPixelSize());}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -