update credits
[LibreOffice.git] / vcl / source / gdi / bmpacc.cxx
blob2851c4b3207134fe112cc1155eea2e55d95624c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
25 #include <impbmp.hxx>
27 #include <string.h>
29 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, sal_Bool bModify ) :
30 mpBuffer ( NULL ),
31 mpScanBuf ( NULL ),
32 mFncGetPixel ( NULL ),
33 mFncSetPixel ( NULL ),
34 mbModify ( bModify )
36 ImplCreate( rBitmap );
39 BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
40 mpBuffer ( NULL ),
41 mpScanBuf ( NULL ),
42 mFncGetPixel ( NULL ),
43 mFncSetPixel ( NULL ),
44 mbModify ( sal_False )
46 ImplCreate( rBitmap );
49 BitmapReadAccess::~BitmapReadAccess()
51 ImplDestroy();
54 void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
56 ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
58 DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
60 if( pImpBmp )
62 if( mbModify && !maBitmap.ImplGetImpBitmap() )
64 rBitmap.ImplMakeUnique();
65 pImpBmp = rBitmap.ImplGetImpBitmap();
67 else
69 DBG_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
70 "Unpredictable results: bitmap is referenced more than once!" );
73 mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
75 if( !mpBuffer )
77 ImpBitmap* pNewImpBmp = new ImpBitmap;
79 if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
81 pImpBmp = pNewImpBmp;
82 rBitmap.ImplSetImpBitmap( pImpBmp );
83 mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
85 else
86 delete pNewImpBmp;
89 if( mpBuffer )
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;
102 else
104 for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
105 mpScanBuf[ nY ] = pTmpLine;
108 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
110 delete[] mpScanBuf;
111 mpScanBuf = NULL;
113 pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
114 mpBuffer = NULL;
116 else
117 maBitmap = rBitmap;
122 void BitmapReadAccess::ImplDestroy()
124 ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
126 delete[] mpScanBuf;
127 mpScanBuf = NULL;
129 if( mpBuffer && pImpBmp )
131 pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
132 mpBuffer = NULL;
136 sal_Bool BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat )
138 sal_Bool bRet = sal_True;
140 switch( nFormat )
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 )
159 default:
160 bRet = sal_False;
161 break;
164 return bRet;
167 void BitmapReadAccess::ImplZeroInitUnusedBits()
169 const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
171 if( nWidth && nHeight && nScanSize && GetBuffer() )
173 sal_uInt32 nBits;
174 bool bMsb;
176 const sal_uLong nScanlineFormat = GetScanlineFormat();
177 switch( nScanlineFormat )
179 case( BMP_FORMAT_1BIT_MSB_PAL ):
180 nBits = 1;
181 bMsb = true;
182 break;
184 case( BMP_FORMAT_1BIT_LSB_PAL ):
185 nBits = 1;
186 bMsb = false;
187 break;
189 case( BMP_FORMAT_4BIT_MSN_PAL ):
190 nBits = 4;
191 bMsb = true;
192 break;
194 case( BMP_FORMAT_4BIT_LSN_PAL ):
195 nBits = 4;
196 bMsb = false;
197 break;
199 case( BMP_FORMAT_8BIT_PAL ):
200 case( BMP_FORMAT_8BIT_TC_MASK ):
201 bMsb = true;
202 nBits = 8;
203 break;
205 case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
206 case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
207 bMsb = true;
208 nBits = 16;
209 break;
211 case( BMP_FORMAT_24BIT_TC_BGR ):
212 case( BMP_FORMAT_24BIT_TC_RGB ):
213 case( BMP_FORMAT_24BIT_TC_MASK ):
214 bMsb = true;
215 nBits = 24;
216 break;
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 ):
223 bMsb = true;
224 nBits = 32;
225 break;
227 default:
229 OSL_FAIL( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
230 nBits = 0;
231 bMsb = true;
233 break;
236 nBits *= nWidth;
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;
245 sal_uInt8 nMask;
247 if( bMsb )
248 nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
249 else
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++ )
257 pLastBytes[j] = 0;
261 else if( nBits & 0x1f )
263 sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
264 sal_uInt8* pLast4Bytes = (sal_uInt8*) GetBuffer() + ( nScanSize - 4 );
266 #ifdef OSL_LITENDIAN
267 nMask = OSL_SWAPDWORD( nMask );
268 #endif
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 ),
283 mpFillColor ( NULL )
287 BitmapWriteAccess::~BitmapWriteAccess()
289 delete mpLineColor;
290 delete mpFillColor;
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() );
304 else
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 );
323 if( nCount )
325 if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
326 memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
327 else
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;
337 switch( nFormat )
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;
356 default:
357 pFncGetPixel = NULL;
358 break;
361 if( pFncGetPixel )
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 );
384 else
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: */