Ejemplo n.º 1
0
PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDesc, ShouldRetain shouldRetain)
{
    // 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.
    return getCachedFontData(fontDesc, FontPlatformData::defaultFontFamily(), false, shouldRetain);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
    const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFamily();
    return getCachedFontData(new FontPlatformData(fontDescription, fallbackFamily));
}
Ejemplo n.º 5
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",
        // 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;

}
Ejemplo n.º 6
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.
    HWndDC dc(0);
    if (dc) {
        GetLastResortFallbackFontProcData procData(this, &description, shouldRetain, fallbackFontName);
        EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData));

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

    ASSERT_NOT_REACHED();
    return 0;
}
Ejemplo n.º 7
0
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))
                return fontData;
        }
    }

    return 0;
}