merged tag ooo/DEV300_m102
[LibreOffice.git] / vcl / win / source / gdi / salbmp.cxx
blob8be85d210bd6b25b2ef09c984ce95b2a376c2176
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <tools/svwin.h>
31 #include <wincomp.hxx>
32 #include <vcl/salbtype.hxx>
33 #include <salgdi.h>
34 #include <saldata.hxx>
35 #include <salbmp.h>
36 #include <vcl/bitmap.hxx> // for BitmapSystemData
37 #include <string.h>
39 // -----------
40 // - Inlines -
41 // -----------
43 inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex )
45 BYTE& rByte = pScanline[ nX >> 1 ];
47 ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) :
48 ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) );
51 // ----------------
52 // - WinSalBitmap -
53 // ----------------
55 WinSalBitmap::WinSalBitmap() :
56 mhDIB ( 0 ),
57 mhDDB ( 0 ),
58 mnBitCount ( 0 )
62 // ------------------------------------------------------------------
64 WinSalBitmap::~WinSalBitmap()
66 Destroy();
69 // ------------------------------------------------------------------
71 bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
73 bool bRet = TRUE;
75 if( bDIB )
76 mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
77 else
78 mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
80 if( mhDIB )
82 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB );
84 maSize = Size( pBIH->biWidth, pBIH->biHeight );
85 mnBitCount = pBIH->biBitCount;
87 if( mnBitCount )
88 mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
90 GlobalUnlock( mhDIB );
92 else if( mhDDB )
94 BITMAP aDDBInfo;
96 if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) )
98 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
99 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
101 if( mnBitCount )
103 mnBitCount = ( mnBitCount <= 1 ) ? 1 :
104 ( mnBitCount <= 4 ) ? 4 :
105 ( mnBitCount <= 8 ) ? 8 : 24;
108 else
110 mhDDB = 0;
111 bRet = FALSE;
114 else
115 bRet = FALSE;
117 return bRet;
120 // ------------------------------------------------------------------
122 bool WinSalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
124 bool bRet = FALSE;
126 mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
128 if( mhDIB )
130 maSize = rSize;
131 mnBitCount = nBitCount;
132 bRet = TRUE;
135 return bRet;
138 // ------------------------------------------------------------------
140 bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap )
142 bool bRet = FALSE;
143 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
145 if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB )
147 HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB,
148 rSalBitmap.mhDIB != 0 );
150 if ( hNewHdl )
152 if( rSalBitmap.mhDIB )
153 mhDIB = (HGLOBAL) hNewHdl;
154 else if( rSalBitmap.mhDDB )
155 mhDDB = (HBITMAP) hNewHdl;
157 maSize = rSalBitmap.maSize;
158 mnBitCount = rSalBitmap.mnBitCount;
160 bRet = TRUE;
164 return bRet;
167 // ------------------------------------------------------------------
169 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
171 bool bRet = FALSE;
173 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
174 WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics);
176 if( rSalBmp.mhDIB )
178 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB );
179 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
180 HDC hDC = pGraphics->mhDC;
181 HBITMAP hNewDDB;
182 BITMAP aDDBInfo;
183 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI +
184 ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD );
186 if( pBIH->biBitCount == 1 )
188 hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL );
190 if( hNewDDB )
191 SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS );
193 else
194 hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
196 GlobalUnlock( rSalBmp.mhDIB );
198 if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) )
200 mhDDB = hNewDDB;
201 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
202 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
204 bRet = TRUE;
206 else if( hNewDDB )
207 DeleteObject( hNewDDB );
210 return bRet;
213 // ------------------------------------------------------------------
215 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, sal_uInt16 nNewBitCount )
217 bool bRet = FALSE;
219 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
221 if( rSalBmp.mhDDB )
223 mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
225 if( mhDIB )
227 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB );
228 const int nLines = (int) rSalBmp.maSize.Height();
229 HDC hDC = GetDC( 0 );
230 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI +
231 ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD );
232 SalData* pSalData = GetSalData();
233 HPALETTE hOldPal = 0;
235 if ( pSalData->mhDitherPal )
237 hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE );
238 RealizePalette( hDC );
241 if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines )
243 GlobalUnlock( mhDIB );
244 maSize = rSalBmp.maSize;
245 mnBitCount = nNewBitCount;
246 bRet = TRUE;
248 else
250 GlobalUnlock( mhDIB );
251 GlobalFree( mhDIB );
252 mhDIB = 0;
255 if( hOldPal )
256 SelectPalette( hDC, hOldPal, TRUE );
258 ReleaseDC( 0, hDC );
262 return bRet;
265 // ------------------------------------------------------------------
267 void WinSalBitmap::Destroy()
269 if( mhDIB )
270 GlobalFree( mhDIB );
271 else if( mhDDB )
272 DeleteObject( mhDDB );
274 maSize = Size();
275 mnBitCount = 0;
278 // ------------------------------------------------------------------
280 sal_uInt16 WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB )
282 sal_uInt16 nColors = 0;
284 if( hDIB )
286 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB );
287 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
289 if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) )
291 if( pBIH->biBitCount <= 8 )
293 if ( pBIH->biClrUsed )
294 nColors = (sal_uInt16) pBIH->biClrUsed;
295 else
296 nColors = 1 << pBIH->biBitCount;
299 else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 )
300 nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount;
302 GlobalUnlock( hDIB );
305 return nColors;
308 // ------------------------------------------------------------------
310 HGLOBAL WinSalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rPal )
312 DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 16 || nBits == 24, "Unsupported BitCount!" );
314 HGLOBAL hDIB = 0;
316 if ( rSize.Width() && rSize.Height() )
318 const sal_uLong nImageSize = AlignedWidth4Bytes( nBits * rSize.Width() ) * rSize.Height();
319 const sal_uInt16 nColors = ( nBits <= 8 ) ? ( 1 << nBits ) : 0;
321 hDIB = GlobalAlloc( GHND, sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD ) + nImageSize );
323 if( hDIB )
325 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB );
326 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
328 pBIH->biSize = sizeof( BITMAPINFOHEADER );
329 pBIH->biWidth = rSize.Width();
330 pBIH->biHeight = rSize.Height();
331 pBIH->biPlanes = 1;
332 pBIH->biBitCount = nBits;
333 pBIH->biCompression = BI_RGB;
334 pBIH->biSizeImage = nImageSize;
335 pBIH->biXPelsPerMeter = 0;
336 pBIH->biYPelsPerMeter = 0;
337 pBIH->biClrUsed = 0;
338 pBIH->biClrImportant = 0;
340 if ( nColors )
342 const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() );
344 if( nMinCount )
345 memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGBQUAD ) );
348 GlobalUnlock( hDIB );
352 return hDIB;
355 // ------------------------------------------------------------------
357 HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
359 HANDLE hCopy = 0;
361 if ( bDIB && hHdl )
363 const sal_uLong nSize = GlobalSize( hHdl );
365 if ( (hCopy = GlobalAlloc( GHND, nSize )) != 0 )
367 memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize );
369 GlobalUnlock( hCopy );
370 GlobalUnlock( hHdl );
373 else if ( hHdl )
375 BITMAP aBmp;
377 // Source-Bitmap nach Groesse befragen
378 WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp );
380 // Destination-Bitmap erzeugen
381 if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 )
383 HDC hBmpDC = CreateCompatibleDC( 0 );
384 HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl );
385 HDC hCopyDC = CreateCompatibleDC( hBmpDC );
386 HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy );
388 BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY );
390 SelectObject( hCopyDC, hCopyOld );
391 DeleteDC( hCopyDC );
393 SelectObject( hBmpDC, hBmpOld );
394 DeleteDC( hBmpDC );
398 return hCopy;
401 // ------------------------------------------------------------------
403 BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
405 BitmapBuffer* pBuffer = NULL;
407 if( mhDIB )
409 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB );
410 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
412 if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) )
414 Size aSizePix( pBIH->biWidth, pBIH->biHeight );
415 HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() );
417 if( hNewDIB )
419 PBITMAPINFO pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB );
420 PBITMAPINFOHEADER pNewBIH = (PBITMAPINFOHEADER) pNewBI;
421 const sal_uInt16 nColorCount = ImplGetDIBColorCount( hNewDIB );
422 const sal_uLong nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD );
423 BYTE* pOldBits = (PBYTE) pBI + nOffset;
424 BYTE* pNewBits = (PBYTE) pNewBI + nOffset;
426 memcpy( pNewBI, pBI, nOffset );
427 pNewBIH->biCompression = 0;
428 ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 );
430 GlobalUnlock( mhDIB );
431 GlobalFree( mhDIB );
432 mhDIB = hNewDIB;
433 pBI = pNewBI;
434 pBIH = pNewBIH;
438 if( pBIH->biPlanes == 1 )
440 pBuffer = new BitmapBuffer;
442 pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
443 ( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
444 pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
445 pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
446 pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
447 pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
448 pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
450 if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
452 pBuffer->mnWidth = maSize.Width();
453 pBuffer->mnHeight = maSize.Height();
454 pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount );
455 pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount;
457 if( pBuffer->mnBitCount <= 8 )
459 const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB );
461 pBuffer->maPalette.SetEntryCount( nPalCount );
462 memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) );
463 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD );
465 else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) )
467 sal_uLong nOffset = 0UL;
469 if( pBIH->biCompression == BI_BITFIELDS )
471 nOffset = 3 * sizeof( RGBQUAD );
472 pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ],
473 *(UINT32*) &pBI->bmiColors[ 1 ],
474 *(UINT32*) &pBI->bmiColors[ 2 ] );
476 else if( pBIH->biBitCount == 16 )
477 pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL );
478 else
479 pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL );
481 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset;
483 else
484 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI;
486 else
488 GlobalUnlock( mhDIB );
489 delete pBuffer;
490 pBuffer = NULL;
493 else
494 GlobalUnlock( mhDIB );
497 return pBuffer;
500 // ------------------------------------------------------------------
502 void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
504 if( pBuffer )
506 if( mhDIB )
508 if( !bReadOnly && !!pBuffer->maPalette )
510 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB );
511 const sal_uInt16 nCount = pBuffer->maPalette.GetEntryCount();
512 const sal_uInt16 nDIBColorCount = ImplGetDIBColorCount( mhDIB );
513 memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) );
514 GlobalUnlock( mhDIB );
517 GlobalUnlock( mhDIB );
520 delete pBuffer;
524 // ------------------------------------------------------------------
526 void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
527 const Size& rSizePixel, bool bRLE4 )
529 HPBYTE pRLE = (HPBYTE) pSrcBuf;
530 HPBYTE pDIB = (HPBYTE) pDstBuf;
531 HPBYTE pRow = (HPBYTE) pDstBuf;
532 sal_uLong nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
533 HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
534 sal_uLong nCountByte;
535 sal_uLong nRunByte;
536 sal_uLong nX = 0;
537 sal_uLong i;
538 BYTE cTmp;
539 bool bEndDecoding = FALSE;
541 if( pRLE && pDIB )
545 if( ( nCountByte = *pRLE++ ) == 0 )
547 nRunByte = *pRLE++;
549 if( nRunByte > 2UL )
551 if( bRLE4 )
553 nCountByte = nRunByte >> 1UL;
555 for( i = 0; i < nCountByte; i++ )
557 cTmp = *pRLE++;
558 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
559 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
562 if( nRunByte & 1 )
563 ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
565 if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
566 pRLE++;
568 else
570 memcpy( &pDIB[ nX ], pRLE, nRunByte );
571 pRLE += nRunByte;
572 nX += nRunByte;
574 if( nRunByte & 1 )
575 pRLE++;
578 else if( !nRunByte )
580 pDIB = ( pRow += nWidthAl );
581 nX = 0UL;
583 else if( nRunByte == 1 )
584 bEndDecoding = TRUE;
585 else
587 nX += *pRLE++;
588 pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
591 else
593 cTmp = *pRLE++;
595 if( bRLE4 )
597 nRunByte = nCountByte >> 1;
599 for( i = 0; i < nRunByte; i++ )
601 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
602 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
605 if( nCountByte & 1 )
606 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
608 else
610 for( i = 0; i < nCountByte; i++ )
611 pDIB[ nX++ ] = cTmp;
615 while( !bEndDecoding && ( pDIB <= pLast ) );
619 bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
621 bool bRet = false;
622 if( mhDIB || mhDDB )
624 bRet = true;
625 rData.pDIB = mhDIB;
626 rData.pDDB = mhDDB;
627 const Size& rSize = GetSize ();
628 rData.mnWidth = rSize.Width();
629 rData.mnHeight = rSize.Height();
631 return bRet;