xref: /aoo42x/main/vcl/source/gdi/salmisc.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <rtl/memory.h>
31 #include <vcl/bmpacc.hxx>
32 #include <vcl/salbtype.hxx>
33 #include <bmpfast.hxx>
34 
35 // -----------
36 // - Defines -
37 // -----------
38 
39 #define IMPL_CASE_GET_FORMAT( Format )							\
40 case( BMP_FORMAT##Format ):									\
41 	pFncGetPixel = BitmapReadAccess::GetPixelFor##Format;		\
42 break
43 
44 // -----------------------------------------------------------------------------
45 
46 #define IMPL_CASE_SET_FORMAT( Format, BitCount )				\
47 case( BMP_FORMAT##Format ):									\
48 {																\
49 	pFncSetPixel = BitmapReadAccess::SetPixelFor##Format;		\
50 	pDstBuffer->mnBitCount = BitCount;							\
51 }																\
52 break
53 
54 // -----------------------------------------------------------------------------
55 
56 #define DOUBLE_SCANLINES()														\
57 while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) )				\
58 {																				\
59 	memcpy( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize );	\
60 	nActY++;																	\
61 }
62 
63 // -----------
64 // - Inlines -
65 // -----------
66 
67 #define TC_TO_PAL_COLORS	4096
68 
69 static long ImplIndexFromColor( const BitmapColor& rCol )
70 {
71 #if TC_TO_PAL_COLORS == 4096
72 
73 	return( ( ( (long) rCol.GetBlue() >> 4L) << 8L ) |
74 			( ( (long) rCol.GetGreen() >> 4L ) << 4L ) |
75 			( (long) rCol.GetRed() >> 4L ) );
76 
77 #elif TC_TO_PAL_COLORS == 32768
78 
79 	return( ( ( (long) rCol.GetBlue() >> 3L) << 10L ) |
80 			( ( (long) rCol.GetGreen() >> 3L ) << 5L ) |
81 			( (long) rCol.GetRed() >> 3L ) );
82 
83 #endif
84 }
85 
86 
87 #define COLOR_TO_INDEX( _def_rCol )
88 
89 // ------------------------
90 // - conversion functions -
91 // ------------------------
92 
93 static void	ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
94 						  FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
95 						  Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
96 {
97 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
98 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
99 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
100 	BitmapPalette		aColMap( rSrcBuffer.maPalette.GetEntryCount() );
101 	BitmapColor*		pColMapBuf = aColMap.ImplGetColorBuffer();
102 	BitmapColor			aIndex( 0 );
103 
104 	for( sal_uInt16 i = 0, nSrcCount = aColMap.GetEntryCount(), nDstCount = rDstBuffer.maPalette.GetEntryCount(); i < nSrcCount; i++ )
105 	{
106 	    if( ( i < nDstCount ) && ( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] ) )
107 		    aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(i) );
108 		else
109 			aIndex.SetIndex( sal::static_int_cast<sal_uInt8>(rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] )) );
110 
111 		pColMapBuf[ i ] = aIndex;
112 	}
113 
114 	for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
115 	{
116 		Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
117 
118 		for( long nX = 0L; nX < nWidth; nX++ )
119 			pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
120 
121 		DOUBLE_SCANLINES();
122 	}
123 }
124 
125 // -----------------------------------------------------------------------------
126 
127 static void	ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
128 						 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
129 						 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
130 {
131 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
132 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
133 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
134 	const BitmapColor*	pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer();
135 
136 	if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_1BIT_MSB_PAL )
137 	{
138 		const BitmapColor	aCol0( pColBuf[ 0 ] );
139 		const BitmapColor	aCol1( pColBuf[ 1 ] );
140 		long				nMapX;
141 
142 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
143 		{
144 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
145 
146 			for( long nX = 0L; nX < nWidth; )
147 			{
148 				nMapX = pMapX[ nX ];
149 				pFncSetPixel( pDstScan, nX++,
150 							  pSrcScan[ nMapX >> 3 ] & ( 1 << ( 7 - ( nMapX & 7 ) ) ) ? aCol1 : aCol0,
151 							  rDstMask );
152 			}
153 
154 			DOUBLE_SCANLINES();
155 		}
156 	}
157 	else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_4BIT_MSN_PAL )
158 	{
159 		long nMapX;
160 
161 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
162 		{
163 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
164 
165 			for( long nX = 0L; nX < nWidth; )
166 			{
167 				nMapX = pMapX[ nX ];
168 				pFncSetPixel( pDstScan, nX++,
169 							  pColBuf[ ( pSrcScan[ nMapX >> 1 ] >> ( nMapX & 1 ? 0 : 4 ) ) & 0x0f ],
170 							  rDstMask );
171 			}
172 
173 			DOUBLE_SCANLINES();
174 		}
175 	}
176 	else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_8BIT_PAL )
177 	{
178 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
179 		{
180 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
181 
182 			for( long nX = 0L; nX < nWidth; nX++ )
183 				pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ], rDstMask );
184 
185 			DOUBLE_SCANLINES();
186 		}
187 	}
188 	else
189 	{
190 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
191 		{
192 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
193 
194 			for( long nX = 0L; nX < nWidth; nX++ )
195 				pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
196 
197 			DOUBLE_SCANLINES();
198 		}
199 	}
200 }
201 
202 // -----------------------------------------------------------------------------
203 
204 static void	ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
205 						FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
206 						Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
207 {
208 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
209 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
210 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
211 
212 	if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_24BIT_TC_BGR )
213 	{
214 		BitmapColor aCol;
215 		sal_uInt8*		pPixel;
216 
217 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
218 		{
219 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
220 
221 			for( long nX = 0L; nX < nWidth; nX++ )
222 			{
223 				aCol.SetBlue( *( pPixel = ( pSrcScan + pMapX[ nX ] * 3 ) )++ );
224 				aCol.SetGreen( *pPixel++ );
225 				aCol.SetRed( *pPixel );
226 				pFncSetPixel( pDstScan, nX, aCol, rDstMask );
227 			}
228 
229 			DOUBLE_SCANLINES()
230 		}
231 	}
232 	else
233 	{
234 		for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
235 		{
236 			Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
237 
238 			for( long nX = 0L; nX < nWidth; nX++ )
239 				pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ), rDstMask );
240 
241 			DOUBLE_SCANLINES();
242 		}
243 	}
244 }
245 
246 // -----------------------------------------------------------------------------
247 
248 static void	ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
249 						 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
250 						 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
251 {
252 	const long			nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
253 	const ColorMask&	rSrcMask = rSrcBuffer.maColorMask;
254 	const ColorMask&	rDstMask = rDstBuffer.maColorMask;
255 	BitmapPalette		aColMap( rSrcBuffer.maPalette.GetEntryCount() );
256 	sal_uInt8*				pColToPalMap = new sal_uInt8[ TC_TO_PAL_COLORS ];
257 	BitmapColor			aIndex( 0 );
258 
259 	for( long nR = 0; nR < 16; nR++ )
260 	{
261 		for( long nG = 0; nG < 16; nG++ )
262 		{
263 			for( long nB = 0; nB < 16; nB++ )
264 			{
265 				BitmapColor aCol( sal::static_int_cast<sal_uInt8>(nR << 4),
266                                   sal::static_int_cast<sal_uInt8>(nG << 4),
267                                   sal::static_int_cast<sal_uInt8>(nB << 4) );
268 				pColToPalMap[ ImplIndexFromColor( aCol ) ] = (sal_uInt8) rDstBuffer.maPalette.GetBestIndex( aCol );
269 			}
270 		}
271 	}
272 
273 	for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
274 	{
275 		Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
276 
277 		for( long nX = 0L; nX < nWidth; nX++ )
278 		{
279 			aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ) ) ] );
280 			pFncSetPixel( pDstScan, nX, aIndex, rDstMask );
281 		}
282 
283 		DOUBLE_SCANLINES();
284 	}
285 
286 	delete[] pColToPalMap;
287 }
288 
289 // -----------------------------------------------------------------------------
290 
291 // ---------------------
292 // - StretchAndConvert -
293 // ---------------------
294 
295 BitmapBuffer* StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
296 								 sal_uLong nDstBitmapFormat, BitmapPalette* pDstPal, ColorMask* pDstMask )
297 {
298     FncGetPixel		pFncGetPixel;
299     FncSetPixel		pFncSetPixel;
300 	BitmapBuffer*	pDstBuffer = new BitmapBuffer;
301     long            i;
302 
303 	// set function for getting pixels
304 	switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
305 	{
306 		IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
307 		IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
308 		IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
309 		IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
310 		IMPL_CASE_GET_FORMAT( _8BIT_PAL );
311 		IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
312 		IMPL_CASE_GET_FORMAT( _16BIT_TC_MSB_MASK );
313 		IMPL_CASE_GET_FORMAT( _16BIT_TC_LSB_MASK );
314 		IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
315 		IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
316 		IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
317 		IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
318 		IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
319 		IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
320 		IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
321 		IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
322 
323 		default:
324             // should never come here
325             // initialize pFncGetPixel to something valid that is
326             // least likely to crash
327             pFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL;
328 			DBG_ERROR( "unknown read format" );
329 		break;
330 	}
331 
332 	// set function for setting pixels
333     const sal_uLong nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
334 	switch( nDstScanlineFormat )
335 	{
336 		IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
337 		IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
338 		IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
339 		IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
340 		IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
341 		IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
342 		IMPL_CASE_SET_FORMAT( _16BIT_TC_MSB_MASK, 16 );
343 		IMPL_CASE_SET_FORMAT( _16BIT_TC_LSB_MASK, 16 );
344 		IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
345 		IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
346 		IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
347 		IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
348 		IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
349 		IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
350 		IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
351 		IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
352 
353 		default:
354             // should never come here
355             // initialize pFncSetPixel to something valid that is
356             // least likely to crash
357             pFncSetPixel = BitmapReadAccess::SetPixelFor_1BIT_MSB_PAL;
358             pDstBuffer->mnBitCount = 1;
359 			DBG_ERROR( "unknown write format" );
360 		break;
361 	}
362 
363 	// fill destination buffer
364 	pDstBuffer->mnFormat = nDstBitmapFormat;
365 	pDstBuffer->mnWidth = rTwoRect.mnDestWidth;
366 	pDstBuffer->mnHeight = rTwoRect.mnDestHeight;
367 	pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * pDstBuffer->mnWidth );
368     try
369     {
370         pDstBuffer->mpBits = new sal_uInt8[ pDstBuffer->mnScanlineSize * pDstBuffer->mnHeight ];
371     }
372     catch( const std::bad_alloc& )
373     {
374         // memory exception, clean up
375         pDstBuffer->mpBits = NULL;
376         delete pDstBuffer;
377         return NULL;
378     }
379 
380 	// do we need a destination palette or color mask?
381 	if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
382 		( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
383 		( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
384 		( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
385 		( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
386 	{
387 		DBG_ASSERT( pDstPal, "destination buffer requires palette" );
388 		pDstBuffer->maPalette = *pDstPal;
389 	}
390 	else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
391 			 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MSB_MASK ) ||
392 			 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_LSB_MASK ) ||
393 			 ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
394 			 ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
395 	{
396 		DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
397 		pDstBuffer->maColorMask = *pDstMask;
398 	}
399 
400     // short circuit the most important conversions
401     bool bFastConvert = ImplFastBitmapConversion( *pDstBuffer, rSrcBuffer, rTwoRect );
402     if( bFastConvert )
403         return pDstBuffer;
404 
405     const long      nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
406     const long      nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
407     const long      nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
408     Scanline*       pSrcScan = NULL;
409     Scanline*       pDstScan = NULL;
410     long*           pMapX = NULL;
411     long*           pMapY = NULL;
412     long            nTmp, nOffset;
413 
414     try
415     {
416         pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
417         pDstScan = new Scanline[ nDstDY ];
418         pMapX = new long[ nDstDX ];
419         pMapY = new long[ nDstDY ];
420     }
421     catch( const std::bad_alloc& )
422     {
423         // memory exception, clean up
424         // remark: the buffer ptr causing the exception
425         // is still NULL here
426         delete[] pSrcScan;
427         delete[] pDstScan;
428         delete[] pMapX;
429         delete[] pMapY;
430         delete pDstBuffer;
431         return NULL;
432     }
433 
434     // horizontal mapping table
435 	if( nDstDX != nSrcDX )
436 	{
437 		const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
438 
439 		for( i = 0L; i < nDstDX; i++ )
440 			pMapX[ i ] = nSrcX + FRound( i * fFactorX );
441 	}
442 	else
443 	{
444 		for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
445 			pMapX[ i ] = nTmp++;
446 	}
447 
448 	// vertical mapping table
449 	if( nDstDY != nSrcDY )
450 	{
451 		const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
452 
453 		for( i = 0L; i < nDstDY; i++ )
454 			pMapY[ i ] = nSrcY + FRound( i * fFactorY );
455 	}
456 	else
457 	{
458 		for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
459 			pMapY[ i ] = nTmp++;
460 	}
461 
462 	// source scanline buffer
463     Scanline pTmpScan;
464 	if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
465 		pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
466 	else
467 	{
468 		pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
469 		nOffset = -rSrcBuffer.mnScanlineSize;
470 	}
471 
472 	for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
473 		pSrcScan[ i ] = pTmpScan;
474 
475 	// destination scanline buffer
476 	if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
477 		pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
478 	else
479 	{
480 		pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
481 		nOffset = -pDstBuffer->mnScanlineSize;
482 	}
483 
484 	for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
485 		pDstScan[ i ] = pTmpScan;
486 
487 	// do buffer scaling and conversion
488 	if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
489 	{
490 		ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
491 					  pSrcScan, pDstScan, pMapX, pMapY );
492 	}
493 	else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
494 	{
495 		ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
496 					 pSrcScan, pDstScan, pMapX, pMapY );
497 	}
498 	else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
499 	{
500 		ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
501 					pSrcScan, pDstScan, pMapX, pMapY );
502 	}
503 	else
504 	{
505 		ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
506 					 pSrcScan, pDstScan, pMapX, pMapY );
507 	}
508 
509 	// cleanup
510 	delete[] pSrcScan;
511 	delete[] pDstScan;
512 	delete[] pMapX;
513 	delete[] pMapY;
514 
515 	return pDstBuffer;
516 }
517