Update ooo320-m1
[ooovba.git] / vcl / source / gdi / bmpacc.cxx
blobed7eb3221f4a21f26e86ff17051279cccc9e4965
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: bmpacc.cxx,v $
10 * $Revision: 1.17 $
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>
37 #include <string.h>
39 // --------------------
40 // - BitmapReadAccess -
41 // --------------------
43 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, BOOL bModify ) :
44 mpBuffer ( NULL ),
45 mpScanBuf ( NULL ),
46 mFncGetPixel ( NULL ),
47 mFncSetPixel ( NULL ),
48 mbModify ( bModify )
50 ImplCreate( rBitmap );
53 // ------------------------------------------------------------------
55 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
56 mpBuffer ( NULL ),
57 mpScanBuf ( NULL ),
58 mFncGetPixel ( NULL ),
59 mFncSetPixel ( NULL ),
60 mbModify ( FALSE )
62 ImplCreate( rBitmap );
65 // ------------------------------------------------------------------
67 BitmapReadAccess::~BitmapReadAccess()
69 ImplDestroy();
72 // ------------------------------------------------------------------
74 void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
76 ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
78 DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
80 if( pImpBmp )
82 if( mbModify && !maBitmap.ImplGetImpBitmap() )
84 rBitmap.ImplMakeUnique();
85 pImpBmp = rBitmap.ImplGetImpBitmap();
87 else
89 DBG_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
90 "Unpredictable results: bitmap is referenced more than once!" );
93 mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
95 if( !mpBuffer )
97 ImpBitmap* pNewImpBmp = new ImpBitmap;
99 if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
101 pImpBmp = pNewImpBmp;
102 rBitmap.ImplSetImpBitmap( pImpBmp );
103 mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
105 else
106 delete pNewImpBmp;
109 if( mpBuffer )
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;
122 else
124 for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
125 mpScanBuf[ nY ] = pTmpLine;
128 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
130 delete[] mpScanBuf;
131 mpScanBuf = NULL;
133 pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
134 mpBuffer = NULL;
136 else
137 maBitmap = rBitmap;
142 // ------------------------------------------------------------------
144 void BitmapReadAccess::ImplDestroy()
146 ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
148 delete[] mpScanBuf;
149 mpScanBuf = NULL;
151 if( mpBuffer && pImpBmp )
153 pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
154 mpBuffer = NULL;
158 // ------------------------------------------------------------------
160 BOOL BitmapReadAccess::ImplSetAccessPointers( ULONG nFormat )
162 BOOL bRet = TRUE;
164 switch( 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 )
183 default:
184 bRet = FALSE;
185 break;
188 return bRet;
191 // ------------------------------------------------------------------
193 void BitmapReadAccess::ImplZeroInitUnusedBits()
195 const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
197 if( nWidth && nHeight && nScanSize && GetBuffer() )
199 sal_uInt32 nBits;
200 bool bMsb;
202 const ULONG nScanlineFormat = GetScanlineFormat();
203 switch( nScanlineFormat )
205 case( BMP_FORMAT_1BIT_MSB_PAL ):
206 nBits = 1;
207 bMsb = true;
208 break;
210 case( BMP_FORMAT_1BIT_LSB_PAL ):
211 nBits = 1;
212 bMsb = false;
213 break;
215 case( BMP_FORMAT_4BIT_MSN_PAL ):
216 nBits = 4;
217 bMsb = true;
218 break;
220 case( BMP_FORMAT_4BIT_LSN_PAL ):
221 nBits = 4;
222 bMsb = false;
223 break;
225 case( BMP_FORMAT_8BIT_PAL ):
226 case( BMP_FORMAT_8BIT_TC_MASK ):
227 bMsb = true;
228 nBits = 8;
229 break;
231 case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
232 case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
233 bMsb = true;
234 nBits = 16;
235 break;
237 case( BMP_FORMAT_24BIT_TC_BGR ):
238 case( BMP_FORMAT_24BIT_TC_RGB ):
239 case( BMP_FORMAT_24BIT_TC_MASK ):
240 bMsb = true;
241 nBits = 24;
242 break;
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 ):
249 bMsb = true;
250 nBits = 32;
251 break;
253 default:
255 DBG_ERROR( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
256 nBits = 0;
257 bMsb = true;
259 break;
262 nBits *= nWidth;
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;
271 sal_uInt8 nMask;
273 if( bMsb )
274 nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
275 else
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++ )
283 pLastBytes[j] = 0;
287 else if( nBits & 0x1f )
289 sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
290 BYTE* pLast4Bytes = (BYTE*) GetBuffer() + ( nScanSize - 4 );
292 #ifdef OSL_LITENDIAN
293 nMask = SWAPLONG( nMask );
294 #endif
295 for( sal_uInt32 i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
296 ( *(sal_uInt32*) pLast4Bytes ) &= nMask;
301 // ------------------------------------------------------------------
303 void BitmapReadAccess::Flush()
305 ImplDestroy();
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 ) )
319 mbModify = bModify;
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 ),
338 mpFillColor ( NULL )
342 // ------------------------------------------------------------------
344 BitmapWriteAccess::~BitmapWriteAccess()
346 delete mpLineColor;
347 delete mpFillColor;
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() );
363 else
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 );
383 if( nCount )
385 if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
386 memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
387 else
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;
397 switch( nFormat )
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;
416 default:
417 pFncGetPixel = NULL;
418 break;
421 if( pFncGetPixel )
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 );
447 else
448 for( long nY = 0L, nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
449 CopyScanline( nY, rReadAcc );