1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/salbtype.hxx>
22 #include <vcl/bitmap.hxx>
23 #include <vcl/bmpacc.hxx>
29 BitmapReadAccess::BitmapReadAccess( Bitmap
& rBitmap
, sal_Bool bModify
) :
32 mFncGetPixel ( NULL
),
33 mFncSetPixel ( NULL
),
36 ImplCreate( rBitmap
);
39 BitmapReadAccess::BitmapReadAccess( Bitmap
& rBitmap
) :
42 mFncGetPixel ( NULL
),
43 mFncSetPixel ( NULL
),
44 mbModify ( sal_False
)
46 ImplCreate( rBitmap
);
49 BitmapReadAccess::~BitmapReadAccess()
54 void BitmapReadAccess::ImplCreate( Bitmap
& rBitmap
)
56 ImpBitmap
* pImpBmp
= rBitmap
.ImplGetImpBitmap();
58 DBG_ASSERT( pImpBmp
, "Forbidden Access to empty bitmap!" );
62 if( mbModify
&& !maBitmap
.ImplGetImpBitmap() )
64 rBitmap
.ImplMakeUnique();
65 pImpBmp
= rBitmap
.ImplGetImpBitmap();
69 DBG_ASSERT( !mbModify
|| pImpBmp
->ImplGetRefCount() == 2,
70 "Unpredictable results: bitmap is referenced more than once!" );
73 mpBuffer
= pImpBmp
->ImplAcquireBuffer( !mbModify
);
77 ImpBitmap
* pNewImpBmp
= new ImpBitmap
;
79 if( pNewImpBmp
->ImplCreate( *pImpBmp
, rBitmap
.GetBitCount() ) )
82 rBitmap
.ImplSetImpBitmap( pImpBmp
);
83 mpBuffer
= pImpBmp
->ImplAcquireBuffer( !mbModify
);
91 const long nHeight
= mpBuffer
->mnHeight
;
92 Scanline pTmpLine
= mpBuffer
->mpBits
;
94 mpScanBuf
= new Scanline
[ nHeight
];
95 maColorMask
= mpBuffer
->maColorMask
;
97 if( BMP_SCANLINE_ADJUSTMENT( mpBuffer
->mnFormat
) == BMP_FORMAT_TOP_DOWN
)
99 for( long nY
= 0L; nY
< nHeight
; nY
++, pTmpLine
+= mpBuffer
->mnScanlineSize
)
100 mpScanBuf
[ nY
] = pTmpLine
;
104 for( long nY
= nHeight
- 1; nY
>= 0; nY
--, pTmpLine
+= mpBuffer
->mnScanlineSize
)
105 mpScanBuf
[ nY
] = pTmpLine
;
108 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer
->mnFormat
) ) )
113 pImpBmp
->ImplReleaseBuffer( mpBuffer
, !mbModify
);
122 void BitmapReadAccess::ImplDestroy()
124 ImpBitmap
* pImpBmp
= maBitmap
.ImplGetImpBitmap();
129 if( mpBuffer
&& pImpBmp
)
131 pImpBmp
->ImplReleaseBuffer( mpBuffer
, !mbModify
);
136 sal_Bool
BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat
)
138 sal_Bool bRet
= sal_True
;
142 CASE_FORMAT( _1BIT_MSB_PAL
)
143 CASE_FORMAT( _1BIT_LSB_PAL
)
144 CASE_FORMAT( _4BIT_MSN_PAL
)
145 CASE_FORMAT( _4BIT_LSN_PAL
)
146 CASE_FORMAT( _8BIT_PAL
)
147 CASE_FORMAT( _8BIT_TC_MASK
)
148 CASE_FORMAT( _16BIT_TC_MSB_MASK
)
149 CASE_FORMAT( _16BIT_TC_LSB_MASK
)
150 CASE_FORMAT( _24BIT_TC_BGR
)
151 CASE_FORMAT( _24BIT_TC_RGB
)
152 CASE_FORMAT( _24BIT_TC_MASK
)
153 CASE_FORMAT( _32BIT_TC_ABGR
)
154 CASE_FORMAT( _32BIT_TC_ARGB
)
155 CASE_FORMAT( _32BIT_TC_BGRA
)
156 CASE_FORMAT( _32BIT_TC_RGBA
)
157 CASE_FORMAT( _32BIT_TC_MASK
)
167 void BitmapReadAccess::ImplZeroInitUnusedBits()
169 const sal_uInt32 nWidth
= Width(), nHeight
= Height(), nScanSize
= GetScanlineSize();
171 if( nWidth
&& nHeight
&& nScanSize
&& GetBuffer() )
176 const sal_uLong nScanlineFormat
= GetScanlineFormat();
177 switch( nScanlineFormat
)
179 case( BMP_FORMAT_1BIT_MSB_PAL
):
184 case( BMP_FORMAT_1BIT_LSB_PAL
):
189 case( BMP_FORMAT_4BIT_MSN_PAL
):
194 case( BMP_FORMAT_4BIT_LSN_PAL
):
199 case( BMP_FORMAT_8BIT_PAL
):
200 case( BMP_FORMAT_8BIT_TC_MASK
):
205 case( BMP_FORMAT_16BIT_TC_MSB_MASK
):
206 case( BMP_FORMAT_16BIT_TC_LSB_MASK
):
211 case( BMP_FORMAT_24BIT_TC_BGR
):
212 case( BMP_FORMAT_24BIT_TC_RGB
):
213 case( BMP_FORMAT_24BIT_TC_MASK
):
218 case( BMP_FORMAT_32BIT_TC_ABGR
):
219 case( BMP_FORMAT_32BIT_TC_ARGB
):
220 case( BMP_FORMAT_32BIT_TC_BGRA
):
221 case( BMP_FORMAT_32BIT_TC_RGBA
):
222 case( BMP_FORMAT_32BIT_TC_MASK
):
229 OSL_FAIL( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
237 if( nScanSize
% 4 || !bMsb
)
239 DBG_ASSERT( 8*nScanSize
>= nBits
,
240 "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
241 const sal_uInt32 nLeftOverBits
= 8*sizeof(sal_uInt8
)*nScanSize
- nBits
;
242 if( nLeftOverBits
!= 0 ) // else there is really nothing to do
244 const sal_uInt32 nBytes
= (nLeftOverBits
+ 7U) >> 3U;
248 nMask
= static_cast<sal_uInt8
>(0xffU
<< (nLeftOverBits
& 3UL));
250 nMask
= static_cast<sal_uInt8
>(0xffU
>> (nLeftOverBits
& 3UL));
252 sal_uInt8
* pLastBytes
= (sal_uInt8
*)GetBuffer() + ( nScanSize
- nBytes
);
253 for( sal_uInt32 i
= 0; i
< nHeight
; i
++, pLastBytes
+= nScanSize
)
255 *pLastBytes
&= nMask
;
256 for( sal_uInt32 j
= 1; j
< nBytes
; j
++ )
261 else if( nBits
& 0x1f )
263 sal_uInt32 nMask
= 0xffffffff << ( ( nScanSize
<< 3 ) - nBits
);
264 sal_uInt8
* pLast4Bytes
= (sal_uInt8
*) GetBuffer() + ( nScanSize
- 4 );
267 nMask
= OSL_SWAPDWORD( nMask
);
269 for( sal_uInt32 i
= 0; i
< nHeight
; i
++, pLast4Bytes
+= nScanSize
)
270 ( *(sal_uInt32
*) pLast4Bytes
) &= nMask
;
275 sal_uInt16
BitmapReadAccess::GetBestPaletteIndex( const BitmapColor
& rBitmapColor
) const
277 return( HasPalette() ? mpBuffer
->maPalette
.GetBestIndex( rBitmapColor
) : 0 );
280 BitmapWriteAccess::BitmapWriteAccess( Bitmap
& rBitmap
) :
281 BitmapReadAccess( rBitmap
, sal_True
),
282 mpLineColor ( NULL
),
287 BitmapWriteAccess::~BitmapWriteAccess()
293 void BitmapWriteAccess::CopyScanline( long nY
, const BitmapReadAccess
& rReadAcc
)
295 DBG_ASSERT( ( nY
>= 0 ) && ( nY
< mpBuffer
->mnHeight
), "y-coordinate in destination out of range!" );
296 DBG_ASSERT( nY
< rReadAcc
.Height(), "y-coordinate in source out of range!" );
297 DBG_ASSERT( ( HasPalette() && rReadAcc
.HasPalette() ) || ( !HasPalette() && !rReadAcc
.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
299 if( ( GetScanlineFormat() == rReadAcc
.GetScanlineFormat() ) &&
300 ( GetScanlineSize() >= rReadAcc
.GetScanlineSize() ) )
302 memcpy( mpScanBuf
[ nY
], rReadAcc
.GetScanline( nY
), rReadAcc
.GetScanlineSize() );
305 // TODO: use fastbmp infrastructure
306 for( long nX
= 0L, nWidth
= std::min( mpBuffer
->mnWidth
, rReadAcc
.Width() ); nX
< nWidth
; nX
++ )
307 SetPixel( nY
, nX
, rReadAcc
.GetPixel( nY
, nX
) );
311 void BitmapWriteAccess::CopyScanline( long nY
, ConstScanline aSrcScanline
,
312 sal_uLong nSrcScanlineFormat
, sal_uLong nSrcScanlineSize
)
314 const sal_uLong nFormat
= BMP_SCANLINE_FORMAT( nSrcScanlineFormat
);
316 DBG_ASSERT( ( nY
>= 0 ) && ( nY
< mpBuffer
->mnHeight
), "y-coordinate in destination out of range!" );
317 DBG_ASSERT( ( HasPalette() && nFormat
<= BMP_FORMAT_8BIT_PAL
) ||
318 ( !HasPalette() && nFormat
> BMP_FORMAT_8BIT_PAL
),
319 "No copying possible between palette and non palette scanlines!" );
321 const sal_uLong nCount
= std::min( GetScanlineSize(), nSrcScanlineSize
);
325 if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat
) )
326 memcpy( mpScanBuf
[ nY
], aSrcScanline
, nCount
);
329 DBG_ASSERT( nFormat
!= BMP_FORMAT_8BIT_TC_MASK
&&
330 nFormat
!= BMP_FORMAT_16BIT_TC_MSB_MASK
&& nFormat
!= BMP_FORMAT_16BIT_TC_LSB_MASK
&&
331 nFormat
!= BMP_FORMAT_24BIT_TC_MASK
&& nFormat
!= BMP_FORMAT_32BIT_TC_MASK
,
332 "No support for pixel formats with color masks yet!" );
334 // TODO: use fastbmp infrastructure
335 FncGetPixel pFncGetPixel
;
339 case( BMP_FORMAT_1BIT_MSB_PAL
): pFncGetPixel
= GetPixelFor_1BIT_MSB_PAL
; break;
340 case( BMP_FORMAT_1BIT_LSB_PAL
): pFncGetPixel
= GetPixelFor_1BIT_LSB_PAL
; break;
341 case( BMP_FORMAT_4BIT_MSN_PAL
): pFncGetPixel
= GetPixelFor_4BIT_MSN_PAL
; break;
342 case( BMP_FORMAT_4BIT_LSN_PAL
): pFncGetPixel
= GetPixelFor_4BIT_LSN_PAL
; break;
343 case( BMP_FORMAT_8BIT_PAL
): pFncGetPixel
= GetPixelFor_8BIT_PAL
; break;
344 case( BMP_FORMAT_8BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_8BIT_TC_MASK
; break;
345 case( BMP_FORMAT_16BIT_TC_MSB_MASK
): pFncGetPixel
= GetPixelFor_16BIT_TC_MSB_MASK
; break;
346 case( BMP_FORMAT_16BIT_TC_LSB_MASK
): pFncGetPixel
= GetPixelFor_16BIT_TC_LSB_MASK
; break;
347 case( BMP_FORMAT_24BIT_TC_BGR
): pFncGetPixel
= GetPixelFor_24BIT_TC_BGR
; break;
348 case( BMP_FORMAT_24BIT_TC_RGB
): pFncGetPixel
= GetPixelFor_24BIT_TC_RGB
; break;
349 case( BMP_FORMAT_24BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_24BIT_TC_MASK
; break;
350 case( BMP_FORMAT_32BIT_TC_ABGR
): pFncGetPixel
= GetPixelFor_32BIT_TC_ABGR
; break;
351 case( BMP_FORMAT_32BIT_TC_ARGB
): pFncGetPixel
= GetPixelFor_32BIT_TC_ARGB
; break;
352 case( BMP_FORMAT_32BIT_TC_BGRA
): pFncGetPixel
= GetPixelFor_32BIT_TC_BGRA
; break;
353 case( BMP_FORMAT_32BIT_TC_RGBA
): pFncGetPixel
= GetPixelFor_32BIT_TC_RGBA
; break;
354 case( BMP_FORMAT_32BIT_TC_MASK
): pFncGetPixel
= GetPixelFor_32BIT_TC_MASK
; break;
363 const ColorMask aDummyMask
;
365 for( long nX
= 0L, nWidth
= mpBuffer
->mnWidth
; nX
< nWidth
; nX
++ )
366 SetPixel( nY
, nX
, pFncGetPixel( aSrcScanline
, nX
, aDummyMask
) );
372 void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess
& rReadAcc
)
374 DBG_ASSERT( ( HasPalette() && rReadAcc
.HasPalette() ) || ( !HasPalette() && !rReadAcc
.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
376 if( ( GetScanlineFormat() == rReadAcc
.GetScanlineFormat() ) &&
377 ( GetScanlineSize() == rReadAcc
.GetScanlineSize() ) )
379 const long nHeight
= std::min( mpBuffer
->mnHeight
, rReadAcc
.Height() );
380 const sal_uLong nCount
= nHeight
* mpBuffer
->mnScanlineSize
;
382 memcpy( mpBuffer
->mpBits
, rReadAcc
.GetBuffer(), nCount
);
385 for( long nY
= 0L, nHeight
= std::min( mpBuffer
->mnHeight
, rReadAcc
.Height() ); nY
< nHeight
; nY
++ )
386 CopyScanline( nY
, rReadAcc
);
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */