2009-07-21 Yong Li <yong.li@torchmobile.com>
authortreat@webkit.org <treat@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Jul 2009 22:42:21 +0000 (22:42 +0000)
committertreat@webkit.org <treat@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Jul 2009 22:42:21 +0000 (22:42 +0000)
        Reviewed by George Staikos.

        https://bugs.webkit.org/show_bug.cgi?id=27509
        Add font-related files for the WinCE port.

        Written by Yong Li <yong.li@torchmobile.com>

        * platform/graphics/wince/FontCacheWince.cpp: Added.
        * platform/graphics/wince/FontCustomPlatformData.cpp: Added.
        * platform/graphics/wince/FontCustomPlatformData.h: Added.
        * platform/graphics/wince/FontPlatformData.cpp: Added.
        * platform/graphics/wince/FontPlatformData.h: Added.
        * platform/graphics/wince/FontWince.cpp: Added.
        * platform/graphics/wince/GlyphPageTreeNodeWince.cpp: Added.
        * platform/graphics/wince/SimpleFontDataWince.cpp: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@46196 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/graphics/wince/FontCacheWince.cpp [new file with mode: 0644]
WebCore/platform/graphics/wince/FontCustomPlatformData.cpp [new file with mode: 0644]
WebCore/platform/graphics/wince/FontCustomPlatformData.h [new file with mode: 0644]
WebCore/platform/graphics/wince/FontPlatformData.cpp [new file with mode: 0644]
WebCore/platform/graphics/wince/FontPlatformData.h [new file with mode: 0644]
WebCore/platform/graphics/wince/FontWince.cpp [new file with mode: 0644]
WebCore/platform/graphics/wince/GlyphPageTreeNodeWince.cpp [new file with mode: 0644]
WebCore/platform/graphics/wince/SimpleFontDataWince.cpp [new file with mode: 0644]

index 0da4c3c..12691a7 100644 (file)
@@ -1,3 +1,21 @@
+2009-07-21  Yong Li  <yong.li@torchmobile.com>
+
+        Reviewed by George Staikos.
+
+        https://bugs.webkit.org/show_bug.cgi?id=27509
+        Add font-related files for the WinCE port.
+
+        Written by Yong Li <yong.li@torchmobile.com>
+
+        * platform/graphics/wince/FontCacheWince.cpp: Added.
+        * platform/graphics/wince/FontCustomPlatformData.cpp: Added.
+        * platform/graphics/wince/FontCustomPlatformData.h: Added.
+        * platform/graphics/wince/FontPlatformData.cpp: Added.
+        * platform/graphics/wince/FontPlatformData.h: Added.
+        * platform/graphics/wince/FontWince.cpp: Added.
+        * platform/graphics/wince/GlyphPageTreeNodeWince.cpp: Added.
+        * platform/graphics/wince/SimpleFontDataWince.cpp: Added.
+
 2009-07-21  Kevin Ollivier  <kevino@theolliviers.com>
 
         Fix the Windows build, and update the comment on top now that wx uses WebCorePrefix.h too.
