summaryrefslogtreecommitdiff
path: root/vcl/source/gdi
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r--vcl/source/gdi/alpha.cxx353
-rw-r--r--vcl/source/gdi/animate.cxx992
-rw-r--r--vcl/source/gdi/bitmap.cxx1980
-rw-r--r--vcl/source/gdi/bitmap2.cxx1269
-rw-r--r--vcl/source/gdi/bitmap3.cxx2248
-rw-r--r--vcl/source/gdi/bitmap4.cxx953
-rw-r--r--vcl/source/gdi/bitmapex.cxx690
-rw-r--r--vcl/source/gdi/bmpacc.cxx448
-rw-r--r--vcl/source/gdi/bmpacc2.cxx353
-rw-r--r--vcl/source/gdi/bmpacc3.cxx351
-rw-r--r--vcl/source/gdi/cvtgrf.cxx232
-rw-r--r--vcl/source/gdi/cvtsvm.cxx2106
-rw-r--r--vcl/source/gdi/font.cxx625
-rw-r--r--vcl/source/gdi/gdimtf.cxx1724
-rw-r--r--vcl/source/gdi/gfxlink.cxx450
-rw-r--r--vcl/source/gdi/gradient.cxx386
-rw-r--r--vcl/source/gdi/graph.cxx832
-rw-r--r--vcl/source/gdi/hatch.cxx262
-rw-r--r--vcl/source/gdi/image.cxx1521
-rw-r--r--vcl/source/gdi/imgcons.cxx593
-rw-r--r--vcl/source/gdi/impanmvw.cxx392
-rw-r--r--vcl/source/gdi/impanmvw.hxx130
-rw-r--r--vcl/source/gdi/impbmp.cxx309
-rw-r--r--vcl/source/gdi/impgraph.cxx1571
-rw-r--r--vcl/source/gdi/impimage.cxx744
-rw-r--r--vcl/source/gdi/implncvt.cxx605
-rw-r--r--vcl/source/gdi/implncvt.hxx113
-rw-r--r--vcl/source/gdi/impprn.cxx256
-rw-r--r--vcl/source/gdi/impvect.cxx1267
-rw-r--r--vcl/source/gdi/impvect.hxx101
-rw-r--r--vcl/source/gdi/jobset.cxx415
-rw-r--r--vcl/source/gdi/lineinfo.cxx300
-rw-r--r--vcl/source/gdi/makefile.mk156
-rw-r--r--vcl/source/gdi/mapmod.cxx356
-rw-r--r--vcl/source/gdi/metaact.cxx3434
-rw-r--r--vcl/source/gdi/metric.cxx142
-rw-r--r--vcl/source/gdi/octree.cxx419
-rw-r--r--vcl/source/gdi/opengl.cxx1714
-rw-r--r--vcl/source/gdi/outdev.cxx1927
-rw-r--r--vcl/source/gdi/outdev2.cxx1928
-rw-r--r--vcl/source/gdi/outdev3.cxx6326
-rw-r--r--vcl/source/gdi/outdev4.cxx1634
-rw-r--r--vcl/source/gdi/outdev5.cxx430
-rw-r--r--vcl/source/gdi/outdev6.cxx1043
-rw-r--r--vcl/source/gdi/outmap.cxx2106
-rw-r--r--vcl/source/gdi/polyscan.cxx389
-rw-r--r--vcl/source/gdi/print.cxx1979
-rw-r--r--vcl/source/gdi/print2.cxx543
-rw-r--r--vcl/source/gdi/regband.cxx785
-rw-r--r--vcl/source/gdi/region.cxx2458
-rw-r--r--vcl/source/gdi/salmisc.cxx497
-rw-r--r--vcl/source/gdi/svcompat.cxx117
-rw-r--r--vcl/source/gdi/virdev.cxx442
-rw-r--r--vcl/source/gdi/wall.cxx616
54 files changed, 54012 insertions, 0 deletions
diff --git a/vcl/source/gdi/alpha.cxx b/vcl/source/gdi/alpha.cxx
new file mode 100644
index 000000000000..9e00d0044787
--- /dev/null
+++ b/vcl/source/gdi/alpha.cxx
@@ -0,0 +1,353 @@
+/*************************************************************************
+ *
+ * $RCSfile: alpha.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ALPHA_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_COLOR_HXX
+#include <color.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+
+// -------------
+// - AlphaMask -
+// -------------
+
+AlphaMask::AlphaMask()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const Bitmap& rBitmap ) :
+ Bitmap( rBitmap )
+{
+ if( !!rBitmap )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) :
+ Bitmap( rAlphaMask )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::AlphaMask( const Size& rSizePixel, BYTE* pEraseTransparency ) :
+ Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) )
+{
+ if( pEraseTransparency )
+ Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask::~AlphaMask()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap )
+{
+ *(Bitmap*) this = rBitmap;
+
+ if( !!rBitmap )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------------
+
+const Bitmap& AlphaMask::ImplGetBitmap() const
+{
+ return( (const Bitmap&) *this );
+}
+
+// -----------------------------------------------------------------------------
+
+void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap )
+{
+ *(Bitmap*) this = rBitmap;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Crop( const Rectangle& rRectPixel )
+{
+ return Bitmap::Crop( rRectPixel );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Expand( ULONG nDX, ULONG nDY, BYTE* pInitTransparency )
+{
+ Color aColor;
+
+ if( pInitTransparency )
+ aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency );
+
+ return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Erase( BYTE cTransparency )
+{
+ return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Invert()
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc && pAcc->GetBitCount() == 8 )
+ {
+ BitmapColor aCol( 0 );
+ const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
+ BYTE* pMap = new BYTE[ 256 ];
+
+ for( long i = 0; i < 256; i++ )
+ pMap[ i ] = ~(BYTE) i;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+
+ delete[] pMap;
+ bRet = TRUE;
+ }
+
+ if( pAcc )
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Mirror( ULONG nMirrorFlags )
+{
+ return Bitmap::Mirror( nMirrorFlags );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ BOOL bRet = Bitmap::Scale( rNewSize, nScaleFlag );
+
+ if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag );
+
+ if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Rotate( long nAngle10, BYTE cFillTransparency )
+{
+ return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) );
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( const Bitmap& rMask, BYTE cReplaceTransparency )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const BitmapColor aReplace( cReplaceTransparency );
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( BYTE cSearchTransparency, BYTE cReplaceTransparency, ULONG nTol )
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" );
+
+ if( pAcc && pAcc->GetBitCount() == 8 )
+ {
+ const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
+
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++, pScan++ )
+ {
+ if( *pScan == cSearchTransparency )
+ *pScan = cReplaceTransparency;
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aReplace( cReplaceTransparency );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ if( pAcc )
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL AlphaMask::Replace( BYTE* pSearchTransparencies, BYTE* pReplaceTransparencies,
+ ULONG nColorCount, ULONG* pTols )
+{
+ Color* pSearchColors = new Color[ nColorCount ];
+ Color* pReplaceColors = new Color[ nColorCount ];
+ BOOL bRet;
+
+ for( ULONG i = 0; i < nColorCount; i++ )
+ {
+ const BYTE cSearchTransparency = pSearchTransparencies[ i ];
+ const BYTE cReplaceTransparency = pReplaceTransparencies[ i ];
+
+ pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency );
+ pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency );
+ }
+
+ bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) &&
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ delete[] pSearchColors;
+ delete[] pReplaceColors;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess )
+{
+ if( pAccess )
+ {
+ Bitmap::ReleaseAccess( pAccess );
+ Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
+ }
+}
diff --git a/vcl/source/gdi/animate.cxx b/vcl/source/gdi/animate.cxx
new file mode 100644
index 000000000000..2a1c7e26ad2b
--- /dev/null
+++ b/vcl/source/gdi/animate.cxx
@@ -0,0 +1,992 @@
+/*************************************************************************
+ *
+ * $RCSfile: animate.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_ANIMATE_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_IMPANMVW_HXX
+#include <impanmvw.hxx>
+#endif
+#ifndef _SV_ANIMATE_HXX
+#include <animate.hxx>
+#endif
+
+DBG_NAME( Animation );
+
+// -----------
+// - Defines -
+// -----------
+
+#define MIN_TIMEOUT 2L
+#define INC_TIMEOUT 0L
+
+// -----------
+// - statics -
+// -----------
+
+ULONG Animation::mnAnimCount = 0UL;
+
+// -------------------
+// - AnimationBitmap -
+// -------------------
+
+ULONG AnimationBitmap::GetChecksum() const
+{
+ sal_uInt32 nCrc = aBmpEx.GetChecksum();
+ SVBT32 aBT32;
+
+ LongToSVBT32( aPosPix.X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aPosPix.Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aSizePix.Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( aSizePix.Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) nWait, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) eDisposal, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) bUserInput, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ return nCrc;
+}
+
+// -------------
+// - Animation -
+// -------------
+
+Animation::Animation() :
+ mbIsInAnimation ( FALSE ),
+ meCycleMode ( CYCLE_NORMAL ),
+ mnLoopCount ( 0 ),
+ mnLoops ( 0 ),
+ mnPos ( 0 ),
+ mbLoopTerminated ( FALSE ),
+ mbIsWaiting ( FALSE )
+{
+ DBG_CTOR( Animation, NULL );
+ maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
+ mpViewList = new List;
+}
+
+// -----------------------------------------------------------------------
+
+Animation::Animation( const Animation& rAnimation ) :
+ maGlobalSize ( rAnimation.maGlobalSize ),
+ maBitmapEx ( rAnimation.maBitmapEx ),
+ meCycleMode ( rAnimation.meCycleMode ),
+ mbIsInAnimation ( FALSE ),
+ mnLoopCount ( rAnimation.mnLoopCount ),
+ mnPos ( rAnimation.mnPos ),
+ mbLoopTerminated ( rAnimation.mbLoopTerminated ),
+ mbIsWaiting ( rAnimation.mbIsWaiting )
+{
+ DBG_CTOR( Animation, NULL );
+
+ for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
+ maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
+
+ maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
+ mpViewList = new List;
+ mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
+}
+
+// -----------------------------------------------------------------------
+
+Animation::~Animation()
+{
+ DBG_DTOR( Animation, NULL );
+
+ if( mbIsInAnimation )
+ Stop();
+
+ for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
+ delete (AnimationBitmap*) pStepBmp;
+
+ for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
+ delete (ImplAnimView*) pView;
+
+ delete mpViewList;
+}
+
+// -----------------------------------------------------------------------
+
+Animation& Animation::operator=( const Animation& rAnimation )
+{
+ Clear();
+
+ for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
+ maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
+
+ maGlobalSize = rAnimation.maGlobalSize;
+ maBitmapEx = rAnimation.maBitmapEx;
+ meCycleMode = rAnimation.meCycleMode;
+ mnLoopCount = rAnimation.mnLoopCount;
+ mnPos = rAnimation.mnPos;
+ mbLoopTerminated = rAnimation.mbLoopTerminated;
+ mbIsWaiting = rAnimation.mbIsWaiting;
+ mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::operator==( const Animation& rAnimation ) const
+{
+ const ULONG nCount = maList.Count();
+ BOOL bRet = FALSE;
+
+ if( rAnimation.maList.Count() == nCount &&
+ rAnimation.maBitmapEx == maBitmapEx &&
+ rAnimation.maGlobalSize == maGlobalSize &&
+ rAnimation.meCycleMode == meCycleMode )
+ {
+ bRet = TRUE;
+
+ for( ULONG n = 0; n < nCount; n++ )
+ {
+ if( ( *(AnimationBitmap*) maList.GetObject( n ) ) !=
+ ( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Animation::IsEqual( const Animation& rAnimation ) const
+{
+ const ULONG nCount = maList.Count();
+ BOOL bRet = FALSE;
+
+ if( rAnimation.maList.Count() == nCount &&
+ rAnimation.maBitmapEx.IsEqual( maBitmapEx ) &&
+ rAnimation.maGlobalSize == maGlobalSize &&
+ rAnimation.meCycleMode == meCycleMode )
+ {
+ for( ULONG n = 0; ( n < nCount ) && !bRet; n++ )
+ if( ( (AnimationBitmap*) maList.GetObject( n ) )->IsEqual( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Animation::IsEmpty() const
+{
+ return( maBitmapEx.IsEmpty() && !maList.Count() );
+}
+
+// ------------------------------------------------------------------
+
+void Animation::SetEmpty()
+{
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ maGlobalSize = Size();
+ maBitmapEx.SetEmpty();
+
+ for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
+ delete (AnimationBitmap*) pStepBmp;
+ maList.Clear();
+
+ for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
+ delete (ImplAnimView*) pView;
+ mpViewList->Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Clear()
+{
+ SetEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::IsTransparent() const
+{
+ Point aPoint;
+ Rectangle aRect( aPoint, maGlobalSize );
+ BOOL bRet = FALSE;
+
+ // Falls irgendein 'kleines' Bildchen durch den Hintergrund
+ // ersetzt werden soll, muessen wir 'transparent' sein, um
+ // richtig dargestellt zu werden, da die Appl. aus Optimierungsgruenden
+ // kein Invalidate auf nicht-transp. Grafiken ausfuehren
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
+
+ if( DISPOSE_BACK == pAnimBmp->eDisposal && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect )
+ {
+ bRet = TRUE;
+ break;
+ }
+ }
+
+ if( !bRet )
+ bRet = maBitmapEx.IsTransparent();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Animation::GetSizeBytes() const
+{
+ ULONG nSizeBytes = GetBitmapEx().GetSizeBytes();
+
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
+ nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes();
+ }
+
+ return nSizeBytes;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Animation::GetChecksum() const
+{
+ SVBT32 aBT32;
+ sal_uInt32 nCrc = GetBitmapEx().GetChecksum();
+
+ LongToSVBT32( maList.Count(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( maGlobalSize.Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( maGlobalSize.Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) meCycleMode, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
+ {
+ LongToSVBT32( ( (AnimationBitmap*) maList.GetObject( i ) )->GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+
+ return nCrc;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ return Start( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ), nExtraData, pFirstFrameOutDev );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ BOOL bRet = FALSE;
+
+ if( maList.Count() )
+ {
+ if( ( pOut->GetOutDevType() == OUTDEV_WINDOW ) && !mbLoopTerminated &&
+ ( ANIMATION_TIMEOUT_ON_CLICK != ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ) )
+ {
+ ImplAnimView* pView;
+ ImplAnimView* pMatch = NULL;
+
+ for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
+ {
+ if( pView->ImplMatches( pOut, nExtraData ) )
+ {
+ if( pView->ImplGetOutPos() == rDestPt &&
+ pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) )
+ {
+ pView->ImplRepaint();
+ pMatch = pView;
+ }
+ else
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = NULL;
+ }
+
+ break;
+ }
+ }
+
+ if( !mpViewList->Count() )
+ {
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ mnPos = 0UL;
+ }
+
+ if( !pMatch )
+ mpViewList->Insert( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ), LIST_APPEND );
+
+ if( !mbIsInAnimation )
+ {
+ ImplRestartTimer( ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait );
+ mbIsInAnimation = TRUE;
+ }
+ }
+ else
+ Draw( pOut, rDestPt, rDestSz );
+
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Stop( OutputDevice* pOut, long nExtraData )
+{
+ ImplAnimView* pView = (ImplAnimView*) mpViewList->First();
+
+ while( pView )
+ {
+ if( pView->ImplMatches( pOut, nExtraData ) )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+
+ if( !mpViewList->Count() )
+ {
+ maTimer.Stop();
+ mbIsInAnimation = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
+{
+ Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const
+{
+ const ULONG nCount = maList.Count();
+
+ if( nCount )
+ {
+ AnimationBitmap* pObj = (AnimationBitmap*) maList.GetObject( Min( mnPos, (long) nCount - 1L ) );
+
+ if( pOut->GetConnectMetaFile() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) )
+ ( (AnimationBitmap*) maList.GetObject( 0 ) )->aBmpEx.Draw( pOut, rDestPt, rDestSz );
+ else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait )
+ pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz );
+ else
+ {
+ const ULONG nOldPos = mnPos;
+ ( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
+ delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 );
+ ( (Animation*) this )->mnPos = nOldPos;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::ImplRestartTimer( ULONG nTimeout )
+{
+#ifdef REMOTE_APPSERVER
+ nTimeout = nTimeout > 40 ? nTimeout : 40;
+#endif
+ maTimer.SetTimeout( Max( nTimeout, MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT ) * 10L );
+ maTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Animation, ImplTimeoutHdl, Timer*, pTimer )
+{
+ const ULONG nAnimCount = maList.Count();
+
+ if( nAnimCount )
+ {
+ ImplAnimView* pView;
+ BOOL bGlobalPause = TRUE;
+
+ if( maNotifyLink.IsSet() )
+ {
+ AInfo* pAInfo;
+
+ // create AInfo-List
+ for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
+ maAInfoList.Insert( pView->ImplCreateAInfo() );
+
+ maNotifyLink.Call( this );
+
+ // set view state from AInfo structure
+ for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
+ {
+ if( !pAInfo->pViewData )
+ {
+ pView = new ImplAnimView( this, pAInfo->pOutDev,
+ pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
+
+ mpViewList->Insert( pView, LIST_APPEND );
+ }
+ else
+ pView = (ImplAnimView*) pAInfo->pViewData;
+
+ pView->ImplPause( pAInfo->bPause );
+ pView->ImplSetMarked( TRUE );
+ }
+
+ // delete AInfo structures
+ for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
+ delete (AInfo*) pAInfo;
+ maAInfoList.Clear();
+
+ // delete all unmarked views and reset marked state
+ pView = (ImplAnimView*) mpViewList->First();
+ while( pView )
+ {
+ if( !pView->ImplIsMarked() )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ {
+ if( !pView->ImplIsPause() )
+ bGlobalPause = FALSE;
+
+ pView->ImplSetMarked( FALSE );
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+ }
+ }
+ else
+ bGlobalPause = FALSE;
+
+ if( !mpViewList->Count() )
+ Stop();
+ else if( bGlobalPause )
+ ImplRestartTimer( 10 );
+ else
+ {
+ AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.GetObject( ++mnPos );
+
+ if( !pStepBmp )
+ {
+ if( mnLoops == 1 )
+ {
+ Stop();
+ mbLoopTerminated = TRUE;
+ mnPos = nAnimCount - 1UL;
+ maBitmapEx = ( (AnimationBitmap*) maList.GetObject( mnPos ) )->aBmpEx;
+ return 0L;
+ }
+ else
+ {
+ if( mnLoops )
+ mnLoops--;
+
+ mnPos = 0;
+ pStepBmp = (AnimationBitmap*) maList.GetObject( mnPos );
+ }
+ }
+
+ // Paint all views; after painting check, if view is
+ // marked; in this case remove view, because area of output
+ // lies out of display area of window; mark state is
+ // set from view itself
+ pView = (ImplAnimView*) mpViewList->First();
+ while( pView )
+ {
+ pView->ImplDraw( mnPos );
+
+ if( pView->ImplIsMarked() )
+ {
+ delete (ImplAnimView*) mpViewList->Remove( pView );
+ pView = (ImplAnimView*) mpViewList->GetCurObject();
+ }
+ else
+ pView = (ImplAnimView*) mpViewList->Next();
+ }
+
+ // stop or restart timer
+ if( !mpViewList->Count() )
+ Stop();
+ else
+ ImplRestartTimer( pStepBmp->nWait );
+ }
+ }
+ else
+ Stop();
+
+ return 0L;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Insert( const AnimationBitmap& rStepBmp )
+{
+ BOOL bRet = FALSE;
+
+ if( !IsInAnimation() )
+ {
+ Point aPoint;
+ Rectangle aGlobalRect( aPoint, maGlobalSize );
+
+ maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
+ maList.Insert( new AnimationBitmap( rStepBmp ), LIST_APPEND );
+
+ // zunaechst nehmen wir die erste BitmapEx als Ersatz-BitmapEx
+ if( maList.Count() == 1 )
+ maBitmapEx = rStepBmp.aBmpEx;
+
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+const AnimationBitmap& Animation::Get( USHORT nAnimation ) const
+{
+ DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
+ return *(AnimationBitmap*) maList.GetObject( nAnimation );
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, USHORT nAnimation )
+{
+ DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
+
+ delete (AnimationBitmap*) maList.Replace( new AnimationBitmap( rNewAnimationBitmap ), nAnimation );
+
+ // Falls wir an erster Stelle einfuegen,
+ // muessen wir natuerlich auch,
+ // auch die Ersatzdarstellungs-BitmapEx
+ // aktualisieren;
+ if ( ( !nAnimation && ( !mbLoopTerminated || ( maList.Count() == 1 ) ) ) ||
+ ( ( nAnimation == maList.Count() - 1 ) && mbLoopTerminated ) )
+ {
+ maBitmapEx = rNewAnimationBitmap.aBmpEx;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::SetLoopCount( const ULONG nLoopCount )
+{
+ mnLoopCount = nLoopCount;
+ ResetLoopCount();
+}
+
+// -----------------------------------------------------------------------
+
+void Animation::ResetLoopCount()
+{
+ mnLoops = mnLoopCount;
+ mbLoopTerminated = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Convert( BmpConversion eConversion )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Convert( eConversion );
+
+ maBitmapEx.Convert( eConversion );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::ReduceColors( USHORT nNewColorCount, BmpReduce eReduce )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.ReduceColors( nNewColorCount, eReduce );
+
+ maBitmapEx.ReduceColors( nNewColorCount, eReduce );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Invert()
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Invert();
+
+ maBitmapEx.Invert();
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Mirror( ULONG nMirrorFlags )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ if( nMirrorFlags )
+ {
+ for( AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.First();
+ pStepBmp && bRet;
+ pStepBmp = (AnimationBitmap*) maList.Next() )
+ {
+ if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) == TRUE )
+ {
+ if( nMirrorFlags & BMP_MIRROR_HORZ )
+ pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
+
+ if( nMirrorFlags & BMP_MIRROR_VERT )
+ pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
+ }
+ }
+
+ maBitmapEx.Mirror( nMirrorFlags );
+ }
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Dither( nDitherFlags, pDitherPal );
+
+ maBitmapEx.Dither( nDitherFlags, pDitherPal );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ {
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert );
+ }
+
+ maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
+
+ BOOL bRet;
+
+ if( !IsInAnimation() && maList.Count() )
+ {
+ bRet = TRUE;
+
+ for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
+ bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
+
+ maBitmapEx.Filter( eFilter, pFilterParam, pProgress );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Animation& rAnimation )
+{
+ const USHORT nCount = rAnimation.Count();
+
+ if( nCount )
+ {
+ const ByteString aDummyStr;
+ const UINT32 nDummy32 = 0UL;
+
+ // Falls keine BitmapEx gesetzt wurde, schreiben wir
+ // einfach die erste Bitmap der Animation
+ if( !rAnimation.GetBitmapEx().GetBitmap() )
+ rOStm << rAnimation.Get( 0 ).aBmpEx;
+ else
+ rOStm << rAnimation.GetBitmapEx();
+
+ // Kennung schreiben ( SDANIMA1 )
+ rOStm << (UINT32) 0x5344414e << (UINT32) 0x494d4931;
+
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
+ const UINT16 nRest = nCount - i - 1;
+
+ // AnimationBitmap schreiben
+ rOStm << rAnimBmp.aBmpEx;
+ rOStm << rAnimBmp.aPosPix;
+ rOStm << rAnimBmp.aSizePix;
+ rOStm << rAnimation.maGlobalSize;
+ rOStm << (UINT16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait );
+ rOStm << (UINT16) rAnimBmp.eDisposal;
+ rOStm << (BYTE) rAnimBmp.bUserInput;
+ rOStm << (UINT32) rAnimation.mnLoopCount;
+ rOStm << nDummy32; // unbenutzt
+ rOStm << nDummy32; // unbenutzt
+ rOStm << nDummy32; // unbenutzt
+ rOStm << aDummyStr; // unbenutzt
+ rOStm << nRest; // Anzahl der Strukturen, die noch _folgen_
+ }
+ }
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Animation& rAnimation )
+{
+ Bitmap aBmp;
+ ULONG nStmPos = rIStm.Tell();
+ UINT32 nAnimMagic1, nAnimMagic2;
+ USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bReadAnimations = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ nStmPos = rIStm.Tell();
+ rIStm >> nAnimMagic1 >> nAnimMagic2;
+
+ rAnimation.Clear();
+
+ // Wenn die BitmapEx am Anfang schon gelesen
+ // wurde ( von Graphic ), koennen wir direkt die Animationsbitmaps einlesen
+ if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
+ bReadAnimations = TRUE;
+ // ansonsten versuchen wir erstmal die Bitmap(-Ex) zu lesen
+ else
+ {
+ rIStm.Seek( nStmPos );
+ rIStm >> rAnimation.maBitmapEx;
+ nStmPos = rIStm.Tell();
+ rIStm >> nAnimMagic1 >> nAnimMagic2;
+
+ if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
+ bReadAnimations = TRUE;
+ else
+ rIStm.Seek( nStmPos );
+ }
+
+ // ggf. Animationsbitmaps lesen
+ if( bReadAnimations )
+ {
+ AnimationBitmap aAnimBmp;
+ BitmapEx aBmpEx;
+ ByteString aDummyStr;
+ Point aPoint;
+ Size aSize;
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ BYTE cTmp;
+
+ do
+ {
+ rIStm >> aAnimBmp.aBmpEx;
+ rIStm >> aAnimBmp.aPosPix;
+ rIStm >> aAnimBmp.aSizePix;
+ rIStm >> rAnimation.maGlobalSize;
+ rIStm >> nTmp16; aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
+ rIStm >> nTmp16; aAnimBmp.eDisposal = ( Disposal) nTmp16;
+ rIStm >> cTmp; aAnimBmp.bUserInput = (BOOL) cTmp;
+ rIStm >> nTmp32; rAnimation.mnLoopCount = (USHORT) nTmp32;
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> nTmp32; // unbenutzt
+ rIStm >> aDummyStr; // unbenutzt
+ rIStm >> nTmp16; // Rest zu lesen
+
+ rAnimation.Insert( aAnimBmp );
+ }
+ while( nTmp16 && !rIStm.GetError() );
+
+ rAnimation.ResetLoopCount();
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return rIStm;
+}
diff --git a/vcl/source/gdi/bitmap.cxx b/vcl/source/gdi/bitmap.cxx
new file mode 100644
index 000000000000..d5016647cfca
--- /dev/null
+++ b/vcl/source/gdi/bitmap.cxx
@@ -0,0 +1,1980 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BITMAP_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap() :
+ mpImpBmp( NULL )
+{
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const ResId& rResId ) :
+ mpImpBmp( NULL )
+{
+ ResMgr * pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
+
+ USHORT nBitmapType;
+ USHORT nBitmapId;
+ nBitmapType = pResMgr->ReadShort();
+ nBitmapId = pResMgr->ReadShort();
+
+ SvStream* pBmpStream = pResMgr->pImpRes->GetBitmapStream( nBitmapId );
+ if( pBmpStream )
+ *pBmpStream >> *this;
+ // pop filename
+ String aDummy = pResMgr->ReadString();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Bitmap& rBitmap ) :
+ maPrefMapMode ( rBitmap.maPrefMapMode ),
+ maPrefSize ( rBitmap.maPrefSize )
+{
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ if ( mpImpBmp )
+ mpImpBmp->ImplIncRefCount();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Size& rSizePixel, USHORT nBitCount, const BitmapPalette* pPal )
+{
+ if( rSizePixel.Width() && rSizePixel.Height() )
+ {
+ BitmapPalette aPal;
+ BitmapPalette* pRealPal = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ if( !pPal )
+ {
+ if( 1 == nBitCount )
+ {
+ aPal.SetEntryCount( 2 );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_WHITE );
+ }
+ else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
+ {
+ aPal.SetEntryCount( 1 << nBitCount );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_BLUE );
+ aPal[ 2 ] = Color( COL_GREEN );
+ aPal[ 3 ] = Color( COL_CYAN );
+ aPal[ 4 ] = Color( COL_RED );
+ aPal[ 5 ] = Color( COL_MAGENTA );
+ aPal[ 6 ] = Color( COL_BROWN );
+ aPal[ 7 ] = Color( COL_GRAY );
+ aPal[ 8 ] = Color( COL_LIGHTGRAY );
+ aPal[ 9 ] = Color( COL_LIGHTBLUE );
+ aPal[ 10 ] = Color( COL_LIGHTGREEN );
+ aPal[ 11 ] = Color( COL_LIGHTCYAN );
+ aPal[ 12 ] = Color( COL_LIGHTRED );
+ aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
+ aPal[ 14 ] = Color( COL_YELLOW );
+ aPal[ 15 ] = Color( COL_WHITE );
+
+ // Dither-Palette erzeugen
+ if( 8 == nBitCount )
+ {
+ USHORT nActCol = 16;
+
+ for( USHORT nB = 0; nB < 256; nB += 51 )
+ for( USHORT nG = 0; nG < 256; nG += 51 )
+ for( USHORT nR = 0; nR < 256; nR += 51 )
+ aPal[ nActCol++ ] = BitmapColor( (BYTE) nR, (BYTE) nG, (BYTE) nB );
+
+ // Standard-Office-Farbe setzen
+ aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
+ }
+ }
+ }
+ else
+ pRealPal = (BitmapPalette*) pPal;
+ }
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
+ }
+ else
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::~Bitmap()
+{
+ ImplReleaseRef();
+}
+
+// ------------------------------------------------------------------
+
+const BitmapPalette& Bitmap::GetGreyPalette( USHORT nEntries )
+{
+ static BitmapPalette aGreyPalette2;
+ static BitmapPalette aGreyPalette4;
+ static BitmapPalette aGreyPalette16;
+ static BitmapPalette aGreyPalette256;
+
+ // create greyscale palette with 2, 4, 16 or 256 entries
+ if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
+ {
+ if( 2 == nEntries )
+ {
+ if( !aGreyPalette2.GetEntryCount() )
+ {
+ aGreyPalette2.SetEntryCount( 2 );
+ aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette2;
+ }
+ else if( 4 == nEntries )
+ {
+ if( !aGreyPalette4.GetEntryCount() )
+ {
+ aGreyPalette4.SetEntryCount( 4 );
+ aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
+ aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
+ aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette4;
+ }
+ else if( 16 == nEntries )
+ {
+ if( !aGreyPalette16.GetEntryCount() )
+ {
+ BYTE cGrey = 0, cGreyInc = 17;
+
+ aGreyPalette16.SetEntryCount( 16 );
+
+ for( USHORT i = 0; i < 16; i++, cGrey += cGreyInc )
+ aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
+ }
+
+ return aGreyPalette16;
+ }
+ else
+ {
+ if( !aGreyPalette256.GetEntryCount() )
+ {
+ aGreyPalette256.SetEntryCount( 256 );
+
+ for( USHORT i = 0; i < 256; i++ )
+ aGreyPalette256[ i ] = BitmapColor( (BYTE) i, (BYTE) i, (BYTE) i );
+ }
+
+ return aGreyPalette256;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
+ return aGreyPalette2;
+ }
+}
+
+// ------------------------------------------------------------------
+
+Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
+{
+ maPrefSize = rBitmap.maPrefSize;
+ maPrefMapMode = rBitmap.maPrefMapMode;
+
+ if ( rBitmap.mpImpBmp )
+ rBitmap.mpImpBmp->ImplIncRefCount();
+
+ ImplReleaseRef();
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ return *this;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::IsEqual( const Bitmap& rBmp ) const
+{
+ return( IsSameInstance( rBmp ) ||
+ ( rBmp.GetSizePixel() == GetSizePixel() &&
+ rBmp.GetBitCount() == GetBitCount() &&
+ rBmp.GetChecksum() == GetChecksum() ) );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetEmpty()
+{
+ maPrefMapMode = MapMode();
+ maPrefSize = Size();
+
+ ImplReleaseRef();
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Size Bitmap::GetSizePixel() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetSizePixel( const Size& rNewSize )
+{
+ Scale( rNewSize );
+}
+
+// ------------------------------------------------------------------
+
+USHORT Bitmap::GetBitCount() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::HasGreyPalette() const
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ if( 1 == nBitCount )
+ bRet = TRUE;
+ else if( 4 == nBitCount || 8 == nBitCount )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) )
+ bRet = TRUE;
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+ULONG Bitmap::GetChecksum() const
+{
+ ULONG nRet = 0UL;
+
+ if( mpImpBmp )
+ {
+ nRet = mpImpBmp->ImplGetChecksum();
+
+ if( !nRet )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc && pRAcc->Width() && pRAcc->Height() )
+ {
+ sal_uInt32 nCrc = 0;
+ SVBT32 aBT32;
+
+ pRAcc->ImplZeroInitUnusedBits();
+
+ LongToSVBT32( pRAcc->Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetBitCount(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ if( pRAcc->HasPalette() )
+ {
+ nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
+ pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
+ }
+
+ nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+
+ mpImpBmp->ImplSetChecksum( nRet = nCrc );
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplReleaseRef()
+{
+ if( mpImpBmp )
+ {
+ if( mpImpBmp->ImplGetRefCount() > 1UL )
+ mpImpBmp->ImplDecRefCount();
+ else
+ {
+ delete mpImpBmp;
+ mpImpBmp = NULL;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplMakeUnique()
+{
+ if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
+ {
+ ImpBitmap* pOldImpBmp = mpImpBmp;
+
+ pOldImpBmp->ImplDecRefCount();
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( *pOldImpBmp );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
+{
+ const Size aOldSizePix( GetSizePixel() );
+ const Size aNewSizePix( rBitmap.GetSizePixel() );
+ const MapMode aOldMapMode( maPrefMapMode );
+ Size aNewPrefSize;
+
+ if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
+ {
+ aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
+ aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
+ }
+ else
+ aNewPrefSize = maPrefSize;
+
+ *this = rBitmap;
+
+ maPrefSize = aNewPrefSize;
+ maPrefMapMode = aOldMapMode;
+}
+
+// ------------------------------------------------------------------
+
+ImpBitmap* Bitmap::ImplGetImpBitmap() const
+{
+ return mpImpBmp;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
+{
+ if( pImpBmp != mpImpBmp )
+ {
+ ImplReleaseRef();
+ mpImpBmp = pImpBmp;
+ }
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess* Bitmap::AcquireReadAccess()
+{
+#ifdef REMOTE_APPSERVER
+ BOOL bGottenFromServer = FALSE;
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet(), bGottenFromServer = TRUE;
+#endif
+
+ BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
+
+ if( !*pReadAccess )
+ {
+ delete pReadAccess;
+ pReadAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pReadAccess && mpImpBmp && bGottenFromServer )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pReadAccess;
+}
+
+// ------------------------------------------------------------------
+
+BitmapWriteAccess* Bitmap::AcquireWriteAccess()
+{
+#ifdef REMOTE_APPSERVER
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet();
+#endif
+
+ BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
+
+ if( !*pWriteAccess )
+ {
+ delete pWriteAccess;
+ pWriteAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pWriteAccess && mpImpBmp )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pWriteAccess;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
+{
+ delete pBitmapAccess;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Erase( const Color& rFillColor )
+{
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ const ULONG nFormat = pWriteAcc->GetScanlineFormat();
+ BYTE cIndex;
+ BOOL bFast;
+
+ switch( nFormat )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_1BIT_LSB_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = ( cIndex ? 255 : 0 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_4BIT_LSN_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = cIndex | ( cIndex << 4 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_8BIT_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ {
+ if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
+ ( rFillColor.GetRed() == rFillColor.GetBlue() ) )
+ {
+ cIndex = rFillColor.GetRed();
+ bFast = TRUE;
+ }
+ else
+ bFast = FALSE;
+ }
+ break;
+
+ default:
+ bFast = FALSE;
+ break;
+ }
+
+ if( bFast )
+ {
+ const ULONG nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
+ HMEMSET( pWriteAcc->GetBuffer(), cIndex, nBufSize );
+ }
+ else
+ {
+ Point aTmpPoint;
+ const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
+ pWriteAcc->SetFillColor( rFillColor );
+ pWriteAcc->FillRect( aRect );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Invert()
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ if( pAcc->HasPalette() )
+ {
+ BitmapPalette aBmpPal( pAcc->GetPalette() );
+ const USHORT nCount = aBmpPal.GetEntryCount();
+
+ for( USHORT i = 0; i < nCount; i++ )
+ aBmpPal[ i ].Invert();
+
+ pAcc->SetPalette( aBmpPal );
+ }
+ else
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ for( long nY = 0L; nY < nHeight; nY++ )
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Mirror( ULONG nMirrorFlags )
+{
+ BOOL bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
+ BOOL bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
+ BOOL bRet = FALSE;
+
+ if( bHorz && !bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+ const long nWidth1 = nWidth - 1L;
+ const long nWidth_2 = nWidth >> 1L;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
+ pAcc->SetPixel( nY, nOther, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bVert && !bHorz )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nScanSize = pAcc->GetScanlineSize();
+ BYTE* pBuffer = new BYTE[ nScanSize ];
+ const long nHeight = pAcc->Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nHeight_2 = nHeight >> 1L;
+
+ for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
+ {
+ HMEMCPY( pBuffer, pAcc->GetScanline( nY ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
+ }
+
+ delete[] pBuffer;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bHorz && bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pAcc->Height();
+ long nHeight_2 = nHeight >> 1;
+
+ for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
+ {
+ for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
+ pAcc->SetPixel( nOtherY, nOtherX, aTemp );
+ }
+ }
+
+ // ggf. noch mittlere Zeile horizontal spiegeln
+ if( nHeight & 1 )
+ {
+ for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
+ pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
+ pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Rotate( long nAngle10, const Color& rFillColor )
+{
+ BOOL bRet = FALSE;
+
+ nAngle10 %= 3600L;
+ nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
+
+ if( !nAngle10 )
+ bRet = TRUE;
+ else if( 1800L == nAngle10 )
+ bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
+ else
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aRotatedBmp;
+
+ if( pReadAcc )
+ {
+ const Size aSizePix( GetSizePixel() );
+
+ if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
+ {
+ const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = aSizePix.Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = aSizePix.Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+
+ if( 900L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
+ for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
+ }
+ else if( 2700L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
+ for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+ else
+ {
+ Point aTmpPoint;
+ Rectangle aTmpRectangle( aTmpPoint, aSizePix );
+ Polygon aPoly( aTmpRectangle );
+ aPoly.Rotate( aTmpPoint, (USHORT) nAngle10 );
+
+ Rectangle aNewBound( aPoly.GetBoundRect() );
+ const Size aNewSizePix( aNewBound.GetSize() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
+ const double fCosAngle = cos( nAngle10 * F_PI1800 );
+ const double fSinAngle = sin( nAngle10 * F_PI1800 );
+ const double fXMin = aNewBound.Left();
+ const double fYMin = aNewBound.Top();
+ const long nWidth = aSizePix.Width();
+ const long nHeight = aSizePix.Height();
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+ long nX;
+ long nY;
+ long nRotX;
+ long nRotY;
+ long nSinY;
+ long nCosY;
+ long* pCosX = new long[ nNewWidth ];
+ long* pSinX = new long[ nNewWidth ];
+ long* pCosY = new long[ nNewHeight ];
+ long* pSinY = new long[ nNewHeight ];
+
+ for ( nX = 0; nX < nNewWidth; nX++ )
+ {
+ const double fTmp = ( fXMin + nX ) * 64.;
+
+ pCosX[ nX ] = FRound( fCosAngle * fTmp );
+ pSinX[ nX ] = FRound( fSinAngle * fTmp );
+ }
+
+ for ( nY = 0; nY < nNewHeight; nY++ )
+ {
+ const double fTmp = ( fYMin + nY ) * 64.;
+
+ pCosY[ nY ] = FRound( fCosAngle * fTmp );
+ pSinY[ nY ] = FRound( fSinAngle * fTmp );
+ }
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nSinY = pSinY[ nY ];
+ nCosY = pCosY[ nY ];
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
+ nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
+
+ if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
+ else
+ pWriteAcc->SetPixel( nY, nX, aFillColor );
+ }
+ }
+
+ delete[] pSinX;
+ delete[] pCosX;
+ delete[] pSinY;
+ delete[] pCosY;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+
+ ReleaseAccess( pReadAcc );
+ }
+
+ if( ( bRet = !!aRotatedBmp ) == TRUE )
+ ImplAssignWithSize( aRotatedBmp );
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Crop( const Rectangle& rRectPixel )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRect( rRectPixel );
+ BOOL bRet = FALSE;
+
+ aRect.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRect.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Point aTmpPoint;
+ const Rectangle aNewRect( aTmpPoint, aRect.GetSize() );
+ Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nOldX = aRect.Left();
+ const long nOldY = aRect.Top();
+ const long nNewWidth = aNewRect.GetWidth();
+ const long nNewHeight = aNewRect.GetHeight();
+
+ for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
+ for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CopyPixel( const Rectangle& rRectDst,
+ const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRectDst( rRectDst );
+ BOOL bRet = FALSE;
+
+ aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectDst.IsEmpty() )
+ {
+ if( pBmpSrc && ( *pBmpSrc != *this ) )
+ {
+ Bitmap* pSrc = (Bitmap*) pBmpSrc;
+ const Size aCopySizePix( pSrc->GetSizePixel() );
+ Rectangle aRectSrc( rRectSrc );
+ const USHORT nSrcBitCount = pBmpSrc->GetBitCount();
+ const USHORT nDstBitCount = GetBitCount();
+
+ if( nSrcBitCount > nDstBitCount )
+ {
+ long nNextIndex = 0L;
+
+ if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
+ Convert( BMP_CONVERSION_24BIT );
+ else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
+ {
+ Convert( BMP_CONVERSION_8BIT_COLORS );
+ nNextIndex = 16;
+ }
+ else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
+ {
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+ nNextIndex = 2;
+ }
+
+ if( nNextIndex )
+ {
+ BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess();
+ BitmapWriteAccess* pDstAcc = AcquireWriteAccess();
+
+ if( pSrcAcc && pDstAcc )
+ {
+ const long nSrcCount = pDstAcc->GetPaletteEntryCount();
+ const long nDstCount = 1 << nDstBitCount;
+ BOOL bFound;
+
+ for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
+ {
+ const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (USHORT) i );
+
+ bFound = FALSE;
+
+ for( long j = 0L; j < nDstCount; j++ )
+ {
+ if( rSrcCol == pDstAcc->GetPaletteColor( (USHORT) j ) )
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if( !bFound )
+ pDstAcc->SetPaletteColor( (USHORT) nNextIndex++, rSrcCol );
+ }
+ }
+
+ if( pSrcAcc )
+ pSrc->ReleaseAccess( pSrcAcc );
+
+ if( pDstAcc )
+ ReleaseAccess( pDstAcc );
+ }
+ }
+
+ aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
+
+ if( !aRectSrc.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcEndX = aRectSrc.Left() + nWidth;
+ const long nSrcEndY = aRectSrc.Top() + nHeight;
+ long nDstY = aRectDst.Top();
+
+ if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
+ {
+ const USHORT nCount = pReadAcc->GetPaletteEntryCount();
+ BYTE* pMap = new BYTE[ nCount ];
+
+ // Index-Map fuer Farbtabelle
+ // aufbauen, da das Bild ja (relativ) farbgenau
+ // kopiert werden soll
+ for( USHORT i = 0; i < nCount; i++ )
+ pMap[ i ] = (BYTE) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
+
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
+
+ delete[] pMap;
+ }
+ else if( pReadAcc->HasPalette() )
+ {
+ }
+ else
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
+
+ ReleaseAccess( pWriteAcc );
+ bRet = ( nWidth > 0L ) && ( nHeight > 0L );
+ }
+
+ pSrc->ReleaseAccess( pReadAcc );
+ }
+ }
+ }
+ else
+ {
+ Rectangle aRectSrc( rRectSrc );
+
+ aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcX = aRectSrc.Left();
+ const long nSrcY = aRectSrc.Top();
+ const long nSrcEndX1 = nSrcX + nWidth - 1L;
+ const long nSrcEndY1 = nSrcY + nHeight - 1L;
+ const long nDstX = aRectDst.Left();
+ const long nDstY = aRectDst.Top();
+ const long nDstEndX1 = nDstX + nWidth - 1L;
+ const long nDstEndY1 = nDstY + nHeight - 1L;
+
+ if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Expand( ULONG nDX, ULONG nDY, const Color* pInitColor )
+{
+ BOOL bRet = FALSE;
+
+ if( nDX || nDY )
+ {
+ const Size aSizePixel( GetSizePixel() );
+ const long nWidth = aSizePixel.Width();
+ const long nHeight = aSizePixel.Height();
+ const Size aNewSize( nWidth + nDX, nHeight + nDY );
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+// Was soll den das ?
+// BitmapPalette aBmpPal( pReadAcc ? pReadAcc->GetPalette() : BitmapPalette() );
+ BitmapPalette aBmpPal( pReadAcc->GetPalette() );
+ Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aColor;
+ const ULONG nScanlineSize = pReadAcc->GetScanlineSize();
+ const long nNewX = nWidth;
+ const long nNewY = nHeight;
+ const long nNewWidth = pWriteAcc->Width();
+ const long nNewHeight = pWriteAcc->Height();
+ long nX;
+ long nY;
+
+ if( pInitColor )
+ aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
+
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ pWriteAcc->CopyScanline( nY, *pReadAcc );
+
+ if( pInitColor && nDX )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+ }
+
+ if( pInitColor && nDY )
+ for( nY = nNewY; nY < nNewHeight; nY++ )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateMask( const Color& rTransColor, ULONG nTol ) const
+{
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ const long nWidth = pReadAcc->Width();
+ const long nHeight = pReadAcc->Height();
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ if( !nTol )
+ {
+ const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
+ long nX, nY, nShift;
+
+ if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
+ pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
+ {
+ // optimized for 4Bit-MSN/LSN source palette
+ const BYTE cTest = aTest.GetIndex();
+ const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ // optimized for 8Bit source palette
+ const BYTE cTest = aTest.GetIndex();
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ // not optimized
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( aTest == pReadAcc->GetPixel( nY, nX ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ long nR, nG, nB;
+ const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPixel( nY, nX );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ bRet = TRUE;
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ if( bRet )
+ {
+ aNewBmp.maPrefSize = maPrefSize;
+ aNewBmp.maPrefMapMode = maPrefMapMode;
+ }
+ else
+ aNewBmp = Bitmap();
+
+ return aNewBmp;
+}
+
+// ------------------------------------------------------------------
+
+Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
+{
+ Region aRegion;
+ Rectangle aRect( rRect );
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
+ aRect.Justify();
+
+ if( pReadAcc )
+ {
+ Rectangle aSubRect;
+ const long nLeft = aRect.Left();
+ const long nTop = aRect.Top();
+ const long nRight = aRect.Right();
+ const long nBottom = aRect.Bottom();
+ const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
+
+ aRegion.ImplBeginAddRect();
+
+ for( long nY = nTop; nY <= nBottom; nY++ )
+ {
+ aSubRect.Top() = aSubRect.Bottom() = nY;
+
+ for( long nX = nLeft; nX <= nRight; )
+ {
+ while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ if( nX <= nRight )
+ {
+ aSubRect.Left() = nX;
+
+ while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ aSubRect.Right() = nX - 1L;
+ aRegion.ImplAddRect( aSubRect );
+ }
+ }
+ }
+
+ aRegion.ImplEndAddRect();
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ }
+ else
+ aRegion = aRect;
+
+ return aRegion;
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BITMAP_SEG1
+#endif
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ BitmapColor aReplace;
+
+ if( pAcc->HasPalette() )
+ {
+ const USHORT nActColors = pAcc->GetPaletteEntryCount();
+ const USHORT nMaxColors = 1 << pAcc->GetBitCount();
+
+ // erst einmal naechste Farbe nehmen
+ aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
+
+ // falls Palettenbild, und die zu setzende Farbe ist nicht
+ // in der Palette, suchen wir nach freien Eintraegen (teuer)
+ if( pAcc->GetPaletteColor( (BYTE) aReplace ) != BitmapColor( rReplaceColor ) )
+ {
+ // erst einmal nachsehen, ob wir unsere ReplaceColor
+ // nicht auf einen freien Platz am Ende der Palette
+ // setzen koennen
+ if( nActColors < nMaxColors )
+ {
+ pAcc->SetPaletteEntryCount( nActColors + 1 );
+ pAcc->SetPaletteColor( nActColors, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) nActColors );
+ }
+ else
+ {
+ BOOL* pFlags = new BOOL[ nMaxColors ];
+
+ // alle Eintraege auf 0 setzen
+ memset( pFlags, 0, nMaxColors );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFlags[ (BYTE) pAcc->GetPixel( nY, nX ) ] = TRUE;
+
+ for( USHORT i = 0UL; i < nMaxColors; i++ )
+ {
+ // Hurra, wir haben einen unbenutzten Eintrag
+ if( !pFlags[ i ] )
+ {
+ pAcc->SetPaletteColor( (USHORT) i, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) i );
+ }
+ }
+
+ delete[] pFlags;
+ }
+ }
+ }
+ else
+ aReplace = rReplaceColor;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
+{
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapReadAccess* pAcc = AcquireReadAccess();
+ BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc && pAlphaAcc && pNewAcc )
+ {
+ BitmapColor aCol;
+ const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetColor( nY, nX );
+ pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (BYTE) pAlphaAcc->GetPixel( nY, nX ) ) );
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pAcc );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
+ aNewBmp.ReleaseAccess( pNewAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+
+ if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
+ nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
+ nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( i, rReplaceColor );
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
+ nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
+ nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+ }
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
+ ULONG nColorCount, ULONG* _pTols )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ long* pMinR = new long[ nColorCount ];
+ long* pMaxR = new long[ nColorCount ];
+ long* pMinG = new long[ nColorCount ];
+ long* pMaxG = new long[ nColorCount ];
+ long* pMinB = new long[ nColorCount ];
+ long* pMaxB = new long[ nColorCount ];
+ long* pTols;
+ ULONG i;
+
+ if( !_pTols )
+ {
+ pTols = new long[ nColorCount ];
+ memset( pTols, 0, nColorCount * sizeof( long ) );
+ }
+ else
+ pTols = (long*) _pTols;
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ const Color& rCol = pSearchColors[ i ];
+ const long nTol = pTols[ i ];
+
+ pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
+ pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
+ pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
+ pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
+ pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
+ pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
+ pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
+ pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( (USHORT)nEntry, pReplaceColors[ i ] );
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ BitmapColor* pReplaces = new BitmapColor[ nColorCount ];
+
+ for( i = 0UL; i < nColorCount; i++ )
+ pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
+ pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
+ pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, pReplaces[ i ] );
+ break;
+ }
+ }
+ }
+ }
+
+ delete[] pReplaces;
+ }
+
+ if( !_pTols )
+ delete[] pTols;
+
+ delete[] pMinR;
+ delete[] pMaxR;
+ delete[] pMinG;
+ delete[] pMaxG;
+ delete[] pMinB;
+ delete[] pMaxB;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
+{
+ Bitmap aDispBmp( *this );
+
+#ifndef REMOTE_APPSERVER
+ if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
+ {
+ ImpBitmap* pImpDispBmp = new ImpBitmap;
+
+ if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
+ aDispBmp.ImplSetImpBitmap( pImpDispBmp );
+ else
+ delete pImpDispBmp;
+ }
+#endif
+
+ return aDispBmp;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const Color aColBlack( COL_BLACK );
+ BitmapColor aPixel;
+ BitmapColor aMaskPixel;
+ const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
+ const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
+
+ switch( eCombine )
+ {
+ case( BMP_COMBINE_COPY ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_INVERT ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ) == aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_AND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NAND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_OR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_XOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NXOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+ }
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+void Bitmap::ImplDrawRemote( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmp( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteEx( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Bitmap& rMask ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rMask );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteAlpha( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const AlphaMask& rAlpha ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rAlpha );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteMask( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Color& rColor ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpMask( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplGetRemoteBmp( OutputDevice* pOut, const Point& rPt, const Size& rSz )
+{
+ DBG_ASSERT( !mpImpBmp, "Bitmap::ImplGetRemoteBmp???" );
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreateRemoteBmp( *this, pOut, rPt, rSz );
+}
+
+#endif
diff --git a/vcl/source/gdi/bitmap2.cxx b/vcl/source/gdi/bitmap2.cxx
new file mode 100644
index 000000000000..e4e4c407fc18
--- /dev/null
+++ b/vcl/source/gdi/bitmap2.cxx
@@ -0,0 +1,1269 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef WIN
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#define _SV_BITMAP_CXX
+
+#include <tools/zcodec.hxx>
+#ifndef _TOOLS_NEW_HXX
+#include <tools/new.hxx>
+#endif
+#ifndef _TOOLS_STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+#define USE_ZCODEC
+
+// -----------
+// - Defines -
+// -----------
+
+#define DIBCOREHEADERSIZE ( 12UL )
+#define DIBINFOHEADERSIZE ( sizeof( DIBInfoHeader ) )
+#define SETPIXEL4( pBuf, nX, cChar )( (pBuf)[ (nX) >> 1 ] |= ( (nX) & 1 ) ? ( cChar ): (cChar) << 4 );
+
+// ----------------------
+// - Compression defines
+// ----------------------
+
+#define COMPRESS_OWN ('S'|('D'<<8UL))
+#define COMPRESS_NONE ( 0UL )
+#define RLE_8 ( 1UL )
+#define RLE_4 ( 2UL )
+#define BITFIELDS ( 3UL )
+#define ZCOMPRESS ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
+
+// -----------------
+// - DIBInfoHeader -
+// -----------------
+
+struct DIBInfoHeader
+{
+ UINT32 nSize;
+ UINT32 nWidth;
+ UINT32 nHeight;
+ UINT16 nPlanes;
+ UINT16 nBitCount;
+ UINT32 nCompression;
+ UINT32 nSizeImage;
+ UINT32 nXPelsPerMeter;
+ UINT32 nYPelsPerMeter;
+ UINT32 nColsUsed;
+ UINT32 nColsImportant;
+
+ DIBInfoHeader() :
+ nSize( 0UL ),
+ nWidth( 0UL ),
+ nHeight( 0UL ),
+ nPlanes( 0 ),
+ nBitCount( 0 ),
+ nCompression( 0UL ),
+ nSizeImage( 0UL ),
+ nXPelsPerMeter( 0UL ),
+ nYPelsPerMeter( 0UL ),
+ nColsUsed( 0UL ),
+ nColsImportant( 0UL ) {}
+
+ ~DIBInfoHeader() {}
+};
+
+// ----------
+// - Bitmap -
+// ----------
+
+SvStream& operator>>( SvStream& rIStm, Bitmap& rBitmap )
+{
+ rBitmap.Read( rIStm, TRUE );
+ return rIStm;
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Bitmap& rBitmap )
+{
+ rBitmap.Write( rOStm, FALSE, TRUE );
+ return rOStm;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Read( SvStream& rIStm, BOOL bFileHeader )
+{
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ const ULONG nOldPos = rIStm.Tell();
+ ULONG nOffset = 0UL;
+ BOOL bRet = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( bFileHeader )
+ {
+ if( ImplReadDIBFileHeader( rIStm, nOffset ) )
+ bRet = ImplReadDIB( rIStm, *this, nOffset );
+ }
+ else
+ bRet = ImplReadDIB( rIStm, *this, nOffset );
+
+ if( !bRet )
+ {
+ if( !rIStm.GetError() )
+ rIStm.SetError( SVSTREAM_GENERALERROR );
+
+ rIStm.Seek( nOldPos );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIB( SvStream& rIStm, Bitmap& rBmp, ULONG nOffset )
+{
+ DIBInfoHeader aHeader;
+ const ULONG nStmPos = rIStm.Tell();
+ BitmapPalette* pPalette = NULL;
+ BOOL bHeaderRead = FALSE;
+ BOOL bRet = FALSE;
+
+ if( ImplReadDIBInfoHeader( rIStm, aHeader ) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount )
+ {
+ USHORT nBitCount = ( aHeader.nBitCount <= 1 ) ? 1 :
+ ( aHeader.nBitCount <= 4 ) ? 4 :
+ ( aHeader.nBitCount <= 8 ) ? 8 : 24;
+
+ const Size aSizePixel( aHeader.nWidth, aHeader.nHeight );
+ BitmapPalette aDummyPal;
+ Bitmap aNewBmp( aSizePixel, nBitCount, &aDummyPal );
+ BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ USHORT nColors;
+ SvStream* pIStm;
+ SvMemoryStream* pMemStm = NULL;
+ BYTE* pData = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ if( aHeader.nColsUsed )
+ nColors = (USHORT) aHeader.nColsUsed;
+ else
+ nColors = ( 1 << aHeader.nBitCount );
+ }
+ else
+ nColors = 0;
+
+#ifdef USE_ZCODEC
+ if( ZCOMPRESS == aHeader.nCompression )
+ {
+ ZCodec aCodec;
+ ULONG nCodedSize, nUncodedSize;
+ ULONG nCodedPos;
+
+ // read coding information
+ rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
+ pData = (BYTE*) SvMemAlloc( nUncodedSize );
+
+ // decode buffer
+ nCodedPos = rIStm.Tell();
+ aCodec.BeginCompression();
+ aCodec.Read( rIStm, pData, nUncodedSize );
+ aCodec.EndCompression();
+
+ // skip unread bytes from coded buffer
+ rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
+
+ // set decoded bytes to memory stream,
+ // from which we will read the bitmap data
+ pIStm = pMemStm = new SvMemoryStream;
+ pMemStm->SetBuffer( (char*) pData, nUncodedSize, FALSE, nUncodedSize );
+ nOffset = 0;
+ }
+ else
+#endif // USE_ZCODEC
+ pIStm = &rIStm;
+
+ // read palette
+ if( nColors )
+ {
+ pAcc->SetPaletteEntryCount( nColors );
+ ImplReadDIBPalette( *pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE );
+ }
+
+ // read bits
+ if( !pIStm->GetError() )
+ {
+ if( nOffset )
+ pIStm->SeekRel( nOffset - ( pIStm->Tell() - nStmPos ) );
+
+ bRet = ImplReadDIBBits( *pIStm, aHeader, *pAcc );
+
+ if( bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter )
+ {
+ MapMode aMapMode( MAP_MM, Point(),
+ Fraction( 1000, aHeader.nXPelsPerMeter ),
+ Fraction( 1000, aHeader.nYPelsPerMeter ) );
+
+ aNewBmp.SetPrefMapMode( aMapMode );
+ aNewBmp.SetPrefSize( Size( aHeader.nWidth, aHeader.nHeight ) );
+ }
+ }
+
+ if( pData )
+ SvMemFree( pData );
+
+ delete pMemStm;
+ aNewBmp.ReleaseAccess( pAcc );
+
+ if( bRet )
+ rBmp = aNewBmp;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBFileHeader( SvStream& rIStm, ULONG& rOffset )
+{
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ BOOL bRet = FALSE;
+
+ rIStm >> nTmp16;
+
+ if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
+ {
+ if ( 0x4142 == nTmp16 )
+ {
+ rIStm.SeekRel( 12L );
+ rIStm >> nTmp16;
+ rIStm.SeekRel( 8L );
+ rIStm >> nTmp32;
+ rOffset = nTmp32 - 28UL;;
+ bRet = ( 0x4D42 == nTmp16 );
+ }
+ else
+ {
+ rIStm.SeekRel( 8L );
+ rIStm >> nTmp32;
+ rOffset = nTmp32 - 14UL;
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ }
+ else
+ rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBInfoHeader( SvStream& rIStm, DIBInfoHeader& rHeader )
+{
+ // BITMAPINFOHEADER or BITMAPCOREHEADER
+ rIStm >> rHeader.nSize;
+
+ // BITMAPCOREHEADER
+ if ( rHeader.nSize == DIBCOREHEADERSIZE )
+ {
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rHeader.nWidth = nTmp16;
+ rIStm >> nTmp16; rHeader.nHeight = nTmp16;
+ rIStm >> nTmp16; rHeader.nPlanes = nTmp16;
+ rIStm >> nTmp16; rHeader.nBitCount = nTmp16;
+ }
+ else
+ {
+ // unknown Header
+ if( rHeader.nSize < DIBINFOHEADERSIZE )
+ {
+ ULONG nUnknownSize = sizeof( rHeader.nSize );
+
+ rIStm >> rHeader.nWidth; nUnknownSize += sizeof( rHeader.nWidth );
+ rIStm >> rHeader.nHeight; nUnknownSize += sizeof( rHeader.nHeight );
+ rIStm >> rHeader.nPlanes; nUnknownSize += sizeof( rHeader.nPlanes );
+ rIStm >> rHeader.nBitCount; nUnknownSize += sizeof( rHeader.nBitCount );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nCompression;
+ nUnknownSize += sizeof( rHeader.nCompression );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nSizeImage;
+ nUnknownSize += sizeof( rHeader.nSizeImage );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nXPelsPerMeter;
+ nUnknownSize += sizeof( rHeader.nXPelsPerMeter );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nYPelsPerMeter;
+ nUnknownSize += sizeof( rHeader.nYPelsPerMeter );
+ }
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nColsUsed;
+ nUnknownSize += sizeof( rHeader.nColsUsed );
+
+ if( nUnknownSize < rHeader.nSize )
+ {
+ rIStm >> rHeader.nColsImportant;
+ nUnknownSize += sizeof( rHeader.nColsImportant );
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ rIStm >> rHeader.nWidth;
+ rIStm >> rHeader.nHeight;
+ rIStm >> rHeader.nPlanes;
+ rIStm >> rHeader.nBitCount;
+ rIStm >> rHeader.nCompression;
+ rIStm >> rHeader.nSizeImage;
+ rIStm >> rHeader.nXPelsPerMeter;
+ rIStm >> rHeader.nYPelsPerMeter;
+ rIStm >> rHeader.nColsUsed;
+ rIStm >> rHeader.nColsImportant;
+ }
+
+ // Eventuell bis zur Palette ueberlesen
+ if ( rHeader.nSize > DIBINFOHEADERSIZE )
+ rIStm.SeekRel( rHeader.nSize - DIBINFOHEADERSIZE );
+ }
+
+ return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, BOOL bQuad )
+{
+ const USHORT nColors = rAcc.GetPaletteEntryCount();
+ const ULONG nPalSize = nColors * ( bQuad ? 4UL : 3UL );
+ BitmapColor aPalColor;
+
+ BYTE* pEntries = new BYTE[ nPalSize ];
+ rIStm.Read( pEntries, nPalSize );
+
+ BYTE* pTmpEntry = pEntries;
+ for( USHORT i = 0; i < nColors; i++ )
+ {
+ aPalColor.SetBlue( *pTmpEntry++ );
+ aPalColor.SetGreen( *pTmpEntry++ );
+ aPalColor.SetRed( *pTmpEntry++ );
+
+ if( bQuad )
+ pTmpEntry++;
+
+ rAcc.SetPaletteColor( i, aPalColor );
+ }
+
+ delete[] pEntries;
+
+ return( rIStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplReadDIBBits( SvStream& rIStm, DIBInfoHeader& rHeader, BitmapWriteAccess& rAcc )
+{
+ const ULONG nAlignedWidth = AlignedWidth4Bytes( rHeader.nWidth * rHeader.nBitCount );
+ UINT32 nRMask;
+ UINT32 nGMask;
+ UINT32 nBMask;
+ BOOL bNative;
+ BOOL bTCMask = ( rHeader.nBitCount == 16 ) || ( rHeader.nBitCount == 32 );
+ BOOL bRLE = ( RLE_8 == rHeader.nCompression && rHeader.nBitCount == 8 ) ||
+ ( RLE_4 == rHeader.nCompression && rHeader.nBitCount == 4 );
+
+ // Is native format?
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ bNative = ( rAcc.IsBottomUp() && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
+ break;
+
+ default:
+ bNative = FALSE;
+ break;
+ }
+
+ // Read data
+ if( bNative )
+ {
+ // true color DIB's can have a (optimization) palette
+ if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
+ rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
+
+ rIStm.Read( rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth );
+ }
+ else
+ {
+ // Read color mask
+ if( bTCMask )
+ {
+ if( rHeader.nCompression == BITFIELDS )
+ {
+ rIStm.SeekRel( -12L );
+ rIStm >> nRMask;
+ rIStm >> nGMask;
+ rIStm >> nBMask;
+ }
+ else
+ {
+ nRMask = ( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL;
+ nGMask = ( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL;
+ nBMask = ( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL;
+ }
+ }
+
+ if( bRLE )
+ {
+ if ( !rHeader.nSizeImage )
+ {
+ const ULONG nOldPos = rIStm.Tell();
+
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ rHeader.nSizeImage = rIStm.Tell() - nOldPos;
+ rIStm.Seek( nOldPos );
+ }
+
+ BYTE* pBuffer = (BYTE*) SvMemAlloc( rHeader.nSizeImage );
+
+ rIStm.Read( (char*) pBuffer, rHeader.nSizeImage );
+ ImplDecodeRLE( pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression );
+
+ SvMemFree( pBuffer );
+ }
+ else
+ {
+ const long nWidth = rHeader.nWidth;
+ const long nHeight = rHeader.nHeight;
+ BYTE* pBuf = new BYTE[ nAlignedWidth ];
+
+ // true color DIB's can have a (optimization) palette
+ if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
+ rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
+
+ switch( rHeader.nBitCount )
+ {
+ case( 1 ):
+ {
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+ cTmp = *pTmp++;
+
+ for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 8L,
+ cTmp = *pTmp++;
+ }
+
+ rAcc.SetPixel( nY, nX, ( cTmp >> --nShift ) & 1 );
+ }
+ }
+ }
+ break;
+
+ case( 4 ):
+ {
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+ cTmp = *pTmp++;
+
+ for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 2UL,
+ cTmp = *pTmp++;
+ }
+
+ rAcc.SetPixel( nY, nX, ( cTmp >> ( --nShift << 2UL ) ) & 0x0f );
+ }
+ }
+ }
+ break;
+
+ case( 8 ):
+ {
+ BYTE* pTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ rAcc.SetPixel( nY, nX, *pTmp++ );
+ }
+ }
+ break;
+
+ case( 16 ):
+ {
+ ColorMask aMask( nRMask, nGMask, nBMask );
+ BitmapColor aColor;
+ UINT16* pTmp16;
+
+ for( long nY = rHeader.nHeight - 1L; nY >= 0L; nY-- )
+ {
+ rIStm.Read( (char*)( pTmp16 = (UINT16*) pBuf ), nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aMask.GetColorFor16Bit( aColor, (BYTE*) pTmp16++ );
+ rAcc.SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ break;
+
+ case( 24 ):
+ {
+ BitmapColor aPixelColor;
+ BYTE* pTmp;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ rIStm.Read( pTmp = pBuf, nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixelColor.SetBlue( *pTmp++ );
+ aPixelColor.SetGreen( *pTmp++ );
+ aPixelColor.SetRed( *pTmp++ );
+ rAcc.SetPixel( nY, nX, aPixelColor );
+ }
+ }
+ }
+ break;
+
+ case( 32 ):
+ {
+ ColorMask aMask( nRMask, nGMask, nBMask );
+ BitmapColor aColor;
+ UINT32* pTmp32;
+
+ for( long nY = rHeader.nHeight - 1L; nY >= 0L; nY-- )
+ {
+ rIStm.Read( (char*)( pTmp32 = (UINT32*) pBuf ), nAlignedWidth );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aMask.GetColorFor32Bit( aColor, (BYTE*) pTmp32++ );
+ rAcc.SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ }
+
+ delete[] pBuf;
+ }
+ }
+
+ return( rIStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Write( SvStream& rOStm, BOOL bCompressed, BOOL bFileHeader ) const
+{
+ BMP_ASSERT( mpImpBmp, "Empty Bitmaps can't be saved" );
+
+ const Size aSizePix( GetSizePixel() );
+ BOOL bRet = FALSE;
+
+ if( mpImpBmp && aSizePix.Width() && aSizePix.Height() )
+ {
+ BitmapReadAccess* pAcc = ( (Bitmap*) this)->AcquireReadAccess();
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ const ULONG nOldPos = rOStm.Tell();
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( pAcc )
+ {
+ if( bFileHeader )
+ {
+ if( ImplWriteDIBFileHeader( rOStm, *pAcc ) )
+ bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
+ }
+ else
+ bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
+
+ ( (Bitmap*) this)->ReleaseAccess( pAcc );
+ }
+
+ if( !bRet )
+ {
+ rOStm.SetError( SVSTREAM_GENERALERROR );
+ rOStm.Seek( nOldPos );
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIB( SvStream& rOStm, BitmapReadAccess& rAcc, BOOL bCompressed ) const
+{
+ DIBInfoHeader aHeader;
+ ULONG nImageSizePos;
+ ULONG nEndPos;
+ ULONG nCompression = 0UL;
+ BOOL bRet = FALSE;
+
+ aHeader.nSize = DIBINFOHEADERSIZE;
+ aHeader.nWidth = rAcc.Width();
+ aHeader.nHeight = rAcc.Height();
+ aHeader.nPlanes = 1;
+
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_16BIT_TC_MASK ):
+ case( BMP_FORMAT_32BIT_TC_MASK ):
+ {
+ aHeader.nBitCount = ( rAcc.GetScanlineFormat() == BMP_FORMAT_16BIT_TC_MASK ) ? 16 : 32;
+ nCompression = BITFIELDS;
+ }
+ break;
+
+ default:
+ {
+ aHeader.nBitCount = rAcc.GetBitCount();
+
+ if( bCompressed )
+ {
+ if( 4 == aHeader.nBitCount )
+ nCompression = RLE_4;
+ else if( 8 == aHeader.nBitCount )
+ nCompression = RLE_8;
+ }
+ else
+ nCompression = COMPRESS_NONE;
+ }
+ break;
+ }
+
+#ifdef USE_ZCODEC
+ if( ( rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP ) &&
+ ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40 ) )
+ {
+ aHeader.nCompression = ZCOMPRESS;
+ }
+ else
+#endif // USE_ZCODEC
+ aHeader.nCompression = nCompression;
+
+ aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
+
+ if( maPrefSize.Width() && maPrefSize.Height() )
+ {
+ const Size aSize100( OutputDevice::LogicToLogic( maPrefSize, maPrefMapMode, MAP_100TH_MM ) );
+
+ if( aSize100.Width() && aSize100.Height() )
+ {
+ aHeader.nXPelsPerMeter = ( rAcc.Width() * 100000UL ) / aSize100.Width();
+ aHeader.nYPelsPerMeter = ( rAcc.Height() * 100000UL ) / aSize100.Height();
+ }
+ }
+
+ aHeader.nColsUsed = ( ( aHeader.nBitCount <= 8 ) ? rAcc.GetPaletteEntryCount() : 0 );
+ aHeader.nColsImportant = 0;
+
+ rOStm << aHeader.nSize;
+ rOStm << aHeader.nWidth;
+ rOStm << aHeader.nHeight;
+ rOStm << aHeader.nPlanes;
+ rOStm << aHeader.nBitCount;
+ rOStm << aHeader.nCompression;
+
+ nImageSizePos = rOStm.Tell();
+ rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
+
+ rOStm << aHeader.nXPelsPerMeter;
+ rOStm << aHeader.nYPelsPerMeter;
+ rOStm << aHeader.nColsUsed;
+ rOStm << aHeader.nColsImportant;
+
+#ifdef USE_ZCODEC
+ if( aHeader.nCompression == ZCOMPRESS )
+ {
+ ZCodec aCodec;
+ SvMemoryStream aMemStm( aHeader.nSizeImage + 4096, 65535 );
+ ULONG nCodedPos = rOStm.Tell(), nLastPos;
+ ULONG nCodedSize, nUncodedSize;
+
+ // write uncoded data palette
+ if( aHeader.nColsUsed )
+ ImplWriteDIBPalette( aMemStm, rAcc );
+
+ // write uncoded bits
+ bRet = ImplWriteDIBBits( aMemStm, rAcc, nCompression, aHeader.nSizeImage );
+
+ // get uncoded size
+ nUncodedSize = aMemStm.Tell();
+
+ // seek over compress info
+ rOStm.SeekRel( 12 );
+
+ // write compressed data
+ aCodec.BeginCompression( 3 );
+ aCodec.Write( rOStm, (BYTE*) aMemStm.GetData(), nUncodedSize );
+ aCodec.EndCompression();
+
+ // update compress info ( coded size, uncoded size, uncoded compression )
+ nCodedSize = ( nLastPos = rOStm.Tell() ) - nCodedPos - 12;
+ rOStm.Seek( nCodedPos );
+ rOStm << nCodedSize << nUncodedSize << nCompression;
+ rOStm.Seek( nLastPos );
+
+ if( bRet )
+ bRet = ( rOStm.GetError() == ERRCODE_NONE );
+ }
+ else
+#endif // USE_ZCODEC
+ {
+ if( aHeader.nColsUsed )
+ ImplWriteDIBPalette( rOStm, rAcc );
+
+ bRet = ImplWriteDIBBits( rOStm, rAcc, aHeader.nCompression, aHeader.nSizeImage );
+ }
+
+ nEndPos = rOStm.Tell();
+ rOStm.Seek( nImageSizePos );
+ rOStm << aHeader.nSizeImage;
+ rOStm.Seek( nEndPos );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBFileHeader( SvStream& rOStm, BitmapReadAccess& rAcc )
+{
+ UINT32 nPalCount = ( rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : rAcc.HasColorMask() ? 3UL : 0UL );
+ UINT32 nOffset = 14 + DIBINFOHEADERSIZE + nPalCount * 4UL;
+
+ rOStm << (UINT16) 0x4D42;
+ rOStm << (UINT32) ( nOffset + ( rAcc.Height() * rAcc.GetScanlineSize() ) );
+ rOStm << (UINT16) 0;
+ rOStm << (UINT16) 0;
+ rOStm << nOffset;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
+{
+ const USHORT nColors = rAcc.GetPaletteEntryCount();
+ const ULONG nPalSize = nColors * 4UL;
+ BYTE* pEntries = new BYTE[ nPalSize ];
+ BYTE* pTmpEntry = pEntries;
+ BitmapColor aPalColor;
+
+ for( USHORT i = 0; i < nColors; i++ )
+ {
+ const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
+
+ *pTmpEntry++ = rPalColor.GetBlue();
+ *pTmpEntry++ = rPalColor.GetGreen();
+ *pTmpEntry++ = rPalColor.GetRed();
+ *pTmpEntry++ = 0;
+ }
+
+ rOStm.Write( pEntries, nPalSize );
+ delete[] pEntries;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteDIBBits( SvStream& rOStm, BitmapReadAccess& rAcc,
+ ULONG nCompression, ULONG& rImageSize )
+{
+ if( BITFIELDS == nCompression )
+ {
+ const ColorMask& rMask = rAcc.GetColorMask();
+ SVBT32 aVal32;
+
+ LongToSVBT32( rMask.GetRedMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ LongToSVBT32( rMask.GetGreenMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ LongToSVBT32( rMask.GetBlueMask(), aVal32 );
+ rOStm.Write( (BYTE*) aVal32, 4UL );
+
+ rImageSize = rOStm.Tell();
+
+ if( rAcc.IsBottomUp() )
+ rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
+ else
+ {
+ for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
+ rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
+ }
+ }
+ else if( ( RLE_4 == nCompression ) || ( RLE_8 == nCompression ) )
+ {
+ rImageSize = rOStm.Tell();
+ ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
+ }
+ else if( !nCompression )
+ {
+ const ULONG nAlignedWidth = AlignedWidth4Bytes( rAcc.Width() * rAcc.GetBitCount() );
+ BOOL bNative = FALSE;
+
+ switch( rAcc.GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ {
+ if( rAcc.IsBottomUp() && ( rAcc.GetScanlineSize() == nAlignedWidth ) )
+ bNative = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ rImageSize = rOStm.Tell();
+
+ if( bNative )
+ rOStm.Write( rAcc.GetBuffer(), nAlignedWidth * rAcc.Height() );
+ else
+ {
+ const long nWidth = rAcc.Width();
+ const long nHeight = rAcc.Height();
+ BYTE* pBuf = new BYTE[ nAlignedWidth ];
+ BYTE* pTmp;
+ BYTE cTmp;
+
+ switch( rAcc.GetBitCount() )
+ {
+ case( 1 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ cTmp = 0;
+
+ for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 8L;
+ *pTmp++ = cTmp;
+ cTmp = 0;
+ }
+
+ cTmp |= ( (BYTE) rAcc.GetPixel( nY, nX ) << --nShift );
+ }
+
+ *pTmp = cTmp;
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ case( 4 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ cTmp = 0;
+
+ for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
+ {
+ if( !nShift )
+ {
+ nShift = 2L;
+ *pTmp++ = cTmp;
+ cTmp = 0;
+ }
+
+ cTmp |= ( (BYTE) rAcc.GetPixel( nY, nX ) << ( --nShift << 2L ) );
+ }
+ *pTmp = cTmp;
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ case( 8 ):
+ {
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ *pTmp++ = rAcc.GetPixel( nY, nX );
+
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+
+ default:
+ {
+ BitmapColor aPixelColor;
+
+ for( long nY = nHeight - 1; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixelColor = rAcc.GetPixel( nY, nX );
+ *pTmp++ = aPixelColor.GetBlue();
+ *pTmp++ = aPixelColor.GetGreen();
+ *pTmp++ = aPixelColor.GetRed();
+ }
+
+ rOStm.Write( pBuf, nAlignedWidth );
+ }
+ }
+ break;
+ }
+
+ delete[] pBuf;
+ }
+ }
+
+ rImageSize = rOStm.Tell() - rImageSize;
+
+ return( rOStm.GetError() == 0UL );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDecodeRLE( BYTE* pBuffer, DIBInfoHeader& rHeader,
+ BitmapWriteAccess& rAcc, BOOL bRLE4 )
+{
+ Scanline pRLE = pBuffer;
+ long nY = rHeader.nHeight - 1L;
+ const ULONG nWidth = rAcc.Width();
+ ULONG nCountByte;
+ ULONG nRunByte;
+ ULONG nX = 0UL;
+ BYTE cTmp;
+ BOOL bEndDecoding = FALSE;
+
+ do
+ {
+ if( !( nCountByte = *pRLE++ ) )
+ {
+ nRunByte = *pRLE++;
+
+ if( nRunByte > 2 )
+ {
+ if( bRLE4 )
+ {
+ nCountByte = nRunByte >> 1;
+
+ for( ULONG i = 0UL; i < nCountByte; i++ )
+ {
+ cTmp = *pRLE++;
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
+ }
+
+ if( nRunByte & 1 )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, *pRLE >> 4 );
+
+ pRLE++;
+ }
+
+ if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
+ pRLE++;
+ }
+ else
+ {
+ for( ULONG i = 0UL; i < nRunByte; i++ )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, *pRLE );
+
+ pRLE++;
+ }
+
+ if( nRunByte & 1 )
+ pRLE++;
+ }
+ }
+ else if( !nRunByte )
+ {
+ nY--;
+ nX = 0UL;
+ }
+ else if( nRunByte == 1 )
+ bEndDecoding = TRUE;
+ else
+ {
+ nX += *pRLE++;
+ nY -= *pRLE++;
+ }
+ }
+ else
+ {
+ cTmp = *pRLE++;
+
+ if( bRLE4 )
+ {
+ nRunByte = nCountByte >> 1;
+
+ for( ULONG i = 0UL; i < nRunByte; i++ )
+ {
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+
+ if( nX < nWidth )
+ rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
+ }
+
+ if( ( nCountByte & 1 ) && ( nX < nWidth ) )
+ rAcc.SetPixel( nY, nX++, cTmp >> 4 );
+ }
+ else
+ {
+ for( ULONG i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
+ rAcc.SetPixel( nY, nX++, cTmp );
+ }
+ }
+ }
+ while ( !bEndDecoding && ( nY >= 0L ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, BOOL bRLE4 )
+{
+ const ULONG nWidth = rAcc.Width();
+ const ULONG nHeight = rAcc.Height();
+ ULONG nX;
+ ULONG nSaveIndex;
+ ULONG nCount;
+ ULONG nBufCount;
+ BYTE* pBuf = new BYTE[ nWidth << 1 ];
+ BYTE* pTmp;
+ BYTE cPix;
+ BYTE cLast;
+ BOOL bFound;
+
+ for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
+ {
+ pTmp = pBuf;
+ nX = nBufCount = 0UL;
+
+ while( nX < nWidth )
+ {
+ nCount = 1L;
+ cPix = rAcc.GetPixel( nY, nX++ );
+
+ while( ( nX < nWidth ) && ( nCount < 255L ) && ( cPix == rAcc.GetPixel( nY, nX ) ) )
+ {
+ nX++;
+ nCount++;
+ }
+
+ if ( nCount > 1 )
+ {
+ *pTmp++ = (BYTE) nCount;
+ *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
+ nBufCount += 2;
+ }
+ else
+ {
+ cLast = cPix;
+ nSaveIndex = nX - 1UL;
+ bFound = FALSE;
+
+ while( ( nX < nWidth ) && ( nCount < 256L ) && ( cPix = rAcc.GetPixel( nY, nX ) ) != cLast )
+ {
+ nX++; nCount++;
+ cLast = cPix;
+ bFound = TRUE;
+ }
+
+ if ( bFound )
+ nX--;
+
+ if ( nCount > 3 )
+ {
+ *pTmp++ = 0;
+ *pTmp++ = (BYTE) --nCount;
+
+ if( bRLE4 )
+ {
+ for ( ULONG i = 0; i < nCount; i++, pTmp++ )
+ {
+ *pTmp = (BYTE) rAcc.GetPixel( nY, nSaveIndex++ ) << 4;
+
+ if ( ++i < nCount )
+ *pTmp |= rAcc.GetPixel( nY, nSaveIndex++ );
+ }
+
+ nCount = ( nCount + 1 ) >> 1;
+ }
+ else
+ {
+ for( ULONG i = 0UL; i < nCount; i++ )
+ *pTmp++ = rAcc.GetPixel( nY, nSaveIndex++ );
+ }
+
+ if ( nCount & 1 )
+ {
+ *pTmp++ = 0;
+ nBufCount += ( nCount + 3 );
+ }
+ else
+ nBufCount += ( nCount + 2 );
+ }
+ else
+ {
+ *pTmp++ = 1;
+ *pTmp++ = (BYTE) rAcc.GetPixel( nY, nSaveIndex ) << ( bRLE4 ? 4 : 0 );
+
+ if ( nCount == 3 )
+ {
+ *pTmp++ = 1;
+ *pTmp++ = (BYTE) rAcc.GetPixel( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
+ nBufCount += 4;
+ }
+ else
+ nBufCount += 2;
+ }
+ }
+ }
+
+ pBuf[ nBufCount++ ] = 0;
+ pBuf[ nBufCount++ ] = 0;
+
+ rOStm.Write( pBuf, nBufCount );
+ }
+
+ rOStm << (BYTE) 0;
+ rOStm << (BYTE) 1;
+
+ delete[] pBuf;
+
+ return( rOStm.GetError() == 0UL );
+}
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
new file mode 100644
index 000000000000..34776a8b00bf
--- /dev/null
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -0,0 +1,2248 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdlib.h>
+#define _SV_BITMAP_CXX
+
+#ifdef W31
+#include <tools/svwin.h>
+#endif
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_IMPOCT_HXX
+#include <impoct.hxx>
+#endif
+#ifndef _SV_OCTREE_HXX
+#include <octree.hxx>
+#endif
+#ifndef _SV_IMPVECT_HXX
+#include <impvect.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define RGB15( _def_cR, _def_cG, _def_cB ) (((ULONG)(_def_cR)<<10UL)|((ULONG)(_def_cG)<<5UL)|(ULONG)(_def_cB))
+#define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
+
+#define CALC_ERRORS \
+ nTemp = p1T[nX++] >> 12; \
+ nBErr = MinMax( nTemp, 0, 255 ); \
+ nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
+ nTemp = p1T[nX++] >> 12; \
+ nGErr = MinMax( nTemp, 0, 255 ); \
+ nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
+ nTemp = p1T[nX] >> 12; \
+ nRErr = MinMax( nTemp, 0, 255 ); \
+ nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
+
+#define CALC_TABLES3 \
+ p2T[nX++] += FloydError3[nBErr]; \
+ p2T[nX++] += FloydError3[nGErr]; \
+ p2T[nX++] += FloydError3[nRErr];
+
+#define CALC_TABLES5 \
+ p2T[nX++] += FloydError5[nBErr]; \
+ p2T[nX++] += FloydError5[nGErr]; \
+ p2T[nX++] += FloydError5[nRErr];
+
+#define CALC_TABLES7 \
+ p1T[++nX] += FloydError7[nBErr]; \
+ p2T[nX++] += FloydError1[nBErr]; \
+ p1T[nX] += FloydError7[nGErr]; \
+ p2T[nX++] += FloydError1[nGErr]; \
+ p1T[nX] += FloydError7[nRErr]; \
+ p2T[nX] += FloydError1[nRErr];
+
+// -----------
+// - Statics -
+// -----------
+
+ULONG nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
+ULONG nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
+ULONG nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
+
+// ------------------------------------------------------------------------
+
+ULONG nVCLDitherLut[ 256 ] =
+{
+ 0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056,
+ 62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
+ 48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
+ 57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016,
+ 12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
+ 23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
+ 14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792,
+ 50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
+ 35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144,
+ 55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136,
+ 5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
+ 27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952,
+ 3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616,
+ 64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
+ 45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776,
+ 60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576,
+ 41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
+ 20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688,
+ 13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328,
+ 18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
+ 34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632,
+ 54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136,
+ 39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
+ 25856, 38144, 21760
+};
+
+// ------------------------------------------------------------------------
+
+ULONG nVCLLut[ 256 ] =
+{
+ 0, 1286, 2572, 3858, 5144, 6430, 7716, 9002,
+ 10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
+ 20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
+ 30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
+ 41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
+ 51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
+ 61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
+ 72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
+ 82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
+ 92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
+ 102880,104166,105452,106738,108024,109310,110596,111882,
+ 113168,114454,115740,117026,118312,119598,120884,122170,
+ 123456,124742,126028,127314,128600,129886,131172,132458,
+ 133744,135030,136316,137602,138888,140174,141460,142746,
+ 144032,145318,146604,147890,149176,150462,151748,153034,
+ 154320,155606,156892,158178,159464,160750,162036,163322,
+ 164608,165894,167180,168466,169752,171038,172324,173610,
+ 174896,176182,177468,178754,180040,181326,182612,183898,
+ 185184,186470,187756,189042,190328,191614,192900,194186,
+ 195472,196758,198044,199330,200616,201902,203188,204474,
+ 205760,207046,208332,209618,210904,212190,213476,214762,
+ 216048,217334,218620,219906,221192,222478,223764,225050,
+ 226336,227622,228908,230194,231480,232766,234052,235338,
+ 236624,237910,239196,240482,241768,243054,244340,245626,
+ 246912,248198,249484,250770,252056,253342,254628,255914,
+ 257200,258486,259772,261058,262344,263630,264916,266202,
+ 267488,268774,270060,271346,272632,273918,275204,276490,
+ 277776,279062,280348,281634,282920,284206,285492,286778,
+ 288064,289350,290636,291922,293208,294494,295780,297066,
+ 298352,299638,300924,302210,303496,304782,306068,307354,
+ 308640,309926,311212,312498,313784,315070,316356,317642,
+ 318928,320214,321500,322786,324072,325358,326644,327930
+};
+
+// ------------------------------------------------------------------------
+
+long FloydMap[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError1[61] =
+{
+ -7680, -7424, -7168, -6912, -6656, -6400, -6144,
+ -5888, -5632, -5376, -5120, -4864, -4608, -4352,
+ -4096, -3840, -3584, -3328, -3072, -2816, -2560,
+ -2304, -2048, -1792, -1536, -1280, -1024, -768,
+ -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
+ 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
+ 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
+ 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError3[61] =
+{
+ -23040, -22272, -21504, -20736, -19968, -19200,
+ -18432, -17664, -16896, -16128, -15360, -14592,
+ -13824, -13056, -12288, -11520, -10752, -9984,
+ -9216, -8448, -7680, -6912, -6144, -5376, -4608,
+ -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
+ 2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
+ 8448, 9216, 9984, 10752, 11520, 12288, 13056,
+ 13824, 14592, 15360, 16128, 16896, 17664, 18432,
+ 19200, 19968, 20736, 21504, 22272, 23040
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError5[61] =
+{
+ -38400, -37120, -35840, -34560, -33280, -32000,
+ -30720, -29440, -28160, -26880, -25600, -24320,
+ -23040, -21760, -20480, -19200, -17920, -16640,
+ -15360, -14080, -12800, -11520, -10240, -8960,
+ -7680, -6400, -5120, -3840, -2560, -1280, 0,
+ 1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
+ 11520, 12800, 14080, 15360, 16640, 17920, 19200,
+ 20480, 21760, 23040, 24320, 25600, 26880, 28160,
+ 29440, 30720, 32000, 33280, 34560, 35840, 37120,
+ 38400
+};
+
+// ------------------------------------------------------------------------
+
+long FloydError7[61] =
+{
+ -53760, -51968, -50176, -48384, -46592, -44800,
+ -43008, -41216, -39424, -37632, -35840, -34048,
+ -32256, -30464, -28672, -26880, -25088, -23296,
+ -21504, -19712, -17920, -16128, -14336, -12544,
+ -10752, -8960, -7168, -5376, -3584, -1792, 0,
+ 1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
+ 16128, 17920, 19712, 21504, 23296, 25088, 26880,
+ 28672, 30464, 32256, 34048, 35840, 37632, 39424,
+ 41216, 43008, 44800, 46592, 48384, 50176, 51968,
+ 53760
+};
+
+// ------------------------------------------------------------------------
+
+long FloydIndexMap[6] =
+{
+ -30, 21, 72, 123, 174, 225
+};
+
+// --------------------------
+// - ImplCreateDitherMatrix -
+// --------------------------
+
+void ImplCreateDitherMatrix( BYTE (*pDitherMatrix)[16][16] )
+{
+ double fVal = 3.125;
+ const double fVal16 = fVal / 16.;
+ long i, j, k, l;
+ USHORT pMtx[ 16 ][ 16 ];
+ USHORT nMax = 0;
+ static BYTE pMagic[4][4] = { 0, 14, 3, 13,
+ 11, 5, 8, 6,
+ 12, 2, 15, 1,
+ 7, 9, 4, 10 };
+
+ // MagicSquare aufbauen
+ for ( i = 0; i < 4; i++ )
+ for ( j = 0; j < 4; j++ )
+ for ( k = 0; k < 4; k++ )
+ for ( l = 0; l < 4; l++ )
+ nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
+ (USHORT) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
+
+ // auf Intervall [0;254] skalieren
+ for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
+ for( j = 0; j < 16; j++ )
+ (*pDitherMatrix)[i][j] = (BYTE) ( fVal * pMtx[i][j] );
+}
+
+// ----------
+// - Bitmap -
+// ----------
+
+BOOL Bitmap::Convert( BmpConversion eConversion )
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ switch( eConversion )
+ {
+ case( BMP_CONVERSION_1BIT_THRESHOLD ):
+ bRet = ImplMakeMono( 128 );
+ break;
+
+ case( BMP_CONVERSION_1BIT_MATRIX ):
+ bRet = ImplMakeMonoDither();
+ break;
+
+ case( BMP_CONVERSION_4BIT_GREYS ):
+ bRet = ImplMakeGreyscales( 16 );
+ break;
+
+ case( BMP_CONVERSION_4BIT_COLORS ):
+ {
+ if( nBitCount < 4 )
+ bRet = ImplConvertUp( 4, NULL );
+ else if( nBitCount > 4 )
+ bRet = ImplConvertDown( 4, NULL );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_4BIT_TRANS ):
+ {
+ Color aTrans( BMP_COL_TRANS );
+
+ if( nBitCount < 4 )
+ bRet = ImplConvertUp( 4, &aTrans );
+ else
+ bRet = ImplConvertDown( 4, &aTrans );
+ }
+ break;
+
+ case( BMP_CONVERSION_8BIT_GREYS ):
+ bRet = ImplMakeGreyscales( 256 );
+ break;
+
+ case( BMP_CONVERSION_8BIT_COLORS ):
+ {
+ if( nBitCount < 8 )
+ bRet = ImplConvertUp( 8 );
+ else if( nBitCount > 8 )
+ bRet = ImplConvertDown( 8 );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_8BIT_TRANS ):
+ {
+ Color aTrans( BMP_COL_TRANS );
+
+ if( nBitCount < 8 )
+ bRet = ImplConvertUp( 8, &aTrans );
+ else
+ bRet = ImplConvertDown( 8, &aTrans );
+ }
+ break;
+
+ case( BMP_CONVERSION_24BIT ):
+ {
+ if( nBitCount < 24 )
+ bRet = ImplConvertUp( 24, FALSE );
+ else
+ bRet = TRUE;
+ }
+ break;
+
+ case( BMP_CONVERSION_GHOSTED ):
+ bRet = ImplConvertGhosted();
+ break;
+
+ default:
+ DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
+ break;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeMono( BYTE cThreshold )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >=
+ cThreshold )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
+ cThreshold )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeMonoDither()
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ BYTE pDitherMatrix[ 16 ][ 16 ];
+
+ ImplCreateDitherMatrix( &pDitherMatrix );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >
+ pDitherMatrix[ nModY ][ nX % 16 ] )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
+ pDitherMatrix[ nModY ][ nX % 16 ] )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMakeGreyscales( USHORT nGreys )
+{
+ DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" )
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ const BitmapPalette& rPal = GetGreyPalette( nGreys );
+ ULONG nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
+ BOOL bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
+
+ if( !bPalDiffers )
+ bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
+
+ if( bPalDiffers )
+ {
+ Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ pWriteAcc->SetPixel( nY, nX,
+ (BYTE) ( pReadAcc->GetPaletteColor(
+ pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift ) );
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
+ pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ nShift += 8;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pReadScan = pReadAcc->GetScanline( nY );
+ Scanline pWriteScan = pWriteAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const ULONG nB = *pReadScan++;
+ const ULONG nG = *pReadScan++;
+ const ULONG nR = *pReadScan++;
+
+ *pWriteScan++ = (BYTE) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
+ pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ nShift += 8;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pReadScan = pReadAcc->GetScanline( nY );
+ Scanline pWriteScan = pWriteAcc->GetScanline( nY );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const ULONG nR = *pReadScan++;
+ const ULONG nG = *pReadScan++;
+ const ULONG nB = *pReadScan++;
+
+ *pWriteScan++ = (BYTE) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, ( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ else
+ {
+ ReleaseAccess( pReadAcc );
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertUp( USHORT nBitCount, Color* pExtColor )
+{
+ DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ BitmapPalette aPal;
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pWriteAcc->HasPalette() )
+ {
+ const USHORT nOldCount = 1 << GetBitCount();
+ const BitmapPalette& rOldPal = pReadAcc->GetPalette();
+
+ aPal.SetEntryCount( 1 << nBitCount );
+
+ for( USHORT i = 0; i < nOldCount; i++ )
+ aPal[ i ] = rOldPal[ i ];
+
+ if( pExtColor )
+ aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
+
+ pWriteAcc->SetPalette( aPal );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
+ }
+ else
+ {
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertDown( USHORT nBitCount, Color* pExtColor )
+{
+ DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ BitmapPalette aPal;
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const USHORT nCount = 1 << nBitCount;
+ const long nWidth = pWriteAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pWriteAcc->Height();
+ Octree aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
+ InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
+ BitmapColor aColor;
+ ImpErrorQuad aErrQuad;
+ ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pQLine1 = pErrQuad1;
+ ImpErrorQuad* pQLine2;
+ long nX, nY;
+ long nYTmp = 0L;
+ BYTE cIndex;
+ BOOL bQ1 = TRUE;
+
+ if( pExtColor )
+ {
+ aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
+ aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
+ }
+
+ // set Black/White always, if we have enough space
+ if( aPal.GetEntryCount() < ( nCount - 1 ) )
+ {
+ aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
+ aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
+ aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
+ }
+
+ pWriteAcc->SetPalette( aPal );
+
+ for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
+ {
+ for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->HasPalette() )
+ pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
+ else
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+ }
+
+ for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
+ {
+ // erstes ZeilenPixel
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
+ pWriteAcc->SetPixel( nY, 0, cIndex );
+
+ for( nX = 1L; nX < nWidth1; nX++ )
+ {
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
+ aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
+ pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
+ pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
+ pWriteAcc->SetPixel( nY, nX, cIndex );
+ }
+
+ // letztes ZeilenPixel
+ cIndex = (BYTE) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
+ pWriteAcc->SetPixel( nY, nX, cIndex );
+
+ // Zeilenpuffer neu fuellen/kopieren
+ pQLine1 = pQLine2;
+ pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
+
+ if( nYTmp < nHeight )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pReadAcc->HasPalette() )
+ pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
+ else
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+ }
+ }
+
+ // Zeilenpuffer zerstoeren
+ delete[] pErrQuad1;
+ delete[] pErrQuad2;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvertGhosted()
+{
+ Bitmap aNewBmp;
+ BitmapReadAccess* pR = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pR )
+ {
+ if( pR->HasPalette() )
+ {
+ BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
+
+ for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rOld = pR->GetPaletteColor( (USHORT) i );
+ aNewPal[ (USHORT) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
+ ( rOld.GetGreen() >> 1 ) | 0x80,
+ ( rOld.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
+ BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
+
+ if( pW )
+ {
+ pW->CopyBuffer( *pR );
+ aNewBmp.ReleaseAccess( pW );
+ bRet = TRUE;
+ }
+ }
+ else
+ {
+ aNewBmp = Bitmap( GetSizePixel(), 24 );
+
+ BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
+
+ if( pW )
+ {
+ const long nWidth = pR->Width(), nHeight = pR->Height();
+
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ const BitmapColor aOld( pR->GetPixel( nY, nX ) );
+ pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
+ ( aOld.GetGreen() >> 1 ) | 0x80,
+ ( aOld.GetBlue() >> 1 ) | 0x80 ) );
+
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pW );
+ bRet = TRUE;
+ }
+ }
+
+ ReleaseAccess( pR );
+ }
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet;
+
+ if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
+ {
+ if( BMP_SCALE_FAST == nScaleFlag )
+ bRet = ImplScaleFast( rScaleX, rScaleY );
+ else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
+ bRet = ImplScaleInterpolate( rScaleX, rScaleY );
+ else
+ bRet = FALSE;
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ const Size aSize( GetSizePixel() );
+ BOOL bRet;
+
+ if( aSize.Width() && aSize.Height() )
+ {
+ bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
+ (double) rNewSize.Height() / aSize.Height(),
+ nScaleFlag );
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
+{
+ const Size aSizePix( GetSizePixel() );
+ const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
+ const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
+ BOOL bRet = FALSE;
+
+ if( nNewWidth && nNewHeight )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nScanlineSize = pWriteAcc->GetScanlineSize();
+ const long nNewWidth1 = nNewWidth - 1L;
+ const long nNewHeight1 = nNewHeight - 1L;
+ const long nWidth1 = pReadAcc->Width() - 1L;
+ const long nHeight1 = pReadAcc->Height() - 1L;
+ long* pLutX = new long[ nNewWidth ];
+ long* pLutY = new long[ nNewHeight ];
+ long nX, nY, nMapY, nActY = 0L;
+
+ if( nNewWidth1 && nNewHeight1 )
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pLutX[ nX ] = nX * nWidth1 / nNewWidth1;
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pLutY[ nY ] = nY * nHeight1 / nNewHeight1;
+
+ while( nActY < nNewHeight )
+ {
+ nMapY = pLutY[ nActY ];
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
+
+ while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
+ {
+ HMEMCPY( pWriteAcc->GetScanline( nActY + 1L ),
+ pWriteAcc->GetScanline( nActY ), nScanlineSize );
+ nActY++;
+ }
+
+ nActY++;
+ }
+
+ bRet = TRUE;
+ }
+
+ delete[] pLutX;
+ delete[] pLutY;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
+{
+ const Size aSizePix( GetSizePixel() );
+ const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
+ const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
+ BOOL bRet = FALSE;
+
+ if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
+ {
+ BitmapColor aCol0;
+ BitmapColor aCol1;
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ long nWidth = pReadAcc->Width();
+ long nHeight = pReadAcc->Height();
+ Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ long* pLutInt;
+ long* pLutFrac;
+ long nX, nY;
+ long lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
+ double fTemp;
+ long nTemp;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nNewWidth1 = nNewWidth - 1L;
+ const long nWidth1 = pReadAcc->Width() - 1L;
+ const double fRevScaleX = (double) nWidth1 / nNewWidth1;
+
+ pLutInt = new long[ nNewWidth ];
+ pLutFrac = new long[ nNewWidth ];
+
+ for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
+ {
+ fTemp = nX * fRevScaleX;
+ pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
+ fTemp -= pLutInt[ nX ];
+ pLutFrac[ nX ] = (long) ( fTemp * 1024. );
+ }
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ if( 1 == nWidth )
+ {
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, 0 ) );
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nTemp = pLutInt[ nX ];
+
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp++ ) );
+ aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp ) );
+
+ nTemp = pLutFrac[ nX ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ if( 1 == nWidth )
+ {
+ aCol0 = pReadAcc->GetPixel( nY, 0 );
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nTemp = pLutInt[ nX ];
+
+ aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
+ aCol1 = pReadAcc->GetPixel( nY, nTemp );
+
+ nTemp = pLutFrac[ nX ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+
+ delete[] pLutInt;
+ delete[] pLutFrac;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+ ImplAssignWithSize( aNewBmp );
+ pReadAcc = AcquireReadAccess();
+ aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
+ pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nNewHeight1 = nNewHeight - 1L;
+ const long nHeight1 = pReadAcc->Height() - 1L;
+ const double fRevScaleY = (double) nHeight1 / nNewHeight1;
+
+ pLutInt = new long[ nNewHeight ];
+ pLutFrac = new long[ nNewHeight ];
+
+ for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
+ {
+ fTemp = nY * fRevScaleY;
+ pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
+ fTemp -= pLutInt[ nY ];
+ pLutFrac[ nY ] = (long) ( fTemp * 1024. );
+ }
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ if( 1 == nHeight )
+ {
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nX ) );
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nTemp = pLutInt[ nY ];
+
+ aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp++, nX ) );
+ aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp, nX ) );
+
+ nTemp = pLutFrac[ nY ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ if( 1 == nHeight )
+ {
+ aCol0 = pReadAcc->GetPixel( 0, nX );
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ else
+ {
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nTemp = pLutInt[ nY ];
+
+ aCol0 = pReadAcc->GetPixel( nTemp++, nX );
+ aCol1 = pReadAcc->GetPixel( nTemp, nX );
+
+ nTemp = pLutFrac[ nY ];
+
+ lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
+ lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
+ lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
+
+ aCol0.SetRed( (BYTE) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
+ aCol0.SetGreen( (BYTE) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
+ aCol0.SetBlue( (BYTE) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
+
+ pWriteAcc->SetPixel( nY, nX, aCol0 );
+ }
+ }
+ }
+ }
+
+ delete[] pLutInt;
+ delete[] pLutFrac;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ if( !bRet )
+ bRet = ImplScaleFast( rScaleX, rScaleY );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ DBG_ASSERT( !pDitherPal, "Sorry, using owner defined palettes is not yet supportet..." );
+
+ BOOL bRet = FALSE;
+
+ const Size aSizePix( GetSizePixel() );
+
+ if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
+ bRet = TRUE;
+ else if( nDitherFlags & BMP_DITHER_MATRIX )
+ bRet = ImplDitherMatrix( pDitherPal );
+ else if( nDitherFlags & BMP_DITHER_FLOYD )
+ bRet = ImplDitherFloyd( pDitherPal );
+ else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
+ bRet = ImplDitherFloyd16();
+
+ return bRet;
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BITMAP3_SEG1
+#endif
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherMatrix( const BitmapPalette* pDitherPal )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 8 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const ULONG nWidth = pReadAcc->Width();
+ const ULONG nHeight = pReadAcc->Height();
+ BitmapColor aIndex( (BYTE) 0 );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( ULONG nY = 0UL; nY < nHeight; nY++ )
+ {
+ for( ULONG nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
+ const ULONG nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
+ const ULONG nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
+ const ULONG nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
+ const ULONG nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
+
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
+ pWriteAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+ else
+ {
+ for( ULONG nY = 0UL; nY < nHeight; nY++ )
+ {
+ for( ULONG nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) );
+ const ULONG nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
+ const ULONG nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
+ const ULONG nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
+ const ULONG nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
+
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
+ pWriteAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherFloyd( const BitmapPalette* pDitherPal )
+{
+ const Size aSize( GetSizePixel() );
+ BOOL bRet = FALSE;
+
+ if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 8 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pReadAcc && pWriteAcc )
+ {
+ BitmapColor aColor;
+ long nWidth = pReadAcc->Width();
+ long nWidth1 = nWidth - 1L;
+ long nHeight = pReadAcc->Height();
+ long nX;
+ long nW = nWidth * 3L;
+ long nW2 = nW - 3L;
+ long nWLen = nW << 2;
+ long nRErr, nGErr, nBErr;
+ long nRC, nGC, nBC;
+ long nTemp;
+ long nZ;
+ long* p1 = new long[ nW ];
+ long* p2 = new long[ nW ];
+ long* p1T = p1;
+ long* p2T = p2;
+ long* pTmp;
+ BOOL bPal = pReadAcc->HasPalette();
+
+ pTmp = p2T;
+
+ if( bPal )
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nZ ) );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ else
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPixel( 0, nZ );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+
+ for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
+ {
+ pTmp = p1T;
+ p1T = p2T;
+ p2T = pTmp;
+
+ if( nY < nHeight )
+ {
+ if( bPal )
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nZ ) );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ else
+ {
+ for( nZ = 0; nZ < nWidth; nZ++ )
+ {
+ aColor = pReadAcc->GetPixel( nY, nZ );
+
+ *pTmp++ = (long) aColor.GetBlue() << 12;
+ *pTmp++ = (long) aColor.GetGreen() << 12;
+ *pTmp++ = (long) aColor.GetRed() << 12;
+ }
+ }
+ }
+
+ // erstes Pixel gesondert betrachten
+ nX = 0;
+ CALC_ERRORS;
+ CALC_TABLES7;
+ nX -= 5;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, 0, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+
+ // mittlere Pixel ueber Schleife
+ for ( long nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
+ {
+ CALC_ERRORS;
+ CALC_TABLES7;
+ nX -= 8;
+ CALC_TABLES3;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, nXAcc, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+ }
+
+ // letztes Pixel gesondert betrachten
+ CALC_ERRORS;
+ nX -= 5;
+ CALC_TABLES3;
+ CALC_TABLES5;
+ pWriteAcc->SetPixel( nYAcc, nWidth1, BitmapColor( (BYTE) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
+ }
+
+ delete[] p1;
+ delete[] p2;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplDitherFloyd16()
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc && pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pWriteAcc->Height();
+ BitmapColor aColor;
+ BitmapColor aBestCol;
+ ImpErrorQuad aErrQuad;
+ ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
+ ImpErrorQuad* pQLine1 = pErrQuad1;
+ ImpErrorQuad* pQLine2;
+ long nX, nY;
+ long nYTmp = 0L;
+ BOOL bQ1 = TRUE;
+
+ for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
+ for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+
+ for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
+ {
+ // erstes ZeilenPixel
+ aBestCol = pQLine1[ 0 ].ImplGetColor();
+ aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
+ pWriteAcc->SetPixel( nY, 0, aBestCol );
+
+ for( nX = 1L; nX < nWidth1; nX++ )
+ {
+ aColor = pQLine1[ nX ].ImplGetColor();
+ aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
+ aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
+ pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
+ pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
+ pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
+ pWriteAcc->SetPixel( nY, nX, aBestCol );
+ }
+
+ // letztes ZeilenPixel
+ aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
+ aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
+ aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
+ aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
+ pWriteAcc->SetPixel( nY, nX, aBestCol );
+
+ // Zeilenpuffer neu fuellen/kopieren
+ pQLine1 = pQLine2;
+ pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
+
+ if( nYTmp < nHeight )
+ for( nX = 0L; nX < nWidth; nX++ )
+ pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
+ }
+
+ // Zeilenpuffer zerstoeren
+ delete[] pErrQuad1;
+ delete[] pErrQuad2;
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ReduceColors( USHORT nColorCount, BmpReduce eReduce )
+{
+ BOOL bRet;
+
+ if( GetColorCount() <= (ULONG) nColorCount )
+ bRet = TRUE;
+ else if( nColorCount )
+ {
+ if( BMP_REDUCE_SIMPLE == eReduce )
+ bRet = ImplReduceSimple( nColorCount );
+ else if( BMP_REDUCE_POPULAR == eReduce )
+ bRet = ImplReducePopular( nColorCount );
+ else
+ bRet = ImplReduceMedian( nColorCount );
+ }
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReduceSimple( USHORT nColorCount )
+{
+ Bitmap aNewBmp;
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ const USHORT nColCount = Min( nColorCount, (USHORT) 256 );
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount <= 2 )
+ nBitCount = 1;
+ else if( nColCount <= 16 )
+ nBitCount = 4;
+ else
+ nBitCount = 8;
+
+ if( pRAcc )
+ {
+ Octree aOct( *pRAcc, nColCount );
+ const BitmapPalette& rPal = aOct.GetPalette();
+ BitmapWriteAccess* pWAcc;
+
+ aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
+ pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+
+ if( pRAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX =0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) ) ) );
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX =0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) ) );
+ }
+
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pRAcc );
+ }
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+struct PopularColorCount
+{
+ sal_uInt32 mnIndex;
+ sal_uInt32 mnCount;
+};
+
+// ------------------------------------------------------------------------
+
+extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
+{
+ int nRet;
+
+ if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
+ nRet = 1;
+ else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
+ nRet = 0;
+ else
+ nRet = -1;
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReducePopular( USHORT nColCount )
+{
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount > 256 )
+ nColCount = 256;
+
+ if( nColCount < 17 )
+ nBitCount = 4;
+ else
+ nBitCount = 8;
+
+ if( pRAcc )
+ {
+ const sal_uInt32 nValidBits = 4;
+ const sal_uInt32 nRightShiftBits = 8 - nValidBits;
+ const sal_uInt32 nLeftShiftBits1 = nValidBits;
+ const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
+ const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
+ const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
+ const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+ PopularColorCount* pCountTable = new PopularColorCount[ nTotalColors ];
+ long nX, nY, nR, nG, nB, nIndex;
+
+ rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
+
+ for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
+ for( nG = 0; nG < 256; nG += nColorOffset )
+ for( nB = 0; nB < 256; nB += nColorOffset )
+ pCountTable[ nIndex ].mnIndex = nIndex++;
+
+ if( pRAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
+ }
+ }
+ }
+
+ BitmapPalette aNewPal( nColCount );
+
+ qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
+
+ for( USHORT n = 0; n < nColCount; n++ )
+ {
+ const PopularColorCount& rPop = pCountTable[ n ];
+ aNewPal[ n ] = BitmapColor( (BYTE) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
+ (BYTE) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
+ (BYTE) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
+ }
+
+ Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
+ BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ BitmapColor aDstCol( (BYTE) 0 );
+ BYTE* pIndexMap = new BYTE[ nTotalColors ];
+
+ for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
+ for( nG = 0; nG < 256; nG += nColorOffset )
+ for( nB = 0; nB < 256; nB += nColorOffset )
+ pIndexMap[ nIndex++ ] = aNewPal.GetBestIndex( BitmapColor( (BYTE) nR, (BYTE) nG, (BYTE) nB ) );
+
+ if( pRAcc->HasPalette() )
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
+ pWAcc->SetPixel( nY, nX, aDstCol );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
+ ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
+ ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
+ pWAcc->SetPixel( nY, nX, aDstCol );
+ }
+ }
+ }
+
+ delete[] pIndexMap;
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ delete[] pCountTable;
+ ReleaseAccess( pRAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::ImplReduceMedian( USHORT nColCount )
+{
+ BitmapReadAccess* pRAcc = AcquireReadAccess();
+ USHORT nBitCount;
+ BOOL bRet = FALSE;
+
+ if( nColCount < 17 )
+ nBitCount = 4;
+ else if( nColCount < 257 )
+ nBitCount = 8;
+ else
+ {
+ DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
+ nBitCount = 8;
+ nColCount = 256;
+ }
+
+ if( pRAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), nBitCount );
+ BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWAcc )
+ {
+ const ULONG nSize = 32768UL * sizeof( ULONG );
+ HPULONG pColBuf = (HPULONG) SvMemAlloc( nSize );
+ const long nWidth = pWAcc->Width();
+ const long nHeight = pWAcc->Height();
+ long nIndex = 0L;
+
+ HMEMSET( (HPBYTE) pColBuf, 0, nSize );
+
+ // create Buffer
+ if( pRAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
+ pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
+ pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
+ }
+ }
+ }
+
+ // create palette via median cut
+ BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
+ ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
+ nColCount, nWidth * nHeight, nIndex );
+
+ // do mapping of colors to palette
+ InverseColorMap aMap( aPal );
+ pWAcc->SetPalette( aPal );
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pWAcc->SetPixel( nY, nX, (BYTE) aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) ) );
+
+ SvMemFree( pColBuf );
+ aNewBmp.ReleaseAccess( pWAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pRAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void Bitmap::ImplMedianCut( ULONG* pColBuf, BitmapPalette& rPal,
+ long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
+ long nColors, long nPixels, long& rIndex )
+{
+ if( !nPixels )
+ return;
+
+ BitmapColor aCol;
+ const long nRLen = nR2 - nR1;
+ const long nGLen = nG2 - nG1;
+ const long nBLen = nB2 - nB1;
+ long nR, nG, nB;
+ HPULONG pBuf = pColBuf;
+
+ if( !nRLen && !nGLen && !nBLen )
+ {
+ if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
+ {
+ aCol.SetRed( (BYTE) ( nR1 << 3 ) );
+ aCol.SetGreen( (BYTE) ( nG1 << 3 ) );
+ aCol.SetBlue( (BYTE) ( nB1 << 3 ) );
+ rPal[ (USHORT) rIndex++ ] = aCol;
+ }
+ }
+ else
+ {
+ if( 1 == nColors || 1 == nPixels )
+ {
+ long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
+
+ for( nR = nR1; nR <= nR2; nR++ )
+ {
+ for( nG = nG1; nG <= nG2; nG++ )
+ {
+ for( nB = nB1; nB <= nB2; nB++ )
+ {
+ nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
+
+ if( nPixSum )
+ {
+ nRSum += nR * nPixSum;
+ nGSum += nG * nPixSum;
+ nBSum += nB * nPixSum;
+ }
+ }
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( ( nRSum / nPixels ) << 3 ) );
+ aCol.SetGreen( (BYTE) ( ( nGSum / nPixels ) << 3 ) );
+ aCol.SetBlue( (BYTE) ( ( nBSum / nPixels ) << 3 ) );
+ rPal[ (USHORT) rIndex++ ] = aCol;
+ }
+ else
+ {
+ const long nTest = ( nPixels >> 1 );
+ long nPixOld, nPixNew = 0;
+
+ if( nBLen > nGLen && nBLen > nRLen )
+ {
+ nB = nB1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nB++, nPixOld = nPixNew;
+ for( nR = nR1; nR <= nR2; nR++ )
+ for( nG = nG1; nG <= nG2; nG++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nB < nB2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ else if( nGLen > nRLen )
+ {
+ nG = nG1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nG++, nPixOld = nPixNew;
+ for( nR = nR1; nR <= nR2; nR++ )
+ for( nB = nB1; nB <= nB2; nB++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nG < nG2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ else
+ {
+ nR = nR1 - 1;
+
+ while( nPixNew < nTest )
+ {
+ nR++, nPixOld = nPixNew;
+ for( nG = nG1; nG <= nG2; nG++ )
+ for( nB = nB1; nB <= nB2; nB++ )
+ nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
+ }
+
+ if( nR < nR2 )
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
+ ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
+ }
+ else
+ {
+ ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
+ ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Vectorize( PolyPolygon& rPolyPoly, ULONG nFlags, const Link* pProgress )
+{
+ return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Vectorize( GDIMetaFile& rMtf, BYTE cReduce, ULONG nFlags, const Link* pProgress )
+{
+ return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ BOOL bRet = FALSE;
+
+ // nothing to do => return quickly
+ if( !nLuminancePercent && !nContrastPercent &&
+ !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
+ ( fGamma == 1.0 ) && !bInvert )
+ {
+ bRet = TRUE;
+ }
+ else
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ BitmapColor aCol;
+ const long nW = pAcc->Width();
+ const long nH = pAcc->Height();
+ BYTE* cMapR = new BYTE[ 256 ];
+ BYTE* cMapG = new BYTE[ 256 ];
+ BYTE* cMapB = new BYTE[ 256 ];
+ long nX, nY;
+ double fM, fROff, fGOff, fBOff, fOff;
+
+ // calculate slope
+ if( nContrastPercent >= 0 )
+ fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
+ else
+ fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
+
+ // total offset = luminance offset + contrast offset
+ fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
+
+ // channel offset = channel offset + total offset
+ fROff = nChannelRPercent * 2.55 + fOff;
+ fGOff = nChannelGPercent * 2.55 + fOff;
+ fBOff = nChannelBPercent * 2.55 + fOff;
+
+ // calculate gamma value
+ fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
+ const BOOL bGamma = ( fGamma != 1.0 );
+
+ // create mapping table
+ for( nX = 0L; nX < 256L; nX++ )
+ {
+ cMapR[ nX ] = (BYTE) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
+ cMapG[ nX ] = (BYTE) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
+ cMapB[ nX ] = (BYTE) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
+
+ if( bGamma )
+ {
+ cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
+ cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
+ cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
+ }
+
+ if( bInvert )
+ {
+ cMapR[ nX ] = ~cMapR[ nX ];
+ cMapG[ nX ] = ~cMapG[ nX ];
+ cMapB[ nX ] = ~cMapB[ nX ];
+ }
+ }
+
+ // do modifying
+ if( pAcc->HasPalette() )
+ {
+ BitmapColor aNewCol;
+
+ for( USHORT i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+ aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
+ aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
+ aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
+ pAcc->SetPaletteColor( i, aNewCol );
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = cMapB[ *pScan ]; pScan++;
+ *pScan = cMapG[ *pScan ]; pScan++;
+ *pScan = cMapR[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = cMapR[ *pScan ]; pScan++;
+ *pScan = cMapG[ *pScan ]; pScan++;
+ *pScan = cMapB[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+ aCol.SetRed( cMapR[ aCol.GetRed() ] );
+ aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
+ aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ delete[] cMapR;
+ delete[] cMapG;
+ delete[] cMapB;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/bitmap4.cxx b/vcl/source/gdi/bitmap4.cxx
new file mode 100644
index 000000000000..d959166272f5
--- /dev/null
+++ b/vcl/source/gdi/bitmap4.cxx
@@ -0,0 +1,953 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#define _SV_BITMAP_CXX
+
+#include <vos/macros.hxx>
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define S2(a,b) { register long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
+#define MN3(a,b,c) S2(a,b); S2(a,c);
+#define MX3(a,b,c) S2(b,c); S2(a,c);
+#define MNMX3(a,b,c) MX3(a,b,c); S2(a,b);
+#define MNMX4(a,b,c,d) S2(a,b); S2(c,d); S2(a,c); S2(b,d);
+#define MNMX5(a,b,c,d,e) S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e);
+#define MNMX6(a,b,c,d,e,f) S2(a,d); S2(b,e); S2(c,f); MN3(a,b,c); MX3(d,e,f);
+
+// ----------
+// - Bitmap -
+// ----------
+
+BOOL Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ switch( eFilter )
+ {
+ case( BMP_FILTER_SMOOTH ):
+ {
+ const long pSmoothMatrix[] = { 1, 2, 1, 2, 5, 2, 1, 2, 1 };
+ bRet = ImplConvolute3( &pSmoothMatrix[ 0 ], 17, pFilterParam, pProgress );
+ }
+ break;
+
+ case( BMP_FILTER_SHARPEN ):
+ {
+ const long pSharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
+ bRet = ImplConvolute3( &pSharpenMatrix[ 0 ], 8, pFilterParam, pProgress );
+ }
+ break;
+
+ case( BMP_FILTER_REMOVENOISE ):
+ bRet = ImplMedianFilter( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SOBEL_GREY ):
+ bRet = ImplSobelGrey( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SOLARIZE ):
+ bRet = ImplSolarize( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_SEPIA ):
+ bRet = ImplSepia( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_MOSAIC ):
+ bRet = ImplMosaic( pFilterParam, pProgress );
+ break;
+
+ case( BMP_FILTER_EMBOSS_GREY ):
+ bRet = ImplEmbossGrey( pFilterParam, pProgress );
+ break;
+
+ default:
+ DBG_ERROR( "Bitmap::Convert(): Unsupported filter" );
+ break;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplConvolute3( const long* pMatrix, long nDivisor,
+ const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
+ const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
+ long* pColm = new long[ nWidth2 ];
+ long* pRows = new long[ nHeight2 ];
+ BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pRowTmp1 = pColRow1;
+ BitmapColor* pRowTmp2 = pColRow2;
+ BitmapColor* pRowTmp3 = pColRow3;
+ BitmapColor* pColor;
+ long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
+ long (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ];
+ long* pTmp;
+
+ // create LUT of products of matrix value and possible color component values
+ for( nY = 0; nY < 9; nY++ )
+ for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal )
+ pKoeff[ nY ][ nX ] = nTmp;
+
+ // create column LUT
+ for( i = 0; i < nWidth2; i++ )
+ pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pColm[ nWidth + 1 ] = pColm[ nWidth ];
+
+ // create row LUT
+ for( i = 0; i < nHeight2; i++ )
+ pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pRows[ nHeight + 1 ] = pRows[ nHeight ];
+
+ // read first three rows of bitmap color
+ for( i = 0; i < nWidth2; i++ )
+ {
+ pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
+ pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
+ pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
+ }
+
+ // do convolution
+ for( nY = 0; nY < nHeight; )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ // first row
+ nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ];
+ nSumG = pTmp[ pColor->GetGreen() ];
+ nSumB = pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // second row
+ nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // third row
+ nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ];
+ nSumG += pTmp[ pColor->GetGreen() ];
+ nSumB += pTmp[ pColor->GetBlue() ];
+
+ // calculate destination color
+ pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) MinMax( nSumR / nDivisor, 0, 255 ),
+ (BYTE) MinMax( nSumG / nDivisor, 0, 255 ),
+ (BYTE) MinMax( nSumB / nDivisor, 0, 255 ) ) );
+ }
+
+ if( ++nY < nHeight )
+ {
+ if( pRowTmp1 == pColRow1 )
+ pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
+ else if( pRowTmp1 == pColRow2 )
+ pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
+ else
+ pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
+
+ for( i = 0; i < nWidth2; i++ )
+ pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
+ }
+ }
+
+ delete[] pKoeff;
+ delete[] (BYTE*) pColRow1;
+ delete[] (BYTE*) pColRow2;
+ delete[] (BYTE*) pColRow3;
+ delete[] pColm;
+ delete[] pRows;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMedianFilter( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
+ const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
+ long* pColm = new long[ nWidth2 ];
+ long* pRows = new long[ nHeight2 ];
+ BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
+ BitmapColor* pRowTmp1 = pColRow1;
+ BitmapColor* pRowTmp2 = pColRow2;
+ BitmapColor* pRowTmp3 = pColRow3;
+ BitmapColor* pColor;
+ long nY, nX, i;
+ long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
+ long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
+ long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
+
+ // create column LUT
+ for( i = 0; i < nWidth2; i++ )
+ pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pColm[ nWidth + 1 ] = pColm[ nWidth ];
+
+ // create row LUT
+ for( i = 0; i < nHeight2; i++ )
+ pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
+
+ pRows[ nHeight + 1 ] = pRows[ nHeight ];
+
+ // read first three rows of bitmap color
+ for( i = 0; i < nWidth2; i++ )
+ {
+ pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
+ pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
+ pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
+ }
+
+ // do median filtering
+ for( nY = 0; nY < nHeight; )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nR1 = ( pColor = pRowTmp1 + nX )->GetRed(), nG1 = pColor->GetGreen(), nB1 = pColor->GetBlue();
+ nR2 = ( ++pColor )->GetRed(), nG2 = pColor->GetGreen(), nB2 = pColor->GetBlue();
+ nR3 = ( ++pColor )->GetRed(), nG3 = pColor->GetGreen(), nB3 = pColor->GetBlue();
+
+ nR4 = ( pColor = pRowTmp2 + nX )->GetRed(), nG4 = pColor->GetGreen(), nB4 = pColor->GetBlue();
+ nR5 = ( ++pColor )->GetRed(), nG5 = pColor->GetGreen(), nB5 = pColor->GetBlue();
+ nR6 = ( ++pColor )->GetRed(), nG6 = pColor->GetGreen(), nB6 = pColor->GetBlue();
+
+ nR7 = ( pColor = pRowTmp3 + nX )->GetRed(), nG7 = pColor->GetGreen(), nB7 = pColor->GetBlue();
+ nR8 = ( ++pColor )->GetRed(), nG8 = pColor->GetGreen(), nB8 = pColor->GetBlue();
+ nR9 = ( ++pColor )->GetRed(), nG9 = pColor->GetGreen(), nB9 = pColor->GetBlue();
+
+ MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 );
+ MNMX5( nR7, nR2, nR3, nR4, nR5 );
+ MNMX4( nR8, nR2, nR3, nR4 );
+ MNMX3( nR9, nR2, nR3 );
+
+ MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 );
+ MNMX5( nG7, nG2, nG3, nG4, nG5 );
+ MNMX4( nG8, nG2, nG3, nG4 );
+ MNMX3( nG9, nG2, nG3 );
+
+ MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 );
+ MNMX5( nB7, nB2, nB3, nB4, nB5 );
+ MNMX4( nB8, nB2, nB3, nB4 );
+ MNMX3( nB9, nB2, nB3 );
+
+ // set destination color
+ pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) nR2, (BYTE) nG2, (BYTE) nB2 ) );
+ }
+
+ if( ++nY < nHeight )
+ {
+ if( pRowTmp1 == pColRow1 )
+ pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
+ else if( pRowTmp1 == pColRow2 )
+ pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
+ else
+ pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
+
+ for( i = 0; i < nWidth2; i++ )
+ pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
+ }
+ }
+
+ delete[] (BYTE*) pColRow1;
+ delete[] (BYTE*) pColRow2;
+ delete[] (BYTE*) pColRow3;
+ delete[] pColm;
+ delete[] pRows;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSobelGrey( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = ImplMakeGreyscales( 256 );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aGrey( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ const long nMask111 = -1, nMask121 = 0, nMask131 = 1;
+ const long nMask211 = -2, nMask221 = 0, nMask231 = 2;
+ const long nMask311 = -1, nMask321 = 0, nMask331 = 1;
+ const long nMask112 = 1, nMask122 = 2, nMask132 = 1;
+ const long nMask212 = 0, nMask222 = 0, nMask232 = 0;
+ const long nMask312 = -1, nMask322 = -2, nMask332 = -1;
+ long nGrey11, nGrey12, nGrey13;
+ long nGrey21, nGrey22, nGrey23;
+ long nGrey31, nGrey32, nGrey33;
+ long* pHMap = new long[ nWidth + 2 ];
+ long* pVMap = new long[ nHeight + 2 ];
+ long nX, nY, nSum1, nSum2;
+
+ // fill mapping tables
+ pHMap[ 0 ] = 0;
+ for( nX = 1; nX <= nWidth; nX++ )
+ pHMap[ nX ] = nX - 1;
+ pHMap[ nWidth + 1 ] = nWidth - 1;
+
+ pVMap[ 0 ] = 0;
+ for( nY = 1; nY <= nHeight; nY++ )
+ pVMap[ nY ] = nY - 1;
+ pVMap[ nHeight + 1 ] = nHeight - 1;
+
+ for( nY = 0; nY < nHeight ; nY++ )
+ {
+ nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
+ nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
+ nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
+ nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
+ nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
+ nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
+ nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
+ nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
+ nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
+
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nSum1 = nSum2 = 0;
+
+ nSum1 += nMask111 * nGrey11;
+ nSum2 += nMask112 * nGrey11;
+
+ nSum1 += nMask121 * nGrey12;
+ nSum2 += nMask122 * nGrey12;
+
+ nSum1 += nMask131 * nGrey13;
+ nSum2 += nMask132 * nGrey13;
+
+ nSum1 += nMask211 * nGrey21;
+ nSum2 += nMask212 * nGrey21;
+
+ nSum1 += nMask221 * nGrey22;
+ nSum2 += nMask222 * nGrey22;
+
+ nSum1 += nMask231 * nGrey23;
+ nSum2 += nMask232 * nGrey23;
+
+ nSum1 += nMask311 * nGrey31;
+ nSum2 += nMask312 * nGrey31;
+
+ nSum1 += nMask321 * nGrey32;
+ nSum2 += nMask322 * nGrey32;
+
+ nSum1 += nMask331 * nGrey33;
+ nSum2 += nMask332 * nGrey33;
+
+ nSum1 = (long) sqrt( ( nSum1 * nSum1 + nSum2 * nSum2 ) );
+ aGrey.SetIndex( ~(BYTE) VOS_BOUND( nSum1, 0, 255 ) );
+ pWriteAcc->SetPixel( nY, nX, aGrey );
+
+ if( nX < ( nWidth - 1 ) )
+ {
+ const long nNextX = pHMap[ nX + 3 ];
+
+ nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
+ nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
+ nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
+ }
+ }
+ }
+
+ delete[] pHMap;
+ delete[] pVMap;
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = ImplMakeGreyscales( 256 );
+
+ if( bRet )
+ {
+ bRet = FALSE;
+
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aGrey( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ long nGrey11, nGrey12, nGrey13;
+ long nGrey21, nGrey22, nGrey23;
+ long nGrey31, nGrey32, nGrey33;
+ double fAzim = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
+ ( pFilterParam->maEmbossAngles.mnAzimuthAngle100 * 0.01 ) : 0.0 ) * F_PI180;
+ double fElev = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
+ ( pFilterParam->maEmbossAngles.mnElevationAngle100 * 0.01 ) : 90.0 ) * F_PI180;
+ long* pHMap = new long[ nWidth + 2 ];
+ long* pVMap = new long[ nHeight + 2 ];
+ long nX, nY, nNx, nNy, nDotL;
+ const long nLx = FRound( cos( fAzim ) * cos( fElev ) * 255.0 );
+ const long nLy = FRound( sin( fAzim ) * cos( fElev ) * 255.0 );
+ const long nLz = FRound( sin( fElev ) * 255.0 );
+ const long nZ2 = ( ( 6 * 255 ) / 4 ) * ( ( 6 * 255 ) / 4 );
+ const long nNzLz = ( ( 6 * 255 ) / 4 ) * nLz;
+ const BYTE cLz = (BYTE) VOS_BOUND( nLz, 0, 255 );
+
+ // fill mapping tables
+ pHMap[ 0 ] = 0;
+ for( nX = 1; nX <= nWidth; nX++ )
+ pHMap[ nX ] = nX - 1;
+ pHMap[ nWidth + 1 ] = nWidth - 1;
+
+ pVMap[ 0 ] = 0;
+ for( nY = 1; nY <= nHeight; nY++ )
+ pVMap[ nY ] = nY - 1;
+ pVMap[ nHeight + 1 ] = nHeight - 1;
+
+ for( nY = 0; nY < nHeight ; nY++ )
+ {
+ nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
+ nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
+ nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
+ nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
+ nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
+ nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
+ nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
+ nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
+ nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
+
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
+ nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
+
+ if( !nNx && !nNy )
+ aGrey.SetIndex( cLz );
+ else if( ( nDotL = nNx * nLx + nNy * nLy +nNzLz ) < 0 )
+ aGrey.SetIndex( 0 );
+ else
+ {
+ const double fGrey = nDotL / sqrt( nNx * nNx + nNy * nNy + nZ2 );
+ aGrey.SetIndex( (BYTE) VOS_BOUND( fGrey, 0, 255 ) );
+ }
+
+ pWriteAcc->SetPixel( nY, nX, aGrey );
+
+ if( nX < ( nWidth - 1 ) )
+ {
+ const long nNextX = pHMap[ nX + 3 ];
+
+ nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
+ nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
+ nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
+ }
+ }
+ }
+
+ delete[] pHMap;
+ delete[] pVMap;
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSolarize( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BOOL bRet = FALSE;
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BYTE cThreshold = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SOLARIZE ) ?
+ pFilterParam->mcSolarGreyThreshold : 128;
+
+ if( pWriteAcc->HasPalette() )
+ {
+ const BitmapPalette& rPal = pWriteAcc->GetPalette();
+
+ for( USHORT i = 0, nCount = rPal.GetEntryCount(); i < nCount; i++ )
+ {
+ if( rPal[ i ].GetLuminance() >= cThreshold )
+ {
+ BitmapColor aCol( rPal[ i ] );
+ pWriteAcc->SetPaletteColor( i, aCol.Invert() );
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol = pWriteAcc->GetPixel( nY, nX );
+
+ if( aCol.GetLuminance() >= cThreshold )
+ pWriteAcc->SetPixel( nY, nX, aCol.Invert() );
+ }
+ }
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplSepia( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ BOOL bRet = FALSE;
+
+ if( pReadAcc )
+ {
+ long nSepiaPercent = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SEPIA ) ?
+ pFilterParam->mcSolarGreyThreshold : 10;
+ const long nSepia = 10000 - 100 * VOS_BOUND( nSepiaPercent, 0, 100 );
+ BitmapPalette aSepiaPal( 256 );
+
+ DBG_ASSERT( nSepiaPercent <= 100, "Bitmap::ImplSepia(): sepia value out of range; defaulting to 100%" );
+
+ for( long i = 0; i < 256; i++ )
+ {
+ BitmapColor& rCol = aSepiaPal[ i ];
+ const BYTE cSepiaValue = (BYTE) ( ( nSepia * i ) / 10000 );
+
+ rCol.SetRed( (BYTE) i );
+ rCol.SetGreen( cSepiaValue );
+ rCol.SetBlue( cSepiaValue );
+ }
+
+ Bitmap aNewBmp( GetSizePixel(), 8, &aSepiaPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aCol( (BYTE) 0 );
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ const USHORT nPalCount = pReadAcc->GetPaletteEntryCount();
+ BYTE* pIndexMap = new BYTE[ nPalCount ];
+
+ for( USHORT i = 0; i < nPalCount; i++ )
+ pIndexMap[ i ] = pReadAcc->GetPaletteColor( i ).GetLuminance();
+
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pIndexMap[ pReadAcc->GetPixel( nY, nX ).GetIndex() ] );
+ pWriteAcc->SetPixel( nY, nX, aCol );
+ }
+
+ delete[] pIndexMap;
+ }
+ }
+ else
+ {
+ for( long nY = 0; nY < nHeight ; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aCol.SetIndex( pReadAcc->GetPixel( nY, nX ).GetLuminance() );
+ pWriteAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL Bitmap::ImplMosaic( const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ ULONG nTileWidth = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
+ pFilterParam->maMosaicTileSize.mnTileWidth : 4;
+ ULONG nTileHeight = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
+ pFilterParam->maMosaicTileSize.mnTileHeight : 4;
+ BOOL bRet = FALSE;
+
+ if( !nTileWidth )
+ nTileWidth = 1;
+
+ if( !nTileHeight )
+ nTileHeight = 1;
+
+ if( nTileWidth > 1 || nTileHeight > 1 )
+ {
+ Bitmap* pNewBmp;
+ BitmapReadAccess* pReadAcc;
+ BitmapWriteAccess* pWriteAcc;
+
+ if( GetBitCount() > 8 )
+ {
+ pNewBmp = NULL;
+ pReadAcc = pWriteAcc = AcquireWriteAccess();
+ }
+ else
+ {
+ pNewBmp = new Bitmap( GetSizePixel(), 24 );
+ pReadAcc = AcquireReadAccess();
+ pWriteAcc = pNewBmp->AcquireWriteAccess();
+ }
+
+ if( pReadAcc && pWriteAcc )
+ {
+ BitmapColor aCol;
+ long nWidth = pReadAcc->Width();
+ long nHeight = pReadAcc->Height();
+ long nX, nY, nX1, nX2, nY1, nY2, nSumR, nSumG, nSumB;
+ double fArea_1;
+
+ nY1 = 0; nY2 = nTileHeight - 1;
+
+ if( nY2 >= nHeight )
+ nY2 = nHeight - 1;
+
+ do
+ {
+ nX1 = 0; nX2 = nTileWidth - 1;
+
+ if( nX2 >= nWidth )
+ nX2 = nWidth - 1;
+
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+
+ if( !pNewBmp )
+ {
+ do
+ {
+ for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
+ {
+ for( nX = nX1; nX <= nX2; nX++ )
+ {
+ aCol = pReadAcc->GetPixel( nY, nX );
+ nSumR += aCol.GetRed();
+ nSumG += aCol.GetGreen();
+ nSumB += aCol.GetBlue();
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
+ aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
+ aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
+
+ for( nY = nY1; nY <= nY2; nY++ )
+ for( nX = nX1; nX <= nX2; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol );
+
+ nX1 += nTileWidth; nX2 += nTileWidth;
+
+ if( nX2 >= nWidth )
+ {
+ nX2 = nWidth - 1;
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+ }
+ }
+ while( nX1 < nWidth );
+ }
+ else
+ {
+ do
+ {
+ for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
+ {
+ for( nX = nX1; nX <= nX2; nX++ )
+ {
+ const BitmapColor& rCol = pReadAcc->GetPaletteColor( (BYTE) pReadAcc->GetPixel( nY, nX ) );
+ nSumR += rCol.GetRed();
+ nSumG += rCol.GetGreen();
+ nSumB += rCol.GetBlue();
+ }
+ }
+
+ aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
+ aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
+ aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
+
+ for( nY = nY1; nY <= nY2; nY++ )
+ for( nX = nX1; nX <= nX2; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aCol );
+
+ nX1 += nTileWidth; nX2 += nTileWidth;
+
+ if( nX2 >= nWidth )
+ {
+ nX2 = nWidth - 1;
+ fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
+ }
+ }
+ while( nX1 < nWidth );
+ }
+
+ nY1 += nTileHeight; nY2 += nTileHeight;
+
+ if( nY2 >= nHeight )
+ nY2 = nHeight - 1;
+ }
+ while( nY1 < nHeight );
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( pNewBmp )
+ {
+ pNewBmp->ReleaseAccess( pWriteAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = *pNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ delete pNewBmp;
+ }
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
new file mode 100644
index 000000000000..a0e388a1db0f
--- /dev/null
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -0,0 +1,690 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmapex.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BITMAPEX_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+
+// ------------
+// - BitmapEx -
+// ------------
+
+BitmapEx::BitmapEx() :
+ eTransparent( TRANSPARENT_NONE ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
+ aBitmap ( rBitmapEx.aBitmap ),
+ aMask ( rBitmapEx.aMask ),
+ aBitmapSize ( rBitmapEx.aBitmapSize ),
+ aTransparentColor ( rBitmapEx.aTransparentColor ),
+ eTransparent ( rBitmapEx.eTransparent ),
+ bAlpha ( rBitmapEx.bAlpha )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp ) :
+ aBitmap ( rBmp ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent( TRANSPARENT_NONE ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
+ aBitmap ( rBmp ),
+ aMask ( rMask ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
+ bAlpha ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
+ aBitmap ( rBmp ),
+ aMask ( rAlphaMask.ImplGetBitmap() ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ eTransparent ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
+ bAlpha ( !rAlphaMask ? FALSE : TRUE )
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
+ aBitmap ( rBmp ),
+ aBitmapSize ( aBitmap.GetSizePixel() ),
+ aTransparentColor ( rTransparentColor ),
+ eTransparent ( TRANSPARENT_BITMAP ),
+ bAlpha ( FALSE )
+{
+ aMask = aBitmap.CreateMask( aTransparentColor );
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx::~BitmapEx()
+{
+}
+
+// ------------------------------------------------------------------
+
+BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
+{
+ if( &rBitmapEx != this )
+ {
+ aBitmap = rBitmapEx.aBitmap;
+ aMask = rBitmapEx.aMask;
+ aBitmapSize = rBitmapEx.aBitmapSize;
+ aTransparentColor = rBitmapEx.aTransparentColor;
+ eTransparent = rBitmapEx.eTransparent;
+ bAlpha = rBitmapEx.bAlpha;
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
+{
+ if( eTransparent != rBitmapEx.eTransparent )
+ return FALSE;
+
+ if( aBitmap != rBitmapEx.aBitmap )
+ return FALSE;
+
+ if( aBitmapSize != rBitmapEx.aBitmapSize )
+ return FALSE;
+
+ if( eTransparent == TRANSPARENT_NONE )
+ return TRUE;
+
+ if( eTransparent == TRANSPARENT_COLOR )
+ return aTransparentColor == rBitmapEx.aTransparentColor;
+
+ return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
+{
+ return( rBmpEx.eTransparent == eTransparent &&
+ rBmpEx.bAlpha == bAlpha &&
+ rBmpEx.aBitmap.IsEqual( aBitmap ) &&
+ rBmpEx.aMask.IsEqual( aMask ) );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsEmpty() const
+{
+ return( aBitmap.IsEmpty() && aMask.IsEmpty() );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::SetEmpty()
+{
+ aBitmap.SetEmpty();
+ aMask.SetEmpty();
+ eTransparent = TRANSPARENT_NONE;
+ bAlpha = FALSE;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Clear()
+{
+ SetEmpty();
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsTransparent() const
+{
+ return( eTransparent != TRANSPARENT_NONE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::IsAlpha() const
+{
+ return( IsTransparent() && bAlpha );
+}
+
+// ------------------------------------------------------------------
+
+Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
+{
+ Bitmap aRetBmp( aBitmap );
+
+ if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
+ {
+ Bitmap aTempMask;
+
+ if( eTransparent == TRANSPARENT_COLOR )
+ aTempMask = aBitmap.CreateMask( aTransparentColor );
+ else
+ aTempMask = aMask;
+
+ if( !IsAlpha() )
+ aRetBmp.Replace( aTempMask, *pTransReplaceColor );
+ else
+ aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
+ }
+
+ return aRetBmp;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap BitmapEx::GetMask() const
+{
+ Bitmap aRet( aMask );
+
+ if( IsAlpha() )
+ aRet.ImplMakeMono( 255 );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------
+
+AlphaMask BitmapEx::GetAlpha() const
+{
+ AlphaMask aAlpha;
+
+ if( IsAlpha() )
+ aAlpha.ImplSetBitmap( aMask );
+ else
+ aAlpha = aMask;
+
+ return aAlpha;
+}
+
+// ------------------------------------------------------------------
+
+ULONG BitmapEx::GetSizeBytes() const
+{
+ ULONG nSizeBytes = aBitmap.GetSizeBytes();
+
+ if( eTransparent == TRANSPARENT_BITMAP )
+ nSizeBytes += aMask.GetSizeBytes();
+
+ return nSizeBytes;
+}
+
+// ------------------------------------------------------------------
+
+ULONG BitmapEx::GetChecksum() const
+{
+ sal_uInt32 nCrc = aBitmap.GetChecksum();
+ SVBT32 aBT32;
+
+ LongToSVBT32( (long) eTransparent, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( (long) bAlpha, aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
+ {
+ LongToSVBT32( aMask.GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+
+ return nCrc;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::SetSizePixel( const Size& rNewSize )
+{
+ Scale( rNewSize );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Invert()
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Invert();
+
+ if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
+ aTransparentColor = BitmapColor( aTransparentColor ).Invert();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Mirror( ULONG nMirrorFlags )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Mirror( nMirrorFlags );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Mirror( nMirrorFlags );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Scale( const double& rScaleX, const double& rScaleY, ULONG nScaleFlag )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL BitmapEx::Scale( const Size& rNewSize, ULONG nScaleFlag )
+{
+ BOOL bRet;
+
+ if( aBitmapSize.Width() && aBitmapSize.Height() )
+ {
+ bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
+ (double) rNewSize.Height() / aBitmapSize.Height(),
+ nScaleFlag );
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ const BOOL bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
+
+ if( bTransRotate )
+ {
+ if( eTransparent == TRANSPARENT_COLOR )
+ bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
+ else
+ {
+ bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
+
+ if( eTransparent == TRANSPARENT_NONE )
+ {
+ aMask = Bitmap( aBitmapSize, 1 );
+ aMask.Erase( COL_BLACK );
+ eTransparent = TRANSPARENT_BITMAP;
+ }
+
+ if( bRet && !!aMask )
+ aMask.Rotate( nAngle10, COL_WHITE );
+ }
+ }
+ else
+ {
+ bRet = aBitmap.Rotate( nAngle10, rFillColor );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Rotate( nAngle10, COL_WHITE );
+ }
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Crop( const Rectangle& rRectPixel )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Crop( rRectPixel );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ aMask.Crop( rRectPixel );
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Convert( BmpConversion eConversion )
+{
+ return( !!aBitmap ? aBitmap.Convert( eConversion ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::ReduceColors( USHORT nNewColorCount, BmpReduce eReduce )
+{
+ return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Expand( ULONG nDX, ULONG nDY, const Color* pInitColor, BOOL bExpandTransparent )
+{
+ BOOL bRet = FALSE;
+
+ if( !!aBitmap )
+ {
+ bRet = aBitmap.Expand( nDX, nDY, pInitColor );
+
+ if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
+ {
+ Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
+ aMask.Expand( nDX, nDY, &aColor );
+ }
+
+ aBitmapSize = aBitmap.GetSizePixel();
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Dither( ULONG nDitherFlags, const BitmapPalette* pDitherPal )
+{
+ return( !!aBitmap ? aBitmap.Dither( nDitherFlags, pDitherPal ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, ULONG nColorCount, const ULONG* pTols )
+{
+ return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (ULONG*) pTols ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
+ double fGamma, BOOL bInvert )
+{
+ return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
+ nChannelRPercent, nChannelGPercent, nChannelBPercent,
+ fGamma, bInvert ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
+{
+ return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : FALSE );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, *this );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapEx::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
+{
+ pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
+{
+ rBitmapEx.aBitmap.Write( rOStm );
+
+ rOStm << (UINT32) 0x25091962;
+ rOStm << (UINT32) 0xACB20201;
+ rOStm << (BYTE) rBitmapEx.eTransparent;
+
+ if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
+ rBitmapEx.aMask.Write( rOStm );
+ else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
+ rOStm << rBitmapEx.aTransparentColor;
+
+ return rOStm;
+}
+
+// ------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
+{
+ Bitmap aBmp;
+
+ rIStm >> aBmp;
+
+ if( !rIStm.GetError() )
+ {
+ const ULONG nStmPos = rIStm.Tell();
+ UINT32 nMagic1;
+ UINT32 nMagic2;
+
+ rIStm >> nMagic1 >> nMagic2;
+
+ if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
+ {
+ rIStm.Seek( nStmPos );
+ rBitmapEx = aBmp;
+ }
+ else
+ {
+ BYTE bTransparent;
+
+ rIStm >> bTransparent;
+
+ if( bTransparent == (BYTE) TRANSPARENT_BITMAP )
+ {
+ Bitmap aMask;
+
+ rIStm >> aMask;
+
+ if( !!aMask)
+ {
+ // do we have an alpha mask?
+ if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
+ {
+ AlphaMask aAlpha;
+
+ // create alpha mask quickly (without greyscale conversion)
+ aAlpha.ImplSetBitmap( aMask );
+ rBitmapEx = BitmapEx( aBmp, aAlpha );
+ }
+ else
+ rBitmapEx = BitmapEx( aBmp, aMask );
+ }
+ else
+ rBitmapEx = aBmp;
+ }
+ else if( bTransparent == (BYTE) TRANSPARENT_COLOR )
+ {
+ Color aTransparentColor;
+
+ rIStm >> aTransparentColor;
+ rBitmapEx = BitmapEx( aBmp, aTransparentColor );
+ }
+ else
+ rBitmapEx = aBmp;
+ }
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+void BitmapEx::ImplDrawRemote( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( !!aBitmap )
+ {
+ switch( eTransparent )
+ {
+ case( TRANSPARENT_NONE ):
+ aBitmap.ImplDrawRemote( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ break;
+
+ case( TRANSPARENT_BITMAP ):
+ {
+ if( !!aMask )
+ {
+ if( IsAlpha() )
+ aBitmap.ImplDrawRemoteAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, GetAlpha() );
+ else
+ aBitmap.ImplDrawRemoteEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, aMask );
+ }
+ else
+ aBitmap.ImplDrawRemote( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ }
+ break;
+
+ default:
+ {
+ DBG_ERROR( "BitmapEx::ImplDrawRemote???" );
+ }
+ break;
+ }
+ }
+}
+
+#endif // REMOTE
diff --git a/vcl/source/gdi/bmpacc.cxx b/vcl/source/gdi/bmpacc.cxx
new file mode 100644
index 000000000000..6fc3657c90fd
--- /dev/null
+++ b/vcl/source/gdi/bmpacc.cxx
@@ -0,0 +1,448 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC_CXX
+
+#ifdef W31
+#include <tools/svwin.h>
+#endif
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#include <string.h>
+
+// --------------------
+// - BitmapReadAccess -
+// --------------------
+
+BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, BOOL bModify ) :
+ mpBuffer ( NULL ),
+ mpScanBuf ( NULL ),
+ mbModify ( bModify ),
+ mFncGetPixel ( NULL ),
+ mFncSetPixel ( NULL )
+{
+ ImplCreate( rBitmap );
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
+ mpBuffer ( NULL ),
+ mpScanBuf ( NULL ),
+ mbModify ( FALSE ),
+ mFncGetPixel ( NULL ),
+ mFncSetPixel ( NULL )
+{
+ ImplCreate( rBitmap );
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess::~BitmapReadAccess()
+{
+ ImplDestroy();
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
+{
+ ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
+
+ BMP_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
+
+ if( pImpBmp )
+ {
+ if( mbModify && !maBitmap.ImplGetImpBitmap() )
+ {
+ rBitmap.ImplMakeUnique();
+ pImpBmp = rBitmap.ImplGetImpBitmap();
+ }
+ else
+ {
+ BMP_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
+ "Unpredictable results: bitmap is referenced more than once!" );
+ }
+
+ mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
+
+ if( !mpBuffer )
+ {
+ ImpBitmap* pNewImpBmp = new ImpBitmap;
+
+ if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
+ {
+ pImpBmp = pNewImpBmp;
+ rBitmap.ImplSetImpBitmap( pImpBmp );
+ mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
+ }
+ else
+ delete pNewImpBmp;
+ }
+
+ if( mpBuffer )
+ {
+ const long nHeight = mpBuffer->mnHeight;
+ Scanline pTmpLine = mpBuffer->mpBits;
+
+ mpScanBuf = new Scanline[ nHeight ];
+ maColorMask = mpBuffer->maColorMask;
+
+ if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ {
+ for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
+ mpScanBuf[ nY ] = pTmpLine;
+ }
+ else
+ {
+ for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
+ mpScanBuf[ nY ] = pTmpLine;
+ }
+
+ if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
+ {
+ delete[] mpScanBuf;
+ mpScanBuf = NULL;
+
+ pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
+ mpBuffer = NULL;
+ }
+ else
+ maBitmap = rBitmap;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplDestroy()
+{
+ ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
+
+ delete[] mpScanBuf;
+ mpScanBuf = NULL;
+
+ if( mpBuffer && pImpBmp )
+ {
+ pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
+ mpBuffer = NULL;
+ }
+}
+
+// ------------------------------------------------------------------
+
+BOOL BitmapReadAccess::ImplSetAccessPointers( ULONG nFormat )
+{
+ BOOL bRet = TRUE;
+
+ switch( nFormat )
+ {
+ CASE_FORMAT( _1BIT_MSB_PAL )
+ CASE_FORMAT( _1BIT_LSB_PAL )
+ CASE_FORMAT( _4BIT_MSN_PAL )
+ CASE_FORMAT( _4BIT_LSN_PAL )
+ CASE_FORMAT( _8BIT_PAL )
+ CASE_FORMAT( _8BIT_TC_MASK )
+ CASE_FORMAT( _16BIT_TC_MASK )
+ CASE_FORMAT( _24BIT_TC_BGR )
+ CASE_FORMAT( _24BIT_TC_RGB )
+ CASE_FORMAT( _24BIT_TC_MASK )
+ CASE_FORMAT( _32BIT_TC_ABGR )
+ CASE_FORMAT( _32BIT_TC_ARGB )
+ CASE_FORMAT( _32BIT_TC_BGRA )
+ CASE_FORMAT( _32BIT_TC_RGBA )
+ CASE_FORMAT( _32BIT_TC_MASK )
+
+ default:
+ bRet = FALSE;
+ break;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ImplZeroInitUnusedBits()
+{
+ const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
+
+ if( nWidth && nHeight && nScanSize && GetBuffer() )
+ {
+ DBG_ASSERT( !( nScanSize % 4 ), "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported scanline alignment" );
+
+ sal_uInt32 nBits;
+
+ switch( GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ nBits = 1;
+ break;
+
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ nBits = 4;
+ break;
+
+ case( BMP_FORMAT_8BIT_PAL ):
+ case( BMP_FORMAT_8BIT_TC_MASK ):
+ nBits = 8;
+ break;
+
+ case( BMP_FORMAT_16BIT_TC_MASK ):
+ nBits = 16;
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ case( BMP_FORMAT_24BIT_TC_MASK ):
+ nBits = 24;
+ break;
+
+ case( BMP_FORMAT_32BIT_TC_ABGR ):
+ case( BMP_FORMAT_32BIT_TC_ARGB ):
+ case( BMP_FORMAT_32BIT_TC_BGRA ):
+ case( BMP_FORMAT_32BIT_TC_RGBA ):
+ case( BMP_FORMAT_32BIT_TC_MASK ):
+ nBits = 32;
+ break;
+
+ default:
+ {
+ DBG_ERROR( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format" );
+ nBits = 0;
+ }
+ break;
+ }
+
+ if( ( nBits *= nWidth ) & 0x1f )
+ {
+ sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
+ BYTE* pLast4Bytes = (BYTE*) GetBuffer() + ( nScanSize - 4 );
+
+#ifdef __LITTLEENDIAN
+ nMask = SWAPLONG( nMask );
+#endif
+ for( long i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
+ ( *(long*) pLast4Bytes ) &= nMask;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::Flush()
+{
+ ImplDestroy();
+}
+
+// ------------------------------------------------------------------
+
+void BitmapReadAccess::ReAccess( BOOL bModify )
+{
+ const ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
+
+ BMP_ASSERT( !mpBuffer, "No ReAccess possible while bitmap is being accessed!" );
+ BMP_ASSERT( pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ), "Accessed bitmap does not exist anymore!" );
+
+ if( !mpBuffer && pImpBmp && ( pImpBmp->ImplGetRefCount() > 1UL ) )
+ {
+ mbModify = bModify;
+ ImplCreate( maBitmap );
+ }
+}
+
+// ------------------------------------------------------------------
+
+USHORT BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
+{
+ return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
+}
+
+// ---------------------
+// - BitmapWriteAccess -
+// ---------------------
+
+BitmapWriteAccess::~BitmapWriteAccess()
+{
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::ImplInitDraw()
+{
+ if( HasPalette() )
+ {
+ if( !maLineColor.IsIndex() )
+ maLineColor = (BYTE) GetBestPaletteIndex( maLineColor );
+
+ if( !maFillColor.IsIndex() )
+ maFillColor = (BYTE) GetBestPaletteIndex( maFillColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
+{
+ BMP_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
+ BMP_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
+ BMP_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
+
+ if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
+ ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
+ {
+ HMEMCPY( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
+ }
+ else
+ for( long nX = 0L, nWidth = Min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
+ SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyScanline( long nY, const Scanline aSrcScanline,
+ ULONG nSrcScanlineFormat, ULONG nSrcScanlineSize )
+{
+ const ULONG nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
+
+ BMP_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
+ BMP_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
+ ( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
+ "No copying possible between palette and non palette scanlines!" );
+
+ const ULONG nCount = Min( GetScanlineSize(), nSrcScanlineSize );
+
+ if( nCount )
+ {
+ if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
+ HMEMCPY( mpScanBuf[ nY ], aSrcScanline, nCount );
+ else
+ {
+ BMP_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK && nFormat != BMP_FORMAT_16BIT_TC_MASK &&
+ nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
+ "No support for pixel formats with color masks yet!" );
+
+ FncGetPixel pFncGetPixel;
+
+ switch( nFormat )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
+ case( BMP_FORMAT_1BIT_LSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
+ case( BMP_FORMAT_4BIT_MSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
+ case( BMP_FORMAT_4BIT_LSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
+ case( BMP_FORMAT_8BIT_PAL ): pFncGetPixel = GetPixelFor_8BIT_PAL; break;
+ case( BMP_FORMAT_8BIT_TC_MASK ): pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
+ case( BMP_FORMAT_16BIT_TC_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_MASK; break;
+ case( BMP_FORMAT_24BIT_TC_BGR ): pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
+ case( BMP_FORMAT_24BIT_TC_RGB ): pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
+ case( BMP_FORMAT_24BIT_TC_MASK ): pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
+ case( BMP_FORMAT_32BIT_TC_ABGR ): pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
+ case( BMP_FORMAT_32BIT_TC_ARGB ): pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
+ case( BMP_FORMAT_32BIT_TC_BGRA ): pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
+ case( BMP_FORMAT_32BIT_TC_RGBA ): pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
+ case( BMP_FORMAT_32BIT_TC_MASK ): pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
+
+ default:
+ pFncGetPixel = NULL;
+ break;
+ }
+
+ if( pFncGetPixel )
+ {
+ const ColorMask aDummyMask;
+
+ for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
+ SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
+ }
+ }
+ }
+}
+
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
+{
+ BMP_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
+
+ if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
+ ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
+ {
+ const long nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() );
+ const ULONG nCount = nHeight * mpBuffer->mnScanlineSize;
+
+ HMEMCPY( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
+ }
+ else
+ for( long nY = 0L, nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
+ CopyScanline( nY, rReadAcc );
+}
diff --git a/vcl/source/gdi/bmpacc2.cxx b/vcl/source/gdi/bmpacc2.cxx
new file mode 100644
index 000000000000..a07f58815a88
--- /dev/null
+++ b/vcl/source/gdi/bmpacc2.cxx
@@ -0,0 +1,353 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC2_CXX
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+
+// ----------------
+// - BitmapAccess -
+// ----------------
+
+IMPL_FORMAT_GETPIXEL( _1BIT_MSB_PAL )
+{
+ return( pScanline[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _1BIT_MSB_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 3 ];
+
+ ( rBitmapColor.GetIndex() & 1 ) ? ( rByte |= 1 << ( 7 - ( nX & 7 ) ) ) :
+ ( rByte &= ~( 1 << ( 7 - ( nX & 7 ) ) ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _1BIT_LSB_PAL )
+{
+ return( pScanline[ nX >> 3 ] & ( 1 << ( nX & 7 ) ) ? 1 : 0 );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _1BIT_LSB_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 3 ];
+
+ ( rBitmapColor.GetIndex() & 1 ) ? ( rByte |= 1 << ( nX & 7 ) ) :
+ ( rByte &= ~( 1 << ( nX & 7 ) ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _4BIT_MSN_PAL )
+{
+ return( ( pScanline[ nX >> 1 ] >> ( nX & 1 ? 0 : 4 ) ) & 0x0f );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _4BIT_MSN_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 1 ];
+
+ ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( rBitmapColor.GetIndex() & 0x0f ) ) :
+ ( rByte &= 0x0f, rByte |= ( rBitmapColor.GetIndex() << 4 ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _4BIT_LSN_PAL )
+{
+ return( ( pScanline[ nX >> 1 ] >> ( nX & 1 ? 4 : 0 ) ) & 0x0f );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _4BIT_LSN_PAL )
+{
+ BYTE& rByte = pScanline[ nX >> 1 ];
+
+ ( nX & 1 ) ? ( rByte &= 0x0f, rByte |= ( rBitmapColor.GetIndex() << 4 ) ) :
+ ( rByte &= 0xf0, rByte |= ( rBitmapColor.GetIndex() & 0x0f ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _8BIT_PAL )
+{
+ return pScanline[ nX ];
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _8BIT_PAL )
+{
+ pScanline[ nX ] = rBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _8BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor8Bit( aColor, pScanline + nX );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _8BIT_TC_MASK )
+{
+ rMask.SetColorFor8Bit( rBitmapColor, pScanline + nX );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _16BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor16Bit( aColor, pScanline + ( nX << 1UL ) );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _16BIT_TC_MASK )
+{
+ rMask.SetColorFor16Bit( rBitmapColor, pScanline + ( nX << 1UL ) );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_BGR )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + nX * 3 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_BGR )
+{
+ *( pScanline = pScanline + nX * 3 )++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_RGB )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + nX * 3 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_RGB )
+{
+ *( pScanline = pScanline + nX * 3 )++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _24BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor24Bit( aColor, pScanline + nX * 3L );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _24BIT_TC_MASK )
+{
+ rMask.SetColorFor24Bit( rBitmapColor, pScanline + nX * 3L );
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_ABGR )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + ( nX << 2 ) + 1 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_ABGR )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = 0;
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_ARGB )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + ( nX << 2 ) + 1 )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_ARGB )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = 0;
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_BGRA )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetBlue( *( pScanline = pScanline + ( nX << 2 ) )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetRed( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_BGRA )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline = 0;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_RGBA )
+{
+ BitmapColor aBitmapColor;
+
+ aBitmapColor.SetRed( *( pScanline = pScanline + ( nX << 2 ) )++ );
+ aBitmapColor.SetGreen( *pScanline++ );
+ aBitmapColor.SetBlue( *pScanline );
+
+ return aBitmapColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_RGBA )
+{
+ *( pScanline = pScanline + ( nX << 2 ) )++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline = 0;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_GETPIXEL( _32BIT_TC_MASK )
+{
+ BitmapColor aColor;
+ rMask.GetColorFor32Bit( aColor, pScanline + ( nX << 2UL ) );
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+IMPL_FORMAT_SETPIXEL( _32BIT_TC_MASK )
+{
+ rMask.SetColorFor32Bit( rBitmapColor, pScanline + ( nX << 2UL ) );
+}
diff --git a/vcl/source/gdi/bmpacc3.cxx b/vcl/source/gdi/bmpacc3.cxx
new file mode 100644
index 000000000000..c26de8c7ecfa
--- /dev/null
+++ b/vcl/source/gdi/bmpacc3.cxx
@@ -0,0 +1,351 @@
+/*************************************************************************
+ *
+ * $RCSfile: bmpacc3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BMPACC_CXX
+
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+
+// ---------------------
+// - BitmapWriteAccess -
+// ---------------------
+
+void BitmapWriteAccess::Erase( const Color& rColor )
+{
+ const BitmapColor aOldFillColor( maFillColor );
+ const Point aPoint;
+ const Rectangle aRect( aPoint, maBitmap.GetSizePixel() );
+
+ SetFillColor( rColor );
+ FillRect( aRect );
+ maFillColor = aOldFillColor;
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawLine( const Point& rStart, const Point& rEnd )
+{
+ long nX;
+ long nY;
+
+ ImplInitDraw();
+
+ if ( rStart.X() == rEnd.X() )
+ {
+ // vertikale Line
+ const long nEndY = rEnd.Y();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if ( nEndY > nY )
+ {
+ for (; nY <= nEndY; nY++ )
+ SetPixel( nY, nX, maLineColor );
+ }
+ else
+ {
+ for (; nY >= nEndY; nY-- )
+ SetPixel( nY, nX, maLineColor );
+ }
+ }
+ else if ( rStart.Y() == rEnd.Y() )
+ {
+ // horizontale Line
+ const long nEndX = rEnd.X();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if ( nEndX > nX )
+ {
+ for (; nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maLineColor );
+ }
+ else
+ {
+ for (; nX >= nEndX; nX-- )
+ SetPixel( nY, nX, maLineColor );
+ }
+ }
+ else
+ {
+ const long nDX = labs( rEnd.X() - rStart.X() );
+ const long nDY = labs( rEnd.Y() - rStart.Y() );
+ long nX1;
+ long nY1;
+ long nX2;
+ long nY2;
+
+ if ( nDX >= nDY )
+ {
+ if ( rStart.X() < rEnd.X() )
+ {
+ nX1 = rStart.X();
+ nY1 = rStart.Y();
+ nX2 = rEnd.X();
+ nY2 = rEnd.Y();
+ }
+ else
+ {
+ nX1 = rEnd.X();
+ nY1 = rEnd.Y();
+ nX2 = rStart.X();
+ nY2 = rStart.Y();
+ }
+
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+ BOOL bPos = nY1 < nY2;
+
+ for ( nX = nX1, nY = nY1; nX <= nX2; nX++ )
+ {
+ SetPixel( nY, nX, maLineColor );
+
+ if ( nD < 0 )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+
+ if ( bPos )
+ nY++;
+ else
+ nY--;
+ }
+ }
+ }
+ else
+ {
+ if ( rStart.Y() < rEnd.Y() )
+ {
+ nX1 = rStart.X();
+ nY1 = rStart.Y();
+ nX2 = rEnd.X();
+ nY2 = rEnd.Y();
+ }
+ else
+ {
+ nX1 = rEnd.X();
+ nY1 = rEnd.Y();
+ nX2 = rStart.X();
+ nY2 = rStart.Y();
+ }
+
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+ BOOL bPos = nX1 < nX2;
+
+ for ( nX = nX1, nY = nY1; nY <= nY2; nY++ )
+ {
+ SetPixel( nY, nX, maLineColor );
+
+ if ( nD < 0 )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+
+ if ( bPos )
+ nX++;
+ else
+ nX--;
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawRect( const Rectangle& rRect )
+{
+ ImplInitDraw();
+ FillRect( rRect );
+ DrawLine( rRect.TopLeft(), rRect.TopRight() );
+ DrawLine( rRect.TopRight(), rRect.BottomRight() );
+ DrawLine( rRect.BottomRight(), rRect.BottomLeft() );
+ DrawLine( rRect.BottomLeft(), rRect.TopLeft() );
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::FillRect( const Rectangle& rRect )
+{
+ Point aPoint;
+ Rectangle aRect( aPoint, maBitmap.GetSizePixel() );
+
+ aRect.Intersection( rRect );
+
+ if( !aRect.IsEmpty() )
+ {
+ const long nStartX = rRect.TopLeft().X();
+ const long nStartY = rRect.TopLeft().Y();
+ const long nEndX = rRect.BottomRight().X();
+ const long nEndY = rRect.BottomRight().Y();
+
+ ImplInitDraw();
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolygon( const Polygon& rPoly )
+{
+ const USHORT nSize = rPoly.GetSize();
+
+ if( nSize )
+ {
+ Region aRegion( rPoly );
+ Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+
+ ImplInitDraw();
+
+ while( aRegion.GetNextEnumRect( aRegHandle, aRect ) )
+ for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+
+ aRegion.EndEnumRects( aRegHandle );
+ }
+
+ if( maLineColor != maFillColor )
+ {
+ for( USHORT i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void BitmapWriteAccess::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ const USHORT nCount = rPolyPoly.Count();
+
+ if( nCount )
+ {
+ Region aRegion( rPolyPoly );
+ Rectangle aRect;
+
+ aRegion.Intersect( Rectangle( Point(), Size( Width(), Height() ) ) );
+
+ if( !aRegion.IsEmpty() )
+ {
+ RegionHandle aRegHandle( aRegion.BeginEnumRects() );
+
+ ImplInitDraw();
+
+ while( aRegion.GetNextEnumRect( aRegHandle, aRect ) )
+ for( long nY = aRect.Top(), nEndY = aRect.Bottom(); nY <= nEndY; nY++ )
+ for( long nX = aRect.Left(), nEndX = aRect.Right(); nX <= nEndX; nX++ )
+ SetPixel( nY, nX, maFillColor );
+
+ aRegion.EndEnumRects( aRegHandle );
+ }
+
+ if( maLineColor != maFillColor )
+ {
+ for( USHORT n = 0; n < nCount; )
+ {
+ const Polygon& rPoly = rPolyPoly[ n++ ];
+ const USHORT nSize = rPoly.GetSize();
+
+ if( nSize )
+ {
+ for( USHORT i = 0, nSize1 = nSize - 1; i < nSize1; i++ )
+ DrawLine( rPoly[ i ], rPoly[ i + 1 ] );
+
+ if( rPoly[ nSize - 1 ] != rPoly[ 0 ] )
+ DrawLine( rPoly[ nSize - 1 ], rPoly[ 0 ] );
+ }
+ }
+ }
+ }
+}
diff --git a/vcl/source/gdi/cvtgrf.cxx b/vcl/source/gdi/cvtgrf.cxx
new file mode 100644
index 000000000000..1005cf3396d5
--- /dev/null
+++ b/vcl/source/gdi/cvtgrf.cxx
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * $RCSfile: cvtgrf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CVTGRF_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+
+// --------------
+// - Callback -
+// --------------
+
+#ifndef REMOTE_APPSERVER
+
+ULONG ImplFilterCallback( void* pInst,
+ ULONG nInFormat, void* pInBuffer, ULONG nInBufSize,
+ ULONG nOutFormat, void** ppOutBuffer )
+{
+ return( ( (GraphicConverter*) pInst )->ImplConvert( nInFormat,
+ pInBuffer, nInBufSize,
+ ppOutBuffer, nOutFormat ) );
+}
+
+#endif
+
+// --------------------
+// - GraphicConverter -
+// --------------------
+
+GraphicConverter::GraphicConverter() :
+ mpConvertData( NULL )
+{
+#ifndef REMOTE_APPSERVER
+ SetFilterCallback( ImplFilterCallback, this );
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GraphicConverter::~GraphicConverter()
+{
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::ImplConvert( ULONG nInFormat, void* pInBuffer, ULONG nInBufSize,
+ void** ppOutBuffer, ULONG nOutFormat )
+{
+ ULONG nRetBufSize = 0UL;
+
+ if( ( nInFormat != nOutFormat ) && pInBuffer )
+ {
+ if( ( nInFormat == CVT_SVM ) || ( nInFormat == CVT_BMP ) )
+ {
+ SvMemoryStream aIStm;
+ Graphic aGraphic;
+
+ aIStm.SetBuffer( (char*) pInBuffer, nInBufSize, FALSE, nInBufSize );
+ aIStm >> aGraphic;
+
+ if( !aIStm.GetError() )
+ {
+ SvMemoryStream aOStm( 64535, 64535 );
+
+ mpConvertData = new ConvertData( aGraphic, aOStm, nOutFormat );
+
+ if( maFilterHdl.IsSet() && maFilterHdl.Call( mpConvertData ) )
+ {
+ nRetBufSize = aOStm.Seek( STREAM_SEEK_TO_END );
+ *ppOutBuffer = (void*) aOStm.GetData();
+ aOStm.ObjectOwnsMemory( FALSE );
+ }
+
+ delete mpConvertData;
+ mpConvertData = NULL;
+ }
+ }
+ else if( ( nOutFormat == CVT_SVM ) || ( nOutFormat == CVT_BMP ) )
+ {
+ SvMemoryStream aIStm;
+
+ aIStm.SetBuffer( (char*) pInBuffer, nInBufSize, FALSE, nInBufSize );
+ mpConvertData = new ConvertData( Graphic(), aIStm, nInFormat );
+
+ if( maFilterHdl.IsSet() && maFilterHdl.Call( mpConvertData ) )
+ {
+ SvMemoryStream aOStm( 645535, 64535 );
+ Graphic& rGraphic = mpConvertData->maGraphic;
+
+ if( ( rGraphic.GetType() == GRAPHIC_BITMAP ) && ( CVT_SVM == nOutFormat ) )
+ {
+ GDIMetaFile aMtf;
+
+ aMtf.SetPrefSize( rGraphic.GetPrefSize() );
+ aMtf.SetPrefMapMode( rGraphic.GetPrefMapMode() );
+ aMtf.AddAction( new MetaBmpExScaleAction( Point(), aMtf.GetPrefSize(), rGraphic.GetBitmapEx() ) );
+ rGraphic = aMtf;
+ }
+ else if( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && ( CVT_BMP == nOutFormat ) )
+ rGraphic = rGraphic.GetBitmapEx();
+
+ aOStm << rGraphic;
+
+ if( !aOStm.GetError() )
+ {
+ nRetBufSize = aOStm.Seek( STREAM_SEEK_TO_END );
+ *ppOutBuffer = (void*) aOStm.GetData();
+ aOStm.ObjectOwnsMemory( FALSE );
+ }
+ }
+
+ delete mpConvertData;
+ mpConvertData = NULL;
+ }
+ }
+
+ return nRetBufSize;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::Import( SvStream& rIStm, Graphic& rGraphic, ULONG nFormat )
+{
+ GraphicConverter* pCvt = ImplGetSVData()->maGDIData.mpGrfConverter;
+ ULONG nRet = ERRCODE_IO_GENERAL;
+
+ if( pCvt && pCvt->GetFilterHdl().IsSet() )
+ {
+ ConvertData aData( rGraphic, rIStm, nFormat );
+
+ if( pCvt->GetFilterHdl().Call( &aData ) )
+ {
+ rGraphic = aData.maGraphic;
+ nRet = ERRCODE_NONE;
+ }
+ else if( rIStm.GetError() )
+ nRet = rIStm.GetError();
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GraphicConverter::Export( SvStream& rOStm, const Graphic& rGraphic, ULONG nFormat )
+{
+ GraphicConverter* pCvt = ImplGetSVData()->maGDIData.mpGrfConverter;
+ ULONG nRet = ERRCODE_IO_GENERAL;
+
+ if( pCvt && pCvt->GetFilterHdl().IsSet() )
+ {
+ ConvertData aData( rGraphic, rOStm, nFormat );
+
+ if( pCvt->GetFilterHdl().Call( &aData ) )
+ nRet = ERRCODE_NONE;
+ else if( rOStm.GetError() )
+ nRet = rOStm.GetError();
+ }
+
+ return nRet;
+}
diff --git a/vcl/source/gdi/cvtsvm.cxx b/vcl/source/gdi/cvtsvm.cxx
new file mode 100644
index 000000000000..f2ac9be53d5d
--- /dev/null
+++ b/vcl/source/gdi/cvtsvm.cxx
@@ -0,0 +1,2106 @@
+/*************************************************************************
+ *
+ * $RCSfile: cvtsvm.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_CVTSVM_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#include <string.h>
+
+#ifndef _STACK_HXX //autogen
+#include <tools/stack.hxx>
+#endif
+#ifndef _DEBUG_HXX //autogen
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#include <cvtsvm.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define CVTSVM_WRITE_SUBACTIONCOUNT 1
+
+// -----------
+// - Inlines -
+// -----------
+
+void ImplReadRect( SvStream& rIStm, Rectangle& rRect )
+{
+ Point aTL;
+ Point aBR;
+
+ rIStm >> aTL;
+ rIStm >> aBR;
+
+ rRect = Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteRect( SvStream& rOStm, const Rectangle& rRect )
+{
+ rOStm << rRect.TopLeft();
+ rOStm << rRect.BottomRight();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadPoly( SvStream& rIStm, Polygon& rPoly )
+{
+ INT32 nSize;
+
+ rIStm >> nSize;
+ rPoly = Polygon( (USHORT) nSize );
+
+ for( USHORT i = 0; i < (USHORT) nSize; i++ )
+ rIStm >> rPoly[ i ];
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePoly( SvStream& rOStm, const Polygon& rPoly )
+{
+ INT32 nSize = rPoly.GetSize();
+
+ rOStm << nSize;
+
+ for( INT32 i = 0; i < nSize; i++ )
+ rOStm << rPoly[ (USHORT) i ];
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadPolyPoly( SvStream& rIStm, PolyPolygon& rPolyPoly )
+{
+ Polygon aPoly;
+ INT32 nPolyCount;
+
+ rIStm >> nPolyCount;
+
+ for( USHORT i = 0; i < (USHORT) nPolyCount; i++ )
+ {
+ ImplReadPoly( rIStm, aPoly );
+ rPolyPoly.Insert( aPoly );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePolyPolyAction( SvStream& rOStm, const PolyPolygon& rPolyPoly )
+{
+ const USHORT nPoly = rPolyPoly.Count();
+ USHORT nPoints = 0;
+ USHORT n;
+
+ for( n = 0; n < nPoly; n++ )
+ nPoints += rPolyPoly[ n ].GetSize();
+
+ rOStm << (INT16) GDI_POLYPOLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoly << 2 ) + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoly;
+
+ for( n = 0; n < nPoly; n++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ n ];
+ const USHORT nSize = rPoly.GetSize();
+
+ rOStm << (INT32) nSize;
+
+ for( USHORT j = 0; j < nSize; j++ )
+ rOStm << rPoly[ j ];
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadColor( SvStream& rIStm, Color& rColor )
+{
+ INT16 nVal;
+
+ rIStm >> nVal; rColor.SetRed( (USHORT) nVal >> 8 );
+ rIStm >> nVal; rColor.SetGreen( (USHORT) nVal >> 8 );
+ rIStm >> nVal; rColor.SetBlue( (USHORT) nVal >> 8 );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteColor( SvStream& rOStm, const Color& rColor )
+{
+ INT16 nVal;
+
+ nVal = ( (INT16) rColor.GetRed() << 8 ) | rColor.GetRed();
+ rOStm << nVal;
+
+ nVal = ( (INT16) rColor.GetGreen() << 8 ) | rColor.GetGreen();
+ rOStm << nVal;
+
+ nVal = ( (INT16) rColor.GetBlue() << 8 ) | rColor.GetBlue();
+ rOStm << nVal;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadMapMode( SvStream& rIStm, MapMode& rMapMode )
+{
+ Point aOrg;
+ INT32 nXNum;
+ INT32 nXDenom;
+ INT32 nYNum;
+ INT32 nYDenom;
+ INT16 nUnit;
+
+ rIStm >> nUnit >> aOrg >> nXNum >> nXDenom >> nYNum >> nYDenom;
+ rMapMode = MapMode( (MapUnit) nUnit, aOrg, Fraction( nXNum, nXDenom ), Fraction( nYNum, nYDenom ) );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteMapMode( SvStream& rOStm, const MapMode& rMapMode )
+{
+ rOStm << (INT16) rMapMode.GetMapUnit();
+ rOStm << rMapMode.GetOrigin();
+ rOStm << (INT32) rMapMode.GetScaleX().GetNumerator();
+ rOStm << (INT32) rMapMode.GetScaleX().GetDenominator();
+ rOStm << (INT32) rMapMode.GetScaleY().GetNumerator();
+ rOStm << (INT32) rMapMode.GetScaleY().GetDenominator();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePushAction( SvStream& rOStm )
+{
+ rOStm << (INT16) GDI_PUSH_ACTION;
+ rOStm << (INT32) 4;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWritePopAction( SvStream& rOStm )
+{
+ rOStm << (INT16) GDI_POP_ACTION;
+ rOStm << (INT32) 4;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteLineColor( SvStream& rOStm, const Color& rColor, INT16 nStyle, INT32 nWidth = 0L )
+{
+ if( rColor.GetTransparency() > 127 )
+ nStyle = 0;
+
+ rOStm << (INT16) GDI_PEN_ACTION;
+ rOStm << (INT32) 16;
+ ImplWriteColor( rOStm, rColor );
+ rOStm << nWidth;
+ rOStm << nStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteFillColor( SvStream& rOStm, const Color& rColor, INT16 nStyle )
+{
+ rOStm << (INT16) GDI_FILLBRUSH_ACTION;
+ rOStm << (INT32) 20;
+ ImplWriteColor( rOStm, rColor );
+
+ if( rColor.GetTransparency() > 127 )
+ nStyle = 0;
+
+ if( nStyle > 1 )
+ {
+ ImplWriteColor( rOStm, COL_WHITE );
+ rOStm << nStyle;
+ rOStm << (INT16) 1;
+ }
+ else
+ {
+ ImplWriteColor( rOStm, COL_BLACK );
+ rOStm << nStyle;
+ rOStm << (INT16) 0;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteFont( SvStream& rOStm, const Font& rFont,
+ rtl_TextEncoding& rActualCharSet )
+{
+ char aName[32];
+ short nWeight;
+
+ ByteString aByteName( rFont.GetName(), rOStm.GetStreamCharSet() );
+ strncpy( aName, aByteName.GetBuffer(), 32 );
+
+ switch ( rFont.GetWeight() )
+ {
+ case WEIGHT_THIN:
+ case WEIGHT_ULTRALIGHT:
+ case WEIGHT_LIGHT:
+ nWeight = 1;
+ break;
+
+ case WEIGHT_NORMAL:
+ case WEIGHT_MEDIUM:
+ nWeight = 2;
+ break;
+
+ case WEIGHT_BOLD:
+ case WEIGHT_ULTRABOLD:
+ case WEIGHT_BLACK:
+ nWeight = 3;
+ break;
+
+ default:
+ nWeight = 0;
+ break;
+ }
+
+ rOStm << (INT16) GDI_FONT_ACTION;
+ rOStm << (INT32) 78;
+
+ rActualCharSet = GetStoreCharSet( rFont.GetCharSet(), rOStm.GetVersion() );
+ ImplWriteColor( rOStm, rFont.GetColor() );
+ ImplWriteColor( rOStm, rFont.GetFillColor() );
+ rOStm.Write( aName, 32 );
+ rOStm << rFont.GetSize();
+ rOStm << (INT16) 0; // no character orientation anymore
+ rOStm << (INT16) rFont.GetOrientation();
+ rOStm << (INT16) rActualCharSet;
+ rOStm << (INT16) rFont.GetFamily();
+ rOStm << (INT16) rFont.GetPitch();
+ rOStm << (INT16) rFont.GetAlign();
+ rOStm << (INT16) nWeight;
+ rOStm << (INT16) rFont.GetUnderline();
+ rOStm << (INT16) rFont.GetStrikeout();
+ rOStm << (BOOL) ( rFont.GetItalic() != ITALIC_NONE );
+ rOStm << rFont.IsOutline();
+ rOStm << rFont.IsShadow();
+ rOStm << rFont.IsTransparent();
+ if ( rActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ rActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplWriteRasterOpAction( SvStream& rOStm, INT16 nRasterOp )
+{
+ rOStm << (INT16) GDI_RASTEROP_ACTION << (INT32) 6 << nRasterOp;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplSkipActions( SvStream& rIStm, ULONG nSkipCount )
+{
+ INT32 nActionSize;
+ INT16 nType;
+
+ for( ULONG i = 0UL; i < nSkipCount; i++ )
+ {
+ rIStm >> nType >> nActionSize;
+ rIStm.SeekRel( nActionSize - 4L );
+ }
+}
+
+// ----------------
+// - SVMConverter -
+// ----------------
+
+SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf, ULONG nConvertMode )
+{
+ if( !rStm.GetError() )
+ {
+ if( CONVERT_FROM_SVM1 == nConvertMode )
+ ImplConvertFromSVM1( rStm, rMtf );
+ else if( CONVERT_TO_SVM1 == nConvertMode )
+ ImplConvertToSVM1( rStm, rMtf );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
+{
+ LineInfo aLineInfo( LINE_NONE, 0 );
+ Stack aLIStack;
+ ULONG nPos = rIStm.Tell();
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding();
+ BOOL bFatLine = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ char aCode[ 5 ];
+ MapMode aMapMode;
+ Size aPrefSz;
+ INT32 nActions;
+ INT16 nSize;
+ INT16 nVersion;
+
+ // Header lesen
+ rIStm.Read( (char*) &aCode, sizeof( aCode ) ); // Kennung
+ rIStm >> nSize; // Size
+ rIStm >> nVersion; // Version
+ rIStm >> aPrefSz; // PrefSize
+ ImplReadMapMode( rIStm, aMapMode ); // MapMode
+ rIStm >> nActions; // Action count
+
+ // Header-Kennung und Versionsnummer pruefen
+ if( ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 ) || ( nVersion != 200 ) )
+ {
+ rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ rIStm.SetNumberFormatInt( nOldFormat );
+ rIStm.Seek( nPos );
+ }
+ else
+ {
+ Polygon aPoly;
+ Rectangle aRect;
+ Point aPt, aPt1;
+ Size aSz;
+ Color aColor;
+ INT32 nTmp, nTmp1, nActionSize;
+ INT16 nType;
+
+ rMtf.SetPrefSize( aPrefSz );
+ rMtf.SetPrefMapMode( aMapMode );
+
+ for( INT32 i = 0L; i < nActions; i++ )
+ {
+ rIStm >> nType;
+ rIStm >> nActionSize;
+
+ DBG_ASSERT( ( nType <= 33 ) || ( nType >= 1024 ), "Unknown GDIMetaAction while converting!" );
+
+ switch( nType )
+ {
+ case( GDI_PIXEL_ACTION ):
+ {
+ rIStm >> aPt;
+ ImplReadColor( rIStm, aColor );
+ rMtf.AddAction( new MetaPixelAction( aPt, aColor ) );
+ }
+ break;
+
+ case( GDI_POINT_ACTION ):
+ {
+ rIStm >> aPt;
+ rMtf.AddAction( new MetaPointAction( aPt ) );
+ }
+ break;
+
+ case( GDI_LINE_ACTION ):
+ {
+ rIStm >> aPt >> aPt1;
+ rMtf.AddAction( new MetaLineAction( aPt, aPt1, aLineInfo ) );
+ }
+ break;
+
+ case( GDI_RECT_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> nTmp >> nTmp1;
+
+ if( nTmp || nTmp1 )
+ rMtf.AddAction( new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
+ else
+ {
+ rMtf.AddAction( new MetaRectAction( aRect ) );
+
+ if( bFatLine )
+ rMtf.AddAction( new MetaPolyLineAction( aRect, aLineInfo ) );
+ }
+ }
+ break;
+
+ case( GDI_ELLIPSE_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaEllipseAction( aRect ) );
+ }
+ break;
+
+ case( GDI_ARC_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> aPt >> aPt1;
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect, aPt, aPt1, POLY_ARC );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaArcAction( aRect, aPt, aPt1 ) );
+ }
+ break;
+
+ case( GDI_PIE_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rIStm >> aPt >> aPt1;
+
+ if( bFatLine )
+ {
+ const Polygon aPoly( aRect, aPt, aPt1, POLY_PIE );
+
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPieAction( aRect, aPt, aPt1 ) );
+ }
+ break;
+
+ case( GDI_INVERTRECT_ACTION ):
+ case( GDI_HIGHLIGHTRECT_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rMtf.AddAction( new MetaPushAction( PUSH_RASTEROP ) );
+ rMtf.AddAction( new MetaRasterOpAction( ROP_INVERT ) );
+ rMtf.AddAction( new MetaRectAction( aRect ) );
+ rMtf.AddAction( new MetaPopAction() );
+ }
+ break;
+
+ case( GDI_POLYLINE_ACTION ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+
+ if( bFatLine )
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ else
+ rMtf.AddAction( new MetaPolyLineAction( aPoly ) );
+ }
+ break;
+
+ case( GDI_POLYGON_ACTION ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+
+ if( bFatLine )
+ {
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+ rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPolygonAction( aPoly ) );
+ }
+ break;
+
+ case( GDI_POLYPOLYGON_ACTION ):
+ {
+ PolyPolygon aPolyPoly;
+
+ ImplReadPolyPoly( rIStm, aPolyPoly );
+
+ if( bFatLine )
+ {
+ rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, FALSE ) );
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ rMtf.AddAction( new MetaPopAction() );
+
+ for( USHORT nPoly = 0, nCount = aPolyPoly.Count(); nPoly < nCount; nPoly++ )
+ rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
+ }
+ else
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ }
+ break;
+
+ case( GDI_FONT_ACTION ):
+ {
+ Font aFont;
+ char aName[ 32 ];
+ INT32 nWidth, nHeight;
+ INT16 nCharSet, nFamily, nPitch, nAlign, nWeight, nUnderline, nStrikeout;
+ INT16 nCharOrient, nLineOrient;
+ BOOL bItalic, bOutline, bShadow, bTransparent;
+
+ ImplReadColor( rIStm, aColor ); aFont.SetColor( aColor );
+ ImplReadColor( rIStm, aColor ); aFont.SetFillColor( aColor );
+ rIStm.Read( aName, 32 );
+ aFont.SetName( UniString( aName, rIStm.GetStreamCharSet() ) );
+ rIStm >> nWidth >> nHeight;
+ rIStm >> nCharOrient >> nLineOrient;
+ rIStm >> nCharSet >> nFamily >> nPitch >> nAlign >> nWeight >> nUnderline >> nStrikeout;
+ rIStm >> bItalic >> bOutline >> bShadow >> bTransparent;
+
+ aFont.SetSize( Size( nWidth, nHeight ) );
+ aFont.SetCharSet( (CharSet) nCharSet );
+ aFont.SetFamily( (FontFamily) nFamily );
+ aFont.SetPitch( (FontPitch) nPitch );
+ aFont.SetAlign( (FontAlign) nAlign );
+ aFont.SetWeight( ( nWeight == 1 ) ? WEIGHT_LIGHT : ( nWeight == 2 ) ? WEIGHT_NORMAL :
+ ( nWeight == 3 ) ? WEIGHT_BOLD : WEIGHT_DONTKNOW );
+ aFont.SetUnderline( (FontUnderline) nUnderline );
+ aFont.SetStrikeout( (FontStrikeout) nStrikeout );
+ aFont.SetItalic( bItalic ? ITALIC_NORMAL : ITALIC_NONE );
+ aFont.SetOutline( bOutline );
+ aFont.SetShadow( bShadow );
+ aFont.SetOrientation( nLineOrient );
+ aFont.SetTransparent( bTransparent );
+
+ eActualCharSet = aFont.GetCharSet();
+ if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eActualCharSet = gsl_getSystemTextEncoding();
+ rMtf.AddAction( new MetaFontAction( aFont ) );
+ }
+ break;
+
+ case( GDI_TEXT_ACTION ):
+ {
+ ByteString aByteStr;
+ INT32 nIndex, nLen;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+ rMtf.AddAction( new MetaTextAction( aPt, aStr, (USHORT) nIndex, (USHORT) nLen ) );
+ }
+ break;
+
+ case( GDI_TEXTARRAY_ACTION ):
+ {
+ ByteString aByteStr;
+ long* pDXAry = NULL;
+ INT32 nIndex, nLen, nAryLen;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp >> nAryLen;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+
+ if( nAryLen > 0L )
+ {
+ pDXAry = new long[ nAryLen ];
+
+ for( long i = 0L; i < nAryLen; i++ )
+ rIStm >> nTmp, pDXAry[ i ] = nTmp;
+ }
+
+ rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, pDXAry, (USHORT) nIndex, (USHORT) nLen ) );
+
+ if( pDXAry )
+ delete[] pDXAry;
+ }
+ break;
+
+ case( GDI_STRETCHTEXT_ACTION ):
+ {
+ ByteString aByteStr;
+ INT32 nIndex, nLen, nWidth;
+
+ rIStm >> aPt >> nIndex >> nLen >> nTmp >> nWidth;
+ rIStm.Read( aByteStr.AllocBuffer( (USHORT)nTmp ), nTmp + 1 );
+ UniString aStr( aByteStr, eActualCharSet );
+ rMtf.AddAction( new MetaStretchTextAction( aPt, nWidth, aStr, (USHORT) nIndex, (USHORT) nLen ) );
+ }
+ break;
+
+ case( GDI_BITMAP_ACTION ):
+ {
+ Bitmap aBmp;
+
+ rIStm >> aPt >> aBmp;
+ rMtf.AddAction( new MetaBmpAction( aPt, aBmp ) );
+ }
+ break;
+
+ case( GDI_BITMAPSCALE_ACTION ):
+ {
+ Bitmap aBmp;
+
+ rIStm >> aPt >> aSz >> aBmp;
+ rMtf.AddAction( new MetaBmpScaleAction( aPt, aSz, aBmp ) );
+ }
+ break;
+
+ case( GDI_BITMAPSCALEPART_ACTION ):
+ {
+ Bitmap aBmp;
+ Size aSz2;
+
+ rIStm >> aPt >> aSz >> aPt1 >> aSz2 >> aBmp;
+ rMtf.AddAction( new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
+ }
+ break;
+
+ case( GDI_PEN_ACTION ):
+ {
+ INT32 nPenWidth;
+ INT16 nPenStyle;
+
+ ImplReadColor( rIStm, aColor );
+ rIStm >> nPenWidth >> nPenStyle;
+
+ aLineInfo.SetStyle( nPenStyle ? LINE_SOLID : LINE_NONE );
+ aLineInfo.SetWidth( nPenWidth );
+ bFatLine = nPenStyle && !aLineInfo.IsDefault();
+
+ rMtf.AddAction( new MetaLineColorAction( aColor, nPenStyle != 0 ) );
+ }
+ break;
+
+ case( GDI_FILLBRUSH_ACTION ):
+ {
+ INT16 nBrushStyle;
+
+ ImplReadColor( rIStm, aColor );
+ rIStm.SeekRel( 6L );
+ rIStm >> nBrushStyle;
+ rMtf.AddAction( new MetaFillColorAction( aColor, nBrushStyle != 0 ) );
+ rIStm.SeekRel( 2L );
+ }
+ break;
+
+ case( GDI_MAPMODE_ACTION ):
+ {
+ ImplReadMapMode( rIStm, aMapMode );
+ rMtf.AddAction( new MetaMapModeAction( aMapMode ) );
+ }
+ break;
+
+ case( GDI_CLIPREGION_ACTION ):
+ {
+ Region aRegion;
+ INT16 nRegType;
+ INT16 bIntersect;
+ BOOL bClip = FALSE;
+
+ rIStm >> nRegType >> bIntersect;
+ ImplReadRect( rIStm, aRect );
+
+ switch( nRegType )
+ {
+ case( 0 ):
+ break;
+
+ case( 1 ):
+ {
+ Rectangle aRegRect;
+
+ ImplReadRect( rIStm, aRegRect );
+ aRegion = Region( aRegRect );
+ bClip = TRUE;
+ }
+ break;
+
+ case( 2 ):
+ {
+ ImplReadPoly( rIStm, aPoly );
+ aRegion = Region( aPoly );
+ bClip = TRUE;
+ }
+ break;
+
+ case( 3 ):
+ {
+ PolyPolygon aPolyPoly;
+ INT32 nPolyCount;
+
+ rIStm >> nPolyCount;
+
+ for( USHORT i = 0; i < (USHORT) nPolyCount; i++ )
+ {
+ ImplReadPoly( rIStm, aPoly );
+ aPolyPoly.Insert( aPoly );
+ }
+
+ aRegion = Region( aPolyPoly );
+ bClip = TRUE;
+ }
+ break;
+ }
+
+ if( bIntersect )
+ aRegion.Intersect( aRect );
+
+ rMtf.AddAction( new MetaClipRegionAction( aRegion, bClip ) );
+ }
+ break;
+
+ case( GDI_MOVECLIPREGION_ACTION ):
+ {
+ rIStm >> nTmp >> nTmp1;
+ rMtf.AddAction( new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
+ }
+ break;
+
+ case( GDI_ISECTCLIPREGION_ACTION ):
+ {
+ ImplReadRect( rIStm, aRect );
+ rMtf.AddAction( new MetaISectRectClipRegionAction( aRect ) );
+ }
+ break;
+
+ case( GDI_RASTEROP_ACTION ):
+ {
+ RasterOp eRasterOp;
+ INT16 nRasterOp;
+
+ rIStm >> nRasterOp;
+
+ switch( nRasterOp )
+ {
+ case( 1 ):
+ eRasterOp = ROP_INVERT;
+ break;
+
+ case( 4 ):
+ case( 5 ):
+ eRasterOp = ROP_XOR;
+ break;
+
+ default:
+ eRasterOp = ROP_OVERPAINT;
+ break;
+ }
+
+ rMtf.AddAction( new MetaRasterOpAction( eRasterOp ) );
+ }
+ break;
+
+ case( GDI_PUSH_ACTION ):
+ {
+ aLIStack.Push( new LineInfo( aLineInfo ) );
+ rMtf.AddAction( new MetaPushAction( PUSH_ALL ) );
+ }
+ break;
+
+ case( GDI_POP_ACTION ):
+ {
+
+ LineInfo* pLineInfo = (LineInfo*) aLIStack.Pop();
+
+ // restore line info
+ if( pLineInfo )
+ {
+ aLineInfo = *pLineInfo;
+ delete pLineInfo;
+ bFatLine = ( LINE_NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
+ }
+
+ rMtf.AddAction( new MetaPopAction() );
+ }
+ break;
+
+ case( GDI_GRADIENT_ACTION ):
+ {
+ Color aStartCol;
+ Color aEndCol;
+ INT16 nStyle;
+ INT16 nAngle;
+ INT16 nBorder;
+ INT16 nOfsX;
+ INT16 nOfsY;
+ INT16 nIntensityStart;
+ INT16 nIntensityEnd;
+
+ ImplReadRect( rIStm, aRect );
+ rIStm >> nStyle;
+ ImplReadColor( rIStm, aStartCol );
+ ImplReadColor( rIStm, aEndCol );
+ rIStm >> nAngle >> nBorder >> nOfsX >> nOfsY >> nIntensityStart >> nIntensityEnd;
+
+ Gradient aGrad( (GradientStyle) nStyle, aStartCol, aEndCol );
+
+ aGrad.SetAngle( nAngle );
+ aGrad.SetBorder( nBorder );
+ aGrad.SetOfsX( nOfsX );
+ aGrad.SetOfsY( nOfsY );
+ aGrad.SetStartIntensity( nIntensityStart );
+ aGrad.SetEndIntensity( nIntensityEnd );
+ rMtf.AddAction( new MetaGradientAction( aRect, aGrad ) );
+ }
+ break;
+
+ case( GDI_TRANSPARENT_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ INT32 nFollowingActionCount;
+ INT16 nTrans;
+
+ rIStm >> aPolyPoly >> nTrans >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTransparentAction( aPolyPoly, nTrans ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_FLOATTRANSPARENT_COMMENT ):
+ {
+ GDIMetaFile aMtf;
+ Point aPos;
+ Size aSize;
+ Gradient aGradient;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aMtf >> aPos >> aSize >> aGradient >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaFloatTransparentAction( aMtf, aPos, aSize, aGradient ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_HATCH_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ Hatch aHatch;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aPolyPoly >> aHatch >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaHatchAction( aPolyPoly, aHatch ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_REFPOINT_COMMENT ):
+ {
+ Point aRefPoint;
+ BOOL bSet;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aRefPoint >> bSet >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaRefPointAction( aRefPoint, bSet ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_TEXTLINECOLOR_COMMENT ):
+ {
+ Color aColor;
+ BOOL bSet;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aColor >> bSet >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTextLineColorAction( aColor, bSet ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_TEXTLINE_COMMENT ):
+ {
+ Point aStartPt;
+ long nWidth;
+ ULONG nStrikeout;
+ ULONG nUnderline;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aStartPt >> nWidth >> nStrikeout >> nUnderline >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaTextLineAction( aStartPt, nWidth,
+ (FontStrikeout) nStrikeout,
+ (FontUnderline) nUnderline ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_GRADIENTEX_COMMENT ):
+ {
+ PolyPolygon aPolyPoly;
+ Gradient aGradient;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aPolyPoly >> aGradient >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaGradientExAction( aPolyPoly, aGradient ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ case( GDI_COMMENT_COMMENT ):
+ {
+ ByteString aComment;
+ long nValue;
+ ULONG nDataSize;
+ BYTE* pData;
+ INT32 nFollowingActionCount;
+
+ rIStm >> aComment >> nValue >> nDataSize;
+
+ if( nDataSize )
+ {
+ pData = new BYTE[ nDataSize ];
+ rIStm.Read( pData, nDataSize );
+ }
+ else
+ pData = NULL;
+
+ rIStm >> nFollowingActionCount;
+ ImplSkipActions( rIStm, nFollowingActionCount );
+ rMtf.AddAction( new MetaCommentAction( aComment, nValue, pData, nDataSize ) );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ i += nFollowingActionCount;
+#endif
+ }
+ break;
+
+ default:
+ rIStm.SeekRel( nActionSize - 4L );
+ break;
+ }
+ }
+
+ // cleanup push-pop stack if neccessary
+ for( void* pLineInfo = aLIStack.Pop(); pLineInfo; pLineInfo = aLIStack.Pop() )
+ delete (LineInfo*) pLineInfo;
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+}
+
+// ------------------------------------------------------------------------
+
+void SVMConverter::ImplConvertToSVM1( SvStream& rOStm, GDIMetaFile& rMtf )
+{
+ ULONG nPos;
+ ULONG nCountPos;
+ Font aSaveFont;
+ const ULONG nActionCount = rMtf.GetActionCount();
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding();
+ const Size aPrefSize( rMtf.GetPrefSize() );
+ BOOL bRop_0_1 = FALSE;
+ VirtualDevice aSaveVDev;
+ Color aLineCol( COL_BLACK );
+ Stack aLineColStack;
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ //MagicCode schreiben
+ rOStm << "SVGDI"; // Kennung
+ nPos = rOStm.Tell();
+ rOStm << (INT16) 42; // HeaderSize
+ rOStm << (INT16) 200; // VERSION
+ rOStm << (INT32) aPrefSize.Width();
+ rOStm << (INT32) aPrefSize.Height();
+ ImplWriteMapMode( rOStm, rMtf.GetPrefMapMode() );
+
+ // ActionCount wird spaeter geschrieben
+ nCountPos = rOStm.Tell();
+ rOStm.SeekRel( 4L );
+
+ const INT32 nActCount = ImplWriteActions( rOStm, rMtf, aSaveVDev, bRop_0_1, aLineCol, aLineColStack, eActualCharSet );
+ const ULONG nActPos = rOStm.Tell();
+
+ rOStm.Seek( nCountPos );
+ rOStm << nActCount;
+ rOStm.Seek( nActPos );
+ rOStm.SetNumberFormatInt( nOldFormat );
+
+ // cleanup push-pop stack if neccessary
+ for( void* pCol = aLineColStack.Pop(); pCol; pCol = aLineColStack.Pop() )
+ delete (Color*) pCol;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
+ VirtualDevice& rSaveVDev, BOOL& rRop_0_1,
+ Color& rLineCol, Stack& rLineColStack,
+ rtl_TextEncoding& rActualCharSet )
+{
+ ULONG nCount = 0;
+ for( ULONG i = 0, nActionCount = rMtf.GetActionCount(); i < nActionCount; i++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( i );
+
+ switch( pAction->GetType() )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ MetaPixelAction* pAct = (MetaPixelAction*) pAction;
+
+ rOStm << (INT16) GDI_PIXEL_ACTION;
+ rOStm << (INT32) 18;
+ rOStm << pAct->GetPoint();
+ ImplWriteColor( rOStm, pAct->GetColor() );
+ nCount++;
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ MetaPointAction* pAct = (MetaPointAction*) pAction;
+
+ rOStm << (INT16) GDI_POINT_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ MetaLineAction* pAct = (MetaLineAction*) pAction;
+ const LineInfo& rInfo = pAct->GetLineInfo();
+ const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+
+ if( bFatLine )
+ {
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+ }
+
+ rOStm << (INT16) GDI_LINE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+
+ if( bFatLine )
+ {
+ ImplWritePopAction( rOStm );
+ nCount += 3;
+ }
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ MetaRectAction* pAct = (MetaRectAction*) pAction;
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) 0;
+ rOStm << (INT32) 0;
+ nCount++;
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) pAct->GetHorzRound();
+ rOStm << (INT32) pAct->GetVertRound();
+ nCount++;
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
+
+ rOStm << (INT16) GDI_ELLIPSE_ACTION;
+ rOStm << (INT32) 20;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ nCount++;
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ MetaArcAction* pAct = (MetaArcAction*) pAction;
+
+ rOStm << (INT16) GDI_ARC_ACTION;
+ rOStm << (INT32) 36;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ MetaPieAction* pAct = (MetaPieAction*) pAction;
+
+ rOStm << (INT16) GDI_PIE_ACTION;
+ rOStm << (INT32) 36;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << pAct->GetStartPoint();
+ rOStm << pAct->GetEndPoint();
+ nCount++;
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ MetaChordAction* pAct = (MetaChordAction*) pAction;
+ Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(),
+ pAct->GetEndPoint(), POLY_CHORD );
+ const USHORT nPoints = aChordPoly.GetSize();
+
+ rOStm << (INT16) GDI_POLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << aChordPoly[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
+ const Polygon& rPoly = pAct->GetPolygon();
+ const LineInfo& rInfo = pAct->GetLineInfo();
+ const USHORT nPoints = rPoly.GetSize();
+ const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+
+ if( bFatLine )
+ {
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+ }
+
+ rOStm << (INT16) GDI_POLYLINE_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << rPoly[ n ];
+
+ nCount++;
+
+ if( bFatLine )
+ {
+ ImplWritePopAction( rOStm );
+ nCount += 3;
+ }
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
+ const Polygon& rPoly = pAct->GetPolygon();
+ const USHORT nPoints = rPoly.GetSize();
+
+ rOStm << (INT16) GDI_POLYGON_ACTION;
+ rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
+ rOStm << (INT32) nPoints;
+
+ for( USHORT n = 0; n < nPoints; n++ )
+ rOStm << rPoly[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
+ ImplWritePolyPolyAction( rOStm, pAct->GetPolyPolygon() );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ MetaTextAction* pAct = (MetaTextAction*) pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ const ULONG nStrLen = aText.Len();
+
+ rOStm << (INT16) GDI_TEXT_ACTION;
+ rOStm << (INT32) ( 24 + ( nStrLen + 1 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) pAct->GetIndex();
+ rOStm << (INT32) pAct->GetLen();
+ rOStm << (INT32) nStrLen;
+ rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ MetaTextArrayAction* pAct = (MetaTextArrayAction*)pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ ULONG nAryLen;
+ ULONG nLen = pAct->GetLen();
+ const ULONG nTextLen = aText.Len();
+ long* pDXArray = pAct->GetDXArray();
+
+ if( ( nLen + pAct->GetIndex() ) > nTextLen )
+ {
+ if( pAct->GetIndex() <= nTextLen )
+ nLen = nTextLen - pAct->GetIndex();
+ else
+ nLen = 0UL;
+ }
+
+ if( !pDXArray || !nLen )
+ nAryLen = 0;
+ else
+ nAryLen = nLen - 1;
+
+ rOStm << (INT16) GDI_TEXTARRAY_ACTION;
+ rOStm << (INT32) ( 28 + ( nLen + 1 ) + ( nAryLen * 4 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) 0;
+ rOStm << (INT32) nLen;
+ rOStm << (INT32) nLen;
+ rOStm << (INT32) nAryLen;
+ rOStm.Write( aText.GetBuffer()+pAct->GetIndex(), nLen + 1 );
+
+ for( ULONG n = 0UL ; n < nAryLen; n++ )
+ rOStm << (INT32) pDXArray[ n ];
+
+ nCount++;
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ {
+ MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
+ ByteString aText( pAct->GetText(), rActualCharSet );
+ const ULONG nStrLen = aText.Len();
+
+ rOStm << (INT16) GDI_STRETCHTEXT_ACTION;
+ rOStm << (INT32) ( 28 + ( nStrLen + 1 ) );
+ rOStm << pAct->GetPoint();
+ rOStm << (INT32) pAct->GetIndex();
+ rOStm << (INT32) pAct->GetLen();
+ rOStm << (INT32) nStrLen;
+ rOStm << (INT32) pAct->GetWidth();
+ rOStm.Write( aText.GetBuffer(), nStrLen + 1 );
+ nCount++;
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pAct = (MetaBmpAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAP_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAPSCALE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetSize();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+
+ rOStm << (INT16) GDI_BITMAPSCALEPART_ACTION;
+ rOStm << (INT32) 36;
+ rOStm << pAct->GetDestPoint();
+ rOStm << pAct->GetDestSize();
+ rOStm << pAct->GetSrcPoint();
+ rOStm << pAct->GetSrcSize();
+ rOStm << pAct->GetBitmap();
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAP_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << pAct->GetPoint();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAPSCALE_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetPoint();
+ rOStm << pAct->GetSize();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+ const Bitmap aBmp( Graphic( pAct->GetBitmapEx() ).GetBitmap() );
+
+ rOStm << (INT16) GDI_BITMAPSCALEPART_ACTION;
+ rOStm << (INT32) 36;
+ rOStm << pAct->GetDestPoint();
+ rOStm << pAct->GetDestSize();
+ rOStm << pAct->GetSrcPoint();
+ rOStm << pAct->GetSrcSize();
+ rOStm << aBmp;
+ nCount++;
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ MetaGradientAction* pAct = (MetaGradientAction*) pAction;
+ const Gradient& rGrad = pAct->GetGradient();
+
+ rOStm << (INT16) GDI_GRADIENT_ACTION;
+ rOStm << (INT32) 46;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT16) rGrad.GetStyle();
+ ImplWriteColor( rOStm, rGrad.GetStartColor() );
+ ImplWriteColor( rOStm, rGrad.GetEndColor() );
+ rOStm << (INT16) rGrad.GetAngle();
+ rOStm << (INT16) rGrad.GetBorder();
+ rOStm << (INT16) rGrad.GetOfsX();
+ rOStm << (INT16) rGrad.GetOfsY();
+ rOStm << (INT16) rGrad.GetStartIntensity();
+ rOStm << (INT16) rGrad.GetEndIntensity();
+ nCount++;
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ const MetaGradientExAction* pA = (MetaGradientExAction*) pAction;
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_GRADIENTEX_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << pA->GetPolyPolygon() << pA->GetGradient();
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
+ const Color& rColor = pAct->GetWallpaper().GetColor();
+
+ ImplWritePushAction( rOStm );
+ ImplWriteLineColor( rOStm, rColor, 1 );
+ ImplWriteFillColor( rOStm, rColor, 1 );
+
+ rOStm << (INT16) GDI_RECT_ACTION;
+ rOStm << (INT32) 28;
+ ImplWriteRect( rOStm, pAct->GetRect() );
+ rOStm << (INT32) 0;
+ rOStm << (INT32) 0;
+
+ ImplWritePopAction( rOStm );
+ nCount += 5;
+ }
+ break;
+
+ case( META_CLIPREGION_ACTION ):
+ {
+ MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
+ const Region& rRegion = pAct->GetRegion();
+ Rectangle aClipRect;
+
+ rOStm << (INT16) GDI_CLIPREGION_ACTION;
+ rOStm << (INT32) 24;
+
+ if( pAct->IsClipping() )
+ {
+ aClipRect = rRegion.GetBoundRect();
+ rOStm << (INT16) 1;
+ }
+ else
+ rOStm << (INT16) 0;
+
+ rOStm << (INT16) 0;
+ ImplWriteRect( rOStm, aClipRect );
+
+ if( pAct->IsClipping() )
+ ImplWriteRect( rOStm, aClipRect );
+
+ nCount++;
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
+
+ rOStm << (INT16) GDI_ISECTCLIPREGION_ACTION;
+ rOStm << (INT32) 20;
+ rOStm << pAct->GetRect();
+ nCount++;
+ }
+ break;
+
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
+
+ rOStm << (INT16) GDI_MOVECLIPREGION_ACTION;
+ rOStm << (INT32) 12;
+ rOStm << (INT32) pAct->GetHorzMove();
+ rOStm << (INT32) pAct->GetVertMove();
+ nCount++;
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
+ ImplWriteLineColor( rOStm, rLineCol = pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
+ nCount++;
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
+ ImplWriteFillColor( rOStm, pAct->GetColor(), pAct->IsSetting() ? 1 : 0 );
+ nCount++;
+ }
+ break;
+
+ case( META_FONT_ACTION ):
+ {
+ rSaveVDev.SetFont( ( (MetaFontAction*) pAction )->GetFont() );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ {
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ aSaveFont.SetColor( ( (MetaTextColorAction*) pAction )->GetColor() );
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTFILLCOLOR_ACTION ):
+ {
+ MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ if( pAct->IsSetting() )
+ aSaveFont.SetFillColor( pAct->GetColor() );
+ else
+ aSaveFont.SetFillColor( Color( COL_TRANSPARENT ) );
+
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTALIGN_ACTION ):
+ {
+ Font aSaveFont( rSaveVDev.GetFont() );
+
+ aSaveFont.SetAlign( ( (MetaTextAlignAction*) pAction )->GetTextAlign() );
+ rSaveVDev.SetFont( aSaveFont );
+ ImplWriteFont( rOStm, rSaveVDev.GetFont(), rActualCharSet );
+ nCount++;
+ }
+ break;
+
+ case( META_MAPMODE_ACTION ):
+ {
+ MetaMapModeAction* pAct = (MetaMapModeAction*) pAction;
+
+ rOStm << (INT16) GDI_MAPMODE_ACTION;
+ rOStm << (INT32) 30;
+ ImplWriteMapMode( rOStm, pAct->GetMapMode() );
+ nCount++;
+ }
+ break;
+
+ case( META_PUSH_ACTION ):
+ {
+ ImplWritePushAction( rOStm );
+ rLineColStack.Push( new Color( rLineCol ) );
+ rSaveVDev.Push();
+ nCount++;
+ }
+ break;
+
+ case( META_POP_ACTION ):
+ {
+ Color* pCol = (Color*) rLineColStack.Pop();
+
+ if( pCol )
+ {
+ rLineCol = *pCol;
+ delete pCol;
+ }
+
+ ImplWritePopAction( rOStm );
+ rSaveVDev.Pop();
+ nCount++;
+ }
+ break;
+
+ case( META_RASTEROP_ACTION ):
+ {
+ MetaRasterOpAction* pAct = (MetaRasterOpAction*) pAction;
+
+ if( ( pAct->GetRasterOp() != ROP_0 ) && ( pAct->GetRasterOp() != ROP_1 ) )
+ {
+ INT16 nRasterOp;
+
+ // Falls vorher ROP_0/1 gesetzt war, alten
+ // Zustand durch Pop erst wieder herstellen
+ if( rRop_0_1 )
+ {
+ ImplWritePopAction( rOStm );
+ rSaveVDev.Pop();
+ rRop_0_1 = FALSE;
+ nCount++;
+ }
+
+ switch( pAct->GetRasterOp() )
+ {
+ case( ROP_OVERPAINT ) : nRasterOp = 0; break;
+ case( ROP_XOR ) : nRasterOp = 4; break;
+ case( ROP_INVERT ): nRasterOp = 1; break;
+ default: nRasterOp = 0; break;
+ }
+
+ ImplWriteRasterOpAction( rOStm, nRasterOp );
+ nCount++;
+ }
+ else
+ {
+ ImplWritePushAction( rOStm );
+ rSaveVDev.Push();
+
+ if( pAct->GetRasterOp() == ROP_0 )
+ {
+ ImplWriteLineColor( rOStm, COL_BLACK, 1 );
+ ImplWriteFillColor( rOStm, COL_BLACK, 1 );
+ }
+ else
+ {
+ ImplWriteLineColor( rOStm, COL_WHITE, 1 );
+ ImplWriteFillColor( rOStm, COL_WHITE, 1 );
+ }
+
+ ImplWriteRasterOpAction( rOStm, 0 );
+ rRop_0_1 = TRUE;
+ nCount += 4;
+ }
+ }
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ {
+ const PolyPolygon& rPolyPoly = ( (MetaTransparentAction*) pAction )->GetPolyPolygon();
+ const INT16 nTrans = ( (MetaTransparentAction*) pAction )->GetTransparence();
+ const INT16 nBrushStyle = ( nTrans < 38 ) ? 8 : ( nTrans < 63 ) ? 9 : 10;
+ ULONG nOldPos, nNewPos;
+
+ // write transparence comment
+ rOStm << (INT16) GDI_TRANSPARENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rPolyPoly;
+ rOStm << nTrans;
+ rOStm << (INT32) 15; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ {
+ // write actions for transparence
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteRasterOpAction( rOStm, 4 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteRasterOpAction( rOStm, 2 );
+ ImplWriteFillColor( rOStm, COL_BLACK, nBrushStyle );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+ ImplWriteRasterOpAction( rOStm, 4 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+ ImplWritePushAction( rOStm );
+ {
+ ImplWriteFillColor( rOStm, Color(), 0 );
+ ImplWritePolyPolyAction( rOStm, rPolyPoly );
+ }
+ ImplWritePopAction( rOStm );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += 15;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ const MetaFloatTransparentAction* pA = (MetaFloatTransparentAction*) pAction;
+ const GDIMetaFile& rTransMtf = pA->GetGDIMetaFile();
+ const Point& rPos = pA->GetPoint();
+ const Size& rSize = pA->GetSize();
+ const Gradient& rGradient = pA->GetGradient();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_FLOATTRANSPARENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rTransMtf << rPos << rSize << rGradient;
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos + 4 );
+ rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
+
+ {
+ // write actions for float transparence
+ ULONG nAddCount;
+ GDIMetaFile aMtf( rTransMtf );
+ const Size aSrcSize( rTransMtf.GetPrefSize() );
+ Point aSrcPt( rTransMtf.GetPrefMapMode().GetOrigin() );
+ const double fScaleX = aSrcSize.Width() ? (double) rSize.Width() / aSrcSize.Width() : 1.0;
+ const double fScaleY = aSrcSize.Height() ? (double) rSize.Height() / aSrcSize.Height() : 1.0;
+ long nMoveX, nMoveY;
+
+ if( fScaleX != 1.0 || fScaleY != 1.0 )
+ {
+ aMtf.Scale( fScaleX, fScaleY );
+ aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
+ }
+
+ nMoveX = rPos.X() - aSrcPt.X(), nMoveY = rPos.Y() - aSrcPt.Y();
+
+ if( nMoveX || nMoveY )
+ aMtf.Move( nMoveX, nMoveY );
+
+ nAddCount = ImplWriteActions( rOStm, aMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) nAddCount;
+ rOStm.Seek( nNewPos );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += nAddCount;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_HATCH_ACTION ):
+ {
+ const MetaHatchAction* pA = (MetaHatchAction*) pAction;
+ const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+ const Hatch& rHatch = pA->GetHatch();
+ ULONG nOldPos, nNewPos, nAddCount;
+
+ // write hatch comment
+ rOStm << (INT16) GDI_HATCH_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write comment data
+ rOStm << rPolyPoly;
+ rOStm << rHatch;
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos + 4 );
+ rOStm.Seek( ( nOldPos = nNewPos ) + 4 );
+
+ {
+ // write actions for hatch
+ VirtualDevice aVDev;
+ GDIMetaFile aTmpMtf;
+
+ aVDev.AddHatchActions( rPolyPoly, rHatch, aTmpMtf );
+ nAddCount = ImplWriteActions( rOStm, aTmpMtf, rSaveVDev, rRop_0_1, rLineCol, rLineColStack, rActualCharSet );
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) nAddCount;
+ rOStm.Seek( nNewPos );
+
+#ifdef CVTSVM_WRITE_SUBACTIONCOUNT
+ nCount += nAddCount;
+#endif
+ }
+
+ nCount++;
+ }
+ break;
+
+ case( META_REFPOINT_ACTION ):
+ {
+ const MetaRefPointAction* pA = (MetaRefPointAction*) pAction;
+ const Point& rRefPoint = pA->GetRefPoint();
+ const BOOL bSet = pA->IsSetting();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_REFPOINT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rRefPoint << bSet;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTLINECOLOR_ACTION ):
+ {
+ const MetaTextLineColorAction* pA = (MetaTextLineColorAction*) pAction;
+ const Color& rColor = pA->GetColor();
+ const BOOL bSet = pA->IsSetting();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_TEXTLINECOLOR_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rColor << bSet;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_TEXTLINE_ACTION ):
+ {
+ const MetaTextLineAction* pA = (MetaTextLineAction*) pAction;
+ const Point& rStartPt = pA->GetStartPoint();
+ const long nWidth = pA->GetWidth();
+ const FontStrikeout eStrikeout = pA->GetStrikeout();
+ const FontUnderline eUnderline = pA->GetUnderline();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_TEXTLINE_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << rStartPt << nWidth << (ULONG) eStrikeout << (ULONG) eUnderline;
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ break;
+
+ case( META_COMMENT_ACTION ):
+ {
+ const MetaCommentAction* pA = (MetaCommentAction*) pAction;
+ const ULONG nDataSize = pA->GetDataSize();
+ ULONG nOldPos, nNewPos;
+
+ // write RefPoint comment
+ rOStm << (INT16) GDI_COMMENT_COMMENT;
+
+ // we'll write the ActionSize later
+ nOldPos = rOStm.Tell();
+ rOStm.SeekRel( 4 );
+
+ // write data
+ rOStm << pA->GetComment() << pA->GetValue() << nDataSize;
+
+ if( nDataSize )
+ rOStm.Write( pA->GetData(), nDataSize );
+
+ rOStm << (INT32) 0; // number of actions that follow this comment
+
+ // calculate and write ActionSize of comment
+ nNewPos = rOStm.Tell();
+ rOStm.Seek( nOldPos );
+ rOStm << (INT32) ( nNewPos - nOldPos );
+ rOStm.Seek( nNewPos );
+
+ nCount++;
+ }
+ break;
+
+#ifdef DBG_UTIL
+ default:
+ {
+ ByteString aStr( "Missing implementation for Action#: " );
+ aStr += ByteString::CreateFromInt32( pAction->GetType() );
+ aStr += '!';
+ DBG_ERROR( aStr.GetBuffer() );
+ }
+ break;
+#endif
+
+/*
+ case( META_TEXTRECT_ACTION ):
+ {
+ MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pAct = (MetaMaskAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+
+/*
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ {
+ MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
+
+ rOStm << ;
+ rOStm << ;
+
+ nCount++;
+ }
+ break;
+*/
+ }
+ }
+
+ return nCount;
+}
diff --git a/vcl/source/gdi/font.cxx b/vcl/source/gdi/font.cxx
new file mode 100644
index 000000000000..657d42a21546
--- /dev/null
+++ b/vcl/source/gdi/font.cxx
@@ -0,0 +1,625 @@
+/*************************************************************************
+ *
+ * $RCSfile: font.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_FONT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_FONT_HXX
+#include <font.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Font );
+
+// -----------------------------------------------------------------------
+
+Impl_Font::Impl_Font() :
+ maColor( COL_BLACK ),
+ maFillColor( COL_TRANSPARENT )
+{
+ mnRefCount = 1;
+ meCharSet = RTL_TEXTENCODING_DONTKNOW;
+ meLanguage = LANGUAGE_DONTKNOW;
+ meFamily = FAMILY_DONTKNOW;
+ mePitch = PITCH_DONTKNOW;
+ meAlign = ALIGN_TOP;
+ meWeight = WEIGHT_DONTKNOW;
+ meWidthType = WIDTH_DONTKNOW;
+ meUnderline = UNDERLINE_NONE;
+ meStrikeout = STRIKEOUT_NONE;
+ meItalic = ITALIC_NONE;
+ mbWordLine = FALSE;
+ mbOutline = FALSE;
+ mbShadow = FALSE;
+ mbKerning = FALSE;
+ mbTransparent = TRUE;
+ mnOrientation = 0;
+}
+
+// -----------------------------------------------------------------------
+
+Impl_Font::Impl_Font( const Impl_Font& rImplFont ) :
+ maColor( rImplFont.maColor ),
+ maFillColor( rImplFont.maFillColor ),
+ maName( rImplFont.maName ),
+ maStyleName( rImplFont.maStyleName ),
+ maSize( rImplFont.maSize )
+{
+ mnRefCount = 1;
+ meCharSet = rImplFont.meCharSet;
+ meLanguage = rImplFont.meLanguage;
+ meFamily = rImplFont.meFamily;
+ mePitch = rImplFont.mePitch;
+ meAlign = rImplFont.meAlign;
+ meWeight = rImplFont.meWeight;
+ meWidthType = rImplFont.meWidthType;
+ meUnderline = rImplFont.meUnderline;
+ meStrikeout = rImplFont.meStrikeout;
+ meItalic = rImplFont.meItalic;
+ mbWordLine = rImplFont.mbWordLine;
+ mbOutline = rImplFont.mbOutline;
+ mbShadow = rImplFont.mbShadow;
+ mbKerning = rImplFont.mbKerning;
+ mbTransparent = rImplFont.mbTransparent;
+ mnOrientation = rImplFont.mnOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::MakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplFont->mnRefCount != 1 )
+ {
+ if ( mpImplFont->mnRefCount )
+ mpImplFont->mnRefCount--;
+ mpImplFont = new Impl_Font( *mpImplFont );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font()
+{
+ DBG_CTOR( Font, NULL );
+
+#ifdef WIN
+ static Impl_Font _near aStaticImplFont;
+#else
+ static Impl_Font aStaticImplFont;
+#endif
+ // RefCount == 0 fuer statische Objekte
+ aStaticImplFont.mnRefCount = 0;
+ mpImplFont = &aStaticImplFont;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const Font& rFont )
+{
+ DBG_CTOR( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+ DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplFont = rFont.mpImplFont;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplFont->mnRefCount )
+ mpImplFont->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const XubString& rName, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->maName = rName;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( const XubString& rName, const XubString& rStyleName, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->maName = rName;
+ mpImplFont->maStyleName = rStyleName;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::Font( FontFamily eFamily, const Size& rSize )
+{
+ DBG_CTOR( Font, NULL );
+
+ mpImplFont = new Impl_Font;
+ mpImplFont->meFamily = eFamily;
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+Font::~Font()
+{
+ DBG_DTOR( Font, NULL );
+
+ // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplFont->mnRefCount )
+ {
+ if ( mpImplFont->mnRefCount == 1 )
+ delete mpImplFont;
+ else
+ mpImplFont->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetFillColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maFillColor = rColor;
+ if ( rColor.GetTransparency() )
+ mpImplFont->mbTransparent = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetTransparent( BOOL bTransparent )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbTransparent = bTransparent;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetAlign( FontAlign eAlign )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meAlign = eAlign;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetName( const XubString& rName )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maName = rName;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetStyleName( const XubString& rStyleName )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maStyleName = rStyleName;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetSize( const Size& rSize )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->maSize = rSize;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetFamily( FontFamily eFamily )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meFamily = eFamily;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetCharSet( CharSet eCharSet )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meCharSet = eCharSet;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetLanguage( LanguageType eLanguage )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meLanguage = eLanguage;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetPitch( FontPitch ePitch )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mePitch = ePitch;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetOrientation( short nOrientation )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mnOrientation = nOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetKerning( BOOL bKerning )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbKerning = bKerning;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWeight( FontWeight eWeight )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meWeight = eWeight;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWidthType( FontWidth eWidth )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meWidthType = eWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetItalic( FontItalic eItalic )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meItalic = eItalic;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetOutline( BOOL bOutline )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbOutline = bOutline;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetShadow( BOOL bShadow )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbShadow = bShadow;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetUnderline( FontUnderline eUnderline )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meUnderline = eUnderline;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetStrikeout( FontStrikeout eStrikeout )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->meStrikeout = eStrikeout;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::SetWordLineMode( BOOL bWordLine )
+{
+ DBG_CHKTHIS( Font, NULL );
+
+ MakeUnique();
+ mpImplFont->mbWordLine = bWordLine;
+}
+
+// -----------------------------------------------------------------------
+
+Font& Font::operator=( const Font& rFont )
+{
+ DBG_CHKTHIS( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+ DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rFont.mpImplFont->mnRefCount )
+ rFont.mpImplFont->mnRefCount++;
+
+ // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplFont->mnRefCount )
+ {
+ if ( mpImplFont->mnRefCount == 1 )
+ delete mpImplFont;
+ else
+ mpImplFont->mnRefCount--;
+ }
+
+ mpImplFont = rFont.mpImplFont;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Font::operator==( const Font& rFont ) const
+{
+ DBG_CHKTHIS( Font, NULL );
+ DBG_CHKOBJ( &rFont, Font, NULL );
+
+ if ( mpImplFont == rFont.mpImplFont )
+ return TRUE;
+
+ if ( (mpImplFont->meWeight == rFont.mpImplFont->meWeight ) &&
+ (mpImplFont->meItalic == rFont.mpImplFont->meItalic ) &&
+ (mpImplFont->meUnderline == rFont.mpImplFont->meUnderline ) &&
+ (mpImplFont->mbWordLine == rFont.mpImplFont->mbWordLine ) &&
+ (mpImplFont->meFamily == rFont.mpImplFont->meFamily ) &&
+ (mpImplFont->mePitch == rFont.mpImplFont->mePitch ) &&
+ (mpImplFont->meCharSet == rFont.mpImplFont->meCharSet ) &&
+ (mpImplFont->meAlign == rFont.mpImplFont->meAlign ) &&
+ (mpImplFont->maName == rFont.mpImplFont->maName ) &&
+ (mpImplFont->maStyleName == rFont.mpImplFont->maStyleName ) &&
+ (mpImplFont->maColor == rFont.mpImplFont->maColor ) &&
+ (mpImplFont->maFillColor == rFont.mpImplFont->maFillColor ) &&
+ (mpImplFont->maSize == rFont.mpImplFont->maSize ) &&
+ (mpImplFont->mnOrientation == rFont.mpImplFont->mnOrientation ) &&
+ (mpImplFont->meStrikeout == rFont.mpImplFont->meStrikeout ) &&
+ (mpImplFont->mbOutline == rFont.mpImplFont->mbOutline ) &&
+ (mpImplFont->mbShadow == rFont.mpImplFont->mbShadow ) &&
+ (mpImplFont->mbKerning == rFont.mpImplFont->mbKerning ) &&
+ (mpImplFont->mbTransparent == rFont.mpImplFont->mbTransparent ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Font::Merge( const Font& rFont )
+{
+ if ( rFont.GetName().Len() )
+ {
+ SetName( rFont.GetName() );
+ SetStyleName( rFont.GetStyleName() );
+ SetFamily( rFont.GetFamily() );
+ SetCharSet( GetCharSet() );
+ SetLanguage( rFont.GetLanguage() );
+ SetPitch( rFont.GetPitch() );
+ }
+
+ if ( rFont.GetSize().Height() )
+ SetSize( rFont.GetSize() );
+ if ( rFont.GetWeight() != WEIGHT_DONTKNOW )
+ SetWeight( rFont.GetWeight() );
+ if ( rFont.GetWidthType() != WIDTH_DONTKNOW )
+ SetWidthType( rFont.GetWidthType() );
+ if ( rFont.GetItalic() != ITALIC_DONTKNOW )
+ SetItalic( rFont.GetItalic() );
+ if ( rFont.GetUnderline() != UNDERLINE_DONTKNOW )
+ {
+ SetUnderline( rFont.GetUnderline() );
+ SetWordLineMode( rFont.IsWordLineMode() );
+ }
+ if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW )
+ {
+ SetStrikeout( rFont.GetStrikeout() );
+ SetWordLineMode( rFont.IsWordLineMode() );
+ }
+
+ // Defaults?
+ SetOrientation( rFont.GetOrientation() );
+ SetKerning( rFont.IsKerning() );
+ SetOutline( rFont.IsOutline() );
+ SetShadow( rFont.IsShadow() );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Impl_Font& rImpl_Font )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+ BOOL bTmp;
+
+ rIStm.ReadByteString( rImpl_Font.maName, rIStm.GetStreamCharSet() );
+ rIStm.ReadByteString( rImpl_Font.maStyleName, rIStm.GetStreamCharSet() );
+ rIStm >> rImpl_Font.maSize;
+// rIStm >> rImpl_Font.maColor; // removed since SUPD396
+// rIStm >> rImpl_Font.maFillColor; // removed since SUPD396
+
+ rIStm >> nTmp16; rImpl_Font.meCharSet = (rtl_TextEncoding) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meFamily = (FontFamily) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.mePitch = (FontPitch) nTmp16;
+// rIStm >> nTmp16; rImpl_Font.meAlign = (FontAlign) nTmp16; // removed since SUPD396
+ rIStm >> nTmp16; rImpl_Font.meWeight = (FontWeight) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meUnderline = (FontUnderline) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meStrikeout = (FontStrikeout) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meItalic = (FontItalic) nTmp16;
+ rIStm >> nTmp16; rImpl_Font.meLanguage = (LanguageType) nTmp16; // new since SUPD 396
+ rIStm >> nTmp16; rImpl_Font.meWidthType = (FontWidth) nTmp16; // new since SUPD 396
+
+ rIStm >> rImpl_Font.mnOrientation;
+
+ rIStm >> bTmp; rImpl_Font.mbWordLine = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbOutline = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbShadow = bTmp;
+ rIStm >> bTmp; rImpl_Font.mbKerning = bTmp;
+// rIStm >> bTmp; rImpl_Font.mbTransparent = bTmp; // removed since SUPD396
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Impl_Font& rImpl_Font )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+ rOStm.WriteByteString( rImpl_Font.maName, rOStm.GetStreamCharSet() );
+ rOStm.WriteByteString( rImpl_Font.maStyleName, rOStm.GetStreamCharSet() );
+ rOStm << rImpl_Font.maSize;
+// rOStm << rImpl_Font.maColor; // removed since SUPD396
+// rOStm << rImpl_Font.maFillColor; // removed since SUPD396
+
+ rOStm << (UINT16) GetStoreCharSet( rImpl_Font.meCharSet, rOStm.GetVersion() );
+ rOStm << (UINT16) rImpl_Font.meFamily;
+ rOStm << (UINT16) rImpl_Font.mePitch;
+// rOStm << (UINT16) rImpl_Font.meAlign; // removed since SUPD396
+ rOStm << (UINT16) rImpl_Font.meWeight;
+ rOStm << (UINT16) rImpl_Font.meUnderline;
+ rOStm << (UINT16) rImpl_Font.meStrikeout;
+ rOStm << (UINT16) rImpl_Font.meItalic;
+ rOStm << (UINT16) rImpl_Font.meLanguage; // new since SUPD 396
+ rOStm << (UINT16) rImpl_Font.meWidthType; // new since SUPD 396
+
+ rOStm << rImpl_Font.mnOrientation;
+
+ rOStm << (BOOL) rImpl_Font.mbWordLine;
+ rOStm << (BOOL) rImpl_Font.mbOutline;
+ rOStm << (BOOL) rImpl_Font.mbShadow;
+ rOStm << (BOOL) rImpl_Font.mbKerning;
+// rOStm << (BOOL) rImpl_Font.mbTransparent; // removed since SUPD396
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Font& rFont )
+{
+ rFont.MakeUnique();
+ return( rIStm >> *rFont.mpImplFont );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Font& rFont )
+{
+ return( rOStm << *rFont.mpImplFont );
+}
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
new file mode 100644
index 000000000000..852dbfcb87a3
--- /dev/null
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -0,0 +1,1724 @@
+/*************************************************************************
+ *
+ * $RCSfile: gdimtf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GDIMTF_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_CVTSVM_HXX
+#include <cvtsvm.hxx>
+#endif
+#include <gdimtf.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
+
+// --------------------------
+// - Color exchange structs -
+// --------------------------
+
+struct ImplColAdjustParam
+{
+ BYTE* pMapR;
+ BYTE* pMapG;
+ BYTE* pMapB;
+};
+
+struct ImplBmpAdjustParam
+{
+ short nLuminancePercent;
+ short nContrastPercent;
+ short nChannelRPercent;
+ short nChannelGPercent;
+ short nChannelBPercent;
+ double fGamma;
+ BOOL bInvert;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColConvertParam
+{
+ MtfConversion eConversion;
+};
+
+struct ImplBmpConvertParam
+{
+ BmpConversion eConversion;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColMonoParam
+{
+ Color aColor;
+};
+
+struct ImplBmpMonoParam
+{
+ Color aColor;
+};
+
+// -----------------------------------------------------------------------------
+
+struct ImplColReplaceParam
+{
+ ULONG* pMinR;
+ ULONG* pMaxR;
+ ULONG* pMinG;
+ ULONG* pMaxG;
+ ULONG* pMinB;
+ ULONG* pMaxB;
+ const Color* pDstCols;
+ ULONG nCount;
+};
+
+struct ImplBmpReplaceParam
+{
+ const Color* pSrcCols;
+ const Color* pDstCols;
+ ULONG nCount;
+ const ULONG* pTols;
+};
+
+
+// ---------
+// - Label -
+// ---------
+
+struct ImpLabel
+{
+ String aLabelName;
+ ULONG nActionPos;
+
+ ImpLabel( const String& rLabelName, ULONG _nActionPos ) :
+ aLabelName( rLabelName ),
+ nActionPos( _nActionPos ) {}
+};
+
+// -------------
+// - LabelList -
+// -------------
+
+class ImpLabelList : private List
+{
+public:
+
+ ImpLabelList() : List( 8, 4, 4 ) {}
+ ImpLabelList( const ImpLabelList& rList );
+ ~ImpLabelList();
+
+ void ImplInsert( ImpLabel* p ) { Insert( p, LIST_APPEND ); }
+ ImpLabel* ImplRemove( ULONG nPos ) { return (ImpLabel*) Remove( nPos ); }
+ void ImplReplace( ImpLabel* p ) { Replace( (void*)p ); }
+ ImpLabel* ImplFirst() { return (ImpLabel*) First(); }
+ ImpLabel* ImplNext() { return (ImpLabel*) Next(); }
+ ImpLabel* ImplGetLabel( ULONG nPos ) const { return (ImpLabel*) GetObject( nPos ); }
+ ULONG ImplGetLabelPos( const String& rLabelName );
+ ULONG ImplCount() const { return Count(); }
+};
+
+// ------------------------------------------------------------------------
+
+ImpLabelList::ImpLabelList( const ImpLabelList& rList ) :
+ List( rList )
+{
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ ImplReplace( new ImpLabel( *pLabel ) );
+}
+
+// ------------------------------------------------------------------------
+
+ImpLabelList::~ImpLabelList()
+{
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ delete pLabel;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpLabelList::ImplGetLabelPos( const String& rLabelName )
+{
+ ULONG nLabelPos = METAFILE_LABEL_NOTFOUND;
+
+ for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
+ {
+ if ( rLabelName == pLabel->aLabelName )
+ {
+ nLabelPos = GetCurPos();
+ break;
+ }
+ }
+
+ return nLabelPos;
+}
+
+// ---------------
+// - GDIMetaFile -
+// ---------------
+
+GDIMetaFile::GDIMetaFile() :
+ List ( 0x3EFF, 64, 64 ),
+ aPrefSize ( 1, 1 ),
+ pPrev ( NULL ),
+ pNext ( NULL ),
+ pOutDev ( NULL ),
+ pLabelList ( NULL ),
+ bPause ( FALSE ),
+ bRecord ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
+ List ( rMtf ),
+ aPrefMapMode ( rMtf.aPrefMapMode ),
+ aPrefSize ( rMtf.aPrefSize ),
+ aHookHdlLink ( rMtf.aHookHdlLink ),
+ pPrev ( rMtf.pPrev ),
+ pNext ( rMtf.pNext ),
+ pOutDev ( NULL ),
+ bPause ( FALSE ),
+ bRecord ( FALSE )
+{
+ // RefCount der MetaActions erhoehen
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Duplicate();
+
+ if( rMtf.pLabelList )
+ pLabelList = new ImpLabelList( *rMtf.pLabelList );
+ else
+ pLabelList = NULL;
+
+ if( rMtf.bRecord )
+ {
+ Record( rMtf.pOutDev );
+
+ if ( rMtf.bPause )
+ Pause( TRUE );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile::~GDIMetaFile()
+{
+ Clear();
+}
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
+{
+ if( this != &rMtf )
+ {
+ Clear();
+
+ List::operator=( rMtf );
+
+ // RefCount der MetaActions erhoehen
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Duplicate();
+
+ if( rMtf.pLabelList )
+ pLabelList = new ImpLabelList( *rMtf.pLabelList );
+ else
+ pLabelList = NULL;
+
+ aPrefMapMode = rMtf.aPrefMapMode;
+ aPrefSize = rMtf.aPrefSize;
+ aHookHdlLink = rMtf.aHookHdlLink;
+ pPrev = rMtf.pPrev;
+ pNext = rMtf.pNext;
+ pOutDev = NULL;
+ bPause = FALSE;
+ bRecord = FALSE;
+
+ if( rMtf.bRecord )
+ {
+ Record( rMtf.pOutDev );
+
+ if( rMtf.bPause )
+ Pause( TRUE );
+ }
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
+{
+ const ULONG nCount = Count();
+ BOOL bRet = FALSE;
+
+ if( this == &rMtf )
+ bRet = TRUE;
+ else if( rMtf.GetActionCount() == nCount &&
+ rMtf.GetPrefSize() == aPrefSize &&
+ rMtf.GetPrefMapMode() == aPrefMapMode )
+ {
+ bRet = TRUE;
+
+ for( ULONG n = 0UL; n < nCount; n++ )
+ {
+ if( GetObject( n ) != rMtf.GetObject( n ) )
+ {
+ bRet = FALSE;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Clear()
+{
+ if( bRecord )
+ Stop();
+
+ for( void* pAct = First(); pAct; pAct = Next() )
+ ( (MetaAction*) pAct )->Delete();
+
+ List::Clear();
+
+ delete pLabelList;
+ pLabelList = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Linker( OutputDevice* pOut, BOOL bLink )
+{
+ if( bLink )
+ {
+ pNext = NULL;
+ pPrev = pOut->GetConnectMetaFile();
+ pOut->SetConnectMetaFile( this );
+
+ if( pPrev )
+ pPrev->pNext = this;
+ }
+ else
+ {
+ if( pNext )
+ {
+ pNext->pPrev = pPrev;
+
+ if( pPrev )
+ pPrev->pNext = pNext;
+ }
+ else
+ {
+ if( pPrev )
+ pPrev->pNext = NULL;
+
+ pOut->SetConnectMetaFile( pPrev );
+ }
+
+ pPrev = NULL;
+ pNext = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+long GDIMetaFile::Hook()
+{
+ return aHookHdlLink.Call( this );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Record( OutputDevice* pOut )
+{
+ if( bRecord )
+ Stop();
+
+ Last();
+ pOutDev = pOut;
+ bRecord = TRUE;
+ Linker( pOut, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( GDIMetaFile& rMtf, ULONG nPos )
+{
+ if ( !bRecord && !rMtf.bRecord )
+ {
+ MetaAction* pAction = GetCurAction();
+ const ULONG nCount = Count();
+
+ if( nPos > nCount )
+ nPos = nCount;
+
+ for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
+ {
+ if( !Hook() )
+ {
+ pAction->Duplicate();
+ rMtf.AddAction( pAction );
+ }
+
+ pAction = (MetaAction*) Next();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( OutputDevice* pOut, ULONG nPos )
+{
+ if( !bRecord )
+ {
+ MetaAction* pAction = GetCurAction();
+ const ULONG nCount = Count();
+ ULONG i = 0, nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
+
+ if( nPos > nCount )
+ nPos = nCount;
+
+ for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
+ {
+ if( !Hook() )
+ {
+ pAction->Execute( pOut );
+
+ // flush output from time to time
+ if( i++ > nSyncCount )
+ ( (Window*) pOut )->Flush(), i = 0;
+ }
+
+ pAction = (MetaAction*) Next();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
+ const Size& rSize, ULONG nPos )
+{
+ Region aDrawClipRegion;
+ MapMode aDrawMap( GetPrefMapMode() );
+ Size aDestSize( pOut->LogicToPixel( rSize ) );
+
+ if( aDestSize.Width() && aDestSize.Height() )
+ {
+ Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
+ GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
+
+ if( !aTmpPrefSize.Width() )
+ aTmpPrefSize.Width() = aDestSize.Width();
+
+ if( !aTmpPrefSize.Height() )
+ aTmpPrefSize.Height() = aDestSize.Height();
+
+ Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
+ Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
+
+ aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
+ aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
+
+ aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
+
+ pOut->Push();
+
+ if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
+ pOut->SetRelativeMapMode( aDrawMap );
+ else
+ pOut->SetMapMode( aDrawMap );
+
+ Play( pOut, nPos );
+
+ pOut->Pop();
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Pause( BOOL _bPause )
+{
+ if( bRecord )
+ {
+ if( _bPause )
+ {
+ if( !bPause )
+ Linker( pOutDev, FALSE );
+ }
+ else
+ {
+ if( bPause )
+ Linker( pOutDev, TRUE );
+ }
+
+ bPause = _bPause;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Stop()
+{
+ if( bRecord )
+ {
+ bRecord = FALSE;
+
+ if( !bPause )
+ Linker( pOutDev, FALSE );
+ else
+ bPause = FALSE;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindStart()
+{
+ if( !bRecord )
+ First();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindEnd()
+{
+ if( !bRecord )
+ Last();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Wind( ULONG nActionPos )
+{
+ if( !bRecord )
+ Seek( nActionPos );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindPrev()
+{
+ if( !bRecord )
+ Prev();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::WindNext()
+{
+ if( !bRecord )
+ Next();
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::AddAction( MetaAction* pAction )
+{
+ Insert( pAction, LIST_APPEND );
+
+ if( pPrev )
+ {
+ pAction->Duplicate();
+ pPrev->AddAction( pAction );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::AddAction( MetaAction* pAction, ULONG nPos )
+{
+ Insert( pAction, nPos );
+
+ if( pPrev )
+ {
+ pAction->Duplicate();
+ pPrev->AddAction( pAction, nPos );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* GDIMetaFile::CopyAction( ULONG nPos ) const
+{
+ return ( (MetaAction*) GetObject( nPos ) )->Clone();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetActionPos( const String& rLabel )
+{
+ ImpLabel* pLabel = NULL;
+
+ if( pLabelList )
+ pLabel = pLabelList->ImplGetLabel( pLabelList->ImplGetLabelPos( rLabel ) );
+ else
+ pLabel = NULL;
+
+ return( pLabel ? pLabel->nActionPos : METAFILE_LABEL_NOTFOUND );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::InsertLabel( const String& rLabel, ULONG nActionPos )
+{
+ BOOL bRet = FALSE;
+
+ if( !pLabelList )
+ pLabelList = new ImpLabelList;
+
+ if( pLabelList->ImplGetLabelPos( rLabel ) == METAFILE_LABEL_NOTFOUND )
+ {
+ pLabelList->ImplInsert( new ImpLabel( rLabel, nActionPos ) );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::RemoveLabel( const String& rLabel )
+{
+ if( pLabelList )
+ {
+ const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
+
+ if( nLabelPos != METAFILE_LABEL_NOTFOUND )
+ delete pLabelList->ImplRemove( nLabelPos );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::RenameLabel( const String& rLabel, const String& rNewLabel )
+{
+ if( pLabelList )
+ {
+ const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
+
+ if ( nLabelPos != METAFILE_LABEL_NOTFOUND )
+ pLabelList->ImplGetLabel( nLabelPos )->aLabelName = rNewLabel;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetLabelCount() const
+{
+ return( pLabelList ? pLabelList->ImplCount() : 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+String GDIMetaFile::GetLabel( ULONG nLabel )
+{
+ String aString;
+
+ if( pLabelList )
+ {
+ const ImpLabel* pLabel = pLabelList->ImplGetLabel( nLabel );
+
+ if( pLabel )
+ aString = pLabel->aLabelName;
+ }
+
+ return aString;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GDIMetaFile::SaveStatus()
+{
+ if ( bRecord )
+ {
+ if ( bPause )
+ Linker( pOutDev, TRUE );
+
+ AddAction( new MetaLineColorAction( pOutDev->GetLineColor(),
+ pOutDev->IsLineColor() ) );
+ AddAction( new MetaFillColorAction( pOutDev->GetFillColor(),
+ pOutDev->IsFillColor() ) );
+ AddAction( new MetaFontAction( pOutDev->GetFont() ) );
+ AddAction( new MetaTextColorAction( pOutDev->GetTextColor() ) );
+ AddAction( new MetaTextFillColorAction( pOutDev->GetTextFillColor(),
+ pOutDev->IsTextFillColor() ) );
+ AddAction( new MetaTextLineColorAction( pOutDev->GetTextLineColor(),
+ pOutDev->IsTextLineColor() ) );
+ AddAction( new MetaTextAlignAction( pOutDev->GetTextAlign() ) );
+ AddAction( new MetaRasterOpAction( pOutDev->GetRasterOp() ) );
+ AddAction( new MetaMapModeAction( pOutDev->GetMapMode() ) );
+ AddAction( new MetaClipRegionAction( pOutDev->GetClipRegion(),
+ pOutDev->IsClipRegion() ) );
+
+ if ( bPause )
+ Linker( pOutDev, FALSE );
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Move( long nX, long nY )
+{
+ for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
+ {
+ MetaAction* pModAct;
+
+ if( pAct->GetRefCount() > 1 )
+ {
+ Replace( pModAct = pAct->Clone(), pAct );
+ pAct->Delete();
+ }
+ else
+ pModAct = pAct;
+
+ pModAct->Move( nX, nY );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Scale( double fScaleX, double fScaleY )
+{
+ for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
+ {
+ MetaAction* pModAct;
+
+ if( pAct->GetRefCount() > 1 )
+ {
+ Replace( pModAct = pAct->Clone(), pAct );
+ pAct->Delete();
+ }
+ else
+ pModAct = pAct;
+
+ pModAct->Scale( fScaleX, fScaleY );
+ }
+
+ aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
+ aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
+{
+ Scale( (double) rScaleX, (double) rScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
+{
+ return Color( rColor.GetTransparency(),
+ ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ],
+ ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ],
+ ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] );
+
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ const ImplBmpAdjustParam* p = (const ImplBmpAdjustParam*) pBmpParam;
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
+ p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
+ p->fGamma, p->bInvert );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
+{
+ BYTE cLum = rColor.GetLuminance();
+
+ if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion )
+ cLum = ( cLum < 128 ) ? 0 : 255;
+
+ return Color( rColor.GetTransparency(), cLum, cLum, cLum );
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColMonoFnc( const Color& rColor, const void* pColParam )
+{
+ return( ( (const ImplColMonoParam*) pColParam )->aColor );
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ BitmapPalette aPal( 3 );
+
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_WHITE );
+ aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor;
+
+ Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
+ aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor );
+
+ if( rBmpEx.IsAlpha() )
+ return BitmapEx( aBmp, rBmpEx.GetAlpha() );
+ else if( rBmpEx.IsTransparent() )
+ return BitmapEx( aBmp, rBmpEx.GetMask() );
+ else
+ return aBmp;
+}
+
+// ------------------------------------------------------------------------
+
+Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
+{
+ const ULONG nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
+
+ for( ULONG i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ )
+ {
+ if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) &&
+ ( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) )
+ {
+ return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] );
+ }
+ }
+
+ return rColor;
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
+{
+ const ImplBmpReplaceParam* p = (const ImplBmpReplaceParam*) pBmpParam;
+ BitmapEx aRet( rBmpEx );
+
+ aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
+ BmpExchangeFnc pFncBmp, const void* pBmpParam )
+{
+ GDIMetaFile aMtf;
+
+ aMtf.aPrefSize = aPrefSize;
+ aMtf.aPrefMapMode = aPrefMapMode;
+
+ for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
+ {
+ const USHORT nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ MetaPixelAction* pAct = (MetaPixelAction*) pAction;
+ aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ {
+ MetaTextColorAction* pAct = (MetaTextColorAction*) pAction;
+ aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTFILLCOLOR_ACTION ):
+ {
+ MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_TEXTLINECOLOR_ACTION ):
+ {
+ MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction;
+
+ if( !pAct->IsSetting() )
+ pAct->Duplicate();
+ else
+ pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
+
+ aMtf.Insert( pAct, LIST_APPEND );
+ }
+ break;
+
+ case( META_FONT_ACTION ):
+ {
+ MetaFontAction* pAct = (MetaFontAction*) pAction;
+ Font aFont( pAct->GetFont() );
+
+ aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
+ aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
+ aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND );
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
+ Wallpaper aWall( pAct->GetWallpaper() );
+ const Rectangle& rRect = pAct->GetRect();
+
+ aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
+
+ if( aWall.IsBitmap() )
+ aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
+
+ if( aWall.IsGradient() )
+ {
+ Gradient aGradient( aWall.GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aWall.SetGradient( aGradient );
+ }
+
+ aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ case( META_BMPEX_ACTION ):
+ case( META_MASK_ACTION ):
+ {
+ DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+ aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+ aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+ aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+ aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+ aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetBitmap(),
+ pFncCol( pAct->GetColor(), pColParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+ aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
+ pAct->GetSrcPoint(), pAct->GetSrcSize(),
+ pAct->GetBitmap(),
+ pFncCol( pAct->GetColor(), pColParam ) ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ MetaGradientAction* pAct = (MetaGradientAction*) pAction;
+ Gradient aGradient( pAct->GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND );
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
+ Gradient aGradient( pAct->GetGradient() );
+
+ aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
+ aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
+ aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND );
+ }
+ break;
+
+ case( META_HATCH_ACTION ):
+ {
+ MetaHatchAction* pAct = (MetaHatchAction*) pAction;
+ Hatch aHatch( pAct->GetHatch() );
+
+ aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
+ aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND );
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
+ GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
+
+ aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
+ aMtf.Insert( new MetaFloatTransparentAction( aTransMtf,
+ pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetGradient() ),
+ LIST_APPEND );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ MetaEPSAction* pAct = (MetaEPSAction*) pAction;
+ GDIMetaFile aSubst( pAct->GetSubstitute() );
+
+ aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
+ aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
+ pAct->GetLink(), aSubst ),
+ LIST_APPEND );
+ }
+ break;
+
+ default:
+ {
+ pAction->Duplicate();
+ aMtf.Insert( pAction, LIST_APPEND );
+ }
+ break;
+ }
+ }
+
+ *this = aMtf;
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
+ short nChannelRPercent, short nChannelGPercent,
+ short nChannelBPercent, double fGamma, BOOL bInvert )
+{
+ // nothing to do? => return quickly
+ if( nLuminancePercent || nContrastPercent ||
+ nChannelRPercent || nChannelGPercent || nChannelBPercent ||
+ ( fGamma != 1.0 ) || bInvert )
+ {
+ double fM, fROff, fGOff, fBOff, fOff;
+ ImplColAdjustParam aColParam;
+ ImplBmpAdjustParam aBmpParam;
+
+ aColParam.pMapR = new BYTE[ 256 ];
+ aColParam.pMapG = new BYTE[ 256 ];
+ aColParam.pMapB = new BYTE[ 256 ];
+
+ // calculate slope
+ if( nContrastPercent >= 0 )
+ fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
+ else
+ fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
+
+ // total offset = luminance offset + contrast offset
+ fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
+
+ // channel offset = channel offset + total offset
+ fROff = nChannelRPercent * 2.55 + fOff;
+ fGOff = nChannelGPercent * 2.55 + fOff;
+ fBOff = nChannelBPercent * 2.55 + fOff;
+
+ // calculate gamma value
+ fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
+ const BOOL bGamma = ( fGamma != 1.0 );
+
+ // create mapping table
+ for( long nX = 0L; nX < 256L; nX++ )
+ {
+ aColParam.pMapR[ nX ] = (BYTE) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
+ aColParam.pMapG[ nX ] = (BYTE) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
+ aColParam.pMapB[ nX ] = (BYTE) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
+
+ if( bGamma )
+ {
+ aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
+ aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
+ aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
+ }
+
+ if( bInvert )
+ {
+ aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
+ aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
+ aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
+ }
+ }
+
+ aBmpParam.nLuminancePercent = nLuminancePercent;
+ aBmpParam.nContrastPercent = nContrastPercent;
+ aBmpParam.nChannelRPercent = nChannelRPercent;
+ aBmpParam.nChannelGPercent = nChannelGPercent;
+ aBmpParam.nChannelBPercent = nChannelBPercent;
+ aBmpParam.fGamma = fGamma;
+ aBmpParam.bInvert = bInvert;
+
+ // do color adjustment
+ ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
+
+ delete[] aColParam.pMapR;
+ delete[] aColParam.pMapG;
+ delete[] aColParam.pMapB;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::Convert( MtfConversion eConversion )
+{
+ // nothing to do? => return quickly
+ if( eConversion != MTF_CONVERSION_NONE )
+ {
+ ImplColConvertParam aColParam;
+ ImplBmpConvertParam aBmpParam;
+
+ aColParam.eConversion = eConversion;
+ aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
+
+ ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol );
+}
+
+// ------------------------------------------------------------------------
+
+void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, ULONG nColorCount, ULONG* pTols )
+{
+ ImplColReplaceParam aColParam;
+ ImplBmpReplaceParam aBmpParam;
+
+ aColParam.pMinR = new ULONG[ nColorCount ];
+ aColParam.pMaxR = new ULONG[ nColorCount ];
+ aColParam.pMinG = new ULONG[ nColorCount ];
+ aColParam.pMaxG = new ULONG[ nColorCount ];
+ aColParam.pMinB = new ULONG[ nColorCount ];
+ aColParam.pMaxB = new ULONG[ nColorCount ];
+
+ for( ULONG i = 0; i < nColorCount; i++ )
+ {
+ const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
+ long nVal;
+
+ nVal = pSearchColors[ i ].GetRed();
+ aColParam.pMinR[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxR[ i ] = (ULONG) Min( nVal + nTol, 255L );
+
+ nVal = pSearchColors[ i ].GetGreen();
+ aColParam.pMinG[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxG[ i ] = (ULONG) Min( nVal + nTol, 255L );
+
+ nVal = pSearchColors[ i ].GetBlue();
+ aColParam.pMinB[ i ] = (ULONG) Max( nVal - nTol, 0L );
+ aColParam.pMaxB[ i ] = (ULONG) Min( nVal + nTol, 255L );
+ }
+
+ aColParam.pDstCols = pReplaceColors;
+ aColParam.nCount = nColorCount;
+
+ aBmpParam.pSrcCols = pSearchColors;
+ aBmpParam.pDstCols = pReplaceColors;
+ aBmpParam.nCount = nColorCount;
+ aBmpParam.pTols = pTols;
+
+ ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
+
+ delete[] aColParam.pMinR;
+ delete[] aColParam.pMaxR;
+ delete[] aColParam.pMinG;
+ delete[] aColParam.pMaxG;
+ delete[] aColParam.pMinB;
+ delete[] aColParam.pMaxB;
+};
+
+// ------------------------------------------------------------------------
+
+GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
+{
+ GDIMetaFile aRet( *this );
+
+ ImplColMonoParam aColParam;
+ ImplBmpMonoParam aBmpParam;
+
+ aColParam.aColor = rColor;
+ aBmpParam.aColor = rColor;
+
+ aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GDIMetaFile::GetChecksum() const
+{
+ GDIMetaFile aMtf;
+ SvMemoryStream aMemStm( 65535, 65535 );
+ ImplMetaWriteData aWriteData; aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
+ SVBT16 aBT16;
+ SVBT32 aBT32;
+ ULONG nCrc = 0;
+
+ for( ULONG i = 0, nCount = GetActionCount(); i < nCount; i++ )
+ {
+ MetaAction* pAction = GetAction( i );
+
+ switch( pAction->GetType() )
+ {
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pAct = (MetaBmpAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pAct = (MetaMaskAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+
+ ShortToSVBT16( pAct->GetType(), aBT16 );
+ nCrc = rtl_crc32( nCrc, aBT16, 2 );
+
+ LongToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetColor().GetColor(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetDestSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+ }
+ break;
+
+ default:
+ {
+ pAction->Write( aMemStm, &aWriteData );
+ nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
+ aMemStm.Seek( 0 );
+ }
+ break;
+ }
+ }
+
+ return nCrc;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
+{
+ if( !rIStm.GetError() )
+ {
+ char aId[ 7 ];
+ ULONG nStmPos = rIStm.Tell();
+ USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bError = FALSE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ rIStm.Read( aId, 6 );
+ aId[ 6 ] = 0;
+
+ if ( !strcmp( aId, "VCLMTF" ) )
+ {
+ // new format
+ VersionCompat* pCompat;
+ MetaAction* pAction;
+ UINT32 nStmCompressMode;
+ UINT32 nCount;
+
+ pCompat = new VersionCompat( rIStm, STREAM_READ );
+
+ rIStm >> nStmCompressMode;
+ rIStm >> rGDIMetaFile.aPrefMapMode;
+ rIStm >> rGDIMetaFile.aPrefSize;
+ rIStm >> nCount;
+
+ delete pCompat;
+
+ ImplMetaReadData aReadData;
+ aReadData.meActualCharSet = rIStm.GetStreamCharSet();
+
+ for( UINT32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
+ {
+ pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
+
+ if( pAction )
+ rGDIMetaFile.AddAction( pAction );
+ }
+ }
+ else
+ {
+ // to avoid possible compiler optimizations => new/delete
+ rIStm.Seek( nStmPos );
+ delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
+ }
+
+ // check for errors
+ if( rIStm.GetError() )
+ {
+ rGDIMetaFile.Clear();
+ rIStm.Seek( nStmPos );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
+{
+ if( !rOStm.GetError() )
+ {
+ if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
+ ((GDIMetaFile&) rGDIMetaFile ).Write( rOStm );
+ else
+ delete( new SVMConverter( rOStm, (GDIMetaFile&) rGDIMetaFile, CONVERT_TO_SVM1 ) );
+ }
+
+ return rOStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& GDIMetaFile::Read( SvStream& rIStm )
+{
+ Clear();
+ rIStm >> *this;
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& GDIMetaFile::Write( SvStream& rOStm )
+{
+ VersionCompat* pCompat;
+ const UINT32 nStmCompressMode = rOStm.GetCompressMode();
+ USHORT nOldFormat = rOStm.GetNumberFormatInt();
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rOStm.Write( "VCLMTF", 6 );
+
+ pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << nStmCompressMode;
+ rOStm << aPrefMapMode;
+ rOStm << aPrefSize;
+ rOStm << (UINT32) GetActionCount();
+
+ delete pCompat;
+
+ ImplMetaWriteData aWriteData;
+ aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
+
+ MetaAction* pAct = (MetaAction*)First();
+ while ( pAct )
+ {
+ pAct->Write( rOStm, &aWriteData );
+ pAct = (MetaAction*)Next();
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+
+ return rOStm;
+}
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
new file mode 100644
index 000000000000..3a175017708e
--- /dev/null
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -0,0 +1,450 @@
+/*************************************************************************
+ *
+ * $RCSfile: gfxlink.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <tools/vcompat.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+#include <tools/tempfile.hxx>
+#include <ucbhelper/content.hxx>
+#include "graph.hxx"
+#include "gfxlink.hxx"
+#include "cvtgrf.hxx"
+
+// -----------
+// - GfxLink -
+// -----------
+
+GfxLink::GfxLink() :
+ meType ( GFX_LINK_TYPE_NONE ),
+ mnBufSize ( 0 ),
+ mpBuf ( NULL ),
+ mpSwap ( NULL ),
+ mnUserId ( 0UL )
+{
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( const GfxLink& rGfxLink )
+{
+ ImplCopy( rGfxLink );
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( const String& rPath, GfxLinkType nType )
+{
+ sal_Int64 nFileSize = 0;
+
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( rPath, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.getPropertyValue( ::rtl::OUString::createFromAscii( "Size" ) ) >>= nFileSize;
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ meType = nType;
+ mnBufSize = nFileSize;
+ mpSwap = NULL;
+ mnUserId = 0UL;
+
+ if( mnBufSize )
+ {
+ SvFileStream aFileStream( rPath, STREAM_READ );
+
+ mpBuf = new ImpBuffer( mnBufSize );
+ aFileStream.Read( mpBuf->mpBuffer, mnBufSize );
+ }
+ else
+ mpBuf = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::GfxLink( BYTE* pBuf, ULONG nSize, GfxLinkType nType, BOOL bOwns )
+{
+ meType = nType;
+ mnBufSize = nSize;
+ mpSwap = NULL;
+ mnUserId = 0UL;
+
+ if( bOwns )
+ mpBuf = new ImpBuffer( pBuf );
+ else if( nSize )
+ {
+ mpBuf = new ImpBuffer( nSize );
+ memcpy( mpBuf->mpBuffer, pBuf, nSize );
+ }
+ else
+ mpBuf = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink::~GfxLink()
+{
+ if( mpBuf && !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ if( mpSwap && !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink& GfxLink::operator=( const GfxLink& rGfxLink )
+{
+ if( &rGfxLink != this )
+ {
+ if ( mpBuf && !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ if( mpSwap && !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+
+ ImplCopy( rGfxLink );
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::ImplCopy( const GfxLink& rGfxLink )
+{
+ mnBufSize = rGfxLink.mnBufSize;
+ meType = rGfxLink.meType;
+ mpBuf = rGfxLink.mpBuf;
+ mpSwap = rGfxLink.mpSwap;
+ mnUserId = rGfxLink.mnUserId;
+
+ if( mpBuf )
+ mpBuf->mnRefCount++;
+
+ if( mpSwap )
+ mpSwap->mnRefCount++;
+}
+
+// ------------------------------------------------------------------------
+
+GfxLinkType GfxLink::GetType() const
+{
+ return meType;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GfxLink::IsNative() const
+{
+ return( meType >= GFX_LINK_FIRST_NATIVE_ID && meType <= GFX_LINK_LAST_NATIVE_ID );
+}
+
+// ------------------------------------------------------------------------
+
+ULONG GfxLink::GetDataSize() const
+{
+ return mnBufSize;
+}
+
+// ------------------------------------------------------------------------
+
+const BYTE* GfxLink::GetData() const
+{
+ if( IsSwappedOut() )
+ ( (GfxLink*) this )->SwapIn();
+
+ return( mpBuf ? mpBuf->mpBuffer : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL GfxLink::LoadNative( Graphic& rGraphic )
+{
+ BOOL bRet = FALSE;
+
+ if( IsNative() && mnBufSize )
+ {
+ const BYTE* pData = GetData();
+
+ if( pData )
+ {
+ SvMemoryStream aMemStm;
+ ULONG nCvtType;
+
+ aMemStm.SetBuffer( (char*) pData, mnBufSize, FALSE, mnBufSize );
+
+ switch( meType )
+ {
+ case( GFX_LINK_TYPE_NATIVE_GIF ): nCvtType = CVT_GIF; break;
+ case( GFX_LINK_TYPE_NATIVE_JPG ): nCvtType = CVT_JPG; break;
+ case( GFX_LINK_TYPE_NATIVE_PNG ): nCvtType = CVT_PNG; break;
+ case( GFX_LINK_TYPE_NATIVE_TIF ): nCvtType = CVT_TIF; break;
+ case( GFX_LINK_TYPE_NATIVE_WMF ): nCvtType = CVT_WMF; break;
+ case( GFX_LINK_TYPE_NATIVE_MET ): nCvtType = CVT_MET; break;
+ case( GFX_LINK_TYPE_NATIVE_PCT ): nCvtType = CVT_PCT; break;
+
+ default: nCvtType = CVT_UNKNOWN; break;
+ }
+
+ if( nCvtType && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::SwapOut()
+{
+ if( !IsSwappedOut() && mpBuf )
+ {
+ mpSwap = new ImpSwap( mpBuf->mpBuffer, mnBufSize );
+
+ if( !mpSwap->IsSwapped() )
+ {
+ delete mpSwap;
+ mpSwap = NULL;
+ }
+ else if( !( --mpBuf->mnRefCount ) )
+ delete mpBuf;
+
+ mpBuf = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GfxLink::SwapIn()
+{
+ if( IsSwappedOut() )
+ {
+ mpBuf = new ImpBuffer( mpSwap->GetData() );
+
+ if( !( --mpSwap->mnRefCount ) )
+ delete mpSwap;
+
+ mpSwap = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const GfxLink& rGfxLink )
+{
+ VersionCompat* pCompat = new VersionCompat( rOStream, STREAM_WRITE, 1 );
+
+ rOStream << (UINT16) rGfxLink.GetType() << rGfxLink.GetDataSize() << rGfxLink.GetUserId();
+
+ delete pCompat;
+
+ if( rGfxLink.GetDataSize() )
+ {
+ if( rGfxLink.IsSwappedOut() )
+ rGfxLink.mpSwap->WriteTo( rOStream );
+ else
+ rOStream.Write( rGfxLink.GetData(), rGfxLink.GetDataSize() );
+ }
+
+ return rOStream;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, GfxLink& rGfxLink)
+{
+ ULONG nSize;
+ ULONG nUserId;
+ UINT16 nType;
+ BYTE* pBuf;
+ VersionCompat* pCompat = new VersionCompat( rIStream, STREAM_READ );
+
+ rIStream >> nType >> nSize >> nUserId;
+
+ delete pCompat;
+
+ pBuf = new BYTE[ nSize ];
+ rIStream.Read( pBuf, nSize );
+
+ rGfxLink = GfxLink( pBuf, nSize, (GfxLinkType) nType, TRUE );
+ rGfxLink.SetUserId( nUserId );
+
+ return rIStream;
+}
+
+// -----------
+// - ImpSwap -
+// -----------
+
+ImpSwap::ImpSwap( BYTE* pData, ULONG nDataSize ) :
+ mnDataSize( nDataSize ),
+ mnRefCount( 1UL )
+{
+ if( pData && mnDataSize )
+ {
+ maFileName = TempFile::CreateTempName();
+
+ if( maFileName.Len() )
+ {
+ SvFileStream aOStm( maFileName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.Write( pData, mnDataSize );
+
+ if( aOStm.GetError() )
+ {
+ aOStm.Close();
+
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( maFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ maFileName.Erase();
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImpSwap::~ImpSwap()
+{
+ if( IsSwapped() )
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( maFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+BYTE* ImpSwap::GetData() const
+{
+ BYTE* pData;
+
+ if( IsSwapped() )
+ {
+ SvFileStream aIStm( maFileName, STREAM_READ );
+
+ pData = new BYTE[ mnDataSize ];
+ aIStm.Read( pData, mnDataSize );
+
+ if( aIStm.GetError() )
+ {
+ aIStm.Close();
+ delete[] pData;
+ pData = NULL;
+ }
+ }
+ else
+ pData = NULL;
+
+ return pData;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpSwap::WriteTo( SvStream& rOStm ) const
+{
+ BYTE* pData = GetData();
+
+ if( pData )
+ {
+ rOStm.Write( pData, mnDataSize );
+ delete[] pData;
+ }
+}
diff --git a/vcl/source/gdi/gradient.cxx b/vcl/source/gdi/gradient.cxx
new file mode 100644
index 000000000000..7a6489f9c8e6
--- /dev/null
+++ b/vcl/source/gdi/gradient.cxx
@@ -0,0 +1,386 @@
+/*************************************************************************
+ *
+ * $RCSfile: gradient.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GRADIENT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Gradient );
+
+// -----------------------------------------------------------------------
+
+Impl_Gradient::Impl_Gradient() :
+ maStartColor( COL_BLACK ),
+ maEndColor( COL_WHITE )
+{
+ mnRefCount = 1;
+ meStyle = GRADIENT_LINEAR;
+ mnAngle = 0;
+ mnBorder = 0;
+ mnOfsX = 50;
+ mnOfsY = 50;
+ mnIntensityStart = 100;
+ mnIntensityEnd = 100;
+ mnStepCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+Impl_Gradient::Impl_Gradient( const Impl_Gradient& rImplGradient ) :
+ maStartColor( rImplGradient.maStartColor ),
+ maEndColor( rImplGradient.maEndColor )
+{
+ mnRefCount = 1;
+ meStyle = rImplGradient.meStyle;
+ mnAngle = rImplGradient.mnAngle;
+ mnBorder = rImplGradient.mnBorder;
+ mnOfsX = rImplGradient.mnOfsX;
+ mnOfsY = rImplGradient.mnOfsY;
+ mnIntensityStart = rImplGradient.mnIntensityStart;
+ mnIntensityEnd = rImplGradient.mnIntensityEnd;
+ mnStepCount = rImplGradient.mnStepCount;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::MakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplGradient->mnRefCount != 1 )
+ {
+ if( mpImplGradient->mnRefCount )
+ mpImplGradient->mnRefCount--;
+
+ mpImplGradient = new Impl_Gradient( *mpImplGradient );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient()
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( const Gradient& rGradient )
+{
+ DBG_CTOR( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ // Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplGradient = rGradient.mpImplGradient;
+ mpImplGradient->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( GradientStyle eStyle )
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+ mpImplGradient->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::Gradient( GradientStyle eStyle,
+ const Color& rStartColor, const Color& rEndColor )
+{
+ DBG_CTOR( Gradient, NULL );
+
+ mpImplGradient = new Impl_Gradient;
+ mpImplGradient->meStyle = eStyle;
+ mpImplGradient->maStartColor = rStartColor;
+ mpImplGradient->maEndColor = rEndColor;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient::~Gradient()
+{
+ DBG_DTOR( Gradient, NULL );
+
+ // Wenn es die letzte Referenz ist, loeschen,
+ // sonst Referenzcounter decrementieren
+ if ( mpImplGradient->mnRefCount == 1 )
+ delete mpImplGradient;
+ else
+ mpImplGradient->mnRefCount--;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStyle( GradientStyle eStyle )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStartColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->maStartColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetEndColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->maEndColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetAngle( USHORT nAngle )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnAngle = nAngle;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetBorder( USHORT nBorder )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnBorder = nBorder;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetOfsX( USHORT nOfsX )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnOfsX = nOfsX;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetOfsY( USHORT nOfsY )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnOfsY = nOfsY;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetStartIntensity( USHORT nIntens )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnIntensityStart = nIntens;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetEndIntensity( USHORT nIntens )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnIntensityEnd = nIntens;
+}
+
+// -----------------------------------------------------------------------
+
+void Gradient::SetSteps( USHORT nSteps )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+
+ MakeUnique();
+ mpImplGradient->mnStepCount = nSteps;
+}
+
+// -----------------------------------------------------------------------
+
+Gradient& Gradient::operator=( const Gradient& rGradient )
+{
+ DBG_CHKTHIS( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rGradient.mpImplGradient->mnRefCount++;
+
+ // Wenn es die letzte Referenz ist, loeschen,
+ // sonst Referenzcounter decrementieren
+ if ( mpImplGradient->mnRefCount == 1 )
+ delete mpImplGradient;
+ else
+ mpImplGradient->mnRefCount--;
+ mpImplGradient = rGradient.mpImplGradient;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Gradient::operator==( const Gradient& rGradient ) const
+{
+ DBG_CHKTHIS( Gradient, NULL );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if ( mpImplGradient == rGradient.mpImplGradient )
+ return TRUE;
+
+ if ( (mpImplGradient->meStyle == rGradient.mpImplGradient->meStyle) ||
+ (mpImplGradient->mnAngle == rGradient.mpImplGradient->mnAngle) ||
+ (mpImplGradient->mnBorder == rGradient.mpImplGradient->mnBorder) ||
+ (mpImplGradient->mnOfsX == rGradient.mpImplGradient->mnOfsX) ||
+ (mpImplGradient->mnOfsY == rGradient.mpImplGradient->mnOfsY) ||
+ (mpImplGradient->mnStepCount == rGradient.mpImplGradient->mnStepCount) ||
+ (mpImplGradient->mnIntensityStart == rGradient.mpImplGradient->mnIntensityStart) ||
+ (mpImplGradient->mnIntensityEnd == rGradient.mpImplGradient->mnIntensityEnd) ||
+ (mpImplGradient->maStartColor == rGradient.mpImplGradient->maStartColor) ||
+ (mpImplGradient->maEndColor == rGradient.mpImplGradient->maEndColor) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+SvStream& operator>>( SvStream& rIStm, Impl_Gradient& rImpl_Gradient )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImpl_Gradient.meStyle = (GradientStyle) nTmp16;
+
+ rIStm >> rImpl_Gradient.maStartColor >>
+ rImpl_Gradient.maEndColor >>
+ rImpl_Gradient.mnAngle >>
+ rImpl_Gradient.mnBorder >>
+ rImpl_Gradient.mnOfsX >>
+ rImpl_Gradient.mnOfsY >>
+ rImpl_Gradient.mnIntensityStart >>
+ rImpl_Gradient.mnIntensityEnd >>
+ rImpl_Gradient.mnStepCount;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Impl_Gradient& rImpl_Gradient )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImpl_Gradient.meStyle <<
+ rImpl_Gradient.maStartColor <<
+ rImpl_Gradient.maEndColor <<
+ rImpl_Gradient.mnAngle <<
+ rImpl_Gradient.mnBorder <<
+ rImpl_Gradient.mnOfsX <<
+ rImpl_Gradient.mnOfsY <<
+ rImpl_Gradient.mnIntensityStart <<
+ rImpl_Gradient.mnIntensityEnd <<
+ rImpl_Gradient.mnStepCount;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Gradient& rGradient )
+{
+ rGradient.MakeUnique();
+ return( rIStm >> *rGradient.mpImplGradient );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Gradient& rGradient )
+{
+ return( rOStm << *rGradient.mpImplGradient );
+}
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
new file mode 100644
index 000000000000..3c847d7dd916
--- /dev/null
+++ b/vcl/source/gdi/graph.cxx
@@ -0,0 +1,832 @@
+/*************************************************************************
+ *
+ * $RCSfile: graph.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_GRAPH_CXX
+
+#ifndef _SV_CLIP_HXX
+#include <clip.hxx>
+#endif
+#ifndef _SV_IMPGRAPH_HXX
+#include <impgraph.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_CLIP_HXX
+#include <clip.hxx>
+#endif
+#ifndef _SV_DRAG_HXX
+#include <drag.hxx>
+#endif
+#include <graph.hxx>
+
+// -----------------------
+// - Compression defines -
+// -----------------------
+
+#define COMPRESS_OWN ('S'|('D'<<8UL))
+#define COMPRESS_NONE ( 0UL )
+#define RLE_8 ( 1UL )
+#define RLE_4 ( 2UL )
+#define BITFIELDS ( 3UL )
+#define ZCOMPRESS ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
+
+// -----------------------
+// - Default-Drawmethode -
+// -----------------------
+
+static void ImplDrawDefault( OutputDevice* pOutDev, const UniString* pText,
+ Font* pFont, const Bitmap* pBitmap,
+ const Point& rDestPt, const Size& rDestSize )
+{
+ USHORT nPixel = (USHORT) pOutDev->PixelToLogic( Size( 1, 1 ) ).Width();
+ USHORT nWidth = nPixel;
+ Point aPoint( rDestPt.X() + nWidth, rDestPt.Y() + nWidth );
+ Size aSize( rDestSize.Width() - ( nWidth << 1 ), rDestSize.Height() - ( nWidth << 1 ) );
+ BOOL bFilled = ( pBitmap != NULL || pFont != NULL );
+ Rectangle aBorderRect( aPoint, aSize );
+
+ pOutDev->Push();
+
+ pOutDev->SetFillColor();
+
+ // Auf dem Drucker ein schwarzes Rechteck und auf dem Bildschirm eins mit 3D-Effekt
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ pOutDev->SetLineColor( COL_BLACK );
+ else
+ {
+ aBorderRect.Left() += nPixel;
+ aBorderRect.Top() += nPixel;
+
+ pOutDev->SetLineColor( COL_LIGHTGRAY );
+ pOutDev->DrawRect( aBorderRect );
+
+ aBorderRect.Left() -= nPixel;
+ aBorderRect.Top() -= nPixel;
+ aBorderRect.Right() -= nPixel;
+ aBorderRect.Bottom() -= nPixel;
+ pOutDev->SetLineColor( COL_GRAY );
+ }
+
+ pOutDev->DrawRect( aBorderRect );
+
+ aPoint.X() += nWidth + 2*nPixel;
+ aPoint.Y() += nWidth + 2*nPixel;
+ aSize.Width() -= 2*nWidth + 4*nPixel;
+ aSize.Height() -= 2*nWidth + 4*nPixel;
+
+ if( aSize.Width() > 0 && aSize.Height() > 0 && pBitmap && !!*pBitmap )
+ {
+ Size aBitmapSize( pOutDev->PixelToLogic(pBitmap->GetSizePixel() ) );
+
+ if( aSize.Height() > aBitmapSize.Height() && aSize.Width() > aBitmapSize.Width() )
+ {
+ pOutDev->DrawBitmap( aPoint, *pBitmap );
+ aPoint.X() += aBitmapSize.Width() + 2*nPixel;
+ aSize.Width() -= aBitmapSize.Width() + 2*nPixel;
+ }
+ }
+
+ if ( aSize.Width() > 0 && aSize.Height() > 0 && pFont && pText && pText->Len()
+ && !(!pOutDev->IsOutputEnabled() /*&& pOutDev->GetConnectMetaFile() */) )
+ {
+ MapMode aMapMode( MAP_POINT );
+ Size aSz = pOutDev->LogicToLogic( Size( 0, 12 ), &aMapMode, NULL );
+ long nThreshold = aSz.Height() / 2;
+ long nStep = nThreshold / 3;
+
+ if ( !nStep )
+ nStep = aSz.Height() - nThreshold;
+
+ for(;; aSz.Height() -= nStep )
+ {
+ pFont->SetSize( aSz );
+ pOutDev->SetFont( *pFont );
+
+ long nTextHeight = pOutDev->GetTextHeight();
+ long nTextWidth = pOutDev->GetTextWidth( *pText );
+ if ( nTextHeight )
+ {
+ // Die N"aherung ber"ucksichtigt keine Ungenauigkeiten durch
+ // Wortumbr"uche
+ long nLines = aSize.Height() / nTextHeight;
+ long nWidth = aSize.Width() * nLines; // N"aherung!!!
+
+ if ( nTextWidth <= nWidth || aSz.Height() <= nThreshold )
+ {
+ USHORT nStart = 0;
+ USHORT nLen = 0;
+
+ while( nStart < pText->Len() && pText->GetChar( nStart ) == ' ' )
+ nStart++;
+ while( nStart+nLen < pText->Len() && pText->GetChar( nStart+nLen ) != ' ' )
+ nLen++;
+ while( nStart < pText->Len() && nLines-- )
+ {
+ USHORT nNext = nLen;
+ do
+ {
+ while ( nStart+nNext < pText->Len() && pText->GetChar( nStart+nNext ) == ' ' )
+ nNext++;
+ while ( nStart+nNext < pText->Len() && pText->GetChar( nStart+nNext ) != ' ' )
+ nNext++;
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, nNext );
+ if ( nTextWidth > aSize.Width() )
+ break;
+ nLen = nNext;
+ }
+ while ( nStart+nNext < pText->Len() );
+
+ USHORT n = nLen;
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, n );
+ while( nTextWidth > aSize.Width() )
+ nTextWidth = pOutDev->GetTextWidth( *pText, nStart, --n );
+ pOutDev->DrawText( aPoint, *pText, nStart, n );
+
+ aPoint.Y() += nTextHeight;
+ nStart += nLen;
+ nLen = nNext-nLen;
+ while( nStart < pText->Len() && pText->GetChar( nStart ) == ' ' )
+ {
+ nStart++;
+ nLen--;
+ }
+ }
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+ // Falls die Default-Graphik keinen Inhalt hat,
+ // malen wir ein rotes Kreuz
+ if( !bFilled )
+ {
+ aBorderRect.Left()++;
+ aBorderRect.Top()++;
+ aBorderRect.Right()--;
+ aBorderRect.Bottom()--;
+
+ pOutDev->SetLineColor( COL_LIGHTRED );
+ pOutDev->DrawLine( aBorderRect.TopLeft(), aBorderRect.BottomRight() );
+ pOutDev->DrawLine( aBorderRect.TopRight(), aBorderRect.BottomLeft() );
+ }
+
+ pOutDev->Pop();
+}
+
+// -----------
+// - Graphic -
+// -----------
+
+TYPEINIT1_AUTOFACTORY( Graphic, SvDataCopyStream );
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic()
+{
+ mpImpGraphic = new ImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Graphic& rGraphic )
+{
+ if( rGraphic.IsAnimated() )
+ mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
+ else
+ {
+ mpImpGraphic = rGraphic.mpImpGraphic;
+ mpImpGraphic->mnRefCount++;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Bitmap& rBmp )
+{
+ mpImpGraphic = new ImpGraphic( rBmp );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const BitmapEx& rBmpEx )
+{
+ mpImpGraphic = new ImpGraphic( rBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const Animation& rAnimation )
+{
+ mpImpGraphic = new ImpGraphic( rAnimation );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::Graphic( const GDIMetaFile& rMtf )
+{
+ mpImpGraphic = new ImpGraphic( rMtf );
+}
+
+// ------------------------------------------------------------------------
+
+Graphic::~Graphic()
+{
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::ImplTestRefCount()
+{
+ if( mpImpGraphic->mnRefCount > 1UL )
+ {
+ mpImpGraphic->mnRefCount--;
+ mpImpGraphic = new ImpGraphic( *mpImpGraphic );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic& Graphic::operator=( const Graphic& rGraphic )
+{
+ if( &rGraphic != this )
+ {
+ if( rGraphic.IsAnimated() )
+ {
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+
+ mpImpGraphic = new ImpGraphic( *rGraphic.mpImpGraphic );
+ }
+ else
+ {
+ rGraphic.mpImpGraphic->mnRefCount++;
+
+ if( mpImpGraphic->mnRefCount == 1UL )
+ delete mpImpGraphic;
+ else
+ mpImpGraphic->mnRefCount--;
+
+ mpImpGraphic = rGraphic.mpImpGraphic;
+ }
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator==( const Graphic& rGraphic ) const
+{
+ return( *mpImpGraphic == *rGraphic.mpImpGraphic );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator!=( const Graphic& rGraphic ) const
+{
+ return( *mpImpGraphic != *rGraphic.mpImpGraphic );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::operator!() const
+{
+ return( GRAPHIC_NONE == mpImpGraphic->ImplGetType() );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Load( SvStream& rIStm )
+{
+ rIStm >> *this;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Save( SvStream& rOStm )
+{
+ rOStm << *this;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Assign( const SvDataCopyStream& rCopyStream )
+{
+ *this = (const Graphic& ) rCopyStream;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Clear()
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplClear();
+}
+
+// ------------------------------------------------------------------------
+
+GraphicType Graphic::GetType() const
+{
+ return mpImpGraphic->ImplGetType();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetDefaultType()
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetDefaultType();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsSupportedGraphic() const
+{
+ return mpImpGraphic->ImplIsSupportedGraphic();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsTransparent() const
+{
+ return mpImpGraphic->ImplIsTransparent();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsAlpha() const
+{
+ return mpImpGraphic->ImplIsAlpha();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsAnimated() const
+{
+ return mpImpGraphic->ImplIsAnimated();
+}
+
+// ------------------------------------------------------------------------
+
+Bitmap Graphic::GetBitmap() const
+{
+ return mpImpGraphic->ImplGetBitmap();
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx Graphic::GetBitmapEx() const
+{
+ return mpImpGraphic->ImplGetBitmapEx();
+}
+
+// ------------------------------------------------------------------------
+
+Animation Graphic::GetAnimation() const
+{
+ return mpImpGraphic->ImplGetAnimation();
+}
+
+// ------------------------------------------------------------------------
+
+const GDIMetaFile& Graphic::GetGDIMetaFile() const
+{
+ return mpImpGraphic->ImplGetGDIMetaFile();
+}
+
+// ------------------------------------------------------------------------
+
+Size Graphic::GetPrefSize() const
+{
+ return mpImpGraphic->ImplGetPrefSize();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetPrefSize( const Size& rPrefSize )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetPrefSize( rPrefSize );
+}
+
+// ------------------------------------------------------------------------
+
+MapMode Graphic::GetPrefMapMode() const
+{
+ return mpImpGraphic->ImplGetPrefMapMode();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetPrefMapMode( const MapMode& rPrefMapMode )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetPrefMapMode( rPrefMapMode );
+}
+
+// ------------------------------------------------------------------
+
+ULONG Graphic::GetSizeBytes() const
+{
+ return mpImpGraphic->ImplGetSizeBytes();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ mpImpGraphic->ImplDraw( pOutDev, rDestPt );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( GRAPHIC_DEFAULT == mpImpGraphic->ImplGetType() )
+ ImplDrawDefault( pOutDev, NULL, NULL, NULL, rDestPt, rDestSz );
+ else
+ mpImpGraphic->ImplDraw( pOutDev, rDestPt, rDestSz );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::Draw( OutputDevice* pOutDev, const String& rText,
+ Font& rFont, const Bitmap& rBitmap,
+ const Point& rDestPt, const Size& rDestSz )
+{
+ ImplDrawDefault( pOutDev, &rText, &rFont, &rBitmap, rDestPt, rDestSz );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StartAnimation( OutputDevice* pOutDev, const Point& rDestPt, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStartAnimation( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
+ const Size& rDestSz, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStartAnimation( pOutDev, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::StopAnimation( OutputDevice* pOutDev, long nExtraData )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplStopAnimation( pOutDev, nExtraData );
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetAnimationNotifyHdl( const Link& rLink )
+{
+ mpImpGraphic->ImplSetAnimationNotifyHdl( rLink );
+}
+
+// ------------------------------------------------------------------------
+
+Link Graphic::GetAnimationNotifyHdl() const
+{
+ return mpImpGraphic->ImplGetAnimationNotifyHdl();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetAnimationLoopCount() const
+{
+ return mpImpGraphic->ImplGetAnimationLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::ResetAnimationLoopCount()
+{
+ mpImpGraphic->ImplResetAnimationLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+List* Graphic::GetAnimationInfoList() const
+{
+ return mpImpGraphic->ImplGetAnimationInfoList();
+}
+
+// ------------------------------------------------------------------------
+
+GraphicReader* Graphic::GetContext()
+{
+ return mpImpGraphic->ImplGetContext();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetContext( GraphicReader* pReader )
+{
+ mpImpGraphic->ImplSetContext( pReader );
+}
+
+// ------------------------------------------------------------------------
+
+USHORT Graphic::GetGraphicsCompressMode( SvStream& rIStm )
+{
+ const ULONG nPos = rIStm.Tell();
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ UINT32 nTmp32;
+ UINT16 nTmp16;
+ USHORT nCompressMode = COMPRESSMODE_NONE;
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ rIStm >> nTmp32;
+
+ // is it a swapped graphic with a bitmap?
+ rIStm.SeekRel( (nTmp32 == (UINT32) GRAPHIC_BITMAP ) ? 40 : -4 );
+
+ // try to read bitmap id
+ rIStm >> nTmp16;
+
+ // check id of BitmapFileHeader
+ if( 0x4D42 == nTmp16 )
+ {
+ // seek to compress field of BitmapInfoHeader
+ rIStm.SeekRel( 28 );
+ rIStm >> nTmp32;
+
+ // Compare with our own compressmode
+ if( ZCOMPRESS == nTmp32 )
+ nCompressMode = COMPRESSMODE_ZBITMAP;
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ rIStm.Seek( nPos );
+
+ return nCompressMode;
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetDocFileName( const String& rName, ULONG nFilePos )
+{
+ mpImpGraphic->ImplSetDocFileName( rName, nFilePos );
+}
+
+// ------------------------------------------------------------------------
+
+const String& Graphic::GetDocFileName() const
+{
+ return mpImpGraphic->ImplGetDocFileName();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetDocFilePos() const
+{
+ return mpImpGraphic->ImplGetDocFilePos();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::ReadEmbedded( SvStream& rIStream, BOOL bSwap )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplReadEmbedded( rIStream, bSwap );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::WriteEmbedded( SvStream& rOStream )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplWriteEmbedded( rOStream );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapOut()
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapOut( SvStream* pOStream )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapOut( pOStream );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapIn()
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapIn();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::SwapIn( SvStream* pStrm )
+{
+ ImplTestRefCount();
+ return mpImpGraphic->ImplSwapIn( pStrm );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsSwapOut() const
+{
+ return mpImpGraphic->ImplIsSwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+void Graphic::SetLink( const GfxLink& rGfxLink )
+{
+ ImplTestRefCount();
+ mpImpGraphic->ImplSetLink( rGfxLink );
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink Graphic::GetLink()
+{
+ return mpImpGraphic->ImplGetLink();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::IsLink() const
+{
+ return mpImpGraphic->ImplIsLink();
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::GetChecksum() const
+{
+ return mpImpGraphic->ImplGetChecksum();
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, Graphic& rGraphic )
+{
+ rGraphic.ImplTestRefCount();
+ return rIStream >> *rGraphic.mpImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const Graphic& rGraphic )
+{
+ return rOStream << *rGraphic.mpImpGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG Graphic::RegisterClipboardFormatName()
+{
+ static ULONG nFormat = 0;
+
+ if ( !nFormat )
+ nFormat = Clipboard::RegisterFormatName( XubString( RTL_CONSTASCII_USTRINGPARAM( "SVXB (StarView Bitmap/Animation)" ) ) );
+
+ return nFormat;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::ClipboardHasFormat()
+{
+ return Clipboard::HasFormat( RegisterClipboardFormatName() )
+ || Clipboard::HasFormat( FORMAT_GDIMETAFILE )
+ || Clipboard::HasFormat( FORMAT_BITMAP );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::DragServerHasFormat( USHORT nItem )
+{
+ return DragServer::HasFormat( nItem, RegisterClipboardFormatName() )
+ || DragServer::HasFormat( nItem, FORMAT_GDIMETAFILE )
+ || DragServer::HasFormat( nItem, FORMAT_BITMAP );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::Copy() const
+{
+ SotDataMemberObjectRef aDataObject = new SotDataMemberObject;
+ SvData* pData = new SvData( RegisterClipboardFormatName() );
+
+ pData->SetData( (SvDataCopyStream*) this, TRANSFER_COPY );
+ aDataObject->Append( pData );
+ VclClipboard::Copy( aDataObject );
+
+ return TRUE;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL Graphic::Paste()
+{
+ const ULONG nFormat = RegisterClipboardFormatName();
+ BOOL bRet = FALSE;
+
+ if( VclClipboard::HasFormat( nFormat ) )
+ {
+ SotDataObjectRef aDataObject = VclClipboard::Paste();
+ SvData aData( nFormat );
+
+ if( aDataObject.Is() && aDataObject->GetData( &aData ) )
+ {
+ Graphic* pGraphic = NULL;
+
+ if( aData.GetData( (SvDataCopyStream**) &pGraphic, StaticType(), TRANSFER_MOVE ) )
+ *this = *pGraphic;
+
+ delete pGraphic;
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/hatch.cxx b/vcl/source/gdi/hatch.cxx
new file mode 100644
index 000000000000..ac66e89fd0cf
--- /dev/null
+++ b/vcl/source/gdi/hatch.cxx
@@ -0,0 +1,262 @@
+/*************************************************************************
+ *
+ * $RCSfile: hatch.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_HATCH_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_HATCX_HXX
+#include <hatch.hxx>
+#endif
+
+DBG_NAME( Hatch );
+
+// --------------
+// - ImplHatch -
+// --------------
+
+ImplHatch::ImplHatch() :
+ mnRefCount ( 1 ),
+ maColor ( COL_BLACK ),
+ meStyle ( HATCH_SINGLE ),
+ mnDistance ( 1 ),
+ mnAngle ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplHatch::ImplHatch( const ImplHatch& rImplHatch ) :
+ mnRefCount ( 1 ),
+ maColor ( rImplHatch.maColor ),
+ meStyle ( rImplHatch.meStyle ),
+ mnDistance ( rImplHatch.mnDistance ),
+ mnAngle ( rImplHatch.mnAngle )
+{
+}
+
+// ---------
+// - Hatch -
+// ---------
+
+Hatch::Hatch()
+{
+ DBG_CTOR( Hatch, NULL );
+ mpImplHatch = new ImplHatch;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::Hatch( const Hatch& rHatch )
+{
+ DBG_CTOR( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+ mpImplHatch = rHatch.mpImplHatch;
+ mpImplHatch->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::Hatch( HatchStyle eStyle, const Color& rColor,
+ long nDistance, USHORT nAngle10 )
+{
+ DBG_CTOR( Hatch, NULL );
+ mpImplHatch = new ImplHatch;
+ mpImplHatch->maColor = rColor;
+ mpImplHatch->meStyle = eStyle;
+ mpImplHatch->mnDistance = nDistance;
+ mpImplHatch->mnAngle = nAngle10;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch::~Hatch()
+{
+ DBG_DTOR( Hatch, NULL );
+ if( !( --mpImplHatch->mnRefCount ) )
+ delete mpImplHatch;
+}
+
+// -----------------------------------------------------------------------
+
+Hatch& Hatch::operator=( const Hatch& rHatch )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+
+ rHatch.mpImplHatch->mnRefCount++;
+
+ if( !( --mpImplHatch->mnRefCount ) )
+ delete mpImplHatch;
+
+ mpImplHatch = rHatch.mpImplHatch;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Hatch::operator==( const Hatch& rHatch ) const
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ DBG_CHKOBJ( &rHatch, Hatch, NULL );
+
+ return( mpImplHatch == rHatch.mpImplHatch ||
+ ( mpImplHatch->maColor == rHatch.mpImplHatch->maColor &&
+ mpImplHatch->meStyle == rHatch.mpImplHatch->meStyle &&
+ mpImplHatch->mnDistance == rHatch.mpImplHatch->mnDistance &&
+ mpImplHatch->mnAngle == rHatch.mpImplHatch->mnAngle ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::ImplMakeUnique()
+{
+ if( mpImplHatch->mnRefCount != 1 )
+ {
+ if( mpImplHatch->mnRefCount )
+ mpImplHatch->mnRefCount--;
+
+ mpImplHatch = new ImplHatch( *mpImplHatch );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetStyle( HatchStyle eStyle )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->maColor = rColor;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetDistance( long nDistance )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->mnDistance = nDistance;
+}
+
+// -----------------------------------------------------------------------
+
+void Hatch::SetAngle( USHORT nAngle10 )
+{
+ DBG_CHKTHIS( Hatch, NULL );
+ ImplMakeUnique();
+ mpImplHatch->mnAngle = nAngle10;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplHatch& rImplHatch )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplHatch.meStyle = (HatchStyle) nTmp16;
+ rIStm >> rImplHatch.maColor >> rImplHatch.mnDistance >> rImplHatch.mnAngle;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplHatch& rImplHatch )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImplHatch.meStyle << rImplHatch.maColor;
+ rOStm << rImplHatch.mnDistance << rImplHatch.mnAngle;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Hatch& rHatch )
+{
+ rHatch.ImplMakeUnique();
+ return( rIStm >> *rHatch.mpImplHatch );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Hatch& rHatch )
+{
+ return( rOStm << *rHatch.mpImplHatch );
+}
diff --git a/vcl/source/gdi/image.cxx b/vcl/source/gdi/image.cxx
new file mode 100644
index 000000000000..16188cdc5143
--- /dev/null
+++ b/vcl/source/gdi/image.cxx
@@ -0,0 +1,1521 @@
+/*************************************************************************
+ *
+ * $RCSfile: image.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#define _SV_IMAGE_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_RC_HXX
+#include <rc.hxx>
+#endif
+#ifndef _SV_RESMGR_HXX
+#include <resmgr.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_IMAGE_H
+#include <image.h>
+#endif
+#define private public
+#ifndef _SV_IMAGE_HXX
+#include <image.hxx>
+#endif
+#undef private
+
+// =======================================================================
+
+DBG_NAME( Image );
+DBG_NAME( ImageList );
+
+#define IMAGE_FILE_VERSION 100
+
+// =======================================================================
+
+ImplImageList::~ImplImageList()
+{
+ if ( mpImageBitmap )
+ delete mpImageBitmap;
+ delete mpAry;
+}
+
+// =======================================================================
+
+ImplImageRefData::~ImplImageRefData()
+{
+ mpImplData->mnIRefCount--;
+ if ( mpImplData->mnRefCount || mpImplData->mnIRefCount )
+ {
+ mpImplData->mpAry[mnIndex].mnRefCount--;
+ if ( !mpImplData->mpAry[mnIndex].mnRefCount )
+ mpImplData->mnRealCount--;
+ }
+ else
+ delete mpImplData;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageRefData::IsEqual( const ImplImageRefData& rData )
+{
+ if ( (mpImplData == rData.mpImplData) && (mnIndex == rData.mnIndex) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplImageData::ImplImageData( const Bitmap& rBmp, const Bitmap& rMaskBmp ) :
+ maBmp( rBmp ),
+ maMaskBmp( rMaskBmp )
+{
+ mbColor = FALSE;
+ mpImageBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageData::ImplImageData( const Bitmap& rBmp, const Color& rColor ) :
+ maBmp( rBmp ),
+ maColor( rColor )
+{
+ mbColor = TRUE;
+ mpImageBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageData::~ImplImageData()
+{
+ if ( mpImageBitmap )
+ delete mpImageBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageData::IsEqual( const ImplImageData& rData )
+{
+ if ( (maBmp == rData.maBmp) && (maMaskBmp == rData.maMaskBmp) &&
+ (maColor == rData.maColor) && (mbColor == rData.mbColor) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplImage::~ImplImage()
+{
+ switch ( meType )
+ {
+ case IMAGETYPE_BITMAP:
+ delete (Bitmap*)mpData;
+ break;
+
+ case IMAGETYPE_IMAGE:
+ delete (ImplImageData*)mpData;
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ delete (ImplImageRefData*)mpData;
+ break;
+ }
+}
+
+// =======================================================================
+
+Image::Image()
+{
+ DBG_CTOR( Image, NULL );
+
+ mpImplData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const ResId& rResId )
+{
+ DBG_CTOR( Image, NULL );
+
+ rResId.SetRT( RSC_IMAGE );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // Header ueberspringen
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ USHORT nObjMask = pResMgr->ReadShort();
+
+ Bitmap aImageBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ if( nObjMask & RSC_IMAGE_IMAGEBITMAP )
+ {
+ aImageBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if( nObjMask & RSC_IMAGE_MASKBITMAP )
+ {
+ aMaskBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ {
+ aMaskColor = Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+
+ if ( !aImageBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ if ( !aMaskBitmap )
+ {
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aImageBitmap, aMaskColor );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( aImageBitmap );
+ }
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aImageBitmap, aMaskBitmap );
+ }
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Image::Image( const ResId& rResId ): No resource!" );
+ mpImplData = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Image& rImage )
+{
+ DBG_CTOR( Image, NULL );
+
+ mpImplData = rImage.mpImplData;
+ if ( mpImplData )
+ mpImplData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( rBitmap );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap, const Bitmap& rMaskBitmap )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ if ( !rMaskBitmap )
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( rBitmap );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( rBitmap, rMaskBitmap );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const Bitmap& rBitmap, const Color& rColor )
+{
+ DBG_CTOR( Image, NULL );
+
+ if ( !rBitmap )
+ mpImplData = NULL;
+ else
+ {
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( rBitmap, rColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::Image( const BitmapEx& rBitmapEx )
+{
+ DBG_CTOR( Image, NULL );
+
+ const Bitmap aBmp( rBitmapEx.GetBitmap() );
+
+ if( !aBmp )
+ mpImplData = NULL;
+ else
+ {
+ const Bitmap aMask( rBitmapEx.GetMask() );
+
+ mpImplData = new ImplImage;
+ mpImplData->mnRefCount = 1;
+
+ if( !aMask )
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( aBmp );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( aBmp, aMask );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image::~Image()
+{
+ DBG_DTOR( Image, NULL );
+
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Image::GetSizePixel() const
+{
+ DBG_CHKTHIS( Image, NULL );
+
+ if ( mpImplData )
+ {
+ switch ( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ return ((Bitmap*)mpImplData->mpData)->GetSizePixel();
+
+ case IMAGETYPE_IMAGE:
+ return ((ImplImageData*)mpImplData->mpData)->maBmp.GetSizePixel();
+
+ case IMAGETYPE_IMAGEREF:
+ return ((ImplImageRefData*)mpImplData->mpData)->mpImplData->maImageSize;
+ }
+ }
+
+ return Size();
+}
+
+// -----------------------------------------------------------------------
+
+Image& Image::operator=( const Image& rImage )
+{
+ DBG_CHKTHIS( Image, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rImage.mpImplData )
+ rImage.mpImplData->mnRefCount++;
+
+ // Abkoppeln
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+
+ // Neue Daten zuweisen
+ mpImplData = rImage.mpImplData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Image::operator==( const Image& rImage ) const
+{
+ DBG_CHKTHIS( Image, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+
+ if ( rImage.mpImplData == mpImplData )
+ return TRUE;
+ if ( !rImage.mpImplData || !mpImplData )
+ return FALSE;
+
+ if ( rImage.mpImplData->mpData == mpImplData->mpData )
+ return TRUE;
+
+ if ( rImage.mpImplData->meType == mpImplData->meType )
+ {
+ switch ( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ if ( *((Bitmap*)rImage.mpImplData->mpData) == *((Bitmap*)mpImplData->mpData) )
+ return TRUE;
+ break;
+
+ case IMAGETYPE_IMAGE:
+ if ( ((ImplImageData*)rImage.mpImplData->mpData)->IsEqual( *((ImplImageData*)mpImplData->mpData) ) )
+ return TRUE;
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ if ( ((ImplImageRefData*)rImage.mpImplData->mpData)->IsEqual( *((ImplImageRefData*)mpImplData->mpData) ) )
+ return TRUE;
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+static void ImplCopyImageListData( ImageList* pThis )
+{
+ if ( pThis->mpImplData->mnRefCount > 1 )
+ {
+ pThis->mpImplData->mnRefCount--;
+
+ ImplImageList* pNewData = new ImplImageList;
+ pNewData->mnRefCount = 1;
+ pNewData->mnIRefCount = 0;
+ pNewData->mnCount = pThis->mpImplData->mnCount;
+ pNewData->mnRealCount = pThis->mpImplData->mnRealCount;
+ pNewData->mnArySize = pThis->mpImplData->mnArySize;
+ pNewData->mpAry = new ImageAryData[pNewData->mnArySize];
+ pNewData->maImageSize = pThis->mpImplData->maImageSize;
+ pNewData->mpImageBitmap = new ImplImageBmp;
+ pNewData->mpImageBitmap->Create( pNewData->maImageSize.Width(),
+ pNewData->maImageSize.Height(),
+ pNewData->mnArySize );
+ memset( pNewData->mpAry, 0, pNewData->mnArySize*sizeof(ImageAryData) );
+
+ USHORT i = 0;
+ USHORT n = 0;
+ while ( i < pThis->mpImplData->mnArySize )
+ {
+ // Nur die Images kopieren, die gebraucht werden
+ if ( pThis->mpImplData->mpAry[i].mnId )
+ {
+ pNewData->mpAry[n].mnId = pThis->mpImplData->mpAry[i].mnId;
+ pNewData->mpAry[n].mnRefCount = 1;
+ pNewData->mpImageBitmap->Replace( n,
+ *(pThis->mpImplData->mpImageBitmap),
+ i );
+ n++;
+ }
+
+ i++;
+ }
+
+ pThis->mpImplData = pNewData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplBmpImageCreate( ImageList* pThis,
+ const Bitmap& rBitmap, const Bitmap& rMaskBmp,
+ const Color& rColor, BOOL bColor,
+ USHORT nInit, USHORT* mpIdAry = NULL,
+ USHORT nGrow = 4 )
+{
+ // Falls es sich um eine leere ImageListe handelt, dann Defaul-Werte
+ // setzen und nichts machen
+ if ( !nInit )
+ {
+ pThis->mpImplData = NULL;
+ pThis->mnInitSize = 1;
+ pThis->mnGrowSize = nGrow;
+ return;
+ }
+
+ DBG_ASSERT( !nInit || rBitmap.GetSizePixel().Width(),
+ "ImageList::ImageList(): nInitSize != 0 and BmpSize.Width() == 0" );
+ DBG_ASSERT( (rBitmap.GetSizePixel().Width() % nInit) == 0,
+ "ImageList::ImageList(): BmpSize % nInitSize != 0" );
+ DBG_ASSERT( !rMaskBmp || (rMaskBmp.GetSizePixel() == rBitmap.GetSizePixel()),
+ "ImageList::ImageList(): BmpSize != MaskBmpSize" );
+#ifdef DBG_UTIL
+ if ( mpIdAry )
+ {
+ for ( USHORT n1 = 0; n1 < nInit; n1++ )
+ {
+ USHORT nId = mpIdAry[n1];
+ if ( !nId )
+ {
+ DBG_ERROR( "ImageList::ImageList(): Id == 0" );
+ }
+ for ( USHORT n2 = 0; n2 < n1; n2++ )
+ {
+ if ( nId == mpIdAry[n2] )
+ {
+ DBG_ERROR1( "ImageList::ImageList(): Double Id (%u)", nId );
+ }
+ }
+ }
+ }
+#endif
+
+ Size aBmpSize = rBitmap.GetSizePixel();
+ pThis->mnInitSize = nInit;
+ pThis->mnGrowSize = nGrow;
+ pThis->mpImplData = new ImplImageList;
+ pThis->mpImplData->mnRefCount = 1;
+ pThis->mpImplData->mnIRefCount = 0;
+ pThis->mpImplData->mnCount = nInit;
+ pThis->mpImplData->mnRealCount = nInit;
+ pThis->mpImplData->mnArySize = nInit;
+ pThis->mpImplData->mpAry = new ImageAryData[nInit];
+ pThis->mpImplData->maImageSize = Size( aBmpSize.Width() / nInit, aBmpSize.Height() );
+
+ for ( USHORT i = 0; i < nInit; i++ )
+ {
+ if ( mpIdAry )
+ pThis->mpImplData->mpAry[i].mnId = mpIdAry[i];
+ else
+ pThis->mpImplData->mpAry[i].mnId = i+1;
+ pThis->mpImplData->mpAry[i].mnRefCount = 1;
+ }
+
+ pThis->mpImplData->mpImageBitmap = new ImplImageBmp;
+ pThis->mpImplData->mpImageBitmap->Create( rBitmap, rMaskBmp,
+ rColor, bColor,
+ pThis->mpImplData->maImageSize.Width(),
+ pThis->mpImplData->maImageSize.Height(),
+ nInit );
+}
+
+// =======================================================================
+
+ImageList::ImageList( USHORT nInit, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ mpImplData = NULL;
+ mnInitSize = nInit;
+ mnGrowSize = nGrow;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const ResId& rResId )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ rResId.SetRT( RSC_IMAGELIST );
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if ( !pResMgr )
+ pResMgr = Resource::GetResManager();
+
+ if ( pResMgr->GetResource( rResId ) )
+ {
+ // Header ueberspringen
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ USHORT nObjMask = pResMgr->ReadShort();
+
+ Bitmap aImageBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ BOOL bCol = FALSE;
+ BOOL bIsIdList = FALSE;
+
+ if ( nObjMask & RSC_IMAGELIST_IMAGEBITMAP )
+ {
+ aImageBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if ( nObjMask & RSC_IMAGELIST_MASKBITMAP )
+ {
+ aMaskBitmap = Bitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ }
+ if ( nObjMask & RSC_IMAGELIST_MASKCOLOR )
+ {
+ aMaskColor = Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
+ bCol = TRUE;
+ }
+ if ( nObjMask & RSC_IMAGELIST_IDLIST )
+ {
+ bIsIdList = TRUE;
+ USHORT nCount = pResMgr->ReadShort();
+ USHORT* pAry = new USHORT[ nCount ];
+ for( int i = 0; i < nCount; i++ )
+ pAry[ i ] = pResMgr->ReadShort();
+ ImplBmpImageCreate( this, aImageBitmap, aMaskBitmap, aMaskColor,
+ bCol, nCount, pAry, 4 );
+ delete pAry;
+ }
+ if ( nObjMask & RSC_IMAGELIST_IDCOUNT )
+ {
+ USHORT nCount = pResMgr->ReadShort();
+ if ( !bIsIdList )
+ {
+ ImplBmpImageCreate( this, aImageBitmap, aMaskBitmap, aMaskColor,
+ bCol, nCount, NULL, 4 );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const ImageList& rImageList )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ mpImplData = rImageList.mpImplData;
+ if ( mpImplData )
+ mpImplData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, Bitmap(), Color(), FALSE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap, const Bitmap& rMaskBmp,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, rMaskBmp, Color(), FALSE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::ImageList( const Bitmap& rBitmap, const Color& rColor,
+ USHORT nInit, USHORT* mpIdAry, USHORT nGrow )
+{
+ DBG_CTOR( ImageList, NULL );
+
+ ImplBmpImageCreate( this, rBitmap, Bitmap(), rColor, TRUE,
+ nInit, mpIdAry, nGrow );
+}
+
+// -----------------------------------------------------------------------
+
+ImageList::~ImageList()
+{
+ DBG_DTOR( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ mpImplData->mnRefCount--;
+ if ( !mpImplData->mnRefCount && !mpImplData->mnIRefCount )
+ delete mpImplData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::AddImage( USHORT nId, const Image& rImage )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( nId, "ImageList::AddImage(): ImageId == 0" );
+ DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::AddImage() - ImageId already exists" );
+ DBG_ASSERT( rImage.mpImplData, "ImageList::AddImage(): Wrong Size" );
+ DBG_ASSERT( !mpImplData || (rImage.GetSizePixel() == mpImplData->maImageSize),
+ "ImageList::AddImage(): Wrong Size" );
+
+ ImageType eImageType = rImage.mpImplData->meType;
+ Size aImageSize = rImage.GetSizePixel();
+ USHORT nIndex;
+
+ if ( !mpImplData )
+ {
+ mpImplData = new ImplImageList;
+ mpImplData->mnRefCount = 1;
+ mpImplData->mnIRefCount = 0;
+ mpImplData->mnCount = 0;
+ mpImplData->mnRealCount = 0;
+ mpImplData->mnArySize = mnInitSize;
+ mpImplData->mpAry = new ImageAryData[mnInitSize];
+ mpImplData->maImageSize = aImageSize;
+ mpImplData->mpImageBitmap = new ImplImageBmp;
+ mpImplData->mpImageBitmap->Create( aImageSize.Width(), aImageSize.Height(),
+ mnInitSize );
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ }
+ else
+ ImplCopyImageListData( this );
+
+ // Gegebenenfalls unser Array erweitern und freien Index ermitteln
+ if ( mpImplData->mnRealCount == mpImplData->mnArySize )
+ {
+ ImageAryData* pOldAry = mpImplData->mpAry;
+ USHORT nOldSize = mpImplData->mnArySize;
+
+ mpImplData->mnArySize += mnGrowSize;
+ mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize];
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ memcpy( mpImplData->mpAry, pOldAry, nOldSize*sizeof(ImageAryData) );
+ mpImplData->mpImageBitmap->Expand( mnGrowSize );
+ delete pOldAry;
+
+ nIndex = mpImplData->mnRealCount;
+ }
+ else
+ {
+ nIndex = 0;
+ while ( mpImplData->mpAry[nIndex].mnRefCount )
+ nIndex++;
+ }
+
+ // Image in Bitmap einfuegen
+ switch ( eImageType )
+ {
+ case IMAGETYPE_BITMAP:
+ mpImplData->mpImageBitmap->Replace( nIndex, *((Bitmap*)rImage.mpImplData->mpData) );
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+ if ( pData->mpImageBitmap )
+ mpImplData->mpImageBitmap->Replace( nIndex, *(pData->mpImageBitmap), 0 );
+ else
+ {
+ if ( pData->mbColor )
+ mpImplData->mpImageBitmap->Replace( nIndex, pData->maBmp, pData->maColor );
+ else
+ mpImplData->mpImageBitmap->Replace( nIndex, pData->maBmp, pData->maMaskBmp );
+ }
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ mpImplData->mpImageBitmap->Replace( nIndex, *(pData->mpImplData->mpImageBitmap),
+ pData->mnIndex );
+ }
+ break;
+ }
+
+ // Array-Daten updaten
+ mpImplData->mnCount++;
+ mpImplData->mnRealCount++;
+ mpImplData->mpAry[nIndex].mnId = nId;
+ mpImplData->mpAry[nIndex].mnRefCount = 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::CopyImage( USHORT nId, USHORT nCopyId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( nId, "ImageList::CopyImage(): ImageId == 0" );
+ DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::CopyImage(): ImageId already exists" );
+ DBG_ASSERT( GetImagePos( nCopyId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::CopyImage(): Unknown nCopyId" );
+
+ USHORT nIndex;
+ USHORT nCopyIndex = 0;
+
+ // Index von CopyId holen
+ while ( nCopyIndex < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nCopyIndex].mnId == nCopyId )
+ break;
+
+ nCopyIndex++;
+ }
+ if ( nCopyIndex >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Gegebenenfalls unser Array erweitern
+ if ( mpImplData->mnRealCount == mpImplData->mnArySize )
+ {
+ ImageAryData* pOldAry = mpImplData->mpAry;
+ USHORT nOldSize = mpImplData->mnArySize;
+
+ mpImplData->mnArySize += mnGrowSize;
+ mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize];
+ memset( mpImplData->mpAry, 0, mpImplData->mnArySize*sizeof(ImageAryData) );
+ memcpy( mpImplData->mpAry, pOldAry, nOldSize*sizeof(ImageAryData) );
+ mpImplData->mpImageBitmap->Expand( mnGrowSize );
+ delete pOldAry;
+
+ nIndex = mpImplData->mnRealCount;
+ }
+ else
+ {
+ nIndex = 0;
+ while ( mpImplData->mpAry[nIndex].mnRefCount )
+ nIndex++;
+ }
+
+ // Kopieren
+ mpImplData->mpImageBitmap->Replace( nIndex, *(mpImplData->mpImageBitmap), nCopyIndex );
+
+ // Array-Daten updaten
+ mpImplData->mnCount++;
+ mpImplData->mnRealCount++;
+ mpImplData->mpAry[nIndex].mnId = nId;
+ mpImplData->mpAry[nIndex].mnRefCount = 1;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::ReplaceImage( USHORT nId, const Image& rImage )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nId" );
+
+ RemoveImage( nId );
+ AddImage( nId, rImage );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::ReplaceImage( USHORT nId, USHORT nReplaceId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nId" );
+ DBG_ASSERT( GetImagePos( nReplaceId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::ReplaceImage(): Unknown nReplaceId" );
+
+ USHORT nPos1 = 0;
+ USHORT nPos2 = 0;
+
+ // Index von Id holen
+ while ( nPos1 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos1].mnId == nId )
+ break;
+
+ nPos1++;
+ }
+ if ( nPos1 >= mpImplData->mnArySize )
+ return;
+
+ // Index von ReplaceId holen
+ while ( nPos2 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos2].mnId == nReplaceId )
+ break;
+
+ nPos2++;
+ }
+ if ( nPos2 >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Ersetzen
+ mpImplData->mpImageBitmap->Replace( nPos1, nPos2 );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::MergeImage( USHORT nId, USHORT nMergeId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::MergeImage(): Unknown nId" );
+ DBG_ASSERT( GetImagePos( nMergeId ) != IMAGELIST_IMAGE_NOTFOUND,
+ "ImageList::MergeImage(): Unknown nMergeId" );
+
+ USHORT nPos1 = 0;
+ USHORT nPos2 = 0;
+
+ // Index von Id holen
+ while ( nPos1 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos1].mnId == nId )
+ break;
+
+ nPos1++;
+ }
+ if ( nPos1 >= mpImplData->mnArySize )
+ return;
+
+ // Index von MergeId holen
+ while ( nPos2 < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[nPos2].mnId == nMergeId )
+ break;
+
+ nPos2++;
+ }
+ if ( nPos2 >= mpImplData->mnArySize )
+ return;
+
+ // Referenz-Counter ueberpruefen
+ ImplCopyImageListData( this );
+
+ // Ersetzen
+ mpImplData->mpImageBitmap->Merge( nPos1, nPos2 );
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::RemoveImage( USHORT nId )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ ImplCopyImageListData( this );
+
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ break;
+
+ i++;
+ }
+
+ if ( i < mpImplData->mnArySize )
+ {
+ mpImplData->mpAry[i].mnRefCount--;
+ mpImplData->mpAry[i].mnId = 0;
+ if ( !mpImplData->mpAry[i].mnRefCount )
+ mpImplData->mnRealCount--;
+
+ mpImplData->mnCount--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image ImageList::GetImage( USHORT nId ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Image aImage;
+
+ if ( mpImplData )
+ {
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ break;
+
+ i++;
+ }
+
+ if ( i < mpImplData->mnArySize )
+ {
+ ImplImageRefData* mpData = new ImplImageRefData;
+
+ mpImplData->mnIRefCount++;
+ mpImplData->mpAry[i].mnRefCount++;
+ mpData->mpImplData = mpImplData;
+ mpData->mnIndex = i;
+
+ aImage.mpImplData = new ImplImage;
+ aImage.mpImplData->mnRefCount = 1;
+ aImage.mpImplData->meType = IMAGETYPE_IMAGEREF;
+ aImage.mpImplData->mpData = mpData;
+ }
+ }
+
+ return aImage;
+}
+
+// -----------------------------------------------------------------------
+
+void ImageList::Clear()
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ if ( mpImplData->mnRefCount > 1 )
+ mpImplData->mnRefCount--;
+ else
+ delete mpImplData;
+ }
+
+ mpImplData = 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImageCount() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mnCount;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImagePos( USHORT nId ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData && nId )
+ {
+ USHORT nPos = 0;
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( mpImplData->mpAry[i].mnId == nId )
+ return nPos;
+
+ if ( mpImplData->mpAry[i].mnId )
+ nPos++;
+ i++;
+ }
+ }
+
+ return IMAGELIST_IMAGE_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImageList::GetImageId( USHORT nPos ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ {
+ USHORT nRealPos = 0;
+ USHORT i = 0;
+ while ( i < mpImplData->mnArySize )
+ {
+ if ( (nPos == nRealPos) && (mpImplData->mpAry[i].mnId) )
+ return mpImplData->mpAry[i].mnId;
+
+ if ( mpImplData->mpAry[i].mnId )
+ nRealPos++;
+ i++;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Size ImageList::GetImageSize() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->maImageSize;
+ else
+ return Size();
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImageList::GetBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Bitmap aBmp;
+
+ if ( mpImplData )
+ {
+ // Positionen ermitteln, die in der Bitmap enthalten sein sollen
+ USHORT* mpPosAry = new USHORT[mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < mpImplData->mnArySize; i++ )
+ {
+ if ( mpImplData->mpAry[i].mnId )
+ {
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmap besorgen
+ aBmp = mpImplData->mpImageBitmap->GetBitmap( nPosCount, mpPosAry );
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+ }
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImageList::GetMaskBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Bitmap aBmp;
+
+ if ( HasMaskBitmap() )
+ {
+ // Positionen ermitteln, die in der Bitmap enthalten sein sollen
+ USHORT* mpPosAry = new USHORT[mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < mpImplData->mnArySize; i++ )
+ {
+ if ( mpImplData->mpAry[i].mnId )
+ {
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmap besorgen
+ aBmp = mpImplData->mpImageBitmap->GetMaskBitmap( nPosCount, mpPosAry );
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+ }
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::HasMaskBitmap() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mpImageBitmap->HasMaskBitmap();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Color ImageList::GetMaskColor() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ Color aColor;
+
+ if ( HasMaskColor() )
+ aColor = mpImplData->mpImageBitmap->GetMaskColor();
+
+ return aColor;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::HasMaskColor() const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+
+ if ( mpImplData )
+ return mpImplData->mpImageBitmap->HasMaskColor();
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImageList& ImageList::operator=( const ImageList& rImageList )
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rImageList.mpImplData )
+ rImageList.mpImplData->mnRefCount++;
+
+ // Abkoppeln
+ if ( mpImplData )
+ {
+ mpImplData->mnRefCount--;
+ if ( !mpImplData->mnRefCount && !mpImplData->mnIRefCount )
+ delete mpImplData;
+ }
+
+ // Neue Daten zuweisen
+ mpImplData = rImageList.mpImplData;
+ mnInitSize = rImageList.mnInitSize;
+ mnGrowSize = rImageList.mnGrowSize;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImageList::operator==( const ImageList& rImageList ) const
+{
+ DBG_CHKTHIS( ImageList, NULL );
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ if ( rImageList.mpImplData == mpImplData )
+ return TRUE;
+ if ( !rImageList.mpImplData || !mpImplData )
+ return FALSE;
+
+ if ( (rImageList.mpImplData->mnCount == mpImplData->mnCount) &&
+ (rImageList.mpImplData->maImageSize == mpImplData->maImageSize) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, ImageList& rImageList )
+{
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ // Falls es eine bestehende ImageListe ist, dann erst abkoppeln
+ if ( rImageList.mpImplData )
+ {
+ rImageList.mpImplData->mnRefCount--;
+ if ( !rImageList.mpImplData->mnRefCount && !rImageList.mpImplData->mnIRefCount )
+ delete rImageList.mpImplData;
+ }
+ rImageList.mpImplData = NULL;
+
+ // Daten lesen
+ USHORT nVersion;
+ Size aImageSize;
+ BOOL bImageList;
+ rIStream >> nVersion;
+ rIStream >> rImageList.mnInitSize;
+ rIStream >> rImageList.mnGrowSize;
+ rIStream >> bImageList;
+
+ // Wenn es eine leere ImageListe ist, dann brauchen wir nicht weiter lesen
+ if ( !bImageList )
+ return rIStream;
+
+ // Image-Groesse lesen
+ rIStream >> aImageSize.Width();
+ rIStream >> aImageSize.Height();
+
+ // Image-Daten anlegen und initialisieren
+ rImageList.mpImplData = new ImplImageList;
+ rImageList.mpImplData->mnRefCount = 1;
+ rImageList.mpImplData->mnIRefCount = 0;
+ rImageList.mpImplData->mnCount = rImageList.mnInitSize;
+ rImageList.mpImplData->mnRealCount = rImageList.mnInitSize;
+ rImageList.mpImplData->mnArySize = rImageList.mnInitSize;
+ rImageList.mpImplData->mpAry = new ImageAryData[rImageList.mnInitSize];
+ rImageList.mpImplData->maImageSize = aImageSize;
+
+ // Array mit ID's lesen und initialisieren
+ for ( USHORT i = 0; i < rImageList.mnInitSize; i++ )
+ {
+ rIStream >> rImageList.mpImplData->mpAry[i].mnId;
+ rImageList.mpImplData->mpAry[i].mnRefCount = 1;
+ }
+
+ // Bitmaps lesen
+ Bitmap aBitmap;
+ Bitmap aMaskBitmap;
+ Color aMaskColor;
+ BYTE bMaskBitmap;
+ BYTE bMaskColor;
+ rIStream >> aBitmap;
+ rIStream >> bMaskBitmap;
+ if ( bMaskBitmap )
+ rIStream >> aMaskBitmap;
+ rIStream >> bMaskColor;
+ if ( bMaskColor )
+ rIStream >> aMaskColor;
+
+ // Systemdaten anlegen
+ rImageList.mpImplData->mpImageBitmap = new ImplImageBmp;
+ rImageList.mpImplData->mpImageBitmap->Create( aBitmap, aMaskBitmap,
+ aMaskColor, bMaskColor,
+ aImageSize.Width(),
+ aImageSize.Height(),
+ rImageList.mnInitSize );
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const ImageList& rImageList )
+{
+ DBG_CHKOBJ( &rImageList, ImageList, NULL );
+
+ BOOL bImageList = (rImageList.mpImplData) ? TRUE : FALSE;
+
+ USHORT nVersion = IMAGE_FILE_VERSION;
+ rOStream << nVersion;
+
+ // Wenn es eine leere ImageListe ist, dann nur InitSize und
+ // GrowSize schreiben
+ if ( !bImageList || !rImageList.mpImplData->mnCount )
+ {
+ BOOL bSaveImageList = FALSE;
+ rOStream << rImageList.mnInitSize;
+ rOStream << rImageList.mnGrowSize;
+ rOStream << bSaveImageList;
+ return rOStream;
+ }
+
+ // Normale Daten schreiben
+ rOStream << rImageList.mpImplData->mnCount;
+ rOStream << rImageList.mnGrowSize;
+ rOStream << bImageList;
+ rOStream << rImageList.mpImplData->maImageSize.Width();
+ rOStream << rImageList.mpImplData->maImageSize.Height();
+
+ // Array schreiben und feststellen, welche Eintraege gespeichert werden
+ // muessen
+ USHORT* mpPosAry = new USHORT[rImageList.mpImplData->mnCount];
+ USHORT nPosCount = 0;
+ for ( USHORT i = 0; i < rImageList.mpImplData->mnArySize; i++ )
+ {
+ if ( rImageList.mpImplData->mpAry[i].mnId )
+ {
+ rOStream << rImageList.mpImplData->mpAry[i].mnId;
+ mpPosAry[nPosCount] = i;
+ nPosCount++;
+ }
+ }
+
+ // Bitmaps rausschreiben
+ Bitmap aBmp;
+ BYTE bMaskBitmap = (BYTE)rImageList.mpImplData->mpImageBitmap->HasMaskBitmap();
+ BYTE bMaskColor = (BYTE)rImageList.mpImplData->mpImageBitmap->HasMaskColor();
+ aBmp = rImageList.mpImplData->mpImageBitmap->GetBitmap( nPosCount, mpPosAry );
+ rOStream << aBmp;
+ rOStream << bMaskBitmap;
+ if ( bMaskBitmap )
+ {
+ aBmp = rImageList.mpImplData->mpImageBitmap->GetMaskBitmap( nPosCount, mpPosAry );
+ rOStream << aBmp;
+ }
+ rOStream << bMaskColor;
+ if ( bMaskColor )
+ {
+ Color aColor = rImageList.mpImplData->mpImageBitmap->GetMaskColor();
+ rOStream << aColor;
+ }
+
+ // Temporaeres Array loeschen
+ delete mpPosAry;
+
+ return rOStream;
+}
+
+// =======================================================================
+
+void OutputDevice::DrawImage( const Point& rPos, const Image& rImage,
+ USHORT nStyle )
+{
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER,
+ "DrawImage(): Images can't be drawn on any mprinter" );
+
+ if( !rImage.mpImplData )
+ return;
+
+ switch( rImage.mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ {
+ DrawBitmap( rPos, *((Bitmap*)rImage.mpImplData->mpData) );
+ }
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+
+ if ( !pData->mpImageBitmap )
+ {
+ Size aSize = pData->maBmp.GetSizePixel();
+ pData->mpImageBitmap = new ImplImageBmp;
+ pData->mpImageBitmap->Create( pData->maBmp, pData->maMaskBmp,
+ pData->maColor, pData->mbColor,
+ aSize.Width(), aSize.Height(),
+ 1 );
+ }
+
+ pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ pData->mpImplData->mpImageBitmap->Draw( pData->mnIndex, this, rPos, nStyle );
+ }
+ break;
+ }
+}
+
+// =======================================================================
+
+void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
+ const Image& rImage, USHORT nStyle )
+{
+ DBG_CHKOBJ( &rImage, Image, NULL );
+ DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER,
+ "DrawImage(): Images can't be drawn on any mprinter" );
+
+ if( !rImage.mpImplData )
+ return;
+
+ switch( rImage.mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ {
+ DrawBitmap( rPos, rSize, *((Bitmap*)rImage.mpImplData->mpData) );
+ }
+ break;
+
+ case IMAGETYPE_IMAGE:
+ {
+ ImplImageData* pData = (ImplImageData*)rImage.mpImplData->mpData;
+
+ if ( !pData->mpImageBitmap )
+ {
+ Size aSize = pData->maBmp.GetSizePixel();
+ pData->mpImageBitmap = new ImplImageBmp;
+ pData->mpImageBitmap->Create( pData->maBmp, pData->maMaskBmp,
+ pData->maColor, pData->mbColor,
+ aSize.Width(), aSize.Height(),
+ 1 );
+ }
+
+ pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
+ }
+ break;
+
+ case IMAGETYPE_IMAGEREF:
+ {
+ ImplImageRefData* pData = (ImplImageRefData*)rImage.mpImplData->mpData;
+ pData->mpImplData->mpImageBitmap->Draw( pData->mnIndex, this, rPos, nStyle, &rSize );
+ }
+ break;
+ }
+}
diff --git a/vcl/source/gdi/imgcons.cxx b/vcl/source/gdi/imgcons.cxx
new file mode 100644
index 000000000000..d20f9c26f1c9
--- /dev/null
+++ b/vcl/source/gdi/imgcons.cxx
@@ -0,0 +1,593 @@
+/*************************************************************************
+ *
+ * $RCSfile: imgcons.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <bmpacc.hxx>
+#include <bitmapex.hxx>
+#include <image.hxx>
+#include <imgcons.hxx>
+
+// -------------------
+// - ImplColorMapper -
+// -------------------
+
+class ImplColorMapper
+{
+ Color maCol;
+ ULONG mnR;
+ ULONG mnG;
+ ULONG mnB;
+ ULONG mnT;
+ ULONG mnRShift;
+ ULONG mnGShift;
+ ULONG mnBShift;
+ ULONG mnTShift;
+
+ ULONG ImplCalcMaskShift( ULONG nVal );
+
+public:
+
+ ImplColorMapper( ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nTMask );
+ ~ImplColorMapper();
+
+ const Color& ImplGetColor( ULONG nColor )
+ {
+ maCol.SetRed( (UINT8) ( ( nColor & mnR ) >> mnRShift ) );
+ maCol.SetGreen( (UINT8) ( ( nColor & mnG ) >> mnGShift ) );
+ maCol.SetBlue( (UINT8) ( ( nColor & mnB ) >> mnBShift ) );
+ maCol.SetTransparency( (UINT8) ( ( nColor & mnT ) >> mnTShift ) );
+ return maCol;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+ImplColorMapper::ImplColorMapper( ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nTMask ) :
+ mnR( nRMask ),
+ mnG( nGMask ),
+ mnB( nBMask ),
+ mnT( nTMask )
+{
+ mnRShift = ImplCalcMaskShift( mnR );
+ mnGShift = ImplCalcMaskShift( mnG );
+ mnBShift = ImplCalcMaskShift( mnB );
+ mnTShift = ImplCalcMaskShift( mnT );
+}
+
+// -----------------------------------------------------------------------------
+
+ImplColorMapper::~ImplColorMapper()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ULONG ImplColorMapper::ImplCalcMaskShift( ULONG nVal )
+{
+ DBG_ASSERT( nVal > 0, "Mask has no value!" );
+
+ ULONG nRet = 0UL;
+
+ for( ULONG i = 0UL; i < 32; i++ )
+ {
+ if( nVal & ( 1UL << i ) )
+ {
+ nRet = i;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------
+// - ImageConsumer -
+// -----------------
+
+ImageConsumer::ImageConsumer() :
+ mnStatus( 0UL ),
+ mpPal ( NULL ),
+ mpMapper( NULL ),
+ mbTrans ( FALSE )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImageConsumer::~ImageConsumer()
+{
+ delete[] mpPal;
+ delete mpMapper;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::Init( ULONG nWidth, ULONG nHeight )
+{
+ maSize = Size( nWidth, nHeight );
+ maBitmap = maMask = Bitmap();
+ mnStatus = 0UL;
+ mbTrans = FALSE;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetColorModel( USHORT nBitCount,
+ ULONG nPalEntries, const ULONG* pRGBAPal,
+ ULONG nRMask, ULONG nGMask, ULONG nBMask, ULONG nAMask )
+{
+ DBG_ASSERT( maSize.Width() && maSize.Height(), "Missing call to ImageConsumer::Init(...)!" );
+
+ BitmapPalette aPal( Min( (USHORT) nPalEntries, (USHORT) 256 ) );
+
+ if( nPalEntries )
+ {
+ BitmapColor aCol;
+ const ULONG* pTmp = pRGBAPal;
+
+ delete mpMapper;
+ mpMapper = NULL;
+
+ delete[] mpPal;
+ mpPal = new Color[ nPalEntries ];
+
+ for( ULONG i = 0; i < nPalEntries; i++, pTmp++ )
+ {
+ Color& rCol = mpPal[ i ];
+ BYTE cVal;
+
+ cVal = (BYTE) ( ( *pTmp & 0xff000000UL ) >> 24UL );
+ rCol.SetRed( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetRed( cVal );
+
+ cVal = (BYTE) ( ( *pTmp & 0x00ff0000UL ) >> 16UL );
+ rCol.SetGreen( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetGreen( cVal );
+
+ cVal = (BYTE) ( ( *pTmp & 0x0000ff00UL ) >> 8UL );
+ rCol.SetBlue( cVal );
+ if( i < 256UL )
+ aPal[ (USHORT) i ].SetBlue( cVal );
+
+ rCol.SetTransparency( (BYTE) ( ( *pTmp & 0x000000ffUL ) ) );
+ }
+
+ if( nBitCount <= 1 )
+ nBitCount = 1;
+ else if( nBitCount <= 4 )
+ nBitCount = 4;
+ else if( nBitCount <= 8 )
+ nBitCount = 8;
+ else
+ nBitCount = 24;
+ }
+ else
+ {
+ delete mpMapper;
+ mpMapper = new ImplColorMapper( nRMask, nGMask, nBMask, nAMask );
+
+ delete[] mpPal;
+ mpPal = NULL;
+
+ nBitCount = 24;
+ }
+
+ if( !maBitmap )
+ {
+
+ maBitmap = Bitmap( maSize, nBitCount, &aPal );
+ maMask = Bitmap( maSize, 1 );
+ maMask.Erase( COL_BLACK );
+ mbTrans = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetPixelsByBytes( ULONG nConsX, ULONG nConsY,
+ ULONG nConsWidth, ULONG nConsHeight,
+ const BYTE* pData, ULONG nOffset, ULONG nScanSize )
+{
+ DBG_ASSERT( !!maBitmap && !!maMask, "Missing call to ImageConsumer::SetColorModel(...)!" );
+
+ BitmapWriteAccess* pBmpAcc = maBitmap.AcquireWriteAccess();
+ BitmapWriteAccess* pMskAcc = maMask.AcquireWriteAccess();
+
+ if( pBmpAcc && pMskAcc )
+ {
+ const long nWidth = pBmpAcc->Width();
+ const long nHeight = pBmpAcc->Height();
+
+ maChangedRect = Rectangle( Point(), Size( nWidth, nHeight ) );
+ maChangedRect.Intersection( Rectangle( Point( nConsX, nConsY ), Size( nConsWidth, nConsHeight ) ) );
+
+ if( !maChangedRect.IsEmpty() )
+ {
+ const long nStartX = maChangedRect.Left();
+ const long nEndX = maChangedRect.Right();
+ const long nStartY = maChangedRect.Top();
+ const long nEndY = maChangedRect.Bottom();
+
+ if( mpMapper && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const Color& rCol = mpMapper->ImplGetColor( *pTmp++ );
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() <= 8 ) )
+ {
+ BitmapColor aIndex( (BYTE) 0 );
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const BYTE cIndex = *pTmp++;
+ const Color& rCol = mpPal[ cIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aIndex.SetIndex( cIndex );
+ pBmpAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const BYTE* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const BYTE cIndex = *pTmp++;
+ const Color& rCol = mpPal[ cIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else
+ {
+ DBG_ERROR( "Producer format error!" );
+ maChangedRect.SetEmpty();
+ }
+ }
+ }
+ else
+ maChangedRect.SetEmpty();
+
+ maBitmap.ReleaseAccess( pBmpAcc );
+ maMask.ReleaseAccess( pMskAcc );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::SetPixelsByLongs( ULONG nConsX, ULONG nConsY,
+ ULONG nConsWidth, ULONG nConsHeight,
+ const ULONG* pData, ULONG nOffset, ULONG nScanSize )
+{
+ DBG_ASSERT( !!maBitmap && !!maMask, "Missing call to ImageConsumer::SetColorModel(...)!" );
+
+ BitmapWriteAccess* pBmpAcc = maBitmap.AcquireWriteAccess();
+ BitmapWriteAccess* pMskAcc = maMask.AcquireWriteAccess();
+
+ if( pBmpAcc && pMskAcc )
+ {
+ const long nWidth = pBmpAcc->Width();
+ const long nHeight = pBmpAcc->Height();
+
+ maChangedRect = Rectangle( Point(), Size( nWidth, nHeight ) );
+ maChangedRect.Intersection( Rectangle( Point( nConsX, nConsY ), Size( nConsWidth, nConsHeight ) ) );
+
+ if( !maChangedRect.IsEmpty() )
+ {
+ const long nStartX = maChangedRect.Left();
+ const long nEndX = maChangedRect.Right();
+ const long nStartY = maChangedRect.Top();
+ const long nEndY = maChangedRect.Bottom();
+
+ if( mpMapper && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const Color& rCol = mpMapper->ImplGetColor( *pTmp++ );
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() <= 8 ) )
+ {
+ BitmapColor aIndex( (BYTE) 0 );
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const ULONG nIndex = *pTmp++;
+ const Color& rCol = mpPal[ nIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aIndex.SetIndex( (BYTE) nIndex );
+ pBmpAcc->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else if( mpPal && ( pBmpAcc->GetBitCount() > 8 ) )
+ {
+ BitmapColor aCol;
+ BitmapColor aMskWhite( pMskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ for( long nY = nStartY; nY <= nEndY; nY++ )
+ {
+ const ULONG* pTmp = pData + ( nY - nStartY ) * nScanSize + nOffset;
+
+ for( long nX = nStartX; nX <= nEndX; nX++ )
+ {
+ const ULONG nIndex = *pTmp++;
+ const Color& rCol = mpPal[ nIndex ];
+
+ // 0: Transparent; >0: Non-Transparent
+ if( !rCol.GetTransparency() )
+ {
+ pMskAcc->SetPixel( nY, nX, aMskWhite );
+ mbTrans = TRUE;
+ }
+ else
+ {
+ aCol.SetRed( rCol.GetRed() );
+ aCol.SetGreen( rCol.GetGreen() );
+ aCol.SetBlue( rCol.GetBlue() );
+ pBmpAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ DataChanged();
+ }
+ else
+ {
+ DBG_ERROR( "Producer format error!" );
+ maChangedRect.SetEmpty();
+ }
+ }
+ }
+ else
+ maChangedRect.SetEmpty();
+
+ maBitmap.ReleaseAccess( pBmpAcc );
+ maMask.ReleaseAccess( pMskAcc );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::Completed( ULONG nStatus /*, ImageProducer& rProducer */ )
+{
+ delete mpMapper;
+ mpMapper = NULL;
+ delete[] mpPal;
+ mpPal = NULL;
+ maSize = Size();
+ mnStatus = nStatus;
+
+ switch( nStatus )
+ {
+ case( SINGLEFRAMEDONE ):
+ case( STATICIMAGEDONE ):
+ {
+ if( !mbTrans )
+ maMask = Bitmap();
+ }
+ break;
+
+ case( IMAGEERROR ):
+ case( IMAGEABORTED ):
+ maBitmap = maMask = Bitmap();
+ break;
+
+ default:
+ break;
+ }
+
+// rProducer.RemoveConsumer( *this );
+
+ if( maDoneLink.IsSet() )
+ maDoneLink.Call( this );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImageConsumer::DataChanged()
+{
+ if( maChgLink.IsSet() )
+ maChgLink.Call( this );
+}
+
+// -----------------------------------------------------------------------------
+
+ULONG ImageConsumer::GetStatus() const
+{
+ return mnStatus;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImageConsumer::GetData( BitmapEx& rBmpEx ) const
+{
+ const BOOL bRet = ( SINGLEFRAMEDONE == mnStatus || STATICIMAGEDONE == mnStatus );
+
+ if( bRet )
+ {
+ if( !!maMask )
+ rBmpEx = BitmapEx( maBitmap, maMask );
+ else
+ rBmpEx = BitmapEx( maBitmap );
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImageConsumer::GetData( Image& rImage ) const
+{
+ const BOOL bRet = ( SINGLEFRAMEDONE == mnStatus || STATICIMAGEDONE == mnStatus );
+
+ if( bRet )
+ {
+ if( !!maMask )
+ rImage = Image( maBitmap, maMask );
+ else
+ rImage = Image( maBitmap );
+ }
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/impanmvw.cxx b/vcl/source/gdi/impanmvw.cxx
new file mode 100644
index 000000000000..fc3a943c0471
--- /dev/null
+++ b/vcl/source/gdi/impanmvw.cxx
@@ -0,0 +1,392 @@
+/*************************************************************************
+ *
+ * $RCSfile: impanmvw.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPANMVW_CXX
+
+#define private public
+
+#include "impanmvw.hxx"
+#include "virdev.hxx"
+#include "window.hxx"
+#include "salbtype.hxx"
+
+// ----------------
+// - ImplAnimView -
+// ----------------
+
+ImplAnimView::ImplAnimView( Animation* pParent, OutputDevice* pOut,
+ const Point& rPt, const Size& rSz,
+ ULONG nExtraData,
+ OutputDevice* pFirstFrameOutDev ) :
+ mpParent ( pParent ),
+ mpOut ( pFirstFrameOutDev ? pFirstFrameOutDev : pOut ),
+ maPt ( rPt ),
+ maSz ( rSz ),
+ maClip ( mpOut->GetClipRegion() ),
+ maSzPix ( mpOut->LogicToPixel( maSz ) ),
+ mnExtraData ( nExtraData ),
+ mpBackground ( new VirtualDevice ),
+ mpRestore ( new VirtualDevice ),
+ meLastDisposal ( DISPOSE_BACK ),
+ mbPause ( FALSE ),
+ mbMarked ( FALSE ),
+ mbHMirr ( maSz.Width() < 0L ),
+ mbVMirr ( maSz.Height() < 0L )
+{
+ mpParent->ImplIncAnimCount();
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ {
+ maDispPt.X() = maPt.X() + maSz.Width() + 1L;
+ maDispSz.Width() = -maSz.Width();
+ maSzPix.Width() = -maSzPix.Width();
+ }
+ else
+ {
+ maDispPt.X() = maPt.X();
+ maDispSz.Width() = maSz.Width();
+ }
+
+ // mirrored vertically?
+ if( mbVMirr )
+ {
+ maDispPt.Y() = maPt.Y() + maSz.Height() + 1L;
+ maDispSz.Height() = -maSz.Height();
+ maSzPix.Height() = -maSzPix.Height();
+ }
+ else
+ {
+ maDispPt.Y() = maPt.Y();
+ maDispSz.Height() = maSz.Height();
+ }
+
+ // save background
+ mpBackground->SetOutputSizePixel( maSzPix );
+
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ MapMode aTempMap( mpOut->GetMapMode() );
+ aTempMap.SetOrigin( Point() );
+ mpBackground->SetMapMode( aTempMap );
+ ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
+ mpBackground->SetMapMode( MapMode() );
+ }
+ else
+ mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+
+ // initial drawing to actual position
+ ImplDrawToPos( mpParent->ImplGetCurPos() );
+
+ // if first frame OutputDevice is set, update variables now for real OutputDevice
+ if( pFirstFrameOutDev )
+ maClip = ( mpOut = pOut )->GetClipRegion();
+}
+
+// ------------------------------------------------------------------------
+
+ImplAnimView::~ImplAnimView()
+{
+ delete mpBackground;
+ delete mpRestore;
+
+ mpParent->ImplDecAnimCount();
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImplAnimView::ImplMatches( OutputDevice* pOut, long nExtraData ) const
+{
+ BOOL bRet = FALSE;
+
+ if( nExtraData )
+ {
+ if( ( mnExtraData == nExtraData ) && ( !pOut || ( pOut == mpOut ) ) )
+ bRet = TRUE;
+ }
+ else if( !pOut || ( pOut == mpOut ) )
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix )
+{
+ const Size& rAnmSize = mpParent->GetDisplaySizePixel();
+ Point aPt2( rAnm.aPosPix.X() + rAnm.aSizePix.Width() - 1L,
+ rAnm.aPosPix.Y() + rAnm.aSizePix.Height() - 1L );
+ double fFactX, fFactY;
+
+ // calculate x scaling
+ if( rAnmSize.Width() > 1L )
+ fFactX = (double) ( maSzPix.Width() - 1L ) / ( rAnmSize.Width() - 1L );
+ else
+ fFactX = 1.0;
+
+ // calculate y scaling
+ if( rAnmSize.Height() > 1L )
+ fFactY = (double) ( maSzPix.Height() - 1L ) / ( rAnmSize.Height() - 1L );
+ else
+ fFactY = 1.0;
+
+ rPosPix.X() = FRound( rAnm.aPosPix.X() * fFactX );
+ rPosPix.Y() = FRound( rAnm.aPosPix.Y() * fFactY );
+
+ aPt2.X() = FRound( aPt2.X() * fFactX );
+ aPt2.Y() = FRound( aPt2.Y() * fFactY );
+
+ rSizePix.Width() = aPt2.X() - rPosPix.X() + 1L;
+ rSizePix.Height() = aPt2.Y() - rPosPix.Y() + 1L;
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ rPosPix.X() = maSzPix.Width() - 1L - aPt2.X();
+
+ // mirrored vertically?
+ if( mbVMirr )
+ rPosPix.Y() = maSzPix.Height() - 1L - aPt2.Y();
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDrawToPos( ULONG nPos )
+{
+ VirtualDevice aVDev;
+ Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
+
+ aVDev.SetOutputSizePixel( maSzPix, FALSE );
+ nPos = Min( nPos, (ULONG) mpParent->Count() - 1UL );
+
+ for( ULONG i = 0UL; i <= nPos; i++ )
+ ImplDraw( i, &aVDev );
+
+ if( pOldClip )
+ mpOut->SetClipRegion( maClip );
+
+ mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, aVDev );
+
+ if( pOldClip )
+ {
+ mpOut->SetClipRegion( *pOldClip );
+ delete pOldClip;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDraw( ULONG nPos )
+{
+ ImplDraw( nPos, NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplDraw( ULONG nPos, VirtualDevice* pVDev )
+{
+ Rectangle aOutRect( mpOut->PixelToLogic( Point() ), mpOut->GetOutputSize() );
+
+ // check, if output lies out of display
+ if( aOutRect.Intersection( Rectangle( maDispPt, maDispSz ) ).IsEmpty() )
+ ImplSetMarked( TRUE );
+ else if( !mbPause )
+ {
+ VirtualDevice* pDev;
+ Point aPosPix;
+ Point aBmpPosPix;
+ Size aSizePix;
+ Size aBmpSizePix;
+ const ULONG nLastPos = mpParent->Count() - 1;
+ const AnimationBitmap& rAnm = mpParent->Get( (USHORT) ( mnActPos = Min( nPos, nLastPos ) ) );
+
+ ImplGetPosSize( rAnm, aPosPix, aSizePix );
+
+ // mirrored horizontically?
+ if( mbHMirr )
+ {
+ aBmpPosPix.X() = aPosPix.X() + aSizePix.Width() - 1L;
+ aBmpSizePix.Width() = -aSizePix.Width();
+ }
+ else
+ {
+ aBmpPosPix.X() = aPosPix.X();
+ aBmpSizePix.Width() = aSizePix.Width();
+ }
+
+ // mirrored vertically?
+ if( mbVMirr )
+ {
+ aBmpPosPix.Y() = aPosPix.Y() + aSizePix.Height() - 1L;
+ aBmpSizePix.Height() = -aSizePix.Height();
+ }
+ else
+ {
+ aBmpPosPix.Y() = aPosPix.Y();
+ aBmpSizePix.Height() = aSizePix.Height();
+ }
+
+ // get output device
+ if( !pVDev )
+ {
+ pDev = new VirtualDevice;
+ pDev->SetOutputSizePixel( maSzPix, FALSE );
+ pDev->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+ }
+ else
+ pDev = pVDev;
+
+ // restore background after each run
+ if( !nPos )
+ {
+ meLastDisposal = DISPOSE_BACK;
+ maRestPt = Point();
+ maRestSz = maSzPix;
+ }
+
+ // restore
+ if( ( DISPOSE_NOT != meLastDisposal ) && maRestSz.Width() && maRestSz.Height() )
+ {
+ if( DISPOSE_BACK == meLastDisposal )
+ pDev->DrawOutDev( maRestPt, maRestSz, maRestPt, maRestSz, *mpBackground );
+ else
+ pDev->DrawOutDev( maRestPt, maRestSz, Point(), maRestSz, *mpRestore );
+ }
+
+ meLastDisposal = rAnm.eDisposal;
+ maRestPt = aPosPix;
+ maRestSz = aSizePix;
+
+ // Was muessen wir beim naechsten Mal restaurieren ?
+ // ==> ggf. in eine Bitmap stecken, ansonsten SaveBitmap
+ // aus Speichergruenden loeschen
+ if( ( meLastDisposal == DISPOSE_BACK ) || ( meLastDisposal == DISPOSE_NOT ) )
+ mpRestore->SetOutputSizePixel( Size( 1, 1 ), FALSE );
+ else
+ {
+ mpRestore->SetOutputSizePixel( maRestSz, FALSE );
+ mpRestore->DrawOutDev( Point(), maRestSz, aPosPix, aSizePix, *pDev );
+ }
+
+ pDev->DrawBitmapEx( aBmpPosPix, aBmpSizePix, rAnm.aBmpEx );
+
+ if( !pVDev )
+ {
+ Region* pOldClip = !maClip.IsNull() ? new Region( mpOut->GetClipRegion() ) : NULL;
+
+ if( pOldClip )
+ mpOut->SetClipRegion( maClip );
+
+ mpOut->DrawOutDev( maDispPt, maDispSz, Point(), maSzPix, *pDev );
+
+ if( pOldClip )
+ {
+ mpOut->SetClipRegion( *pOldClip );
+ delete pOldClip;
+ }
+
+ delete pDev;
+
+#ifndef REMOTE_APPSERVER
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ ( (Window*) mpOut )->Sync();
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImplAnimView::ImplRepaint()
+{
+ const BOOL bOldPause = mbPause;
+
+ if( mpOut->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ MapMode aTempMap( mpOut->GetMapMode() );
+ aTempMap.SetOrigin( Point() );
+ mpBackground->SetMapMode( aTempMap );
+ ( (Window*) mpOut )->SaveBackground( maDispPt, maDispSz, Point(), *mpBackground );
+ mpBackground->SetMapMode( MapMode() );
+ }
+ else
+ mpBackground->DrawOutDev( Point(), maSzPix, maDispPt, maDispSz, *mpOut );
+
+ mbPause = FALSE;
+ ImplDrawToPos( mnActPos );
+ mbPause = bOldPause;
+}
+
+// ------------------------------------------------------------------------
+
+AInfo* ImplAnimView::ImplCreateAInfo() const
+{
+ AInfo* pAInfo = new AInfo;
+
+ pAInfo->aStartOrg = maPt;
+ pAInfo->aStartSize = maSz;
+ pAInfo->pOutDev = mpOut;
+ pAInfo->pViewData = (void*) this;
+ pAInfo->nExtraData = mnExtraData;
+ pAInfo->bPause = mbPause;
+
+ return pAInfo;
+}
diff --git a/vcl/source/gdi/impanmvw.hxx b/vcl/source/gdi/impanmvw.hxx
new file mode 100644
index 000000000000..fdefa420cc62
--- /dev/null
+++ b/vcl/source/gdi/impanmvw.hxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * $RCSfile: impanmvw.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_IMPANMVW_HXX
+#define _SV_IMPANMVW_HXX
+
+#include "animate.hxx"
+
+// ----------------
+// - ImplAnimView -
+// ----------------
+
+class Animation;
+class OutputDevice;
+class VirtualDevice;
+struct AnimationBitmap;
+
+class ImplAnimView
+{
+private:
+
+ Animation* mpParent;
+ OutputDevice* mpOut;
+ long mnExtraData;
+ Point maPt;
+ Point maDispPt;
+ Point maRestPt;
+ Size maSz;
+ Size maSzPix;
+ Size maDispSz;
+ Size maRestSz;
+ MapMode maMap;
+ Region maClip;
+ VirtualDevice* mpBackground;
+ VirtualDevice* mpRestore;
+ ULONG mnActPos;
+ Disposal meLastDisposal;
+ BOOL mbPause;
+ BOOL mbFirst;
+ BOOL mbMarked;
+ BOOL mbHMirr;
+ BOOL mbVMirr;
+
+ void ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix );
+ void ImplDraw( ULONG nPos, VirtualDevice* pVDev );
+
+public:
+
+ ImplAnimView( Animation* pParent, OutputDevice* pOut,
+ const Point& rPt, const Size& rSz, ULONG nExtraData,
+ OutputDevice* pFirstFrameOutDev = NULL );
+ ~ImplAnimView();
+
+ BOOL ImplMatches( OutputDevice* pOut, long nExtraData ) const;
+ void ImplDrawToPos( ULONG nPos );
+ void ImplDraw( ULONG nPos );
+ void ImplRepaint();
+ AInfo* ImplCreateAInfo() const;
+
+ const Point& ImplGetOutPos() const { return maPt; }
+
+ const Size& ImplGetOutSize() const { return maSz; }
+ const Size& ImplGetOutSizePix() const { return maSzPix; }
+
+ void ImplPause( BOOL bPause ) { mbPause = bPause; }
+ BOOL ImplIsPause() const { return mbPause; }
+
+ void ImplSetMarked( BOOL bMarked ) { mbMarked = bMarked; }
+ BOOL ImplIsMarked() const { return mbMarked; }
+};
+
+#endif
diff --git a/vcl/source/gdi/impbmp.cxx b/vcl/source/gdi/impbmp.cxx
new file mode 100644
index 000000000000..3cb648163026
--- /dev/null
+++ b/vcl/source/gdi/impbmp.cxx
@@ -0,0 +1,309 @@
+/*************************************************************************
+ *
+ * $RCSfile: impbmp.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPBMP_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALBMP_HXX
+#include <salbmp.hxx>
+#endif
+#else
+#include <indbmp.hxx>
+#ifndef _SV_RMBITMAP_HXX
+#include <rmbitmap.hxx>
+#endif
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#include <impbmp.hxx>
+#include <bitmap.hxx>
+
+// --------------
+// - ImpBitmap -
+// --------------
+
+ImpBitmap::ImpBitmap() :
+ mnRefCount ( 1UL ),
+ mnChecksum ( 0UL ),
+ mpRMBitmap ( NULL ),
+#ifndef REMOTE_APPSERVER
+ mpSalBitmap ( new SalBitmap )
+#else
+ mpSalBitmap ( new ImplServerBitmap )
+#endif
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImpBitmap::~ImpBitmap()
+{
+#ifdef REMOTE_APPSERVER
+ ImplReleaseRemoteBmp();
+#endif
+ delete mpSalBitmap;
+}
+
+// -----------------------------------------------------------------------
+#ifndef REMOTE_APPSERVER
+void ImpBitmap::ImplSetSalBitmap( SalBitmap* pBitmap )
+#else
+void ImpBitmap::ImplSetSalBitmap( ImplServerBitmap* pBitmap )
+#endif
+{
+ delete mpSalBitmap, mpSalBitmap = pBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
+{
+ return mpSalBitmap->Create( rSize, nBitCount, rPal );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap )
+{
+ mnChecksum = rImpBitmap.mnChecksum;
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap, SalGraphics* pGraphics )
+{
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap, pGraphics );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplCreate( const ImpBitmap& rImpBitmap, USHORT nNewBitCount )
+{
+ return mpSalBitmap->Create( *rImpBitmap.mpSalBitmap, nNewBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDestroy()
+{
+ mpSalBitmap->Destroy();
+}
+
+// -----------------------------------------------------------------------
+
+Size ImpBitmap::ImplGetSize() const
+{
+#ifdef REMOTE_APPSERVER
+ if( ImplIsGetPrepared() )
+ return mpRMBitmap->GetSize();
+ else
+#endif
+ return mpSalBitmap->GetSize();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ImpBitmap::ImplGetBitCount() const
+{
+ USHORT nBitCount;
+
+#ifdef REMOTE_APPSERVER
+ if( ImplIsGetPrepared() )
+ nBitCount = mpRMBitmap->GetBitCount();
+ else
+#endif
+ nBitCount = mpSalBitmap->GetBitCount();
+
+ return( ( nBitCount <= 1 ) ? 1 : ( nBitCount <= 4 ) ? 4 : ( nBitCount <= 8 ) ? 8 : 24 );
+}
+
+// -----------------------------------------------------------------------
+
+BitmapBuffer* ImpBitmap::ImplAcquireBuffer( BOOL bReadOnly )
+{
+ return mpSalBitmap->AcquireBuffer( bReadOnly );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplReleaseBuffer( BitmapBuffer* pBuffer, BOOL bReadOnly )
+{
+ mpSalBitmap->ReleaseBuffer( pBuffer, bReadOnly );
+
+ if( !bReadOnly )
+ mnChecksum = 0;
+}
+
+#ifdef REMOTE_APPSERVER
+
+RMBitmap* ImpBitmap::ImplGetRemoteBmp()
+{
+ return mpRMBitmap;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplCreateRemoteBmp( const Bitmap& rBitmap )
+{
+ DBG_ASSERT( !mpRMBitmap, "ImplCreateRemoteBmp( Bitmap& rBitmap )???" );
+
+ mpRMBitmap = new RMBitmap( &(Bitmap&) rBitmap );
+ mpRMBitmap->Create();
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplCreateRemoteBmp( const Bitmap& rBitmap,
+ OutputDevice* pOut,
+ const Point& rPt, const Size& rSz )
+{
+ DBG_ASSERT( !mpRMBitmap, "ImplCreateRemoteBmp( Bitmap& rBitmap )???" );
+
+ mpRMBitmap = new RMBitmap( &(Bitmap&) rBitmap );
+ mpRMBitmap->CreateGet( pOut, rPt, rSz );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplReleaseRemoteBmp()
+{
+ delete mpRMBitmap;
+ mpRMBitmap = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmp( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->Draw( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpEx( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Bitmap& rMask )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rMask );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpAlpha( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const AlphaMask& rAlpha )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rAlpha );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplDrawRemoteBmpMask( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Color& rColor )
+{
+ if( mpRMBitmap )
+ mpRMBitmap->DrawMask( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rColor );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImpBitmap::ImplIsGetPrepared() const
+{
+ return( mpRMBitmap ? mpRMBitmap->IsGetPrepared() : FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void ImpBitmap::ImplResolveGet()
+{
+ if( mpRMBitmap )
+ {
+ Bitmap aBmp;
+ mpRMBitmap->Get( aBmp );
+ ImpBitmap* pGetImpBmp = aBmp.ImplGetImpBitmap();
+
+ if( pGetImpBmp )
+ {
+ // wir nehmen der gegetteten Bitmap einfach
+ // die SalBitmap weg; Null-Setzen nicht vergessen,
+ // da die Bitmap die SalBitmap sonst abraeumt
+ delete mpSalBitmap;
+ mpSalBitmap = pGetImpBmp->mpSalBitmap;
+ pGetImpBmp->mpSalBitmap = NULL;
+ }
+ }
+}
+
+#endif
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
new file mode 100644
index 000000000000..a53739ec6041
--- /dev/null
+++ b/vcl/source/gdi/impgraph.cxx
@@ -0,0 +1,1571 @@
+/*************************************************************************
+ *
+ * $RCSfile: impgraph.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPGRAPH_CXX
+
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _TOOLS_TEMPFILE_HXX
+#include <tools/tempfile.hxx>
+#endif
+#ifndef _UCBHELPER_CONTENT_HXX
+#include <ucbhelper/content.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _NEW_HXX
+#include <tools/new.hxx>
+#endif
+#include <impgraph.hxx>
+#ifndef _GFXLINK_HXX
+#include <gfxlink.hxx>
+#endif
+#ifndef _SV_CVTGRF_HXX
+#include <cvtgrf.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define GRAPHIC_MAXPARTLEN 256000L
+#define GRAPHIC_MTFTOBMP_MAXEXT 2048
+#define GRAPHIC_STREAMBUFSIZE 8192UL
+
+#define SYS_WINMETAFILE 0x00000003UL
+#define SYS_WNTMETAFILE 0x00000004UL
+#define SYS_OS2METAFILE 0x00000005UL
+#define SYS_MACMETAFILE 0x00000006UL
+
+#define GRAPHIC_FORMAT_50 COMPAT_FORMAT( 'G', 'R', 'F', '5' )
+#define NATIVE_FORMAT_50 COMPAT_FORMAT( 'N', 'A', 'T', '5' )
+
+// ---------------
+// - ImpSwapFile -
+// ---------------
+
+struct ImpSwapFile
+{
+ String aSwapFileName;
+ USHORT nRefCount;
+};
+
+// -----------------
+// - Graphicreader -
+// -----------------
+
+GraphicReader::~GraphicReader()
+{
+}
+
+// --------------
+// - ImpGraphic -
+// --------------
+
+ImpGraphic::ImpGraphic() :
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_NONE ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const ImpGraphic& rImpGraphic ) :
+ maEx ( rImpGraphic.maEx ),
+ maMetaFile ( rImpGraphic.maMetaFile ),
+ mpContext ( NULL ),
+ mpSwapFile ( rImpGraphic.mpSwapFile ),
+ meType ( rImpGraphic.meType ),
+ maDocFileName ( rImpGraphic.maDocFileName ),
+ mnDocFilePos ( rImpGraphic.mnDocFilePos ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( rImpGraphic.mbSwapOut ),
+ mbSwapUnderway ( FALSE )
+{
+ if( mpSwapFile )
+ mpSwapFile->nRefCount++;
+
+ if( rImpGraphic.mpGfxLink )
+ mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
+ else
+ mpGfxLink = NULL;
+
+ if( rImpGraphic.mpAnimation )
+ {
+ mpAnimation = new Animation( *rImpGraphic.mpAnimation );
+ maEx = mpAnimation->GetBitmapEx();
+ }
+ else
+ mpAnimation = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
+ maEx ( rBitmap ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( !rBitmap ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
+ maEx ( rBitmapEx ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( !rBitmapEx ? GRAPHIC_NONE : GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
+ maEx ( rAnimation.GetBitmapEx() ),
+ mpAnimation ( new Animation( rAnimation ) ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_BITMAP ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
+ maMetaFile ( rMtf ),
+ mpAnimation ( NULL ),
+ mpContext ( NULL ),
+ mpSwapFile ( NULL ),
+ mpGfxLink ( NULL ),
+ meType ( GRAPHIC_GDIMETAFILE ),
+ mnDocFilePos ( 0UL ),
+ mnRefCount ( 1UL ),
+ mbSwapOut ( FALSE ),
+ mbSwapUnderway ( FALSE )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic::~ImpGraphic()
+{
+ ImplClear();
+
+ if( (ULONG) mpContext > 1UL )
+ delete mpContext;
+}
+
+// ------------------------------------------------------------------------
+
+ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
+{
+ if( &rImpGraphic != this )
+ {
+ if( !mbSwapUnderway )
+ ImplClear();
+
+ maMetaFile = rImpGraphic.maMetaFile;
+ meType = rImpGraphic.meType;
+
+ delete mpAnimation;
+
+ if ( rImpGraphic.mpAnimation )
+ {
+ mpAnimation = new Animation( *rImpGraphic.mpAnimation );
+ maEx = mpAnimation->GetBitmapEx();
+ }
+ else
+ {
+ mpAnimation = NULL;
+ maEx = rImpGraphic.maEx;
+ }
+
+ if( !mbSwapUnderway )
+ {
+ maDocFileName = rImpGraphic.maDocFileName;
+ mnDocFilePos = rImpGraphic.mnDocFilePos;
+ mbSwapOut = rImpGraphic.mbSwapOut;
+ mpSwapFile = rImpGraphic.mpSwapFile;
+
+ if( mpSwapFile )
+ mpSwapFile->nRefCount++;
+ }
+
+ delete mpGfxLink;
+
+ if( rImpGraphic.mpGfxLink )
+ mpGfxLink = new GfxLink( *rImpGraphic.mpGfxLink );
+ else
+ mpGfxLink = NULL;
+ }
+
+ return *this;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
+{
+ BOOL bRet = FALSE;
+
+ if( this == &rImpGraphic )
+ bRet = TRUE;
+ else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ bRet = TRUE;
+ break;
+
+ case( GRAPHIC_GDIMETAFILE ):
+ {
+ if( rImpGraphic.maMetaFile == maMetaFile )
+ bRet = TRUE;
+ }
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ {
+ if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) )
+ bRet = TRUE;
+ }
+ else if( !rImpGraphic.mpAnimation && ( rImpGraphic.maEx == maEx ) )
+ bRet = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplClearGraphics( BOOL bCreateSwapInfo )
+{
+ if( bCreateSwapInfo && !ImplIsSwapOut() )
+ {
+ maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
+ maSwapInfo.maPrefSize = ImplGetPrefSize();
+ }
+
+ maEx.Clear();
+ maMetaFile.Clear();
+
+ if( mpAnimation )
+ {
+ mpAnimation->Clear();
+ delete mpAnimation;
+ mpAnimation = NULL;
+ }
+
+ if( mpGfxLink )
+ {
+ delete mpGfxLink;
+ mpGfxLink = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplClear()
+{
+ if( mpSwapFile )
+ {
+ if( mpSwapFile->nRefCount > 1 )
+ mpSwapFile->nRefCount--;
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( mpSwapFile->aSwapFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ delete mpSwapFile;
+ }
+
+ mpSwapFile = NULL;
+ }
+
+ mbSwapOut = FALSE;
+ mnDocFilePos = 0UL;
+ maDocFileName.Erase();
+
+ // cleanup
+ ImplClearGraphics( FALSE );
+ meType = GRAPHIC_NONE;
+}
+
+// ------------------------------------------------------------------------
+
+GraphicType ImpGraphic::ImplGetType() const
+{
+ return meType;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetDefaultType()
+{
+ ImplClear();
+ meType = GRAPHIC_DEFAULT;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsSupportedGraphic() const
+{
+ return( meType != GRAPHIC_NONE );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsTransparent() const
+{
+ BOOL bRet;
+
+ if( meType == GRAPHIC_BITMAP )
+ bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsAlpha() const
+{
+ BOOL bRet;
+
+ if( meType == GRAPHIC_BITMAP )
+ bRet = ( NULL == mpAnimation ) && maEx.IsAlpha();
+ else
+ bRet = FALSE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsAnimated() const
+{
+ return( mpAnimation != NULL );
+}
+
+// ------------------------------------------------------------------------
+
+Bitmap ImpGraphic::ImplGetBitmap() const
+{
+ Bitmap aRetBmp;
+
+ if( meType == GRAPHIC_BITMAP )
+ {
+ const BitmapEx& rRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
+ const Color aReplaceColor( COL_WHITE );
+
+ aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
+ }
+ else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
+ {
+ VirtualDevice aVDev;
+ Size aSizePix( aVDev.LogicToPixel( maMetaFile.GetPrefSize(),
+ maMetaFile.GetPrefMapMode() ) );
+
+ if( aSizePix.Width() && aSizePix.Height() &&
+ ( aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT ) )
+ {
+ double fWH = (double) aSizePix.Width() / aSizePix.Height();
+
+ if( fWH <= 1.0 )
+ {
+ aSizePix.Width() = FRound( fWH * GRAPHIC_MTFTOBMP_MAXEXT );
+ aSizePix.Height() = GRAPHIC_MTFTOBMP_MAXEXT;
+ }
+ else
+ {
+ aSizePix.Width() = GRAPHIC_MTFTOBMP_MAXEXT;
+ aSizePix.Height() = FRound( GRAPHIC_MTFTOBMP_MAXEXT / fWH );
+ }
+ }
+
+ if( aVDev.SetOutputSizePixel( aSizePix ) )
+ {
+ const Point aPt;
+ ImplDraw( &aVDev, aPt, aSizePix );
+ aRetBmp = aVDev.GetBitmap( aPt, aSizePix );
+ }
+ }
+
+ if( !!aRetBmp )
+ {
+ aRetBmp.SetPrefMapMode( ImplGetPrefMapMode() );
+ aRetBmp.SetPrefSize( ImplGetPrefSize() );
+ }
+
+ return aRetBmp;
+}
+
+// ------------------------------------------------------------------------
+
+BitmapEx ImpGraphic::ImplGetBitmapEx() const
+{
+ BitmapEx aRetBmpEx;
+
+ if( meType == GRAPHIC_BITMAP )
+ aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
+ else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
+ {
+ const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
+ aRetBmpEx = BitmapEx( ImplGetBitmap(), aMonoMask.ImplGetBitmap() );
+ }
+
+ return aRetBmpEx;
+}
+
+// ------------------------------------------------------------------------
+
+Animation ImpGraphic::ImplGetAnimation() const
+{
+ Animation aAnimation;
+
+ if( mpAnimation )
+ aAnimation = *mpAnimation;
+
+ return aAnimation;
+}
+
+// ------------------------------------------------------------------------
+
+const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
+{
+ return maMetaFile;
+}
+
+// ------------------------------------------------------------------------
+
+Size ImpGraphic::ImplGetPrefSize() const
+{
+ Size aSize;
+
+ if( ImplIsSwapOut() )
+ aSize = maSwapInfo.maPrefSize;
+ else
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ aSize = maEx.GetPrefSize();
+
+ if( !aSize.Width() || !aSize.Height() )
+ aSize = maEx.GetSizePixel();
+ }
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ aSize = maMetaFile.GetPrefSize();
+ }
+ break;
+ }
+ }
+
+ return aSize;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
+{
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ maEx.SetPrefSize( rPrefSize );
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ maMetaFile.SetPrefSize( rPrefSize );
+ }
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+MapMode ImpGraphic::ImplGetPrefMapMode() const
+{
+ MapMode aMapMode;
+
+ if( ImplIsSwapOut() )
+ aMapMode = maSwapInfo.maPrefMapMode;
+ else
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ const Size aSize( maEx.GetPrefSize() );
+
+ if ( aSize.Width() && aSize.Height() )
+ aMapMode = maEx.GetPrefMapMode();
+ }
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ return maMetaFile.GetPrefMapMode();
+ }
+ break;
+ }
+ }
+
+ return aMapMode;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
+{
+ switch( meType )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ maEx.SetPrefMapMode( rPrefMapMode );
+ break;
+
+ default:
+ {
+ if( ImplIsSupportedGraphic() )
+ maMetaFile.SetPrefMapMode( rPrefMapMode );
+ }
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetSizeBytes() const
+{
+ ULONG nSizeBytes;
+
+ if( meType == GRAPHIC_BITMAP )
+ {
+ if( mpAnimation )
+ nSizeBytes = mpAnimation->GetSizeBytes();
+ else
+ nSizeBytes = maEx.GetSizeBytes();
+ }
+ else
+ nSizeBytes = 0UL;
+
+ return nSizeBytes;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if ( mpAnimation )
+ mpAnimation->Draw( pOutDev, rDestPt );
+ else
+ maEx.Draw( pOutDev, rDestPt );
+ }
+ break;
+
+ default:
+ ImplDraw( pOutDev, rDestPt, maMetaFile.GetPrefSize() );
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplDraw( OutputDevice* pOutDev,
+ const Point& rDestPt, const Size& rDestSize ) const
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ mpAnimation->Draw( pOutDev, rDestPt, rDestSize );
+ else
+ maEx.Draw( pOutDev, rDestPt, rDestSize );
+ }
+ break;
+
+ default:
+ {
+ ( (ImpGraphic*) this )->maMetaFile.WindStart();
+ ( (ImpGraphic*) this )->maMetaFile.Play( pOutDev, rDestPt, rDestSize );
+ ( (ImpGraphic*) this )->maMetaFile.WindStart();
+ }
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev,
+ const Point& rDestPt,
+ long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Start( pOutDev, rDestPt, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt,
+ const Size& rDestSize, long nExtraData,
+ OutputDevice* pFirstFrameOutDev )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
+{
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
+ mpAnimation->Stop( pOutDev, nExtraData );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetAnimationNotifyHdl( const Link& rLink )
+{
+ if( mpAnimation )
+ mpAnimation->SetNotifyHdl( rLink );
+}
+
+// ------------------------------------------------------------------------
+
+Link ImpGraphic::ImplGetAnimationNotifyHdl() const
+{
+ Link aLink;
+
+ if( mpAnimation )
+ aLink = mpAnimation->GetNotifyHdl();
+
+ return aLink;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetAnimationLoopCount() const
+{
+ return( mpAnimation ? mpAnimation->GetLoopCount() : 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplResetAnimationLoopCount()
+{
+ if( mpAnimation )
+ mpAnimation->ResetLoopCount();
+}
+
+// ------------------------------------------------------------------------
+
+List* ImpGraphic::ImplGetAnimationInfoList() const
+{
+ return( mpAnimation ? mpAnimation->GetAInfoList() : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+GraphicReader* ImpGraphic::ImplGetContext()
+{
+ return mpContext;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetContext( GraphicReader* pReader )
+{
+ mpContext = pReader;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetDocFileName( const String& rName, ULONG nFilePos )
+{
+ maDocFileName = rName;
+ mnDocFilePos = nFilePos;
+}
+
+// ------------------------------------------------------------------------
+
+const String& ImpGraphic::ImplGetDocFileName() const
+{
+ return maDocFileName;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetDocFilePos() const
+{
+ return mnDocFilePos;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplReadEmbedded( SvStream& rIStm, BOOL bSwap )
+{
+ MapMode aMapMode;
+ Size aSize;
+ const ULONG nStartPos = rIStm.Tell();
+ ULONG nId;
+ ULONG nHeaderLen;
+ long nType;
+ long nLen;
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+ BOOL bRet = FALSE;
+
+ if( !mbSwapUnderway )
+ {
+ const String aTempName( maDocFileName );
+ const ULONG nTempPos = mnDocFilePos;
+
+ ImplClear();
+
+ maDocFileName = aTempName;
+ mnDocFilePos = nTempPos;
+ }
+
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rIStm >> nId;
+
+ // check version
+ if( GRAPHIC_FORMAT_50 == nId )
+ {
+ // read new style header
+ VersionCompat* pCompat = new VersionCompat( rIStm, STREAM_READ );
+
+ rIStm >> nType;
+ rIStm >> nLen;
+ rIStm >> aSize;
+ rIStm >> aMapMode;
+
+ delete pCompat;
+ }
+ else
+ {
+ // read old style header
+ long nWidth, nHeight;
+ long nMapMode, nScaleNumX, nScaleDenomX;
+ long nScaleNumY, nScaleDenomY, nOffsX, nOffsY;
+
+ rIStm.SeekRel( -4L );
+
+ rIStm >> nType >> nLen >> nWidth >> nHeight;
+ rIStm >> nMapMode >> nScaleNumX >> nScaleDenomX >> nScaleNumY;
+ rIStm >> nScaleDenomY >> nOffsX >> nOffsY;
+
+ // swapped
+ if( nType > 100L )
+ {
+ nType = SWAPLONG( nType );
+ nLen = SWAPLONG( nLen );
+ nWidth = SWAPLONG( nWidth );
+ nHeight = SWAPLONG( nHeight );
+ nMapMode = SWAPLONG( nMapMode );
+ nScaleNumX = SWAPLONG( nScaleNumX );
+ nScaleDenomX = SWAPLONG( nScaleDenomX );
+ nScaleNumY = SWAPLONG( nScaleNumY );
+ nScaleDenomY = SWAPLONG( nScaleDenomY );
+ nOffsX = SWAPLONG( nOffsX );
+ nOffsY = SWAPLONG( nOffsY );
+ }
+
+ aSize = Size( nWidth, nHeight );
+ aMapMode = MapMode( (MapUnit) nMapMode, Point( nOffsX, nOffsY ),
+ Fraction( nScaleNumX, nScaleDenomX ),
+ Fraction( nScaleNumY, nScaleDenomY ) );
+ }
+
+ nHeaderLen = rIStm.Tell() - nStartPos;
+ meType = (GraphicType) nType;
+
+ if( meType )
+ {
+ if( meType == GRAPHIC_BITMAP )
+ {
+ maEx.aBitmapSize = aSize;
+
+ if( aMapMode != MapMode() )
+ {
+ maEx.SetPrefMapMode( aMapMode );
+ maEx.SetPrefSize( aSize );
+ }
+ }
+ else
+ {
+ maMetaFile.SetPrefMapMode( aMapMode );
+ maMetaFile.SetPrefSize( aSize );
+ }
+
+ if( bSwap )
+ {
+ if( maDocFileName.Len() )
+ {
+ rIStm.Seek( nStartPos + nHeaderLen + nLen );
+ bRet = mbSwapOut = TRUE;
+ }
+ else
+ {
+ const String aTmpName( TempFile::CreateTempName() );
+
+ if( aTmpName.Len() )
+ {
+ SvFileStream aOStm( aTmpName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( !aOStm.GetError() )
+ {
+ ULONG nFullLen = nHeaderLen + nLen;
+ ULONG nPartLen = Min( nFullLen, (ULONG) GRAPHIC_MAXPARTLEN );
+ BYTE* pBuffer = (BYTE*) SvMemAlloc( nPartLen );
+
+ if( pBuffer )
+ {
+ rIStm.Seek( nStartPos );
+
+ while( nFullLen )
+ {
+ rIStm.Read( (char*) pBuffer, nPartLen );
+ aOStm.Write( (char*) pBuffer, nPartLen );
+
+ nFullLen -= nPartLen;
+
+ if( nFullLen < GRAPHIC_MAXPARTLEN )
+ nPartLen = nFullLen;
+ }
+
+ SvMemFree( pBuffer );
+
+ ULONG nReadErr = rIStm.GetError();
+ ULONG nWriteErr = aOStm.GetError();
+
+ aOStm.Close();
+
+ if( !nReadErr && !nWriteErr )
+ {
+ bRet = mbSwapOut = TRUE;
+ mpSwapFile = new ImpSwapFile;
+ mpSwapFile->nRefCount = 1;
+ mpSwapFile->aSwapFileName = aTmpName;
+ }
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( aTmpName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if( meType == GRAPHIC_BITMAP || meType == GRAPHIC_GDIMETAFILE )
+ {
+ rIStm >> *this;
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ else if( meType >= SYS_WINMETAFILE && meType <= SYS_MACMETAFILE )
+ {
+ Graphic aSysGraphic;
+ ULONG nCvtType;
+
+ switch( (ULONG) meType )
+ {
+ case( SYS_WINMETAFILE ):
+ case( SYS_WNTMETAFILE ): nCvtType = CVT_WMF; break;
+ case( SYS_OS2METAFILE ): nCvtType = CVT_MET; break;
+ case( SYS_MACMETAFILE ): nCvtType = CVT_PCT; break;
+
+ default:
+ nCvtType = CVT_UNKNOWN;
+ break;
+ }
+
+ if( nType && GraphicConverter::Import( rIStm, aSysGraphic, nCvtType ) == ERRCODE_NONE )
+ {
+ *this = ImpGraphic( aSysGraphic.GetGDIMetaFile() );
+ bRet = ( rIStm.GetError() == 0UL );
+ }
+ else
+ meType = GRAPHIC_DEFAULT;
+ }
+
+ if( bRet )
+ {
+ ImplSetPrefMapMode( aMapMode );
+ ImplSetPrefSize( aSize );
+ }
+ }
+ else
+ bRet = TRUE;
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplWriteEmbedded( SvStream& rOStm )
+{
+ BOOL bRet = FALSE;
+
+ if( ( meType != GRAPHIC_NONE ) && ( meType != GRAPHIC_DEFAULT ) && !ImplIsSwapOut() )
+ {
+ const MapMode aMapMode( ImplGetPrefMapMode() );
+ const Size aSize( ImplGetPrefSize() );
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ const ULONG nStmPos1 = rOStm.Tell();
+ ULONG nDataFieldPos;
+
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ // write correct version ( old style/new style header )
+ if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
+ {
+ // write ID for new format (5.0)
+ rOStm << GRAPHIC_FORMAT_50;
+
+ // write new style header
+ VersionCompat* pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (long) meType;
+
+ // data size is updated later
+ nDataFieldPos = rOStm.Tell();
+ rOStm << (long) 0;
+
+ rOStm << aSize;
+ rOStm << aMapMode;
+
+ delete pCompat;
+ }
+ else
+ {
+ // write old style (<=4.0) header
+ rOStm << (long) meType;
+
+ // data size is updated later
+ nDataFieldPos = rOStm.Tell();
+ rOStm << (long) 0;
+
+ rOStm << (long) aSize.Width();
+ rOStm << (long) aSize.Height();
+ rOStm << (long) aMapMode.GetMapUnit();
+ rOStm << (long) aMapMode.GetScaleX().GetNumerator();
+ rOStm << (long) aMapMode.GetScaleX().GetDenominator();
+ rOStm << (long) aMapMode.GetScaleY().GetNumerator();
+ rOStm << (long) aMapMode.GetScaleY().GetDenominator();
+ rOStm << (long) aMapMode.GetOrigin().X();
+ rOStm << (long) aMapMode.GetOrigin().Y();
+ }
+
+ // write data block
+ if( !rOStm.GetError() )
+ {
+ const ULONG nDataStart = rOStm.Tell();
+
+ if( ImplIsSupportedGraphic() )
+ rOStm << *this;
+
+ if( !rOStm.GetError() )
+ {
+ const ULONG nStmPos2 = rOStm.Tell();
+ rOStm.Seek( nDataFieldPos );
+ rOStm << (long) ( nStmPos2 - nDataStart );
+ rOStm.Seek( nStmPos2 );
+ bRet = TRUE;
+ }
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapOut()
+{
+ BOOL bRet = FALSE;
+
+ if( !ImplIsSwapOut() )
+ {
+ if( !maDocFileName.Len() )
+ {
+ const String aTmpName( TempFile::CreateTempName() );
+
+ if( aTmpName.Len() )
+ {
+ SvFileStream aOStm( aTmpName, STREAM_WRITE | STREAM_SHARE_DENYWRITE );
+
+ aOStm.SetVersion( SOFFICE_FILEFORMAT_NOW );
+ aOStm.SetCompressMode( COMPRESSMODE_NATIVE );
+
+ if( ( bRet = ImplSwapOut( &aOStm ) ) == TRUE )
+ {
+ mpSwapFile = new ImpSwapFile;
+ mpSwapFile->nRefCount = 1;
+ mpSwapFile->aSwapFileName = aTmpName;
+ }
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( aTmpName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+ }
+ }
+ }
+ else
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapOut( SvStream* pOStm )
+{
+ BOOL bRet = FALSE;
+
+ if( pOStm )
+ {
+ pOStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
+
+ if( !pOStm->GetError() && ImplWriteEmbedded( *pOStm ) )
+ {
+ pOStm->Flush();
+
+ if( !pOStm->GetError() )
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+ }
+ }
+ else
+ {
+ ImplClearGraphics( TRUE );
+ bRet = mbSwapOut = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapIn()
+{
+ BOOL bRet = FALSE;
+
+ if( ImplIsSwapOut() )
+ {
+ const String aFileName = ( mpSwapFile ? mpSwapFile->aSwapFileName : maDocFileName );
+ SvFileStream aIStm( aFileName, STREAM_READ | STREAM_SHARE_DENYWRITE );
+
+ aIStm.SetVersion( SOFFICE_FILEFORMAT_NOW );
+ aIStm.SetCompressMode( COMPRESSMODE_NATIVE );
+
+ if( !mpSwapFile )
+ aIStm.Seek( mnDocFilePos );
+
+ bRet = ImplSwapIn( &aIStm );
+ aIStm.Close();
+
+ if( mpSwapFile )
+ {
+ if( mpSwapFile->nRefCount > 1 )
+ mpSwapFile->nRefCount--;
+ else
+ {
+ try
+ {
+ ::ucb::Content aCnt( INetURLObject( mpSwapFile->aSwapFileName, INET_PROT_FILE ).GetMainURL(),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+
+ aCnt.executeCommand( ::rtl::OUString::createFromAscii( "delete" ),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch( ::com::sun::star::ucb::CommandAbortedException& )
+ {
+ DBG_ERRORFILE( "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ DBG_ERRORFILE( "Any other exception" );
+ }
+
+ delete mpSwapFile;
+ }
+
+ mpSwapFile = NULL;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplSwapIn( SvStream* pIStm )
+{
+ BOOL bRet = FALSE;
+
+ if( pIStm )
+ {
+ pIStm->SetBufferSize( GRAPHIC_STREAMBUFSIZE );
+
+ if( !pIStm->GetError() )
+ {
+ mbSwapUnderway = TRUE;
+ bRet = ImplReadEmbedded( *pIStm );
+ mbSwapUnderway = FALSE;
+
+ if( !bRet )
+ ImplClear();
+ else
+ mbSwapOut = FALSE;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsSwapOut() const
+{
+ return mbSwapOut;
+}
+
+// ------------------------------------------------------------------------
+
+void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink )
+{
+ delete mpGfxLink;
+ mpGfxLink = new GfxLink( rGfxLink );
+
+ if( mpGfxLink->IsNative() )
+ mpGfxLink->SwapOut();
+}
+
+// ------------------------------------------------------------------------
+
+GfxLink ImpGraphic::ImplGetLink()
+{
+ return( mpGfxLink ? *mpGfxLink : GfxLink() );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplIsLink() const
+{
+ return ( mpGfxLink != NULL ) ? TRUE : FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+ULONG ImpGraphic::ImplGetChecksum() const
+{
+ ULONG nRet = 0;
+
+ if( ImplIsSupportedGraphic() && !ImplIsSwapOut() )
+ {
+ switch( meType )
+ {
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case( GRAPHIC_BITMAP ):
+ {
+ if( mpAnimation )
+ nRet = mpAnimation->GetChecksum();
+ else
+ nRet = maEx.GetChecksum();
+ }
+ break;
+
+ default:
+ nRet = maMetaFile.GetChecksum();
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplCopy() const
+{
+ DBG_ERROR( "Missing implementation!" );
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL ImpGraphic::ImplPaste()
+{
+ DBG_ERROR( "Missing implementation!" );
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImpGraphic& rImpGraphic )
+{
+ if( !rIStm.GetError() )
+ {
+ const ULONG nStmPos1 = rIStm.Tell();
+ ULONG nTmp;
+
+ if ( !rImpGraphic.mbSwapUnderway )
+ rImpGraphic.ImplClear();
+
+ // read Id
+ rIStm >> nTmp;
+
+ if( NATIVE_FORMAT_50 == nTmp )
+ {
+ Graphic aGraphic;
+ GfxLink aLink;
+ VersionCompat* pCompat;
+
+ // read compat info
+ pCompat = new VersionCompat( rIStm, STREAM_READ );
+ delete pCompat;
+
+ rIStm >> aLink;
+
+ // set dummy link to avoid creation of additional link after filtering;
+ // we set a default link to avoid unnecessary swapping of native data
+ aGraphic.SetLink( GfxLink() );
+
+ if( !rIStm.GetError() && aLink.LoadNative( aGraphic ) )
+ {
+ // set link only, if no other link was set
+ const BOOL bSetLink = ( rImpGraphic.mpGfxLink == NULL );
+
+ // assign graphic
+ rImpGraphic = *aGraphic.ImplGetImpGraphic();
+
+ if( bSetLink )
+ rImpGraphic.ImplSetLink( aLink );
+ }
+ else
+ {
+ rIStm.Seek( nStmPos1 );
+ rIStm.SetError( ERRCODE_IO_WRONGFORMAT );
+ }
+ }
+ else
+ {
+ BitmapEx aBmpEx;
+ const USHORT nOldFormat = rIStm.GetNumberFormatInt();
+
+ rIStm.SeekRel( -4 );
+ rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rIStm >> aBmpEx;
+
+ if( !rIStm.GetError() )
+ {
+ UINT32 nMagic1, nMagic2;
+ ULONG nActPos = rIStm.Tell();
+
+ rIStm >> nMagic1 >> nMagic2;
+ rIStm.Seek( nActPos );
+
+ rImpGraphic = ImpGraphic( aBmpEx );
+
+ if( ( 0x5344414e == nMagic1 ) && ( 0x494d4931 == nMagic2 ) && !rIStm.GetError() )
+ {
+ delete rImpGraphic.mpAnimation;
+ rImpGraphic.mpAnimation = new Animation;
+ rIStm >> *rImpGraphic.mpAnimation;
+ }
+ }
+ else
+ {
+ GDIMetaFile aMtf;
+
+ rIStm.Seek( nStmPos1 );
+ rIStm.ResetError();
+ rIStm >> aMtf;
+
+ if( !rIStm.GetError() )
+ rImpGraphic = aMtf;
+ else
+ rIStm.Seek( nStmPos1 );
+ }
+
+ rIStm.SetNumberFormatInt( nOldFormat );
+ }
+ }
+
+ return rIStm;
+}
+
+// ------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImpGraphic& rImpGraphic )
+{
+ if( !rOStm.GetError() )
+ {
+ if( !rImpGraphic.ImplIsSwapOut() )
+ {
+ if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) &&
+ ( rOStm.GetCompressMode() & COMPRESSMODE_NATIVE ) &&
+ rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() )
+ {
+ VersionCompat* pCompat;
+
+ // native format
+ rOStm << NATIVE_FORMAT_50;
+
+ // write compat info
+ pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
+ delete pCompat;
+
+ rOStm << *rImpGraphic.mpGfxLink;
+ }
+ else
+ {
+ // own format
+ const USHORT nOldFormat = rOStm.GetNumberFormatInt();
+ rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ switch( rImpGraphic.ImplGetType() )
+ {
+ case( GRAPHIC_NONE ):
+ case( GRAPHIC_DEFAULT ):
+ break;
+
+ case GRAPHIC_BITMAP:
+ {
+ if ( rImpGraphic.ImplIsAnimated() )
+ rOStm << *rImpGraphic.mpAnimation;
+ else
+ rOStm << rImpGraphic.maEx;
+ }
+ break;
+
+ default:
+ {
+ if( rImpGraphic.ImplIsSupportedGraphic() )
+ rOStm << rImpGraphic.maMetaFile;
+ }
+ break;
+ }
+
+ rOStm.SetNumberFormatInt( nOldFormat );
+ }
+ }
+ else
+ rOStm.SetError( SVSTREAM_GENERALERROR );
+ }
+
+ return rOStm;
+}
diff --git a/vcl/source/gdi/impimage.cxx b/vcl/source/gdi/impimage.cxx
new file mode 100644
index 000000000000..1dcebb60009a
--- /dev/null
+++ b/vcl/source/gdi/impimage.cxx
@@ -0,0 +1,744 @@
+/*************************************************************************
+ *
+ * $RCSfile: impimage.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPIMAGE_CXX
+
+#include <string.h>
+
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_IMAGE_H
+#include <image.h>
+#endif
+
+// -------------
+// - FASTIMAGE -
+// -------------
+
+#ifndef REMOTE_APPSERVER
+#if defined WIN || defined WNT || defined OS2
+#undef FASTTRANSPARENT
+extern BOOL bFastTransparent;
+#else
+#undef FASTTRANSPARENT
+#endif
+#else
+#undef FASTTRANSPARENT
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define IPOS( nPos ) ( Point( (nPos) * aSize.Width(), 0L ) )
+#define IMPSYSIMAGEITEM_NOTFREE ( 0x01 )
+#define IMPSYSIMAGEITEM_MASK ( 0x02 )
+#define DISA_ALL ( 0xffff )
+#define PAINT_ALL ( 0xffff )
+
+// ----------------
+// - ImplImageBmp -
+// ----------------
+
+ImplImageBmp::ImplImageBmp() :
+ pInfoAry ( NULL ),
+ nCount ( 0 ),
+ nSize ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplImageBmp::~ImplImageBmp()
+{
+ delete[] pInfoAry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Create( long nItemWidth, long nItemHeight, USHORT nInitSize )
+{
+ const Size aTotalSize( nInitSize * nItemWidth, nItemHeight );
+
+ nCount = 0;
+ aSize = Size( nItemWidth, nItemHeight );
+ nSize = nInitSize;
+
+ aBmp = Bitmap( aTotalSize, 4 );
+ aMask = Bitmap( aTotalSize, 1 );
+
+ delete[] pInfoAry;
+ pInfoAry = new BYTE[ nSize ];
+ memset( pInfoAry, 0, nSize );
+ ImplClearCaches();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Create( const Bitmap& rBmp, const Bitmap& rMaskBmp,
+ const Color& rColor, BOOL bColor,
+ long nItemWidth, long nItemHeight, USHORT nInitSize )
+{
+ BYTE nStyle = IMPSYSIMAGEITEM_NOTFREE;
+
+ ImplClearCaches();
+
+ if ( bColor || !!rMaskBmp )
+ nStyle |= IMPSYSIMAGEITEM_MASK;
+
+ aSize = Size( nItemWidth, nItemHeight );
+ nCount = 0;
+ nSize = nInitSize;
+
+ delete[] pInfoAry;
+ pInfoAry = new BYTE[ nSize ];
+ memset( pInfoAry, nStyle, nSize );
+
+ aBmp = rBmp;
+
+ if( !!rMaskBmp )
+ aMask = rMaskBmp;
+ else if( bColor )
+ aMask = aBmp.CreateMask( rColor );
+
+#ifdef FASTTRANSPARENT
+ if( nStyle & IMPSYSIMAGEITEM_MASK )
+ ImplUpdatePaintBmp( DISA_ALL );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Expand( USHORT nGrowSize )
+{
+ const ULONG nDX = nGrowSize * aSize.Width();
+ const USHORT nOldSize = nSize;
+ BYTE* pNewAry = new BYTE[ nSize += nGrowSize ];
+
+ ImplClearCaches();
+
+ aBmp.Expand( nDX, 0UL );
+ aMask.Expand( nDX, 0UL );
+
+ if( !!aDisa )
+ aDisa.Expand( nDX, 0UL );
+
+ memset( pNewAry, 0, nSize );
+ memcpy( pNewAry, pInfoAry, nOldSize );
+ delete[] pInfoAry;
+ pInfoAry = pNewAry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, USHORT nSrcPos )
+{
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect );
+
+ if ( pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+ aMask.CopyPixel( aDstRect, aSrcRect );
+
+ if( !!aDisa )
+ aDisa.CopyPixel( aDstRect, aSrcRect );
+ }
+
+ pInfoAry[ nPos ] = pInfoAry[ nSrcPos ];
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const ImplImageBmp& rImageBmp, USHORT nSrcPos )
+{
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aBmp );
+
+ if ( rImageBmp.pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+ aMask.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aMask );
+
+ if( !!aDisa )
+ aDisa.CopyPixel( aDstRect, aSrcRect, &rImageBmp.aDisa );
+ }
+
+ pInfoAry[ nPos ] = rImageBmp.pInfoAry[ nSrcPos ];
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp )
+{
+ Point aPoint;
+ const Rectangle aSrcRect( aPoint, aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rBmp );
+ pInfoAry[ nPos ] &= ~IMPSYSIMAGEITEM_MASK;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp, const Bitmap& rMaskBmp )
+{
+ Point aPoint;
+ const Rectangle aSrcRect( aPoint, aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+
+ ImplClearCaches();
+
+ aBmp.CopyPixel( aDstRect, aSrcRect, &rBmp );
+ aMask.CopyPixel( aDstRect, aSrcRect, &rMaskBmp );
+
+ if( !!aDisa )
+ ImplUpdateDisaBmp( nPos );
+
+ pInfoAry[ nPos ] |= IMPSYSIMAGEITEM_MASK;
+
+#ifdef FASTTRANSPARENT
+ ImplUpdatePaintBmp( nPos );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Replace( USHORT nPos, const Bitmap& rBmp, const Color& rColor )
+{
+ Replace( nPos, rBmp, rBmp.CreateMask( rColor ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Merge( USHORT nPos, USHORT nSrcPos )
+{
+ if ( !( pInfoAry[ nSrcPos ] & IMPSYSIMAGEITEM_MASK ) )
+ Replace( nPos, nSrcPos );
+ else
+ {
+ ImplClearCaches();
+
+ const Rectangle aSrcRect( IPOS( nSrcPos ), aSize );
+ const Rectangle aDstRect( IPOS( nPos ), aSize );
+ BitmapWriteAccess* pBmp = aBmp.AcquireWriteAccess();
+ BitmapWriteAccess* pMsk = aMask.AcquireWriteAccess();
+
+ if ( pBmp && pMsk )
+ {
+ const BitmapColor aMskBlack( pMsk->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ BitmapColor aDstCol, aSrcCol;
+ long nDstLeft = aDstRect.Left();
+ long nDstRight = aDstRect.Right();
+ long nDstBottom = aDstRect.Bottom();
+ long nSrcLeft = aSrcRect.Left();
+ long nSrcRight = aSrcRect.Right();
+ long nSrcTop = aSrcRect.Bottom();
+
+ for( long nDstY = aDstRect.Top(), nSrcY = aSrcRect.Top(); nDstY <= nDstBottom; nDstY++, nSrcY++ )
+ {
+ for( long nDstX = nDstLeft, nSrcX = nSrcLeft; nDstX <= nDstRight; nDstX++, nSrcX++ )
+ {
+ aDstCol = pMsk->GetPixel( nDstY, nDstX );
+ aSrcCol = pMsk->GetPixel( nSrcY, nSrcX );
+
+ if( aMskBlack == aDstCol )
+ {
+ if( aMskBlack == aSrcCol )
+ pBmp->SetPixel( nDstY, nDstX, pBmp->GetPixel( nSrcY, nSrcX ) );
+ }
+ else if( aMskBlack == aSrcCol )
+ {
+ pBmp->SetPixel( nDstY, nDstX, pBmp->GetPixel( nSrcY, nSrcX ) );
+ pMsk->SetPixel( nDstY, nDstX, aMskBlack );
+ }
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pBmp );
+ aMask.ReleaseAccess( pMsk );
+
+ if( !!aDisa )
+ ImplUpdateDisaBmp( nPos );
+
+ pInfoAry[ nPos ] |= IMPSYSIMAGEITEM_MASK;
+
+#ifdef FASTTRANSPARENT
+ ImplUpdatePaintBmp( nPos );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImplImageBmp::GetBitmap( USHORT nPosCount, USHORT* pPosAry ) const
+{
+ Bitmap aNewBmp( Size( nPosCount * aSize.Width(), aSize.Height() ), aBmp.GetBitCount() );
+
+ for( USHORT i = 0; i < nPosCount; i++ )
+ {
+ const Rectangle aSrcRect( IPOS( pPosAry[ i ] ), aSize );
+ const Rectangle aDstRect( IPOS( i ), aSize );
+
+ aNewBmp.CopyPixel( aDstRect, aSrcRect, &aBmp );
+ }
+
+ return aNewBmp;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageBmp::HasMaskBitmap() const
+{
+ return( !!aMask );
+}
+
+// -----------------------------------------------------------------------
+
+Bitmap ImplImageBmp::GetMaskBitmap( USHORT nPosCount, USHORT* pPosAry ) const
+{
+ Bitmap aNewMask( Size( nPosCount * aSize.Width(), aSize.Height() ), aMask.GetBitCount() );
+
+ for( USHORT i = 0; i < nPosCount; i++ )
+ {
+ const Rectangle aSrcRect( IPOS( pPosAry[ i ] ), aSize );
+ const Rectangle aDstRect( IPOS( i ), aSize );
+
+ aNewMask.CopyPixel( aDstRect, aSrcRect, &aMask );
+ }
+
+ return aNewMask;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplImageBmp::HasMaskColor() const
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Color ImplImageBmp::GetMaskColor() const
+{
+ return Color();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::Draw( USHORT nPos, OutputDevice* pOutDev,
+ const Point& rPos, USHORT nStyle,
+ const Size* pSize )
+{
+ if( pOutDev->IsDeviceOutputNecessary() )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( !aBmpDisp && !!aBmp )
+ aBmpDisp = aBmp.CreateDisplayBitmap( pOutDev );
+
+ if( !aMaskDisp && !!aMask )
+ aMaskDisp = aMask.CreateDisplayBitmap( pOutDev );
+
+#else // REMOTE_APPSERVER
+
+ if( !aBmpDisp && !!aBmp )
+ aBmpDisp = aBmp;
+
+ if( !aMaskDisp && !!aMask )
+ aMaskDisp = aMask;
+
+ if( !aDisaDisp && !!aDisa )
+ aDisaDisp = aDisa;
+
+#endif // REMOTE_APPSERVER
+
+ if( !aBmpEx )
+ aBmpEx = BitmapEx( aBmpDisp, aMaskDisp );
+
+ if( pInfoAry[ nPos ] & IMPSYSIMAGEITEM_MASK )
+ {
+#ifdef FASTTRANSPARENT
+ BOOL bTmp = bFastTransparent;
+ bFastTransparent = TRUE;
+#endif
+
+ Point aOutPos = pOutDev->LogicToPixel( rPos );
+ Size aOutSize;
+ BOOL bOldMap = pOutDev->mbMap;
+
+ if( pSize )
+ aOutSize = pOutDev->LogicToPixel( *pSize );
+ else
+ aOutSize = aSize;
+
+ pOutDev->mbMap = FALSE;
+
+ if ( nStyle & IMAGE_DRAW_DISABLE )
+ {
+ Point aOutPos1( aOutPos.X()+1, aOutPos.Y()+1 );
+ const Point aPos( IPOS( nPos) );
+ const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+
+ if( !aDisa )
+ {
+ aDisa = Bitmap( aBmpEx.GetSizePixel(), 1 );
+ ImplUpdateDisaBmp( DISA_ALL );
+#ifndef REMOTE_APPSERVER
+ aDisaDisp = aDisa.CreateDisplayBitmap( pOutDev );
+#else // REMOTE_APPSERVER
+ aDisaDisp = aDisa;
+#endif // REMOTE_APPSERVER
+ }
+
+ if( !aDisaDisp && !!aDisa )
+ aDisaDisp = aDisa.CreateDisplayBitmap( pOutDev );
+
+ pOutDev->DrawMask( aOutPos1, aOutSize, aPos, aSize,
+ aDisaDisp, rSettings.GetLightColor() );
+ pOutDev->DrawMask( aOutPos, aOutSize, aPos, aSize,
+ aDisaDisp, rSettings.GetShadowColor() );
+ }
+ else
+ {
+ BOOL bDrawn = FALSE;
+
+ if( nStyle & ( IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE ) )
+ {
+ Bitmap aTmpBmp( aBmp );
+ BitmapWriteAccess* pAcc;
+
+ aTmpBmp.Crop( Rectangle( IPOS( nPos ), aSize ) );
+ pAcc = aTmpBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+ Color aColor;
+ BitmapColor aCol;
+ const long nW = pAcc->Width();
+ const long nH = pAcc->Height();
+ BYTE* pMapR = new BYTE[ 256 ];
+ BYTE* pMapG = new BYTE[ 256 ];
+ BYTE* pMapB = new BYTE[ 256 ];
+ long nX, nY;
+
+ if( nStyle & IMAGE_DRAW_HIGHLIGHT )
+ aColor = rSettings.GetHighlightColor();
+ else
+ aColor = rSettings.GetDeactiveColor();
+
+ const BYTE cR = aColor.GetRed();
+ const BYTE cG = aColor.GetGreen();
+ const BYTE cB = aColor.GetBlue();
+
+ for( nX = 0L; nX < 256L; nX++ )
+ {
+ pMapR[ nX ] = (BYTE) ( ( ( nY = ( nX + cR ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapG[ nX ] = (BYTE) ( ( ( nY = ( nX + cG ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapB[ nX ] = (BYTE) ( ( ( nY = ( nX + cB ) >> 1 ) > 255 ) ? 255 : nY );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+ aCol.SetRed( pMapR[ rCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ rCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ rCol.GetBlue() ] );
+ pAcc->SetPaletteColor( i, aCol );
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = pMapB[ *pScan ]; pScan++;
+ *pScan = pMapG[ *pScan ]; pScan++;
+ *pScan = pMapR[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+ aCol.SetRed( pMapR[ aCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ aCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ aCol.GetBlue() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ delete[] pMapR;
+ delete[] pMapG;
+ delete[] pMapB;
+ aTmpBmp.ReleaseAccess( pAcc );
+
+ Bitmap aTmpMsk( aMask );
+ aTmpMsk.Crop( Rectangle( IPOS( nPos), aSize ) );
+ pOutDev->DrawBitmapEx( aOutPos, BitmapEx( aTmpBmp, aTmpMsk ) );
+ bDrawn = TRUE;
+ }
+ }
+
+ if( !bDrawn )
+ pOutDev->DrawBitmapEx( aOutPos, aOutSize, IPOS( nPos), aSize, aBmpEx );
+ }
+
+ pOutDev->mbMap = bOldMap;
+
+#ifdef FASTTRANSPARENT
+ bFastTransparent = bTmp;
+#endif
+ }
+ else if( pSize )
+ pOutDev->DrawBitmap( rPos, *pSize,
+ IPOS( nPos), aSize, aBmpEx.GetBitmap() );
+ else
+ pOutDev->DrawBitmap( rPos, pOutDev->PixelToLogic( aSize ),
+ IPOS( nPos), aSize, aBmpEx.GetBitmap() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplUpdateDisaBmp( USHORT nPos )
+{
+ BitmapReadAccess* pAcc = aBmp.AcquireReadAccess();
+ BitmapReadAccess* pMsk = aMask.AcquireReadAccess();
+ BitmapWriteAccess* pDis = aDisa.AcquireWriteAccess();
+
+ if( pAcc && pMsk && pDis )
+ {
+ const Color aWhite( COL_WHITE );
+ const Color aBlack( COL_BLACK );
+ const BitmapColor aAccWhite( pAcc->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aMskWhite( pMsk->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aDisWhite( pDis->GetBestMatchingColor( aWhite ) );
+ const BitmapColor aDisBlack( pDis->GetBestMatchingColor( aBlack ) );
+ long nLeft;
+ long nTop;
+ long nRight;
+ long nBottom;
+
+ if( DISA_ALL != nPos )
+ {
+ const Point aPos( IPOS( nPos ) );
+
+ nLeft = aPos.X();
+ nTop = aPos.Y();
+ nRight = nLeft + aSize.Width();
+ nBottom = nTop + aSize.Height();
+ }
+ else
+ {
+ nLeft = nTop = 0L;
+ nRight = pDis->Width();
+ nBottom = pDis->Height();
+ }
+
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL &&
+ pMsk->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ // optimized version
+ const BYTE cAccTest = aAccWhite.GetIndex();
+ const BYTE cMskTest = aMskWhite.GetIndex();
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ Scanline pAccScan = pAcc->GetScanline( nY );
+ Scanline pMskScan = pMsk->GetScanline( nY );
+
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( cMskTest == ( pMskScan[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 ) ) ||
+ ( cAccTest == ( ( pAccScan[ nX >> 1 ] >> ( nX & 1 ? 0 : 4 ) ) & 0x0f ) ) )
+ {
+ pDis->SetPixel( nY, nX, aDisWhite );
+ }
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL &&
+ pMsk->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ // optimized version
+ const BYTE cAccTest = aAccWhite.GetIndex();
+ const BYTE cMskTest = aMskWhite.GetIndex();
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ Scanline pAccScan = pAcc->GetScanline( nY );
+ Scanline pMskScan = pMsk->GetScanline( nY );
+
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( cMskTest == ( pMskScan[ nX >> 3 ] & ( 1 << ( 7 - ( nX & 7 ) ) ) ? 1 : 0 ) ) ||
+ ( cAccTest == pAccScan[ nX ] ) )
+ {
+ pDis->SetPixel( nY, nX, aDisWhite );
+ }
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = nTop; nY < nBottom; nY++ )
+ {
+ for( long nX = nLeft; nX < nRight; nX++ )
+ {
+ if( ( aMskWhite == pMsk->GetPixel( nY, nX ) ) || ( aAccWhite == pAcc->GetPixel( nY, nX ) ) )
+ pDis->SetPixel( nY, nX, aDisWhite );
+ else
+ pDis->SetPixel( nY, nX, aDisBlack );
+ }
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ aMask.ReleaseAccess( pMsk );
+ aDisa.ReleaseAccess( pDis );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplUpdatePaintBmp( USHORT nPos )
+{
+ BitmapWriteAccess* pBmp = aBmp.AcquireWriteAccess();
+ BitmapReadAccess* pMsk = aMask.AcquireReadAccess();
+
+ if ( pBmp && pMsk )
+ {
+ const Color aBlack( COL_BLACK );
+ const BitmapColor aBmpBlack( pBmp->GetBestMatchingColor( aBlack ) );
+ const BitmapColor aMskBlack( pMsk->GetBestMatchingColor( aBlack ) );
+ long nLeft, nTop, nRight, nBottom;
+
+ if( PAINT_ALL != nPos )
+ {
+ const Point aPos( IPOS( nPos ) );
+
+ nLeft = aPos.X();
+ nTop = aPos.Y();
+ nRight = nLeft + aSize.Width();
+ nBottom = nTop + aSize.Height();
+ }
+ else
+ {
+ nLeft = nTop = 0L;
+ nRight = pBmp->Width();
+ nBottom = pBmp->Height();
+ }
+
+ for( long nY = nTop; nY < nBottom; nY++ )
+ for( long nX = nLeft; nX < nRight; nX++ )
+ if( aMskBlack != pMsk->GetPixel( nY, nX ) )
+ pBmp->SetPixel( nY, nX, aBmpBlack );
+ }
+
+ aBmp.ReleaseAccess( pBmp );
+ aMask.ReleaseAccess( pMsk );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplImageBmp::ImplClearCaches()
+{
+ aBmpEx.Clear();
+ aBmpDisp = aMaskDisp = aDisaDisp = Bitmap();
+}
diff --git a/vcl/source/gdi/implncvt.cxx b/vcl/source/gdi/implncvt.cxx
new file mode 100644
index 000000000000..98a428d36380
--- /dev/null
+++ b/vcl/source/gdi/implncvt.cxx
@@ -0,0 +1,605 @@
+/*************************************************************************
+ *
+ * $RCSfile: implncvt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_SALBTYPE_HXX
+#include "salbtype.hxx"
+#endif
+#ifndef _SV_IMPLNCVT_HXX
+#include "implncvt.hxx"
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define CURVE_LEFT 1
+#define CURVE_RIGHT 2
+#define CURVE_STRAIGHTON 3
+
+// -----------------
+// - ImplFloatPoint
+// -----------------
+
+struct ImplFloatPoint
+{
+ double fX;
+ double fY;
+
+ inline ImplFloatPoint() {}
+ inline ImplFloatPoint( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
+ inline ImplFloatPoint( double _fX, double _fY ) { fX = _fX; fY = _fY; }
+ inline ImplFloatPoint( const ImplFloatPoint& rPoint ) { fX = rPoint.fX; fY = rPoint.fY; }
+ inline ~ImplFloatPoint() {}
+
+ void operator+=( const ImplFloatPoint& rPoint ) { fX += rPoint.fX; fY += rPoint.fY; }
+ void operator-=( const ImplFloatPoint& rPoint ) { fX -= rPoint.fX; fY -= rPoint.fY; }
+ void operator*=( const double& rD ) { fX *= rD; fY *= rD; }
+ BOOL operator==( const ImplFloatPoint& rPoint ) const { return ( ( rPoint.fX == fX ) && ( rPoint.fY == fY ) ); } const
+ void operator=( const Point rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
+
+ ImplFloatPoint GetOVec( const ImplFloatPoint& rPoint ) const;
+ ImplFloatPoint GetNVec( const ImplFloatPoint& rPoint ) const;
+};
+
+// -----------------------------------------------------------------------------
+
+ImplFloatPoint ImplFloatPoint::GetOVec( const ImplFloatPoint& rPoint ) const
+{
+ double fxt = rPoint.fX - fX;
+ double fyt = rPoint.fY - fY;
+ double fL;
+
+ if( fyt != 0.0 )
+ {
+ fyt = -fxt / fyt;
+ fL = sqrt( 1 + fyt * fyt );
+
+ return ImplFloatPoint( 1.0 / fL, fyt / fL );
+ }
+ else
+ return ImplFloatPoint( fyt, ( fxt > 0.0 ) ? 1.0 : -1.0 );
+};
+
+// -----------------------------------------------------------------------------
+
+ImplFloatPoint ImplFloatPoint::GetNVec( const ImplFloatPoint& rPoint ) const
+{
+ const double fxt = rPoint.fX - fX;
+ const double fyt = rPoint.fY - fY;
+ const double fL = hypot( fxt, fyt );
+
+ return ImplFloatPoint( fxt / fL, fyt / fL );
+};
+
+// --------------------
+// - ImplLineConverter
+// --------------------
+
+ImplLineConverter::ImplLineConverter( const Polygon& rPolygon, const LineInfo& rLineInfo, const Point* pRefPoint ) :
+ maLineInfo ( rLineInfo ),
+ mfWidthHalf ( rLineInfo.GetWidth() >> 1 ),
+ mpFloatPoint ( NULL ),
+ mpFloat0 ( new ImplFloatPoint[ 6 ] ),
+ mpFloat1 ( new ImplFloatPoint[ 6 ] ),
+ mnLines ( 0 )
+{
+ UINT16 nIndex, nPolySize = rPolygon.GetSize();
+ if ( nPolySize )
+ {
+ if( rPolygon.GetFlags( 0 ) == POLY_NORMAL )
+ {
+ mpFloatPoint = new ImplFloatPoint[ nPolySize ];
+ mpFloatPoint[ 0 ] = rPolygon[ 0 ];
+
+ nIndex = 0;
+
+ while( ++nIndex < nPolySize ) // doppelte Punkte eliminieren und ein FloatPointArray anlegen
+ {
+ if( rPolygon.GetFlags( nIndex ) == POLY_NORMAL )
+ {
+ double nxt = mpFloatPoint[ mnLines ].fX;
+ double nyt = mpFloatPoint[ mnLines ].fY;
+
+ if ( ( nxt == rPolygon[ nIndex ].X() ) && ( nyt == rPolygon[ nIndex ].Y() ) )
+ continue;
+
+ mpFloatPoint[ ++mnLines ] = rPolygon[ nIndex ];
+ }
+ else
+ {
+ DBG_ERROR( "Bezier points not supported!" );
+ }
+ }
+ mbClosed = ( mpFloatPoint[ 0 ] == mpFloatPoint[ mnLines ] ) ;
+
+ if ( ( mnLines == 1 ) && ( maLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ BOOL bX = mpFloatPoint[ 0 ].fY == mpFloatPoint[ 1 ].fY;
+ BOOL bY = mpFloatPoint[ 0 ].fX == mpFloatPoint[ 1 ].fX;
+ mbRefPoint = pRefPoint && ( bX || bY );
+ if ( mbRefPoint )
+ {
+ if ( !maLineInfo.GetDashCount() )
+ {
+ maLineInfo.SetDashCount( maLineInfo.GetDotCount() );
+ maLineInfo.SetDashLen( maLineInfo.GetDotLen() );
+ maLineInfo.SetDotCount( 0 );
+ }
+ INT32 nDistance = maLineInfo.GetDistance();
+ INT32 nDashLen = maLineInfo.GetDashCount() * ( maLineInfo.GetDashLen() + nDistance );
+ INT32 nDotLen = maLineInfo.GetDotCount() * ( maLineInfo.GetDotLen() + nDistance );
+ if ( bX )
+ {
+ if ( mpFloatPoint[ 1 ].fX > mpFloatPoint[ 0 ].fX )
+ {
+ ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
+ mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
+ mpFloatPoint[ 1 ] = aFloat;
+ }
+ mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X();
+ }
+ else
+ {
+ if ( mpFloatPoint[ 1 ].fY > mpFloatPoint[ 0 ].fY )
+ {
+ ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
+ mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
+ mpFloatPoint[ 1 ] = aFloat;
+ }
+ mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y();
+ }
+
+// mnRefDistance = ( (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X() ) +
+// ( (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y() );
+
+ mnRefDistance = mnRefDistance % ( nDashLen + nDotLen );
+ if ( mnRefDistance < 0 )
+ mnRefDistance = ( nDashLen + nDotLen ) + mnRefDistance;
+ }
+ }
+ }
+ }
+};
+
+//------------------------------------------------------------------------
+
+ImplLineConverter::~ImplLineConverter()
+{
+ delete[] mpFloat0;
+ delete[] mpFloat1;
+ delete[] mpFloatPoint;
+};
+
+//------------------------------------------------------------------------
+
+const Polygon* ImplLineConverter::ImplGetFirst()
+{
+ mnFloat1Points = 0;
+ mnLinesAvailable = mnLines;
+
+ if ( mnLines )
+ {
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ mfDashDotLenght = mnDashCount ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+
+ if ( mbRefPoint )
+ {
+ INT32 nDistance = maLineInfo.GetDistance();
+ INT32 nDashLen = maLineInfo.GetDashLen() + nDistance;
+ INT32 nDashesLen = maLineInfo.GetDashCount() * nDashLen;
+ INT32 nDotLen = maLineInfo.GetDotLen() + nDistance;
+ INT32 nDotsLen = maLineInfo.GetDotCount() * nDotLen;
+
+ if ( mnRefDistance >= nDashesLen )
+ {
+ // get dotcount
+ if ( nDotLen )
+ {
+ INT32 nLen = ( mnRefDistance - nDashesLen ) % nDotLen;
+ if ( nLen >= maLineInfo.GetDotLen() )
+ {
+ mnDotCount -= 1 + ( mnRefDistance - nDashesLen ) / nDotLen;
+ if ( mnDotCount )
+ mnDashCount = 0;
+ else
+ mnDotCount = maLineInfo.GetDotCount();
+ mfDashDotLenght = 0.0;
+ mfDistanceLenght = ( maLineInfo.GetDotLen() + nDistance ) - nLen;
+ }
+ else
+ {
+ mnDashCount = 0;
+ mfDashDotLenght = maLineInfo.GetDotLen() - nLen;
+ mnDotCount -= ( mnRefDistance - nDashesLen ) / nDotLen;
+ }
+ }
+ }
+ else
+ {
+ if ( nDashLen )
+ {
+ // get dashcount
+ INT32 nLen = mnRefDistance % nDashLen;
+ if ( nLen >= maLineInfo.GetDashLen() )
+ {
+ mfDashDotLenght = 0.0;
+ mfDistanceLenght = ( maLineInfo.GetDashLen() + nDistance ) - nLen;
+ mnDashCount -= 1 + ( mnRefDistance / nDashLen );
+ }
+ else
+ {
+ mfDashDotLenght = maLineInfo.GetDashLen() - nLen;
+ mnDashCount -= ( mnRefDistance / nDashLen );
+ }
+ }
+ }
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ if ( ( mfDashDotLenght == 0.0 ) && ( mfDistanceLenght == 0.0 ) )
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ }
+ return ImplGetNext();
+};
+
+//------------------------------------------------------------------------
+
+const Polygon* ImplLineConverter::ImplGetNext()
+{
+ while( mnFloat1Points || mnLinesAvailable )
+ {
+ if ( maLineInfo.GetWidth() > 1 )
+ {
+ if ( !mnFloat1Points )
+ {
+ ImplFloatPoint aPointA( mpFloatPoint[ mnLinesAvailable-- ] );
+ ImplFloatPoint aPointB( mpFloatPoint[ mnLinesAvailable ] );
+ ImplFloatPoint aOVecAB( aPointA.GetOVec( aPointB ) );
+ ImplFloatPoint aN1Vec( aPointA.GetNVec( aPointB ) );
+ aN1Vec *= mfWidthHalf;
+
+ if ( !mbClosed && ( ( mnLinesAvailable + 1 ) == mnLines ) )
+ aPointA -= aN1Vec;
+
+ aOVecAB *= mfWidthHalf;
+ mpFloat0[ 0 ] = aPointA;
+ mpFloat0[ 0 ] -= aOVecAB;
+ mpFloat0[ 3 ] = aPointA;
+ mpFloat0[ 3 ] += aOVecAB;
+ mpFloat0[ 1 ] = aPointB;
+ mpFloat0[ 1 ] -= aOVecAB;
+ mpFloat0[ 2 ] = aPointB;
+ mpFloat0[ 2 ] += aOVecAB;
+
+ double f1D = ( aN1Vec.fX == 0 ) ? 1 : ( aN1Vec.fY / aN1Vec.fX );
+ double f2D = -f1D;
+
+ mnFloat0Points = 4;
+
+ int nDirection;
+
+ BOOL bContinues = ( mnLinesAvailable || mbClosed );
+ if ( bContinues )
+ {
+ ImplFloatPoint aPointC;
+
+ if ( mnLinesAvailable )
+ aPointC = mpFloatPoint[ mnLinesAvailable - 1 ];
+ else
+ aPointC = mpFloatPoint[ mnLines - 1 ];
+
+ ImplFloatPoint aOVecBC( aPointB.GetOVec( aPointC ) );
+ aOVecBC *= mfWidthHalf;
+ ImplFloatPoint aPointR0( aPointB );
+ aPointR0 -= aOVecBC;
+ ImplFloatPoint aPointR1( aPointB );
+ aPointR1 += aOVecBC;
+ ImplFloatPoint aN2Vec( aPointB.GetNVec( aPointC ) );
+ aN2Vec *= mfWidthHalf;
+
+ f2D = ( aN2Vec.fX == 0 ) ? 1 : ( aN2Vec.fY / aN2Vec.fX );
+ if ( f1D == f2D )
+ nDirection = CURVE_STRAIGHTON;
+ else
+ {
+ if ( ( aN1Vec.fX * aN2Vec.fY - aN1Vec.fY * aN2Vec.fX ) > 0 )
+ nDirection = CURVE_LEFT;
+ else
+ nDirection = CURVE_RIGHT;
+ }
+ if ( nDirection != CURVE_STRAIGHTON )
+ {
+ double fWidth;
+ ImplFloatPoint aDestPoint;
+ if ( hypot( aPointR0.fX - aPointA.fX, aPointR0.fY - aPointA.fY ) > hypot( aPointR1.fX - aPointA.fX, aPointR1.fY - aPointA.fY ) )
+ aDestPoint = aPointR0;
+ else
+ aDestPoint = aPointR1;
+
+ UINT16 nFirst = 0;
+ if ( aN1Vec.fY > 0 )
+ {
+ if ( nDirection != CURVE_RIGHT )
+ nFirst++;
+ }
+ else
+ {
+ if ( nDirection == CURVE_RIGHT )
+ nFirst++;
+ }
+ fWidth = hypot( mpFloat0[ 1 + nFirst ].fX - aDestPoint.fX, mpFloat0[ 1 + nFirst ].fY - aDestPoint.fY );
+ fWidth = sqrt( fWidth * fWidth / 2 );
+ if ( fWidth > mfWidthHalf )
+ {
+ // Spitzer Winkel :
+ mnFloat0Points = 6;
+ mpFloat0[ 4 + nFirst ^ 1 ] = aDestPoint;
+ aDestPoint -= aN2Vec;
+ mpFloat0[ 4 + nFirst ] = aDestPoint;
+ mpFloat0[ 1 + nFirst ] += aN1Vec;
+ }
+ else
+ {
+ // Stumpferwinkel : Schnittpunkt wird berechnet
+ mnFloat0Points = 5;
+ ImplFloatPoint aSourcePoint;
+ double fX, fY, fBDest, fBSource;
+ aSourcePoint = mpFloat0[ 1 + nFirst ];
+
+ int nValid = 0;
+
+ if ( ( aN2Vec.fX ) == 0 )
+ {
+ fX = aDestPoint.fX;
+ nValid = 1;
+ }
+ else
+ fBDest = aDestPoint.fY - ( aN2Vec.fY / aN2Vec.fX * aDestPoint.fX );
+
+ if ( ( aN1Vec.fX ) == 0 )
+ {
+ fX = aSourcePoint.fX;
+ nValid = 2;
+ }
+ else
+ fBSource = aSourcePoint.fY - ( aN1Vec.fY / aN1Vec.fX * aSourcePoint.fX );
+
+ if ( !nValid )
+ fX = ( fBSource - fBDest ) / ( aN2Vec.fY / aN2Vec.fX - aN1Vec.fY / aN1Vec.fX );
+ if ( nValid < 2 )
+ fY = aN1Vec.fY / aN1Vec.fX * fX + fBSource;
+ else
+ fY = aN2Vec.fY / aN2Vec.fX * fX + fBDest;
+
+ mpFloat0[ 1 + nFirst ].fX = fX;
+ mpFloat0[ 1 + nFirst ].fY = fY;
+ mpFloat0[ 4 ] = aDestPoint;
+ }
+ }
+ else if ( ( aN1Vec.fX - aN2Vec.fX + aN1Vec.fY - aN2Vec.fY ) != 0 ) // besitzt zweiter Richtungsvektor die gleiche Steigung aber andere
+ bContinues = FALSE; // Richtung, dann wird hinten noch eine halbe Linienbreite angehaengt
+ }
+ if ( !bContinues )
+ {
+ mpFloat0[ 1 ] += aN1Vec;
+ mpFloat0[ 2 ] += aN1Vec;
+ }
+ }
+ else
+ {
+ mnFloat0Points = mnFloat1Points;
+ ImplFloatPoint* pTemp = mpFloat1;
+ mpFloat1 = mpFloat0;
+ mpFloat0 = pTemp;
+ }
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ double fLenghtDone = 0;
+ double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
+
+ double fDistance;
+
+ fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
+ if ( mnFloat0Points == 5 )
+ {
+ double fDist = hypot( mpFloat0[ 2 ].fX - mpFloat0[ 3 ].fX, mpFloat0[ 2 ].fY - mpFloat0[ 3 ].fY );
+ if ( fDist < fDistance )
+ fDistance = fDist;
+ }
+
+ if ( fDistance > fLenght )
+ {
+ fLenghtDone = fLenght;
+
+ ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
+ aNVec *= fLenght;
+ mnFloat1Points = mnFloat0Points;
+ ImplFloatPoint* pTemp = mpFloat1;
+ mpFloat1 = mpFloat0;
+ mpFloat0 = pTemp;
+ mnFloat0Points = 4;
+ mpFloat0[ 0 ] = mpFloat0[ 1 ] = mpFloat1[ 0 ];
+ mpFloat0[ 1 ] += aNVec;
+ mpFloat0[ 2 ] = mpFloat0[ 3 ] = mpFloat1[ 3 ];
+ mpFloat0[ 2 ] += aNVec;
+
+ mpFloat1[ 0 ] = mpFloat0[ 1 ];
+ mpFloat1[ 3 ] = mpFloat0[ 2 ];
+ }
+ else
+ {
+ mnFloat1Points = 0;
+ fLenghtDone = fDistance;
+ }
+
+ if ( mfDashDotLenght > 0.0 )
+ { // Ein Dash oder Dot wurde erzeugt
+ mfDashDotLenght -= fLenghtDone;
+ if ( mfDashDotLenght == 0.0 )
+ { // Komplett erzeugt
+ if ( mnDashCount )
+ mnDashCount--;
+ else
+ mnDotCount--;
+
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ else
+ { // Das erzeugte Polygon muessen wir ignorieren
+ mfDistanceLenght -= fLenghtDone;
+ if ( mfDistanceLenght == 0.0 )
+ mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+ continue;
+ }
+ }
+ maPolygon.SetSize( (UINT16)mnFloat0Points );
+ UINT16 i = 0;
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 0 ].fX ), FRound( mpFloat0[ 0 ].fY ) );
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 1 ].fX ), FRound( mpFloat0[ 1 ].fY ) );
+ if ( mnFloat0Points > 4 )
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 4 ].fX ), FRound( mpFloat0[ 4 ].fY ) );
+ if ( mnFloat0Points > 5 )
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 5 ].fX ), FRound( mpFloat0[ 5 ].fY ) );
+ maPolygon[ i++ ] = Point( FRound( mpFloat0[ 2 ].fX ), FRound( mpFloat0[ 2 ].fY ) );
+ maPolygon[ i ] = Point( FRound( mpFloat0[ 3 ].fX ), FRound( mpFloat0[ 3 ].fY ) );
+
+ }
+ else
+ {
+ if ( !mnFloat1Points )
+ {
+ mpFloat0[ 0 ] = mpFloatPoint[ mnLinesAvailable-- ];
+ mpFloat0[ 1 ] = mpFloatPoint[ mnLinesAvailable ];
+ }
+ else
+ {
+ mpFloat0[ 0 ] = mpFloat1[ 0 ];
+ mpFloat0[ 1 ] = mpFloat1[ 1 ];
+ }
+ if ( maLineInfo.GetStyle() == LINE_DASH )
+ {
+ double fLenghtDone = 0;
+ double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
+ double fDistance;
+ fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
+ if ( fDistance > fLenght )
+ {
+ fLenghtDone = fLenght;
+ ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
+ aNVec *= fLenght;
+ mpFloat1[ 1 ] = mpFloat0[ 1 ];
+ mpFloat0[ 1 ] = mpFloat0[ 0 ];
+ mpFloat0[ 1 ] += aNVec;
+ mpFloat1[ 0 ] = mpFloat0[ 1 ];
+ mnFloat1Points = 2;
+ }
+ else
+ {
+ mnFloat1Points = 0;
+ fLenghtDone = fDistance;
+ }
+ if ( mfDashDotLenght > 0.0 )
+ { // Ein Dash oder Dot wurde erzeugt
+ mfDashDotLenght -= fLenghtDone;
+ if ( mfDashDotLenght == 0.0 )
+ { // Komplett erzeugt
+ if ( mnDashCount )
+ mnDashCount--;
+ else
+ mnDotCount--;
+
+ if ( ! ( mnDashCount | mnDotCount ) )
+ {
+ mnDashCount = maLineInfo.GetDashCount();
+ mnDotCount = maLineInfo.GetDotCount();
+ }
+ mfDistanceLenght = maLineInfo.GetDistance();
+ }
+ }
+ else
+ { // Das erzeugte Polygon muessen wir ignorieren
+ mfDistanceLenght -= fLenghtDone;
+ if ( mfDistanceLenght == 0.0 )
+ mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
+ continue;
+ }
+ }
+ maPolygon.SetSize( 2 );
+ maPolygon[ 0 ] = Point( (long)mpFloat0[ 0 ].fX, (long)mpFloat0[ 0 ].fY );
+ maPolygon[ 1 ] = Point( (long)mpFloat0[ 1 ].fX, (long)mpFloat0[ 1 ].fY );
+ }
+ return &maPolygon;
+ }
+ return NULL;
+};
diff --git a/vcl/source/gdi/implncvt.hxx b/vcl/source/gdi/implncvt.hxx
new file mode 100644
index 000000000000..5b4aa5bcee6e
--- /dev/null
+++ b/vcl/source/gdi/implncvt.hxx
@@ -0,0 +1,113 @@
+/*************************************************************************
+ *
+ * $RCSfile: implncvt.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_LINECONV_HXX
+#define _SV_LINECONV_HXX
+
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+
+// --------------------
+// - ImplLineConverter
+// --------------------
+
+struct ImplFloatPoint;
+
+class ImplLineConverter
+{
+ BOOL mbClosed;
+ BOOL mbRefPoint;
+ INT32 mnRefDistance;
+
+ double mfWidthHalf;
+ LineInfo maLineInfo;
+
+ double mfDashDotLenght;
+ double mfDistanceLenght;
+
+ UINT32 mnDashCount;
+ UINT32 mnDotCount;
+
+ Polygon maPolygon;
+ UINT32 mnFloat0Points;
+ ImplFloatPoint* mpFloat0;
+ UINT32 mnFloat1Points;
+ ImplFloatPoint* mpFloat1;
+
+ UINT32 mnLinesAvailable;
+ UINT32 mnLines;
+
+ ImplFloatPoint* mpFloatPoint;
+
+ public:
+
+ ImplLineConverter( const Polygon& rPoly, const LineInfo& rLineInfo, const Point* pRefPoint );
+ ~ImplLineConverter();
+
+ const Polygon* ImplGetFirst();
+ const Polygon* ImplGetNext();
+};
+
+#endif
diff --git a/vcl/source/gdi/impprn.cxx b/vcl/source/gdi/impprn.cxx
new file mode 100644
index 000000000000..ce41b8cce763
--- /dev/null
+++ b/vcl/source/gdi/impprn.cxx
@@ -0,0 +1,256 @@
+/*************************************************************************
+ *
+ * $RCSfile: impprn.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef REMOTE_APPSERVER
+
+#define _SV_IMPPRN_CXX
+#define _SPOOLPRINTER_EXT
+
+#ifndef _QUEUE_HXX
+#include <tools/queue.hxx>
+#endif
+
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_IMPPRN_HXX
+#include <impprn.hxx>
+#endif
+
+// =======================================================================
+
+struct QueuePage
+{
+ GDIMetaFile* mpMtf;
+ JobSetup* mpSetup;
+ USHORT mnPage;
+ BOOL mbEndJob;
+
+ QueuePage() { mpMtf = NULL; mpSetup = NULL; }
+ ~QueuePage() { delete mpMtf; if ( mpSetup ) delete mpSetup; }
+};
+
+// =======================================================================
+
+ImplQPrinter::ImplQPrinter( Printer* pParent ) :
+ Printer( pParent->GetName() )
+{
+ SetSelfAsQueuePrinter( TRUE );
+ SetPrinterProps( pParent );
+ SetPageQueueSize( 0 );
+ mpParent = pParent;
+ mnCopyCount = pParent->mnCopyCount;
+ mbCollateCopy = pParent->mbCollateCopy;
+ mpQueue = new Queue( mpParent->GetPageQueueSize() );
+ mbAborted = FALSE;
+ mbUserCopy = FALSE;
+ mbDestroyAllowed= TRUE;
+ mbDestroyed = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplQPrinter::~ImplQPrinter()
+{
+ QueuePage* pQueuePage = (QueuePage*)mpQueue->Get();
+ while ( pQueuePage )
+ {
+ delete pQueuePage;
+ pQueuePage = (QueuePage*)mpQueue->Get();
+ }
+
+ delete mpQueue;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplQPrinter::Destroy()
+{
+ if( mbDestroyAllowed )
+ delete this;
+ else
+ mbDestroyed = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ImplQPrinter, ImplPrintHdl, Timer*, EMPTYARG )
+{
+ // Ist Drucken abgebrochen wurden?
+ if ( !IsPrinting() )
+ return 0;
+
+ // Nur drucken, wenn genuegend Seiten im Cache stehen
+ if ( mpParent->IsJobActive() && (mpQueue->Count() < (ULONG)mpParent->GetPageQueueSize()) )
+ return 0;
+
+ // Druck-Job zuende?
+ QueuePage* pActPage = (QueuePage*) mpQueue->Get();
+
+ if ( pActPage->mbEndJob )
+ {
+ maTimer.Stop();
+ delete pActPage;
+ EndJob();
+ mpParent->ImplEndPrint();
+ }
+ else
+ {
+ USHORT nCopyCount = 1;
+ GDIMetaFile aMtf;
+
+ mbDestroyAllowed = FALSE;
+ GetPreparedMetaFile( *pActPage->mpMtf, aMtf );
+
+ if ( mbUserCopy && !mbCollateCopy )
+ nCopyCount = mnCopyCount;
+
+ for ( USHORT i = 0; i < nCopyCount; i++ )
+ {
+ ULONG nActionPos = 0UL;
+
+ if ( pActPage->mpSetup )
+ {
+ SetJobSetup( *pActPage->mpSetup );
+ if ( mbAborted )
+ break;
+ }
+
+ StartPage();
+
+ if ( mbAborted )
+ break;
+
+ for( MetaAction* pAct = aMtf.FirstAction(); pAct; pAct = aMtf.NextAction() )
+ {
+ pAct->Execute( this );
+ Application::Reschedule();
+
+ if( mbAborted )
+ break;
+ }
+
+ if( !mbAborted )
+ EndPage();
+ else
+ break;
+ }
+
+ delete pActPage;
+ mbDestroyAllowed = TRUE;
+
+ if( mbDestroyed )
+ Destroy();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::StartQueuePrint()
+{
+ maTimer.SetTimeout( 50 );
+ maTimer.SetTimeoutHdl( LINK( this, ImplQPrinter, ImplPrintHdl ) );
+ maTimer.Start();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::EndQueuePrint()
+{
+ QueuePage* pQueuePage = new QueuePage;
+ pQueuePage->mbEndJob = TRUE;
+ mpQueue->Put( pQueuePage );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::AbortQueuePrint()
+{
+ maTimer.Stop();
+ mbAborted = TRUE;
+ AbortJob();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplQPrinter::AddQueuePage( GDIMetaFile* pPage, USHORT nPage, BOOL bNewJobSetup )
+{
+ QueuePage* pQueuePage = new QueuePage;
+ pQueuePage->mpMtf = pPage;
+ pQueuePage->mnPage = nPage;
+ pQueuePage->mbEndJob = FALSE;
+ if ( bNewJobSetup )
+ pQueuePage->mpSetup = new JobSetup( mpParent->GetJobSetup() );
+ mpQueue->Put( pQueuePage );
+}
+
+#endif
diff --git a/vcl/source/gdi/impvect.cxx b/vcl/source/gdi/impvect.cxx
new file mode 100644
index 000000000000..2a3e27ebf2c5
--- /dev/null
+++ b/vcl/source/gdi/impvect.cxx
@@ -0,0 +1,1267 @@
+/*************************************************************************
+ *
+ * $RCSfile: impvect.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_IMPVECT_CXX
+
+#include <stdlib.h>
+#include <tools/new.hxx>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_VECTORIZ_HXX
+#include <impvect.hxx>
+#endif
+
+// !!! ggf. einkommentieren, um Bitmaps zu erzeugen (nur, wenn File mit Debug uebersetzt wurde)
+// #define DEBUG_BMPOUTPUT
+
+#if defined DEBUG && defined DEBUG_BMPOUTPUT
+#define DBG_BMP 1
+#else
+#undef DBG_BMP
+#endif
+
+#ifdef DBG_BMP
+#include <tools/stream.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define VECT_POLY_MAX 8192
+
+// -----------------------------------------------------------------------------
+
+#define VECT_FREE_INDEX 0
+#define VECT_CONT_INDEX 1
+#define VECT_DONE_INDEX 2
+
+// -----------------------------------------------------------------------------
+
+#define VECT_POLY_INLINE_INNER 1UL
+#define VECT_POLY_INLINE_OUTER 2UL
+#define VECT_POLY_OUTLINE_INNER 4UL
+#define VECT_POLY_OUTLINE_OUTER 8UL
+
+// -----------------------------------------------------------------------------
+
+#define VECT_MAP( _def_pIn, _def_pOut, _def_nVal ) _def_pOut[_def_nVal]=(_def_pIn[_def_nVal]=((_def_nVal)*4L)+1L)+5L;
+#define BACK_MAP( _def_nVal ) ((((_def_nVal)+2)>>2)-1)
+#define VECT_PROGRESS( _def_pProgress, _def_nVal ) if(_def_pProgress&&_def_pProgress->IsSet())(_def_pProgress->Call((void*)_def_nVal));
+
+// -----------
+// - statics -
+// -----------
+
+struct ChainMove { long nDX; long nDY; };
+
+static ChainMove aImplMove[ 8 ] = {
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, -1L },
+ { -1, -1L },
+ { -1L, 1L },
+ { 1L, 1L }
+ };
+
+static ChainMove aImplMoveInner[ 8 ] = {
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L },
+ { -1L, 0L }
+ };
+
+static ChainMove aImplMoveOuter[ 8 ] = {
+ { 0L, -1L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { -1L, 0L },
+ { 0L, 1L },
+ { 1L, 0L },
+ { 0L, -1L }
+ };
+
+// ----------------
+// - ImplColorSet -
+// ----------------
+
+struct ImplColorSet
+{
+ BitmapColor maColor;
+ USHORT mnIndex;
+ BOOL mbSet;
+
+ BOOL operator<( const ImplColorSet& rSet ) const;
+ BOOL operator>( const ImplColorSet& rSet ) const;
+};
+
+// ----------------------------------------------------------------------------
+
+inline BOOL ImplColorSet::operator<( const ImplColorSet& rSet ) const
+{
+ return( mbSet && ( !rSet.mbSet || ( maColor.GetLuminance() > rSet.maColor.GetLuminance() ) ) );
+}
+
+// ----------------------------------------------------------------------------
+
+inline BOOL ImplColorSet::operator>( const ImplColorSet& rSet ) const
+{
+ return( !mbSet || ( rSet.mbSet && maColor.GetLuminance() < rSet.maColor.GetLuminance() ) );
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" int __LOADONCALLAPI ImplColorSetCmpFnc( const void* p1, const void* p2 )
+{
+ ImplColorSet* pSet1 = (ImplColorSet*) p1;
+ ImplColorSet* pSet2 = (ImplColorSet*) p2;
+ int nRet;
+
+ if( pSet1->mbSet && pSet2->mbSet )
+ {
+ const BYTE cLum1 = pSet1->maColor.GetLuminance();
+ const BYTE cLum2 = pSet2->maColor.GetLuminance();
+ nRet = ( ( cLum1 > cLum2 ) ? -1 : ( ( cLum1 == cLum2 ) ? 0 : 1 ) );
+ }
+ else if( pSet1->mbSet )
+ nRet = -1;
+ else if( pSet2->mbSet )
+ nRet = 1;
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+// ------------------
+// - ImplPointArray -
+// ------------------
+
+#ifdef WIN
+typedef Point* huge HPPoint;
+#else
+typedef Point* HPPoint;
+#endif
+
+class ImplPointArray
+{
+ HPPoint mpArray;
+ ULONG mnSize;
+ ULONG mnRealSize;
+
+public:
+
+ ImplPointArray();
+ ~ImplPointArray();
+
+ void ImplSetSize( ULONG nSize );
+
+ ULONG ImplGetRealSize() const { return mnRealSize; }
+ void ImplSetRealSize( ULONG nRealSize ) { mnRealSize = nRealSize; }
+
+ inline Point& operator[]( ULONG nPos );
+ inline const Point& operator[]( ULONG nPos ) const;
+
+ void ImplCreatePoly( Polygon& rPoly ) const;
+};
+
+// -----------------------------------------------------------------------------
+
+ImplPointArray::ImplPointArray() :
+ mnSize ( 0UL ),
+ mnRealSize ( 0UL ),
+ mpArray ( NULL )
+
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImplPointArray::~ImplPointArray()
+{
+ if( mpArray )
+ SvMemFree( mpArray );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplPointArray::ImplSetSize( ULONG nSize )
+{
+ const ULONG nTotal = nSize * sizeof( Point );
+
+ mnSize = nSize;
+ mnRealSize = 0UL;
+
+ if( mpArray )
+ SvMemFree( mpArray );
+
+ mpArray = (HPPoint) SvMemAlloc( nTotal );
+ HMEMSET( (HPBYTE) mpArray, 0, nTotal );
+}
+
+// -----------------------------------------------------------------------------
+
+inline Point& ImplPointArray::operator[]( ULONG nPos )
+{
+ DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
+ return mpArray[ nPos ];
+}
+
+// -----------------------------------------------------------------------------
+
+inline const Point& ImplPointArray::operator[]( ULONG nPos ) const
+{
+ DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
+ return mpArray[ nPos ];
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplPointArray::ImplCreatePoly( Polygon& rPoly ) const
+{
+ rPoly.SetSize( (USHORT) mnRealSize );
+ HMEMCPY( rPoly.ImplGetPointAry(), mpArray, mnRealSize * sizeof( Point ) );
+}
+
+// ---------------
+// - ImplVectMap -
+// ---------------
+
+class ImplVectMap
+{
+private:
+
+ Scanline mpBuf;
+ Scanline* mpScan;
+ long mnWidth;
+ long mnHeight;
+
+ ImplVectMap() {};
+
+public:
+
+ ImplVectMap( long nWidth, long nHeight );
+ ~ImplVectMap();
+
+ inline long Width() const { return mnWidth; }
+ inline long Height() const { return mnHeight; }
+
+ inline void Set( long nY, long nX, BYTE cVal );
+ inline BYTE Get( long nY, long nX ) const;
+
+ inline BOOL IsFree( long nY, long nX ) const;
+ inline BOOL IsCont( long nY, long nX ) const;
+ inline BOOL IsDone( long nY, long nX ) const;
+
+#ifdef DBG_BMP
+ Bitmap GetBitmap() const;
+#endif // DBG_BMP
+};
+
+// -----------------------------------------------------------------------------
+
+ImplVectMap::ImplVectMap( long nWidth, long nHeight ) :
+ mnWidth ( nWidth ),
+ mnHeight( nHeight )
+{
+ const long nWidthAl = ( nWidth >> 2L ) + 1L;
+ const long nSize = nWidthAl * nHeight;
+ Scanline pTmp = mpBuf = (Scanline) SvMemAlloc( nSize );
+
+ HMEMSET( mpBuf, 0, nSize );
+ mpScan = (Scanline*) SvMemAlloc( nHeight * sizeof( Scanline ) );
+
+ for( long nY = 0L; nY < nHeight; pTmp += nWidthAl )
+ mpScan[ nY++ ] = pTmp;
+}
+
+// -----------------------------------------------------------------------------
+
+
+ImplVectMap::~ImplVectMap()
+{
+ SvMemFree( mpBuf );
+ SvMemFree( mpScan );
+}
+
+// -----------------------------------------------------------------------------
+
+inline void ImplVectMap::Set( long nY, long nX, BYTE cVal )
+{
+ const BYTE cShift = 6 - ( ( nX & 3 ) << 1 );
+ ( ( mpScan[ nY ][ nX >> 2 ] ) &= ~( 3 << cShift ) ) |= ( cVal << cShift );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BYTE ImplVectMap::Get( long nY, long nX ) const
+{
+ return( ( ( mpScan[ nY ][ nX >> 2 ] ) >> ( 6 - ( ( nX & 3 ) << 1 ) ) ) & 3 );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsFree( long nY, long nX ) const
+{
+ return( VECT_FREE_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsCont( long nY, long nX ) const
+{
+ return( VECT_CONT_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+inline BOOL ImplVectMap::IsDone( long nY, long nX ) const
+{
+ return( VECT_DONE_INDEX == Get( nY, nX ) );
+}
+
+// -----------------------------------------------------------------------------
+
+#ifdef DBG_BMP
+Bitmap ImplVectMap::GetBitmap() const
+{
+ Bitmap aBmp( Size( mnWidth, mnHeight ), 4 );
+ BitmapWriteAccess* pAcc = aBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ for( long nY = 0L; nY < mnHeight; nY++ )
+ {
+ for( long nX = 0L; nX < mnWidth; nX++ )
+ {
+ switch( Get( nY, nX ) )
+ {
+ case( VECT_FREE_INDEX ): pAcc->SetPixel( nY, nX, 15 ); break;
+ case( VECT_CONT_INDEX ): pAcc->SetPixel( nY, nX, 0 ); break;
+ case( VECT_DONE_INDEX ): pAcc->SetPixel( nY, nX, 2); break;
+ }
+ }
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ }
+
+ return aBmp;
+}
+#endif // DBG_BMP
+
+// -------------
+// - ImplChain -
+// -------------
+
+class ImplChain
+{
+private:
+
+ Polygon maPoly;
+ Point maStartPt;
+ ULONG mnArraySize;
+ ULONG mnCount;
+ long mnResize;
+ BYTE* mpCodes;
+
+ void ImplGetSpace();
+
+ void ImplCreate();
+ void ImplCreateInner();
+ void ImplCreateOuter();
+ void ImplPostProcess( const ImplPointArray& rArr );
+
+public:
+
+ ImplChain( ULONG nInitCount = 1024UL, long nResize = -1L );
+ ~ImplChain();
+
+ void ImplBeginAdd( const Point& rStartPt );
+ inline void ImplAdd( BYTE nCode );
+ void ImplEndAdd( ULONG nTypeFlag );
+
+ const Polygon& ImplGetPoly() { return maPoly; }
+};
+
+// -----------------------------------------------------------------------------
+
+ImplChain::ImplChain( ULONG nInitCount, long nResize ) :
+ mnCount ( 0UL ),
+ mnArraySize ( nInitCount ),
+ mnResize ( nResize )
+{
+ DBG_ASSERT( nInitCount && nResize, "ImplChain::ImplChain(): invalid parameters!" );
+ mpCodes = new BYTE[ mnArraySize ];
+}
+
+// -----------------------------------------------------------------------------
+
+ImplChain::~ImplChain()
+{
+ delete[] mpCodes;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplGetSpace()
+{
+ const ULONG nOldArraySize = mnArraySize;
+ BYTE* pNewCodes;
+
+ mnArraySize = ( mnResize < 0L ) ? ( mnArraySize << 1UL ) : ( mnArraySize + (ULONG) mnResize );
+ pNewCodes = new BYTE[ mnArraySize ];
+ HMEMCPY( pNewCodes, mpCodes, nOldArraySize );
+ delete[] mpCodes;
+ mpCodes = pNewCodes;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplBeginAdd( const Point& rStartPt )
+{
+ maPoly = Polygon();
+ maStartPt = rStartPt;
+ mnCount = 0UL;
+}
+
+// -----------------------------------------------------------------------------
+
+inline void ImplChain::ImplAdd( BYTE nCode )
+{
+ if( mnCount == mnArraySize )
+ ImplGetSpace();
+
+ mpCodes[ mnCount++ ] = nCode;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplEndAdd( ULONG nFlag )
+{
+ if( mnCount )
+ {
+ ImplPointArray aArr;
+
+ if( nFlag & VECT_POLY_INLINE_INNER )
+ {
+ long nFirstX, nFirstY;
+ long nLastX, nLastY;
+
+ nFirstX = nLastX = maStartPt.X();
+ nFirstY = nLastY = maStartPt.Y();
+ aArr.ImplSetSize( mnCount << 1 );
+
+ USHORT i, nPolyPos;
+ for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
+ {
+ const BYTE cMove = mpCodes[ i ];
+ const BYTE cNextMove = mpCodes[ i + 1 ];
+ const ChainMove& rMove = aImplMove[ cMove ];
+ const ChainMove& rMoveInner = aImplMoveInner[ cMove ];
+ Point& rPt = aArr[ nPolyPos ];
+ BOOL bDone = TRUE;
+
+ nLastX += rMove.nDX;
+ nLastY += rMove.nDY;
+
+ if( cMove < 4 )
+ {
+ if( ( cMove == 0 && cNextMove == 3 ) ||
+ ( cMove == 3 && cNextMove == 2 ) ||
+ ( cMove == 2 && cNextMove == 1 ) ||
+ ( cMove == 1 && cNextMove == 0 ) )
+ {
+ }
+ else if( cMove == 2 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 3 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 0 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 1 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+ }
+ else
+ bDone = FALSE;
+ }
+ else if( cMove == 7 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 4 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else
+ bDone = FALSE;
+
+ if( !bDone )
+ {
+ aArr[ nPolyPos ].X() = nLastX + rMoveInner.nDX;
+ aArr[ nPolyPos++ ].Y() = nLastY + rMoveInner.nDY;
+ }
+ }
+
+ aArr[ nPolyPos ].X() = nFirstX + 1L;
+ aArr[ nPolyPos++ ].Y() = nFirstY + 1L;
+ aArr.ImplSetRealSize( nPolyPos );
+ }
+ else if( nFlag & VECT_POLY_INLINE_OUTER )
+ {
+ long nFirstX, nFirstY;
+ long nLastX, nLastY;
+
+ nFirstX = nLastX = maStartPt.X();
+ nFirstY = nLastY = maStartPt.Y();
+ aArr.ImplSetSize( mnCount << 1 );
+
+ USHORT i, nPolyPos;
+ for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
+ {
+ const BYTE cMove = mpCodes[ i ];
+ const BYTE cNextMove = mpCodes[ i + 1 ];
+ const ChainMove& rMove = aImplMove[ cMove ];
+ const ChainMove& rMoveOuter = aImplMoveOuter[ cMove ];
+ Point& rPt = aArr[ nPolyPos ];
+ BOOL bDone = TRUE;
+
+ nLastX += rMove.nDX;
+ nLastY += rMove.nDY;
+
+ if( cMove < 4 )
+ {
+ if( ( cMove == 0 && cNextMove == 1 ) ||
+ ( cMove == 1 && cNextMove == 2 ) ||
+ ( cMove == 2 && cNextMove == 3 ) ||
+ ( cMove == 3 && cNextMove == 0 ) )
+ {
+ }
+ else if( cMove == 0 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 3 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else if( cMove == 2 && cNextMove == 1 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 1 && cNextMove == 0 )
+ {
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX - 1;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+ }
+ else
+ bDone = FALSE;
+ }
+ else if( cMove == 7 && cNextMove == 3 )
+ {
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY - 1;
+
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+ }
+ else if( cMove == 6 && cNextMove == 2 )
+ {
+ aArr[ nPolyPos ].X() = nLastX + 1;
+ aArr[ nPolyPos++ ].Y() = nLastY;
+
+ aArr[ nPolyPos ].X() = nLastX;
+ aArr[ nPolyPos++ ].Y() = nLastY + 1;
+ }
+ else
+ bDone = FALSE;
+
+ if( !bDone )
+ {
+ aArr[ nPolyPos ].X() = nLastX + rMoveOuter.nDX;
+ aArr[ nPolyPos++ ].Y() = nLastY + rMoveOuter.nDY;
+ }
+ }
+
+ aArr[ nPolyPos ].X() = nFirstX - 1L;
+ aArr[ nPolyPos++ ].Y() = nFirstY - 1L;
+ aArr.ImplSetRealSize( nPolyPos );
+ }
+ else
+ {
+ long nLastX = maStartPt.X(), nLastY = maStartPt.Y();
+
+ aArr.ImplSetSize( mnCount + 1 );
+ aArr[ 0 ] = Point( nLastX, nLastY );
+
+ for( ULONG i = 0; i < mnCount; )
+ {
+ const ChainMove& rMove = aImplMove[ mpCodes[ i ] ];
+ aArr[ ++i ] = Point( nLastX += rMove.nDX, nLastY += rMove.nDY );
+ }
+
+ aArr.ImplSetRealSize( mnCount + 1 );
+ }
+
+ ImplPostProcess( aArr );
+ }
+ else
+ maPoly.SetSize( 0 );
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplChain::ImplPostProcess( const ImplPointArray& rArr )
+{
+ ImplPointArray aNewArr1;
+ ImplPointArray aNewArr2;
+ Point* pLast;
+ Point* pLeast;
+ ULONG nNewPos;
+ ULONG nCount = rArr.ImplGetRealSize();
+ ULONG n;
+
+ // pass 1
+ aNewArr1.ImplSetSize( nCount );
+ pLast = &( aNewArr1[ 0 ] );
+ pLast->X() = BACK_MAP( rArr[ 0 ].X() );
+ pLast->Y() = BACK_MAP( rArr[ 0 ].Y() );
+
+ for( n = nNewPos = 1; n < nCount; )
+ {
+ const Point& rPt = rArr[ n++ ];
+ const long nX = BACK_MAP( rPt.X() );
+ const long nY = BACK_MAP( rPt.Y() );
+
+ if( nX != pLast->X() || nY != pLast->Y() )
+ {
+ pLast = pLeast = &( aNewArr1[ nNewPos++ ] );
+ pLeast->X() = nX;
+ pLeast->Y() = nY;
+ }
+ }
+
+ aNewArr1.ImplSetRealSize( nCount = nNewPos );
+
+ // pass 2
+ aNewArr2.ImplSetSize( nCount );
+ pLast = &( aNewArr2[ 0 ] );
+ *pLast = aNewArr1[ 0 ];
+
+ for( n = nNewPos = 1; n < nCount; )
+ {
+ pLeast = &( aNewArr1[ n++ ] );
+
+ if( pLeast->X() == pLast->X() )
+ {
+ while( n < nCount && aNewArr1[ n ].X() == pLast->X() )
+ pLeast = &( aNewArr1[ n++ ] );
+ }
+ else if( pLeast->Y() == pLast->Y() )
+ {
+ while( n < nCount && aNewArr1[ n ].Y() == pLast->Y() )
+ pLeast = &( aNewArr1[ n++ ] );
+ }
+
+ aNewArr2[ nNewPos++ ] = *( pLast = pLeast );
+ }
+
+ aNewArr2.ImplSetRealSize( nNewPos );
+ aNewArr2.ImplCreatePoly( maPoly );
+}
+
+// ------------------
+// - ImplVectorizer -
+// ------------------
+
+ImplVectorizer::ImplVectorizer()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ImplVectorizer::~ImplVectorizer()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf,
+ BYTE cReduce, ULONG nFlags, const Link* pProgress )
+{
+ BOOL bRet = FALSE;
+
+ VECT_PROGRESS( pProgress, 0 );
+
+ Bitmap* pBmp = new Bitmap( rColorBmp );
+ BitmapReadAccess* pRAcc = pBmp->AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ PolyPolygon aPolyPoly;
+ double fPercent = 0.0;
+ double fPercentStep_2 = 0.0;
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+ const USHORT nColorCount = pRAcc->GetPaletteEntryCount();
+ USHORT n;
+ ImplColorSet* pColorSet = (ImplColorSet*) new BYTE[ 256 * sizeof( ImplColorSet ) ];
+
+ memset( pColorSet, 0, 256 * sizeof( ImplColorSet ) );
+ rMtf.Clear();
+
+ // get used palette colors and sort them from light to dark colors
+ for( n = 0; n < nColorCount; n++ )
+ {
+ pColorSet[ n ].mnIndex = n;
+ pColorSet[ n ].maColor = pRAcc->GetPaletteColor( n );
+ }
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pColorSet[ pRAcc->GetPixel( nY, nX ).GetIndex() ].mbSet = 1;
+
+ qsort( pColorSet, 256, sizeof( ImplColorSet ), ImplColorSetCmpFnc );
+
+ for( n = 0; n < 256; n++ )
+ if( !pColorSet[ n ].mbSet )
+ break;
+
+ if( n )
+ fPercentStep_2 = 45.0 / n;
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += 10.0 ) );
+
+ for( USHORT i = 0; i < n; i++ )
+ {
+ const BitmapColor aBmpCol( pRAcc->GetPaletteColor( pColorSet[ i ].mnIndex ) );
+ const Color aFindColor( aBmpCol.GetRed(), aBmpCol.GetGreen(), aBmpCol.GetBlue() );
+ const BYTE cLum = aFindColor.GetLuminance();
+ ImplVectMap* pMap = ImplExpand( pRAcc, aFindColor );
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
+
+ if( pMap )
+ {
+ aPolyPoly.Clear();
+ ImplCalculate( pMap, aPolyPoly, cReduce, nFlags );
+ delete pMap;
+
+ if( aPolyPoly.Count() )
+ {
+ ImplLimitPolyPoly( aPolyPoly );
+
+ if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
+ aPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
+
+ if( aPolyPoly.Count() )
+ {
+ rMtf.AddAction( new MetaLineColorAction( aFindColor, TRUE ) );
+ rMtf.AddAction( new MetaFillColorAction( aFindColor, TRUE ) );
+ rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ }
+ }
+ }
+
+ VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
+ }
+
+ delete[] (BYTE*) pColorSet;
+
+ if( rMtf.GetActionCount() )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ VirtualDevice aVDev;
+ const Size aLogSize1( aVDev.PixelToLogic( Size( 1, 1 ), aMap ) );
+
+ rMtf.SetPrefMapMode( aMap );
+ rMtf.SetPrefSize( Size( nWidth + 2, nHeight + 2 ) );
+ rMtf.Move( 1, 1 );
+ rMtf.Scale( aLogSize1.Width(), aLogSize1.Height() );
+ bRet = TRUE;
+ }
+ }
+
+ pBmp->ReleaseAccess( pRAcc );
+ delete pBmp;
+ VECT_PROGRESS( pProgress, 100 );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplVectorize( const Bitmap& rMonoBmp,
+ PolyPolygon& rPolyPoly,
+ ULONG nFlags, const Link* pProgress )
+{
+ Bitmap* pBmp = new Bitmap( rMonoBmp );
+ BitmapReadAccess* pRAcc;
+ ImplVectMap* pMap;
+ BOOL bRet = FALSE;
+
+ VECT_PROGRESS( pProgress, 10 );
+
+ if( pBmp->GetBitCount() > 1 )
+ pBmp->Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ VECT_PROGRESS( pProgress, 30 );
+
+ pRAcc = pBmp->AcquireReadAccess();
+ pMap = ImplExpand( pRAcc, COL_BLACK );
+ pBmp->ReleaseAccess( pRAcc );
+ delete pBmp;
+
+ VECT_PROGRESS( pProgress, 60 );
+
+ if( pMap )
+ {
+ rPolyPoly.Clear();
+ ImplCalculate( pMap, rPolyPoly, 0, nFlags );
+ delete pMap;
+ ImplLimitPolyPoly( rPolyPoly );
+
+ if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
+ rPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
+
+ bRet = TRUE;
+ }
+
+ VECT_PROGRESS( pProgress, 100 );
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplVectorizer::ImplLimitPolyPoly( PolyPolygon& rPolyPoly )
+{
+ if( rPolyPoly.Count() > VECT_POLY_MAX )
+ {
+ PolyPolygon aNewPolyPoly;
+ long nReduce = 0;
+ USHORT nNewCount;
+
+ do
+ {
+ aNewPolyPoly.Clear();
+ nReduce++;
+
+ for( USHORT i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ const Rectangle aBound( rPolyPoly[ i ].GetBoundRect() );
+
+ if( aBound.GetWidth() > nReduce && aBound.GetHeight() > nReduce )
+ {
+ if( rPolyPoly[ i ].GetSize() )
+ aNewPolyPoly.Insert( rPolyPoly[ i ] );
+ }
+ }
+
+ nNewCount = aNewPolyPoly.Count();
+ }
+ while( nNewCount > VECT_POLY_MAX );
+
+ rPolyPoly = aNewPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+ImplVectMap* ImplVectorizer::ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor )
+{
+ ImplVectMap* pMap = NULL;
+
+ if( pRAcc && pRAcc->Width() && pRAcc->Height() )
+ {
+ const long nOldWidth = pRAcc->Width();
+ const long nOldHeight = pRAcc->Height();
+ const long nNewWidth = ( nOldWidth << 2L ) + 4L;
+ const long nNewHeight = ( nOldHeight << 2L ) + 4L;
+ const BitmapColor aTest( pRAcc->GetBestMatchingColor( rColor ) );
+ long* pMapIn = new long[ Max( nOldWidth, nOldHeight ) ];
+ long* pMapOut = new long[ Max( nOldWidth, nOldHeight ) ];
+ long nX, nY, nTmpX, nTmpY;
+
+ pMap = new ImplVectMap( nNewWidth, nNewHeight );
+
+ for( nX = 0L; nX < nOldWidth; nX++ )
+ VECT_MAP( pMapIn, pMapOut, nX );
+
+ for( nY = 0L, nTmpY = 5L; nY < nOldHeight; nY++, nTmpY += 4L )
+ {
+ for( nX = 0L; nX < nOldWidth; )
+ {
+ if( pRAcc->GetPixel( nY, nX ) == aTest )
+ {
+ nTmpX = pMapIn[ nX++ ];
+ nTmpY -= 3L;
+
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+
+ while( nX < nOldWidth && pRAcc->GetPixel( nY, nX ) == aTest )
+ nX++;
+
+ nTmpX = pMapOut[ nX - 1L ];
+ nTmpY -= 3L;
+
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+ }
+ else
+ nX++;
+ }
+ }
+
+ for( nY = 0L; nY < nOldHeight; nY++ )
+ VECT_MAP( pMapIn, pMapOut, nY );
+
+ for( nX = 0L, nTmpX = 5L; nX < nOldWidth; nX++, nTmpX += 4L )
+ {
+ for( nY = 0L; nY < nOldHeight; )
+ {
+ if( pRAcc->GetPixel( nY, nX ) == aTest )
+ {
+ nTmpX -= 3L;
+ nTmpY = pMapIn[ nY++ ];
+
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+
+ while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest )
+ nY++;
+
+ nTmpX -= 3L;
+ nTmpY = pMapOut[ nY - 1L ];
+
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
+ pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
+ }
+ else
+ nY++;
+ }
+ }
+
+ // cleanup
+ delete[] pMapIn;
+ delete[] pMapOut;
+ }
+
+ return pMap;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplVectorizer::ImplCalculate( ImplVectMap* pMap, PolyPolygon& rPolyPoly, BYTE cReduce, ULONG nFlags )
+{
+ const long nWidth = pMap->Width(), nHeight= pMap->Height();
+
+#ifdef DBG_BMP
+ if( pMap )
+ {
+ SvFileStream aOStm( "d:\\cont.bmp", STREAM_WRITE | STREAM_TRUNC );
+ aOStm << pMap->GetBitmap();
+ }
+#endif // DBG_BMP
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ long nX = 0L;
+ BOOL bInner = TRUE;
+
+ while( nX < nWidth )
+ {
+ // skip free
+ while( ( nX < nWidth ) && pMap->IsFree( nY, nX ) )
+ nX++;
+
+ if( nX == nWidth )
+ break;
+
+ if( pMap->IsCont( nY, nX ) )
+ {
+ // new contour
+ ImplChain aChain;
+ const Point aStartPt( nX++, nY );
+
+ // get chain code
+ aChain.ImplBeginAdd( aStartPt );
+ ImplGetChain( pMap, aStartPt, aChain );
+
+ if( nFlags & BMP_VECTORIZE_INNER )
+ aChain.ImplEndAdd( bInner ? VECT_POLY_INLINE_INNER : VECT_POLY_INLINE_OUTER );
+ else
+ aChain.ImplEndAdd( bInner ? VECT_POLY_OUTLINE_INNER : VECT_POLY_OUTLINE_OUTER );
+
+ const Polygon& rPoly = aChain.ImplGetPoly();
+
+ if( rPoly.GetSize() > 2 )
+ {
+ if( cReduce )
+ {
+ const Rectangle aBound( rPoly.GetBoundRect() );
+
+ if( aBound.GetWidth() > cReduce && aBound.GetHeight() > cReduce )
+ rPolyPoly.Insert( rPoly );
+ }
+ else
+ rPolyPoly.Insert( rPoly );
+ }
+
+ // skip rest of detected contour
+ while( pMap->IsCont( nY, nX ) )
+ nX++;
+ }
+ else
+ {
+ // process done segment
+ const long nStartSegX = nX++;
+
+ while( pMap->IsDone( nY, nX ) )
+ nX++;
+
+ if( ( ( nX - nStartSegX ) == 1L ) || ( ImplIsUp( pMap, nY, nStartSegX ) != ImplIsUp( pMap, nY, nX - 1L ) ) )
+ bInner = !bInner;
+ }
+ }
+ }
+
+#ifdef DBG_BMP
+ if( pMap )
+ {
+ SvFileStream aOStm( "d:\\vect.bmp", STREAM_WRITE | STREAM_TRUNC );
+ aOStm << pMap->GetBitmap();
+ }
+#endif // DBG_BMP
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain )
+{
+ long nActX = rStartPt.X();
+ long nActY = rStartPt.Y();
+ long nTryX;
+ long nTryY;
+ ULONG nFound;
+ ULONG nLastDir = 0UL;
+ ULONG nDir;
+
+ do
+ {
+ nFound = 0UL;
+
+ // first try last direction
+ nTryX = nActX + aImplMove[ nLastDir ].nDX;
+ nTryY = nActY + aImplMove[ nLastDir ].nDY;
+
+ if( pMap->IsCont( nTryY, nTryX ) )
+ {
+ rChain.ImplAdd( (BYTE) nLastDir );
+ pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
+ nFound = 1UL;
+ }
+ else
+ {
+ // try other directions
+ for( nDir = 0UL; nDir < 8UL; nDir++ )
+ {
+ // we already tried nLastDir
+ if( nDir != nLastDir )
+ {
+ nTryX = nActX + aImplMove[ nDir ].nDX;
+ nTryY = nActY + aImplMove[ nDir ].nDY;
+
+ if( pMap->IsCont( nTryY, nTryX ) )
+ {
+ rChain.ImplAdd( (BYTE) nDir );
+ pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
+ nFound = 1UL;
+ nLastDir = nDir;
+ break;
+ }
+ }
+ }
+ }
+ }
+ while( nFound );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------------
+
+BOOL ImplVectorizer::ImplIsUp( ImplVectMap* pMap, long nY, long nX ) const
+{
+ if( pMap->IsDone( nY - 1L, nX ) )
+ return TRUE;
+ else if( pMap->IsDone( nY + 1L, nX ) )
+ return FALSE;
+ else if( pMap->IsDone( nY - 1L, nX - 1L ) || pMap->IsDone( nY - 1L, nX + 1L ) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/gdi/impvect.hxx b/vcl/source/gdi/impvect.hxx
new file mode 100644
index 000000000000..34750c220109
--- /dev/null
+++ b/vcl/source/gdi/impvect.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * $RCSfile: impvect.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SV_IMPVECT_HXX
+#define _SV_IMPVECT_HXX
+
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+
+// --------------
+// - Vectorizer -
+// --------------
+
+class BitmapReadAccess;
+class ImplChain;
+class ImplVectMap;
+
+class ImplVectorizer
+{
+private:
+
+ ImplVectMap* ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor );
+ void ImplCalculate( ImplVectMap* pMap, PolyPolygon& rPolyPoly, BYTE cReduce, ULONG nFlags );
+ BOOL ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain );
+ BOOL ImplIsUp( ImplVectMap* pMap, long nY, long nX ) const;
+ void ImplLimitPolyPoly( PolyPolygon& rPolyPoly );
+
+public:
+
+ ImplVectorizer();
+ ~ImplVectorizer();
+
+ BOOL ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf,
+ BYTE cReduce, ULONG nFlags, const Link* pProgress );
+ BOOL ImplVectorize( const Bitmap& rMonoBmp, PolyPolygon& rPolyPoly,
+ ULONG nFlags, const Link* pProgress );
+};
+
+#endif
diff --git a/vcl/source/gdi/jobset.cxx b/vcl/source/gdi/jobset.cxx
new file mode 100644
index 000000000000..7edcf104d113
--- /dev/null
+++ b/vcl/source/gdi/jobset.cxx
@@ -0,0 +1,415 @@
+/*************************************************************************
+ *
+ * $RCSfile: jobset.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_JOBSET_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_JOBSET_HXX
+#include <jobset.hxx>
+#endif
+#ifndef _SV_JOBSET_H
+#include <jobset.h>
+#endif
+
+// =======================================================================
+
+DBG_NAME( JobSetup );
+
+#define JOBSET_FILEFORMAT2 3780
+#define JOBSET_FILE364_SYSTEM ((USHORT)0xFFFF)
+
+struct ImplOldJobSetupData
+{
+ char cPrinterName[64];
+ char cDeviceName[32];
+ char cPortName[32];
+ char cDriverName[32];
+};
+
+struct Impl364JobSetupData
+{
+ SVBT16 nSize;
+ SVBT16 nSystem;
+ SVBT32 nDriverDataLen;
+ SVBT16 nOrientation;
+ SVBT16 nPaperBin;
+ SVBT16 nPaperFormat;
+ SVBT32 nPaperWidth;
+ SVBT32 nPaperHeight;
+};
+
+// =======================================================================
+
+ImplJobSetup::ImplJobSetup()
+{
+ mnRefCount = 1;
+ mnSystem = 0;
+ meOrientation = ORIENTATION_PORTRAIT;
+ mnPaperBin = 0;
+ mePaperFormat = PAPER_USER;
+ mnPaperWidth = 0;
+ mnPaperHeight = 0;
+ mnDriverDataLen = 0;
+ mpDriverData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup::ImplJobSetup( const ImplJobSetup& rJobSetup ) :
+ maPrinterName( rJobSetup.maPrinterName ),
+ maDriver( rJobSetup.maDriver )
+{
+ mnRefCount = 1;
+ mnSystem = rJobSetup.mnSystem;
+ meOrientation = rJobSetup.meOrientation;
+ mnPaperBin = rJobSetup.mnPaperBin;
+ mePaperFormat = rJobSetup.mePaperFormat;
+ mnPaperWidth = rJobSetup.mnPaperWidth;
+ mnPaperHeight = rJobSetup.mnPaperHeight;
+ mnDriverDataLen = rJobSetup.mnDriverDataLen;
+ if ( rJobSetup.mpDriverData )
+ {
+ mpDriverData = new BYTE[mnDriverDataLen];
+ memcpy( mpDriverData, rJobSetup.mpDriverData, mnDriverDataLen );
+ }
+ else
+ mpDriverData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup::~ImplJobSetup()
+{
+ delete mpDriverData;
+}
+
+// =======================================================================
+
+ImplJobSetup* JobSetup::ImplGetData()
+{
+ if ( !mpData )
+ mpData = new ImplJobSetup;
+ else if ( mpData->mnRefCount != 1 )
+ {
+ mpData->mnRefCount--;
+ mpData = new ImplJobSetup( *mpData );
+ }
+
+ return mpData;
+}
+
+// -----------------------------------------------------------------------
+
+ImplJobSetup* JobSetup::ImplGetConstData()
+{
+ if ( !mpData )
+ mpData = new ImplJobSetup;
+ return mpData;
+}
+
+// -----------------------------------------------------------------------
+
+const ImplJobSetup* JobSetup::ImplGetConstData() const
+{
+ if ( !mpData )
+ ((JobSetup*)this)->mpData = new ImplJobSetup;
+ return mpData;
+}
+
+// =======================================================================
+
+JobSetup::JobSetup()
+{
+ DBG_CTOR( JobSetup, NULL );
+
+ mpData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup::JobSetup( const JobSetup& rJobSetup )
+{
+ DBG_CTOR( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+ DBG_ASSERT( !rJobSetup.mpData || (rJobSetup.mpData->mnRefCount < 0xFFFE), "JobSetup: RefCount overflow" );
+
+ mpData = rJobSetup.mpData;
+ if ( mpData )
+ mpData->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup::~JobSetup()
+{
+ DBG_DTOR( JobSetup, NULL );
+
+ if ( mpData )
+ {
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString JobSetup::GetPrinterName() const
+{
+ if ( mpData )
+ return mpData->maPrinterName;
+ else
+ {
+ XubString aName;
+ return aName;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString JobSetup::GetDriverName() const
+{
+ if ( mpData )
+ return mpData->maDriver;
+ else
+ {
+ XubString aDriver;
+ return aDriver;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+JobSetup& JobSetup::operator=( const JobSetup& rJobSetup )
+{
+ DBG_CHKTHIS( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+ DBG_ASSERT( !rJobSetup.mpData || (rJobSetup.mpData->mnRefCount) < 0xFFFE, "JobSetup: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rJobSetup.mpData )
+ rJobSetup.mpData->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpData )
+ {
+ if ( mpData->mnRefCount == 1 )
+ delete mpData;
+ else
+ mpData->mnRefCount--;
+ }
+
+ mpData = rJobSetup.mpData;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL JobSetup::operator==( const JobSetup& rJobSetup ) const
+{
+ DBG_CHKTHIS( JobSetup, NULL );
+ DBG_CHKOBJ( &rJobSetup, JobSetup, NULL );
+
+ if ( mpData == rJobSetup.mpData )
+ return TRUE;
+
+ if ( !mpData || !rJobSetup.mpData )
+ return FALSE;
+
+ ImplJobSetup* pData1 = mpData;
+ ImplJobSetup* pData2 = rJobSetup.mpData;
+ if ( (pData1->mnSystem == pData2->mnSystem) &&
+ (pData1->maPrinterName == pData2->maPrinterName) &&
+ (pData1->maDriver == pData2->maDriver) &&
+ (pData1->meOrientation == pData2->meOrientation) &&
+ (pData1->mnPaperBin == pData2->mnPaperBin) &&
+ (pData1->mePaperFormat == pData2->mePaperFormat) &&
+ (pData1->mnPaperWidth == pData2->mnPaperWidth) &&
+ (pData1->mnPaperHeight == pData2->mnPaperHeight) &&
+ (pData1->mnDriverDataLen == pData2->mnDriverDataLen) &&
+ (memcmp( pData1->mpDriverData, pData2->mpDriverData, pData1->mnDriverDataLen ) == 0) )
+ return TRUE;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, JobSetup& rJobSetup )
+{
+ DBG_ASSERTWARNING( rIStream.GetVersion(), "JobSetup::>> - Solar-Version not set on rOStream" );
+
+ // Zur Zeit haben wir noch kein neues FileFormat
+// if ( rIStream.GetVersion() < JOBSET_FILEFORMAT2 )
+ {
+ USHORT nLen;
+ USHORT nSystem;
+ rIStream >> nLen;
+ if ( !nLen )
+ return rIStream;
+ rIStream >> nSystem;
+ char* pTempBuf = new char[nLen];
+ rIStream.Read( pTempBuf, nLen - sizeof( nLen ) - sizeof( nSystem ) );
+ if ( nLen >= sizeof(ImplOldJobSetupData)+4 )
+ {
+ ImplOldJobSetupData* pData = (ImplOldJobSetupData*)pTempBuf;
+ if ( rJobSetup.mpData )
+ {
+ if ( rJobSetup.mpData->mnRefCount == 1 )
+ delete rJobSetup.mpData;
+ else
+ rJobSetup.mpData->mnRefCount--;
+ }
+ rJobSetup.mpData = new ImplJobSetup;
+ ImplJobSetup* pJobData = rJobSetup.mpData;
+ pJobData->maPrinterName = UniString( pData->cPrinterName, RTL_TEXTENCODING_UTF8 );
+ pJobData->maDriver = UniString( pData->cDriverName, RTL_TEXTENCODING_UTF8 );
+
+ // Sind es unsere neuen JobSetup-Daten?
+ if ( nSystem == JOBSET_FILE364_SYSTEM )
+ {
+ Impl364JobSetupData* pOldJobData = (Impl364JobSetupData*)(pTempBuf + sizeof( ImplOldJobSetupData ));
+ USHORT nOldJobDataSize = SVBT16ToShort( pOldJobData->nSize );
+ pJobData->mnSystem = SVBT16ToShort( pOldJobData->nSystem );
+ pJobData->mnDriverDataLen = SVBT32ToLong( pOldJobData->nDriverDataLen );
+ pJobData->meOrientation = (Orientation)SVBT16ToShort( pOldJobData->nOrientation );
+ pJobData->mnPaperBin = SVBT16ToShort( pOldJobData->nPaperBin );
+ pJobData->mePaperFormat = (Paper)SVBT16ToShort( pOldJobData->nPaperFormat );
+ pJobData->mnPaperWidth = (long)SVBT32ToLong( pOldJobData->nPaperWidth );
+ pJobData->mnPaperHeight = (long)SVBT32ToLong( pOldJobData->nPaperHeight );
+ if ( pJobData->mnDriverDataLen )
+ {
+ BYTE* pDriverData = ((BYTE*)pOldJobData) + nOldJobDataSize;
+ pJobData->mpDriverData = new BYTE[pJobData->mnDriverDataLen];
+ memcpy( pJobData->mpDriverData, pDriverData, pJobData->mnDriverDataLen );
+ }
+ }
+ }
+ delete pTempBuf;
+ }
+/*
+ else
+ {
+ }
+*/
+
+ return rIStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const JobSetup& rJobSetup )
+{
+ DBG_ASSERTWARNING( rOStream.GetVersion(), "JobSetup::<< - Solar-Version not set on rOStream" );
+
+ // Zur Zeit haben wir noch kein neues FileFormat
+// if ( rOStream.GetVersion() < JOBSET_FILEFORMAT2 )
+ {
+ USHORT nLen = 0;
+ if ( !rJobSetup.mpData )
+ rOStream << nLen;
+ else
+ {
+ USHORT nSystem = JOBSET_FILE364_SYSTEM;
+
+ const ImplJobSetup* pJobData = rJobSetup.ImplGetConstData();
+ Impl364JobSetupData aOldJobData;
+ USHORT nOldJobDataSize = sizeof( aOldJobData );
+ ShortToSVBT16( nOldJobDataSize, aOldJobData.nSize );
+ ShortToSVBT16( pJobData->mnSystem, aOldJobData.nSystem );
+ LongToSVBT32( pJobData->mnDriverDataLen, aOldJobData.nDriverDataLen );
+ ShortToSVBT16( (USHORT)(pJobData->meOrientation), aOldJobData.nOrientation );
+ ShortToSVBT16( pJobData->mnPaperBin, aOldJobData.nPaperBin );
+ ShortToSVBT16( (USHORT)(pJobData->mePaperFormat), aOldJobData.nPaperFormat );
+ LongToSVBT32( (ULONG)(pJobData->mnPaperWidth), aOldJobData.nPaperWidth );
+ LongToSVBT32( (ULONG)(pJobData->mnPaperHeight), aOldJobData.nPaperHeight );
+
+ ImplOldJobSetupData aOldData;
+ memset( &aOldData, 0, sizeof( aOldData ) );
+ ByteString aPrnByteName( rJobSetup.GetPrinterName(), RTL_TEXTENCODING_UTF8 );
+ strncpy( aOldData.cPrinterName, aPrnByteName.GetBuffer(), 63 );
+ ByteString aDriverByteName( rJobSetup.GetDriverName(), RTL_TEXTENCODING_UTF8 );
+ strncpy( aOldData.cDriverName, aDriverByteName.GetBuffer(), 31 );
+ nLen = sizeof( aOldData ) + 4 + nOldJobDataSize + pJobData->mnDriverDataLen;
+ rOStream << nLen;
+ rOStream << nSystem;
+ rOStream.Write( (char*)&aOldData, sizeof( aOldData ) );
+ rOStream.Write( (char*)&aOldJobData, nOldJobDataSize );
+ rOStream.Write( (char*)pJobData->mpDriverData, pJobData->mnDriverDataLen );
+ }
+ }
+/*
+ else
+ {
+ }
+*/
+
+ return rOStream;
+}
diff --git a/vcl/source/gdi/lineinfo.cxx b/vcl/source/gdi/lineinfo.cxx
new file mode 100644
index 000000000000..fde91e8ee702
--- /dev/null
+++ b/vcl/source/gdi/lineinfo.cxx
@@ -0,0 +1,300 @@
+/*************************************************************************
+ *
+ * $RCSfile: lineinfo.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_LINEINFO_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+
+DBG_NAME( LineInfo );
+
+// ----------------
+// - ImplLineInfo -
+// ----------------
+
+ImplLineInfo::ImplLineInfo() :
+ mnRefCount ( 1 ),
+ meStyle ( LINE_SOLID ),
+ mnWidth ( 0 ),
+ mnDashCount ( 0 ),
+ mnDashLen ( 0 ),
+ mnDotCount ( 0 ),
+ mnDotLen ( 0 ),
+ mnDistance ( 0 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
+ mnRefCount ( 1 ),
+ meStyle ( rImplLineInfo.meStyle ),
+ mnWidth ( rImplLineInfo.mnWidth ),
+ mnDashCount ( rImplLineInfo.mnDashCount ),
+ mnDashLen ( rImplLineInfo.mnDashLen ),
+ mnDotCount ( rImplLineInfo.mnDotCount ),
+ mnDotLen ( rImplLineInfo.mnDotLen ),
+ mnDistance ( rImplLineInfo.mnDistance )
+{
+}
+
+// ------------
+// - LineInfo -
+// ------------
+
+LineInfo::LineInfo( LineStyle eStyle, long nWidth )
+{
+ DBG_CTOR( LineInfo, NULL );
+ mpImplLineInfo = new ImplLineInfo;
+ mpImplLineInfo->meStyle = eStyle;
+ mpImplLineInfo->mnWidth = nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo::LineInfo( const LineInfo& rLineInfo )
+{
+ DBG_CTOR( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+ mpImplLineInfo = rLineInfo.mpImplLineInfo;
+ mpImplLineInfo->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo::~LineInfo()
+{
+ DBG_DTOR( LineInfo, NULL );
+ if( !( --mpImplLineInfo->mnRefCount ) )
+ delete mpImplLineInfo;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+
+ rLineInfo.mpImplLineInfo->mnRefCount++;
+
+ if( !( --mpImplLineInfo->mnRefCount ) )
+ delete mpImplLineInfo;
+
+ mpImplLineInfo = rLineInfo.mpImplLineInfo;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL LineInfo::operator==( const LineInfo& rLineInfo ) const
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
+
+ return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
+ ( mpImplLineInfo->meStyle == rLineInfo.mpImplLineInfo->meStyle &&
+ mpImplLineInfo->mnWidth == rLineInfo.mpImplLineInfo->mnWidth &&
+ mpImplLineInfo->mnDashCount == rLineInfo.mpImplLineInfo->mnDashCount &&
+ mpImplLineInfo->mnDashLen == rLineInfo.mpImplLineInfo->mnDashLen &&
+ mpImplLineInfo->mnDotCount == rLineInfo.mpImplLineInfo->mnDotCount &&
+ mpImplLineInfo->mnDotLen == rLineInfo.mpImplLineInfo->mnDotLen &&
+ mpImplLineInfo->mnDistance == rLineInfo.mpImplLineInfo->mnDistance ) );
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::ImplMakeUnique()
+{
+ if( mpImplLineInfo->mnRefCount != 1 )
+ {
+ if( mpImplLineInfo->mnRefCount )
+ mpImplLineInfo->mnRefCount--;
+
+ mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetStyle( LineStyle eStyle )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetWidth( long nWidth )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnWidth = nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDashCount( USHORT nDashCount )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDashCount = nDashCount;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDashLen( long nDashLen )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDashLen = nDashLen;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDotCount( USHORT nDotCount )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDotCount = nDotCount;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDotLen( long nDotLen )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDotLen = nDotLen;
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::SetDistance( long nDistance )
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+ ImplMakeUnique();
+ mpImplLineInfo->mnDistance = nDistance;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
+ rIStm >> rImplLineInfo.mnWidth;
+
+ if( aCompat.GetVersion() >= 2 )
+ {
+ // version 2
+ rIStm >> rImplLineInfo.mnDashCount >> rImplLineInfo.mnDashLen;
+ rIStm >> rImplLineInfo.mnDotCount >> rImplLineInfo.mnDotLen;
+ rIStm >> rImplLineInfo.mnDistance;
+ }
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 2 );
+
+ // version 1
+ rOStm << (UINT16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
+
+ // since version2
+ rOStm << rImplLineInfo.mnDashCount << rImplLineInfo.mnDashLen;
+ rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
+ rOStm << rImplLineInfo.mnDistance;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
+{
+ rLineInfo.ImplMakeUnique();
+ return( rIStm >> *rLineInfo.mpImplLineInfo );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
+{
+ return( rOStm << *rLineInfo.mpImplLineInfo );
+}
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
new file mode 100644
index 000000000000..cecf617abb1c
--- /dev/null
+++ b/vcl/source/gdi/makefile.mk
@@ -0,0 +1,156 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=gdi
+
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+.IF "$(COM)"=="ICC"
+CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/salmisc.obj \
+ $(SLO)$/animate.obj \
+ $(SLO)$/impanmvw.obj \
+ $(SLO)$/bitmap.obj \
+ $(SLO)$/bitmap2.obj \
+ $(SLO)$/bitmap3.obj \
+ $(SLO)$/bitmap4.obj \
+ $(SLO)$/alpha.obj \
+ $(SLO)$/bitmapex.obj \
+ $(SLO)$/imgcons.obj \
+ $(SLO)$/bmpacc.obj \
+ $(SLO)$/bmpacc2.obj \
+ $(SLO)$/bmpacc3.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/cvtsvm.obj \
+ $(SLO)$/cvtgrf.obj \
+ $(SLO)$/font.obj \
+ $(SLO)$/gdimtf.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/gradient.obj \
+ $(SLO)$/hatch.obj \
+ $(SLO)$/graph.obj \
+ $(SLO)$/image.obj \
+ $(SLO)$/impbmp.obj \
+ $(SLO)$/impgraph.obj \
+ $(SLO)$/impimage.obj \
+ $(SLO)$/impprn.obj \
+ $(SLO)$/impvect.obj \
+ $(SLO)$/implncvt.obj \
+ $(SLO)$/jobset.obj \
+ $(SLO)$/line.obj \
+ $(SLO)$/lineinfo.obj \
+ $(SLO)$/mapmod.obj \
+ $(SLO)$/metaact.obj \
+ $(SLO)$/metric.obj \
+ $(SLO)$/octree.obj \
+ $(SLO)$/outmap.obj \
+ $(SLO)$/outdev.obj \
+ $(SLO)$/outdev2.obj \
+ $(SLO)$/outdev3.obj \
+ $(SLO)$/outdev4.obj \
+ $(SLO)$/outdev5.obj \
+ $(SLO)$/outdev6.obj \
+ $(SLO)$/poly.obj \
+ $(SLO)$/poly2.obj \
+ $(SLO)$/print.obj \
+ $(SLO)$/print2.obj \
+ $(SLO)$/regband.obj \
+ $(SLO)$/region.obj \
+ $(SLO)$/virdev.obj \
+ $(SLO)$/wall.obj \
+ $(SLO)$/opengl.obj
+
+.IF "$(remote)"!=""
+EXCEPTIONSFILES= $(SLO)$/bitmap.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/impgraph.obj \
+ $(SLO)$/impvect.obj \
+ $(SLO)$/outdev.obj \
+ $(SLO)$/outdev3.obj \
+ $(SLO)$/outdev6.obj \
+ $(SLO)$/print.obj \
+ $(SLO)$/print2.obj \
+ $(SLO)$/virdev.obj
+
+.ELSE
+EXCEPTIONSFILES= $(SLO)$/outdev.obj \
+ $(SLO)$/gfxlink.obj \
+ $(SLO)$/impgraph.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/vcl/source/gdi/mapmod.cxx b/vcl/source/gdi/mapmod.cxx
new file mode 100644
index 000000000000..5690e1c7cf0f
--- /dev/null
+++ b/vcl/source/gdi/mapmod.cxx
@@ -0,0 +1,356 @@
+/*************************************************************************
+ *
+ * $RCSfile: mapmod.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MAPMOD_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#define private public
+#ifndef _SV_MAPMOD_HXX
+#include <mapmod.hxx>
+#endif
+#undef private
+
+// =======================================================================
+
+DBG_NAME( MapMode );
+
+// -----------------------------------------------------------------------
+
+ImplMapMode::ImplMapMode() :
+ maOrigin( 0, 0 ),
+ maScaleX( 1, 1 ),
+ maScaleY( 1, 1 )
+{
+ mnRefCount = 1;
+ meUnit = MAP_PIXEL;
+ mbSimple = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplMapMode::ImplMapMode( const ImplMapMode& rImplMapMode ) :
+ maOrigin( rImplMapMode.maOrigin ),
+ maScaleX( rImplMapMode.maScaleX ),
+ maScaleY( rImplMapMode.maScaleY )
+{
+ mnRefCount = 1;
+ meUnit = rImplMapMode.meUnit;
+ mbSimple = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplMapMode& rImplMapMode )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ rIStm >> nTmp16; rImplMapMode.meUnit = (MapUnit) nTmp16;
+ rIStm >> rImplMapMode.maOrigin >> rImplMapMode.maScaleX >>
+ rImplMapMode.maScaleY >> rImplMapMode.mbSimple;
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplMapMode& rImplMapMode )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
+
+ rOStm << (UINT16) rImplMapMode.meUnit <<
+ rImplMapMode.maOrigin <<
+ rImplMapMode.maScaleX <<
+ rImplMapMode.maScaleY <<
+ rImplMapMode.mbSimple;
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+static ImplMapMode* ImplGetStaticMapMode( MapUnit eUnit )
+{
+ // Achtung: Ganz fies und dreckig !!!
+#ifdef WIN
+ static long _near aStaticImplMapModeAry[(MAP_LASTENUMDUMMY)*sizeof(ImplMapMode)/sizeof(long)];
+#else
+ static long aStaticImplMapModeAry[(MAP_LASTENUMDUMMY)*sizeof(ImplMapMode)/sizeof(long)];
+#endif
+
+ ImplMapMode* pImplMapMode = ((ImplMapMode*)aStaticImplMapModeAry)+eUnit;
+ if ( !pImplMapMode->mbSimple )
+ {
+ Fraction aDefFraction( 1, 1 );
+ pImplMapMode->maScaleX = aDefFraction;
+ pImplMapMode->maScaleY = aDefFraction;
+ pImplMapMode->meUnit = eUnit;
+ pImplMapMode->mbSimple = TRUE;
+ }
+
+ return pImplMapMode;
+}
+
+// -----------------------------------------------------------------------
+
+inline void MapMode::ImplMakeUnique()
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplMapMode->mnRefCount != 1 )
+ {
+ if ( mpImplMapMode->mnRefCount )
+ mpImplMapMode->mnRefCount--;
+ mpImplMapMode = new ImplMapMode( *mpImplMapMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode()
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = ImplGetStaticMapMode( MAP_PIXEL );
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( const MapMode& rMapMode )
+{
+ DBG_CTOR( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+ DBG_ASSERT( rMapMode.mpImplMapMode->mnRefCount < 0xFFFE, "MapMode: RefCount overflow" );
+
+ // shared Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplMapMode = rMapMode.mpImplMapMode;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplMapMode->mnRefCount )
+ mpImplMapMode->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( MapUnit eUnit )
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = ImplGetStaticMapMode( eUnit );
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::MapMode( MapUnit eUnit, const Point& rLogicOrg,
+ const Fraction& rScaleX, const Fraction& rScaleY )
+{
+ DBG_CTOR( MapMode, NULL );
+
+ mpImplMapMode = new ImplMapMode;
+ mpImplMapMode->meUnit = eUnit;
+ mpImplMapMode->maOrigin = rLogicOrg;
+ mpImplMapMode->maScaleX = rScaleX;
+ mpImplMapMode->maScaleY = rScaleY;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode::~MapMode()
+{
+ DBG_DTOR( MapMode, NULL );
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplMapMode->mnRefCount )
+ {
+ if ( mpImplMapMode->mnRefCount == 1 )
+ delete mpImplMapMode;
+ else
+ mpImplMapMode->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetMapUnit( MapUnit eUnit )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->meUnit = eUnit;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetOrigin( const Point& rLogicOrg )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maOrigin = rLogicOrg;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetScaleX( const Fraction& rScaleX )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maScaleX = rScaleX;
+}
+
+// -----------------------------------------------------------------------
+
+void MapMode::SetScaleY( const Fraction& rScaleY )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMakeUnique();
+ mpImplMapMode->maScaleY = rScaleY;
+}
+
+// -----------------------------------------------------------------------
+
+MapMode& MapMode::operator=( const MapMode& rMapMode )
+{
+ DBG_CHKTHIS( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+ DBG_ASSERT( rMapMode.mpImplMapMode->mnRefCount < 0xFFFE, "MapMode: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rMapMode.mpImplMapMode->mnRefCount )
+ rMapMode.mpImplMapMode->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplMapMode->mnRefCount )
+ {
+ if ( mpImplMapMode->mnRefCount == 1 )
+ delete mpImplMapMode;
+ else
+ mpImplMapMode->mnRefCount--;
+ }
+
+ mpImplMapMode = rMapMode.mpImplMapMode;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MapMode::operator==( const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( MapMode, NULL );
+ DBG_CHKOBJ( &rMapMode, MapMode, NULL );
+
+ if ( mpImplMapMode == rMapMode.mpImplMapMode )
+ return TRUE;
+
+ if ( (mpImplMapMode->meUnit == rMapMode.mpImplMapMode->meUnit) &&
+ (mpImplMapMode->maOrigin == rMapMode.mpImplMapMode->maOrigin) &&
+ (mpImplMapMode->maScaleX == rMapMode.mpImplMapMode->maScaleX) &&
+ (mpImplMapMode->maScaleY == rMapMode.mpImplMapMode->maScaleY) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MapMode::IsDefault() const
+{
+ DBG_CHKTHIS( MapMode, NULL );
+
+ ImplMapMode* pDefMapMode = ImplGetStaticMapMode( MAP_PIXEL );
+ if ( mpImplMapMode == pDefMapMode )
+ return TRUE;
+
+ if ( (mpImplMapMode->meUnit == pDefMapMode->meUnit) &&
+ (mpImplMapMode->maOrigin == pDefMapMode->maOrigin) &&
+ (mpImplMapMode->maScaleX == pDefMapMode->maScaleX) &&
+ (mpImplMapMode->maScaleY == pDefMapMode->maScaleY) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, MapMode& rMapMode )
+{
+ rMapMode.ImplMakeUnique();
+ return (rIStm >> *rMapMode.mpImplMapMode);
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const MapMode& rMapMode )
+{
+ return (rOStm << *rMapMode.mpImplMapMode);
+}
diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx
new file mode 100644
index 000000000000..caa28f1ee856
--- /dev/null
+++ b/vcl/source/gdi/metaact.cxx
@@ -0,0 +1,3434 @@
+/*************************************************************************
+ *
+ * $RCSfile: metaact.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_METAACT_CXX
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#include <string.h>
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+
+// ========================================================================
+
+inline void ImplScalePoint( Point& rPt, double fScaleX, double fScaleY )
+{
+ rPt.X() = FRound( fScaleX * rPt.X() );
+ rPt.Y() = FRound( fScaleY * rPt.Y() );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleSize( Size& rSz, double fScaleX, double fScaleY )
+{
+ rSz.Width() = FRound( fScaleX * rSz.Width() );
+ rSz.Height() = FRound( fScaleY * rSz.Height() );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleRect( Rectangle& rRect, double fScaleX, double fScaleY )
+{
+ Point aTL( rRect.TopLeft() );
+ Point aBR( rRect.BottomRight() );
+
+ ImplScalePoint( aTL, fScaleX, fScaleY );
+ ImplScalePoint( aBR, fScaleX, fScaleY );
+
+ rRect = Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScalePoly( Polygon& rPoly, double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+ ImplScalePoint( rPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+inline void ImplScaleLineInfo( LineInfo& rLineInfo, double fScaleX, double fScaleY )
+{
+ if( !rLineInfo.IsDefault() )
+ {
+ const double fScale = ( fScaleX + fScaleY ) * 0.5;
+
+ rLineInfo.SetWidth( FRound( fScale * rLineInfo.GetWidth() ) );
+ rLineInfo.SetDashLen( FRound( fScale * rLineInfo.GetDashLen() ) );
+ rLineInfo.SetDotLen( FRound( fScale * rLineInfo.GetDotLen() ) );
+ rLineInfo.SetDistance( FRound( fScale * rLineInfo.GetDistance() ) );
+ }
+}
+
+// ========================================================================
+
+#define COMPAT( _def_rIStm ) VersionCompat aCompat( ( _def_rIStm ), STREAM_READ );
+#define COMPAT_VERSION() aCompat.GetVersion()
+#define WRITE_BASE_COMPAT( _def_rOStm, _def_nVer, _pWriteData ) \
+ MetaAction::Write( ( _def_rOStm ), _pWriteData ); \
+ VersionCompat aCompat( ( _def_rOStm ), STREAM_WRITE, ( _def_nVer ) );
+
+// ========================================================================
+
+MetaAction::MetaAction() :
+ mnRefCount( 1 ),
+ mnType( META_NULL_ACTION )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction::MetaAction( USHORT nType ) :
+ mnRefCount( 1 ),
+ mnType( nType )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction::~MetaAction()
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Execute( OutputDevice* pOut )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaAction::Clone()
+{
+ return new MetaAction;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Move( long nHorzMove, long nVertMove )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Scale( double fScaleX, double fScaleY )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Write( SvStream& rOStm, ImplMetaWriteData* )
+{
+ rOStm << mnType;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ rIStm >> mnType;
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaAction::ReadMetaAction( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ MetaAction* pAction = NULL;
+ UINT16 nType;
+
+ rIStm >> nType;
+
+ switch( nType )
+ {
+ case( META_NULL_ACTION ): pAction = new MetaAction; break;
+ case( META_PIXEL_ACTION ): pAction = new MetaPixelAction; break;
+ case( META_POINT_ACTION ): pAction = new MetaPointAction; break;
+ case( META_LINE_ACTION ): pAction = new MetaLineAction; break;
+ case( META_RECT_ACTION ): pAction = new MetaRectAction; break;
+ case( META_ROUNDRECT_ACTION ): pAction = new MetaRoundRectAction; break;
+ case( META_ELLIPSE_ACTION ): pAction = new MetaEllipseAction; break;
+ case( META_ARC_ACTION ): pAction = new MetaArcAction; break;
+ case( META_PIE_ACTION ): pAction = new MetaPieAction; break;
+ case( META_CHORD_ACTION ): pAction = new MetaChordAction; break;
+ case( META_POLYLINE_ACTION ): pAction = new MetaPolyLineAction; break;
+ case( META_POLYGON_ACTION ): pAction = new MetaPolygonAction; break;
+ case( META_POLYPOLYGON_ACTION ): pAction = new MetaPolyPolygonAction; break;
+ case( META_TEXT_ACTION ): pAction = new MetaTextAction; break;
+ case( META_TEXTARRAY_ACTION ): pAction = new MetaTextArrayAction; break;
+ case( META_STRETCHTEXT_ACTION ): pAction = new MetaStretchTextAction; break;
+ case( META_TEXTRECT_ACTION ): pAction = new MetaTextRectAction; break;
+ case( META_TEXTLINE_ACTION ): pAction = new MetaTextLineAction; break;
+ case( META_BMP_ACTION ): pAction = new MetaBmpAction; break;
+ case( META_BMPSCALE_ACTION ): pAction = new MetaBmpScaleAction; break;
+ case( META_BMPSCALEPART_ACTION ): pAction = new MetaBmpScalePartAction; break;
+ case( META_BMPEX_ACTION ): pAction = new MetaBmpExAction; break;
+ case( META_BMPEXSCALE_ACTION ): pAction = new MetaBmpExScaleAction; break;
+ case( META_BMPEXSCALEPART_ACTION ): pAction = new MetaBmpExScalePartAction; break;
+ case( META_MASK_ACTION ): pAction = new MetaMaskAction; break;
+ case( META_MASKSCALE_ACTION ): pAction = new MetaMaskScaleAction; break;
+ case( META_MASKSCALEPART_ACTION ): pAction = new MetaMaskScalePartAction; break;
+ case( META_GRADIENT_ACTION ): pAction = new MetaGradientAction; break;
+ case( META_GRADIENTEX_ACTION ): pAction = new MetaGradientExAction; break;
+ case( META_HATCH_ACTION ): pAction = new MetaHatchAction; break;
+ case( META_WALLPAPER_ACTION ): pAction = new MetaWallpaperAction; break;
+ case( META_CLIPREGION_ACTION ): pAction = new MetaClipRegionAction; break;
+ case( META_ISECTRECTCLIPREGION_ACTION ): pAction = new MetaISectRectClipRegionAction; break;
+ case( META_ISECTREGIONCLIPREGION_ACTION ): pAction = new MetaISectRegionClipRegionAction; break;
+ case( META_MOVECLIPREGION_ACTION ): pAction = new MetaMoveClipRegionAction; break;
+ case( META_LINECOLOR_ACTION ): pAction = new MetaLineColorAction; break;
+ case( META_FILLCOLOR_ACTION ): pAction = new MetaFillColorAction; break;
+ case( META_TEXTCOLOR_ACTION ): pAction = new MetaTextColorAction; break;
+ case( META_TEXTFILLCOLOR_ACTION ): pAction = new MetaTextFillColorAction; break;
+ case( META_TEXTLINECOLOR_ACTION ): pAction = new MetaTextLineColorAction; break;
+ case( META_TEXTALIGN_ACTION ): pAction = new MetaTextAlignAction; break;
+ case( META_MAPMODE_ACTION ): pAction = new MetaMapModeAction; break;
+ case( META_FONT_ACTION ): pAction = new MetaFontAction; break;
+ case( META_PUSH_ACTION ): pAction = new MetaPushAction; break;
+ case( META_POP_ACTION ): pAction = new MetaPopAction; break;
+ case( META_RASTEROP_ACTION ): pAction = new MetaRasterOpAction; break;
+ case( META_TRANSPARENT_ACTION ): pAction = new MetaTransparentAction; break;
+ case( META_FLOATTRANSPARENT_ACTION ): pAction = new MetaFloatTransparentAction; break;
+ case( META_EPS_ACTION ): pAction = new MetaEPSAction; break;
+ case( META_REFPOINT_ACTION ): pAction = new MetaRefPointAction; break;
+ case( META_COMMENT_ACTION ): pAction = new MetaCommentAction; break;
+
+ default:
+ {
+ // Action ueberlesen durch Kombination Ctor/Dtor,
+ // new/delete, weil Compiler sonst vielleicht wegoptimieren
+ delete ( new VersionCompat( rIStm, STREAM_READ ) );
+ }
+ break;
+ }
+
+ if( pAction )
+ pAction->Read( rIStm, pData );
+
+ return pAction;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pixel, META_PIXEL_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPixelAction::MetaPixelAction( const Point& rPt, const Color& rColor ) :
+ MetaAction ( META_PIXEL_ACTION ),
+ maPt ( rPt ),
+ maColor ( rColor )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPixel( maPt, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPixelAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPixelAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ maColor.Write( rOStm, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPixelAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ maColor.Read( rIStm, TRUE );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Point, META_POINT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPointAction::MetaPointAction( const Point& rPt ) :
+ MetaAction ( META_POINT_ACTION ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPixel( maPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPointAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPointAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPointAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Line, META_LINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaLineAction::MetaLineAction( const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_LINE_ACTION ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaLineAction::MetaLineAction( const Point& rStart, const Point& rEnd,
+ const LineInfo& rLineInfo ) :
+ MetaAction ( META_LINE_ACTION ),
+ maLineInfo ( rLineInfo ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Execute( OutputDevice* pOut )
+{
+ if( maLineInfo.IsDefault() )
+ pOut->DrawLine( maStartPt, maEndPt );
+ else
+ pOut->DrawLine( maStartPt, maEndPt, maLineInfo );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+ ImplScaleLineInfo( maLineInfo, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maStartPt << maEndPt; // Version 1
+ rOStm << maLineInfo; // Version 2
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ // Version 1
+ rIStm >> maStartPt >> maEndPt;
+
+ // Version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ rIStm >> maLineInfo;
+ }
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Rect, META_RECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRectAction::MetaRectAction( const Rectangle& rRect ) :
+ MetaAction ( META_RECT_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawRect( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRectAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RoundRect, META_ROUNDRECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRoundRectAction::MetaRoundRectAction( const Rectangle& rRect,
+ long nHorzRound, long nVertRound ) :
+ MetaAction ( META_ROUNDRECT_ACTION ),
+ maRect ( rRect ),
+ mnHorzRound ( nHorzRound ),
+ mnVertRound ( nVertRound )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawRect( maRect, mnHorzRound, mnVertRound );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRoundRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRoundRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ mnHorzRound = FRound( mnHorzRound * fScaleX );
+ mnVertRound = FRound( mnVertRound * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << mnHorzRound << mnVertRound;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRoundRectAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> mnHorzRound >> mnVertRound;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Ellipse, META_ELLIPSE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaEllipseAction::MetaEllipseAction( const Rectangle& rRect ) :
+ MetaAction ( META_ELLIPSE_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawEllipse( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaEllipseAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaEllipseAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEllipseAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Arc, META_ARC_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaArcAction::MetaArcAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_ARC_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawArc( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaArcAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaArcAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaArcAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pie, META_PIE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPieAction::MetaPieAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_PIE_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPie( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPieAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPieAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPieAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Chord, META_CHORD_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaChordAction::MetaChordAction( const Rectangle& rRect,
+ const Point& rStart, const Point& rEnd ) :
+ MetaAction ( META_CHORD_ACTION ),
+ maRect ( rRect ),
+ maStartPt ( rStart ),
+ maEndPt ( rEnd )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawChord( maRect, maStartPt, maEndPt );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaChordAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaChordAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+ maStartPt.Move( nHorzMove, nVertMove );
+ maEndPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+ ImplScalePoint( maEndPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maStartPt << maEndPt;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaChordAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maStartPt >> maEndPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( PolyLine, META_POLYLINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolyLineAction::MetaPolyLineAction( const Polygon& rPoly ) :
+ MetaAction ( META_POLYLINE_ACTION ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaPolyLineAction::MetaPolyLineAction( const Polygon& rPoly, const LineInfo& rLineInfo ) :
+ MetaAction ( META_POLYLINE_ACTION ),
+ maLineInfo ( rLineInfo ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Execute( OutputDevice* pOut )
+{
+ if( maLineInfo.IsDefault() )
+ pOut->DrawPolyLine( maPoly );
+ else
+ pOut->DrawPolyLine( maPoly, maLineInfo );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolyLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolyLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoly( maPoly, fScaleX, fScaleY );
+ ImplScaleLineInfo( maLineInfo, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maPoly; // Version 1
+ rOStm << maLineInfo; // Version 2
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ // Version 1
+ rIStm >> maPoly;
+
+ // Version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ rIStm >> maLineInfo;
+ }
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Polygon, META_POLYGON_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolygonAction::MetaPolygonAction( const Polygon& rPoly ) :
+ MetaAction ( META_POLYGON_ACTION ),
+ maPoly ( rPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPolygon( maPoly );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolygonAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolygonAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoly( maPoly, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPoly;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolygonAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPoly;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( PolyPolygon, META_POLYPOLYGON_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPolyPolygonAction::MetaPolyPolygonAction( const PolyPolygon& rPolyPoly ) :
+ MetaAction ( META_POLYPOLYGON_ACTION ),
+ maPolyPoly ( rPolyPoly )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawPolyPolygon( maPolyPoly );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPolyPolygonAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPolyPolygonAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPolyPolygonAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Text, META_TEXT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextAction::MetaTextAction( const Point& rPt, const XubString& rStr,
+ USHORT nIndex, USHORT nLen ) :
+ MetaAction ( META_TEXT_ACTION ),
+ maPt ( rPt ),
+ maStr ( rStr ),
+ mnIndex ( nIndex ),
+ mnLen ( nLen )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawText( maPt, maStr, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnIndex;
+ rOStm << mnLen;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+}
+
+// ========================================================================
+
+MetaTextArrayAction::MetaTextArrayAction() :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ mpDXAry ( NULL ),
+ mnIndex ( 0 ),
+ mnLen ( 0 )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::MetaTextArrayAction( const MetaTextArrayAction& rAction ) :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ maStartPt ( rAction.maStartPt ),
+ maStr ( rAction.maStr ),
+ mnIndex ( rAction.mnIndex ),
+ mnLen ( rAction.mnLen )
+{
+ if( rAction.mpDXAry )
+ {
+ const ULONG nAryLen = mnLen - 1;
+
+ mpDXAry = new long[ nAryLen ];
+ memcpy( mpDXAry, rAction.mpDXAry, nAryLen * sizeof( long ) );
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt,
+ const XubString& rStr,
+ const long* pDXAry,
+ USHORT nIndex,
+ USHORT nLen ) :
+ MetaAction ( META_TEXTARRAY_ACTION ),
+ maStartPt ( rStartPt ),
+ maStr ( rStr ),
+ mnIndex ( nIndex ),
+ mnLen ( ( nLen == STRING_LEN ) ? rStr.Len() : nLen )
+{
+ const ULONG nAryLen = ( ( mnLen > 1 ) && pDXAry ) ? ( mnLen - 1 ) : 0UL;
+
+ if( nAryLen )
+ {
+ mpDXAry = new long[ nAryLen ];
+ memcpy( mpDXAry, pDXAry, nAryLen * sizeof( long ) );
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+MetaTextArrayAction::~MetaTextArrayAction()
+{
+ delete[] mpDXAry;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTextArray( maStartPt, maStr, mpDXAry, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextArrayAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextArrayAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Move( long nHorzMove, long nVertMove )
+{
+ maStartPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maStartPt, fScaleX, fScaleY );
+
+ if ( mpDXAry && mnLen )
+ {
+ for ( USHORT i = 0, nCount = mnLen - 1; i < nCount; i++ )
+ mpDXAry[ i ] = FRound( mpDXAry[ i ] * fScaleX );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ const ULONG nAryLen = ( ( mnLen > 1 ) && mpDXAry ) ? ( mnLen - 1 ) : 0UL;
+
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maStartPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnIndex;
+ rOStm << mnLen;
+ rOStm << nAryLen;
+
+ for( ULONG i = 0UL; i < nAryLen; i++ )
+ rOStm << mpDXAry[ i ];
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextArrayAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ ULONG nAryLen;
+
+ delete[] mpDXAry;
+
+ COMPAT( rIStm );
+ rIStm >> maStartPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+ rIStm >> nAryLen;
+
+ if( nAryLen )
+ {
+ mpDXAry = new long[ nAryLen ];
+
+ for( ULONG i = 0UL; i < nAryLen; i++ )
+ rIStm >> mpDXAry[ i ];
+ }
+ else
+ mpDXAry = NULL;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( StretchText, META_STRETCHTEXT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaStretchTextAction::MetaStretchTextAction( const Point& rPt, ULONG nWidth,
+ const XubString& rStr,
+ USHORT nIndex, USHORT nLen ) :
+ MetaAction ( META_STRETCHTEXT_ACTION ),
+ maPt ( rPt ),
+ maStr ( rStr ),
+ mnWidth ( nWidth ),
+ mnIndex ( nIndex ),
+ mnLen ( nLen )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawStretchText( maPt, mnWidth, maStr, mnIndex, mnLen );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaStretchTextAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaStretchTextAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ mnWidth = (ULONG)FRound( mnWidth * fScaleX );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPt;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnWidth;
+ rOStm << mnIndex;
+ rOStm << mnLen;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaStretchTextAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maPt;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnWidth;
+ rIStm >> mnIndex;
+ rIStm >> mnLen;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextRect, META_TEXTRECT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextRectAction::MetaTextRectAction( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle ) :
+ MetaAction ( META_TEXTRECT_ACTION ),
+ maRect ( rRect ),
+ maStr ( rStr ),
+ mnStyle ( nStyle )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawText( maRect, maStr, mnStyle );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextRectAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextRectAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+ rOStm.WriteByteString( maStr, pData->meActualCharSet );
+ rOStm << mnStyle;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextRectAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+ rIStm.ReadByteString( maStr, pData->meActualCharSet );
+ rIStm >> mnStyle;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextLine, META_TEXTLINE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextLineAction::MetaTextLineAction( const Point& rPos, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline ) :
+ MetaAction ( META_TEXTLINE_ACTION ),
+ maPos ( rPos ),
+ mnWidth ( nWidth ),
+ meStrikeout ( eStrikeout ),
+ meUnderline ( eUnderline )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTextLine( maPos, mnWidth, meStrikeout, meUnderline );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextLineAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*)new MetaTextLineAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Move( long nHorzMove, long nVertMove )
+{
+ maPos.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPos, fScaleX, fScaleY );
+ mnWidth = FRound( mnWidth * fScaleX );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 2, pData );
+
+ rOStm << maPos;
+ rOStm << mnWidth;
+ rOStm << (ULONG)meStrikeout;
+ rOStm << (ULONG)meUnderline;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+
+ ULONG nTemp;
+ rIStm >> maPos;
+ rIStm >> mnWidth;
+ rIStm >> nTemp;
+ meStrikeout = (FontStrikeout)nTemp;
+ rIStm >> nTemp;
+ meUnderline = (FontUnderline)nTemp;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Bmp, META_BMP_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpAction::MetaBmpAction( const Point& rPt, const Bitmap& rBmp ) :
+ MetaAction ( META_BMP_ACTION ),
+ maBmp ( rBmp ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maPt, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpScale, META_BMPSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpScaleAction::MetaBmpScaleAction( const Point& rPt, const Size& rSz,
+ const Bitmap& rBmp ) :
+ MetaAction ( META_BMPSCALE_ACTION ),
+ maBmp ( rBmp ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maPt, maSz, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpScalePart, META_BMPSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpScalePartAction::MetaBmpScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Bitmap& rBmp ) :
+ MetaAction ( META_BMPSCALEPART_ACTION ),
+ maBmp ( rBmp ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmap( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpEx, META_BMPEX_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExAction::MetaBmpExAction( const Point& rPt, const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEX_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maPt, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpExScale, META_BMPEXSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExScaleAction::MetaBmpExScaleAction( const Point& rPt, const Size& rSz,
+ const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEXSCALE_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maPt, maSz, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( BmpExScalePart, META_BMPEXSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaBmpExScalePartAction::MetaBmpExScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const BitmapEx& rBmpEx ) :
+ MetaAction ( META_BMPEXSCALEPART_ACTION ),
+ maBmpEx ( rBmpEx ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawBitmapEx( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmpEx );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaBmpExScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaBmpExScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmpEx.GetBitmap() )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmpEx << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaBmpExScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmpEx >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Mask, META_MASK_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskAction::MetaMaskAction( const Point& rPt,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASK_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maPt ( rPt )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maPt, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MaskScale, META_MASKSCALE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskScaleAction::MetaMaskScaleAction( const Point& rPt, const Size& rSz,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASKSCALE_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maPt ( rPt ),
+ maSz ( rSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maPt, maSz, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskScaleAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskScaleAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Move( long nHorzMove, long nVertMove )
+{
+ maPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPt, fScaleX, fScaleY );
+ ImplScaleSize( maSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp << maPt << maSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScaleAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp >> maPt >> maSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MaskScalePart, META_MASKSCALEPART_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMaskScalePartAction::MetaMaskScalePartAction( const Point& rDstPt, const Size& rDstSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Bitmap& rBmp,
+ const Color& rColor ) :
+ MetaAction ( META_MASKSCALEPART_ACTION ),
+ maBmp ( rBmp ),
+ maColor ( rColor ),
+ maDstPt ( rDstPt ),
+ maDstSz ( rDstSz ),
+ maSrcPt ( rSrcPt ),
+ maSrcSz ( rSrcSz )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawMask( maDstPt, maDstSz, maSrcPt, maSrcSz, maBmp, maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMaskScalePartAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMaskScalePartAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Move( long nHorzMove, long nVertMove )
+{
+ maDstPt.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maDstPt, fScaleX, fScaleY );
+ ImplScaleSize( maDstSz, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ if( !!maBmp )
+ {
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maBmp;
+ maColor.Write( rOStm, TRUE );
+ rOStm << maDstPt << maDstSz << maSrcPt << maSrcSz;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMaskScalePartAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maBmp;
+ maColor.Read( rIStm, TRUE );
+ rIStm >> maDstPt >> maDstSz >> maSrcPt >> maSrcSz;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Gradient, META_GRADIENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaGradientAction::MetaGradientAction( const Rectangle& rRect, const Gradient& rGradient ) :
+ MetaAction ( META_GRADIENT_ACTION ),
+ maRect ( rRect ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawGradient( maRect, maGradient );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaGradientAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaGradientAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect >> maGradient;
+}
+
+// ========================================================================
+
+MetaGradientExAction::MetaGradientExAction() :
+ MetaAction ( META_GRADIENTEX_ACTION )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaGradientExAction::MetaGradientExAction( const PolyPolygon& rPolyPoly, const Gradient& rGradient ) :
+ MetaAction ( META_GRADIENTEX_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+MetaGradientExAction::~MetaGradientExAction()
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Execute( OutputDevice* pOut )
+{
+ if( pOut->GetConnectMetaFile() )
+ pOut->GetConnectMetaFile()->AddAction( Clone() );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaGradientExAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaGradientExAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaGradientExAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly >> maGradient;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Hatch, META_HATCH_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaHatchAction::MetaHatchAction( const PolyPolygon& rPolyPoly, const Hatch& rHatch ) :
+ MetaAction ( META_HATCH_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ maHatch ( rHatch )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawHatch( maPolyPoly, maHatch );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaHatchAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaHatchAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly << maHatch;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaHatchAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly >> maHatch;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Wallpaper, META_WALLPAPER_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaWallpaperAction::MetaWallpaperAction( const Rectangle& rRect,
+ const Wallpaper& rPaper ) :
+ MetaAction ( META_WALLPAPER_ACTION ),
+ maRect ( rRect ),
+ maWallpaper ( rPaper )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawWallpaper( maRect, maWallpaper );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaWallpaperAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaWallpaperAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maWallpaper;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaWallpaperAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maWallpaper;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ClipRegion, META_CLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaClipRegionAction::MetaClipRegionAction( const Region& rRegion, BOOL bClip ) :
+ MetaAction ( META_CLIPREGION_ACTION ),
+ maRegion ( rRegion ),
+ mbClip ( bClip )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Execute( OutputDevice* pOut )
+{
+ if( mbClip )
+ pOut->SetClipRegion( maRegion );
+ else
+ pOut->SetClipRegion();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRegion.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ maRegion.Scale( fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRegion << mbClip;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRegion >> mbClip;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ISectRectClipRegion, META_ISECTRECTCLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaISectRectClipRegionAction::MetaISectRectClipRegionAction( const Rectangle& rRect ) :
+ MetaAction ( META_ISECTRECTCLIPREGION_ACTION ),
+ maRect ( rRect )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->IntersectClipRegion( maRect );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaISectRectClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaISectRectClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRect.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScaleRect( maRect, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRect;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRectClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRect;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( ISectRegionClipRegion, META_ISECTREGIONCLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaISectRegionClipRegionAction::MetaISectRegionClipRegionAction( const Region& rRegion ) :
+ MetaAction ( META_ISECTREGIONCLIPREGION_ACTION ),
+ maRegion ( rRegion )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->IntersectClipRegion( maRegion );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaISectRegionClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaISectRegionClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Move( long nHorzMove, long nVertMove )
+{
+ maRegion.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ maRegion.Scale( fScaleX, fScaleY );
+}
+
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRegion;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaISectRegionClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRegion;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MoveClipRegion, META_MOVECLIPREGION_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMoveClipRegionAction::MetaMoveClipRegionAction( long nHorzMove, long nVertMove ) :
+ MetaAction ( META_MOVECLIPREGION_ACTION ),
+ mnHorzMove ( nHorzMove ),
+ mnVertMove ( nVertMove )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Execute( OutputDevice* pOut )
+{
+ pOut->MoveClipRegion( mnHorzMove, mnVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMoveClipRegionAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMoveClipRegionAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Scale( double fScaleX, double fScaleY )
+{
+ mnHorzMove = FRound( mnHorzMove * fScaleX );
+ mnVertMove = FRound( mnVertMove * fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << mnHorzMove << mnVertMove;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMoveClipRegionAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> mnHorzMove >> mnVertMove;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( LineColor, META_LINECOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaLineColorAction::MetaLineColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_LINECOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetLineColor( maColor );
+ else
+ pOut->SetLineColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaLineColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaLineColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaLineColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( FillColor, META_FILLCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFillColorAction::MetaFillColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_FILLCOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetFillColor( maColor );
+ else
+ pOut->SetFillColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFillColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFillColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFillColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextColor, META_TEXTCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextColorAction::MetaTextColorAction( const Color& rColor ) :
+ MetaAction ( META_TEXTCOLOR_ACTION ),
+ maColor ( rColor )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetTextColor( maColor );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextFillColor, META_TEXTFILLCOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextFillColorAction::MetaTextFillColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_TEXTFILLCOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetTextFillColor( maColor );
+ else
+ pOut->SetTextFillColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextFillColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextFillColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextFillColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextLineColor, META_TEXTLINECOLOR_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextLineColorAction::MetaTextLineColorAction( const Color& rColor, BOOL bSet ) :
+ MetaAction ( META_TEXTLINECOLOR_ACTION ),
+ maColor ( rColor ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetTextLineColor( maColor );
+ else
+ pOut->SetTextLineColor();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextLineColorAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextLineColorAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ maColor.Write( rOStm, TRUE );
+ rOStm << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextLineColorAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ maColor.Read( rIStm, TRUE );
+ rIStm >> mbSet;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( TextAlign, META_TEXTALIGN_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTextAlignAction::MetaTextAlignAction( TextAlign aAlign ) :
+ MetaAction ( META_TEXTALIGN_ACTION ),
+ maAlign ( aAlign )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetTextAlign( maAlign );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTextAlignAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTextAlignAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << (UINT16) maAlign;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTextAlignAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ UINT16 nTmp16;
+
+ COMPAT( rIStm );
+ rIStm >> nTmp16; maAlign = (TextAlign) nTmp16;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( MapMode, META_MAPMODE_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaMapModeAction::MetaMapModeAction( const MapMode& rMapMode ) :
+ MetaAction ( META_MAPMODE_ACTION ),
+ maMapMode ( rMapMode )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetMapMode( maMapMode );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaMapModeAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaMapModeAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Scale( double fScaleX, double fScaleY )
+{
+ Point aPoint( maMapMode.GetOrigin() );
+
+ ImplScalePoint( aPoint, fScaleX, fScaleY );
+ maMapMode.SetOrigin( aPoint );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maMapMode;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaMapModeAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maMapMode;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Font, META_FONT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFontAction::MetaFontAction( const Font& rFont ) :
+ MetaAction ( META_FONT_ACTION ),
+ maFont ( rFont )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetFont( maFont );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFontAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFontAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Scale( double fScaleX, double fScaleY )
+{
+ Size aSize( maFont.GetSize() );
+
+ ImplScaleSize( aSize, fScaleX, fScaleY );
+ maFont.SetSize( aSize );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maFont;
+ pData->meActualCharSet = maFont.GetCharSet();
+ if ( pData->meActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ pData->meActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFontAction::Read( SvStream& rIStm, ImplMetaReadData* pData )
+{
+ COMPAT( rIStm );
+ rIStm >> maFont;
+ pData->meActualCharSet = maFont.GetCharSet();
+ if ( pData->meActualCharSet == RTL_TEXTENCODING_DONTKNOW )
+ pData->meActualCharSet = gsl_getSystemTextEncoding();
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Push, META_PUSH_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaPushAction::MetaPushAction( USHORT nFlags ) :
+ MetaAction ( META_PUSH_ACTION ),
+ mnFlags ( nFlags )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Execute( OutputDevice* pOut )
+{
+ pOut->Push( mnFlags );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPushAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPushAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << mnFlags;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPushAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> mnFlags;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Pop, META_POP_ACTION )
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Execute( OutputDevice* pOut )
+{
+ pOut->Pop();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaPopAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaPopAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaPopAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RasterOp, META_RASTEROP_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRasterOpAction::MetaRasterOpAction( RasterOp eRasterOp ) :
+ MetaAction ( META_RASTEROP_ACTION ),
+ meRasterOp ( eRasterOp )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Execute( OutputDevice* pOut )
+{
+ pOut->SetRasterOp( meRasterOp );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRasterOpAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRasterOpAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << (UINT16) meRasterOp;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRasterOpAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ UINT16 nTmp16;
+
+ COMPAT( rIStm );
+ rIStm >> nTmp16; meRasterOp = (RasterOp) nTmp16;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( Transparent, META_TRANSPARENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaTransparentAction::MetaTransparentAction( const PolyPolygon& rPolyPoly, USHORT nTransPercent ) :
+ MetaAction ( META_TRANSPARENT_ACTION ),
+ maPolyPoly ( rPolyPoly ),
+ mnTransPercent ( nTransPercent )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTransparent( maPolyPoly, mnTransPercent );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaTransparentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaTransparentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Move( long nHorzMove, long nVertMove )
+{
+ maPolyPoly.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Scale( double fScaleX, double fScaleY )
+{
+ for( USHORT i = 0, nCount = maPolyPoly.Count(); i < nCount; i++ )
+ ImplScalePoly( maPolyPoly[ i ], fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maPolyPoly;
+ rOStm << mnTransPercent;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaTransparentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maPolyPoly;
+ rIStm >> mnTransPercent;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( FloatTransparent, META_FLOATTRANSPARENT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaFloatTransparentAction::MetaFloatTransparentAction( const GDIMetaFile& rMtf, const Point& rPos,
+ const Size& rSize, const Gradient& rGradient ) :
+ MetaAction ( META_FLOATTRANSPARENT_ACTION ),
+ maMtf ( rMtf ),
+ maPoint ( rPos ),
+ maSize ( rSize ),
+ maGradient ( rGradient )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawTransparent( maMtf, maPoint, maSize, maGradient );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaFloatTransparentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaFloatTransparentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoint.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPoint, fScaleX, fScaleY );
+ ImplScaleSize( maSize, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maMtf << maPoint << maSize << maGradient;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaFloatTransparentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maMtf >> maPoint >> maSize >> maGradient;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( EPS, META_EPS_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaEPSAction::MetaEPSAction( const Point& rPoint, const Size& rSize,
+ const GfxLink& rGfxLink, const GDIMetaFile& rSubst ) :
+ MetaAction ( META_EPS_ACTION ),
+ maGfxLink ( rGfxLink ),
+ maSubst ( rSubst ),
+ maPoint ( rPoint ),
+ maSize ( rSize )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Execute( OutputDevice* pOut )
+{
+ pOut->DrawEPS( maPoint, maSize, maGfxLink, &maSubst );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaEPSAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaEPSAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Move( long nHorzMove, long nVertMove )
+{
+ maPoint.Move( nHorzMove, nVertMove );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Scale( double fScaleX, double fScaleY )
+{
+ ImplScalePoint( maPoint, fScaleX, fScaleY );
+ ImplScaleSize( maSize, fScaleX, fScaleY );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maGfxLink;
+ rOStm << maPoint;
+ rOStm << maSize;
+ rOStm << maSubst;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaEPSAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maGfxLink;
+ rIStm >> maPoint;
+ rIStm >> maSize;
+ rIStm >> maSubst;
+}
+
+// ========================================================================
+
+IMPL_META_ACTION( RefPoint, META_REFPOINT_ACTION )
+
+// ------------------------------------------------------------------------
+
+MetaRefPointAction::MetaRefPointAction( const Point& rRefPoint, BOOL bSet ) :
+ MetaAction ( META_REFPOINT_ACTION ),
+ maRefPoint ( rRefPoint ),
+ mbSet ( bSet )
+{
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Execute( OutputDevice* pOut )
+{
+ if( mbSet )
+ pOut->SetRefPoint( maRefPoint );
+ else
+ pOut->SetRefPoint();
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaRefPointAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaRefPointAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maRefPoint << mbSet;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaRefPointAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maRefPoint >> mbSet;
+}
+
+// ========================================================================
+
+MetaCommentAction::MetaCommentAction( long nValue ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ mnValue ( nValue )
+{
+ ImplInitDynamicData( NULL, 0UL );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const MetaCommentAction& rAct ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ maComment ( rAct.maComment ),
+ mnValue ( rAct.mnValue )
+{
+ ImplInitDynamicData( rAct.mpData, rAct.mnDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const ByteString& rComment, long nValue, const BYTE* pData, ULONG nDataSize ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ maComment ( rComment ),
+ mnValue ( nValue )
+{
+ ImplInitDynamicData( pData, nDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::MetaCommentAction( const BYTE* pData, ULONG nDataSize ) :
+ MetaAction ( META_COMMENT_ACTION ),
+ mnValue ( 0L )
+{
+ ImplInitDynamicData( pData, nDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+MetaCommentAction::~MetaCommentAction()
+{
+ if ( mpData )
+ delete[] mpData;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::ImplInitDynamicData( const BYTE* pData, ULONG nDataSize )
+{
+ if ( nDataSize && pData )
+ {
+ mnDataSize = nDataSize, mpData = new BYTE[ mnDataSize ];
+ HMEMCPY( mpData, pData, mnDataSize );
+ }
+ else
+ {
+ mnDataSize = 0;
+ mpData = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Execute( OutputDevice* pOut )
+{
+ if ( pOut->GetConnectMetaFile() )
+ pOut->GetConnectMetaFile()->AddAction( Clone() );
+}
+
+// ------------------------------------------------------------------------
+
+MetaAction* MetaCommentAction::Clone()
+{
+ MetaAction* pClone = (MetaAction*) new MetaCommentAction( *this );
+ pClone->ResetRefCount();
+ return pClone;
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Write( SvStream& rOStm, ImplMetaWriteData* pData )
+{
+ WRITE_BASE_COMPAT( rOStm, 1, pData );
+ rOStm << maComment << mnValue << mnDataSize;
+
+ if ( mnDataSize )
+ rOStm.Write( mpData, mnDataSize );
+}
+
+// ------------------------------------------------------------------------
+
+void MetaCommentAction::Read( SvStream& rIStm, ImplMetaReadData* )
+{
+ COMPAT( rIStm );
+ rIStm >> maComment >> mnValue >> mnDataSize;
+
+ if( mpData )
+ delete[] mpData;
+
+ if( mnDataSize )
+ {
+ mpData = new BYTE[ mnDataSize ];
+ rIStm.Read( mpData, mnDataSize );
+ }
+ else
+ mpData = NULL;
+}
diff --git a/vcl/source/gdi/metric.cxx b/vcl/source/gdi/metric.cxx
new file mode 100644
index 000000000000..b4a5f70fa5cd
--- /dev/null
+++ b/vcl/source/gdi/metric.cxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * $RCSfile: metric.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <metric.hxx>
+
+// =======================================================================
+
+FontInfo::FontInfo()
+{
+ mpImplMetric = new ImplFontMetric;
+ mpImplMetric->mnRefCount = 1;
+ mpImplMetric->meType = TYPE_DONTKNOW;
+ mpImplMetric->mbDevice = FALSE;
+ mpImplMetric->mnAscent = 0;
+ mpImplMetric->mnDescent = 0;
+ mpImplMetric->mnLeading = 0;
+ mpImplMetric->mnLineHeight = 0;
+ mpImplMetric->mnSlant = 0;
+ mpImplMetric->mnFirstChar = 0;
+ mpImplMetric->mnLastChar = 0;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo::FontInfo( const FontInfo& rInfo ) :
+ Font( rInfo )
+{
+ mpImplMetric = rInfo.mpImplMetric;
+ mpImplMetric->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo::~FontInfo()
+{
+ // Eventuell Metric loeschen
+ if ( mpImplMetric->mnRefCount > 1 )
+ mpImplMetric->mnRefCount--;
+ else
+ delete mpImplMetric;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo& FontInfo::operator=( const FontInfo& rInfo )
+{
+ Font::operator=( rInfo );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ rInfo.mpImplMetric->mnRefCount++;
+
+ // Sind wir nicht die letzten ?
+ if ( mpImplMetric->mnRefCount > 1 )
+ mpImplMetric->mnRefCount--;
+ else
+ delete mpImplMetric;
+
+ mpImplMetric = rInfo.mpImplMetric;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FontInfo::operator==( const FontInfo& rInfo ) const
+{
+ if ( !Font::operator==( rInfo ) )
+ return FALSE;
+
+ if ( mpImplMetric == rInfo.mpImplMetric )
+ return TRUE;
+
+ if ( (mpImplMetric->meType == rInfo.mpImplMetric->meType ) &&
+ (mpImplMetric->mbDevice == rInfo.mpImplMetric->mbDevice ) &&
+ (mpImplMetric->mnAscent == rInfo.mpImplMetric->mnAscent ) &&
+ (mpImplMetric->mnDescent == rInfo.mpImplMetric->mnDescent ) &&
+ (mpImplMetric->mnLeading == rInfo.mpImplMetric->mnLeading ) &&
+ (mpImplMetric->mnSlant == rInfo.mpImplMetric->mnSlant ) &&
+ (mpImplMetric->mnFirstChar == rInfo.mpImplMetric->mnFirstChar ) &&
+ (mpImplMetric->mnLastChar == rInfo.mpImplMetric->mnLastChar ) )
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/vcl/source/gdi/octree.cxx b/vcl/source/gdi/octree.cxx
new file mode 100644
index 000000000000..7d4f9f688d65
--- /dev/null
+++ b/vcl/source/gdi/octree.cxx
@@ -0,0 +1,419 @@
+/*************************************************************************
+ *
+ * $RCSfile: octree.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include <limits.h>
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_IMPOCT_HXX
+#include <impoct.hxx>
+#endif
+#ifndef _NEW_HXX
+#include<tools/new.hxx>
+#endif
+#include <octree.hxx>
+
+// ------------
+// - Typedefs -
+// ------------
+
+#ifdef WIN
+typedef ULONG huge* HPULONG;
+#else
+typedef ULONG* HPULONG;
+#endif
+
+// ---------
+// - pMask -
+// ---------
+
+static BYTE pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+// -------------
+// - NodeCache -
+// -------------
+
+ImpNodeCache::ImpNodeCache( const ULONG nInitSize ) :
+ pActNode( NULL )
+{
+ const ULONG nSize = nInitSize + 4;
+
+ for( ULONG i = 0; i < nSize; i++ )
+ {
+ OctreeNode* pNewNode = new NODE;
+
+ pNewNode->pNextInCache = pActNode;
+ pActNode = pNewNode;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImpNodeCache::~ImpNodeCache()
+{
+ while( pActNode )
+ {
+ OctreeNode* pNode = pActNode;
+
+ pActNode = pNode->pNextInCache;
+ delete pNode;
+ }
+}
+
+// ----------
+// - Octree -
+// ----------
+
+Octree::Octree( ULONG nColors ) :
+ nMax ( nColors ),
+ nLeafCount ( 0L ),
+ pTree ( NULL ),
+ pAcc ( NULL )
+{
+ pNodeCache = new ImpNodeCache( nColors );
+ memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
+}
+
+// ------------------------------------------------------------------------
+
+Octree::Octree( const BitmapReadAccess& rReadAcc, ULONG nColors ) :
+ nMax ( nColors ),
+ nLeafCount ( 0L ),
+ pTree ( NULL ),
+ pAcc ( &rReadAcc )
+{
+ pNodeCache = new ImpNodeCache( nColors );
+ memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
+ ImplCreateOctree();
+}
+
+// ------------------------------------------------------------------------
+
+Octree::~Octree()
+{
+ ImplDeleteOctree( &pTree );
+ delete pNodeCache;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::AddColor( const BitmapColor& rColor )
+{
+ pColor = &(BitmapColor&) rColor;
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplCreateOctree()
+{
+ if( !!*pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+
+ if( pAcc->HasPalette() )
+ {
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ pColor = &(BitmapColor&) pAcc->GetPaletteColor( pAcc->GetPixel( nY, nX ) );
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aColor;
+
+ pColor = &aColor;
+
+ for( long nY = 0; nY < nHeight; nY++ )
+ {
+ for( long nX = 0; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPixel( nY, nX );
+ nLevel = 0L;
+ ImplAdd( &pTree );
+
+ while( nLeafCount > nMax )
+ ImplReduce();
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplDeleteOctree( PPNODE ppNode )
+{
+ for ( ULONG i = 0UL; i < 8UL; i++ )
+ {
+ if ( (*ppNode)->pChild[ i ] )
+ ImplDeleteOctree( &(*ppNode)->pChild[ i ] );
+ }
+
+ pNodeCache->ImplReleaseNode( *ppNode );
+ *ppNode = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplAdd( PPNODE ppNode )
+{
+ // ggf. neuen Knoten erzeugen
+ if( !*ppNode )
+ {
+ *ppNode = pNodeCache->ImplGetFreeNode();
+ (*ppNode)->bLeaf = ( OCTREE_BITS == nLevel );
+
+ if( (*ppNode)->bLeaf )
+ nLeafCount++;
+ else
+ {
+ (*ppNode)->pNext = pReduce[ nLevel ];
+ pReduce[ nLevel ] = *ppNode;
+ }
+ }
+
+ if( (*ppNode)->bLeaf )
+ {
+ (*ppNode)->nCount++;
+ (*ppNode)->nRed += pColor->GetRed();
+ (*ppNode)->nGreen += pColor->GetGreen();
+ (*ppNode)->nBlue += pColor->GetBlue();
+ }
+ else
+ {
+ const ULONG nShift = 7 - nLevel;
+ const BYTE cMask = pImplMask[ nLevel ];
+ const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
+ ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
+ ( ( pColor->GetBlue() & cMask ) >> nShift );
+
+ nLevel++;
+ ImplAdd( &(*ppNode)->pChild[ nIndex ] );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::ImplReduce()
+{
+ ULONG i;
+ PNODE pNode;
+ ULONG nRedSum = 0L;
+ ULONG nGreenSum = 0L;
+ ULONG nBlueSum = 0L;
+ ULONG nChilds = 0L;
+
+ for ( i = OCTREE_BITS - 1; i && !pReduce[i]; i-- ) {}
+
+ pNode = pReduce[ i ];
+ pReduce[ i ] = pNode->pNext;
+
+ for ( i = 0; i < 8; i++ )
+ {
+ if ( pNode->pChild[ i ] )
+ {
+ PNODE pChild = pNode->pChild[ i ];
+
+ nRedSum += pChild->nRed;
+ nGreenSum += pChild->nGreen;
+ nBlueSum += pChild->nBlue;
+ pNode->nCount += pChild->nCount;
+
+ pNodeCache->ImplReleaseNode( pNode->pChild[ i ] );
+ pNode->pChild[ i ] = NULL;
+ nChilds++;
+ }
+ }
+
+ pNode->bLeaf = TRUE;
+ pNode->nRed = nRedSum;
+ pNode->nGreen = nGreenSum;
+ pNode->nBlue = nBlueSum;
+ nLeafCount -= --nChilds;
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::CreatePalette( PNODE pNode )
+{
+ if( pNode->bLeaf )
+ {
+ pNode->nPalIndex = nPalIndex;
+ aPal[ nPalIndex++ ] = BitmapColor( (BYTE) ( (double) pNode->nRed / pNode->nCount ),
+ (BYTE) ( (double) pNode->nGreen / pNode->nCount ),
+ (BYTE) ( (double) pNode->nBlue / pNode->nCount ) );
+ }
+ else for( ULONG i = 0UL; i < 8UL; i++ )
+ if( pNode->pChild[ i ] )
+ CreatePalette( pNode->pChild[ i ] );
+
+}
+
+// ------------------------------------------------------------------------
+
+void Octree::GetPalIndex( PNODE pNode )
+{
+ if ( pNode->bLeaf )
+ nPalIndex = pNode->nPalIndex;
+ else
+ {
+ const ULONG nShift = 7 - nLevel;
+ const BYTE cMask = pImplMask[ nLevel++ ];
+ const ULONG nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
+ ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
+ ( ( pColor->GetBlue() & cMask ) >> nShift );
+
+ GetPalIndex( pNode->pChild[ nIndex ] );
+ }
+}
+
+// -------------------
+// - InverseColorMap -
+// -------------------
+
+InverseColorMap::InverseColorMap( const BitmapPalette& rPal ) :
+ nBits( 8 - OCTREE_BITS )
+{
+ HPULONG cdp;
+ BYTE* crgbp;
+ const ULONG nColorMax = 1 << OCTREE_BITS;
+ const ULONG xsqr = 1 << ( nBits << 1 );
+ const ULONG xsqr2 = xsqr << 1;
+ const ULONG gstride = nColorMax;
+ const ULONG rstride = nColorMax * nColorMax;
+ const ULONG nColors = rPal.GetEntryCount();
+ const long x = 1L << nBits;
+ const long x2 = x >> 1L;
+ ULONG r, g, b;
+ long rxx, gxx, bxx;
+ long rdist, gdist, bdist;
+ long crinc, cginc, cbinc;
+
+ ImplCreateBuffers( nColorMax );
+
+ for( ULONG nIndex = 0; nIndex < nColors; nIndex++ )
+ {
+ const BitmapColor& rColor = rPal[ (USHORT) nIndex ];
+ const BYTE cRed = rColor.GetRed();
+ const BYTE cGreen = rColor.GetGreen();
+ const BYTE cBlue = rColor.GetBlue();
+
+ rdist = cRed - x2;
+ gdist = cGreen - x2;
+ bdist = cBlue - x2;
+ rdist = rdist*rdist + gdist*gdist + bdist*bdist;
+
+ crinc = ( xsqr - ( cRed << nBits ) ) << 1L;
+ cginc = ( xsqr - ( cGreen << nBits ) ) << 1L;
+ cbinc = ( xsqr - ( cBlue << nBits ) ) << 1L;
+
+ cdp = (HPULONG) pBuffer;
+ crgbp = pMap;
+
+ for( r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2 )
+ {
+ for( g = 0, gdist = rdist, gxx = cginc; g < nColorMax; gdist += gxx, g++, gxx += xsqr2 )
+ {
+ for( b = 0, bdist = gdist, bxx = cbinc; b < nColorMax; bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2 )
+ if ( !nIndex || ( (long) *cdp ) > bdist )
+ {
+ *cdp = bdist;
+ *crgbp = (BYTE) nIndex;
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+InverseColorMap::~InverseColorMap()
+{
+ SvMemFree( pBuffer );
+ SvMemFree( pMap );
+}
+
+// ------------------------------------------------------------------------
+
+void InverseColorMap::ImplCreateBuffers( const ULONG nMax )
+{
+ const ULONG nCount = nMax * nMax * nMax;
+ const ULONG nSize = nCount * sizeof( ULONG );
+
+ pMap = (BYTE*) SvMemAlloc( nCount );
+ HMEMSET( pMap, 0x00, nCount );
+
+ pBuffer = (BYTE*) SvMemAlloc( nSize );
+ HMEMSET( pBuffer, 0xff, nSize );
+}
diff --git a/vcl/source/gdi/opengl.cxx b/vcl/source/gdi/opengl.cxx
new file mode 100644
index 000000000000..fa45d1700725
--- /dev/null
+++ b/vcl/source/gdi/opengl.cxx
@@ -0,0 +1,1714 @@
+/*************************************************************************
+ *
+ * $RCSfile: opengl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OPENGL_CXX
+
+#define private public
+#include <svsys.h>
+#include <window.hxx>
+#undef private
+#define private public
+
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_SALOGL_HXX
+#include <salogl.hxx>
+#endif
+#ifndef _SV_OPENGL_HXX
+#include <opengl.hxx>
+#endif
+
+#include <svapp.hxx>
+#include <vos/mutex.hxx>
+
+// -----------------------
+// - Fnc-Pointer-Typedef -
+// -----------------------
+
+typedef void ( *OGLFncClearDepth )( GLclampd fDepth );
+typedef void ( *OGLFncDepthFunc )( GLenum fFunc );
+typedef void ( *OGLFncEnable )( GLenum eCap );
+typedef void ( *OGLFncDisable )( GLenum eCap );
+typedef void ( *OGLFncDepthMask )( GLboolean bFlag );
+typedef void ( *OGLFncShadeModel )( GLenum eMode );
+typedef void ( *OGLFncEdgeFlag )( GLboolean bFlag );
+typedef void ( *OGLFncClear )( GLbitfield nMask );
+typedef void ( *OGLFncFlush )( void );
+typedef void ( *OGLFncFinish )( void );
+typedef void ( *OGLFncViewport )( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight );
+typedef void ( *OGLFncBegin )( GLenum eMode );
+typedef void ( *OGLFncEnd )( void );
+typedef void ( *OGLFncVertex3dv )( const GLdouble *fV );
+typedef void ( *OGLFncNormal3dv )( const GLdouble *fV );
+typedef void ( *OGLFncColor4ub )( GLubyte cRed, GLubyte cGreen, GLubyte cBlue, GLubyte cAlpha );
+typedef void ( *OGLFncMaterialfv )( GLenum eFace, GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncMaterialf )( GLenum eFace, GLenum ePName, GLfloat fParam );
+typedef void ( *OGLFncLightModelfv )( GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncLightModelf )( GLenum ePname, GLfloat fParam );
+typedef void ( *OGLFncLightfv )( GLenum eLight, GLenum ePNname, const GLfloat *fParams );
+typedef void ( *OGLFncLightf )( GLenum eLight, GLenum ePname, GLfloat fParam );
+typedef void ( *OGLFncPolygonMode )( GLenum eFace, GLenum eMode );
+typedef void ( *OGLFncCullFace )( GLenum eMode );
+typedef void ( *OGLFncPointSize )( GLfloat fSize );
+typedef void ( *OGLFncLineWidth )( GLfloat fWidth );
+typedef void ( *OGLFncMatrixMode )( GLenum eMode );
+typedef void ( *OGLFncLoadMatrixd )( const GLdouble *fM );
+typedef void ( *OGLFncTexCoord2dv )( const GLdouble *pParams );
+typedef void ( *OGLFncTexCoord3dv )( const GLdouble *fV );
+typedef void ( *OGLFncTexImage1D )( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncTexImage2D )( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncCopyTexImage1D )( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border );
+typedef void ( *OGLFncCopyTexImage2D )( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border );
+typedef void ( *OGLFncCopyTexSubImage1D )( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+typedef void ( *OGLFncCopyTexSubImage2D )( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+typedef void ( *OGLFncPixelTransferf )( GLenum pname, GLfloat param );
+typedef void ( *OGLFncPixelTransferi )( GLenum pname, GLint param );
+typedef void ( *OGLFncGetTexLevelParameterfv )( GLenum target, GLint level, GLenum pname, GLfloat *params );
+typedef void ( *OGLFncGetTexLevelParameteriv )( GLenum target, GLint level, GLenum pname, GLint *params );
+typedef void ( *OGLFncGetTexParameterfv )( GLenum target, GLenum pname, GLfloat *params );
+typedef void ( *OGLFncGetTexParameteriv )( GLenum target, GLenum pname, GLint *params );
+typedef void ( *OGLFncTexSubImage1D )( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncTexSubImage2D )( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void ( *OGLFncPixelStoref )( GLenum pname, GLfloat param );
+typedef void ( *OGLFncPixelStorei )( GLenum pname, GLint param );
+typedef void ( *OGLFncGenTextures )( GLsizei n, GLuint *textures );
+typedef GLboolean ( *OGLFncIsTexture )( GLuint texture );
+typedef void ( *OGLFncBindTexture )( GLenum target, GLuint texture );
+typedef void ( *OGLFncDeleteTextures )( GLsizei n, const GLuint *textures );
+typedef GLboolean ( *OGLFncAreTexturesResident )( GLsizei n, const GLuint *textures, GLboolean *residences );
+typedef void ( *OGLFncPrioritizeTextures )( GLsizei n, const GLuint *textures, const GLclampf *priorities );
+typedef void ( *OGLFncTexEnvf )( GLenum target, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexEnvfv )( GLenum target, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexEnvi )( GLenum target, GLenum pname, GLint param );
+typedef void ( *OGLFncTexEnviv )( GLenum target, GLenum pname, const GLint *params );
+typedef void ( *OGLFncTexParameterf )( GLenum target, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexParameterfv )( GLenum target, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexParameteri )( GLenum target, GLenum pname, GLint param );
+typedef void ( *OGLFncTexParameteriv )( GLenum target, GLenum pname, const GLint *params );
+typedef void ( *OGLFncTexGend )( GLenum coord, GLenum pname, GLdouble param );
+typedef void ( *OGLFncTexGendv )( GLenum coord, GLenum pname, const GLdouble *params );
+typedef void ( *OGLFncTexGenf )( GLenum coord, GLenum pname, GLfloat param );
+typedef void ( *OGLFncTexGenfv )( GLenum coord, GLenum pname, const GLfloat *params );
+typedef void ( *OGLFncTexGeni )( GLenum coord, GLenum pname, GLint param );
+typedef void ( *OGLFncTexGeniv )( GLenum coord, GLenum pname, const GLint *params );
+typedef void ( *OGLFncGetIntegerv )( GLenum pname, GLint *params );
+typedef void ( *OGLFncPolygonOffset ) ( GLfloat factor, GLfloat units );
+typedef void ( *OGLFncScissor ) ( GLint x, GLint y, GLsizei width, GLsizei height );
+
+typedef void ( *OGLFncEnableClientState ) ( GLenum array );
+typedef void ( *OGLFncDisableClientState ) ( GLenum array );
+typedef void ( *OGLFncVertexPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncColorPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncIndexPointer ) ( GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncNormalPointer ) ( GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncTexCoordPointer ) ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncEdgeFlagPointer ) ( GLsizei stride, const GLvoid *pointer );
+typedef void ( *OGLFncArrayElement ) ( GLint i );
+typedef void ( *OGLFncDrawElements ) ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices );
+typedef void ( *OGLFncDrawArrays ) ( GLenum mode, GLint first, GLsizei count );
+typedef void ( *OGLFncInterleavedArrays ) ( GLenum format, GLsizei stride, const GLvoid *pointer );
+
+typedef void ( *OGLFncLoadIdentity ) ();
+typedef void ( *OGLFncBlendFunc ) ( GLenum sfactor, GLenum dfactor );
+
+// ----------
+// - Macros -
+// ----------
+
+#define PGRAPHICS mpOutDev->mpGraphics
+
+#ifndef REMOTE_APPSERVER
+#define OGL_INIT() (mpOGL && (mpOutDev->mpGraphics || mpOutDev->ImplGetGraphics()))
+#else
+#define OGL_INIT() (mpOGL && (mpOutDev->mpGraphics || mpOutDev->ImplGetGraphics()))
+#endif
+
+#define INIT_OGLFNC( FncName ) static OGLFnc##FncName pImplOpenGLFnc##FncName = NULL;
+#define GET_OGLFNC_GL( FncName ) \
+pImplOpenGLFnc##FncName = (OGLFnc##FncName##) mpOGL->GetOGLFnc( "gl" #FncName ); \
+if( !pImplOpenGLFnc##FncName ) bRet = FALSE;
+
+// ----------
+// - OpenGL -
+// ----------
+
+static BOOL bImplOpenGLFncPtrInitialized = FALSE;
+
+INIT_OGLFNC( ClearDepth );
+INIT_OGLFNC( DepthFunc );
+INIT_OGLFNC( Enable );
+INIT_OGLFNC( Disable );
+INIT_OGLFNC( DepthMask );
+INIT_OGLFNC( ShadeModel );
+INIT_OGLFNC( EdgeFlag );
+INIT_OGLFNC( Clear );
+INIT_OGLFNC( Flush );
+INIT_OGLFNC( Finish );
+INIT_OGLFNC( Viewport );
+INIT_OGLFNC( Begin );
+INIT_OGLFNC( End );
+INIT_OGLFNC( Vertex3dv );
+INIT_OGLFNC( Normal3dv );
+INIT_OGLFNC( Color4ub );
+INIT_OGLFNC( Materialfv );
+INIT_OGLFNC( Materialf );
+INIT_OGLFNC( LightModelfv );
+INIT_OGLFNC( LightModelf );
+INIT_OGLFNC( Lightfv );
+INIT_OGLFNC( Lightf );
+INIT_OGLFNC( PolygonMode );
+INIT_OGLFNC( CullFace );
+INIT_OGLFNC( PointSize );
+INIT_OGLFNC( LineWidth );
+INIT_OGLFNC( MatrixMode );
+INIT_OGLFNC( LoadMatrixd );
+INIT_OGLFNC( TexCoord2dv );
+INIT_OGLFNC( TexCoord3dv );
+INIT_OGLFNC( TexImage1D );
+INIT_OGLFNC( TexImage2D );
+INIT_OGLFNC( CopyTexImage1D );
+INIT_OGLFNC( CopyTexImage2D );
+INIT_OGLFNC( CopyTexSubImage1D );
+INIT_OGLFNC( CopyTexSubImage2D );
+INIT_OGLFNC( PixelTransferf );
+INIT_OGLFNC( PixelTransferi );
+INIT_OGLFNC( GetTexLevelParameterfv );
+INIT_OGLFNC( GetTexLevelParameteriv );
+INIT_OGLFNC( GetTexParameterfv );
+INIT_OGLFNC( GetTexParameteriv );
+INIT_OGLFNC( TexSubImage1D );
+INIT_OGLFNC( TexSubImage2D );
+INIT_OGLFNC( PixelStoref );
+INIT_OGLFNC( PixelStorei );
+INIT_OGLFNC( GenTextures );
+INIT_OGLFNC( IsTexture );
+INIT_OGLFNC( BindTexture );
+INIT_OGLFNC( DeleteTextures );
+INIT_OGLFNC( AreTexturesResident );
+INIT_OGLFNC( PrioritizeTextures );
+INIT_OGLFNC( TexEnvf );
+INIT_OGLFNC( TexEnvfv );
+INIT_OGLFNC( TexEnvi );
+INIT_OGLFNC( TexEnviv );
+INIT_OGLFNC( TexParameterf );
+INIT_OGLFNC( TexParameterfv );
+INIT_OGLFNC( TexParameteri );
+INIT_OGLFNC( TexParameteriv );
+INIT_OGLFNC( TexGend );
+INIT_OGLFNC( TexGendv );
+INIT_OGLFNC( TexGenf );
+INIT_OGLFNC( TexGenfv );
+INIT_OGLFNC( TexGeni );
+INIT_OGLFNC( TexGeniv );
+INIT_OGLFNC( GetIntegerv );
+INIT_OGLFNC( PolygonOffset );
+INIT_OGLFNC( Scissor );
+
+INIT_OGLFNC( EnableClientState );
+INIT_OGLFNC( DisableClientState );
+INIT_OGLFNC( VertexPointer );
+INIT_OGLFNC( ColorPointer );
+INIT_OGLFNC( IndexPointer );
+INIT_OGLFNC( NormalPointer );
+INIT_OGLFNC( TexCoordPointer );
+INIT_OGLFNC( EdgeFlagPointer );
+INIT_OGLFNC( ArrayElement );
+INIT_OGLFNC( DrawElements );
+INIT_OGLFNC( DrawArrays );
+INIT_OGLFNC( InterleavedArrays );
+
+INIT_OGLFNC( LoadIdentity );
+INIT_OGLFNC( BlendFunc );
+
+// ------------------------------------------------------------------------
+
+BOOL OpenGL::ImplInitFncPointers()
+{
+#ifndef REMOTE_APPSERVER
+ BOOL bRet = TRUE;
+
+ GET_OGLFNC_GL( ClearDepth );
+ GET_OGLFNC_GL( DepthFunc );
+ GET_OGLFNC_GL( Enable );
+ GET_OGLFNC_GL( Disable );
+ GET_OGLFNC_GL( DepthMask );
+ GET_OGLFNC_GL( ShadeModel );
+ GET_OGLFNC_GL( EdgeFlag );
+ GET_OGLFNC_GL( Clear );
+ GET_OGLFNC_GL( Flush );
+ GET_OGLFNC_GL( Finish );
+ GET_OGLFNC_GL( Viewport );
+ GET_OGLFNC_GL( Begin );
+ GET_OGLFNC_GL( End );
+ GET_OGLFNC_GL( Vertex3dv );
+ GET_OGLFNC_GL( Normal3dv );
+ GET_OGLFNC_GL( Color4ub );
+ GET_OGLFNC_GL( Materialfv );
+ GET_OGLFNC_GL( Materialf );
+ GET_OGLFNC_GL( LightModelfv );
+ GET_OGLFNC_GL( LightModelf );
+ GET_OGLFNC_GL( Lightfv );
+ GET_OGLFNC_GL( Lightf );
+ GET_OGLFNC_GL( PolygonMode );
+ GET_OGLFNC_GL( CullFace );
+ GET_OGLFNC_GL( PointSize );
+ GET_OGLFNC_GL( LineWidth );
+ GET_OGLFNC_GL( MatrixMode );
+ GET_OGLFNC_GL( LoadMatrixd );
+ GET_OGLFNC_GL( TexCoord2dv );
+ GET_OGLFNC_GL( TexCoord3dv );
+ GET_OGLFNC_GL( TexImage1D );
+ GET_OGLFNC_GL( TexImage2D );
+ GET_OGLFNC_GL( CopyTexImage1D );
+ GET_OGLFNC_GL( CopyTexImage2D );
+ GET_OGLFNC_GL( CopyTexSubImage1D );
+ GET_OGLFNC_GL( CopyTexSubImage2D );
+ GET_OGLFNC_GL( PixelTransferf );
+ GET_OGLFNC_GL( PixelTransferi );
+ GET_OGLFNC_GL( GetTexLevelParameterfv );
+ GET_OGLFNC_GL( GetTexLevelParameteriv );
+ GET_OGLFNC_GL( GetTexParameterfv );
+ GET_OGLFNC_GL( GetTexParameteriv );
+ GET_OGLFNC_GL( TexSubImage1D );
+ GET_OGLFNC_GL( TexSubImage2D );
+ GET_OGLFNC_GL( PixelStoref );
+ GET_OGLFNC_GL( PixelStorei );
+ GET_OGLFNC_GL( GenTextures );
+ GET_OGLFNC_GL( IsTexture );
+ GET_OGLFNC_GL( BindTexture );
+ GET_OGLFNC_GL( DeleteTextures );
+ GET_OGLFNC_GL( AreTexturesResident );
+ GET_OGLFNC_GL( PrioritizeTextures );
+ GET_OGLFNC_GL( TexEnvf );
+ GET_OGLFNC_GL( TexEnvfv );
+ GET_OGLFNC_GL( TexEnvi );
+ GET_OGLFNC_GL( TexEnviv );
+ GET_OGLFNC_GL( TexParameterf );
+ GET_OGLFNC_GL( TexParameterfv );
+ GET_OGLFNC_GL( TexParameteri );
+ GET_OGLFNC_GL( TexParameteriv );
+ GET_OGLFNC_GL( TexGend );
+ GET_OGLFNC_GL( TexGendv );
+ GET_OGLFNC_GL( TexGenf );
+ GET_OGLFNC_GL( TexGenfv );
+ GET_OGLFNC_GL( TexGeni );
+ GET_OGLFNC_GL( TexGeniv );
+ GET_OGLFNC_GL( GetIntegerv );
+ GET_OGLFNC_GL( PolygonOffset );
+ GET_OGLFNC_GL( Scissor );
+
+ GET_OGLFNC_GL( EnableClientState );
+ GET_OGLFNC_GL( DisableClientState );
+ GET_OGLFNC_GL( VertexPointer );
+ GET_OGLFNC_GL( ColorPointer );
+ GET_OGLFNC_GL( IndexPointer );
+ GET_OGLFNC_GL( NormalPointer );
+ GET_OGLFNC_GL( TexCoordPointer );
+ GET_OGLFNC_GL( EdgeFlagPointer );
+ GET_OGLFNC_GL( ArrayElement );
+ GET_OGLFNC_GL( DrawElements );
+ GET_OGLFNC_GL( DrawArrays );
+ GET_OGLFNC_GL( InterleavedArrays );
+
+ GET_OGLFNC_GL( LoadIdentity );
+ GET_OGLFNC_GL( BlendFunc );
+
+ return bRet;
+#else
+ return FALSE;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+OpenGL::OpenGL( OutputDevice* pOutDev ) :
+ mpOutDev( pOutDev )
+{
+ ImplInit();
+}
+
+// ------------------------------------------------------------------------
+
+OpenGL::~OpenGL()
+{
+#ifndef REMOTE_APPSERVER
+ delete mpOGL;
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ImplInit()
+{
+#ifndef REMOTE_APPSERVER
+ if( PGRAPHICS || mpOutDev->ImplGetGraphics() )
+ {
+ mpOGL = new SalOpenGL( PGRAPHICS );
+
+ if ( !mpOGL->Create() || (!bImplOpenGLFncPtrInitialized && !ImplInitFncPointers()) )
+ {
+ delete mpOGL;
+ mpOGL = NULL;
+ }
+ else
+ bImplOpenGLFncPtrInitialized = TRUE;
+ }
+ else
+ mpOGL = NULL;
+#else
+ mpOGL = NULL;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::SetConnectOutputDevice( OutputDevice* pOutDev )
+{
+#ifndef REMOTE_APPSERVER
+ delete mpOGL;
+ mpOutDev = pOutDev;
+ ImplInit();
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ClearDepth( GLclampd fDepth )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncClearDepth( fDepth );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DepthFunc( GLenum eFunc )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDepthFunc( eFunc );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Enable( GLenum eCap )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnable( eCap );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Disable( GLenum eCap )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDisable( eCap );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DepthMask( GLboolean bFlag )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDepthMask( bFlag );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ShadeModel( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncShadeModel( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EdgeFlag( GLboolean bFlag )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEdgeFlag( bFlag );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Clear( GLbitfield nMask )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+#if defined UNX && ! defined MACOSX
+ mpOGL->StartScene( PGRAPHICS );
+#endif
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncClear( nMask );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Flush()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncFlush();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Finish()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncFinish();
+#if defined UNX && ! defined MACOSX
+ mpOGL->StopScene();
+#endif
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Viewport( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ long nOutHeight;
+
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ nOutHeight = ( (Window*) mpOutDev )->mpFrameWindow->mnOutHeight;
+ else
+ nOutHeight = mpOutDev->mnOutHeight;
+
+ mpOGL->OGLEntry( PGRAPHICS );
+
+ pImplOpenGLFncViewport( nX + mpOutDev->mnOutOffX,
+ nOutHeight - nY - nHeight - mpOutDev->mnOutOffY,
+ nWidth, nHeight );
+
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Begin( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBegin( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::End()
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnd();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Vertex3dv( const GLdouble* fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncVertex3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Normal3dv( const GLdouble* fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncNormal3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Color4ub( GLubyte cRed, GLubyte cGreen, GLubyte cBlue, GLubyte cAlpha )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncColor4ub( cRed, cGreen, cBlue, cAlpha );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Materialfv( GLenum eFace, GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMaterialfv( eFace, ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Materialf( GLenum eFace, GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMaterialf( eFace, ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LightModelfv( GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightModelfv( ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LightModelf( GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightModelf( ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Lightfv( GLenum eLight, GLenum ePName, const GLfloat *fParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightfv( eLight, ePName, fParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Lightf( GLenum eLight, GLenum ePName, GLfloat fParam )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLightf( eLight, ePName, fParam );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PolygonMode( GLenum eFace, GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPolygonMode( eFace, eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CullFace( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCullFace( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PointSize( GLfloat fSize )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPointSize( fSize );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LineWidth( GLfloat fWidth )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLineWidth( fWidth );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::MatrixMode( GLenum eMode )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncMatrixMode( eMode );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LoadMatrixd( const GLdouble *fM )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLoadMatrixd( fM );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoord2dv( const GLdouble *pParams )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoord2dv( pParams );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoord3dv( const GLdouble *fVar )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoord3dv( fVar );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexImage1D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexImage1D( target, level, internalformat, width, border, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexImage2D( target, level, internalformat, width, height, border, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexImage1D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexImage1D( target, level, internalFormat, x, y, width, border );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexImage2D( target, level, internalFormat, x, y, width, height, border );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexSubImage1D( target, level, xoffset, x, y, width );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::CopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelTransferf( GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelTransferf( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelTransferi( GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelTransferi( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexLevelParameterfv( GLenum target, GLint level, GLenum pname, GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexLevelParameterfv( target, level, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexLevelParameteriv( target, level, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexParameterfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetTexParameteriv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexSubImage1D( target, level, xoffset, width, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexSubImage2D( target, level, xoffset, yoffset, width, height, format, type, pixels );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelStoref( GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelStoref( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PixelStorei( GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPixelStorei( pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GenTextures( GLsizei n, GLuint *textures )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGenTextures( n, textures );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GLboolean OpenGL::IsTexture( GLuint texture )
+{
+ GLboolean bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ bRet = pImplOpenGLFncIsTexture( texture );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::BindTexture( GLenum target, GLuint texture )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBindTexture( target, texture );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DeleteTextures( GLsizei n, const GLuint *textures )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDeleteTextures( n, textures );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+GLboolean OpenGL::AreTexturesResident( GLsizei n, const GLuint *textures, GLboolean *residences )
+{
+ GLboolean bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ bRet = pImplOpenGLFncAreTexturesResident( n, textures, residences );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PrioritizeTextures( GLsizei n, const GLuint *textures, const GLclampf *priorities )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPrioritizeTextures( n, textures, priorities );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvf( GLenum target, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvf( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvfv( GLenum target, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnvi( GLenum target, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnvi( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexEnviv( GLenum target, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexEnviv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameterf( GLenum target, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameterf( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameterfv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameteri( GLenum target, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameteri( target, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexParameteriv( GLenum target, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexParameteriv( target, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGend( GLenum coord, GLenum pname, GLdouble param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGend( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGendv( GLenum coord, GLenum pname, const GLdouble *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGendv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGenf( GLenum coord, GLenum pname, GLfloat param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGenf( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGenfv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGeni( GLenum coord, GLenum pname, GLint param )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGeni( coord, pname, param );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexGeniv( GLenum coord, GLenum pname, const GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexGeniv( coord, pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::GetIntegerv( GLenum pname, GLint *params )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncGetIntegerv( pname, params );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::PolygonOffset( GLfloat factor, GLfloat units )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncPolygonOffset( factor, units );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::Scissor( GLint nX, GLint nY, GLsizei nWidth, GLsizei nHeight )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ long nOutHeight;
+
+ if( mpOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ nOutHeight = ( (Window*) mpOutDev )->mpFrameWindow->mnOutHeight;
+ else
+ nOutHeight = mpOutDev->mnOutHeight;
+
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncScissor( nX + mpOutDev->mnOutOffX,
+ nOutHeight - nY - nHeight - mpOutDev->mnOutOffY,
+ nWidth, nHeight );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EnableClientState( GLenum array )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEnableClientState( array );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DisableClientState( GLenum array )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDisableClientState( array );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::VertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncVertexPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncColorPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::IndexPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncIndexPointer( type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::NormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncNormalPointer( type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::TexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncTexCoordPointer( size, type, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::EdgeFlagPointer( GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncEdgeFlagPointer( stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::ArrayElement( GLint i )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncArrayElement( i );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDrawElements( mode, count, type, indices );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::DrawArrays( GLenum mode, GLint first, GLsizei count )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncDrawArrays( mode, first, count );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::InterleavedArrays( GLenum format, GLsizei stride, const GLvoid *pointer )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncInterleavedArrays( format, stride, pointer );
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::LoadIdentity( )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncLoadIdentity();
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+void OpenGL::BlendFunc( GLenum sfactor, GLenum dfactor )
+{
+#ifndef REMOTE_APPSERVER
+ if( OGL_INIT() )
+ {
+ mpOGL->OGLEntry( PGRAPHICS );
+ pImplOpenGLFncBlendFunc( sfactor, dfactor);
+ mpOGL->OGLExit( PGRAPHICS );
+ }
+#else
+#endif
+}
+
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
new file mode 100644
index 000000000000..591ecf8c8f8d
--- /dev/null
+++ b/vcl/source/gdi/outdev.cxx
@@ -0,0 +1,1927 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+#include <tools/ref.hxx>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _SV_SALVD_HXX
+#include <salvd.hxx>
+#endif
+#ifndef _SV_SALPRN_HXX
+#include <salprn.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_SALOTYPE_HXX
+#include <salotype.hxx>
+#endif
+#ifndef _SV_OPENGL_HXX
+#include <opengl.hxx>
+#endif
+#ifndef _VCL_IMPLNCVT_HXX
+#include <implncvt.hxx>
+#endif
+#ifndef _SV_OUTDEV3D_HXX
+#include <outdev3d.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _VCL_UNOWRAP_HXX
+#include <unowrap.hxx>
+#endif
+
+#include <com/sun/star/awt/XGraphics.hpp>
+
+DBG_NAME( OutputDevice );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+DBG_NAMEEX( Region );
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgCheckOutputDevice( const void* pObj )
+{
+ DBG_TESTSOLARMUTEX();
+
+ const OutputDevice* pOutDev = (OutputDevice*)pObj;
+
+ if ( (pOutDev->GetOutDevType() != OUTDEV_DONTKNOW) &&
+ (pOutDev->GetOutDevType() != OUTDEV_WINDOW) &&
+ (pOutDev->GetOutDevType() != OUTDEV_PRINTER) &&
+ (pOutDev->GetOutDevType() != OUTDEV_VIRDEV) )
+ return "OutputDevice data overwrite";
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+#define OUTDEV_POLYPOLY_STACKBUF 32
+
+// =======================================================================
+
+struct ImplObjStack
+{
+ ImplObjStack* mpPrev;
+ MapMode* mpMapMode;
+ Region* mpClipRegion;
+ Color* mpLineColor;
+ Color* mpFillColor;
+ Font* mpFont;
+ Color* mpTextColor;
+ Color* mpTextFillColor;
+ Color* mpTextLineColor;
+ Point* mpRefPoint;
+ TextAlign meTextAlign;
+ RasterOp meRasterOp;
+ USHORT mnFlags;
+};
+
+// -----------------------------------------------------------------------
+
+static void ImplDeleteObjStack( ImplObjStack* pObjStack )
+{
+ if ( pObjStack->mnFlags & PUSH_LINECOLOR )
+ {
+ if ( pObjStack->mpLineColor )
+ delete pObjStack->mpLineColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_FILLCOLOR )
+ {
+ if ( pObjStack->mpFillColor )
+ delete pObjStack->mpFillColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_FONT )
+ delete pObjStack->mpFont;
+ if ( pObjStack->mnFlags & PUSH_TEXTCOLOR )
+ delete pObjStack->mpTextColor;
+ if ( pObjStack->mnFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( pObjStack->mpTextFillColor )
+ delete pObjStack->mpTextFillColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( pObjStack->mpTextLineColor )
+ delete pObjStack->mpTextLineColor;
+ }
+ if ( pObjStack->mnFlags & PUSH_MAPMODE )
+ {
+ if ( pObjStack->mpMapMode )
+ delete pObjStack->mpMapMode;
+ }
+ if ( pObjStack->mnFlags & PUSH_CLIPREGION )
+ {
+ if ( pObjStack->mpClipRegion )
+ delete pObjStack->mpClipRegion;
+ }
+ if ( pObjStack->mnFlags & PUSH_REFPOINT )
+ {
+ if ( pObjStack->mpRefPoint )
+ delete pObjStack->mpRefPoint;
+ }
+
+ delete pObjStack;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+BOOL OutputDevice::ImplSelectClipRegion( SalGraphics* pGraphics, const Region& rRegion )
+{
+ DBG_TESTSOLARMUTEX();
+
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ULONG nRectCount;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+ BOOL bClipRegion = TRUE;
+
+ nRectCount = rRegion.GetRectCount();
+ pGraphics->BeginSetClipRegion( nRectCount );
+ bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ if ( !pGraphics->UnionClipRegion( nX, nY, nWidth, nHeight ) )
+ bClipRegion = FALSE;
+ DBG_ASSERT( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't cerate region" );
+ bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ pGraphics->EndSetClipRegion();
+ return bClipRegion;
+}
+
+#endif
+
+// =======================================================================
+
+OutputDevice::OutputDevice() :
+ maRegion( REGION_NULL ),
+ maSettings( Application::GetSettings() ),
+ maFillColor( COL_WHITE ),
+ maTextLineColor( COL_TRANSPARENT )
+{
+ DBG_CTOR( OutputDevice, ImplDbgCheckOutputDevice );
+
+ mpGraphics = NULL;
+ mpUnoGraphicsList = NULL;
+ mpPrevGraphics = NULL;
+ mpNextGraphics = NULL;
+ mpMetaFile = NULL;
+ mpFontEntry = NULL;
+ mpFontCache = NULL;
+ mpFontList = NULL;
+ mpGetDevFontList = NULL;
+ mpGetDevSizeList = NULL;
+ mpObjStack = NULL;
+ mpOutDevData = NULL;
+ mp3DContext = NULL;
+ mnOutOffX = 0;
+ mnOutOffY = 0;
+ mnOutWidth = 0;
+ mnOutHeight = 0;
+ mnDPIX = 0;
+ mnDPIY = 0;
+ mnTextOffX = 0;
+ mnTextOffY = 0;
+ mnDrawMode = 0;
+ meOutDevType = OUTDEV_DONTKNOW;
+ mbMap = FALSE;
+ mbClipRegion = FALSE;
+ mbBackground = FALSE;
+ mbOutput = TRUE;
+ mbDevOutput = FALSE;
+ mbOutputClipped = FALSE;
+ maTextColor = maFont.GetColor();
+ maTextFillColorDummy= maFont.GetFillColor();
+ meTextAlign = maFont.GetAlign();
+ meRasterOp = ROP_OVERPAINT;
+ mbLineColor = TRUE;
+ mbFillColor = TRUE;
+ mbInitLineColor = TRUE;
+ mbInitFillColor = TRUE;
+ mbInitFont = TRUE;
+ mbInitTextColor = TRUE;
+ mbInitClipRegion = TRUE;
+ mbClipRegionSet = FALSE;
+ mbKerning = FALSE;
+ mbNewFont = TRUE;
+ mbTextLines = FALSE;
+ mbTextSpecial = FALSE;
+ mbRefPoint = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+OutputDevice::~OutputDevice()
+{
+ DBG_DTOR( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( GetUnoGraphicsList() )
+ {
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ if ( pWrapper )
+ pWrapper->ReleaseAllGraphics( this );
+ delete mpUnoGraphicsList;
+ mpUnoGraphicsList = NULL;
+ }
+
+ if ( mp3DContext )
+ mp3DContext->Destroy( this );
+
+ if ( mpOutDevData )
+ ImplDeInitOutDevData();
+
+ ImplObjStack* pData = mpObjStack;
+ if ( pData )
+ {
+ DBG_ERRORFILE( "OutputDevice::~OutputDevice(): OutputDevice::Push() calls != OutputDevice::Pop() calls" );
+ while ( pData )
+ {
+ ImplObjStack* pTemp = pData;
+ pData = pData->mpPrev;
+ ImplDeleteObjStack( pTemp );
+ }
+ }
+
+ if ( mpFontEntry )
+ mpFontCache->Release( mpFontEntry );
+ if ( mpGetDevFontList )
+ delete mpGetDevFontList;
+ if ( mpGetDevSizeList )
+ delete mpGetDevSizeList;
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+int OutputDevice::ImplGetGraphics()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mpGraphics )
+ return TRUE;
+
+ mbInitLineColor = TRUE;
+ mbInitFillColor = TRUE;
+ mbInitFont = TRUE;
+ mbInitTextColor = TRUE;
+ mbInitClipRegion = TRUE;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( meOutDevType == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+
+ mpGraphics = pWindow->mpFrame->GetGraphics();
+ // Wenn wir keinen bekommen haben, versuchen wir uns einen zu klauen
+ if ( !mpGraphics )
+ {
+ OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
+ while ( pReleaseOutDev )
+ {
+ if ( ((Window*)pReleaseOutDev)->mpFrame == pWindow->mpFrame )
+ break;
+ pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
+ }
+
+ if ( pReleaseOutDev )
+ {
+ mpGraphics = pReleaseOutDev->mpGraphics;
+ pReleaseOutDev->ImplReleaseGraphics( FALSE );
+ }
+ else
+ {
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastWinGraphics )
+ break;
+ pSVData->maGDIData.mpLastWinGraphics->ImplReleaseGraphics();
+ mpGraphics = pWindow->mpFrame->GetGraphics();
+ }
+ }
+ }
+
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
+ pSVData->maGDIData.mpFirstWinGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastWinGraphics )
+ pSVData->maGDIData.mpLastWinGraphics = this;
+ }
+ }
+ else if ( meOutDevType == OUTDEV_VIRDEV )
+ {
+ VirtualDevice* pVirDev = (VirtualDevice*)this;
+
+ if ( pVirDev->mpVirDev )
+ {
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ break;
+ pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
+ pSVData->maGDIData.mpFirstVirGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ pSVData->maGDIData.mpLastVirGraphics = this;
+ }
+ }
+ }
+ else if ( meOutDevType == OUTDEV_PRINTER )
+ {
+ Printer* pPrinter = (Printer*)this;
+
+ if ( pPrinter->mpJobGraphics )
+ mpGraphics = pPrinter->mpJobGraphics;
+ else if ( pPrinter->mpDisplayDev )
+ {
+ VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ break;
+ pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
+ mpGraphics = pVirDev->mpVirDev->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
+ pSVData->maGDIData.mpFirstVirGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastVirGraphics )
+ pSVData->maGDIData.mpLastVirGraphics = this;
+ }
+ }
+ else
+ {
+ mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
+ while ( !mpGraphics )
+ {
+ if ( !pSVData->maGDIData.mpLastPrnGraphics )
+ break;
+ pSVData->maGDIData.mpLastPrnGraphics->ImplReleaseGraphics();
+ mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
+ }
+ if ( mpGraphics )
+ {
+ mpNextGraphics = pSVData->maGDIData.mpFirstPrnGraphics;
+ pSVData->maGDIData.mpFirstPrnGraphics = this;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = this;
+ if ( !pSVData->maGDIData.mpLastPrnGraphics )
+ pSVData->maGDIData.mpLastPrnGraphics = this;
+ }
+ }
+ }
+
+ if ( mpGraphics )
+ {
+ mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp) );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplReleaseGraphics( BOOL bRelease )
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !mpGraphics )
+ return;
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( meOutDevType == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+
+ if ( bRelease )
+ pWindow->mpFrame->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
+ }
+ else if ( meOutDevType == OUTDEV_VIRDEV )
+ {
+ VirtualDevice* pVirDev = (VirtualDevice*)this;
+
+ if ( bRelease )
+ pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
+ }
+ else if ( meOutDevType == OUTDEV_PRINTER )
+ {
+ Printer* pPrinter = (Printer*)this;
+
+ if ( !pPrinter->mpJobGraphics )
+ {
+ if ( pPrinter->mpDisplayDev )
+ {
+ VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
+ if ( bRelease )
+ pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
+ }
+ else
+ {
+ if ( bRelease )
+ pPrinter->mpInfoPrinter->ReleaseGraphics( mpGraphics );
+ if ( mpPrevGraphics )
+ mpPrevGraphics->mpNextGraphics = mpNextGraphics;
+ else
+ pSVData->maGDIData.mpFirstPrnGraphics = mpNextGraphics;
+ if ( mpNextGraphics )
+ mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
+ else
+ pSVData->maGDIData.mpLastPrnGraphics = mpPrevGraphics;
+ }
+ }
+ }
+
+ mpGraphics = NULL;
+ mpPrevGraphics = NULL;
+ mpNextGraphics = NULL;
+
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitOutDevData()
+{
+ if ( !mpOutDevData )
+ {
+ mpOutDevData = new ImplOutDevData;
+ mpOutDevData->mpRotateDev = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDeInitOutDevData()
+{
+ if ( mpOutDevData )
+ {
+ if ( mpOutDevData->mpRotateDev )
+ delete mpOutDevData->mpRotateDev;
+ delete mpOutDevData;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitLineColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+#ifndef REMOTE_APPSERVER
+ if( mbLineColor )
+ {
+ if( ROP_0 == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_0 );
+ else if( ROP_1 == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_1 );
+ else if( ROP_INVERT == meRasterOp )
+ mpGraphics->SetROPLineColor( SAL_ROP_INVERT );
+ else
+ mpGraphics->SetLineColor( ImplColorToSal( maLineColor ) );
+ }
+ else
+ mpGraphics->SetLineColor();
+#else
+ mpGraphics->SetLineColor( maLineColor );
+#endif
+
+ mbInitLineColor = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitFillColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+#ifndef REMOTE_APPSERVER
+ if( mbFillColor )
+ {
+ if( ROP_0 == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_0 );
+ else if( ROP_1 == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_1 );
+ else if( ROP_INVERT == meRasterOp )
+ mpGraphics->SetROPFillColor( SAL_ROP_INVERT );
+ else
+ mpGraphics->SetFillColor( ImplColorToSal( maFillColor ) );
+ }
+ else
+ mpGraphics->SetFillColor();
+#else
+ mpGraphics->SetFillColor( maFillColor );
+#endif
+
+ mbInitFillColor = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitClipRegion()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pWindow = (Window*)this;
+ Region aRegion;
+ // Hintergrund-Sicherung zuruecksetzen
+ if ( pWindow->mpFrameData->mpFirstBackWin )
+ pWindow->ImplInvalidateAllOverlapBackgrounds();
+ if ( pWindow->mbInPaint )
+ aRegion = *(pWindow->mpPaintRegion);
+ else
+ aRegion = *(pWindow->ImplGetWinChildClipRegion());
+ if ( mbClipRegion )
+ aRegion.Intersect( ImplPixelToDevicePixel( maRegion ) );
+ if ( aRegion.IsEmpty() )
+ mbOutputClipped = TRUE;
+ else
+ {
+ mbOutputClipped = FALSE;
+#ifndef REMOTE_APPSERVER
+ ImplSelectClipRegion( mpGraphics, aRegion );
+#else
+ mpGraphics->SetClipRegion( aRegion );
+#endif
+ }
+ mbClipRegionSet = TRUE;
+ }
+ else
+ {
+ if ( mbClipRegion )
+ {
+ if ( maRegion.IsEmpty() )
+ mbOutputClipped = TRUE;
+ else
+ {
+ mbOutputClipped = FALSE;
+#ifndef REMOTE_APPSERVER
+ ImplSelectClipRegion( mpGraphics, maRegion );
+#else
+ mpGraphics->SetClipRegion( maRegion );
+#endif
+ }
+
+ mbClipRegionSet = TRUE;
+ }
+ else
+ {
+ if ( mbClipRegionSet )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->ResetClipRegion();
+#else
+ mpGraphics->SetClipRegion();
+#endif
+ mbClipRegionSet = FALSE;
+ }
+
+ mbOutputClipped = FALSE;
+ }
+ }
+
+ mbInitClipRegion = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplSetClipRegion( const Region* pRegion )
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !pRegion )
+ {
+ if ( mbClipRegion )
+ {
+ maRegion = Region( REGION_NULL );
+ mbClipRegion = FALSE;
+ mbInitClipRegion = TRUE;
+ }
+ }
+ else
+ {
+ maRegion = *pRegion;
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetClipRegion()
+{
+ DBG_TRACE( "OutputDevice::SetClipRegion()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaClipRegionAction( Region(), FALSE ) );
+
+ ImplSetClipRegion( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetClipRegion( const Region& rRegion )
+{
+ DBG_TRACE( "OutputDevice::SetClipRegion( rRegion )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaClipRegionAction( rRegion, TRUE ) );
+
+ if ( rRegion.GetType() == REGION_NULL )
+ ImplSetClipRegion( NULL );
+ else
+ {
+ Region aRegion = LogicToPixel( rRegion );
+ ImplSetClipRegion( &aRegion );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::GetClipRegion() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ return PixelToLogic( maRegion );
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::GetActiveClipRegion() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Region aRegion( REGION_NULL );
+ Window* pWindow = (Window*)this;
+ if ( pWindow->mbInPaint )
+ {
+ aRegion = *(pWindow->mpPaintRegion);
+ aRegion.Move( -mnOutOffX, -mnOutOffY );
+ }
+ if ( mbClipRegion )
+ aRegion.Intersect( maRegion );
+ return PixelToLogic( aRegion );
+ }
+ else
+ return GetClipRegion();
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::MoveClipRegion( long nHorzMove, long nVertMove )
+{
+ DBG_TRACE( "OutputDevice::MoveClipRegion()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbClipRegion )
+ {
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaMoveClipRegionAction( nHorzMove, nVertMove ) );
+
+ maRegion.Move( ImplLogicWidthToDevicePixel( nHorzMove ),
+ ImplLogicHeightToDevicePixel( nVertMove ) );
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::IntersectClipRegion( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::IntersectClipRegion( rRect )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaISectRectClipRegionAction( rRect ) );
+
+ Rectangle aRect = LogicToPixel( rRect );
+ maRegion.Intersect( aRect );
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::IntersectClipRegion( const Region& rRegion )
+{
+ DBG_TRACE( "OutputDevice::IntersectClipRegion( rRegion )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rRegion.GetType();
+
+ if ( eType != REGION_NULL )
+ {
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaISectRegionClipRegionAction( rRegion ) );
+
+ Region aRegion = LogicToPixel( rRegion );
+ maRegion.Intersect( aRegion );
+ mbClipRegion = TRUE;
+ mbInitClipRegion = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetDrawMode( ULONG nDrawMode )
+{
+ DBG_TRACE1( "OutputDevice::SetDrawMode( %lx )", nDrawMode );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ mnDrawMode = nDrawMode;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRasterOp( RasterOp eRasterOp )
+{
+ DBG_TRACE1( "OutputDevice::SetRasterOp( %d )", (int)eRasterOp );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) );
+
+ if ( meRasterOp != eRasterOp )
+ {
+ meRasterOp = eRasterOp;
+ mbInitLineColor = mbInitFillColor = TRUE;
+
+#ifndef REMOTE_APPSERVER
+ if( mpGraphics || ImplGetGraphics() )
+ mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp) );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if( pGraphics )
+ pGraphics->SetRasterOp( eRasterOp );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetLineColor()
+{
+ DBG_TRACE( "OutputDevice::SetLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineColorAction( Color(), FALSE ) );
+
+ if ( mbLineColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = FALSE;
+ maLineColor = Color( COL_TRANSPARENT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetLineColor( const Color& rColor )
+{
+ DBG_TRACE1( "OutputDevice::SetLineColor( %lx )", rColor.GetColor() );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKLINE )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITELINE )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80);
+ }
+ }
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineColorAction( aColor, TRUE ) );
+
+ if( ImplIsColorTransparent( aColor ) )
+ {
+ if ( mbLineColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = FALSE;
+ maLineColor = Color( COL_TRANSPARENT );
+ }
+ }
+ else
+ {
+ if( maLineColor != aColor )
+ {
+ mbInitLineColor = TRUE;
+ mbLineColor = TRUE;
+ maLineColor = aColor;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetFillColor()
+{
+ DBG_TRACE( "OutputDevice::SetFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color(), FALSE ) );
+
+ if ( mbFillColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = FALSE;
+ maFillColor = Color( COL_TRANSPARENT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetFillColor( const Color& rColor )
+{
+ DBG_TRACE1( "OutputDevice::SetFillColor( %lx )", rColor.GetColor() );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL |
+ DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKFILL )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITEFILL )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+ else if( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aColor = Color( COL_TRANSPARENT );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDFILL )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80);
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFillColorAction( aColor, TRUE ) );
+
+ if ( ImplIsColorTransparent( aColor ) )
+ {
+ if ( mbFillColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = FALSE;
+ maFillColor = Color( COL_TRANSPARENT );
+ }
+ }
+ else
+ {
+ if ( maFillColor != aColor )
+ {
+ mbInitFillColor = TRUE;
+ mbFillColor = TRUE;
+ maFillColor = aColor;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetBackground()
+{
+ DBG_TRACE( "OutputDevice::SetBackground()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ maBackground = Wallpaper();
+ mbBackground = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetBackground( const Wallpaper& rBackground )
+{
+ DBG_TRACE( "OutputDevice::SetBackground( rBackground )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ maBackground = rBackground;
+
+ if( rBackground.GetStyle() == WALLPAPER_NULL )
+ mbBackground = FALSE;
+ else
+ mbBackground = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRefPoint()
+{
+ DBG_TRACE( "OutputDevice::SetRefPoint()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRefPointAction( Point(), FALSE ) );
+
+ mbRefPoint = FALSE;
+ maRefPoint.X() = maRefPoint.Y() = 0L;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRefPoint( const Point& rRefPoint )
+{
+ DBG_TRACE( "OutputDevice::SetRefPoint( rRefPoint )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, TRUE ) );
+
+ mbRefPoint = TRUE;
+ maRefPoint = rRefPoint;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ Point aEndPt = ImplLogicToDevicePixel( rEndPt );
+
+ mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawLine( ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt,
+ const LineInfo& rLineInfo )
+{
+ DBG_TRACE( "OutputDevice::DrawLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rLineInfo.IsDefault() )
+ {
+ DrawLine( rStartPt, rEndPt );
+ return;
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt, rLineInfo ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || ( LINE_NONE == rLineInfo.GetStyle() ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( ( aInfo.GetWidth() > 1L ) || ( LINE_DASH == aInfo.GetStyle() ) )
+ {
+ Polygon aPoly( 2 ); aPoly[ 0 ] = rStartPt; aPoly[ 1 ] = rEndPt;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( aPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+
+ if ( aInfo.GetWidth() > 1 )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->ImplGetConstPointAry() );
+
+ SetFillColor( aOldFillColor );
+ SetLineColor( aOldLineColor );
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ for ( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawLine( (*pPoly)[ 0 ].X(), (*pPoly)[ 0 ].Y(), (*pPoly)[ 1 ].X(), (*pPoly)[ 1 ].Y() );
+ }
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) );
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y() );
+ }
+
+#else
+
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( ( aInfo.GetWidth() > 1L ) || ( LINE_DASH == aInfo.GetStyle() ) )
+ {
+ Polygon aPoly( 2 ); aPoly[ 0 ] = rStartPt; aPoly[ 1 ] = rEndPt;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( aPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+
+ if ( aInfo.GetWidth() > 1 )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolygon( *pPoly );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ for ( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() ) {
+ Point xPoint((*pPoly)[ 0 ].X(), (*pPoly)[ 0 ].Y());
+ Point yPoint((*pPoly)[ 1 ].X(), (*pPoly)[ 1 ].Y());
+ mpGraphics->DrawLine( xPoint, yPoint );
+ }
+ }
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ pGraphics->DrawLine( ImplLogicToDevicePixel( rStartPt ), ImplLogicToDevicePixel( rEndPt ) );
+ }
+ }
+
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawRect( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::DrawRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRectAction( rRect ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawRect( aRect );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyLine( const Polygon& rPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyLineAction( rPoly ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || (nPoints < 2) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Polygon aPoly = ImplLogicToDevicePixel( rPoly );
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolyLine( nPoints, pPtAry );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawPolyLine( ImplLogicToDevicePixel( rPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if ( rLineInfo.IsDefault() )
+ {
+ DrawPolyLine( rPoly );
+ return;
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( aInfo.GetWidth() > 1L )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->ImplGetConstPointAry() );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( LINE_DASH == aInfo.GetStyle() )
+ {
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ mpGraphics->DrawPolyLine( pPoly->GetSize(), (const SalPoint*)pPoly->ImplGetConstPointAry() );
+ }
+ else
+ mpGraphics->DrawPolyLine( nPoints, (const SalPoint*) ImplLogicToDevicePixel( rPoly ).ImplGetConstPointAry() );
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+
+ if ( pGraphics )
+ {
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+
+ if( aInfo.GetWidth() > 1L )
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+
+ mpMetaFile = NULL;
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolygon( *pPoly );
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ mpMetaFile = pOldMetaFile;
+ }
+ else
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( LINE_DASH == aInfo.GetStyle() )
+ {
+ ImplLineConverter aLineCvt( ImplLogicToDevicePixel( rPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ pGraphics->DrawPolyLine( *pPoly );
+ }
+ else
+ pGraphics->DrawPolyLine( ImplLogicToDevicePixel( rPoly ) );
+ }
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolygon( const Polygon& rPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolygon()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPoly, Polygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ Polygon aPoly = ImplLogicToDevicePixel( rPoly );
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nPoints, pPtAry );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawPolygon( ImplLogicToDevicePixel( rPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ DBG_TRACE( "OutputDevice::DrawPolyPolygon()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
+
+ USHORT nPoly = rPolyPoly.Count();
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ if ( nPoly == 1 )
+ {
+ Polygon aPoly = ImplLogicToDevicePixel( rPolyPoly.GetObject( 0 ) );
+ USHORT nSize = aPoly.GetSize();
+ if ( nSize >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nSize, pPtAry );
+ }
+ }
+ else
+ {
+ PolyPolygon aPolyPoly = ImplLogicToDevicePixel( rPolyPoly );
+ ULONG aStackAry1[OUTDEV_POLYPOLY_STACKBUF];
+ PCONSTSALPOINT aStackAry2[OUTDEV_POLYPOLY_STACKBUF];
+ ULONG* pPointAry;
+ PCONSTSALPOINT* pPointAryAry;
+ USHORT i = 0;
+ if ( nPoly > OUTDEV_POLYPOLY_STACKBUF )
+ {
+ pPointAry = new ULONG[nPoly];
+ pPointAryAry = new PCONSTSALPOINT[nPoly];
+ }
+ else
+ {
+ pPointAry = aStackAry1;
+ pPointAryAry = aStackAry2;
+ }
+ do
+ {
+ const Polygon& rPoly = aPolyPoly.GetObject( i );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize )
+ {
+ pPointAry[i] = nSize;
+ pPointAryAry[i] = (PCONSTSALPOINT)rPoly.ImplGetConstPointAry();
+ i++;
+ }
+ else
+ nPoly--;
+ }
+ while ( i < nPoly );
+
+ if ( nPoly == 1 )
+ mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry );
+ else
+ mpGraphics->DrawPolyPolygon( nPoly, pPointAry, pPointAryAry );
+
+ if ( pPointAry != aStackAry1 )
+ {
+ delete pPointAry;
+ delete pPointAryAry;
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ if ( nPoly == 1 )
+ {
+ Polygon aPoly = ImplLogicToDevicePixel( rPolyPoly.GetObject( 0 ) );
+ USHORT nSize = aPoly.GetSize();
+ if ( nSize >= 2 )
+ pGraphics->DrawPolygon( aPoly );
+ }
+ else
+ pGraphics->DrawPolyPolygon( ImplLogicToDevicePixel( rPolyPoly ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Push( USHORT nFlags )
+{
+ DBG_TRACE( "OutputDevice::Push()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPushAction( nFlags ) );
+
+ ImplObjStack* pData = new ImplObjStack;
+ pData->mpPrev = mpObjStack;
+ mpObjStack = pData;
+
+ pData->mnFlags = nFlags;
+
+ if ( nFlags & PUSH_LINECOLOR )
+ {
+ if ( mbLineColor )
+ pData->mpLineColor = new Color( maLineColor );
+ else
+ pData->mpLineColor = NULL;
+ }
+ if ( nFlags & PUSH_FILLCOLOR )
+ {
+ if ( mbFillColor )
+ pData->mpFillColor = new Color( maFillColor );
+ else
+ pData->mpFillColor = NULL;
+ }
+ if ( nFlags & PUSH_FONT )
+ pData->mpFont = new Font( maFont );
+ if ( nFlags & PUSH_TEXTCOLOR )
+ pData->mpTextColor = new Color( GetTextColor() );
+ if ( nFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( IsTextFillColor() )
+ pData->mpTextFillColor = new Color( GetTextFillColor() );
+ else
+ pData->mpTextFillColor = NULL;
+ }
+ if ( nFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( IsTextLineColor() )
+ pData->mpTextLineColor = new Color( GetTextLineColor() );
+ else
+ pData->mpTextLineColor = NULL;
+ }
+ if ( nFlags & PUSH_TEXTALIGN )
+ pData->meTextAlign = GetTextAlign();
+ if ( nFlags & PUSH_RASTEROP )
+ pData->meRasterOp = GetRasterOp();
+ if ( nFlags & PUSH_MAPMODE )
+ {
+ if ( mbMap )
+ pData->mpMapMode = new MapMode( maMapMode );
+ else
+ pData->mpMapMode = NULL;
+ }
+ if ( nFlags & PUSH_CLIPREGION )
+ {
+ if ( mbClipRegion )
+ pData->mpClipRegion = new Region( maRegion );
+ else
+ pData->mpClipRegion = NULL;
+ }
+ if ( nFlags & PUSH_REFPOINT )
+ {
+ if ( mbRefPoint )
+ pData->mpRefPoint = new Point( maRefPoint );
+ else
+ pData->mpRefPoint = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Pop()
+{
+ DBG_TRACE( "OutputDevice::Pop()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPopAction() );
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ ImplObjStack* pData = mpObjStack;
+ mpMetaFile = NULL;
+
+ if ( !pData )
+ {
+ DBG_ERRORFILE( "OutputDevice::Pop() without OutputDevice::Push()" );
+ return;
+ }
+
+ mpObjStack = pData->mpPrev;
+
+ if ( pData->mnFlags & PUSH_LINECOLOR )
+ {
+ if ( pData->mpLineColor )
+ SetLineColor( *pData->mpLineColor );
+ else
+ SetLineColor();
+ }
+ if ( pData->mnFlags & PUSH_FILLCOLOR )
+ {
+ if ( pData->mpFillColor )
+ SetFillColor( *pData->mpFillColor );
+ else
+ SetFillColor();
+ }
+ if ( pData->mnFlags & PUSH_FONT )
+ SetFont( *pData->mpFont );
+ if ( pData->mnFlags & PUSH_TEXTCOLOR )
+ SetTextColor( *pData->mpTextColor );
+ if ( pData->mnFlags & PUSH_TEXTFILLCOLOR )
+ {
+ if ( pData->mpTextFillColor )
+ SetTextFillColor( *pData->mpTextFillColor );
+ else
+ SetTextFillColor();
+ }
+ if ( pData->mnFlags & PUSH_TEXTLINECOLOR )
+ {
+ if ( pData->mpTextLineColor )
+ SetTextLineColor( *pData->mpTextLineColor );
+ else
+ SetTextLineColor();
+ }
+ if ( pData->mnFlags & PUSH_TEXTALIGN )
+ SetTextAlign( pData->meTextAlign );
+ if ( pData->mnFlags & PUSH_RASTEROP )
+ SetRasterOp( pData->meRasterOp );
+ if ( pData->mnFlags & PUSH_MAPMODE )
+ {
+ if ( pData->mpMapMode )
+ SetMapMode( *pData->mpMapMode );
+ else
+ SetMapMode();
+ }
+ if ( pData->mnFlags & PUSH_CLIPREGION )
+ ImplSetClipRegion( pData->mpClipRegion );
+ if ( pData->mnFlags & PUSH_REFPOINT )
+ {
+ if ( pData->mpRefPoint )
+ SetRefPoint( *pData->mpRefPoint );
+ else
+ SetRefPoint();
+ }
+
+ ImplDeleteObjStack( pData );
+
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetBitCount() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( meOutDevType == OUTDEV_VIRDEV )
+ return ((VirtualDevice*)this)->mnBitCount;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !((OutputDevice*)this)->ImplGetGraphics() )
+ return 0;
+ }
+#endif
+
+ return (USHORT)mpGraphics->GetBitCount();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG OutputDevice::GetColorCount() const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ const USHORT nBitCount = GetBitCount();
+ return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (ULONG) 1 ) << nBitCount) );
+}
+
+// -----------------------------------------------------------------------
+
+OpenGL* OutputDevice::GetOpenGL()
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+#ifndef REMOTE_APPSERVER
+ OpenGL* pOGL;
+
+ if( OUTDEV_PRINTER != meOutDevType )
+ {
+ pOGL = new OpenGL( this );
+
+ if( !pOGL->IsValid() )
+ {
+ delete pOGL;
+ pOGL = NULL;
+ }
+ }
+ else
+ pOGL = NULL;
+
+ return pOGL;
+#else
+ return NULL;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > OutputDevice::CreateUnoGraphics()
+{
+ UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
+ return pWrapper ? pWrapper->CreateGraphics( this ) : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >();
+}
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx
new file mode 100644
index 000000000000..b454fe3632ff
--- /dev/null
+++ b/vcl/source/gdi/outdev2.cxx
@@ -0,0 +1,1928 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV2_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALBMP_HXX
+#include <salbmp.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifdef REMOTE_APPSERVER
+#include <rmoutdev.hxx>
+#endif
+
+#define BAND_MAX_SIZE 512000
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// =======================================================================
+
+// -----------
+// - Defines -
+// -----------
+
+#ifndef REMOTE_APPSERVER
+
+#define OUTDEV_INIT() \
+{ \
+ if ( !IsDeviceOutputNecessary() ) \
+ return; \
+ \
+ if ( !mpGraphics ) \
+ if ( !ImplGetGraphics() ) \
+ return; \
+ \
+ if ( mbInitClipRegion ) \
+ ImplInitClipRegion(); \
+ \
+ if ( mbOutputClipped ) \
+ return; \
+}
+
+#else // !REMOTE_APPSERVER
+
+#define OUTDEV_INIT() \
+{ \
+ if ( !IsDeviceOutputNecessary() ) \
+ return; \
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics(); \
+ if ( !pGraphics ) \
+ return; \
+}
+
+#endif // REMOTE_APPSERVER
+
+#ifndef REMOTE_APPSERVER
+#define TwoRect SalTwoRect
+#else
+#define TwoRect RemoteTwoRect
+#endif
+
+// -------------
+// - externals -
+// -------------
+
+extern ULONG nVCLRLut[ 6 ];
+extern ULONG nVCLGLut[ 6 ];
+extern ULONG nVCLBLut[ 6 ];
+extern ULONG nVCLDitherLut[ 256 ];
+extern ULONG nVCLLut[ 256 ];
+
+// =======================================================================
+
+ULONG ImplAdjustTwoRect( TwoRect& rTwoRect, const Size& rSizePix )
+{
+ ULONG nMirrFlags = 0;
+
+ if ( rTwoRect.mnDestWidth < 0 )
+ {
+ rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
+ rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
+ rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if ( rTwoRect.mnDestHeight < 0 )
+ {
+ rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
+ rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
+ rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ return nMirrFlags;
+}
+
+// =======================================================================
+
+void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, void* pVoidPosAry )
+{
+ TwoRect* pPosAry = (TwoRect*)pVoidPosAry;
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics2;
+#else
+ ImplServerGraphics* pGraphics2;
+#endif
+
+ if ( pPosAry->mnSrcWidth && pPosAry->mnSrcHeight && pPosAry->mnDestWidth && pPosAry->mnDestHeight )
+ {
+ if ( this == pSrcDev )
+ pGraphics2 = NULL;
+ else
+ {
+ if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
+ (GetOutDevType() != OUTDEV_WINDOW) )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( !pSrcDev->mpGraphics )
+ {
+ if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
+ return;
+ }
+#endif
+ pGraphics2 = pSrcDev->mpGraphics;
+ }
+ else
+ {
+ if ( ((Window*)this)->mpFrameWindow == ((Window*)pSrcDev)->mpFrameWindow )
+ pGraphics2 = NULL;
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ if ( !pSrcDev->mpGraphics )
+ {
+ if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
+ return;
+ }
+#endif
+ pGraphics2 = pSrcDev->mpGraphics;
+
+#ifndef REMOTE_APPSERVER
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+ DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
+ "OutputDevice::DrawOutDev(): We need more than one Graphics" );
+#endif
+ }
+ }
+ }
+
+ Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
+ Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
+ Rectangle aSrcRect( Point( pPosAry->mnSrcX, pPosAry->mnSrcY ),
+ Size( pPosAry->mnSrcWidth, pPosAry->mnSrcHeight ) );
+ const long nOldRight = aSrcRect.Right();
+ const long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (pPosAry->mnSrcX+pPosAry->mnSrcWidth-1) > aSrcOutRect.Right() )
+ {
+ const long nOldWidth = pPosAry->mnSrcWidth;
+ pPosAry->mnSrcWidth -= (nOldRight - aSrcRect.Right());
+ pPosAry->mnDestWidth = pPosAry->mnDestWidth * pPosAry->mnSrcWidth / nOldWidth;
+ }
+
+ if ( (pPosAry->mnSrcY+pPosAry->mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ {
+ const long nOldHeight = pPosAry->mnSrcHeight;
+ pPosAry->mnSrcHeight -= (nOldBottom - aSrcRect.Bottom());
+ pPosAry->mnDestHeight = pPosAry->mnDestHeight * pPosAry->mnSrcHeight / nOldHeight;
+ }
+
+ mpGraphics->CopyBits( pPosAry, pGraphics2 );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPt, const Size& rSrcSize )
+{
+ DBG_TRACE( "OutputDevice::DrawOutDev()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+
+ if ( meOutDevType == OUTDEV_PRINTER )
+ return;
+
+ if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ }
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+ aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+
+ Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
+ long nOldRight = aSrcRect.Right();
+ long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
+ {
+ long nOldWidth = aPosAry.mnSrcWidth;
+ aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
+ aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth;
+ }
+
+ if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ {
+ long nOldHeight = aPosAry.mnSrcHeight;
+ aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
+ aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight;
+ }
+
+ mpGraphics->CopyBits( &aPosAry, NULL );
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPt, const Size& rSrcSize,
+ const OutputDevice& rOutDev )
+{
+ DBG_TRACE( "OutputDevice::DrawOutDev()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+ DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
+
+ if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) )
+ return;
+
+ if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ }
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ ImplDrawOutDevDirect( &rOutDev, &aPosAry );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::CopyArea( const Point& rDestPt,
+ const Point& rSrcPt, const Size& rSrcSize,
+ USHORT nFlags )
+{
+ DBG_TRACE( "OutputDevice::CopyArea()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
+
+ if ( meOutDevType == OUTDEV_PRINTER )
+ return;
+
+ RasterOp eOldRop = GetRasterOp();
+ SetRasterOp( ROP_OVERPAINT );
+
+ OUTDEV_INIT();
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
+ aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
+ {
+ aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+
+ Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
+ long nOldRight = aSrcRect.Right();
+ long nOldBottom = aSrcRect.Bottom();
+
+ if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
+ {
+ if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
+ aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
+
+ if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
+ aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
+
+ if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) )
+ {
+ ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect,
+ aPosAry.mnDestX-aPosAry.mnSrcX,
+ aPosAry.mnDestY-aPosAry.mnSrcY,
+ FALSE );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
+ aPosAry.mnSrcX, aPosAry.mnSrcY,
+ aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
+ SAL_COPYAREA_WINDOWINVALIDATE );
+#else
+ mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
+ aPosAry.mnSrcX, aPosAry.mnSrcY,
+ aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
+ COPYAREA_WINDOWINVALIDATE );
+#endif
+ }
+ else
+ {
+ aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
+ aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
+ mpGraphics->CopyBits( &aPosAry, NULL );
+ }
+ }
+ }
+
+ SetRasterOp( eOldRop );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
+ const OutputDevice& rOutDev, const Region& rRegion )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ BOOL bOldMap = mbMap;
+ RasterOp eOldROP = GetRasterOp();
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ SetRasterOp( ROP_OVERPAINT );
+
+#ifndef REMOTE_APPSERVER
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+#else
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#endif
+
+ // ClipRegion zuruecksetzen
+#ifndef REMOTE_APPSERVER
+ if ( rRegion.IsNull() )
+ mpGraphics->ResetClipRegion();
+ else
+ ImplSelectClipRegion( mpGraphics, rRegion );
+#else
+ if ( rRegion.IsNull() )
+ mpGraphics->SetClipRegion();
+ else
+ mpGraphics->SetClipRegion( rRegion );
+#endif
+
+ TwoRect aPosAry;
+ aPosAry.mnSrcX = rDevPt.X();
+ aPosAry.mnSrcY = rDevPt.Y();
+ aPosAry.mnSrcWidth = rDevSize.Width();
+ aPosAry.mnSrcHeight = rDevSize.Height();
+ aPosAry.mnDestX = rPt.X();
+ aPosAry.mnDestY = rPt.Y();
+ aPosAry.mnDestWidth = rDevSize.Width();
+ aPosAry.mnDestHeight = rDevSize.Height();
+ ImplDrawOutDevDirect( &rOutDev, &aPosAry );
+
+ // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird
+ mbInitClipRegion = TRUE;
+
+ SetRasterOp( eOldROP );
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
+ OutputDevice& rDev )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+ rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
+ mbMap = bOldMap;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap()" );
+ const Size aSizePix( rBitmap.GetSizePixel() );
+ ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap( Size )" );
+ ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
+ ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
+}
+
+// -----------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Bitmap aBmp( rBitmap );
+
+ if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
+ return;
+ else if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+ else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
+ DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ Pop();
+ return;
+ }
+ else if( !!aBmp )
+ {
+ if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
+ aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
+ aBmp.Convert( BMP_CONVERSION_GHOSTED );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_BMP_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpScalePartAction(
+ rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+ if( ( OUTDEV_PRINTER == meOutDevType ) && mbClipRegion && ( REGION_COMPLEX == maRegion.GetType() ) )
+ {
+ Bitmap aMask;
+ ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+
+ if ( !( !aBmp ) )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
+
+ if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+ if ( nMirrFlags )
+ aBmp.Mirror( nMirrFlags );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawBitmap( &aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap() );
+#else
+ aBmp.ImplDrawRemote( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ) );
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx()" );
+
+ if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
+ else
+ {
+ const Size aSizePix( rBitmapEx.GetSizePixel() );
+ ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
+
+ if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
+ else
+ ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const BitmapEx& rBitmapEx )
+{
+ DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
+
+ if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
+ DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
+ else
+ ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const BitmapEx& rBitmapEx, const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BitmapEx aBmpEx( rBitmapEx );
+
+ if ( mnDrawMode & DRAWMODE_NOBITMAP )
+ return;
+ else if ( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+ else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
+ DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
+ {
+ Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
+
+ if( aBmpEx.IsAlpha() )
+ aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetAlpha() );
+ else
+ aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
+ }
+ else if( !!aBmpEx )
+ {
+ if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
+ aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
+ aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_BMPEX_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
+ rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() );
+ aBmp.Replace( aMask, Color( COL_WHITE ) );
+ ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#ifndef REMOTE_APPSERVER
+ else if( rBitmapEx.IsAlpha() )
+ {
+ ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#endif
+
+ if( !( !aBmpEx ) )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() );
+
+ if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( nMirrFlags )
+ aBmpEx.Mirror( nMirrFlags );
+
+ const ImpBitmap* pImpBmp = aBmpEx.ImplGetBitmapImpBitmap();
+ const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap();
+
+ if ( pMaskBmp )
+ mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), *pMaskBmp->ImplGetSalBitmap() );
+ else
+ mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap() );
+
+#else
+
+ if( nMirrFlags )
+ aBmpEx.Mirror( nMirrFlags );
+
+ aBmpEx.ImplDrawRemote( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ) );
+
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask()" );
+ const Size aSizePix( rBitmap.GetSizePixel() );
+ ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask( Size )" );
+ ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const Color& rMaskColor )
+{
+ DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" );
+ ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION );
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ const Bitmap& rBitmap, const Color& rMaskColor,
+ const ULONG nAction )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( ROP_INVERT == meRasterOp )
+ {
+ DrawRect( Rectangle( rDestPt, rDestSize ) );
+ return;
+ }
+
+ if ( mpMetaFile )
+ {
+ switch( nAction )
+ {
+ case( META_MASK_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
+ rBitmap, rMaskColor ) );
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
+ rDestSize, rBitmap, rMaskColor ) );
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
+ rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
+ break;
+ }
+ }
+
+ OUTDEV_INIT();
+
+#ifndef REMOTE_APPSERVER
+ if ( OUTDEV_PRINTER == meOutDevType )
+ {
+ ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
+ return;
+ }
+#endif
+
+ const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
+
+ if ( pImpBmp )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ // spiegeln via Koordinaten wollen wir nicht
+ const ULONG nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
+
+ // check if output is necessary
+ if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+#ifndef REMOTE_APPSERVER
+
+ if( nMirrFlags )
+ {
+ Bitmap aTmp( rBitmap );
+ aTmp.Mirror( nMirrFlags );
+ mpGraphics->DrawMask( &aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
+ ImplColorToSal( rMaskColor ) );
+ }
+ else
+ mpGraphics->DrawMask( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
+ ImplColorToSal( rMaskColor ) );
+
+#else
+
+ if( nMirrFlags )
+ {
+ Bitmap aTmp( rBitmap );
+ aTmp.Mirror( nMirrFlags );
+ aTmp.ImplDrawRemoteMask( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ),
+ rMaskColor );
+ }
+ else
+ rBitmap.ImplDrawRemoteMask( this,
+ Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
+ Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ),
+ Point( aPosAry.mnDestX, aPosAry.mnDestY ),
+ Size( aPosAry.mnDestWidth, aPosAry.mnDestHeight ),
+ rMaskColor );
+
+#endif
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Bitmap aBmp;
+ long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
+ long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
+#endif
+ {
+ if ( nWidth && nHeight )
+ {
+#ifndef REMOTE_APPSERVER
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ BOOL bClipped = FALSE;
+
+ // X-Koordinate ausserhalb des Bereichs?
+ if ( nX < mnOutOffX )
+ {
+ nWidth -= ( mnOutOffX - nX );
+ nX = mnOutOffX;
+ bClipped = TRUE;
+ }
+
+ // Y-Koordinate ausserhalb des Bereichs?
+ if ( nY < mnOutOffY )
+ {
+ nHeight -= ( mnOutOffY - nY );
+ nY = mnOutOffY;
+ bClipped = TRUE;
+ }
+
+ // Breite ausserhalb des Bereichs?
+ if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
+ {
+ nWidth = mnOutOffX + mnOutWidth - nX;
+ bClipped = TRUE;
+ }
+
+ // Hoehe ausserhalb des Bereichs?
+ if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
+ {
+ nHeight = mnOutOffY + mnOutHeight - nY;
+ bClipped = TRUE;
+ }
+
+ if ( bClipped )
+ {
+ // Falls auf den sichtbaren Bereich geclipped wurde,
+ // muessen wir eine Bitmap in der rchtigen Groesse
+ // erzeugen, in die die geclippte Bitmap an die angepasste
+ // Position kopiert wird
+ VirtualDevice aVDev( *this );
+
+ if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
+ {
+ if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
+ {
+ TwoRect aPosAry;
+
+ aPosAry.mnSrcX = nX;
+ aPosAry.mnSrcY = nY;
+ aPosAry.mnSrcWidth = nWidth;
+ aPosAry.mnSrcHeight = nHeight;
+ aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
+ aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
+ aPosAry.mnDestWidth = nWidth;
+ aPosAry.mnDestHeight = nHeight;
+
+ if ( (nWidth > 0) && (nHeight > 0) )
+ (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( &aPosAry, mpGraphics );
+
+ aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+ else
+ bClipped = FALSE;
+ }
+ else
+ bClipped = FALSE;
+ }
+
+ if ( !bClipped )
+ {
+ SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight );
+
+ if( pSalBmp )
+ {
+ ImpBitmap* pImpBmp = new ImpBitmap;
+ pImpBmp->ImplSetSalBitmap( pSalBmp );
+ aBmp.ImplSetImpBitmap( pImpBmp );
+ }
+ }
+#else
+ aBmp.ImplGetRemoteBmp( (OutputDevice*) this, Point( nX, nY ), Size( nWidth, nHeight ) );
+#endif
+ }
+ }
+
+ return aBmp;
+}
+
+// ------------------------------------------------------------------
+
+void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize,
+ Bitmap& rBitmap ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bOldMap = mbMap;
+ ((OutputDevice*)this)->mbMap = FALSE;
+ rBitmap = GetBitmap( rDestPt, rSize );
+ ((OutputDevice*)this)->mbMap = bOldMap;
+}
+
+// ------------------------------------------------------------------
+
+Color OutputDevice::GetPixel( const Point& rPt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ((OutputDevice*)this)->ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ const long nX = ImplLogicXToDevicePixel( rPt.X() );
+ const long nY = ImplLogicYToDevicePixel( rPt.Y() );
+ const SalColor aSalCol = mpGraphics->GetPixel( nX, nY );
+ aColor.SetRed( SALCOLOR_RED( aSalCol ) );
+ aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
+ aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
+ }
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ( (OutputDevice*) this )->ImplGetServerGraphics();
+ if( pGraphics )
+ {
+ const long nX = ImplLogicXToDevicePixel( rPt.X() );
+ const long nY = ImplLogicYToDevicePixel( rPt.Y() );
+ aColor = pGraphics->GetPixel( Point( nX, nY ) );
+ }
+#endif // REMOTE_APPSERVER
+
+ return aColor;
+}
+
+// ------------------------------------------------------------------
+
+Color* OutputDevice::GetPixel( const Polygon& rPts ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color* pColors = NULL;
+ const USHORT nSize = rPts.GetSize();
+
+ if( nSize )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ((OutputDevice*)this)->ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ pColors = new Color[ nSize ];
+
+ for( USHORT i = 0; i < nSize; i++ )
+ {
+ Color& rCol = pColors[ i ];
+ const Point& rPt = rPts[ i ];
+ const SalColor aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ),
+ ImplLogicYToDevicePixel( rPt.Y() ) ) );
+
+ rCol.SetRed( SALCOLOR_RED( aSalCol ) );
+ rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) );
+ rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) );
+ }
+ }
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ( (OutputDevice*) this )->ImplGetServerGraphics();
+ if( pGraphics )
+ {
+ pColors = pGraphics->GetPixel( ImplLogicToDevicePixel( rPts ) );
+ }
+#endif // REMOTE_APPSERVER
+ }
+
+ return pColors;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Point& rPt )
+{
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPointAction( rPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ Point aPt = ImplLogicToDevicePixel( rPt );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ if( !ImplIsColorTransparent( aColor ) )
+ {
+ if( mnDrawMode & DRAWMODE_BLACKLINE )
+ {
+ aColor = Color( COL_BLACK );
+ }
+ else if( mnDrawMode & DRAWMODE_WHITELINE )
+ {
+ aColor = Color( COL_WHITE );
+ }
+ else if( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80 );
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
+
+ if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ Point aPt = ImplLogicToDevicePixel( rPt );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ) );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPt ), aColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
+{
+ if ( !pColors )
+ DrawPixel( rPts, GetLineColor() );
+ else
+ {
+ DBG_TRACE( "OutputDevice::DrawPixel()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
+
+ const USHORT nSize = rPts.GetSize();
+
+ if ( nSize )
+ {
+ if ( mpMetaFile )
+ for ( USHORT i = 0; i < nSize; i++ )
+ mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ for ( USHORT i = 0; i < nSize; i++ )
+ {
+ const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
+ mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ) );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ pGraphics->DrawPixel( ImplLogicToDevicePixel( rPts ), pColors );
+ }
+#endif
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
+{
+ if( rColor != COL_TRANSPARENT )
+ {
+ const USHORT nSize = rPts.GetSize();
+ Color* pColArray = new Color[ nSize ];
+
+ for( USHORT i = 0; i < nSize; i++ )
+ pColArray[ i ] = rColor;
+
+ DrawPixel( rPts, pColArray );
+ delete[] pColArray;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+ Point aPt;
+ Point aOutPt( LogicToPixel( rDestPt ) );
+ Size aOutSz( LogicToPixel( rDestSize ) );
+ Rectangle aDstRect( aPt, GetOutputSizePixel() );
+ const BOOL bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0;
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
+ }
+
+ if( bHMirr )
+ {
+ aOutSz.Width() = -aOutSz.Width();
+ aOutPt.X() -= ( aOutSz.Width() - 1L );
+ }
+
+ if( bVMirr )
+ {
+ aOutSz.Height() = -aOutSz.Height();
+ aOutPt.Y() -= ( aOutSz.Height() - 1L );
+ }
+
+ if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
+ {
+ Rectangle aBmpRect( aPt, rBmp.GetSizePixel() );
+
+ if( !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL;
+ const BOOL bOldMap = mbMap; mbMap = FALSE;
+ Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
+ BitmapColor aDstCol;
+ const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
+ const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
+ const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
+ const long nOffX = aDstRect.Left() - aOutPt.X(), nOffY = aDstRect.Top() - aOutPt.Y();
+ long nX, nOutX, nY, nOutY, nMirrOffX, nMirrOffY;
+ long* pMapX = new long[ nDstWidth ];
+ long* pMapY = new long[ nDstHeight ];
+
+ // create horizontal mapping table
+ if( bHMirr )
+ nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
+
+ for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
+ {
+ pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
+
+ if( bHMirr )
+ pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
+ }
+
+ // create vertical mapping table
+ if( bVMirr )
+ nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
+
+ for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
+ {
+ pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
+
+ if( bVMirr )
+ pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
+ }
+
+ if( GetBitCount() <= 8 )
+ {
+ Bitmap aDither( aBmp.GetSizePixel(), 8 );
+ BitmapColor aIndex( 0 );
+ BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
+ BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapReadAccess* pB = aBmp.AcquireReadAccess();
+ BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
+
+ if( pB && pP && pA && pW )
+ {
+ for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ const long nModY = ( nOutY & 0x0FL ) << 4L;
+
+ for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ const ULONG nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
+
+ aDstCol = pB->GetColor( nY, nX );
+ aDstCol.Merge( pP->GetColor( nMapY, nMapX ), (BYTE) pA->GetPixel( nMapY, nMapX ) );
+ aIndex.SetIndex( (BYTE) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
+ nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
+ nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
+ pW->SetPixel( nY, nX, aIndex );
+ }
+ }
+ }
+
+ ( (Bitmap&) rBmp ).ReleaseAccess( pP );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
+ aBmp.ReleaseAccess( pB );
+ aDither.ReleaseAccess( pW );
+ DrawBitmap( aDstRect.TopLeft(), aDither );
+ }
+ else
+ {
+ BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
+ BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
+
+ if( pP && pA && pB )
+ {
+ if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ switch( pP->GetScanlineFormat() )
+ {
+ case( BMP_FORMAT_8BIT_PAL ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ Scanline pTmp = pPScan + nMapX * 3;
+
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pPScan = pP->GetScanline( nMapY );
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ Scanline pTmp = pPScan + nMapX * 3;
+
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+ Scanline pAScan = pA->GetScanline( nMapY );
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
+ pAScan[ nMapX ] ) );
+ }
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nDstHeight; nY++ )
+ {
+ const long nMapY = pMapY[ nY ];
+
+ for( nX = 0; nX < nDstWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ aDstCol = pB->GetPixel( nY, nX );
+ pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
+ (BYTE) pA->GetPixel( nMapY, nMapX ) ) );
+ }
+ }
+ }
+ }
+
+ ( (Bitmap&) rBmp ).ReleaseAccess( pP );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
+ aBmp.ReleaseAccess( pB );
+ DrawBitmap( aDstRect.TopLeft(), aBmp );
+ }
+
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+static Pair* ImplGetMap( long nFromSize, long nToSize )
+{
+ DBG_ASSERT( nFromSize && nToSize, "ImplGetMap(): Invalid size!" );
+
+ Pair* pMap = new Pair[ nFromSize ];
+ const double fSize = (double) nToSize / nFromSize;
+ double fRealSum = 0.0;
+ const long nLastToPos = nToSize - 1L;
+ long nErrSum = 0L, nPos = 0L, nSize = 0L;
+
+ for( long i = 0L; i < nFromSize; i++ )
+ {
+ nPos = nPos + nSize;
+ nSize = Max( FRound( fSize - ( nErrSum - fRealSum ) ), 0L );
+
+ nErrSum += nSize;
+ fRealSum += fSize;
+
+ pMap[ i ].A() = nPos = Min( nPos, nLastToPos );
+ pMap[ i ].B() = Min( nPos + Max( nSize, 1L ) - 1L, nLastToPos );
+ }
+
+ return pMap;
+}
+
+// ------------------------------------------------------------------------
+
+static BOOL ImplCreateBandBitmaps( BitmapReadAccess* pPAcc, BitmapReadAccess* pMAcc,
+ long* pMapX, long* pMapY,
+ long nDstWidth, long nDstY1, long nDstY2,
+ Bitmap& rPaint, Bitmap& rMask )
+{
+ const Size aSz( nDstWidth, nDstY2 - nDstY1 + 1 );
+ BOOL bRet = FALSE;
+
+ rPaint = Bitmap( aSz, pPAcc->GetBitCount(), pPAcc->HasPalette() ? &pPAcc->GetPalette() : NULL );
+ rMask = Bitmap( aSz, pMAcc->GetBitCount(), pMAcc->HasPalette() ? &pMAcc->GetPalette() : NULL );
+
+ BitmapWriteAccess* pWPAcc = rPaint.AcquireWriteAccess();
+ BitmapWriteAccess* pWMAcc = rMask.AcquireWriteAccess();
+
+ if( pWPAcc && pWMAcc )
+ {
+ const long nWidth = pWPAcc->Width();
+ const long nHeight = pWPAcc->Width();
+ const long nPScanSize = pWPAcc->GetScanlineSize();
+ const long nMScanSize = pWMAcc->GetScanlineSize();
+ long nY = 0, nScanY = nDstY1;
+
+ while( nScanY <= nDstY2 )
+ {
+ const long nMapY = pMapY[ nScanY ];
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ const long nMapX = pMapX[ nX ];
+ pWPAcc->SetPixel( nY, nX, pPAcc->GetPixel( nMapY, nMapX ) );
+ pWMAcc->SetPixel( nY, nX, pMAcc->GetPixel( nMapY, nMapX ) );
+ }
+
+ while( ( nScanY < nDstY2 ) && ( pMapY[ nScanY + 1 ] == nMapY ) )
+ {
+ HMEMCPY( pWPAcc->GetScanline( nY + 1L ), pWPAcc->GetScanline( nY ), nPScanSize );
+ HMEMCPY( pWMAcc->GetScanline( nY + 1L ), pWMAcc->GetScanline( nY ), nMScanSize );
+ nY++, nScanY++;
+ }
+
+ nY++, nScanY++;
+ }
+
+ bRet = TRUE;
+ }
+
+ if( pWPAcc )
+ rPaint.ReleaseAccess( pWPAcc );
+
+ if( pWMAcc )
+ rMask.ReleaseAccess( pWMAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+ Point aPt;
+ Point aDestPt( LogicToPixel( rDestPt ) );
+ Size aDestSz( LogicToPixel( rDestSize ) );
+ Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
+
+ aSrcRect.Justify();
+
+ if( !!rBmp && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
+ {
+ ULONG nMirrFlags = 0UL;
+ Bitmap aPaint( rBmp );
+ Bitmap aMask( rMask );
+ Region aDstRgn;
+ BOOL bMask = !!aMask;
+
+ if( bMask && ( aMask.GetBitCount() > 1 ) )
+ aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ // mirrored horizontically
+ if( aDestSz.Width() < 0L )
+ {
+ aDestSz.Width() = -aDestSz.Width();
+ aDestPt.X() -= ( aDestSz.Width() - 1L );
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ // mirrored vertically
+ if( aDestSz.Height() < 0L )
+ {
+ aDestSz.Height() = -aDestSz.Height();
+ aDestPt.Y() -= ( aDestSz.Height() - 1L );
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ // source cropped?
+ if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
+ {
+ aPaint.Crop( aSrcRect );
+ if( bMask )
+ aMask.Crop( aSrcRect );
+ }
+
+ // destination mirrored
+ if( nMirrFlags )
+ {
+ aPaint.Mirror( nMirrFlags );
+ if( bMask )
+ aMask.Mirror( nMirrFlags );
+ }
+
+ const Rectangle aDstRect( aDestPt, aDestSz );
+
+ // create destination region
+ if( mbClipRegion && !maRegion.IsEmpty() )
+ {
+ aDstRgn = maRegion;
+ aDstRgn.Intersect( aDstRect );
+ }
+ else
+ aDstRgn = aDstRect;
+
+ aDstRgn.Move( -aDstRect.Left(), -aDstRect.Top() );
+
+ // we always want to have a mask
+ if( !bMask )
+ {
+ aMask = Bitmap( aSrcRect.GetSize(), 1 );
+ aMask.Erase( Color( COL_BLACK ) );
+ }
+
+ BitmapReadAccess* pPAcc = aPaint.AcquireReadAccess();
+ BitmapReadAccess* pMAcc = aMask.AcquireReadAccess();
+
+ if( pPAcc && pMAcc )
+ {
+ const long nWidth = aDestSz.Width();
+ const long nHeight = aDestSz.Height();
+ const long nWidth1 = nWidth - 1;
+ const long nHeight1 = nHeight - 1;
+ const long nOldWidth1 = aSrcRect.GetWidth() - 1;
+ const long nOldHeight1 = aSrcRect.GetHeight() - 1;
+ const long nScanByteCount = Max( nWidth * aPaint.GetBitCount() / 8L, 1L );
+ const long nBandHeight = BAND_MAX_SIZE / nScanByteCount + 1;
+ long* pMapX = new long[ nWidth ];
+ long* pMapY = new long[ nHeight ];
+ long nX, nY;
+ long nBandY1, nBandY2;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const BOOL bOldMap = mbMap;
+
+ mpMetaFile = NULL;
+ Push( PUSH_CLIPREGION );
+ SetClipRegion();
+ mbMap = FALSE;
+
+ // create mapping tables
+ for( nX = 0L; nX < nWidth; nX++ )
+ pMapX[ nX ] = nWidth1 ? ( nX * nOldWidth1 / nWidth1 ) : 0;
+
+ for( nY = 0L; nY < nHeight; nY++ )
+ pMapY[ nY ] = nHeight1 ? ( nY * nOldHeight1 / nHeight1 ) : 0;
+
+ // process bands
+ for( nBandY1 = 0, nBandY2 = nBandHeight; nBandY1 < nHeight; nBandY1 += nBandHeight, nBandY2 += nBandHeight )
+ {
+ Bitmap aWorkPaint, aWorkMask;
+
+ // don't walk over bounds
+ if( nBandY2 > nHeight1 )
+ nBandY2 = nHeight1;
+
+ if( ImplCreateBandBitmaps( pPAcc, pMAcc, pMapX, pMapY, nWidth, nBandY1, nBandY2, aWorkPaint, aWorkMask ) )
+ {
+ Region aWorkRgn( aDstRgn );
+ aWorkRgn.Move( 0, -nBandY1 );
+ aWorkRgn.Intersect( aWorkMask.CreateRegion( COL_BLACK, Rectangle( aPt, aWorkMask.GetSizePixel() ) ) );
+
+ ImplRegionInfo aInfo;
+ long nWorkX, nWorkY, nWorkWidth, nWorkHeight;
+ BOOL bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY,
+ nWorkWidth, nWorkHeight );
+
+ while( bRgnRect )
+ {
+ Bitmap aCropBmp( aWorkPaint );
+ const Point aOutPt( nWorkX + aDestPt.X(), nWorkY + nBandY1 + aDestPt.Y() );
+ const Size aOutSz( nWorkWidth, nWorkHeight );
+ const Size aOutSz1( nWorkWidth + 1, nWorkHeight + 1 );
+
+ aCropBmp.Crop( Rectangle( Point( nWorkX, nWorkY ), aOutSz ) );
+ ImplDrawBitmap( aOutPt, aOutSz1, Point(), aOutSz, aCropBmp, META_BMPSCALE_ACTION );
+ bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
+ }
+ }
+ }
+
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ Pop();
+ mpMetaFile = pOldMetaFile;
+ }
+
+ if( pPAcc )
+ aPaint.ReleaseAccess( pPAcc );
+
+ if( pMAcc )
+ aMask.ReleaseAccess( pMAcc );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel )
+{
+#ifndef REMOTE_APPSERVER
+
+ Point aPt;
+ Point aDestPt( LogicToPixel( rDestPt ) );
+ Size aDestSz( LogicToPixel( rDestSize ) );
+ Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
+
+ aSrcRect.Justify();
+
+ if( !!rMask &&
+ aSrcRect.GetWidth() && aSrcRect.GetHeight() &&
+ aDestSz.Width() && aDestSz.Height() )
+ {
+ ULONG nMirrFlags = 0UL;
+ Bitmap aMask( rMask );
+ Region aRegion;
+
+ if( aMask.GetBitCount() > 1 )
+ aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
+
+ if( aDestSz.Width() < 0L )
+ {
+ aDestSz.Width() = -aDestSz.Width();
+ aDestPt.X() -= ( aDestSz.Width() - 1L );
+ nMirrFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if( aDestSz.Height() < 0L )
+ {
+ aDestSz.Height() = -aDestSz.Height();
+ aDestPt.Y() -= ( aDestSz.Height() - 1L );
+ nMirrFlags |= BMP_MIRROR_VERT;
+ }
+
+ // source cropped?
+ if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) )
+ aMask.Crop( aSrcRect );
+
+ // destination mirrored
+ if( nMirrFlags )
+ aMask.Mirror( nMirrFlags );
+
+ aRegion = aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) );
+
+ ImplRegionInfo aInfo;
+ const Size aSrcSz( aMask.GetSizePixel() );
+ long nSrcX, nSrcY, nSrcWidth, nSrcHeight;
+ long nDstX, nDstY, nDstWidth, nDstHeight;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ Pair* pMapX = ImplGetMap( aSrcSz.Width(), aDestSz.Width() );
+ Pair* pMapY = ImplGetMap( aSrcSz.Height(), aDestSz.Height() );
+ BOOL bOldMap = mbMap;
+ BOOL bRegionRect = aRegion.ImplGetFirstRect( aInfo, nSrcX, nSrcY, nSrcWidth, nSrcHeight );
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
+ SetLineColor( rMaskColor );
+ SetFillColor( rMaskColor );
+ ImplInitLineColor();
+ ImplInitFillColor();
+
+ while( bRegionRect )
+ {
+ nDstX = pMapX[ nSrcX ].A();
+ nDstY = pMapY[ nSrcY ].A();
+ nDstWidth = pMapX[ nSrcX + nSrcWidth - 1L ].B() - nDstX + 1L;
+ nDstHeight = pMapY[ nSrcY + nSrcHeight - 1L ].B() - nDstY + 1L;
+ mpGraphics->DrawRect( nDstX + aDestPt.X(), nDstY + aDestPt.Y(), nDstWidth, nDstHeight );
+ bRegionRect = aRegion.ImplGetNextRect( aInfo, nSrcX, nSrcY, nSrcWidth, nSrcHeight );
+ }
+
+ Pop();
+ delete[] pMapX;
+ delete[] pMapY;
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+ }
+
+#endif
+}
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
new file mode 100644
index 000000000000..4dbd5935f2ae
--- /dev/null
+++ b/vcl/source/gdi/outdev3.cxx
@@ -0,0 +1,6326 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <math.h>
+#include <string.h>
+
+#define _SV_OUTDEV_CXX
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <metric.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_EDIT_HXX
+#include <edit.hxx>
+#endif
+
+#include <unohelp.hxx>
+
+#ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
+#include <com/sun/star/text/XBreakIterator.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
+#include <com/sun/star/text/WordType.hpp>
+#endif
+
+#if defined UNX
+#define GLYPH_FONT_HEIGHT 128
+#elif defined OS2
+#define GLYPH_FONT_HEIGHT 176
+#else
+#define GLYPH_FONT_HEIGHT 256
+#endif
+
+#define WSstrcmp strcmp
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Font );
+
+// =======================================================================
+
+#define OUTDEV_CHARCONVERT_REPLACE FALSE
+
+using namespace ::com::sun::star;
+using namespace ::rtl;
+
+
+// =======================================================================
+
+#define MAX_DX_WORDS 120
+#define TEXT_DRAW_ELLIPSIS (TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_PATHELLIPSIS | TEXT_DRAW_NEWSELLIPSIS)
+
+// =======================================================================
+
+#define UNDERLINE_LAST UNDERLINE_BOLDWAVE
+#define STRIKEOUT_LAST STRIKEOUT_X
+
+// =======================================================================
+
+void OutputDevice::ImplUpdateFontData( BOOL bNewFontLists )
+{
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( bNewFontLists )
+ {
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ }
+
+ if ( GetOutDevType() == OUTDEV_PRINTER )
+ {
+ mpFontCache->Clear();
+
+ if ( bNewFontLists )
+ {
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( ImplGetGraphics() )
+#endif
+ {
+ mpFontList->Clear();
+ mpGraphics->GetDevFontList( mpFontList );
+ mpFontList->InitStdFonts();
+ }
+ }
+ }
+
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+
+ // Bei Fenstern auch alle Child-Fenster mit updaten
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pChild = ((Window*)this)->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplUpdateFontData( TRUE );
+ pChild = pChild->mpNext;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplUpdateAllFontData( BOOL bNewFontLists )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Alle Fenster updaten
+ Window* pFrame = pSVData->maWinData.mpFirstFrame;
+ while ( pFrame )
+ {
+ pFrame->ImplUpdateFontData( bNewFontLists );
+
+ Window* pSysWin = pFrame->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ pSysWin->ImplUpdateFontData( bNewFontLists );
+ pSysWin = pSysWin->mpNextOverlap;
+ }
+
+ pFrame = pFrame->mpFrameData->mpNextFrame;
+ }
+
+ // Alle VirDev's updaten
+ VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
+ while ( pVirDev )
+ {
+ pVirDev->ImplUpdateFontData( bNewFontLists );
+ pVirDev = pVirDev->mpNext;
+ }
+
+ // Alle Printer updaten
+ Printer* pPrinter = pSVData->maGDIData.mpFirstPrinter;
+ while ( pPrinter )
+ {
+ pPrinter->ImplUpdateFontData( bNewFontLists );
+ pPrinter = pPrinter->mpNext;
+ }
+
+ // Globale Fontlisten leeren, damit diese geupdatet werden
+ pSVData->maGDIData.mpScreenFontCache->Clear();
+ if ( bNewFontLists )
+ {
+ pSVData->maGDIData.mpScreenFontList->Clear();
+ pFrame = pSVData->maWinData.mpFirstFrame;
+ if ( pFrame )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFrame->ImplGetGraphics() )
+#endif
+ {
+ pFrame->mpGraphics->GetDevFontList( pFrame->mpFrameData->mpFontList );
+ pFrame->mpFrameData->mpFontList->InitStdFonts();
+ }
+ }
+ }
+}
+
+// =======================================================================
+
+struct ImplFontSubstEntry
+{
+ XubString maName;
+ XubString maReplaceName;
+ XubString maMatchName;
+ XubString maMatchReplaceName;
+ USHORT mnFlags;
+ ImplFontSubstEntry* mpNext;
+};
+
+// =======================================================================
+
+static void ImplStrEraseAllSymbols( XubString& rStr )
+{
+ xub_StrLen i = 0;
+ xub_Unicode c = rStr.GetChar( i );
+ while ( c )
+ {
+ // Alle Zeichen kleiner 0 zwischen 9-A, Z-a und z-127 loeschen
+ if ( (c < 48) || ((c > 57) && (c < 65)) || ((c > 90) && (c < 97)) ||
+ ((c > 122) && (c <= 127)) )
+ rStr.Erase( i, 1 );
+ else
+ i++;
+ c = rStr.GetChar( i );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static xub_StrLen ImplStrMatch( const XubString& rStr1, const XubString& rStr2 )
+{
+ xub_StrLen nMatch = 0;
+ const xub_Unicode* pStr1 = rStr1.GetBuffer();
+ const xub_Unicode* pStr2 = rStr2.GetBuffer();
+ while ( (*pStr1 == *pStr2) && *pStr1 )
+ {
+ pStr1++;
+ pStr2++;
+ nMatch++;
+ }
+ return nMatch;
+}
+
+// -----------------------------------------------------------------------
+
+static int ImplStrFullMatch( const XubString& rStr1, const char* pStr2 )
+{
+ const xub_Unicode* pStr1 = rStr1.GetBuffer();
+ while ( (*pStr1 == (xub_Unicode)(unsigned char)*pStr2) && *pStr1 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+ return !(*pStr1);
+}
+
+// =======================================================================
+
+#if 0
+
+#define FONT_ATTR_SYMBOL ((ULONG)0x00000001)
+#define FONT_ATTR_FIXED ((ULONG)0x00000002)
+#define FONT_ATTR_ITALIC ((ULONG)0x00000004)
+#define FONT_ATTR_NORMAL ((ULONG)0x00000008)
+#define FONT_ATTR_STANDARD ((ULONG)0x00000010)
+#define FONT_ATTR_SPECIAL ((ULONG)0x00000020)
+#define FONT_ATTR_TITLING ((ULONG)0x00000040)
+#define FONT_ATTR_SERIF ((ULONG)0x00000080)
+#define FONT_ATTR_NONSERIF ((ULONG)0x00000100)
+#define FONT_ATTR_ROUNDED ((ULONG)0x00000200)
+#define FONT_ATTR_OUTLINE ((ULONG)0x00000400)
+#define FONT_ATTR_SHADOW ((ULONG)0x00000800)
+#define FONT_ATTR_SCRIPT ((ULONG)0x00001000)
+#define FONT_ATTR_HANDWRITING ((ULONG)0x00002000)
+#define FONT_ATTR_DECORATION ((ULONG)0x00004000)
+#define FONT_ATTR_CHARSCRIPT ((ULONG)0x00008000)
+#define FONT_ATTR_CHANCERY ((ULONG)0x00010000)
+#define FONT_ATTR_OLDSTYLE ((ULONG)0x00020000)
+#define FONT_ATTR_FAVOR1 ((ULONG)0x01000000)
+#define FONT_ATTR_FAVOR2 ((ULONG)0x02000000)
+#define FONT_ATTR_FAVOR3 ((ULONG)0x04000000)
+#define FONT_ATTR_FAVOR4 ((ULONG)0x08000000)
+#define FONT_ATTR_FOUND ((ULONG)0x80000000)
+
+struct ImplFontAttrWidthSearchData
+{
+ const char* mpStr;
+ FontWidth meWidth;
+};
+
+static ImplFontAttrWidthSearchData const aImplWidthAttrSearchList[] =
+{
+{ "narrow", WIDTH_CONDENSED },
+{ "semicondensed", WIDTH_SEMI_CONDENSED },
+{ "ultracondensed", WIDTH_ULTRA_CONDENSED },
+{ "semiexpanded", WIDTH_SEMI_EXPANDED },
+{ "ultraexpanded", WIDTH_ULTRA_EXPANDED },
+{ "expanded", WIDTH_EXPANDED },
+{ "wide", WIDTH_ULTRA_EXPANDED },
+{ "condensed", WIDTH_CONDENSED },
+{ "cond", WIDTH_CONDENSED },
+{ "cn", WIDTH_CONDENSED },
+{ NULL, WIDTH_DONTKNOW },
+};
+
+struct ImplFontAttrWeightSearchData
+{
+ const char* mpStr;
+ FontWeight meWeight;
+};
+
+static ImplFontAttrWeightSearchData const aImplWeightAttrSearchList[] =
+{
+{ "extrablack", WEIGHT_BLACK },
+{ "ultrablack", WEIGHT_BLACK },
+{ "black", WEIGHT_BLACK },
+{ "heavy", WEIGHT_BLACK },
+{ "ultrabold", WEIGHT_ULTRABOLD },
+{ "semibold", WEIGHT_SEMIBOLD },
+{ "bold", WEIGHT_BOLD },
+{ "ultralight", WEIGHT_ULTRALIGHT },
+{ "semilight", WEIGHT_SEMILIGHT },
+{ "light", WEIGHT_LIGHT },
+{ "demi", WEIGHT_SEMIBOLD },
+{ "medium", WEIGHT_MEDIUM },
+{ NULL, WEIGHT_DONTKNOW },
+};
+
+struct ImplFontAttrTypeSearchData
+{
+ const char* mpStr;
+ ULONG mnType;
+};
+
+static ImplFontAttrTypeSearchData const aImplTypeAttrSearchList[] =
+{
+{ "titling", FONT_ATTR_TITLING },
+{ "outline", FONT_ATTR_OUTLINE },
+{ "shadow", FONT_ATTR_SHADOW },
+{ NULL, 0 },
+};
+
+// =======================================================================
+
+struct ImplFontNameAttr
+{
+ const char* mpName;
+ FontFamily meFamily;
+ FontWeight meWeight;
+ FontWidth meWidth;
+ ULONG mnType;
+};
+
+static const ImplFontNameAttr aImplFullList[] =
+{
+{ "Bookman", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NORMAL | FONT_ATTR_STANDARD | FONT_ATTR_SERIF },
+{ NULL, FAMILY_DONTKNOW,WEIGHT_DONTKNOW,WIDTH_DONTKNOW, 0 }
+};
+
+static const ImplFontNameAttr aImplMatchList[] =
+{
+{ "bookman", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NORMAL | FONT_ATTR_STANDARD | FONT_ATTR_SERIF },
+{ "comicsansms", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "kristenitc", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "maiandragd", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT | FONT_ATTR_FAVOR3 },
+{ "arioso", FAMILY_SCRIPT, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_ITALIC | FONT_ATTR_DECORATION | FONT_ATTR_OLDSTYLE | FONT_ATTR_FAVOR3 },
+{ "tempussansitc", FAMILY_SCRIPT, WEIGHT_LIGHT, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT },
+{ "papyrus", FAMILY_SCRIPT, WEIGHT_LIGHT, WIDTH_NORMAL, FONT_ATTR_NONSERIF | FONT_ATTR_SCRIPT | FONT_ATTR_CHARSCRIPT },
+{ "lucidashadowtitling", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "lucidaopenboldtitling",FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "lucidaopentitling", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "lucidaopen", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE },
+{ "lucidashadow", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "chevara", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_EXPANDED, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "colonnamt", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_SPECIAL | FONT_ATTR_OUTLINE },
+{ "imprintmtshadow", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW },
+{ "castellar", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE },
+{ "algerian", FAMILY_ROMAN, WEIGHT_NORMAL, WIDTH_NORMAL, FONT_ATTR_SERIF | FONT_ATTR_SPECIAL | FONT_ATTR_TITLING | FONT_ATTR_OUTLINE | FONT_ATTR_SHADOW | FONT_ATTR_OLDSTYLE },
+{ NULL, FAMILY_DONTKNOW,WEIGHT_DONTKNOW,WIDTH_DONTKNOW, 0 }
+};
+
+#endif
+
+static const char* aImplSwissMatchList[] =
+{
+ "arial",
+ "avantgarde",
+ "cgomega",
+ "centurygothic",
+ "charcoal",
+ "chicago",
+ "frutiger",
+ "geneva",
+ "haettenschweiler",
+ "helmet",
+ "helv",
+ "lucida",
+ "impact",
+ "tahoma",
+ "univers",
+ "vagrounded",
+ "verdana",
+ NULL
+};
+
+static const char* aImplSwissSearchList[] =
+{
+ "sansserif",
+ "swiss",
+ NULL
+};
+
+static const char* aImplRomanMatchList[] =
+{
+ "algerian",
+ "antiqua",
+ "caliso",
+ "clarendon",
+ "colonna",
+ "garamond",
+ "newyork",
+ "palatino",
+ "timmons",
+ NULL
+};
+
+static const char* aImplRomanSearchList[] =
+{
+ "book",
+ "times",
+ "roman",
+ "bright",
+ NULL
+};
+
+static const char* aImplFixedMatchList[] =
+{
+ "lineprinter",
+ "monaco",
+ "typewriter",
+ NULL
+};
+
+static const char* aImplFixedSearchList[] =
+{
+ "console",
+ "courier",
+ "fixed",
+ "letter",
+ "monospace",
+ "terminal",
+ NULL
+};
+
+static const char* aImplScriptMatchList[] =
+{
+ "arioso",
+ "coronet",
+ "cursive",
+ "marigold",
+ "zapfchancery",
+ NULL
+};
+
+static const char* aImplScriptSearchList[] =
+{
+ "script",
+ "signet",
+ "handwriting",
+ "calligraphy",
+ NULL
+};
+
+static const char* aImplSymbolMatchList[] =
+{
+ "marlett",
+ "monotypesorts",
+ "msoutlook",
+ NULL
+};
+
+static const char* aImplSymbolSearchList[] =
+{
+ "symbol",
+ "bats",
+ "dings",
+ "math",
+ NULL
+};
+
+static const char* aImplTypeList[] =
+{
+ "black",
+ "bold",
+ "condensed",
+ "expanded",
+ "narrow",
+ "outline",
+ NULL
+};
+
+// =======================================================================
+
+static const char* aImplSearchScriptList[] =
+{
+ "ce",
+ "we",
+ "cyr",
+ "tur",
+ "wt",
+ "greek",
+ "wl",
+ NULL
+};
+
+// -----------------------------------------------------------------------
+
+struct ImplScriptSearchList
+{
+ const char* mpScript;
+ rtl_Script meScript;
+};
+
+static void ImplCutScriptAndSpaces( XubString& rName )
+{
+ rName.EraseLeadingAndTrailingChars( ' ' );
+
+ USHORT nLen = rName.Len();
+ if ( nLen < 3 )
+ return;
+
+ // Scriptname must be the last part of the fontname and
+ // looks like "fontname (scriptname)". So there can only be a
+ // script name at the and of the fontname, when the last char is
+ // ')'.
+ if ( rName.GetChar( nLen-1 ) == ')' )
+ {
+ int nOpen = 1;
+ nLen -= 2;
+ while ( nLen )
+ {
+ if ( rName.GetChar( nLen ) == '(' )
+ {
+ nOpen--;
+ if ( !nOpen && nLen && (rName.GetChar( nLen-1 ) == ' ') )
+ {
+ XubString aScript = rName.Copy( nLen+1, rName.Len()-1-nLen-1 );
+ rName.Erase( nLen-1 );
+ return;
+ }
+ }
+ if ( rName.GetChar( nLen ) == ')' )
+ nOpen++;
+ nLen--;
+ }
+ }
+
+ // For compatibility with older version we must search for a
+ // script name at the end of a fontname without brakets
+ USHORT nSpacePos = rName.SearchBackward( ' ' );
+ if ( nSpacePos && (nSpacePos != STRING_NOTFOUND) )
+ {
+ XubString aScript = rName.Copy( nSpacePos+1 );
+ const char** pScript = aImplSearchScriptList;
+ while ( *pScript )
+ {
+ if ( aScript.EqualsAscii( *pScript ) )
+ {
+ rName.Erase( nSpacePos );
+ break;
+ }
+ pScript++;
+ }
+ }
+}
+
+// =======================================================================
+
+#if 0
+
+static const ImplFontNameAttr* ImplFindFontAttr( const XubString& rFontName )
+{
+ const ImplFontNameAttr* pList;
+
+ pList = aImplFullList;
+ while ( pList->mpName )
+ {
+ if ( rFontName.EqualsAscii( pList->mpName ) )
+ return pList;
+ pList++;
+ }
+
+ pList = aImplMatchList;
+ while ( pList->mpName )
+ {
+ if ( ImplStrFullMatch( rFontName, pList->mpName ) )
+ return pList;
+ pList++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetFontAttr( const XubString& rFontName,
+ FontFamily& rFamily, CharSet& rCharSet,
+ FontPitch& rPitch )
+{
+ if ( (rFamily == FAMILY_DONTKNOW) || (rPitch == PITCH_DONTKNOW) ||
+ (rCharSet == CHARSET_DONTKNOW) )
+ {
+ }
+}
+
+#endif
+
+// =======================================================================
+
+BOOL ImplTestFontName( const XubString& rName,
+ const sal_Char** pMatchList,
+ const sal_Char** pSearchList )
+{
+ const char** pAlias;
+
+ pAlias = pMatchList;
+ while ( *pAlias )
+ {
+ if ( ImplStrFullMatch( rName, *pAlias ) )
+ return TRUE;
+ pAlias++;
+ }
+
+ pAlias = pSearchList;
+ while ( *pAlias )
+ {
+ if ( rName.SearchAscii( *pAlias ) != STRING_NOTFOUND )
+ return TRUE;
+ pAlias++;
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+static void ImplFontAttrFromName( const XubString& rFontName,
+ FontFamily& rFamily, CharSet& rCharSet,
+ FontPitch& rPitch )
+{
+ if ( rFamily == FAMILY_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplRomanMatchList, aImplRomanSearchList ) )
+ rFamily = FAMILY_ROMAN;
+ else if ( ImplTestFontName( rFontName, aImplSwissMatchList, aImplSwissSearchList ) )
+ rFamily = FAMILY_SWISS;
+ else if ( ImplTestFontName( rFontName, aImplScriptMatchList, aImplScriptSearchList ) )
+ rFamily = FAMILY_SCRIPT;
+ }
+
+ if ( rPitch == PITCH_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplFixedMatchList, aImplFixedSearchList ) )
+ rPitch = PITCH_FIXED;
+ }
+
+ if ( rCharSet == RTL_TEXTENCODING_DONTKNOW )
+ {
+ if ( ImplTestFontName( rFontName, aImplSymbolMatchList, aImplSymbolSearchList ) )
+ rCharSet = RTL_TEXTENCODING_SYMBOL;
+ }
+}
+
+// =======================================================================
+
+static const char* aImplStdSwissList[] =
+{
+ "helvetica",
+ "arial",
+ "lucida sans",
+ "lucidasans",
+ "lucida",
+ "geneva",
+ "helmet",
+ NULL
+};
+
+static const char* aImplStdRomanList[] =
+{
+ "times",
+ "times new roman",
+ "timesnewroman",
+ "roman",
+ "lucida serif",
+ "lucidaserif",
+ "lucida bright",
+ "lucidabright",
+ "bookman",
+ "garamond",
+ "timmons",
+ NULL
+};
+
+static const char* aImplStdFixedList[] =
+{
+ "courier",
+ "courier new",
+ "lucida typewriter",
+ "lucidatypewriter",
+ "lucida sans typewriter",
+ "lucidasanstypewriter",
+ NULL
+};
+
+static const char* aImplStdScriptList[] =
+{
+ "zapf chancery",
+ "zapfchancery",
+ "lucida calligraphy",
+ "lucidacalligraphy",
+ "lucida handwriting",
+ "lucidahandwriting",
+ "arioso",
+ "script",
+ "marigold",
+ NULL
+};
+
+static const char* aImplStdSymbolList[] =
+{
+ "starbats",
+ "symbol",
+ "zapf dingbats",
+ "zapfdingbats",
+ "wingdings",
+ "lucida dingbats",
+ "lucidadingbats",
+ "lucida sans dingbats",
+ "lucidasansdingbats",
+ NULL
+};
+
+// =======================================================================
+
+void ImplFreeOutDevFontData()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ while ( pEntry )
+ {
+ ImplFontSubstEntry* pNext = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pNext;
+ }
+}
+
+// =======================================================================
+
+static ImplFontData* ImplFindScript( ImplDevFontListData* pData,
+ rtl_Script eScript )
+{
+ // Testen, ob ein Font mit einem entsprechendem
+ // Script vorhanden ist
+ ImplFontData* pCurFontData = pData->mpFirst;
+ while ( pCurFontData )
+ {
+ // Detect Unicode Font !!!
+ if ( pData->maMatchName.EqualsAscii( "arial unicode ms" ) )
+ return pCurFontData;
+ if ( eScript == pCurFontData->meScript )
+ return pCurFontData;
+ pCurFontData = pCurFontData->mpNext;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+/* !!! UNICODE - Duerfte nicht mehr gebraucht werden !!!
+static rtl_TextEncoding ImplGetFakeEncoding( rtl_TextEncoding eEncoding )
+{
+ rtl_TextEncoding eSystemEncoding = GetSystemCharSet();
+ // MS_1252 und 8859_1 sind kompatible
+ if ( ((eEncoding == RTL_TEXTENCODING_MS_1252) ||
+ (eEncoding == RTL_TEXTENCODING_ISO_8859_1)) &&
+ ((eSystemEncoding == RTL_TEXTENCODING_MS_1252) ||
+ (eSystemEncoding == RTL_TEXTENCODING_ISO_8859_1)) )
+ return eEncoding;
+ else
+ {
+ // Wir testen, ob beide Zeichensaetze dem gleichem Script
+ // entsprechen, um so der Applikation das gleiche Encoding
+ // vorzugaukeln. Dies ist beispielsweise bei Russisch wichtig
+ // da hier Fonts mit unterschiedlichem Encoding auftauchen
+ // koennen.
+ rtl_Script eSrcScript;
+ rtl_Script eSystemScript;
+ rtl_TextEncodingInfo aTEncInfo;
+ aTEncInfo.StructSize = sizeof( aTEncInfo );
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ if ( !rtl_getTextEncodingInfo( eEncoding, &aTEncInfo ) )
+ return eEncoding;
+ else
+ eSrcScript = aTEncInfo.Script;
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ if ( !rtl_getTextEncodingInfo( eSystemEncoding, &aTEncInfo ) )
+ return eEncoding;
+ else
+ eSystemScript = aTEncInfo.Script;
+ if ( eSrcScript == eSystemScript )
+ eEncoding = eSystemEncoding;
+ }
+
+ return eEncoding;
+}
+*/
+
+// =======================================================================
+
+void OutputDevice::BeginFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maGDIData.mbFontSubChanged = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::EndFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maGDIData.mbFontSubChanged )
+ {
+ ImplUpdateAllFontData( FALSE );
+
+ Application* pApp = GetpApp();
+ DataChangedEvent aDCEvt( DATACHANGED_FONTSUBSTITUTION );
+ pApp->DataChanged( aDCEvt );
+ pApp->NotifyAllWindows( aDCEvt );
+ pSVData->maGDIData.mbFontSubChanged = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddFontSubstitute( const XubString& rFontName,
+ const XubString& rReplaceFontName,
+ USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = new ImplFontSubstEntry;
+
+ pEntry->maName = rFontName;
+ pEntry->maReplaceName = rReplaceFontName;
+ pEntry->maMatchName = rFontName;
+ pEntry->maMatchReplaceName = rReplaceFontName;
+ pEntry->mnFlags = nFlags;
+ pEntry->mpNext = pSVData->maGDIData.mpFirstFontSubst;
+ pEntry->maMatchName.ToLowerAscii();
+ pEntry->maMatchReplaceName.ToLowerAscii();
+ ImplCutScriptAndSpaces( pEntry->maMatchName );
+ ImplCutScriptAndSpaces( pEntry->maMatchReplaceName );
+ pSVData->maGDIData.mpFirstFontSubst = pEntry;
+ pSVData->maGDIData.mbFontSubChanged = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::RemoveFontSubstitute( USHORT n )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ ImplFontSubstEntry* pPrev = NULL;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ if ( nCount == n )
+ {
+ pSVData->maGDIData.mbFontSubChanged = TRUE;
+ if ( pPrev )
+ pPrev->mpNext = pEntry->mpNext;
+ else
+ pSVData->maGDIData.mpFirstFontSubst = pEntry->mpNext;
+ delete pEntry;
+ break;
+ }
+
+ nCount++;
+ pPrev = pEntry;
+ pEntry = pEntry->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetFontSubstituteCount()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ nCount++;
+ pEntry = pEntry->mpNext;
+ }
+
+ return nCount;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetFontSubstitute( USHORT n,
+ XubString& rFontName,
+ XubString& rReplaceFontName,
+ USHORT& rFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ USHORT nCount = 0;
+ while ( pEntry )
+ {
+ if ( nCount == n )
+ {
+ rFontName = pEntry->maName;
+ rReplaceFontName = pEntry->maReplaceName;
+ rFlags = pEntry->mnFlags;
+ break;
+ }
+
+ nCount++;
+ pEntry = pEntry->mpNext;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplFontSubstitute( XubString& rFontName,
+ USHORT nFlags1, USHORT nFlags2 )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplFontSubstEntry* pEntry = pSVData->maGDIData.mpFirstFontSubst;
+ while ( pEntry )
+ {
+ if ( ((pEntry->mnFlags & nFlags1) == nFlags2) &&
+ (pEntry->maMatchName == rFontName) )
+ {
+ rFontName = pEntry->maMatchReplaceName;
+ return TRUE;
+ }
+
+ pEntry = pEntry->mpNext;
+ }
+
+ return FALSE;
+}
+
+// =======================================================================
+
+ImplDevFontList::ImplDevFontList() :
+ List( CONTAINER_MAXBLOCKSIZE, 96, 32 )
+{
+#if 0
+ mbIsInitMatchData = FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontList::~ImplDevFontList()
+{
+ // Alle Eintraege loeschen
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ // Liste der Font loeschen
+ ImplFontData* pFontData = pEntry->mpFirst;
+ do
+ {
+ ImplFontData* pTempFontData = pFontData;
+ pFontData = pFontData->mpNext;
+ delete pTempFontData;
+ }
+ while ( pFontData );
+ // Entry loeschen
+ delete pEntry;
+
+ pEntry = Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static StringCompare ImplCompareFontDataWithoutSize( const ImplFontData* pEntry1,
+ const ImplFontData* pEntry2 )
+{
+ // Vergleichen nach CharSet, Groesse, Breite, Weight, Italic, StyleName
+ if ( pEntry1->meCharSet < pEntry2->meCharSet )
+ return COMPARE_LESS;
+ else if ( pEntry1->meCharSet > pEntry2->meCharSet )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meWidthType < pEntry2->meWidthType )
+ return COMPARE_LESS;
+ else if ( pEntry1->meWidthType > pEntry2->meWidthType )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meWeight < pEntry2->meWeight )
+ return COMPARE_LESS;
+ else if ( pEntry1->meWeight > pEntry2->meWeight )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->meItalic < pEntry2->meItalic )
+ return COMPARE_LESS;
+ else if ( pEntry1->meItalic > pEntry2->meItalic )
+ return COMPARE_GREATER;
+
+ return pEntry1->maStyleName.CompareTo( pEntry2->maStyleName );
+}
+
+// -----------------------------------------------------------------------
+
+static StringCompare ImplCompareFontData( const ImplFontData* pEntry1,
+ const ImplFontData* pEntry2 )
+{
+ StringCompare eComp = ImplCompareFontDataWithoutSize( pEntry1, pEntry2 );
+ if ( eComp != COMPARE_EQUAL )
+ return eComp;
+
+ if ( pEntry1->mnHeight < pEntry2->mnHeight )
+ return COMPARE_LESS;
+ else if ( pEntry1->mnHeight > pEntry2->mnHeight )
+ return COMPARE_GREATER;
+
+ if ( pEntry1->mnWidth < pEntry2->mnWidth )
+ return COMPARE_LESS;
+ else if ( pEntry1->mnWidth > pEntry2->mnWidth )
+ return COMPARE_GREATER;
+
+ return COMPARE_EQUAL;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::Add( ImplFontData* pNewData )
+{
+ XubString aSearchName = pNewData->maName;
+ aSearchName.ToLowerAscii();
+
+ // Query Script for FontTest
+ rtl_TextEncodingInfo aTEncInfo;
+ aTEncInfo.StructSize = sizeof( aTEncInfo );
+ aTEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( pNewData->meCharSet, &aTEncInfo );
+ pNewData->meScript = aTEncInfo.Script;
+
+ // Add Font
+ ULONG nIndex;
+ ImplDevFontListData* pFoundData = ImplFind( aSearchName, &nIndex );
+ BOOL bDelete = FALSE;
+
+ if ( !pFoundData )
+ {
+ pFoundData = new ImplDevFontListData;
+ pFoundData->maName = pNewData->maName;
+ pFoundData->maMatchName = aSearchName;
+ pFoundData->maMatchName2 = aSearchName;
+ pFoundData->mpFirst = pNewData;
+#if 0
+ pFoundData->mbScalable = FALSE;
+ ImplStrEraseAllSymbols( pFoundData->maMatchName2 );
+/*
+ pFoundData->meMatchFamily = pNewData->meFamily;
+ pFoundData->meMatchPitch = pNewData->mePitch;
+ CharSet eCharSet = pNewData->meCharSet;
+ ImplFontAttrFromName( pFoundData->maMatchName2, pFoundData->meMatchFamily,
+ eCharSet, pFoundData->meMatchPitch );
+ pFoundData->mbSymbol = eCharSet == RTL_TEXTENCODING_SYMBOL;
+*/
+#else
+ pFoundData->meMatchFamily = pNewData->meFamily;
+ pFoundData->meMatchPitch = pNewData->mePitch;
+ pFoundData->mnMatch = 0;
+ CharSet eCharSet = pNewData->meCharSet;
+ ImplStrEraseAllSymbols( pFoundData->maMatchName2 );
+ ImplFontAttrFromName( pFoundData->maMatchName2, pFoundData->meMatchFamily,
+ eCharSet, pFoundData->meMatchPitch );
+ pFoundData->mbSymbol = eCharSet == RTL_TEXTENCODING_SYMBOL;
+#endif
+
+ pNewData->mpNext = NULL;
+ Insert( pFoundData, nIndex );
+ }
+ else
+ {
+ // Name ersetzen (spart Speicherplatz)
+ pNewData->maName = pFoundData->maName;
+
+ BOOL bInsert = TRUE;
+ ImplFontData* pPrev = NULL;
+ ImplFontData* pTemp = pFoundData->mpFirst;
+ do
+ {
+ StringCompare eComp = ImplCompareFontData( pNewData, pTemp );
+ if ( eComp != COMPARE_GREATER )
+ {
+ // Wenn Font gleich ist, nehmen wir einen Devicefont,
+ // oder ignorieren den Font
+ if ( eComp == COMPARE_EQUAL )
+ {
+ // Wir nehmen den Font mit der besseren Quality,
+ // ansonsten ziehen wir den Device-Font vor
+ if ( (pNewData->mnQuality > pTemp->mnQuality) ||
+ ((pNewData->mnQuality == pTemp->mnQuality) &&
+ (pNewData->mbDevice && !pTemp->mbDevice)) )
+ {
+ pNewData->mpNext = pTemp->mpNext;
+ if ( pPrev )
+ pPrev->mpNext = pNewData;
+ else
+ pFoundData->mpFirst = pNewData;
+ delete pTemp;
+ }
+ else
+ {
+ bDelete = TRUE;
+ delete pNewData;
+ }
+
+ bInsert = FALSE;
+ }
+ break;
+ }
+
+ pPrev = pTemp;
+ pTemp = pTemp->mpNext;
+ }
+ while ( pTemp );
+
+ if ( bInsert )
+ {
+ pNewData->mpNext = pTemp;
+ if ( pPrev )
+ pPrev->mpNext = pNewData;
+ else
+ pFoundData->mpFirst = pNewData;
+ }
+ }
+
+ // Match zusammenzaehlen
+ if ( !bDelete )
+ {
+#if 0
+ if ( (pNewData->meType == TYPE_SCALABLE) && (pNewData->mnHeight == 0) )
+ pFoundData->mbScalable = TRUE;
+#else
+ if ( (pNewData->meType == TYPE_SCALABLE) && (pNewData->mnHeight == 0) )
+ {
+ if ( pNewData->meWidthType == WIDTH_NORMAL )
+ pFoundData->mnMatch += 30;
+ else
+ pFoundData->mnMatch += 3;
+ if ( pNewData->meItalic == ITALIC_NONE )
+ pFoundData->mnMatch += 20;
+ else
+ pFoundData->mnMatch += 2;
+ if ( (pNewData->meWeight == WEIGHT_NORMAL) || (pNewData->meWeight == WEIGHT_MEDIUM) )
+ pFoundData->mnMatch += 10;
+ else
+ pFoundData->mnMatch += 1;
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::ImplFind( const XubString& rFontName, ULONG* pIndex ) const
+{
+ ULONG nCount = Count();
+ if ( !nCount )
+ {
+ if ( pIndex )
+ *pIndex = LIST_APPEND;
+ return NULL;
+ }
+
+ // Fonts in der Liste suchen
+ ImplDevFontListData* pCompareData;
+ ImplDevFontListData* pFoundData = NULL;
+ ULONG nLow = 0;
+ ULONG nHigh = nCount-1;
+ ULONG nMid;
+ StringCompare eCompare;
+
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ pCompareData = Get( nMid );
+ eCompare = rFontName.CompareTo( pCompareData->maMatchName );
+ if ( eCompare == COMPARE_LESS )
+ {
+ if ( !nMid )
+ break;
+ nHigh = nMid-1;
+ }
+ else
+ {
+ if ( eCompare == COMPARE_GREATER )
+ nLow = nMid + 1;
+ else
+ {
+ pFoundData = pCompareData;
+ break;
+ }
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( pIndex )
+ {
+ eCompare = rFontName.CompareTo( pCompareData->maMatchName );
+ if ( eCompare == COMPARE_GREATER )
+ *pIndex = (nMid+1);
+ else
+ *pIndex = nMid;
+ }
+
+ return pFoundData;
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::FindFont( const XubString& rFontName ) const
+{
+ XubString aName = rFontName;
+ aName.ToLowerAscii();
+ ImplCutScriptAndSpaces( aName );
+ return ImplFind( aName );
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData* ImplDevFontList::FindStdFont( const sal_Char** pStdFontNames,
+ rtl_Script eScript ) const
+{
+ // We want a scalable font with a system script
+ ImplDevFontListData* pRasterFoundData = NULL;
+ ImplDevFontListData* pWrongScriptRasterData = NULL;
+ ImplDevFontListData* pWrongScriptData = NULL;
+ while ( *pStdFontNames )
+ {
+ XubString aStdName( *pStdFontNames, RTL_TEXTENCODING_ASCII_US );
+ ImplDevFontListData* pFoundData = ImplFind( aStdName );
+ if ( pFoundData )
+ {
+ if ( (eScript == SCRIPT_SYMBOL) ||
+ ImplFindScript( pFoundData, eScript ) )
+ {
+ if ( pFoundData->mpFirst->meType != TYPE_RASTER )
+ return pFoundData;
+ else if ( !pRasterFoundData )
+ pRasterFoundData = pFoundData;
+ }
+ else
+ {
+ if ( pFoundData->mpFirst->meType != TYPE_RASTER )
+ {
+ if ( !pWrongScriptData )
+ pWrongScriptData = pFoundData;
+ }
+ else
+ {
+ if ( !pWrongScriptRasterData )
+ pWrongScriptRasterData = pFoundData;
+ }
+ }
+ }
+ pStdFontNames++;
+ }
+
+ // Wenn keine passende Schrift, dann die Reihenfolge:
+ // - passender Zeichensatz
+ // - Skalierbar
+ // - eine passende Schrift die nicht skalierbar und den
+ // falschen Zeichensatz hat
+ // - keine
+ if ( pRasterFoundData )
+ return pRasterFoundData;
+ else if ( pWrongScriptData )
+ return pWrongScriptData;
+ else
+ return pWrongScriptRasterData;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::Clear()
+{
+ // Alle Eintraege loeschen
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ // Liste der Font loeschen
+ ImplFontData* pFontData = pEntry->mpFirst;
+ do
+ {
+ ImplFontData* pTempFontData = pFontData;
+ pFontData = pFontData->mpNext;
+ delete pTempFontData;
+ }
+ while ( pFontData );
+ // Entry loeschen
+ delete pEntry;
+
+ pEntry = Next();
+ }
+ List::Clear();
+
+ // Standard-Fonts loeschen
+ for ( USHORT i = 0; i < IMPL_STDFONT_COUNT; i++ )
+ mpStdFontAry[i] = NULL;
+#if 0
+ mbIsInitMatchData = FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#if 0
+void ImplDevFontList::InitMatchData()
+{
+ if ( mbIsInitMatchData )
+ return;
+ mbIsInitMatchData = TRUE;
+/*
+ // Fuer alle Eintraege die Matchdaten ermitteln
+ ImplDevFontListData* pEntry = First();
+ while ( pEntry )
+ {
+ ImplFontData* pFontData = pEntry->mpFirst;
+
+ pEntry = Next();
+ }
+*/
+}
+#endif
+
+// -----------------------------------------------------------------------
+
+void ImplDevFontList::InitStdFonts()
+{
+ rtl_Script eSystemScript;
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ aTextEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( gsl_getSystemTextEncoding(), &aTextEncInfo );
+ eSystemScript = aTextEncInfo.Script;
+
+ mpStdFontAry[IMPL_STDFONT_SWISS] = FindStdFont( aImplStdSwissList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_ROMAN] = FindStdFont( aImplStdRomanList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_FIXED] = FindStdFont( aImplStdFixedList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_SCRIPT] = FindStdFont( aImplStdScriptList, eSystemScript );
+ mpStdFontAry[IMPL_STDFONT_SYMBOL] = FindStdFont( aImplStdSymbolList, SCRIPT_SYMBOL );
+}
+
+// =======================================================================
+
+void ImplGetDevSizeList::Add( long nNewHeight )
+{
+ ULONG n = Count();
+ if ( !n || (nNewHeight > Get( n-1 )) )
+ Insert( (void*)nNewHeight, LIST_APPEND );
+ else
+ {
+ for ( ULONG i=0 ; i < n; i++ )
+ {
+ long nHeight = Get( i );
+
+ if ( nNewHeight <= nHeight )
+ {
+ if ( nNewHeight != nHeight )
+ Insert( (void*)nNewHeight, i );
+ break;
+ }
+ }
+ }
+}
+
+// =======================================================================
+
+ImplFontEntry::~ImplFontEntry()
+{
+ if ( mpWidthAry )
+ delete mpWidthAry;
+
+ if ( mpKernPairs )
+ delete mpKernPairs;
+
+ if ( mpKernInfo )
+ delete mpKernInfo;
+}
+
+// =======================================================================
+
+ImplFontCache::ImplFontCache( BOOL bPrinter )
+{
+ mpFirstEntry = NULL;
+ mnRef0Count = 0;
+ mbPrinter = bPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontCache::~ImplFontCache()
+{
+ // Alle Eintraege loeschen
+ ImplFontEntry* pTemp;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ pTemp = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pTemp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontEntry* ImplFontCache::Get( ImplDevFontList* pFontList,
+ const Font& rFont, const Size& rSize )
+{
+ const XubString& rName = rFont.GetName();
+ const XubString& rStyleName = rFont.GetStyleName();
+ long nWidth = rSize.Width();
+ long nHeight = rSize.Height();
+ FontFamily eFamily = rFont.GetFamily();
+ CharSet eCharSet = rFont.GetCharSet();
+ FontWeight eWeight = rFont.GetWeight();
+ FontItalic eItalic = rFont.GetItalic();
+ FontPitch ePitch = rFont.GetPitch();
+ short nOrientation = (short)(rFont.GetOrientation() % 3600);
+ BOOL bShadow = rFont.IsShadow();
+ BOOL bOutline = rFont.IsOutline();
+
+ // Groesse anpassen
+ if ( nHeight < 0 )
+ nHeight = -nHeight;
+ if ( nWidth < 0 )
+ nWidth = -nWidth;
+
+ // Eintrag suchen
+ ImplFontEntry* pPrevEntry = NULL;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ ImplFontSelectData* pFontSelData = &(pEntry->maFontSelData);
+ if ( (nHeight == pFontSelData->mnHeight) &&
+ (eWeight == pFontSelData->meWeight) &&
+ (eItalic == pFontSelData->meItalic) &&
+ (rName == pFontSelData->maName) &&
+ (rStyleName == pFontSelData->maStyleName) &&
+ (eCharSet == pFontSelData->meCharSet) &&
+ (eFamily == pFontSelData->meFamily) &&
+ (ePitch == pFontSelData->mePitch) &&
+ (nWidth == pFontSelData->mnWidth) &&
+ (nOrientation == pFontSelData->mnOrientation) )
+ {
+ if ( !pEntry->mnRefCount )
+ mnRef0Count--;
+
+ pEntry->mnRefCount++;
+
+ // Entry nach vorne bringen
+ if ( pPrevEntry )
+ {
+ pPrevEntry->mpNext = pEntry->mpNext;
+ pEntry->mpNext = mpFirstEntry;
+ mpFirstEntry = pEntry;
+ }
+
+ return pEntry;
+ }
+
+ pPrevEntry = pEntry;
+ pEntry = pEntry->mpNext;
+ }
+
+ // Wir suchen zuerst ueber den Namen den passenden Font
+ XubString aLowerFontName = rName;
+ XubString aFirstName;
+ XubString aTempName;
+ XubString aTempName2;
+ ImplDevFontListData* pFoundData;
+ ImplDevFontListData* pTempFoundData;
+ xub_StrLen nFirstNameIndex = 0;
+ xub_StrLen nIndex = 0;
+ USHORT nSubstFlags1 = FONT_SUBSTITUTE_ALWAYS;
+ USHORT nSubstFlags2 = FONT_SUBSTITUTE_ALWAYS;
+ rtl_Script eScript = SCRIPT_DONTKNOW;
+ rtl_Script eCharSetScript;
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ aTextEncInfo.Script = SCRIPT_DONTKNOW;
+ rtl_getTextEncodingInfo( eCharSet, &aTextEncInfo );
+ eCharSetScript = aTextEncInfo.Script;
+ if ( mbPrinter )
+ nSubstFlags1 |= FONT_SUBSTITUTE_SCREENONLY;
+ aLowerFontName.ToLowerAscii();
+ pTempFoundData = NULL;
+ do
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( !aFirstName.Len() )
+ {
+ aFirstName = aTempName;
+ nFirstNameIndex = nIndex;
+ }
+ ImplFontSubstitute( aTempName, nSubstFlags1, nSubstFlags2 );
+ pFoundData = pFontList->ImplFind( aTempName );
+ if ( pFoundData )
+ {
+ if ( eCharSetScript != SCRIPT_DONTKNOW )
+ {
+ if ( !pTempFoundData )
+ {
+ aTempName2 = aTempName;
+ pTempFoundData = pFoundData;
+ }
+
+ // Testen, ob ein Font mit einem entsprechendem
+ // Script vorhanden ist
+ if ( ImplFindScript( pFoundData, eCharSetScript ) )
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ else
+ pFoundData = NULL;
+ }
+ else
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ }
+ }
+ while ( nIndex != STRING_NOTFOUND );
+ if ( !pFoundData && pTempFoundData )
+ {
+ pFoundData = pTempFoundData;
+ aLowerFontName = aTempName2;
+ }
+
+ // Danach versuchen wir es nocheinmal unter Beruecksichtigung
+ // der gloablen Fontersetzungstabelle, wobei wir jetzt auch
+ // die Fonts nehmen, die ersetzt werden sollen, wenn sie
+ // nicht vorhanden sind
+ if ( !pFoundData )
+ {
+ nSubstFlags1 &= ~FONT_SUBSTITUTE_ALWAYS;
+ nSubstFlags2 &= ~FONT_SUBSTITUTE_ALWAYS;
+ nIndex = 0;
+ do
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( ImplFontSubstitute( aTempName, nSubstFlags1, nSubstFlags2 ) )
+ {
+ pFoundData = pFontList->ImplFind( aTempName );
+ if ( pFoundData )
+ {
+ aLowerFontName = aTempName;
+ break;
+ }
+ }
+ }
+ while ( nIndex != STRING_NOTFOUND );
+ }
+
+ // Wenn kein Font mit dem entsprechenden Namen existiert, versuchen
+ // wir ueber den Namen und die Attribute einen passenden Font zu
+ // finden
+ ULONG nFontCount = pFontList->Count();
+ if ( !pFoundData && nFontCount )
+ {
+#if 0
+ pFontList->InitMatchData();
+
+ // 1. Token vom Fontnamen nehmen und Sonderzeichen entfernen
+ XubString aNoSymbolName = aFirstName;
+ ImplCutScriptAndSpaces( aNoSymbolName );
+ ImplStrEraseAllSymbols( aNoSymbolName );
+
+ // Script evtl. aus CharSet gewinnen, wenn nicht ueber den Fontnamen
+ // ermittelt werden konnte
+ if ( eScript == SCRIPT_DONTKNOW )
+ eScript = eCharSetScript;
+
+ // wir versuchen zuerst einen Font zu finden, der ueber den Namen
+ // matched
+ ULONG nTestMatch;
+ ULONG nBestMatch = 0;
+ for ( ULONG i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+
+ nTestMatch = 0;
+
+ // Wir wollen schon Zeichen erkennen
+ if ( eScript != SCRIPT_DONTKNOW )
+ {
+ if ( ImplFindScript( pData, eScript ) )
+ nTestMatch += 1000000000;
+ }
+
+ // skalierbare Schriften haben schon einen echten Vorteil
+ // gegenueber nicht skalierbaren Schriften
+ if ( pData->mbScalable )
+ nTestMatch += 500000000;
+
+/*
+ // Wir gehen davon aus, wenn der Name groesstenteils matcht,
+ // das er schon zur richtigen Familie gehoert
+
+
+ // Beim matchen ignorieren wir alle Sonderzeichen
+ ULONG nTestMatch = ImplStrMatch( aNoSymbolName, pData->maMatchName2 );
+ if ( nTestMatch >= nBestMatch )
+ {
+ // Match nur erlaubt, wenn auch die Attribute uebereinstimmen
+ BOOL bTestFamily = pData->meMatchFamily != FAMILY_DONTKNOW;
+ BOOL bTestSymbol = pData->mbSymbol;
+ BOOL bTestFixed = pData->meMatchPitch == PITCH_FIXED;
+ if ( (bFixed == bTestFixed) && (bSymbol == bTestSymbol) &&
+ (!bFamily || !bTestFamily || (eSearchFamily == pData->meMatchFamily)) )
+ {
+ xub_StrLen nAttrMatch = 0;
+ // Die Anzahl der uebereinstimmenden Attribute zaehlen
+ const char** pTypeList = aImplTypeList;
+ while ( *pTypeList )
+ {
+ if ( (aNoSymbolName.Search( *pTypeList ) != STRING_NOTFOUND) &&
+ (pData->maMatchName2.Search( *pTypeList ) != STRING_NOTFOUND) )
+ nAttrMatch++;
+ pTypeList++;
+ }
+
+ // Wenn beide Matches gleich gut sind,
+ // entscheiden die uebereinstimmenden Attribute
+ if ( nBestMatch == nTestMatch )
+ {
+ if ( (nAttrMatch > nBestAttrMatch) ||
+ ((nAttrMatch == nBestAttrMatch) &&
+ (pData->maMatchName2.Len() < nBestStrLen)) )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ else
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ }
+*/
+
+ if ( nTestMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ }
+ }
+
+ if ( !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ // Wenn alles nichts hilft, nehmen wir den ersten
+ if ( !pFoundData )
+ pFontList->Get( 0 );
+ }
+#else
+ // 1. Token vom Fontnamen nehmen und Sonderzeichen entfernen
+ XubString aNoSymbolName = aFirstName;
+ ImplStrEraseAllSymbols( aNoSymbolName );
+
+ // Suchattribute ermitteln
+ BOOL bFamily;
+ BOOL bSymbol;
+ BOOL bFixed;
+ FontFamily eSearchFamily = eFamily;
+ CharSet eSearchCharSet = eCharSet;
+ FontPitch eSearchPitch = ePitch;
+ ImplFontAttrFromName( aNoSymbolName, eSearchFamily, eSearchCharSet, eSearchPitch );
+ bFamily = eSearchFamily != FAMILY_DONTKNOW;
+ bSymbol = eSearchCharSet == RTL_TEXTENCODING_SYMBOL;
+ bFixed = eSearchPitch == PITCH_FIXED;
+ // Solange in der Namesliste suchen, bis wir auswertbare
+ // Attribute gefunden haben
+ xub_StrLen nTempIndex = nFirstNameIndex;
+ while ( (nTempIndex != STRING_NOTFOUND) && !bFamily && !bFixed && !bSymbol )
+ {
+ aTempName = aLowerFontName.GetToken( 0, ';', nTempIndex );
+ ImplCutScriptAndSpaces( aTempName );
+ if ( !aTempName.Len() )
+ break;
+ ImplStrEraseAllSymbols( aTempName );
+ ImplFontAttrFromName( aTempName, eSearchFamily, eSearchCharSet, eSearchPitch );
+ bFamily = eSearchFamily != FAMILY_DONTKNOW;
+ bSymbol = eSearchCharSet == RTL_TEXTENCODING_SYMBOL;
+ bFixed = eSearchPitch == PITCH_FIXED;
+ }
+ aLowerFontName = aFirstName;
+
+ // wir versuchen zuerst einen Font zu finden, der ueber den Namen
+ // matched
+ ULONG i;
+ xub_StrLen nBestMatch = 5;
+ xub_StrLen nBestAttrMatch = 0;
+ xub_StrLen nBestStrLen = 0xFFFF;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ // Beim matchen ignorieren wir alle Sonderzeichen
+ xub_StrLen nTestMatch = ImplStrMatch( aNoSymbolName, pData->maMatchName2 );
+ if ( nTestMatch >= nBestMatch )
+ {
+ // Match nur erlaubt, wenn auch die Attribute uebereinstimmen
+ BOOL bTestFamily = pData->meMatchFamily != FAMILY_DONTKNOW;
+ BOOL bTestSymbol = pData->mbSymbol;
+ BOOL bTestFixed = pData->meMatchPitch == PITCH_FIXED;
+ if ( (bFixed == bTestFixed) && (bSymbol == bTestSymbol) &&
+ (!bFamily || !bTestFamily || (eSearchFamily == pData->meMatchFamily)) )
+ {
+ xub_StrLen nAttrMatch = 0;
+ // Die Anzahl der uebereinstimmenden Attribute zaehlen
+ const char** pTypeList = aImplTypeList;
+ while ( *pTypeList )
+ {
+ if ( (aNoSymbolName.SearchAscii( *pTypeList ) != STRING_NOTFOUND) &&
+ (pData->maMatchName2.SearchAscii( *pTypeList ) != STRING_NOTFOUND) )
+ nAttrMatch++;
+ pTypeList++;
+ }
+
+ // Wenn beide Matches gleich gut sind,
+ // entscheiden die uebereinstimmenden Attribute
+ if ( nBestMatch == nTestMatch )
+ {
+ if ( (nAttrMatch > nBestAttrMatch) ||
+ ((nAttrMatch == nBestAttrMatch) &&
+ (pData->maMatchName2.Len() < nBestStrLen)) )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ else
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestAttrMatch = nAttrMatch;
+ nBestStrLen = pData->maMatchName2.Len();
+ }
+ }
+ }
+ }
+
+ // Wenn wir immer noch keinen passenden Font gefunden haben, versuchen
+ // wir es ueber die Attribute
+ if ( !pFoundData )
+ {
+ if ( bFixed )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_FIXED );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( (pData->meMatchPitch == PITCH_FIXED) &&
+ !pData->mbSymbol &&
+ (pData->meMatchFamily != FAMILY_DECORATIVE) )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bFamily && !pFoundData )
+ {
+ if ( eSearchFamily == FAMILY_SWISS )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SWISS );
+ else if ( eSearchFamily == FAMILY_ROMAN )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ else if ( eSearchFamily == FAMILY_SCRIPT )
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SCRIPT );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( (pData->meMatchFamily == eSearchFamily) &&
+ !pData->mbSymbol &&
+ (pData->meMatchPitch != PITCH_FIXED) )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bSymbol && !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_SYMBOL );
+ if ( !pFoundData )
+ {
+ nBestMatch = 0;
+ for ( i = 0; i < nFontCount; i++ )
+ {
+ ImplDevFontListData* pData = pFontList->Get( i );
+ if ( pData->mbSymbol )
+ {
+ if ( pData->mnMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = pData->mnMatch;
+ }
+ }
+ }
+ }
+ }
+
+ if ( !pFoundData )
+ {
+ pFoundData = pFontList->GetStandardFont( IMPL_STDFONT_ROMAN );
+ // Wenn alles nichts hilft, nehmen wir den ersten
+ if ( !pFoundData )
+ pFontList->Get( 0 );
+ }
+ }
+#endif
+ }
+
+ // Script evtl. aus CharSet gewinnen, wenn nicht ueber den Fontnamen
+ // ermittelt werden konnte
+ if ( eScript == SCRIPT_DONTKNOW )
+ eScript = eCharSetScript;
+
+ // Jetzt suchen wir den Font ueber die Attribute
+ ImplFontData* pFontData = NULL;
+ if ( pFoundData )
+ {
+ ULONG nBestMatch = 0; // Der groessere Wert ist der bessere
+ ULONG nBestHeightMatch = 0; // Der kleinere Wert ist der bessere
+ ULONG nBestWidthMatch = 0; // Der kleinere Wert ist der bessere
+ ULONG nMatch;
+ ULONG nHeightMatch;
+ ULONG nWidthMatch;
+ ImplFontData* pCurFontData;
+
+// !!!!! Wegen Office-Fehler !!!!
+// XubString aCompareStyleName = rStyleName;
+// aCompareStyleName.ToLowerAscii();
+
+ // Vorallem wegen OS2-System-Standard-Fonts vergleichen wir
+ // den FontNamen mit FontName + StyleName, damit
+ // WarpSans Bold auch einen fetten Font ergibt
+ const xub_Unicode* pCompareStyleName = NULL;
+ if ( (aLowerFontName.Len() > pFoundData->maMatchName.Len()) &&
+ aLowerFontName.Equals( pFoundData->maMatchName, 0, pFoundData->maMatchName.Len() ) )
+ pCompareStyleName = aLowerFontName.GetBuffer()+pFoundData->maMatchName.Len()+1;
+
+ pCurFontData = pFoundData->mpFirst;
+ while ( pCurFontData )
+ {
+ nMatch = 0;
+ nHeightMatch = 0;
+ nWidthMatch = 0;
+
+// if ( aCompareStyleName.Len() &&
+// aCompareStyleName.EqualsIgnoreCaseAscii( pCurFontData->maStyleName ) )
+// nMatch += 120000;
+ if ( pCompareStyleName &&
+ pCurFontData->maStyleName.EqualsIgnoreCaseAscii( pCompareStyleName ) )
+ nMatch += 120000;
+
+ if ( eCharSet != RTL_TEXTENCODING_DONTKNOW )
+ {
+ if ( eCharSet == pCurFontData->meCharSet )
+ nMatch += 60000;
+ }
+
+ if ( eScript == pCurFontData->meScript )
+ nMatch += 30000;
+
+ if ( (ePitch != PITCH_DONTKNOW) && (ePitch == pCurFontData->mePitch) )
+ nMatch += 15000;
+
+ if ( (eFamily != FAMILY_DONTKNOW) && (eFamily == pCurFontData->meFamily) )
+ nMatch += 7500;
+
+ // Normale Schriftbreiten bevorzugen, da wir noch keine Daten
+ // von den Applikationen bekommen
+ if ( pCurFontData->meWidthType == WIDTH_NORMAL )
+ nMatch += 3750;
+
+ if ( eWeight != WEIGHT_DONTKNOW )
+ {
+ USHORT nReqWeight;
+ USHORT nGivenWeight;
+ USHORT nWeightDiff;
+ // schmale Fonts werden bei nicht Bold vor fetten
+ // Fonts bevorzugt
+ if ( eWeight > WEIGHT_MEDIUM )
+ nReqWeight = ((USHORT)eWeight)+100;
+ else
+ nReqWeight = (USHORT)eWeight;
+ if ( pCurFontData->meWeight > WEIGHT_MEDIUM )
+ nGivenWeight = ((USHORT)pCurFontData->meWeight)+100;
+ else
+ nGivenWeight = (USHORT)pCurFontData->meWeight;
+ if ( nReqWeight > nGivenWeight )
+ nWeightDiff = nReqWeight-nGivenWeight;
+ else
+ nWeightDiff = nGivenWeight-nReqWeight;
+
+ if ( nWeightDiff == 0 )
+ nMatch += 1000;
+ else if ( nWeightDiff == 1 )
+ nMatch += 700;
+ else if ( nWeightDiff < 50 )
+ nMatch += 200;
+ }
+ if ( eItalic == ITALIC_NONE )
+ {
+ if ( pCurFontData->meItalic == ITALIC_NONE )
+ nMatch += 900;
+ }
+ else
+ {
+ if ( eItalic == pCurFontData->meItalic )
+ nMatch += 900;
+ else if ( pCurFontData->meItalic != ITALIC_NONE )
+ nMatch += 600;
+ }
+
+ if ( pCurFontData->mbDevice )
+ nMatch += 40;
+ if ( pCurFontData->meType == TYPE_SCALABLE )
+ {
+ if ( nOrientation )
+ nMatch += 80;
+ else
+ {
+ if ( nWidth )
+ nMatch += 25;
+ else
+ nMatch += 5;
+ }
+ }
+ else
+ {
+ if ( nHeight == pCurFontData->mnHeight )
+ {
+ nMatch += 20;
+ if ( nWidth == pCurFontData->mnWidth )
+ nMatch += 10;
+ }
+ else
+ {
+ // Dann kommt die Size-Abweichung in die
+ // Bewertung rein. Hier bevorzugen wir
+ // nach Moeglichkeit den kleineren Font
+ if ( nHeight < pCurFontData->mnHeight )
+ nHeightMatch += pCurFontData->mnHeight-nHeight;
+ else
+ nHeightMatch += (nHeight-pCurFontData->mnHeight-nHeight)+10000;
+ if ( nWidth && pCurFontData->mnWidth && (nWidth != pCurFontData->mnWidth) )
+ {
+ if ( nWidth < pCurFontData->mnWidth )
+ nWidthMatch += pCurFontData->mnWidth-nWidth;
+ else
+ nWidthMatch += nWidth-pCurFontData->mnWidth-nWidth;
+ }
+ }
+ }
+
+ if ( nMatch > nBestMatch )
+ {
+ pFontData = pCurFontData;
+ nBestMatch = nMatch;
+ nBestHeightMatch = nHeightMatch;
+ nBestWidthMatch = nWidthMatch;
+ }
+ else if ( nMatch == nBestMatch )
+ {
+ // Wenn 2 gleichwertig sind, kommt die Size-Bewertung
+ // Hier gewinnt der jenige, der die niedrigere Abweichung
+ // in der Groesse hat (also den kleinsten Match)
+ if ( nHeightMatch < nBestHeightMatch )
+ {
+ pFontData = pCurFontData;
+ nBestHeightMatch = nHeightMatch;
+ nBestWidthMatch = nWidthMatch;
+ }
+ else if ( nHeightMatch == nBestHeightMatch )
+ {
+ if ( nWidthMatch < nBestWidthMatch )
+ {
+ pFontData = pCurFontData;
+ nBestWidthMatch = nWidthMatch;
+ }
+ }
+ }
+
+ pCurFontData = pCurFontData->mpNext;
+ }
+ }
+
+ // Daten initialisieren und in die Liste aufnehmen
+ pEntry = new ImplFontEntry;
+ pEntry->mbInit = FALSE;
+ pEntry->mnRefCount = 1;
+ pEntry->mpNext = mpFirstEntry;
+ pEntry->mnWidthAryCount = 0;
+ pEntry->mnWidthArySize = 0;
+ pEntry->mpWidthAry = NULL;
+ pEntry->mpKernPairs = NULL;
+ pEntry->mpKernInfo = NULL;
+ pEntry->mnOwnOrientation = 0;
+ pEntry->mnOrientation = 0;
+ mpFirstEntry = pEntry;
+
+ // Font-Selection-Daten setzen
+ ImplFontSelectData* pFontSelData = &(pEntry->maFontSelData);
+ pFontSelData->mpFontData = pFontData;
+ pFontSelData->mpSysSelData = NULL;
+ pFontSelData->maName = rName;
+ pFontSelData->maStyleName = rStyleName;
+ pFontSelData->mnWidth = nWidth;
+ pFontSelData->mnHeight = nHeight;
+ pFontSelData->meFamily = eFamily;
+ pFontSelData->meCharSet = eCharSet;
+ pFontSelData->meWidthType = WIDTH_DONTKNOW;
+ pFontSelData->meWeight = eWeight;
+ pFontSelData->meItalic = eItalic;
+ pFontSelData->mePitch = ePitch;
+ pFontSelData->mnOrientation = nOrientation;
+
+ return pEntry;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFontCache::Release( ImplFontEntry* pEntry )
+{
+ pEntry->mnRefCount--;
+
+ if ( !pEntry->mnRefCount )
+ {
+ if ( mnRef0Count >= MAXFONT_CACHE )
+ {
+ // Letzten Entry mit RefCount 0 loeschen
+ ImplFontEntry* pPrevDelEntry = mpFirstEntry;
+ ImplFontEntry* pDelEntry = pPrevDelEntry->mpNext;
+ USHORT nCurRef0Count = !(pPrevDelEntry->mnRefCount);
+ while ( pDelEntry )
+ {
+ if ( !pDelEntry->mnRefCount )
+ nCurRef0Count++;
+
+ if ( nCurRef0Count >= MAXFONT_CACHE )
+ {
+ pPrevDelEntry->mpNext = pDelEntry->mpNext;
+ delete pDelEntry;
+ break;
+ }
+
+ pPrevDelEntry = pDelEntry;
+ pDelEntry = pDelEntry->mpNext;
+ }
+ }
+ else
+ mnRef0Count++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplFontCache::Clear()
+{
+ // Alle Eintraege loeschen
+ ImplFontEntry* pTemp;
+ ImplFontEntry* pEntry = mpFirstEntry;
+ while ( pEntry )
+ {
+ DBG_ASSERT( !pEntry->mnRefCount, "ImplFontCache::Clear() - Font in use" );
+ pTemp = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pTemp;
+ }
+
+ mpFirstEntry = NULL;
+ mnRef0Count = 0;
+}
+
+// =======================================================================
+
+class ImplTextLineInfo
+{
+private:
+ long mnWidth;
+ xub_StrLen mnIndex;
+ xub_StrLen mnLen;
+
+public:
+ ImplTextLineInfo( long nWidth, xub_StrLen nIndex, xub_StrLen nLen )
+ {
+ mnWidth = nWidth;
+ mnIndex = nIndex;
+ mnLen = nLen;
+ }
+
+ long GetWidth() const { return mnWidth; }
+ xub_StrLen GetIndex() const { return mnIndex; }
+ xub_StrLen GetLen() const { return mnLen; }
+};
+
+#define MULTITEXTLINEINFO_RESIZE 16
+typedef ImplTextLineInfo* PImplTextLineInfo;
+
+class ImplMultiTextLineInfo
+{
+private:
+ PImplTextLineInfo* mpLines;
+ xub_StrLen mnLines;
+ xub_StrLen mnSize;
+
+public:
+ ImplMultiTextLineInfo();
+ ~ImplMultiTextLineInfo();
+
+ void AddLine( ImplTextLineInfo* pLine );
+ void Clear();
+
+ ImplTextLineInfo* GetLine( USHORT nLine ) const
+ { return mpLines[nLine]; }
+ xub_StrLen Count() const { return mnLines; }
+
+private:
+ ImplMultiTextLineInfo( const ImplMultiTextLineInfo& );
+ ImplMultiTextLineInfo& operator=( const ImplMultiTextLineInfo& );
+};
+
+ImplMultiTextLineInfo::ImplMultiTextLineInfo()
+{
+ mpLines = new PImplTextLineInfo[MULTITEXTLINEINFO_RESIZE];
+ mnLines = 0;
+ mnSize = MULTITEXTLINEINFO_RESIZE;
+}
+
+ImplMultiTextLineInfo::~ImplMultiTextLineInfo()
+{
+ for ( xub_StrLen i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ delete mpLines;
+}
+
+void ImplMultiTextLineInfo::AddLine( ImplTextLineInfo* pLine )
+{
+ if ( mnSize == mnLines )
+ {
+ mnSize += MULTITEXTLINEINFO_RESIZE;
+ PImplTextLineInfo* pNewLines = new PImplTextLineInfo[mnSize];
+ memcpy( pNewLines, mpLines, mnLines*sizeof(PImplTextLineInfo) );
+ mpLines = pNewLines;
+ }
+
+ mpLines[mnLines] = pLine;
+ mnLines++;
+}
+
+void ImplMultiTextLineInfo::Clear()
+{
+ for ( xub_StrLen i = 0; i < mnLines; i++ )
+ delete mpLines[i];
+ mnLines = 0;
+}
+
+// =======================================================================
+
+void OutputDevice::ImplInitFont()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mbInitFont )
+ {
+#ifndef REMOTE_APPSERVER
+ mpFontEntry->mnSetFontFlags = mpGraphics->SetFont( &(mpFontEntry->maFontSelData) );
+ mbInitFont = FALSE;
+#else
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ RemoteFont aFont;
+
+ if ( pFontEntry->maFontSelData.mpFontData )
+ {
+ aFont.maName = pFontEntry->maFontSelData.mpFontData->maName;
+ aFont.maStyleName = pFontEntry->maFontSelData.mpFontData->maStyleName;
+ }
+ else
+ {
+ aFont.maName = pFontEntry->maFontSelData.maName;
+ aFont.maStyleName = pFontEntry->maFontSelData.maStyleName;
+ }
+ aFont.mnWidth = pFontEntry->maFontSelData.mnWidth;
+ aFont.mnHeight = pFontEntry->maFontSelData.mnHeight;
+ aFont.meFamily = pFontEntry->maFontSelData.meFamily;
+ aFont.meCharSet = pFontEntry->maFontSelData.meCharSet;
+ aFont.meWidthType = pFontEntry->maFontSelData.meWidthType;
+ aFont.meWeight = pFontEntry->maFontSelData.meWeight;
+ aFont.meItalic = pFontEntry->maFontSelData.meItalic;
+ aFont.mePitch = pFontEntry->maFontSelData.mePitch;
+ aFont.mnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ mpGraphics->SetFont( aFont );
+ pFontEntry->mnSetFontFlags = 0;
+ mbInitFont = FALSE;
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitTextColor()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( mbInitTextColor )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetTextColor( ImplColorToSal( GetTextColor() ) );
+#else
+ mpGraphics->SetTextColor( GetTextColor() );
+#endif
+ mbInitTextColor = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int OutputDevice::ImplNewFont()
+{
+ DBG_TESTSOLARMUTEX();
+
+ if ( !mbNewFont )
+ return TRUE;
+
+ mbNewFont = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return FALSE;
+ }
+ SalGraphics* pGraphics = mpGraphics;
+#else
+ // Da wegen Clipping hier NULL zurueckkommen kann, koennen wir nicht
+ // den Rueckgabewert nehmen
+ ImplGetServerGraphics();
+ ImplServerGraphics* pGraphics = mpGraphics;
+#endif
+
+ // Groesse umrechnen
+ Size aSize = ImplLogicToDevicePixel( maFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // Nur dann Defaultgroesse setzen, wenn Fonthoehe auch in logischen
+ // Koordinaaten 0 ist
+ if ( maFont.GetSize().Height() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*mnDPIY)/72;
+ }
+
+ // Neuen Font besorgen
+ ImplFontEntry* pOldEntry = mpFontEntry;
+ mpFontEntry = mpFontCache->Get( mpFontList, maFont, aSize );
+ ImplFontEntry* pFontEntry = mpFontEntry;
+
+ // Feststellen, ob Font neu selektiert werden muss
+ if ( pFontEntry != pOldEntry )
+ mbInitFont = TRUE;
+
+ // these two may be filled in remote version
+ ImplKernPairData* pKernPairs = NULL;
+ long nKernPairs = 0;
+ // Wenn Font nicht initialisiert ist, dann sofort selektieren
+ if ( !pFontEntry->mbInit )
+ {
+ ImplInitFont();
+
+ // und die Font-Daten besorgen
+ if ( pGraphics )
+ {
+ pFontEntry->mbInit = TRUE;
+
+ pFontEntry->maMetric.mnWidth = pFontEntry->maFontSelData.mnWidth;
+ pFontEntry->maMetric.meFamily = pFontEntry->maFontSelData.meFamily;
+ pFontEntry->maMetric.meCharSet = pFontEntry->maFontSelData.meCharSet;
+ pFontEntry->maMetric.meWeight = pFontEntry->maFontSelData.meWeight;
+ pFontEntry->maMetric.meItalic = pFontEntry->maFontSelData.meItalic;
+ pFontEntry->maMetric.mePitch = pFontEntry->maFontSelData.mePitch;
+ pFontEntry->maMetric.mnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ if ( pFontEntry->maFontSelData.mpFontData )
+ {
+ pFontEntry->maMetric.meType = pFontEntry->maFontSelData.mpFontData->meType;
+ pFontEntry->maMetric.maName = pFontEntry->maFontSelData.mpFontData->maName;
+ pFontEntry->maMetric.maStyleName= pFontEntry->maFontSelData.mpFontData->maStyleName;
+ pFontEntry->maMetric.mbDevice = pFontEntry->maFontSelData.mpFontData->mbDevice;
+ }
+ else
+ {
+ pFontEntry->maMetric.meType = TYPE_DONTKNOW;
+ pFontEntry->maMetric.maName = pFontEntry->maFontSelData.maName.GetToken( 0 );
+ pFontEntry->maMetric.maStyleName= pFontEntry->maFontSelData.maStyleName;
+ pFontEntry->maMetric.mbDevice = FALSE;
+ }
+ pFontEntry->maMetric.mnSuperscriptSize = 0;
+ pFontEntry->maMetric.mnSuperscriptOffset = 0;
+ pFontEntry->maMetric.mnSubscriptSize = 0;
+ pFontEntry->maMetric.mnSubscriptOffset = 0;
+ pFontEntry->maMetric.mnUnderlineSize = 0;
+ pFontEntry->maMetric.mnUnderlineOffset = 0;
+ pFontEntry->maMetric.mnBUnderlineSize = 0;
+ pFontEntry->maMetric.mnBUnderlineOffset = 0;
+ pFontEntry->maMetric.mnDUnderlineSize = 0;
+ pFontEntry->maMetric.mnDUnderlineOffset1 = 0;
+ pFontEntry->maMetric.mnDUnderlineOffset2 = 0;
+ pFontEntry->maMetric.mnWUnderlineSize = 0;
+ pFontEntry->maMetric.mnWUnderlineOffset = 0;
+ pFontEntry->maMetric.mnStrikeoutSize = 0;
+ pFontEntry->maMetric.mnStrikeoutOffset = 0;
+ pFontEntry->maMetric.mnBStrikeoutSize = 0;
+ pFontEntry->maMetric.mnBStrikeoutOffset = 0;
+ pFontEntry->maMetric.mnDStrikeoutSize = 0;
+ pFontEntry->maMetric.mnDStrikeoutOffset1 = 0;
+ pFontEntry->maMetric.mnDStrikeoutOffset2 = 0;
+#ifndef REMOTE_APPSERVER
+ pGraphics->GetFontMetric( &(pFontEntry->maMetric) );
+ pFontEntry->mnWidthFactor = pGraphics->GetCharWidth( 0, CHARCACHE_STD-1, pFontEntry->maWidthAry );
+#else
+ long nFactor = 0;
+
+ pGraphics->GetFontMetric(
+ pFontEntry->maMetric,
+ nFactor, 0, CHARCACHE_STD-1, pFontEntry->maWidthAry,
+ maFont.IsKerning(), &pKernPairs, nKernPairs
+ );
+ pFontEntry->mnWidthFactor = nFactor;
+#endif
+ if ( !pFontEntry->mnWidthFactor )
+ {
+ memset( pFontEntry->maWidthAry, 0, sizeof(long)*(CHARCACHE_STD-1) );
+ pFontEntry->mnWidthFactor = 1;
+ }
+
+ pFontEntry->mbFixedFont = pFontEntry->maMetric.mePitch == PITCH_FIXED;
+ pFontEntry->mnLineHeight = pFontEntry->maMetric.mnAscent+pFontEntry->maMetric.mnDescent;
+ pFontEntry->mbInitKernPairs = FALSE;
+ pFontEntry->mnKernPairs = nKernPairs;
+
+ if ( pFontEntry->maFontSelData.mnOrientation && !pFontEntry->maMetric.mnOrientation &&
+ (meOutDevType != OUTDEV_PRINTER) )
+ {
+ pFontEntry->mnOwnOrientation = pFontEntry->maFontSelData.mnOrientation;
+ pFontEntry->mnOrientation = pFontEntry->mnOwnOrientation;
+ }
+ else
+ pFontEntry->mnOrientation = pFontEntry->maMetric.mnOrientation;
+ }
+ }
+
+ // Wenn Kerning gewuenscht ist, die Kerning-Werte ermitteln
+ if ( maFont.IsKerning() )
+ {
+ ImplInitKerningPairs( pKernPairs, nKernPairs );
+ mbKerning = (pFontEntry->mnKernPairs) != 0;
+ }
+ else
+ mbKerning = FALSE;
+
+ // Je nach TextAlign den TextOffset berechnen
+ TextAlign eAlign = maFont.GetAlign();
+ if ( eAlign == ALIGN_BASELINE )
+ {
+ mnTextOffX = 0;
+ mnTextOffY = 0;
+ }
+ else if ( eAlign == ALIGN_TOP )
+ {
+ long nOrientation = pFontEntry->mnOrientation;
+ if ( nOrientation )
+ {
+ double nRad = ((double)nOrientation * F_2PI) / 3600.0;
+ long nOff = pFontEntry->maMetric.mnAscent;
+ mnTextOffX = (long)(nOff * sin( nRad ));
+ mnTextOffY = (long)(nOff * cos( nRad ));
+ }
+ else
+ {
+ mnTextOffX = 0;
+ mnTextOffY = pFontEntry->maMetric.mnAscent;
+ }
+ }
+ else // eAlign == ALIGN_BOTTOM
+ {
+ long nOrientation = pFontEntry->mnOrientation;
+ if ( nOrientation )
+ {
+ double nRad = ((double)nOrientation * F_2PI) / 3600.0;
+ long nOff = pFontEntry->maMetric.mnDescent;
+ mnTextOffX = (long)(nOff - (nOff * sin( nRad )));
+ nOff = -nOff;
+ mnTextOffY = (long)(nOff * cos( nRad ));
+ }
+ else
+ {
+ mnTextOffX = 0;
+ mnTextOffY = -pFontEntry->maMetric.mnDescent;
+ }
+ }
+
+ mbTextLines = ((maFont.GetUnderline() != UNDERLINE_NONE) && (maFont.GetUnderline() != UNDERLINE_DONTKNOW)) ||
+ ((maFont.GetStrikeout() != STRIKEOUT_NONE) && (maFont.GetStrikeout() != STRIKEOUT_DONTKNOW));
+ mbTextSpecial = maFont.IsShadow() || maFont.IsOutline();
+
+ if ( pOldEntry )
+ mpFontCache->Release( pOldEntry );
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetCharWidth( sal_Unicode c ) const
+{
+ USHORT nChar = (USHORT)c;
+ if ( nChar < CHARCACHE_STD )
+ return mpFontEntry->maWidthAry[nChar];
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ ImplWidthInfoData* pInfo;
+ ImplWidthInfoData* pWidthAry = pFontEntry->mpWidthAry;
+ USHORT nWidthCount = pFontEntry->mnWidthAryCount;
+ USHORT nInsIndex;
+
+ if ( nWidthCount )
+ {
+ USHORT nLow;
+ USHORT nHigh;
+ USHORT nMid;
+ USHORT nCompareChar;
+
+ nLow = 0;
+ nHigh = nWidthCount-1;
+ do
+ {
+ nMid = (nLow+nHigh)/2;
+ pInfo = pWidthAry+nMid;
+ nCompareChar = pInfo->mnChar;
+ if ( nChar < nCompareChar )
+ {
+ if ( !nMid )
+ break;
+ nHigh = nMid-1;
+ }
+ else
+ {
+ if ( nChar > nCompareChar )
+ nLow = nMid+1;
+ else
+ return pInfo->mnWidth;
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( nChar > nCompareChar )
+ nInsIndex = nMid+1;
+ else
+ nInsIndex = nMid;
+ }
+ else
+ {
+ pFontEntry->mnWidthArySize = WIDTHARY_INIT;
+ pFontEntry->mpWidthAry = new ImplWidthInfoData[pFontEntry->mnWidthArySize];
+ pWidthAry = pFontEntry->mpWidthAry;
+ nInsIndex = 0;
+ }
+
+ if ( nWidthCount == pFontEntry->mnWidthArySize )
+ {
+ USHORT nOldSize = pFontEntry->mnWidthArySize;
+ pFontEntry->mnWidthArySize += WIDTHARY_RESIZE;
+ pFontEntry->mpWidthAry = new ImplWidthInfoData[pFontEntry->mnWidthArySize];
+ memcpy( pFontEntry->mpWidthAry, pWidthAry, nOldSize*sizeof(ImplWidthInfoData) );
+ delete pWidthAry;
+ pWidthAry = pFontEntry->mpWidthAry;
+ }
+
+ // Um die Zeichenbreite zu ermitteln, brauchen wir einen Graphics und der
+ // Font muss natuerlich auch selektiert sein
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !((OutputDevice*)this)->ImplGetGraphics() )
+ return 0;
+ }
+#else
+ // Da wegen Clipping hier NULL zurueckkommen kann, koennen wir nicht
+ // den Rueckgabewert nehmen
+ ((OutputDevice*)this)->ImplGetServerGraphics();
+#endif
+
+ if ( mbNewFont )
+ ((OutputDevice*)this)->ImplNewFont();
+ if ( mbInitFont )
+ ((OutputDevice*)this)->ImplInitFont();
+
+ long nWidth;
+#ifndef REMOTE_APPSERVER
+ long nWidthFactor = mpGraphics->GetCharWidth( nChar, nChar, &nWidth );
+#else
+ long nWidthFactor = pFontEntry->mnWidthFactor;
+ mpGraphics->GetCharWidth( nChar, nChar, &nWidth );
+#endif
+ if ( !nWidthFactor )
+ return 0;
+
+ DBG_ASSERT( (nWidthFactor == pFontEntry->mnWidthFactor),
+ "OutputDevice::ImplGetCharWidth() - other WidthFactor" );
+
+ // Breite in Liste einfuegen und zurueckgeben
+ pInfo = pWidthAry+nInsIndex;
+ memmove( pInfo+1, pInfo, (nWidthCount-nInsIndex)*sizeof(ImplWidthInfoData) );
+ pFontEntry->mnWidthAryCount++;
+ pInfo->mnChar = nChar;
+ pInfo->mnWidth = nWidth;
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitKerningPairs( ImplKernPairData* pKernPairs, long nKernPairs )
+{
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ if ( !pFontEntry->mbInitKernPairs )
+ {
+ if ( mbInitFont )
+ ImplInitFont();
+ pFontEntry->mbInitKernPairs = TRUE;
+#ifndef REMOTE_APPSERVER
+ pFontEntry->mnKernPairs = mpGraphics->GetKernPairs( 0, NULL );
+ if ( pFontEntry->mnKernPairs )
+ {
+ ImplKernInfoData* pKernInfo = new ImplKernInfoData;
+ pKernPairs = new ImplKernPairData[pFontEntry->mnKernPairs];
+ memset( pKernPairs, 0, sizeof(ImplKernPairData)*pFontEntry->mnKernPairs );
+ pFontEntry->mnKernPairs = mpGraphics->GetKernPairs( pFontEntry->mnKernPairs, pKernPairs );
+ pFontEntry->mpKernInfo = pKernInfo;
+ pFontEntry->mpKernPairs = pKernPairs;
+
+ // Wir akzeptieren erstmal nur max. 65535-Paare
+ USHORT nMaxKernPairs;
+ if ( pFontEntry->mnKernPairs > 0xFFFF )
+ nMaxKernPairs = 0xFFFF;
+ else
+ nMaxKernPairs = (USHORT)pFontEntry->mnKernPairs;
+ memset( pKernInfo->maFirstAry, 0xFF, sizeof( pKernInfo->maFirstAry ) );
+ memset( pKernInfo->maLastAry, 0, sizeof( pKernInfo->maLastAry ) );
+ for ( USHORT i = 0; i < nMaxKernPairs; i++ )
+ {
+ USHORT nFirst = pKernPairs[i].mnChar1;
+ if ( nFirst < 0xFF )
+ {
+ if ( i < pKernInfo->maFirstAry[nFirst] )
+ pKernInfo->maFirstAry[nFirst] = i;
+ pKernInfo->maLastAry[nFirst] = i;
+ }
+ }
+ }
+#else
+ // Wir arbeiten erstmal nur mit USHORT
+ if( ! pKernPairs )
+ nKernPairs = mpGraphics->GetKernPairs( &pKernPairs );
+ if ( nKernPairs )
+ {
+ ImplKernInfoData* pKernInfo = new ImplKernInfoData;
+ pFontEntry->mpKernInfo = pKernInfo;
+ pFontEntry->mpKernPairs = pKernPairs;
+
+ // Wir akzeptieren erstmal nur max. 65535-Paare
+ USHORT nMaxKernPairs;
+ if( ! pFontEntry->mnKernPairs )
+ pFontEntry->mnKernPairs = nKernPairs;
+ if ( pFontEntry->mnKernPairs > 0xFFFF )
+ nMaxKernPairs = 0xFFFF;
+ else
+ nMaxKernPairs = (USHORT)pFontEntry->mnKernPairs;
+ memset( pKernInfo->maFirstAry, 0xFF, sizeof( pKernInfo->maFirstAry ) );
+ memset( pKernInfo->maLastAry, 0, sizeof( pKernInfo->maLastAry ) );
+ for ( USHORT i = 0; i < nMaxKernPairs; i++ )
+ {
+ USHORT nFirst = pKernPairs[i].mnChar1;
+ if ( nFirst < 0xFF )
+ {
+ if ( i < pKernInfo->maFirstAry[nFirst] )
+ pKernInfo->maFirstAry[nFirst] = i;
+ pKernInfo->maLastAry[nFirst] = i;
+ }
+ }
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplCalcKerning( const sal_Unicode* pStr, xub_StrLen nLen,
+ long* pDXAry, xub_StrLen nAryLen ) const
+{
+ if ( !nLen )
+ return 0;
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplKernPairData* pKernPairs = pEntry->mpKernPairs;
+ ImplKernInfoData* pKernInfo = pEntry->mpKernInfo;
+ long nWidth = 0;
+
+#ifdef DBG_UTIL
+ {
+ ImplKernPairData aTestPair;
+#ifdef __LITTLEENDIAN
+ ULONG nTestComp = ((ULONG)((USHORT)0xAABB) << 16) | (USHORT)0xCCDD;
+#else
+ ULONG nTestComp = ((ULONG)((USHORT)0xCCDD) << 16) | (USHORT)0xAABB;
+#endif
+ aTestPair.mnChar1 = 0xCCDD;
+ aTestPair.mnChar2 = 0xAABB;
+ DBG_ASSERT( nTestComp == *((ULONG*)&aTestPair), "Code doesn't work in this Version" );
+ }
+#endif
+
+ for ( USHORT i = 0; i < nLen-1; i++ )
+ {
+ USHORT nIndex = (USHORT)(unsigned char)pStr[i];
+ USHORT nFirst = pKernInfo->maFirstAry[nIndex];
+ USHORT nLast = pKernInfo->maLastAry[nIndex];
+#ifdef __LITTLEENDIAN
+ ULONG nComp = ((ULONG)((USHORT)(unsigned char)pStr[i+1]) << 16) | nIndex;
+#else
+ ULONG nComp = ((ULONG)nIndex << 16) | ((USHORT)(unsigned char)pStr[i+1]);
+#endif
+ for ( USHORT j = nFirst; j <= nLast; j++ )
+ {
+ if ( nComp == *((ULONG*)&(pKernPairs[j])) )
+ {
+ long nAmount = pKernPairs[j].mnKern;
+ nWidth += nAmount;
+ if ( pDXAry )
+ {
+ for ( USHORT n = i; n < nAryLen; n++ )
+ pDXAry[n] += nAmount;
+ }
+ }
+ }
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetTextWidth( const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDX )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nWidth = 0;
+
+ if ( nLen )
+ {
+ if ( pDX )
+ {
+ if ( nLen > 1 )
+ nWidth += pDX[nLen-2];
+ nWidth += ImplGetCharWidth( pStr[nLen-1] ) / nFactor;
+ }
+ else
+ {
+ // Bei Fixed-Fonts reicht eine Multiplikation
+ if ( pFontEntry->mbFixedFont )
+ nWidth = ImplGetCharWidth( 'A' ) * nLen;
+ else
+ {
+ const sal_Unicode* pTempStr = pStr;
+ xub_StrLen nTempLen = nLen;
+ while ( nTempLen )
+ {
+ nWidth += ImplGetCharWidth( *pTempStr );
+ nTempLen--;
+ pTempStr++;
+ }
+ }
+ nWidth /= nFactor;
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nWidth += ImplCalcKerning( pStr, nLen, NULL, 0 );
+ }
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplRotatePos( long nOriginX, long nOriginY, long& rX, long& rY,
+ short nOrientation )
+{
+ double nRealOrientation = nOrientation*F_PI1800;
+ double nCos = cos( nRealOrientation );
+ double nSin = sin( nRealOrientation );
+
+ // Translation...
+ long nX = rX-nOriginX;
+ long nY = rY-nOriginY;
+
+ // Rotation...
+ rX = ((long) ( nCos*nX + nSin*nY )) + nOriginX;
+ rY = ((long) - ( nSin*nX - nCos*nY )) + nOriginY;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextRect( long nBaseX, long nBaseY,
+ long nX, long nY, long nWidth, long nHeight )
+{
+ if ( mpFontEntry->mnOrientation )
+ {
+ if ( !(mpFontEntry->mnOrientation % 900) )
+ {
+ long nX2 = nX+nWidth;
+ long nY2 = nY+nHeight;
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nX2, nY2, mpFontEntry->mnOrientation );
+ nWidth = nX2-nX;
+ nHeight = nY2-nY;
+ }
+ else
+ {
+ // Da Polygone kleiner gezeichnet werden
+ nHeight++;
+ nWidth++;
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Polygon aPoly( aRect );
+ aPoly.Rotate( Point( nBaseX, nBaseY ), mpFontEntry->mnOrientation );
+#ifndef REMOTE_APPSERVER
+ ImplDrawPolygon( aPoly );
+#else
+ mpGraphics->DrawPolygon( aPoly );
+#endif
+ return;
+ }
+ }
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawRect( nX, nY, nWidth, nHeight );
+#else
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ mpGraphics->DrawRect( aRect );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextBackground( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( GetTextFillColor() ) );
+ mbInitFillColor = TRUE;
+
+ ImplDrawTextRect( nX, nY, nX, nY-mpFontEntry->maMetric.mnAscent,
+ ImplGetTextWidth( pStr, nLen, pDXAry ),
+ mpFontEntry->mnLineHeight );
+#else
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( GetTextFillColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ ImplDrawTextRect( nX, nY, nX, nY-mpFontEntry->maMetric.mnAscent,
+ ImplGetTextWidth( pStr, nLen, pDXAry ),
+ mpFontEntry->mnLineHeight );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplGetTextBoundRect( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ if( !nLen )
+ return Rectangle();
+
+ if ( mbNewFont )
+ ImplNewFont();
+
+ if ( mbInitFont )
+ ImplInitFont();
+
+ long nBaseX = nX, nBaseY = nY;
+ long nWidth = ImplGetTextWidth( pStr, nLen, pDXAry ), nHeight = mpFontEntry->mnLineHeight;
+
+ nY -= mpFontEntry->maMetric.mnAscent;
+
+ if ( mpFontEntry->mnOrientation )
+ {
+ if ( !(mpFontEntry->mnOrientation % 900) )
+ {
+ long nX2 = nX+nWidth;
+ long nY2 = nY+nHeight;
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nX2, nY2, mpFontEntry->mnOrientation );
+ nWidth = nX2-nX;
+ nHeight = nY2-nY;
+ }
+ else
+ {
+ // Da Polygone kleiner gezeichnet werden
+ nHeight++;
+ nWidth++;
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Polygon aPoly( aRect );
+ aPoly.Rotate( Point( nBaseX, nBaseY ), mpFontEntry->mnOrientation );
+ return aPoly.GetBoundRect();
+ }
+ }
+
+ return Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplInitTextLineSize()
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nLineHeight;
+ long nLineHeight2;
+ long nBLineHeight;
+ long nBLineHeight2;
+ long n2LineHeight;
+ long n2LineDY;
+ long n2LineDY2;
+ long nUnderlineOffset;
+ long nStrikeoutOffset;
+
+ nLineHeight = ((mpFontEntry->maMetric.mnDescent*25)+50) / 100;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+ nLineHeight2 = nLineHeight / 2;
+ if ( !nLineHeight2 )
+ nLineHeight2 = 1;
+
+ nBLineHeight = ((mpFontEntry->maMetric.mnDescent*50)+50) / 100;
+ if ( nBLineHeight == nLineHeight )
+ nBLineHeight++;
+ nBLineHeight2 = nBLineHeight/2;
+ if ( !nBLineHeight2 )
+ nBLineHeight2 = 1;
+
+ n2LineHeight = ((mpFontEntry->maMetric.mnDescent*16)+50) / 100;
+ if ( !n2LineHeight )
+ n2LineHeight = 1;
+ n2LineDY = n2LineHeight;
+ if ( n2LineDY <= 0 )
+ n2LineDY = 1;
+ n2LineDY2 = n2LineDY/2;
+ if ( !n2LineDY2 )
+ n2LineDY2 = 1;
+
+ nUnderlineOffset = mpFontEntry->maMetric.mnDescent/2 + 1;
+ nStrikeoutOffset = -((mpFontEntry->maMetric.mnAscent-mpFontEntry->maMetric.mnLeading)/3);
+
+ if ( !pFontEntry->maMetric.mnUnderlineSize )
+ {
+ pFontEntry->maMetric.mnUnderlineSize = nLineHeight;
+ pFontEntry->maMetric.mnUnderlineOffset = nUnderlineOffset - nLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnBUnderlineSize )
+ {
+ pFontEntry->maMetric.mnBUnderlineSize = nBLineHeight;
+ pFontEntry->maMetric.mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnDUnderlineSize )
+ {
+ pFontEntry->maMetric.mnDUnderlineSize = n2LineHeight;
+ pFontEntry->maMetric.mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight;
+ pFontEntry->maMetric.mnDUnderlineOffset2 = pFontEntry->maMetric.mnDUnderlineOffset1 + n2LineDY + n2LineHeight;
+ }
+ if ( !pFontEntry->maMetric.mnWUnderlineSize )
+ {
+ if ( mpFontEntry->maMetric.mnDescent < 6 )
+ {
+ if ( (mpFontEntry->maMetric.mnDescent == 1) ||
+ (mpFontEntry->maMetric.mnDescent == 2) )
+ pFontEntry->maMetric.mnWUnderlineSize = mpFontEntry->maMetric.mnDescent;
+ else
+ pFontEntry->maMetric.mnWUnderlineSize = 3;
+ }
+ else
+ pFontEntry->maMetric.mnWUnderlineSize = ((mpFontEntry->maMetric.mnDescent*50)+50) / 100;
+ pFontEntry->maMetric.mnWUnderlineOffset = nUnderlineOffset;
+ }
+ if ( !pFontEntry->maMetric.mnStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnStrikeoutSize = nLineHeight;
+ pFontEntry->maMetric.mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnBStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnBStrikeoutSize = nBLineHeight;
+ pFontEntry->maMetric.mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2;
+ }
+ if ( !pFontEntry->maMetric.mnDStrikeoutSize )
+ {
+ pFontEntry->maMetric.mnDStrikeoutSize = n2LineHeight;
+ pFontEntry->maMetric.mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight;
+ pFontEntry->maMetric.mnDStrikeoutOffset2 = pFontEntry->maMetric.mnDStrikeoutOffset1 + n2LineDY + n2LineHeight;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawWavePixel( long nOriginX, long nOriginY,
+ long nCurX, long nCurY,
+ short nOrientation,
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics,
+#else
+ ImplServerGraphics* pGraphics,
+#endif
+ BOOL bDrawPixAsRect,
+ long nPixWidth, long nPixHeight )
+{
+ if ( nOrientation )
+ ImplRotatePos( nOriginX, nOriginY, nCurX, nCurY, nOrientation );
+
+ if ( bDrawPixAsRect )
+ {
+#ifndef REMOTE_APPSERVER
+ pGraphics->DrawRect( nCurX, nCurY, nPixWidth, nPixHeight );
+#else
+ Point aPos( nCurX, nCurY );
+ Size aSize( nPixWidth, nPixHeight );
+ Rectangle aRect( aPos, aSize );
+ pGraphics->DrawRect( aRect );
+#endif
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ pGraphics->DrawPixel( nCurX, nCurY );
+#else
+ Point aPos( nCurX, nCurY );
+ pGraphics->DrawPixel( aPos );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawWaveLine( long nBaseX, long nBaseY,
+ long nStartX, long nStartY,
+ long nWidth, long nHeight,
+ long nLineWidth, short nOrientation,
+ const Color& rColor )
+{
+ if ( !nHeight )
+ return;
+
+ // Bei Hoehe von 1 Pixel reicht es, eine Linie auszugeben
+ if ( (nLineWidth == 1) && (nHeight == 1) )
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+ mbInitLineColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ SetLineColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+#endif
+
+ long nEndX = nStartX+nWidth;
+ long nEndY = nStartY;
+ if ( nOrientation )
+ {
+ ImplRotatePos( nBaseX, nBaseY, nStartX, nStartY, nOrientation );
+ ImplRotatePos( nBaseX, nBaseY, nEndX, nEndY, nOrientation );
+ }
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawLine( nStartX, nStartY, nEndX, nEndY );
+#else
+ mpGraphics->DrawLine( Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+#endif
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+#endif
+ }
+ else
+ {
+ long nCurX = nStartX;
+ long nCurY = nStartY;
+ long nDiffX = 2;
+ long nDiffY = nHeight-1;
+ long nCount = nWidth;
+ long nOffY = -1;
+ long nFreq;
+ long i;
+ long nPixWidth;
+ long nPixHeight;
+ BOOL bDrawPixAsRect;
+#ifdef REMOTE_APPSERVER
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+#endif
+ // Auf Druckern die Pixel per DrawRect() ausgeben
+ if ( (GetOutDevType() == OUTDEV_PRINTER) || (nLineWidth > 1) )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( rColor ) );
+ mbInitFillColor = TRUE;
+#else
+ SetLineColor();
+ SetFillColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+#endif
+ bDrawPixAsRect = TRUE;
+ nPixWidth = nLineWidth;
+ nPixHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+ mbInitLineColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ SetLineColor( rColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+#endif
+ nPixWidth = 1;
+ nPixHeight = 1;
+ bDrawPixAsRect = FALSE;
+ }
+
+ if ( !nDiffY )
+ {
+ while ( nWidth )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nWidth--;
+ }
+ }
+ else
+ {
+ nCurY += nDiffY;
+ nFreq = nCount / (nDiffX+nDiffY);
+ while ( nFreq-- )
+ {
+ for( i = nDiffY; i; --i )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nCurY += nOffY;
+ }
+ for( i = nDiffX; i; --i )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ }
+ nOffY = -nOffY;
+ }
+ nFreq = nCount % (nDiffX+nDiffY);
+ if ( nFreq )
+ {
+ for( i = nDiffY; i && nFreq; --i, --nFreq )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ nCurY += nOffY;
+ }
+ for( i = nDiffX; i && nFreq; --i, --nFreq )
+ {
+ ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+ mpGraphics,
+ bDrawPixAsRect, nPixWidth, nPixHeight );
+ nCurX++;
+ }
+ }
+ }
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextLine( long nBaseX,
+ long nX, long nY, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ Color aTextLineColor = GetTextLineColor();
+ long nBaseY = nY;
+ long nLineHeight;
+ long nLinePos;
+ long nLinePos2;
+ long nLeft;
+ BOOL bNormalLines = TRUE;
+
+ if ( !IsTextLineColor() )
+ aTextLineColor = GetTextColor();
+
+ if ( (eUnderline == UNDERLINE_SMALLWAVE) ||
+ (eUnderline == UNDERLINE_WAVE) ||
+ (eUnderline == UNDERLINE_DOUBLEWAVE) ||
+ (eUnderline == UNDERLINE_BOLDWAVE) )
+ {
+ if ( !pFontEntry->maMetric.mnWUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnWUnderlineSize;
+ if ( (eUnderline == UNDERLINE_SMALLWAVE) &&
+ (nLineHeight > 3) )
+ nLineHeight = 3;
+ long nLineWidth = (mnDPIX/300);
+ if ( !nLineWidth )
+ nLineWidth = 1;
+ if ( eUnderline == UNDERLINE_BOLDWAVE )
+ nLineWidth *= 2;
+ nLinePos = nY + pFontEntry->maMetric.mnWUnderlineOffset - (nLineHeight / 2);
+ long nLineWidthHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+ if ( eUnderline == UNDERLINE_DOUBLEWAVE )
+ {
+ long nOrgLineHeight = nLineHeight;
+ nLineHeight /= 3;
+ if ( nLineHeight < 2 )
+ {
+ if ( nOrgLineHeight > 1 )
+ nLineHeight = 2;
+ else
+ nLineHeight = 1;
+ }
+ long nLineDY = nOrgLineHeight-(nLineHeight*2);
+ if ( nLineDY < nLineWidthHeight )
+ nLineDY = nLineWidthHeight;
+ long nLineDY2 = nLineDY/2;
+ if ( !nLineDY2 )
+ nLineDY2 = 1;
+ nLinePos -= nLineWidthHeight-nLineDY2;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ nLinePos += nLineWidthHeight+nLineDY;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ }
+ else
+ {
+ nLinePos -= nLineWidthHeight/2;
+ ImplDrawWaveLine( nBaseX, nBaseY, nX, nLinePos, nWidth, nLineHeight,
+ nLineWidth, mpFontEntry->mnOrientation, aTextLineColor );
+ }
+
+ if ( (eStrikeout == STRIKEOUT_NONE) ||
+ (eStrikeout == STRIKEOUT_DONTKNOW) )
+ bNormalLines = FALSE;
+ }
+
+ if ( bNormalLines &&
+ ((eStrikeout == STRIKEOUT_SLASH) || (eStrikeout == STRIKEOUT_X)) )
+ {
+ BOOL bOldMap = IsMapModeEnabled();
+ EnableMapMode( FALSE );
+ Color aOldColor = GetTextColor();
+ SetTextColor( aTextLineColor );
+ ImplInitTextColor();
+ xub_Unicode c;
+ if ( eStrikeout == STRIKEOUT_SLASH )
+ c = '/';
+ else /* ( eStrikeout == STRIKEOUT_X ) */
+ c = 'X';
+ // Strikeout-String zusammenbauen
+ XubString aStrikeoutText( c );
+ aStrikeoutText += aStrikeoutText.GetChar( 0 );
+ long nStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ long nChars = nWidth/(nStrikeoutWidth/2);
+ aStrikeoutText.Fill( (USHORT)(nChars+1), c );
+ // String solange kuerzen, bis er nicht allzuweit uebersteht
+ long nMaxWidth = nStrikeoutWidth/4;
+ if ( nMaxWidth < 2 )
+ nMaxWidth = 2;
+ nMaxWidth += nWidth;
+ long nFullStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ while ( (nFullStrikeoutWidth > nMaxWidth) && aStrikeoutText.Len() )
+ {
+ aStrikeoutText.Erase( aStrikeoutText.Len()-1 );
+ nFullStrikeoutWidth = GetTextWidth( aStrikeoutText );
+ }
+ if ( mpFontEntry->mnOrientation )
+ ImplRotatePos( nBaseX, nBaseY, nX, nY, mpFontEntry->mnOrientation );
+ ImplDrawTextDirect( nX, nY,
+ aStrikeoutText.GetBuffer(), aStrikeoutText.Len(),
+ NULL, FALSE );
+ SetTextColor( aOldColor );
+ ImplInitTextColor();
+ EnableMapMode( bOldMap );
+
+ if ( (eUnderline == UNDERLINE_NONE) ||
+ (eUnderline == UNDERLINE_DONTKNOW) ||
+ (eUnderline == UNDERLINE_SMALLWAVE) ||
+ (eUnderline == UNDERLINE_WAVE) ||
+ (eUnderline == UNDERLINE_DOUBLEWAVE) ||
+ (eUnderline == UNDERLINE_BOLDWAVE) )
+ bNormalLines = FALSE;
+ }
+
+ if ( bNormalLines )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+ mpGraphics->SetFillColor( ImplColorToSal( aTextLineColor ) );
+ mbInitFillColor = TRUE;
+#else
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( aTextLineColor );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+#endif
+
+ if ( eUnderline > UNDERLINE_LAST )
+ eUnderline = UNDERLINE_SINGLE;
+
+ if ( (eUnderline == UNDERLINE_SINGLE) ||
+ (eUnderline == UNDERLINE_DOTTED) ||
+ (eUnderline == UNDERLINE_DASH) ||
+ (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_DASHDOT) ||
+ (eUnderline == UNDERLINE_DASHDOTDOT) )
+ {
+ if ( !pFontEntry->maMetric.mnUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnUnderlineOffset;
+ }
+ else if ( (eUnderline == UNDERLINE_BOLD) ||
+ (eUnderline == UNDERLINE_BOLDDOTTED) ||
+ (eUnderline == UNDERLINE_BOLDDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOTDOT) )
+ {
+ if ( !pFontEntry->maMetric.mnBUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnBUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnBUnderlineOffset;
+ }
+ else if ( eUnderline == UNDERLINE_DOUBLE )
+ {
+ if ( !pFontEntry->maMetric.mnDUnderlineSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnDUnderlineSize;
+ nLinePos = nY + pFontEntry->maMetric.mnDUnderlineOffset1;
+ nLinePos2 = nY + pFontEntry->maMetric.mnDUnderlineOffset2;
+ }
+ else
+ nLineHeight = 0;
+
+ if ( nLineHeight )
+ {
+ nLeft = nX;
+
+ if ( (eUnderline == UNDERLINE_SINGLE) ||
+ (eUnderline == UNDERLINE_BOLD) )
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ else if ( eUnderline == UNDERLINE_DOUBLE )
+ {
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+ }
+ else if ( (eUnderline == UNDERLINE_DOTTED) ||
+ (eUnderline == UNDERLINE_BOLDDOTTED) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nTempWidth = nDotWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempWidth > nEnd )
+ nTempWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASH) ||
+ (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nMinDashWidth;
+ long nMinSpaceWidth;
+ long nSpaceWidth;
+ long nDashWidth;
+ if ( (eUnderline == UNDERLINE_LONGDASH) ||
+ (eUnderline == UNDERLINE_BOLDLONGDASH) )
+ {
+ nMinDashWidth = nDotWidth*6;
+ nMinSpaceWidth = nDotWidth*2;
+ nDashWidth = 200;
+ nSpaceWidth = 100;
+ }
+ else
+ {
+ nMinDashWidth = nDotWidth*4;
+ nMinSpaceWidth = (nDotWidth*150)/100;
+ nDashWidth = 100;
+ nSpaceWidth = 50;
+ }
+ nDashWidth = ((nDashWidth*mnDPIX)+1270)/2540;
+ nSpaceWidth = ((nSpaceWidth*mnDPIX)+1270)/2540;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ if ( nSpaceWidth < nMinSpaceWidth )
+ nSpaceWidth = nMinSpaceWidth;
+ long nTempWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempWidth > nEnd )
+ nTempWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+ nLeft += nDashWidth+nSpaceWidth;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASHDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOT) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nDashWidth = ((100*mnDPIX)+1270)/2540;
+ long nMinDashWidth = nDotWidth*4;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ long nTempDotWidth = nDotWidth;
+ long nTempDashWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDashWidth > nEnd )
+ nTempDashWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+ nLeft += nDashWidth+nDotWidth;
+ }
+ }
+ else if ( (eUnderline == UNDERLINE_DASHDOTDOT) ||
+ (eUnderline == UNDERLINE_BOLDDASHDOTDOT) )
+ {
+ long nDotWidth = nLineHeight*mnDPIY;
+ nDotWidth += mnDPIY/2;
+ nDotWidth /= mnDPIY;
+ long nDashWidth = ((100*mnDPIX)+1270)/2540;
+ long nMinDashWidth = nDotWidth*4;
+ // DashWidth wird gegebenenfalls verbreitert, wenn
+ // die dicke der Linie im Verhaeltnis zur Laenge
+ // zu dick wird
+ if ( nDashWidth < nMinDashWidth )
+ nDashWidth = nMinDashWidth;
+ long nTempDotWidth = nDotWidth;
+ long nTempDashWidth = nDashWidth;
+ long nEnd = nLeft+nWidth;
+ while ( nLeft < nEnd )
+ {
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDotWidth > nEnd )
+ nTempDotWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+ nLeft += nDotWidth*2;
+ if ( nLeft > nEnd )
+ break;
+ if ( nLeft+nTempDashWidth > nEnd )
+ nTempDashWidth = nEnd-nLeft;
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+ nLeft += nDashWidth+nDotWidth;
+ }
+ }
+ }
+
+ if ( eStrikeout > STRIKEOUT_LAST )
+ eStrikeout = STRIKEOUT_SINGLE;
+
+ if ( eStrikeout == STRIKEOUT_SINGLE )
+ {
+ if ( !pFontEntry->maMetric.mnStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnStrikeoutOffset;
+ }
+ else if ( eStrikeout == STRIKEOUT_BOLD )
+ {
+ if ( !pFontEntry->maMetric.mnBStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnBStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnBStrikeoutOffset;
+ }
+ else if ( eStrikeout == STRIKEOUT_DOUBLE )
+ {
+ if ( !pFontEntry->maMetric.mnDStrikeoutSize )
+ ImplInitTextLineSize();
+ nLineHeight = pFontEntry->maMetric.mnDStrikeoutSize;
+ nLinePos = nY + pFontEntry->maMetric.mnDStrikeoutOffset1;
+ nLinePos2 = nY + pFontEntry->maMetric.mnDStrikeoutOffset2;
+ }
+ else
+ nLineHeight = 0;
+
+ if ( nLineHeight )
+ {
+ nLeft = nX;
+
+ if ( (eStrikeout == STRIKEOUT_SINGLE) ||
+ (eStrikeout == STRIKEOUT_BOLD) )
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ else if ( eStrikeout == STRIKEOUT_DOUBLE )
+ {
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+ ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+ }
+ }
+
+#ifdef REMOTE_APPSERVER
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextLines( long nX, long nY,
+ const sal_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline,
+ BOOL bWordLine )
+{
+ if ( bWordLine )
+ {
+ ::rtl::OUString aText( pStr, nLen );
+ uno::Reference < text::XBreakIterator > xBI = vcl::unohelper::CreateBreakIterator();
+ uno::Reference< linguistic::XHyphenator > xHyph;
+ text::LineBreakHyphenationOptions aHyphOptions( xHyph, 1 );
+ text::LineBreakUserOptions aUserOptions;
+
+ text::Boundary aBoundary = xBI->getWordBoundary( aText, 0, GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES, TRUE );
+ while ( ( aBoundary.startPos >= 0 ) && ( aBoundary.startPos < nLen ) )
+ {
+ xub_StrLen nWordEnd = Max( (xub_StrLen)aBoundary.endPos, nLen );
+ long nTempX = ImplGetTextWidth( pStr, aBoundary.startPos, pDXAry );
+ long nWidth = ImplGetTextWidth( pStr+aBoundary.startPos, aBoundary.endPos-aBoundary.startPos, pDXAry );
+ ImplDrawTextLine( nX, nX + nTempX, nY, nWidth, eStrikeout, eUnderline );
+ aBoundary = xBI->nextWord( aText, aBoundary.endPos, GetSettings().GetLocale(), text::WordType::ANYWORD_IGNOREWHITESPACES );
+ }
+ }
+ else
+ {
+ ImplDrawTextLine( nX, nX, nY, ImplGetTextWidth( pStr, nLen, pDXAry ), eStrikeout, eUnderline );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawMnemonicLine( long nX, long nY, xub_Unicode c )
+{
+ ImplDrawTextLines( nX, nY, &c, 1, NULL, STRIKEOUT_NONE, UNDERLINE_SINGLE, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::ImplDrawRotateText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ if ( !mpOutDevData )
+ ImplInitOutDevData();
+ if ( !mpOutDevData->mpRotateDev )
+ mpOutDevData->mpRotateDev = new VirtualDevice( *this, 1 );
+ VirtualDevice* pVDev = mpOutDevData->mpRotateDev;
+ long nWidth = ImplGetTextWidth( pStr, nLen, pDXAry );
+ long nHeight = mpFontEntry->mnLineHeight;
+ Size aSize( nWidth, nHeight );
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Font aFont( GetFont() );
+ Bitmap aBmp;
+ long nOff;
+
+ nX -= mnTextOffX;
+ nY -= mnTextOffY;
+ if ( GetTextAlign() == ALIGN_TOP )
+ {
+ nOff = 0L;
+ nY += mpFontEntry->maMetric.mnAscent;
+ }
+ else if ( GetTextAlign() == ALIGN_BOTTOM )
+ {
+ nOff = mpFontEntry->maMetric.mnAscent;
+ nY += -mpFontEntry->maMetric.mnDescent;
+ }
+ else
+ nOff = mpFontEntry->maMetric.mnAscent;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( Size( mpFontEntry->maFontSelData.mnWidth, mpFontEntry->maFontSelData.mnHeight ) );
+ pVDev->SetFont( aFont );
+ // Da Farben und Alignment noch im Font haengen, muessen diese jedesmal
+ // gesetzt werden
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+ pVDev->ImplDrawText( 0, 0, pStr, nLen, pDXAry );
+
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ if ( !!aBmp && aBmp.Rotate( mpFontEntry->mnOwnOrientation, COL_WHITE ) )
+ {
+ Point aTempPoint;
+ Polygon aPoly( Rectangle( aTempPoint, aSize ) );
+ long nOldOffX = mnOutOffX;
+ long nOldOffY = mnOutOffY;
+ BOOL bOldMap = mbMap;
+
+ aTempPoint.Y() = nOff;
+ aPoly.Rotate( aTempPoint, mpFontEntry->mnOwnOrientation );
+ const Rectangle aBound( aPoly.GetBoundRect() );
+
+ mnOutOffX = 0L;
+ mnOutOffY = 0L;
+ mbMap = FALSE;
+
+ DrawMask( Point( nX + aBound.Left(),
+ nY + aBound.Top() - mpFontEntry->maMetric.mnAscent ),
+ aBmp, GetTextColor() );
+
+ mnOutOffX = nOldOffX;
+ mnOutOffY = nOldOffY;
+ mbMap = bOldMap;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawTextDirect( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry,
+ BOOL bTextLines )
+{
+ BOOL bDraw = FALSE;
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ if ( pFontEntry->mnOwnOrientation )
+ bDraw = ImplDrawRotateText( nX, nY, pStr, nLen, pDXAry );
+ if ( !bDraw )
+ {
+ if ( !pDXAry )
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFontEntry->mnSetFontFlags & SAL_SETFONT_USEDRAWTEXTARRAY )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nOffset = 0;
+ long aStackAry[128];
+ long* pTempDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( USHORT i = 0; i < nLen-1; i++ )
+ {
+ nOffset += ImplGetCharWidth( pStr[i] );
+ pTempDXAry[i] = nOffset / nFactor;
+ }
+ mpGraphics->DrawTextArray( nX, nY, pStr, nLen, pTempDXAry );
+ ImplReleaseStackBuffer( pTempDXAry, aStackAry );
+ }
+ else
+#endif
+ mpGraphics->DrawText( nX, nY, pStr, nLen );
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ if ( pFontEntry->mnSetFontFlags & SAL_SETFONT_USEDRAWTEXT )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ long nOffset = 0;
+ long nDiff;
+ long nTempX = nX;
+ const sal_Unicode* pTempStr = pStr;
+ xub_StrLen nCombineChars = 1;
+ for ( xub_StrLen i = 0; i < nLen-1; i++ )
+ {
+ nOffset += ImplGetCharWidth( pStr[i] );
+ nDiff = (nOffset/nFactor) - pDXAry[i];
+ if ( (nDiff < -1) || (nDiff > 0) )
+ {
+ mpGraphics->DrawText( nTempX, nY, pTempStr, nCombineChars );
+ nTempX = nX+pDXAry[i];
+ nOffset = pDXAry[i]*nFactor;
+ pTempStr += nCombineChars;
+ nCombineChars = 1;
+ }
+ else
+ nCombineChars++;
+ }
+ mpGraphics->DrawText( nTempX, nY, pTempStr, nCombineChars );
+ }
+ else
+#endif
+ mpGraphics->DrawTextArray( nX, nY, pStr, nLen, pDXAry );
+ }
+
+ if ( bTextLines )
+ {
+ ImplDrawTextLines( nX, nY, pStr, nLen, pDXAry,
+ maFont.GetStrikeout(),
+ maFont.GetUnderline(),
+ maFont.IsWordLineMode() );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawSpecialText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ Color aOldColor = GetTextColor();
+ Color aOldTextLineColor = GetTextLineColor();
+
+ if ( maFont.IsShadow() )
+ {
+ long nOff = 1 + ((mpFontEntry->mnLineHeight-24)/24);
+ if ( maFont.IsOutline() )
+ nOff++;
+ SetTextLineColor();
+ if ( GetTextColor().GetColor() == COL_BLACK )
+ SetTextColor( Color( COL_LIGHTGRAY ) );
+ else
+ SetTextColor( Color( COL_BLACK ) );
+ ImplInitTextColor();
+ ImplDrawTextDirect( nX+nOff, nY+nOff, pStr, nLen, pDXAry, mbTextLines );
+ SetTextColor( aOldColor );
+ SetTextLineColor( aOldTextLineColor );
+ ImplInitTextColor();
+
+ if ( !maFont.IsOutline() )
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+ }
+
+ if ( maFont.IsOutline() )
+ {
+ ImplDrawTextDirect( nX-1, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY+1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX-1, nY, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX-1, nY-1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX, nY-1, pStr, nLen, pDXAry, mbTextLines );
+ ImplDrawTextDirect( nX+1, nY-1, pStr, nLen, pDXAry, mbTextLines );
+
+ SetTextColor( Color( COL_WHITE ) );
+ SetTextLineColor( Color( COL_WHITE ) );
+ ImplInitTextColor();
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+ SetTextColor( aOldColor );
+ SetTextLineColor( aOldTextLineColor );
+ ImplInitTextColor();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen, const long* pDXAry )
+{
+ nX += mnTextOffX;
+ nY += mnTextOffY;
+
+ if ( IsTextFillColor() )
+ ImplDrawTextBackground( nX, nY, pStr, nLen, pDXAry );
+
+ if ( mbTextSpecial )
+ ImplDrawSpecialText( nX, nY, pStr, nLen, pDXAry );
+ else
+ ImplDrawTextDirect( nX, nY, pStr, nLen, pDXAry, mbTextLines );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplFillDXAry( long* pDXAry,
+ const xub_Unicode* pStr, xub_StrLen nLen, long nWidth )
+{
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+
+ // Breiten-Array fuer errechnete Werte mit den Breiten der einzelnen
+ // Character fuellen
+ xub_StrLen i;
+ long nSum = 0;
+ for ( i = 0; i < nLen; i++ )
+ {
+ // Characterbreiten ueber Array holen
+ nSum += ImplGetCharWidth( pStr[i] );
+ pDXAry[i] = nSum / nFactor;
+ }
+ nSum /= nFactor;
+
+ // Differenz zwischen Soll- und Ist-Laenge errechnen
+ // Zusaetzliche Pixel per Character errechnen
+ // Anzahl der zusaetzlich verbliebenen Pixel errechnen
+ long nDelta = (long)nWidth - nSum;
+ long nDeltaPerChar = 0;
+ long nDeltaRest = 0;
+ if ( nLen > 1 )
+ {
+ nDeltaPerChar = nDelta / (long)(nLen-1);
+ nDeltaRest = nDelta % (long)(nLen-1);
+ }
+ long nDeltaRestAbs = Abs( nDeltaRest );
+
+ long nErrorSum = nDeltaRestAbs;
+ long nDeltaSum = 0;
+ for ( i = 0; i < nLen-1; i++, nErrorSum += nDeltaRestAbs )
+ {
+ nDeltaSum += nDeltaPerChar;
+ if ( nErrorSum >= nLen-1 )
+ {
+ nErrorSum -= nLen-1;
+ if ( nDeltaRest > 0 )
+ nDeltaSum++;
+ else if ( nDeltaRest < 0 )
+ nDeltaSum--;
+ }
+ pDXAry[i] += nDeltaSum;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
+ long nWidth, const XubString& rStr,
+ USHORT nStyle ) const
+{
+ DBG_ASSERT( nWidth >= 0, "ImplGetTextLines: nWidth <= 0!" );
+
+ long nMaxLineWidth = 0;
+ rLineInfo.Clear();
+ if ( rStr.Len() && ( nWidth > 0 ) )
+ {
+ ::rtl::OUString aText( rStr );
+ uno::Reference < text::XBreakIterator > xBI;
+ uno::Reference< linguistic::XHyphenator > xHyph;
+ text::LineBreakHyphenationOptions aHyphOptions( xHyph, 1 );
+ text::LineBreakUserOptions aUserOptions;
+
+ USHORT nPos = 0;
+ USHORT nLen = rStr.Len();
+ while ( nPos < nLen )
+ {
+ xub_StrLen nBreakPos = nPos;
+ while ( ( nBreakPos < nLen ) && ( rStr.GetChar( nBreakPos ) != _CR ) && ( rStr.GetChar( nBreakPos ) != _LF ) )
+ nBreakPos++;
+
+ long nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ if ( ( nLineWidth > nWidth ) && ( nStyle & TEXT_DRAW_WORDBREAK ) )
+ {
+ if ( !xBI.is() )
+ xBI = vcl::unohelper::CreateBreakIterator();
+
+ xub_StrLen nSoftBreak = GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
+ DBG_ASSERT( nSoftBreak < nBreakPos, "Break?!" );
+ text::LineBreakResults aLBR = xBI->getLineBreak( aText, nSoftBreak, GetSettings().GetLocale(), nPos, aHyphOptions, aUserOptions );
+ nBreakPos = aLBR.breakIndex;
+ if ( nBreakPos <= nPos )
+ nBreakPos = nSoftBreak;
+ nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ }
+
+ if ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ if ( ( rStr.GetChar( nBreakPos ) == _CR ) || ( rStr.GetChar( nBreakPos ) == _LF ) )
+ {
+ nBreakPos++;
+ // CR/LF?
+ if ( ( nPos < nLen ) && ( rStr.GetChar( nBreakPos ) == _LF ) && ( rStr.GetChar( nBreakPos-1 ) == _CR ) )
+ nBreakPos++;
+ }
+
+ if ( nBreakPos == nPos )
+ nBreakPos++;
+
+ rLineInfo.AddLine( new ImplTextLineInfo( nLineWidth, nPos, nBreakPos-nPos ) );
+
+ nPos = nBreakPos;
+ }
+ }
+
+ return nMaxLineWidth;
+}
+
+// =======================================================================
+
+void OutputDevice::SetFont( const Font& rNewFont )
+{
+ DBG_TRACE( "OutputDevice::SetFont()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rNewFont, Font, NULL );
+
+ Font aFont( rNewFont );
+
+ if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
+ DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL) )
+ {
+ Color aTextColor( aFont.GetColor() );
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aTextColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aTextColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aTextColor.GetLuminance();
+ aTextColor = Color( cLum, cLum, cLum );
+ }
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aTextColor = Color( (aTextColor.GetRed() >> 1 ) | 0x80,
+ (aTextColor.GetGreen() >> 1 ) | 0x80,
+ (aTextColor.GetBlue() >> 1 ) | 0x80 );
+ }
+ aFont.SetColor( aTextColor );
+
+ BOOL bTransFill = aFont.IsTransparent();
+ if ( !bTransFill )
+ {
+ Color aTextFillColor( aFont.GetFillColor() );
+ if ( mnDrawMode & DRAWMODE_BLACKFILL )
+ aTextFillColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITEFILL )
+ aTextFillColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aTextFillColor.GetLuminance();
+ aTextFillColor = Color( cLum, cLum, cLum );
+ }
+ else if ( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aTextFillColor = Color( COL_TRANSPARENT );
+ bTransFill = TRUE;
+ }
+ if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
+ {
+ aTextFillColor = Color( (aTextFillColor.GetRed() >> 1) | 0x80,
+ (aTextFillColor.GetGreen() >> 1) | 0x80,
+ (aTextFillColor.GetBlue() >> 1) | 0x80 );
+ }
+ aFont.SetFillColor( aTextFillColor );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ const Color& rTextFillColor = aFont.GetFillColor();
+
+ mpMetaFile->AddAction( new MetaFontAction( aFont ) );
+ mpMetaFile->AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
+ mpMetaFile->AddAction( new MetaTextColorAction( aFont.GetColor() ) );
+ mpMetaFile->AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
+ }
+
+ if ( !maFont.IsSameInstance( aFont ) )
+ {
+ if ( maFont.GetColor() != aFont.GetColor() )
+ mbInitTextColor = TRUE;
+ maFont = aFont;
+ mbNewFont = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+ DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextColorAction( aColor ) );
+
+ if ( maFont.GetColor() != aColor )
+ {
+ maFont.SetColor( aColor );
+ mbInitTextColor = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextFillColor()
+{
+ DBG_TRACE( "OutputDevice::SetTextFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextFillColorAction( Color(), FALSE ) );
+
+ if ( maFont.GetColor() != Color( COL_TRANSPARENT ) )
+ maFont.SetFillColor( Color( COL_TRANSPARENT ) );
+ if ( !maFont.IsTransparent() )
+ maFont.SetTransparent( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextFillColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextFillColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+ BOOL bTransFill = ImplIsColorTransparent( aColor );
+
+ if ( !bTransFill )
+ {
+ if ( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL |
+ DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKFILL )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITEFILL )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+ else if ( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aColor = Color( COL_TRANSPARENT );
+ bTransFill = TRUE;
+ }
+ if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextFillColorAction( aColor, TRUE ) );
+
+ if ( maFont.GetFillColor() != aColor )
+ maFont.SetFillColor( aColor );
+ if ( maFont.IsTransparent() != bTransFill )
+ maFont.SetTransparent( bTransFill );
+}
+
+// -----------------------------------------------------------------------
+
+Color OutputDevice::GetTextFillColor() const
+{
+ if ( maFont.IsTransparent() )
+ return Color( COL_TRANSPARENT );
+ else
+ return maFont.GetFillColor();
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextLineColor()
+{
+ DBG_TRACE( "OutputDevice::SetTextLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineColorAction( Color(), FALSE ) );
+
+ maTextLineColor = Color( COL_TRANSPARENT );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextLineColor( const Color& rColor )
+{
+ DBG_TRACE( "OutputDevice::SetTextLineColor()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Color aColor( rColor );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+ DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT ) )
+ {
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+ (aColor.GetGreen() >> 1) | 0x80,
+ (aColor.GetBlue() >> 1) | 0x80 );
+ }
+ }
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, TRUE ) );
+
+ maTextLineColor = aColor;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetTextAlign( TextAlign eAlign )
+{
+ DBG_TRACE( "OutputDevice::SetTextAlign()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextAlignAction( eAlign ) );
+
+ if ( maFont.GetAlign() != eAlign )
+ {
+ maFont.SetAlign( eAlign );
+ mbNewFont = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTextLine( const Point& rPos, long nWidth,
+ FontStrikeout eStrikeout,
+ FontUnderline eUnderline )
+{
+ DBG_TRACE( "OutputDevice::DrawTextLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline ) );
+
+ if ( ((eUnderline == UNDERLINE_NONE) || (eUnderline == UNDERLINE_DONTKNOW)) &&
+ ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
+ return;
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+
+ Point aPos = ImplLogicToDevicePixel( rPos );
+ nWidth = ImplLogicWidthToDevicePixel( nWidth );
+ aPos.X() += mnTextOffX;
+ aPos.Y() += mnTextOffY;
+ ImplDrawTextLine( aPos.X(), aPos.X(), aPos.Y(), nWidth, eStrikeout, eUnderline );
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos,
+ USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawWaveLine()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+#ifndef REMOTE_APPSERVER
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPos );
+ Point aEndPt = ImplLogicToDevicePixel( rEndPos );
+ long nStartX = aStartPt.X();
+ long nStartY = aStartPt.Y();
+ long nEndX = aEndPt.X();
+ long nEndY = aEndPt.Y();
+ short nOrientation = 0;
+
+ if ( (nStartY != nEndY) || (nStartX > nEndX) )
+ {
+ long nDX = nEndX - nStartX;
+ double nO = atan2( -nEndY + nStartY, ((nDX == 0L) ? 0.000000001 : nDX) );
+ nO /= F_PI1800;
+ nOrientation = (short)nO;
+ ImplRotatePos( nStartX, nStartY, nEndX, nEndY, -nOrientation );
+ }
+
+ long nWaveHeight;
+ if ( nStyle == WAVE_NORMAL )
+ {
+ nWaveHeight = 3;
+ nStartY++;
+ nEndY++;
+ }
+ else if( nStyle == WAVE_SMALL )
+ {
+ nWaveHeight = 2;
+ nStartY++;
+ nEndY++;
+ }
+ else // WAVE_FLAT
+ nWaveHeight = 1;
+
+ ImplDrawWaveLine( nStartX, nStartY, nStartX, nStartY,
+ nEndX-nStartX, nWaveHeight, 1,
+ nOrientation, GetLineColor() );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Point aPos1 = ImplLogicToDevicePixel( rStartPos );
+ Point aPos2 = ImplLogicToDevicePixel( rEndPos );
+ pGraphics->DrawWaveLine( aPos1, aPos2, nStyle );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawText( const Point& rStartPt, const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextAction( rStartPt, rStr, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ if ( mbKerning )
+ {
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ USHORT i;
+
+ // DX-Array berechnen
+ long nOffset = 0;
+ long aStackAry[128];
+ long* pDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( i = 0; i < nLen-1; i++ )
+ {
+ nOffset += pCharWidthAry[(unsigned char)pStr[i]];
+ pDXAry[i] = nOffset / nFactor;
+ }
+ ImplCalcKerning( pStr, nLen, pDXAry, nLen-1 );
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+ ImplReleaseStackBuffer( pDXAry, aStackAry );
+ }
+ else
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextWidth( const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextWidth()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long nWidth = 0;
+
+ if ( nIndex < rStr.Len() )
+ {
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+
+ if ( nLen )
+ {
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+
+ // Bei Fixed-Fonts reicht eine Multiplikation
+ if ( pFontEntry->mbFixedFont )
+ {
+ nWidth = pCharWidthAry['A'] * nLen;
+ nWidth /= pFontEntry->mnWidthFactor;
+ }
+ else
+ {
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ const sal_Unicode* pTempStr;
+ USHORT nTempLen;
+ pStr += nIndex;
+ pTempStr = pStr;
+ nTempLen = nLen;
+ while ( nTempLen )
+ {
+ nWidth += ImplGetCharWidth( *pTempStr );
+ nTempLen--;
+ pTempStr++;
+ }
+ nWidth /= pFontEntry->mnWidthFactor;
+
+ // Kerning beruecksichtigen (tun wir nur bei Fonts ohne feste Breite)
+ if ( mbKerning )
+ nWidth += ImplCalcKerning( pStr, nLen, NULL, 0 );
+ }
+ }
+ }
+
+ if ( mbMap )
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextHeight() const
+{
+ DBG_TRACE( "OutputDevice::GetTextHeight()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ long nHeight = mpFontEntry->mnLineHeight;
+
+ if ( mbMap )
+ nHeight = ImplDevicePixelToLogicHeight( nHeight );
+
+ return nHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTextArray( const Point& rStartPt, const XubString& rStr,
+ const long* pDXAry,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawTextArray()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextArrayAction( rStartPt, rStr, pDXAry, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+ // Bei keinem Pos-Array, DrawText benutzen
+ if ( !pDXAry || (nLen < 2) )
+ {
+ // hier Aufrufen, damit keine doppelte MetaFile Aufzeichnung
+ DrawText( rStartPt, rStr, nIndex, nLen );
+ return;
+ }
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ if ( mbMap )
+ {
+ long nLogStartX = rStartPt.X();
+ long nPixStartX = aStartPt.X();
+ long aStackAry[128];
+ long* pPixDXAry = (long*)ImplGetStackBuffer( sizeof(long)*(nLen-1), aStackAry, sizeof( aStackAry ) );
+ for ( xub_StrLen i = 0; i < (nLen-1); i++ )
+ pPixDXAry[i] = ImplLogicXToDevicePixel( nLogStartX+pDXAry[i] )-nPixStartX;
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pPixDXAry );
+ ImplReleaseStackBuffer( pPixDXAry, aStackAry );
+ }
+ else
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetTextArray( const UniString& rStr, long* pDXAry,
+ xub_StrLen nIndex, xub_StrLen nLen ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextArray()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !pDXAry )
+ return GetTextWidth( rStr, nIndex, nLen );
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ if ( !nLen )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pTempStr;
+ const sal_Unicode* pStr;
+ long nOffset = 0;
+ xub_StrLen i;
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ pTempStr = pStr;
+
+ // Breiten ermitteln
+ for ( i = 0; i < nLen; i++ )
+ {
+ nOffset += ImplGetCharWidth( *pTempStr );
+ pDXAry[i] = nOffset / nFactor;
+ pTempStr++;
+ }
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ ImplCalcKerning( pStr, nLen, pDXAry, nLen );
+
+ // Breite und Hoehe ermitteln
+ long nWidth = pDXAry[nLen-1];
+
+ // Wenn MapMode gesetzt, dann Werte umrechnen
+ if ( mbMap )
+ {
+ for ( i = 0; i < nLen; i++ )
+ pDXAry[i] = ImplDevicePixelToLogicWidth( pDXAry[i] );
+
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+ }
+
+ return nWidth;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawStretchText( const Point& rStartPt, ULONG nWidth,
+ const UniString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen )
+{
+ DBG_TRACE( "OutputDevice::DrawStretchText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaStretchTextAction( rStartPt, nWidth, rStr, nIndex, nLen ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // String-Laenge fuer die Ermittlung der Groesse setzen
+ if ( (ULONG)nLen+nIndex > rStr.Len() )
+ {
+ if ( nIndex < rStr.Len() )
+ nLen = rStr.Len()-nIndex;
+ else
+ nLen = 0;
+ }
+
+ // Ist die Ausgabe leer, dann mache nichts
+ if ( !nLen )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ if ( mbNewFont )
+ {
+ if ( !ImplNewFont() )
+ return;
+ }
+ if ( mbInitFont )
+ ImplInitFont();
+ if ( mbInitTextColor )
+ ImplInitTextColor();
+
+ Point aStartPt = ImplLogicToDevicePixel( rStartPt );
+ nWidth = ImplLogicWidthToDevicePixel( nWidth );
+
+ // Pointer auf den String-Buffer setzen und um den Index korrigieren
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ pStr += nIndex;
+
+ // Breiten-Array fuer errechnete Werte allocieren und
+ // mit den Breiten der einzelnen Character fuellen lassen
+ long aStackAry[128];
+ long* pDXAry = (long*)ImplGetStackBuffer( sizeof(long)*nLen, aStackAry, sizeof( aStackAry ) );
+ ImplFillDXAry( pDXAry, pStr, nLen, (long)nWidth );
+ ImplDrawText( aStartPt.X(), aStartPt.Y(), pStr, nLen, pDXAry );
+ ImplReleaseStackBuffer( pDXAry, aStackAry );
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen OutputDevice::GetTextBreak( const XubString& rStr, long nTextWidth,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ long nCharExtra ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextBreak()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nIndex > rStr.Len() )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pStr;
+ long nCalcWidth = 0;
+ xub_StrLen nLastIndex;
+
+ if ( mbMap )
+ {
+ nTextWidth = ImplLogicWidthToDevicePixel( nTextWidth*10 );
+ nTextWidth *= nFactor;
+ nTextWidth /= 10;
+ if ( nCharExtra )
+ {
+ nCharExtra = ImplLogicWidthToDevicePixel( nCharExtra*10 );
+ nCharExtra *= nFactor;
+ nCharExtra /= 10;
+ }
+ }
+ else
+ {
+ nCharExtra *= nFactor;
+ nTextWidth *= nFactor;
+ }
+
+ // Letzte Index-Position ermitteln
+ if ( (ULONG)nIndex+nLen > rStr.Len() )
+ nLastIndex = rStr.Len();
+ else
+ nLastIndex = nIndex + nLen;
+
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ while ( nIndex < nLastIndex )
+ {
+ nCalcWidth += ImplGetCharWidth( *pStr );
+
+ if ( nCalcWidth > nTextWidth )
+ return nIndex;
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nCalcWidth += ImplCalcKerning( pStr, 2, NULL, 0 )*nFactor;
+ nCalcWidth += nCharExtra;
+
+ nIndex++;
+ pStr++;
+ }
+
+ return STRING_LEN;
+}
+
+// -----------------------------------------------------------------------
+
+xub_StrLen OutputDevice::GetTextBreak( const XubString& rStr, long nTextWidth,
+ sal_Unicode nExtraChar, xub_StrLen& rExtraCharPos,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ long nCharExtra ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextBreak()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nIndex > rStr.Len() )
+ return 0;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return 0;
+ }
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+ long* pCharWidthAry = pFontEntry->maWidthAry;
+ long nFactor = pFontEntry->mnWidthFactor;
+ const sal_Unicode* pStr;
+ long nTextWidth2;
+ long nCalcWidth = 0;
+ xub_StrLen nIndex2 = STRING_LEN;
+ xub_StrLen nLastIndex;
+
+ if ( mbMap )
+ {
+ nTextWidth = ImplLogicWidthToDevicePixel( nTextWidth*10 );
+ nTextWidth *= nFactor;
+ nTextWidth /= 10;
+ if ( nCharExtra )
+ {
+ nCharExtra = ImplLogicWidthToDevicePixel( nCharExtra*10 );
+ nCharExtra *= nFactor;
+ nCharExtra /= 10;
+ }
+ }
+ else
+ {
+ nCharExtra *= nFactor;
+ nTextWidth *= nFactor;
+ }
+
+ // Letzte Index-Position ermitteln
+ if ( (ULONG)nIndex+nLen > rStr.Len() )
+ nLastIndex = rStr.Len();
+ else
+ nLastIndex = nIndex + nLen;
+
+ nTextWidth2 = nTextWidth - ImplGetCharWidth( nExtraChar ) - nCharExtra;
+
+ pStr = rStr.GetBuffer();
+ pStr += nIndex;
+ while ( nIndex < nLastIndex )
+ {
+ nCalcWidth += ImplGetCharWidth( *pStr );
+
+ if ( nCalcWidth > nTextWidth2 )
+ {
+ if ( nIndex2 == STRING_LEN )
+ nIndex2 = nIndex;
+ }
+ if ( nCalcWidth > nTextWidth )
+ {
+ if ( nIndex2 == STRING_LEN )
+ rExtraCharPos = nIndex;
+ else
+ rExtraCharPos = nIndex2;
+ return nIndex;
+ }
+
+ // Kerning beruecksichtigen
+ if ( mbKerning )
+ nCalcWidth += ImplCalcKerning( pStr, 2, NULL, 0 )*nFactor;
+ nCalcWidth += nCharExtra;
+
+ nIndex++;
+ pStr++;
+ }
+
+ rExtraCharPos = nIndex2;
+ return STRING_LEN;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetCharWidth( sal_Unicode nFirstChar, sal_Unicode nLastChar,
+ long* pWidthAry ) const
+{
+ DBG_TRACE( "OutputDevice::GetCharWidth()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_ASSERT( nFirstChar <= nLastChar, "OutputDevice::GetCharWidth(): nFirst > nLast" );
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return;
+ }
+
+ long nFactor = mpFontEntry->mnWidthFactor;
+ sal_Unicode nCharCount = nLastChar-nFirstChar+1;
+
+ if ( mbMap )
+ {
+ while ( nCharCount )
+ {
+ *pWidthAry = ImplDevicePixelToLogicWidth( ImplGetCharWidth( nFirstChar ) ) / nFactor;
+ pWidthAry++;
+ nFirstChar++;
+ nCharCount--;
+ }
+ }
+ else
+ {
+ while ( nCharCount )
+ {
+ *pWidthAry = ImplGetCharWidth( nFirstChar ) / nFactor;
+ pWidthAry++;
+ nFirstChar++;
+ nCharCount--;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawText( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawText( const Rectangle& )" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextRectAction( rRect, rStr, nStyle ) );
+
+ if ( !IsDeviceOutputNecessary() || !rStr.Len() || rRect.IsEmpty() )
+ return;
+
+ // Vorsichtshalber hier auch schon Aufrufen, da ImplDrawMnemonicLine()
+ // dies nicht macht
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ Color aOldTextColor;
+ Color aOldTextFillColor;
+ BOOL bRestoreFillColor;
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ aOldTextColor = GetTextColor();
+ if ( IsTextFillColor() )
+ {
+ bRestoreFillColor = TRUE;
+ aOldTextFillColor = GetTextFillColor();
+ }
+ else
+ bRestoreFillColor = FALSE;
+ SetTextColor( GetSettings().GetStyleSettings().GetLightColor() );
+ Rectangle aRect = rRect;
+ aRect.Move( 1, 1 );
+ DrawText( aRect, rStr, nStyle & ~TEXT_DRAW_DISABLE );
+ SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ }
+
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+
+ if ( ((nWidth <= 0) || (nHeight <= 0)) && (nStyle & TEXT_DRAW_CLIP) )
+ return;
+
+ XubString aStr = rStr;
+ Point aPos = rRect.TopLeft();
+ long nTextHeight = GetTextHeight();
+ TextAlign eAlign = GetTextAlign();
+ xub_StrLen nMnemonicPos = STRING_NOTFOUND;
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ aStr = GetNonMnemonicString( aStr, nMnemonicPos );
+
+ // Mehrzeiligen Text behandeln wir anders
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ XubString aLastLine;
+ ImplMultiTextLineInfo aMultiLineInfo;
+ ImplTextLineInfo* pLineInfo;
+ long nMaxTextWidth;
+ xub_StrLen i;
+ xub_StrLen nLines;
+ xub_StrLen nFormatLines;
+
+ if ( nTextHeight )
+ {
+ nMaxTextWidth = ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nLines = (xub_StrLen)(nHeight/nTextHeight);
+ nFormatLines = aMultiLineInfo.Count();
+ if ( !nLines )
+ nLines = 1;
+ if ( nFormatLines > nLines )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ // Letzte Zeile zusammenbauen und kuerzen
+ nFormatLines = nLines-1;
+ pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
+ aLastLine = aStr.Copy( pLineInfo->GetIndex() );
+ aLastLine.ConvertLineEnd( LINEEND_LF );
+ // Alle LineFeed's durch Spaces ersetzen
+ xub_StrLen nLastLineLen = aLastLine.Len();
+ for ( i = 0; i < nLastLineLen; i++ )
+ {
+ if ( aLastLine.GetChar( i ) == _LF )
+ aLastLine.SetChar( i, ' ' );
+ }
+ aLastLine = GetEllipsisString( aLastLine, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
+ nStyle |= TEXT_DRAW_TOP;
+ }
+ }
+ else
+ {
+ if ( nMaxTextWidth <= nWidth )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Muss in der Hoehe geclippt werden?
+ if ( nFormatLines*nTextHeight > nHeight )
+ nStyle |= TEXT_DRAW_CLIP;
+
+ // Clipping setzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-(nFormatLines*nTextHeight);
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += nTextHeight;
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += GetFontMetric().GetAscent();
+
+ // Alle Zeilen ausgeben, bis auf die letzte
+ for ( i = 0; i < nFormatLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-pLineInfo->GetWidth();
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
+ xub_StrLen nIndex = pLineInfo->GetIndex();
+ xub_StrLen nLineLen = pLineInfo->GetLen();
+ DrawText( aPos, aStr, nIndex, nLineLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( (nMnemonicPos >= nIndex) && (nMnemonicPos < nIndex+nLineLen) )
+ {
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ Point aTempPos = LogicToPixel( aPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, nIndex, nMnemonicPos-nIndex ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+ aPos.Y() += nTextHeight;
+ aPos.X() = rRect.Left();
+ }
+
+ // Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
+ // da die Zeile gekuerzt wurde
+ if ( aLastLine.Len() )
+ DrawText( aPos, aLastLine );
+
+ // Clipping zuruecksetzen
+ if ( nStyle & TEXT_DRAW_CLIP )
+ Pop();
+ }
+ }
+ else
+ {
+ long nTextWidth = GetTextWidth( aStr );
+
+ // Evt. Text kuerzen
+ if ( nTextWidth > nWidth )
+ {
+ if ( nStyle & TEXT_DRAW_ELLIPSIS )
+ {
+ aStr = GetEllipsisString( aStr, nWidth, nStyle );
+ nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
+ nStyle |= TEXT_DRAW_LEFT;
+ nTextWidth = GetTextWidth( aStr );
+ }
+ }
+ else
+ {
+ if ( nTextHeight <= nHeight )
+ nStyle &= ~TEXT_DRAW_CLIP;
+ }
+
+ // Vertikales Alignment
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aPos.X() += nWidth-nTextWidth;
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ aPos.X() += (nWidth-nTextWidth)/2;
+
+ // Font Alignment
+ if ( eAlign == ALIGN_BOTTOM )
+ aPos.Y() += nTextHeight;
+ else if ( eAlign == ALIGN_BASELINE )
+ aPos.Y() += GetFontMetric().GetAscent();
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aPos.Y() += nHeight-nTextHeight;
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ aPos.Y() += (nHeight-nTextHeight)/2;
+
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ Point aTempPos = LogicToPixel( aPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, 0, nMnemonicPos ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ }
+
+ if ( nStyle & TEXT_DRAW_CLIP )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+ DrawText( aPos, aStr );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ Pop();
+ }
+ else
+ {
+ DrawText( aPos, aStr );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ SetTextColor( aOldTextColor );
+ if ( bRestoreFillColor )
+ SetTextFillColor( aOldTextFillColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle,
+ TextRectInfo* pInfo ) const
+{
+ DBG_TRACE( "OutputDevice::GetTextRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Rectangle aRect = rRect;
+ XubString aStr = rStr;
+ xub_StrLen nLines;
+ long nWidth = rRect.GetWidth();
+ long nMaxWidth;
+ long nTextHeight = GetTextHeight();
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ aStr = GetNonMnemonicString( aStr );
+
+ if ( nStyle & TEXT_DRAW_MULTILINE )
+ {
+ ImplMultiTextLineInfo aMultiLineInfo;
+ ImplTextLineInfo* pLineInfo;
+ xub_StrLen nFormatLines;
+ xub_StrLen i;
+
+ nMaxWidth = 0;
+ ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nFormatLines = aMultiLineInfo.Count();
+ if ( !nTextHeight )
+ nTextHeight = 1;
+ nLines = (USHORT)(aRect.GetHeight()/nTextHeight);
+ if ( pInfo )
+ pInfo->mnLineCount = nFormatLines;
+ if ( !nLines )
+ nLines = 1;
+ if ( nFormatLines <= nLines )
+ nLines = nFormatLines;
+ else
+ {
+ if ( !(nStyle & TEXT_DRAW_ENDELLIPSIS) )
+ nLines = nFormatLines;
+ else
+ {
+ if ( pInfo )
+ pInfo->mbEllipsis = TRUE;
+ nMaxWidth = nWidth;
+ }
+ }
+ if ( pInfo )
+ {
+ BOOL bMaxWidth = nMaxWidth == 0;
+ pInfo->mnMaxWidth = 0;
+ for ( i = 0; i < nLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( bMaxWidth && (pLineInfo->GetWidth() > nMaxWidth) )
+ nMaxWidth = pLineInfo->GetWidth();
+ if ( pLineInfo->GetWidth() > pInfo->mnMaxWidth )
+ pInfo->mnMaxWidth = pLineInfo->GetWidth();
+ }
+ }
+ else if ( !nMaxWidth )
+ {
+ for ( i = 0; i < nLines; i++ )
+ {
+ pLineInfo = aMultiLineInfo.GetLine( i );
+ if ( pLineInfo->GetWidth() > nMaxWidth )
+ nMaxWidth = pLineInfo->GetWidth();
+ }
+ }
+ }
+ else
+ {
+ nLines = 1;
+ nMaxWidth = GetTextWidth( aStr );
+
+ if ( pInfo )
+ {
+ pInfo->mnLineCount = 1;
+ pInfo->mnMaxWidth = nMaxWidth;
+ }
+
+ if ( (nMaxWidth > nWidth) && (nStyle & TEXT_DRAW_ELLIPSIS) )
+ {
+ if ( pInfo )
+ pInfo->mbEllipsis = TRUE;
+ nMaxWidth = nWidth;
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_RIGHT )
+ aRect.Left() = aRect.Right()-nMaxWidth+1;
+ else if ( nStyle & TEXT_DRAW_CENTER )
+ {
+ aRect.Left() += (nWidth-nMaxWidth)/2;
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+ }
+ else
+ aRect.Right() = aRect.Left()+nMaxWidth-1;
+
+ if ( nStyle & TEXT_DRAW_BOTTOM )
+ aRect.Top() = aRect.Bottom()-(nTextHeight*nLines)+1;
+ else if ( nStyle & TEXT_DRAW_VCENTER )
+ {
+ aRect.Top() += (aRect.GetHeight()-(nTextHeight*nLines))/2;
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+ }
+ else
+ aRect.Bottom() = aRect.Top()+(nTextHeight*nLines)-1;
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplIsCharIn( xub_Unicode c, const sal_Char* pStr )
+{
+ while ( *pStr )
+ {
+ if ( *pStr == c )
+ return TRUE;
+ pStr++;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+XubString OutputDevice::GetEllipsisString( const XubString& rStr, long nMaxWidth,
+ USHORT nStyle ) const
+{
+ DBG_TRACE( "OutputDevice::GetEllipsisString()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ XubString aStr = rStr;
+ xub_StrLen nIndex = GetTextBreak( aStr, nMaxWidth );
+
+ if ( nIndex != STRING_LEN )
+ {
+ if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
+ {
+ aStr.Erase( nIndex );
+ if ( nIndex > 1 )
+ {
+ aStr.AppendAscii( "..." );
+ while ( aStr.Len() && (GetTextWidth( aStr ) > nMaxWidth) )
+ {
+ if ( (nIndex > 1) || (nIndex == aStr.Len()) )
+ nIndex--;
+ aStr.Erase( nIndex, 1 );
+ }
+ }
+
+ if ( !aStr.Len() && (nStyle & TEXT_DRAW_CLIP) )
+ aStr += rStr.GetChar( 0 );
+ }
+ else if ( nStyle & (TEXT_DRAW_PATHELLIPSIS | TEXT_DRAW_NEWSELLIPSIS) )
+ {
+ static sal_Char const aPathSepChars[] = "\\/:";
+ static sal_Char const aNewsSepChars[] = ".";
+ const sal_Char* pSepChars;
+
+ if ( nStyle & TEXT_DRAW_PATHELLIPSIS )
+ pSepChars = aPathSepChars;
+ else
+ pSepChars = aNewsSepChars;
+
+ // Letztes Teilstueck ermitteln
+ xub_StrLen nLastContent = rStr.Len();
+ while ( nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( rStr.GetChar( nLastContent ), pSepChars ) )
+ break;
+ }
+ while ( nLastContent &&
+ ImplIsCharIn( rStr.GetChar( nLastContent-1 ), pSepChars ) )
+ nLastContent--;
+
+ XubString aLastStr( rStr, nLastContent, rStr.Len() );
+ XubString aTempLastStr( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
+ aTempLastStr += aLastStr;
+ if ( GetTextWidth( aTempLastStr ) > nMaxWidth )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ USHORT nFirstContent = 0;
+ while ( nFirstContent < nLastContent )
+ {
+ nFirstContent++;
+ if ( ImplIsCharIn( rStr.GetChar( nFirstContent ), pSepChars ) )
+ break;
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( rStr.GetChar( nFirstContent ), pSepChars ) )
+ nFirstContent++;
+
+ if ( nFirstContent >= nLastContent )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ if ( nFirstContent > 4 )
+ nFirstContent = 4;
+ XubString aFirstStr( rStr, 0, nFirstContent );
+ aFirstStr.AppendAscii( "..." );
+ XubString aTempStr = aFirstStr;
+ aTempStr += aLastStr;
+ if ( GetTextWidth( aTempStr ) > nMaxWidth )
+ aStr = GetEllipsisString( rStr, nMaxWidth, nStyle | TEXT_DRAW_ENDELLIPSIS );
+ else
+ {
+ do
+ {
+ aStr = aTempStr;
+ while ( nFirstContent < nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( rStr.GetChar( nLastContent ), pSepChars ) )
+ break;
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( rStr.GetChar( nLastContent-1 ), pSepChars ) )
+ nLastContent--;
+
+ if ( nFirstContent < nLastContent )
+ {
+ XubString aTempLastStr( rStr, nLastContent, rStr.Len() );
+ aTempStr = aFirstStr;
+ aTempStr += aTempLastStr;
+ if ( GetTextWidth( aTempStr ) > nMaxWidth )
+ break;
+ }
+ }
+ while ( nFirstContent < nLastContent );
+ }
+ }
+ }
+ }
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawCtrlText( const Point& rPos, const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ USHORT nStyle )
+{
+ DBG_TRACE( "OutputDevice::DrawCtrlText()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !IsDeviceOutputNecessary() || (nIndex >= rStr.Len()) )
+ return;
+
+ // Vorsichtshalber hier auch schon Aufrufen, da ImplDrawMnemonicLine()
+ // dies nicht macht
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+#else
+ if ( !ImplGetServerGraphics() )
+ return;
+#endif
+
+ XubString aStr = rStr;
+ xub_StrLen nMnemonicPos = STRING_NOTFOUND;
+ long nMnemonicX;
+ long nMnemonicY;
+ xub_Unicode cMnemonic;
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ {
+ aStr = GetNonMnemonicString( aStr, nMnemonicPos );
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ if ( nMnemonicPos < nIndex )
+ nIndex--;
+ else if ( (nLen < STRING_LEN) &&
+ (nMnemonicPos >= nIndex) && (nMnemonicPos < (ULONG)(nIndex+nLen)) )
+ nLen--;
+ Point aTempPos = LogicToPixel( rPos );
+ cMnemonic = aStr.GetChar( nMnemonicPos );
+ nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( GetTextWidth( aStr, 0, nMnemonicPos ) );
+ nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ }
+ }
+
+ if ( nStyle & TEXT_DRAW_DISABLE )
+ {
+ Color aOldTextColor;
+ Color aOldTextFillColor;
+ BOOL bRestoreFillColor;
+ aOldTextColor = GetTextColor();
+ if ( IsTextFillColor() )
+ {
+ bRestoreFillColor = TRUE;
+ aOldTextFillColor = GetTextFillColor();
+ }
+ else
+ bRestoreFillColor = FALSE;
+ SetTextColor( GetSettings().GetStyleSettings().GetLightColor() );
+ DrawText( Point( rPos.X()+1, rPos.Y()+1 ), aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX+1, nMnemonicY+1, cMnemonic );
+ }
+ SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ DrawText( rPos, aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ SetTextColor( aOldTextColor );
+ if ( bRestoreFillColor )
+ SetTextFillColor( aOldTextFillColor );
+ }
+ else
+ {
+ DrawText( rPos, aStr, nIndex, nLen );
+ if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) )
+ {
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, cMnemonic );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::GetCtrlTextWidth( const XubString& rStr,
+ xub_StrLen nIndex, xub_StrLen nLen,
+ USHORT nStyle ) const
+{
+ DBG_TRACE( "OutputDevice::GetCtrlTextSize()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( nStyle & TEXT_DRAW_MNEMONIC )
+ {
+ xub_StrLen nMnemonicPos;
+ XubString aStr = GetNonMnemonicString( rStr, nMnemonicPos );
+ if ( nMnemonicPos != STRING_NOTFOUND )
+ {
+ if ( nMnemonicPos < nIndex )
+ nIndex--;
+ else if ( (nLen < STRING_LEN) &&
+ (nMnemonicPos >= nIndex) && (nMnemonicPos < (ULONG)(nIndex+nLen)) )
+ nLen--;
+ }
+ return GetTextWidth( aStr, nIndex, nLen );
+ }
+ else
+ return GetTextWidth( rStr, nIndex, nLen );
+}
+
+// -----------------------------------------------------------------------
+
+XubString OutputDevice::GetNonMnemonicString( const XubString& rStr, xub_StrLen& rMnemonicPos )
+{
+ XubString aStr = rStr;
+ xub_StrLen nLen = aStr.Len();
+ xub_StrLen i = 0;
+
+ rMnemonicPos = STRING_NOTFOUND;
+ while ( i < nLen )
+ {
+ if ( aStr.GetChar( i ) == '~' )
+ {
+ if ( aStr.GetChar( i+1 ) != '~' )
+ {
+ if ( rMnemonicPos == STRING_NOTFOUND )
+ rMnemonicPos = i;
+ aStr.Erase( i, 1 );
+ nLen--;
+ }
+ else
+ {
+ aStr.Erase( i, 1 );
+ nLen--;
+ i++;
+ }
+ }
+ else
+ i++;
+ }
+
+ return aStr;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetDevFontCount() const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Wenn wir schon eine Liste der Fonts haben, dann nicht iterieren
+ if ( mpGetDevFontList )
+ return (USHORT)mpGetDevFontList->Count();
+
+ ((OutputDevice*)this)->mpGetDevFontList = new ImplGetDevFontList;
+
+ // Fill Fontlist
+ ImplDevFontListData* pFontListData = mpFontList->First();
+ while ( pFontListData )
+ {
+ ImplFontData* pLastData = NULL;
+ ImplFontData* pData = pFontListData->mpFirst;
+ while ( pData )
+ {
+ // Compare with the last font, because we wan't in the list
+ // only fonts, that have different attributes, but not
+ // different sizes
+ if ( !pLastData ||
+ (ImplCompareFontDataWithoutSize( pLastData, pData ) != 0) )
+ mpGetDevFontList->Add( pData );
+
+ pLastData = pData;
+ pData = pData->mpNext;
+ }
+
+ pFontListData = mpFontList->Next();
+ }
+
+ return (USHORT)mpGetDevFontList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo OutputDevice::GetDevFont( USHORT nDevFont ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFont()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ FontInfo aFontInfo;
+ USHORT nCount = GetDevFontCount();
+
+ // Wertebereich ueberpruefen
+ if ( nDevFont < nCount )
+ {
+ ImplFontData* pData = mpGetDevFontList->Get( nDevFont );
+ aFontInfo.SetName( pData->maName );
+ aFontInfo.SetStyleName( pData->maStyleName );
+// !!! UNICODE !!! aFontInfo.SetCharSet( ImplGetFakeEncoding( pData->meCharSet ) );
+ aFontInfo.SetCharSet( pData->meCharSet );
+ aFontInfo.SetFamily( pData->meFamily );
+ aFontInfo.SetPitch( pData->mePitch );
+ aFontInfo.SetWeight( pData->meWeight );
+ aFontInfo.SetItalic( pData->meItalic );
+ aFontInfo.mpImplMetric->meType = pData->meType;
+ aFontInfo.mpImplMetric->mbDevice = pData->mbDevice;
+ }
+
+ return aFontInfo;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT OutputDevice::GetDevFontSizeCount( const Font& rFont ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontSizeCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ XubString aFontName = rFont.GetName();
+
+ // Wenn die Liste schon existiert und der FontName sich nicht
+ // unterscheidet, dann brauchen wir Sie nicht neu erzeugen
+ if ( mpGetDevSizeList )
+ {
+ if ( mpGetDevSizeList->GetFontName() == aFontName )
+ return (USHORT)mpGetDevSizeList->Count();
+ else
+ {
+ mpGetDevSizeList->Clear();
+ mpGetDevSizeList->SetFontName( aFontName );
+ }
+ }
+ else
+ ((OutputDevice*)this)->mpGetDevSizeList = new ImplGetDevSizeList( aFontName );
+
+ // Fonts aus unserer Fontliste in die GetDevFontSizeListe eintragen
+ ImplDevFontListData* pFontListData = mpFontList->FindFont( aFontName );
+ if ( pFontListData )
+ {
+ ImplFontData* pData = pFontListData->mpFirst;
+ do
+ {
+ mpGetDevSizeList->Add( pData->mnHeight );
+ pData = pData->mpNext;
+ }
+ while ( pData );
+ }
+
+ return (USHORT)mpGetDevSizeList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::GetDevFontSize( const Font& rFont, USHORT nSize ) const
+{
+ DBG_TRACE( "OutputDevice::GetDevFontSize()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ USHORT nCount = GetDevFontSizeCount( rFont );
+
+ // Wertebereich ueberpruefen
+ if ( nSize >= nCount )
+ return Size();
+
+ // Wenn MapMode gesetzt ist, wird auf ,5-Points gerundet
+ Size aSize( 0, mpGetDevSizeList->Get( nSize ) );
+ if ( mbMap )
+ {
+ aSize.Height() *= 10;
+ MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
+ aSize = PixelToLogic( aSize, aMap );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ long nRound = aSize.Height() % 5;
+ if ( nRound >= 3 )
+ aSize.Height() += (5-nRound);
+ else
+ aSize.Height() -= nRound;
+ aSize.Height() *= 10;
+ aSize = LogicToPixel( aSize, aMap );
+ aSize = PixelToLogic( aSize );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ }
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::IsFontAvailable( const XubString& rFontName ) const
+{
+ DBG_TRACE( "OutputDevice::IsFontAvailable()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ return (mpFontList->FindFont( rFontName ) != 0);
+}
+
+// -----------------------------------------------------------------------
+
+FontMetric OutputDevice::GetFontMetric() const
+{
+ DBG_TRACE( "OutputDevice::GetFontMetric()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ FontMetric aMetric;
+
+ if ( mbNewFont )
+ {
+ if ( !((OutputDevice*)this)->ImplNewFont() )
+ return aMetric;
+ }
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplFontMetricData* pMetric = &(pEntry->maMetric);
+
+ // Mappen und StarView Struktur fuellen
+ aMetric.Font::operator=( maFont );
+
+ // Fontdaten ermitteln und setzen
+ aMetric.SetName( pMetric->maName );
+ aMetric.SetStyleName( pMetric->maStyleName );
+ aMetric.SetSize( PixelToLogic( Size( pMetric->mnWidth, pMetric->mnAscent+pMetric->mnDescent-pMetric->mnLeading ) ) );
+ aMetric.SetCharSet( pMetric->meCharSet );
+ aMetric.SetFamily( pMetric->meFamily );
+ aMetric.SetPitch( pMetric->mePitch );
+ aMetric.SetWeight( pMetric->meWeight );
+ aMetric.SetItalic( pMetric->meItalic );
+ if ( pEntry->mnOwnOrientation )
+ aMetric.SetOrientation( pEntry->mnOwnOrientation );
+ else
+ aMetric.SetOrientation( pMetric->mnOrientation );
+ if ( !mbKerning )
+ aMetric.SetKerning( FALSE );
+
+ // restliche Metricen setzen
+ aMetric.mpImplMetric->meType = pMetric->meType;
+ aMetric.mpImplMetric->mbDevice = pMetric->mbDevice;
+ aMetric.mpImplMetric->mnAscent = ImplDevicePixelToLogicHeight( pMetric->mnAscent );
+ aMetric.mpImplMetric->mnDescent = ImplDevicePixelToLogicHeight( pMetric->mnDescent );
+ aMetric.mpImplMetric->mnLeading = ImplDevicePixelToLogicHeight( pMetric->mnLeading );
+ aMetric.mpImplMetric->mnLineHeight = ImplDevicePixelToLogicHeight( pMetric->mnAscent+pMetric->mnDescent );
+ aMetric.mpImplMetric->mnSlant = ImplDevicePixelToLogicHeight( pMetric->mnSlant );
+ aMetric.mpImplMetric->mnFirstChar = pMetric->mnFirstChar;
+ aMetric.mpImplMetric->mnLastChar = pMetric->mnLastChar;
+
+ return aMetric;
+}
+
+// -----------------------------------------------------------------------
+
+FontMetric OutputDevice::GetFontMetric( const Font& rFont ) const
+{
+ // Uebergebenen Font selektieren, Metric abfragen und alten wieder
+ // selektieren
+ Font aOldFont = GetFont();
+ ((OutputDevice*)this)->SetFont( rFont );
+ FontMetric aMetric( GetFontMetric() );
+ ((OutputDevice*)this)->SetFont( aOldFont );
+ return aMetric;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG OutputDevice::GetKerningPairCount() const
+{
+ DBG_TRACE( "OutputDevice::GetKerningPairCount()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ ((OutputDevice*)this)->ImplInitKerningPairs();
+ return mpFontEntry->mnKernPairs;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::GetKerningPairs( ULONG nPairs, KerningPair* pKernPairs ) const
+{
+ DBG_TRACE( "OutputDevice::GetKerningPairs()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ ((OutputDevice*)this)->ImplInitKerningPairs();
+ if ( nPairs > mpFontEntry->mnKernPairs )
+ nPairs = mpFontEntry->mnKernPairs;
+ if ( nPairs )
+ memcpy( pKernPairs, mpFontEntry->mpKernPairs, nPairs*sizeof( KerningPair ) );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::GetGlyphBoundRect( xub_Unicode cChar, Rectangle& rRect, BOOL bOptimize )
+{
+ DBG_TRACE( "OutputDevice::GetGlyphBoundRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ Font* pOldFont;
+ long nLeft, nTop, nWidth, nHeight;
+ long nFontWidth, nFontHeight;
+ long nOrgWidth, nOrgHeight;
+
+ if ( bOptimize )
+ {
+ pOldFont = new Font( GetFont() );
+
+ Font aFont( *pOldFont );
+ Size aFontSize( LogicToPixel( aFont.GetSize() ) );
+
+ if ( aFontSize.Width() && aFontSize.Height() )
+ {
+ const double fFactor = (double) aFontSize.Width() / aFontSize.Height();
+
+ if ( fFactor < 1.0 )
+ {
+ aFontSize.Width() = FRound( fFactor * 500. );
+ aFontSize.Height() = 500;
+ }
+ else
+ {
+ aFontSize.Width() = 500;
+ aFontSize.Height() = FRound( 500. / fFactor );
+ }
+
+ aFont.SetSize( PixelToLogic( aFontSize ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = aFont.GetSize().Width();
+ nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = pOldFont->GetSize().Width();
+ nOrgHeight = pOldFont->GetSize().Height();
+ }
+ else
+ {
+ aFont.SetSize( PixelToLogic( Size( 0, 500 ) ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = nOrgHeight = pOldFont->GetSize().Height();
+ }
+ }
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ if ( mpGraphics->GetGlyphBoundRect( cChar, &nLeft, &nTop, &nWidth, &nHeight ) )
+ {
+ if ( bOptimize )
+ {
+ nLeft = ImplDevicePixelToLogicWidth( nLeft ) * nOrgWidth / nFontWidth;
+ nTop = ImplDevicePixelToLogicHeight( nTop ) * nOrgHeight / nFontHeight;
+ nWidth = ImplDevicePixelToLogicWidth( nWidth ) * nOrgWidth / nFontWidth;
+ nHeight = ImplDevicePixelToLogicHeight( nHeight ) * nOrgHeight / nFontHeight;
+ }
+ else
+ {
+ nLeft = ImplDevicePixelToLogicWidth( nLeft );
+ nTop = ImplDevicePixelToLogicHeight( nTop );
+ nWidth = ImplDevicePixelToLogicWidth( nWidth );
+ nHeight = ImplDevicePixelToLogicHeight( nHeight );
+ }
+
+ rRect = Rectangle( Point( nLeft, nTop ), Size( nWidth, nHeight ) );
+ bRet = TRUE;
+ }
+
+ if ( bOptimize )
+ {
+ ((OutputDevice*)this)->SetFont( *pOldFont );
+ delete pOldFont;
+ }
+
+ if ( !bRet && (OUTDEV_PRINTER != meOutDevType) )
+ {
+ if ( bOptimize )
+ {
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+ }
+
+ VirtualDevice* pVDev = new VirtualDevice( 1 );
+ long nWidth = ImplGetTextWidth( &cChar, 1, NULL );
+ long nHeight = mpFontEntry->mnLineHeight;
+ Point aOffset( nWidth >> 1, 8 );
+ Size aSize( nWidth + ( aOffset.X() << 1 ), nHeight + ( aOffset.Y() << 1 ) );
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Font aFont( GetFont() );
+ Bitmap aBmp;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( Size( mpFontEntry->maFontSelData.mnWidth, mpFontEntry->maFontSelData.mnHeight ) );
+
+ pVDev->SetFont( aFont );
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+ pVDev->ImplDrawText( aOffset.X(), aOffset.Y(), &cChar, 1, NULL );
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ delete pVDev;
+
+ BitmapReadAccess* pAcc = aBmp.AcquireReadAccess();
+
+ if ( pAcc )
+ {
+ const long nW = pAcc->Width();
+ const long nW1 = nW - 1L;
+ const long nH = pAcc->Height();
+ long nRight, nBottom;
+ const BitmapColor aBlack( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ BOOL bLineDone;
+
+ nLeft = nW;
+ nTop = nH;
+ nRight = nBottom = -1L;
+
+ for( long nY = 0L; nY < nH; nY++ )
+ {
+ bLineDone = FALSE;
+
+ for( long nX = 0L; ( nX < nW ) && !bLineDone; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ) == aBlack )
+ {
+ // find y minimum
+ if( nY < nTop )
+ nTop = nY;
+
+ // find y maximum
+ if( nY > nBottom )
+ nBottom = nY;
+
+ // find x minimum
+ if( nX < nLeft )
+ nLeft = nX;
+
+ // find x maximum (last pixel in line)
+ for( long nX2 = nW1; nX2 >= nX; nX2-- )
+ {
+ if( pAcc->GetPixel( nY, nX2 ) == aBlack )
+ {
+ if( nX2 > nRight )
+ nRight = nX2;
+
+ bLineDone = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( nLeft < nW && nTop < nH && nRight > -1L && nBottom > -1L )
+ {
+ nLeft -= aOffset.X(), nTop -= aOffset.Y();
+ nRight -= aOffset.X(), nBottom -= aOffset.Y();
+
+ nWidth = ImplDevicePixelToLogicWidth( nRight - nLeft + 1L );
+ nHeight = ImplDevicePixelToLogicHeight( nBottom - nTop + 1L );
+ nLeft = ImplDevicePixelToLogicWidth( nLeft );
+ nTop = ImplDevicePixelToLogicHeight( nTop );
+ rRect = Rectangle( Point( nLeft, nTop ), Size( nWidth, nHeight ) );
+ bRet = TRUE;
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ }
+ }
+ else
+ delete pVDev;
+ }
+ }
+#else
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ bRet = mpGraphics->GetGlyphBoundRect( cChar, rRect, bOptimize );
+
+ if ( bRet )
+ {
+ rRect = Rectangle( Point( ImplDevicePixelToLogicWidth( rRect.Left() ),
+ ImplDevicePixelToLogicHeight( rRect.Top() ) ),
+ Size( ImplDevicePixelToLogicWidth( rRect.GetWidth() ),
+ ImplDevicePixelToLogicHeight( rRect.GetHeight() ) ) );
+ }
+
+#endif
+
+ if ( !bRet )
+ rRect.SetEmpty();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL OutputDevice::GetGlyphOutline( xub_Unicode cChar, PolyPolygon& rPolyPoly, BOOL bOptimize )
+{
+ DBG_TRACE( "OutputDevice::GetGlyphOutline()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRet = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpGraphics || ImplGetGraphics() )
+ {
+ Font* pOldFont;
+ USHORT* pPolySizes = NULL;
+ SalPoint* pPoints = NULL;
+ BYTE* pFlags = NULL;
+ long nFontWidth, nFontHeight;
+ long nOrgWidth, nOrgHeight;
+ ULONG nPolyCount;
+
+ if ( bOptimize )
+ {
+ pOldFont = new Font( GetFont() );
+
+ Font aFont( *pOldFont );
+ Size aFontSize( LogicToPixel( aFont.GetSize() ) );
+
+ if ( aFontSize.Width() && aFontSize.Height() )
+ {
+ const double fFactor = (double) aFontSize.Width() / aFontSize.Height();
+
+ if ( fFactor < 1.0 )
+ {
+ aFontSize.Width() = FRound( fFactor * 500. );
+ aFontSize.Height() = 500;
+ }
+ else
+ {
+ aFontSize.Width() = 500;
+ aFontSize.Height() = FRound( 500. / fFactor );
+ }
+
+ aFont.SetSize( PixelToLogic( aFontSize ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = aFont.GetSize().Width();
+ nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = pOldFont->GetSize().Width();
+ nOrgHeight = pOldFont->GetSize().Height();
+ }
+ else
+ {
+ aFont.SetSize( PixelToLogic( Size( 0, 500 ) ) );
+ ((OutputDevice*)this)->SetFont( aFont );
+ nFontWidth = nFontHeight = aFont.GetSize().Height();
+ nOrgWidth = nOrgHeight = pOldFont->GetSize().Height();
+ }
+ }
+
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ nPolyCount = mpGraphics->GetGlyphOutline( cChar, &pPolySizes, &pPoints, &pFlags );
+ if ( nPolyCount && pPolySizes && pPoints && pFlags )
+ {
+ ULONG nTotalPos = 0UL;
+
+ rPolyPoly.Clear();
+
+ for( ULONG i = 0UL; i < nPolyCount; i++ )
+ {
+ const USHORT nSize = pPolySizes[ i ];
+
+ if( nSize )
+ {
+ Polygon aPoly( nSize );
+ Point* pPt = aPoly.ImplGetPointAry();
+ BYTE* pFl = aPoly.ImplGetFlagAry();
+
+ memcpy( pFl, pFlags + nTotalPos, nSize );
+
+ for( USHORT n = 0; n < nSize; n++ )
+ {
+ const SalPoint& rSalPt = pPoints[ nTotalPos++ ];
+ Point& rPt = pPt[ n ];
+
+ if( bOptimize )
+ {
+ rPt.X() = ImplDevicePixelToLogicWidth( rSalPt.mnX ) *
+ nOrgWidth / nFontWidth;
+ rPt.Y() = ImplDevicePixelToLogicHeight( rSalPt.mnY ) *
+ nOrgHeight / nFontHeight;
+ }
+ else
+ {
+ rPt.X() = ImplDevicePixelToLogicWidth( rSalPt.mnX );
+ rPt.Y() = ImplDevicePixelToLogicHeight( rSalPt.mnY );
+ }
+ }
+
+ rPolyPoly.Insert( aPoly );
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ delete[] pPolySizes;
+ delete[] pPoints;
+ delete[] pFlags;
+
+ if ( bOptimize )
+ {
+ ((OutputDevice*)this)->SetFont( *pOldFont );
+ delete pOldFont;
+ }
+
+ if ( !bRet && (OUTDEV_PRINTER != meOutDevType) )
+ {
+ if ( bOptimize )
+ {
+ if( mbNewFont )
+ ImplNewFont();
+ if( mbInitFont )
+ ImplInitFont();
+ }
+
+ Font aFont( GetFont() );
+ VirtualDevice* pVDev = new VirtualDevice( 1 );
+ const Size aFontSize( pVDev->LogicToPixel( Size( 0, GLYPH_FONT_HEIGHT ), MAP_POINT ) );
+ const long nOrgWidth = ImplGetTextWidth( &cChar, 1, NULL );
+ const long nOrgHeight = mpFontEntry->mnLineHeight;
+
+ aFont.SetShadow( FALSE );
+ aFont.SetOutline( FALSE );
+ aFont.SetOrientation( 0 );
+ aFont.SetSize( aFontSize );
+ pVDev->SetFont( aFont );
+ pVDev->SetTextAlign( ALIGN_TOP );
+ pVDev->SetTextColor( Color( COL_BLACK ) );
+ pVDev->SetTextFillColor();
+ pVDev->ImplNewFont();
+ pVDev->ImplInitFont();
+ pVDev->ImplInitTextColor();
+
+ const long nWidth = pVDev->ImplGetTextWidth( &cChar, 1, NULL );
+ const long nHeight = pVDev->mpFontEntry->mnLineHeight;
+ const Point aOffset( nWidth >> 1, 8 );
+ const Size aSize( nWidth + ( aOffset.X() << 1 ), nHeight + ( aOffset.Y() << 1 ) );
+ const double fScaleX = ( nOrgWidth && nWidth ) ? ( (double) nOrgWidth / nWidth ) : 0.0;
+ const double fScaleY = ( nOrgHeight && nHeight ) ? ( (double) nOrgHeight / nHeight ) : 0.0;
+
+ if ( pVDev->SetOutputSizePixel( aSize ) )
+ {
+ Bitmap aBmp;
+
+ pVDev->ImplDrawText( aOffset.X(), aOffset.Y(), &cChar, 1, NULL );
+ aBmp = pVDev->GetBitmap( Point(), aSize );
+ delete pVDev;
+
+ if( aBmp.Vectorize( rPolyPoly, BMP_VECTORIZE_OUTER | BMP_VECTORIZE_REDUCE_EDGES ) )
+ {
+ const long nOffX = aOffset.X(), nOffY = aOffset.Y();
+
+ for( USHORT i = 0UL, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ Polygon& rPoly = rPolyPoly[ i ];
+
+ for( USHORT n = 0, nSize = rPoly.GetSize(); n < nSize; n++ )
+ {
+ Point& rPt = rPoly[ n ];
+ rPt.X() = FRound( ImplDevicePixelToLogicWidth( rPt.X() - nOffX ) * fScaleX );
+ rPt.Y() = FRound( ImplDevicePixelToLogicHeight( rPt.Y() - nOffY ) * fScaleY );
+ }
+ }
+
+ bRet = TRUE;
+ }
+ }
+ else
+ delete pVDev;
+ }
+ }
+#else
+ if ( mbNewFont )
+ ImplNewFont();
+ if ( mbInitFont )
+ ImplInitFont();
+
+ bRet = mpGraphics->GetGlyphOutline( cChar, rPolyPoly, bOptimize );
+
+ if( bRet )
+ {
+ for( USHORT i = 0UL, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ Polygon& rPoly = rPolyPoly[ i ];
+
+ for( USHORT n = 0, nSize = rPoly.GetSize(); n < nSize; n++ )
+ {
+ Point& rPt = rPoly[ n ];
+ rPt.X() = ImplDevicePixelToLogicWidth( rPt.X() );
+ rPt.Y() = ImplDevicePixelToLogicHeight( rPt.Y() );
+ }
+ }
+ }
+
+#endif
+
+ if( !bRet )
+ rPolyPoly = PolyPolygon();
+
+ return bRet;
+}
diff --git a/vcl/source/gdi/outdev4.cxx b/vcl/source/gdi/outdev4.cxx
new file mode 100644
index 000000000000..fc8e313b825d
--- /dev/null
+++ b/vcl/source/gdi/outdev4.cxx
@@ -0,0 +1,1634 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+
+#include <math.h>
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_LINE_HXX
+#include <line.hxx>
+#endif
+#ifndef _SV_HATCH_HXX
+#include <hatch.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define HATCH_MAXPOINTS 1024
+#define GRADIENT_DEFAULT_STEPCOUNT 0
+
+// ----------------
+// - Cmp-Function -
+// ----------------
+
+extern "C" int __LOADONCALLAPI ImplHatchCmpFnc( const void* p1, const void* p2 )
+{
+ const long nX1 = ( (Point*) p1 )->X();
+ const long nX2 = ( (Point*) p2 )->X();
+ const long nY1 = ( (Point*) p1 )->Y();
+ const long nY2 = ( (Point*) p2 )->Y();
+
+ return ( nX1 > nX2 ? 1 : nX1 == nX2 ? nY1 > nY2 ? 1: nY1 == nY2 ? 0 : -1 : -1 );
+}
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Gradient );
+
+// =======================================================================
+
+#ifndef REMOTE_APPSERVER
+
+void OutputDevice::ImplDrawPolygon( const Polygon& rPoly )
+{
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ const SalPoint* pPtAry = (const SalPoint*)rPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nPoints, pPtAry );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ USHORT nPoly = rPolyPoly.Count();
+
+ if ( !nPoly )
+ return;
+
+ if ( nPoly == 1 )
+ {
+ const Polygon rPoly = rPolyPoly.GetObject( 0 );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)rPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolygon( nSize, pPtAry );
+ }
+ }
+ else
+ {
+ ULONG* pPointAry = new ULONG[nPoly];
+ PCONSTSALPOINT* pPointAryAry = new PCONSTSALPOINT[nPoly];
+ USHORT i = 0;
+ do
+ {
+ const Polygon& rPoly = rPolyPoly.GetObject( i );
+ USHORT nSize = rPoly.GetSize();
+ if ( nSize )
+ {
+ pPointAry[i] = nSize;
+ pPointAryAry[i] = (PCONSTSALPOINT)rPoly.ImplGetConstPointAry();
+ i++;
+ }
+ else
+ nPoly--;
+ }
+ while ( i < nPoly );
+
+ if ( nPoly == 1 )
+ mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry );
+ else
+ mpGraphics->DrawPolyPolygon( nPoly, pPointAry, pPointAryAry );
+
+ delete pPointAry;
+ delete pPointAryAry;
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+inline UINT8 ImplGetGradientColorValue( long nValue )
+{
+ if ( nValue < 0 )
+ return 0;
+ else if ( nValue > 0xFF )
+ return 0xFF;
+ else
+ return (UINT8)nValue;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawLinearGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // rotiertes BoundRect ausrechnen
+ Rectangle aRect = rRect;
+ aRect.Left()--;
+ aRect.Top()--;
+ aRect.Right()++;
+ aRect.Bottom()++;
+ USHORT nAngle = rGradient.GetAngle();
+ double fAngle = (nAngle % 3600) * F_PI1800;
+ double fWidth = aRect.GetWidth();
+ double fHeight = aRect.GetHeight();
+ double fDX = fWidth * fabs( cos( fAngle ) ) +
+ fHeight * fabs( sin( fAngle ) );
+ double fDY = fHeight * fabs( cos( fAngle ) ) +
+ fWidth * fabs( sin( fAngle ) );
+ fDX = (fDX - fWidth) * 0.5 + 0.5;
+ fDY = (fDY - fHeight) * 0.5 + 0.5;
+ aRect.Left() -= (long)fDX;
+ aRect.Right() += (long)fDX;
+ aRect.Top() -= (long)fDY;
+ aRect.Bottom() += (long)fDY;
+
+ // Rand berechnen und Rechteck neu setzen
+ Point aCenter = rRect.Center();
+ Rectangle aFullRect = aRect;
+ long nBorder = (long)rGradient.GetBorder() * aRect.GetHeight() / 100;
+ BOOL bLinear;
+
+ // Rand berechnen und Rechteck neu setzen fuer linearen Farbverlauf
+ if ( rGradient.GetStyle() == GRADIENT_LINEAR )
+ {
+ bLinear = TRUE;
+ aRect.Top() += nBorder;
+ }
+ // Rand berechnen und Rechteck neu setzen fuer axiale Farbverlauf
+ else
+ {
+ bLinear = FALSE;
+ nBorder >>= 1;
+
+ aRect.Top() += nBorder;
+ aRect.Bottom() -= nBorder;
+ }
+
+ // Top darf nicht groesser als Bottom sein
+ aRect.Top() = Min( aRect.Top(), (long)(aRect.Bottom() - 1) );
+
+ long nMinRect = aRect.GetHeight();
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Bei nicht linearen Farbverlaeufen haben wir nur die halben Steps
+ // pro Farbe
+ if ( !bLinear )
+ {
+ nRedSteps <<= 1;
+ nGreenSteps <<= 1;
+ nBlueSteps <<= 1;
+ }
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Falls axialer Farbverlauf, muss die Schrittanzahl ungerade sein
+ if ( !bLinear && !(nSteps & 1) )
+ nSteps++;
+
+ // Berechnung ueber Double-Addition wegen Genauigkeit
+ double fScanLine = aRect.Top();
+ double fScanInc = (double)aRect.GetHeight() / (double)nSteps;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed;
+ UINT8 nGreen;
+ UINT8 nBlue;
+ long nSteps2;
+ long nStepsHalf;
+ if ( bLinear )
+ {
+ // Um 1 erhoeht, um die Border innerhalb der Schleife
+ // zeichnen zu koennen
+ nSteps2 = nSteps + 1;
+ nRed = (UINT8)nStartRed;
+ nGreen = (UINT8)nStartGreen;
+ nBlue = (UINT8)nStartBlue;
+ }
+ else
+ {
+ // Um 2 erhoeht, um die Border innerhalb der Schleife
+ // zeichnen zu koennen
+ nSteps2 = nSteps + 2;
+ nRed = (UINT8)nEndRed;
+ nGreen = (UINT8)nEndGreen;
+ nBlue = (UINT8)nEndBlue;
+ nStepsHalf = nSteps >> 1;
+ }
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Startpolygon erzeugen (== Borderpolygon)
+ Polygon aPoly( 4 );
+ Polygon aTempPoly( 2 );
+ aPoly[0] = aFullRect.TopLeft();
+ aPoly[1] = aFullRect.TopRight();
+ aPoly[2] = aRect.TopRight();
+ aPoly[3] = aRect.TopLeft();
+ aPoly.Rotate( aCenter, nAngle );
+
+ // Schleife, um rotierten Verlauf zu fuellen
+ for ( long i = 0; i < nSteps2; i++ )
+ {
+ // berechnetesPolygon ausgeben
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( aPoly );
+#endif
+
+ // neues Polygon berechnen
+ aRect.Top() = (long)(fScanLine += fScanInc);
+
+ // unteren Rand komplett fuellen
+ if ( i == nSteps )
+ {
+ aTempPoly[0] = aFullRect.BottomLeft();
+ aTempPoly[1] = aFullRect.BottomRight();
+ }
+ else
+ {
+ aTempPoly[0] = aRect.TopLeft();
+ aTempPoly[1] = aRect.TopRight();
+ }
+ aTempPoly.Rotate( aCenter, nAngle );
+
+ aPoly[0] = aPoly[3];
+ aPoly[1] = aPoly[2];
+ aPoly[2] = aTempPoly[1];
+ aPoly[3] = aTempPoly[0];
+
+ // Farbintensitaeten aendern...
+ // fuer lineare FV
+ if ( bLinear )
+ {
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps2) );
+ }
+ // fuer radiale FV
+ else
+ {
+ // fuer axiale FV muss die letzte Farbe der ersten
+ // Farbe entsprechen
+ if ( i > nSteps )
+ {
+ nRed = (UINT8)nEndRed;
+ nGreen = (UINT8)nEndGreen;
+ nBlue = (UINT8)nEndBlue;
+ }
+ else
+ {
+ if ( i <= nStepsHalf )
+ {
+ nRed = ImplGetGradientColorValue( nEndRed-((nRedSteps*i)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nEndGreen-((nGreenSteps*i)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nEndBlue-((nBlueSteps*i)/nSteps2) );
+ }
+ // genau die Mitte und hoeher
+ else
+ {
+ long i2 = i - nStepsHalf;
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i2)/nSteps2) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i2)/nSteps2) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i2)/nSteps2) );
+ }
+ }
+ }
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawRadialGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // Feststellen ob Ausgabe ueber Polygon oder PolyPolygon
+ // Bei Rasteroperationen ungleich Overpaint immer PolyPolygone,
+ // da es zu falschen Ergebnissen kommt, wenn man mehrfach uebereinander
+ // ausgibt
+ // Bei Druckern auch immer PolyPolygone, da nicht alle Drucker
+ // das Uebereinanderdrucken von Polygonen koennen
+ // Virtuelle Device werden auch ausgeklammert, da einige Treiber
+ // ansonsten zu langsam sind
+ PolyPolygon* pPolyPoly;
+ if ( (meRasterOp != ROP_OVERPAINT) || (meOutDevType != OUTDEV_WINDOW) || bMtf )
+ pPolyPoly = new PolyPolygon( 2 );
+ else
+ pPolyPoly = NULL;
+
+ // Radien-Berechnung fuer Kreisausgabe (Kreis schliesst Rechteck ein)
+ USHORT nAngle = rGradient.GetAngle();
+ Rectangle aFullRect = rRect;
+ Rectangle aRect = rRect;
+ long nZWidth = aRect.GetWidth() * (long)rGradient.GetOfsX() / 100;
+ long nZHeight= aRect.GetHeight() * (long)rGradient.GetOfsY() / 100;
+ Size aSize = aRect.GetSize();
+ Point aCenter( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
+ if ( rGradient.GetStyle() == GRADIENT_RADIAL )
+ {
+ aSize.Width() = (long)(0.5 + sqrt((double)aSize.Width()*(double)aSize.Width() +
+ (double)aSize.Height()*(double)aSize.Height()));
+ aSize.Height() = aSize.Width();
+ }
+ // Radien-Berechnung fuer Ellipse
+ else
+ {
+ aSize.Width() = (long)(0.5 + (double)aSize.Width() * 1.4142);
+ aSize.Height() = (long)(0.5 + (double)aSize.Height() * 1.4142);
+ }
+
+ // Border berechnen
+ long nBorderX = (long)rGradient.GetBorder() * aSize.Width() / 100;
+ long nBorderY = (long)rGradient.GetBorder() * aSize.Height() / 100;
+ aSize.Width() -= nBorderX;
+ aSize.Height() -= nBorderY;
+ aRect.Left() = aCenter.X() - (aSize.Width() >> 1);
+ aRect.Top() = aCenter.Y() - (aSize.Height() >> 1);
+ aRect.SetSize( aSize );
+
+ long nMinRect = Min( aRect.GetWidth(), aRect.GetHeight() );
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Ausgabebegrenzungen und Schrittweite fuer jede Richtung festlegen
+ double fScanLeft = aRect.Left();
+ double fScanTop = aRect.Top();
+ double fScanRight = aRect.Right();
+ double fScanBottom = aRect.Bottom();
+ double fScanInc = (double)nMinRect / (double)nSteps * 0.5;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed = (UINT8)nStartRed;
+ UINT8 nGreen = (UINT8)nStartGreen;
+ UINT8 nBlue = (UINT8)nStartBlue;
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Recteck erstmal ausgeben
+ aFullRect.Bottom()++;
+ aFullRect.Right()++;
+ Polygon aPoly( aFullRect );
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Schleife, um nacheinander die Polygone/PolyPolygone auszugeben
+ for ( long i = 0; i < nSteps; i++ )
+ {
+ // neues Polygon berechnen
+ aRect.Left() = (long)(fScanLeft += fScanInc);
+ aRect.Top() = (long)(fScanTop += fScanInc);
+ aRect.Right() = (long)(fScanRight -= fScanInc);
+ aRect.Bottom() = (long)(fScanBottom -= fScanInc);
+
+ if ( (aRect.GetWidth() < 2) || (aRect.GetHeight() < 2) )
+ break;
+
+ // ... Evt. eine maximale Anzahl von Stuetztstellen fuer W16
+ aPoly = Polygon( aRect.Center(),
+ aRect.GetWidth() >> 1,
+ aRect.GetHeight() >> 1 );
+ aPoly.Rotate( aCenter, nAngle );
+
+ // entweder langsame PolyPolygon-Ausgaben oder
+ // schnelles Polygon-Painting
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Farbe entsprechend anpassen
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps) );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+
+ // Falls PolyPolygon-Ausgabe, muessen wir noch ein letztes
+ // inneres Polygon zeichnen
+ if ( pPolyPoly )
+ {
+ const Polygon rPoly = pPolyPoly->GetObject( 1 );
+ if ( !rPoly.GetBoundRect().IsEmpty() )
+ {
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( rPoly );
+#endif
+ }
+ delete pPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawRectGradient( const Rectangle& rRect,
+ const Gradient& rGradient,
+ BOOL bMtf )
+{
+ // Feststellen ob Ausgabe ueber Polygon oder PolyPolygon
+ // Bei Rasteroperationen ungleich Overpaint immer PolyPolygone,
+ // da es zu falschen Ergebnissen kommt, wenn man mehrfach uebereinander
+ // ausgibt
+ // Bei Druckern auch immer PolyPolygone, da nicht alle Drucker
+ // das Uebereinanderdrucken von Polygonen koennen
+ // Virtuelle Device werden auch ausgeklammert, da einige Treiber
+ // ansonsten zu langsam sind
+ PolyPolygon* pPolyPoly;
+ if ( (meRasterOp != ROP_OVERPAINT) || (meOutDevType != OUTDEV_WINDOW) || bMtf )
+ pPolyPoly = new PolyPolygon( 2 );
+ else
+ pPolyPoly = NULL;
+
+ // rotiertes BoundRect ausrechnen
+ Rectangle aRect( rRect );
+ aRect.Left()--;
+ aRect.Top()--;
+ aRect.Right()++;
+ aRect.Bottom()++;
+
+ Rectangle aFullRect( aRect );
+ USHORT nAngle = rGradient.GetAngle();
+ double fAngle = (nAngle % 3600) * F_PI1800;
+ double fWidth = aRect.GetWidth();
+ double fHeight = aRect.GetHeight();
+ double fDX = fWidth * fabs( cos( fAngle ) ) +
+ fHeight * fabs( sin( fAngle ) );
+ double fDY = fHeight * fabs( cos( fAngle ) ) +
+ fWidth * fabs( sin( fAngle ) );
+ fDX = (fDX - fWidth) * 0.5 + 0.5;
+ fDY = (fDY - fHeight) * 0.5 + 0.5;
+ aRect.Left() -= (long)fDX;
+ aRect.Right() += (long)fDX;
+ aRect.Top() -= (long)fDY;
+ aRect.Bottom() += (long)fDY;
+
+ // Quadratisch machen, wenn angefordert;
+ Size aSize = aRect.GetSize();
+ if ( rGradient.GetStyle() == GRADIENT_SQUARE )
+ {
+ if ( aSize.Width() > aSize.Height() )
+ aSize.Height() = aSize.Width();
+ else
+ aSize.Width() = aSize.Height();
+ }
+
+ // neue Mittelpunkte berechnen
+ long nZWidth = aRect.GetWidth() * (long)rGradient.GetOfsX() / 100;
+ long nZHeight = aRect.GetHeight() * (long)rGradient.GetOfsY() / 100;
+ long nBorderX = (long)rGradient.GetBorder() * aSize.Width() / 100;
+ long nBorderY = (long)rGradient.GetBorder() * aSize.Height() / 100;
+ Point aCenter( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
+
+ // Rand beruecksichtigen
+ aSize.Width() -= nBorderX;
+ aSize.Height() -= nBorderY;
+
+ // Ausgaberechteck neu setzen
+ aRect.Left() = aCenter.X() - (aSize.Width() >> 1);
+ aRect.Top() = aCenter.Y() - (aSize.Height() >> 1);
+ aRect.SetSize( aSize );
+
+ long nMinRect = Min( aRect.GetWidth(), aRect.GetHeight() );
+
+ // Intensitaeten von Start- und Endfarbe ggf. aendern und
+ // Farbschrittweiten berechnen
+ long nFactor;
+ Color aStartCol = rGradient.GetStartColor();
+ Color aEndCol = rGradient.GetEndColor();
+ long nStartRed = aStartCol.GetRed();
+ long nStartGreen = aStartCol.GetGreen();
+ long nStartBlue = aStartCol.GetBlue();
+ long nEndRed = aEndCol.GetRed();
+ long nEndGreen = aEndCol.GetGreen();
+ long nEndBlue = aEndCol.GetBlue();
+ nFactor = rGradient.GetStartIntensity();
+ nStartRed = (nStartRed * nFactor) / 100;
+ nStartGreen = (nStartGreen * nFactor) / 100;
+ nStartBlue = (nStartBlue * nFactor) / 100;
+ nFactor = rGradient.GetEndIntensity();
+ nEndRed = (nEndRed * nFactor) / 100;
+ nEndGreen = (nEndGreen * nFactor) / 100;
+ nEndBlue = (nEndBlue * nFactor) / 100;
+ long nRedSteps = nEndRed - nStartRed;
+ long nGreenSteps = nEndGreen - nStartGreen;
+ long nBlueSteps = nEndBlue - nStartBlue;
+
+ // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
+ USHORT nStepCount = rGradient.GetSteps();
+ if ( !nStepCount )
+ {
+ long nInc;
+
+ if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
+ nInc = (nMinRect < 50) ? 2 : 4;
+ else
+ nInc = ((nMinRect >> 9) + 1) << 3;
+
+ if ( !nInc )
+ nInc = 1;
+
+ nStepCount = (USHORT)(nMinRect / nInc);
+ }
+ // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
+ long nSteps = Max( nStepCount, (USHORT)3 );
+ long nCalcSteps = Abs( nRedSteps );
+ long nTempSteps = Abs( nGreenSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ nTempSteps = Abs( nBlueSteps );
+ if ( nTempSteps > nCalcSteps )
+ nCalcSteps = nTempSteps;
+ if ( nCalcSteps < nSteps )
+ nSteps = nCalcSteps;
+ if ( !nSteps )
+ nSteps = 1;
+
+ // Ausgabebegrenzungen und Schrittweite fuer jede Richtung festlegen
+ double fScanLeft = aRect.Left();
+ double fScanTop = aRect.Top();
+ double fScanRight = aRect.Right();
+ double fScanBottom = aRect.Bottom();
+ double fScanInc = (double)nMinRect / (double)nSteps * 0.5;
+
+ // Startfarbe berechnen und setzen
+ UINT8 nRed = (UINT8)nStartRed;
+ UINT8 nGreen = (UINT8)nStartGreen;
+ UINT8 nBlue = (UINT8)nStartBlue;
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+
+ // Recteck erstmal ausgeben
+ Polygon aPoly( aFullRect );
+#ifndef REMOTE_APPSERVER
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Insert( aPoly );
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+ pPolyPoly->Insert( aPoly );
+
+ // erstes Polygon zeichnen (entspricht Rechteck)
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Schleife, um nacheinander die Polygone/PolyPolygone auszugeben
+ for ( long i = 0; i < nSteps; i++ )
+ {
+ // neues Polygon berechnen
+ aRect.Left() = (long)(fScanLeft += fScanInc);
+ aRect.Top() = (long)(fScanTop += fScanInc);
+ aRect.Right() = (long)(fScanRight -= fScanInc);
+ aRect.Bottom() = (long)(fScanBottom-= fScanInc);
+
+ if ( (aRect.GetWidth() < 2) || (aRect.GetHeight() < 2) )
+ break;
+
+ aPoly = Polygon( aRect );
+ aPoly.Rotate( aCenter, nAngle );
+
+#ifndef REMOTE_APPSERVER
+ // entweder langsame PolyPolygon-Ausgaben oder
+ // schnelles Polygon-Painting
+ if ( pPolyPoly )
+ {
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+ else
+ ImplDrawPolyPolygon( *pPolyPoly );
+ }
+ else
+ ImplDrawPolygon( aPoly );
+#else
+ pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
+ pPolyPoly->Replace( aPoly, 1 );
+ mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
+#endif
+
+ // Farbe entsprechend anpassen
+ nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps) );
+ nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps) );
+ nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps) );
+
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), TRUE ) );
+#ifndef REMOTE_APPSERVER
+ else
+ mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
+#endif
+ }
+
+ // Falls PolyPolygon-Ausgabe, muessen wir noch ein letztes
+ // inneres Polygon zeichnen
+ if ( pPolyPoly )
+ {
+ const Polygon rPoly = pPolyPoly->GetObject( 1 );
+ if ( !rPoly.GetBoundRect().IsEmpty() )
+ {
+ if ( bMtf )
+ mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
+#ifndef REMOTE_APPSERVER
+ else
+ ImplDrawPolygon( rPoly );
+#endif
+ }
+ delete pPolyPoly;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawGradient( const Rectangle& rRect,
+ const Gradient& rGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawGradient()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if ( mnDrawMode & DRAWMODE_NOGRADIENT )
+ return;
+ else if ( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawRect( rRect );
+ Pop();
+ return;
+ }
+
+ Gradient aGradient( rGradient );
+
+ if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
+ {
+ Color aStartCol( aGradient.GetStartColor() );
+ Color aEndCol( aGradient.GetEndColor() );
+
+ if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
+ {
+ BYTE cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
+ aStartCol = Color( cStartLum, cStartLum, cStartLum );
+ aEndCol = Color( cEndLum, cEndLum, cEndLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
+ {
+ aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
+ ( aStartCol.GetGreen() >> 1 ) | 0x80,
+ ( aStartCol.GetBlue() >> 1 ) | 0x80 );
+
+ aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
+ ( aEndCol.GetGreen() >> 1 ) | 0x80,
+ ( aEndCol.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aGradient.SetStartColor( aStartCol );
+ aGradient.SetEndColor( aEndCol );
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaGradientAction( rRect, aGradient ) );
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+ // Rechteck in Pixel umrechnen
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ aRect.Justify();
+
+ // Wenn Rechteck leer ist, brauchen wir nichts machen
+ if ( !aRect.IsEmpty() )
+ {
+#ifndef REMOTE_APPSERVER
+ // Clip Region sichern
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rRect );
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( !mbOutputClipped )
+ {
+ // Gradienten werden ohne Umrandung gezeichnet
+ if ( mbLineColor || mbInitLineColor )
+ {
+ mpGraphics->SetLineColor();
+ mbInitLineColor = TRUE;
+ }
+
+ mbInitFillColor = TRUE;
+
+ // calculate step count if neccessary
+ if ( !aGradient.GetSteps() )
+ aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
+
+ // Farbverlauf ausgeben
+ switch( aGradient.GetStyle() )
+ {
+ case GRADIENT_LINEAR:
+ case GRADIENT_AXIAL:
+ ImplDrawLinearGradient( aRect, aGradient, FALSE );
+ break;
+
+ case GRADIENT_RADIAL:
+ case GRADIENT_ELLIPTICAL:
+ ImplDrawRadialGradient( aRect, aGradient, FALSE );
+ break;
+
+ case GRADIENT_SQUARE:
+ case GRADIENT_RECT:
+ ImplDrawRectGradient( aRect, aGradient, FALSE );
+ break;
+ }
+ }
+
+ Pop();
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawGradient( aRect, aGradient );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
+ const Gradient& rGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawGradient()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ if( rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() && !( mnDrawMode & DRAWMODE_NOGRADIENT ) )
+ {
+ if( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT ) )
+ {
+ BYTE cCmpVal;
+
+ if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
+ cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT ) ? 0x80 : 0;
+ else
+ cCmpVal = 255;
+
+ Color aCol( cCmpVal, cCmpVal, cCmpVal );
+ Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ SetLineColor( aCol );
+ SetFillColor( aCol );
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ return;
+ }
+
+ if( mpMetaFile )
+ {
+ const Rectangle aRect( rPolyPoly.GetBoundRect() );
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rPolyPoly );
+ DrawGradient( aRect, rGradient );
+ Pop();
+ }
+ else
+ {
+ const BOOL bOldOutput = IsOutputEnabled();
+
+ EnableOutput( FALSE );
+ Push( PUSH_RASTEROP );
+ SetRasterOp( ROP_XOR );
+ DrawGradient( aRect, rGradient );
+ SetFillColor( COL_BLACK );
+ SetRasterOp( ROP_0 );
+ DrawPolyPolygon( rPolyPoly );
+ SetRasterOp( ROP_XOR );
+ DrawGradient( aRect, rGradient );
+ Pop();
+ EnableOutput( bOldOutput );
+ }
+ }
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+ Gradient aGradient( rGradient );
+
+ if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
+ {
+ Color aStartCol( aGradient.GetStartColor() );
+ Color aEndCol( aGradient.GetEndColor() );
+
+ if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
+ {
+ BYTE cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
+ aStartCol = Color( cStartLum, cStartLum, cStartLum );
+ aEndCol = Color( cEndLum, cEndLum, cEndLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
+ {
+ aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
+ ( aStartCol.GetGreen() >> 1 ) | 0x80,
+ ( aStartCol.GetBlue() >> 1 ) | 0x80 );
+
+ aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
+ ( aEndCol.GetGreen() >> 1 ) | 0x80,
+ ( aEndCol.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aGradient.SetStartColor( aStartCol );
+ aGradient.SetEndColor( aEndCol );
+ }
+
+#ifndef REMOTE_APPSERVER
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( rPolyPoly );
+ DrawGradient( rPolyPoly.GetBoundRect(), aGradient );
+ Pop();
+ }
+ else
+ {
+ const PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
+ const Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ aDstRect.Intersection( aBoundRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice aVDev;
+ const Size aDstSize( aDstRect.GetSize() );
+
+ if( aVDev.SetOutputSizePixel( aDstSize) )
+ {
+ MapMode aVDevMap;
+ const RasterOp eOldROP = GetRasterOp();
+ const BOOL bOldMap = mbMap;
+
+ mbMap = FALSE;
+
+ aVDev.DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
+ DrawGradient( aBoundRect, aGradient );
+ aVDev.SetRasterOp( ROP_XOR );
+ aVDev.DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
+ aVDev.SetFillColor( COL_BLACK );
+ aVDev.SetRasterOp( ROP_0 );
+ aVDevMap.SetOrigin( Point( -aDstRect.Left(), -aDstRect.Top() ) );
+ aVDev.SetMapMode( aVDevMap );
+ aVDev.DrawPolyPolygon( aPolyPoly );
+ aVDevMap.SetOrigin( Point() );
+ aVDev.SetMapMode( aVDevMap );
+ SetRasterOp( ROP_XOR );
+ DrawOutDev( aDstRect.TopLeft(), aDstSize, Point(), aDstSize, aVDev );
+ SetRasterOp( eOldROP );
+
+ mbMap = bOldMap;
+ }
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->DrawGradient( ImplLogicToDevicePixel( rPolyPoly ), aGradient );
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddGradientActions( const Rectangle& rRect, const Gradient& rGradient,
+ GDIMetaFile& rMtf )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rGradient, Gradient, NULL );
+
+ Rectangle aRect( rRect );
+
+ aRect.Justify();
+
+ // Wenn Rechteck leer ist, brauchen wir nichts machen
+ if ( !aRect.IsEmpty() )
+ {
+ Gradient aGradient( rGradient );
+ GDIMetaFile* pOldMtf = mpMetaFile;
+
+ mpMetaFile = &rMtf;
+ mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
+ mpMetaFile->AddAction( new MetaISectRectClipRegionAction( aRect ) );
+ mpMetaFile->AddAction( new MetaLineColorAction( Color(), FALSE ) );
+
+ // calculate step count if neccessary
+ if ( !aGradient.GetSteps() )
+ aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
+
+ // Farbverlaufactions aufzeichnen
+ switch( rGradient.GetStyle() )
+ {
+ case GRADIENT_LINEAR:
+ case GRADIENT_AXIAL:
+ ImplDrawLinearGradient( aRect, aGradient, TRUE );
+ break;
+
+ case GRADIENT_RADIAL:
+ case GRADIENT_ELLIPTICAL:
+ ImplDrawRadialGradient( aRect, aGradient, TRUE );
+ break;
+
+ case GRADIENT_SQUARE:
+ case GRADIENT_RECT:
+ ImplDrawRectGradient( aRect, aGradient, TRUE );
+ break;
+ }
+
+ mpMetaFile->AddAction( new MetaPopAction() );
+ mpMetaFile = pOldMtf;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch )
+{
+ DBG_TRACE( "OutputDevice::DrawHatch()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Hatch aHatch( rHatch );
+
+ if ( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
+ DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE ) )
+ {
+ Color aColor( rHatch.GetColor() );
+
+ if ( mnDrawMode & DRAWMODE_BLACKLINE )
+ aColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITELINE )
+ aColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYLINE )
+ {
+ const UINT8 cLum = aColor.GetLuminance();
+ aColor = Color( cLum, cLum, cLum );
+ }
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDLINE )
+ {
+ aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
+ ( aColor.GetGreen() >> 1 ) | 0x80,
+ ( aColor.GetBlue() >> 1 ) | 0x80);
+ }
+
+ aHatch.SetColor( aColor );
+ }
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaHatchAction( rPolyPoly, aHatch ) );
+
+ if( !IsDeviceOutputNecessary() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+#endif
+
+ PolyPolygon aPolyPoly( rPolyPoly );
+ aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME | POLY_OPTIMIZE_CLOSE );
+
+ if( aPolyPoly.Count() )
+ {
+#ifndef REMOTE_APPSERVER
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+
+ mpMetaFile = NULL;
+ Push( PUSH_LINECOLOR );
+ SetLineColor( aHatch.GetColor() );
+ ImplInitLineColor();
+ ImplDrawHatch( aPolyPoly, aHatch, FALSE );
+ Pop();
+ mpMetaFile = pOldMetaFile;
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ aHatch.SetDistance( ImplLogicWidthToDevicePixel( aHatch.GetDistance() ) );
+ pGraphics->DrawHatch( ImplLogicToDevicePixel( aPolyPoly ), aHatch );
+ }
+#endif
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::AddHatchActions( const PolyPolygon& rPolyPoly, const Hatch& rHatch,
+ GDIMetaFile& rMtf )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ PolyPolygon aPolyPoly( rPolyPoly );
+ aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME | POLY_OPTIMIZE_CLOSE );
+
+ if( aPolyPoly.Count() )
+ {
+ GDIMetaFile* pOldMtf = mpMetaFile;
+
+ mpMetaFile = &rMtf;
+ mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
+ mpMetaFile->AddAction( new MetaLineColorAction( rHatch.GetColor(), TRUE ) );
+ ImplDrawHatch( aPolyPoly, rHatch, TRUE );
+ mpMetaFile->AddAction( new MetaPopAction() );
+ mpMetaFile = pOldMtf;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch, BOOL bMtf )
+{
+ Rectangle aRect( rPolyPoly.GetBoundRect() );
+ const long nLogPixelWidth = ImplDevicePixelToLogicWidth( 1 );
+ const long nWidth = ImplDevicePixelToLogicWidth( Max( ImplLogicWidthToDevicePixel( rHatch.GetDistance() ), 5L ) );
+ Point* pPtBuffer = new Point[ HATCH_MAXPOINTS ];
+ Point aPt1, aPt2, aEndPt1;
+ Size aInc;
+
+ // Single hatch
+ aRect.Left() -= nLogPixelWidth; aRect.Top() -= nLogPixelWidth; aRect.Right() += nLogPixelWidth; aRect.Bottom() += nLogPixelWidth;
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle(), aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+
+ if( ( rHatch.GetStyle() == HATCH_DOUBLE ) || ( rHatch.GetStyle() == HATCH_TRIPLE ) )
+ {
+ // Double hatch
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 900, aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+
+ if( rHatch.GetStyle() == HATCH_TRIPLE )
+ {
+ // Triple hatch
+ ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 450, aPt1, aPt2, aInc, aEndPt1 );
+ do
+ {
+ ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
+ aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
+ aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
+ }
+ while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
+ }
+ }
+
+ delete[] pPtBuffer;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplCalcHatchValues( const Rectangle& rRect, long nDist, USHORT nAngle10,
+ Point& rPt1, Point& rPt2, Size& rInc, Point& rEndPt1 )
+{
+ Point aRef;
+ long nAngle = nAngle10 % 1800;
+ long nOffset = 0;
+
+ if( nAngle > 900 )
+ nAngle -= 1800;
+
+ aRef = ( !IsRefPoint() ? rRect.TopLeft() : GetRefPoint() );
+
+ if( 0 == nAngle )
+ {
+ rInc = Size( 0, nDist );
+ rPt1 = rRect.TopLeft();
+ rPt2 = rRect.TopRight();
+ rEndPt1 = rRect.BottomLeft();
+
+ if( aRef.Y() <= rRect.Top() )
+ nOffset = ( ( rRect.Top() - aRef.Y() ) % nDist );
+ else
+ nOffset = ( nDist - ( ( aRef.Y() - rRect.Top() ) % nDist ) );
+
+ rPt1.Y() -= nOffset;
+ rPt2.Y() -= nOffset;
+ }
+ else if( 900 == nAngle )
+ {
+ rInc = Size( nDist, 0 );
+ rPt1 = rRect.TopLeft();
+ rPt2 = rRect.BottomLeft();
+ rEndPt1 = rRect.TopRight();
+
+ if( aRef.X() <= rRect.Left() )
+ nOffset = ( rRect.Left() - aRef.X() ) % nDist;
+ else
+ nOffset = nDist - ( ( aRef.X() - rRect.Left() ) % nDist );
+
+ rPt1.X() -= nOffset;
+ rPt2.X() -= nOffset;
+ }
+ else if( nAngle >= -450 && nAngle <= 450 )
+ {
+ const double fAngle = F_PI1800 * labs( nAngle );
+ const double fTan = tan( fAngle );
+ const long nYOff = FRound( ( rRect.Right() - rRect.Left() ) * fTan );
+ long nPY;
+
+ rInc = Size( 0, nDist = FRound( nDist / cos( fAngle ) ) );
+
+ if( nAngle > 0 )
+ {
+ rPt1 = rRect.TopLeft();
+ rPt2 = Point( rRect.Right(), rRect.Top() - nYOff );
+ rEndPt1 = Point( rRect.Left(), rRect.Bottom() + nYOff );
+ nPY = FRound( aRef.Y() - ( ( rPt1.X() - aRef.X() ) * fTan ) );
+ }
+ else
+ {
+ rPt1 = rRect.TopRight();
+ rPt2 = Point( rRect.Left(), rRect.Top() - nYOff );
+ rEndPt1 = Point( rRect.Right(), rRect.Bottom() + nYOff );
+ nPY = FRound( aRef.Y() + ( ( rPt1.X() - aRef.X() ) * fTan ) );
+ }
+
+ if( nPY <= rPt1.Y() )
+ nOffset = ( rPt1.Y() - nPY ) % nDist;
+ else
+ nOffset = nDist - ( ( nPY - rPt1.Y() ) % nDist );
+
+ rPt1.Y() -= nOffset;
+ rPt2.Y() -= nOffset;
+ }
+ else
+ {
+ const double fAngle = F_PI1800 * labs( nAngle );
+ const double fTan = tan( fAngle );
+ const long nXOff = FRound( ( rRect.Bottom() - rRect.Top() ) / fTan );
+ long nPX;
+
+ rInc = Size( nDist = FRound( nDist / sin( fAngle ) ), 0 );
+
+ if( nAngle > 0 )
+ {
+ rPt1 = rRect.TopLeft();
+ rPt2 = Point( rRect.Left() - nXOff, rRect.Bottom() );
+ rEndPt1 = Point( rRect.Right() + nXOff, rRect.Top() );
+ nPX = FRound( aRef.X() - ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
+ }
+ else
+ {
+ rPt1 = rRect.BottomLeft();
+ rPt2 = Point( rRect.Left() - nXOff, rRect.Top() );
+ rEndPt1 = Point( rRect.Right() + nXOff, rRect.Bottom() );
+ nPX = FRound( aRef.X() + ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
+ }
+
+ if( nPX <= rPt1.X() )
+ nOffset = ( rPt1.X() - nPX ) % nDist;
+ else
+ nOffset = nDist - ( ( nPX - rPt1.X() ) % nDist );
+
+ rPt1.X() -= nOffset;
+ rPt2.X() -= nOffset;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::ImplDrawHatchLine( const Line& rLine, const PolyPolygon& rPolyPoly,
+ Point* pPtBuffer, BOOL bMtf )
+{
+#ifdef REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics;
+ if( !bMtf && !( pGraphics = ImplGetServerGraphics() ) )
+ return;
+#endif
+
+ double fSaveDist = 0.0;
+ long nPCounter = 0;
+
+ for( long nPoly = 0, nPolyCount = rPolyPoly.Count(); nPoly < nPolyCount; nPoly++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ (USHORT) nPoly ];
+
+ if( rPoly.GetSize() > 1 )
+ {
+ Point aIntersection;
+ Point aPt1( rPoly[0] );
+
+ for( long i = 1, nCount = rPoly.GetSize(); i < nCount; i++ )
+ {
+ const Point& rPt2 = rPoly[ (USHORT) i ];
+
+ if( rLine.Intersection( Line( aPt1, rPt2 ), aIntersection ) )
+ {
+ const BOOL bDifferent = !nPCounter || aIntersection != pPtBuffer[ nPCounter - 1 ];
+
+ if( aIntersection == aPt1 )
+ {
+ double fDist1 = rLine.GetDistance( rPoly[ ( i > 1 ) ? i - 2 : nCount - 2 ] );
+ double fDist2 = rLine.GetDistance( rPt2 );
+
+ if( 1 == i )
+ nCount--;
+
+ if( bDifferent )
+ {
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+
+ if( ( ( fDist1 < 0.0 && fDist2 < 0.0 ) || ( fDist1 > 0.0 && fDist2 > 0.0 ) ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ else if( fDist1 == 0.0 )
+ {
+ if( ( fSaveDist > 0.0 && fDist2 < 0.0 ) || ( fSaveDist < 0.0 && fDist2 > 0.0 ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ }
+ }
+ }
+ else if( aIntersection == rPt2 )
+ {
+ double fDist1 = rLine.GetDistance( aPt1 );
+ double fDist2 = rLine.GetDistance( rPoly[ ( i < nCount - 1 ) ? i + 1 : 1 ] );
+
+ if( bDifferent )
+ {
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+
+ if( ( ( fDist1 < 0.0 && fDist2 < 0.0 ) || ( fDist1 > 0.0 && fDist2 > 0.0 ) ) )
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ else if( fDist2 == 0.0 )
+ fSaveDist = fDist1;
+ }
+ }
+ else
+ pPtBuffer[ nPCounter++ ] = aIntersection;
+ }
+
+ aPt1 = rPt2;
+ }
+ }
+ }
+
+ if( nPCounter > 1 )
+ {
+ qsort( pPtBuffer, nPCounter, sizeof( Point ), ImplHatchCmpFnc );
+
+ if( nPCounter & 1 )
+ nPCounter--;
+
+ if( bMtf )
+ {
+ for( long i = 0; i < nPCounter; i += 2 )
+ mpMetaFile->AddAction( new MetaLineAction( pPtBuffer[ i ], pPtBuffer[ i + 1 ] ) );
+ }
+ else
+ {
+ for( long i = 0; i < nPCounter; i += 2 )
+ {
+ const Point aPt1( ImplLogicToDevicePixel( pPtBuffer[ i ] ) );
+ const Point aPt2( ImplLogicToDevicePixel( pPtBuffer[ i + 1 ] ) );
+
+#ifndef REMOTE_APPSERVER
+ mpGraphics->DrawLine( aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y() );
+#else
+ pGraphics->DrawLine( aPt1, aPt2 );
+#endif
+ }
+ }
+ }
+}
diff --git a/vcl/source/gdi/outdev5.cxx b/vcl/source/gdi/outdev5.cxx
new file mode 100644
index 000000000000..f162b1196fd1
--- /dev/null
+++ b/vcl/source/gdi/outdev5.cxx
@@ -0,0 +1,430 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev5.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_OUTDEV_CXX
+#include <tools/ref.hxx>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_OUTDATA_HXX
+#include <outdata.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// =======================================================================
+
+void OutputDevice::DrawRect( const Rectangle& rRect,
+ ULONG nHorzRound, ULONG nVertRound )
+{
+ DBG_TRACE( "OutputDevice::DrawRoundRect()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ const Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+
+ nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound );
+ nVertRound = ImplLogicHeightToDevicePixel( nVertRound );
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ if ( !nHorzRound && !nVertRound )
+ mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
+ else
+ {
+ const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound );
+
+ if ( aRoundRectPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.ImplGetConstPointAry();
+
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry );
+ else
+ mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ if ( !nHorzRound || !nVertRound )
+ pGraphics->DrawRect( aRect );
+ else
+ pGraphics->DrawRect( aRect, nHorzRound, nVertRound );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawEllipse( const Rectangle& rRect )
+{
+ DBG_TRACE( "OutputDevice::DrawEllipse()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaEllipseAction( rRect ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ Polygon aRectPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
+ if ( aRectPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aRectPoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aRectPoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aRectPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawEllipse( aRect );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawArc( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawArc()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaArcAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || !mbLineColor )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aArcPoly( aRect, aStart, aEnd, POLY_ARC );
+
+ if ( aArcPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aArcPoly.ImplGetConstPointAry();
+ mpGraphics->DrawPolyLine( aArcPoly.GetSize(), pPtAry );
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawArc( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawPie( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawPie()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaPieAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aPiePoly( aRect, aStart, aEnd, POLY_PIE );
+
+ if ( aPiePoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aPiePoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aPiePoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aPiePoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawPie( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawChord( const Rectangle& rRect,
+ const Point& rStartPt, const Point& rEndPt )
+{
+ DBG_TRACE( "OutputDevice::DrawChord()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaChordAction( rRect, rStartPt, rEndPt ) );
+
+ if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ if ( aRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+
+ const Point aStart( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEnd( ImplLogicToDevicePixel( rEndPt ) );
+ Polygon aChordPoly( aRect, aStart, aEnd, POLY_CHORD );
+
+ if ( aChordPoly.GetSize() >= 2 )
+ {
+ const SalPoint* pPtAry = (const SalPoint*)aChordPoly.ImplGetConstPointAry();
+ if ( !mbFillColor )
+ mpGraphics->DrawPolyLine( aChordPoly.GetSize(), pPtAry );
+ else
+ {
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawPolygon( aChordPoly.GetSize(), pPtAry );
+ }
+ }
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawChord( aRect,
+ ImplLogicToDevicePixel( rStartPt ),
+ ImplLogicToDevicePixel( rEndPt ) );
+ }
+#endif
+}
diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx
new file mode 100644
index 000000000000..371334530488
--- /dev/null
+++ b/vcl/source/gdi/outdev6.cxx
@@ -0,0 +1,1043 @@
+/*************************************************************************
+ *
+ * $RCSfile: outdev6.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WALL_CXX
+
+#include <math.h>
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#else // REMOTE_APPSERVER
+#include <tools/stream.hxx>
+#endif // REMOTE_APPSERVER
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_GRAPH_HXX
+#include <graph.hxx>
+#endif
+#ifdef REMOTE_APPSERVER
+#include <rmoutdev.hxx>
+#endif
+#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
+#include <com/sun/star/uno/Sequence.hxx>
+#endif
+
+// ========================================================================
+
+DBG_NAMEEX( OutputDevice );
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, ULONG nFlags )
+{
+ DBG_TRACE( "OutputDevice::DrawGrid()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
+ aDstRect.Intersection( rRect );
+
+ if( aDstRect.IsEmpty() )
+ return;
+
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+
+ if( !pGraphics )
+ return;
+#endif
+
+ const long nDistX = Max( rDist.Width(), 1L );
+ const long nDistY = Max( rDist.Height(), 1L );
+ long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
+ long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
+ const long nRight = aDstRect.Right();
+ const long nBottom = aDstRect.Bottom();
+ const long nStartX = ImplLogicXToDevicePixel( nX );
+ const long nEndX = ImplLogicXToDevicePixel( nRight );
+ const long nStartY = ImplLogicYToDevicePixel( nY );
+ const long nEndY = ImplLogicYToDevicePixel( nBottom );
+ long nHorzCount = 0L;
+ long nVertCount = 0L;
+
+ ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
+ ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
+ {
+ aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
+ aVertBuf[ nVertCount++ ] = nStartY;
+ while( ( nY += nDistY ) <= nBottom )
+ aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
+ }
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
+ {
+ aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
+ aHorzBuf[ nHorzCount++ ] = nStartX;
+ while( ( nX += nDistX ) <= nRight )
+ aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
+ }
+
+ if( mbInitLineColor )
+ ImplInitLineColor();
+
+ if( mbInitFillColor )
+ ImplInitFillColor();
+
+#ifndef REMOTE_APPSERVER
+ const BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+
+ if( nFlags & GRID_DOTS )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ for( long j = 0L, nY = aVertBuf[ i ]; j < nHorzCount; j++ )
+ mpGraphics->DrawPixel( aHorzBuf[ j ], nY );
+ }
+ else
+ {
+ if( nFlags & GRID_HORZLINES )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ {
+ nY = aVertBuf[ i ];
+ mpGraphics->DrawLine( nStartX, nY, nEndX, nY );
+ }
+ }
+
+ if( nFlags & GRID_VERTLINES )
+ {
+ for( long i = 0L; i < nHorzCount; i++ )
+ {
+ nX = aHorzBuf[ i ];
+ mpGraphics->DrawLine( nX, nStartY, nX, nEndY );
+ }
+ }
+ }
+
+ mbMap = bOldMap;
+#else // REMOTE_APPSERVER
+ aHorzBuf.realloc( nHorzCount );
+ aVertBuf.realloc( nVertCount );
+ pGraphics->DrawGrid( nStartX, nEndX, aHorzBuf, nStartY, nEndY, aVertBuf, nFlags );
+#endif // REMOTE_APPSERVER
+}
+
+// ------------------------------------------------------------------------
+
+void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
+ USHORT nTransparencePercent )
+{
+ DBG_TRACE( "OutputDevice::DrawTransparent()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if( !mbFillColor || ( 0 == nTransparencePercent ) )
+ DrawPolyPolygon( rPolyPoly );
+ else if( 100 == nTransparencePercent )
+ {
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ }
+ else
+ {
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
+
+ if( !IsDeviceOutputNecessary() || ( !mbLineColor && !mbFillColor ) )
+ return;
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ mpMetaFile = NULL;
+
+ if( OUTDEV_PRINTER == meOutDevType )
+ {
+ Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
+ const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
+ const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L );
+ long nMove;
+ const USHORT nTrans = ( nTransparencePercent < 13 ) ? 0 :
+ ( nTransparencePercent < 38 ) ? 25 :
+ ( nTransparencePercent < 63 ) ? 50 :
+ ( nTransparencePercent < 88 ) ? 75 : 100;
+
+ switch( nTrans )
+ {
+ case( 25 ): nMove = nBaseExtent * 3; break;
+ case( 50 ): nMove = nBaseExtent * 4; break;
+ case( 75 ): nMove = nBaseExtent * 6; break;
+ }
+
+ Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
+ IntersectClipRegion( rPolyPoly );
+ SetLineColor( GetFillColor() );
+
+ Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
+
+ const BOOL bOldMap = mbMap;
+ mbMap = FALSE;
+
+ while( aRect.Top() <= aPolyRect.Bottom() )
+ {
+ DrawRect( aRect );
+ aRect.Move( 0, nMove );
+ }
+
+ aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
+ while( aRect.Left() <= aPolyRect.Right() )
+ {
+ DrawRect( aRect );
+ aRect.Move( nMove, 0 );
+ }
+
+ mbMap = bOldMap;
+ Pop();
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
+ Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ aDstRect.Intersection( aPolyRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice aVDev( *this, 1 );
+ const Size aDstSz( aDstRect.GetSize() );
+ const BYTE cTrans = (BYTE) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
+
+ if( aDstRect.Left() || aDstRect.Top() )
+ aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
+
+ if( aVDev.SetOutputSizePixel( aDstSz ) )
+ {
+ const BOOL bOldMap = mbMap;
+
+ mbMap = FALSE;
+
+ aVDev.SetLineColor( COL_BLACK );
+ aVDev.SetFillColor( COL_BLACK );
+ aVDev.DrawPolyPolygon( aPolyPoly );
+
+ Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
+ Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
+ BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
+ BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
+
+ if( pW && pR )
+ {
+ BitmapColor aPixCol;
+ const BitmapColor aFillCol( GetFillColor() );
+ const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const long nWidth = pW->Width(), nHeight = pW->Height();
+ const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
+ long nX, nY;
+
+ if( aPaint.GetBitCount() <= 8 )
+ {
+ const BitmapPalette& rPal = pW->GetPalette();
+ const USHORT nCount = rPal.GetEntryCount();
+ BitmapColor* pMap = (BitmapColor*) new BYTE[ nCount * sizeof( BitmapColor ) ];
+
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ BitmapColor aCol( rPal[ i ] );
+ pMap[ i ] = BitmapColor( (BYTE) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
+ }
+
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ const BYTE cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ BYTE cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ *pWScan = (BYTE) pMap[ *pWScan ].GetIndex();
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ for( nX = 0; nX < nWidth; nX++ )
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
+ }
+
+ delete[] (BYTE*) pMap;
+ }
+ else
+ {
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ const BYTE cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ BYTE cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ {
+ pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
+ pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
+ pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ {
+ aPixCol = pW->GetColor( nY, nX );
+ pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ aPolyMask.ReleaseAccess( pR );
+ aPaint.ReleaseAccess( pW );
+
+ DrawBitmap( aDstRect.TopLeft(), aPaint );
+
+ mbMap = bOldMap;
+
+ if( mbLineColor )
+ {
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ }
+ }
+ else
+ DrawPolyPolygon( rPolyPoly );
+ }
+#else // REMOTE_APPSERVER
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawTransparent( ImplLogicToDevicePixel( rPolyPoly ), nTransparencePercent );
+ }
+#endif // REMOTE_APPSERVER
+ }
+
+ mpMetaFile = pOldMetaFile;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
+ const Size& rSize, const Gradient& rTransparenceGradient )
+{
+ DBG_TRACE( "OutputDevice::DrawTransparent()" );
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ const Color aBlack( COL_BLACK );
+
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
+
+ if( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack )
+ {
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ }
+ else
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ mpMetaFile = NULL;
+ aDstRect.Intersection( aOutRect );
+
+ if( OUTDEV_WINDOW == meOutDevType )
+ {
+ const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
+
+ if( !aPaintRgn.IsNull() )
+ aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
+ }
+
+ if( !aDstRect.IsEmpty() )
+ {
+ VirtualDevice* pVDev = new VirtualDevice;
+
+ pVDev->mnDPIX = mnDPIX;
+ pVDev->mnDPIY = mnDPIY;
+
+ if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
+ {
+ Bitmap aPaint, aMask;
+ AlphaMask aAlpha;
+ MapMode aMap( GetMapMode() );
+ Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
+ const BOOL bOldMap = mbMap;
+
+ aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
+ pVDev->SetMapMode( aMap );
+
+ // create paint bitmap
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( FALSE );
+ aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( TRUE );
+
+ // create mask bitmap
+ pVDev->SetLineColor( COL_BLACK );
+ pVDev->SetFillColor( COL_BLACK );
+ pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
+ pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
+ DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( FALSE );
+ aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( TRUE );
+
+ // create alpha mask from gradient
+ pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
+ pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
+ pVDev->SetDrawMode( DRAWMODE_DEFAULT );
+ pVDev->EnableMapMode( FALSE );
+ pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
+
+#ifndef REMOTE_APPSERVER
+ aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+#else
+ aAlpha.ImplSetBitmap( pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ) );
+#endif
+
+ delete pVDev;
+
+ mbMap = FALSE;
+ DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
+ mbMap = bOldMap;
+ }
+ else
+ delete pVDev;
+ }
+
+ mpMetaFile = pOldMetaFile;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbOutputClipped )
+ return;
+
+ // Wallpaper ohne Umrandung zeichnen
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( rWallpaper.GetColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ mpGraphics->DrawRect( nX+mnOutOffX, nY+mnOutOffY, nWidth, nHeight );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( rWallpaper.GetColor() );
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+ pGraphics->DrawRect( Rectangle( Point( nX+mnOutOffX, nY+mnOutOffY ), Size( nWidth, nHeight ) ) );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ BitmapEx aBmpEx;
+ const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
+ Point aPos;
+ Size aSize;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const WallpaperStyle eStyle = rWallpaper.GetStyle();
+ const BOOL bOldMap = mbMap;
+ BOOL bDrawn = FALSE;
+ BOOL bDrawGradientBackground = FALSE;
+ BOOL bDrawColorBackground = FALSE;
+
+ if( pCached )
+ aBmpEx = *pCached;
+ else
+ aBmpEx = rWallpaper.GetBitmap();
+
+ const long nBmpWidth = aBmpEx.GetSizePixel().Width();
+ const long nBmpHeight = aBmpEx.GetSizePixel().Height();
+ const BOOL bTransparent = aBmpEx.IsTransparent();
+
+ // draw background
+ if( bTransparent )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = TRUE;
+ else
+ {
+ if( !pCached && !rWallpaper.GetColor().GetTransparency() )
+ {
+ VirtualDevice aVDev( *this );
+ aVDev.SetBackground( rWallpaper.GetColor() );
+ aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
+ aVDev.DrawBitmapEx( Point(), aBmpEx );
+ aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+
+ bDrawColorBackground = TRUE;
+ }
+ }
+ else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = TRUE;
+ else
+ bDrawColorBackground = TRUE;
+ }
+
+ // background of bitmap?
+ if( bDrawGradientBackground )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( bDrawColorBackground && bTransparent )
+ {
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ bDrawColorBackground = FALSE;
+ }
+
+ // calc pos and size
+ if( rWallpaper.IsRect() )
+ {
+ const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
+ aPos = aBound.TopLeft();
+ aSize = aBound.GetSize();
+ }
+ else
+ {
+ aPos = Point( nX, nY );
+ aSize = Size( nWidth, nHeight );
+ }
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ switch( eStyle )
+ {
+ case( WALLPAPER_SCALE ):
+ {
+ if( !pCached || ( pCached->GetSizePixel() != aSize ) )
+ {
+ if( pCached )
+ rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
+
+ aBmpEx = rWallpaper.GetBitmap();
+ aBmpEx.Scale( aSize );
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
+ }
+ }
+ break;
+
+ case( WALLPAPER_TOPLEFT ):
+ break;
+
+ case( WALLPAPER_TOP ):
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ break;
+
+ case( WALLPAPER_TOPRIGHT ):
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ break;
+
+ case( WALLPAPER_LEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ break;
+
+ case( WALLPAPER_CENTER ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_RIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMLEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ break;
+
+ case( WALLPAPER_BOTTOM ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMRIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ default:
+ {
+ const long nRight = nX + nWidth - 1L;
+ const long nBottom = nY + nHeight - 1L;
+ long nFirstX;
+ long nFirstY;
+
+ if( eStyle == WALLPAPER_TILE )
+ {
+ nFirstX = aPos.X();
+ nFirstY = aPos.Y();
+ }
+ else
+ {
+ nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
+ nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
+ }
+
+ const long nOffX = ( nFirstX - nX ) % nBmpWidth;
+ const long nOffY = ( nFirstY - nY ) % nBmpHeight;
+ long nStartX = nX + nOffX;
+ long nStartY = nY + nOffY;
+
+ if( nOffX > 0L )
+ nStartX -= nBmpWidth;
+
+ if( nOffY > 0L )
+ nStartY -= nBmpHeight;
+
+ for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
+ for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
+ DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
+
+ bDrawn = TRUE;
+ }
+ break;
+ }
+
+ if( !bDrawn )
+ {
+ // optimized for non-transparent bitmaps
+ if( bDrawColorBackground )
+ {
+ const Size aBmpSize( aBmpEx.GetSizePixel() );
+ const Point aTmpPoint;
+ const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
+ const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Rectangle aWorkRect;
+
+ aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+
+ DrawBitmapEx( aPos, aBmpEx );
+ }
+
+ rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
+
+ Pop();
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ Rectangle aBound;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const BOOL bOldMap = mbMap;
+
+/*
+ if ( rWallpaper.IsRect() )
+ aBound = LogicToPixel( rWallpaper.GetRect() );
+ else
+*/
+ aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
+
+ mpMetaFile = NULL;
+ mbMap = FALSE;
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ DrawGradient( aBound, rWallpaper.GetGradient() );
+
+ Pop();
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDrawWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ if( rWallpaper.IsBitmap() )
+ ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( rWallpaper.IsGradient() )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawWallpaper( const Rectangle& rRect,
+ const Wallpaper& rWallpaper )
+{
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
+ {
+ Rectangle aRect = LogicToPixel( rRect );
+ aRect.Justify();
+
+ if ( !aRect.IsEmpty() )
+ {
+ ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::Erase()
+{
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( mbBackground )
+ {
+ RasterOp eRasterOp = GetRasterOp();
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( ROP_OVERPAINT );
+ ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( eRasterOp );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect,
+ const Color& rLeftTopColor,
+ const Color& rRightBottomColor )
+{
+#ifndef REMOTE_APPSERVER
+ SetFillColor( rLeftTopColor );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
+ SetFillColor( rRightBottomColor );
+ DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
+ DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
+#else
+ if ( mpMetaFile )
+ {
+ BOOL bOutputEnabled = IsOutputEnabled();
+ EnableOutput( FALSE );
+ SetFillColor( rLeftTopColor );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
+ DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
+ SetFillColor( rRightBottomColor );
+ DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
+ DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
+ EnableOutput( bOutputEnabled );
+ }
+
+ if ( IsDeviceOutputNecessary() && !rRect.IsEmpty() )
+ {
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ {
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+ pGraphics->Draw2ColorFrame( aRect, rLeftTopColor, rRightBottomColor );
+ }
+ }
+ SetFillColor( rRightBottomColor );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
+ const GfxLink& rGfxLink, GDIMetaFile* pSubst )
+{
+ if ( mpMetaFile )
+ {
+ GDIMetaFile aSubst;
+
+ if( pSubst )
+ aSubst = *pSubst;
+
+ mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
+ }
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
+ BOOL bDrawn = FALSE;
+
+ if( !aRect.IsEmpty() )
+ {
+ aRect.Justify();
+
+ if( GetOutDevType() == OUTDEV_PRINTER )
+ {
+#ifndef REMOTE_APPSERVER
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( !mbOutputClipped )
+ {
+ bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ (BYTE*) rGfxLink.GetData(), rGfxLink.GetDataSize() );
+ }
+#else
+ DBG_ERROR( "No direct EPS-support for remote appserver!" );
+#endif
+ }
+
+ if( !bDrawn && pSubst )
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+
+ mpMetaFile = NULL;
+ Graphic( *pSubst ).Draw( this, rPoint, rSize );
+ mpMetaFile = pOldMetaFile;
+ }
+ }
+}
diff --git a/vcl/source/gdi/outmap.cxx b/vcl/source/gdi/outmap.cxx
new file mode 100644
index 000000000000..c086efb92bbc
--- /dev/null
+++ b/vcl/source/gdi/outmap.cxx
@@ -0,0 +1,2106 @@
+/*************************************************************************
+ *
+ * $RCSfile: outmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <limits.h>
+
+#define _SV_OUTMAP_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef _BIGINT_HXX
+#include <tools/bigint.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _SV_REGION_H
+#include <region.h>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_CURSOR_HXX
+#include <cursor.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_LINEINFO_HXX
+#include <lineinfo.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAMEEX( OutputDevice );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+DBG_NAMEEX( Region );
+
+// =======================================================================
+
+static long aImplNumeratorAry[MAP_PIXEL+1] =
+ { 1, 1, 5, 50, 1, 1, 1, 1, 1, 1, 1 };
+static long aImplDenominatorAry[MAP_PIXEL+1] =
+ { 2540, 254, 127, 127, 1000, 100, 10, 1, 72, 1440, 1 };
+
+// -----------------------------------------------------------------------
+
+/*
+Reduziert die Genauigkeit bis eine Fraction draus wird (sollte mal
+ein Fraction ctor werden) koennte man dann auch mit BigInts machen
+*/
+
+static Fraction ImplMakeFraction( long nN1, long nN2, long nD1, long nD2 )
+{
+ long i = 1;
+
+ if ( nN1 < 0 ) { i = -i; nN1 = -nN1; }
+ if ( nN2 < 0 ) { i = -i; nN2 = -nN2; }
+ if ( nD1 < 0 ) { i = -i; nD1 = -nD1; }
+ if ( nD2 < 0 ) { i = -i; nD2 = -nD2; }
+ // alle positiv; i Vorzeichen
+
+ Fraction aF( i*nN1, nD1 );
+ aF *= Fraction( nN2, nD2 );
+
+ while ( aF.GetDenominator() == -1 )
+ {
+ if ( nN1 > nN2 )
+ nN1 = (nN1 + 1) / 2;
+ else
+ nN2 = (nN2 + 1) / 2;
+ if ( nD1 > nD2 )
+ nD1 = (nD1 + 1) / 2;
+ else
+ nD2 = (nD2 + 1) / 2;
+
+ aF = Fraction( i*nN1, nD1 );
+ aF *= Fraction( nN2, nD2 );
+ }
+
+ return aF;
+}
+
+// -----------------------------------------------------------------------
+
+// Fraction.GetNumerator()
+// Fraction.GetDenominator() > 0
+// rOutRes.nPixPerInch? > 0
+// rMapRes.nMapScNum?
+// rMapRes.nMapScDenom? > 0
+
+static void ImplCalcBigIntThreshold( long nDPIX, long nDPIY,
+ const ImplMapRes& rMapRes,
+ ImplThresholdRes& rThresRes )
+{
+ if ( LONG_MAX / nDPIX < Abs( rMapRes.mnMapScNumX ) )
+ {
+ rThresRes.mnThresLogToPixX = 0;
+ rThresRes.mnThresPixToLogX = 0;
+ }
+ else
+ {
+ // Schwellenwerte fuer BigInt Arithmetik berechnen
+ long nDenomHalfX = rMapRes.mnMapScDenomX / 2;
+ ULONG nDenomX = rMapRes.mnMapScDenomX;
+ long nProductX = nDPIX * rMapRes.mnMapScNumX;
+
+ if ( !nProductX )
+ rThresRes.mnThresLogToPixX = LONG_MAX;
+ else
+ rThresRes.mnThresLogToPixX = Abs( (LONG_MAX - nDenomHalfX) / nProductX );
+
+ if ( !nDenomX )
+ rThresRes.mnThresPixToLogX = LONG_MAX;
+ else if ( nProductX >= 0 )
+ rThresRes.mnThresPixToLogX = (long)(((ULONG)LONG_MAX - (ULONG)( nProductX/2)) / nDenomX);
+ else
+ rThresRes.mnThresPixToLogX = (long)(((ULONG)LONG_MAX + (ULONG)(-nProductX/2)) / nDenomX);
+ }
+
+ if ( LONG_MAX / nDPIY < Abs( rMapRes.mnMapScNumY ) )
+ {
+ rThresRes.mnThresLogToPixY = 0;
+ rThresRes.mnThresPixToLogY = 0;
+ }
+ else
+ {
+ // Schwellenwerte fuer BigInt Arithmetik berechnen
+ long nDenomHalfY = rMapRes.mnMapScDenomY / 2;
+ ULONG nDenomY = rMapRes.mnMapScDenomY;
+ long nProductY = nDPIY * rMapRes.mnMapScNumY;
+
+ if ( !nProductY )
+ rThresRes.mnThresLogToPixY = LONG_MAX;
+ else
+ rThresRes.mnThresLogToPixY = Abs( (LONG_MAX - nDenomHalfY) / nProductY );
+
+ if ( !nDenomY )
+ rThresRes.mnThresPixToLogY = LONG_MAX;
+ else if ( nProductY >= 0 )
+ rThresRes.mnThresPixToLogY = (long)(((ULONG)LONG_MAX - (ULONG)( nProductY/2)) / nDenomY);
+ else
+ rThresRes.mnThresPixToLogY = (long)(((ULONG)LONG_MAX + (ULONG)(-nProductY/2)) / nDenomY);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalcMapResolution( const MapMode& rMapMode,
+ long nDPIX, long nDPIY, ImplMapRes& rMapRes )
+{
+ switch ( rMapMode.GetMapUnit() )
+ {
+ case MAP_RELATIVE:
+ break;
+ case MAP_100TH_MM:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 2540;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 2540;
+ break;
+ case MAP_10TH_MM:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 254;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 254;
+ break;
+ case MAP_MM:
+ rMapRes.mnMapScNumX = 5; // 10
+ rMapRes.mnMapScDenomX = 127; // 254
+ rMapRes.mnMapScNumY = 5; // 10
+ rMapRes.mnMapScDenomY = 127; // 254
+ break;
+ case MAP_CM:
+ rMapRes.mnMapScNumX = 50; // 100
+ rMapRes.mnMapScDenomX = 127; // 254
+ rMapRes.mnMapScNumY = 50; // 100
+ rMapRes.mnMapScDenomY = 127; // 254
+ break;
+ case MAP_1000TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1000;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1000;
+ break;
+ case MAP_100TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 100;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 100;
+ break;
+ case MAP_10TH_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 10;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 10;
+ break;
+ case MAP_INCH:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1;
+ break;
+ case MAP_POINT:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 72;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 72;
+ break;
+ case MAP_TWIP:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = 1440;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = 1440;
+ break;
+ case MAP_PIXEL:
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = nDPIX;
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = nDPIY;
+ break;
+ case MAP_SYSFONT:
+ case MAP_APPFONT:
+ case MAP_REALAPPFONT:
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maGDIData.mnAppFontX )
+ {
+ WorkWindow* pWin = new WorkWindow( NULL, 0 );
+ delete pWin;
+ }
+ if ( rMapMode.GetMapUnit() == MAP_REALAPPFONT )
+ rMapRes.mnMapScNumX = pSVData->maGDIData.mnRealAppFontX;
+ else
+ rMapRes.mnMapScNumX = pSVData->maGDIData.mnAppFontX;
+ rMapRes.mnMapScDenomX = nDPIX * 40;
+ rMapRes.mnMapScNumY = pSVData->maGDIData.mnAppFontY;;
+ rMapRes.mnMapScDenomY = nDPIY * 80;
+ }
+ break;
+ }
+
+ Fraction aScaleX = rMapMode.GetScaleX();
+ Fraction aScaleY = rMapMode.GetScaleY();
+
+ // Offset laut MapMode setzen
+ Point aOrigin = rMapMode.GetOrigin();
+ if ( rMapMode.GetMapUnit() != MAP_RELATIVE )
+ {
+ rMapRes.mnMapOfsX = aOrigin.X();
+ rMapRes.mnMapOfsY = aOrigin.Y();
+ }
+ else
+ {
+ BigInt aX( rMapRes.mnMapOfsX );
+ aX *= BigInt( aScaleX.GetDenominator() );
+ if ( rMapRes.mnMapOfsX >= 0 )
+ {
+ if ( aScaleX.GetNumerator() >= 0 )
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ else
+ aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
+ }
+ else
+ {
+ if ( aScaleX.GetNumerator() >= 0 )
+ aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
+ else
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ }
+ aX /= BigInt( aScaleX.GetNumerator() );
+ rMapRes.mnMapOfsX = (long)aX + aOrigin.X();
+ BigInt aY( rMapRes.mnMapOfsY );
+ aY *= BigInt( aScaleY.GetDenominator() );
+ if( rMapRes.mnMapOfsY >= 0 )
+ {
+ if ( aScaleY.GetNumerator() >= 0 )
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ else
+ aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
+ }
+ else
+ {
+ if ( aScaleY.GetNumerator() >= 0 )
+ aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
+ else
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ }
+ aY /= BigInt( aScaleY.GetNumerator() );
+ rMapRes.mnMapOfsY = (long)aY + aOrigin.Y();
+ }
+
+ // Scaling Faktor laut MapMode einberechnen
+ // aTemp? = rMapRes.mnMapSc? * aScale?
+ Fraction aTempX = ImplMakeFraction( rMapRes.mnMapScNumX,
+ aScaleX.GetNumerator(),
+ rMapRes.mnMapScDenomX,
+ aScaleX.GetDenominator() );
+ Fraction aTempY = ImplMakeFraction( rMapRes.mnMapScNumY,
+ aScaleY.GetNumerator(),
+ rMapRes.mnMapScDenomY,
+ aScaleY.GetDenominator() );
+ rMapRes.mnMapScNumX = aTempX.GetNumerator();
+ rMapRes.mnMapScDenomX = aTempX.GetDenominator();
+ rMapRes.mnMapScNumY = aTempY.GetNumerator();
+ rMapRes.mnMapScDenomY = aTempY.GetDenominator();
+
+ // hack: 0/n ungef"ahr 1/max
+ if ( !rMapRes.mnMapScNumX )
+ {
+ rMapRes.mnMapScNumX = 1;
+ rMapRes.mnMapScDenomX = LONG_MAX;
+ }
+ if ( !rMapRes.mnMapScNumY )
+ {
+ rMapRes.mnMapScNumY = 1;
+ rMapRes.mnMapScDenomY = LONG_MAX;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplCalcMapResolution( const MapMode& rMapMode,
+ long nDPIX, long nDPIY,
+ ImplMapRes& rMapRes,
+ ImplThresholdRes& rThresRes )
+{
+ ImplCalcMapResolution( rMapMode, nDPIX, nDPIY, rMapRes );
+ ImplCalcBigIntThreshold( nDPIX, nDPIY, rMapRes, rThresRes );
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetMapMode()
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaMapModeAction( MapMode() ) );
+
+ if ( mbMap || !maMapMode.IsDefault() )
+ {
+ mbMap = FALSE;
+ maMapMode = MapMode();
+
+ // create new objects (clip region werden nicht neu skaliert)
+ mbNewFont = TRUE;
+ mbInitFont = TRUE;
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ if ( ((Window*)this)->mpCursor )
+ ((Window*)this)->mpCursor->ImplNew();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetMapMode( const MapMode& rNewMapMode )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ BOOL bRelMap = (rNewMapMode.GetMapUnit() == MAP_RELATIVE);
+
+ if ( mpMetaFile )
+ {
+ mpMetaFile->AddAction( new MetaMapModeAction( rNewMapMode ) );
+#ifdef DBG_UTIL
+ if ( GetOutDevType() != OUTDEV_PRINTER )
+ DBG_ASSERTWARNING( bRelMap, "Please record only relative MapModes!" );
+#endif
+ }
+
+ // Ist der MapMode der gleiche wie vorher, dann mache nichts
+ if ( maMapMode == rNewMapMode )
+ return;
+
+ // Ist Default-MapMode, dann bereche nichts
+ BOOL bOldMap = mbMap;
+ mbMap = !rNewMapMode.IsDefault();
+ if ( mbMap )
+ {
+ // Falls nur der Orign umgesetzt wird, dann scaliere nichts neu
+ if ( (rNewMapMode.GetMapUnit() == maMapMode.GetMapUnit()) &&
+ (rNewMapMode.GetScaleX() == maMapMode.GetScaleX()) &&
+ (rNewMapMode.GetScaleY() == maMapMode.GetScaleY()) &&
+ (bOldMap == mbMap) )
+ {
+ // Offset setzen
+ Point aOrigin = rNewMapMode.GetOrigin();
+ maMapRes.mnMapOfsX = aOrigin.X();
+ maMapRes.mnMapOfsY = aOrigin.Y();
+ maMapMode = rNewMapMode;
+ return;
+ }
+ if ( !bOldMap && bRelMap )
+ {
+ maMapRes.mnMapScNumX = 1;
+ maMapRes.mnMapScNumY = 1;
+ maMapRes.mnMapScDenomX = mnDPIX;
+ maMapRes.mnMapScDenomY = mnDPIY;
+ maMapRes.mnMapOfsX = 0;
+ maMapRes.mnMapOfsY = 0;
+ }
+
+ // Neue MapMode-Aufloesung berechnen
+ ImplCalcMapResolution( rNewMapMode, mnDPIX, mnDPIY, maMapRes, maThresRes );
+ }
+
+ // Neuen MapMode setzen
+ if ( bRelMap )
+ {
+ Point aOrigin( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY );
+ // aScale? = maMapMode.GetScale?() * rNewMapMode.GetScale?()
+ Fraction aScaleX = ImplMakeFraction( maMapMode.GetScaleX().GetNumerator(),
+ rNewMapMode.GetScaleX().GetNumerator(),
+ maMapMode.GetScaleX().GetDenominator(),
+ rNewMapMode.GetScaleX().GetDenominator() );
+ Fraction aScaleY = ImplMakeFraction( maMapMode.GetScaleY().GetNumerator(),
+ rNewMapMode.GetScaleY().GetNumerator(),
+ maMapMode.GetScaleY().GetDenominator(),
+ rNewMapMode.GetScaleY().GetDenominator() );
+ maMapMode.SetOrigin( aOrigin );
+ maMapMode.SetScaleX( aScaleX );
+ maMapMode.SetScaleY( aScaleY );
+ }
+ else
+ maMapMode = rNewMapMode;
+
+ // create new objects (clip region werden nicht neu skaliert)
+ mbNewFont = TRUE;
+ mbInitFont = TRUE;
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ if ( ((Window*)this)->mpCursor )
+ ((Window*)this)->mpCursor->ImplNew();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void OutputDevice::SetRelativeMapMode( const MapMode& rNewMapMode )
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist der MapMode der gleiche wie vorher, dann mache nichts
+ if ( maMapMode == rNewMapMode )
+ return;
+
+ MapUnit eOld = maMapMode.GetMapUnit();
+ MapUnit eNew = rNewMapMode.GetMapUnit();
+
+ // a?F = rNewMapMode.GetScale?() / maMapMode.GetScale?()
+ Fraction aXF = ImplMakeFraction( rNewMapMode.GetScaleX().GetNumerator(),
+ maMapMode.GetScaleX().GetDenominator(),
+ rNewMapMode.GetScaleX().GetDenominator(),
+ maMapMode.GetScaleX().GetNumerator() );
+ Fraction aYF = ImplMakeFraction( rNewMapMode.GetScaleY().GetNumerator(),
+ maMapMode.GetScaleY().GetDenominator(),
+ rNewMapMode.GetScaleY().GetDenominator(),
+ maMapMode.GetScaleY().GetNumerator() );
+
+ Point aPt( LogicToLogic( Point(), NULL, &rNewMapMode ) );
+ if ( eNew != eOld )
+ {
+ if ( eOld > MAP_PIXEL )
+ {
+ DBG_ERRORFILE( "Not implemented MapUnit" )
+ }
+ else if ( eNew > MAP_PIXEL )
+ {
+ DBG_ERRORFILE( "Not implemented MapUnit" )
+ }
+ else
+ {
+ Fraction aF( aImplNumeratorAry[eNew] * aImplDenominatorAry[eOld],
+ aImplNumeratorAry[eOld] * aImplDenominatorAry[eNew] );
+
+ // a?F = a?F * aF
+ aXF = ImplMakeFraction( aXF.GetNumerator(), aF.GetNumerator(),
+ aXF.GetDenominator(), aF.GetDenominator() );
+ aYF = ImplMakeFraction( aYF.GetNumerator(), aF.GetNumerator(),
+ aYF.GetDenominator(), aF.GetDenominator() );
+ if ( eOld == MAP_PIXEL )
+ {
+ aXF *= Fraction( mnDPIX, 1 );
+ aYF *= Fraction( mnDPIY, 1 );
+ }
+ else if ( eNew == MAP_PIXEL )
+ {
+ aXF *= Fraction( 1, mnDPIX );
+ aYF *= Fraction( 1, mnDPIY );
+ }
+ }
+ }
+
+ MapMode aNewMapMode( MAP_RELATIVE, Point( -aPt.X(), -aPt.Y() ), aXF, aYF );
+ SetMapMode( aNewMapMode );
+
+ if ( eNew != eOld )
+ maMapMode = rNewMapMode;
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplLogicToPixel( long n, long nDPI, long nMapNum, long nMapDenom,
+ long nThres )
+{
+ if ( Abs( n ) < nThres )
+ {
+ n *= nDPI * nMapNum;
+ n += n >= 0 ? nMapDenom/2 : -((nMapDenom-1)/2);
+ return (n / nMapDenom);
+ }
+ else
+ {
+ BigInt aTemp( n );
+ aTemp *= BigInt( nDPI );
+ aTemp *= BigInt( nMapNum );
+
+ if ( aTemp.IsNeg() )
+ {
+ BigInt aMapScDenom2( (nMapDenom-1)/2 );
+ aTemp -= aMapScDenom2;
+ }
+ else
+ {
+ BigInt aMapScDenom2( nMapDenom/2 );
+ aTemp += aMapScDenom2;
+ }
+
+ aTemp /= BigInt( nMapDenom );
+ return (long)aTemp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static long ImplPixelToLogic( long n, long nDPI, long nMapNum, long nMapDenom,
+ long nThres )
+{
+ if ( Abs( n ) < nThres )
+ {
+ long nDenom = nDPI * nMapNum;
+ long nNum = n * nMapDenom;
+ if ( nNum >= 0 )
+ {
+ if ( nDenom >= 0 )
+ nNum += nDenom/2;
+ else
+ nNum -= (nDenom+1)/2;
+ }
+ else
+ {
+ if ( nDenom >= 0 )
+ nNum -= (nDenom-1)/2;
+ else
+ nNum += nDenom/2;
+ }
+ return (nNum / nDenom);
+ }
+ else
+ {
+ BigInt aDenom( nDPI );
+ aDenom *= BigInt( nMapNum );
+
+ BigInt aNum( n );
+ aNum *= BigInt( nMapDenom );
+
+ BigInt aDenom2( aDenom );
+ if ( aNum.IsNeg() )
+ {
+ if ( aDenom.IsNeg() )
+ {
+ aDenom2 /= BigInt(2);
+ aNum += aDenom2;
+ }
+ else
+ {
+ aDenom2 -= 1;
+ aDenom2 /= BigInt(2);
+ aNum -= aDenom2;
+ }
+ }
+ else
+ {
+ if ( aDenom.IsNeg() )
+ {
+ aDenom2 += 1;
+ aDenom2 /= BigInt(2);
+ aNum -= aDenom2;
+ }
+ else
+ {
+ aDenom2 /= BigInt(2);
+ aNum += aDenom2;
+ }
+ }
+
+ aNum /= aDenom;
+ return (long)aNum;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicXToDevicePixel( long nX ) const
+{
+ if ( !mbMap )
+ return nX+mnOutOffX;
+
+ return ImplLogicToPixel( nX + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicYToDevicePixel( long nY ) const
+{
+ if ( !mbMap )
+ return nY+mnOutOffY;
+
+ return ImplLogicToPixel( nY + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY;
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicWidthToDevicePixel( long nWidth ) const
+{
+ if ( !mbMap )
+ return nWidth;
+
+ return ImplLogicToPixel( nWidth, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplLogicHeightToDevicePixel( long nHeight ) const
+{
+ if ( !mbMap )
+ return nHeight;
+
+ return ImplLogicToPixel( nHeight, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplDevicePixelToLogicWidth( long nWidth ) const
+{
+ if ( !mbMap )
+ return nWidth;
+
+ return ImplPixelToLogic( nWidth, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX );
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::ImplDevicePixelToLogicHeight( long nHeight ) const
+{
+ if ( !mbMap )
+ return nHeight;
+
+ return ImplPixelToLogic( nHeight, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY );
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::ImplLogicToDevicePixel( const Point& rLogicPt ) const
+{
+ if ( !mbMap )
+ return Point( rLogicPt.X()+mnOutOffX, rLogicPt.Y()+mnOutOffY );
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::ImplLogicToDevicePixel( const Size& rLogicSize ) const
+{
+ if ( !mbMap )
+ return rLogicSize;
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplLogicToDevicePixel( const Rectangle& rLogicRect ) const
+{
+ if ( rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ if ( !mbMap )
+ {
+ return Rectangle( rLogicRect.Left()+mnOutOffX, rLogicRect.Top()+mnOutOffY,
+ rLogicRect.Right()+mnOutOffX, rLogicRect.Bottom()+mnOutOffY );
+ }
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicRect.Top()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY,
+ ImplLogicToPixel( rLogicRect.Right()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX,
+ ImplLogicToPixel( rLogicRect.Bottom()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::ImplLogicToDevicePixel( const Polygon& rLogicPoly ) const
+{
+ if ( !mbMap && !mnOutOffX && !mnOutOffY )
+ return rLogicPoly;
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ if ( mbMap )
+ {
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X()+maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX )+mnOutOffX;
+ pPt->Y() = ImplLogicToPixel( pPt->Y()+maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY )+mnOutOffY;
+ }
+ }
+ else
+ {
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() += mnOutOffX;
+ pPt->Y() += mnOutOffY;
+ }
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::ImplLogicToDevicePixel( const PolyPolygon& rLogicPolyPoly ) const
+{
+ if ( !mbMap && !mnOutOffX && !mnOutOffY )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = ImplLogicToDevicePixel( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+LineInfo OutputDevice::ImplLogicToDevicePixel( const LineInfo& rLineInfo ) const
+{
+ LineInfo aInfo( rLineInfo );
+
+ if( aInfo.GetStyle() == LINE_DASH )
+ {
+ if( aInfo.GetDotCount() && aInfo.GetDotLen() )
+ aInfo.SetDotLen( Max( ImplLogicWidthToDevicePixel( aInfo.GetDotLen() ), 1L ) );
+ else
+ aInfo.SetDotCount( 0 );
+
+ if( aInfo.GetDashCount() && aInfo.GetDashLen() )
+ aInfo.SetDashLen( Max( ImplLogicWidthToDevicePixel( aInfo.GetDashLen() ), 1L ) );
+ else
+ aInfo.SetDashCount( 0 );
+
+ aInfo.SetDistance( ImplLogicWidthToDevicePixel( aInfo.GetDistance() ) );
+
+ if( ( !aInfo.GetDashCount() && !aInfo.GetDotCount() ) || !aInfo.GetDistance() )
+ aInfo.SetStyle( LINE_SOLID );
+ }
+
+ aInfo.SetWidth( ImplLogicWidthToDevicePixel( aInfo.GetWidth() ) );
+
+ return aInfo;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::ImplDevicePixelToLogic( const Rectangle& rPixelRect ) const
+{
+ if ( rPixelRect.IsEmpty() )
+ return rPixelRect;
+
+ if ( !mbMap )
+ {
+ return Rectangle( rPixelRect.Left()-mnOutOffX, rPixelRect.Top()-mnOutOffY,
+ rPixelRect.Right()-mnOutOffX, rPixelRect.Bottom()-mnOutOffY );
+ }
+
+ return Rectangle( ImplPixelToLogic( rPixelRect.Left()-mnOutOffX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rPixelRect.Top()-mnOutOffY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY,
+ ImplPixelToLogic( rPixelRect.Right()-mnOutOffX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rPixelRect.Bottom()-mnOutOffY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::ImplPixelToDevicePixel( const Region& rRegion ) const
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ if ( !mnOutOffX && !mnOutOffY )
+ return rRegion;
+
+ Region aRegion( rRegion );
+ aRegion.Move( mnOutOffX, mnOutOffY );
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToPixel( const Point& rLogicPt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rLogicPt;
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToPixel( const Size& rLogicSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rLogicSize;
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToPixel( const Rectangle& rLogicRect ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap || rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Top() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ),
+ ImplLogicToPixel( rLogicRect.Right() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Bottom() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::LogicToPixel( const Polygon& rLogicPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPoly, Polygon, NULL );
+
+ if ( !mbMap )
+ return rLogicPoly;
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X() + maMapRes.mnMapOfsX, mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresLogToPixX );
+ pPt->Y() = ImplLogicToPixel( pPt->Y() + maMapRes.mnMapOfsY, mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresLogToPixY );
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPolyPoly, PolyPolygon, NULL );
+
+ if ( !mbMap )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = LogicToPixel( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::LogicToPixel( const Region& rLogicRegion ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rLogicRegion.GetType();
+
+ if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rLogicRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rLogicRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( LogicToPixel( *pPolyPoly ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rLogicRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( LogicToPixel( aRect ) );
+ bRegionRect = rLogicRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToPixel( const Point& rLogicPt,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPt;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Point( ImplLogicToPixel( rLogicPt.X() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicPt.Y() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToPixel( const Size& rLogicSize,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicSize;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToPixel( const Rectangle& rLogicRect,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( rMapMode.IsDefault() || rLogicRect.IsEmpty() )
+ return rLogicRect;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Rectangle( ImplLogicToPixel( rLogicRect.Left() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Top() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ),
+ ImplLogicToPixel( rLogicRect.Right() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX ),
+ ImplLogicToPixel( rLogicRect.Bottom() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::LogicToPixel( const Polygon& rLogicPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPoly, Polygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPoly;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ USHORT i;
+ USHORT nPoints = rLogicPoly.GetSize();
+ Polygon aPoly( rLogicPoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplLogicToPixel( pPt->X() + aMapRes.mnMapOfsX, mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresLogToPixX );
+ pPt->Y() = ImplLogicToPixel( pPt->Y() + aMapRes.mnMapOfsY, mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresLogToPixY );
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicPolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rLogicPolyPoly;
+
+ PolyPolygon aPolyPoly( rLogicPolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = LogicToPixel( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::LogicToPixel( const Region& rLogicRegion,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rLogicRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rLogicRegion.GetType();
+
+ if ( rMapMode.IsDefault() || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rLogicRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rLogicRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if( pPolyPoly )
+ aRegion = Region( LogicToPixel( *pPolyPoly, rMapMode ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rLogicRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( LogicToPixel( aRect, rMapMode ) );
+ bRegionRect = rLogicRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::PixelToLogic( const Point& rDevicePt ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rDevicePt;
+
+ return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::PixelToLogic( const Size& rDeviceSize ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap )
+ return rDeviceSize;
+
+ return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ),
+ ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::PixelToLogic( const Rectangle& rDeviceRect ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ if ( !mbMap || rDeviceRect.IsEmpty() )
+ return rDeviceRect;
+
+ return Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY,
+ ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::PixelToLogic( const Polygon& rDevicePoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePoly, Polygon, NULL );
+
+ if ( !mbMap )
+ return rDevicePoly;
+
+ USHORT i;
+ USHORT nPoints = rDevicePoly.GetSize();
+ Polygon aPoly( rDevicePoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplPixelToLogic( pPt->X(), mnDPIX,
+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
+ maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX;
+ pPt->Y() = ImplPixelToLogic( pPt->Y(), mnDPIY,
+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
+ maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY;
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePolyPoly, PolyPolygon, NULL );
+
+ if ( !mbMap )
+ return rDevicePolyPoly;
+
+ PolyPolygon aPolyPoly( rDevicePolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = PixelToLogic( rPoly );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDeviceRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rDeviceRegion.GetType();
+
+ if ( !mbMap || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rDeviceRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( PixelToLogic( *pPolyPoly ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rDeviceRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( PixelToLogic( aRect ) );
+ bRegionRect = rDeviceRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::PixelToLogic( const Point& rDevicePt,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDevicePt;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::PixelToLogic( const Size& rDeviceSize,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDeviceSize;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ),
+ ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::PixelToLogic( const Rectangle& rDeviceRect,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() || rDeviceRect.IsEmpty() )
+ return rDeviceRect;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ return Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY,
+ ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX,
+ ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Polygon OutputDevice::PixelToLogic( const Polygon& rDevicePoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePoly, Polygon, NULL );
+
+ // Ist Default-MapMode, dann bereche nichts
+ if ( rMapMode.IsDefault() )
+ return rDevicePoly;
+
+ // MapMode-Aufloesung berechnen und Umrechnen
+ ImplMapRes aMapRes;
+ ImplThresholdRes aThresRes;
+ ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
+
+ USHORT i;
+ USHORT nPoints = rDevicePoly.GetSize();
+ Polygon aPoly( rDevicePoly );
+
+ // Pointer auf das Point-Array holen (Daten werden kopiert)
+#ifdef WIN
+ Point huge* pPointAry = (Point huge*)aPoly.ImplGetPointAry();
+#else
+ Point* pPointAry = aPoly.ImplGetPointAry();
+#endif
+
+ for ( i = 0; i < nPoints; i++ )
+ {
+ Point* pPt = &(pPointAry[i]);
+ pPt->X() = ImplPixelToLogic( pPt->X(), mnDPIX,
+ aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
+ aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX;
+ pPt->Y() = ImplPixelToLogic( pPt->Y(), mnDPIY,
+ aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
+ aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY;
+ }
+
+ return aPoly;
+}
+
+// -----------------------------------------------------------------------
+
+PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDevicePolyPoly, PolyPolygon, NULL );
+
+ if ( rMapMode.IsDefault() )
+ return rDevicePolyPoly;
+
+ PolyPolygon aPolyPoly( rDevicePolyPoly );
+ USHORT nPoly = aPolyPoly.Count();
+ for( USHORT i = 0; i < nPoly; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[i];
+ rPoly = PixelToLogic( rPoly, rMapMode );
+ }
+ return aPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+
+Region OutputDevice::PixelToLogic( const Region& rDeviceRegion,
+ const MapMode& rMapMode ) const
+{
+ DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
+ DBG_CHKOBJ( &rDeviceRegion, Region, ImplDbgTestRegion );
+
+ RegionType eType = rDeviceRegion.GetType();
+
+ if ( rMapMode.IsDefault() || (eType == REGION_EMPTY) || (eType == REGION_NULL) )
+ return rDeviceRegion;
+
+ Region aRegion;
+ PolyPolygon* pPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
+
+ if ( pPolyPoly )
+ aRegion = Region( PixelToLogic( *pPolyPoly, rMapMode ) );
+ else
+ {
+ long nX;
+ long nY;
+ long nWidth;
+ long nHeight;
+ ImplRegionInfo aInfo;
+ BOOL bRegionRect;
+
+ aRegion.ImplBeginAddRect();
+ bRegionRect = rDeviceRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ aRegion.ImplAddRect( PixelToLogic( aRect, rMapMode ) );
+ bRegionRect = rDeviceRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ aRegion.ImplEndAddRect();
+ }
+
+ return aRegion;
+}
+
+// -----------------------------------------------------------------------
+
+#define ENTER0( rSource, pMapModeSource, pMapModeDest ) \
+ if ( !pMapModeSource ) \
+ pMapModeSource = &maMapMode; \
+ if ( !pMapModeDest ) \
+ pMapModeDest = &maMapMode; \
+ if ( *pMapModeSource == *pMapModeDest ) \
+ return rSource
+
+// -----------------------------------------------------------------------
+
+#define ENTER1( rSource, pMapModeSource, pMapModeDest ) \
+ ENTER0( rSource, pMapModeSource, pMapModeDest ); \
+ \
+ ImplMapRes aMapResSource; \
+ ImplMapRes aMapResDest; \
+ \
+ if ( !mbMap || pMapModeSource != &maMapMode ) \
+ { \
+ if ( pMapModeSource->GetMapUnit() == MAP_RELATIVE ) \
+ aMapResSource = maMapRes; \
+ ImplCalcMapResolution( *pMapModeSource, \
+ mnDPIX, mnDPIY, aMapResSource ); \
+ } \
+ else \
+ aMapResSource = maMapRes; \
+ if ( !mbMap || pMapModeDest != &maMapMode ) \
+ { \
+ if ( pMapModeDest->GetMapUnit() == MAP_RELATIVE ) \
+ aMapResDest = maMapRes; \
+ ImplCalcMapResolution( *pMapModeDest, \
+ mnDPIX, mnDPIY, aMapResDest ); \
+ } \
+ else \
+ aMapResDest = maMapRes
+
+// -----------------------------------------------------------------------
+
+#define ENTER2( eUnitSource, eUnitDest ) \
+ DBG_ASSERT( eUnitSource != MAP_SYSFONT \
+ && eUnitSource != MAP_APPFONT \
+ && eUnitSource != MAP_RELATIVE, \
+ "Source MapUnit nicht erlaubt" ); \
+ DBG_ASSERT( eUnitDest != MAP_SYSFONT \
+ && eUnitDest != MAP_APPFONT \
+ && eUnitDest != MAP_RELATIVE, \
+ "Destination MapUnit nicht erlaubt" ); \
+ DBG_ASSERTWARNING( eUnitSource != MAP_PIXEL, \
+ "MAP_PIXEL mit 72dpi angenaehert" ); \
+ DBG_ASSERTWARNING( eUnitDest != MAP_PIXEL, \
+ "MAP_PIXEL mit 72dpi angenaehert" )
+
+// -----------------------------------------------------------------------
+
+#define ENTER3( eUnitSource, eUnitDest ) \
+ long nNumerator = aImplNumeratorAry[eUnitSource] * \
+ aImplDenominatorAry[eUnitDest]; \
+ long nDenominator = aImplNumeratorAry[eUnitDest] * \
+ aImplDenominatorAry[eUnitSource]; \
+ if ( eUnitSource == MAP_PIXEL ) \
+ nDenominator *= 72; \
+ else if( eUnitDest == MAP_PIXEL ) \
+ nNumerator *= 72
+
+// -----------------------------------------------------------------------
+
+#define ENTER4( rMapModeSource, rMapModeDest ) \
+ ImplMapRes aMapResSource; \
+ ImplMapRes aMapResDest; \
+ \
+ ImplCalcMapResolution( rMapModeSource, 72, 72, aMapResSource ); \
+ ImplCalcMapResolution( rMapModeDest, 72, 72, aMapResDest )
+
+// -----------------------------------------------------------------------
+
+// return (n1 * n2 * n3) / (n4 * n5)
+static long fn5( const long n1,
+ const long n2,
+ const long n3,
+ const long n4,
+ const long n5 )
+{
+ if ( n1 == 0 || n2 == 0 || n3 == 0 || n4 == 0 || n5 == 0 )
+ return 0;
+ if ( LONG_MAX / Abs(n2) < Abs(n3) )
+ {
+ // a6 wird "ubersprungen
+ BigInt a7 = n2;
+ a7 *= n3;
+ a7 *= n1;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ } // of if
+ else
+ {
+ long n8 = n4 * n5;
+
+ if ( a7.IsNeg() )
+ a7 -= n8 / 2;
+ else
+ a7 += n8 / 2;
+
+ a7 /= n8;
+ } // of else
+ return (long)a7;
+ } // of if
+ else
+ {
+ long n6 = n2 * n3;
+
+ if ( LONG_MAX / Abs(n1) < Abs(n6) )
+ {
+ BigInt a7 = n1;
+ a7 *= n6;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ } // of if
+ else
+ {
+ long n8 = n4 * n5;
+
+ if ( a7.IsNeg() )
+ a7 -= n8 / 2;
+ else
+ a7 += n8 / 2;
+
+ a7 /= n8;
+ } // of else
+ return (long)a7;
+ } // of if
+ else
+ {
+ long n7 = n1 * n6;
+
+ if ( LONG_MAX / Abs(n4) < Abs(n5) )
+ {
+ BigInt a7 = n7;
+ BigInt a8 = n4;
+ a8 *= n5;
+
+ BigInt a9 = a8;
+ a9 /= 2;
+ if ( a7.IsNeg() )
+ a7 -= a9;
+ else
+ a7 += a9;
+
+ a7 /= a8;
+ return (long)a7;
+ } // of if
+ else
+ {
+ const long n8 = n4 * n5;
+ const long n8_2 = n8 / 2;
+
+ if( n7 < 0 )
+ {
+ if( ( n7 - LONG_MIN ) >= n8_2 )
+ n7 -= n8_2;
+ }
+ else if( ( LONG_MAX - n7 ) >= n8_2 )
+ n7 += n8_2;
+
+ return n7 / n8;
+ } // of else
+ } // of else
+ } // of else
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+// return (n1 * n2) / n3
+static long fn3( const long n1, const long n2, const long n3 )
+{
+ if ( n1 == 0 || n2 == 0 || n3 == 0 )
+ return 0;
+ if ( LONG_MAX / Abs(n1) < Abs(n2) )
+ {
+ BigInt a4 = n1;
+ a4 *= n2;
+
+ if ( a4.IsNeg() )
+ a4 -= n3 / 2;
+ else
+ a4 += n3 / 2;
+
+ a4 /= n3;
+ return (long)a4;
+ } // of if
+ else
+ {
+ long n4 = n1 * n2;
+ const long n3_2 = n3 / 2;
+
+ if( n4 < 0 )
+ {
+ if( ( n4 - LONG_MIN ) >= n3_2 )
+ n4 -= n3_2;
+ }
+ else if( ( LONG_MAX - n4 ) >= n3_2 )
+ n4 += n3_2;
+
+ return n4 / n3;
+ } // of else
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToLogic( const Point& rPtSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rPtSource, pMapModeSource, pMapModeDest );
+
+ return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToLogic( const Size& rSzSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rSzSource, pMapModeSource, pMapModeDest );
+
+ return Size( fn5( rSzSource.Width(),
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
+ fn5( rSzSource.Height(),
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( rRectSource, pMapModeSource, pMapModeDest );
+
+ return Rectangle( fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY,
+ fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+}
+
+// -----------------------------------------------------------------------
+
+long* OutputDevice::LogicToLogic( long* pX, USHORT nCount,
+ const MapMode* pMapModeSource,
+ const MapMode* pMapModeDest ) const
+{
+ ENTER1( pX, pMapModeSource, pMapModeDest );
+
+ for( ; nCount; nCount--, pX++ )
+ {
+ *pX = fn5( *pX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX );
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+Point OutputDevice::LogicToLogic( const Point& rPtSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rPtSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Point( fn3( rPtSource.X(), nNumerator, nDenominator ),
+ fn3( rPtSource.Y(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size OutputDevice::LogicToLogic( const Size& rSzSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rSzSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Size( fn3( rSzSource.Width(), nNumerator, nDenominator ),
+ fn3( rSzSource.Height(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Size( fn5( rSzSource.Width(),
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
+ fn5( rSzSource.Height(),
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource,
+ const MapMode& rMapModeSource,
+ const MapMode& rMapModeDest )
+{
+ if ( rMapModeSource == rMapModeDest )
+ return rRectSource;
+
+ MapUnit eUnitSource = rMapModeSource.GetMapUnit();
+ MapUnit eUnitDest = rMapModeDest.GetMapUnit();
+ ENTER2( eUnitSource, eUnitDest );
+
+ if ( rMapModeSource.mpImplMapMode->mbSimple &&
+ rMapModeDest.mpImplMapMode->mbSimple )
+ {
+ ENTER3( eUnitSource, eUnitDest );
+
+ return Rectangle( fn3( rRectSource.Left(), nNumerator, nDenominator ),
+ fn3( rRectSource.Top(), nNumerator, nDenominator ),
+ fn3( rRectSource.Right(), nNumerator, nDenominator ),
+ fn3( rRectSource.Bottom(), nNumerator, nDenominator ) );
+ }
+ else
+ {
+ ENTER4( rMapModeSource, rMapModeDest );
+
+ return Rectangle( fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY,
+ fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
+ aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
+ aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
+ aMapResDest.mnMapOfsX,
+ fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
+ aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
+ aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
+ aMapResDest.mnMapOfsY );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long OutputDevice::LogicToLogic( long nLongSource,
+ MapUnit eUnitSource, MapUnit eUnitDest )
+{
+ if ( eUnitSource == eUnitDest )
+ return nLongSource;
+
+ ENTER2( eUnitSource, eUnitDest );
+ ENTER3( eUnitSource, eUnitDest );
+
+ return fn3( nLongSource, nNumerator, nDenominator );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::ImplLogicUnitToPixelX( long nX, MapUnit eUnit )
+{
+ if ( eUnit != MAP_PIXEL )
+ {
+ ImplFrameData* pFrameData = mpFrameData;
+
+ // Map-Einheit verschieden, dann neu berechnen
+ if ( pFrameData->meMapUnit != eUnit )
+ {
+ pFrameData->meMapUnit = eUnit;
+ ImplCalcMapResolution( MapMode( eUnit ), mnDPIX, mnDPIY,
+ pFrameData->maMapUnitRes );
+ }
+
+ // Es wird kein BigInt gebraucht, da diese Funktion nur zur Umrechnung
+ // von Fensterposition benutzt wird
+ nX = nX * mnDPIX * pFrameData->maMapUnitRes.mnMapScNumX;
+ nX += nX >= 0 ? (pFrameData->maMapUnitRes.mnMapScDenomX/2) :
+ -((pFrameData->maMapUnitRes.mnMapScDenomX-1)/2);
+ nX /= pFrameData->maMapUnitRes.mnMapScDenomX;
+ }
+
+ return nX;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::ImplLogicUnitToPixelY( long nY, MapUnit eUnit )
+{
+ if ( eUnit != MAP_PIXEL )
+ {
+ ImplFrameData* pFrameData = mpFrameData;
+
+ // Map-Einheit verschieden, dann neu berechnen
+ if ( pFrameData->meMapUnit != eUnit )
+ {
+ pFrameData->meMapUnit = eUnit;
+ ImplCalcMapResolution( MapMode( eUnit ), mnDPIX, mnDPIY,
+ pFrameData->maMapUnitRes );
+ }
+
+ // Es wird kein BigInt gebraucht, da diese Funktion nur zur Umrechnung
+ // von Fensterposition benutzt wird
+ nY = nY * mnDPIY * pFrameData->maMapUnitRes.mnMapScNumY;
+ nY += nY >= 0 ? (pFrameData->maMapUnitRes.mnMapScDenomY/2) :
+ -((pFrameData->maMapUnitRes.mnMapScDenomY-1)/2);
+ nY /= pFrameData->maMapUnitRes.mnMapScDenomY;
+ }
+
+ return nY;
+}
diff --git a/vcl/source/gdi/polyscan.cxx b/vcl/source/gdi/polyscan.cxx
new file mode 100644
index 000000000000..cb9714d51765
--- /dev/null
+++ b/vcl/source/gdi/polyscan.cxx
@@ -0,0 +1,389 @@
+/*************************************************************************
+ *
+ * $RCSfile: polyscan.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+#include <tools/new.hxx>
+#include "salbtype.hxx"
+#include "poly.hxx"
+#include "polyscan.hxx"
+
+// ----------------
+// - PolyScanline -
+// ----------------
+
+PolyScanline::PolyScanline() :
+ mpFirst ( NULL ),
+ mpLast ( NULL ),
+ mpAct ( NULL ),
+ mnLeft ( 0L ),
+ mnRight ( 0L )
+{
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanline::~PolyScanline()
+{
+ ImplDelete();
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::ImplDelete()
+{
+ ScanlinePoint* pAct = mpFirst;
+
+ while( pAct )
+ {
+ ScanlinePoint* pNext = pAct->mpNext;
+ delete pAct;
+ pAct = pNext;
+ }
+
+ mnLeft = mnRight = 0L;
+ mpFirst = mpAct = mpLast = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::Insert( long nX )
+{
+ // first point to insert?
+ if( !mpFirst )
+ mpLast = mpFirst = new ScanlinePoint( mnLeft = mnRight = nX, NULL );
+ else
+ {
+ // insert at the beginning of the scanline
+ if( nX <= mpFirst->mnX )
+ mpFirst = new ScanlinePoint( mnLeft = nX, mpFirst );
+ else if( nX >= mnRight )
+ mpLast = mpLast->mpNext = new ScanlinePoint( mnRight = nX, NULL );
+ else
+ {
+ ScanlinePoint* pLast = mpFirst;
+ ScanlinePoint* pAct = mpFirst->mpNext;
+
+ while( pAct )
+ {
+ // insert in the midlle of the scanline?
+ if( nX <= pAct->mnX )
+ {
+ pLast->mpNext = new ScanlinePoint( nX, pAct );
+ break;
+ }
+
+ pLast = pAct;
+ pAct = pAct->mpNext;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanline::Set( long nStart, long nEnd )
+{
+ if( mpFirst )
+ ImplDelete();
+
+ if( nStart <= nEnd )
+ mpFirst = new ScanlinePoint( mnLeft = nStart, mpLast = new ScanlinePoint( mnRight = nEnd, NULL ) );
+ else
+ mpFirst = new ScanlinePoint( mnLeft = nEnd, mpLast = new ScanlinePoint( mnRight = nStart, NULL ) );
+}
+
+// ------------------------------------------------------------------------
+
+BOOL PolyScanline::GetFirstSegment( PolyScanSegment& rSegment )
+{
+ BOOL bRet = GetFirstX( rSegment.mnStart );
+
+ if( bRet && !GetNextX( rSegment.mnEnd ) )
+ rSegment.mnEnd = rSegment.mnStart;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+BOOL PolyScanline::GetNextSegment( PolyScanSegment& rSegment )
+{
+ BOOL bRet = GetNextX( rSegment.mnStart );
+
+ if( bRet && !GetNextX( rSegment.mnEnd ) )
+ rSegment.mnEnd = rSegment.mnStart;
+
+ return bRet;
+}
+
+// ---------------
+// - PolyScanner -
+// ---------------
+
+PolyScanner::PolyScanner( const Rectangle& rRect )
+{
+ if( !rRect.IsEmpty() )
+ {
+ Rectangle aRect( rRect );
+ ULONG nHeight;
+
+ aRect.Justify();
+ mnLeft = aRect.Left();
+ mnTop = aRect.Top();
+ mnRight = aRect.Right();
+ mnBottom = aRect.Bottom();
+ mpArray = new PolyScanline[ nHeight = Height() ];
+
+ for( ULONG i = 0UL; i < nHeight; i++ )
+ mpArray[ i ].Set( mnLeft, mnRight );
+ }
+ else
+ {
+ mnLeft = mnTop = mnRight = mnBottom = 0L;
+ mpArray = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::PolyScanner( const Polygon& rPoly )
+{
+ const long nCount = rPoly.GetSize();
+
+ if( nCount )
+ {
+ long nLast = nCount - 1;
+ Point aFirst( rPoly[ 0 ] );
+ Point aLast( rPoly[ (USHORT) nLast ] );
+
+ while( nLast && ( aLast == aFirst ) )
+ aLast = rPoly[ (USHORT) --nLast ];
+
+ if( !nLast )
+ {
+ aLast = rPoly[ 0 ];
+ mnLeft = mnRight = aLast.X();
+ mnTop = mnBottom = aLast.Y();
+ mpArray = new PolyScanline[ 1UL ];
+ mpArray[ 0 ].Set( mnLeft, mnRight );
+ }
+ else
+ {
+ const Rectangle aRect( rPoly.GetBoundRect() );
+ ULONG nHeight;
+
+ mnLeft = aRect.Left();
+ mnTop = aRect.Top();
+ mnRight = aRect.Right();
+ mnBottom = aRect.Bottom();
+ aLast = aFirst;
+ mpArray = new PolyScanline[ nHeight = Height() ];
+
+ for( long i = 1L; i <= nLast; i++ )
+ {
+ const Point& rPt = rPoly[ (USHORT) i ];
+
+ if( rPt != aLast )
+ {
+ InsertLine( aLast, rPt );
+ aLast = rPt;
+ }
+ }
+
+ InsertLine( aLast, aFirst );
+ }
+ }
+ else
+ mpArray = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::PolyScanner( const PolyPolygon& rPolyPoly )
+{
+ mpArray = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanner::~PolyScanner()
+{
+ delete[] mpArray;
+}
+
+// ------------------------------------------------------------------------
+
+PolyScanline* PolyScanner::operator[]( ULONG nPos ) const
+{
+ DBG_ASSERT( nPos < Count(), "nPos out of range!" );
+ return( mpArray ? ( mpArray + nPos ) : NULL );
+}
+
+// ------------------------------------------------------------------------
+
+void PolyScanner::InsertLine( const Point& rStart, const Point& rEnd )
+{
+ long nX, nY;
+
+ if( rStart.Y() == rEnd.Y() )
+ mpArray[ rStart.Y() - mnTop ].Insert( rStart.X() );
+ else if( rStart.X() == rEnd.X() )
+ {
+ // vertical line
+ const long nEndY = rEnd.Y();
+
+ nX = rStart.X();
+ nY = rStart.Y();
+
+ if( nEndY > nY )
+ while( nY < nEndY )
+ mpArray[ nY++ - mnTop ].Insert( nX );
+ else
+ while( nY > nEndY )
+ mpArray[ nY-- - mnTop ].Insert( nX );
+ }
+ else
+ {
+ const long nDX = labs( rEnd.X() - rStart.X() );
+ const long nDY = labs( rEnd.Y() - rStart.Y() );
+ const long nStartX = rStart.X();
+ const long nStartY = rStart.Y();
+ const long nEndX = rEnd.X();
+ const long nEndY = rEnd.Y();
+ const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
+ const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
+ long nLastX = nStartX;
+ long nLastY = nStartY;
+ BOOL bLast = FALSE;
+
+ mpArray[ nStartY - mnTop ].Insert( nStartX );
+
+ if( nDX >= nDY )
+ {
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+
+ for( nX = nStartX, nY = nLastY = nStartY; nX != nEndX; )
+ {
+ if( nY != nLastY )
+ {
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+
+ mpArray[ nY - mnTop ].Insert( nX );
+ bLast = FALSE;
+ }
+ else
+ bLast = TRUE;
+
+ nLastX = nX;
+ nLastY = nY;
+
+ if( nD < 0L )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+ nY += nYInc;
+ }
+
+ nX += nXInc;
+ }
+ }
+ else
+ {
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+
+ for( nX = nStartX, nY = nStartY; nY != nEndY; )
+ {
+ if( nY != nLastY )
+ {
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+
+ mpArray[ nY - mnTop ].Insert( nX );
+ bLast = FALSE;
+ }
+ else
+ bLast = TRUE;
+
+ nLastX = nX;
+ nLastY = nY;
+
+ if( nD < 0L )
+ nD += nDY2;
+ else
+ {
+ nD += nDYX;
+ nX += nXInc;
+ }
+
+ nY += nYInc;
+ }
+ }
+
+ if( bLast )
+ mpArray[ nLastY - mnTop ].Insert( nLastX );
+ }
+}
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
new file mode 100644
index 000000000000..84c54f0cc5b2
--- /dev/null
+++ b/vcl/source/gdi/print.cxx
@@ -0,0 +1,1979 @@
+/*************************************************************************
+ *
+ * $RCSfile: print.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_PRINT_CXX
+#define _SPOOLPRINTER_EXT
+#define _RMPRINTER_EXT
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+
+#ifndef REMOTE_APPSERVER
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALPTYPE_HXX
+#include <salptype.hxx>
+#endif
+#ifndef _SV_SALPRN_HXX
+#include <salprn.hxx>
+#endif
+
+#else
+
+#include "rmoutdev.hxx"
+#include "rmprint.hxx"
+#include "rmwindow.hxx"
+#include "rvp.hxx"
+#include <vos/mutex.hxx>
+
+using namespace ::com::sun::star::uno;
+
+struct SalPrinterQueueInfo
+{
+ XubString maPrinterName;
+ XubString maDriver;
+ XubString maLocation;
+ XubString maComment;
+ ULONG mnStatus;
+ ULONG mnJobs;
+ void* mpSysData;
+
+ SalPrinterQueueInfo();
+ ~SalPrinterQueueInfo();
+};
+
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_JOBSET_H
+#include <jobset.h>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_IMPPRN_HXX
+#include <impprn.hxx>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+
+int nImplSysDialog = 0;
+
+#define PRINTERSEQ_GET( _def_Seq, _def_Obj ) \
+{ \
+ SvMemoryStream* _def_pStm = new SvMemoryStream( (char*)_def_Seq.getConstArray(), _def_Seq.getLength(), STREAM_READ ); \
+ _def_pStm->SetCompressMode( COMPRESSMODE_FULL ); \
+ *_def_pStm >> _def_Obj; \
+ delete _def_pStm; \
+}
+
+#define PRINTERSEQ_SET( _def_Obj, _def_Seq, _def_Type ) \
+{ \
+ SvMemoryStream* _def_pStm = new SvMemoryStream( 8192, 8192 ); \
+ _def_pStm->SetCompressMode( COMPRESSMODE_FULL ); \
+ *_def_pStm << _def_Obj; \
+ _def_Seq = _def_Type( (sal_Int8*) (_def_pStm)->GetData(), (_def_pStm)->Tell() ); \
+ delete _def_pStm; \
+}
+
+// =======================================================================
+
+#define PAPER_SLOPPY 20
+#define PAPER_COUNT 9
+
+static long ImplPaperFormats[PAPER_COUNT*2] =
+{
+ 29700, 42000, // A3
+ 21000, 29700, // A4
+ 14800, 21000, // A5
+ 25000, 35300, // B4
+ 17600, 25000, // B5
+ 21600, 27900, // Letter
+ 21600, 35600, // Legal
+ 27900, 43100, // Tabloid
+ 0, 0 // USER
+};
+
+// =======================================================================
+
+Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
+{
+ USHORT i;
+
+ for( i = 0; i < PAPER_COUNT; i++ )
+ {
+ if ( (ImplPaperFormats[i*2] == nWidth100thMM) &&
+ (ImplPaperFormats[i*2+1] == nHeight100thMM) )
+ return (Paper)i;
+ }
+
+ for( i = 0; i < PAPER_COUNT; i++ )
+ {
+ if ( (Abs( ImplPaperFormats[i*2]-nWidth100thMM ) < PAPER_SLOPPY) &&
+ (Abs( ImplPaperFormats[i*2+1]-nHeight100thMM ) < PAPER_SLOPPY) )
+ return (Paper)i;
+ }
+
+ return PAPER_USER;
+}
+
+// =======================================================================
+
+void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
+{
+ const ImplJobSetup* pConstData = rJobSetup.ImplGetConstData();
+
+ if ( !pConstData->mnPaperWidth || !pConstData->mnPaperHeight )
+ {
+ if ( pConstData->mePaperFormat != PAPER_USER )
+ {
+ ImplJobSetup* pData = rJobSetup.ImplGetData();
+ pData->mnPaperWidth = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2];
+ pData->mnPaperHeight = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2+1];
+ }
+ }
+ else if ( pConstData->mePaperFormat == PAPER_USER )
+ {
+ Paper ePaper = ImplGetPaperFormat( pConstData->mnPaperWidth, pConstData->mnPaperHeight );
+ if ( ePaper != PAPER_USER )
+ rJobSetup.ImplGetData()->mePaperFormat = ePaper;
+ }
+}
+
+// =======================================================================
+
+QueueInfo::QueueInfo()
+{
+ mnStatus = 0;
+ mnJobs = 0;
+}
+
+// -----------------------------------------------------------------------
+
+QueueInfo::QueueInfo( const QueueInfo& rInfo ) :
+ maPrinterName( rInfo.maPrinterName ),
+ maDriver( rInfo.maDriver ),
+ maLocation( rInfo.maLocation ),
+ maComment( rInfo.maComment ),
+ mnStatus( rInfo.mnStatus ),
+ mnJobs( rInfo.mnJobs )
+{
+}
+
+// -----------------------------------------------------------------------
+
+QueueInfo::~QueueInfo()
+{
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& QueueInfo::operator==( const QueueInfo& rInfo )
+{
+ maPrinterName = rInfo.maPrinterName;
+ maDriver = rInfo.maDriver;
+ maLocation = rInfo.maLocation;
+ maComment = rInfo.maComment;
+ mnStatus = rInfo.mnStatus;
+ mnJobs = rInfo.mnJobs;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStream, const QueueInfo& rInfo )
+{
+ VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
+
+ rOStream.WriteByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
+ rOStream.WriteByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
+ rOStream << rInfo.mnStatus;
+ rOStream << rInfo.mnJobs;
+
+ return rOStream;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStream, QueueInfo& rInfo )
+{
+ VersionCompat aCompat( rIStream, STREAM_READ );
+
+ rIStream.ReadByteString( rInfo.maPrinterName, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maDriver, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maLocation, RTL_TEXTENCODING_UTF8 );
+ rIStream.ReadByteString( rInfo.maComment, RTL_TEXTENCODING_UTF8 );
+ rIStream >> rInfo.mnStatus;
+ rIStream >> rInfo.mnJobs;
+
+ return rIStream;
+}
+
+// =======================================================================
+
+SalPrinterQueueInfo::SalPrinterQueueInfo()
+{
+ mnStatus = 0;
+ mnJobs = QUEUE_JOBS_DONTKNOW;
+ mpSysData = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinterQueueInfo::~SalPrinterQueueInfo()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ImplPrnQueueList::Add( SalPrinterQueueInfo* pData )
+{
+ ImplPrnQueueData* pInfo = new ImplPrnQueueData;
+ pInfo->mpQueueInfo = NULL;
+ pInfo->mpSalQueueInfo = pData;
+ List::Insert( (void*)pInfo, LIST_APPEND );
+}
+
+// =======================================================================
+
+static void ImplInitPrnQueueList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ pSVData->maGDIData.mpPrinterQueueList = new ImplPrnQueueList;
+
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->GetPrinterQueueInfo( pSVData->maGDIData.mpPrinterQueueList );
+#else
+ if ( pSVData->mpRemotePrinterList && pSVData->mpRemotePrinterList->GetPrinterCount() )
+ {
+ const ULONG nCount = pSVData->mpRemotePrinterList->GetPrinterCount();
+ for( ULONG i = 0; i < nCount; i++ )
+ {
+ NMSP_CLIENT::RmQueueInfo aRmQInfo;
+ QueueInfo aQInfo;
+ SalPrinterQueueInfo* pNewInfo = new SalPrinterQueueInfo;
+
+ RemotePrinterInfo* pPrinterInfo = pSVData->mpRemotePrinterList->GetPrinter( i );
+ REF( NMSP_CLIENT::XRmPrinterEnvironment ) xPrinterEnv( pSVData->mpRemotePrinterList->GetPrinterEnv( pPrinterInfo->aServerName ) );
+
+ if ( xPrinterEnv.is() && xPrinterEnv->GetPrinterInfo(
+ pPrinterInfo->aPrinterName.GetBuffer(), aRmQInfo ) )
+ {
+ PRINTERSEQ_GET( aRmQInfo, aQInfo );
+ pNewInfo->maPrinterName = pPrinterInfo->GetFullName();
+ pNewInfo->maDriver = aQInfo.GetDriver();
+ pNewInfo->maLocation = aQInfo.GetLocation();
+ pNewInfo->maComment = aQInfo.GetComment();
+ pNewInfo->mnStatus = aQInfo.GetStatus();
+ pNewInfo->mnJobs = aQInfo.GetJobs();
+ pNewInfo->mpSysData = NULL;
+ pSVData->maGDIData.mpPrinterQueueList->Add( pNewInfo );
+ }
+ }
+ }
+ if ( !pSVData->maGDIData.mpPrinterQueueList->Count() )
+ {
+ SalPrinterQueueInfo* pNewInfo = new SalPrinterQueueInfo;
+ pNewInfo->maPrinterName = String::CreateFromAscii("No Printer");
+ pNewInfo->mpSysData = NULL;
+ pSVData->maGDIData.mpPrinterQueueList->Add( pNewInfo );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void ImplDeletePrnQueueList()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList;
+
+ if ( pPrnList )
+ {
+ ImplPrnQueueData* pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpQueueInfo )
+ delete pInfo->mpQueueInfo;
+
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->DeletePrinterQueueInfo( pInfo->mpSalQueueInfo );
+#else
+ delete pInfo->mpSalQueueInfo;
+#endif
+
+ delete pInfo;
+ pInfo = pPrnList->Next();
+ }
+
+ delete pPrnList;
+ pSVData->maGDIData.mpPrinterQueueList = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetQueueCount()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ return (USHORT)(pSVData->maGDIData.mpPrinterQueueList->Count());
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& Printer::GetQueueInfo( USHORT nQueue )
+{
+ return GetQueueInfo( nQueue, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+const QueueInfo& Printer::GetQueueInfo( USHORT nQueue, BOOL bStatus )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ DBG_ASSERT( nQueue < pSVData->maGDIData.mpPrinterQueueList->Count(),
+ "Printer::GetQueueInfo() - nQueue > QueueCount" );
+
+ ImplPrnQueueData* pInfo = pSVData->maGDIData.mpPrinterQueueList->Get( nQueue );
+
+#ifndef REMOTE_APPSERVER
+ if ( bStatus )
+ pSVData->mpDefInst->GetPrinterQueueState( pInfo->mpSalQueueInfo );
+#else
+ // ???
+#endif
+
+ if ( !pInfo->mpQueueInfo )
+ pInfo->mpQueueInfo = new QueueInfo;
+
+ pInfo->mpQueueInfo->maPrinterName = pInfo->mpSalQueueInfo->maPrinterName;
+ pInfo->mpQueueInfo->maDriver = pInfo->mpSalQueueInfo->maDriver;
+ pInfo->mpQueueInfo->maLocation = pInfo->mpSalQueueInfo->maLocation;
+ pInfo->mpQueueInfo->maComment = pInfo->mpSalQueueInfo->maComment;
+ pInfo->mpQueueInfo->mnStatus = pInfo->mpSalQueueInfo->mnStatus;
+ pInfo->mpQueueInfo->mnJobs = pInfo->mpSalQueueInfo->mnJobs;
+ return *pInfo->mpQueueInfo;
+}
+
+// -----------------------------------------------------------------------
+
+XubString Printer::GetDefaultPrinterName()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+#ifndef REMOTE_APPSERVER
+ return pSVData->mpDefInst->GetDefaultPrinter();
+#else
+ XubString aDefPrinterName;
+ if ( pSVData->mpRemotePrinterList )
+ {
+ RemotePrinterInfo* pDefPrinter = pSVData->mpRemotePrinterList->GetDefaultPrinter();
+ if ( pDefPrinter )
+ aDefPrinterName = pDefPrinter->GetFullName();
+
+ }
+ return aDefPrinterName;
+#endif
+}
+
+// =======================================================================
+
+void Printer::ImplInitData()
+{
+ mbDevOutput = FALSE;
+ meOutDevType = OUTDEV_PRINTER;
+
+ mbDefPrinter = FALSE;
+ mnError = 0;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ mnPageQueueSize = 0;
+ mnCopyCount = 1;
+ mbCollateCopy = FALSE;
+ mbPrinting = FALSE;
+ mbJobActive = FALSE;
+ mbPrintFile = FALSE;
+ mbInPrintPage = FALSE;
+ mbNewJobSetup = FALSE;
+ mpInfoPrinter = NULL;
+ mpPrinter = NULL;
+ mpDisplayDev = NULL;
+ mpQPrinter = NULL;
+ mpQMtf = NULL;
+ mbIsQueuePrinter = FALSE;
+
+ // Printer in die Liste eintragen
+ ImplSVData* pSVData = ImplGetSVData();
+ mpNext = pSVData->maGDIData.mpFirstPrinter;
+ mpPrev = NULL;
+ if ( mpNext )
+ mpNext->mpPrev = this;
+ else
+ pSVData->maGDIData.mpLastPrinter = this;
+ pSVData->maGDIData.mpFirstPrinter = this;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplInit( SalPrinterQueueInfo* pInfo )
+{
+ // Testen, ob Treiber ueberhaupt mit dem JobSetup uebereinstimmt
+ ImplJobSetup* pJobSetup = maJobSetup.ImplGetData();
+
+ if ( pJobSetup->mpDriverData )
+ {
+ if ( (pJobSetup->maPrinterName != pInfo->maPrinterName) ||
+ (pJobSetup->maDriver != pInfo->maDriver) )
+ {
+ delete pJobSetup->mpDriverData;
+ pJobSetup->mpDriverData = NULL;
+ pJobSetup->mnDriverDataLen = 0;
+ }
+ }
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Printernamen merken
+ maPrinterName = pInfo->maPrinterName;
+ maDriver = pInfo->maDriver;
+
+ // In JobSetup den Printernamen eintragen
+ pJobSetup->maPrinterName = maPrinterName;
+ pJobSetup->maDriver = maDriver;
+
+#ifndef REMOTE_APPSERVER
+ mpInfoPrinter = pSVData->mpDefInst->CreateInfoPrinter( pInfo, pJobSetup );
+ mpPrinter = NULL;
+ mpJobPrinter = NULL;
+ mpJobGraphics = NULL;
+ ImplUpdateJobSetupPaper( maJobSetup );
+
+ if ( !mpInfoPrinter )
+ {
+ ImplInitDisplay( NULL );
+ return;
+ }
+
+ // we need a graphics
+ if ( !ImplGetGraphics() )
+ {
+ ImplInitDisplay( NULL );
+ return;
+ }
+#else
+
+ String aPrinterName( maPrinterName.GetToken( 0, '@' ) );
+ String aPrintServerName( maPrinterName.GetToken( 1, '@' ) );
+
+
+ mpInfoPrinter = new RmPrinter;
+
+ Reference< ::com::sun::star::lang::XMultiServiceFactory > xPrinterFactory;
+ Reference< NMSP_CLIENT::XRmPrinter > xPrinter;
+
+ if (pSVData->mpRemotePrinterList)
+ {
+// if ( !aPrintServerName.Len() )
+// aPrintServerName = pSVData->mpRemotePrinterList->FindLocalPrintServer( aPrinterName );
+
+ xPrinterFactory = pSVData->mpRemotePrinterList->GetServerFactory( aPrintServerName );
+ if( xPrinterFactory.is() )
+ {
+ xPrinter = Reference< NMSP_CLIENT::XRmPrinter >( xPrinterFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OfficePrinter.stardiv.de" ) ) ), NMSP_UNO::UNO_QUERY );
+ mpInfoPrinter->SetInterface( xPrinter );
+ }
+ }
+
+ if ( ! xPrinter.is() )
+ {
+ delete mpInfoPrinter;
+ mpInfoPrinter = NULL;
+ ImplInitDisplay( NULL );
+ return;
+ }
+ else
+ {
+ QueueInfo aQInfo;
+ NMSP_CLIENT::RmQueueInfo aRmQInfo;
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ const REF( NMSP_CLIENT::XRmPrinter )& rxPrinter = mpInfoPrinter->GetInterface();
+
+ aQInfo.maPrinterName = aPrinterName;
+ aQInfo.maDriver = pInfo->maDriver;
+ aQInfo.maLocation = pInfo->maLocation;
+ aQInfo.maComment = pInfo->maComment;
+ aQInfo.mnStatus = pInfo->mnStatus;
+ aQInfo.mnJobs = pInfo->mnJobs;
+
+ PRINTERSEQ_SET( aQInfo, aRmQInfo, NMSP_CLIENT::RmQueueInfo );
+ mpInfoPrinter->Create( aRmQInfo, aRmJobSetup );
+ PRINTERSEQ_GET( aRmJobSetup, maJobSetup );
+
+ if( rxPrinter.is() )
+ {
+ mpGraphics = new ImplServerGraphics( pSVData->mpRemotePrinterList->GetServerAtoms( aPrintServerName ) );
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )( rxPrinter, NMSP_UNO::UNO_QUERY ) );
+ }
+
+ if( !mpGraphics->GetInterface().is() )
+ {
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ ImplInitDisplay( NULL );
+ return;
+ }
+ }
+#endif
+
+ // Daten initialisieren
+ ImplUpdatePageData();
+ mpFontList = new ImplDevFontList;
+ mpFontCache = new ImplFontCache( TRUE );
+ mpGraphics->GetDevFontList( mpFontList );
+ mpFontList->InitStdFonts();
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplInitDisplay( const Window* pWindow )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ mpInfoPrinter = NULL;
+ mpPrinter = NULL;
+ mpJobPrinter = NULL;
+ mpJobGraphics = NULL;
+
+ if ( pWindow )
+ mpDisplayDev = new VirtualDevice( *pWindow );
+ else
+ mpDisplayDev = new VirtualDevice();
+ mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mnDPIX = mpDisplayDev->mnDPIX;
+ mnDPIY = mpDisplayDev->mnDPIY;
+
+#ifdef REMOTE_APPSERVER
+ mpGraphics = mpDisplayDev->mpGraphics;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinterQueueInfo* Printer::ImplGetQueueInfo( const XubString& rPrinterName,
+ const XubString* pDriver )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( !pSVData->maGDIData.mpPrinterQueueList )
+ ImplInitPrnQueueList();
+
+ ImplPrnQueueList* pPrnList = pSVData->maGDIData.mpPrinterQueueList;
+ if ( pPrnList && pPrnList->Count() )
+ {
+ // Zuerst suchen wir nach dem Printer-Namen
+ ImplPrnQueueData* pBestInfo = NULL;
+ ImplPrnQueueData* pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName == rPrinterName )
+ {
+ pBestInfo = pInfo;
+ if ( !pDriver || (pInfo->mpSalQueueInfo->maDriver == *pDriver) )
+ return pInfo->mpSalQueueInfo;
+ }
+ pInfo = pPrnList->Next();
+ }
+
+ // Wenn wir einen PrinterNamen gefunden haben und nur der Treiber
+ // nicht passt, nehmen wir diesen
+ if ( pBestInfo )
+ return pBestInfo->mpSalQueueInfo;
+
+ // Dann suchen wir caseinsensitiv
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName.EqualsIgnoreCaseAscii( rPrinterName ) )
+ {
+ pBestInfo = pInfo;
+ if ( !pDriver || pInfo->mpSalQueueInfo->maDriver.EqualsIgnoreCaseAscii( *pDriver ) )
+ return pInfo->mpSalQueueInfo;
+ }
+ pInfo = pPrnList->Next();
+ }
+
+ // Wenn wir einen PrinterNamen gefunden haben und nur der Treiber
+ // nicht passt, nehmen wir diesen
+ if ( pBestInfo )
+ return pBestInfo->mpSalQueueInfo;
+
+ // Und wenn wir immer noch keinen gefunden haben, suchen wir
+ // noch nach einem passenden Treiber
+ if ( pDriver )
+ {
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maDriver == *pDriver )
+ return pInfo->mpSalQueueInfo;
+ pInfo = pPrnList->Next();
+ }
+ }
+
+ // Und wenn wir immer noch keinen gefunden, dann wir der
+ // Default-Drucker genommen
+ XubString aPrinterName = GetDefaultPrinterName();
+ pInfo = pPrnList->First();
+ while ( pInfo )
+ {
+ if ( pInfo->mpSalQueueInfo->maPrinterName == aPrinterName )
+ return pInfo->mpSalQueueInfo;
+ pInfo = pPrnList->Next();
+ }
+
+ // Und wenn wir diesen auch nicht finden, nehmen wir den ersten
+ // in der Liste, denn einige Installationen zerstoeren den
+ // Namen und andere Programme weichen dann normalerweise noch
+ // auf irgendeinen Drucker aus
+ pInfo = pPrnList->First();
+ if ( pInfo )
+ return pInfo->mpSalQueueInfo;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplUpdatePageData()
+{
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !ImplGetGraphics() )
+ return;
+
+ mpGraphics->GetResolution( mnDPIX, mnDPIY );
+ mpInfoPrinter->GetPageInfo( maJobSetup.ImplGetConstData(),
+ mnOutWidth, mnOutHeight,
+ maPageOffset.X(), maPageOffset.Y(),
+ maPaperSize.Width(), maPaperSize.Height() );
+#else
+ if ( mpInfoPrinter && mpGraphics )
+ {
+ mpGraphics->GetResolution( mnDPIX, mnDPIY );
+ mpInfoPrinter->GetPageInfo( mnOutWidth, mnOutHeight,
+ maPageOffset.X(), maPageOffset.Y(),
+ maPaperSize.Width(), maPaperSize.Height() );
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplUpdateFontList()
+{
+ ImplUpdateFontData( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer()
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( GetDefaultPrinterName(), NULL );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ if ( !IsDisplayPrinter() )
+ mbDefPrinter = TRUE;
+ }
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const Window* pWindow )
+{
+ ImplInitData();
+ ImplInitDisplay( pWindow );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const JobSetup& rJobSetup ) :
+ maJobSetup( rJobSetup )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rJobSetup.mpData->maPrinterName,
+ &rJobSetup.mpData->maDriver );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ SetJobSetup( rJobSetup );
+ }
+ else
+ {
+ ImplInitDisplay( NULL );
+ maJobSetup = JobSetup();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const QueueInfo& rQueueInfo )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rQueueInfo.GetPrinterName(),
+ &rQueueInfo.GetDriver() );
+ if ( pInfo )
+ ImplInit( pInfo );
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::Printer( const XubString& rPrinterName )
+{
+ ImplInitData();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( rPrinterName, NULL );
+ if ( pInfo )
+ ImplInit( pInfo );
+ else
+ ImplInitDisplay( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Printer::~Printer()
+{
+ DBG_ASSERT( !IsPrinting(), "Printer::~Printer() - Job is printing" );
+ DBG_ASSERT( !IsJobActive(), "Printer::~Printer() - Job is active" );
+ DBG_ASSERT( !mpQPrinter, "Printer::~Printer() - QueuePrinter not destroyed" );
+ DBG_ASSERT( !mpQMtf, "Printer::~Printer() - QueueMetafile not destroyed" );
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter )
+ ImplGetSVData()->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+ if ( mpDisplayDev )
+ delete mpDisplayDev;
+ else
+ {
+ // OutputDevice-Dtor versucht das gleiche, deshalb muss hier
+ // der FontEntry auch auf NULL gesetzt werden
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ }
+
+ // Printer aus der Liste eintragen
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ pSVData->maGDIData.mpFirstPrinter = mpNext;
+ if ( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ pSVData->maGDIData.mpLastPrinter = mpPrev;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Printer::GetCapabilities( USHORT nType ) const
+{
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ return mpInfoPrinter->GetCapabilities( maJobSetup.ImplGetConstData(), nType );
+#else
+ return mpInfoPrinter->GetCapabilities( nType );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::HasSupport( PrinterSupport eFeature, BOOL bInJob ) const
+{
+ switch ( eFeature )
+ {
+ case SUPPORT_SET_ORIENTATION:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETORIENTATION );
+ case SUPPORT_SET_PAPERBIN:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERBIN );
+ case SUPPORT_SET_PAPERSIZE:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPERSIZE );
+ case SUPPORT_SET_PAPER:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SETPAPER );
+ case SUPPORT_COPY:
+ return (GetCapabilities( PRINTER_CAPABILITIES_COPIES ) != 0);
+ case SUPPORT_COLLATECOPY:
+ return (GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES ) != 0);
+ case SUPPORT_SETUPDIALOG:
+ return (BOOL)GetCapabilities( PRINTER_CAPABILITIES_SUPPORTDIALOG );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetJobSetup( const JobSetup& rSetup )
+{
+ if ( IsDisplayPrinter() || mbInPrintPage )
+ return FALSE;
+
+ JobSetup aJobSetup = rSetup;
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetPrinterData( aJobSetup.ImplGetData() ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+
+ return FALSE;
+#else
+ if ( mpInfoPrinter )
+ {
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetJobSetup( aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ return FALSE;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+IMPL_LINK( Printer, UserSetupCompleted, ::com::sun::star::uno::Any*, pResult )
+{
+ ::vos::OGuard guard( Application::GetSolarMutex( ) );
+
+ if( pResult->hasValue() )
+ {
+ mbUserSetupResult = TRUE;
+
+ ::com::sun::star::portal::client::RmJobSetup aRmJobSetup;
+ *pResult >>= aRmJobSetup;
+ JobSetup aJobSetup;
+ PRNSEQ_GET( aRmJobSetup, aJobSetup );
+
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ }
+ else
+ mbUserSetupResult = FALSE;
+
+ mbUserSetupCompleted = TRUE;
+ return 0;
+}
+#endif
+
+BOOL Printer::Setup( Window* pWindow )
+{
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ JobSetup aJobSetup = maJobSetup;
+ SalFrame* pFrame;
+ if ( !pWindow )
+ pFrame = ImplGetDefaultWindow()->ImplGetFrame();
+ else
+ pFrame = pWindow->ImplGetFrame();
+ ImplReleaseGraphics();
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maAppData.mnModalMode++;
+ nImplSysDialog++;
+ BOOL bSetup = mpInfoPrinter->Setup( pFrame, aJobSetup.ImplGetData() );
+ pSVData->maAppData.mnModalMode--;
+ nImplSysDialog--;
+ if ( bSetup )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ return FALSE;
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRNSEQ_SET( aRmJobSetup, maJobSetup );
+ mpInfoPrinter->SetJobSetup( aRmJobSetup );
+ RmFrameWindow* pFrame;
+ if ( !pWindow )
+ pFrame = ImplGetDefaultWindow()->ImplGetFrame();
+ else
+ pFrame = pWindow->ImplGetFrame();
+ mbUserSetupCompleted = FALSE;
+ mpInfoPrinter->UserSetup( pFrame->GetFrameInterface(), pFrame->InsertUserEventLink( LINK( this, Printer, UserSetupCompleted ) ) );
+ while( ! mbUserSetupCompleted )
+ Application::Reschedule();
+ return mbUserSetupResult;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPrinterProps( const Printer* pPrinter )
+{
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ mbDefPrinter = pPrinter->mbDefPrinter;
+ maPrintFile = pPrinter->maPrintFile;
+ mbPrintFile = pPrinter->mbPrintFile;
+ mnCopyCount = pPrinter->mnCopyCount;
+ mbCollateCopy = pPrinter->mbCollateCopy;
+ mnPageQueueSize = pPrinter->mnPageQueueSize;
+
+ if ( pPrinter->IsDisplayPrinter() )
+ {
+ // Alten Printer zerstoeren
+ if ( !IsDisplayPrinter() )
+ {
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+ mpInfoPrinter = NULL;
+ }
+
+ // Neuen Printer bauen
+ ImplInitDisplay( NULL );
+ return TRUE;
+ }
+
+ // Alten Printer zerstoeren?
+ if ( GetName() != pPrinter->GetName() )
+ {
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+#endif
+ if ( mpDisplayDev )
+ {
+ delete mpDisplayDev;
+ mpDisplayDev = NULL;
+ }
+ else
+ {
+#ifndef REMOTE_APPSERVER
+ pSVData->mpDefInst->DestroyInfoPrinter( mpInfoPrinter );
+#else
+ if ( mpInfoPrinter )
+ {
+ if( mpGraphics )
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+
+ ImplReleaseServerGraphics();
+ delete mpGraphics, mpGraphics = NULL;
+ delete mpInfoPrinter, mpInfoPrinter = NULL;
+ }
+#endif
+
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+ delete mpFontList;
+ delete mpFontCache;
+ mbInitFont = TRUE;
+ mbNewFont = TRUE;
+ mpInfoPrinter = NULL;
+ }
+
+ // Neuen Printer bauen
+ XubString maDriver = pPrinter->GetDriverName();
+ SalPrinterQueueInfo* pInfo = ImplGetQueueInfo( pPrinter->GetName(), &maDriver );
+ if ( pInfo )
+ {
+ ImplInit( pInfo );
+ SetJobSetup( pPrinter->GetJobSetup() );
+ }
+ else
+ ImplInitDisplay( NULL );
+ }
+ else
+ SetJobSetup( pPrinter->GetJobSetup() );
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetOrientation( Orientation eOrientation )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( maJobSetup.ImplGetConstData()->meOrientation != eOrientation )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->meOrientation = eOrientation;
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_ORIENTATION, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetOrientation( (unsigned short)eOrientation, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Orientation Printer::GetOrientation() const
+{
+ return maJobSetup.ImplGetConstData()->meOrientation;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaperBin( USHORT nPaperBin )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( (maJobSetup.ImplGetConstData()->mnPaperBin != nPaperBin) &&
+ (nPaperBin < GetPaperBinCount()) )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mnPaperBin = nPaperBin;
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERBIN, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaperBin( nPaperBin, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetPaperBin() const
+{
+ return maJobSetup.ImplGetConstData()->mnPaperBin;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaper( Paper ePaper )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ if ( maJobSetup.ImplGetConstData()->mePaperFormat != ePaper )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mePaperFormat = ePaper;
+ if ( ePaper != PAPER_USER )
+ {
+ pSetupData->mnPaperWidth = ImplPaperFormats[((USHORT)ePaper)*2];
+ pSetupData->mnPaperHeight = ImplPaperFormats[((USHORT)ePaper)*2+1];
+ }
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaper( (unsigned short)ePaper, aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetPaperSizeUser( const Size& rSize )
+{
+ if ( mbInPrintPage )
+ return FALSE;
+
+ MapMode aMap100thMM( MAP_100TH_MM );
+ Size aPixSize = LogicToPixel( rSize );
+ Size aPageSize = PixelToLogic( aPixSize, aMap100thMM );
+ if ( (maJobSetup.ImplGetConstData()->mePaperFormat != PAPER_USER) ||
+ (maJobSetup.ImplGetConstData()->mnPaperWidth != aPageSize.Width()) ||
+ (maJobSetup.ImplGetConstData()->mnPaperHeight != aPageSize.Height()) )
+ {
+ JobSetup aJobSetup = maJobSetup;
+ ImplJobSetup* pSetupData = aJobSetup.ImplGetData();
+ pSetupData->mePaperFormat = PAPER_USER;
+ pSetupData->mnPaperWidth = aPageSize.Width();
+ pSetupData->mnPaperHeight = aPageSize.Height();
+
+ if ( IsDisplayPrinter() )
+ {
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ return TRUE;
+ }
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+ if ( mpInfoPrinter->SetData( SAL_JOBSET_PAPERSIZE, pSetupData ) )
+ {
+ ImplUpdateJobSetupPaper( aJobSetup );
+#else
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRINTERSEQ_SET( aJobSetup, aRmJobSetup, NMSP_CLIENT::RmJobSetup );
+ if ( mpInfoPrinter->SetPaperSizeUser( aPixSize.Width(), aPixSize.Height(), aRmJobSetup ) )
+ {
+ PRINTERSEQ_GET( aRmJobSetup, aJobSetup );
+#endif
+ mbNewJobSetup = TRUE;
+ maJobSetup = aJobSetup;
+ ImplUpdatePageData();
+ ImplUpdateFontList();
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Paper Printer::GetPaper() const
+{
+ return maJobSetup.ImplGetConstData()->mePaperFormat;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Printer::GetPaperBinCount() const
+{
+ if ( IsDisplayPrinter() )
+ return 0;
+
+#ifndef REMOTE_APPSERVER
+ return (USHORT)mpInfoPrinter->GetPaperBinCount( maJobSetup.ImplGetConstData() );
+#else
+ if ( mpInfoPrinter )
+ return mpInfoPrinter->GetPaperBinCount();
+ else
+ return 0;
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+XubString Printer::GetPaperBinName( USHORT nPaperBin ) const
+{
+ if ( IsDisplayPrinter() )
+ return ImplGetSVEmptyStr();
+
+#ifndef REMOTE_APPSERVER
+ if ( nPaperBin < GetPaperBinCount() )
+ return mpInfoPrinter->GetPaperBinName( maJobSetup.ImplGetConstData(), nPaperBin );
+ else
+ return ImplGetSVEmptyStr();
+#else
+ if ( mpInfoPrinter )
+ return (String)mpInfoPrinter->GetPaperBinName( nPaperBin );
+ else
+ return ImplGetSVEmptyStr();
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::SetCopyCount( USHORT nCopy, BOOL bCollate )
+{
+ mnCopyCount = nCopy;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::Error()
+{
+ maErrorHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::StartPrint()
+{
+ maStartPrintHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::EndPrint()
+{
+ maEndPrintHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::PrintPage()
+{
+ maPrintPageHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+#ifndef REMOTE_APPSERVER
+
+ULONG ImplSalPrinterErrorCodeToVCL( ULONG nError )
+{
+ ULONG nVCLError;
+ switch ( nError )
+ {
+ case 0:
+ nVCLError = PRINTER_OK;
+ break;
+ case SAL_PRINTER_ERROR_ABORT:
+ nVCLError = PRINTER_ABORT;
+ break;
+ default:
+ nVCLError = PRINTER_GENERALERROR;
+ break;
+ }
+
+ return nVCLError;
+}
+
+// -----------------------------------------------------------------------
+
+void Printer::ImplEndPrint()
+{
+ mbPrinting = FALSE;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ EndPrint();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Printer, ImplDestroyPrinterAsync, void*, pSalPrinter )
+{
+ SalPrinter* pPrinter = (SalPrinter*)pSalPrinter;
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpDefInst->DestroyPrinter( pPrinter );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+#else
+
+// -----------------------------------------------------------------------
+
+static void ImplDeletePrintSpooler( PrintSpooler* pPrintSpooler )
+{
+ if( pPrintSpooler != 0 )
+ {
+ pPrintSpooler->mxPrintSpooler = REF( NMSP_CLIENT::XRmPrintSpooler )();
+ }
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::StartJob( const XubString& rJobName )
+{
+ mnError = PRINTER_OK;
+
+ if ( IsDisplayPrinter() )
+ return FALSE;
+
+ if ( IsJobActive() || IsPrinting() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ ULONG nCopies = mnCopyCount;
+ BOOL bCollateCopy = mbCollateCopy;
+ BOOL bUserCopy = FALSE;
+ if ( IsQueuePrinter() )
+ {
+ if ( ((ImplQPrinter*)this)->IsUserCopy() )
+ {
+ nCopies = 1;
+ bCollateCopy = FALSE;
+ }
+ }
+ else if ( nCopies > 1 )
+ {
+ ULONG nDevCopy;
+ if ( bCollateCopy )
+ nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES );
+ else
+ nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COPIES );
+ // Muessen Kopien selber gemacht werden?
+ if ( nCopies > nDevCopy )
+ {
+ bUserCopy = TRUE;
+ nCopies = 1;
+ bCollateCopy = FALSE;
+ if ( !mnPageQueueSize )
+ mnPageQueueSize = 1;
+ }
+ }
+ else
+ bCollateCopy = FALSE;
+
+ if ( !mnPageQueueSize )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
+
+ if ( !mpPrinter )
+ return FALSE;
+
+ XubString* pPrintFile;
+ if ( mbPrintFile )
+ pPrintFile = &maPrintFile;
+ else
+ pPrintFile = NULL;
+
+ if ( !mpPrinter->StartJob( pPrintFile, rJobName, Application::GetDisplayName(),
+ nCopies, bCollateCopy,
+ maJobSetup.ImplGetConstData() ) )
+ {
+ mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() );
+ if ( !mnError )
+ mnError = PRINTER_GENERALERROR;
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpDefInst->DestroyPrinter( mpPrinter );
+ mpPrinter = NULL;
+ return FALSE;
+ }
+
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mnCurPrintPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ StartPrint();
+ }
+ else
+ {
+ mpQPrinter = new ImplQPrinter( this );
+ mpQPrinter->SetUserCopy( bUserCopy );
+ if ( mpQPrinter->StartJob( rJobName ) )
+ {
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ StartPrint();
+ mpQPrinter->StartQueuePrint();
+ }
+ else
+ {
+ mnError = mpQPrinter->GetErrorCode();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ return FALSE;
+ }
+ }
+#else
+ BOOL bResult = FALSE;
+ ImplSVData* pSVData = ImplGetSVData();
+
+ String aServerName( maPrinterName.GetToken( 1, '@' ) );
+
+ // build a new connection if not client
+ Reference< ::com::sun::star::lang::XMultiServiceFactory > xServerFactory;
+ Reference< ::com::sun::star::connection::XConnection > xConnection;
+ Reference< ::com::sun::star::bridge::XBridgeFactory > xBridgeFactory;
+
+ if( ! aServerName.EqualsAscii( RVP_CLIENT_SERVER_NAME ) )
+ pSVData->mpRemotePrinterList->CreateNewPrinterConnection( maPrinterName.GetToken( 1, '@' ), xServerFactory, xConnection, xBridgeFactory );
+ else
+ xServerFactory = pSVData->mxClientFactory;
+ if( xServerFactory.is() )
+ {
+ REF( NMSP_CLIENT::XRmSpoolLauncher ) xLauncher( xServerFactory->createInstance( ::rtl::OUString::createFromAscii( "OfficeSpoolLauncher.stardiv.de" ) ), NMSP_UNO::UNO_QUERY );
+ if( xLauncher.is() &&
+ xLauncher->LaunchSpooler( pSVData->mpUserInfo->sName,
+ pSVData->mpUserInfo->sPassword ) )
+ {
+ if( xBridgeFactory.is() ) // else this a the client connection
+ {
+ // get objects from transferred sospool connection
+ xServerFactory = Reference< ::com::sun::star::lang::XMultiServiceFactory >();
+ Reference< ::com::sun::star::bridge::XBridge >
+ xBridge( xBridgeFactory->createBridge( ::rtl::OUString(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "iiop" ) ), xConnection, Reference< ::com::sun::star::bridge::XInstanceProvider >() ) );
+ xServerFactory = Reference< ::com::sun::star::lang::XMultiServiceFactory >( xBridge->getInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SpoolMultiServiceFactory.sprintd.daemons.stardiv.de" ) ) ), UNO_QUERY );
+ }
+
+ mpPrinter = new PrintSpooler();
+ mpPrinter->mxPrintSpooler = REF( NMSP_CLIENT::XRmPrintSpooler )( xServerFactory->createInstance( ::rtl::OUString::createFromAscii( "OfficePrintSpooler.stardiv.de" ) ), NMSP_UNO::UNO_QUERY );
+ if( mpPrinter->mxPrintSpooler.is() )
+ {
+ NMSP_CLIENT::RmJobSetup aRmJobSetup;
+ PRNSEQ_SET( aRmJobSetup, maJobSetup );
+ mpPrinter->mxPrintSpooler->Create( aRmJobSetup );
+ bResult = mpPrinter->mxPrintSpooler->StartJob( mnCopyCount, mbCollateCopy, rJobName, maPrintFile, mbPrintFile );
+ }
+ }
+
+ if ( bResult )
+ {
+ mbNewJobSetup = FALSE;
+ maJobName = rJobName;
+ mnCurPage = 1;
+ mnCurPrintPage = 1;
+ mbJobActive = TRUE;
+ mbPrinting = TRUE;
+ }
+ else if ( mpPrinter && mpPrinter->mxPrintSpooler.is() )
+ {
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+ }
+ }
+
+ if ( !bResult )
+ mnError = PRINTER_GENERALERROR;
+
+ return bResult;
+#endif
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::EndJob()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+ DBG_ASSERT( !mbInPrintPage, "Printer::EndJob() - StartPage() without EndPage() called" );
+
+ mbJobActive = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ ImplReleaseGraphics();
+
+ mnCurPage = 0;
+
+ if ( mpPrinter )
+ {
+ mbPrinting = FALSE;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+
+ mbDevOutput = FALSE;
+ mpPrinter->EndJob();
+ // Hier den Drucker nicht asyncron zerstoeren, da es
+ // W95 nicht verkraftet, wenn gleichzeitig gedruckt wird
+ // und ein Druckerobjekt zerstoert wird
+ ImplGetSVData()->mpDefInst->DestroyPrinter( mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+ }
+ else
+ mpQPrinter->EndQueuePrint();
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpPrinter->mxPrintSpooler->EndJob();
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ EndPrint();
+
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::AbortJob()
+{
+ // Wenn wir einen Queue-Printer haben, kann man diesen noch mit
+ // AbortJob() abbrechen, solange dieser noch am Drucken ist
+ if ( !IsJobActive() && !IsPrinting() )
+ return FALSE;
+
+ mbJobActive = FALSE;
+ mbInPrintPage = FALSE;
+ mpJobGraphics = NULL;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+
+ if ( mpPrinter )
+ {
+ ImplReleaseGraphics();
+ mbDevOutput = FALSE;
+ mpPrinter->AbortJob();
+ Application::PostUserEvent( LINK( this, Printer, ImplDestroyPrinterAsync ), mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+ }
+ else
+ {
+ mpQPrinter->AbortQueuePrint();
+ mpQPrinter->Destroy();
+ mpQPrinter = NULL;
+ if ( mpQMtf )
+ {
+ mpQMtf->Clear();
+ delete mpQMtf;
+ mpQMtf = NULL;
+ }
+ EndPrint();
+ }
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpPrinter->mxPrintSpooler->AbortJob();
+ if ( mpQMtf )
+ {
+ mpQMtf->Clear();
+ delete mpQMtf;
+ mpQMtf = NULL;
+ }
+
+ mbPrinting = FALSE;
+ mnCurPage = 0;
+ mnCurPrintPage = 0;
+ maJobName.Erase();
+ ImplDeletePrintSpooler( mpPrinter );
+ mpPrinter = NULL;
+ EndPrint();
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::StartPage()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ if ( mpPrinter )
+ {
+ SalGraphics* pGraphics = mpPrinter->StartPage( maJobSetup.ImplGetConstData(), mbNewJobSetup );
+ if ( pGraphics )
+ {
+ ImplReleaseGraphics();
+ mpJobGraphics = pGraphics;
+ }
+ mbDevOutput = TRUE;
+ }
+ else
+ {
+ ImplGetGraphics();
+ mpJobGraphics = mpGraphics;
+ }
+
+ // PrintJob not aborted ???
+ if ( IsJobActive() )
+ {
+ mbInPrintPage = TRUE;
+ mnCurPage++;
+ if ( mpQPrinter )
+ {
+ mpQMtf = new GDIMetaFile;
+ mpQMtf->Record( this );
+ mpQMtf->SaveStatus();
+ }
+ else
+ {
+ mnCurPrintPage++;
+ PrintPage();
+ }
+ }
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter )
+ {
+ mpQMtf = new GDIMetaFile;
+ mpQMtf->Record( this );
+ mpQMtf->SaveStatus();
+
+ mbInPrintPage = TRUE;
+ mnCurPage++;
+ mnCurPrintPage++;
+ PrintPage();
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Printer::EndPage()
+{
+ if ( !IsJobActive() )
+ return FALSE;
+
+ mbInPrintPage = FALSE;
+
+#ifndef REMOTE_APPSERVER
+ if ( mpPrinter || mpQPrinter )
+ {
+ if ( mpPrinter )
+ {
+ mpPrinter->EndPage();
+ ImplReleaseGraphics();
+ mbDevOutput = FALSE;
+ }
+ else if ( mpQPrinter )
+ {
+ // Eigentuemeruebergang an QPrinter
+ mpQMtf->Stop();
+ mpQMtf->WindStart();
+ GDIMetaFile* pPage = mpQMtf;
+ mpQMtf = NULL;
+ mpQPrinter->AddQueuePage( pPage, mnCurPage, mbNewJobSetup );
+ }
+
+ mpJobGraphics = NULL;
+ mbNewJobSetup = FALSE;
+
+ return TRUE;
+ }
+#else
+ if ( mpPrinter && mpQMtf )
+ {
+ mpQMtf->Stop();
+ mpQMtf->WindStart();
+
+ PrinterPage aPage( mpQMtf, mbNewJobSetup, GetJobSetup() );
+ NMSP_CLIENT::RmPrinterPage aRmPage;
+ PRINTERSEQ_SET( aPage, aRmPage, NMSP_CLIENT::RmPrinterPage );
+ mpPrinter->mxPrintSpooler->SpoolPage( aRmPage );
+ mpQMtf = NULL;
+ mbNewJobSetup = FALSE;
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx
new file mode 100644
index 000000000000..9e301b906012
--- /dev/null
+++ b/vcl/source/gdi/print2.cxx
@@ -0,0 +1,543 @@
+/*************************************************************************
+ *
+ * $RCSfile: print2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_PRINT_CXX
+#define _SPOOLPRINTER_EXT
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <gdimtf.hxx>
+#endif
+#ifndef _SV_PRINT_H
+#include <print.h>
+#endif
+#ifndef _SV_PRINT_HXX
+#include <print.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#define MAX_BANDWIDTH 1000000
+
+// -----------
+// - statics -
+// -----------
+
+static USHORT aSpecialPrintActions[] =
+{
+ META_TRANSPARENT_ACTION,
+ META_FLOATTRANSPARENT_ACTION
+};
+
+// -----------------
+// - ImplCheckRect -
+// -----------------
+
+struct ImplCheckRect
+{
+ Rectangle* mpRect;
+ MetaAction* mpAct;
+ ImplCheckRect* mpNext;
+ BOOL mbSpecialOutput;
+
+ ImplCheckRect() { }
+ ~ImplCheckRect() { delete mpRect; }
+ void ImplCreate( MetaAction* pAct, OutputDevice* pOut, BOOL bSpecial );
+ BOOL Intersects( const ImplCheckRect& rRect )
+ {
+ return( mpRect && rRect.mpRect ) ? mpRect->IsOver( *rRect.mpRect ) : FALSE;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+void ImplCheckRect::ImplCreate( MetaAction* pAct, OutputDevice* pOut, BOOL bSpecial )
+{
+ mpAct = pAct;
+ mpNext = NULL;
+
+ switch( mpAct->GetType() )
+ {
+ case( META_PIXEL_ACTION ):
+ mpRect = new Rectangle( ( (MetaPixelAction*) mpAct )->GetPoint(), Size( 1, 1 ) );
+ break;
+
+ case( META_POINT_ACTION ):
+ mpRect = new Rectangle( ( (MetaPointAction*) mpAct )->GetPoint(), Size( 1, 1 ) );
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ MetaLineAction* pA = (MetaLineAction*) mpAct;
+ mpRect = new Rectangle( pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ mpRect = new Rectangle( ( (MetaRectAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ MetaRoundRectAction* pA = (MetaRoundRectAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetHorzRound(),
+ pA->GetVertRound() ).GetBoundRect() );
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ MetaEllipseAction* pA = (MetaEllipseAction*) mpAct;
+ const Rectangle& rRect = pA->GetRect();
+ mpRect = new Rectangle( Polygon( rRect.Center(),
+ rRect.GetWidth() >> 1,
+ rRect.GetHeight() >> 1 ).GetBoundRect() );
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ MetaArcAction* pA = (MetaArcAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_ARC ).GetBoundRect() );
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ MetaPieAction* pA = (MetaPieAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_PIE ).GetBoundRect() );
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ MetaChordAction* pA = (MetaChordAction*) mpAct;
+ mpRect = new Rectangle( Polygon( pA->GetRect(),
+ pA->GetStartPoint(),
+ pA->GetEndPoint(), POLY_CHORD ).GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ MetaPolyLineAction* pA = (MetaPolyLineAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ MetaPolygonAction* pA = (MetaPolygonAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ MetaPolyPolygonAction* pA = (MetaPolyPolygonAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPolyPolygon().GetBoundRect() );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pA = (MetaBmpAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmap().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pA = (MetaBmpScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pA = (MetaBmpScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pA = (MetaBmpExAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pA = (MetaBmpExScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pA = (MetaBmpExScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pA = (MetaMaskAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pOut->PixelToLogic( pA->GetBitmap().GetSizePixel() ) );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScaleAction* pA = (MetaMaskScaleAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pA = (MetaMaskScalePartAction*) mpAct;
+ mpRect = new Rectangle( pA->GetDestPoint(), pA->GetDestSize() );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ mpRect = new Rectangle( ( (MetaGradientAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_HATCH_ACTION ):
+ mpRect = new Rectangle( ( (MetaHatchAction*) mpAct )->GetPolyPolygon().GetBoundRect() );
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ mpRect = new Rectangle( ( (MetaWallpaperAction*) mpAct )->GetRect() );
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ mpRect = new Rectangle( ( (MetaTransparentAction*) mpAct )->GetPolyPolygon().GetBoundRect() );
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ MetaFloatTransparentAction* pA = (MetaFloatTransparentAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ MetaEPSAction* pA = (MetaEPSAction*) mpAct;
+ mpRect = new Rectangle( pA->GetPoint(), pA->GetSize() );
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ MetaTextAction* pA = (MetaTextAction*) mpAct;
+ const Point aPt( pOut->LogicToPixel( pA->GetPoint() ) );
+ const XubString aString( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ mpRect = new Rectangle( pOut->PixelToLogic( pOut->ImplGetTextBoundRect( aPt.X(), aPt.Y(), aString.GetBuffer(), aString.Len(), NULL ) ) );
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ MetaTextArrayAction* pA = (MetaTextArrayAction*) mpAct;
+ const Point aPt( pOut->LogicToPixel( pA->GetPoint() ) );
+ const XubString aString( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ mpRect = new Rectangle( pOut->PixelToLogic( pOut->ImplGetTextBoundRect( aPt.X(), aPt.Y(), aString.GetBuffer(), aString.Len(), pA->GetDXArray() ) ) );
+ }
+ break;
+
+ case( META_TEXTRECT_ACTION ):
+ {
+ MetaTextRectAction* pA = (MetaTextRectAction*) mpAct;
+ mpRect = new Rectangle( pA->GetRect() );
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ case( META_TEXTLINE_ACTION ):
+ mpRect = NULL;
+ // !!! DBG_ERROR( "Missing" );
+ break;
+
+ default:
+ mpRect = NULL;
+ break;
+ }
+
+ if( mpRect )
+ {
+ *mpRect = pOut->LogicToPixel( *mpRect );
+ mbSpecialOutput = bSpecial;
+ }
+ else
+ mbSpecialOutput = FALSE;
+}
+
+// -----------
+// - Printer -
+// -----------
+
+void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutMtf, ULONG nFlags )
+{
+ const ULONG nSpecialCount = sizeof( aSpecialPrintActions ) / sizeof( aSpecialPrintActions[ 0 ] );
+ MetaAction* pAct;
+ ULONG i, j;
+ BOOL bSpecial = FALSE;
+
+ rOutMtf.Clear();
+
+ // look, if we've got special actions
+ for( pAct = ( (GDIMetaFile&) rInMtf ).FirstAction(); pAct && !bSpecial; pAct = ( (GDIMetaFile&) rInMtf ).NextAction() )
+ for( i = 0; i < nSpecialCount; i++ )
+ if( pAct->GetType() == aSpecialPrintActions[ i ] )
+ bSpecial = TRUE;
+
+ // separate actions which are special actions or which are affected by special actions
+ if( bSpecial )
+ {
+ Rectangle aBoundPixel;
+ const ULONG nCount = rInMtf.GetActionCount();
+ VirtualDevice aPaintVDev;
+ ImplCheckRect* pRects = new ImplCheckRect[ nCount ];
+ ImplCheckRect* pIListFirst = NULL;
+ ImplCheckRect* pIListPrev = NULL;
+ ImplCheckRect* pIListAct = NULL;
+ ImplCheckRect* pOListFirst = NULL;
+ ImplCheckRect* pOListLast = NULL;
+ ImplCheckRect* pOListAct = NULL;
+ ImplCheckRect* pO;
+
+ aPaintVDev.mnDPIX = mnDPIX;
+ aPaintVDev.mnDPIY = mnDPIY;
+ aPaintVDev.mbOutput = FALSE;
+
+ // create list of special action rects
+ for( i = 0, pO = pRects, pAct = ( (GDIMetaFile&) rInMtf ).FirstAction(); pAct;
+ pAct = ( (GDIMetaFile&) rInMtf ).NextAction(), i++, pO++ )
+ {
+ for( j = 0, bSpecial = FALSE; j < nSpecialCount && !bSpecial; j++ )
+ if( pAct->GetType() == aSpecialPrintActions[ j ] )
+ bSpecial = TRUE;
+
+ // execute action to get correct MapMode's etc.
+ pAct->Execute( &aPaintVDev );
+
+ // create (bounding) rect object
+ pO->ImplCreate( pAct, &aPaintVDev, bSpecial );
+
+ // add object to one of the lists
+ if( pO->mbSpecialOutput )
+ {
+ if( !pOListFirst )
+ pOListFirst = pOListAct = pOListLast = pO;
+ else
+ pOListAct = pOListAct->mpNext = pOListLast = pO;
+ }
+ else
+ {
+ if( !pIListFirst )
+ pIListFirst = pIListAct = pO;
+ else
+ pIListAct = pIListAct->mpNext = pO;
+ }
+ }
+
+ // find all intersections and create list of (bitmap)
+ for( pO = pOListFirst; pO; pO = pO->mpNext )
+ {
+ pIListPrev = NULL, pIListAct = pIListFirst;
+
+ while( pIListAct )
+ {
+ // move act object from in list to out list?
+ if( pIListAct->Intersects( *pO ) )
+ {
+ // mark it as special object
+ pIListAct->mbSpecialOutput = TRUE;
+
+ if( pIListPrev )
+ pIListPrev->mpNext = pIListAct->mpNext;
+ else
+ pIListFirst = pIListAct->mpNext;
+
+ pOListLast = pOListLast->mpNext = pIListAct;
+ }
+ else
+ pIListPrev = pIListAct;
+
+ pIListAct = pIListAct->mpNext;
+ pOListLast->mpNext = NULL;
+ }
+ }
+
+ // calculate bounding rectangle of special actions
+ for( pO = pOListFirst; pO; pO = pO->mpNext )
+ aBoundPixel.Union( *pO->mpRect );
+
+ const Size aSzPix( aBoundPixel.GetSize() );
+
+ // create new bitmap action first
+ if( aSzPix.Width() && aSzPix.Height() )
+ {
+ Point aDstPtPix( aBoundPixel.TopLeft() );
+ Size aDstSzPix( aSzPix.Width(), Max( MAX_BANDWIDTH / aSzPix.Width(), 2L ) );
+ const long nLastY = aDstPtPix.Y() + aSzPix.Height() - 1L;
+ VirtualDevice aMapVDev;
+
+ rOutMtf.AddAction( new MetaPushAction( PUSH_MAPMODE ) );
+ rOutMtf.AddAction( new MetaMapModeAction() );
+
+ aPaintVDev.mbOutput = TRUE;
+ aMapVDev.mbOutput = FALSE;
+
+ while( aDstPtPix.Y() <= nLastY )
+ {
+ if( ( aDstPtPix.Y() + aDstSzPix.Height() - 1L ) > nLastY )
+ aDstSzPix.Height() = nLastY - aDstPtPix.Y() + 1L;
+
+ if( aPaintVDev.SetOutputSizePixel( aDstSzPix ) )
+ {
+ aPaintVDev.Push();
+ aMapVDev.Push();
+
+ aMapVDev.mnDPIX = aPaintVDev.mnDPIX = mnDPIX;
+ aMapVDev.mnDPIY = aPaintVDev.mnDPIY = mnDPIY;
+
+ for( i = 0, pO = pRects; i < nCount; i++, pO++ )
+ {
+ MetaAction* pAction = pO->mpAct;
+ const USHORT nType = pAction->GetType();
+
+ if( META_MAPMODE_ACTION == nType )
+ {
+ pAction->Execute( &aMapVDev );
+
+ MapMode aMtfMap( aMapVDev.GetMapMode() );
+ const Point aNewOrg( aMapVDev.PixelToLogic( aDstPtPix ) );
+
+ aMtfMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) );
+ aPaintVDev.SetMapMode( aMtfMap );
+ }
+ else if( ( META_PUSH_ACTION == nType ) || ( META_POP_ACTION ) == nType )
+ {
+ pAction->Execute( &aMapVDev );
+ pAction->Execute( &aPaintVDev );
+ }
+ else
+ pAction->Execute( &aPaintVDev );
+
+ if( !( i % 4 ) )
+ Application::Reschedule();
+ }
+
+ aPaintVDev.mbMap = FALSE;
+ Bitmap aBandBmp( aPaintVDev.GetBitmap( Point(), aDstSzPix ) );
+#ifdef DEBUG
+ aBandBmp.Invert();
+#endif
+ rOutMtf.AddAction( new MetaBmpScaleAction( aDstPtPix, aDstSzPix, aBandBmp ) );
+ aPaintVDev.mbMap = TRUE;
+
+ aMapVDev.Pop();
+ aPaintVDev.Pop();
+ }
+
+ // overlapping bands to avoid missing lines (e.g. PostScript)
+ aDstPtPix.Y() += aDstSzPix.Height();
+ }
+
+ rOutMtf.AddAction( new MetaPopAction() );
+ }
+
+ // add normal actions
+ for( i = 0, pO = pRects; i < nCount; i++, pO++ )
+ if( !pO->mbSpecialOutput )
+ rOutMtf.AddAction( ( pO->mpAct->Duplicate(), pO->mpAct ) );
+
+ rOutMtf.SetPrefMapMode( rInMtf.GetPrefMapMode() );
+ rOutMtf.SetPrefSize( rInMtf.GetPrefSize() );
+ delete[] pRects;
+ }
+ else
+ rOutMtf = rInMtf;
+}
diff --git a/vcl/source/gdi/regband.cxx b/vcl/source/gdi/regband.cxx
new file mode 100644
index 000000000000..51a0a366727b
--- /dev/null
+++ b/vcl/source/gdi/regband.cxx
@@ -0,0 +1,785 @@
+/*************************************************************************
+ *
+ * $RCSfile: regband.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_REGBAND_CXX
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _SV_REGBAND_HXX
+#include <regband.hxx>
+#endif
+
+// =======================================================================
+//
+// ImplRegionBand
+//
+// Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
+// enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
+// Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
+// Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
+//
+// Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
+//
+// Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
+// in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
+// Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
+// in Rechtecke umgewandelt und die Liste der Punkte geloescht.
+//
+// -----------------------------------------------------------------------
+
+ImplRegionBand::ImplRegionBand( long nTop, long nBottom )
+{
+ // save boundaries
+ mnYTop = nTop;
+ mnYBottom = nBottom;
+
+ // initialize lists
+ mpNextBand = NULL;
+ mpPrevBand = NULL;
+ mpFirstSep = NULL;
+ mpFirstBandPoint = NULL;
+ mbTouched = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegionBand::ImplRegionBand( const ImplRegionBand& rRegionBand )
+{
+ // copy boundaries
+ mnYTop = rRegionBand.mnYTop;
+ mnYBottom = rRegionBand.mnYBottom;
+ mbTouched = rRegionBand.mbTouched;
+
+ // initialisation
+ mpNextBand = NULL;
+ mpPrevBand = NULL;
+ mpFirstSep = NULL;
+ mpFirstBandPoint = NULL;
+
+ // copy all elements of the list with separations
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = rRegionBand.mpFirstSep;
+ while ( pSep )
+ {
+ // create new and copy data
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = pSep->mnXRight;
+ pNewSep->mbRemoved = pSep->mbRemoved;
+ pNewSep->mpNextSep = NULL;
+ if ( pSep == rRegionBand.mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+
+ pPrevSep = pNewSep;
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegionBand::~ImplRegionBand()
+{
+ DBG_ASSERT( mpFirstBandPoint == NULL, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
+
+ // delete elements of the list
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ ImplRegionBandSep* pTempSep = pSep->mpNextSep;
+ delete pSep;
+ pSep = pTempSep;
+ }
+
+ // delete elements of the list
+ ImplRegionBandPoint* pPoint = mpFirstBandPoint;
+ while ( pPoint )
+ {
+ ImplRegionBandPoint* pTempPoint = pPoint->mpNextBandPoint;
+ delete pPoint;
+ pPoint = pTempPoint;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// generate separations from lines and process union with existing
+// separations
+
+void ImplRegionBand::ProcessPoints()
+{
+ // check Pointlist
+ ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
+ while ( pRegionBandPoint )
+ {
+ // within list?
+ if ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
+ {
+ // start/stop?
+ if ( pRegionBandPoint->mbEndPoint && pRegionBandPoint->mpNextBandPoint->mbEndPoint )
+ {
+ // same direction? -> remove next point!
+ if ( pRegionBandPoint->meLineType == pRegionBandPoint->mpNextBandPoint->meLineType )
+ {
+ ImplRegionBandPoint* pSaveRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ pRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
+ delete pSaveRegionBandPoint;
+ }
+ }
+ }
+
+ // continue with next element in the list
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ pRegionBandPoint = mpFirstBandPoint;
+ while ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
+ {
+ Union( pRegionBandPoint->mnX, pRegionBandPoint->mpNextBandPoint->mnX );
+
+ ImplRegionBandPoint* pNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
+
+ // remove allready processed points
+ delete pRegionBandPoint->mpNextBandPoint;
+ delete pRegionBandPoint;
+
+ // continue with next element in the list
+ pRegionBandPoint = pNextBandPoint;
+ }
+
+ // remove last element if necessary
+ if ( pRegionBandPoint )
+ delete pRegionBandPoint;
+
+ // list is now empty
+ mpFirstBandPoint = NULL;
+}
+
+// -----------------------------------------------------------------------
+//
+// generate separations from lines and process union with existing
+// separations
+
+BOOL ImplRegionBand::InsertPoint( long nX, long nLineId,
+ BOOL bEndPoint, LineType eLineType )
+{
+ if ( !mpFirstBandPoint )
+ {
+ mpFirstBandPoint = new ImplRegionBandPoint;
+ mpFirstBandPoint->mnX = nX;
+ mpFirstBandPoint->mnLineId = nLineId;
+ mpFirstBandPoint->mbEndPoint = bEndPoint;
+ mpFirstBandPoint->meLineType = eLineType;
+ mpFirstBandPoint->mpNextBandPoint = NULL;
+ return TRUE;
+ }
+
+ // look if line allready touched the band
+ ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
+ ImplRegionBandPoint* pLastTestedRegionBandPoint = NULL;
+ while( pRegionBandPoint )
+ {
+ if ( pRegionBandPoint->mnLineId == nLineId )
+ {
+ if ( bEndPoint )
+ {
+ if( !pRegionBandPoint->mbEndPoint )
+ {
+ // remove old band point
+ if( !mpFirstBandPoint->mpNextBandPoint )
+ {
+ // if we've only got one point => replace first point
+ pRegionBandPoint->mnX = nX;
+ pRegionBandPoint->mbEndPoint = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ // remove current point
+ if( !pLastTestedRegionBandPoint )
+ {
+ // remove and delete old first point
+ ImplRegionBandPoint* pSaveBandPoint = mpFirstBandPoint;
+ mpFirstBandPoint = mpFirstBandPoint->mpNextBandPoint;
+ delete pSaveBandPoint;
+ }
+ else
+ {
+ // remove and delete current band point
+ pLastTestedRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint;
+ delete pRegionBandPoint;
+ }
+
+ break;
+ }
+ }
+ }
+ else
+ return FALSE;
+ }
+
+ // use next element
+ pLastTestedRegionBandPoint = pRegionBandPoint;
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ // search appropriate position and insert point into the list
+ ImplRegionBandPoint* pNewRegionBandPoint;
+
+ pRegionBandPoint = mpFirstBandPoint;
+ pLastTestedRegionBandPoint = NULL;
+ while ( pRegionBandPoint )
+ {
+ // new point completly left? -> insert as first point
+ if ( nX <= pRegionBandPoint->mnX )
+ {
+ pNewRegionBandPoint = new ImplRegionBandPoint;
+ pNewRegionBandPoint->mnX = nX;
+ pNewRegionBandPoint->mnLineId = nLineId;
+ pNewRegionBandPoint->mbEndPoint = bEndPoint;
+ pNewRegionBandPoint->meLineType = eLineType;
+ pNewRegionBandPoint->mpNextBandPoint = pRegionBandPoint;
+
+ // connections to the new point
+ if ( !pLastTestedRegionBandPoint )
+ mpFirstBandPoint = pNewRegionBandPoint;
+ else
+ pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
+
+ return TRUE;
+ }
+
+ // use next element
+ pLastTestedRegionBandPoint = pRegionBandPoint;
+ pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
+ }
+
+ // not inserted -> add to the end of the list
+ pNewRegionBandPoint = new ImplRegionBandPoint;
+ pNewRegionBandPoint->mnX = nX;
+ pNewRegionBandPoint->mnLineId = nLineId;
+ pNewRegionBandPoint->mbEndPoint = bEndPoint;
+ pNewRegionBandPoint->meLineType = eLineType;
+ pNewRegionBandPoint->mpNextBandPoint = NULL;
+
+ // connections to the new point
+ pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::MoveX( long nHorzMove )
+{
+ // move all x-separations
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ pSep->mnXLeft += nHorzMove;
+ pSep->mnXRight += nHorzMove;
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::ScaleX( double fHorzScale )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ pSep->mnXLeft = FRound( pSep->mnXLeft * fHorzScale );
+ pSep->mnXRight = FRound( pSep->mnXRight * fHorzScale );
+ pSep = pSep->mpNextSep;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// combine overlaping sparations
+
+BOOL ImplRegionBand::OptimizeBand()
+{
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // remove?
+ if ( pSep->mbRemoved || (pSep->mnXRight < pSep->mnXLeft) )
+ {
+ ImplRegionBandSep* pOldSep = pSep;
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pSep->mpNextSep;
+ else
+ pPrevSep->mpNextSep = pSep->mpNextSep;
+ pSep = pSep->mpNextSep;
+ delete pOldSep;
+ continue;
+ }
+
+ // overlaping separations? -> combine!
+ if ( pSep->mpNextSep )
+ {
+ if ( (pSep->mnXRight+1) >= pSep->mpNextSep->mnXLeft )
+ {
+ if ( pSep->mpNextSep->mnXRight > pSep->mnXRight )
+ pSep->mnXRight = pSep->mpNextSep->mnXRight;
+
+ ImplRegionBandSep* pOldSep = pSep->mpNextSep;
+ pSep->mpNextSep = pOldSep->mpNextSep;
+ delete pOldSep;
+ continue;
+ }
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Union( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Union(): nxLeft > nXRight" );
+
+ // band empty? -> add element
+ if ( !mpFirstSep )
+ {
+ mpFirstSep = new ImplRegionBandSep;
+ mpFirstSep->mnXLeft = nXLeft;
+ mpFirstSep->mnXRight = nXRight;
+ mpFirstSep->mbRemoved = FALSE;
+ mpFirstSep->mpNextSep = NULL;
+ return;
+ }
+
+ // process real union
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completely inside? nothing to do!
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ return;
+
+ // new separation completly left? -> new separation!
+ if ( nXRight < pSep->mnXLeft )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = nXLeft;
+ pNewSep->mnXRight = nXRight;
+ pNewSep->mbRemoved = FALSE;
+
+ pNewSep->mpNextSep = pSep;
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ break;
+ }
+
+ // new separation overlaping from left? -> extend boundary
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ pSep->mnXLeft = nXLeft;
+
+ // new separation overlaping from right? -> extend boundary
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXRight;
+ break;
+ }
+
+ // not inserted, but last element? -> add to the end of the list
+ if ( !pSep->mpNextSep && (nXLeft > pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = nXLeft;
+ pNewSep->mnXRight = nXRight;
+ pNewSep->mbRemoved = FALSE;
+
+ pSep->mpNextSep = pNewSep;
+ pNewSep->mpNextSep = NULL;
+ break;
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Intersect( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
+
+ // band has been touched
+ mbTouched = TRUE;
+
+ // band empty? -> nothing to do
+ if ( !mpFirstSep )
+ return;
+
+ // process real intersection
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completly outside? -> remove separation
+ if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
+ // will be removed from the optimizer
+ pSep->mbRemoved = TRUE;
+
+ // new separation overlaping from left? -> reduce right boundary
+ if ( (nXLeft <= pSep->mnXLeft) &&
+ (nXRight <= pSep->mnXRight) &&
+ (nXRight >= pSep->mnXLeft) )
+ pSep->mnXRight = nXRight;
+
+ // new separation overlaping from right? -> reduce right boundary
+ if ( (nXLeft >= pSep->mnXLeft) &&
+ (nXLeft <= pSep->mnXRight) &&
+ (nXRight >= pSep->mnXRight) )
+ pSep->mnXLeft = nXLeft;
+
+ // new separation within the actual one? -> reduce both boundaries
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXRight;
+ pSep->mnXLeft = nXLeft;
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::Exclude( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
+
+ // band has been touched
+ mbTouched = TRUE;
+
+ // band empty? -> nothing to do
+ if ( !mpFirstSep )
+ return;
+
+ // process real exclusion
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ BOOL bSepProcessed = FALSE;
+
+ // new separation completely overlapping? -> remove separation
+ if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
+ {
+ // will be removed from the optimizer
+ pSep->mbRemoved = TRUE;
+ bSepProcessed = TRUE;
+ }
+
+ // new separation overlaping from left? -> reduce boundary
+ if ( !bSepProcessed )
+ {
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ {
+ pSep->mnXLeft = nXRight+1;
+ bSepProcessed = TRUE;
+ }
+ }
+
+ // new separation overlaping from right? -> reduce boundary
+ if ( !bSepProcessed )
+ {
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ {
+ pSep->mnXRight = nXLeft-1;
+ bSepProcessed = TRUE;
+ }
+ }
+
+ // new separation within the actual one? -> reduce boundary
+ // and add new entry for reminder
+ if ( !bSepProcessed )
+ {
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = nXLeft-1;
+ pNewSep->mbRemoved = FALSE;
+
+ pSep->mnXLeft = nXRight+1;
+
+ // connections from the new separation
+ pNewSep->mpNextSep = pSep;
+
+ // connections to the new separation
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ }
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegionBand::XOr( long nXLeft, long nXRight )
+{
+ DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::XOr(): nxLeft > nXRight" );
+
+ // band empty? -> add element
+ if ( !mpFirstSep )
+ {
+ mpFirstSep = new ImplRegionBandSep;
+ mpFirstSep->mnXLeft = nXLeft;
+ mpFirstSep->mnXRight = nXRight;
+ mpFirstSep->mbRemoved = FALSE;
+ mpFirstSep->mpNextSep = NULL;
+ return;
+ }
+
+ // process real xor
+ ImplRegionBandSep* pNewSep;
+ ImplRegionBandSep* pPrevSep;
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ // new separation completely overlapping?
+ // -> move boundaries to left remainder
+ // -> reduce boundaries of new separation
+ if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
+ {
+ int iOldXRight = pSep->mnXRight;
+ pSep->mnXRight = pSep->mnXLeft;
+ pSep->mnXLeft = nXLeft;
+ nXLeft = pSep->mnXRight;
+ }
+
+ // new separation overlaping from left?
+ // -> move boundaries to left remainder
+ // -> set boundaries of new separation to right remainder
+ if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
+ {
+ int iOldXRight = pSep->mnXRight;
+ pSep->mnXRight = pSep->mnXLeft;
+ pSep->mnXLeft = nXLeft;
+ nXLeft = pSep->mnXRight;
+ }
+
+ // new separation overlaping from right? -> reduce boundary
+ if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
+ pSep->mnXRight = nXLeft;
+
+ // new separation within the actual one? -> reduce boundary
+ // and add new entry for reminder
+ if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
+ {
+ pNewSep = new ImplRegionBandSep;
+ pNewSep->mnXLeft = pSep->mnXLeft;
+ pNewSep->mnXRight = nXLeft;
+
+ pSep->mnXLeft = nXRight;
+
+ // connections from the new separation
+ pNewSep->mpNextSep = pSep;
+
+ // connections to the new separation
+ if ( pSep == mpFirstSep )
+ mpFirstSep = pNewSep;
+ else
+ pPrevSep->mpNextSep = pNewSep;
+ }
+
+ pPrevSep = pSep;
+ pSep = pSep->mpNextSep;
+ }
+
+ OptimizeBand();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsInside( long nX )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsOver( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft < nRight) && (pSep->mnXRight > nLeft) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::IsInside( long nLeft, long nRight )
+{
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep )
+ {
+ if ( (pSep->mnXLeft >= nLeft) && (nRight <= pSep->mnXRight) )
+ return TRUE;
+
+ pSep = pSep->mpNextSep;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplRegionBand::GetXLeftBoundary() const
+{
+ DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
+
+ return mpFirstSep->mnXLeft;
+}
+
+// -----------------------------------------------------------------------
+
+long ImplRegionBand::GetXRightBoundary() const
+{
+ DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XRightBoundary -> no separation in band!" );
+
+ // search last separation
+ ImplRegionBandSep* pSep = mpFirstSep;
+ while ( pSep->mpNextSep )
+ pSep = pSep->mpNextSep;
+ return pSep->mnXRight;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
+{
+ ImplRegionBandSep* pOwnRectBandSep = mpFirstSep;
+ ImplRegionBandSep* pSecondRectBandSep = rRegionBand.mpFirstSep;
+ while ( pOwnRectBandSep && pSecondRectBandSep )
+ {
+ // get boundaries of current rectangle
+ long nOwnXLeft = pOwnRectBandSep->mnXLeft;
+ long nSecondXLeft = pSecondRectBandSep->mnXLeft;
+ if ( nOwnXLeft != nSecondXLeft )
+ return FALSE;
+
+ long nOwnXRight = pOwnRectBandSep->mnXRight;
+ long nSecondXRight = pSecondRectBandSep->mnXRight;
+ if ( nOwnXRight != nSecondXRight )
+ return FALSE;
+
+ // get next separation from current band
+ pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+
+ // get next separation from current band
+ pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+ }
+
+ // differnt number of separations?
+ if ( pOwnRectBandSep || pSecondRectBandSep )
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
new file mode 100644
index 000000000000..000cad2a909b
--- /dev/null
+++ b/vcl/source/gdi/region.cxx
@@ -0,0 +1,2458 @@
+/*************************************************************************
+ *
+ * $RCSfile: region.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_REGION_CXX
+
+#include <limits.h>
+
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _REGION_H
+#include <region.h>
+#endif
+#ifndef _REGION_HXX
+#include <region.hxx>
+#endif
+#ifndef _REGBAND_HXX
+#include <regband.hxx>
+#endif
+
+// =======================================================================
+//
+// ImplRegionBand
+//
+// Die Klassen RegionBand/ImplRegionBand speichert Regionen in Form von
+// Rechtecken ab. Die Region ist in Y-Richtung in Baendern unterteilt, die
+// wiederum ein oder mehrere Rechtecke mit der Hoehe des Bandes enthalten.
+//
+// Leere Baender werden entfernt.
+//
+// Polygone und PolyPolygone werden ebenfalls in Rechtecke zerlegt und in
+// der Baendern abgelegt. Hierzu werden alle Punkte der einzelnen Polygone
+// mit dem Bresenham-Algorithmus berechnet und in die Baender eingetragen.
+// Nach der vollstaendigen Berechung aller Kanten werden die entsprechenden
+// Rechntecke berechnet
+
+// =======================================================================
+
+static ImplRegionBase aImplNullRegion = { 0, 0, NULL };
+static ImplRegionBase aImplEmptyRegion = { 0, 0, NULL };
+
+// =======================================================================
+
+DBG_NAME( Region );
+DBG_NAMEEX( Polygon );
+DBG_NAMEEX( PolyPolygon );
+
+// -----------------------------------------------------------------------
+
+#ifdef DBG_UTIL
+const char* ImplDbgTestRegion( const void* pObj )
+{
+ Region* pRegion = (Region*)pObj;
+ ImplRegion* pImplRegion = pRegion->ImplGetImplRegion();
+
+ if ( aImplNullRegion.mnRefCount )
+ return "Null-Region-RefCount modified";
+ if ( aImplNullRegion.mnRectCount )
+ return "Null-Region-RectCount modified";
+ if ( aImplNullRegion.mpPolyPoly )
+ return "Null-Region-PolyPoly modified";
+ if ( aImplEmptyRegion.mnRefCount )
+ return "Emptry-Region-RefCount modified";
+ if ( aImplEmptyRegion.mnRectCount )
+ return "Emptry-Region-RectCount modified";
+ if ( aImplEmptyRegion.mpPolyPoly )
+ return "Emptry-Region-PolyPoly modified";
+
+ if ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
+ {
+ ULONG nCount = 0;
+ const ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
+ while ( pBand )
+ {
+ if ( pBand->mnYBottom < pBand->mnYTop )
+ return "YBottom < YTop";
+ if ( pBand->mpNextBand )
+ {
+ if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
+ return "overlapping bands in region";
+ }
+ if ( pBand->mbTouched > 1 )
+ return "Band-mbTouched overwrite";
+
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ if ( pSep->mnXRight < pSep->mnXLeft )
+ return "XLeft < XRight";
+ if ( pSep->mpNextSep )
+ {
+ if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
+ return "overlapping separations in region";
+ }
+ if ( pSep->mbRemoved > 1 )
+ return "Sep-mbRemoved overwrite";
+
+ nCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ if ( pImplRegion->mnRectCount != nCount )
+ return "mnRetCount is not valid";
+ }
+
+ return NULL;
+}
+#endif
+
+// =======================================================================
+
+inline void Region::ImplPolyPolyRegionToBandRegion()
+{
+ if ( mpImplRegion->mpPolyPoly )
+ ImplPolyPolyRegionToBandRegionFunc();
+}
+
+// =======================================================================
+
+ImplRegion::ImplRegion()
+{
+ mnRefCount = 1;
+ mnRectCount = 0;
+ mpPolyPoly = NULL;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+}
+
+// ------------------------------------------------------------------------
+
+ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
+{
+ mnRefCount = 1;
+ mnRectCount = 0;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+ mpPolyPoly = new PolyPolygon( rPolyPoly );
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
+{
+ mnRefCount = 1;
+ mnRectCount = rImplRegion.mnRectCount;
+ mpFirstBand = NULL;
+ mpLastCheckedBand = NULL;
+ if ( rImplRegion.mpPolyPoly )
+ mpPolyPoly = new PolyPolygon( *rImplRegion.mpPolyPoly );
+ else
+ mpPolyPoly = NULL;
+
+ // insert band(s) into the list
+ ImplRegionBand* pNewBand;
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = rImplRegion.mpFirstBand;
+ while ( pBand )
+ {
+ pNewBand = new ImplRegionBand( *pBand );
+
+ // first element? -> set as first into the list
+ if ( pBand == rImplRegion.mpFirstBand )
+ mpFirstBand = pNewBand;
+ else
+ pPrevBand->mpNextBand = pNewBand;
+
+ pPrevBand = pNewBand;
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ImplRegion::~ImplRegion()
+{
+ DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
+ "ImplRegion::~ImplRegion() - Empty oder NULL-Region" )
+
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ ImplRegionBand* pTempBand = pBand->mpNextBand;
+ delete pBand;
+ pBand = pTempBand;
+ }
+
+ delete mpPolyPoly;
+}
+
+// -----------------------------------------------------------------------
+//
+// create complete range of bands in single steps
+
+void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
+{
+ // add top band
+ mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
+
+ // begin first search from the first element
+ mpLastCheckedBand = mpFirstBand;
+
+ ImplRegionBand* pBand = mpFirstBand;
+ for ( int i = nYTop; i <= nYBottom+1; i++ )
+ {
+ // create new band
+ ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
+ pBand->mpNextBand = pNewBand;
+ if ( pBand != mpFirstBand )
+ pNewBand->mpPrevBand = pBand;
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ImplRegion::InsertLine( const Point& rStartPt, const Point& rEndPt,
+ long nLineId )
+{
+ long nX, nY;
+
+ // lines consisting of a single point do not interest here
+ if ( rStartPt == rEndPt )
+ return TRUE;
+
+ LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
+ if ( rStartPt.X() == rEndPt.X() )
+ {
+ // vertical line
+ const long nEndY = rEndPt.Y();
+
+ nX = rStartPt.X();
+ nY = rStartPt.Y();
+
+ if( nEndY > nY )
+ {
+ for ( ; nY <= nEndY; nY++ )
+ {
+ Point aNewPoint( nX, nY );
+ InsertPoint( aNewPoint, nLineId,
+ (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
+ eLineType );
+ }
+ }
+ else
+ {
+ for ( ; nY >= nEndY; nY-- )
+ {
+ Point aNewPoint( nX, nY );
+ InsertPoint( aNewPoint, nLineId,
+ (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
+ eLineType );
+ }
+ }
+ }
+ else if ( rStartPt.Y() != rEndPt.Y() )
+ {
+ const long nDX = labs( rEndPt.X() - rStartPt.X() );
+ const long nDY = labs( rEndPt.Y() - rStartPt.Y() );
+ const long nStartX = rStartPt.X();
+ const long nStartY = rStartPt.Y();
+ const long nEndX = rEndPt.X();
+ const long nEndY = rEndPt.Y();
+ const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
+ const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
+
+ if ( nDX >= nDY )
+ {
+ const long nDYX = ( nDY - nDX ) << 1;
+ const long nDY2 = nDY << 1;
+ long nD = nDY2 - nDX;
+
+ for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
+ {
+ InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
+
+ if ( nD < 0L )
+ nD += nDY2;
+ else
+ nD += nDYX, nY += nYInc;
+ }
+ }
+ else
+ {
+ const long nDYX = ( nDX - nDY ) << 1;
+ const long nDY2 = nDX << 1;
+ long nD = nDY2 - nDY;
+
+ for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
+ {
+ InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
+
+ if ( nD < 0L )
+ nD += nDY2;
+ else
+ nD += nDYX, nX += nXInc;
+ }
+ }
+
+ // last point
+ InsertPoint( Point( nEndX, nEndY ), nLineId, TRUE, eLineType );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+//
+// search for appropriate place for the new point
+
+BOOL ImplRegion::InsertPoint( const Point &rPoint, long nLineID,
+ BOOL bEndPoint, LineType eLineType )
+{
+ DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
+
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
+ {
+ // Search ascending
+ while ( mpLastCheckedBand )
+ {
+ // Insert point if possible
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint reached the end of the list!" );
+ }
+ else
+ {
+ // Search descending
+ while ( mpLastCheckedBand )
+ {
+ // Insert point if possible
+ if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
+ {
+ mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
+ return TRUE;
+ }
+
+ mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint reached the beginning of the list!" );
+ }
+
+ DBG_ERROR( "ImplRegion::InsertPoint point not inserted!" );
+
+ // reinitialize pointer (should never be reached!)
+ mpLastCheckedBand = mpFirstBand;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+//
+// search for appropriate places for the new bands
+
+void ImplRegion::InsertBands( long nTop, long nBottom )
+{
+ // region empty? -> set rectagle as first entry!
+ if ( !mpFirstBand )
+ {
+ // add band with boundaries of the rectangle
+ mpFirstBand = new ImplRegionBand( nTop, nBottom );
+ return;
+ }
+
+ // find/insert bands for the boundaries of the rectangle
+ BOOL bTopBoundaryInserted = FALSE;
+ BOOL bTop2BoundaryInserted = FALSE;
+ BOOL bBottomBoundaryInserted = FALSE;
+
+ // special case: top boundary is above the first band
+ ImplRegionBand* pNewBand;
+ if ( nTop < mpFirstBand->mnYTop )
+ {
+ // create new band above the first in the list
+ pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
+ if ( nBottom < mpFirstBand->mnYTop )
+ pNewBand->mnYBottom = nBottom;
+
+ // insert band into the list
+ pNewBand->mpNextBand = mpFirstBand;
+ mpFirstBand = pNewBand;
+
+ bTopBoundaryInserted = TRUE;
+ }
+
+ // insert band(s) into the list
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ // Insert Bands if possible
+ if ( !bTopBoundaryInserted )
+ bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
+
+ if ( !bTop2BoundaryInserted )
+ bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
+
+ if ( !bBottomBoundaryInserted && (nTop != nBottom) )
+ bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
+
+ // both boundaries inserted? -> nothing more to do
+ if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
+ break;
+
+ // insert bands between two bands if neccessary
+ if ( pBand->mpNextBand )
+ {
+ if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( pBand->mnYBottom+1,
+ pBand->mpNextBand->mnYTop-1 );
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mpNextBand = pNewBand;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// create new band and insert it into the list
+
+BOOL ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
+ long nYBandPosition )
+{
+ // boundary already included in band with height 1? -> nothing to do!
+ if ( (pBand->mnYTop == pBand->mnYBottom) &&
+ (nYBandPosition == pBand->mnYTop) )
+ return TRUE;
+
+ // insert single height band on top?
+ ImplRegionBand* pNewBand;
+ if ( nYBandPosition == pBand->mnYTop )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition+1;
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition;
+ pBand->mpNextBand = pNewBand;
+
+ return TRUE;
+ }
+
+ // top of new rectangle within the current band? -> insert new band and copy data
+ if ( (nYBandPosition > pBand->mnYTop) &&
+ (nYBandPosition < pBand->mnYBottom) )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition;
+
+ // insert band into the list
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition;
+ pBand->mpNextBand = pNewBand;
+
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = nYBandPosition;
+
+ // insert band into the list
+ pBand->mpNextBand->mnYTop = nYBandPosition+1;
+
+ pNewBand->mpNextBand = pBand->mpNextBand;
+ pBand->mnYBottom = nYBandPosition - 1;
+ pBand->mpNextBand = pNewBand;
+
+ return TRUE;
+ }
+
+ // create new band behind the current in the list
+ if ( !pBand->mpNextBand )
+ {
+ if ( nYBandPosition == pBand->mnYBottom )
+ {
+ // copy band with list and set new boundary
+ pNewBand = new ImplRegionBand( *pBand );
+ pNewBand->mnYTop = pBand->mnYBottom;
+ pNewBand->mnYBottom = nYBandPosition;
+
+ pBand->mnYBottom = nYBandPosition-1;
+
+ // append band to the list
+ pBand->mpNextBand = pNewBand;
+ return TRUE;
+ }
+
+ if ( nYBandPosition > pBand->mnYBottom )
+ {
+ // create new band
+ pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
+
+ // append band to the list
+ pBand->mpNextBand = pNewBand;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
+
+ // process union
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->Union( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::Union() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegion::Exclude( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
+
+ // process exclude
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->Exclude( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::Exclude() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplRegion::XOr( long nLeft, long nTop, long nRight, long nBottom )
+{
+ DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
+ DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
+
+ // process xor
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ if ( pBand->mnYTop >= nTop )
+ {
+ if ( pBand->mnYBottom <= nBottom )
+ pBand->XOr( nLeft, nRight );
+ else
+ {
+#ifdef DBG_UTIL
+ long nCurY = pBand->mnYBottom;
+ pBand = pBand->mpNextBand;
+ while ( pBand )
+ {
+ if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
+ {
+ DBG_ERROR( "ImplRegion::XOr() - Bands not sorted!" );
+ }
+ pBand = pBand->mpNextBand;
+ }
+#endif
+ break;
+ }
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+}
+
+// -----------------------------------------------------------------------
+//
+// remove empty bands
+
+BOOL ImplRegion::OptimizeBandList()
+{
+ DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
+ "ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
+
+ mnRectCount = 0;
+
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = mpFirstBand;
+ while ( pBand )
+ {
+ const BOOL bBTEqual = pBand->mpNextBand &&
+ (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
+
+ // no separation? -> remove!
+ if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
+ {
+ // save pointer
+ ImplRegionBand* pOldBand = pBand;
+
+ // previous element of the list
+ if ( pBand == mpFirstBand )
+ mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ else
+ {
+ // fixup
+ if ( bBTEqual )
+ pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
+
+ // this and next band with equal separations? -> combine!
+ if ( pBand->mpNextBand &&
+ ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
+ (*pBand == *pBand->mpNextBand) )
+ {
+ // expand current height
+ pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
+
+ // remove next band from list
+ ImplRegionBand* pDeletedBand = pBand->mpNextBand;
+ pBand->mpNextBand = pDeletedBand->mpNextBand;
+ delete pDeletedBand;
+
+ // check band again!
+ }
+ else
+ {
+ // count rectangles within band
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mnRectCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ pBand = mpFirstBand;
+ while ( pBand )
+ {
+ DBG_ASSERT( pBand->mpFirstSep != NULL,
+ "Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
+
+ if ( pBand->mnYBottom < pBand->mnYTop )
+ DBG_ERROR( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
+
+ if ( pBand->mpNextBand )
+ {
+ if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
+ DBG_ERROR( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+#endif
+
+ return (mnRectCount != 0);
+}
+
+// =======================================================================
+
+void Region::ImplCopyData()
+{
+ mpImplRegion->mnRefCount--;
+ mpImplRegion = new ImplRegion( *mpImplRegion );
+}
+
+// =======================================================================
+
+Region::Region()
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( RegionType eType )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_ASSERT( (eType == REGION_NULL) || (eType == REGION_EMPTY),
+ "Region( RegionType ) - RegionType != EMPTY/NULL" );
+
+ if ( eType == REGION_NULL )
+ mpImplRegion = (ImplRegion*)(&aImplNullRegion);
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Rectangle& rRect )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+
+ ImplCreateRectRegion( rRect );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Polygon& rPolygon )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rPolygon, Polygon, NULL );
+
+ ImplCreatePolyPolyRegion( rPolygon );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const PolyPolygon& rPolyPoly )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
+
+ ImplCreatePolyPolyRegion( rPolyPoly );
+}
+
+// -----------------------------------------------------------------------
+
+Region::Region( const Region& rRegion )
+{
+ DBG_CTOR( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+ DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
+
+ // copy pointer to instance of implementation
+ mpImplRegion = rRegion.mpImplRegion;
+ if ( mpImplRegion->mnRefCount )
+ mpImplRegion->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Region::~Region()
+{
+ DBG_DTOR( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplCreateRectRegion( const Rectangle& rRect )
+{
+ if ( rRect.IsEmpty() )
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ else
+ {
+ // get justified rectangle
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+
+ // create instance of implementation class
+ mpImplRegion = new ImplRegion();
+
+ // add band with boundaries of the rectangle
+ mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
+
+ // Set left and right boundaries of the band
+ mpImplRegion->mpFirstBand->Union( nLeft, nRight );
+ mpImplRegion->mnRectCount = 1;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
+{
+ const USHORT nPolyCount = rPolyPoly.Count();
+ if ( nPolyCount )
+ {
+ // polypolygon empty? -> empty region
+ const Rectangle aRect( rPolyPoly.GetBoundRect() );
+
+ if ( !aRect.IsEmpty() )
+ {
+ // width OR height == 1 ? => Rectangular region
+ if ( (aRect.GetWidth() == 1) || (aRect.GetHeight() == 1) )
+ ImplCreateRectRegion( aRect );
+ else
+ mpImplRegion = new ImplRegion( rPolyPoly );
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplPolyPolyRegionToBandRegionFunc()
+{
+ const PolyPolygon aPolyPoly( *mpImplRegion->mpPolyPoly );
+
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+
+ const USHORT nPolyCount = aPolyPoly.Count();
+ if ( nPolyCount )
+ {
+ // polypolygon empty? -> empty region
+ const Rectangle aRect( aPolyPoly.GetBoundRect() );
+
+ if ( !aRect.IsEmpty() )
+ {
+ long nLineID = 0L;
+
+ // initialisation and creation of Bands
+ mpImplRegion = new ImplRegion();
+ mpImplRegion->CreateBandRange( aRect.Top(), aRect.Bottom() );
+
+ // insert polygons
+ for ( USHORT nPoly = 0; nPoly < nPolyCount; nPoly++ )
+ {
+ // get reference to current polygon
+ const Polygon& aPoly = aPolyPoly.GetObject( nPoly );
+ const USHORT nSize = aPoly.GetSize();
+
+ // not enough points ( <= 2 )? -> nothing to do!
+ if ( nSize <= 2 )
+ continue;
+
+ // band the polygon
+ for ( USHORT nPoint = 1; nPoint < nSize; nPoint++ )
+ mpImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
+
+ // close polygon with line from first point to last point, if neccesary
+ const Point rLastPoint = aPoly.GetPoint(nSize-1);
+ const Point rFirstPoint = aPoly.GetPoint(0);
+ if ( rLastPoint != rFirstPoint )
+ mpImplRegion->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
+ }
+
+ // process bands with lines
+ ImplRegionBand* pRegionBand = mpImplRegion->mpFirstBand;
+ while ( pRegionBand )
+ {
+ // generate separations from the lines and process union
+ pRegionBand->ProcessPoints();
+ pRegionBand = pRegionBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ else
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::Move( long nHorzMove, long nVertMove )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no region data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ if ( mpImplRegion->mpPolyPoly )
+ mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
+ else
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // process the vertical move
+ if ( nVertMove != 0)
+ {
+ pBand->mnYTop = pBand->mnYTop + nVertMove;
+ pBand->mnYBottom = pBand->mnYBottom + nVertMove;
+ }
+
+ // process the horizontal move
+ if ( nHorzMove != 0)
+ pBand->MoveX( nHorzMove );
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Region::Scale( double fScaleX, double fScaleY )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no region data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ if ( mpImplRegion->mpPolyPoly )
+ mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
+ else
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // process the vertical move
+ if ( fScaleY != 0.0 )
+ {
+ pBand->mnYTop = FRound( pBand->mnYTop * fScaleY );
+ pBand->mnYBottom = FRound( pBand->mnYBottom * fScaleY );
+ }
+
+ // process the horizontal move
+ if ( fScaleX != 0.0 )
+ pBand->ScaleX( fScaleX );
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Union( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process union
+ mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Intersect( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ {
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return TRUE;
+ }
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // is region empty? -> nothing to do!
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return TRUE;
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // is own region NULL-region? -> copy data!
+ if ( mpImplRegion == &aImplNullRegion )
+ {
+ // create instance of implementation class
+ mpImplRegion = new ImplRegion();
+
+ // add band with boundaries of the rectangle
+ mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
+
+ // Set left and right boundaries of the band
+ mpImplRegion->mpFirstBand->Union( nLeft, nRight );
+ mpImplRegion->mnRectCount = 1;
+
+ return TRUE;
+ }
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process intersections
+ ImplRegionBand* pPrevBand;
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // band within intersection boundary? -> process. otherwise remove
+ if ( (pBand->mnYTop >= nTop) &&
+ (pBand->mnYBottom <= nBottom) )
+ {
+ // process intersection
+ pBand->Intersect( nLeft, nRight );
+
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ else
+ {
+ ImplRegionBand* pOldBand = pBand;
+ if ( pBand == mpImplRegion->mpFirstBand )
+ mpImplRegion->mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Exclude( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process exclude
+ mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::XOr( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> nothing to do
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( nTop, nBottom );
+
+ // process xor
+ mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Union( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> create!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ mpImplRegion = new ImplRegion();
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->Union( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Intersect( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // same instance data? -> nothing to do!
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return TRUE;
+
+ // is region null? -> nothing to do
+ if ( rRegion.mpImplRegion == &aImplNullRegion )
+ return TRUE;
+
+ // is rectangle empty? -> nothing to do
+ if ( rRegion.mpImplRegion == &aImplEmptyRegion )
+ {
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return TRUE;
+ }
+
+ // is own region NULL-region? -> copy data!
+ if ( mpImplRegion == &aImplNullRegion)
+ {
+ mpImplRegion = rRegion.mpImplRegion;
+ rRegion.mpImplRegion->mnRefCount++;
+ return TRUE;
+ }
+
+ // Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
+ if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
+ {
+ Region aTempRegion = rRegion;
+ aTempRegion.Intersect( *this );
+ *this = aTempRegion;
+ }
+ else
+ {
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // mark all bands as untouched
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ pBand->mbTouched = FALSE;
+ pBand = pBand->mpNextBand;
+ }
+
+ pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ // left boundary?
+ if ( pSep == pBand->mpFirstSep )
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( LONG_MIN+1, pBand->mnYTop,
+ pSep->mnXLeft-1, pBand->mnYBottom );
+ }
+
+ // right boundary?
+ if ( pSep->mpNextSep == NULL )
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
+ LONG_MAX-1, pBand->mnYBottom );
+ }
+ else
+ {
+ // process intersection and do not remove untouched bands
+ mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
+ pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
+ }
+
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // remove all untouched bands if bands allready left
+ ImplRegionBand* pPrevBand;
+ pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ if ( !pBand->mbTouched )
+ {
+ // save pointer
+ ImplRegionBand* pOldBand = pBand;
+
+ // previous element of the list
+ if ( pBand == mpImplRegion->mpFirstBand )
+ mpImplRegion->mpFirstBand = pBand->mpNextBand;
+ else
+ pPrevBand->mpNextBand = pBand->mpNextBand;
+
+ pBand = pBand->mpNextBand;
+ delete pOldBand;
+ }
+ else
+ {
+ pPrevBand = pBand;
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::Exclude( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->Exclude( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ // Wir optimieren schon in der Schleife, da wir davon
+ // ausgehen, das wir insgesammt weniger Baender ueberpruefen
+ // muessen
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ break;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::XOr( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // is region empty or null? -> nothing to do
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no instance data? -> nothing to do
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return TRUE;
+
+ // no own instance data? -> make own copy!
+ if ( mpImplRegion->mnRefCount > 1 )
+ ImplCopyData();
+
+ // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // insert bands if the boundaries are not allready in the list
+ mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
+
+ // process all elements of the list
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ mpImplRegion->XOr( pSep->mnXLeft, pBand->mnYTop,
+ pSep->mnXRight, pBand->mnYBottom );
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Region::GetBoundRect() const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ Rectangle aRect;
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return aRect;
+
+ // PolyPolygon data im Imp structure?
+ if ( mpImplRegion->mpPolyPoly )
+ return mpImplRegion->mpPolyPoly->GetBoundRect();
+
+ // no band in the list? -> region is empty!
+ if ( !mpImplRegion->mpFirstBand )
+ return aRect;
+
+ // get the boundaries of the first band
+ long nYTop = mpImplRegion->mpFirstBand->mnYTop;
+ long nYBottom = mpImplRegion->mpFirstBand->mnYBottom;
+ long nXLeft = mpImplRegion->mpFirstBand->GetXLeftBoundary();
+ long nXRight = mpImplRegion->mpFirstBand->GetXRightBoundary();
+
+ // look in the band list (don't test first band again!)
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand->mpNextBand;
+ while ( pBand )
+ {
+ nYBottom = pBand->mnYBottom;
+ nXLeft = Min( nXLeft, pBand->GetXLeftBoundary() );
+ nXRight = Max( nXRight, pBand->GetXRightBoundary() );
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // set rectangle
+ aRect = Rectangle( nXLeft, nYTop, nXRight, nYBottom );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
+ long& rX, long& rY,
+ long& rWidth, long& rHeight ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // no band in the list? -> region is empty!
+ if ( mpImplRegion->mpFirstBand == NULL )
+ return FALSE;
+
+ // initialise pointer for first access
+ ImplRegionBand* pCurrRectBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pCurrRectBandSep = pCurrRectBand->mpFirstSep;
+
+ DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
+ if ( !pCurrRectBandSep )
+ return FALSE;
+
+ // get boundaries of current rectangle
+ rX = pCurrRectBandSep->mnXLeft;
+ rY = pCurrRectBand->mnYTop;
+ rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
+ rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
+
+ // save pointers
+ rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
+ rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
+ long& rX, long& rY,
+ long& rWidth, long& rHeight ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // get last pointers
+ ImplRegionBand* pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
+ ImplRegionBandSep* pCurrRectBandSep = (ImplRegionBandSep*)rImplRegionInfo.mpVoidCurrRectBandSep;
+
+ // get next separation from current band
+ pCurrRectBandSep = pCurrRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pCurrRectBandSep )
+ {
+ // get next band
+ pCurrRectBand = pCurrRectBand->mpNextBand;
+
+ // no band found? -> not further rectangles!
+ if( !pCurrRectBand )
+ return FALSE;
+
+ // get first separation in current band
+ pCurrRectBandSep = pCurrRectBand->mpFirstSep;
+ }
+
+ // get boundaries of current rectangle
+ rX = pCurrRectBandSep->mnXLeft;
+ rY = pCurrRectBand->mnYTop;
+ rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
+ rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
+
+ // save new pointers
+ rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
+ rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+RegionType Region::GetType() const
+{
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return REGION_EMPTY;
+ else if ( mpImplRegion == &aImplNullRegion )
+ return REGION_NULL;
+ else if ( mpImplRegion->mnRectCount == 1 )
+ return REGION_RECTANGLE;
+ else
+ return REGION_COMPLEX;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsInside( const Point& rPoint ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // PolyPolygon data im Imp structure?
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+/*
+ if ( mpImplRegion->mpPolyPoly )
+ return mpImplRegion->mpPolyPoly->IsInside( rPoint );
+*/
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // search band list
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // is point within band?
+ if ( (pBand->mnYTop <= rPoint.Y()) &&
+ (pBand->mnYBottom >= rPoint.Y()) )
+ {
+ // is point within separation of the band?
+ if ( pBand->IsInside( rPoint.X() ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsInside( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> not inside
+ if ( rRect.IsEmpty() )
+ return FALSE;
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // create region from rectangle and intersect own region
+ Region aRegion = rRect;
+ aRegion.Exclude( *this );
+
+ // rectangle is inside if exclusion is empty
+ return aRegion.IsEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::IsOver( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ // Can we optimize this ??? - is used in StarDraw for brushes pointers
+ // Why we have no IsOver for Regions ???
+ // create region from rectangle and intersect own region
+ Region aRegion = rRect;
+ aRegion.Intersect( *this );
+
+ // rectangle is over if include is not empty
+ return !aRegion.IsEmpty();
+}
+
+// -----------------------------------------------------------------------
+
+void Region::SetNull()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // set new type
+ mpImplRegion = (ImplRegion*)(&aImplNullRegion);
+}
+
+// -----------------------------------------------------------------------
+
+void Region::SetEmpty()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // set new type
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+}
+
+// -----------------------------------------------------------------------
+
+Region& Region::operator=( const Region& rRegion )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+ DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ // RefCount == 0 fuer statische Objekte
+ if ( rRegion.mpImplRegion->mnRefCount )
+ rRegion.mpImplRegion->mnRefCount++;
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ mpImplRegion = rRegion.mpImplRegion;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+Region& Region::operator=( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ ImplCreateRectRegion( rRect );
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::operator==( const Region& rRegion ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ // reference to same object? -> equal!
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
+ return FALSE;
+
+ if ( rRegion.mpImplRegion->mpPolyPoly && mpImplRegion->mpPolyPoly )
+ return *rRegion.mpImplRegion->mpPolyPoly == *mpImplRegion->mpPolyPoly;
+ else
+ {
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // Eine der beiden Regions kann jetzt Empty sein
+ if ( mpImplRegion == rRegion.mpImplRegion )
+ return TRUE;
+
+ if ( mpImplRegion == &aImplEmptyRegion )
+ return FALSE;
+
+ if ( rRegion.mpImplRegion == &aImplEmptyRegion )
+ return FALSE;
+ }
+
+ // initialise pointers
+ ImplRegionBand* pOwnRectBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ ImplRegionBand* pSecondRectBand = rRegion.mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+ while ( pOwnRectBandSep && pSecondRectBandSep )
+ {
+ // get boundaries of current rectangle
+ long nOwnXLeft = pOwnRectBandSep->mnXLeft;
+ long nSecondXLeft = pSecondRectBandSep->mnXLeft;
+ if ( nOwnXLeft != nSecondXLeft )
+ return FALSE;
+
+ long nOwnYTop = pOwnRectBand->mnYTop;
+ long nSecondYTop = pSecondRectBand->mnYTop;
+ if ( nOwnYTop != nSecondYTop )
+ return FALSE;
+
+ long nOwnXRight = pOwnRectBandSep->mnXRight;
+ long nSecondXRight = pSecondRectBandSep->mnXRight;
+ if ( nOwnXRight != nSecondXRight )
+ return FALSE;
+
+ long nOwnYBottom = pOwnRectBand->mnYBottom;
+ long nSecondYBottom = pSecondRectBand->mnYBottom;
+ if ( nOwnYBottom != nSecondYBottom )
+ return FALSE;
+
+ // get next separation from current band
+ pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pOwnRectBandSep )
+ {
+ // get next band
+ pOwnRectBand = pOwnRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pOwnRectBand )
+ pOwnRectBandSep = pOwnRectBand->mpFirstSep;
+ }
+
+ // get next separation from current band
+ pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pSecondRectBandSep )
+ {
+ // get next band
+ pSecondRectBand = pSecondRectBand->mpNextBand;
+
+ // get first separation in current band
+ if( pSecondRectBand )
+ pSecondRectBandSep = pSecondRectBand->mpFirstSep;
+ }
+
+ if ( pOwnRectBandSep && !pSecondRectBandSep )
+ return FALSE;
+
+ if ( !pOwnRectBandSep && pSecondRectBandSep )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
+
+SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ VersionCompat aCompat( rIStrm, STREAM_READ );
+ UINT16 nVersion;
+ UINT16 nTmp16;
+
+ // statische Object haben RefCount von 0
+ if ( rRegion.mpImplRegion->mnRefCount )
+ {
+ if ( rRegion.mpImplRegion->mnRefCount > 1 )
+ rRegion.mpImplRegion->mnRefCount--;
+ else
+ delete rRegion.mpImplRegion;
+ }
+
+ // get version of streamed region
+ rIStrm >> nVersion;
+
+ // get type of region
+ rIStrm >> nTmp16;
+
+ RegionType meStreamedType = (RegionType)nTmp16;
+
+ switch( meStreamedType )
+ {
+ case REGION_NULL:
+ rRegion.mpImplRegion = (ImplRegion*)&aImplNullRegion;
+ break;
+
+ case REGION_EMPTY:
+ rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
+ break;
+
+ default:
+ // create instance of implementation class
+ rRegion.mpImplRegion = new ImplRegion();
+
+ // get header from first element
+ rIStrm >> nTmp16;
+
+ // get all bands
+ rRegion.mpImplRegion->mnRectCount = 0;
+ ImplRegionBand* pCurrBand = NULL;
+ while ( (StreamEntryType)nTmp16 != STREAMENTRY_END )
+ {
+ // insert new band or new separation?
+ if ( (StreamEntryType)nTmp16 == STREAMENTRY_BANDHEADER )
+ {
+ long nYTop;
+ long nYBottom;
+
+ rIStrm >> nYTop;
+ rIStrm >> nYBottom;
+
+ // create band
+ ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
+
+ // first element? -> set as first into the list
+ if ( !pCurrBand )
+ rRegion.mpImplRegion->mpFirstBand = pNewBand;
+ else
+ pCurrBand->mpNextBand = pNewBand;
+
+ // save pointer for next creation
+ pCurrBand = pNewBand;
+ }
+ else
+ {
+ long nXLeft;
+ long nXRight;
+
+ rIStrm >> nXLeft;
+ rIStrm >> nXRight;
+
+ // add separation
+ if ( pCurrBand )
+ {
+ pCurrBand->Union( nXLeft, nXRight );
+ rRegion.mpImplRegion->mnRectCount++;
+ }
+ }
+
+ // get next header
+ rIStrm >> nTmp16;
+ }
+ break;
+ }
+
+ return rIStrm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStrm, const Region& rRegion )
+{
+ DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
+
+ VersionCompat aCompat( rOStrm, STREAM_WRITE );
+ UINT16 nVersion = 1;
+
+ ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
+
+ // put version
+ rOStrm << nVersion;
+
+ // put type
+ rOStrm << (UINT16)rRegion.GetType();
+
+ // put all bands if not null or empty
+ if ( (rRegion.mpImplRegion != &aImplEmptyRegion) && (rRegion.mpImplRegion != &aImplNullRegion) )
+ {
+ ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ // put boundaries
+ rOStrm << (UINT16) STREAMENTRY_BANDHEADER;
+ rOStrm << pBand->mnYTop;
+ rOStrm << pBand->mnYBottom;
+
+ // put separations of current band
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while ( pSep )
+ {
+ // put separation
+ rOStrm << (UINT16) STREAMENTRY_SEPARATION;
+ rOStrm << pSep->mnXLeft;
+ rOStrm << pSep->mnXRight;
+
+ // next separation from current band
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+
+ // put endmarker
+ rOStrm << (UINT16) STREAMENTRY_END;
+ }
+
+ return rOStrm;
+}
+
+// -----------------------------------------------------------------------
+
+RegionOverlapType Region::GetOverlapType( const Rectangle& rRect ) const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // is rectangle empty? -> not inside
+ if ( rRect.IsEmpty() )
+ return REGION_OUTSIDE;
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+ // no instance data? -> not inside
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return REGION_OUTSIDE;
+
+ // resolve pointer
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+
+ // complex region? don't check for now. This may change in the future...
+ if ( pBand->mpNextBand || pSep->mpNextSep )
+ return REGION_OVER;
+
+ // get justified rectangle
+ long nLeft = Min( rRect.Left(), rRect.Right() );
+ long nTop = Min( rRect.Top(), rRect.Bottom() );
+ long nRight = Max( rRect.Left(), rRect.Right() );
+ long nBottom = Max( rRect.Top(), rRect.Bottom() );
+
+ // check rectangle region
+ BOOL boLeft = (nLeft >= pSep->mnXLeft) && (nLeft < pSep->mnXRight);
+ BOOL boRight = (nRight <= pSep->mnXRight) && (nRight > pSep->mnXLeft);
+ BOOL boTop = (nTop >= pBand->mnYTop) && (nTop < pBand->mnYBottom);
+ BOOL boBottom = (nBottom <= pBand->mnYBottom) && (nBottom > pBand->mnYTop);
+ if ( boLeft && boRight && boTop && boBottom )
+ return REGION_INSIDE;
+ if ( boLeft || boRight || boTop || boBottom )
+ return REGION_OVER;
+
+ return REGION_OUTSIDE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplBeginAddRect()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ // statische Object haben RefCount von 0
+ if ( mpImplRegion->mnRefCount )
+ {
+ if ( mpImplRegion->mnRefCount > 1 )
+ mpImplRegion->mnRefCount--;
+ else
+ delete mpImplRegion;
+ }
+
+ // create fresh region
+ mpImplRegion = new ImplRegion();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::ImplAddRect( const Rectangle& rRect )
+{
+ // Hier kein CheckThis, da nicht alle Daten auf Stand
+
+ if ( rRect.IsEmpty() )
+ return TRUE;
+
+ // get justified rectangle
+ long nTop;
+ long nBottom;
+ long nLeft;
+ long nRight;
+ if ( rRect.Top() <= rRect.Bottom() )
+ {
+ nTop = rRect.Top();
+ nBottom = rRect.Bottom();
+ }
+ else
+ {
+ nTop = rRect.Bottom();
+ nBottom = rRect.Top();
+ }
+ if ( rRect.Left() <= rRect.Right() )
+ {
+ nLeft = rRect.Left();
+ nRight = rRect.Right();
+ }
+ else
+ {
+ nLeft = rRect.Right();
+ nRight = rRect.Left();
+ }
+
+ if ( !mpImplRegion->mpLastCheckedBand )
+ {
+ // create new band
+ mpImplRegion->mpLastCheckedBand = new ImplRegionBand( nTop, nBottom );
+
+ // set band as current
+ mpImplRegion->mpFirstBand = mpImplRegion->mpLastCheckedBand;
+ mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
+ }
+ else
+ {
+ DBG_ASSERT( nTop >= mpImplRegion->mpLastCheckedBand->mnYTop,
+ "Region::ImplAddRect() - nTopY < nLastTopY" );
+
+ // new band? create it!
+ if ( (nTop != mpImplRegion->mpLastCheckedBand->mnYTop) ||
+ (nBottom != mpImplRegion->mpLastCheckedBand->mnYBottom) )
+ {
+ // create new band
+ ImplRegionBand* pNewRegionBand = new ImplRegionBand( nTop, nBottom );
+
+ // append band to the end
+ mpImplRegion->mpLastCheckedBand->mpNextBand = pNewRegionBand;
+
+ // skip to the new band
+ mpImplRegion->mpLastCheckedBand = mpImplRegion->mpLastCheckedBand->mpNextBand;
+ }
+
+ // Insert Sep
+ mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
+ }
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::ImplEndAddRect()
+{
+ // check if we are empty
+ if ( !mpImplRegion->mpFirstBand )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ return;
+ }
+
+ // check if we have somthing to optimize
+ if ( !mpImplRegion->mpFirstBand->mpNextBand )
+ {
+ // update mpImplRegion->mnRectCount, because no OptimizeBandList is called
+ ImplRegionBandSep* pSep = mpImplRegion->mpFirstBand->mpFirstSep;
+ mpImplRegion->mnRectCount = 0;
+ while( pSep )
+ {
+ mpImplRegion->mnRectCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ // Erst hier testen, da hier die Daten wieder stimmen
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ return;
+ }
+
+ // have to revert list? -> do it now!
+ if ( mpImplRegion->mpFirstBand->mnYTop >
+ mpImplRegion->mpFirstBand->mpNextBand->mnYTop )
+ {
+ ImplRegionBand * pNewFirstRegionBand;
+
+ // initialize temp list with first element
+ pNewFirstRegionBand = mpImplRegion->mpFirstBand;
+ mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
+ pNewFirstRegionBand->mpNextBand = NULL;
+
+ // insert elements to the temp list
+ while ( mpImplRegion->mpFirstBand )
+ {
+ ImplRegionBand * pSavedRegionBand = pNewFirstRegionBand;
+ pNewFirstRegionBand = mpImplRegion->mpFirstBand;
+ mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
+ pNewFirstRegionBand->mpNextBand = pSavedRegionBand;
+ }
+
+ // set temp list as new list
+ mpImplRegion->mpFirstBand = pNewFirstRegionBand;
+ }
+
+ // cleanup
+ if ( !mpImplRegion->OptimizeBandList() )
+ {
+ delete mpImplRegion;
+ mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
+ }
+
+ // Erst hier testen, da hier die Daten wieder stimmen
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Region::GetRectCount() const
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ((Region*)this)->ImplPolyPolyRegionToBandRegion();
+
+#ifdef DBG_UTIL
+ ULONG nCount = 0;
+
+ // all bands if not null or empty
+ if ( (mpImplRegion != &aImplEmptyRegion) && (mpImplRegion != &aImplNullRegion) )
+ {
+ ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
+ while ( pBand )
+ {
+ ImplRegionBandSep* pSep = pBand->mpFirstSep;
+ while( pSep )
+ {
+ nCount++;
+ pSep = pSep->mpNextSep;
+ }
+
+ pBand = pBand->mpNextBand;
+ }
+ }
+
+ DBG_ASSERT( mpImplRegion->mnRectCount == nCount, "Region: invalid mnRectCount!" );
+#endif
+
+ return mpImplRegion->mnRectCount;
+}
+
+// -----------------------------------------------------------------------
+
+RegionHandle Region::BeginEnumRects()
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplPolyPolyRegionToBandRegion();
+
+ // no internal data? -> region is empty!
+ if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
+ return NULL;
+
+ // no band in the list? -> region is empty!
+ if ( mpImplRegion->mpFirstBand == NULL )
+ {
+ DBG_ASSERT( mpImplRegion->mpFirstBand, "Region::BeginEnumRects() First Band is Empty!" );
+ return NULL;
+ }
+
+ ImplRegionHandle* pData = new ImplRegionHandle;
+ pData->mpRegion = new Region( *this );
+ pData->mbFirst = TRUE;
+
+ // save pointers
+ pData->mpCurrRectBand = pData->mpRegion->mpImplRegion->mpFirstBand;
+ pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
+
+ return (RegionHandle)pData;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Region::GetEnumRects( RegionHandle pVoidData, Rectangle& rRect )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
+ if ( !pData )
+ return FALSE;
+
+ if ( pData->mbFirst )
+ pData->mbFirst = FALSE;
+ else
+ {
+ // get next separation from current band
+ pData->mpCurrRectBandSep = pData->mpCurrRectBandSep->mpNextSep;
+
+ // no separation found? -> go to next band!
+ if ( !pData->mpCurrRectBandSep )
+ {
+ // get next band
+ pData->mpCurrRectBand = pData->mpCurrRectBand->mpNextBand;
+
+ // no band found? -> not further rectangles!
+ if ( !pData->mpCurrRectBand )
+ return FALSE;
+
+ // get first separation in current band
+ pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
+ }
+ }
+
+ // get boundaries of current rectangle
+ rRect.Top() = pData->mpCurrRectBand->mnYTop;
+ rRect.Bottom() = pData->mpCurrRectBand->mnYBottom;
+ rRect.Left() = pData->mpCurrRectBandSep->mnXLeft;
+ rRect.Right() = pData->mpCurrRectBandSep->mnXRight;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Region::EndEnumRects( RegionHandle pVoidData )
+{
+ DBG_CHKTHIS( Region, ImplDbgTestRegion );
+
+ ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
+ if ( !pData )
+ return;
+
+ // cleanup
+ delete pData->mpRegion;
+ delete pData;
+}
diff --git a/vcl/source/gdi/salmisc.cxx b/vcl/source/gdi/salmisc.cxx
new file mode 100644
index 000000000000..50af07d0eda9
--- /dev/null
+++ b/vcl/source/gdi/salmisc.cxx
@@ -0,0 +1,497 @@
+/*************************************************************************
+ *
+ * $RCSfile: salmisc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _RTL_MEMORY_H_
+#include <rtl/memory.h>
+#endif
+#include <bmpacc.hxx>
+#include <salbtype.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define IMPL_CASE_GET_FORMAT( Format ) \
+case( BMP_FORMAT##Format ): \
+ pFncGetPixel = BitmapReadAccess::GetPixelFor##Format; \
+break
+
+// -----------------------------------------------------------------------------
+
+#define IMPL_CASE_SET_FORMAT( Format, BitCount ) \
+case( BMP_FORMAT##Format ): \
+{ \
+ pFncSetPixel = BitmapReadAccess::SetPixelFor##Format; \
+ pDstBuffer->mnBitCount = BitCount; \
+} \
+break
+
+// -----------------------------------------------------------------------------
+
+#define DOUBLE_SCANLINES() \
+while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) ) \
+{ \
+ HMEMCPY( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize ); \
+ nActY++; \
+}
+
+// -----------
+// - Inlines -
+// -----------
+
+#define TC_TO_PAL_COLORS 4096
+
+static long ImplIndexFromColor( const BitmapColor& rCol )
+{
+#if TC_TO_PAL_COLORS == 4096
+
+ return( ( ( (long) rCol.GetBlue() >> 4L) << 8L ) |
+ ( ( (long) rCol.GetGreen() >> 4L ) << 4L ) |
+ ( (long) rCol.GetRed() >> 4L ) );
+
+#elif TC_TO_PAL_COLORS == 32768
+
+ return( ( ( (long) rCol.GetBlue() >> 3L) << 10L ) |
+ ( ( (long) rCol.GetGreen() >> 3L ) << 5L ) |
+ ( (long) rCol.GetRed() >> 3L ) );
+
+#endif
+}
+
+
+#define COLOR_TO_INDEX( _def_rCol )
+
+// ------------------------
+// - conversion functions -
+// ------------------------
+
+static void ImplPALToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
+ BitmapColor* pColMapBuf = aColMap.ImplGetColorBuffer();
+ BitmapColor aIndex( 0 );
+
+ for( USHORT i = 0, nCount = aColMap.GetEntryCount(); i < nCount; i++ )
+ {
+ if( rSrcBuffer.maPalette[ i ] == rDstBuffer.maPalette[ i ] )
+ aIndex.SetIndex( i );
+ else
+ aIndex.SetIndex( rDstBuffer.maPalette.GetBestIndex( rSrcBuffer.maPalette[ i ] ) );
+
+ pColMapBuf[ i ] = aIndex;
+ }
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColMapBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplPALToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ const BitmapColor* pColBuf = rSrcBuffer.maPalette.ImplGetColorBuffer();
+
+ if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_1BIT_MSB_PAL )
+ {
+ const BitmapColor aCol0( pColBuf[ 0 ] );
+ const BitmapColor aCol1( pColBuf[ 1 ] );
+ long nMapX;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; )
+ {
+ nMapX = pMapX[ nX ];
+ pFncSetPixel( pDstScan, nX++,
+ pSrcScan[ nMapX >> 3 ] & ( 1 << ( 7 - ( nMapX & 7 ) ) ) ? aCol1 : aCol0,
+ rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_4BIT_MSN_PAL )
+ {
+ long nMapX;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; )
+ {
+ nMapX = pMapX[ nX ];
+ pFncSetPixel( pDstScan, nX++,
+ pColBuf[ ( pSrcScan[ nMapX >> 1 ] >> ( nMapX & 1 ? 0 : 4 ) ) & 0x0f ],
+ rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_8BIT_PAL )
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColBuf[ pSrcScan[ pMapX[ nX ] ] ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+ else
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pColBuf[ pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ).GetIndex() ], rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplTCToTC( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+
+ if( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ BitmapColor aCol;
+ BYTE* pPixel;
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol.SetBlue( *( pPixel = ( pSrcScan + pMapX[ nX ] * 3 ) )++ );
+ aCol.SetGreen( *pPixel++ );
+ aCol.SetRed( *pPixel );
+ pFncSetPixel( pDstScan, nX, aCol, rDstMask );
+ }
+
+ DOUBLE_SCANLINES()
+ }
+ }
+ else
+ {
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFncSetPixel( pDstScan, nX, pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ), rDstMask );
+
+ DOUBLE_SCANLINES();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+static void ImplTCToPAL( const BitmapBuffer& rSrcBuffer, BitmapBuffer& rDstBuffer,
+ FncGetPixel pFncGetPixel, FncSetPixel pFncSetPixel,
+ Scanline* pSrcScanMap, Scanline* pDstScanMap, long* pMapX, long* pMapY )
+{
+ const long nWidth = rDstBuffer.mnWidth, nHeight = rDstBuffer.mnHeight, nHeight1 = nHeight - 1;
+ const ColorMask& rSrcMask = rSrcBuffer.maColorMask;
+ const ColorMask& rDstMask = rDstBuffer.maColorMask;
+ BitmapPalette aColMap( rSrcBuffer.maPalette.GetEntryCount() );
+ BYTE* pColToPalMap = new BYTE[ TC_TO_PAL_COLORS ];
+ BitmapColor aIndex( 0 );
+
+ for( long nR = 0; nR < 16; nR++ )
+ {
+ for( long nG = 0; nG < 16; nG++ )
+ {
+ for( long nB = 0; nB < 16; nB++ )
+ {
+ BitmapColor aCol( nR << 4, nG << 4, nB << 4 );
+ pColToPalMap[ ImplIndexFromColor( aCol ) ] = (BYTE) rDstBuffer.maPalette.GetBestIndex( aCol );
+ }
+ }
+ }
+
+ for( long nActY = 0, nMapY; nActY < nHeight; nActY++ )
+ {
+ Scanline pSrcScan( pSrcScanMap[ nMapY = pMapY[ nActY ] ] ), pDstScan( pDstScanMap[ nActY ] );
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aIndex.SetIndex( pColToPalMap[ ImplIndexFromColor( pFncGetPixel( pSrcScan, pMapX[ nX ], rSrcMask ) ) ] );
+ pFncSetPixel( pDstScan, nX, aIndex, rDstMask );
+ }
+
+ DOUBLE_SCANLINES();
+ }
+
+ delete[] pColToPalMap;
+}
+
+// ---------------------
+// - StretchAndConvert -
+// ---------------------
+
+BitmapBuffer* StretchAndConvert( const BitmapBuffer& rSrcBuffer, const SalTwoRect& rTwoRect,
+ ULONG nDstBitmapFormat, BitmapPalette* pDstPal, ColorMask* pDstMask )
+{
+ FncGetPixel pFncGetPixel;
+ FncSetPixel pFncSetPixel;
+ BitmapBuffer* pDstBuffer = new BitmapBuffer;
+ const ULONG nDstScanlineFormat = BMP_SCANLINE_FORMAT( nDstBitmapFormat );
+ const long nSrcX = rTwoRect.mnSrcX, nSrcY = rTwoRect.mnSrcY;
+ const long nSrcDX = rTwoRect.mnSrcWidth, nSrcDY = rTwoRect.mnSrcHeight;
+ const long nDstDX = rTwoRect.mnDestWidth, nDstDY = rTwoRect.mnDestHeight;
+ Scanline* pSrcScan = new Scanline[ rSrcBuffer.mnHeight ];
+ Scanline* pDstScan = new Scanline[ nDstDY ];
+ long* pMapX = new long[ nDstDX ];
+ long* pMapY = new long[ nDstDY ];
+ Scanline pTmpScan;
+ long i, nTmp, nOffset;
+
+ // set function for getting pixels
+ switch( BMP_SCANLINE_FORMAT( rSrcBuffer.mnFormat ) )
+ {
+ IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL );
+ IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL );
+ IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL );
+ IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL );
+ IMPL_CASE_GET_FORMAT( _8BIT_PAL );
+ IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _16BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB );
+ IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA );
+ IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK );
+
+ default:
+ DBG_ERROR( "unknown read format" );
+ break;
+ }
+
+ // set function for setting pixels
+ switch( nDstScanlineFormat )
+ {
+ IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL, 1 );
+ IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL, 4 );
+ IMPL_CASE_SET_FORMAT( _8BIT_PAL, 8 );
+ IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK, 8 );
+ IMPL_CASE_SET_FORMAT( _16BIT_TC_MASK, 16 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR, 24 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB, 24 );
+ IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK, 24 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA, 32 );
+ IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK, 32 );
+
+ default:
+ DBG_ERROR( "unknown write format" );
+ break;
+ }
+
+ // fill destination buffer
+ pDstBuffer->mnFormat = nDstBitmapFormat;
+ pDstBuffer->mnWidth = nDstDX;
+ pDstBuffer->mnHeight = nDstDY;
+ pDstBuffer->mnScanlineSize = AlignedWidth4Bytes( pDstBuffer->mnBitCount * nDstDX );
+ pDstBuffer->mpBits = new BYTE[ pDstBuffer->mnScanlineSize * nDstDY ];
+ rtl_zeroMemory( pDstBuffer->mpBits, pDstBuffer->mnScanlineSize * nDstDY );
+
+ // do we need a destination palette or color mask?
+ if( ( nDstScanlineFormat == BMP_FORMAT_1BIT_MSB_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_1BIT_LSB_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_4BIT_MSN_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_4BIT_LSN_PAL ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_8BIT_PAL ) )
+ {
+ DBG_ASSERT( pDstPal, "destination buffer requires palette" );
+ pDstBuffer->maPalette = *pDstPal;
+ }
+ else if( ( nDstScanlineFormat == BMP_FORMAT_8BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_16BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_24BIT_TC_MASK ) ||
+ ( nDstScanlineFormat == BMP_FORMAT_32BIT_TC_MASK ) )
+ {
+ DBG_ASSERT( pDstMask, "destination buffer requires color mask" );
+ pDstBuffer->maColorMask = *pDstMask;
+ }
+
+ // horizontal mapping table
+ if( nDstDX != nSrcDX )
+ {
+ const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
+
+ for( i = 0L; i < nDstDX; i++ )
+ pMapX[ i ] = nSrcX + FRound( i * fFactorX );
+ }
+ else
+ {
+ for( i = 0L, nTmp = nSrcX; i < nDstDX; i++ )
+ pMapX[ i ] = nTmp++;
+ }
+
+ // vertical mapping table
+ if( nDstDY != nSrcDY )
+ {
+ const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
+
+ for( i = 0L; i < nDstDY; i++ )
+ pMapY[ i ] = nSrcY + FRound( i * fFactorY );
+ }
+ else
+ {
+ for( i = 0L, nTmp = nSrcY; i < nDstDY; i++ )
+ pMapY[ i ] = nTmp++;
+ }
+
+ // source scanline buffer
+ if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer.mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ pTmpScan = rSrcBuffer.mpBits, nOffset = rSrcBuffer.mnScanlineSize;
+ else
+ {
+ pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
+ nOffset = -rSrcBuffer.mnScanlineSize;
+ }
+
+ for( i = 0L; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset )
+ pSrcScan[ i ] = pTmpScan;
+
+ // destination scanline buffer
+ if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
+ pTmpScan = pDstBuffer->mpBits, nOffset = pDstBuffer->mnScanlineSize;
+ else
+ {
+ pTmpScan = pDstBuffer->mpBits + ( nDstDY - 1 ) * pDstBuffer->mnScanlineSize;
+ nOffset = -pDstBuffer->mnScanlineSize;
+ }
+
+ for( i = 0L; i < nDstDY; i++, pTmpScan += nOffset )
+ pDstScan[ i ] = pTmpScan;
+
+ // do buffer scaling and conversion
+ if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount <= 8 )
+ {
+ ImplPALToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else if( rSrcBuffer.mnBitCount <= 8 && pDstBuffer->mnBitCount > 8 )
+ {
+ ImplPALToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else if( rSrcBuffer.mnBitCount > 8 && pDstBuffer->mnBitCount > 8 )
+ {
+ ImplTCToTC( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+ else
+ {
+ ImplTCToPAL( rSrcBuffer, *pDstBuffer, pFncGetPixel, pFncSetPixel,
+ pSrcScan, pDstScan, pMapX, pMapY );
+ }
+
+ // cleanup
+ delete[] pSrcScan;
+ delete[] pDstScan;
+ delete[] pMapX;
+ delete[] pMapY;
+
+ return pDstBuffer;
+}
diff --git a/vcl/source/gdi/svcompat.cxx b/vcl/source/gdi/svcompat.cxx
new file mode 100644
index 000000000000..dc037185e064
--- /dev/null
+++ b/vcl/source/gdi/svcompat.cxx
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * $RCSfile: svcompat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_COMPAT_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _SV_SVCOMPAT_HXX
+#include <svcompat.hxx>
+#endif
+
+// --------------
+// - ImplCompat -
+// --------------
+
+ImplCompat::ImplCompat( SvStream& rStm, USHORT nStreamMode, USHORT nVersion ) :
+ mpRWStm ( &rStm ),
+ mnStmMode ( nStreamMode ),
+ mnVersion ( nVersion )
+{
+ if( !mpRWStm->GetError() )
+ {
+ if( STREAM_WRITE == mnStmMode )
+ {
+ *mpRWStm << mnVersion;
+ mnTotalSize = ( mnCompatPos = mpRWStm->Tell() ) + 4UL;
+ mpRWStm->SeekRel( 4L );
+ }
+ else
+ {
+ *mpRWStm >> mnVersion;
+ *mpRWStm >> mnTotalSize;
+ mnCompatPos = mpRWStm->Tell();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImplCompat::~ImplCompat()
+{
+ if( STREAM_WRITE == mnStmMode )
+ {
+ const UINT32 nEndPos = mpRWStm->Tell();
+
+ mpRWStm->Seek( mnCompatPos );
+ *mpRWStm << ( nEndPos - mnTotalSize );
+ mpRWStm->Seek( nEndPos );
+ }
+ else
+ {
+ const UINT32 nReadSize = mpRWStm->Tell() - mnCompatPos;
+
+ if( mnTotalSize > nReadSize )
+ mpRWStm->SeekRel( mnTotalSize - nReadSize );
+ }
+}
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
new file mode 100644
index 000000000000..ff8c7268c9fe
--- /dev/null
+++ b/vcl/source/gdi/virdev.cxx
@@ -0,0 +1,442 @@
+/*************************************************************************
+ *
+ * $RCSfile: virdev.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_VIRDEV_CXX
+
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALINST_HXX
+#include <salinst.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#ifndef _SV_SALVD_HXX
+#include <salvd.hxx>
+#endif
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_SETTINGS_HXX
+#include <settings.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+#ifndef _SV_WRKWIN_HXX
+#include <wrkwin.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+
+using namespace ::com::sun::star::uno;
+
+// appserver
+#ifdef REMOTE_APPSERVER
+#ifndef _SV_RMOUTDEV_HXX
+#include <rmoutdev.hxx>
+#endif
+#ifndef _SV_RMVIRDEV_HXX
+#include <rmvirdev.hxx>
+#endif
+#ifndef _VCL_RMCACHE_HXX_
+#include <rmcache.hxx>
+#endif
+#endif
+
+// =======================================================================
+
+// interface cache
+#ifdef REMOTE_APPSERVER
+
+static ::vcl::InterfacePairCache< ::com::sun::star::portal::client::XRmVirtualDevice, ::com::sun::star::portal::client::XRmOutputDevice >* pRemoteVirdevCache = NULL;
+
+typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::portal::client::XRmVirtualDevice >, ::com::sun::star::uno::Reference< ::com::sun::star::portal::client::XRmOutputDevice > > virdevInterfacePair;
+
+void eraseRemoteVirdevCache()
+{
+ if( pRemoteVirdevCache )
+ {
+ delete pRemoteVirdevCache;
+ pRemoteVirdevCache = NULL;
+ }
+}
+
+#endif
+
+// =======================================================================
+
+void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
+ long nDX, long nDY, USHORT nBitCount )
+{
+ DBG_ASSERT( nBitCount <= 1,
+ "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );
+
+ if ( nDX < 1 )
+ nDX = 1;
+
+ if ( nDY < 1 )
+ nDY = 1;
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( !pOutDev )
+ pOutDev = ImplGetDefaultWindow();
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+ if ( !pOutDev->mpGraphics )
+ ((OutputDevice*)pOutDev)->ImplGetGraphics();
+ pGraphics = pOutDev->mpGraphics;
+ if ( pGraphics )
+ mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount );
+ else
+ mpVirDev = NULL;
+ if ( !mpVirDev )
+ GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
+#else
+ if( ! pRemoteVirdevCache )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ pRemoteVirdevCache = new ::vcl::InterfacePairCache< ::com::sun::star::portal::client::XRmVirtualDevice, ::com::sun::star::portal::client::XRmOutputDevice >(
+ pSVData->mxMultiFactory,
+ ::rtl::OUString::createFromAscii( "OfficeVirtualDevice.stardiv.de" ),
+ 20, 10, 40 );
+ }
+
+ if( pOutDev->GetOutDevType() == OUTDEV_PRINTER || ! mpVirDev )
+ {
+ virdevInterfacePair aPair = pRemoteVirdevCache->takeInterface();
+ if( aPair.first.is() && aPair.second.is() )
+ {
+ if( ! mpVirDev )
+ mpVirDev = new RmVirtualDevice;
+ mpVirDev->SetInterface( aPair.first );
+ mpVirDev->Create( (ULONG) pOutDev, nDX, nDY, nBitCount );
+
+ if( ! mpGraphics )
+ mpGraphics = new ImplServerGraphics();
+ mpGraphics->SetInterface( aPair.second );
+ }
+ }
+ else
+ {
+ // this was done in ImpGetServerGraphics before
+ // and is now here because of interface caching
+ if( mpGraphics && mpGraphics->GetInterface().is() )
+ {
+ try
+ {
+ mpGraphics->GetInterface()->SetFillColor( mpGraphics->maFillColor.GetColor() );
+ }
+ catch (...)
+ {
+ if( mpGraphics )
+ delete mpGraphics, mpGraphics = NULL;
+
+ if( mpVirDev )
+ {
+ virdevInterfacePair aPair = pRemoteVirdevCache->takeInterface();
+ if( aPair.first.is() && aPair.second.is() )
+ {
+ mpVirDev->SetInterface( aPair.first );
+ mpVirDev->Create( (ULONG)NULL, mnOutWidth, mnOutHeight, mnBitCount );
+ mpGraphics = new ImplServerGraphics();
+ mpGraphics->SetInterface( aPair.second );
+ }
+ else
+ mpVirDev->SetInterface( REF( NMSP_CLIENT::XRmVirtualDevice )() );
+ }
+ }
+ }
+ ImplGetServerGraphics( TRUE );
+ }
+#endif
+
+ mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
+ mnOutWidth = nDX;
+ mnOutHeight = nDY;
+ mbScreenComp = TRUE;
+
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ mbScreenComp = FALSE;
+ else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
+ mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;
+
+ meOutDevType = OUTDEV_VIRDEV;
+ mbDevOutput = TRUE;
+ mpFontList = pSVData->maGDIData.mpScreenFontList;
+ mpFontCache = pSVData->maGDIData.mpScreenFontCache;
+ mnDPIX = pOutDev->mnDPIX;
+ mnDPIY = pOutDev->mnDPIY;
+ maFont = pOutDev->maFont;
+
+ // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
+ SetBackground( Wallpaper( Color( COL_WHITE ) ) );
+ Erase();
+
+ // VirDev in Liste eintragen
+ mpNext = pSVData->maGDIData.mpFirstVirDev;
+ mpPrev = NULL;
+ if ( mpNext )
+ mpNext->mpPrev = this;
+ else
+ pSVData->maGDIData.mpLastVirDev = this;
+ pSVData->maGDIData.mpFirstVirDev = this;
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::VirtualDevice( USHORT nBitCount )
+ : mpVirDev( NULL )
+{
+ DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );
+
+ ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
+ : mpVirDev( NULL )
+{
+ DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );
+
+ ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
+}
+
+// -----------------------------------------------------------------------
+
+VirtualDevice::~VirtualDevice()
+{
+ DBG_TRACE( "VirtualDevice::~VirtualDevice()" );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+#ifndef REMOTE_APPSERVER
+ ImplReleaseGraphics();
+
+ if ( mpVirDev )
+ pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
+#else
+ if ( pRemoteVirdevCache && mpVirDev && mpGraphics )
+ {
+ virdevInterfacePair aPair( mpVirDev->GetInterface(), mpGraphics->GetInterface() );
+ aPair.first->Create( 0, 0, 0, 0 );
+ pRemoteVirdevCache->putInterface( aPair );
+ }
+
+ mpGraphics->SetInterface( REF( NMSP_CLIENT::XRmOutputDevice )() );
+ ImplReleaseServerGraphics();
+ delete mpVirDev;
+ delete mpGraphics;
+#endif
+
+ // VirDev aus der Liste eintragen
+ if( mpPrev )
+ mpPrev->mpNext = mpNext;
+ else
+ pSVData->maGDIData.mpFirstVirDev = mpNext;
+
+ if( mpNext )
+ mpNext->mpPrev = mpPrev;
+ else
+ pSVData->maGDIData.mpLastVirDev = mpPrev;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
+{
+ DBG_TRACE3( "VirtualDevice::SetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );
+
+ if ( !mpVirDev )
+ return FALSE;
+ else if ( rNewSize == GetOutputSizePixel() )
+ {
+ if ( bErase )
+ Erase();
+ return TRUE;
+ }
+
+#ifdef REMOTE_APPSERVER
+ long nOldWidth = mnOutWidth, nOldHeight = mnOutHeight;
+
+ try
+ {
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ mpVirDev->ResizeOutputSizePixel( mnOutWidth, mnOutHeight );
+ }
+ catch (...)
+ {
+ delete mpVirDev, mpVirDev = NULL;
+ ImplInitVirDev( NULL, mnOutWidth, mnOutHeight, mnBitCount );
+ }
+
+ if( bErase )
+ Erase();
+ else
+ {
+ if ( nOldWidth < mnOutWidth )
+ Erase( Rectangle( Point( nOldWidth, 0 ), Size( mnOutWidth-nOldWidth, Max( nOldHeight, mnOutHeight ) ) ) );
+ if ( nOldHeight< mnOutHeight )
+ Erase( Rectangle( Point( 0, nOldHeight ), Size( Max( nOldWidth, mnOutWidth ), mnOutHeight-nOldHeight ) ) );
+ }
+
+ return TRUE;
+#else
+ BOOL bRet;
+ long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();
+
+ if ( nNewWidth < 1 )
+ nNewWidth = 1;
+
+ if ( nNewHeight < 1 )
+ nNewHeight = 1;
+
+ if ( bErase )
+ {
+ bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );
+
+ if ( bRet )
+ {
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ Erase();
+ }
+ }
+ else
+ {
+ SalVirtualDevice* pNewVirDev;
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return FALSE;
+ }
+
+ pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
+ if ( pNewVirDev )
+ {
+ SalGraphics* pGraphics = pNewVirDev->GetGraphics();
+ if ( pGraphics )
+ {
+ SalTwoRect aPosAry;
+ long nWidth;
+ long nHeight;
+ if ( mnOutWidth < nNewWidth )
+ nWidth = mnOutWidth;
+ else
+ nWidth = nNewWidth;
+ if ( mnOutHeight < nNewHeight )
+ nHeight = mnOutHeight;
+ else
+ nHeight = nNewHeight;
+ aPosAry.mnSrcX = 0;
+ aPosAry.mnSrcY = 0;
+ aPosAry.mnSrcWidth = nWidth;
+ aPosAry.mnSrcHeight = nHeight;
+ aPosAry.mnDestX = 0;
+ aPosAry.mnDestY = 0;
+ aPosAry.mnDestWidth = nWidth;
+ aPosAry.mnDestHeight = nHeight;
+
+ pGraphics->CopyBits( &aPosAry, mpGraphics );
+ pNewVirDev->ReleaseGraphics( pGraphics );
+ ImplReleaseGraphics();
+ pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
+ mpVirDev = pNewVirDev;
+ mnOutWidth = rNewSize.Width();
+ mnOutHeight = rNewSize.Height();
+ bRet = TRUE;
+ }
+ else
+ {
+ bRet = FALSE;
+ pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
+ }
+ }
+ else
+ bRet = FALSE;
+ }
+
+ return bRet;
+#endif
+}
+
diff --git a/vcl/source/gdi/wall.cxx b/vcl/source/gdi/wall.cxx
new file mode 100644
index 000000000000..64eb82b23585
--- /dev/null
+++ b/vcl/source/gdi/wall.cxx
@@ -0,0 +1,616 @@
+/*************************************************************************
+ *
+ * $RCSfile: wall.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:39 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WALL_CXX
+
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _VCOMPAT_HXX
+#include <tools/vcompat.hxx>
+#endif
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _SV_BITMAPEX_HXX
+#include <bitmapex.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <gradient.hxx>
+#endif
+#ifndef _SV_WALL_HXX
+#include <wall.hxx>
+#endif
+
+// =======================================================================
+
+DBG_NAME( Wallpaper );
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::ImplWallpaper() :
+ maColor( COL_TRANSPARENT )
+{
+ mnRefCount = 1;
+ mpBitmap = NULL;
+ mpCache = NULL;
+ mpGradient = NULL;
+ mpRect = NULL;
+ meStyle = WALLPAPER_NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::ImplWallpaper( const ImplWallpaper& rImplWallpaper ) :
+ maColor( rImplWallpaper.maColor )
+{
+ mnRefCount = 1;
+ meStyle = rImplWallpaper.meStyle;
+
+ if ( rImplWallpaper.mpBitmap )
+ mpBitmap = new BitmapEx( *rImplWallpaper.mpBitmap );
+ else
+ mpBitmap = NULL;
+ if( rImplWallpaper.mpCache )
+ mpCache = new BitmapEx( *rImplWallpaper.mpCache );
+ else
+ mpCache = NULL;
+ if ( rImplWallpaper.mpGradient )
+ mpGradient = new Gradient( *rImplWallpaper.mpGradient );
+ else
+ mpGradient = NULL;
+ if ( rImplWallpaper.mpRect )
+ mpRect = new Rectangle( *rImplWallpaper.mpRect );
+ else
+ mpRect = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplWallpaper::~ImplWallpaper()
+{
+ delete mpBitmap;
+ delete mpCache;
+ delete mpGradient;
+ delete mpRect;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWallpaper::ImplSetCachedBitmap( BitmapEx& rBmp )
+{
+ if( !mpCache )
+ mpCache = new BitmapEx( rBmp );
+ else
+ *mpCache = rBmp;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplWallpaper::ImplReleaseCachedBitmap()
+{
+ delete mpCache;
+ mpCache = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, ImplWallpaper& rImplWallpaper )
+{
+ VersionCompat aCompat( rIStm, STREAM_READ );
+ UINT16 nTmp16;
+
+ delete rImplWallpaper.mpRect;
+ rImplWallpaper.mpRect = NULL;
+
+ delete rImplWallpaper.mpGradient;
+ rImplWallpaper.mpGradient = NULL;
+
+ delete rImplWallpaper.mpBitmap;
+ rImplWallpaper.mpBitmap = NULL;
+
+ // version 1
+ rIStm >> rImplWallpaper.maColor;
+ rIStm >> nTmp16; rImplWallpaper.meStyle = (WallpaperStyle) nTmp16;
+
+ // version 2
+ if( aCompat.GetVersion() >= 2 )
+ {
+ BOOL bRect, bGrad, bBmp, bDummy;
+
+ rIStm >> bRect >> bGrad >> bBmp >> bDummy >> bDummy >> bDummy;
+
+ if( bRect )
+ {
+ rImplWallpaper.mpRect = new Rectangle;
+ rIStm >> *rImplWallpaper.mpRect;
+ }
+
+ if( bGrad )
+ {
+ rImplWallpaper.mpGradient = new Gradient;
+ rIStm >> *rImplWallpaper.mpGradient;
+ }
+
+ if( bBmp )
+ {
+ rImplWallpaper.mpBitmap = new BitmapEx;
+ rIStm >> *rImplWallpaper.mpBitmap;
+ }
+
+ // version 3 (new color format)
+ if( aCompat.GetVersion() >= 3 )
+ {
+ rImplWallpaper.maColor.Read( rIStm, TRUE );
+ }
+ }
+
+ return rIStm;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const ImplWallpaper& rImplWallpaper )
+{
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 3 );
+ BOOL bRect = ( rImplWallpaper.mpRect != NULL );
+ BOOL bGrad = ( rImplWallpaper.mpGradient != NULL );
+ BOOL bBmp = ( rImplWallpaper.mpBitmap != NULL );
+ BOOL bDummy = FALSE;
+
+ // version 1
+ rOStm << rImplWallpaper.maColor << (UINT16) rImplWallpaper.meStyle;
+
+ // version 2
+ rOStm << bRect << bGrad << bBmp << bDummy << bDummy << bDummy;
+
+ if( bRect )
+ rOStm << *rImplWallpaper.mpRect;
+
+ if( bGrad )
+ rOStm << *rImplWallpaper.mpGradient;
+
+ if( bBmp )
+ rOStm << *rImplWallpaper.mpBitmap;
+
+ // version 3 (new color format)
+ ( (Color&) rImplWallpaper.maColor ).Write( rOStm, TRUE );
+
+ return rOStm;
+}
+
+// -----------------------------------------------------------------------
+
+inline void Wallpaper::ImplMakeUnique( BOOL bReleaseCache )
+{
+ // Falls noch andere Referenzen bestehen, dann kopieren
+ if ( mpImplWallpaper->mnRefCount != 1 )
+ {
+ if ( mpImplWallpaper->mnRefCount )
+ mpImplWallpaper->mnRefCount--;
+ mpImplWallpaper = new ImplWallpaper( *(mpImplWallpaper) );
+ }
+
+ if( bReleaseCache )
+ mpImplWallpaper->ImplReleaseCachedBitmap();
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper()
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+#ifdef WIN
+ static ImplWallpaper _near aStaticImplWallpaper;
+#else
+ static ImplWallpaper aStaticImplWallpaper;
+#endif
+
+ aStaticImplWallpaper.mnRefCount = 0;
+ mpImplWallpaper = &aStaticImplWallpaper;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Wallpaper& rWallpaper )
+{
+ DBG_CTOR( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+ DBG_ASSERT( rWallpaper.mpImplWallpaper->mnRefCount < 0xFFFE, "Wallpaper: RefCount overflow" );
+
+ // Instance Daten uebernehmen und Referenzcounter erhoehen
+ mpImplWallpaper = rWallpaper.mpImplWallpaper;
+ // RefCount == 0 fuer statische Objekte
+ if ( mpImplWallpaper->mnRefCount )
+ mpImplWallpaper->mnRefCount++;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Color& rColor )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->maColor = rColor;
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const BitmapEx& rBmpEx )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->mpBitmap = new BitmapEx( rBmpEx );
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::Wallpaper( const Gradient& rGradient )
+{
+ DBG_CTOR( Wallpaper, NULL );
+
+ mpImplWallpaper = new ImplWallpaper;
+ mpImplWallpaper->mpGradient = new Gradient( rGradient );
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper::~Wallpaper()
+{
+ DBG_DTOR( Wallpaper, NULL );
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplWallpaper->mnRefCount )
+ {
+ if ( mpImplWallpaper->mnRefCount == 1 )
+ delete mpImplWallpaper;
+ else
+ mpImplWallpaper->mnRefCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetColor( const Color& rColor )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique();
+ mpImplWallpaper->maColor = rColor;
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetStyle( WallpaperStyle eStyle )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique( FALSE );
+ mpImplWallpaper->meStyle = eStyle;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetBitmap( const BitmapEx& rBitmap )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( !rBitmap )
+ {
+ if ( mpImplWallpaper->mpBitmap )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpBitmap;
+ mpImplWallpaper->mpBitmap = NULL;
+ }
+ }
+ else
+ {
+ ImplMakeUnique();
+ if ( mpImplWallpaper->mpBitmap )
+ *(mpImplWallpaper->mpBitmap) = rBitmap;
+ else
+ mpImplWallpaper->mpBitmap = new BitmapEx( rBitmap );
+ }
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetBitmap()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpBitmap )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpBitmap;
+ mpImplWallpaper->mpBitmap = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BitmapEx Wallpaper::GetBitmap() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpBitmap )
+ return *(mpImplWallpaper->mpBitmap);
+ else
+ {
+ BitmapEx aBmp;
+ return aBmp;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetGradient( const Gradient& rGradient )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique();
+
+ if ( mpImplWallpaper->mpGradient )
+ *(mpImplWallpaper->mpGradient) = rGradient;
+ else
+ mpImplWallpaper->mpGradient = new Gradient( rGradient );
+
+ if( WALLPAPER_NULL == mpImplWallpaper->meStyle )
+ mpImplWallpaper->meStyle = WALLPAPER_TILE;
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetGradient()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpGradient )
+ {
+ ImplMakeUnique();
+ delete mpImplWallpaper->mpGradient;
+ mpImplWallpaper->mpGradient = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Gradient Wallpaper::GetGradient() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpGradient )
+ return *(mpImplWallpaper->mpGradient);
+ else
+ {
+ Gradient aGradient;
+ return aGradient;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetRect( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ ImplMakeUnique( FALSE );
+
+ if ( rRect.IsEmpty() )
+ {
+ if ( mpImplWallpaper->mpRect )
+ {
+ delete mpImplWallpaper->mpRect;
+ mpImplWallpaper->mpRect = NULL;
+ }
+ }
+ else
+ {
+ if ( mpImplWallpaper->mpRect )
+ *(mpImplWallpaper->mpRect) = rRect;
+ else
+ mpImplWallpaper->mpRect = new Rectangle( rRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Wallpaper::SetRect()
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpRect )
+ {
+ ImplMakeUnique( FALSE );
+ delete mpImplWallpaper->mpRect;
+ mpImplWallpaper->mpRect = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Wallpaper::GetRect() const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+
+ if ( mpImplWallpaper->mpRect )
+ return *(mpImplWallpaper->mpRect);
+ else
+ {
+ Rectangle aRect;
+ return aRect;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::IsFixed() const
+{
+ if ( mpImplWallpaper->meStyle == WALLPAPER_NULL )
+ return FALSE;
+ else
+ return (!mpImplWallpaper->mpBitmap && !mpImplWallpaper->mpGradient);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::IsScrollable() const
+{
+ if ( mpImplWallpaper->meStyle == WALLPAPER_NULL )
+ return FALSE;
+ else if ( !mpImplWallpaper->mpBitmap && !mpImplWallpaper->mpGradient )
+ return TRUE;
+ else if ( mpImplWallpaper->mpBitmap )
+ return (mpImplWallpaper->meStyle == WALLPAPER_TILE);
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Wallpaper& Wallpaper::operator=( const Wallpaper& rWallpaper )
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+ DBG_ASSERT( rWallpaper.mpImplWallpaper->mnRefCount < 0xFFFE, "Wallpaper: RefCount overflow" );
+
+ // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
+ if ( rWallpaper.mpImplWallpaper->mnRefCount )
+ rWallpaper.mpImplWallpaper->mnRefCount++;
+
+ // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es
+ // die letzte Referenz ist, sonst Referenzcounter decrementieren
+ if ( mpImplWallpaper->mnRefCount )
+ {
+ if ( mpImplWallpaper->mnRefCount == 1 )
+ delete mpImplWallpaper;
+ else
+ mpImplWallpaper->mnRefCount--;
+ }
+
+ mpImplWallpaper = rWallpaper.mpImplWallpaper;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Wallpaper::operator==( const Wallpaper& rWallpaper ) const
+{
+ DBG_CHKTHIS( Wallpaper, NULL );
+ DBG_CHKOBJ( &rWallpaper, Wallpaper, NULL );
+
+ if ( mpImplWallpaper == rWallpaper.mpImplWallpaper )
+ return TRUE;
+
+ if ( ( mpImplWallpaper->meStyle != rWallpaper.mpImplWallpaper->meStyle ) ||
+ ( mpImplWallpaper->maColor != rWallpaper.mpImplWallpaper->maColor ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpRect != rWallpaper.mpImplWallpaper->mpRect
+ && ( !mpImplWallpaper->mpRect
+ || !rWallpaper.mpImplWallpaper->mpRect
+ || *(mpImplWallpaper->mpRect) != *(rWallpaper.mpImplWallpaper->mpRect) ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpBitmap != rWallpaper.mpImplWallpaper->mpBitmap
+ && ( !mpImplWallpaper->mpBitmap
+ || !rWallpaper.mpImplWallpaper->mpBitmap
+ || *(mpImplWallpaper->mpBitmap) != *(rWallpaper.mpImplWallpaper->mpBitmap) ) )
+ return FALSE;
+
+ if ( mpImplWallpaper->mpGradient != rWallpaper.mpImplWallpaper->mpGradient
+ && ( !mpImplWallpaper->mpGradient
+ || !rWallpaper.mpImplWallpaper->mpGradient
+ || *(mpImplWallpaper->mpGradient) != *(rWallpaper.mpImplWallpaper->mpGradient) ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rIStm, Wallpaper& rWallpaper )
+{
+ rWallpaper.ImplMakeUnique();
+ return( rIStm >> *rWallpaper.mpImplWallpaper );
+}
+
+// -----------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rOStm, const Wallpaper& rWallpaper )
+{
+ return( rOStm << *rWallpaper.mpImplWallpaper );
+}