• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved.
3  *  Copyright (C) 2010 Patrick Gansterer <paroga@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 
create(const IntSize & size,BitmapInfo::BitCount bitCount,bool initPixels)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 
create(const Vector<unsigned> & data,const IntSize & size,bool hasAlpha)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 
SharedBitmap(const IntSize & size,BitmapInfo::BitCount bitCount,bool initPixels)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 
~SharedBitmap()86 SharedBitmap::~SharedBitmap()
87 {
88 #ifndef NDEBUG
89     sharedBitmapLeakCounter.decrement();
90 #endif
91 }
92 
resetPixels(bool black)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 
convert32To16(unsigned pixel)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 
to16bit()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 
freeMemory()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 
createHandle(void ** pixels,BitmapInfo * bmpInfo,int height,bool use16bit) const190 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 
ensureHandle()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 
draw(GraphicsContext * ctxt,const IntRect & dstRect,const IntRect & srcRect,ColorSpace styleColorSpace,CompositeOperator compositeOp)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 
draw(HDC hdc,const IntRect & dstRect,const IntRect & srcRect,CompositeOperator compositeOp)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 
clipBitmap(const IntRect & rect,bool useAlpha,BitmapInfo & bmpInfo,void * & pixels)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 
clipBitmap(const IntRect & rect,bool useAlpha)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 
drawPatternSimple(HDC hdc,const RECT & destRect,HBITMAP hbmp,const POINT & phase)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 
drawPatternSimple(HDC hdc,const RECT & destRect,const SharedBitmap * bmp,const SIZE & bmpSize,const POINT & phase)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 
normalizePhase(LONG phase,int limit)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 
drawPattern(GraphicsContext * ctxt,const FloatRect & tileRectIn,const AffineTransform & patternTransform,const FloatPoint & phase,ColorSpace styleColorSpace,CompositeOperator op,const FloatRect & destRect,const IntSize & origSourceSize)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 
drawPattern(HDC hdc,const AffineTransform & transform,const FloatRect & tileRectIn,const AffineTransform & patternTransform,const FloatPoint & phase,ColorSpace styleColorSpace,CompositeOperator op,const FloatRect & destRect,const IntSize & origSourceSize)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 
getDC(SharedBitmap * bmp,unsigned * key)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 
releaseDC(SharedBitmap *,HDC hdc,unsigned key1)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 
clearPixels(const IntRect & rect)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