summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/win/FontPlatformDataWin.cpp')
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataWin.cpp108
1 files changed, 94 insertions, 14 deletions
diff --git a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
index f209dbf..a5fab36 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -2,8 +2,7 @@
* 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, 2008 Apple Inc.
- * Copyright (C) 2008 Brent Fulgham
+ * Copyright (C) 2006, 2007 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,6 +26,7 @@
#include "PlatformString.h"
#include "StringHash.h"
+#include <ApplicationServices/ApplicationServices.h>
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
@@ -39,6 +39,77 @@ static const int Bold = (1 << 0);
static const int Italic = (1 << 1);
static const int BoldOblique = (1 << 2);
+static inline USHORT readBigEndianWord(const BYTE* word) { return (word[0] << 8) | word[1]; }
+
+static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc)
+{
+ const DWORD cMaxNameTableSize = 1024 * 1024;
+
+ static HashMap<String, RetainPtr<CFStringRef> > nameMap;
+
+ // Check our hash first.
+ String faceString(faceName);
+ RetainPtr<CFStringRef> result = nameMap.get(faceString);
+ if (result)
+ return result.get();
+
+ // We need to obtain the PostScript name from the name table and use it instead,.
+ DWORD bufferSize = GetFontData(dc, 'eman', 0, NULL, 0); // "name" backwards
+ if (bufferSize == 0 || bufferSize == GDI_ERROR || bufferSize > cMaxNameTableSize)
+ return NULL;
+
+ Vector<BYTE> bufferVector(bufferSize);
+ BYTE* buffer = bufferVector.data();
+ if (GetFontData(dc, 'eman', 0, buffer, bufferSize) == GDI_ERROR)
+ return NULL;
+
+ if (bufferSize < 6)
+ return NULL;
+
+ USHORT numberOfRecords = readBigEndianWord(buffer + 2);
+ UINT stringsOffset = readBigEndianWord(buffer + 4);
+ if (bufferSize < stringsOffset)
+ return NULL;
+
+ BYTE* strings = buffer + stringsOffset;
+
+ // Now walk each name record looking for a Mac or Windows PostScript name.
+ UINT offset = 6;
+ for (int i = 0; i < numberOfRecords; i++) {
+ if (bufferSize < offset + 12)
+ return NULL;
+
+ USHORT platformID = readBigEndianWord(buffer + offset);
+ USHORT encodingID = readBigEndianWord(buffer + offset + 2);
+ USHORT languageID = readBigEndianWord(buffer + offset + 4);
+ USHORT nameID = readBigEndianWord(buffer + offset + 6);
+ USHORT length = readBigEndianWord(buffer + offset + 8);
+ USHORT nameOffset = readBigEndianWord(buffer + offset + 10);
+
+ if (platformID == 3 && encodingID == 1 && languageID == 0x409 && nameID == 6) {
+ // This is a Windows PostScript name and is therefore UTF-16.
+ // Pass Big Endian as the encoding.
+ if (bufferSize < stringsOffset + nameOffset + length)
+ return NULL;
+ result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingUTF16BE, false));
+ break;
+ } else if (platformID == 1 && encodingID == 0 && languageID == 0 && nameID == 6) {
+ // This is a Mac PostScript name and is therefore ASCII.
+ // See http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
+ if (bufferSize < stringsOffset + nameOffset + length)
+ return NULL;
+ result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingASCII, false));
+ break;
+ }
+
+ offset += 12;
+ }
+
+ if (result)
+ nameMap.set(faceString, result);
+ return result.get();
+}
+
static int CALLBACK enumStylesCallback(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
{
int *style = reinterpret_cast<int*>(lParam);
@@ -60,12 +131,7 @@ static int CALLBACK enumStylesCallback(const LOGFONT* logFont, const TEXTMETRIC*
FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI)
: m_font(font)
, m_size(size)
-#if PLATFORM(CG)
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
- , m_fontFace(0)
- , m_scaledFont(0)
-#endif
, m_syntheticBold(false)
, m_syntheticOblique(false)
, m_useGDI(useGDI)
@@ -113,8 +179,17 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
m_syntheticOblique = true;
}
- platformDataInit(font, size, hdc, faceName);
-
+ // Try the face name first. Windows may end up localizing this name, and CG doesn't know about
+ // the localization. If the create fails, we'll try the PostScript name.
+ RetainPtr<CFStringRef> fullName(AdoptCF, CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName)));
+ m_cgFont = CGFontCreateWithFontName(fullName.get());
+ if (!m_cgFont) {
+ CFStringRef postScriptName = getPostScriptName(fullName.get(), hdc);
+ if (postScriptName) {
+ m_cgFont = CGFontCreateWithFontName(postScriptName);
+ ASSERT(m_cgFont);
+ }
+ }
free(metrics);
}
@@ -125,12 +200,17 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
: m_font(0)
, m_size(size)
-#if PLATFORM(CG)
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
- , m_fontFace(0)
- , m_scaledFont(0)
-#endif
+ , m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+ , m_useGDI(false)
+{
+}
+
+FontPlatformData::FontPlatformData(CGFontRef font, float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+ , m_cgFont(font)
, m_syntheticBold(bold)
, m_syntheticOblique(oblique)
, m_useGDI(false)