+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.
--- /dev/null
+/*
+* 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);
+}
+
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
+
+}
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
+
+}
--- /dev/null
+/*
+ * 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;
+}
+
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
+}