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