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