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