1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <tools/svwin.h> 32 33 #include <vcl/bitmap.hxx> // for BitmapSystemData 34 #include <vcl/salbtype.hxx> 35 36 #include <win/wincomp.hxx> 37 #include <win/salgdi.h> 38 #include <win/saldata.hxx> 39 #include <win/salbmp.h> 40 41 #include <string.h> 42 43 // ----------- 44 // - Inlines - 45 // ----------- 46 47 inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex ) 48 { 49 BYTE& rByte = pScanline[ nX >> 1 ]; 50 51 ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) : 52 ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) ); 53 } 54 55 // ---------------- 56 // - WinSalBitmap - 57 // ---------------- 58 59 WinSalBitmap::WinSalBitmap() : 60 mhDIB ( 0 ), 61 mhDDB ( 0 ), 62 mnBitCount ( 0 ) 63 { 64 } 65 66 // ------------------------------------------------------------------ 67 68 WinSalBitmap::~WinSalBitmap() 69 { 70 Destroy(); 71 } 72 73 // ------------------------------------------------------------------ 74 75 bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ) 76 { 77 bool bRet = TRUE; 78 79 if( bDIB ) 80 mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap ); 81 else 82 mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap ); 83 84 if( mhDIB ) 85 { 86 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB ); 87 88 maSize = Size( pBIH->biWidth, pBIH->biHeight ); 89 mnBitCount = pBIH->biBitCount; 90 91 if( mnBitCount ) 92 mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24; 93 94 GlobalUnlock( mhDIB ); 95 } 96 else if( mhDDB ) 97 { 98 BITMAP aDDBInfo; 99 100 if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) ) 101 { 102 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 103 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 104 105 if( mnBitCount ) 106 { 107 mnBitCount = ( mnBitCount <= 1 ) ? 1 : 108 ( mnBitCount <= 4 ) ? 4 : 109 ( mnBitCount <= 8 ) ? 8 : 24; 110 } 111 } 112 else 113 { 114 mhDDB = 0; 115 bRet = FALSE; 116 } 117 } 118 else 119 bRet = FALSE; 120 121 return bRet; 122 } 123 124 // ------------------------------------------------------------------ 125 126 bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) 127 { 128 bool bRet = FALSE; 129 130 mhDIB = ImplCreateDIB( rSize, nBitCount, rPal ); 131 132 if( mhDIB ) 133 { 134 maSize = rSize; 135 mnBitCount = nBitCount; 136 bRet = TRUE; 137 } 138 139 return bRet; 140 } 141 142 // ------------------------------------------------------------------ 143 144 bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap ) 145 { 146 bool bRet = FALSE; 147 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 148 149 if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB ) 150 { 151 HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB, 152 rSalBitmap.mhDIB != 0 ); 153 154 if ( hNewHdl ) 155 { 156 if( rSalBitmap.mhDIB ) 157 mhDIB = (HGLOBAL) hNewHdl; 158 else if( rSalBitmap.mhDDB ) 159 mhDDB = (HBITMAP) hNewHdl; 160 161 maSize = rSalBitmap.maSize; 162 mnBitCount = rSalBitmap.mnBitCount; 163 164 bRet = TRUE; 165 } 166 } 167 168 return bRet; 169 } 170 171 // ------------------------------------------------------------------ 172 173 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics ) 174 { 175 bool bRet = FALSE; 176 177 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 178 WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics); 179 180 if( rSalBmp.mhDIB ) 181 { 182 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB ); 183 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 184 HDC hDC = pGraphics->mhDC; 185 HBITMAP hNewDDB; 186 BITMAP aDDBInfo; 187 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 188 ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD ); 189 190 if( pBIH->biBitCount == 1 ) 191 { 192 hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL ); 193 194 if( hNewDDB ) 195 SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS ); 196 } 197 else 198 hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); 199 200 GlobalUnlock( rSalBmp.mhDIB ); 201 202 if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) ) 203 { 204 mhDDB = hNewDDB; 205 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); 206 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; 207 208 bRet = TRUE; 209 } 210 else if( hNewDDB ) 211 DeleteObject( hNewDDB ); 212 } 213 214 return bRet; 215 } 216 217 // ------------------------------------------------------------------ 218 219 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount ) 220 { 221 bool bRet = FALSE; 222 223 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp); 224 225 if( rSalBmp.mhDDB ) 226 { 227 mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() ); 228 229 if( mhDIB ) 230 { 231 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 232 const int nLines = (int) rSalBmp.maSize.Height(); 233 HDC hDC = GetDC( 0 ); 234 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 235 ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD ); 236 SalData* pSalData = GetSalData(); 237 HPALETTE hOldPal = 0; 238 239 if ( pSalData->mhDitherPal ) 240 { 241 hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 242 RealizePalette( hDC ); 243 } 244 245 if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines ) 246 { 247 GlobalUnlock( mhDIB ); 248 maSize = rSalBmp.maSize; 249 mnBitCount = nNewBitCount; 250 bRet = TRUE; 251 } 252 else 253 { 254 GlobalUnlock( mhDIB ); 255 GlobalFree( mhDIB ); 256 mhDIB = 0; 257 } 258 259 if( hOldPal ) 260 SelectPalette( hDC, hOldPal, TRUE ); 261 262 ReleaseDC( 0, hDC ); 263 } 264 } 265 266 return bRet; 267 } 268 269 // ------------------------------------------------------------------ 270 271 void WinSalBitmap::Destroy() 272 { 273 if( mhDIB ) 274 GlobalFree( mhDIB ); 275 else if( mhDDB ) 276 DeleteObject( mhDDB ); 277 278 maSize = Size(); 279 mnBitCount = 0; 280 } 281 282 // ------------------------------------------------------------------ 283 284 sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB ) 285 { 286 sal_uInt16 nColors = 0; 287 288 if( hDIB ) 289 { 290 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); 291 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 292 293 if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) ) 294 { 295 if( pBIH->biBitCount <= 8 ) 296 { 297 if ( pBIH->biClrUsed ) 298 nColors = (sal_uInt16) pBIH->biClrUsed; 299 else 300 nColors = 1 << pBIH->biBitCount; 301 } 302 } 303 else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 ) 304 nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount; 305 306 GlobalUnlock( hDIB ); 307 } 308 309 return nColors; 310 } 311 312 // ------------------------------------------------------------------ 313 314 HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal ) 315 { 316 DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" ); 317 318 HGLOBAL hDIB = 0; 319 320 if ( rSize.Width() && rSize.Height() ) 321 { 322 const sal_uLong nImageSize = AlignedWidth4Bytes( nBits * rSize.Width() ) * rSize.Height(); 323 const sal_uInt16 nColors = ( nBits <= 8 ) ? ( 1 << nBits ) : 0; 324 325 hDIB = GlobalAlloc( GHND, sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD ) + nImageSize ); 326 327 if( hDIB ) 328 { 329 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); 330 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 331 332 pBIH->biSize = sizeof( BITMAPINFOHEADER ); 333 pBIH->biWidth = rSize.Width(); 334 pBIH->biHeight = rSize.Height(); 335 pBIH->biPlanes = 1; 336 pBIH->biBitCount = nBits; 337 pBIH->biCompression = BI_RGB; 338 pBIH->biSizeImage = nImageSize; 339 pBIH->biXPelsPerMeter = 0; 340 pBIH->biYPelsPerMeter = 0; 341 pBIH->biClrUsed = 0; 342 pBIH->biClrImportant = 0; 343 344 if ( nColors ) 345 { 346 const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() ); 347 348 if( nMinCount ) 349 memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGBQUAD ) ); 350 } 351 352 GlobalUnlock( hDIB ); 353 } 354 } 355 356 return hDIB; 357 } 358 359 // ------------------------------------------------------------------ 360 361 HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB ) 362 { 363 HANDLE hCopy = 0; 364 365 if ( bDIB && hHdl ) 366 { 367 const sal_uLong nSize = GlobalSize( hHdl ); 368 369 if ( (hCopy = GlobalAlloc( GHND, nSize )) != 0 ) 370 { 371 memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize ); 372 373 GlobalUnlock( hCopy ); 374 GlobalUnlock( hHdl ); 375 } 376 } 377 else if ( hHdl ) 378 { 379 BITMAP aBmp; 380 381 // Source-Bitmap nach Groesse befragen 382 WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp ); 383 384 // Destination-Bitmap erzeugen 385 if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 ) 386 { 387 HDC hBmpDC = CreateCompatibleDC( 0 ); 388 HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl ); 389 HDC hCopyDC = CreateCompatibleDC( hBmpDC ); 390 HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy ); 391 392 BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY ); 393 394 SelectObject( hCopyDC, hCopyOld ); 395 DeleteDC( hCopyDC ); 396 397 SelectObject( hBmpDC, hBmpOld ); 398 DeleteDC( hBmpDC ); 399 } 400 } 401 402 return hCopy; 403 } 404 405 // ------------------------------------------------------------------ 406 407 BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) 408 { 409 BitmapBuffer* pBuffer = NULL; 410 411 if( mhDIB ) 412 { 413 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 414 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 415 416 if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) ) 417 { 418 Size aSizePix( pBIH->biWidth, pBIH->biHeight ); 419 HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() ); 420 421 if( hNewDIB ) 422 { 423 PBITMAPINFO pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB ); 424 PBITMAPINFOHEADER pNewBIH = (PBITMAPINFOHEADER) pNewBI; 425 const sal_uInt16 nColorCount = ImplGetDIBColorCount( hNewDIB ); 426 const sal_uLong nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD ); 427 BYTE* pOldBits = (PBYTE) pBI + nOffset; 428 BYTE* pNewBits = (PBYTE) pNewBI + nOffset; 429 430 memcpy( pNewBI, pBI, nOffset ); 431 pNewBIH->biCompression = 0; 432 ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 ); 433 434 GlobalUnlock( mhDIB ); 435 GlobalFree( mhDIB ); 436 mhDIB = hNewDIB; 437 pBI = pNewBI; 438 pBIH = pNewBIH; 439 } 440 } 441 442 if( pBIH->biPlanes == 1 ) 443 { 444 pBuffer = new BitmapBuffer; 445 446 pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP | 447 ( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL : 448 pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL : 449 pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL : 450 pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK : 451 pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR : 452 pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL ); 453 454 if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) ) 455 { 456 pBuffer->mnWidth = maSize.Width(); 457 pBuffer->mnHeight = maSize.Height(); 458 pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount ); 459 pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount; 460 461 if( pBuffer->mnBitCount <= 8 ) 462 { 463 const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB ); 464 465 pBuffer->maPalette.SetEntryCount( nPalCount ); 466 memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) ); 467 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD ); 468 } 469 else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) ) 470 { 471 sal_uLong nOffset = 0UL; 472 473 if( pBIH->biCompression == BI_BITFIELDS ) 474 { 475 nOffset = 3 * sizeof( RGBQUAD ); 476 pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ], 477 *(UINT32*) &pBI->bmiColors[ 1 ], 478 *(UINT32*) &pBI->bmiColors[ 2 ] ); 479 } 480 else if( pBIH->biBitCount == 16 ) 481 pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL ); 482 else 483 pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL ); 484 485 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset; 486 } 487 else 488 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI; 489 } 490 else 491 { 492 GlobalUnlock( mhDIB ); 493 delete pBuffer; 494 pBuffer = NULL; 495 } 496 } 497 else 498 GlobalUnlock( mhDIB ); 499 } 500 501 return pBuffer; 502 } 503 504 // ------------------------------------------------------------------ 505 506 void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) 507 { 508 if( pBuffer ) 509 { 510 if( mhDIB ) 511 { 512 if( !bReadOnly && !!pBuffer->maPalette ) 513 { 514 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); 515 const sal_uInt16 nCount = pBuffer->maPalette.GetEntryCount(); 516 const sal_uInt16 nDIBColorCount = ImplGetDIBColorCount( mhDIB ); 517 memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) ); 518 GlobalUnlock( mhDIB ); 519 } 520 521 GlobalUnlock( mhDIB ); 522 } 523 524 delete pBuffer; 525 } 526 } 527 528 // ------------------------------------------------------------------ 529 530 void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf, 531 const Size& rSizePixel, bool bRLE4 ) 532 { 533 HPBYTE pRLE = (HPBYTE) pSrcBuf; 534 HPBYTE pDIB = (HPBYTE) pDstBuf; 535 HPBYTE pRow = (HPBYTE) pDstBuf; 536 sal_uLong nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) ); 537 HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1; 538 sal_uLong nCountByte; 539 sal_uLong nRunByte; 540 sal_uLong nX = 0; 541 sal_uLong i; 542 BYTE cTmp; 543 bool bEndDecoding = FALSE; 544 545 if( pRLE && pDIB ) 546 { 547 do 548 { 549 if( ( nCountByte = *pRLE++ ) == 0 ) 550 { 551 nRunByte = *pRLE++; 552 553 if( nRunByte > 2UL ) 554 { 555 if( bRLE4 ) 556 { 557 nCountByte = nRunByte >> 1UL; 558 559 for( i = 0; i < nCountByte; i++ ) 560 { 561 cTmp = *pRLE++; 562 ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 563 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 564 } 565 566 if( nRunByte & 1 ) 567 ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 ); 568 569 if( ( ( nRunByte + 1 ) >> 1 ) & 1 ) 570 pRLE++; 571 } 572 else 573 { 574 memcpy( &pDIB[ nX ], pRLE, nRunByte ); 575 pRLE += nRunByte; 576 nX += nRunByte; 577 578 if( nRunByte & 1 ) 579 pRLE++; 580 } 581 } 582 else if( !nRunByte ) 583 { 584 pDIB = ( pRow += nWidthAl ); 585 nX = 0UL; 586 } 587 else if( nRunByte == 1 ) 588 bEndDecoding = TRUE; 589 else 590 { 591 nX += *pRLE++; 592 pDIB = ( pRow += ( *pRLE++ ) * nWidthAl ); 593 } 594 } 595 else 596 { 597 cTmp = *pRLE++; 598 599 if( bRLE4 ) 600 { 601 nRunByte = nCountByte >> 1; 602 603 for( i = 0; i < nRunByte; i++ ) 604 { 605 ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 606 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); 607 } 608 609 if( nCountByte & 1 ) 610 ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); 611 } 612 else 613 { 614 for( i = 0; i < nCountByte; i++ ) 615 pDIB[ nX++ ] = cTmp; 616 } 617 } 618 } 619 while( !bEndDecoding && ( pDIB <= pLast ) ); 620 } 621 } 622 623 bool WinSalBitmap::GetSystemData( BitmapSystemData& rData ) 624 { 625 bool bRet = false; 626 if( mhDIB || mhDDB ) 627 { 628 bRet = true; 629 rData.pDIB = mhDIB; 630 rData.pDDB = mhDDB; 631 const Size& rSize = GetSize (); 632 rData.mnWidth = rSize.Width(); 633 rData.mnHeight = rSize.Height(); 634 } 635 return bRet; 636 } 637