xref: /trunk/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