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