Changeset 23539 in webkit


Ignore:
Timestamp:
Jun 14, 2007 2:58:39 PM (17 years ago)
Author:
hyatt
Message:

Fix for missing text in non-English Windows installs.

Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r23536 r23539  
     12007-06-14  Dave Hyatt  <hyatt@apple.com>
     2
     3        Fix for Bugzilla bug 14806, missing text for bold/italic fonts in non-English Windows installs.
     4       
     5        This patch adds an additional step after the lookup by full name fails.  It will then look up
     6        a PostScript name in a (localized full name) -> (PostScript name) cache.  If the name is not
     7        found, then the font's name table is obtained and searched for a PostScript name (and the
     8        result is cached).
     9       
     10        If lookup on PostScript name fails too, then we now properly fall back to the next font in the
     11        list (so text should never be missing).
     12
     13        Reviewed by Darin (thoroughly reviewed, super reviewed even)
     14
     15        * platform/win/FontCacheWin.cpp:
     16        * platform/win/FontPlatformDataWin.cpp:
     17
    1182007-06-14  Anders Carlsson  <andersca@apple.com>
    219
  • trunk/WebCore/platform/win/FontCacheWin.cpp

    r23462 r23539  
    159159    }
    160160   
    161     return new FontPlatformData(hfont, fontDescription.computedPixelSize(),
    162         fontDescription.bold(), fontDescription.italic());
     161    FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(),
     162                                                    fontDescription.bold(), fontDescription.italic());
     163    if (!result->cgFont()) {
     164        // The creation of the CGFontRef failed for some reason.  We already asserted in debug builds, but to make
     165        // absolutely sure that we don't use this font, go ahead and return 0 so that we can fall back to the next
     166        // font.
     167        delete result;
     168        DeleteObject(hfont);
     169        return 0;
     170    }       
     171
     172    return result;
    163173}
    164174
  • trunk/WebCore/platform/win/FontPlatformDataWin.cpp

    r23462 r23539  
    2424#include "config.h"
    2525#include "FontPlatformData.h"
     26
     27#include "PlatformString.h"
     28#include "StringHash.h"
    2629#include <ApplicationServices/ApplicationServices.h>
     30#include <wtf/HashMap.h>
     31#include <wtf/RetainPtr.h>
     32#include <wtf/Vector.h>
    2733
    2834using std::min;
     
    3339static const int Italic = (1 << 1);
    3440static const int BoldOblique = (1 << 2);
     41
     42static inline USHORT readBigEndianWord(const BYTE* word) { return (word[0] << 8) | word[1]; }
     43
     44static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc)
     45{
     46    const DWORD cMaxNameTableSize = 1024 * 1024;
     47
     48    static HashMap<String, RetainPtr<CFStringRef> > nameMap;
     49
     50    // Check our hash first.
     51    String faceString(faceName);
     52    RetainPtr<CFStringRef> result = nameMap.get(faceString);
     53    if (result)
     54        return result.get();
     55
     56    // We need to obtain the PostScript name from the name table and use it instead,.
     57    DWORD bufferSize = GetFontData(dc, 'eman', 0, NULL, 0); // "name" backwards
     58    if (bufferSize == 0 || bufferSize == GDI_ERROR || bufferSize > cMaxNameTableSize)
     59        return NULL;
     60   
     61    Vector<BYTE> bufferVector(bufferSize);
     62    BYTE* buffer = bufferVector.data();
     63    if (GetFontData(dc, 'eman', 0, buffer, bufferSize) == GDI_ERROR)
     64        return NULL;
     65
     66    if (bufferSize < 6)
     67        return NULL;
     68
     69    USHORT numberOfRecords = readBigEndianWord(buffer + 2);
     70    UINT stringsOffset = readBigEndianWord(buffer + 4);
     71    if (bufferSize < stringsOffset)
     72        return NULL;
     73
     74    BYTE* strings = buffer + stringsOffset;
     75
     76    // Now walk each name record looking for a Mac or Windows PostScript name.
     77    UINT offset = 6;
     78    for (int i = 0; i < numberOfRecords; i++) {
     79        if (bufferSize < offset + 12)
     80            return NULL;
     81
     82        USHORT platformID = readBigEndianWord(buffer + offset);
     83        USHORT encodingID = readBigEndianWord(buffer + offset + 2);
     84        USHORT languageID = readBigEndianWord(buffer + offset + 4);
     85        USHORT nameID = readBigEndianWord(buffer + offset + 6);
     86        USHORT length = readBigEndianWord(buffer + offset + 8);
     87        USHORT nameOffset = readBigEndianWord(buffer + offset + 10);
     88
     89        if (platformID == 3 && encodingID == 1 && languageID == 0x409 && nameID == 6) {
     90            // This is a Windows PostScript name and is therefore UTF-16.
     91            // Pass Big Endian as the encoding.
     92            if (bufferSize < stringsOffset + nameOffset + length)
     93                return NULL;
     94            result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingUTF16BE, false));
     95            break;
     96        } else if (platformID == 1 && encodingID == 0 && languageID == 0 && nameID == 6) {
     97            // This is a Mac PostScript name and is therefore ASCII.
     98            // See http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
     99            if (bufferSize < stringsOffset + nameOffset + length)
     100                return NULL;
     101            result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingASCII, false));
     102            break;
     103        }
     104
     105        offset += 12;
     106    }
     107
     108    if (result)
     109        nameMap.set(faceString, result);
     110    return result.get();
     111}
    35112
    36113static int CALLBACK enumStylesCallback(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
     
    67144    ASSERT_WITH_MESSAGE(bufferSize != 0, "Bitmap fonts not supported with CoreGraphics.");
    68145
    69     if (bufferSize != 0)
    70     {
     146    if (bufferSize != 0) {
    71147        OUTLINETEXTMETRICW* metrics = (OUTLINETEXTMETRICW*)malloc(bufferSize);
    72148
     
    103179        }
    104180
    105         CFStringRef cfName = CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName));
    106         m_cgFont = CGFontCreateWithFontName(cfName);
    107         ASSERT(m_cgFont);
    108         CFRelease(cfName);
    109        
     181        // Try the face name first.  Windows may end up localizing this name, and CG doesn't know about
     182        // the localization.  If the create fails, we'll try the PostScript name.
     183        RetainPtr<CFStringRef> fullName(AdoptCF, CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName)));
     184        m_cgFont = CGFontCreateWithFontName(fullName.get());
     185        if (!m_cgFont) {
     186            CFStringRef postScriptName = getPostScriptName(fullName.get(), hdc);
     187            if (postScriptName) {
     188                m_cgFont = CGFontCreateWithFontName(postScriptName);
     189                ASSERT(m_cgFont);
     190            }
     191        }
    110192        free(metrics);
    111193    }
Note: See TracChangeset for help on using the changeset viewer.