Changeset 28867

Show
Ignore:
Timestamp:
2007-12-19 11:24:10 (10 months ago)
Author:
hyatt@apple.com
Message:

Add support for GDI text on Windows.

Location:
trunk/WebCore
Files:
19 modified

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r28864 r28867  
     12007-12-19  Dave Hyatt  <hyatt@apple.com> 
     2 
     3        Add support for GDI text rendering to WebKit. 
     4       
     5        Reviewed by mitz 
     6         
     7        * css/CSSStyleSelector.cpp: 
     8        (WebCore::CSSStyleSelector::applyProperty): 
     9        * dom/Document.cpp: 
     10        (WebCore::Document::recalcStyle): 
     11        * page/Settings.cpp: 
     12        (WebCore::Settings::setFontRenderingMode): 
     13        (WebCore::Settings::fontRenderingMode): 
     14        * page/Settings.h: 
     15        * platform/graphics/Font.h: 
     16        (WebCore::Font::renderingMode): 
     17        * platform/graphics/FontCache.cpp: 
     18        (WebCore::FontPlatformDataCacheKey::FontPlatformDataCacheKey): 
     19        (WebCore::FontPlatformDataCacheKey::operator==): 
     20        (WebCore::computeHash): 
     21        (WebCore::FontCache::getCachedFontPlatformData): 
     22        * platform/graphics/FontDescription.h: 
     23        (WebCore::): 
     24        (WebCore::FontDescription::FontDescription): 
     25        (WebCore::FontDescription::renderingMode): 
     26        (WebCore::FontDescription::setRenderingMode): 
     27        (WebCore::FontDescription::operator==): 
     28        * platform/graphics/GraphicsContext.h: 
     29        * platform/graphics/win/FontCacheWin.cpp: 
     30        (WebCore::FontCache::fontExists): 
     31        (WebCore::FontCache::createFontPlatformData): 
     32        * platform/graphics/win/FontDataWin.cpp: 
     33        (WebCore::FontData::platformInit): 
     34        (WebCore::FontData::smallCapsFontData): 
     35        (WebCore::FontData::containsCharacters): 
     36        (WebCore::FontData::determinePitch): 
     37        (WebCore::FontData::platformWidthForGlyph): 
     38        * platform/graphics/win/FontPlatformData.h: 
     39        (WebCore::FontPlatformData::FontPlatformData): 
     40        (WebCore::FontPlatformData::useGDI): 
     41        (WebCore::FontPlatformData::operator==): 
     42        * platform/graphics/win/FontPlatformDataWin.cpp: 
     43        (WebCore::FontPlatformData::FontPlatformData): 
     44        * platform/graphics/win/FontWin.cpp: 
     45        (WebCore::Font::drawGlyphs): 
     46        * platform/graphics/win/IconWin.cpp: 
     47        (WebCore::Icon::paint): 
     48        * platform/win/GraphicsContextWin.cpp: 
     49        (WebCore::GraphicsContext::getWindowsContext): 
     50        (WebCore::GraphicsContext::releaseWindowsContext): 
     51        * platform/win/UniscribeController.cpp: 
     52        (WebCore::UniscribeController::shapeAndPlaceItem): 
     53        * platform/win/UniscribeController.h: 
     54        * plugins/win/PluginViewWin.cpp: 
     55        (WebCore::PluginViewWin::paint): 
     56 
    1572007-12-19  Sven Herzberg  <sven@imendio.com> 
    258 
  • trunk/WebCore/css/CSSStyleSelector.cpp

    r28775 r28867  
    33393339                fontDirty = true; 
    33403340        } else if (isInitial) { 
     3341            Settings* settings = m_document->settings(); 
    33413342            FontDescription fontDescription; 
    33423343            fontDescription.setGenericFamily(FontDescription::StandardFamily); 
     3344            fontDescription.setRenderingMode(settings->fontRenderingMode()); 
     3345            fontDescription.setUsePrinterFont(m_document->printing()); 
    33433346            const AtomicString& standardFontFamily = m_document->settings()->standardFontFamily(); 
    33443347            if (!standardFontFamily.isEmpty()) { 
  • trunk/WebCore/dom/Document.cpp

    r28784 r28867  
    10651065        fontDescription.setUsePrinterFont(printing()); 
    10661066        if (Settings* settings = this->settings()) { 
     1067            fontDescription.setRenderingMode(settings->fontRenderingMode()); 
    10671068            if (printing() && !settings->shouldPrintBackgrounds()) 
    10681069                _style->setForceBackgroundsToWhite(true); 
  • trunk/WebCore/page/Settings.cpp

    r28693 r28867  
    315315} 
    316316 
     317void Settings::setFontRenderingMode(FontRenderingMode mode) 
     318{ 
     319    if (m_fontRenderingMode == mode) 
     320        return; 
     321    m_fontRenderingMode = mode; 
     322    setNeedsReapplyStylesInAllFrames(m_page); 
     323} 
     324 
     325FontRenderingMode Settings::fontRenderingMode() const 
     326{ 
     327    return m_fontRenderingMode; 
     328} 
     329 
    317330} // namespace WebCore 
  • trunk/WebCore/page/Settings.h

    r28693 r28867  
    3030#include "AtomicString.h" 
    3131#include "KURL.h" 
     32#include "FontDescription.h" 
    3233 
    3334namespace WebCore { 
     
    147148        unsigned long long defaultDatabaseOriginQuota() const; 
    148149         
     150        void setFontRenderingMode(FontRenderingMode mode); 
     151        FontRenderingMode fontRenderingMode() const; 
     152 
    149153    private: 
    150154        Page* m_page; 
     
    182186        bool m_developerExtrasEnabled : 1; 
    183187        bool m_authorAndUserStylesEnabled : 1; 
     188        FontRenderingMode m_fontRenderingMode : 1; 
    184189    }; 
    185190 
  • trunk/WebCore/platform/graphics/Font.h

    r28688 r28867  
    160160    bool isFixedPitch() const; 
    161161    bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); } 
     162     
     163    FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); } 
    162164 
    163165    FontFamily& firstFamily() { return m_fontDescription.firstFamily(); } 
  • trunk/WebCore/platform/graphics/FontCache.cpp

    r28626 r28867  
    4141struct FontPlatformDataCacheKey { 
    4242    FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, bool bold = false, bool italic = false, 
    43                              bool isPrinterFont = false) 
     43                             bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode) 
    4444        : m_family(family) 
    4545        , m_size(size) 
     
    4747        , m_italic(italic) 
    4848        , m_printerFont(isPrinterFont) 
     49        , m_renderingMode(renderingMode) 
    4950    { 
    5051    } 
     
    5354    { 
    5455        return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&  
    55                m_bold == other.m_bold && m_italic == other.m_italic && m_printerFont == other.m_printerFont; 
     56               m_bold == other.m_bold && m_italic == other.m_italic && m_printerFont == other.m_printerFont && 
     57               m_renderingMode == other.m_renderingMode; 
    5658    } 
    5759     
     
    6163    bool m_italic; 
    6264    bool m_printerFont; 
     65    FontRenderingMode m_renderingMode; 
    6366}; 
    6467 
    6568inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey) 
    6669{ 
    67     unsigned hashCodes[3] = { 
     70    unsigned hashCodes[4] = { 
    6871        CaseFoldingHash::hash(fontKey.m_family), 
    6972        fontKey.m_size, 
    70         static_cast<unsigned>(fontKey.m_bold) << 2 | static_cast<unsigned>(fontKey.m_italic) << 1 | static_cast<unsigned>(fontKey.m_printerFont) 
     73        static_cast<unsigned>(fontKey.m_bold) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | 
     74        static_cast<unsigned>(fontKey.m_renderingMode) 
    7175    }; 
    72     return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 3 * sizeof(unsigned) / sizeof(UChar)); 
     76    return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 4 * sizeof(unsigned) / sizeof(UChar)); 
    7377} 
    7478 
     
    142146 
    143147    FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.bold(), fontDescription.italic(), 
    144                                  fontDescription.usePrinterFont()); 
     148                                 fontDescription.usePrinterFont(), fontDescription.renderingMode()); 
    145149    FontPlatformData* result = 0; 
    146150    bool foundResult; 
  • trunk/WebCore/platform/graphics/FontDescription.h

    r28234 r28867  
    3232const unsigned cBoldWeight = 63; 
    3333 
     34// This setting is used to provide ways of switching between multiple rendering modes that may have different 
     35// metrics.  It is used to switch between CG and GDI text on Windows. 
     36enum FontRenderingMode { NormalRenderingMode, AlternateRenderingMode }; 
     37 
    3438class FontDescription { 
    3539public: 
     
    4044        : m_specifiedSize(0), m_computedSize(0),  
    4145          m_italic(false), m_smallCaps(false), m_isAbsoluteSize(false), m_weight(cNormalWeight),  
    42           m_genericFamily(NoFamily), m_usePrinterFont(false), m_keywordSize(0) 
     46          m_genericFamily(NoFamily), m_usePrinterFont(false), m_renderingMode(NormalRenderingMode), m_keywordSize(0) 
    4347          {} 
    4448     
     
    5862    GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); } 
    5963    bool usePrinterFont() const { return m_usePrinterFont; } 
     64    FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); } 
    6065    int keywordSize() const { return m_keywordSize; } 
    6166 
     
    7075    void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; } 
    7176    void setUsePrinterFont(bool p) { m_usePrinterFont = p; } 
     77    void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; } 
    7278    void setKeywordSize(int s) { m_keywordSize = s; } 
    7379 
     
    8692    unsigned m_genericFamily : 3; // GenericFamilyType 
    8793    bool m_usePrinterFont : 1; 
    88      
     94 
     95    unsigned m_renderingMode : 1;  // Used to switch between CG and GDI text on Windows. 
     96 
    8997    int m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium).  If so, 
    9098                           // then we can accurately translate across different generic families to adjust for different preference settings 
     
    103111        && m_genericFamily == other.m_genericFamily 
    104112        && m_usePrinterFont == other.m_usePrinterFont 
     113        && m_renderingMode == other.m_renderingMode 
    105114        && m_keywordSize == other.m_keywordSize; 
    106115} 
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r28588 r28867  
    222222#if PLATFORM(WIN) 
    223223        GraphicsContext(HDC); // FIXME: To be removed. 
    224         HDC getWindowsContext(bool supportAlphaBlend = false, const IntRect* = 0); // The passed in rect is used to create a bitmap for compositing inside transparency layers. 
    225         void releaseWindowsContext(HDC, bool supportAlphaBlend = false, const IntRect* = 0);    // The passed in HDC should be the one handed back by getWindowsContext. 
     224        HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers. 
     225        void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true);    // The passed in HDC should be the one handed back by getWindowsContext. 
    226226#endif 
    227227 
  • trunk/WebCore/platform/graphics/win/FontCacheWin.cpp

    r28838 r28867  
    216216    // Windows will always give us a valid pointer here, even if the face name is non-existent.  We have to double-check 
    217217    // and see if the family name was really used. 
    218     HDC dc = GetDC((HWND)0); 
     218    HDC dc = GetDC(0); 
    219219    SaveDC(dc); 
    220220    SelectObject(dc, hfont); 
     
    231231FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) 
    232232{ 
     233    bool isLucidaGrande = false; 
     234    static AtomicString lucidaStr("Lucida Grande"); 
     235    if (equalIgnoringCase(family, lucidaStr)) 
     236        isLucidaGrande = true; 
     237 
     238    bool useGDI = fontDescription.renderingMode() == AlternateRenderingMode && !isLucidaGrande; 
     239 
    233240    LOGFONT winfont; 
    234241 
    235     // The size here looks unusual.  The negative number is intentional.  The logical size constant is 32. 
    236     winfont.lfHeight = -fontDescription.computedPixelSize() * 32; 
     242    // The size here looks unusual.  The negative number is intentional.  The logical size constant is 32. We do this 
     243    // for subpixel precision when rendering using Uniscribe.  This masks rounding errors related to the HFONT metrics being 
     244    // different from the CGFont metrics. 
     245    // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't look as nice.  That may be solvable though. 
     246    winfont.lfHeight = -fontDescription.computedPixelSize() * (useGDI ? 1 : 32); 
    237247    winfont.lfWidth = 0; 
    238248    winfont.lfEscapement = 0; 
     
    241251    winfont.lfStrikeOut = false; 
    242252    winfont.lfCharSet = DEFAULT_CHARSET; 
    243 #if PLATFORM(CG) 
    244253    winfont.lfOutPrecision = OUT_TT_ONLY_PRECIS; 
    245 #else 
    246     winfont.lfOutPrecision = OUT_TT_PRECIS; 
    247 #endif 
    248     winfont.lfQuality = 5; // Force cleartype. 
     254    winfont.lfQuality = DEFAULT_QUALITY; 
    249255    winfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; 
    250256    winfont.lfItalic = fontDescription.italic(); 
     
    255261    // FIXME: Hardcoding Lucida Grande for now.  It uses different weights than typical Win32 fonts 
    256262    // (500/600 instead of 400/700). 
    257     static AtomicString lucidaStr("Lucida Grande"); 
    258     if (equalIgnoringCase(family, lucidaStr)) 
     263    if (isLucidaGrande) { 
    259264        winfont.lfWeight = fontDescription.bold() ? 600 : 500; 
    260     else 
     265        useGDI = false; // Never use GDI for Lucida Grande. 
     266    } else 
    261267        winfont.lfWeight = fontDescription.bold() ? 700 : 400; 
    262268    int len = min(family.length(), (unsigned int)LF_FACESIZE - 1); 
     
    267273    // Windows will always give us a valid pointer here, even if the face name is non-existent.  We have to double-check 
    268274    // and see if the family name was really used. 
    269     HDC dc = GetDC((HWND)0); 
     275    HDC dc = GetDC(0); 
    270276    SaveDC(dc); 
    271277    SelectObject(dc, hfont); 
     
    281287     
    282288    FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(), 
    283                                                     fontDescription.bold(), fontDescription.italic()); 
     289                                                    fontDescription.bold(), fontDescription.italic(), useGDI); 
    284290    if (!result->cgFont()) { 
    285291        // The creation of the CGFontRef failed for some reason.  We already asserted in debug builds, but to make 
  • trunk/WebCore/platform/graphics/win/FontDataWin.cpp

    r28641 r28867  
    6060{     
    6161    m_syntheticBoldOffset = m_font.syntheticBold() ? 1.0f : 0.f; 
     62    m_scriptCache = 0; 
     63    m_scriptFontProperties = 0; 
     64    m_isSystemFont = false; 
     65     
     66    if (m_font.useGDI()) { 
     67        HDC hdc = GetDC(0); 
     68        HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont()); 
     69        OUTLINETEXTMETRIC metrics; 
     70        GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics); 
     71        TEXTMETRIC& textMetrics = metrics.otmTextMetrics; 
     72        m_ascent = textMetrics.tmAscent; 
     73        m_descent = textMetrics.tmDescent; 
     74        m_lineGap = textMetrics.tmExternalLeading; 
     75        m_lineSpacing = m_ascent + m_descent + m_lineGap; 
     76        m_xHeight = m_ascent * 0.56f; // Best guess for xHeight if no x glyph is present. 
     77 
     78        GLYPHMETRICS gm; 
     79        MAT2 mat = { 1, 0, 0, 1 }; 
     80        DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat); 
     81        if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0) 
     82            m_xHeight = gm.gmptGlyphOrigin.y; 
     83 
     84        m_unitsPerEm = metrics.otmEMSquare; 
     85 
     86        SelectObject(hdc, oldFont); 
     87        ReleaseDC(0, hdc); 
     88 
     89        return; 
     90    } 
    6291 
    6392    CGFontRef font = m_font.cgFont(); 
     
    71100    float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize; 
    72101 
    73     m_isSystemFont = false; 
    74102    if (!isCustomFont()) { 
    75103        HDC dc = GetDC(0); 
     
    116144        m_xHeight = scaleEmToUnits(iXHeight, m_unitsPerEm) * pointSize; 
    117145    } 
    118  
    119     m_scriptCache = 0; 
    120     m_scriptFontProperties = 0; 
    121146} 
    122147 
     
    146171            LOGFONT winfont; 
    147172            GetObject(m_font.hfont(), sizeof(LOGFONT), &winfont); 
    148             winfont.lfHeight = -lroundf(smallCapsHeight * 32); 
     173            winfont.lfHeight = -lroundf(smallCapsHeight * m_font.useGDI() ? 1 : 32); 
    149174            HFONT hfont = CreateFontIndirect(&winfont); 
    150             m_smallCapsFontData = new FontData(FontPlatformData(hfont, smallCapsHeight, fontDescription.bold(), fontDescription.italic())); 
     175            m_smallCapsFontData = new FontData(FontPlatformData(hfont, smallCapsHeight, fontDescription.bold(), fontDescription.italic(), m_font.useGDI())); 
    151176        } 
    152177    } 
     
    167192        return false; 
    168193 
    169     HDC dc = GetDC((HWND)0); 
     194    HDC dc = GetDC(0); 
    170195     
    171196    DWORD acpCodePages; 
     
    198223 
    199224    // TEXTMETRICS have this.  Set m_treatAsFixedPitch based off that. 
    200     HDC dc = GetDC((HWND)0); 
     225    HDC dc = GetDC(0); 
    201226    SaveDC(dc); 
    202227    SelectObject(dc, m_font.hfont()); 
     
    214239float FontData::platformWidthForGlyph(Glyph glyph) const 
    215240{ 
     241    if (m_font.useGDI()) { 
     242        HDC hdc = GetDC(0); 
     243        HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont()); 
     244        int width; 
     245        GetCharWidthI(hdc, glyph, 1, 0, &width); 
     246        SelectObject(hdc, oldFont); 
     247        ReleaseDC(0, hdc); 
     248        return width; 
     249    } 
     250 
    216251    CGFontRef font = m_font.cgFont(); 
    217252    float pointSize = m_font.size(); 
  • trunk/WebCore/platform/graphics/win/FontPlatformData.h

    r28641 r28867  
    4646    , m_syntheticBold(false) 
    4747    , m_syntheticOblique(false) 
     48    , m_useGDI(false) 
    4849    {} 
    4950 
     
    5455    , m_syntheticBold(false) 
    5556    , m_syntheticOblique(false) 
     57    , m_useGDI(false) 
    5658    {} 
    5759 
    58     FontPlatformData(HFONT, float size, bool bold, bool oblique); 
     60    FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); 
    5961    FontPlatformData(CGFontRef, float size, bool bold, bool oblique); 
    6062    ~FontPlatformData(); 
     
    6769    bool syntheticBold() const { return m_syntheticBold; } 
    6870    bool syntheticOblique() const { return m_syntheticOblique; } 
     71    bool useGDI() const { return m_useGDI; } 
    6972 
    7073    unsigned hash() const 
     
    7679    {  
    7780        return m_font == other.m_font && m_cgFont ==other.m_cgFont && m_size == other.m_size && 
    78                m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique; 
     81               m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique && 
     82               m_useGDI == other.m_useGDI; 
    7983    } 
    8084 
     
    8690    bool m_syntheticBold; 
    8791    bool m_syntheticOblique; 
     92    bool m_useGDI; 
    8893}; 
    8994 
  • trunk/WebCore/platform/graphics/win/FontPlatformDataWin.cpp

    r28641 r28867  
    129129} 
    130130 
    131 FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique) 
     131FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI) 
    132132    : m_font(font) 
    133133    , m_size(size) 
     
    135135    , m_syntheticBold(false) 
    136136    , m_syntheticOblique(false) 
     137    , m_useGDI(useGDI) 
    137138{ 
    138139    HDC hdc = GetDC(0); 
     
    179180        } 
    180181 
     182        // For GDI text, synthetic bold and oblique never need to be set. 
     183        m_syntheticBold = m_syntheticOblique = false; 
     184 
    181185        // Try the face name first.  Windows may end up localizing this name, and CG doesn't know about 
    182186        // the localization.  If the create fails, we'll try the PostScript name. 
     
    203207    , m_syntheticBold(bold) 
    204208    , m_syntheticOblique(oblique) 
     209    , m_useGDI(false) 
    205210{ 
    206211} 
  • trunk/WebCore/platform/graphics/win/FontWin.cpp

    r28536 r28867  
    4545                      int from, int numGlyphs, const FloatPoint& point) const 
    4646{ 
     47    if (font->m_font.useGDI()) { 
     48        // FIXME: Support alpha blending. 
     49        // FIXME: Support text stroke/fill. 
     50        // FIXME: Support text shadow. 
     51        Color fillColor = graphicsContext->fillColor(); 
     52        if (fillColor.alpha() == 0) 
     53            return; 
     54 
     55        // We have to convert CG's two-dimensional floating point advances to just horizontal integer advances. 
     56        Vector<int, 2048> gdiAdvances; 
     57        int totalWidth = 0; 
     58        for (int i = 0; i < numGlyphs; i++) { 
     59            gdiAdvances.append(lroundf(glyphBuffer.advanceAt(from + i))); 
     60            totalWidth += gdiAdvances[i]; 
     61        } 
     62 
     63        // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges. 
     64        IntRect textRect(point.x() - font->lineGap(), point.y() - font->ascent() - font->lineGap(), totalWidth + 2 * font->lineGap(), font->lineSpacing()); 
     65        HDC hdc = graphicsContext->getWindowsContext(textRect); 
     66        SelectObject(hdc, font->m_font.hfont()); 
     67 
     68        // Set the correct color. 
     69        HDC textDrawingDC = hdc; 
     70        /*if (fillColor.hasAlpha() || graphicsContext->inTransparencyLayer()) { 
     71            // GDI can't handle drawing transparent text.  We have to draw into a mask.  We draw black text on a white-filled background. 
     72            // We also do this when inside transparency layers, since GDI also can't draw onto a surface with alpha. 
     73            graphicsContext->save(); 
     74            graphicsContext->setFillColor(Color::white); 
     75            textDrawingDC = graphicsContext->getWindowsBitmapContext(textRect); 
     76            SetTextColor(hdc, RGB(0, 0, 0)); 
     77        } else*/ 
     78            SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue())); 
     79 
     80        SetBkMode(hdc, TRANSPARENT); 
     81        SetTextAlign(hdc, TA_LEFT | TA_BASELINE); 
     82 
     83        // Uniscribe gives us offsets to help refine the positioning of combining glyphs. 
     84        FloatSize translation = glyphBuffer.offsetAt(from); 
     85        if (translation.width() || translation.height()) { 
     86            XFORM xform; 
     87            xform.eM11 = 1.0; 
     88            xform.eM12 = 0; 
     89            xform.eM21 = 0; 
     90            xform.eM22 = 1.0; 
     91            xform.eDx = translation.width(); 
     92            xform.eDy = translation.height(); 
     93            ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY); 
     94        } 
     95        ExtTextOut(hdc, point.x(), point.y(), ETO_GLYPH_INDEX, 0, (WCHAR*)glyphBuffer.glyphs(from), numGlyphs, gdiAdvances.data()); 
     96 
     97        /*if (fillColor.hasAlpha() || graphicsContext->inTransparencyLayer()) { 
     98            // TODOD: We have to walk the bits of the bitmap and invert them.  We also copy over the green component value into the alpha value 
     99            // to keep ClearType looking reasonable. 
     100 
     101            // Now that we have drawn the text into a bitmap and inverted it, obtain a CGImageRef mask. 
     102            CGImageRef mask = graphicsContext->releaseWindowsBitmapContextIntoMask(textDrawingDC, textRect); 
     103             
     104            // Apply the mask to the fill color. 
     105            CGContextRef bitmapContext = graphicsContext->getWindowsCompatibleCGBitmapContext(textRect.size()); 
     106            CGFloat red, green, blue, alpha; 
     107            color.getRGBA(red, green, blue, alpha); 
     108            CGContextSetRGBFillColor(context, red, green, blue, alpha); 
     109            CGContextFillRect(bitmapContext, IntRect(0, 0, textRect.width(), textRect.height())); 
     110            CGImageRef fillColorImage = CGBitmapContextCreateImage(bitmapContext); 
     111         
     112            // Apply the mask. 
     113            CGImageRef finalImage = CGImageCreateWithMask(fillColorImage, mask); 
     114 
     115            // The bitmap image needs to be drawn into the HDC. 
     116            graphicsContext->drawImageIntoWindowsContext(hdc, finalImage); 
     117