Home | History | Annotate | Download | only in wince
      1 /*
      2  *  Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved.
      3  *  Copyright (C) 2010 Patrick Gansterer <paroga (at) paroga.com>
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Library General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Library General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Library General Public License
     16  *  along with this library; see the file COPYING.LIB.  If not, write to
     17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  *  Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "SharedBitmap.h"
     23 
     24 #include "GDIExtras.h"
     25 #include "GraphicsContext.h"
     26 #include "GraphicsTypes.h"
     27 #include "TransformationMatrix.h"
     28 #include "WinCEGraphicsExtras.h"
     29 #include <wtf/HashSet.h>
     30 #include <wtf/RefCountedLeakCounter.h>
     31 #include <wtf/PassOwnArrayPtr.h>
     32 #include <wtf/OwnPtr.h>
     33 
     34 #include <windows.h>
     35 
     36 namespace WebCore {
     37 
     38 #ifndef NDEBUG
     39 static WTF::RefCountedLeakCounter sharedBitmapLeakCounter("SharedBitmap");
     40 #endif
     41 
     42 
     43 PassRefPtr<SharedBitmap> SharedBitmap::create(const IntSize& size, BitmapInfo::BitCount bitCount, bool initPixels)
     44 {
     45     RefPtr<SharedBitmap> resultantBitmap = adoptRef(new SharedBitmap(size, bitCount, initPixels));
     46     if (resultantBitmap && !resultantBitmap->bytes())
     47         return 0;
     48     return resultantBitmap.release();
     49 }
     50 
     51 PassRefPtr<SharedBitmap> SharedBitmap::create(const Vector<unsigned>& data, const IntSize& size, bool hasAlpha)
     52 {
     53     RefPtr<SharedBitmap> result = create(size, BitmapInfo::BitCount32, false);
     54     if (!result)
     55         return 0;
     56     memcpy(result->bytes(), data.data(), data.size() * sizeof(unsigned));
     57     result->setHasAlpha(hasAlpha);
     58     return result.release();
     59 }
     60 
     61 SharedBitmap::SharedBitmap(const IntSize& size, BitmapInfo::BitCount bitCount, bool initPixels)
     62     : m_bmpInfo(BitmapInfo::createBottomUp(size, bitCount))
     63     , m_locked(false)
     64     , m_usesTransparentColor(false)
     65     , m_transparentColor(RGB(0, 0, 0))
     66     , m_pixels(0)
     67     , m_hasAlpha(false)
     68     , m_validHeight(abs(size.height()))
     69     , m_hbitmap(0)
     70 {
     71 #ifndef NDEBUG
     72     sharedBitmapLeakCounter.increment();
     73 #endif
     74 
     75     unsigned bufferSize = m_bmpInfo.numPixels();
     76     if (bitCount == BitmapInfo::BitCount16)
     77         bufferSize /= 2;
     78 
     79     m_pixelData = adoptArrayPtr(new unsigned[bufferSize]);
     80     m_pixels = m_pixelData.get();
     81 
     82     if (initPixels)
     83         resetPixels();
     84 }
     85 
     86 SharedBitmap::~SharedBitmap()
     87 {
     88 #ifndef NDEBUG
     89     sharedBitmapLeakCounter.decrement();
     90 #endif
     91 }
     92 
     93 void SharedBitmap::resetPixels(bool black)
     94 {
     95     if (!m_pixels)
     96         return;
     97 
     98     unsigned bufferSize = m_bmpInfo.numPixels();
     99     if (black) {
    100         unsigned bufferSizeInBytes = bufferSize * (is16bit() ? 2 : 4);
    101         memset(m_pixels, 0, bufferSizeInBytes);
    102         return;
    103     }
    104 
    105     if (is16bit()) {
    106         // Fill it with white color
    107         wmemset(static_cast<wchar_t*>(m_pixels), 0xFFFF, bufferSize);
    108         return;
    109     }
    110 
    111     // Make it white but transparent
    112     unsigned* pixel = static_cast<unsigned*>(m_pixels);
    113     const unsigned* bufferEnd = pixel + bufferSize;
    114     while (pixel < bufferEnd)
    115         *pixel++ = 0x00FFFFFF;
    116 }
    117 
    118 static inline unsigned short convert32To16(unsigned pixel)
    119 {
    120     unsigned short r = static_cast<unsigned short>((pixel & 0x00F80000) >> 8);
    121     unsigned short g = static_cast<unsigned short>((pixel & 0x0000FC00) >> 5);
    122     unsigned short b = static_cast<unsigned short>((pixel & 0x000000F8) >> 3);
    123     return r | g | b;
    124 }
    125 
    126 bool SharedBitmap::to16bit()
    127 {
    128     if (m_locked)
    129         return false;
    130     if (is16bit())
    131         return true;
    132 
    133     BitmapInfo newBmpInfo = BitmapInfo::create(m_bmpInfo.size(), BitmapInfo::BitCount16);
    134 
    135     int width = newBmpInfo.width();
    136     int paddedWidth = newBmpInfo.paddedWidth();
    137     int bufferSize = paddedWidth * newBmpInfo.height();
    138     OwnArrayPtr<unsigned> newPixelData = adoptArrayPtr(new unsigned[bufferSize / 2]);
    139     void* newPixels = newPixelData.get();
    140 
    141     if (!newPixels)
    142         return false;
    143 
    144     unsigned short* p16 = static_cast<unsigned short*>(newPixels);
    145     const unsigned* p32 = static_cast<const unsigned*>(m_pixels);
    146 
    147     bool skips = paddedWidth != width;
    148 
    149     const unsigned short* p16end = p16 + bufferSize;
    150     while (p16 < p16end) {
    151         for (unsigned short* p16lineEnd = p16 + width; p16 < p16lineEnd; )
    152             *p16++ = convert32To16(*p32++);
    153 
    154         if (skips)
    155             *p16++ = 0;
    156     }
    157 
    158     if (m_hbitmap)
    159         m_hbitmap = nullptr;
    160     else
    161         m_pixelData = newPixelData.release();
    162 
    163     m_pixels = newPixels;
    164     m_bmpInfo = newBmpInfo;
    165 
    166     setHasAlpha(false);
    167     return true;
    168 }
    169 
    170 bool SharedBitmap::freeMemory()
    171 {
    172     if (m_locked)
    173         return false;
    174 
    175     if (m_hbitmap) {
    176         m_hbitmap = nullptr;
    177         m_pixels = 0;
    178         return true;
    179     }
    180 
    181     if (m_pixels) {
    182         m_pixelData = nullptr;
    183         m_pixels = 0;
    184         return true;
    185     }
    186 
    187     return false;
    188 }
    189 
    190 PassOwnPtr<HBITMAP> SharedBitmap::createHandle(void** pixels, BitmapInfo* bmpInfo, int height, bool use16bit) const
    191 {
    192     if (!m_pixels)
    193         return 0;
    194 
    195     if (height == -1)
    196         height = this->height();
    197     *bmpInfo = BitmapInfo::createBottomUp(IntSize(width(), height), (use16bit || is16bit()) ? BitmapInfo::BitCount16 : BitmapInfo::BitCount32);
    198 
    199     OwnPtr<HBITMAP> hbmp = adoptPtr(CreateDIBSection(0, bmpInfo, DIB_RGB_COLORS, pixels, 0, 0));
    200 
    201     if (!hbmp)
    202         return 0;
    203 
    204     OwnPtr<HDC> bmpDC = adoptPtr(CreateCompatibleDC(0));
    205     HGDIOBJ hOldBmp = SelectObject(bmpDC.get(), hbmp.get());
    206 
    207     StretchDIBits(bmpDC.get(), 0, 0, width(), height, 0, 0, width(), height, m_pixels, &m_bmpInfo, DIB_RGB_COLORS, SRCCOPY);
    208 
    209     SelectObject(bmpDC.get(), hOldBmp);
    210 
    211     return hbmp.release();
    212 }
    213 
    214 bool SharedBitmap::ensureHandle()
    215 {
    216     if (m_hbitmap)
    217         return true;
    218 
    219     if (!m_pixels)
    220         return false;
    221 
    222     if (m_locked)
    223         return false;
    224 
    225     BitmapInfo bmpInfo;
    226     void* pixels;
    227     m_hbitmap = createHandle(&pixels, &bmpInfo, -1, !hasAlpha());
    228 
    229     if (!m_hbitmap)
    230         return false;
    231 
    232     m_pixelData = nullptr;
    233     m_pixels = pixels;
    234     m_bmpInfo = bmpInfo;
    235 
    236     return true;
    237 }
    238 
    239 void SharedBitmap::draw(GraphicsContext* ctxt, const IntRect& dstRect, const IntRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
    240 {
    241     if (!m_pixels)
    242         return;
    243     ctxt->drawBitmap(this, dstRect, srcRect, styleColorSpace, compositeOp);
    244 }
    245 
    246 void SharedBitmap::draw(HDC hdc, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator compositeOp)
    247 {
    248     if (!m_pixels)
    249         return;
    250 
    251     if (dstRect.isEmpty() || srcRect.isEmpty())
    252         return;
    253 
    254     HBITMAP hbitmap = 0;
    255     OwnPtr<HBITMAP> hTempBitmap;
    256     bool usingHandle = compositeOp == CompositeSourceOver && (hasAlpha() && hasAlphaBlendSupport() || usesTransparentColor());
    257 
    258     if (usingHandle) {
    259         if (ensureHandle())
    260             hbitmap = m_hbitmap.get();
    261         else {
    262             void* pixels;
    263             BitmapInfo bmpInfo;
    264             hTempBitmap = createHandle(&pixels, &bmpInfo, -1, usesTransparentColor());
    265             hbitmap = hTempBitmap.get();
    266         }
    267     }
    268     if (!hbitmap) {
    269         // FIXME: handle other composite operation types?
    270         DWORD rop = compositeOp == CompositeCopy ? SRCCOPY
    271             : compositeOp == CompositeXOR ? PATINVERT
    272             : compositeOp == CompositeClear ? WHITENESS
    273             : SRCCOPY;
    274 
    275         StretchDIBits(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(),
    276             srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), m_pixels, &m_bmpInfo, DIB_RGB_COLORS, rop);
    277         return;
    278     }
    279 
    280     OwnPtr<HDC> hmemdc = adoptPtr(CreateCompatibleDC(hdc));
    281     HGDIOBJ hOldBmp = SelectObject(hmemdc.get(), hbitmap);
    282 
    283     if (!usesTransparentColor() && hasAlphaBlendSupport()) {
    284         static const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
    285         bool success = alphaBlendIfSupported(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(), hmemdc.get(),
    286             srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), blend);
    287         ASSERT_UNUSED(success, success);
    288     } else {
    289         TransparentBlt(hdc, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height(), hmemdc.get(),
    290             srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), transparentColor());
    291     }
    292 
    293     SelectObject(hmemdc.get(), hOldBmp);
    294 }
    295 
    296 PassOwnPtr<HBITMAP> SharedBitmap::clipBitmap(const IntRect& rect, bool useAlpha, BitmapInfo& bmpInfo, void*& pixels)
    297 {
    298     if (!bytes())
    299         return 0;
    300 
    301     int oldWidth = width();
    302     int oldHeight = height();
    303     int copyWidth = std::min<int>(rect.width(), oldWidth - rect.x());
    304     int copyHeight = std::min<int>(rect.height(), oldHeight - rect.y());
    305     if (!copyWidth || !copyHeight)
    306         return 0;
    307 
    308     bmpInfo = BitmapInfo::createBottomUp(IntSize(copyWidth, copyHeight), (useAlpha && is32bit()) ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16);
    309     OwnPtr<HBITMAP> newBmp = adoptPtr(CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, &pixels, 0, 0));
    310 
    311     if (!newBmp)
    312         return 0;
    313 
    314     OwnPtr<HDC> dcNew = adoptPtr(CreateCompatibleDC(0));
    315     HGDIOBJ tmpNew = SelectObject(dcNew.get(), newBmp.get());
    316 
    317     StretchDIBits(dcNew.get(), 0, 0, copyWidth, copyHeight, rect.x(), rect.y(), copyWidth, copyHeight,
    318         bytes(), &bitmapInfo(), DIB_RGB_COLORS, SRCCOPY);
    319 
    320     SelectObject(dcNew.get(), tmpNew);
    321     return newBmp.release();
    322 }
    323 
    324 PassRefPtr<SharedBitmap> SharedBitmap::clipBitmap(const IntRect& rect, bool useAlpha)
    325 {
    326     int oldWidth = width();
    327     int oldHeight = height();
    328     int copyWidth = std::min<int>(rect.width(), oldWidth - rect.x());
    329     int copyHeight = std::min<int>(rect.height(), oldHeight - rect.y());
    330     if (!copyWidth || !copyHeight)
    331         return 0;
    332 
    333     RefPtr<SharedBitmap> newBmp = create(IntSize(copyWidth, copyHeight), useAlpha && is32bit() ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16, false);
    334 
    335     if (!newBmp || !newBmp->bytes())
    336         return 0;
    337 
    338     DCHolder dcNew(newBmp.get());
    339 
    340     StretchDIBits(dcNew.get(), 0, 0, copyWidth, copyHeight, rect.x(), rect.y(), copyWidth, copyHeight,
    341         bytes(), &bitmapInfo(), DIB_RGB_COLORS, SRCCOPY);
    342 
    343     return newBmp;
    344 }
    345 
    346 static void drawPatternSimple(HDC hdc, const RECT& destRect, HBITMAP hbmp, const POINT& phase)
    347 {
    348     OwnPtr<HBRUSH> hBrush = adoptPtr(CreatePatternBrush(hbmp));
    349     if (!hBrush)
    350         return;
    351 
    352     POINT oldOrg;
    353     SetBrushOrgEx(hdc, destRect.left - phase.x, destRect.top - phase.y, &oldOrg);
    354     FillRect(hdc, &destRect, hBrush.get());
    355     SetBrushOrgEx(hdc, oldOrg.x, oldOrg.y, 0);
    356 }
    357 
    358 static void drawPatternSimple(HDC hdc, const RECT& destRect, const SharedBitmap* bmp, const SIZE& bmpSize, const POINT& phase)
    359 {
    360     int dstY = destRect.top;
    361     for (int sourceY = phase.y; dstY < destRect.bottom; ) {
    362         int sourceH = std::min<int>(bmpSize.cy - sourceY, destRect.bottom - dstY);
    363         int dstX = destRect.left;
    364         for (int sourceX = phase.x; dstX < destRect.right; ) {
    365             int sourceW = std::min<int>(bmpSize.cx - sourceX, destRect.right - dstX);
    366 
    367             StretchDIBits(hdc, dstX, dstY, sourceW, sourceH, sourceX, sourceY, sourceW, sourceH,
    368                 bmp->bytes(), &bmp->bitmapInfo(), DIB_RGB_COLORS, SRCCOPY);
    369 
    370             dstX += sourceW;
    371             sourceX = 0;
    372         }
    373 
    374         dstY += sourceH;
    375         sourceY = 0;
    376     }
    377 }
    378 
    379 static LONG normalizePhase(LONG phase, int limit)
    380 {
    381     if (!phase || limit < 2)
    382         return 0;
    383 
    384     if (limit == 2)
    385         return phase & 1;
    386 
    387     if (phase < 0) {
    388         phase = -phase;
    389         if (phase > limit)
    390             phase = static_cast<LONG>(static_cast<unsigned>(phase) % static_cast<unsigned>(limit));
    391         if (phase)
    392             phase = limit - phase;
    393         return phase;
    394     }
    395 
    396     if (phase < limit)
    397         return phase;
    398 
    399     return static_cast<LONG>(static_cast<unsigned>(phase) % static_cast<unsigned>(limit));
    400 }
    401 
    402 void SharedBitmap::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
    403                         const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize)
    404 {
    405     if (!m_pixels)
    406         return;
    407     ctxt->drawBitmapPattern(this, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, origSourceSize);
    408 }
    409 
    410 void SharedBitmap::drawPattern(HDC hdc, const AffineTransform& transform, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
    411                         const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize)
    412 {
    413     if (!m_pixels)
    414         return;
    415 
    416     if (tileRectIn.width() <= 0 || tileRectIn.height() <= 0)
    417         return;
    418 
    419     bool useAlpha = op == CompositeSourceOver && hasAlpha() && is32bit();
    420 
    421     int bmpWidth = width();
    422     int bmpHeight = height();
    423 
    424     FloatRect tileRect(tileRectIn);
    425     if (bmpWidth != origSourceSize.width()) {
    426         double rate = static_cast<double>(bmpWidth) / origSourceSize.width();
    427         double temp = tileRect.width() * rate;
    428         tileRect.setX(tileRect.x() * rate);
    429         tileRect.setWidth(temp);
    430         temp = tileRect.height() * rate;
    431         tileRect.setY(tileRect.y() * rate);
    432         tileRect.setHeight(temp);
    433     }
    434 
    435     OwnPtr<HBITMAP> clippedBmp;
    436 
    437     if (tileRect.x() || tileRect.y() || tileRect.width() != bmpWidth || tileRect.height() != bmpHeight) {
    438         BitmapInfo patternBmpInfo;
    439         void* patternPixels;
    440         clippedBmp = clipBitmap(IntRect(tileRect), useAlpha, patternBmpInfo, patternPixels);
    441         if (!clippedBmp)
    442             return;
    443 
    444         bmpWidth = tileRect.width();
    445         bmpHeight = tileRect.height();
    446     }
    447 
    448     AffineTransform tf = patternTransform * transform;
    449 
    450     FloatRect trRect = tf.mapRect(destRect);
    451 
    452     RECT clipBox;
    453     int clipType = GetClipBox(hdc, &clipBox);
    454     if (clipType == SIMPLEREGION)
    455         trRect.intersect(FloatRect(clipBox.left, clipBox.top, clipBox.right - clipBox.left, clipBox.bottom - clipBox.top));
    456     else if (clipType == COMPLEXREGION) {
    457         OwnPtr<HRGN> clipRgn = adoptPtr(CreateRectRgn(0, 0, 0, 0));
    458         if (GetClipRgn(hdc, clipRgn.get()) > 0) {
    459             DWORD regionDataSize = GetRegionData(clipRgn.get(), sizeof(RGNDATA), 0);
    460             if (regionDataSize) {
    461                 Vector<RGNDATA> regionData(regionDataSize);
    462                 GetRegionData(clipRgn.get(), regionDataSize, regionData.data());
    463                 RECT* rect = reinterpret_cast<RECT*>(regionData[0].Buffer);
    464                 for (DWORD i = 0; i < regionData[0].rdh.nCount; ++i, ++rect)
    465                     trRect.intersect(FloatRect(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top));
    466             }
    467         }
    468     }
    469 
    470     if (trRect.width() <= 0 || trRect.height() <= 0)
    471         return;
    472 
    473     trRect.inflate(1);
    474     IntRect visibleDstRect = enclosingIntRect(tf.inverse().mapRect(trRect));
    475     visibleDstRect.intersect(IntRect(destRect));
    476 
    477     if (visibleDstRect.width() <= 0 || visibleDstRect.height() <= 0)
    478         return;
    479 
    480     trRect = tf.mapRect(visibleDstRect);
    481     RECT dstRectWin = {
    482         stableRound(trRect.x()),
    483         stableRound(trRect.y()),
    484         stableRound(trRect.maxX()),
    485         stableRound(trRect.maxY()),
    486     };
    487     if (dstRectWin.right <= dstRectWin.left || dstRectWin.bottom <= dstRectWin.top)
    488         return;
    489 
    490     SIZE bmpSize = { bmpWidth, bmpHeight };
    491 
    492     // Relative to destination, in bitmap pixels
    493     POINT phaseWin = { stableRound(visibleDstRect.x() - phase.x()), stableRound(visibleDstRect.y() - phase.y()) };
    494     phaseWin.x = normalizePhase(phaseWin.x, bmpSize.cx);
    495     phaseWin.y = normalizePhase(phaseWin.y, bmpSize.cy);
    496 
    497     RECT srcRectWin = {
    498         0,
    499         0,
    500         stableRound(visibleDstRect.maxX()) - stableRound(visibleDstRect.x()),
    501         stableRound(visibleDstRect.maxY()) - stableRound(visibleDstRect.y())
    502     };
    503     if (srcRectWin.right <= 0 || srcRectWin.bottom <= 0)
    504         return;
    505 
    506     BitmapInfo bmpInfo = BitmapInfo::createBottomUp(IntSize(srcRectWin.right, srcRectWin.bottom), useAlpha ? BitmapInfo::BitCount32 : BitmapInfo::BitCount16);
    507     void* pixels;
    508     OwnPtr<HBITMAP> hbmpTemp = adoptPtr(CreateDIBSection(0, &bmpInfo, DIB_RGB_COLORS, &pixels, 0, 0));
    509 
    510     if (!hbmpTemp)
    511         return;
    512 
    513     OwnPtr<HDC> hmemdc = adoptPtr(CreateCompatibleDC(hdc));
    514     HGDIOBJ oldBmp = SelectObject(hmemdc.get(), hbmpTemp.get());
    515     if (clippedBmp)
    516         drawPatternSimple(hmemdc.get(), srcRectWin, clippedBmp.get(), phaseWin);
    517     else if ((op != CompositeSourceOver || canUseDIBits()) && srcRectWin.right <= bmpSize.cx * 2 && srcRectWin.bottom <= bmpSize.cy * 2)
    518         drawPatternSimple(hmemdc.get(), srcRectWin, this, bmpSize, phaseWin);
    519     else if (ensureHandle())
    520         drawPatternSimple(hmemdc.get(), srcRectWin, getHandle(), phaseWin);
    521     else {
    522         void* pixels;
    523         BitmapInfo bmpInfo;
    524         OwnPtr<HBITMAP> hbmp = createHandle(&pixels, &bmpInfo, -1, false);
    525         if (hbmp)
    526             drawPatternSimple(hmemdc.get(), srcRectWin, hbmp.get(), phaseWin);
    527         else {
    528             SelectObject(hmemdc.get(), oldBmp);
    529             return;
    530         }
    531     }
    532 
    533     if (useAlpha && hasAlphaBlendSupport()) {
    534         static const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
    535         bool success = alphaBlendIfSupported(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left, dstRectWin.bottom - dstRectWin.top,
    536             hmemdc.get(), 0, 0, srcRectWin.right, srcRectWin.bottom, blend);
    537         ASSERT_UNUSED(success, success);
    538     } else if (useAlpha && !hasAlphaBlendSupport() || op == CompositeSourceOver && usesTransparentColor()) {
    539         TransparentBlt(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left,
    540             dstRectWin.bottom - dstRectWin.top, hmemdc.get(), 0, 0, srcRectWin.right, srcRectWin.bottom, transparentColor());
    541     } else {
    542         DWORD bmpOp = op == CompositeCopy ? SRCCOPY
    543                     : op == CompositeSourceOver ? SRCCOPY
    544                     : op == CompositeXOR ? PATINVERT
    545                     : op == CompositeClear ? WHITENESS
    546                     : SRCCOPY; // FIXEME: other types?
    547 
    548         StretchDIBits(hdc, dstRectWin.left, dstRectWin.top, dstRectWin.right - dstRectWin.left,
    549             dstRectWin.bottom - dstRectWin.top, 0, 0, srcRectWin.right, srcRectWin.bottom,
    550             pixels, &bmpInfo, DIB_RGB_COLORS, bmpOp);
    551     }
    552     SelectObject(hmemdc.get(), oldBmp);
    553 }
    554 
    555 SharedBitmap::DCProvider* SharedBitmap::s_dcProvider = new SharedBitmap::DCProvider;
    556 
    557 HDC SharedBitmap::DCProvider::getDC(SharedBitmap* bmp, unsigned* key)
    558 {
    559     if (!bmp || !bmp->ensureHandle())
    560         return 0;
    561 
    562     HDC hdc = CreateCompatibleDC(0);
    563     if (!hdc)
    564         return 0;
    565 
    566     *key = reinterpret_cast<unsigned>(SelectObject(hdc, bmp->getHandle()));
    567     RECT rect = { 0, 0, bmp->width(), bmp->height() };
    568     OwnPtr<HRGN> clipRgn = adoptPtr(CreateRectRgnIndirect(&rect));
    569     SelectClipRgn(hdc, clipRgn.get());
    570 
    571     return hdc;
    572 }
    573 
    574 void SharedBitmap::DCProvider::releaseDC(SharedBitmap*, HDC hdc, unsigned key1)
    575 {
    576     if (!hdc)
    577         return;
    578 
    579     SelectObject(hdc, reinterpret_cast<HGDIOBJ>(key1));
    580     DeleteDC(hdc);
    581 }
    582 
    583 void SharedBitmap::clearPixels(const IntRect& rect)
    584 {
    585     if (!m_pixels)
    586         return;
    587 
    588     IntRect bmpRect(0, 0, width(), height());
    589     bmpRect.intersect(rect);
    590     if (is16bit()) {
    591         unsigned w = m_bmpInfo.paddedWidth();
    592         unsigned short* dst = static_cast<unsigned short*>(m_pixels);
    593         dst += bmpRect.y() * w + bmpRect.x();
    594         int wordsToSet = bmpRect.width();
    595         const unsigned short* dstEnd = dst + bmpRect.height() * w;
    596         while (dst < dstEnd) {
    597             wmemset(reinterpret_cast<wchar_t*>(dst), 0, wordsToSet);
    598             dst += w;
    599         }
    600         return;
    601     }
    602 
    603     unsigned w = width();
    604     unsigned* dst = static_cast<unsigned*>(m_pixels);
    605     dst += bmpRect.y() * w + bmpRect.x();
    606     int wordsToSet = bmpRect.width() * 2;
    607     const unsigned* dstEnd = dst + bmpRect.height() * w;
    608     while (dst < dstEnd) {
    609         wmemset(reinterpret_cast<wchar_t*>(dst), 0, wordsToSet);
    610         dst += w;
    611     }
    612 }
    613 
    614 } // namespace WebCore
    615