Changeset 31246 in webkit


Ignore:
Timestamp:
Mar 24, 2008 10:55:58 AM (16 years ago)
Author:
mitz@apple.com
Message:

Reviewed by Sam Weinig.

  • fix <rdar://problem/5792582> CSS opacity does not work with GDI text
  • fix <rdar://problem/5792619> non-opaque CSS colors do not work with GDI text (RGBA, HSLA)
  • fix <rdar://problem/5792624> GDI text can't be stroked/filled independently
  • make text-shadow work with GDI text
  • make -webkit-background-clip: text work with GDI text
  • platform/graphics/GraphicsContext.cpp: (WebCore::GraphicsContext::setShadow): Made this a shared method that updates the state and calls the platform-specific method. (WebCore::GraphicsContext::clearShadow): Ditto. (WebCore::GraphicsContext::getShadow): Added.
  • platform/graphics/GraphicsContext.h: (WebCore::GraphicsContext::WindowsBitmap): Added this class that represents a bitmap with a Windows device context that GDI can draw into.
  • platform/graphics/GraphicsContextPrivate.h: (WebCore::GraphicsContextState::GraphicsContextState): Added the shadow parameters to the graphics state.
  • platform/graphics/cairo/GraphicsContextCairo.cpp: (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform- specific implementation to this. (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform- specific implementation to this.
  • platform/graphics/cg/GraphicsContextCG.cpp: (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform- specific implementation to this. (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform- specific implementation to this.
  • platform/graphics/qt/GraphicsContextQt.cpp: (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform- specific implementation to this. (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform- specific implementation to this.
  • platform/graphics/win/FontCGWin.cpp: (WebCore::toCGFloat): Added. Converts a Windows FIXED. (WebCore::createPathForGlyph): Added. Retrieves a glyph's hinted outline from GDI and creates a CGPath containing it. (WebCore::Font::drawGlyphs): Added two code paths in the GDI case. The existing code path, which uses GDI to draw text directly to the graphics context, is used for opaque-colored, non-transformed, non-stroked, non-shadowed text in a GDI-backed graphics context that is not in a transparency layer. An additional code path is used for non-stroked text in all other cases. It uses GDI to draw black text into an all-white Windows bitmap, then uses the green channel as a mask to create a bitmap with the desired fill color and alpha. The bitmap is then drawn into the graphics context, at which time transparency layers, transforms and shadows are handled properly. A third code path is used for stroked text. It constructs a path from hinted glyph outlines retrieved from GDI and strokes (and optionally fills) it.
  • platform/graphics/win/GraphicsContextCGWin.cpp: (WebCore::GraphicsContext::getWindowsContext): Added a mayCreateBitmap parameter. When false, prevents this method from creating a Windows device context if the graphics context does not already have one. (WebCore::GraphicsContext::releaseWindowsContext): Added a mayCreateBitmap parameter to match getWindowsContext(). (WebCore::GraphicsContext::WindowsBitmap::WindowsBitmap): (WebCore::GraphicsContext::WindowsBitmap::~WindowsBitmap): (WebCore::GraphicsContext::createWindowsBitmap): Added. (WebCore::GraphicsContext::drawWindowsBitmap): Added. Draws the bitmap as a non-alpha-premultiplied image.
Location:
trunk/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r31245 r31246  
     12008-03-24  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        - fix <rdar://problem/5792582> CSS opacity does not work with GDI text
     6        - fix <rdar://problem/5792619> non-opaque CSS colors do not work with GDI text (RGBA, HSLA)
     7        - fix <rdar://problem/5792624> GDI text can't be stroked/filled independently
     8        - make text-shadow work with GDI text
     9        - make -webkit-background-clip: text work with GDI text
     10
     11        * platform/graphics/GraphicsContext.cpp:
     12        (WebCore::GraphicsContext::setShadow): Made this a shared method that
     13        updates the state and calls the platform-specific method.
     14        (WebCore::GraphicsContext::clearShadow): Ditto.
     15        (WebCore::GraphicsContext::getShadow): Added.
     16
     17        * platform/graphics/GraphicsContext.h:
     18        (WebCore::GraphicsContext::WindowsBitmap): Added this class that
     19        represents a bitmap with a Windows device context that GDI can draw into.
     20
     21        * platform/graphics/GraphicsContextPrivate.h:
     22        (WebCore::GraphicsContextState::GraphicsContextState): Added the shadow
     23        parameters to the graphics state.
     24
     25        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     26        (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform-
     27        specific implementation to this.
     28        (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform-
     29        specific implementation to this.
     30
     31        * platform/graphics/cg/GraphicsContextCG.cpp:
     32        (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform-
     33        specific implementation to this.
     34        (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform-
     35        specific implementation to this.
     36
     37        * platform/graphics/qt/GraphicsContextQt.cpp:
     38        (WebCore::GraphicsContext::setPlatformShadow): Renamed the platform-
     39        specific implementation to this.
     40        (WebCore::GraphicsContext::clearPlatformShadow): Renamed the platform-
     41        specific implementation to this.
     42
     43        * platform/graphics/win/FontCGWin.cpp:
     44        (WebCore::toCGFloat): Added. Converts a Windows FIXED.
     45        (WebCore::createPathForGlyph): Added. Retrieves a glyph's hinted
     46        outline from GDI and creates a CGPath containing it.
     47        (WebCore::Font::drawGlyphs): Added two code paths in the GDI case.
     48        The existing code path, which uses GDI to draw text directly to the
     49        graphics context, is used for opaque-colored, non-transformed,
     50        non-stroked, non-shadowed text in a GDI-backed graphics context that is
     51        not in a transparency layer.
     52        An additional code path is used for non-stroked text in all other cases.
     53        It uses GDI to draw black text into an all-white Windows bitmap, then
     54        uses the green channel as a mask to create a bitmap with the desired
     55        fill color and alpha. The bitmap is then drawn into the graphics
     56        context, at which time transparency layers, transforms and shadows are
     57        handled properly.
     58        A third code path is used for stroked text. It constructs a path from
     59        hinted glyph outlines retrieved from GDI and strokes (and optionally
     60        fills) it.
     61
     62        * platform/graphics/win/GraphicsContextCGWin.cpp:
     63        (WebCore::GraphicsContext::getWindowsContext): Added a mayCreateBitmap
     64        parameter. When false, prevents this method from creating a Windows
     65        device context if the graphics context does not already have one.
     66        (WebCore::GraphicsContext::releaseWindowsContext): Added a
     67        mayCreateBitmap parameter to match getWindowsContext().
     68        (WebCore::GraphicsContext::WindowsBitmap::WindowsBitmap):
     69        (WebCore::GraphicsContext::WindowsBitmap::~WindowsBitmap):
     70        (WebCore::GraphicsContext::createWindowsBitmap): Added.
     71        (WebCore::GraphicsContext::drawWindowsBitmap): Added. Draws the bitmap
     72        as a non-alpha-premultiplied image.
     73
    1742008-03-24  Kevin McCullough <kmccullough@apple.com>
    275
  • trunk/WebCore/platform/graphics/GraphicsContext.cpp

    r31200 r31246  
    138138}
    139139
     140void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color)
     141{
     142    m_common->state.shadowSize = size;
     143    m_common->state.shadowBlur = blur;
     144    m_common->state.shadowColor = color;
     145    setPlatformShadow(size, blur, color);
     146}
     147
     148void GraphicsContext::clearShadow()
     149{
     150    m_common->state.shadowSize = IntSize();
     151    m_common->state.shadowBlur = 0;
     152    m_common->state.shadowColor = Color();
     153    clearPlatformShadow();
     154}
     155
     156void GraphicsContext::getShadow(IntSize& size, int& blur, Color& color)
     157{
     158    size = m_common->state.shadowSize;
     159    blur = m_common->state.shadowBlur;
     160    color = m_common->state.shadowColor;
     161}
     162
    140163float GraphicsContext::strokeThickness() const
    141164{
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r31200 r31246  
    192192
    193193        void setShadow(const IntSize&, int blur, const Color&);
     194        void getShadow(IntSize&, int&, Color&);
    194195        void clearShadow();
    195196
     
    229230        GraphicsContext(HDC); // FIXME: To be removed.
    230231        bool inTransparencyLayer() const;
    231         HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
    232         void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true);    // The passed in HDC should be the one handed back by getWindowsContext.
     232        HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
     233        void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);    // The passed in HDC should be the one handed back by getWindowsContext.
     234
     235        class WindowsBitmap : public Noncopyable {
     236        public:
     237            WindowsBitmap(HDC, IntSize);
     238            ~WindowsBitmap();
     239
     240            HDC hdc() const { return m_hdc; }
     241            UInt8* buffer() const { return m_bitmapBuffer; }
     242            unsigned bufferLength() const { return m_bitmapBufferLength; }
     243            IntSize size() const { return m_size; }
     244            unsigned bytesPerRow() const { return m_bytesPerRow; }
     245
     246        private:
     247            HDC m_hdc;
     248            HBITMAP m_bitmap;
     249            UInt8* m_bitmapBuffer;
     250            unsigned m_bitmapBufferLength;
     251            IntSize m_size;
     252            unsigned m_bytesPerRow;
     253        };
     254
     255        WindowsBitmap* createWindowsBitmap(IntSize);
     256        // The bitmap should be non-premultiplied.
     257        void drawWindowsBitmap(WindowsBitmap*, const IntPoint&);
    233258#endif
    234259
     
    254279        void setPlatformFillColor(const Color&);
    255280        void setPlatformFont(const Font& font);
     281        void setPlatformShadow(const IntSize&, int blur, const Color&);
     282        void clearPlatformShadow();
    256283
    257284        int focusRingWidth() const;
  • trunk/WebCore/platform/graphics/GraphicsContextPrivate.h

    r30933 r31246  
    3939            , textDrawingMode(cTextFill)
    4040            , paintingDisabled(false)
     41            , shadowBlur(0)
    4142        {
    4243        }
     
    4950        int textDrawingMode;
    5051        bool paintingDisabled;
     52        IntSize shadowSize;
     53        unsigned shadowBlur;
     54        Color shadowColor;
    5155    };
    5256
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r30533 r31246  
    584584
    585585
    586 void GraphicsContext::setShadow(IntSize const&, int, Color const&)
     586void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&)
    587587{
    588588    notImplemented();
    589589}
    590590
    591 void GraphicsContext::clearShadow()
     591void GraphicsContext::clearPlatformShadow()
    592592{
    593593    notImplemented();
  • trunk/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

    r31200 r31246  
    514514}
    515515
    516 void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color)
     516void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
    517517{
    518518    // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
     
    553553}
    554554
    555 void GraphicsContext::clearShadow()
     555void GraphicsContext::clearPlatformShadow()
    556556{
    557557    if (paintingDisabled())
  • trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r30337 r31246  
    600600}
    601601
    602 void GraphicsContext::setShadow(const IntSize& pos, int blur, const Color &color)
     602void GraphicsContext::setPlatformShadow(const IntSize& pos, int blur, const Color &color)
    603603{
    604604    if (paintingDisabled())
     
    611611}
    612612
    613 void GraphicsContext::clearShadow()
     613void GraphicsContext::clearPlatformShadow()
    614614{
    615615    if (paintingDisabled())
  • trunk/WebCore/platform/graphics/win/FontCGWin.cpp

    r30056 r31246  
    2727#include "Font.h"
    2828
     29#include "AffineTransform.h"
     30#include "FloatConversion.h"
    2931#include "GlyphBuffer.h"
    3032#include "GraphicsContext.h"
     
    4042const int syntheticObliqueAngle = 14;
    4143
     44static inline CGFloat toCGFloat(FIXED f)
     45{
     46    return f.value + f.fract / CGFloat(65536.0);
     47}
     48
     49static CGPathRef createPathForGlyph(HDC hdc, Glyph glyph)
     50{
     51    CGMutablePathRef path = CGPathCreateMutable();
     52
     53    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
     54    GLYPHMETRICS glyphMetrics;
     55    // GGO_NATIVE matches the outline perfectly when Windows font smoothing is off.
     56    // GGO_NATIVE | GGO_UNHINTED does not match perfectly either when Windows font smoothing is on or off.
     57    DWORD outlineLength = GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, 0, 0, &identity);
     58    ASSERT(outlineLength >= 0);
     59    if (outlineLength < 0)
     60        return path;
     61
     62    Vector<UInt8> outline(outlineLength);
     63    GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, outlineLength, outline.data(), &identity);
     64
     65    unsigned offset = 0;
     66    while (offset < outlineLength) {
     67        LPTTPOLYGONHEADER subpath = reinterpret_cast<LPTTPOLYGONHEADER>(outline.data() + offset);
     68        ASSERT(subpath->dwType == TT_POLYGON_TYPE);
     69        if (subpath->dwType != TT_POLYGON_TYPE)
     70            return path;
     71
     72        CGPathMoveToPoint(path, 0, toCGFloat(subpath->pfxStart.x), toCGFloat(subpath->pfxStart.y));
     73
     74        unsigned subpathOffset = sizeof(*subpath);
     75        while (subpathOffset < subpath->cb) {
     76            LPTTPOLYCURVE segment = reinterpret_cast<LPTTPOLYCURVE>(reinterpret_cast<UInt8*>(subpath) + subpathOffset);
     77            switch (segment->wType) {
     78                case TT_PRIM_LINE:
     79                    for (unsigned i = 0; i < segment->cpfx; i++)
     80                        CGPathAddLineToPoint(path, 0, toCGFloat(segment->apfx[i].x), toCGFloat(segment->apfx[i].y));
     81                    break;
     82
     83                case TT_PRIM_QSPLINE:
     84                    for (unsigned i = 0; i < segment->cpfx; i++) {
     85                        CGFloat x = toCGFloat(segment->apfx[i].x);
     86                        CGFloat y = toCGFloat(segment->apfx[i].y);
     87                        CGFloat cpx;
     88                        CGFloat cpy;
     89
     90                        if (i == segment->cpfx - 2) {
     91                            cpx = toCGFloat(segment->apfx[i + 1].x);
     92                            cpy = toCGFloat(segment->apfx[i + 1].y);
     93                            i++;
     94                        } else {
     95                            cpx = (toCGFloat(segment->apfx[i].x) + toCGFloat(segment->apfx[i + 1].x)) / 2;
     96                            cpy = (toCGFloat(segment->apfx[i].y) + toCGFloat(segment->apfx[i + 1].y)) / 2;
     97                        }
     98
     99                        CGPathAddQuadCurveToPoint(path, 0, x, y, cpx, cpy);
     100                    }
     101                    break;
     102
     103                case TT_PRIM_CSPLINE:
     104                    for (unsigned i = 0; i < segment->cpfx; i += 3) {
     105                        CGFloat cp1x = toCGFloat(segment->apfx[i].x);
     106                        CGFloat cp1y = toCGFloat(segment->apfx[i].y);
     107                        CGFloat cp2x = toCGFloat(segment->apfx[i + 1].x);
     108                        CGFloat cp2y = toCGFloat(segment->apfx[i + 1].y);
     109                        CGFloat x = toCGFloat(segment->apfx[i + 2].x);
     110                        CGFloat y = toCGFloat(segment->apfx[i + 2].y);
     111
     112                        CGPathAddCurveToPoint(path, 0, cp1x, cp1y, cp2x, cp2y, x, y);
     113                    }
     114                    break;
     115
     116                default:
     117                    ASSERT_NOT_REACHED();
     118                    return path;
     119            }
     120
     121            subpathOffset += sizeof(*segment) + (segment->cpfx - 1) * sizeof(segment->apfx[0]);
     122        }
     123        CGPathCloseSubpath(path);
     124        offset += subpath->cb;
     125    }
     126    return path;
     127}
     128
    42129void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
    43130                      int from, int numGlyphs, const FloatPoint& point) const
    44131{
    45132    if (font->m_font.useGDI()) {
    46         // FIXME: Support alpha blending.
    47         // FIXME: Support text stroke/fill.
    48         // FIXME: Support text shadow.
    49133        Color fillColor = graphicsContext->fillColor();
    50         if (fillColor.alpha() == 0)
     134        if (!fillColor.alpha())
    51135            return;
    52136
     
    59143        }
    60144
    61         // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
    62         int lineGap = font->lineGap();
    63         IntRect textRect(point.x() - lineGap, point.y() - font->ascent() - lineGap, totalWidth + 2 * lineGap, font->lineSpacing());
    64         HDC hdc = graphicsContext->getWindowsContext(textRect);
     145        bool drawIntoBitmap = false;
     146        int drawingMode = graphicsContext->textDrawingMode();
     147        if (drawingMode == cTextFill) {
     148            drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer();
     149            if (!drawIntoBitmap) {
     150                IntSize size;
     151                int blur;
     152                Color color;
     153                graphicsContext->getShadow(size, blur, color);
     154                drawIntoBitmap = !size.isEmpty() || blur;
     155            }
     156        }
     157
     158        HDC hdc = 0;
     159        OwnPtr<GraphicsContext::WindowsBitmap> bitmap;
     160        IntRect textRect;
     161        if (!drawIntoBitmap)
     162            hdc = graphicsContext->getWindowsContext(textRect, true, false);
     163        if (!hdc) {
     164            drawIntoBitmap = true;
     165            // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
     166            // FIXME: Can get glyphs' optical bounds (even from CG) to get this right.
     167            // FIXME: Line gap does not make sense as a horizontal distance.
     168            int lineGap = font->lineGap();
     169            textRect = IntRect(point.x() - lineGap, point.y() - font->ascent() - lineGap, totalWidth + 2 * lineGap, font->lineSpacing());
     170            bitmap.set(graphicsContext->createWindowsBitmap(textRect.size()));
     171            memset(bitmap->buffer(), 255, bitmap->bufferLength());
     172            hdc = bitmap->hdc();
     173
     174            XFORM xform;
     175            xform.eM11 = 1.0f;
     176            xform.eM12 = 0.0f;
     177            xform.eM21 = 0.0f;
     178            xform.eM22 = 1.0f;
     179            xform.eDx = -textRect.x();
     180            xform.eDy = -textRect.y();
     181            SetWorldTransform(hdc, &xform);
     182        }
     183
    65184        SelectObject(hdc, font->m_font.hfont());
    66185
    67186        // Set the correct color.
    68         HDC textDrawingDC = hdc;
    69         SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue()));
     187        if (drawIntoBitmap)
     188            SetTextColor(hdc, RGB(0, 0, 0));
     189        else
     190            SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue()));
    70191
    71192        SetBkMode(hdc, TRANSPARENT);
     
    84205            ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
    85206        }
    86         ExtTextOut(hdc, point.x(), point.y(), ETO_GLYPH_INDEX, 0, (WCHAR*)glyphBuffer.glyphs(from), numGlyphs, gdiAdvances.data());
    87 
    88         graphicsContext->releaseWindowsContext(hdc, textRect);
     207
     208        if (drawingMode == cTextFill)
     209            ExtTextOut(hdc, point.x(), point.y(), ETO_GLYPH_INDEX, 0, (WCHAR*)glyphBuffer.glyphs(from), numGlyphs, gdiAdvances.data());
     210        else {
     211            RetainPtr<CGMutablePathRef> path(AdoptCF, CGPathCreateMutable());
     212
     213            XFORM xform;
     214            GetWorldTransform(hdc, &xform);
     215            AffineTransform hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy);
     216            CGAffineTransform initialGlyphTransform = hdcTransform.isInvertible() ? hdcTransform.inverse() : CGAffineTransformIdentity;
     217            initialGlyphTransform.tx = 0;
     218            initialGlyphTransform.ty = 0;
     219            CGAffineTransform glyphTranslation = CGAffineTransformIdentity;
     220
     221            for (unsigned i = 0; i < numGlyphs; ++i) {
     222                RetainPtr<CGPathRef> glyphPath(AdoptCF, createPathForGlyph(hdc, glyphBuffer.glyphAt(from + i)));
     223                CGAffineTransform glyphTransform = CGAffineTransformConcat(initialGlyphTransform, glyphTranslation);
     224                CGPathAddPath(path.get(), &glyphTransform, glyphPath.get());
     225                glyphTranslation = CGAffineTransformTranslate(glyphTranslation, gdiAdvances[i], 0);
     226            }
     227
     228            CGContextRef cgContext = graphicsContext->platformContext();
     229            CGContextSaveGState(cgContext);
     230
     231            BOOL fontSmoothingEnabled = false;
     232            SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothingEnabled, 0);
     233            CGContextSetShouldAntialias(cgContext, fontSmoothingEnabled);
     234
     235            CGContextScaleCTM(cgContext, 1.0, -1.0);
     236            CGContextTranslateCTM(cgContext, point.x() + glyphBuffer.offsetAt(from).width(), -(point.y() + glyphBuffer.offsetAt(from).height()));
     237
     238            if (drawingMode & cTextFill) {
     239                CGContextAddPath(cgContext, path.get());
     240                CGContextFillPath(cgContext);
     241            }
     242            if (drawingMode & cTextStroke) {
     243                CGContextAddPath(cgContext, path.get());
     244                CGContextStrokePath(cgContext);
     245            }
     246            CGContextRestoreGState(cgContext);
     247        }
     248
     249        if (drawIntoBitmap) {
     250            UInt8* buffer = bitmap->buffer();
     251            unsigned bufferLength = bitmap->bufferLength();
     252            for (unsigned i = 0; i < bufferLength; i += 4) {
     253                // Use green, which is always in the middle.
     254                UInt8 alpha = (255 - buffer[i + 1]) * fillColor.alpha() / 255;
     255                buffer[i] = fillColor.blue();
     256                buffer[i + 1] = fillColor.green();
     257                buffer[i + 2] = fillColor.red();
     258                buffer[i + 3] = alpha;
     259            }
     260            graphicsContext->drawWindowsBitmap(bitmap.get(), textRect.topLeft());
     261        } else
     262            graphicsContext->releaseWindowsContext(hdc, textRect, true, false);
     263
    89264        return;
    90265    }
  • trunk/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp

    r30533 r31246  
    7777bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
    7878
    79 HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend)
    80 {
    81     if (inTransparencyLayer()) {
     79// FIXME: Is it possible to merge getWindowsContext and createWindowsBitmap into a single API
     80// suitable for all clients?
     81HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
     82{
     83    // FIXME: Should a bitmap be created also when a shadow is set?
     84    if (mayCreateBitmap && inTransparencyLayer()) {
    8285        if (dstRect.isEmpty())
    8386            return 0;
     
    134137}
    135138
    136 void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend)
    137 {
    138     if (hdc && inTransparencyLayer()) {
     139void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
     140{
     141    if (mayCreateBitmap && hdc && inTransparencyLayer()) {
    139142        if (dstRect.isEmpty())
    140143            return;
     
    167170
    168171    m_data->restore();
     172}
     173
     174GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, IntSize size)
     175    : m_hdc(0)
     176    , m_size(size)
     177{
     178    BITMAPINFO bitmapInfo;
     179    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     180    bitmapInfo.bmiHeader.biWidth = m_size.width();
     181    bitmapInfo.bmiHeader.biHeight = m_size.height();
     182    bitmapInfo.bmiHeader.biPlanes = 1;
     183    bitmapInfo.bmiHeader.biBitCount = 32;
     184    bitmapInfo.bmiHeader.biCompression = BI_RGB;
     185    bitmapInfo.bmiHeader.biSizeImage = 0;
     186    bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
     187    bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
     188    bitmapInfo.bmiHeader.biClrUsed = 0;
     189    bitmapInfo.bmiHeader.biClrImportant = 0;
     190
     191    m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&m_bitmapBuffer), 0, 0);
     192    if (!m_bitmap)
     193        return;
     194
     195    m_hdc = CreateCompatibleDC(hdc);
     196    SelectObject(m_hdc, m_bitmap);
     197
     198    BITMAP bmpInfo;
     199    GetObject(m_bitmap, sizeof(bmpInfo), &bmpInfo);
     200    m_bytesPerRow = bmpInfo.bmWidthBytes;
     201    m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
     202
     203    SetGraphicsMode(m_hdc, GM_ADVANCED);
     204}
     205
     206GraphicsContext::WindowsBitmap::~WindowsBitmap()
     207{
     208    if (!m_bitmap)
     209        return;
     210
     211    DeleteDC(m_hdc);
     212    DeleteObject(m_bitmap);
     213}
     214
     215GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize size)
     216{
     217    return new WindowsBitmap(m_data->m_hdc, size);
     218}
     219
     220void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& point)
     221{
     222    RetainPtr<CGColorSpaceRef> deviceRGB(AdoptCF, CGColorSpaceCreateDeviceRGB());
     223    RetainPtr<CFDataRef> imageData(AdoptCF, CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, image->buffer(), image->bufferLength(), kCFAllocatorNull));
     224    RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(imageData.get()));
     225    RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(image->size().width(), image->size().height(), 8, 32, image->bytesPerRow(), deviceRGB.get(),
     226                                                         kCGBitmapByteOrder32Little | kCGImageAlphaFirst, dataProvider.get(), 0, true, kCGRenderingIntentDefault));
     227    CGContextDrawImage(m_data->m_cgContext, CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());   
    169228}
    170229
Note: See TracChangeset for help on using the changeset viewer.