10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* Copyright (C) 2007-2009 Torch Mobile, Inc.
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*
50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* Redistribution and use in source and binary forms, with or without
60bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* modification, are permitted provided that the following conditions
70bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* are met:
80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* 1.  Redistributions of source code must retain the above copyright
100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*     notice, this list of conditions and the following disclaimer.
110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* 2.  Redistributions in binary form must reproduce the above copyright
120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*     notice, this list of conditions and the following disclaimer in the
130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*     documentation and/or other materials provided with the distribution.
140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*     its contributors may be used to endorse or promote products derived
160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*     from this software without specific prior written permission.
170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*
180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch*/
290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h"
310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FontCache.h"
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "Font.h"
340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FontData.h"
350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SimpleFontData.h"
360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "UnicodeRange.h"
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "wtf/OwnPtr.h"
380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <windows.h>
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <mlang.h>
410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochnamespace WebCore {
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochextern HDC g_screenDC;
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic IMultiLanguage *multiLanguage = 0;
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic IMLangFontLink2* langFontLink = 0;
500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic IMLangFontLink* langFontLink = 0;
520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenIMultiLanguage* FontCache::getMultiLanguageInterface()
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!multiLanguage)
570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, (void**)&multiLanguage);
580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return multiLanguage;
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochIMLangFontLink2* FontCache::getFontLinkInterface()
640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochIMLangFontLink* FontCache::getFontLinkInterface()
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!langFontLink) {
690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (IMultiLanguage* mli = getMultiLanguageInterface())
700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            mli->QueryInterface(&langFontLink);
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return langFontLink;
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool currentFontContainsCharacter(IMLangFontLink2* langFontLink, HDC hdc, UChar character)
780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    UINT unicodeRanges;
800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (S_OK != langFontLink->GetFontUnicodeRanges(hdc, &unicodeRanges, 0))
810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static Vector<UNICODERANGE, 64> glyphsetBuffer;
840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    glyphsetBuffer.resize(unicodeRanges);
850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (S_OK != langFontLink->GetFontUnicodeRanges(hdc, &unicodeRanges, glyphsetBuffer.data()))
870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // FIXME: Change this to a binary search. (Yong Li: That's easy. But, is it guaranteed that the ranges are sorted?)
900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    for (Vector<UNICODERANGE, 64>::const_iterator i = glyphsetBuffer.begin(); i != glyphsetBuffer.end(); ++i) {
910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (i->wcTo >= character)
920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return i->wcFrom <= character;
930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return false;
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool currentFontContainsCharacter(IMLangFontLink* langFontLink, HDC hdc, HFONT hfont, UChar character, const wchar_t* faceName)
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD fontCodePages = 0, charCodePages = 0;
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HRESULT result = langFontLink->GetFontCodePages(hdc, hfont, &fontCodePages);
1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (result != S_OK)
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    result = langFontLink->GetCharCodePages(character, &charCodePages);
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (result != S_OK)
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    fontCodePages |= FontPlatformData::getKnownFontCodePages(faceName);
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (fontCodePages & charCodePages)
1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return false;
1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codePageMask, UChar character = 0)
1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HFONT mlangFont;
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (SUCCEEDED(langFontLink->MapFont(hdc, codePageMask, character, &mlangFont)))
1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return mlangFont;
1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 0;
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic HFONT createMLangFont(IMLangFontLink* langFontLink, HDC hdc, const FontPlatformData& refFont, DWORD codePageMask)
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HFONT mlangFont;
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LRESULT result = langFontLink->MapFont(hdc, codePageMask, refFont.hfont(), &mlangFont);
1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return result == S_OK ? mlangFont : 0;
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const Vector<DWORD, 4>& getCJKCodePageMasks()
1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // The default order in which we look for a font for a CJK character. If the user's default code page is
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // one of these, we will use it first.
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static const UINT CJKCodePages[] = {
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        932, /* Japanese */
1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        936, /* Simplified Chinese */
1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        950, /* Traditional Chinese */
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        949  /* Korean */
1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    };
1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static Vector<DWORD, 4> codePageMasks;
1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static bool initialized;
1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!initialized) {
1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        initialized = true;
1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface();
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!langFontLink)
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return codePageMasks;
1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        UINT defaultCodePage;
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        DWORD defaultCodePageMask = 0;
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE, reinterpret_cast<LPWSTR>(&defaultCodePage), sizeof(defaultCodePage)))
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            langFontLink->CodePageToCodePages(defaultCodePage, &defaultCodePageMask);
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (defaultCodePage == CJKCodePages[0] || defaultCodePage == CJKCodePages[1] || defaultCodePage == CJKCodePages[2] || defaultCodePage == CJKCodePages[3])
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            codePageMasks.append(defaultCodePageMask);
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (unsigned i = 0; i < 4; ++i) {
1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (defaultCodePage != CJKCodePages[i]) {
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                DWORD codePageMask;
1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                langFontLink->CodePageToCodePages(CJKCodePages[i], &codePageMask);
1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                codePageMasks.append(codePageMask);
1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return codePageMasks;
1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstruct TraitsInFamilyProcData {
1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    TraitsInFamilyProcData(const AtomicString& familyName)
1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        : m_familyName(familyName)
1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    const AtomicString& m_familyName;
1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HashSet<unsigned> m_traitsMasks;
1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    unsigned traitsMask = 0;
1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    traitsMask |= FontVariantNormalMask;
1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LONG weight = FontPlatformData::adjustedGDIFontWeight(logFont->lfWeight, procData->m_familyName);
1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    traitsMask |= weight == FW_THIN ? FontWeight100Mask :
1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_EXTRALIGHT ? FontWeight200Mask :
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_LIGHT ? FontWeight300Mask :
1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_NORMAL ? FontWeight400Mask :
1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_MEDIUM ? FontWeight500Mask :
2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_SEMIBOLD ? FontWeight600Mask :
2010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_BOLD ? FontWeight700Mask :
2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        weight == FW_EXTRABOLD ? FontWeight800Mask :
2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                 FontWeight900Mask;
2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    procData->m_traitsMasks.add(traitsMask);
2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 1;
2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid FontCache::platformInit()
2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid FontCache::comInitialize()
2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid FontCache::comUninitialize()
2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (langFontLink) {
2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        langFontLink->Release();
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        langFontLink = 0;
2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (multiLanguage) {
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        multiLanguage->Release();
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        multiLanguage = 0;
2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochconst SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    String familyName;
2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    WCHAR name[LF_FACESIZE];
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    UChar character = characters[0];
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    const FontPlatformData& origFont = font.primaryFont()->fontDataForCharacter(character)->platformData();
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    unsigned unicodeRange = findCharUnicodeRange(character);
2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (IMLangFontLink2* langFontLink = getFontLinkInterface()) {
2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (IMLangFontLink* langFontLink = getFontLinkInterface()) {
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        HGDIOBJ oldFont = GetCurrentObject(g_screenDC, OBJ_FONT);
2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        HFONT hfont = 0;
2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        DWORD codePages = 0;
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        UINT codePage = 0;
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Try MLang font linking first.
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        langFontLink->GetCharCodePages(character, &codePages);
2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (codePages && unicodeRange == cRangeSetCJK) {
2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // The CJK character may belong to multiple code pages. We want to
2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // do font linking against a single one of them, preferring the default
2510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // code page for the user's locale.
2520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const Vector<DWORD, 4>& CJKCodePageMasks = getCJKCodePageMasks();
2530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            unsigned numCodePages = CJKCodePageMasks.size();
2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            for (unsigned i = 0; i < numCodePages; ++i) {
2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                hfont = createMLangFont(langFontLink, g_screenDC, CJKCodePageMasks[i]);
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                hfont = createMLangFont(langFontLink, g_screenDC, origFont, CJKCodePageMasks[i]);
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (!hfont)
2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    continue;
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                SelectObject(g_screenDC, hfont);
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                GetTextFace(g_screenDC, LF_FACESIZE, name);
2650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (hfont && !(codePages & CJKCodePageMasks[i])) {
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    // We asked about a code page that is not one of the code pages
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    // returned by MLang, so the font might not contain the character.
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) {
2710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
2720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) {
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        SelectObject(g_screenDC, oldFont);
2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        langFontLink->ReleaseFont(hfont);
2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        hfont = 0;
2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        continue;
2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    }
2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                }
2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                break;
2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
2820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else {
2830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            hfont = createMLangFont(langFontLink, g_screenDC, codePages, character);
2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            hfont = createMLangFont(langFontLink, g_screenDC, origFont, codePages);
2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            SelectObject(g_screenDC, hfont);
2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            GetTextFace(g_screenDC, LF_FACESIZE, name);
2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        SelectObject(g_screenDC, oldFont);
2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (hfont) {
2940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            familyName = name;
2950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            langFontLink->ReleaseFont(hfont);
2960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else
2970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            FontPlatformData::mapKnownFont(codePages, familyName);
2980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (familyName.isEmpty())
3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        familyName = FontPlatformData::defaultFontFamily();
3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!familyName.isEmpty()) {
3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // FIXME: temporary workaround for Thai font problem
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        FontDescription fontDescription(font.fontDescription());
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (unicodeRange == cRangeThai && fontDescription.weight() > FontWeightNormal)
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            fontDescription.setWeight(FontWeightNormal);
3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        FontPlatformData* result = getCachedFontPlatformData(fontDescription, familyName);
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (result && result->hash() != origFont.hash()) {
3110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (SimpleFontData* fontData = getCachedFontData(result))
3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return fontData;
3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 0;
3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockSimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return 0;
3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockSimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc)
3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // FIXME: Would be even better to somehow get the user's default font here.  For now we'll pick
3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // the default that the user would get without changing any prefs.
3288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return getCachedFontData(fontDesc, FontPlatformData::defaultFontFamily());
3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochFontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    FontPlatformData* result = new FontPlatformData(fontDescription, family);
3340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return result;
3350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
3380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LOGFONT logFont;
3400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    logFont.lfCharSet = DEFAULT_CHARSET;
3410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    unsigned familyLength = std::min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
3420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
3430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    logFont.lfFaceName[familyLength] = 0;
3440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    logFont.lfPitchAndFamily = 0;
3450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    TraitsInFamilyProcData procData(familyName);
3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    EnumFontFamiliesEx(g_screenDC, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
3480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    copyToVector(procData.m_traitsMasks, traitsMasks);
3490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
35168513a70bcd92384395513322f1b801e7bf9c729Steve Block} // namespace WebCore
352