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