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