xref: /aoo41x/main/vcl/source/gdi/bmpacc.cxx (revision 4b612aeb)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
109f62ea84SAndrew Rist  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
199f62ea84SAndrew Rist  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <vcl/salbtype.hxx>
28cdf0e10cSrcweir #include <vcl/bitmap.hxx>
29cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <impbmp.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <string.h>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir // --------------------
36cdf0e10cSrcweir // - BitmapReadAccess -
37cdf0e10cSrcweir // --------------------
38cdf0e10cSrcweir 
BitmapReadAccess(Bitmap & rBitmap,sal_Bool bModify)39cdf0e10cSrcweir BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, sal_Bool bModify ) :
40cdf0e10cSrcweir 			mpBuffer		( NULL ),
41cdf0e10cSrcweir 			mpScanBuf		( NULL ),
42cdf0e10cSrcweir 			mFncGetPixel	( NULL ),
43cdf0e10cSrcweir 			mFncSetPixel	( NULL ),
44cdf0e10cSrcweir 			mbModify		( bModify )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir 	ImplCreate( rBitmap );
47cdf0e10cSrcweir }
48cdf0e10cSrcweir 
49cdf0e10cSrcweir // ------------------------------------------------------------------
50cdf0e10cSrcweir 
BitmapReadAccess(Bitmap & rBitmap)51cdf0e10cSrcweir BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
52cdf0e10cSrcweir 			mpBuffer		( NULL ),
53cdf0e10cSrcweir 			mpScanBuf		( NULL ),
54cdf0e10cSrcweir 			mFncGetPixel	( NULL ),
55cdf0e10cSrcweir 			mFncSetPixel	( NULL ),
56cdf0e10cSrcweir 			mbModify		( sal_False )
57cdf0e10cSrcweir {
58cdf0e10cSrcweir 	ImplCreate( rBitmap );
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
61cdf0e10cSrcweir // ------------------------------------------------------------------
62cdf0e10cSrcweir 
~BitmapReadAccess()63cdf0e10cSrcweir BitmapReadAccess::~BitmapReadAccess()
64cdf0e10cSrcweir {
65cdf0e10cSrcweir 	ImplDestroy();
66cdf0e10cSrcweir }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir // ------------------------------------------------------------------
69cdf0e10cSrcweir 
ImplCreate(Bitmap & rBitmap)70cdf0e10cSrcweir void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir 	ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 	DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
75cdf0e10cSrcweir 
76cdf0e10cSrcweir 	if( pImpBmp )
77cdf0e10cSrcweir 	{
78cdf0e10cSrcweir 		if( mbModify && !maBitmap.ImplGetImpBitmap() )
79cdf0e10cSrcweir 		{
80cdf0e10cSrcweir 			rBitmap.ImplMakeUnique();
81cdf0e10cSrcweir 			pImpBmp = rBitmap.ImplGetImpBitmap();
82cdf0e10cSrcweir 		}
83cdf0e10cSrcweir 		else
84cdf0e10cSrcweir 		{
85cdf0e10cSrcweir 			DBG_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
86cdf0e10cSrcweir 						"Unpredictable results: bitmap is referenced more than once!" );
87cdf0e10cSrcweir 		}
88cdf0e10cSrcweir 
89cdf0e10cSrcweir 		mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
90cdf0e10cSrcweir 
91cdf0e10cSrcweir 		if( !mpBuffer )
92cdf0e10cSrcweir 		{
93cdf0e10cSrcweir 			ImpBitmap* pNewImpBmp = new ImpBitmap;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir 			if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount()  ) )
96cdf0e10cSrcweir 			{
97cdf0e10cSrcweir 				pImpBmp = pNewImpBmp;
98cdf0e10cSrcweir 				rBitmap.ImplSetImpBitmap( pImpBmp );
99cdf0e10cSrcweir 				mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
100cdf0e10cSrcweir 			}
101cdf0e10cSrcweir 			else
102cdf0e10cSrcweir 				delete pNewImpBmp;
103cdf0e10cSrcweir 		}
104cdf0e10cSrcweir 
105cdf0e10cSrcweir 		if( mpBuffer )
106cdf0e10cSrcweir 		{
107cdf0e10cSrcweir 			const long	nHeight = mpBuffer->mnHeight;
108cdf0e10cSrcweir 			Scanline	pTmpLine = mpBuffer->mpBits;
109cdf0e10cSrcweir 
110*4b612aebSArrigo Marchiori             try {
111*4b612aebSArrigo Marchiori                 mpScanBuf = new Scanline[ nHeight ];
112*4b612aebSArrigo Marchiori             } catch (std::bad_alloc &) {
113*4b612aebSArrigo Marchiori                 mpScanBuf = NULL;
114*4b612aebSArrigo Marchiori             }
115*4b612aebSArrigo Marchiori             if (mpScanBuf) {
116*4b612aebSArrigo Marchiori                 maColorMask = mpBuffer->maColorMask;
117*4b612aebSArrigo Marchiori 
118*4b612aebSArrigo Marchiori                 if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
119*4b612aebSArrigo Marchiori                 {
120*4b612aebSArrigo Marchiori                     for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
121*4b612aebSArrigo Marchiori                         mpScanBuf[ nY ] = pTmpLine;
122*4b612aebSArrigo Marchiori                 }
123*4b612aebSArrigo Marchiori                 else
124*4b612aebSArrigo Marchiori                 {
125*4b612aebSArrigo Marchiori                     for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
126*4b612aebSArrigo Marchiori                         mpScanBuf[ nY ] = pTmpLine;
127*4b612aebSArrigo Marchiori                 }
128*4b612aebSArrigo Marchiori 
129*4b612aebSArrigo Marchiori                 if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
130*4b612aebSArrigo Marchiori                 {
131*4b612aebSArrigo Marchiori                     delete[] mpScanBuf;
132*4b612aebSArrigo Marchiori                     mpScanBuf = NULL;
133*4b612aebSArrigo Marchiori 
134*4b612aebSArrigo Marchiori                     pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
135*4b612aebSArrigo Marchiori                     mpBuffer = NULL;
136*4b612aebSArrigo Marchiori                 }
137*4b612aebSArrigo Marchiori                 else
138*4b612aebSArrigo Marchiori                     maBitmap = rBitmap;
139*4b612aebSArrigo Marchiori             } else {
140*4b612aebSArrigo Marchiori                 pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
141*4b612aebSArrigo Marchiori                 mpBuffer = NULL;
142*4b612aebSArrigo Marchiori             }
143*4b612aebSArrigo Marchiori         }
144cdf0e10cSrcweir 	}
145cdf0e10cSrcweir }
146cdf0e10cSrcweir 
147cdf0e10cSrcweir // ------------------------------------------------------------------
148cdf0e10cSrcweir 
ImplDestroy()149cdf0e10cSrcweir void BitmapReadAccess::ImplDestroy()
150cdf0e10cSrcweir {
151cdf0e10cSrcweir 	ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 	delete[] mpScanBuf;
154cdf0e10cSrcweir 	mpScanBuf = NULL;
155cdf0e10cSrcweir 
156cdf0e10cSrcweir 	if( mpBuffer && pImpBmp )
157cdf0e10cSrcweir 	{
158cdf0e10cSrcweir 		pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
159cdf0e10cSrcweir 		mpBuffer = NULL;
160cdf0e10cSrcweir 	}
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir // ------------------------------------------------------------------
164cdf0e10cSrcweir 
ImplSetAccessPointers(sal_uLong nFormat)165cdf0e10cSrcweir sal_Bool BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat )
166cdf0e10cSrcweir {
167cdf0e10cSrcweir 	sal_Bool bRet = sal_True;
168cdf0e10cSrcweir 
169cdf0e10cSrcweir 	switch( nFormat )
170cdf0e10cSrcweir 	{
171cdf0e10cSrcweir 		CASE_FORMAT( _1BIT_MSB_PAL )
172cdf0e10cSrcweir 		CASE_FORMAT( _1BIT_LSB_PAL )
173cdf0e10cSrcweir 		CASE_FORMAT( _4BIT_MSN_PAL )
174cdf0e10cSrcweir 		CASE_FORMAT( _4BIT_LSN_PAL )
175cdf0e10cSrcweir 		CASE_FORMAT( _8BIT_PAL )
176cdf0e10cSrcweir 		CASE_FORMAT( _8BIT_TC_MASK )
177cdf0e10cSrcweir 		CASE_FORMAT( _16BIT_TC_MSB_MASK )
178cdf0e10cSrcweir 		CASE_FORMAT( _16BIT_TC_LSB_MASK )
179cdf0e10cSrcweir 		CASE_FORMAT( _24BIT_TC_BGR )
180cdf0e10cSrcweir 		CASE_FORMAT( _24BIT_TC_RGB )
181cdf0e10cSrcweir 		CASE_FORMAT( _24BIT_TC_MASK )
182cdf0e10cSrcweir 		CASE_FORMAT( _32BIT_TC_ABGR )
183cdf0e10cSrcweir 		CASE_FORMAT( _32BIT_TC_ARGB )
184cdf0e10cSrcweir 		CASE_FORMAT( _32BIT_TC_BGRA )
185cdf0e10cSrcweir 		CASE_FORMAT( _32BIT_TC_RGBA )
186cdf0e10cSrcweir 		CASE_FORMAT( _32BIT_TC_MASK )
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 		default:
189cdf0e10cSrcweir 			bRet = sal_False;
190cdf0e10cSrcweir 		break;
191cdf0e10cSrcweir 	}
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	return bRet;
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
196cdf0e10cSrcweir // ------------------------------------------------------------------
197cdf0e10cSrcweir 
ImplZeroInitUnusedBits()198cdf0e10cSrcweir void BitmapReadAccess::ImplZeroInitUnusedBits()
199cdf0e10cSrcweir {
200cdf0e10cSrcweir 	const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
201cdf0e10cSrcweir 
202cdf0e10cSrcweir 	if( nWidth && nHeight && nScanSize && GetBuffer() )
203cdf0e10cSrcweir 	{
204cdf0e10cSrcweir 		sal_uInt32 nBits;
205cdf0e10cSrcweir         bool       bMsb;
206cdf0e10cSrcweir 
207cdf0e10cSrcweir         const sal_uLong nScanlineFormat = GetScanlineFormat();
208cdf0e10cSrcweir 		switch( nScanlineFormat )
209cdf0e10cSrcweir 		{
210cdf0e10cSrcweir             case( BMP_FORMAT_1BIT_MSB_PAL ):
211cdf0e10cSrcweir 				nBits = 1;
212cdf0e10cSrcweir 				bMsb = true;
213cdf0e10cSrcweir                 break;
214cdf0e10cSrcweir 
215cdf0e10cSrcweir             case( BMP_FORMAT_1BIT_LSB_PAL ):
216cdf0e10cSrcweir 				nBits = 1;
217cdf0e10cSrcweir 				bMsb = false;
218cdf0e10cSrcweir                 break;
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 			case( BMP_FORMAT_4BIT_MSN_PAL ):
221cdf0e10cSrcweir 				nBits = 4;
222cdf0e10cSrcweir 				bMsb = true;
223cdf0e10cSrcweir                 break;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir             case( BMP_FORMAT_4BIT_LSN_PAL ):
226cdf0e10cSrcweir 				nBits = 4;
227cdf0e10cSrcweir 				bMsb = false;
228cdf0e10cSrcweir                 break;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir 			case( BMP_FORMAT_8BIT_PAL ):
231cdf0e10cSrcweir 			case( BMP_FORMAT_8BIT_TC_MASK ):
232cdf0e10cSrcweir 				bMsb = true;
233cdf0e10cSrcweir 				nBits = 8;
234cdf0e10cSrcweir 			break;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 			case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
237cdf0e10cSrcweir 			case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
238cdf0e10cSrcweir 				bMsb = true;
239cdf0e10cSrcweir 				nBits = 16;
240cdf0e10cSrcweir 			break;
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 			case( BMP_FORMAT_24BIT_TC_BGR ):
243cdf0e10cSrcweir 			case( BMP_FORMAT_24BIT_TC_RGB ):
244cdf0e10cSrcweir 			case( BMP_FORMAT_24BIT_TC_MASK ):
245cdf0e10cSrcweir 				bMsb = true;
246cdf0e10cSrcweir 				nBits = 24;
247cdf0e10cSrcweir 			break;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 			case( BMP_FORMAT_32BIT_TC_ABGR ):
250cdf0e10cSrcweir 			case( BMP_FORMAT_32BIT_TC_ARGB ):
251cdf0e10cSrcweir 			case( BMP_FORMAT_32BIT_TC_BGRA ):
252cdf0e10cSrcweir 			case( BMP_FORMAT_32BIT_TC_RGBA ):
253cdf0e10cSrcweir 			case( BMP_FORMAT_32BIT_TC_MASK ):
254cdf0e10cSrcweir 				bMsb = true;
255cdf0e10cSrcweir 				nBits = 32;
256cdf0e10cSrcweir 			break;
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 			default:
259cdf0e10cSrcweir 			{
260cdf0e10cSrcweir 				DBG_ERROR( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
261cdf0e10cSrcweir 				nBits = 0;
262cdf0e10cSrcweir 				bMsb = true;
263cdf0e10cSrcweir 			}
264cdf0e10cSrcweir 			break;
265cdf0e10cSrcweir 		}
266cdf0e10cSrcweir 
267cdf0e10cSrcweir         nBits *= nWidth;
268cdf0e10cSrcweir 		if( nScanSize % 4 || !bMsb )
269cdf0e10cSrcweir         {
270cdf0e10cSrcweir             DBG_ASSERT( 8*nScanSize >= nBits,
271cdf0e10cSrcweir                         "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
272cdf0e10cSrcweir 			const sal_uInt32 nLeftOverBits = 8*sizeof(sal_uInt8)*nScanSize - nBits;
273cdf0e10cSrcweir             if( nLeftOverBits != 0 ) // else there is really nothing to do
274cdf0e10cSrcweir             {
275cdf0e10cSrcweir                 const sal_uInt32 nBytes = (nLeftOverBits + 7U) >> 3U;
276cdf0e10cSrcweir                 sal_uInt8	     nMask;
277cdf0e10cSrcweir 
278cdf0e10cSrcweir                 if( bMsb )
279cdf0e10cSrcweir                     nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
280cdf0e10cSrcweir                 else
281cdf0e10cSrcweir                     nMask = static_cast<sal_uInt8>(0xffU >> (nLeftOverBits & 3UL));
282cdf0e10cSrcweir 
283cdf0e10cSrcweir                 sal_uInt8* pLastBytes = (sal_uInt8*)GetBuffer() + ( nScanSize - nBytes );
284cdf0e10cSrcweir                 for( sal_uInt32 i = 0; i < nHeight; i++, pLastBytes += nScanSize )
285cdf0e10cSrcweir                 {
286cdf0e10cSrcweir                     *pLastBytes &= nMask;
287cdf0e10cSrcweir                     for( sal_uInt32 j = 1; j < nBytes; j++ )
288cdf0e10cSrcweir                         pLastBytes[j] = 0;
289cdf0e10cSrcweir                 }
290cdf0e10cSrcweir             }
291cdf0e10cSrcweir         }
292cdf0e10cSrcweir         else if( nBits & 0x1f )
293cdf0e10cSrcweir 		{
294cdf0e10cSrcweir 			sal_uInt32	nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
295cdf0e10cSrcweir 			sal_uInt8*		pLast4Bytes = (sal_uInt8*) GetBuffer() + ( nScanSize - 4 );
296cdf0e10cSrcweir 
297cdf0e10cSrcweir #ifdef OSL_LITENDIAN
298cdf0e10cSrcweir 			nMask = SWAPLONG( nMask );
299cdf0e10cSrcweir #endif
300cdf0e10cSrcweir 			for( sal_uInt32 i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
301cdf0e10cSrcweir 				( *(sal_uInt32*) pLast4Bytes ) &= nMask;
302cdf0e10cSrcweir 		}
303cdf0e10cSrcweir 	}
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir // ------------------------------------------------------------------
307cdf0e10cSrcweir 
Flush()308cdf0e10cSrcweir void BitmapReadAccess::Flush()
309cdf0e10cSrcweir {
310cdf0e10cSrcweir 	ImplDestroy();
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir // ------------------------------------------------------------------
314cdf0e10cSrcweir 
ReAccess(sal_Bool bModify)315cdf0e10cSrcweir void BitmapReadAccess::ReAccess( sal_Bool bModify )
316cdf0e10cSrcweir {
317cdf0e10cSrcweir 	const ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 	DBG_ASSERT( !mpBuffer, "No ReAccess possible while bitmap is being accessed!" );
320cdf0e10cSrcweir 	DBG_ASSERT( pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ), "Accessed bitmap does not exist anymore!" );
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 	if( !mpBuffer && pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ) )
323cdf0e10cSrcweir 	{
324cdf0e10cSrcweir 		mbModify = bModify;
325cdf0e10cSrcweir 		ImplCreate( maBitmap );
326cdf0e10cSrcweir 	}
327cdf0e10cSrcweir }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir // ------------------------------------------------------------------
330cdf0e10cSrcweir 
GetBestPaletteIndex(const BitmapColor & rBitmapColor) const331cdf0e10cSrcweir sal_uInt16 BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
332cdf0e10cSrcweir {
333cdf0e10cSrcweir 	return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
GetInterpolatedColorWithFallback(double fY,double fX,const BitmapColor & rFallback) const336f8c0d554SArmin Le Grand BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
337f8c0d554SArmin Le Grand {
338f8c0d554SArmin Le Grand     // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
339f8c0d554SArmin Le Grand     // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
340f8c0d554SArmin Le Grand     if(mpBuffer && fX >= 0.0 && fY >= 0.0)
341f8c0d554SArmin Le Grand     {
342f8c0d554SArmin Le Grand         const sal_Int32 nX(static_cast< sal_Int32 >(fX));
343f8c0d554SArmin Le Grand         const sal_Int32 nY(static_cast< sal_Int32 >(fY));
344f8c0d554SArmin Le Grand 
345f8c0d554SArmin Le Grand         if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
346f8c0d554SArmin Le Grand         {
347f8c0d554SArmin Le Grand             // get base-return value from inside pixel
348f8c0d554SArmin Le Grand             BitmapColor aRetval(GetColor(nY, nX));
349f8c0d554SArmin Le Grand 
350f8c0d554SArmin Le Grand             // calculate deltas and indices for neighbour accesses
351f8c0d554SArmin Le Grand             sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
352f8c0d554SArmin Le Grand             sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
353f8c0d554SArmin Le Grand             sal_Int16 nIndX(0);
354f8c0d554SArmin Le Grand             sal_Int16 nIndY(0);
355f8c0d554SArmin Le Grand 
356f8c0d554SArmin Le Grand             if(nDeltaX > 0)
357f8c0d554SArmin Le Grand             {
358f8c0d554SArmin Le Grand                 nIndX = nX + 1;
359f8c0d554SArmin Le Grand             }
360f8c0d554SArmin Le Grand             else
361f8c0d554SArmin Le Grand             {
362f8c0d554SArmin Le Grand                 nIndX = nX - 1;
363f8c0d554SArmin Le Grand                 nDeltaX = -nDeltaX;
364f8c0d554SArmin Le Grand             }
365f8c0d554SArmin Le Grand 
366f8c0d554SArmin Le Grand             if(nDeltaY > 0)
367f8c0d554SArmin Le Grand             {
368f8c0d554SArmin Le Grand                 nIndY = nY + 1;
369f8c0d554SArmin Le Grand             }
370f8c0d554SArmin Le Grand             else
371f8c0d554SArmin Le Grand             {
372f8c0d554SArmin Le Grand                 nIndY = nY - 1;
373f8c0d554SArmin Le Grand                 nDeltaY = -nDeltaY;
374f8c0d554SArmin Le Grand             }
375f8c0d554SArmin Le Grand 
376f8c0d554SArmin Le Grand             // get right/left neighbour
377f8c0d554SArmin Le Grand             BitmapColor aXCol(rFallback);
378f8c0d554SArmin Le Grand 
379f8c0d554SArmin Le Grand             if(nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
380f8c0d554SArmin Le Grand             {
381f8c0d554SArmin Le Grand                 aXCol = GetColor(nY, nIndX);
382f8c0d554SArmin Le Grand             }
383f8c0d554SArmin Le Grand 
384f8c0d554SArmin Le Grand             // get top/bottom neighbour
385f8c0d554SArmin Le Grand             BitmapColor aYCol(rFallback);
386f8c0d554SArmin Le Grand 
387f8c0d554SArmin Le Grand             if(nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
388f8c0d554SArmin Le Grand             {
389f8c0d554SArmin Le Grand                 aYCol = GetColor(nIndY, nX);
390f8c0d554SArmin Le Grand             }
391f8c0d554SArmin Le Grand 
392f8c0d554SArmin Le Grand             // get one of four edge neighbours
393f8c0d554SArmin Le Grand             BitmapColor aXYCol(rFallback);
394f8c0d554SArmin Le Grand 
395f8c0d554SArmin Le Grand             if(nDeltaX && nDeltaY && nIndX >=0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth && nIndY < mpBuffer->mnHeight)
396f8c0d554SArmin Le Grand             {
397f8c0d554SArmin Le Grand                 aXYCol = GetColor(nIndY, nIndX);
398f8c0d554SArmin Le Grand             }
399f8c0d554SArmin Le Grand 
400f8c0d554SArmin Le Grand             // merge return value with right/left neighbour
401f8c0d554SArmin Le Grand             if(aXCol != aRetval)
402f8c0d554SArmin Le Grand             {
403f8c0d554SArmin Le Grand                 aRetval.Merge(aXCol, 255 - nDeltaX);
404f8c0d554SArmin Le Grand             }
405f8c0d554SArmin Le Grand 
406f8c0d554SArmin Le Grand             // merge top/bottom neighbour with edge
407f8c0d554SArmin Le Grand             if(aYCol != aXYCol)
408f8c0d554SArmin Le Grand             {
409f8c0d554SArmin Le Grand                 aYCol.Merge(aXYCol, 255 - nDeltaX);
410f8c0d554SArmin Le Grand             }
411f8c0d554SArmin Le Grand 
412f8c0d554SArmin Le Grand             // merge return value with already merged top/bottom neighbour
413f8c0d554SArmin Le Grand             if(aRetval != aYCol)
414f8c0d554SArmin Le Grand             {
415f8c0d554SArmin Le Grand                 aRetval.Merge(aYCol, 255 - nDeltaY);
416f8c0d554SArmin Le Grand             }
417f8c0d554SArmin Le Grand 
418f8c0d554SArmin Le Grand             return aRetval;
419f8c0d554SArmin Le Grand         }
420f8c0d554SArmin Le Grand     }
421f8c0d554SArmin Le Grand 
422f8c0d554SArmin Le Grand     return rFallback;
423f8c0d554SArmin Le Grand }
424f8c0d554SArmin Le Grand 
GetColorWithFallback(double fY,double fX,const BitmapColor & rFallback) const425f8c0d554SArmin Le Grand BitmapColor BitmapReadAccess::GetColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
426f8c0d554SArmin Le Grand {
427f8c0d554SArmin Le Grand     // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
428f8c0d554SArmin Le Grand     // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
429f8c0d554SArmin Le Grand     if(mpBuffer && fX >= 0.0 && fY >= 0.0)
430f8c0d554SArmin Le Grand     {
431f8c0d554SArmin Le Grand         const sal_Int32 nX(static_cast< sal_Int32 >(fX));
432f8c0d554SArmin Le Grand         const sal_Int32 nY(static_cast< sal_Int32 >(fY));
433f8c0d554SArmin Le Grand 
434f8c0d554SArmin Le Grand         if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
435f8c0d554SArmin Le Grand         {
436f8c0d554SArmin Le Grand             return GetColor(nY, nX);
437f8c0d554SArmin Le Grand         }
438f8c0d554SArmin Le Grand     }
439f8c0d554SArmin Le Grand 
440f8c0d554SArmin Le Grand     return rFallback;
441f8c0d554SArmin Le Grand }
442f8c0d554SArmin Le Grand 
GetColorWithFallback(long nY,long nX,const BitmapColor & rFallback) const443f8c0d554SArmin Le Grand BitmapColor BitmapReadAccess::GetColorWithFallback( long nY, long nX, const BitmapColor& rFallback ) const
444f8c0d554SArmin Le Grand {
445f8c0d554SArmin Le Grand     if(mpBuffer)
446f8c0d554SArmin Le Grand     {
447f8c0d554SArmin Le Grand         if(nX >= 0 && nY >= 0 && nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
448f8c0d554SArmin Le Grand         {
449f8c0d554SArmin Le Grand             return GetColor(nY, nX);
450f8c0d554SArmin Le Grand         }
451f8c0d554SArmin Le Grand     }
452f8c0d554SArmin Le Grand 
453f8c0d554SArmin Le Grand     return rFallback;
454f8c0d554SArmin Le Grand }
455f8c0d554SArmin Le Grand 
456cdf0e10cSrcweir // ---------------------
457cdf0e10cSrcweir // - BitmapWriteAccess -
458cdf0e10cSrcweir // ---------------------
459cdf0e10cSrcweir 
BitmapWriteAccess(Bitmap & rBitmap)460cdf0e10cSrcweir BitmapWriteAccess::BitmapWriteAccess( Bitmap& rBitmap ) :
461cdf0e10cSrcweir             BitmapReadAccess( rBitmap, sal_True ),
462cdf0e10cSrcweir             mpLineColor     ( NULL ),
463cdf0e10cSrcweir             mpFillColor     ( NULL )
464cdf0e10cSrcweir {
465cdf0e10cSrcweir }
466cdf0e10cSrcweir 
467cdf0e10cSrcweir // ------------------------------------------------------------------
468cdf0e10cSrcweir 
~BitmapWriteAccess()469cdf0e10cSrcweir BitmapWriteAccess::~BitmapWriteAccess()
470cdf0e10cSrcweir {
471cdf0e10cSrcweir 	delete mpLineColor;
472cdf0e10cSrcweir 	delete mpFillColor;
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir // ------------------------------------------------------------------
476cdf0e10cSrcweir 
CopyScanline(long nY,const BitmapReadAccess & rReadAcc)477cdf0e10cSrcweir void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
478cdf0e10cSrcweir {
479cdf0e10cSrcweir 	DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
480cdf0e10cSrcweir 	DBG_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
481cdf0e10cSrcweir 	DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
482cdf0e10cSrcweir 
483cdf0e10cSrcweir 	if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
484cdf0e10cSrcweir 		( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
485cdf0e10cSrcweir 	{
486cdf0e10cSrcweir 		memcpy( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
487cdf0e10cSrcweir 	}
488cdf0e10cSrcweir 	else
489cdf0e10cSrcweir         // TODO: use fastbmp infrastructure
490cdf0e10cSrcweir 		for( long nX = 0L, nWidth = Min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
491cdf0e10cSrcweir 			SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
492cdf0e10cSrcweir }
493cdf0e10cSrcweir 
494cdf0e10cSrcweir // ------------------------------------------------------------------
495cdf0e10cSrcweir 
CopyScanline(long nY,ConstScanline aSrcScanline,sal_uLong nSrcScanlineFormat,sal_uLong nSrcScanlineSize)496cdf0e10cSrcweir void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline,
497cdf0e10cSrcweir 									  sal_uLong nSrcScanlineFormat, sal_uLong nSrcScanlineSize )
498cdf0e10cSrcweir {
499cdf0e10cSrcweir 	const sal_uLong nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
500cdf0e10cSrcweir 
501cdf0e10cSrcweir 	DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
502cdf0e10cSrcweir 	DBG_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
503cdf0e10cSrcweir 				( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
504cdf0e10cSrcweir 				"No copying possible between palette and non palette scanlines!" );
505cdf0e10cSrcweir 
506cdf0e10cSrcweir 	const sal_uLong nCount = Min( GetScanlineSize(), nSrcScanlineSize );
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 	if( nCount )
509cdf0e10cSrcweir 	{
510cdf0e10cSrcweir 		if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
511cdf0e10cSrcweir 			memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
512cdf0e10cSrcweir 		else
513cdf0e10cSrcweir 		{
514cdf0e10cSrcweir 			DBG_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK &&
515cdf0e10cSrcweir                         nFormat != BMP_FORMAT_16BIT_TC_MSB_MASK && nFormat != BMP_FORMAT_16BIT_TC_LSB_MASK &&
516cdf0e10cSrcweir 						nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
517cdf0e10cSrcweir 						"No support for pixel formats with color masks yet!" );
518cdf0e10cSrcweir 
519cdf0e10cSrcweir             // TODO: use fastbmp infrastructure
520cdf0e10cSrcweir             FncGetPixel pFncGetPixel;
521cdf0e10cSrcweir 
522cdf0e10cSrcweir 			switch( nFormat )
523cdf0e10cSrcweir 			{
524cdf0e10cSrcweir 				case( BMP_FORMAT_1BIT_MSB_PAL ):	pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
525cdf0e10cSrcweir 				case( BMP_FORMAT_1BIT_LSB_PAL ):	pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
526cdf0e10cSrcweir 				case( BMP_FORMAT_4BIT_MSN_PAL ):	pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
527cdf0e10cSrcweir 				case( BMP_FORMAT_4BIT_LSN_PAL ):	pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
528cdf0e10cSrcweir 				case( BMP_FORMAT_8BIT_PAL ):		pFncGetPixel = GetPixelFor_8BIT_PAL; break;
529cdf0e10cSrcweir 				case( BMP_FORMAT_8BIT_TC_MASK ):	pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
530cdf0e10cSrcweir 				case( BMP_FORMAT_16BIT_TC_MSB_MASK ):	pFncGetPixel = GetPixelFor_16BIT_TC_MSB_MASK; break;
531cdf0e10cSrcweir 				case( BMP_FORMAT_16BIT_TC_LSB_MASK ):	pFncGetPixel = GetPixelFor_16BIT_TC_LSB_MASK; break;
532cdf0e10cSrcweir 				case( BMP_FORMAT_24BIT_TC_BGR ):	pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
533cdf0e10cSrcweir 				case( BMP_FORMAT_24BIT_TC_RGB ):	pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
534cdf0e10cSrcweir 				case( BMP_FORMAT_24BIT_TC_MASK ):	pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
535cdf0e10cSrcweir 				case( BMP_FORMAT_32BIT_TC_ABGR ):	pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
536cdf0e10cSrcweir 				case( BMP_FORMAT_32BIT_TC_ARGB ):	pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
537cdf0e10cSrcweir 				case( BMP_FORMAT_32BIT_TC_BGRA ):	pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
538cdf0e10cSrcweir 				case( BMP_FORMAT_32BIT_TC_RGBA ):	pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
539cdf0e10cSrcweir 				case( BMP_FORMAT_32BIT_TC_MASK ):	pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 				default:
542cdf0e10cSrcweir 					pFncGetPixel = NULL;
543cdf0e10cSrcweir 				break;
544cdf0e10cSrcweir 			}
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 			if( pFncGetPixel )
547cdf0e10cSrcweir 			{
548cdf0e10cSrcweir 				const ColorMask aDummyMask;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 				for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
551cdf0e10cSrcweir 					SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
552cdf0e10cSrcweir 			}
553cdf0e10cSrcweir 		}
554cdf0e10cSrcweir 	}
555cdf0e10cSrcweir }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir 
558cdf0e10cSrcweir // ------------------------------------------------------------------
559cdf0e10cSrcweir 
CopyBuffer(const BitmapReadAccess & rReadAcc)560cdf0e10cSrcweir void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
561cdf0e10cSrcweir {
562cdf0e10cSrcweir 	DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
563cdf0e10cSrcweir 
564cdf0e10cSrcweir 	if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
565cdf0e10cSrcweir 		( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
566cdf0e10cSrcweir 	{
567cdf0e10cSrcweir 		const long	nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() );
568cdf0e10cSrcweir 		const sal_uLong nCount = nHeight * mpBuffer->mnScanlineSize;
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 		memcpy( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
571cdf0e10cSrcweir 	}
572cdf0e10cSrcweir 	else
573cdf0e10cSrcweir 		for( long nY = 0L, nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
574cdf0e10cSrcweir 			CopyScanline( nY, rReadAcc );
575cdf0e10cSrcweir }
576