SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans")); DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif")); DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("Monospace")); FontPlatformData* fontPlatformData = 0; switch (description.genericFamily()) { case FontDescription::SerifFamily: fontPlatformData = getCachedFontPlatformData(description, serifStr); break; case FontDescription::MonospaceFamily: fontPlatformData = getCachedFontPlatformData(description, monospaceStr); break; case FontDescription::SansSerifFamily: default: fontPlatformData = getCachedFontPlatformData(description, sansStr); break; } if (!fontPlatformData) { // we should at least have Arial; this is the SkFontHost_fontconfig last resort fallback DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial")); fontPlatformData = getCachedFontPlatformData(description, arialStr); }
FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName, bool checkingAlternateName) { if (!gFontPlatformDataCache) { gFontPlatformDataCache = new FontPlatformDataCache; } FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.bold(), fontDescription.italic(), fontDescription.usePrinterFont()); FontPlatformData* result = 0; bool foundResult; FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key); if (it == gFontPlatformDataCache->end()) { result = createFontPlatformData(fontDescription, familyName); gFontPlatformDataCache->set(key, result); foundResult = result; } else { result = it->second; foundResult = true; } if (!foundResult && !checkingAlternateName) { // We were unable to find a font. We have a small set of fonts that we alias to other names, // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name. const AtomicString& alternateName = alternateFamilyName(familyName); if (!alternateName.isEmpty()) result = getCachedFontPlatformData(fontDescription, alternateName, true); if (result) gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name. } key.m_family = AtomicString(); return result; }
FontPlatformData* FontCache::getLastResortFallbackFont(const Font& font) { // 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(font.fontDescription(), timesStr); }
const FontData* FontCache::getFontData(const Font& font, int& familyIndex) { FontPlatformData* result = 0; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); for (int i = 0; startFamily && i < startIndex; i++) startFamily = startFamily->next(); const FontFamily* currFamily = startFamily; while (currFamily && !result) { familyIndex++; if (currFamily->family().length()) result = getCachedFontPlatformData(font.fontDescription(), currFamily->family()); currFamily = currFamily->next(); } if (!currFamily) familyIndex = cAllFamiliesScanned; if (!result) // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform. // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the // Geeza Pro font. result = getSimilarFontPlatformData(font); if (!result && startIndex == 0) // We still don't have a result. Hand back our last resort fallback font. We only do the last resort fallback // when trying to find the primary font. Otherwise our fallback will rely on the actual characters used. result = getLastResortFallbackFont(font); // Now that we have a result, we need to go from FontPlatformData -> FontData. return getCachedFontData(result); }
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { String family = getFontFamilyForCharacters(characters, length); if (family.isEmpty()) return 0; AtomicString atomicFamily(family); return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, false)); }
RefPtr<Font> FontCache::fontForFamily(const FontDescription& fontDescription, const AtomicString& family, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, bool checkingAlternateName) { if (!m_purgeTimer.isActive()) m_purgeTimer.startOneShot(0ms); FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, fontFaceFeatures, fontFaceVariantSettings, checkingAlternateName); if (!platformData) return nullptr; return fontForPlatformData(*platformData); }
RefPtr<Font> FontCache::fontForFamily(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName) { if (!m_purgeTimer.isActive()) m_purgeTimer.startOneShot(std::chrono::milliseconds::zero()); FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, checkingAlternateName); if (!platformData) return nullptr; return fontForPlatformData(*platformData); }
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { icu::Locale locale = icu::Locale::getDefault(); String family = PlatformBridge::getFontFamilyForCharacters(characters, length, locale.getLanguage()); if (family.isEmpty()) return 0; AtomicString atomicFamily(family); return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, DoNotRetain)); }
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font) { static AtomicString str("sans-serif"); FontPlatformData* fpd = getCachedFontPlatformData(font, str); if(fpd) { SimpleFontData* ptr = getCachedFontData(fpd); return ptr; } return NULL; }
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description) { static const AtomicString sansStr("Sans"); static const AtomicString serifStr("Serif"); static const AtomicString monospaceStr("Monospace"); FontPlatformData* fontPlatformData = 0; switch (description.genericFamily()) { case FontDescription::SerifFamily: fontPlatformData = getCachedFontPlatformData(description, serifStr); break; case FontDescription::MonospaceFamily: fontPlatformData = getCachedFontPlatformData(description, monospaceStr); break; case FontDescription::SansSerifFamily: default: fontPlatformData = getCachedFontPlatformData(description, sansStr); break; } ASSERT(fontPlatformData); return fontPlatformData; }
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, serif, ("Serif")); DEFINE_STATIC_LOCAL(const AtomicString, monospace, ("Monospace")); DEFINE_STATIC_LOCAL(const AtomicString, sans, ("Sans")); FontPlatformData* fontPlatformData = 0; switch (description.genericFamily()) { case FontDescription::SerifFamily: fontPlatformData = getCachedFontPlatformData(description, serif); break; case FontDescription::MonospaceFamily: fontPlatformData = getCachedFontPlatformData(description, monospace); break; case FontDescription::SansSerifFamily: default: fontPlatformData = getCachedFontPlatformData(description, sans); break; } ASSERT(fontPlatformData); return getCachedFontData(fontPlatformData, shouldRetain); }
SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { // See the comments in the FontCache::getFontDataForCharacters. This function serves similar purpose. #if 1 return 0; #else const FontDescription& fontDescription(font.fontDescription()); const AtomicString& fontFamily(font.family().family()); FontPlatformData* platformData = getCachedFontPlatformData(font.fontDescription(), fontFamily, false); SimpleFontData* fontData = getCachedFontData(platformData); return fontData; #endif }
FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription, const AtomicString& passedFamilyName, bool checkingAlternateName) { #if PLATFORM(IOS) FontLocker fontLocker; #endif #if OS(WINDOWS) && ENABLE(OPENTYPE_VERTICAL) // Leading "@" in the font name enables Windows vertical flow flag for the font. // Because we do vertical flow by ourselves, we don't want to use the Windows feature. // IE disregards "@" regardless of the orientatoin, so we follow the behavior. const AtomicString& familyName = (passedFamilyName.isEmpty() || passedFamilyName[0] != '@') ? passedFamilyName : AtomicString(passedFamilyName.impl()->substring(1)); #else const AtomicString& familyName = passedFamilyName; #endif static bool initialized; if (!initialized) { platformInit(); initialized = true; } FontPlatformDataCacheKey key(familyName, fontDescription); auto addResult = fontPlatformDataCache().add(key, nullptr); FontPlatformDataCache::iterator it = addResult.iterator; if (addResult.isNewEntry) { it->value = createFontPlatformData(fontDescription, familyName); if (!it->value && !checkingAlternateName) { // We were unable to find a font. We have a small set of fonts that we alias to other names, // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name. const AtomicString alternateName = alternateFamilyName(familyName); if (!alternateName.isNull()) { FontPlatformData* fontPlatformDataForAlternateName = getCachedFontPlatformData(fontDescription, alternateName, true); // Lookup the key in the hash table again as the previous iterator may have // been invalidated by the recursive call to getCachedFontPlatformData(). it = fontPlatformDataCache().find(key); ASSERT(it != fontPlatformDataCache().end()); if (fontPlatformDataForAlternateName) it->value = std::make_unique<FontPlatformData>(*fontPlatformDataForAlternateName); } } } return it->value.get(); }
PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans")); DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif")); DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("Monospace")); FontPlatformData* fontPlatformData = 0; switch (description.genericFamily()) { case FontDescription::SerifFamily: fontPlatformData = getCachedFontPlatformData(description, serifStr); break; case FontDescription::MonospaceFamily: fontPlatformData = getCachedFontPlatformData(description, monospaceStr); break; case FontDescription::SansSerifFamily: default: fontPlatformData = getCachedFontPlatformData(description, sansStr); break; } if (!fontPlatformData) { DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial")); fontPlatformData = getCachedFontPlatformData(description, arialStr); }
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain) { // We do want this method to be enabled in case everything else fails and the application has loaded a fallback font. // As a last resort, we create the font out of the standard font specified by the application in the EA::WebKit::Parameters // when initializing the library. const EA::WebKit::Parameters& params = EA::WebKit::GetParameters(); const char16_t* type = params.mFontFamilyStandard; AtomicString fontFamily(type); FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, fontFamily, false); SimpleFontData* fontData = getCachedFontData(platformData); return fontData; }
const FontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { // IMLangFontLink::MapFont Method does what we want. IMLangFontLink2* langFontLink = getFontLinkInterface(); if (!langFontLink) return 0; FontData* fontData = 0; HDC hdc = GetDC(0); HFONT primaryFont = font.primaryFont()->m_font.hfont(); HGDIOBJ oldFont = SelectObject(hdc, primaryFont); HFONT hfont = 0; DWORD acpCodePages; langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); DWORD actualCodePages; long cchActual; langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &cchActual); if (cchActual) { HFONT result; if (langFontLink->MapFont(hdc, actualCodePages, characters[0], &result) == S_OK) { // Fill in a log font with the returned font from MLang, and then use that to create a new font. LOGFONT lf; GetObject(result, sizeof(LOGFONT), &lf); langFontLink->ReleaseFont(result); hfont = CreateFontIndirect(&lf); SelectObject(hdc, hfont); WCHAR name[LF_FACESIZE]; GetTextFace(hdc, LF_FACESIZE, name); String familyName(name); if (!familyName.isEmpty()) { FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName); if (result) fontData = getCachedFontData(result); } } } SelectObject(hdc, oldFont); if (hfont) DeleteObject(hfont); ReleaseDC(0, hdc); return fontData; }
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description) { FontDescription::GenericFamilyType generic = description.genericFamily(); // 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); }
FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName, bool checkingAlternateName) { NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeFontLoading, EA::WebKit::kVProcessStatusStarted); if (!gFontPlatformDataCache) { gFontPlatformDataCache = new FontPlatformDataCache; platformInit(); } FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(), fontDescription.usePrinterFont(), fontDescription.renderingMode()); FontPlatformData* result = 0; bool foundResult; FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key); if (it == gFontPlatformDataCache->end()) { result = createFontPlatformData(fontDescription, familyName); if(result) gFontPlatformDataCache->set(key, result); foundResult = result; } else { result = it->second; foundResult = true; } if (!foundResult && !checkingAlternateName) { // We were unable to find a font. We have a small set of fonts that we alias to other names, // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name. const AtomicString* pAlternateName = alternateFamilyName(familyName); if (!pAlternateName->isEmpty()) result = getCachedFontPlatformData(fontDescription, *pAlternateName, true); if (result) { gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name. } } NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeFontLoading, EA::WebKit::kVProcessStatusEnded); return result; }
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { FcCharSet* cset = FcCharSetCreate(); for (int i = 0; i < length; ++i) FcCharSetAddChar(cset, characters[i]); FcPattern* pattern = FcPatternCreate(); FcValue fcvalue; fcvalue.type = FcTypeCharSet; fcvalue.u.c = cset; FcPatternAdd(pattern, FC_CHARSET, fcvalue, 0); FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; FcPattern* match = FcFontMatch(0, pattern, &result); FcPatternDestroy(pattern); SimpleFontData* ret = 0; if (match) { FcChar8* family; if (FcPatternGetString(match, FC_FAMILY, 0, &family) == FcResultMatch) { AtomicString fontFamily(reinterpret_cast<char*>(family)); ret = getCachedFontData(getCachedFontPlatformData(font.fontDescription(), fontFamily, false)); } FcPatternDestroy(match); } FcCharSetDestroy(cset); return ret; }
PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { icu::Locale locale = icu::Locale::getDefault(); FontCache::SimpleFontFamily family; FontCache::getFontFamilyForCharacters(characters, length, locale.getLanguage(), font.fontDescription(), &family); if (family.name.isEmpty()) return 0; AtomicString atomicFamily(family.name); // Changes weight and/or italic of given FontDescription depends on // the result of fontconfig so that keeping the correct font mapping // of the given characters. See http://crbug.com/32109 for details. bool shouldSetFakeBold = false; bool shouldSetFakeItalic = false; FontDescription description(font.fontDescription()); if (family.isBold && description.weight() < FontWeightBold) description.setWeight(FontWeightBold); if (!family.isBold && description.weight() >= FontWeightBold) { shouldSetFakeBold = true; description.setWeight(FontWeightNormal); } if (family.isItalic && description.italic() == FontItalicOff) description.setItalic(FontItalicOn); if (!family.isItalic && description.italic() == FontItalicOn) { shouldSetFakeItalic = true; description.setItalic(FontItalicOff); } FontPlatformData* substitutePlatformData = getCachedFontPlatformData(description, atomicFamily, DoNotRetain); if (!substitutePlatformData) return 0; FontPlatformData platformData = FontPlatformData(*substitutePlatformData); platformData.setFakeBold(shouldSetFakeBold); platformData.setFakeItalic(shouldSetFakeItalic); return getCachedFontData(&platformData, DoNotRetain); }
FontPlatformData* FontCache::getCachedFallbackScriptFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { return getCachedFontPlatformData(fontDescription, family, true); }
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { String familyName; WCHAR name[LF_FACESIZE]; UChar character = characters[0]; const FontPlatformData& origFont = font.primaryFont()->fontDataForCharacter(character)->platformData(); unsigned unicodeRange = findCharUnicodeRange(character); #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) if (IMLangFontLink2* langFontLink = getFontLinkInterface()) { #else if (IMLangFontLink* langFontLink = getFontLinkInterface()) { #endif HGDIOBJ oldFont = GetCurrentObject(g_screenDC, OBJ_FONT); HFONT hfont = 0; DWORD codePages = 0; UINT codePage = 0; // Try MLang font linking first. langFontLink->GetCharCodePages(character, &codePages); if (codePages && unicodeRange == cRangeSetCJK) { // The CJK character may belong to multiple code pages. We want to // do font linking against a single one of them, preferring the default // code page for the user's locale. const Vector<DWORD, 4>& CJKCodePageMasks = getCJKCodePageMasks(); unsigned numCodePages = CJKCodePageMasks.size(); for (unsigned i = 0; i < numCodePages; ++i) { #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) hfont = createMLangFont(langFontLink, g_screenDC, CJKCodePageMasks[i]); #else hfont = createMLangFont(langFontLink, g_screenDC, origFont, CJKCodePageMasks[i]); #endif if (!hfont) continue; SelectObject(g_screenDC, hfont); GetTextFace(g_screenDC, LF_FACESIZE, name); if (hfont && !(codePages & CJKCodePageMasks[i])) { // We asked about a code page that is not one of the code pages // returned by MLang, so the font might not contain the character. #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) { #else if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) { #endif SelectObject(g_screenDC, oldFont); langFontLink->ReleaseFont(hfont); hfont = 0; continue; } } break; } } else { #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) hfont = createMLangFont(langFontLink, g_screenDC, codePages, character); #else hfont = createMLangFont(langFontLink, g_screenDC, origFont, codePages); #endif SelectObject(g_screenDC, hfont); GetTextFace(g_screenDC, LF_FACESIZE, name); } SelectObject(g_screenDC, oldFont); if (hfont) { familyName = name; langFontLink->ReleaseFont(hfont); } else FontPlatformData::mapKnownFont(codePages, familyName); } if (familyName.isEmpty()) familyName = FontPlatformData::defaultFontFamily(); if (!familyName.isEmpty()) { // FIXME: temporary workaround for Thai font problem FontDescription fontDescription(font.fontDescription()); if (unicodeRange == cRangeThai && fontDescription.weight() > FontWeightNormal) fontDescription.setWeight(FontWeightNormal); FontPlatformData* result = getCachedFontPlatformData(fontDescription, familyName); if (result && result->hash() != origFont.hash()) { if (SimpleFontData* fontData = getCachedFontData(result, DoNotRetain)) return fontData; } } return 0; }
// 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", // Six fonts below (and code2000 at the end) are not from MS, but // once installed, cover a very wide range of characters. L"dejavu serif", L"dejavu sasns", 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 = WTF_ARRAY_LENGTH(cjkFonts); } else { panUniFonts = commonFonts; numFonts = WTF_ARRAY_LENGTH(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, DoNotRetain); return 0; }
PassRefPtr<SimpleFontData> FontCache::systemFallbackForCharacters(const FontDescription& description, const SimpleFontData* originalFontData, bool, const UChar* characters, int length) { String familyName; WCHAR name[LF_FACESIZE]; UChar character = characters[0]; const FontPlatformData& origFont = originalFontData->platformData(); if (IMLangFontLinkType* langFontLink = getFontLinkInterface()) { HGDIOBJ oldFont = GetCurrentObject(g_screenDC, OBJ_FONT); HFONT hfont = 0; DWORD codePages = 0; UINT codePage = 0; // Try MLang font linking first. langFontLink->GetCharCodePages(character, &codePages); if (codePages && u_getIntPropertyValue(character, UCHAR_UNIFIED_IDEOGRAPH)) { // The CJK character may belong to multiple code pages. We want to // do font linking against a single one of them, preferring the default // code page for the user's locale. const Vector<DWORD, 4>& CJKCodePageMasks = getCJKCodePageMasks(); unsigned numCodePages = CJKCodePageMasks.size(); for (unsigned i = 0; i < numCodePages; ++i) { hfont = createMLangFont(langFontLink, g_screenDC, origFont, CJKCodePageMasks[i]); if (!hfont) continue; SelectObject(g_screenDC, hfont); GetTextFace(g_screenDC, LF_FACESIZE, name); if (hfont && !(codePages & CJKCodePageMasks[i])) { // We asked about a code page that is not one of the code pages // returned by MLang, so the font might not contain the character. if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) { SelectObject(g_screenDC, oldFont); langFontLink->ReleaseFont(hfont); hfont = 0; continue; } } break; } } else { hfont = createMLangFont(langFontLink, g_screenDC, origFont, codePages, character); SelectObject(g_screenDC, hfont); GetTextFace(g_screenDC, LF_FACESIZE, name); } SelectObject(g_screenDC, oldFont); if (hfont) { familyName = name; langFontLink->ReleaseFont(hfont); } else FontPlatformData::mapKnownFont(codePages, familyName); } if (familyName.isEmpty()) familyName = FontPlatformData::defaultFontFamily(); if (!familyName.isEmpty()) { // FIXME: temporary workaround for Thai font problem FontDescription fontDescription(description); if (ublock_getCode(c) == UBLOCK_THAI && fontDescription.weight() > FontWeightNormal) fontDescription.setWeight(FontWeightNormal); FontPlatformData* result = getCachedFontPlatformData(fontDescription, familyName); if (result && result->hash() != origFont.hash()) { if (RefPtr<SimpleFontData> fontData = getCachedFontData(result, DoNotRetain)) return fontData.release(); } } return 0; }
const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) { FontPlatformData* result = 0; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); for (int i = 0; startFamily && i < startIndex; i++) startFamily = startFamily->next(); const FontFamily* currFamily = startFamily; while (currFamily && !result) { familyIndex++; if (currFamily->family().length()) { if (fontSelector) { FontData* data = fontSelector->getFontData(font.fontDescription(), currFamily->family()); if (data) return data; } result = getCachedFontPlatformData(font.fontDescription(), currFamily->family()); } currFamily = currFamily->next(); } if (!currFamily) familyIndex = cAllFamiliesScanned; if (!result) { // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform. // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the // Geeza Pro font. //+ 4/27/09 CSidhall - The old code created a new fontPlatfromData here but left the pointer to leak. // We will use the exising font cache to store it in so that we can collect it. // There might be some risk if fontPlatformData gets added from another location with the same // key value. This would overwrite the mapped value, causing a leak. Have not seen this to occur in // however while testing several sites. // Original code: // result = getSimilarFontPlatformData(font); // New code: // Verify that we don't have one already in the cache (the familyIndex might have skipped this step) const FontDescription& fontDescription = font.fontDescription(); // Use first font family as default name for the key const AtomicString& familyName = font.fontDescription().family().family(); result = getCachedFontPlatformData(fontDescription, familyName); if(!result) { // No default font was found so should be safe to add to key location result = getSimilarFontPlatformData(font); FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(), fontDescription.usePrinterFont(), fontDescription.renderingMode()); gFontPlatformDataCache->set(key,result); } //- CS } if (!result && startIndex == 0) { // If it's the primary font that we couldn't find, we try the following. In all other cases, we will // just use per-character system fallback. if (fontSelector) { // Try the user's preferred standard font. if (FontData* data = fontSelector->getFontData(font.fontDescription(), "-webkit-standard")) return data; } // Still no result. Hand back our last resort fallback font. result = getLastResortFallbackFont(font.fontDescription()); } // Now that we have a result, we need to go from FontPlatformData -> FontData. return getCachedFontData(result); }
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& font) { static AtomicString str("sans-serif"); return getCachedFontPlatformData(font, str); }