Update ooo320-m1
[ooovba.git] / vcl / source / gdi / salmisc.cxx
blob492942ddcfa097812ec1f15f9e2c13bc70302699
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salmisc.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <rtl/memory.h>
34 #include <vcl/bmpacc.hxx>
35 #include <vcl/salbtype.hxx>
36 #include <vcl/bmpfast.hxx>
38 // -----------
39 // - Defines -
40 // -----------
42 #define IMPL_CASE_GET_FORMAT( Format ) \
43 case( BMP_FORMAT##Format ): \
44 pFncGetPixel = BitmapReadAccess::GetPixelFor##Format; \
45 break
47 // -----------------------------------------------------------------------------
49 #define IMPL_CASE_SET_FORMAT( Format, BitCount ) \
50 case( BMP_FORMAT##Format ): \
51 { \
52 pFncSetPixel = BitmapReadAccess::SetPixelFor##Format; \
53 pDstBuffer->mnBitCount = BitCount; \
54 } \
55 break
57 // -----------------------------------------------------------------------------
59 #define DOUBLE_SCANLINES() \
60 while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) ) \
61 { \
62 memcpy( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize ); \
63 nActY++; \
66 // -----------
67 // - Inlines -
68 // -----------
70 #define TC_TO_PAL_COLORS 4096
72 static long ImplIndexFromColor( const BitmapColor& rCol )
74 #if TC_TO_PAL_COLORS == 4096
76 return( ( ( (long) rCol.GetBlue() >> 4L) << 8L ) |
77 ( ( (long) rCol.GetGreen() >> 4L ) << 4L ) |
78 ( (long) rCol.GetRed() >> 4L ) );
80 #elif TC_TO_PAL_COLORS == 32768
82 return( ( ( (long) rCol.GetBlue() >> 3L) << 10L ) |
83 ( ( (long) rCol.GetGreen() >> 3L ) << 5L ) |
84 ( (long) rCol.GetRed() >> 3L ) );
86 #endif
90 #define COLOR_TO_INDEX( _def_rCol )
92 // ------------------------
93 // - conversion functions -
94 // ------------------------
96 static void ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
97 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
98 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
100 const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
101 const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
102 const ColorMask& rDstMask = rDstBuffer.maColorMask;
103 BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
104 BitmapColor* pColMapBuf = aColMap.ImplGetColorBuffer();
105 BitmapColor aIndex( 0 );
107 for( USHORT i = 0, nSrcCount = aColMap.GetEntryCount(), nDstCount = rDstBuffer.maPalette.GetEntryCount(); i < nSrcCount; i++ )
109 if( ( i < nDstCount ) && ( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] ) )
110 aIndex.SetIndex( sal::static_int_cast<BYTE>(i) );
111 else
112 aIndex.SetIndex( sal::static_int_cast<BYTE>(rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] )) );
114 pColMapBuf[ i ] = aIndex;
117 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
119 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
121 for( long nX = 0L; nX < nWidth; nX++ )
122 pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
124 DOUBLE_SCANLINES();
128 // -----------------------------------------------------------------------------
130 static void ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
131 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
132 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
134 const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
135 const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
136 const ColorMask& rDstMask = rDstBuffer.maColorMask;
137 const BitmapColor* pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer();
139 if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_1BIT_MSB_PAL )
141 const BitmapColor aCol0( pColBuf[ 0 ] );
142 const BitmapColor aCol1( pColBuf[ 1 ] );
143 long nMapX;
145 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
147 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
149 for( long nX = 0L; nX < nWidth; )
151 nMapX = pMapX[ nX ];
152 pFncSetPixel( pDstScan, nX++,
153 pSrcScan[ nMapX >> 3 ] & ( 1 << ( 7 - ( nMapX & 7 ) ) ) ? aCol1 : aCol0,
154 rDstMask );
157 DOUBLE_SCANLINES();
160 else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_4BIT_MSN_PAL )
162 long nMapX;
164 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
166 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
168 for( long nX = 0L; nX < nWidth; )
170 nMapX = pMapX[ nX ];
171 pFncSetPixel( pDstScan, nX++,
172 pColBuf[ ( pSrcScan[ nMapX >> 1 ] >> ( nMapX & 1 ? 0 : 4 ) ) & 0x0f ],
173 rDstMask );
176 DOUBLE_SCANLINES();
179 else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_8BIT_PAL )
181 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
183 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
185 for( long nX = 0L; nX < nWidth; nX++ )
186 pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ], rDstMask );
188 DOUBLE_SCANLINES();
191 else
193 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
195 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
197 for( long nX = 0L; nX < nWidth; nX++ )
198 pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
200 DOUBLE_SCANLINES();
205 // -----------------------------------------------------------------------------
207 static void ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
208 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
209 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
211 const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
212 const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
213 const ColorMask& rDstMask = rDstBuffer.maColorMask;
215 if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_24BIT_TC_BGR )
217 BitmapColor aCol;
218 BYTE* pPixel;
220 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
222 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
224 for( long nX = 0L; nX < nWidth; nX++ )
226 aCol.SetBlue( *( pPixel = ( pSrcScan + pMapX[ nX ] * 3 ) )++ );
227 aCol.SetGreen( *pPixel++ );
228 aCol.SetRed( *pPixel );
229 pFncSetPixel( pDstScan, nX, aCol, rDstMask );
232 DOUBLE_SCANLINES()
235 else
237 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
239 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
241 for( long nX = 0L; nX < nWidth; nX++ )
242 pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ), rDstMask );
244 DOUBLE_SCANLINES();
249 // -----------------------------------------------------------------------------
251 static void ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
252 FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
253 Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
255 const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
256 const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
257 const ColorMask& rDstMask = rDstBuffer.maColorMask;
258 BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
259 BYTE* pColToPalMap = new BYTE[ TC_TO_PAL_COLORS ];
260 BitmapColor aIndex( 0 );
262 for( long nR = 0; nR < 16; nR++ )
264 for( long nG = 0; nG < 16; nG++ )
266 for( long nB = 0; nB < 16; nB++ )
268 BitmapColor aCol( sal::static_int_cast<BYTE>(nR << 4),
269 sal::static_int_cast<BYTE>(nG << 4),
270 sal::static_int_cast<BYTE>(nB << 4) );
271 pColToPalMap[ ImplIndexFromColor( aCol ) ] = (BYTE) rDstBuffer.maPalette.GetBestIndex( aCol );
276 for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
278 Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
280 for( long nX = 0L; nX < nWidth; nX++ )
282 aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ) ) ] );
283 pFncSetPixel( pDstScan, nX, aIndex, rDstMask );
286 DOUBLE_SCANLINES();
289 delete[] pColToPalMap;
292 // -----------------------------------------------------------------------------
294 // ---------------------
295 // - StretchAndConvert -
296 // ---------------------
298 BitmapBuffer* StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
299 ULONG nDstBitmapFormat, BitmapPalette* pDstPal, ColorMask* pDstMask )
301 FncGetPixel pFncGetPixel;
302 FncSetPixel pFncSetPixel;
303 BitmapBuffer* pDstBuffer = new BitmapBuffer;
304 long i;
306 // set function for getting pixels
307 switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
309 IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
310 IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
311 IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
312 IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
313 IMPL_CASE_GET_FORMAT( _8BIT_PAL );
314 IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
315 IMPL_CASE_GET_FORMAT( _16BIT_TC_MSB_MASK );
316 IMPL_CASE_GET_FORMAT( _16BIT_TC_LSB_MASK );
317 IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
318 IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
319 IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
320 IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
321 IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
322 IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
323 IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
324 IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
326 default:
327 // should never come here
328 // initialize pFncGetPixel to something valid that is
329 // least likely to crash
330 pFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL;
331 DBG_ERROR( "unknown read format" );
332 break;
335 // set function for setting pixels
336 const ULONG nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
337 switch( nDstScanlineFormat )
339 IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
340 IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
341 IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
342 IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
343 IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
344 IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
345 IMPL_CASE_SET_FORMAT( _16BIT_TC_MSB_MASK, 16 );
346 IMPL_CASE_SET_FORMAT( _16BIT_TC_LSB_MASK, 16 );
347 IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
348 IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
349 IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
350 IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
351 IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
352 IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
353 IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
354 IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
356 default:
357 // should never come here
358 // initialize pFncSetPixel to something valid that is
359 // least likely to crash
360 pFncSetPixel = BitmapReadAccess::SetPixelFor_1BIT_MSB_PAL;
361 pDstBuffer->mnBitCount = 1;
362 DBG_ERROR( "unknown write format" );
363 break;
366 // fill destination buffer
367 pDstBuffer->mnFormat = nDstBitmapFormat;
368 pDstBuffer->mnWidth = rTwoRect.mnDestWidth;
369 pDstBuffer->mnHeight = rTwoRect.mnDestHeight;
370 pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * pDstBuffer->mnWidth );
373 pDstBuffer->mpBits = new BYTE[ pDstBuffer->mnScanlineSize * pDstBuffer->mnHeight ];
375 catch( const std::bad_alloc& )
377 // memory exception, clean up
378 pDstBuffer->mpBits = NULL;
379 delete pDstBuffer;
380 return NULL;
383 // do we need a destination palette or color mask?
384 if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
385 ( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
386 ( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
387 ( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
388 ( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
390 DBG_ASSERT( pDstPal, "destination buffer requires palette" );
391 pDstBuffer->maPalette = *pDstPal;
393 else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
394 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MSB_MASK ) ||
395 ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_LSB_MASK ) ||
396 ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
397 ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
399 DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
400 pDstBuffer->maColorMask = *pDstMask;
403 // short circuit the most important conversions
404 bool bFastConvert = ImplFastBitmapConversion( *pDstBuffer, rSrcBuffer, rTwoRect );
405 if( bFastConvert )
406 return pDstBuffer;
408 const long nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
409 const long nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
410 const long nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
411 Scanline* pSrcScan = NULL;
412 Scanline* pDstScan = NULL;
413 long* pMapX = NULL;
414 long* pMapY = NULL;
415 long nTmp, nOffset;
419 pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
420 pDstScan = new Scanline[ nDstDY ];
421 pMapX = new long[ nDstDX ];
422 pMapY = new long[ nDstDY ];
424 catch( const std::bad_alloc& )
426 // memory exception, clean up
427 // remark: the buffer ptr causing the exception
428 // is still NULL here
429 delete pSrcScan;
430 delete pDstScan;
431 delete pMapX;
432 delete pMapY;
433 delete pDstBuffer;
434 return NULL;
437 // horizontal mapping table
438 if( nDstDX != nSrcDX )
440 const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
442 for( i = 0L; i < nDstDX; i++ )
443 pMapX[ i ] = nSrcX + FRound( i * fFactorX );
445 else
447 for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
448 pMapX[ i ] = nTmp++;
451 // vertical mapping table
452 if( nDstDY != nSrcDY )
454 const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
456 for( i = 0L; i < nDstDY; i++ )
457 pMapY[ i ] = nSrcY + FRound( i * fFactorY );
459 else
461 for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
462 pMapY[ i ] = nTmp++;
465 // source scanline buffer
466 Scanline pTmpScan;
467 if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
468 pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
469 else
471 pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
472 nOffset = -rSrcBuffer.mnScanlineSize;
475 for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
476 pSrcScan[ i ] = pTmpScan;
478 // destination scanline buffer
479 if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
480 pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
481 else
483 pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
484 nOffset = -pDstBuffer->mnScanlineSize;
487 for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
488 pDstScan[ i ] = pTmpScan;
490 // do buffer scaling and conversion
491 if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
493 ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
494 pSrcScan, pDstScan, pMapX, pMapY );
496 else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
498 ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
499 pSrcScan, pDstScan, pMapX, pMapY );
501 else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
503 ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
504 pSrcScan, pDstScan, pMapX, pMapY );
506 else
508 ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
509 pSrcScan, pDstScan, pMapX, pMapY );
512 // cleanup
513 delete[] pSrcScan;
514 delete[] pDstScan;
515 delete[] pMapX;
516 delete[] pMapY;
518 return pDstBuffer;