xref: /AOO41X/main/vcl/win/source/gdi/salbmp.cxx (revision 562e22fb8ee6c20bbd32cd788ccd218e1815e10b)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew 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 
316*562e22fbSHerbert Dürr 	if( rSize.Width() <= 0 || rSize.Height() <= 0 )
317*562e22fbSHerbert Dürr 		return hDIB;
318*562e22fbSHerbert Dürr 
319*562e22fbSHerbert Dürr 	// calculate bitmap size in Bytes
320*562e22fbSHerbert Dürr 	const sal_uLong nAlignedWidth4Bytes = AlignedWidth4Bytes( nBits * rSize.Width() );
321*562e22fbSHerbert Dürr 	const sal_uLong nImageSize = nAlignedWidth4Bytes * rSize.Height();
322*562e22fbSHerbert Dürr 	bool bOverflow = (nImageSize / nAlignedWidth4Bytes) != rSize.Height();
323*562e22fbSHerbert Dürr 	if( bOverflow )
324*562e22fbSHerbert Dürr 		return hDIB;
325*562e22fbSHerbert Dürr 
326*562e22fbSHerbert Dürr 	// allocate bitmap memory including header and palette
327cdf0e10cSrcweir 	const sal_uInt16 nColors = (nBits <= 8) ? (1 << nBits) : 0;
328*562e22fbSHerbert Dürr 	const sal_uLong nHeaderSize = sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD );
329*562e22fbSHerbert Dürr 	bOverflow = (nHeaderSize + nImageSize) < nImageSize;
330*562e22fbSHerbert Dürr 	if( bOverflow )
331*562e22fbSHerbert Dürr 		return hDIB;
332cdf0e10cSrcweir 
333*562e22fbSHerbert Dürr 	hDIB = GlobalAlloc( GHND, nHeaderSize + nImageSize );
334*562e22fbSHerbert Dürr 	if( !hDIB )
335*562e22fbSHerbert Dürr 		return hDIB;
336cdf0e10cSrcweir 
337*562e22fbSHerbert Dürr 	PBITMAPINFO pBI = static_cast<PBITMAPINFO>( GlobalLock( hDIB ) );
338*562e22fbSHerbert Dürr 	PBITMAPINFOHEADER pBIH = static_cast<PBITMAPINFOHEADER>( pBI );
339cdf0e10cSrcweir 
340cdf0e10cSrcweir 	pBIH->biSize = sizeof( BITMAPINFOHEADER );
341cdf0e10cSrcweir 	pBIH->biWidth = rSize.Width();
342cdf0e10cSrcweir 	pBIH->biHeight = rSize.Height();
343cdf0e10cSrcweir 	pBIH->biPlanes = 1;
344cdf0e10cSrcweir 	pBIH->biBitCount = nBits;
345cdf0e10cSrcweir 	pBIH->biCompression = BI_RGB;
346cdf0e10cSrcweir 	pBIH->biSizeImage = nImageSize;
347cdf0e10cSrcweir 	pBIH->biXPelsPerMeter = 0;
348cdf0e10cSrcweir 	pBIH->biYPelsPerMeter = 0;
349cdf0e10cSrcweir 	pBIH->biClrUsed = 0;
350cdf0e10cSrcweir 	pBIH->biClrImportant = 0;
351cdf0e10cSrcweir 
352cdf0e10cSrcweir 	if( nColors )
353cdf0e10cSrcweir 	{
354*562e22fbSHerbert Dürr 		// copy the palette entries if any
355cdf0e10cSrcweir 		const sal_uInt16 nMinCount = Min( nColors, rPal.GetEntryCount() );
356cdf0e10cSrcweir 		if( nMinCount )
357cdf0e10cSrcweir 			memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof(RGBQUAD) );
358cdf0e10cSrcweir 	}
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 	GlobalUnlock( hDIB );
361cdf0e10cSrcweir 
362cdf0e10cSrcweir 	return hDIB;
363cdf0e10cSrcweir }
364cdf0e10cSrcweir 
365cdf0e10cSrcweir // ------------------------------------------------------------------
366cdf0e10cSrcweir 
367cdf0e10cSrcweir HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
368cdf0e10cSrcweir {
369cdf0e10cSrcweir 	HANDLE	hCopy = 0;
370cdf0e10cSrcweir 
371cdf0e10cSrcweir 	if ( bDIB && hHdl )
372cdf0e10cSrcweir 	{
373cdf0e10cSrcweir 		const sal_uLong nSize = GlobalSize( hHdl );
374cdf0e10cSrcweir 
375cdf0e10cSrcweir 		if ( (hCopy = GlobalAlloc( GHND, nSize  )) != 0 )
376cdf0e10cSrcweir 		{
377cdf0e10cSrcweir 			memcpy( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize );
378cdf0e10cSrcweir 
379cdf0e10cSrcweir 			GlobalUnlock( hCopy );
380cdf0e10cSrcweir 			GlobalUnlock( hHdl );
381cdf0e10cSrcweir 		}
382cdf0e10cSrcweir 	}
383cdf0e10cSrcweir 	else if ( hHdl )
384cdf0e10cSrcweir 	{
385cdf0e10cSrcweir 		BITMAP aBmp;
386cdf0e10cSrcweir 
387cdf0e10cSrcweir 		// Source-Bitmap nach Groesse befragen
388cdf0e10cSrcweir 		WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp );
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 		// Destination-Bitmap erzeugen
391cdf0e10cSrcweir 		if ( (hCopy = CreateBitmapIndirect( &aBmp )) != 0 )
392cdf0e10cSrcweir 		{
393cdf0e10cSrcweir 			HDC 	hBmpDC = CreateCompatibleDC( 0 );
394cdf0e10cSrcweir 			HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl );
395cdf0e10cSrcweir 			HDC 	hCopyDC = CreateCompatibleDC( hBmpDC );
396cdf0e10cSrcweir 			HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy );
397cdf0e10cSrcweir 
398cdf0e10cSrcweir 			BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY );
399cdf0e10cSrcweir 
400cdf0e10cSrcweir 			SelectObject( hCopyDC, hCopyOld );
401cdf0e10cSrcweir 			DeleteDC( hCopyDC );
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 			SelectObject( hBmpDC, hBmpOld );
404cdf0e10cSrcweir 			DeleteDC( hBmpDC );
405cdf0e10cSrcweir 		}
406cdf0e10cSrcweir 	}
407cdf0e10cSrcweir 
408cdf0e10cSrcweir 	return hCopy;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir 
411cdf0e10cSrcweir // ------------------------------------------------------------------
412cdf0e10cSrcweir 
413cdf0e10cSrcweir BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
414cdf0e10cSrcweir {
415cdf0e10cSrcweir 	BitmapBuffer* pBuffer = NULL;
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 	if( mhDIB )
418cdf0e10cSrcweir 	{
419cdf0e10cSrcweir 		PBITMAPINFO 		pBI = (PBITMAPINFO) GlobalLock( mhDIB );
420cdf0e10cSrcweir 		PBITMAPINFOHEADER	pBIH = (PBITMAPINFOHEADER) pBI;
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 		if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) )
423cdf0e10cSrcweir 		{
424cdf0e10cSrcweir 			Size	aSizePix( pBIH->biWidth, pBIH->biHeight );
425cdf0e10cSrcweir 			HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 			if( hNewDIB )
428cdf0e10cSrcweir 			{
429cdf0e10cSrcweir 				PBITMAPINFO 		pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB );
430cdf0e10cSrcweir 				PBITMAPINFOHEADER	pNewBIH = (PBITMAPINFOHEADER) pNewBI;
431cdf0e10cSrcweir 				const sal_uInt16		nColorCount = ImplGetDIBColorCount( hNewDIB );
432cdf0e10cSrcweir 				const sal_uLong 		nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD );
433cdf0e10cSrcweir 				BYTE*				pOldBits = (PBYTE) pBI + nOffset;
434cdf0e10cSrcweir 				BYTE*				pNewBits = (PBYTE) pNewBI + nOffset;
435cdf0e10cSrcweir 
436cdf0e10cSrcweir 				memcpy( pNewBI, pBI, nOffset );
437cdf0e10cSrcweir 				pNewBIH->biCompression = 0;
438cdf0e10cSrcweir 				ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 );
439cdf0e10cSrcweir 
440cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
441cdf0e10cSrcweir 				GlobalFree( mhDIB );
442cdf0e10cSrcweir 				mhDIB = hNewDIB;
443cdf0e10cSrcweir 				pBI = pNewBI;
444cdf0e10cSrcweir 				pBIH = pNewBIH;
445cdf0e10cSrcweir 			}
446cdf0e10cSrcweir 		}
447cdf0e10cSrcweir 
448cdf0e10cSrcweir 		if( pBIH->biPlanes == 1 )
449cdf0e10cSrcweir 		{
450cdf0e10cSrcweir 			pBuffer = new BitmapBuffer;
451cdf0e10cSrcweir 
452cdf0e10cSrcweir 			pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP |
453cdf0e10cSrcweir 								( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL :
454cdf0e10cSrcweir 								  pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL :
455cdf0e10cSrcweir 								  pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL :
456cdf0e10cSrcweir 								  pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK :
457cdf0e10cSrcweir 								  pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR :
458cdf0e10cSrcweir 								  pBIH->biBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL );
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 			if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) )
461cdf0e10cSrcweir 			{
462cdf0e10cSrcweir 				pBuffer->mnWidth = maSize.Width();
463cdf0e10cSrcweir 				pBuffer->mnHeight = maSize.Height();
464cdf0e10cSrcweir 				pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->biBitCount );
465cdf0e10cSrcweir 				pBuffer->mnBitCount = (sal_uInt16) pBIH->biBitCount;
466cdf0e10cSrcweir 
467cdf0e10cSrcweir 				if( pBuffer->mnBitCount <= 8 )
468cdf0e10cSrcweir 				{
469cdf0e10cSrcweir 					const sal_uInt16 nPalCount = ImplGetDIBColorCount( mhDIB );
470cdf0e10cSrcweir 
471cdf0e10cSrcweir 					pBuffer->maPalette.SetEntryCount( nPalCount );
472cdf0e10cSrcweir 					memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) );
473cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD );
474cdf0e10cSrcweir 				}
475cdf0e10cSrcweir 				else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) )
476cdf0e10cSrcweir 				{
477cdf0e10cSrcweir 					sal_uLong nOffset = 0UL;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir 					if( pBIH->biCompression == BI_BITFIELDS )
480cdf0e10cSrcweir 					{
481cdf0e10cSrcweir 						nOffset = 3 * sizeof( RGBQUAD );
482cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ],
483cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 1 ],
484cdf0e10cSrcweir 														  *(UINT32*) &pBI->bmiColors[ 2 ] );
485cdf0e10cSrcweir 					}
486cdf0e10cSrcweir 					else if( pBIH->biBitCount == 16 )
487cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL );
488cdf0e10cSrcweir 					else
489cdf0e10cSrcweir 						pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL );
490cdf0e10cSrcweir 
491cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset;
492cdf0e10cSrcweir 				}
493cdf0e10cSrcweir 				else
494cdf0e10cSrcweir 					pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI;
495cdf0e10cSrcweir 			}
496cdf0e10cSrcweir 			else
497cdf0e10cSrcweir 			{
498cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
499cdf0e10cSrcweir 				delete pBuffer;
500cdf0e10cSrcweir 				pBuffer = NULL;
501cdf0e10cSrcweir 			}
502cdf0e10cSrcweir 		}
503cdf0e10cSrcweir 		else
504cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
505cdf0e10cSrcweir 	}
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 	return pBuffer;
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir // ------------------------------------------------------------------
511cdf0e10cSrcweir 
512cdf0e10cSrcweir void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
513cdf0e10cSrcweir {
514cdf0e10cSrcweir 	if( pBuffer )
515cdf0e10cSrcweir 	{
516cdf0e10cSrcweir 		if( mhDIB )
517cdf0e10cSrcweir 		{
518cdf0e10cSrcweir 			if( !bReadOnly && !!pBuffer->maPalette )
519cdf0e10cSrcweir 			{
520cdf0e10cSrcweir 				PBITMAPINFO 	pBI = (PBITMAPINFO) GlobalLock( mhDIB );
521cdf0e10cSrcweir 				const sal_uInt16	nCount = pBuffer->maPalette.GetEntryCount();
522cdf0e10cSrcweir 				const sal_uInt16	nDIBColorCount = ImplGetDIBColorCount( mhDIB );
523cdf0e10cSrcweir 				memcpy( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), Min( nDIBColorCount, nCount ) * sizeof( RGBQUAD ) );
524cdf0e10cSrcweir 				GlobalUnlock( mhDIB );
525cdf0e10cSrcweir 			}
526cdf0e10cSrcweir 
527cdf0e10cSrcweir 			GlobalUnlock( mhDIB );
528cdf0e10cSrcweir 		}
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 		delete pBuffer;
531cdf0e10cSrcweir 	}
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir // ------------------------------------------------------------------
535cdf0e10cSrcweir 
536cdf0e10cSrcweir void WinSalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf,
537cdf0e10cSrcweir 									 const Size& rSizePixel, bool bRLE4 )
538cdf0e10cSrcweir {
539cdf0e10cSrcweir 	HPBYTE			pRLE = (HPBYTE) pSrcBuf;
540cdf0e10cSrcweir 	HPBYTE			pDIB = (HPBYTE) pDstBuf;
541cdf0e10cSrcweir 	HPBYTE			pRow = (HPBYTE) pDstBuf;
542cdf0e10cSrcweir 	sal_uLong			nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) );
543cdf0e10cSrcweir 	HPBYTE			pLast = pDIB + rSizePixel.Height() * nWidthAl - 1;
544cdf0e10cSrcweir 	sal_uLong			nCountByte;
545cdf0e10cSrcweir 	sal_uLong			nRunByte;
546cdf0e10cSrcweir 	sal_uLong			nX = 0;
547cdf0e10cSrcweir 	sal_uLong			i;
548cdf0e10cSrcweir 	BYTE			cTmp;
549cdf0e10cSrcweir 	bool			bEndDecoding = FALSE;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 	if( pRLE && pDIB )
552cdf0e10cSrcweir 	{
553cdf0e10cSrcweir 		do
554cdf0e10cSrcweir 		{
555cdf0e10cSrcweir 			if( ( nCountByte = *pRLE++ ) == 0 )
556cdf0e10cSrcweir 			{
557cdf0e10cSrcweir 				nRunByte = *pRLE++;
558cdf0e10cSrcweir 
559cdf0e10cSrcweir 				if( nRunByte > 2UL )
560cdf0e10cSrcweir 				{
561cdf0e10cSrcweir 					if( bRLE4 )
562cdf0e10cSrcweir 					{
563cdf0e10cSrcweir 						nCountByte = nRunByte >> 1UL;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 						for( i = 0; i < nCountByte; i++ )
566cdf0e10cSrcweir 						{
567cdf0e10cSrcweir 							cTmp = *pRLE++;
568cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
569cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
570cdf0e10cSrcweir 						}
571cdf0e10cSrcweir 
572cdf0e10cSrcweir 						if( nRunByte & 1 )
573cdf0e10cSrcweir 							ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
574cdf0e10cSrcweir 
575cdf0e10cSrcweir 						if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
576cdf0e10cSrcweir 							pRLE++;
577cdf0e10cSrcweir 					}
578cdf0e10cSrcweir 					else
579cdf0e10cSrcweir 					{
580cdf0e10cSrcweir 						memcpy( &pDIB[ nX ], pRLE, nRunByte );
581cdf0e10cSrcweir 						pRLE += nRunByte;
582cdf0e10cSrcweir 						nX += nRunByte;
583cdf0e10cSrcweir 
584cdf0e10cSrcweir 						if( nRunByte & 1 )
585cdf0e10cSrcweir 							pRLE++;
586cdf0e10cSrcweir 					}
587cdf0e10cSrcweir 				}
588cdf0e10cSrcweir 				else if( !nRunByte )
589cdf0e10cSrcweir 				{
590cdf0e10cSrcweir 					pDIB = ( pRow += nWidthAl );
591cdf0e10cSrcweir 					nX = 0UL;
592cdf0e10cSrcweir 				}
593cdf0e10cSrcweir 				else if( nRunByte == 1 )
594cdf0e10cSrcweir 					bEndDecoding = TRUE;
595cdf0e10cSrcweir 				else
596cdf0e10cSrcweir 				{
597cdf0e10cSrcweir 					nX += *pRLE++;
598cdf0e10cSrcweir 					pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
599cdf0e10cSrcweir 				}
600cdf0e10cSrcweir 			}
601cdf0e10cSrcweir 			else
602cdf0e10cSrcweir 			{
603cdf0e10cSrcweir 				cTmp = *pRLE++;
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 				if( bRLE4 )
606cdf0e10cSrcweir 				{
607cdf0e10cSrcweir 					nRunByte = nCountByte >> 1;
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 					for( i = 0; i < nRunByte; i++ )
610cdf0e10cSrcweir 					{
611cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
612cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
613cdf0e10cSrcweir 					}
614cdf0e10cSrcweir 
615cdf0e10cSrcweir 					if( nCountByte & 1 )
616cdf0e10cSrcweir 						ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
617cdf0e10cSrcweir 				}
618cdf0e10cSrcweir 				else
619cdf0e10cSrcweir 				{
620cdf0e10cSrcweir 					for( i = 0; i < nCountByte; i++ )
621cdf0e10cSrcweir 						pDIB[ nX++ ] = cTmp;
622cdf0e10cSrcweir 				}
623cdf0e10cSrcweir 			}
624cdf0e10cSrcweir 		}
625cdf0e10cSrcweir 		while( !bEndDecoding && ( pDIB <= pLast ) );
626cdf0e10cSrcweir 	}
627cdf0e10cSrcweir }
628cdf0e10cSrcweir 
629cdf0e10cSrcweir bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
630cdf0e10cSrcweir {
631cdf0e10cSrcweir     bool bRet = false;
632cdf0e10cSrcweir     if( mhDIB || mhDDB )
633cdf0e10cSrcweir     {
634cdf0e10cSrcweir         bRet = true;
635cdf0e10cSrcweir         rData.pDIB = mhDIB;
636cdf0e10cSrcweir         rData.pDDB = mhDDB;
637cdf0e10cSrcweir         const Size& rSize = GetSize ();
638cdf0e10cSrcweir         rData.mnWidth = rSize.Width();
639cdf0e10cSrcweir         rData.mnHeight = rSize.Height();
640cdf0e10cSrcweir     }
641cdf0e10cSrcweir     return bRet;
642cdf0e10cSrcweir }
643