Update ooo320-m1
[ooovba.git] / vcl / win / source / gdi / salbmp.cxx
blobb83ece63c1ab917f67259fc49f49981d4813fb0e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salbmp.cxx,v $
10 * $Revision: 1.13 $
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>
36 #include <salgdi.h>
37 #include <saldata.hxx>
38 #include <salbmp.h>
39 #include <vcl/bitmap.hxx> // for BitmapSystemData
40 #include <string.h>
42 // -----------
43 // - Inlines -
44 // -----------
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 ) );
54 // ----------------
55 // - WinSalBitmap -
56 // ----------------
58 WinSalBitmap::WinSalBitmap() :
59 mhDIB ( 0 ),
60 mhDDB ( 0 ),
61 mnBitCount ( 0 )
65 // ------------------------------------------------------------------
67 WinSalBitmap::~WinSalBitmap()
69 Destroy();
72 // ------------------------------------------------------------------
74 bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle )
76 bool bRet = TRUE;
78 if( bDIB )
79 mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap );
80 else
81 mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap );
83 if( mhDIB )
85 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB );
87 maSize = Size( pBIH->biWidth, pBIH->biHeight );
88 mnBitCount = pBIH->biBitCount;
90 if( mnBitCount )
91 mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24;
93 GlobalUnlock( mhDIB );
95 else if( mhDDB )
97 BITMAP aDDBInfo;
99 if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) )
101 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
102 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
104 if( mnBitCount )
106 mnBitCount = ( mnBitCount <= 1 ) ? 1 :
107 ( mnBitCount <= 4 ) ? 4 :
108 ( mnBitCount <= 8 ) ? 8 : 24;
111 else
113 mhDDB = 0;
114 bRet = FALSE;
117 else
118 bRet = FALSE;
120 return bRet;
123 // ------------------------------------------------------------------
125 bool WinSalBitmap::Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
127 bool bRet = FALSE;
129 mhDIB = ImplCreateDIB( rSize, nBitCount, rPal );
131 if( mhDIB )
133 maSize = rSize;
134 mnBitCount = nBitCount;
135 bRet = TRUE;
138 return bRet;
141 // ------------------------------------------------------------------
143 bool WinSalBitmap::Create( const SalBitmap& rSSalBitmap )
145 bool bRet = FALSE;
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 );
153 if ( hNewHdl )
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;
163 bRet = TRUE;
167 return bRet;
170 // ------------------------------------------------------------------
172 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
174 bool bRet = FALSE;
176 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
177 WinSalGraphics* pGraphics = static_cast<WinSalGraphics*>(pSGraphics);
179 if( rSalBmp.mhDIB )
181 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB );
182 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
183 HDC hDC = pGraphics->mhDC;
184 HBITMAP hNewDDB;
185 BITMAP aDDBInfo;
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 );
193 if( hNewDDB )
194 SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS );
196 else
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 ) )
203 mhDDB = hNewDDB;
204 maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight );
205 mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel;
207 bRet = TRUE;
209 else if( hNewDDB )
210 DeleteObject( hNewDDB );
213 return bRet;
216 // ------------------------------------------------------------------
218 bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, USHORT nNewBitCount )
220 bool bRet = FALSE;
222 const WinSalBitmap& rSalBmp = static_cast<const WinSalBitmap&>(rSSalBmp);
224 if( rSalBmp.mhDDB )
226 mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() );
228 if( mhDIB )
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;
249 bRet = TRUE;
251 else
253 GlobalUnlock( mhDIB );
254 GlobalFree( mhDIB );
255 mhDIB = 0;
258 if( hOldPal )
259 SelectPalette( hDC, hOldPal, TRUE );
261 ReleaseDC( 0, hDC );
265 return bRet;
268 // ------------------------------------------------------------------
270 bool WinSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ )
272 return false;
275 // ------------------------------------------------------------------
277 void WinSalBitmap::Destroy()
279 if( mhDIB )
280 GlobalFree( mhDIB );
281 else if( mhDDB )
282 DeleteObject( mhDDB );
284 maSize = Size();
285 mnBitCount = 0;
288 // ------------------------------------------------------------------
290 USHORT WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB )
292 USHORT nColors = 0;
294 if( 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;
305 else
306 nColors = 1 << pBIH->biBitCount;
309 else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 )
310 nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount;
312 GlobalUnlock( hDIB );
315 return nColors;
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!" );
324 HGLOBAL hDIB = 0;
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 );
333 if( hDIB )
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();
341 pBIH->biPlanes = 1;
342 pBIH->biBitCount = nBits;
343 pBIH->biCompression = BI_RGB;
344 pBIH->biSizeImage = nImageSize;
345 pBIH->biXPelsPerMeter = 0;
346 pBIH->biYPelsPerMeter = 0;
347 pBIH->biClrUsed = 0;
348 pBIH->biClrImportant = 0;
350 if ( nColors )
352 const USHORT nMinCount = Min( nColors, rPal.GetEntryCount() );
354 if( nMinCount )
355 memcpy( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGBQUAD ) );
358 GlobalUnlock( hDIB );
362 return hDIB;
365 // ------------------------------------------------------------------
367 HANDLE WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB )
369 HANDLE hCopy = 0;
371 if ( bDIB && hHdl )
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 );
383 else if ( hHdl )
385 BITMAP aBmp;
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 );
401 DeleteDC( hCopyDC );
403 SelectObject( hBmpDC, hBmpOld );
404 DeleteDC( hBmpDC );
408 return hCopy;
411 // ------------------------------------------------------------------
413 BitmapBuffer* WinSalBitmap::AcquireBuffer( bool /*bReadOnly*/ )
415 BitmapBuffer* pBuffer = NULL;
417 if( mhDIB )
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() );
427 if( hNewDIB )
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 );
441 GlobalFree( mhDIB );
442 mhDIB = hNewDIB;
443 pBI = pNewBI;
444 pBIH = pNewBIH;
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 ) )
477 ULONG nOffset = 0UL;
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 );
488 else
489 pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL );
491 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset;
493 else
494 pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI;
496 else
498 GlobalUnlock( mhDIB );
499 delete pBuffer;
500 pBuffer = NULL;
503 else
504 GlobalUnlock( mhDIB );
507 return pBuffer;
510 // ------------------------------------------------------------------
512 void WinSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
514 if( pBuffer )
516 if( mhDIB )
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 );
530 delete pBuffer;
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;
544 ULONG nCountByte;
545 ULONG nRunByte;
546 ULONG nX = 0;
547 ULONG i;
548 BYTE cTmp;
549 bool bEndDecoding = FALSE;
551 if( pRLE && pDIB )
555 if( ( nCountByte = *pRLE++ ) == 0 )
557 nRunByte = *pRLE++;
559 if( nRunByte > 2UL )
561 if( bRLE4 )
563 nCountByte = nRunByte >> 1UL;
565 for( i = 0; i < nCountByte; i++ )
567 cTmp = *pRLE++;
568 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
569 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
572 if( nRunByte & 1 )
573 ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 );
575 if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
576 pRLE++;
578 else
580 memcpy( &pDIB[ nX ], pRLE, nRunByte );
581 pRLE += nRunByte;
582 nX += nRunByte;
584 if( nRunByte & 1 )
585 pRLE++;
588 else if( !nRunByte )
590 pDIB = ( pRow += nWidthAl );
591 nX = 0UL;
593 else if( nRunByte == 1 )
594 bEndDecoding = TRUE;
595 else
597 nX += *pRLE++;
598 pDIB = ( pRow += ( *pRLE++ ) * nWidthAl );
601 else
603 cTmp = *pRLE++;
605 if( bRLE4 )
607 nRunByte = nCountByte >> 1;
609 for( i = 0; i < nRunByte; i++ )
611 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
612 ImplSetPixel4( pDIB, nX++, cTmp & 0x0f );
615 if( nCountByte & 1 )
616 ImplSetPixel4( pDIB, nX++, cTmp >> 4 );
618 else
620 for( i = 0; i < nCountByte; i++ )
621 pDIB[ nX++ ] = cTmp;
625 while( !bEndDecoding && ( pDIB <= pLast ) );
629 bool WinSalBitmap::GetSystemData( BitmapSystemData& rData )
631 bool bRet = false;
632 if( mhDIB || mhDDB )
634 bRet = true;
635 rData.pDIB = mhDIB;
636 rData.pDDB = mhDDB;
637 const Size& rSize = GetSize ();
638 rData.mnWidth = rSize.Width();
639 rData.mnHeight = rSize.Height();
641 return bRet;