Exemplo n.º 1
0
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
{
    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;

    SimpleFontData* simpleFont = getCachedFontData(description, fontStr, false, shouldRetain);
    if (simpleFont)
        return simpleFont;

    // Fall back to system fonts as Win Safari does because this function must
    // return a valid font. Once we find a valid system font, we save its name
    // to a static variable and use it to prevent trying system fonts again.
    static wchar_t fallbackFontName[LF_FACESIZE] = {0};
    if (fallbackFontName[0])
        return getCachedFontData(description, fallbackFontName, false, shouldRetain);

    // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
    if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
        LOGFONT defaultGUILogFont;
        GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, defaultGUILogFont, fallbackFontName))
            return simpleFont;
    }

    // Fall back to Non-client metrics fonts.
    NONCLIENTMETRICS nonClientMetrics = {0};
    nonClientMetrics.cbSize = sizeof(nonClientMetrics);
    if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName))
            return simpleFont;
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName))
            return simpleFont;
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName))
            return simpleFont;
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName))
            return simpleFont;
        if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
            return simpleFont;
    }

    // Fall back to all the fonts installed in this PC. When a font has a
    // localized name according to the system locale as well as an English name,
    // both GetTextFace() and EnumFontFamilies() return the localized name. So,
    // FontCache::createFontPlatformData() does not filter out the fonts
    // returned by this EnumFontFamilies() call.
    HDC dc = GetDC(0);
    if (dc) {
        GetLastResortFallbackFontProcData procData(this, &description, shouldRetain, fallbackFontName);
        EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));
        ReleaseDC(0, dc);

        if (procData.m_fontData)
            return procData.m_fontData;
    }

    ASSERT_NOT_REACHED();
    return 0;
}
static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
{
    GetLastResortFallbackFontProcData* procData = reinterpret_cast<GetLastResortFallbackFontProcData*>(lParam);
    procData->m_fontData = fontDataFromDescriptionAndLogFont(procData->m_fontCache, *procData->m_fontDescription, *logFont, procData->m_fontName);
    return !procData->m_fontData;
}