diff --git a/WebCore/platform/graphics/wince/FontCacheWince.cpp b/WebCore/platform/graphics/wince/FontCacheWince.cpp
new file mode 100644 (file)
index 0000000..f67f1b4
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+* Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
+* Copyright (C) 2007-2009 Torch Mobile, Inc.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1.  Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer. 
+* 2.  Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in the
+*     documentation and/or other materials provided with the distribution. 
+* 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+*     its contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission. 
+*
+* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+#include "FontCache.h"
+
+#include "Font.h"
+#include "FontData.h"
+#include "SimpleFontData.h"
+#include "UnicodeRange.h"
+#include "wtf/OwnPtr.h"
+
+#include <windows.h>
+#include <mlang.h>
+
+namespace WebCore {
+
+extern HDC g_screenDC;
+
+static IMultiLanguage *multiLanguage = 0;
+
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+static IMLangFontLink2* langFontLink = 0;
+#else
+static IMLangFontLink* langFontLink = 0;
+#endif
+
+IMultiLanguage* getMultiLanguageInterface()
+{
+    if (!multiLanguage)
+        CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, (void**)&multiLanguage);
+
+    return multiLanguage;
+}
+
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+IMLangFontLink2* FontCache::getFontLinkInterface()
+#else
+IMLangFontLink* FontCache::getFontLinkInterface()
+#endif
+{
+    if (!langFontLink) {
+        if (IMultiLanguage* mli = getMultiLanguageInterface())
+            mli->QueryInterface(&langFontLink);
+    }
+
+    return langFontLink;
+}
+
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+static bool currentFontContainsCharacter(IMLangFontLink2* langFontLink, HDC hdc, UChar character)
+{
+    UINT unicodeRanges;
+    if (S_OK != langFontLink->GetFontUnicodeRanges(hdc, &unicodeRanges, 0))
+        return false;
+
+    static Vector<UNICODERANGE, 64> glyphsetBuffer;
+    glyphsetBuffer.resize(unicodeRanges);
+
+    if (S_OK != langFontLink->GetFontUnicodeRanges(hdc, &unicodeRanges, glyphsetBuffer.data()))
+        return false;
+
+    // FIXME: Change this to a binary search. (Yong Li: That's easy. But, is it guaranteed that the ranges are sorted?)
+    for (Vector<UNICODERANGE, 64>::const_iterator i = glyphsetBuffer.begin(); i != glyphsetBuffer.end(); ++i) {
+        if (i->wcTo >= character)
+            return i->wcFrom <= character;
+    }
+
+    return false;
+}
+#else
+static bool currentFontContainsCharacter(IMLangFontLink* langFontLink, HDC hdc, HFONT hfont, UChar character, const wchar_t* faceName)
+{
+    DWORD fontCodePages = 0, charCodePages = 0;
+    HRESULT result = langFontLink->GetFontCodePages(hdc, hfont, &fontCodePages);
+    if (result != S_OK)
+        return false;
+    result = langFontLink->GetCharCodePages(character, &charCodePages);
+    if (result != S_OK)
+        return false;
+
+    fontCodePages |= FontPlatformData::getKnownFontCodePages(faceName);
+    if (fontCodePages & charCodePages)
+        return true;
+
+    return false;
+}
+#endif
+
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+static HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codePageMask, UChar character = 0)
+{
+    HFONT mlangFont;
+    if (SUCCEEDED(langFontLink->MapFont(hdc, codePageMask, character, &mlangFont)))
+        return mlangFont;
+
+    return 0;
+}
+#else
+static HFONT createMLangFont(IMLangFontLink* langFontLink, HDC hdc, const FontPlatformData& refFont, DWORD codePageMask)
+{
+    HFONT mlangFont;
+    LRESULT result = langFontLink->MapFont(hdc, codePageMask, refFont.hfont(), &mlangFont);
+
+    return result == S_OK ? mlangFont : 0;
+}
+#endif
+
+static const Vector<DWORD, 4>& getCJKCodePageMasks()
+{
+    // The default order in which we look for a font for a CJK character. If the user's default code page is
+    // one of these, we will use it first.
+    static const UINT CJKCodePages[] = {
+        932, /* Japanese */
+        936, /* Simplified Chinese */
+        950, /* Traditional Chinese */
+        949  /* Korean */
+    };
+
+    static Vector<DWORD, 4> codePageMasks;
+    static bool initialized;
+    if (!initialized) {
+        initialized = true;
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+        IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
+#else
+        IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface();
+#endif
+        if (!langFontLink)
+            return codePageMasks;
+
+        UINT defaultCodePage;
+        DWORD defaultCodePageMask = 0;
+        if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE, reinterpret_cast<LPWSTR>(&defaultCodePage), sizeof(defaultCodePage)))
+            langFontLink->CodePageToCodePages(defaultCodePage, &defaultCodePageMask);
+
+        if (defaultCodePage == CJKCodePages[0] || defaultCodePage == CJKCodePages[1] || defaultCodePage == CJKCodePages[2] || defaultCodePage == CJKCodePages[3])
+            codePageMasks.append(defaultCodePageMask);
+        for (unsigned i = 0; i < 4; ++i) {
+            if (defaultCodePage != CJKCodePages[i]) {
+                DWORD codePageMask;
+                langFontLink->CodePageToCodePages(CJKCodePages[i], &codePageMask);
+                codePageMasks.append(codePageMask);
+            }
+        }
+    }
+    return codePageMasks;
+}
+
+
+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 = FontPlatformData::adjustedGDIFontWeight(logFont->lfWeight, procData->m_familyName);
+    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::platformInit()
+{
+}
+
+void FontCache::comInitialize()
+{
+}
+
+void FontCache::comUninitialize()
+{
+    if (langFontLink) {
+        langFontLink->Release();
+        langFontLink = 0;
+    }
+    if (multiLanguage) {
+        multiLanguage->Release();
+        multiLanguage = 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;
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+    return 0;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc)
+{
+    // 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 getCachedFontPlatformData(fontDesc, FontPlatformData::defaultFontFamily());
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+    FontPlatformData* result = new FontPlatformData(fontDescription, family);
+    return result;
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+{
+    LOGFONT logFont;
+    logFont.lfCharSet = DEFAULT_CHARSET;
+    unsigned familyLength = std::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(g_screenDC, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
+    copyToVector(procData.m_traitsMasks, traitsMasks);
+}
+
+}
+
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
new file mode 100644 (file)
index 0000000..7c6853c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontCustomPlatformData.h"
+
+#include "Base64.h"
+#include "CachedFont.h"
+#include "FontPlatformData.h"
+#include <wtf/RandomNumber.h>
+
+namespace WebCore {
+
+static CustomFontCache* g_customFontCache = 0;
+
+bool renameFont(SharedBuffer* fontData, const String& fontName);
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+    if (g_customFontCache && !m_name.isEmpty())
+        g_customFontCache->unregisterFont(m_name);
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode renderingMode)
+{
+    FontDescription fontDesc;
+    fontDesc.setComputedSize(size);
+    fontDesc.setSpecifiedSize(size);
+    fontDesc.setItalic(italic);
+    fontDesc.setWeight(bold ? FontWeightBold : FontWeightNormal);
+    return FontPlatformData(fontDesc, m_name, false);
+}
+
+// Creates a unique and unpredictable font name, in order to avoid collisions and to
+// not allow access from CSS.
+static String createUniqueFontName()
+{
+    Vector<char> fontUuid(sizeof(GUID));
+
+    unsigned int* ptr = reinterpret_cast<unsigned int*>(fontUuid.data());
+    for (int i = 0; i < sizeof(GUID) / sizeof(int) ; ++i)
+        *(ptr + i) = static_cast<unsigned int>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0));
+
+    Vector<char> fontNameVector;
+    base64Encode(fontUuid, fontNameVector);
+    ASSERT(fontNameVector.size() < LF_FACESIZE);
+    String fontName(fontNameVector.data(), fontNameVector.size());
+    return fontName.replace('/', '_');
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(CachedFont* cachedFont)
+{
+    if (g_customFontCache && cachedFont->CachedResource::data()) {
+        String fontName = createUniqueFontName();
+        if (renameFont(cachedFont->CachedResource::data(), fontName) && g_customFontCache->registerFont(fontName, cachedFont))
+            return new FontCustomPlatformData(fontName);
+    }
+    return 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/WebCore/platform/graphics/wince/FontCustomPlatformData.h
new file mode 100644 (file)
index 0000000..b1f64a0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include "FontRenderingMode.h"
+#include "PlatformString.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+    class FontPlatformData;
+    class CachedFont;
+
+    class CustomFontCache {
+    public:
+        virtual bool registerFont(const String& fontName, CachedFont*) = 0;
+        virtual void unregisterFont(const String& fontName) = 0;
+    };
+
+    struct FontCustomPlatformData : Noncopyable {
+        FontCustomPlatformData(const String& name)
+            : m_name(name)
+        {
+        }
+
+        ~FontCustomPlatformData();
+
+        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
+        String m_name;
+    };
+
+    FontCustomPlatformData* createFontCustomPlatformData(CachedFont*);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/wince/FontPlatformData.cpp b/WebCore/platform/graphics/wince/FontPlatformData.cpp
new file mode 100644 (file)
index 0000000..acaad2d
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ *  Copyright (C) 2007-2009 Torch Mobile Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+#include "Font.h"
+#include "FontCache.h"
+#include "FontData.h"
+#include "SimpleFontData.h"
+#include "UnicodeRange.h"
+#include "wtf/OwnPtr.h"
+
+#include <windows.h>
+#include <mlang.h>
+
+namespace WebCore {
+
+extern HDC g_screenDC;
+
+static wchar_t songTiStr[] = { 0x5b8b, 0x4f53, 0 };
+static wchar_t heiTiStr[] = { 0x9ed1, 0x4f53, 0 };
+
+class FontFamilyCodePageInfo {
+public:
+    FontFamilyCodePageInfo()
+        : m_codePage(0), m_codePages(0)
+    {
+    }
+    FontFamilyCodePageInfo(const wchar_t* family, UINT codePage)
+        : m_family(family), m_codePage(codePage), m_codePages(0)
+    {
+    }
+    DWORD codePages() const
+    {
+        if (!m_codePages) {
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+            if (IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface())
+                langFontLink->CodePageToCodePages(m_codePage, &m_codePages);
+#else
+            if (IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface())
+                langFontLink->CodePageToCodePages(m_codePage, &m_codePages);
+#endif
+        }
+        return m_codePages;
+    }
+
+    String m_family;
+    UINT m_codePage;
+private:
+    mutable DWORD m_codePages;
+};
+
+class FontFamilyChecker {
+public:
+    FontFamilyChecker(const wchar_t* family)
+        : m_exists(false)
+    {
+        EnumFontFamilies(g_screenDC, family, enumFontFamProc, (LPARAM)this);
+    }
+    bool isSupported() const { return m_exists; }
+private:
+    bool m_exists;
+    static int CALLBACK enumFontFamProc(const LOGFONT FAR* lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam);
+};
+
+class ValidFontFamilyFinder {
+public:
+    ValidFontFamilyFinder()
+    {
+        EnumFontFamilies(g_screenDC, 0, enumFontFamProc, (LPARAM)this);
+    }
+    const String& family() const { return m_family; }
+private:
+    String m_family;
+    static int CALLBACK enumFontFamProc(const LOGFONT FAR* lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam);
+};
+
+class FixedSizeFontData: public RefCounted<FixedSizeFontData> {
+public:
+    LOGFONT m_font;
+    OwnPtr<HFONT> m_hfont;
+    TEXTMETRIC m_metrics;
+    DWORD m_codePages;
+    unsigned m_weight;
+    bool m_italic;
+
+    static PassRefPtr<FixedSizeFontData> create(const AtomicString& family, unsigned weight, bool italic);
+private:
+    FixedSizeFontData()
+        : m_codePages(0)
+        , m_weight(0)
+        , m_italic(false)
+    {
+        memset(&m_font, 0, sizeof(m_font));
+        memset(&m_metrics, 0, sizeof(m_metrics));
+    }
+};
+
+struct FixedSizeFontDataKey {
+    FixedSizeFontDataKey(const AtomicString& family = AtomicString(), unsigned weight = 0, bool italic = false)
+        : m_family(family)
+        , m_weight(weight)
+        , m_italic(italic)
+    {
+    }
+
+    FixedSizeFontDataKey(WTF::HashTableDeletedValueType) : m_weight(-2) { }
+    bool isHashTableDeletedValue() const { return m_weight == -2; }
+
+    bool operator==(const FixedSizeFontDataKey& other) const
+    {
+        return equalIgnoringCase(m_family, other.m_family)
+            && m_weight == other.m_weight
+            && m_italic == other.m_italic;
+    }
+
+    AtomicString m_family;
+    unsigned m_weight;
+    bool m_italic;
+};
+
+struct FixedSizeFontDataKeyHash {
+    static unsigned hash(const FixedSizeFontDataKey& font)
+    {
+        unsigned hashCodes[] = {
+            CaseFoldingHash::hash(font.m_family),
+            font.m_weight,
+            // static_cast<unsigned>(font.m_italic);
+        };
+        return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+    }
+
+    static bool equal(const FixedSizeFontDataKey& a, const FixedSizeFontDataKey& b)
+    {
+        return a == b;
+    }
+
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct FixedSizeFontDataKeyTraits : WTF::GenericHashTraits<FixedSizeFontDataKey> {
+    static const bool emptyValueIsZero = true;
+    static const FixedSizeFontDataKey& emptyValue()
+    {
+        DEFINE_STATIC_LOCAL(FixedSizeFontDataKey, key, (nullAtom));
+        return key;
+    }
+    static void constructDeletedValue(FixedSizeFontDataKey& slot)
+    {
+        new (&slot) FixedSizeFontDataKey(WTF::HashTableDeletedValue);
+    }
+    static bool isDeletedValue(const FixedSizeFontDataKey& value)
+    {
+        return value.isHashTableDeletedValue();
+    }
+};
+
+int CALLBACK FontFamilyChecker::enumFontFamProc(const LOGFONT FAR* lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam)
+{
+    ((FontFamilyChecker*)lParam)->m_exists = true;
+    return 0;
+}
+
+int CALLBACK ValidFontFamilyFinder::enumFontFamProc(const LOGFONT FAR* lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam)
+{
+    if (lpelf->lfCharSet != SYMBOL_CHARSET) {
+        ((ValidFontFamilyFinder*)lParam)->m_family = String(lpelf->lfFaceName);
+        return 0;
+    }
+    return 1;
+}
+
+typedef Vector<FontFamilyCodePageInfo> KnownFonts;
+static KnownFonts& knownFonts()
+{
+    static KnownFonts fonts;
+    static bool firstTime = true;
+    if (firstTime) {
+        firstTime = false;
+        if (FontPlatformData::isSongTiSupported())
+            fonts.append(FontFamilyCodePageInfo(songTiStr, 936));
+    }
+    return fonts;
+}
+
+static String getDefaultFontFamily()
+{
+    if (FontFamilyChecker(L"Tahoma").isSupported())
+        return String(L"Tahoma");
+
+    bool good = false;
+    String family;
+    HKEY key;
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\GDI\\SysFnt", 0, 0, &key) == ERROR_SUCCESS) {
+        DWORD maxlen, type;
+        if (RegQueryValueEx(key, L"Nm", 0, &type, 0, &maxlen) == ERROR_SUCCESS && type == REG_SZ) {
+            ++maxlen;
+            if (wchar_t* buffer = new wchar_t[maxlen]) {
+                if (RegQueryValueEx(key, L"Nm", 0, &type, (LPBYTE)buffer, &maxlen) == ERROR_SUCCESS) {
+                    family = String(buffer, maxlen);
+                    good = true;
+                }
+                delete[] buffer;
+            }
+        }
+        RegCloseKey(key);
+    }
+    if (good)
+        return family;
+
+    return ValidFontFamilyFinder().family();
+}
+
+typedef HashMap<FixedSizeFontDataKey, RefPtr<FixedSizeFontData>, FixedSizeFontDataKeyHash, FixedSizeFontDataKeyTraits> FixedSizeFontCache;
+FixedSizeFontCache g_fixedSizeFontCache;
+
+PassRefPtr<FixedSizeFontData> FixedSizeFontData::create(const AtomicString& family, unsigned weight, bool italic)
+{
+    FixedSizeFontData* fontData = new FixedSizeFontData();
+
+    fontData->m_weight = weight;
+    fontData->m_italic = italic;
+
+    LOGFONT& winFont = fontData->m_font;
+    // The size here looks unusual.  The negative number is intentional.
+    winFont.lfHeight = -72;
+    winFont.lfWidth = 0;
+    winFont.lfEscapement = 0;
+    winFont.lfOrientation = 0;
+    winFont.lfUnderline = false;
+    winFont.lfStrikeOut = false;
+    winFont.lfCharSet = DEFAULT_CHARSET;
+    winFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+    winFont.lfQuality = CLEARTYPE_QUALITY; //DEFAULT_QUALITY;
+    winFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+    winFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+    winFont.lfItalic = italic;
+    winFont.lfWeight = FontPlatformData::adjustedGDIFontWeight(weight, family);
+
+    int len = std::min(family.length(), (unsigned int)LF_FACESIZE - 1);
+    wmemcpy(winFont.lfFaceName, family.characters(), len);
+    winFont.lfFaceName[len] = L'\0';
+
+    fontData->m_hfont.set(CreateFontIndirect(&winFont));
+
+    HGDIOBJ oldFont = SelectObject(g_screenDC, fontData->m_hfont.get());
+
+    GetTextMetrics(g_screenDC, &fontData->m_metrics);
+
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+    if (IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface()) {
+#else
+    if (IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface()) {
+#endif
+        langFontLink->GetFontCodePages(g_screenDC, fontData->m_hfont.get(), &fontData->m_codePages);
+        fontData->m_codePages |= FontPlatformData::getKnownFontCodePages(winFont.lfFaceName);
+    }
+
+    SelectObject(g_screenDC, oldFont);
+
+    return adoptRef(fontData);
+}
+
+static PassRefPtr<FixedSizeFontData> createFixedSizeFontData(const AtomicString& family, unsigned weight, bool italic)
+{
+    FixedSizeFontDataKey key(family, weight, italic);
+    pair<FixedSizeFontCache::iterator, bool> result = g_fixedSizeFontCache.add(key, RefPtr<FixedSizeFontData>());
+    if (result.second)
+        result.first->second = FixedSizeFontData::create(family, weight, italic);
+
+    return result.first->second;
+}
+
+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];
+}
+
+class FontPlatformPrivateData {
+public:
+    int m_reference;
+    RefPtr<FixedSizeFontData> m_rootFontData;
+    AtomicString m_family;
+    FontDescription m_fontDescription;
+    OwnPtr<HFONT> m_hfontScaled;
+    int m_size;
+    long m_fontScaledWidth;
+    long m_fontScaledHeight;
+    bool m_disabled;
+    FontPlatformPrivateData(int size, unsigned weight)
+        : m_reference(1)
+        , m_family(FontPlatformData::defaultFontFamily())
+        , m_size(size)
+        , m_fontScaledWidth(0)
+        , m_fontScaledHeight(0)
+        , m_disabled(false)
+    {
+        m_rootFontData = createFixedSizeFontData(m_family, weight, false);
+    }
+    FontPlatformPrivateData(const FontDescription& fontDescription, const AtomicString& family)
+        : m_reference(1)
+        , m_size(fontDescription.computedPixelSize())
+        , m_fontDescription(fontDescription)
+        , m_family(family)
+        , m_fontScaledWidth(0)
+        , m_fontScaledHeight(0)
+        , m_disabled(!fontDescription.specifiedSize())
+    {
+        m_rootFontData = FixedSizeFontData::create(family, toGDIFontWeight(fontDescription.weight()), fontDescription.italic());
+    }
+};
+
+FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& desiredFamily, bool useDefaultFontIfNotPresent)
+{
+    String family(desiredFamily);
+    if (!equalIgnoringCase(family, defaultFontFamily()) && !FontFamilyChecker(family.charactersWithNullTermination()).isSupported()) {
+        if (equalIgnoringCase(family, String(heiTiStr)) && isSongTiSupported())
+            family = String(songTiStr);
+        else if (useDefaultFontIfNotPresent)
+            family = defaultFontFamily();
+    }
+
+    m_private = new FontPlatformPrivateData(fontDescription, family);
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+{
+    if (!size)
+        m_private = 0;
+    else
+        m_private = new FontPlatformPrivateData((int)(size + 0.5), bold ? FW_BOLD : FW_NORMAL);
+}
+
+FontPlatformData::~FontPlatformData()
+{
+    if (isValid() && !--m_private->m_reference) {
+        if (m_private->m_rootFontData->refCount() == 2) {
+            FixedSizeFontDataKey key(m_private->m_family, m_private->m_rootFontData->m_weight, m_private->m_rootFontData->m_italic);
+            g_fixedSizeFontCache.remove(key);
+        }
+        delete m_private;
+    }
+}
+
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& o)
+{
+    if (isValid() && !--m_private->m_reference)
+        delete m_private;
+
+    if (m_private = o.m_private)
+        ++m_private->m_reference;
+
+    return *this;
+}
+
+HFONT FontPlatformData::hfont() const
+{
+    if (!isValid())
+        return 0;
+
+    if (m_private->m_disabled)
+        return 0;
+
+    if (!m_private->m_rootFontData->m_hfont)
+        m_private->m_rootFontData->m_hfont.set(CreateFontIndirect(&m_private->m_rootFontData->m_font));
+
+    return m_private->m_rootFontData->m_hfont.get();
+}
+
+HFONT FontPlatformData::getScaledFontHandle(int height, int width) const
+{
+    if (!isValid() || m_private->m_disabled)
+        return 0;
+
+    if (!m_private->m_hfontScaled || m_private->m_fontScaledHeight != height || m_private->m_fontScaledWidth != width) {
+        m_private->m_fontScaledHeight = height;
+        m_private->m_fontScaledWidth = width;
+        LOGFONT font = m_private->m_rootFontData->m_font;
+        font.lfHeight = -height;
+        font.lfWidth = width;
+        m_private->m_hfontScaled.set(CreateFontIndirect(&font));
+    }
+
+    return m_private->m_hfontScaled.get();
+}
+
+bool FontPlatformData::discardFontHandle()
+{
+    if (!isValid())
+        return false;
+
+    if (m_private->m_rootFontData->m_hfont) {
+        m_private->m_rootFontData->m_hfont.set(0);
+        return true;
+    }
+
+    if (m_private->m_hfontScaled) {
+        m_private->m_hfontScaled.set(0);
+        return true;
+    }
+    return false;
+}
+
+const TEXTMETRIC& FontPlatformData::metrics() const
+{
+    return m_private->m_rootFontData->m_metrics;
+}
+
+bool FontPlatformData::isSystemFont() const
+{
+    return false;
+}
+
+int FontPlatformData::size() const
+{
+    return m_private->m_size;
+}
+
+const FontDescription& FontPlatformData::fontDescription() const
+{
+    return m_private->m_fontDescription;
+}
+
+const AtomicString& FontPlatformData::family() const
+{
+    return m_private->m_family;
+}
+
+const LOGFONT& FontPlatformData::logFont() const
+{
+    return m_private->m_rootFontData->m_font;
+}
+
+int FontPlatformData::averageCharWidth() const
+{
+    return (m_private->m_rootFontData->m_metrics.tmAveCharWidth * size() + 36) / 72;
+}
+
+bool FontPlatformData::isDisabled() const
+{
+    return !isValid() || m_private->m_disabled;
+}
+
+DWORD FontPlatformData::codePages() const
+{
+    return m_private->m_rootFontData->m_codePages;
+}
+
+bool FontPlatformData::isSongTiSupported()
+{
+    static bool exists = FontFamilyChecker(songTiStr).isSupported();
+    return exists;
+}
+
+bool FontPlatformData::mapKnownFont(DWORD codePages, String& family)
+{
+    KnownFonts& fonts = knownFonts();
+    for (KnownFonts::iterator i = fonts.begin(); i != fonts.end(); ++i) {
+        if (i->codePages() & codePages) {
+            family = i->m_family;
+            return true;
+        }
+    }
+    return false;
+}
+
+DWORD FontPlatformData::getKnownFontCodePages(const wchar_t* family)
+{
+    KnownFonts& fonts = knownFonts();
+    for (KnownFonts::iterator i = fonts.begin(); i != fonts.end(); ++i) {
+        if (equalIgnoringCase(i->m_family, String(family)))
+            return i->codePages();
+    }
+    return 0;
+}
+
+const String& FontPlatformData::defaultFontFamily()
+{
+    static String family(getDefaultFontFamily());
+    return family;
+}
+
+LONG FontPlatformData::adjustedGDIFontWeight(LONG gdiFontWeight, const String& family)
+{
+    static AtomicString lucidaStr("Lucida Grande");
+    if (equalIgnoringCase(family, lucidaStr)) {
+        if (gdiFontWeight == FW_NORMAL)
+            return FW_MEDIUM;
+        if (gdiFontWeight == FW_BOLD)
+            return FW_SEMIBOLD;
+    }
+    return gdiFontWeight;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/wince/FontPlatformData.h b/WebCore/platform/graphics/wince/FontPlatformData.h
new file mode 100644 (file)
index 0000000..e8e07dc
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the internal font implementation.  It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006, 2007 Apple Inc.
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontPlatformDataWince_H
+#define FontPlatformDataWince_H
+
+#include "FontDescription.h"
+#include "StringImpl.h"
+#include <wtf/Noncopyable.h>
+
+typedef struct tagTEXTMETRICW TEXTMETRIC;
+typedef struct tagLOGFONTW LOGFONT;
+
+namespace WebCore {
+
+    class FontPlatformPrivateData;
+
+    class FontPlatformData {
+
+    public:
+
+        FontPlatformData(): m_private(0) {}
+        FontPlatformData(float size, bool bold, bool oblique);
+
+        // Used for deleted values in the font cache's hash tables.
+        FontPlatformData(WTF::HashTableDeletedValueType) : m_private((FontPlatformPrivateData*)1) {}
+        bool isHashTableDeletedValue() const { return (unsigned)m_private == 1; }
+
+        FontPlatformData(const FontDescription& fontDescription, const AtomicString& family, bool useDefaultFontIfNotPresent = true);
+
+        ~FontPlatformData();
+
+        FontPlatformData(const FontPlatformData& o) : m_private(0) { operator=(o); }
+        FontPlatformData& operator=(const FontPlatformData& o);
+
+        int isValid() const { return reinterpret_cast<unsigned>(m_private) & ~1; }
+        HFONT hfont() const;
+        const TEXTMETRIC& metrics() const;
+        bool isSystemFont() const;
+        int size() const;
+        unsigned hash() const { return (unsigned)m_private; }
+        const FontDescription& fontDescription() const;
+        const AtomicString& family() const;
+        bool operator==(const FontPlatformData& other) const {     return m_private == other.m_private; }
+        HFONT getScaledFontHandle(int height, int width) const;
+        const LOGFONT& logFont() const;
+        int averageCharWidth() const;
+        bool isDisabled() const;
+        bool discardFontHandle();
+        DWORD codePages() const;
+
+        static bool isSongTiSupported();
+        static bool mapKnownFont(DWORD codePages, String& family);
+        static DWORD getKnownFontCodePages(const wchar_t* family);
+        static const String& defaultFontFamily();
+        static LONG adjustedGDIFontWeight(LONG gdiFontWeight, const String& family);
+    private:
+        FontPlatformPrivateData* m_private;
+    };
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWince.cpp
new file mode 100644 (file)
index 0000000..d00336b
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 Holger Hans Peter Freyther
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "FloatRect.h"
+#include "FontCache.h"
+#include "FontData.h"
+#include "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "TransformationMatrix.h"
+#include "WidthIterator.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/unicode/Unicode.h>
+
+#include <windows.h>
+
+using namespace WTF::Unicode;
+
+namespace WebCore {
+
+HDC g_screenDC = GetDC(0);
+
+class ScreenDcReleaser {
+public:
+    ~ScreenDcReleaser()
+    {
+        ReleaseDC(0, g_screenDC);
+    }
+};
+
+ScreenDcReleaser releaseScreenDc;
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer,
+                      int from, int numGlyphs, const FloatPoint& point) const
+{
+    graphicsContext->drawText(fontData, glyphBuffer, from, numGlyphs, point);
+}
+
+class TextRunComponent {
+public:
+    TextRunComponent() : m_textRun(0, 0) {}
+    TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int offset);
+    TextRunComponent(int spaces, const Font &font, int offset);
+    ~TextRunComponent() { m_textRun; }
+
+    bool isSpace() const { return m_spaces; }
+    int textLength() const { return m_spaces ? m_spaces : m_textRun.length(); }
+
+    TextRun m_textRun;
+    float m_width;
+    int m_offset;
+    int m_spaces;
+};
+
+TextRunComponent::TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int o)
+    : m_textRun(start, length, parentTextRun.allowTabs(), 0, 0
+        , parentTextRun.rtl()
+        , parentTextRun.directionalOverride()
+        , parentTextRun.applyRunRounding()
+        , parentTextRun.applyWordRounding())
+    , m_offset(o)
+    , m_spaces(0)
+{
+    WidthIterator it(&font, m_textRun);
+    it.advance(m_textRun.length(), 0);
+    m_width = it.m_runWidthSoFar;
+}
+
+TextRunComponent::TextRunComponent(int s, const Font &font, int o)
+    : m_textRun(0, 0)
+    , m_offset(o)
+    , m_spaces(s)
+{
+    m_width = s * font.primaryFont()->widthForGlyph(' ');
+}
+
+typedef Vector<TextRunComponent, 128> TextRunComponents;
+
+static int generateComponents(TextRunComponents* components, const Font &font, const TextRun &run)
+{
+    int letterSpacing = font.letterSpacing();
+    int wordSpacing = font.wordSpacing();
+    int padding = run.padding();
+    int numSpaces = 0;
+    if (padding) {
+        for (int i = 0; i < run.length(); i++)
+            if (Font::treatAsSpace(run[i]))
+                ++numSpaces;
+    }
+
+    int offset = 0;
+    if (letterSpacing) {
+        // need to draw every letter on it's own
+        int start = 0;
+        if (Font::treatAsSpace(run[0])) {
+            int add = 0;
+            if (numSpaces) {
+                add = padding/numSpaces;
+                padding -= add;
+                --numSpaces;
+            }
+            components->append(TextRunComponent(1, font, offset));
+            offset += add + letterSpacing + components->last().m_width;
+            start = 1;
+        }
+        for (int i = 1; i < run.length(); ++i) {
+            uint ch = run[i];
+            if (isHighSurrogate(ch) && isLowSurrogate(run[i-1]))
+                ch = surrogateToUcs4(ch, run[i-1]);
+            if (isLowSurrogate(ch) || category(ch) == Mark_NonSpacing)
+                continue;
+            if (Font::treatAsSpace(run[i])) {
+                int add = 0;
+                if (i - start > 0) {
+                    components->append(TextRunComponent(run.characters() + start, i - start,
+                                                        run, font, offset));
+                    offset += components->last().m_width + letterSpacing;
+                }
+                if (numSpaces) {
+                    add = padding/numSpaces;
+                    padding -= add;
+                    --numSpaces;
+                }
+                components->append(TextRunComponent(1, font, offset));
+                offset += wordSpacing + add + components->last().m_width + letterSpacing;
+                start = i + 1;
+                continue;
+            }
+            if (i - start > 0) {
+                components->append(TextRunComponent(run.characters() + start, i - start,
+                                                    run,
+                                                    font, offset));
+                offset += components->last().m_width + letterSpacing;
+            }
+            start = i;
+        }
+        if (run.length() - start > 0) {
+            components->append(TextRunComponent(run.characters() + start, run.length() - start,
+                                                run,
+                                                font, offset));
+            offset += components->last().m_width;
+        }
+        offset += letterSpacing;
+    } else {
+        int start = 0;
+        for (int i = 0; i < run.length(); ++i) {
+            if (Font::treatAsSpace(run[i])) {
+                if (i - start > 0) {
+                    components->append(TextRunComponent(run.characters() + start, i - start,
+                                                        run,
+                                                        font, offset));
+                    offset += components->last().m_width;
+                }
+                int add = 0;
+                if (numSpaces) {
+                    add = padding/numSpaces;
+                    padding -= add;
+                    --numSpaces;
+                }
+                components->append(TextRunComponent(1, font, offset));
+                offset += add + components->last().m_width;
+                if (i)
+                    offset += wordSpacing;
+                start = i + 1;
+            }
+        }
+        if (run.length() - start > 0) {
+            components->append(TextRunComponent(run.characters() + start, run.length() - start,
+                                                run,
+                                                font, offset));
+            offset += components->last().m_width;
+        }
+    }
+    return offset;
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
+                           int from, int to) const
+{
+    if (to < 0)
+        to = run.length();
+    if (from < 0)
+        from = 0;
+
+    TextRunComponents components;
+    int w = generateComponents(&components, *this, run);
+
+    int curPos = 0;
+    for (int i = 0; i < (int)components.size(); ++i) {
+        const TextRunComponent& comp = components.at(i);
+        int len = comp.textLength();
+        int curEnd = curPos + len;
+        if (curPos < to && from < curEnd && !comp.isSpace()) {
+            FloatPoint pt = point;
+            if (run.rtl())
+                pt.setX(point.x() + w - comp.m_offset - comp.m_width);
+            else
+                pt.setX(point.x() + comp.m_offset);
+            drawSimpleText(context, comp.m_textRun, pt, from - curPos, std::min(to, curEnd) - curPos);
+        }
+        curPos += len;
+        if (from < curPos)
+            from = curPos;
+    }
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+{
+    TextRunComponents components;
+    int w = generateComponents(&components, *this, run);
+    return w;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
+{
+    TextRunComponents components;
+    int w = generateComponents(&components, *this, run);
+
+    if (position >= w)
+        return run.length();
+
+    int offset = 0;
+    if (run.rtl()) {
+        for (size_t i = 0; i < components.size(); ++i) {
+            const TextRunComponent& comp = components.at(i);
+            int xe = w - comp.m_offset;
+            int xs = xe - comp.m_width;
+            if (position >= xs)
+                return offset + (comp.isSpace()
+                    ? static_cast<int>((position - xe) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
+                    : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
+
+            offset += comp.textLength();
+        }
+    } else {
+        for (size_t i = 0; i < components.size(); ++i) {
+            const TextRunComponent& comp = components.at(i);
+            int xs = comp.m_offset;
+            int xe = xs + comp.m_width;
+            if (position <= xe) {
+                if (position - xs >= xe)
+                    return offset + comp.textLength();
+                return offset + (comp.isSpace()
+                    ? static_cast<int>((position - xs) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
+                    : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
+            }
+            offset += comp.textLength();
+        }
+    }
+    return run.length();
+}
+
+
+static float cursorToX(const Font* font, const TextRunComponents& components, int width, bool rtl, int cursor)
+{
+    int start = 0;
+    for (size_t i = 0; i < components.size(); ++i) {
+        const TextRunComponent& comp = components.at(i);
+        if (start + comp.textLength() <= cursor) {
+            start += comp.textLength();
+            continue;
+        }
+        int xs = comp.m_offset;
+        if (rtl)
+            xs = width - xs - comp.m_width;
+
+        int pos = cursor - start;
+        if (comp.isSpace()) {
+            if (rtl)
+                pos = comp.textLength() - pos;
+            return xs + pos * comp.m_width / comp.m_spaces;
+        }
+        WidthIterator it(font, comp.m_textRun);
+        it.advance(pos);
+        return xs + it.m_runWidthSoFar;
+    }
+    return width;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt,
+                                     int h, int from, int to) const
+{
+    TextRunComponents components;
+    int w = generateComponents(&components, *this, run);
+
+    if (!from && to == run.length())
+        return FloatRect(pt.x(), pt.y(), w, h);
+
+    float x1 = cursorToX(this, components, w, run.rtl(), from);
+    float x2 = cursorToX(this, components, w, run.rtl(), to);
+    if (x2 < x1)
+        std::swap(x1, x2);
+
+    return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+    return false;
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/GlyphPageTreeNodeWince.cpp b/WebCore/platform/graphics/wince/GlyphPageTreeNodeWince.cpp
new file mode 100644 (file)
index 0000000..27c4e15
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (C) 2007-2009 Torch Mobile Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "GlyphPageTreeNode.h"
+
+#include "Font.h"
+#include "FontCache.h"
+#include "FontData.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+DWORD getKnownFontCodePages(const wchar_t* family);
+
+typedef unsigned (*funcGetCharCodePages)(unsigned short c, unsigned& lastPos);
+funcGetCharCodePages getCharCodePages = 0;
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+    if (length != bufferLength)
+        return false;
+
+    if (fontData->platformData().hfont()) {
+        DWORD fontCodePages = fontData->platformData().codePages();
+        if (fontCodePages) {
+            if (getCharCodePages) {
+                unsigned lastPos = 0;
+                for (unsigned i = 0; i < bufferLength; ++i) {
+                    DWORD actualCodePages = getCharCodePages(buffer[i], lastPos);
+                    if (!actualCodePages || (actualCodePages & fontCodePages))
+                        setGlyphDataForIndex(offset + i, buffer[i], fontData);
+                    else
+                        setGlyphDataForIndex(offset + i, buffer[i], 0);
+                }
+                return true;
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+            } else if (IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface()) {
+#else
+            } else if (IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface()) {
+#endif
+                for (unsigned i = 0; i < bufferLength; ++i) {
+                    DWORD actualCodePages;
+                    langFontLink->GetCharCodePages(buffer[i], &actualCodePages);
+                    if (!actualCodePages || (actualCodePages & fontCodePages))
+                        setGlyphDataForIndex(offset + i, buffer[i], fontData);
+                    else
+                        setGlyphDataForIndex(offset + i, buffer[i], 0);
+                }
+                return true;
+            }
+        }
+    }
+
+    for (unsigned i = 0; i < length; ++i)
+        setGlyphDataForIndex(offset + i, buffer[i], fontData);
+
+    return true;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp b/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp
new file mode 100644 (file)
index 0000000..1195294
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "SimpleFontData.h"
+
+#include "FloatRect.h"
+#include "Font.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include <wtf/MathExtras.h>
+#include <mlang.h>
+#include <tchar.h>
+
+namespace WebCore {
+
+extern HDC g_screenDC;
+
+void SimpleFontData::platformInit()
+{
+    if (!m_platformData.isValid())
+        return;
+
+    const TEXTMETRIC& tm = m_platformData.metrics();
+    m_isSystemFont = m_platformData.isSystemFont();
+
+    m_ascent = (tm.tmAscent * m_platformData.size() + 36) / 72;
+    m_descent = (tm.tmDescent * m_platformData.size() + 36) / 72;
+    m_lineGap = (tm.tmExternalLeading * m_platformData.size() + 36) / 72;
+    m_lineSpacing = m_ascent + m_descent + m_lineGap;
+    m_xHeight = m_ascent * 0.56f;
+}
+
+void SimpleFontData::platformDestroy()
+{
+    delete m_smallCapsFontData;
+    m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+    if (!m_smallCapsFontData) {
+        FontDescription fontDesc(fontDescription);
+        fontDesc.setComputedSize(lroundf(0.70f * fontDesc.computedSize()));
+        fontDesc.setSpecifiedSize(lroundf(0.70f * fontDesc.specifiedSize()));
+        fontDesc.setKeywordSize(lroundf(0.70f * fontDesc.keywordSize()));
+        FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family());
+        if (result)
+            m_smallCapsFontData = new SimpleFontData(*result);
+    }
+    return m_smallCapsFontData;
+}
+
+DWORD getKnownFontCodePages(const wchar_t* family);
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+    if (m_platformData.isDisabled())
+        return true;
+
+    // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC
+    // merely by testing code page intersection.  This seems suspect though.  Can't a font only partially
+    // cover a given code page?
+
+    // FIXME: in the case that we failed to get the interface, still use the font.
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+    IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
+#else
+    IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface();
+#endif
+    if (!langFontLink)
+        return true;
+
+    DWORD fontCodePages = m_platformData.codePages();
+    if (!fontCodePages)
+        return false;
+
+    DWORD acpCodePages = 0;
+    langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
+
+    DWORD actualCodePages;
+    long numCharactersProcessed;
+    while (length) {
+        langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed);
+        if (actualCodePages && !(actualCodePages & fontCodePages))
+            return false;
+
+        length -= numCharactersProcessed;
+        characters += numCharactersProcessed;
+    }
+
+    return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+    if (!m_platformData.isValid())
+        return;
+
+    const TEXTMETRIC& tm = m_platformData.metrics();
+
+    // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
+    // is *not* fixed pitch.  Unbelievable but true.
+    m_treatAsFixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+    if (m_platformData.isDisabled())
+        return 0;
+
+    HGDIOBJ hOldFont = SelectObject(g_screenDC, m_platformData.hfont());
+
+    SIZE fontSize;
+    wchar_t c = glyph;
+    GetTextExtentPoint32(g_screenDC, &c, 1, &fontSize);
+
+    SelectObject(g_screenDC, hOldFont);
+
+    return (float)fontSize.cx * (float)m_platformData.size() / 72.f;
+}
+
+
+void SimpleFontData::platformCharWidthInit()
+{
+    if (!m_platformData.isValid())
+        return;
+
+    const TEXTMETRIC& tm = m_platformData.metrics();
+    m_avgCharWidth = (tm.tmAveCharWidth * m_platformData.size() + 36) / 72;
+    m_maxCharWidth = (tm.tmMaxCharWidth * m_platformData.size() + 36) / 72;
+}
+
+}