1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bmpacc.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <vcl/salbtype.hxx>
34 #include <vcl/impbmp.hxx>
35 #include <vcl/bitmap.hxx>
36 #include <vcl/bmpacc.hxx>
39 // --------------------
40 // - BitmapReadAccess -
41 // --------------------
43 BitmapReadAccess::BitmapReadAccess( Bitmap
& rBitmap
, BOOL bModify
) :
46 mFncGetPixel ( NULL
),
47 mFncSetPixel ( NULL
),
50 ImplCreate( rBitmap
);
53 // ------------------------------------------------------------------
55 BitmapReadAccess::BitmapReadAccess( Bitmap
& rBitmap
) :
58 mFncGetPixel ( NULL
),
59 mFncSetPixel ( NULL
),
62 ImplCreate( rBitmap
);
65 // ------------------------------------------------------------------
67 BitmapReadAccess::~BitmapReadAccess()
72 // ------------------------------------------------------------------
74 void BitmapReadAccess::ImplCreate( Bitmap
& rBitmap
)
76 ImpBitmap
* pImpBmp
= rBitmap
.ImplGetImpBitmap();
78 DBG_ASSERT( pImpBmp
, "Forbidden Access to empty bitmap!" );
82 if( mbModify
&& !maBitmap
.ImplGetImpBitmap() )
84 rBitmap
.ImplMakeUnique();
85 pImpBmp
= rBitmap
.ImplGetImpBitmap();
89 DBG_ASSERT( !mbModify
|| pImpBmp
->ImplGetRefCount() == 2,
90 "Unpredictable results: bitmap is referenced more than once!" );
93 mpBuffer
= pImpBmp
->ImplAcquireBuffer( !mbModify
);
97 ImpBitmap
* pNewImpBmp
= new ImpBitmap
;
99 if( pNewImpBmp
->ImplCreate( *pImpBmp
, rBitmap
.GetBitCount() ) )
101 pImpBmp
= pNewImpBmp
;
102 rBitmap
.ImplSetImpBitmap( pImpBmp
);
103 mpBuffer
= pImpBmp
->ImplAcquireBuffer( !mbModify
);
111 const long nHeight
= mpBuffer
->mnHeight
;
112 Scanline pTmpLine
= mpBuffer
->mpBits
;
114 mpScanBuf
= new Scanline
[ nHeight
];
115 maColorMask
= mpBuffer
->maColorMask
;
117 if( BMP_SCANLINE_ADJUSTMENT( mpBuffer
->mnFormat
) == BMP_FORMAT_TOP_DOWN
)
119 for( long nY
= 0L; nY
< nHeight
; nY
++, pTmpLine
+= mpBuffer
->mnScanlineSize
)
120 mpScanBuf
[ nY
] = pTmpLine
;
124 for( long nY
= nHeight
- 1; nY
>= 0; nY
--, pTmpLine
+= mpBuffer
->mnScanlineSize
)
125 mpScanBuf
[ nY
] = pTmpLine
;
128 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer
->mnFormat
) ) )
133 pImpBmp
->ImplReleaseBuffer( mpBuffer
, !mbModify
);
142 // ------------------------------------------------------------------
144 void BitmapReadAccess::ImplDestroy()
146 ImpBitmap
* pImpBmp
= maBitmap
.ImplGetImpBitmap();
151 if( mpBuffer
&& pImpBmp
)
153 pImpBmp
->ImplReleaseBuffer( mpBuffer
, !mbModify
);
158 // ------------------------------------------------------------------
160 BOOL
BitmapReadAccess::ImplSetAccessPointers( ULONG nFormat
)
166 CASE_FORMAT( _1BIT_MSB_PAL
)
167 CASE_FORMAT( _1BIT_LSB_PAL
)
168 CASE_FORMAT( _4BIT_MSN_PAL
)
169 CASE_FORMAT( _4BIT_LSN_PAL
)
170 CASE_FORMAT( _8BIT_PAL
)
171 CASE_FORMAT( _8BIT_TC_MASK
)
172 CASE_FORMAT( _16BIT_TC_MSB_MASK
)
173 CASE_FORMAT( _16BIT_TC_LSB_MASK
)
174 CASE_FORMAT( _24BIT_TC_BGR
)
175 CASE_FORMAT( _24BIT_TC_RGB
)
176 CASE_FORMAT( _24BIT_TC_MASK
)
177 CASE_FORMAT( _32BIT_TC_ABGR
)
178 CASE_FORMAT( _32BIT_TC_ARGB
)
179 CASE_FORMAT( _32BIT_TC_BGRA
)
180 CASE_FORMAT( _32BIT_TC_RGBA
)
181 CASE_FORMAT( _32BIT_TC_MASK
)
191 // ------------------------------------------------------------------
193 void BitmapReadAccess::ImplZeroInitUnusedBits()
195 const sal_uInt32 nWidth
= Width(), nHeight
= Height(), nScanSize
= GetScanlineSize();
197 if( nWidth
&& nHeight
&& nScanSize
&& GetBuffer() )
202 const ULONG nScanlineFormat
= GetScanlineFormat();
203 switch( nScanlineFormat
)
205 case( BMP_FORMAT_1BIT_MSB_PAL
):
210 case( BMP_FORMAT_1BIT_LSB_PAL
):
215 case( BMP_FORMAT_4BIT_MSN_PAL
):
220 case( BMP_FORMAT_4BIT_LSN_PAL
):
225 case( BMP_FORMAT_8BIT_PAL
):
226 case( BMP_FORMAT_8BIT_TC_MASK
):
231 case( BMP_FORMAT_16BIT_TC_MSB_MASK
):
232 case( BMP_FORMAT_16BIT_TC_LSB_MASK
):
237 case( BMP_FORMAT_24BIT_TC_BGR
):
238 case( BMP_FORMAT_24BIT_TC_RGB
):
239 case( BMP_FORMAT_24BIT_TC_MASK
):
244 case( BMP_FORMAT_32BIT_TC_ABGR
):
245 case( BMP_FORMAT_32BIT_TC_ARGB
):
246 case( BMP_FORMAT_32BIT_TC_BGRA
):
247 case( BMP_FORMAT_32BIT_TC_RGBA
):
248 case( BMP_FORMAT_32BIT_TC_MASK
):
255 DBG_ERROR( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
263 if( nScanSize
% 4 || !bMsb
)
265 DBG_ASSERT( 8*nScanSize
>= nBits
,
266 "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
267 const sal_uInt32 nLeftOverBits
= 8*sizeof(sal_uInt8
)*nScanSize
- nBits
;
268 if( nLeftOverBits
!= 0 ) // else there is really nothing to do
270 const sal_uInt32 nBytes
= (nLeftOverBits
+ 7U) >> 3U;
274 nMask
= static_cast<sal_uInt8
>(0xffU
<< (nLeftOverBits
& 3UL));
276 nMask
= static_cast<sal_uInt8
>(0xffU
>> (nLeftOverBits
& 3UL));
278 BYTE
* pLastBytes
= (BYTE
*)GetBuffer() + ( nScanSize
- nBytes
);
279 for( sal_uInt32 i
= 0; i
< nHeight
; i
++, pLastBytes
+= nScanSize
)
281 *pLastBytes
&= nMask
;
282 for( sal_uInt32 j
= 1; j
< nBytes
; j
++ )
287 else if( nBits
& 0x1f )
289 sal_uInt32 nMask
= 0xffffffff << ( ( nScanSize
<< 3 ) - nBits
);
290 BYTE
* pLast4Bytes
= (BYTE
*) GetBuffer() + ( nScanSize
- 4 );
293 nMask
= SWAPLONG( nMask
);
295 for( sal_uInt32 i
= 0; i
< nHeight
; i
++, pLast4Bytes
+= nScanSize
)
296 ( *(sal_uInt32
*) pLast4Bytes
) &= nMask
;
301 // ------------------------------------------------------------------
303 void BitmapReadAccess::Flush()
308 // ------------------------------------------------------------------
310 void BitmapReadAccess::ReAccess( BOOL bModify
)
312 const ImpBitmap
* pImpBmp
= maBitmap
.ImplGetImpBitmap();
314 DBG_ASSERT( !mpBuffer
, "No ReAccess possible while bitmap is being accessed!" );
315 DBG_ASSERT( pImpBmp
&& ( pImpBmp
->ImplGetRefCount() > 1UL ), "Accessed bitmap does not exist anymore!" );
317 if( !mpBuffer
&& pImpBmp
&& ( pImpBmp
->ImplGetRefCount() > 1UL ) )
320 ImplCreate( maBitmap
);
324 // ------------------------------------------------------------------
326 USHORT
BitmapReadAccess::GetBestPaletteIndex( const BitmapColor
& rBitmapColor
) const
328 return( HasPalette() ? mpBuffer
->maPalette
.GetBestIndex( rBitmapColor
) : 0 );
331 // ---------------------
332 // - BitmapWriteAccess -
333 // ---------------------
335 BitmapWriteAccess::BitmapWriteAccess( Bitmap
& rBitmap
) :
336 BitmapReadAccess( rBitmap
, TRUE
),
337 mpLineColor ( NULL
),
342 // ------------------------------------------------------------------
344 BitmapWriteAccess::~BitmapWriteAccess()
350 // ------------------------------------------------------------------
352 void BitmapWriteAccess::CopyScanline( long nY
, const BitmapReadAccess
& rReadAcc
)
354 DBG_ASSERT( ( nY
>= 0 ) && ( nY
< mpBuffer
->mnHeight
), "y-coordinate in destination out of range!" );
355 DBG_ASSERT( nY
< rReadAcc
.Height(), "y-coordinate in source out of range!" );
356 DBG_ASSERT( ( HasPalette() && rReadAcc
.HasPalette() ) || ( !HasPalette() && !rReadAcc
.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
358 if( ( GetScanlineFormat() == rReadAcc
.GetScanlineFormat() ) &&
359 ( GetScanlineSize() >= rReadAcc
.GetScanlineSize() ) )
361 memcpy( mpScanBuf
[ nY
], rReadAcc
.GetScanline( nY
), rReadAcc
.GetScanlineSize() );
364 // TODO: use fastbmp infrastructure
365 for( long nX
= 0L, nWidth
= Min( mpBuffer
->mnWidth
, rReadAcc
.Width() ); nX
< nWidth
; nX
++ )
366 SetPixel( nY
, nX
, rReadAcc
.GetPixel( nY
, nX
) );
369 // ------------------------------------------------------------------
371 void BitmapWriteAccess::CopyScanline( long nY
, ConstScanline aSrcScanline
,
372 ULONG nSrcScanlineFormat
, ULONG nSrcScanlineSize
)
374 const ULONG nFormat
= BMP_SCANLINE_FORMAT( nSrcScanlineFormat
);
376 DBG_ASSERT( ( nY
>= 0 ) && ( nY
< mpBuffer
->mnHeight
), "y-coordinate in destination out of range!" );
377 DBG_ASSERT( ( HasPalette() && nFormat
<= BMP_FORMAT_8BIT_PAL
) ||
378 ( !HasPalette() && nFormat
> BMP_FORMAT_8BIT_PAL
),
379 "No copying possible between palette and non palette scanlines!" );
381 const ULONG nCount
= Min( GetScanlineSize(), nSrcScanlineSize
);
385 if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat
) )
386 memcpy( mpScanBuf
[ nY
], aSrcScanline
, nCount
);
389 DBG_ASSERT( nFormat
!= BMP_FORMAT_8BIT_TC_MASK
&&
390 nFormat
!= BMP_FORMAT_16BIT_TC_MSB_MASK
&& nFormat
!= BMP_FORMAT_16BIT_TC_LSB_MASK
&&
391 nFormat
!= BMP_FORMAT_24BIT_TC_MASK
&& nFormat
!= BMP_FORMAT_32BIT_TC_MASK
,
392 "No support for pixel formats with color masks yet!" );
394 // TODO: use fastbmp infrastructure
395 FncGetPixel pFncGetPixel
;
399 case( BMP_FORMAT_1BIT_MSB_PAL
): pFncGetPixel
= GetPixelFor_1BIT_MSB_PAL
; break;
400 case( BMP_FORMAT_1BIT_LSB_PAL
): pFncGetPixel
= GetPixelFor_1BIT_LSB_PAL
; break;
401 case( BMP_FORMAT_4BIT_MSN_PAL
): pFncGetPixel
= GetPixelFor_4BIT_MSN_PAL
; break;
402 case( BMP_FORMAT_4BIT_LSN_PAL
): pFncGetPixel
= GetPixelFor_4BIT_LSN_PAL
; break;
403 case( BMP_FORMAT_8BIT_PAL
): pFncGetPixel
= GetPixelFor_8BIT_PAL
; break;
404 case( BMP_FORMAT_8BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_8BIT_TC_MASK
; break;
405 case( BMP_FORMAT_16BIT_TC_MSB_MASK
): pFncGetPixel
= GetPixelFor_16BIT_TC_MSB_MASK
; break;
406 case( BMP_FORMAT_16BIT_TC_LSB_MASK
): pFncGetPixel
= GetPixelFor_16BIT_TC_LSB_MASK
; break;
407 case( BMP_FORMAT_24BIT_TC_BGR
): pFncGetPixel
= GetPixelFor_24BIT_TC_BGR
; break;
408 case( BMP_FORMAT_24BIT_TC_RGB
): pFncGetPixel
= GetPixelFor_24BIT_TC_RGB
; break;
409 case( BMP_FORMAT_24BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_24BIT_TC_MASK
; break;
410 case( BMP_FORMAT_32BIT_TC_ABGR
): pFncGetPixel
= GetPixelFor_32BIT_TC_ABGR
; break;
411 case( BMP_FORMAT_32BIT_TC_ARGB
): pFncGetPixel
= GetPixelFor_32BIT_TC_ARGB
; break;
412 case( BMP_FORMAT_32BIT_TC_BGRA
): pFncGetPixel
= GetPixelFor_32BIT_TC_BGRA
; break;
413 case( BMP_FORMAT_32BIT_TC_RGBA
): pFncGetPixel
= GetPixelFor_32BIT_TC_RGBA
; break;
414 case( BMP_FORMAT_32BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_32BIT_TC_MASK
; break;
423 const ColorMask aDummyMask
;
425 for( long nX
= 0L, nWidth
= mpBuffer
->mnWidth
; nX
< nWidth
; nX
++ )
426 SetPixel( nY
, nX
, pFncGetPixel( aSrcScanline
, nX
, aDummyMask
) );
433 // ------------------------------------------------------------------
435 void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess
& rReadAcc
)
437 DBG_ASSERT( ( HasPalette() && rReadAcc
.HasPalette() ) || ( !HasPalette() && !rReadAcc
.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
439 if( ( GetScanlineFormat() == rReadAcc
.GetScanlineFormat() ) &&
440 ( GetScanlineSize() == rReadAcc
.GetScanlineSize() ) )
442 const long nHeight
= Min( mpBuffer
->mnHeight
, rReadAcc
.Height() );
443 const ULONG nCount
= nHeight
* mpBuffer
->mnScanlineSize
;
445 memcpy( mpBuffer
->mpBits
, rReadAcc
.GetBuffer(), nCount
);
448 for( long nY
= 0L, nHeight
= Min( mpBuffer
->mnHeight
, rReadAcc
.Height() ); nY
< nHeight
; nY
++ )
449 CopyScanline( nY
, rReadAcc
);