1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salbmp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/svwin.h>
34 #include <wincomp.hxx>
35 #include <vcl/salbtype.hxx>
37 #include <saldata.hxx>
39 #include <vcl/bitmap.hxx> // for BitmapSystemData
46 inline void ImplSetPixel4( const HPBYTE pScanline
, long nX
, const BYTE cIndex
)
48 BYTE
& rByte
= pScanline
[ nX
>> 1 ];
50 ( nX
& 1 ) ? ( rByte
&= 0xf0, rByte
|= ( cIndex
& 0x0f ) ) :
51 ( rByte
&= 0x0f, rByte
|= ( cIndex
<< 4 ) );
58 WinSalBitmap::WinSalBitmap() :
65 // ------------------------------------------------------------------
67 WinSalBitmap::~WinSalBitmap()
72 // ------------------------------------------------------------------
74 bool WinSalBitmap::Create( HANDLE hBitmap
, bool bDIB
, bool bCopyHandle
)
79 mhDIB
= (HGLOBAL
) ( bCopyHandle
? ImplCopyDIBOrDDB( hBitmap
, TRUE
) : hBitmap
);
81 mhDDB
= (HBITMAP
) ( bCopyHandle
? ImplCopyDIBOrDDB( hBitmap
, FALSE
) : hBitmap
);
85 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) GlobalLock( mhDIB
);
87 maSize
= Size( pBIH
->biWidth
, pBIH
->biHeight
);
88 mnBitCount
= pBIH
->biBitCount
;
91 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 : ( mnBitCount
<= 4 ) ? 4 : ( mnBitCount
<= 8 ) ? 8 : 24;
93 GlobalUnlock( mhDIB
);
99 if( WIN_GetObject( mhDDB
, sizeof( BITMAP
), &aDDBInfo
) )
101 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
102 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
106 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 :
107 ( mnBitCount
<= 4 ) ? 4 :
108 ( mnBitCount
<= 8 ) ? 8 : 24;
123 // ------------------------------------------------------------------
125 bool WinSalBitmap::Create( const Size
& rSize
, USHORT nBitCount
, const BitmapPalette
& rPal
)
129 mhDIB
= ImplCreateDIB( rSize
, nBitCount
, rPal
);
134 mnBitCount
= nBitCount
;
141 // ------------------------------------------------------------------
143 bool WinSalBitmap::Create( const SalBitmap
& rSSalBitmap
)
146 const WinSalBitmap
& rSalBitmap
= static_cast<const WinSalBitmap
&>(rSSalBitmap
);
148 if ( rSalBitmap
.mhDIB
|| rSalBitmap
.mhDDB
)
150 HANDLE hNewHdl
= ImplCopyDIBOrDDB( rSalBitmap
.mhDIB
? rSalBitmap
.mhDIB
: rSalBitmap
.mhDDB
,
151 rSalBitmap
.mhDIB
!= 0 );
155 if( rSalBitmap
.mhDIB
)
156 mhDIB
= (HGLOBAL
) hNewHdl
;
157 else if( rSalBitmap
.mhDDB
)
158 mhDDB
= (HBITMAP
) hNewHdl
;
160 maSize
= rSalBitmap
.maSize
;
161 mnBitCount
= rSalBitmap
.mnBitCount
;
170 // ------------------------------------------------------------------
172 bool WinSalBitmap::Create( const SalBitmap
& rSSalBmp
, SalGraphics
* pSGraphics
)
176 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
177 WinSalGraphics
* pGraphics
= static_cast<WinSalGraphics
*>(pSGraphics
);
181 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( rSalBmp
.mhDIB
);
182 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) pBI
;
183 HDC hDC
= pGraphics
->mhDC
;
186 PBYTE pBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
+
187 ImplGetDIBColorCount( rSalBmp
.mhDIB
) * sizeof( RGBQUAD
);
189 if( pBIH
->biBitCount
== 1 )
191 hNewDDB
= CreateBitmap( pBIH
->biWidth
, pBIH
->biHeight
, 1, 1, NULL
);
194 SetDIBits( hDC
, hNewDDB
, 0, pBIH
->biHeight
, pBits
, pBI
, DIB_RGB_COLORS
);
197 hNewDDB
= CreateDIBitmap( hDC
, (PBITMAPINFOHEADER
) pBI
, CBM_INIT
, pBits
, pBI
, DIB_RGB_COLORS
);
199 GlobalUnlock( rSalBmp
.mhDIB
);
201 if( hNewDDB
&& WIN_GetObject( hNewDDB
, sizeof( BITMAP
), &aDDBInfo
) )
204 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
205 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
210 DeleteObject( hNewDDB
);
216 // ------------------------------------------------------------------
218 bool WinSalBitmap::Create( const SalBitmap
& rSSalBmp
, USHORT nNewBitCount
)
222 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
226 mhDIB
= ImplCreateDIB( rSalBmp
.maSize
, nNewBitCount
, BitmapPalette() );
230 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( mhDIB
);
231 const int nLines
= (int) rSalBmp
.maSize
.Height();
232 HDC hDC
= GetDC( 0 );
233 PBYTE pBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
+
234 ImplGetDIBColorCount( mhDIB
) * sizeof( RGBQUAD
);
235 SalData
* pSalData
= GetSalData();
236 HPALETTE hOldPal
= 0;
238 if ( pSalData
->mhDitherPal
)
240 hOldPal
= SelectPalette( hDC
, pSalData
->mhDitherPal
, TRUE
);
241 RealizePalette( hDC
);
244 if( GetDIBits( hDC
, rSalBmp
.mhDDB
, 0, nLines
, pBits
, pBI
, DIB_RGB_COLORS
) == nLines
)
246 GlobalUnlock( mhDIB
);
247 maSize
= rSalBmp
.maSize
;
248 mnBitCount
= nNewBitCount
;
253 GlobalUnlock( mhDIB
);
259 SelectPalette( hDC
, hOldPal
, TRUE
);
268 // ------------------------------------------------------------------
270 bool WinSalBitmap::Create( const ::com::sun::star::uno::Reference
< ::com::sun::star::rendering::XBitmapCanvas
> /*xBitmapCanvas*/, Size
& /*rSize*/, bool /*bMask*/ )
275 // ------------------------------------------------------------------
277 void WinSalBitmap::Destroy()
282 DeleteObject( mhDDB
);
288 // ------------------------------------------------------------------
290 USHORT
WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB
)
296 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( hDIB
);
297 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) pBI
;
299 if ( pBIH
->biSize
!= sizeof( BITMAPCOREHEADER
) )
301 if( pBIH
->biBitCount
<= 8 )
303 if ( pBIH
->biClrUsed
)
304 nColors
= (USHORT
) pBIH
->biClrUsed
;
306 nColors
= 1 << pBIH
->biBitCount
;
309 else if( ( (PBITMAPCOREHEADER
) pBI
)->bcBitCount
<= 8 )
310 nColors
= 1 << ( (PBITMAPCOREHEADER
) pBI
)->bcBitCount
;
312 GlobalUnlock( hDIB
);
318 // ------------------------------------------------------------------
320 HGLOBAL
WinSalBitmap::ImplCreateDIB( const Size
& rSize
, USHORT nBits
, const BitmapPalette
& rPal
)
322 DBG_ASSERT( nBits
== 1 || nBits
== 4 || nBits
== 8 || nBits
== 16 || nBits
== 24, "Unsupported BitCount!" );
326 if ( rSize
.Width() && rSize
.Height() )
328 const ULONG nImageSize
= AlignedWidth4Bytes( nBits
* rSize
.Width() ) * rSize
.Height();
329 const USHORT nColors
= ( nBits
<= 8 ) ? ( 1 << nBits
) : 0;
331 hDIB
= GlobalAlloc( GHND
, sizeof( BITMAPINFOHEADER
) + nColors
* sizeof( RGBQUAD
) + nImageSize
);
335 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( hDIB
);
336 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) pBI
;
338 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
339 pBIH
->biWidth
= rSize
.Width();
340 pBIH
->biHeight
= rSize
.Height();
342 pBIH
->biBitCount
= nBits
;
343 pBIH
->biCompression
= BI_RGB
;
344 pBIH
->biSizeImage
= nImageSize
;
345 pBIH
->biXPelsPerMeter
= 0;
346 pBIH
->biYPelsPerMeter
= 0;
348 pBIH
->biClrImportant
= 0;
352 const USHORT nMinCount
= Min( nColors
, rPal
.GetEntryCount() );
355 memcpy( pBI
->bmiColors
, rPal
.ImplGetColorBuffer(), nMinCount
* sizeof( RGBQUAD
) );
358 GlobalUnlock( hDIB
);
365 // ------------------------------------------------------------------
367 HANDLE
WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl
, bool bDIB
)
373 const ULONG nSize
= GlobalSize( hHdl
);
375 if ( (hCopy
= GlobalAlloc( GHND
, nSize
)) != 0 )
377 memcpy( (LPSTR
) GlobalLock( hCopy
), (LPSTR
) GlobalLock( hHdl
), nSize
);
379 GlobalUnlock( hCopy
);
380 GlobalUnlock( hHdl
);
387 // Source-Bitmap nach Groesse befragen
388 WIN_GetObject( hHdl
, sizeof( BITMAP
), (LPSTR
) &aBmp
);
390 // Destination-Bitmap erzeugen
391 if ( (hCopy
= CreateBitmapIndirect( &aBmp
)) != 0 )
393 HDC hBmpDC
= CreateCompatibleDC( 0 );
394 HBITMAP hBmpOld
= (HBITMAP
) SelectObject( hBmpDC
, hHdl
);
395 HDC hCopyDC
= CreateCompatibleDC( hBmpDC
);
396 HBITMAP hCopyOld
= (HBITMAP
) SelectObject( hCopyDC
, hCopy
);
398 BitBlt( hCopyDC
, 0, 0, aBmp
.bmWidth
, aBmp
.bmHeight
, hBmpDC
, 0, 0, SRCCOPY
);
400 SelectObject( hCopyDC
, hCopyOld
);
403 SelectObject( hBmpDC
, hBmpOld
);
411 // ------------------------------------------------------------------
413 BitmapBuffer
* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
415 BitmapBuffer
* pBuffer
= NULL
;
419 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( mhDIB
);
420 PBITMAPINFOHEADER pBIH
= (PBITMAPINFOHEADER
) pBI
;
422 if( ( pBIH
->biCompression
== BI_RLE4
) || ( pBIH
->biCompression
== BI_RLE8
) )
424 Size
aSizePix( pBIH
->biWidth
, pBIH
->biHeight
);
425 HGLOBAL hNewDIB
= ImplCreateDIB( aSizePix
, pBIH
->biBitCount
, BitmapPalette() );
429 PBITMAPINFO pNewBI
= (PBITMAPINFO
) GlobalLock( hNewDIB
);
430 PBITMAPINFOHEADER pNewBIH
= (PBITMAPINFOHEADER
) pNewBI
;
431 const USHORT nColorCount
= ImplGetDIBColorCount( hNewDIB
);
432 const ULONG nOffset
= *(DWORD
*) pBI
+ nColorCount
* sizeof( RGBQUAD
);
433 BYTE
* pOldBits
= (PBYTE
) pBI
+ nOffset
;
434 BYTE
* pNewBits
= (PBYTE
) pNewBI
+ nOffset
;
436 memcpy( pNewBI
, pBI
, nOffset
);
437 pNewBIH
->biCompression
= 0;
438 ImplDecodeRLEBuffer( pOldBits
, pNewBits
, aSizePix
, pBIH
->biCompression
== BI_RLE4
);
440 GlobalUnlock( mhDIB
);
448 if( pBIH
->biPlanes
== 1 )
450 pBuffer
= new BitmapBuffer
;
452 pBuffer
->mnFormat
= BMP_FORMAT_BOTTOM_UP
|
453 ( pBIH
->biBitCount
== 1 ? BMP_FORMAT_1BIT_MSB_PAL
:
454 pBIH
->biBitCount
== 4 ? BMP_FORMAT_4BIT_MSN_PAL
:
455 pBIH
->biBitCount
== 8 ? BMP_FORMAT_8BIT_PAL
:
456 pBIH
->biBitCount
== 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK
:
457 pBIH
->biBitCount
== 24 ? BMP_FORMAT_24BIT_TC_BGR
:
458 pBIH
->biBitCount
== 32 ? BMP_FORMAT_32BIT_TC_MASK
: 0UL );
460 if( BMP_SCANLINE_FORMAT( pBuffer
->mnFormat
) )
462 pBuffer
->mnWidth
= maSize
.Width();
463 pBuffer
->mnHeight
= maSize
.Height();
464 pBuffer
->mnScanlineSize
= AlignedWidth4Bytes( maSize
.Width() * pBIH
->biBitCount
);
465 pBuffer
->mnBitCount
= (USHORT
) pBIH
->biBitCount
;
467 if( pBuffer
->mnBitCount
<= 8 )
469 const USHORT nPalCount
= ImplGetDIBColorCount( mhDIB
);
471 pBuffer
->maPalette
.SetEntryCount( nPalCount
);
472 memcpy( pBuffer
->maPalette
.ImplGetColorBuffer(), pBI
->bmiColors
, nPalCount
* sizeof( RGBQUAD
) );
473 pBuffer
->mpBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
+ nPalCount
* sizeof( RGBQUAD
);
475 else if( ( pBIH
->biBitCount
== 16 ) || ( pBIH
->biBitCount
== 32 ) )
479 if( pBIH
->biCompression
== BI_BITFIELDS
)
481 nOffset
= 3 * sizeof( RGBQUAD
);
482 pBuffer
->maColorMask
= ColorMask( *(UINT32
*) &pBI
->bmiColors
[ 0 ],
483 *(UINT32
*) &pBI
->bmiColors
[ 1 ],
484 *(UINT32
*) &pBI
->bmiColors
[ 2 ] );
486 else if( pBIH
->biBitCount
== 16 )
487 pBuffer
->maColorMask
= ColorMask( 0x00007c00UL
, 0x000003e0UL
, 0x0000001fUL
);
489 pBuffer
->maColorMask
= ColorMask( 0x00ff0000UL
, 0x0000ff00UL
, 0x000000ffUL
);
491 pBuffer
->mpBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
+ nOffset
;
494 pBuffer
->mpBits
= (PBYTE
) pBI
+ *(DWORD
*) pBI
;
498 GlobalUnlock( mhDIB
);
504 GlobalUnlock( mhDIB
);
510 // ------------------------------------------------------------------
512 void WinSalBitmap::ReleaseBuffer( BitmapBuffer
* pBuffer
, bool bReadOnly
)
518 if( !bReadOnly
&& !!pBuffer
->maPalette
)
520 PBITMAPINFO pBI
= (PBITMAPINFO
) GlobalLock( mhDIB
);
521 const USHORT nCount
= pBuffer
->maPalette
.GetEntryCount();
523 memcpy( pBI
->bmiColors
, pBuffer
->maPalette
.ImplGetColorBuffer(), nCount
* sizeof( RGBQUAD
) );
524 GlobalUnlock( mhDIB
);
527 GlobalUnlock( mhDIB
);
534 // ------------------------------------------------------------------
536 void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE
* pSrcBuf
, BYTE
* pDstBuf
,
537 const Size
& rSizePixel
, bool bRLE4
)
539 HPBYTE pRLE
= (HPBYTE
) pSrcBuf
;
540 HPBYTE pDIB
= (HPBYTE
) pDstBuf
;
541 HPBYTE pRow
= (HPBYTE
) pDstBuf
;
542 ULONG nWidthAl
= AlignedWidth4Bytes( rSizePixel
.Width() * ( bRLE4
? 4UL : 8UL ) );
543 HPBYTE pLast
= pDIB
+ rSizePixel
.Height() * nWidthAl
- 1;
549 bool bEndDecoding
= FALSE
;
555 if( ( nCountByte
= *pRLE
++ ) == 0 )
563 nCountByte
= nRunByte
>> 1UL;
565 for( i
= 0; i
< nCountByte
; i
++ )
568 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
569 ImplSetPixel4( pDIB
, nX
++, cTmp
& 0x0f );
573 ImplSetPixel4( pDIB
, nX
++, *pRLE
++ >> 4 );
575 if( ( ( nRunByte
+ 1 ) >> 1 ) & 1 )
580 memcpy( &pDIB
[ nX
], pRLE
, nRunByte
);
590 pDIB
= ( pRow
+= nWidthAl
);
593 else if( nRunByte
== 1 )
598 pDIB
= ( pRow
+= ( *pRLE
++ ) * nWidthAl
);
607 nRunByte
= nCountByte
>> 1;
609 for( i
= 0; i
< nRunByte
; i
++ )
611 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
612 ImplSetPixel4( pDIB
, nX
++, cTmp
& 0x0f );
616 ImplSetPixel4( pDIB
, nX
++, cTmp
>> 4 );
620 for( i
= 0; i
< nCountByte
; i
++ )
625 while( !bEndDecoding
&& ( pDIB
<= pLast
) );
629 bool WinSalBitmap::GetSystemData( BitmapSystemData
& rData
)
637 const Size
& rSize
= GetSize ();
638 rData
.mnWidth
= rSize
.Width();
639 rData
.mnHeight
= rSize
.Height();