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>
34 #include <saldata.hxx>
36 #include <vcl/bitmap.hxx> // for BitmapSystemData
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 ) );
55 WinSalBitmap::WinSalBitmap() :
62 // ------------------------------------------------------------------
64 WinSalBitmap::~WinSalBitmap()
69 // ------------------------------------------------------------------
71 bool WinSalBitmap::Create( HANDLE hBitmap
, bool bDIB
, bool bCopyHandle
)
76 mhDIB
= (HGLOBAL
) ( bCopyHandle
? ImplCopyDIBOrDDB( hBitmap
, TRUE
) : hBitmap
);
78 mhDDB
= (HBITMAP
) ( bCopyHandle
? ImplCopyDIBOrDDB( hBitmap
, FALSE
) : hBitmap
);
82 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) GlobalLock( mhDIB
);
84 maSize
= Size( pBIH
->biWidth
, pBIH
->biHeight
);
85 mnBitCount
= pBIH
->biBitCount
;
88 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 : ( mnBitCount
<= 4 ) ? 4 : ( mnBitCount
<= 8 ) ? 8 : 24;
90 GlobalUnlock( mhDIB
);
96 if( WIN_GetObject( mhDDB
, sizeof( BITMAP
), &aDDBInfo
) )
98 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
99 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
103 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 :
104 ( mnBitCount
<= 4 ) ? 4 :
105 ( mnBitCount
<= 8 ) ? 8 : 24;
120 // ------------------------------------------------------------------
122 bool WinSalBitmap::Create( const Size
& rSize
, sal_uInt16 nBitCount
, const BitmapPalette
& rPal
)
126 mhDIB
= ImplCreateDIB( rSize
, nBitCount
, rPal
);
131 mnBitCount
= nBitCount
;
138 // ------------------------------------------------------------------
140 bool WinSalBitmap::Create( const SalBitmap
& rSSalBitmap
)
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 );
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
;
167 // ------------------------------------------------------------------
169 bool WinSalBitmap::Create( const SalBitmap
& rSSalBmp
, SalGraphics
* pSGraphics
)
173 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
174 WinSalGraphics
* pGraphics
= static_cast<WinSalGraphics
*>(pSGraphics
);
178 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( rSalBmp
.mhDIB
);
179 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) pBI
;
180 HDC hDC
= pGraphics
->mhDC
;
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
);
191 SetDIBits( hDC
, hNewDDB
, 0, pBIH
->biHeight
, pBits
, pBI
, DIB_RGB_COLORS
);
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
) )
201 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
202 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
207 DeleteObject( hNewDDB
);
213 // ------------------------------------------------------------------
215 bool WinSalBitmap::Create( const SalBitmap
& rSSalBmp
, sal_uInt16 nNewBitCount
)
219 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
223 mhDIB
= ImplCreateDIB( rSalBmp
.maSize
, nNewBitCount
, BitmapPalette() );
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
;
250 GlobalUnlock( mhDIB
);
256 SelectPalette( hDC
, hOldPal
, TRUE
);
265 // ------------------------------------------------------------------
267 void WinSalBitmap::Destroy()
272 DeleteObject( mhDDB
);
278 // ------------------------------------------------------------------
280 sal_uInt16
WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB
)
282 sal_uInt16 nColors
= 0;
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
;
296 nColors
= 1 << pBIH
->biBitCount
;
299 else if( ( (PBITMAPCOREHEADER
) pBI
)->bcBitCount
<= 8 )
300 nColors
= 1 << ( (PBITMAPCOREHEADER
) pBI
)->bcBitCount
;
302 GlobalUnlock( hDIB
);
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!" );
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
);
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();
332 pBIH
->biBitCount
= nBits
;
333 pBIH
->biCompression
= BI_RGB
;
334 pBIH
->biSizeImage
= nImageSize
;
335 pBIH
->biXPelsPerMeter
= 0;
336 pBIH
->biYPelsPerMeter
= 0;
338 pBIH
->biClrImportant
= 0;
342 const sal_uInt16 nMinCount
= Min( nColors
, rPal
.GetEntryCount() );
345 memcpy( pBI
->bmiColors
, rPal
.ImplGetColorBuffer(), nMinCount
* sizeof( RGBQUAD
) );
348 GlobalUnlock( hDIB
);
355 // ------------------------------------------------------------------
357 HANDLE
WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl
, bool bDIB
)
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
);
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
);
393 SelectObject( hBmpDC
, hBmpOld
);
401 // ------------------------------------------------------------------
403 BitmapBuffer
* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
405 BitmapBuffer
* pBuffer
= NULL
;
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() );
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
);
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
);
479 pBuffer
->maColorMask
= ColorMask( 0x00ff0000UL
, 0x0000ff00UL
, 0x000000ffUL
);
481 pBuffer
->mpBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
+ nOffset
;
484 pBuffer
->mpBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
;
488 GlobalUnlock( mhDIB
);
494 GlobalUnlock( mhDIB
);
500 // ------------------------------------------------------------------
502 void WinSalBitmap::ReleaseBuffer( BitmapBuffer
* pBuffer
, bool bReadOnly
)
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
);
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
;
539 bool bEndDecoding
= FALSE
;
545 if( ( nCountByte
= *pRLE
++ ) == 0 )
553 nCountByte
= nRunByte
>> 1UL;
555 for( i
= 0; i
< nCountByte
; i
++ )
558 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
559 ImplSetPixel4( pDIB
, nX
++, cTmp
& 0x0f );
563 ImplSetPixel4( pDIB
, nX
++, *pRLE
++ >> 4 );
565 if( ( ( nRunByte
+ 1 ) >> 1 ) & 1 )
570 memcpy( &pDIB
[ nX
], pRLE
, nRunByte
);
580 pDIB
= ( pRow
+= nWidthAl
);
583 else if( nRunByte
== 1 )
588 pDIB
= ( pRow
+= ( *pRLE
++ ) * nWidthAl
);
597 nRunByte
= nCountByte
>> 1;
599 for( i
= 0; i
< nRunByte
; i
++ )
601 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
602 ImplSetPixel4( pDIB
, nX
++, cTmp
& 0x0f );
606 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
610 for( i
= 0; i
< nCountByte
; i
++ )
615 while( !bEndDecoding
&& ( pDIB
<= pLast
) );
619 bool WinSalBitmap::GetSystemData( BitmapSystemData
& rData
)
627 const Size
& rSize
= GetSize ();
628 rData
.mnWidth
= rSize
.Width();
629 rData
.mnHeight
= rSize
.Height();