Commit 8b28373d authored by hyatt's avatar hyatt

Fix for missing text in non-English Windows installs.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@23539 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2b1d0661
2007-06-14 Dave Hyatt <hyatt@apple.com>
Fix for Bugzilla bug 14806, missing text for bold/italic fonts in non-English Windows installs.
This patch adds an additional step after the lookup by full name fails. It will then look up
a PostScript name in a (localized full name) -> (PostScript name) cache. If the name is not
found, then the font's name table is obtained and searched for a PostScript name (and the
result is cached).
If lookup on PostScript name fails too, then we now properly fall back to the next font in the
list (so text should never be missing).
Reviewed by Darin (thoroughly reviewed, super reviewed even)
* platform/win/FontCacheWin.cpp:
* platform/win/FontPlatformDataWin.cpp:
2007-06-14 Anders Carlsson <andersca@apple.com>
Reviewed by Geoff.
......@@ -158,8 +158,18 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
return 0;
}
return new FontPlatformData(hfont, fontDescription.computedPixelSize(),
fontDescription.bold(), fontDescription.italic());
FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(),
fontDescription.bold(), fontDescription.italic());
if (!result->cgFont()) {
// The creation of the CGFontRef failed for some reason. We already asserted in debug builds, but to make
// absolutely sure that we don't use this font, go ahead and return 0 so that we can fall back to the next
// font.
delete result;
DeleteObject(hfont);
return 0;
}
return result;
}
}
......
......@@ -23,7 +23,13 @@
#include "config.h"
#include "FontPlatformData.h"
#include "PlatformString.h"
#include "StringHash.h"
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/HashMap.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
using std::min;
......@@ -33,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);
......@@ -66,8 +143,7 @@ FontPlatformData::FontPlatformData(HFONT font, int size, bool bold, bool oblique
ASSERT_WITH_MESSAGE(bufferSize != 0, "Bitmap fonts not supported with CoreGraphics.");
if (bufferSize != 0)
{
if (bufferSize != 0) {
OUTLINETEXTMETRICW* metrics = (OUTLINETEXTMETRICW*)malloc(bufferSize);
GetOutlineTextMetricsW(hdc, bufferSize, metrics);
......@@ -102,11 +178,17 @@ FontPlatformData::FontPlatformData(HFONT font, int size, bool bold, bool oblique
m_syntheticOblique = true;
}
CFStringRef cfName = CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName));
m_cgFont = CGFontCreateWithFontName(cfName);
ASSERT(m_cgFont);
CFRelease(cfName);
// 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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment