xref: /aoo41x/main/vcl/source/gdi/outdev2.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <tools/debug.hxx>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <vcl/bitmap.hxx>
34*cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
35*cdf0e10cSrcweir #include <vcl/window.hxx>
36*cdf0e10cSrcweir #include <vcl/metaact.hxx>
37*cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
38*cdf0e10cSrcweir #include <vcl/virdev.hxx>
39*cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
40*cdf0e10cSrcweir #include <vcl/outdev.hxx>
41*cdf0e10cSrcweir #include <vcl/window.hxx>
42*cdf0e10cSrcweir #include <vcl/image.hxx>
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir #include <bmpfast.hxx>
45*cdf0e10cSrcweir #include <salbmp.hxx>
46*cdf0e10cSrcweir #include <salgdi.hxx>
47*cdf0e10cSrcweir #include <impbmp.hxx>
48*cdf0e10cSrcweir #include <sallayout.hxx>
49*cdf0e10cSrcweir #include <image.h>
50*cdf0e10cSrcweir #include <outdev.h>
51*cdf0e10cSrcweir #include <window.h>
52*cdf0e10cSrcweir #include <region.h>
53*cdf0e10cSrcweir #include <outdata.hxx>
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir #define BAND_MAX_SIZE 512000
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir // =======================================================================
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir DBG_NAMEEX( OutputDevice )
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir // =======================================================================
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir // -----------
64*cdf0e10cSrcweir // - Defines -
65*cdf0e10cSrcweir // -----------
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir #define OUTDEV_INIT()						\
68*cdf0e10cSrcweir {											\
69*cdf0e10cSrcweir 	if ( !IsDeviceOutputNecessary() )		\
70*cdf0e10cSrcweir 		return; 							\
71*cdf0e10cSrcweir 											\
72*cdf0e10cSrcweir 	if ( !mpGraphics )						\
73*cdf0e10cSrcweir 		if ( !ImplGetGraphics() )			\
74*cdf0e10cSrcweir 			return; 						\
75*cdf0e10cSrcweir 											\
76*cdf0e10cSrcweir 	if ( mbInitClipRegion ) 				\
77*cdf0e10cSrcweir 		ImplInitClipRegion();				\
78*cdf0e10cSrcweir 											\
79*cdf0e10cSrcweir 	if ( mbOutputClipped )					\
80*cdf0e10cSrcweir 		return; 							\
81*cdf0e10cSrcweir }
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir #define TwoRect 	SalTwoRect
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir // -------------
86*cdf0e10cSrcweir // - externals -
87*cdf0e10cSrcweir // -------------
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir extern sal_uLong nVCLRLut[ 6 ];
90*cdf0e10cSrcweir extern sal_uLong nVCLGLut[ 6 ];
91*cdf0e10cSrcweir extern sal_uLong nVCLBLut[ 6 ];
92*cdf0e10cSrcweir extern sal_uLong nVCLDitherLut[ 256 ];
93*cdf0e10cSrcweir extern sal_uLong nVCLLut[ 256 ];
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir // =======================================================================
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir sal_uLong ImplAdjustTwoRect( TwoRect& rTwoRect, const Size& rSizePix )
98*cdf0e10cSrcweir {
99*cdf0e10cSrcweir 	sal_uLong nMirrFlags = 0;
100*cdf0e10cSrcweir 
101*cdf0e10cSrcweir 	if ( rTwoRect.mnDestWidth < 0 )
102*cdf0e10cSrcweir 	{
103*cdf0e10cSrcweir 		rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
104*cdf0e10cSrcweir 		rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
105*cdf0e10cSrcweir 		rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
106*cdf0e10cSrcweir 		nMirrFlags |= BMP_MIRROR_HORZ;
107*cdf0e10cSrcweir 	}
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir 	if ( rTwoRect.mnDestHeight < 0 )
110*cdf0e10cSrcweir 	{
111*cdf0e10cSrcweir 		rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
112*cdf0e10cSrcweir 		rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
113*cdf0e10cSrcweir 		rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
114*cdf0e10cSrcweir 		nMirrFlags |= BMP_MIRROR_VERT;
115*cdf0e10cSrcweir 	}
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir 	if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
118*cdf0e10cSrcweir 		( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
119*cdf0e10cSrcweir 		( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
120*cdf0e10cSrcweir 		( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
121*cdf0e10cSrcweir 	{
122*cdf0e10cSrcweir 		const Rectangle	aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
123*cdf0e10cSrcweir 									 Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
124*cdf0e10cSrcweir 		Rectangle		aCropRect( aSourceRect );
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir 		aCropRect.Intersection( Rectangle( Point(), rSizePix ) );
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir 		if( aCropRect.IsEmpty() )
129*cdf0e10cSrcweir 			rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
130*cdf0e10cSrcweir 		else
131*cdf0e10cSrcweir 		{
132*cdf0e10cSrcweir 			const double	fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
133*cdf0e10cSrcweir 			const double	fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir 			const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
136*cdf0e10cSrcweir 			const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
137*cdf0e10cSrcweir 			const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
138*cdf0e10cSrcweir 			const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir 			rTwoRect.mnSrcX = aCropRect.Left();
141*cdf0e10cSrcweir 			rTwoRect.mnSrcY = aCropRect.Top();
142*cdf0e10cSrcweir 			rTwoRect.mnSrcWidth = aCropRect.GetWidth();
143*cdf0e10cSrcweir 			rTwoRect.mnSrcHeight = aCropRect.GetHeight();
144*cdf0e10cSrcweir 			rTwoRect.mnDestX = nDstX1;
145*cdf0e10cSrcweir 			rTwoRect.mnDestY = nDstY1;
146*cdf0e10cSrcweir 			rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
147*cdf0e10cSrcweir 			rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
148*cdf0e10cSrcweir 		}
149*cdf0e10cSrcweir 	}
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir 	return nMirrFlags;
152*cdf0e10cSrcweir }
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir // =======================================================================
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, void* pVoidPosAry )
157*cdf0e10cSrcweir {
158*cdf0e10cSrcweir 	TwoRect*			pPosAry = (TwoRect*)pVoidPosAry;
159*cdf0e10cSrcweir 	SalGraphics*		pGraphics2;
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir 	if ( pPosAry->mnSrcWidth && pPosAry->mnSrcHeight && pPosAry->mnDestWidth && pPosAry->mnDestHeight )
162*cdf0e10cSrcweir 	{
163*cdf0e10cSrcweir 		if ( this == pSrcDev )
164*cdf0e10cSrcweir 			pGraphics2 = NULL;
165*cdf0e10cSrcweir 		else
166*cdf0e10cSrcweir 		{
167*cdf0e10cSrcweir 			if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
168*cdf0e10cSrcweir 				 (GetOutDevType() != OUTDEV_WINDOW) )
169*cdf0e10cSrcweir 			{
170*cdf0e10cSrcweir 				if ( !pSrcDev->mpGraphics )
171*cdf0e10cSrcweir 				{
172*cdf0e10cSrcweir 					if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
173*cdf0e10cSrcweir 						return;
174*cdf0e10cSrcweir 				}
175*cdf0e10cSrcweir 				pGraphics2 = pSrcDev->mpGraphics;
176*cdf0e10cSrcweir 			}
177*cdf0e10cSrcweir 			else
178*cdf0e10cSrcweir 			{
179*cdf0e10cSrcweir 				if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow )
180*cdf0e10cSrcweir 					pGraphics2 = NULL;
181*cdf0e10cSrcweir 				else
182*cdf0e10cSrcweir 				{
183*cdf0e10cSrcweir 					if ( !pSrcDev->mpGraphics )
184*cdf0e10cSrcweir 					{
185*cdf0e10cSrcweir 						if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
186*cdf0e10cSrcweir 							return;
187*cdf0e10cSrcweir 					}
188*cdf0e10cSrcweir 					pGraphics2 = pSrcDev->mpGraphics;
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir 					if ( !mpGraphics )
191*cdf0e10cSrcweir 					{
192*cdf0e10cSrcweir 						if ( !ImplGetGraphics() )
193*cdf0e10cSrcweir 							return;
194*cdf0e10cSrcweir 					}
195*cdf0e10cSrcweir 					DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
196*cdf0e10cSrcweir 								"OutputDevice::DrawOutDev(): We need more than one Graphics" );
197*cdf0e10cSrcweir 				}
198*cdf0e10cSrcweir 			}
199*cdf0e10cSrcweir 		}
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir         // #102532# Offset only has to be pseudo window offset
202*cdf0e10cSrcweir 		Rectangle	aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
203*cdf0e10cSrcweir 								 Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
204*cdf0e10cSrcweir 		Rectangle	aSrcRect( Point( pPosAry->mnSrcX, pPosAry->mnSrcY ),
205*cdf0e10cSrcweir 							  Size( pPosAry->mnSrcWidth, pPosAry->mnSrcHeight ) );
206*cdf0e10cSrcweir 		const long	nOldRight = aSrcRect.Right();
207*cdf0e10cSrcweir 		const long	nOldBottom = aSrcRect.Bottom();
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir 		if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
210*cdf0e10cSrcweir 		{
211*cdf0e10cSrcweir 			if ( (pPosAry->mnSrcX+pPosAry->mnSrcWidth-1) > aSrcOutRect.Right() )
212*cdf0e10cSrcweir 			{
213*cdf0e10cSrcweir 				const long nOldWidth = pPosAry->mnSrcWidth;
214*cdf0e10cSrcweir 				pPosAry->mnSrcWidth -= (nOldRight - aSrcRect.Right());
215*cdf0e10cSrcweir 				pPosAry->mnDestWidth = pPosAry->mnDestWidth * pPosAry->mnSrcWidth / nOldWidth;
216*cdf0e10cSrcweir 			}
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir 			if ( (pPosAry->mnSrcY+pPosAry->mnSrcHeight-1) > aSrcOutRect.Bottom() )
219*cdf0e10cSrcweir 			{
220*cdf0e10cSrcweir 				const long nOldHeight = pPosAry->mnSrcHeight;
221*cdf0e10cSrcweir 				pPosAry->mnSrcHeight -= (nOldBottom - aSrcRect.Bottom());
222*cdf0e10cSrcweir 				pPosAry->mnDestHeight = pPosAry->mnDestHeight * pPosAry->mnSrcHeight / nOldHeight;
223*cdf0e10cSrcweir 			}
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir             // --- RTL --- if this is no window, but pSrcDev is a window
226*cdf0e10cSrcweir             // mirroring may be required
227*cdf0e10cSrcweir             // because only windows have a SalGraphicsLayout
228*cdf0e10cSrcweir             // mirroring is performed here
229*cdf0e10cSrcweir             if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) )
230*cdf0e10cSrcweir             {
231*cdf0e10cSrcweir 		        SalTwoRect pPosAry2 = *pPosAry;
232*cdf0e10cSrcweir 			    pGraphics2->mirror( pPosAry2.mnSrcX, pPosAry2.mnSrcWidth, pSrcDev );
233*cdf0e10cSrcweir 			    mpGraphics->CopyBits( &pPosAry2, pGraphics2, this, pSrcDev );
234*cdf0e10cSrcweir             }
235*cdf0e10cSrcweir             else
236*cdf0e10cSrcweir 			    mpGraphics->CopyBits( pPosAry, pGraphics2, this, pSrcDev );
237*cdf0e10cSrcweir 		}
238*cdf0e10cSrcweir 	}
239*cdf0e10cSrcweir }
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir // ------------------------------------------------------------------
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
244*cdf0e10cSrcweir 							   const Point& rSrcPt,  const Size& rSrcSize )
245*cdf0e10cSrcweir {
246*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawOutDev()" );
247*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
248*cdf0e10cSrcweir 	DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
251*cdf0e10cSrcweir         return;
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 	if ( meOutDevType == OUTDEV_PRINTER )
254*cdf0e10cSrcweir 		return;
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir 	if ( ROP_INVERT == meRasterOp )
257*cdf0e10cSrcweir 	{
258*cdf0e10cSrcweir 		DrawRect( Rectangle( rDestPt, rDestSize ) );
259*cdf0e10cSrcweir 		return;
260*cdf0e10cSrcweir 	}
261*cdf0e10cSrcweir 
262*cdf0e10cSrcweir 	if ( mpMetaFile )
263*cdf0e10cSrcweir 	{
264*cdf0e10cSrcweir 		const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
265*cdf0e10cSrcweir 		mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
266*cdf0e10cSrcweir 	}
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir 	OUTDEV_INIT();
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir 	TwoRect aPosAry;
271*cdf0e10cSrcweir 	aPosAry.mnSrcWidth	 = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
272*cdf0e10cSrcweir 	aPosAry.mnSrcHeight  = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
273*cdf0e10cSrcweir 	aPosAry.mnDestWidth  = ImplLogicWidthToDevicePixel( rDestSize.Width() );
274*cdf0e10cSrcweir 	aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir 	if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
277*cdf0e10cSrcweir 	{
278*cdf0e10cSrcweir 		aPosAry.mnSrcX		 = ImplLogicXToDevicePixel( rSrcPt.X() );
279*cdf0e10cSrcweir 		aPosAry.mnSrcY		 = ImplLogicYToDevicePixel( rSrcPt.Y() );
280*cdf0e10cSrcweir 		aPosAry.mnDestX 	 = ImplLogicXToDevicePixel( rDestPt.X() );
281*cdf0e10cSrcweir 		aPosAry.mnDestY 	 = ImplLogicYToDevicePixel( rDestPt.Y() );
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir 		Rectangle	aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
284*cdf0e10cSrcweir 								 Size( mnOutWidth, mnOutHeight ) );
285*cdf0e10cSrcweir 		Rectangle	aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
286*cdf0e10cSrcweir 							  Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
287*cdf0e10cSrcweir 		long		nOldRight = aSrcRect.Right();
288*cdf0e10cSrcweir 		long		nOldBottom = aSrcRect.Bottom();
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir 		if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
291*cdf0e10cSrcweir 		{
292*cdf0e10cSrcweir 			if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
293*cdf0e10cSrcweir 			{
294*cdf0e10cSrcweir 				long nOldWidth = aPosAry.mnSrcWidth;
295*cdf0e10cSrcweir 				aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
296*cdf0e10cSrcweir 				aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth;
297*cdf0e10cSrcweir 			}
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir 			if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
300*cdf0e10cSrcweir 			{
301*cdf0e10cSrcweir 				long nOldHeight = aPosAry.mnSrcHeight;
302*cdf0e10cSrcweir 				aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
303*cdf0e10cSrcweir 				aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight;
304*cdf0e10cSrcweir 			}
305*cdf0e10cSrcweir 
306*cdf0e10cSrcweir 			mpGraphics->CopyBits( &aPosAry, NULL, this, NULL );
307*cdf0e10cSrcweir 		}
308*cdf0e10cSrcweir 	}
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir     if( mpAlphaVDev )
311*cdf0e10cSrcweir         mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize );
312*cdf0e10cSrcweir }
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir // ------------------------------------------------------------------
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
317*cdf0e10cSrcweir 							   const Point& rSrcPt,  const Size& rSrcSize,
318*cdf0e10cSrcweir 							   const OutputDevice& rOutDev )
319*cdf0e10cSrcweir {
320*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawOutDev()" );
321*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
322*cdf0e10cSrcweir 	DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice );
323*cdf0e10cSrcweir 	DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
324*cdf0e10cSrcweir 	DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir 	if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) || ImplIsRecordLayout() )
327*cdf0e10cSrcweir 		return;
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir 	if ( ROP_INVERT == meRasterOp )
330*cdf0e10cSrcweir 	{
331*cdf0e10cSrcweir 		DrawRect( Rectangle( rDestPt, rDestSize ) );
332*cdf0e10cSrcweir 		return;
333*cdf0e10cSrcweir 	}
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir 	if ( mpMetaFile )
336*cdf0e10cSrcweir 	{
337*cdf0e10cSrcweir 		const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
338*cdf0e10cSrcweir 		mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
339*cdf0e10cSrcweir 	}
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir 	OUTDEV_INIT();
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir 	TwoRect aPosAry;
344*cdf0e10cSrcweir 	aPosAry.mnSrcX		 = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
345*cdf0e10cSrcweir 	aPosAry.mnSrcY		 = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
346*cdf0e10cSrcweir 	aPosAry.mnSrcWidth	 = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
347*cdf0e10cSrcweir 	aPosAry.mnSrcHeight  = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
348*cdf0e10cSrcweir 	aPosAry.mnDestX 	 = ImplLogicXToDevicePixel( rDestPt.X() );
349*cdf0e10cSrcweir 	aPosAry.mnDestY 	 = ImplLogicYToDevicePixel( rDestPt.Y() );
350*cdf0e10cSrcweir 	aPosAry.mnDestWidth  = ImplLogicWidthToDevicePixel( rDestSize.Width() );
351*cdf0e10cSrcweir 	aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir     if( mpAlphaVDev )
354*cdf0e10cSrcweir     {
355*cdf0e10cSrcweir         if( rOutDev.mpAlphaVDev )
356*cdf0e10cSrcweir         {
357*cdf0e10cSrcweir             // alpha-blend source over destination
358*cdf0e10cSrcweir             DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir             // This would be mode SOURCE:
361*cdf0e10cSrcweir             // copy source alpha channel to our alpha channel
362*cdf0e10cSrcweir             //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev );
363*cdf0e10cSrcweir         }
364*cdf0e10cSrcweir         else
365*cdf0e10cSrcweir         {
366*cdf0e10cSrcweir             ImplDrawOutDevDirect( &rOutDev, &aPosAry );
367*cdf0e10cSrcweir 
368*cdf0e10cSrcweir             // #i32109#: make destination rectangle opaque - source has no alpha
369*cdf0e10cSrcweir             mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
370*cdf0e10cSrcweir         }
371*cdf0e10cSrcweir     }
372*cdf0e10cSrcweir     else
373*cdf0e10cSrcweir     {
374*cdf0e10cSrcweir         if( rOutDev.mpAlphaVDev )
375*cdf0e10cSrcweir         {
376*cdf0e10cSrcweir             // alpha-blend source over destination
377*cdf0e10cSrcweir             DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
378*cdf0e10cSrcweir         }
379*cdf0e10cSrcweir         else
380*cdf0e10cSrcweir         {
381*cdf0e10cSrcweir             // no alpha at all, neither in source nor destination device
382*cdf0e10cSrcweir             ImplDrawOutDevDirect( &rOutDev, &aPosAry );
383*cdf0e10cSrcweir         }
384*cdf0e10cSrcweir     }
385*cdf0e10cSrcweir }
386*cdf0e10cSrcweir 
387*cdf0e10cSrcweir // ------------------------------------------------------------------
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir void OutputDevice::CopyArea( const Point& rDestPt,
390*cdf0e10cSrcweir 							 const Point& rSrcPt,  const Size& rSrcSize,
391*cdf0e10cSrcweir 							 sal_uInt16 nFlags )
392*cdf0e10cSrcweir {
393*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::CopyArea()" );
394*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
395*cdf0e10cSrcweir 	DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir 	if ( meOutDevType == OUTDEV_PRINTER || ImplIsRecordLayout() )
398*cdf0e10cSrcweir 		return;
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir 	RasterOp eOldRop = GetRasterOp();
401*cdf0e10cSrcweir 	SetRasterOp( ROP_OVERPAINT );
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir 	OUTDEV_INIT();
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir 	TwoRect aPosAry;
406*cdf0e10cSrcweir 	aPosAry.mnSrcWidth	 = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
407*cdf0e10cSrcweir 	aPosAry.mnSrcHeight  = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir 	if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
410*cdf0e10cSrcweir 	{
411*cdf0e10cSrcweir 		aPosAry.mnSrcX		 = ImplLogicXToDevicePixel( rSrcPt.X() );
412*cdf0e10cSrcweir 		aPosAry.mnSrcY		 = ImplLogicYToDevicePixel( rSrcPt.Y() );
413*cdf0e10cSrcweir 		aPosAry.mnDestX 	 = ImplLogicXToDevicePixel( rDestPt.X() );
414*cdf0e10cSrcweir 		aPosAry.mnDestY 	 = ImplLogicYToDevicePixel( rDestPt.Y() );
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir 		Rectangle	aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
417*cdf0e10cSrcweir 								 Size( mnOutWidth, mnOutHeight ) );
418*cdf0e10cSrcweir 		Rectangle	aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
419*cdf0e10cSrcweir 							  Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
420*cdf0e10cSrcweir 		long		nOldRight = aSrcRect.Right();
421*cdf0e10cSrcweir 		long		nOldBottom = aSrcRect.Bottom();
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir 		if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
424*cdf0e10cSrcweir 		{
425*cdf0e10cSrcweir 			if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
426*cdf0e10cSrcweir 				aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
427*cdf0e10cSrcweir 
428*cdf0e10cSrcweir 			if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
429*cdf0e10cSrcweir 				aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
430*cdf0e10cSrcweir 
431*cdf0e10cSrcweir 			if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) )
432*cdf0e10cSrcweir 			{
433*cdf0e10cSrcweir 				((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect,
434*cdf0e10cSrcweir 															   aPosAry.mnDestX-aPosAry.mnSrcX,
435*cdf0e10cSrcweir 															   aPosAry.mnDestY-aPosAry.mnSrcY,
436*cdf0e10cSrcweir 															   sal_False );
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir 				mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
439*cdf0e10cSrcweir 									  aPosAry.mnSrcX, aPosAry.mnSrcY,
440*cdf0e10cSrcweir 									  aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
441*cdf0e10cSrcweir 									  SAL_COPYAREA_WINDOWINVALIDATE, this );
442*cdf0e10cSrcweir 			}
443*cdf0e10cSrcweir 			else
444*cdf0e10cSrcweir 			{
445*cdf0e10cSrcweir 				aPosAry.mnDestWidth  = aPosAry.mnSrcWidth;
446*cdf0e10cSrcweir 				aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
447*cdf0e10cSrcweir 				mpGraphics->CopyBits( &aPosAry, NULL, this, NULL );
448*cdf0e10cSrcweir 			}
449*cdf0e10cSrcweir 		}
450*cdf0e10cSrcweir 	}
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir 	SetRasterOp( eOldRop );
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir     if( mpAlphaVDev )
455*cdf0e10cSrcweir         mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags );
456*cdf0e10cSrcweir }
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir // ------------------------------------------------------------------
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
461*cdf0e10cSrcweir 									 const OutputDevice& rOutDev, const Region& rRegion )
462*cdf0e10cSrcweir {
463*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir 	GDIMetaFile*	pOldMetaFile = mpMetaFile;
466*cdf0e10cSrcweir 	sal_Bool			bOldMap = mbMap;
467*cdf0e10cSrcweir 	RasterOp		eOldROP = GetRasterOp();
468*cdf0e10cSrcweir 	mpMetaFile = NULL;
469*cdf0e10cSrcweir 	mbMap = sal_False;
470*cdf0e10cSrcweir 	SetRasterOp( ROP_OVERPAINT );
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir 	if ( !IsDeviceOutputNecessary() )
473*cdf0e10cSrcweir 		return;
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir 	if ( !mpGraphics )
476*cdf0e10cSrcweir 	{
477*cdf0e10cSrcweir 		if ( !ImplGetGraphics() )
478*cdf0e10cSrcweir 			return;
479*cdf0e10cSrcweir 	}
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir 	// ClipRegion zuruecksetzen
482*cdf0e10cSrcweir 	if ( rRegion.IsNull() )
483*cdf0e10cSrcweir 		mpGraphics->ResetClipRegion();
484*cdf0e10cSrcweir 	else
485*cdf0e10cSrcweir 		ImplSelectClipRegion( rRegion );
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir 	TwoRect aPosAry;
488*cdf0e10cSrcweir 	aPosAry.mnSrcX		 = rDevPt.X();
489*cdf0e10cSrcweir 	aPosAry.mnSrcY		 = rDevPt.Y();
490*cdf0e10cSrcweir 	aPosAry.mnSrcWidth	 = rDevSize.Width();
491*cdf0e10cSrcweir 	aPosAry.mnSrcHeight  = rDevSize.Height();
492*cdf0e10cSrcweir 	aPosAry.mnDestX 	 = rPt.X();
493*cdf0e10cSrcweir 	aPosAry.mnDestY 	 = rPt.Y();
494*cdf0e10cSrcweir 	aPosAry.mnDestWidth  = rDevSize.Width();
495*cdf0e10cSrcweir 	aPosAry.mnDestHeight = rDevSize.Height();
496*cdf0e10cSrcweir 	ImplDrawOutDevDirect( &rOutDev, &aPosAry );
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir 	// Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird
499*cdf0e10cSrcweir 	mbInitClipRegion = sal_True;
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 	SetRasterOp( eOldROP );
502*cdf0e10cSrcweir 	mbMap = bOldMap;
503*cdf0e10cSrcweir 	mpMetaFile = pOldMetaFile;
504*cdf0e10cSrcweir }
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir // ------------------------------------------------------------------
507*cdf0e10cSrcweir 
508*cdf0e10cSrcweir void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
509*cdf0e10cSrcweir 									OutputDevice& rDev )
510*cdf0e10cSrcweir {
511*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
512*cdf0e10cSrcweir 
513*cdf0e10cSrcweir 	sal_Bool bOldMap = mbMap;
514*cdf0e10cSrcweir 	mbMap = sal_False;
515*cdf0e10cSrcweir 	rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
516*cdf0e10cSrcweir 	mbMap = bOldMap;
517*cdf0e10cSrcweir }
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir // ------------------------------------------------------------------
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
522*cdf0e10cSrcweir {
523*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmap()" );
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
526*cdf0e10cSrcweir         return;
527*cdf0e10cSrcweir 
528*cdf0e10cSrcweir 	const Size aSizePix( rBitmap.GetSizePixel() );
529*cdf0e10cSrcweir 	ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
530*cdf0e10cSrcweir 
531*cdf0e10cSrcweir     if( mpAlphaVDev )
532*cdf0e10cSrcweir     {
533*cdf0e10cSrcweir         // #i32109#: Make bitmap area opaque
534*cdf0e10cSrcweir         mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) );
535*cdf0e10cSrcweir     }
536*cdf0e10cSrcweir }
537*cdf0e10cSrcweir 
538*cdf0e10cSrcweir // ------------------------------------------------------------------
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
541*cdf0e10cSrcweir {
542*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmap( Size )" );
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
545*cdf0e10cSrcweir         return;
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir 	ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
548*cdf0e10cSrcweir 
549*cdf0e10cSrcweir     if( mpAlphaVDev )
550*cdf0e10cSrcweir     {
551*cdf0e10cSrcweir         // #i32109#: Make bitmap area opaque
552*cdf0e10cSrcweir         mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
553*cdf0e10cSrcweir     }
554*cdf0e10cSrcweir }
555*cdf0e10cSrcweir 
556*cdf0e10cSrcweir // ------------------------------------------------------------------
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
559*cdf0e10cSrcweir 							   const Point& rSrcPtPixel, const Size& rSrcSizePixel,
560*cdf0e10cSrcweir 							   const Bitmap& rBitmap )
561*cdf0e10cSrcweir {
562*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
565*cdf0e10cSrcweir         return;
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir 	ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
568*cdf0e10cSrcweir 
569*cdf0e10cSrcweir     if( mpAlphaVDev )
570*cdf0e10cSrcweir     {
571*cdf0e10cSrcweir         // #i32109#: Make bitmap area opaque
572*cdf0e10cSrcweir         mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
573*cdf0e10cSrcweir     }
574*cdf0e10cSrcweir }
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir // -----------------------------------------------------------------------------
577*cdf0e10cSrcweir 
578*cdf0e10cSrcweir void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
579*cdf0e10cSrcweir 								   const Point& rSrcPtPixel, const Size& rSrcSizePixel,
580*cdf0e10cSrcweir 								   const Bitmap& rBitmap, const sal_uLong nAction )
581*cdf0e10cSrcweir {
582*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir 	Bitmap aBmp( rBitmap );
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir 	if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
587*cdf0e10cSrcweir 		return;
588*cdf0e10cSrcweir 	else if ( ROP_INVERT == meRasterOp )
589*cdf0e10cSrcweir 	{
590*cdf0e10cSrcweir 		DrawRect( Rectangle( rDestPt, rDestSize ) );
591*cdf0e10cSrcweir 		return;
592*cdf0e10cSrcweir 	}
593*cdf0e10cSrcweir 	else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
594*cdf0e10cSrcweir 							 DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
595*cdf0e10cSrcweir 	{
596*cdf0e10cSrcweir 		if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
597*cdf0e10cSrcweir 		{
598*cdf0e10cSrcweir 			sal_uInt8 cCmpVal;
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
601*cdf0e10cSrcweir 				cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
602*cdf0e10cSrcweir 			else
603*cdf0e10cSrcweir 				cCmpVal = 255;
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir 			Color aCol( cCmpVal, cCmpVal, cCmpVal );
606*cdf0e10cSrcweir 			Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
607*cdf0e10cSrcweir 			SetLineColor( aCol );
608*cdf0e10cSrcweir 			SetFillColor( aCol );
609*cdf0e10cSrcweir 			DrawRect( Rectangle( rDestPt, rDestSize ) );
610*cdf0e10cSrcweir 			Pop();
611*cdf0e10cSrcweir 			return;
612*cdf0e10cSrcweir 		}
613*cdf0e10cSrcweir 		else if( !!aBmp )
614*cdf0e10cSrcweir 		{
615*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
616*cdf0e10cSrcweir 				aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
617*cdf0e10cSrcweir 
618*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
619*cdf0e10cSrcweir 				aBmp.Convert( BMP_CONVERSION_GHOSTED );
620*cdf0e10cSrcweir 		}
621*cdf0e10cSrcweir 	}
622*cdf0e10cSrcweir 
623*cdf0e10cSrcweir 	if ( mpMetaFile )
624*cdf0e10cSrcweir 	{
625*cdf0e10cSrcweir 		switch( nAction )
626*cdf0e10cSrcweir 		{
627*cdf0e10cSrcweir 			case( META_BMP_ACTION ):
628*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
629*cdf0e10cSrcweir 			break;
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir 			case( META_BMPSCALE_ACTION ):
632*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
633*cdf0e10cSrcweir 			break;
634*cdf0e10cSrcweir 
635*cdf0e10cSrcweir 			case( META_BMPSCALEPART_ACTION ):
636*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpScalePartAction(
637*cdf0e10cSrcweir 					rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
638*cdf0e10cSrcweir 			break;
639*cdf0e10cSrcweir 		}
640*cdf0e10cSrcweir 	}
641*cdf0e10cSrcweir 
642*cdf0e10cSrcweir 	OUTDEV_INIT();
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir 	if( !aBmp.IsEmpty() )
645*cdf0e10cSrcweir 	{
646*cdf0e10cSrcweir 		TwoRect aPosAry;
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir 		aPosAry.mnSrcX = rSrcPtPixel.X();
649*cdf0e10cSrcweir 		aPosAry.mnSrcY = rSrcPtPixel.Y();
650*cdf0e10cSrcweir 		aPosAry.mnSrcWidth = rSrcSizePixel.Width();
651*cdf0e10cSrcweir 		aPosAry.mnSrcHeight = rSrcSizePixel.Height();
652*cdf0e10cSrcweir 		aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
653*cdf0e10cSrcweir 		aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
654*cdf0e10cSrcweir 		aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
655*cdf0e10cSrcweir 		aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
656*cdf0e10cSrcweir 
657*cdf0e10cSrcweir 		const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir 		if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
660*cdf0e10cSrcweir 		{
661*cdf0e10cSrcweir 			if ( nMirrFlags )
662*cdf0e10cSrcweir 				aBmp.Mirror( nMirrFlags );
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir             /* #i75264# (corrected with #i81576#)
665*cdf0e10cSrcweir             * sometimes a bitmap is scaled to a ridiculous size and drawn
666*cdf0e10cSrcweir             * to a quite normal VDev, so only a very small part of
667*cdf0e10cSrcweir             * the scaled bitmap will be visible. However actually scaling
668*cdf0e10cSrcweir             * the bitmap will use so much memory that we end with a crash.
669*cdf0e10cSrcweir             * Workaround: since only a small part of the scaled bitmap will
670*cdf0e10cSrcweir             * be actually drawn anyway (because of clipping on the device
671*cdf0e10cSrcweir             * boundary), limit the destination and source rectangles so
672*cdf0e10cSrcweir             * that the destination rectangle will overlap the device but only
673*cdf0e10cSrcweir             * be reasonably (say factor 2) larger than the device itself.
674*cdf0e10cSrcweir             */
675*cdf0e10cSrcweir             if( aPosAry.mnDestWidth > 2048 || aPosAry.mnDestHeight > 2048 )
676*cdf0e10cSrcweir             {
677*cdf0e10cSrcweir                  if( meOutDevType == OUTDEV_WINDOW ||
678*cdf0e10cSrcweir                      (meOutDevType == OUTDEV_VIRDEV && mpPDFWriter == 0 ) )
679*cdf0e10cSrcweir                 {
680*cdf0e10cSrcweir                     // #i81576# do the following trick only if there is overlap at all
681*cdf0e10cSrcweir                     // else the formulae don't work
682*cdf0e10cSrcweir                     // theoretically in this case we wouldn't need to draw the bitmap at all
683*cdf0e10cSrcweir                     // however there are some esoteric case where that is needed
684*cdf0e10cSrcweir                     if( aPosAry.mnDestX + aPosAry.mnDestWidth >= 0
685*cdf0e10cSrcweir                         && aPosAry.mnDestX < mnOutWidth
686*cdf0e10cSrcweir                         && aPosAry.mnDestY + aPosAry.mnDestHeight >= 0
687*cdf0e10cSrcweir                         && aPosAry.mnDestY < mnOutHeight )
688*cdf0e10cSrcweir                     {
689*cdf0e10cSrcweir                         // reduce scaling to something reasonable taking into account the output size
690*cdf0e10cSrcweir                         if( aPosAry.mnDestWidth > 3*mnOutWidth && aPosAry.mnSrcWidth )
691*cdf0e10cSrcweir                         {
692*cdf0e10cSrcweir                             const double nScaleX = aPosAry.mnDestWidth/double(aPosAry.mnSrcWidth);
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir                             if( aPosAry.mnDestX + aPosAry.mnDestWidth > mnOutWidth )
695*cdf0e10cSrcweir                             {
696*cdf0e10cSrcweir                                 aPosAry.mnDestWidth = Max(long(0),mnOutWidth-aPosAry.mnDestX);
697*cdf0e10cSrcweir                             }
698*cdf0e10cSrcweir                             if( aPosAry.mnDestX < 0 )
699*cdf0e10cSrcweir                             {
700*cdf0e10cSrcweir                                 aPosAry.mnDestWidth += aPosAry.mnDestX;
701*cdf0e10cSrcweir                                 aPosAry.mnSrcX -= sal::static_int_cast<long>(aPosAry.mnDestX / nScaleX);
702*cdf0e10cSrcweir                                 aPosAry.mnDestX = 0;
703*cdf0e10cSrcweir                             }
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir                             aPosAry.mnSrcWidth = sal::static_int_cast<long>(aPosAry.mnDestWidth / nScaleX);
706*cdf0e10cSrcweir                         }
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir                         if( aPosAry.mnDestHeight > 3*mnOutHeight && aPosAry.mnSrcHeight != 0 )
709*cdf0e10cSrcweir                         {
710*cdf0e10cSrcweir                             const double nScaleY = aPosAry.mnDestHeight/double(aPosAry.mnSrcHeight);
711*cdf0e10cSrcweir 
712*cdf0e10cSrcweir                             if( aPosAry.mnDestY + aPosAry.mnDestHeight > mnOutHeight )
713*cdf0e10cSrcweir                             {
714*cdf0e10cSrcweir                                 aPosAry.mnDestHeight = Max(long(0),mnOutHeight-aPosAry.mnDestY);
715*cdf0e10cSrcweir                             }
716*cdf0e10cSrcweir                             if( aPosAry.mnDestY < 0 )
717*cdf0e10cSrcweir                             {
718*cdf0e10cSrcweir                                 aPosAry.mnDestHeight += aPosAry.mnDestY;
719*cdf0e10cSrcweir                                 aPosAry.mnSrcY -= sal::static_int_cast<long>(aPosAry.mnDestY / nScaleY);
720*cdf0e10cSrcweir                                 aPosAry.mnDestY = 0;
721*cdf0e10cSrcweir                             }
722*cdf0e10cSrcweir 
723*cdf0e10cSrcweir                             aPosAry.mnSrcHeight = sal::static_int_cast<long>(aPosAry.mnDestHeight / nScaleY);
724*cdf0e10cSrcweir                         }
725*cdf0e10cSrcweir                     }
726*cdf0e10cSrcweir                 }
727*cdf0e10cSrcweir             }
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir             if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
730*cdf0e10cSrcweir                 mpGraphics->DrawBitmap( &aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
731*cdf0e10cSrcweir 		}
732*cdf0e10cSrcweir 	}
733*cdf0e10cSrcweir }
734*cdf0e10cSrcweir 
735*cdf0e10cSrcweir // ------------------------------------------------------------------
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt,
738*cdf0e10cSrcweir 								 const BitmapEx& rBitmapEx )
739*cdf0e10cSrcweir {
740*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmapEx()" );
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
743*cdf0e10cSrcweir         return;
744*cdf0e10cSrcweir 
745*cdf0e10cSrcweir 	if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
746*cdf0e10cSrcweir 		DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
747*cdf0e10cSrcweir 	else
748*cdf0e10cSrcweir 	{
749*cdf0e10cSrcweir 		const Size aSizePix( rBitmapEx.GetSizePixel() );
750*cdf0e10cSrcweir 		ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
751*cdf0e10cSrcweir 	}
752*cdf0e10cSrcweir }
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir // ------------------------------------------------------------------
755*cdf0e10cSrcweir 
756*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
757*cdf0e10cSrcweir 								 const BitmapEx& rBitmapEx )
758*cdf0e10cSrcweir {
759*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
762*cdf0e10cSrcweir         return;
763*cdf0e10cSrcweir 
764*cdf0e10cSrcweir 	if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
765*cdf0e10cSrcweir 		DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
766*cdf0e10cSrcweir 	else
767*cdf0e10cSrcweir 		ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
768*cdf0e10cSrcweir }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir // ------------------------------------------------------------------
771*cdf0e10cSrcweir 
772*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
773*cdf0e10cSrcweir 								 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
774*cdf0e10cSrcweir 								 const BitmapEx& rBitmapEx )
775*cdf0e10cSrcweir {
776*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
777*cdf0e10cSrcweir 
778*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
779*cdf0e10cSrcweir         return;
780*cdf0e10cSrcweir 
781*cdf0e10cSrcweir 	if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
782*cdf0e10cSrcweir 		DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
783*cdf0e10cSrcweir 	else
784*cdf0e10cSrcweir 		ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
785*cdf0e10cSrcweir }
786*cdf0e10cSrcweir 
787*cdf0e10cSrcweir // ------------------------------------------------------------------
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
790*cdf0e10cSrcweir 									 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
791*cdf0e10cSrcweir 									 const BitmapEx& rBitmapEx, const sal_uLong nAction )
792*cdf0e10cSrcweir {
793*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
794*cdf0e10cSrcweir 
795*cdf0e10cSrcweir 	BitmapEx aBmpEx( rBitmapEx );
796*cdf0e10cSrcweir 
797*cdf0e10cSrcweir 	if ( mnDrawMode & DRAWMODE_NOBITMAP )
798*cdf0e10cSrcweir 		return;
799*cdf0e10cSrcweir 	else if ( ROP_INVERT == meRasterOp )
800*cdf0e10cSrcweir 	{
801*cdf0e10cSrcweir 		DrawRect( Rectangle( rDestPt, rDestSize ) );
802*cdf0e10cSrcweir 		return;
803*cdf0e10cSrcweir 	}
804*cdf0e10cSrcweir 	else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
805*cdf0e10cSrcweir 							 DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
806*cdf0e10cSrcweir 	{
807*cdf0e10cSrcweir 		if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
808*cdf0e10cSrcweir 		{
809*cdf0e10cSrcweir 			Bitmap	aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
810*cdf0e10cSrcweir 			sal_uInt8	cCmpVal;
811*cdf0e10cSrcweir 
812*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
813*cdf0e10cSrcweir 				cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
814*cdf0e10cSrcweir 			else
815*cdf0e10cSrcweir 				cCmpVal = 255;
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir 			aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
818*cdf0e10cSrcweir 
819*cdf0e10cSrcweir 			if( aBmpEx.IsAlpha() )
820*cdf0e10cSrcweir             {
821*cdf0e10cSrcweir                 // Create one-bit mask out of alpha channel, by
822*cdf0e10cSrcweir                 // thresholding it at alpha=0.5. As
823*cdf0e10cSrcweir                 // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
824*cdf0e10cSrcweir                 // output, having alpha-induced grey levels is not
825*cdf0e10cSrcweir                 // acceptable.
826*cdf0e10cSrcweir                 Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() );
827*cdf0e10cSrcweir                 aMask.MakeMono( 128 );
828*cdf0e10cSrcweir 				aBmpEx = BitmapEx( aColorBmp, aMask );
829*cdf0e10cSrcweir             }
830*cdf0e10cSrcweir 			else
831*cdf0e10cSrcweir             {
832*cdf0e10cSrcweir 				aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
833*cdf0e10cSrcweir             }
834*cdf0e10cSrcweir 		}
835*cdf0e10cSrcweir 		else if( !!aBmpEx )
836*cdf0e10cSrcweir 		{
837*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
838*cdf0e10cSrcweir 				aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
839*cdf0e10cSrcweir 
840*cdf0e10cSrcweir 			if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
841*cdf0e10cSrcweir 				aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
842*cdf0e10cSrcweir 		}
843*cdf0e10cSrcweir 	}
844*cdf0e10cSrcweir 
845*cdf0e10cSrcweir 	if ( mpMetaFile )
846*cdf0e10cSrcweir 	{
847*cdf0e10cSrcweir 		switch( nAction )
848*cdf0e10cSrcweir 		{
849*cdf0e10cSrcweir 			case( META_BMPEX_ACTION ):
850*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
851*cdf0e10cSrcweir 			break;
852*cdf0e10cSrcweir 
853*cdf0e10cSrcweir 			case( META_BMPEXSCALE_ACTION ):
854*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
855*cdf0e10cSrcweir 			break;
856*cdf0e10cSrcweir 
857*cdf0e10cSrcweir 			case( META_BMPEXSCALEPART_ACTION ):
858*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
859*cdf0e10cSrcweir 																	 rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
860*cdf0e10cSrcweir 			break;
861*cdf0e10cSrcweir 		}
862*cdf0e10cSrcweir 	}
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir 	OUTDEV_INIT();
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir 	if( OUTDEV_PRINTER == meOutDevType )
867*cdf0e10cSrcweir 	{
868*cdf0e10cSrcweir         if( aBmpEx.IsAlpha() )
869*cdf0e10cSrcweir         {
870*cdf0e10cSrcweir             // #107169# For true alpha bitmaps, no longer masking the
871*cdf0e10cSrcweir             // bitmap, but perform a full alpha blend against a white
872*cdf0e10cSrcweir             // background here.
873*cdf0e10cSrcweir             Bitmap aBmp( aBmpEx.GetBitmap() );
874*cdf0e10cSrcweir             aBmp.Blend( aBmpEx.GetAlpha(), Color( COL_WHITE) );
875*cdf0e10cSrcweir             DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp );
876*cdf0e10cSrcweir         }
877*cdf0e10cSrcweir         else
878*cdf0e10cSrcweir         {
879*cdf0e10cSrcweir             Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() );
880*cdf0e10cSrcweir             aBmp.Replace( aMask, Color( COL_WHITE ) );
881*cdf0e10cSrcweir             ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
882*cdf0e10cSrcweir         }
883*cdf0e10cSrcweir 	    return;
884*cdf0e10cSrcweir 	}
885*cdf0e10cSrcweir 	else if( aBmpEx.IsAlpha() )
886*cdf0e10cSrcweir 	{
887*cdf0e10cSrcweir 		ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
888*cdf0e10cSrcweir 		return;
889*cdf0e10cSrcweir 	}
890*cdf0e10cSrcweir 
891*cdf0e10cSrcweir 	if( !( !aBmpEx ) )
892*cdf0e10cSrcweir 	{
893*cdf0e10cSrcweir 		TwoRect aPosAry;
894*cdf0e10cSrcweir 
895*cdf0e10cSrcweir 		aPosAry.mnSrcX = rSrcPtPixel.X();
896*cdf0e10cSrcweir 		aPosAry.mnSrcY = rSrcPtPixel.Y();
897*cdf0e10cSrcweir 		aPosAry.mnSrcWidth = rSrcSizePixel.Width();
898*cdf0e10cSrcweir 		aPosAry.mnSrcHeight = rSrcSizePixel.Height();
899*cdf0e10cSrcweir 		aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
900*cdf0e10cSrcweir 		aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
901*cdf0e10cSrcweir 		aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
902*cdf0e10cSrcweir 		aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
903*cdf0e10cSrcweir 
904*cdf0e10cSrcweir 		const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() );
905*cdf0e10cSrcweir 
906*cdf0e10cSrcweir 		if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
907*cdf0e10cSrcweir 		{
908*cdf0e10cSrcweir 
909*cdf0e10cSrcweir 			if( nMirrFlags )
910*cdf0e10cSrcweir 				aBmpEx.Mirror( nMirrFlags );
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir 			const ImpBitmap* pImpBmp = aBmpEx.ImplGetBitmapImpBitmap();
913*cdf0e10cSrcweir 			const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap();
914*cdf0e10cSrcweir 
915*cdf0e10cSrcweir 			if ( pMaskBmp )
916*cdf0e10cSrcweir             {
917*cdf0e10cSrcweir                 // #4919452# reduce operation area to bounds of
918*cdf0e10cSrcweir                 // cliprect. since masked transparency involves
919*cdf0e10cSrcweir                 // creation of a large vdev and copying the screen
920*cdf0e10cSrcweir                 // content into that (slooow read from framebuffer),
921*cdf0e10cSrcweir                 // that should considerably increase performance for
922*cdf0e10cSrcweir                 // large bitmaps and small clippings.
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir                 // Note that this optimisation is a workaround for a
925*cdf0e10cSrcweir                 // Writer peculiarity, namely, to decompose background
926*cdf0e10cSrcweir                 // graphics into myriads of disjunct, tiny
927*cdf0e10cSrcweir                 // rectangles. That otherwise kills us here, since for
928*cdf0e10cSrcweir                 // transparent output, SAL always prepares the whole
929*cdf0e10cSrcweir                 // bitmap, if aPosAry contains the whole bitmap (and
930*cdf0e10cSrcweir                 // it's _not_ to blame for that).
931*cdf0e10cSrcweir 
932*cdf0e10cSrcweir                 // Note the call to ImplPixelToDevicePixel(), since
933*cdf0e10cSrcweir                 // aPosAry already contains the mnOutOff-offsets, they
934*cdf0e10cSrcweir                 // also have to be applied to the region
935*cdf0e10cSrcweir                 Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir                 // TODO: Also respect scaling (that's a bit tricky,
938*cdf0e10cSrcweir                 // since the source points have to move fractional
939*cdf0e10cSrcweir                 // amounts (which is not possible, thus has to be
940*cdf0e10cSrcweir                 // emulated by increases copy area)
941*cdf0e10cSrcweir                 // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
942*cdf0e10cSrcweir                 // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir                 // for now, only identity scales allowed
945*cdf0e10cSrcweir                 if( !aClipRegionBounds.IsEmpty() &&
946*cdf0e10cSrcweir                     aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
947*cdf0e10cSrcweir                     aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
948*cdf0e10cSrcweir                 {
949*cdf0e10cSrcweir                     // now intersect dest rect with clip region
950*cdf0e10cSrcweir                     aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
951*cdf0e10cSrcweir                                                                aPosAry.mnDestY,
952*cdf0e10cSrcweir                                                                aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
953*cdf0e10cSrcweir                                                                aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
954*cdf0e10cSrcweir 
955*cdf0e10cSrcweir                     // Note: I could theoretically optimize away the
956*cdf0e10cSrcweir                     // DrawBitmap below, if the region is empty
957*cdf0e10cSrcweir                     // here. Unfortunately, cannot rule out that
958*cdf0e10cSrcweir                     // somebody relies on the side effects.
959*cdf0e10cSrcweir                     if( !aClipRegionBounds.IsEmpty() )
960*cdf0e10cSrcweir                     {
961*cdf0e10cSrcweir                         aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
962*cdf0e10cSrcweir                         aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
963*cdf0e10cSrcweir                         aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
964*cdf0e10cSrcweir                         aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir                         aPosAry.mnDestX = aClipRegionBounds.Left();
967*cdf0e10cSrcweir                         aPosAry.mnDestY = aClipRegionBounds.Top();
968*cdf0e10cSrcweir                         aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
969*cdf0e10cSrcweir                         aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
970*cdf0e10cSrcweir                     }
971*cdf0e10cSrcweir                 }
972*cdf0e10cSrcweir 
973*cdf0e10cSrcweir 				mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
974*cdf0e10cSrcweir                                         *pMaskBmp->ImplGetSalBitmap(),
975*cdf0e10cSrcweir                                         this );
976*cdf0e10cSrcweir 
977*cdf0e10cSrcweir                 // #110958# Paint mask to alpha channel. Luckily, the
978*cdf0e10cSrcweir                 // black and white representation of the mask maps to
979*cdf0e10cSrcweir                 // the alpha channel
980*cdf0e10cSrcweir 
981*cdf0e10cSrcweir                 // #i25167# Restrict mask painting to _opaque_ areas
982*cdf0e10cSrcweir                 // of the mask, otherwise we spoil areas where no
983*cdf0e10cSrcweir                 // bitmap content was ever visible. Interestingly
984*cdf0e10cSrcweir                 // enough, this can be achieved by taking the mask as
985*cdf0e10cSrcweir                 // the transparency mask of itself
986*cdf0e10cSrcweir                 if( mpAlphaVDev )
987*cdf0e10cSrcweir                     mpAlphaVDev->DrawBitmapEx( rDestPt,
988*cdf0e10cSrcweir                                                rDestSize,
989*cdf0e10cSrcweir                                                BitmapEx( aBmpEx.GetMask(),
990*cdf0e10cSrcweir                                                          aBmpEx.GetMask() ) );
991*cdf0e10cSrcweir             }
992*cdf0e10cSrcweir 			else
993*cdf0e10cSrcweir             {
994*cdf0e10cSrcweir 				mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), this );
995*cdf0e10cSrcweir 
996*cdf0e10cSrcweir                 if( mpAlphaVDev )
997*cdf0e10cSrcweir                 {
998*cdf0e10cSrcweir                     // #i32109#: Make bitmap area opaque
999*cdf0e10cSrcweir                     mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
1000*cdf0e10cSrcweir                 }
1001*cdf0e10cSrcweir             }
1002*cdf0e10cSrcweir 		}
1003*cdf0e10cSrcweir 	}
1004*cdf0e10cSrcweir }
1005*cdf0e10cSrcweir 
1006*cdf0e10cSrcweir // ------------------------------------------------------------------
1007*cdf0e10cSrcweir 
1008*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt,
1009*cdf0e10cSrcweir 							 const Bitmap& rBitmap, const Color& rMaskColor )
1010*cdf0e10cSrcweir {
1011*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawMask()" );
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
1014*cdf0e10cSrcweir         return;
1015*cdf0e10cSrcweir 
1016*cdf0e10cSrcweir 	const Size aSizePix( rBitmap.GetSizePixel() );
1017*cdf0e10cSrcweir 	ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
1018*cdf0e10cSrcweir 
1019*cdf0e10cSrcweir     if( mpAlphaVDev )
1020*cdf0e10cSrcweir     {
1021*cdf0e10cSrcweir         const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir         // #i25167# Restrict mask painting to _opaque_ areas
1024*cdf0e10cSrcweir         // of the mask, otherwise we spoil areas where no
1025*cdf0e10cSrcweir         // bitmap content was ever visible. Interestingly
1026*cdf0e10cSrcweir         // enough, this can be achieved by taking the mask as
1027*cdf0e10cSrcweir         // the transparency mask of itself
1028*cdf0e10cSrcweir         mpAlphaVDev->DrawBitmapEx( rDestPt,
1029*cdf0e10cSrcweir                                    PixelToLogic( aSizePix ),
1030*cdf0e10cSrcweir                                    BitmapEx( rMask, rMask ) );
1031*cdf0e10cSrcweir     }
1032*cdf0e10cSrcweir }
1033*cdf0e10cSrcweir 
1034*cdf0e10cSrcweir // ------------------------------------------------------------------
1035*cdf0e10cSrcweir 
1036*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1037*cdf0e10cSrcweir 							 const Bitmap& rBitmap, const Color& rMaskColor )
1038*cdf0e10cSrcweir {
1039*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawMask( Size )" );
1040*cdf0e10cSrcweir 
1041*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
1042*cdf0e10cSrcweir         return;
1043*cdf0e10cSrcweir 
1044*cdf0e10cSrcweir 	ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
1045*cdf0e10cSrcweir 
1046*cdf0e10cSrcweir     // TODO: Use mask here
1047*cdf0e10cSrcweir     if( mpAlphaVDev )
1048*cdf0e10cSrcweir     {
1049*cdf0e10cSrcweir         const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1050*cdf0e10cSrcweir 
1051*cdf0e10cSrcweir         // #i25167# Restrict mask painting to _opaque_ areas
1052*cdf0e10cSrcweir         // of the mask, otherwise we spoil areas where no
1053*cdf0e10cSrcweir         // bitmap content was ever visible. Interestingly
1054*cdf0e10cSrcweir         // enough, this can be achieved by taking the mask as
1055*cdf0e10cSrcweir         // the transparency mask of itself
1056*cdf0e10cSrcweir         mpAlphaVDev->DrawBitmapEx( rDestPt,
1057*cdf0e10cSrcweir                                    rDestSize,
1058*cdf0e10cSrcweir                                    BitmapEx( rMask, rMask ) );
1059*cdf0e10cSrcweir     }
1060*cdf0e10cSrcweir }
1061*cdf0e10cSrcweir 
1062*cdf0e10cSrcweir // ------------------------------------------------------------------
1063*cdf0e10cSrcweir 
1064*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1065*cdf0e10cSrcweir 							 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1066*cdf0e10cSrcweir 							 const Bitmap& rBitmap, const Color& rMaskColor )
1067*cdf0e10cSrcweir {
1068*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" );
1069*cdf0e10cSrcweir 
1070*cdf0e10cSrcweir     if( ImplIsRecordLayout() )
1071*cdf0e10cSrcweir         return;
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir 	ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION );
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir     // TODO: Use mask here
1076*cdf0e10cSrcweir     if( mpAlphaVDev )
1077*cdf0e10cSrcweir     {
1078*cdf0e10cSrcweir         const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1079*cdf0e10cSrcweir 
1080*cdf0e10cSrcweir         // #i25167# Restrict mask painting to _opaque_ areas
1081*cdf0e10cSrcweir         // of the mask, otherwise we spoil areas where no
1082*cdf0e10cSrcweir         // bitmap content was ever visible. Interestingly
1083*cdf0e10cSrcweir         // enough, this can be achieved by taking the mask as
1084*cdf0e10cSrcweir         // the transparency mask of itself
1085*cdf0e10cSrcweir         mpAlphaVDev->DrawBitmapEx( rDestPt,
1086*cdf0e10cSrcweir                                    rDestSize,
1087*cdf0e10cSrcweir                                    rSrcPtPixel,
1088*cdf0e10cSrcweir                                    rSrcSizePixel,
1089*cdf0e10cSrcweir                                    BitmapEx( rMask, rMask ) );
1090*cdf0e10cSrcweir     }
1091*cdf0e10cSrcweir }
1092*cdf0e10cSrcweir 
1093*cdf0e10cSrcweir // ------------------------------------------------------------------
1094*cdf0e10cSrcweir 
1095*cdf0e10cSrcweir void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize,
1096*cdf0e10cSrcweir 								 const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1097*cdf0e10cSrcweir 								 const Bitmap& rBitmap, const Color& rMaskColor,
1098*cdf0e10cSrcweir 								 const sal_uLong nAction )
1099*cdf0e10cSrcweir {
1100*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1101*cdf0e10cSrcweir 
1102*cdf0e10cSrcweir 	if( ROP_INVERT == meRasterOp )
1103*cdf0e10cSrcweir 	{
1104*cdf0e10cSrcweir 		DrawRect( Rectangle( rDestPt, rDestSize ) );
1105*cdf0e10cSrcweir 		return;
1106*cdf0e10cSrcweir 	}
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir 	if ( mpMetaFile )
1109*cdf0e10cSrcweir 	{
1110*cdf0e10cSrcweir 		switch( nAction )
1111*cdf0e10cSrcweir 		{
1112*cdf0e10cSrcweir 			case( META_MASK_ACTION ):
1113*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
1114*cdf0e10cSrcweir 					rBitmap, rMaskColor ) );
1115*cdf0e10cSrcweir 			break;
1116*cdf0e10cSrcweir 
1117*cdf0e10cSrcweir 			case( META_MASKSCALE_ACTION ):
1118*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
1119*cdf0e10cSrcweir 					rDestSize, rBitmap, rMaskColor ) );
1120*cdf0e10cSrcweir 			break;
1121*cdf0e10cSrcweir 
1122*cdf0e10cSrcweir 			case( META_MASKSCALEPART_ACTION ):
1123*cdf0e10cSrcweir 				mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
1124*cdf0e10cSrcweir 					rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
1125*cdf0e10cSrcweir 			break;
1126*cdf0e10cSrcweir 		}
1127*cdf0e10cSrcweir 	}
1128*cdf0e10cSrcweir 
1129*cdf0e10cSrcweir 	OUTDEV_INIT();
1130*cdf0e10cSrcweir 
1131*cdf0e10cSrcweir 	if ( OUTDEV_PRINTER == meOutDevType )
1132*cdf0e10cSrcweir 	{
1133*cdf0e10cSrcweir 		ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
1134*cdf0e10cSrcweir 		return;
1135*cdf0e10cSrcweir 	}
1136*cdf0e10cSrcweir 
1137*cdf0e10cSrcweir 	const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
1138*cdf0e10cSrcweir 	if ( pImpBmp )
1139*cdf0e10cSrcweir 	{
1140*cdf0e10cSrcweir 		TwoRect aPosAry;
1141*cdf0e10cSrcweir 
1142*cdf0e10cSrcweir 		aPosAry.mnSrcX = rSrcPtPixel.X();
1143*cdf0e10cSrcweir 		aPosAry.mnSrcY = rSrcPtPixel.Y();
1144*cdf0e10cSrcweir 		aPosAry.mnSrcWidth = rSrcSizePixel.Width();
1145*cdf0e10cSrcweir 		aPosAry.mnSrcHeight = rSrcSizePixel.Height();
1146*cdf0e10cSrcweir 		aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
1147*cdf0e10cSrcweir 		aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
1148*cdf0e10cSrcweir 		aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
1149*cdf0e10cSrcweir 		aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
1150*cdf0e10cSrcweir 
1151*cdf0e10cSrcweir 		// spiegeln via Koordinaten wollen wir nicht
1152*cdf0e10cSrcweir 		const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
1153*cdf0e10cSrcweir 
1154*cdf0e10cSrcweir 		// check if output is necessary
1155*cdf0e10cSrcweir 		if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
1156*cdf0e10cSrcweir 		{
1157*cdf0e10cSrcweir 
1158*cdf0e10cSrcweir 			if( nMirrFlags )
1159*cdf0e10cSrcweir 			{
1160*cdf0e10cSrcweir 				Bitmap aTmp( rBitmap );
1161*cdf0e10cSrcweir 				aTmp.Mirror( nMirrFlags );
1162*cdf0e10cSrcweir 				mpGraphics->DrawMask( &aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
1163*cdf0e10cSrcweir 									  ImplColorToSal( rMaskColor ) , this);
1164*cdf0e10cSrcweir 			}
1165*cdf0e10cSrcweir 			else
1166*cdf0e10cSrcweir 				mpGraphics->DrawMask( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
1167*cdf0e10cSrcweir 									  ImplColorToSal( rMaskColor ), this );
1168*cdf0e10cSrcweir 
1169*cdf0e10cSrcweir 		}
1170*cdf0e10cSrcweir 	}
1171*cdf0e10cSrcweir }
1172*cdf0e10cSrcweir 
1173*cdf0e10cSrcweir // ------------------------------------------------------------------
1174*cdf0e10cSrcweir 
1175*cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle )
1176*cdf0e10cSrcweir {
1177*cdf0e10cSrcweir 	DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1178*cdf0e10cSrcweir 
1179*cdf0e10cSrcweir 	if( !rImage.mpImplData || ImplIsRecordLayout() )
1180*cdf0e10cSrcweir 		return;
1181*cdf0e10cSrcweir 
1182*cdf0e10cSrcweir 	switch( rImage.mpImplData->meType )
1183*cdf0e10cSrcweir 	{
1184*cdf0e10cSrcweir 		case IMAGETYPE_BITMAP:
1185*cdf0e10cSrcweir 			DrawBitmap( rPos, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) );
1186*cdf0e10cSrcweir 		break;
1187*cdf0e10cSrcweir 
1188*cdf0e10cSrcweir 		case IMAGETYPE_IMAGE:
1189*cdf0e10cSrcweir 		{
1190*cdf0e10cSrcweir 			ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1191*cdf0e10cSrcweir 
1192*cdf0e10cSrcweir 			if( !pData->mpImageBitmap )
1193*cdf0e10cSrcweir 			{
1194*cdf0e10cSrcweir 				const Size aSize( pData->maBmpEx.GetSizePixel() );
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir 				pData->mpImageBitmap = new ImplImageBmp;
1197*cdf0e10cSrcweir 				pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1198*cdf0e10cSrcweir 			}
1199*cdf0e10cSrcweir 
1200*cdf0e10cSrcweir 			pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
1201*cdf0e10cSrcweir 		}
1202*cdf0e10cSrcweir 		break;
1203*cdf0e10cSrcweir 
1204*cdf0e10cSrcweir 		default:
1205*cdf0e10cSrcweir 		break;
1206*cdf0e10cSrcweir 	}
1207*cdf0e10cSrcweir }
1208*cdf0e10cSrcweir 
1209*cdf0e10cSrcweir // ------------------------------------------------------------------
1210*cdf0e10cSrcweir 
1211*cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
1212*cdf0e10cSrcweir 							  const Image& rImage, sal_uInt16 nStyle )
1213*cdf0e10cSrcweir {
1214*cdf0e10cSrcweir 	DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1215*cdf0e10cSrcweir 
1216*cdf0e10cSrcweir 	if( rImage.mpImplData && !ImplIsRecordLayout() )
1217*cdf0e10cSrcweir 	{
1218*cdf0e10cSrcweir 		switch( rImage.mpImplData->meType )
1219*cdf0e10cSrcweir 		{
1220*cdf0e10cSrcweir 			case IMAGETYPE_BITMAP:
1221*cdf0e10cSrcweir 				DrawBitmap( rPos, rSize, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) );
1222*cdf0e10cSrcweir 			break;
1223*cdf0e10cSrcweir 
1224*cdf0e10cSrcweir 			case IMAGETYPE_IMAGE:
1225*cdf0e10cSrcweir 			{
1226*cdf0e10cSrcweir 				ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1227*cdf0e10cSrcweir 
1228*cdf0e10cSrcweir 				if ( !pData->mpImageBitmap )
1229*cdf0e10cSrcweir 				{
1230*cdf0e10cSrcweir 					const Size aSize( pData->maBmpEx.GetSizePixel() );
1231*cdf0e10cSrcweir 
1232*cdf0e10cSrcweir 					pData->mpImageBitmap = new ImplImageBmp;
1233*cdf0e10cSrcweir 					pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1234*cdf0e10cSrcweir 				}
1235*cdf0e10cSrcweir 
1236*cdf0e10cSrcweir 				pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
1237*cdf0e10cSrcweir 			}
1238*cdf0e10cSrcweir 			break;
1239*cdf0e10cSrcweir 
1240*cdf0e10cSrcweir 			default:
1241*cdf0e10cSrcweir 			break;
1242*cdf0e10cSrcweir 		}
1243*cdf0e10cSrcweir 	}
1244*cdf0e10cSrcweir }
1245*cdf0e10cSrcweir 
1246*cdf0e10cSrcweir // ------------------------------------------------------------------
1247*cdf0e10cSrcweir 
1248*cdf0e10cSrcweir Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
1249*cdf0e10cSrcweir {
1250*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir 	Bitmap	aBmp;
1253*cdf0e10cSrcweir 	long	nX = ImplLogicXToDevicePixel( rSrcPt.X() );
1254*cdf0e10cSrcweir 	long	nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
1255*cdf0e10cSrcweir 	long	nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
1256*cdf0e10cSrcweir 	long	nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
1257*cdf0e10cSrcweir 
1258*cdf0e10cSrcweir 	if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
1259*cdf0e10cSrcweir 	{
1260*cdf0e10cSrcweir 		if ( nWidth && nHeight )
1261*cdf0e10cSrcweir 		{
1262*cdf0e10cSrcweir 			Rectangle	aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
1263*cdf0e10cSrcweir 			sal_Bool		bClipped = sal_False;
1264*cdf0e10cSrcweir 
1265*cdf0e10cSrcweir 			// X-Koordinate ausserhalb des Bereichs?
1266*cdf0e10cSrcweir 			if ( nX < mnOutOffX )
1267*cdf0e10cSrcweir 			{
1268*cdf0e10cSrcweir 				nWidth -= ( mnOutOffX - nX );
1269*cdf0e10cSrcweir 				nX = mnOutOffX;
1270*cdf0e10cSrcweir 				bClipped = sal_True;
1271*cdf0e10cSrcweir 			}
1272*cdf0e10cSrcweir 
1273*cdf0e10cSrcweir 			// Y-Koordinate ausserhalb des Bereichs?
1274*cdf0e10cSrcweir 			if ( nY < mnOutOffY )
1275*cdf0e10cSrcweir 			{
1276*cdf0e10cSrcweir 				nHeight -= ( mnOutOffY - nY );
1277*cdf0e10cSrcweir 				nY = mnOutOffY;
1278*cdf0e10cSrcweir 				bClipped = sal_True;
1279*cdf0e10cSrcweir 			}
1280*cdf0e10cSrcweir 
1281*cdf0e10cSrcweir 			// Breite ausserhalb des Bereichs?
1282*cdf0e10cSrcweir 			if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
1283*cdf0e10cSrcweir 			{
1284*cdf0e10cSrcweir 				nWidth	= mnOutOffX + mnOutWidth - nX;
1285*cdf0e10cSrcweir 				bClipped = sal_True;
1286*cdf0e10cSrcweir 			}
1287*cdf0e10cSrcweir 
1288*cdf0e10cSrcweir 			// Hoehe ausserhalb des Bereichs?
1289*cdf0e10cSrcweir 			if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
1290*cdf0e10cSrcweir 			{
1291*cdf0e10cSrcweir 				nHeight = mnOutOffY + mnOutHeight - nY;
1292*cdf0e10cSrcweir 				bClipped = sal_True;
1293*cdf0e10cSrcweir 			}
1294*cdf0e10cSrcweir 
1295*cdf0e10cSrcweir 			if ( bClipped )
1296*cdf0e10cSrcweir 			{
1297*cdf0e10cSrcweir 				// Falls auf den sichtbaren Bereich geclipped wurde,
1298*cdf0e10cSrcweir 				// muessen wir eine Bitmap in der rchtigen Groesse
1299*cdf0e10cSrcweir 				// erzeugen, in die die geclippte Bitmap an die angepasste
1300*cdf0e10cSrcweir 				// Position kopiert wird
1301*cdf0e10cSrcweir 				VirtualDevice aVDev( *this );
1302*cdf0e10cSrcweir 
1303*cdf0e10cSrcweir 				if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
1304*cdf0e10cSrcweir 				{
1305*cdf0e10cSrcweir 					if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
1306*cdf0e10cSrcweir 					{
1307*cdf0e10cSrcweir 						TwoRect aPosAry;
1308*cdf0e10cSrcweir 
1309*cdf0e10cSrcweir 						aPosAry.mnSrcX = nX;
1310*cdf0e10cSrcweir 						aPosAry.mnSrcY = nY;
1311*cdf0e10cSrcweir 						aPosAry.mnSrcWidth = nWidth;
1312*cdf0e10cSrcweir 						aPosAry.mnSrcHeight = nHeight;
1313*cdf0e10cSrcweir 						aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
1314*cdf0e10cSrcweir 						aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
1315*cdf0e10cSrcweir 						aPosAry.mnDestWidth = nWidth;
1316*cdf0e10cSrcweir 						aPosAry.mnDestHeight = nHeight;
1317*cdf0e10cSrcweir 
1318*cdf0e10cSrcweir 						if ( (nWidth > 0) && (nHeight > 0) )
1319*cdf0e10cSrcweir 							(((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( &aPosAry, mpGraphics, this, this );
1320*cdf0e10cSrcweir 
1321*cdf0e10cSrcweir 						aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
1322*cdf0e10cSrcweir 					 }
1323*cdf0e10cSrcweir 					 else
1324*cdf0e10cSrcweir 						bClipped = sal_False;
1325*cdf0e10cSrcweir 				}
1326*cdf0e10cSrcweir 				else
1327*cdf0e10cSrcweir 					bClipped = sal_False;
1328*cdf0e10cSrcweir 			}
1329*cdf0e10cSrcweir 
1330*cdf0e10cSrcweir 			if ( !bClipped )
1331*cdf0e10cSrcweir 			{
1332*cdf0e10cSrcweir 				SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
1333*cdf0e10cSrcweir 
1334*cdf0e10cSrcweir 				if( pSalBmp )
1335*cdf0e10cSrcweir 				{
1336*cdf0e10cSrcweir 					ImpBitmap* pImpBmp = new ImpBitmap;
1337*cdf0e10cSrcweir 					pImpBmp->ImplSetSalBitmap( pSalBmp );
1338*cdf0e10cSrcweir 					aBmp.ImplSetImpBitmap( pImpBmp );
1339*cdf0e10cSrcweir 				}
1340*cdf0e10cSrcweir 			}
1341*cdf0e10cSrcweir 		}
1342*cdf0e10cSrcweir 	}
1343*cdf0e10cSrcweir 
1344*cdf0e10cSrcweir 	return aBmp;
1345*cdf0e10cSrcweir }
1346*cdf0e10cSrcweir 
1347*cdf0e10cSrcweir // ------------------------------------------------------------------
1348*cdf0e10cSrcweir 
1349*cdf0e10cSrcweir BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
1350*cdf0e10cSrcweir {
1351*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1352*cdf0e10cSrcweir 
1353*cdf0e10cSrcweir     // #110958# Extract alpha value from VDev, if any
1354*cdf0e10cSrcweir     if( mpAlphaVDev )
1355*cdf0e10cSrcweir     {
1356*cdf0e10cSrcweir         Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
1357*cdf0e10cSrcweir 
1358*cdf0e10cSrcweir         // ensure 8 bit alpha
1359*cdf0e10cSrcweir         if( aAlphaBitmap.GetBitCount() > 8 )
1360*cdf0e10cSrcweir             aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
1361*cdf0e10cSrcweir 
1362*cdf0e10cSrcweir         return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
1363*cdf0e10cSrcweir     }
1364*cdf0e10cSrcweir     else
1365*cdf0e10cSrcweir         return GetBitmap( rSrcPt, rSize );
1366*cdf0e10cSrcweir }
1367*cdf0e10cSrcweir 
1368*cdf0e10cSrcweir // ------------------------------------------------------------------
1369*cdf0e10cSrcweir 
1370*cdf0e10cSrcweir void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize,
1371*cdf0e10cSrcweir 									   Bitmap& rBitmap ) const
1372*cdf0e10cSrcweir {
1373*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1374*cdf0e10cSrcweir 
1375*cdf0e10cSrcweir 	sal_Bool bOldMap = mbMap;
1376*cdf0e10cSrcweir 	((OutputDevice*)this)->mbMap = sal_False;
1377*cdf0e10cSrcweir 	rBitmap = GetBitmap( rDestPt, rSize );
1378*cdf0e10cSrcweir 	((OutputDevice*)this)->mbMap = bOldMap;
1379*cdf0e10cSrcweir }
1380*cdf0e10cSrcweir 
1381*cdf0e10cSrcweir // ------------------------------------------------------------------
1382*cdf0e10cSrcweir 
1383*cdf0e10cSrcweir Color OutputDevice::GetPixel( const Point& rPt ) const
1384*cdf0e10cSrcweir {
1385*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1386*cdf0e10cSrcweir 
1387*cdf0e10cSrcweir 	Color aColor;
1388*cdf0e10cSrcweir 
1389*cdf0e10cSrcweir 	if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
1390*cdf0e10cSrcweir 	{
1391*cdf0e10cSrcweir 		if ( mbInitClipRegion )
1392*cdf0e10cSrcweir 			((OutputDevice*)this)->ImplInitClipRegion();
1393*cdf0e10cSrcweir 
1394*cdf0e10cSrcweir 		if ( !mbOutputClipped )
1395*cdf0e10cSrcweir 		{
1396*cdf0e10cSrcweir 			const long		nX = ImplLogicXToDevicePixel( rPt.X() );
1397*cdf0e10cSrcweir 			const long		nY = ImplLogicYToDevicePixel( rPt.Y() );
1398*cdf0e10cSrcweir 			const SalColor	aSalCol = mpGraphics->GetPixel( nX, nY, this );
1399*cdf0e10cSrcweir 			aColor.SetRed( SALCOLOR_RED( aSalCol ) );
1400*cdf0e10cSrcweir 			aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
1401*cdf0e10cSrcweir 			aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
1402*cdf0e10cSrcweir 		}
1403*cdf0e10cSrcweir 	}
1404*cdf0e10cSrcweir 	return aColor;
1405*cdf0e10cSrcweir }
1406*cdf0e10cSrcweir 
1407*cdf0e10cSrcweir // ------------------------------------------------------------------
1408*cdf0e10cSrcweir 
1409*cdf0e10cSrcweir Color* OutputDevice::GetPixel( const Polygon& rPts ) const
1410*cdf0e10cSrcweir {
1411*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1412*cdf0e10cSrcweir 
1413*cdf0e10cSrcweir 	Color*			pColors = NULL;
1414*cdf0e10cSrcweir 	const sal_uInt16	nSize = rPts.GetSize();
1415*cdf0e10cSrcweir 
1416*cdf0e10cSrcweir 	if( nSize )
1417*cdf0e10cSrcweir 	{
1418*cdf0e10cSrcweir 		if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
1419*cdf0e10cSrcweir 		{
1420*cdf0e10cSrcweir 			if ( mbInitClipRegion )
1421*cdf0e10cSrcweir 				((OutputDevice*)this)->ImplInitClipRegion();
1422*cdf0e10cSrcweir 
1423*cdf0e10cSrcweir 			if ( !mbOutputClipped )
1424*cdf0e10cSrcweir 			{
1425*cdf0e10cSrcweir 				pColors = new Color[ nSize ];
1426*cdf0e10cSrcweir 
1427*cdf0e10cSrcweir 				for( sal_uInt16 i = 0; i < nSize; i++ )
1428*cdf0e10cSrcweir 				{
1429*cdf0e10cSrcweir 					Color&			rCol = pColors[ i ];
1430*cdf0e10cSrcweir 					const Point&	rPt = rPts[ i ];
1431*cdf0e10cSrcweir 					const SalColor	aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ),
1432*cdf0e10cSrcweir 																   ImplLogicYToDevicePixel( rPt.Y() ) , this) );
1433*cdf0e10cSrcweir 
1434*cdf0e10cSrcweir 					rCol.SetRed( SALCOLOR_RED( aSalCol ) );
1435*cdf0e10cSrcweir 					rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) );
1436*cdf0e10cSrcweir 					rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) );
1437*cdf0e10cSrcweir 				}
1438*cdf0e10cSrcweir 			}
1439*cdf0e10cSrcweir 		}
1440*cdf0e10cSrcweir 	}
1441*cdf0e10cSrcweir 
1442*cdf0e10cSrcweir 	return pColors;
1443*cdf0e10cSrcweir }
1444*cdf0e10cSrcweir 
1445*cdf0e10cSrcweir // -----------------------------------------------------------------------
1446*cdf0e10cSrcweir 
1447*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt )
1448*cdf0e10cSrcweir {
1449*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawPixel()" );
1450*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1451*cdf0e10cSrcweir 
1452*cdf0e10cSrcweir 	if ( mpMetaFile )
1453*cdf0e10cSrcweir 		mpMetaFile->AddAction( new MetaPointAction( rPt ) );
1454*cdf0e10cSrcweir 
1455*cdf0e10cSrcweir 	if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
1456*cdf0e10cSrcweir 		return;
1457*cdf0e10cSrcweir 
1458*cdf0e10cSrcweir 	Point aPt = ImplLogicToDevicePixel( rPt );
1459*cdf0e10cSrcweir 
1460*cdf0e10cSrcweir 	// we need a graphics
1461*cdf0e10cSrcweir 	if ( !mpGraphics )
1462*cdf0e10cSrcweir 	{
1463*cdf0e10cSrcweir 		if ( !ImplGetGraphics() )
1464*cdf0e10cSrcweir 			return;
1465*cdf0e10cSrcweir 	}
1466*cdf0e10cSrcweir 
1467*cdf0e10cSrcweir 	if ( mbInitClipRegion )
1468*cdf0e10cSrcweir 		ImplInitClipRegion();
1469*cdf0e10cSrcweir 	if ( mbOutputClipped )
1470*cdf0e10cSrcweir 		return;
1471*cdf0e10cSrcweir 
1472*cdf0e10cSrcweir 	if ( mbInitLineColor )
1473*cdf0e10cSrcweir 		ImplInitLineColor();
1474*cdf0e10cSrcweir 
1475*cdf0e10cSrcweir 	mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this );
1476*cdf0e10cSrcweir 
1477*cdf0e10cSrcweir     if( mpAlphaVDev )
1478*cdf0e10cSrcweir         mpAlphaVDev->DrawPixel( rPt );
1479*cdf0e10cSrcweir }
1480*cdf0e10cSrcweir 
1481*cdf0e10cSrcweir // -----------------------------------------------------------------------
1482*cdf0e10cSrcweir 
1483*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
1484*cdf0e10cSrcweir {
1485*cdf0e10cSrcweir 	DBG_TRACE( "OutputDevice::DrawPixel()" );
1486*cdf0e10cSrcweir 	DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1487*cdf0e10cSrcweir 
1488*cdf0e10cSrcweir 	Color aColor( rColor );
1489*cdf0e10cSrcweir 
1490*cdf0e10cSrcweir 	if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
1491*cdf0e10cSrcweir 					   DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE |
1492*cdf0e10cSrcweir                        DRAWMODE_SETTINGSLINE ) )
1493*cdf0e10cSrcweir 	{
1494*cdf0e10cSrcweir 		if( !ImplIsColorTransparent( aColor ) )
1495*cdf0e10cSrcweir 		{
1496*cdf0e10cSrcweir 			if( mnDrawMode & DRAWMODE_BLACKLINE )
1497*cdf0e10cSrcweir 			{
1498*cdf0e10cSrcweir 				aColor = Color( COL_BLACK );
1499*cdf0e10cSrcweir 			}
1500*cdf0e10cSrcweir 			else if( mnDrawMode & DRAWMODE_WHITELINE )
1501*cdf0e10cSrcweir 			{
1502*cdf0e10cSrcweir 				aColor = Color( COL_WHITE );
1503*cdf0e10cSrcweir 			}
1504*cdf0e10cSrcweir 			else if( mnDrawMode & DRAWMODE_GRAYLINE )
1505*cdf0e10cSrcweir 			{
1506*cdf0e10cSrcweir 				const sal_uInt8 cLum = aColor.GetLuminance();
1507*cdf0e10cSrcweir 				aColor = Color( cLum, cLum, cLum );
1508*cdf0e10cSrcweir 			}
1509*cdf0e10cSrcweir             else if( mnDrawMode & DRAWMODE_SETTINGSLINE )
1510*cdf0e10cSrcweir             {
1511*cdf0e10cSrcweir                 aColor = GetSettings().GetStyleSettings().GetFontColor();
1512*cdf0e10cSrcweir             }
1513*cdf0e10cSrcweir 
1514*cdf0e10cSrcweir 			if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
1515*cdf0e10cSrcweir 			{
1516*cdf0e10cSrcweir 				aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
1517*cdf0e10cSrcweir 								( aColor.GetGreen() >> 1 ) | 0x80,
1518*cdf0e10cSrcweir 								( aColor.GetBlue() >> 1 ) | 0x80 );
1519*cdf0e10cSrcweir 			}
1520*cdf0e10cSrcweir 		}
1521*cdf0e10cSrcweir 	}
1522*cdf0e10cSrcweir 
1523*cdf0e10cSrcweir 	if ( mpMetaFile )
1524*cdf0e10cSrcweir 		mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
1525*cdf0e10cSrcweir 
1526*cdf0e10cSrcweir 	if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() )
1527*cdf0e10cSrcweir 		return;
1528*cdf0e10cSrcweir 
1529*cdf0e10cSrcweir 	Point aPt = ImplLogicToDevicePixel( rPt );
1530*cdf0e10cSrcweir 
1531*cdf0e10cSrcweir 	// we need a graphics
1532*cdf0e10cSrcweir 	if ( !mpGraphics )
1533*cdf0e10cSrcweir 	{
1534*cdf0e10cSrcweir 		if ( !ImplGetGraphics() )
1535*cdf0e10cSrcweir 			return;
1536*cdf0e10cSrcweir 	}
1537*cdf0e10cSrcweir 
1538*cdf0e10cSrcweir 	if ( mbInitClipRegion )
1539*cdf0e10cSrcweir 		ImplInitClipRegion();
1540*cdf0e10cSrcweir 	if ( mbOutputClipped )
1541*cdf0e10cSrcweir 		return;
1542*cdf0e10cSrcweir 
1543*cdf0e10cSrcweir 	mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this );
1544*cdf0e10cSrcweir 
1545*cdf0e10cSrcweir     if( mpAlphaVDev )
1546*cdf0e10cSrcweir         mpAlphaVDev->DrawPixel( rPt );
1547*cdf0e10cSrcweir }
1548*cdf0e10cSrcweir 
1549*cdf0e10cSrcweir // -----------------------------------------------------------------------
1550*cdf0e10cSrcweir 
1551*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
1552*cdf0e10cSrcweir {
1553*cdf0e10cSrcweir 	if ( !pColors )
1554*cdf0e10cSrcweir 		DrawPixel( rPts, GetLineColor() );
1555*cdf0e10cSrcweir 	else
1556*cdf0e10cSrcweir 	{
1557*cdf0e10cSrcweir 		DBG_TRACE( "OutputDevice::DrawPixel()" );
1558*cdf0e10cSrcweir 		DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1559*cdf0e10cSrcweir 		DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
1560*cdf0e10cSrcweir 
1561*cdf0e10cSrcweir 		const sal_uInt16 nSize = rPts.GetSize();
1562*cdf0e10cSrcweir 
1563*cdf0e10cSrcweir 		if ( nSize )
1564*cdf0e10cSrcweir 		{
1565*cdf0e10cSrcweir 			if ( mpMetaFile )
1566*cdf0e10cSrcweir 				for ( sal_uInt16 i = 0; i < nSize; i++ )
1567*cdf0e10cSrcweir 					mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
1568*cdf0e10cSrcweir 
1569*cdf0e10cSrcweir 			if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1570*cdf0e10cSrcweir 				return;
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir 			// we need a graphics
1573*cdf0e10cSrcweir 			if ( mpGraphics || ImplGetGraphics() )
1574*cdf0e10cSrcweir 			{
1575*cdf0e10cSrcweir 				if ( mbInitClipRegion )
1576*cdf0e10cSrcweir 					ImplInitClipRegion();
1577*cdf0e10cSrcweir 
1578*cdf0e10cSrcweir 				if ( mbOutputClipped )
1579*cdf0e10cSrcweir 					return;
1580*cdf0e10cSrcweir 
1581*cdf0e10cSrcweir 				for ( sal_uInt16 i = 0; i < nSize; i++ )
1582*cdf0e10cSrcweir 				{
1583*cdf0e10cSrcweir 					const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
1584*cdf0e10cSrcweir 					mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this );
1585*cdf0e10cSrcweir 				}
1586*cdf0e10cSrcweir 			}
1587*cdf0e10cSrcweir 		}
1588*cdf0e10cSrcweir 	}
1589*cdf0e10cSrcweir 
1590*cdf0e10cSrcweir     if( mpAlphaVDev )
1591*cdf0e10cSrcweir         mpAlphaVDev->DrawPixel( rPts, pColors );
1592*cdf0e10cSrcweir }
1593*cdf0e10cSrcweir 
1594*cdf0e10cSrcweir // -----------------------------------------------------------------------
1595*cdf0e10cSrcweir 
1596*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
1597*cdf0e10cSrcweir {
1598*cdf0e10cSrcweir 	if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() )
1599*cdf0e10cSrcweir 	{
1600*cdf0e10cSrcweir 		const sal_uInt16	nSize = rPts.GetSize();
1601*cdf0e10cSrcweir 		Color*			pColArray = new Color[ nSize ];
1602*cdf0e10cSrcweir 
1603*cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < nSize; i++ )
1604*cdf0e10cSrcweir 			pColArray[ i ] = rColor;
1605*cdf0e10cSrcweir 
1606*cdf0e10cSrcweir 		DrawPixel( rPts, pColArray );
1607*cdf0e10cSrcweir 		delete[] pColArray;
1608*cdf0e10cSrcweir 	}
1609*cdf0e10cSrcweir 
1610*cdf0e10cSrcweir     if( mpAlphaVDev )
1611*cdf0e10cSrcweir         mpAlphaVDev->DrawPixel( rPts, rColor );
1612*cdf0e10cSrcweir }
1613*cdf0e10cSrcweir 
1614*cdf0e10cSrcweir // ------------------------------------------------------------------------
1615*cdf0e10cSrcweir 
1616*cdf0e10cSrcweir namespace
1617*cdf0e10cSrcweir {
1618*cdf0e10cSrcweir     sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceOpaq, const sal_uInt8 nDestColor )
1619*cdf0e10cSrcweir     {
1620*cdf0e10cSrcweir         int c = ( (int)nDestColor * ( 255 - nSourceOpaq ) )
1621*cdf0e10cSrcweir             +     (int)nSourceOpaq * (int)nSourceColor;
1622*cdf0e10cSrcweir         return sal_uInt8( c / 255 );
1623*cdf0e10cSrcweir     }
1624*cdf0e10cSrcweir }
1625*cdf0e10cSrcweir 
1626*cdf0e10cSrcweir // ------------------------------------------------------------------------
1627*cdf0e10cSrcweir 
1628*cdf0e10cSrcweir Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap              aBmp,
1629*cdf0e10cSrcweir                                          BitmapReadAccess*	 pP,
1630*cdf0e10cSrcweir                                          BitmapReadAccess*	 pA,
1631*cdf0e10cSrcweir                                          const Rectangle&    aDstRect,
1632*cdf0e10cSrcweir                                          const sal_Int32     nOffY,
1633*cdf0e10cSrcweir                                          const sal_Int32     nDstHeight,
1634*cdf0e10cSrcweir                                          const sal_Int32     nOffX,
1635*cdf0e10cSrcweir                                          const sal_Int32     nDstWidth,
1636*cdf0e10cSrcweir                                          const long*         pMapX,
1637*cdf0e10cSrcweir                                          const long*         pMapY )
1638*cdf0e10cSrcweir {
1639*cdf0e10cSrcweir     BitmapColor aDstCol,aSrcCol;
1640*cdf0e10cSrcweir     Bitmap      res;
1641*cdf0e10cSrcweir     int         nX, nOutX, nY, nOutY;
1642*cdf0e10cSrcweir 
1643*cdf0e10cSrcweir     OSL_ENSURE(mpAlphaVDev,
1644*cdf0e10cSrcweir                "ImplBlendWithAlpha(): call me only with valid alpha VDev!" );
1645*cdf0e10cSrcweir 
1646*cdf0e10cSrcweir     sal_Bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
1647*cdf0e10cSrcweir     mpAlphaVDev->EnableMapMode(sal_False);
1648*cdf0e10cSrcweir 
1649*cdf0e10cSrcweir     Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
1650*cdf0e10cSrcweir     BitmapWriteAccess*	pAlphaW = aAlphaBitmap.AcquireWriteAccess();
1651*cdf0e10cSrcweir 
1652*cdf0e10cSrcweir     if( GetBitCount() <= 8 )
1653*cdf0e10cSrcweir     {
1654*cdf0e10cSrcweir         Bitmap				aDither( aBmp.GetSizePixel(), 8 );
1655*cdf0e10cSrcweir         BitmapColor 		aIndex( 0 );
1656*cdf0e10cSrcweir         BitmapReadAccess*	pB = aBmp.AcquireReadAccess();
1657*cdf0e10cSrcweir         BitmapWriteAccess*	pW = aDither.AcquireWriteAccess();
1658*cdf0e10cSrcweir 
1659*cdf0e10cSrcweir         if( pB && pP && pA && pW && pAlphaW )
1660*cdf0e10cSrcweir         {
1661*cdf0e10cSrcweir             for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1662*cdf0e10cSrcweir             {
1663*cdf0e10cSrcweir                 const long nMapY = pMapY[ nY ];
1664*cdf0e10cSrcweir                 const long nModY = ( nOutY & 0x0FL ) << 4L;
1665*cdf0e10cSrcweir 
1666*cdf0e10cSrcweir                 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1667*cdf0e10cSrcweir                 {
1668*cdf0e10cSrcweir                     const long	nMapX = pMapX[ nX ];
1669*cdf0e10cSrcweir                     const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
1670*cdf0e10cSrcweir 
1671*cdf0e10cSrcweir                     aSrcCol = pP->GetColor( nMapY, nMapX );
1672*cdf0e10cSrcweir                     aDstCol = pB->GetColor( nY, nX );
1673*cdf0e10cSrcweir                     const sal_uInt8 nSrcOpaq = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex();
1674*cdf0e10cSrcweir                     const sal_uInt8 nDstOpaq  = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex();
1675*cdf0e10cSrcweir 
1676*cdf0e10cSrcweir                     aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) );
1677*cdf0e10cSrcweir                     aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) );
1678*cdf0e10cSrcweir                     aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) );
1679*cdf0e10cSrcweir 
1680*cdf0e10cSrcweir                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
1681*cdf0e10cSrcweir                                               nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
1682*cdf0e10cSrcweir                                               nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
1683*cdf0e10cSrcweir                     pW->SetPixel( nY, nX, aIndex );
1684*cdf0e10cSrcweir 
1685*cdf0e10cSrcweir                     // Have to perform the compositing 'algebra' in
1686*cdf0e10cSrcweir                     // the inverse alpha space (with 255 meaning
1687*cdf0e10cSrcweir                     // opaque), otherwise, transitivity is not
1688*cdf0e10cSrcweir                     // achieved.
1689*cdf0e10cSrcweir                     const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq );
1690*cdf0e10cSrcweir 
1691*cdf0e10cSrcweir                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] +
1692*cdf0e10cSrcweir                                               nVCLGLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] +
1693*cdf0e10cSrcweir                                               nVCLBLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] ) );
1694*cdf0e10cSrcweir                     pAlphaW->SetPixel( nY, nX, aIndex );
1695*cdf0e10cSrcweir                 }
1696*cdf0e10cSrcweir             }
1697*cdf0e10cSrcweir         }
1698*cdf0e10cSrcweir 
1699*cdf0e10cSrcweir         aBmp.ReleaseAccess( pB );
1700*cdf0e10cSrcweir         aDither.ReleaseAccess( pW );
1701*cdf0e10cSrcweir         res = aDither;
1702*cdf0e10cSrcweir     }
1703*cdf0e10cSrcweir     else
1704*cdf0e10cSrcweir     {
1705*cdf0e10cSrcweir         BitmapWriteAccess*	pB = aBmp.AcquireWriteAccess();
1706*cdf0e10cSrcweir         if( pP && pA && pB )
1707*cdf0e10cSrcweir         {
1708*cdf0e10cSrcweir             for( nY = 0; nY < nDstHeight; nY++ )
1709*cdf0e10cSrcweir             {
1710*cdf0e10cSrcweir                 const long	nMapY = pMapY[ nY ];
1711*cdf0e10cSrcweir 
1712*cdf0e10cSrcweir                 for( nX = 0; nX < nDstWidth; nX++ )
1713*cdf0e10cSrcweir                 {
1714*cdf0e10cSrcweir                     const long nMapX = pMapX[ nX ];
1715*cdf0e10cSrcweir 
1716*cdf0e10cSrcweir                     aSrcCol = pP->GetColor( nMapY, nMapX );
1717*cdf0e10cSrcweir                     aDstCol = pB->GetColor( nY, nX );
1718*cdf0e10cSrcweir                     const sal_uInt8 nSrcOpaq  = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex();
1719*cdf0e10cSrcweir                     const sal_uInt8 nDstOpaq  = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex();
1720*cdf0e10cSrcweir 
1721*cdf0e10cSrcweir                     aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) );
1722*cdf0e10cSrcweir                     aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) );
1723*cdf0e10cSrcweir                     aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) );
1724*cdf0e10cSrcweir 
1725*cdf0e10cSrcweir                     pB->SetPixel( nY, nX, aDstCol );
1726*cdf0e10cSrcweir 
1727*cdf0e10cSrcweir                     // Have to perform the compositing 'algebra' in
1728*cdf0e10cSrcweir                     // the inverse alpha space (with 255 meaning
1729*cdf0e10cSrcweir                     // opaque), otherwise, transitivity is not
1730*cdf0e10cSrcweir                     // achieved.
1731*cdf0e10cSrcweir                     const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq );
1732*cdf0e10cSrcweir 
1733*cdf0e10cSrcweir                     pAlphaW->SetPixel( nY, nX, Color(nSrcAlpha, nSrcAlpha, nSrcAlpha) );
1734*cdf0e10cSrcweir                 }
1735*cdf0e10cSrcweir             }
1736*cdf0e10cSrcweir         }
1737*cdf0e10cSrcweir 
1738*cdf0e10cSrcweir         aBmp.ReleaseAccess( pB );
1739*cdf0e10cSrcweir         res = aBmp;
1740*cdf0e10cSrcweir     }
1741*cdf0e10cSrcweir 
1742*cdf0e10cSrcweir     aAlphaBitmap.ReleaseAccess( pAlphaW );
1743*cdf0e10cSrcweir     mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
1744*cdf0e10cSrcweir     mpAlphaVDev->EnableMapMode( bOldMapMode );
1745*cdf0e10cSrcweir 
1746*cdf0e10cSrcweir     return res;
1747*cdf0e10cSrcweir }
1748*cdf0e10cSrcweir 
1749*cdf0e10cSrcweir // ------------------------------------------------------------------------
1750*cdf0e10cSrcweir 
1751*cdf0e10cSrcweir Bitmap OutputDevice::ImplBlend( Bitmap              aBmp,
1752*cdf0e10cSrcweir                                 BitmapReadAccess*	pP,
1753*cdf0e10cSrcweir                                 BitmapReadAccess*	pA,
1754*cdf0e10cSrcweir                                 const sal_Int32     nOffY,
1755*cdf0e10cSrcweir                                 const sal_Int32     nDstHeight,
1756*cdf0e10cSrcweir                                 const sal_Int32     nOffX,
1757*cdf0e10cSrcweir                                 const sal_Int32     nDstWidth,
1758*cdf0e10cSrcweir                                 const Rectangle&    aBmpRect,
1759*cdf0e10cSrcweir                                 const Size&         aOutSz,
1760*cdf0e10cSrcweir                                 const bool          bHMirr,
1761*cdf0e10cSrcweir                                 const bool          bVMirr,
1762*cdf0e10cSrcweir                                 const long*         pMapX,
1763*cdf0e10cSrcweir                                 const long*         pMapY )
1764*cdf0e10cSrcweir {
1765*cdf0e10cSrcweir     BitmapColor aDstCol;
1766*cdf0e10cSrcweir     Bitmap      res;
1767*cdf0e10cSrcweir     int         nX, nOutX, nY, nOutY;
1768*cdf0e10cSrcweir 
1769*cdf0e10cSrcweir     if( GetBitCount() <= 8 )
1770*cdf0e10cSrcweir     {
1771*cdf0e10cSrcweir         Bitmap				aDither( aBmp.GetSizePixel(), 8 );
1772*cdf0e10cSrcweir         BitmapColor 		aIndex( 0 );
1773*cdf0e10cSrcweir         BitmapReadAccess*	pB = aBmp.AcquireReadAccess();
1774*cdf0e10cSrcweir         BitmapWriteAccess*	pW = aDither.AcquireWriteAccess();
1775*cdf0e10cSrcweir 
1776*cdf0e10cSrcweir         if( pB && pP && pA && pW )
1777*cdf0e10cSrcweir         {
1778*cdf0e10cSrcweir             for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1779*cdf0e10cSrcweir             {
1780*cdf0e10cSrcweir                 const long nMapY = pMapY[ nY ];
1781*cdf0e10cSrcweir                 const long nModY = ( nOutY & 0x0FL ) << 4L;
1782*cdf0e10cSrcweir 
1783*cdf0e10cSrcweir                 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1784*cdf0e10cSrcweir                 {
1785*cdf0e10cSrcweir                     const long	nMapX = pMapX[ nX ];
1786*cdf0e10cSrcweir                     const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
1787*cdf0e10cSrcweir 
1788*cdf0e10cSrcweir                     aDstCol = pB->GetColor( nY, nX );
1789*cdf0e10cSrcweir                     aDstCol.Merge( pP->GetColor( nMapY, nMapX ), (sal_uInt8) pA->GetPixel( nMapY, nMapX ) );
1790*cdf0e10cSrcweir                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
1791*cdf0e10cSrcweir                                               nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
1792*cdf0e10cSrcweir                                               nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
1793*cdf0e10cSrcweir                     pW->SetPixel( nY, nX, aIndex );
1794*cdf0e10cSrcweir                 }
1795*cdf0e10cSrcweir             }
1796*cdf0e10cSrcweir         }
1797*cdf0e10cSrcweir 
1798*cdf0e10cSrcweir         aBmp.ReleaseAccess( pB );
1799*cdf0e10cSrcweir         aDither.ReleaseAccess( pW );
1800*cdf0e10cSrcweir         res = aDither;
1801*cdf0e10cSrcweir     }
1802*cdf0e10cSrcweir     else
1803*cdf0e10cSrcweir     {
1804*cdf0e10cSrcweir         BitmapWriteAccess*	pB = aBmp.AcquireWriteAccess();
1805*cdf0e10cSrcweir 
1806*cdf0e10cSrcweir         bool bFastBlend = false;
1807*cdf0e10cSrcweir         if( pP && pA && pB )
1808*cdf0e10cSrcweir         {
1809*cdf0e10cSrcweir             SalTwoRect aTR;
1810*cdf0e10cSrcweir             aTR.mnSrcX      = aBmpRect.Left();
1811*cdf0e10cSrcweir             aTR.mnSrcY      = aBmpRect.Top();
1812*cdf0e10cSrcweir             aTR.mnSrcWidth  = aBmpRect.GetWidth();
1813*cdf0e10cSrcweir             aTR.mnSrcHeight = aBmpRect.GetHeight();
1814*cdf0e10cSrcweir             aTR.mnDestX     = nOffX;
1815*cdf0e10cSrcweir             aTR.mnDestY     = nOffY;
1816*cdf0e10cSrcweir             aTR.mnDestWidth = aOutSz.Width();
1817*cdf0e10cSrcweir             aTR.mnDestHeight= aOutSz.Height();
1818*cdf0e10cSrcweir 
1819*cdf0e10cSrcweir             if( !bHMirr || !bVMirr )
1820*cdf0e10cSrcweir                 bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
1821*cdf0e10cSrcweir         }
1822*cdf0e10cSrcweir 
1823*cdf0e10cSrcweir         if( pP && pA && pB && !bFastBlend )
1824*cdf0e10cSrcweir         {
1825*cdf0e10cSrcweir             switch( pP->GetScanlineFormat() )
1826*cdf0e10cSrcweir             {
1827*cdf0e10cSrcweir                 case( BMP_FORMAT_8BIT_PAL ):
1828*cdf0e10cSrcweir                     {
1829*cdf0e10cSrcweir                         for( nY = 0; nY < nDstHeight; nY++ )
1830*cdf0e10cSrcweir                         {
1831*cdf0e10cSrcweir                             const long	nMapY = pMapY[ nY ];
1832*cdf0e10cSrcweir                             Scanline	pPScan = pP->GetScanline( nMapY );
1833*cdf0e10cSrcweir                             Scanline	pAScan = pA->GetScanline( nMapY );
1834*cdf0e10cSrcweir 
1835*cdf0e10cSrcweir                             for( nX = 0; nX < nDstWidth; nX++ )
1836*cdf0e10cSrcweir                             {
1837*cdf0e10cSrcweir                                 const long nMapX = pMapX[ nX ];
1838*cdf0e10cSrcweir                                 aDstCol = pB->GetPixel( nY, nX );
1839*cdf0e10cSrcweir                                 pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
1840*cdf0e10cSrcweir                                                                      pAScan[ nMapX ] ) );
1841*cdf0e10cSrcweir                             }
1842*cdf0e10cSrcweir                         }
1843*cdf0e10cSrcweir                     }
1844*cdf0e10cSrcweir                     break;
1845*cdf0e10cSrcweir 
1846*cdf0e10cSrcweir                 case( BMP_FORMAT_24BIT_TC_BGR ):
1847*cdf0e10cSrcweir                     {
1848*cdf0e10cSrcweir                         for( nY = 0; nY < nDstHeight; nY++ )
1849*cdf0e10cSrcweir                         {
1850*cdf0e10cSrcweir                             const long	nMapY = pMapY[ nY ];
1851*cdf0e10cSrcweir                             Scanline	pPScan = pP->GetScanline( nMapY );
1852*cdf0e10cSrcweir                             Scanline	pAScan = pA->GetScanline( nMapY );
1853*cdf0e10cSrcweir 
1854*cdf0e10cSrcweir                             for( nX = 0; nX < nDstWidth; nX++ )
1855*cdf0e10cSrcweir                             {
1856*cdf0e10cSrcweir                                 const long	nMapX = pMapX[ nX ];
1857*cdf0e10cSrcweir                                 Scanline	pTmp = pPScan + nMapX * 3;
1858*cdf0e10cSrcweir 
1859*cdf0e10cSrcweir                                 aDstCol = pB->GetPixel( nY, nX );
1860*cdf0e10cSrcweir                                 pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
1861*cdf0e10cSrcweir                                                                      pAScan[ nMapX ] ) );
1862*cdf0e10cSrcweir                             }
1863*cdf0e10cSrcweir                         }
1864*cdf0e10cSrcweir                     }
1865*cdf0e10cSrcweir                     break;
1866*cdf0e10cSrcweir 
1867*cdf0e10cSrcweir                 case( BMP_FORMAT_24BIT_TC_RGB ):
1868*cdf0e10cSrcweir                     {
1869*cdf0e10cSrcweir                         for( nY = 0; nY < nDstHeight; nY++ )
1870*cdf0e10cSrcweir                         {
1871*cdf0e10cSrcweir                             const long	nMapY = pMapY[ nY ];
1872*cdf0e10cSrcweir                             Scanline	pPScan = pP->GetScanline( nMapY );
1873*cdf0e10cSrcweir                             Scanline	pAScan = pA->GetScanline( nMapY );
1874*cdf0e10cSrcweir 
1875*cdf0e10cSrcweir                             for( nX = 0; nX < nDstWidth; nX++ )
1876*cdf0e10cSrcweir                             {
1877*cdf0e10cSrcweir                                 const long	nMapX = pMapX[ nX ];
1878*cdf0e10cSrcweir                                 Scanline    pTmp = pPScan + nMapX * 3;
1879*cdf0e10cSrcweir 
1880*cdf0e10cSrcweir                                 aDstCol = pB->GetPixel( nY, nX );
1881*cdf0e10cSrcweir                                 pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
1882*cdf0e10cSrcweir                                                                      pAScan[ nMapX ] ) );
1883*cdf0e10cSrcweir                             }
1884*cdf0e10cSrcweir                         }
1885*cdf0e10cSrcweir                     }
1886*cdf0e10cSrcweir                     break;
1887*cdf0e10cSrcweir 
1888*cdf0e10cSrcweir                 default:
1889*cdf0e10cSrcweir                 {
1890*cdf0e10cSrcweir                     for( nY = 0; nY < nDstHeight; nY++ )
1891*cdf0e10cSrcweir                     {
1892*cdf0e10cSrcweir                         const long	nMapY = pMapY[ nY ];
1893*cdf0e10cSrcweir                         Scanline	pAScan = pA->GetScanline( nMapY );
1894*cdf0e10cSrcweir 
1895*cdf0e10cSrcweir                         for( nX = 0; nX < nDstWidth; nX++ )
1896*cdf0e10cSrcweir                         {
1897*cdf0e10cSrcweir                             const long nMapX = pMapX[ nX ];
1898*cdf0e10cSrcweir                             aDstCol = pB->GetPixel( nY, nX );
1899*cdf0e10cSrcweir                             pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
1900*cdf0e10cSrcweir                                                                  pAScan[ nMapX ] ) );
1901*cdf0e10cSrcweir                         }
1902*cdf0e10cSrcweir                     }
1903*cdf0e10cSrcweir                 }
1904*cdf0e10cSrcweir                 break;
1905*cdf0e10cSrcweir             }
1906*cdf0e10cSrcweir         }
1907*cdf0e10cSrcweir 
1908*cdf0e10cSrcweir         aBmp.ReleaseAccess( pB );
1909*cdf0e10cSrcweir         res = aBmp;
1910*cdf0e10cSrcweir     }
1911*cdf0e10cSrcweir 
1912*cdf0e10cSrcweir     return res;
1913*cdf0e10cSrcweir }
1914*cdf0e10cSrcweir 
1915*cdf0e10cSrcweir // ------------------------------------------------------------------------
1916*cdf0e10cSrcweir 
1917*cdf0e10cSrcweir void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
1918*cdf0e10cSrcweir 								  const Point& rDestPt, const Size& rDestSize,
1919*cdf0e10cSrcweir 								  const Point& rSrcPtPixel, const Size& rSrcSizePixel )
1920*cdf0e10cSrcweir {
1921*cdf0e10cSrcweir 	const Point aNullPt;
1922*cdf0e10cSrcweir 	Point		aOutPt( LogicToPixel( rDestPt ) );
1923*cdf0e10cSrcweir 	Size        aOutSz( LogicToPixel( rDestSize ) );
1924*cdf0e10cSrcweir 	Rectangle	aDstRect( aNullPt, GetOutputSizePixel() );
1925*cdf0e10cSrcweir 	const sal_Bool	bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0;
1926*cdf0e10cSrcweir 
1927*cdf0e10cSrcweir 	if( OUTDEV_WINDOW == meOutDevType )
1928*cdf0e10cSrcweir 	{
1929*cdf0e10cSrcweir 		const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
1930*cdf0e10cSrcweir 
1931*cdf0e10cSrcweir 		if( !aPaintRgn.IsNull() )
1932*cdf0e10cSrcweir 			aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
1933*cdf0e10cSrcweir 	}
1934*cdf0e10cSrcweir 
1935*cdf0e10cSrcweir 	if( bHMirr )
1936*cdf0e10cSrcweir 	{
1937*cdf0e10cSrcweir 		aOutSz.Width() = -aOutSz.Width();
1938*cdf0e10cSrcweir 		aOutPt.X() -= ( aOutSz.Width() - 1L );
1939*cdf0e10cSrcweir 	}
1940*cdf0e10cSrcweir 
1941*cdf0e10cSrcweir 	if( bVMirr )
1942*cdf0e10cSrcweir 	{
1943*cdf0e10cSrcweir 		aOutSz.Height() = -aOutSz.Height();
1944*cdf0e10cSrcweir 		aOutPt.Y() -= ( aOutSz.Height() - 1L );
1945*cdf0e10cSrcweir 	}
1946*cdf0e10cSrcweir 
1947*cdf0e10cSrcweir 	if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
1948*cdf0e10cSrcweir 	{
1949*cdf0e10cSrcweir         bool bNativeAlpha = false;
1950*cdf0e10cSrcweir         static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
1951*cdf0e10cSrcweir         // #i83087# Naturally, system alpha blending cannot work with
1952*cdf0e10cSrcweir         // separate alpha VDev
1953*cdf0e10cSrcweir         if( !mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr )
1954*cdf0e10cSrcweir         {
1955*cdf0e10cSrcweir             Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
1956*cdf0e10cSrcweir             SalTwoRect aTR = {
1957*cdf0e10cSrcweir                 rSrcPtPixel.X(), rSrcPtPixel.Y(),
1958*cdf0e10cSrcweir                 rSrcSizePixel.Width(), rSrcSizePixel.Height(),
1959*cdf0e10cSrcweir                 aRelPt.X(), aRelPt.Y(),
1960*cdf0e10cSrcweir                 aOutSz.Width(), aOutSz.Height()
1961*cdf0e10cSrcweir             };
1962*cdf0e10cSrcweir             SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap();
1963*cdf0e10cSrcweir             SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
1964*cdf0e10cSrcweir             bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this );
1965*cdf0e10cSrcweir         }
1966*cdf0e10cSrcweir 
1967*cdf0e10cSrcweir         VirtualDevice* pOldVDev = mpAlphaVDev;
1968*cdf0e10cSrcweir 
1969*cdf0e10cSrcweir 		Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() );
1970*cdf0e10cSrcweir 		if( !bNativeAlpha
1971*cdf0e10cSrcweir                 &&  !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
1972*cdf0e10cSrcweir 		{
1973*cdf0e10cSrcweir 			GDIMetaFile*	pOldMetaFile = mpMetaFile; mpMetaFile = NULL;
1974*cdf0e10cSrcweir 			const sal_Bool		bOldMap = mbMap; mbMap = sal_False;
1975*cdf0e10cSrcweir 			Bitmap			aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
1976*cdf0e10cSrcweir 
1977*cdf0e10cSrcweir             // #109044# The generated bitmap need not necessarily be
1978*cdf0e10cSrcweir             // of aDstRect dimensions, it's internally clipped to
1979*cdf0e10cSrcweir             // window bounds. Thus, we correct the dest size here,
1980*cdf0e10cSrcweir             // since we later use it (in nDstWidth/Height) for pixel
1981*cdf0e10cSrcweir             // access)
1982*cdf0e10cSrcweir             // #i38887# reading from screen may sometimes fail
1983*cdf0e10cSrcweir             if( aBmp.ImplGetImpBitmap() )
1984*cdf0e10cSrcweir                 aDstRect.SetSize( aBmp.GetSizePixel() );
1985*cdf0e10cSrcweir 
1986*cdf0e10cSrcweir 			BitmapColor 	aDstCol;
1987*cdf0e10cSrcweir 			const long		nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
1988*cdf0e10cSrcweir 			const long		nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
1989*cdf0e10cSrcweir 			const long		nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
1990*cdf0e10cSrcweir 			// calculate offset in original bitmap
1991*cdf0e10cSrcweir 			// in RTL case this is a little more complicated since the contents of the
1992*cdf0e10cSrcweir 			// bitmap is not mirrored (it never is), however the paint region and bmp region
1993*cdf0e10cSrcweir 			// are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
1994*cdf0e10cSrcweir 			// is content wise somewhere else and needs to take mirroring into account
1995*cdf0e10cSrcweir 			const long		nOffX = IsRTLEnabled()
1996*cdf0e10cSrcweir 			                        ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
1997*cdf0e10cSrcweir 			                        : aDstRect.Left() - aOutPt.X(),
1998*cdf0e10cSrcweir 				            nOffY = aDstRect.Top() - aOutPt.Y();
1999*cdf0e10cSrcweir 			long			nX, nOutX, nY, nOutY;
2000*cdf0e10cSrcweir 			long			nMirrOffX = 0;
2001*cdf0e10cSrcweir 			long			nMirrOffY = 0;
2002*cdf0e10cSrcweir 			long*			pMapX = new long[ nDstWidth ];
2003*cdf0e10cSrcweir 			long*			pMapY = new long[ nDstHeight ];
2004*cdf0e10cSrcweir 
2005*cdf0e10cSrcweir 			// create horizontal mapping table
2006*cdf0e10cSrcweir 			if( bHMirr )
2007*cdf0e10cSrcweir 				nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
2008*cdf0e10cSrcweir 
2009*cdf0e10cSrcweir 			for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
2010*cdf0e10cSrcweir 			{
2011*cdf0e10cSrcweir 				pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
2012*cdf0e10cSrcweir 				if( bHMirr )
2013*cdf0e10cSrcweir 					pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
2014*cdf0e10cSrcweir 			}
2015*cdf0e10cSrcweir 
2016*cdf0e10cSrcweir 			// create vertical mapping table
2017*cdf0e10cSrcweir 			if( bVMirr )
2018*cdf0e10cSrcweir 				nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
2019*cdf0e10cSrcweir 
2020*cdf0e10cSrcweir 			for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
2021*cdf0e10cSrcweir 			{
2022*cdf0e10cSrcweir 				pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
2023*cdf0e10cSrcweir 
2024*cdf0e10cSrcweir 				if( bVMirr )
2025*cdf0e10cSrcweir 					pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
2026*cdf0e10cSrcweir 			}
2027*cdf0e10cSrcweir 
2028*cdf0e10cSrcweir             BitmapReadAccess*	pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
2029*cdf0e10cSrcweir             BitmapReadAccess*	pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
2030*cdf0e10cSrcweir 
2031*cdf0e10cSrcweir             DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
2032*cdf0e10cSrcweir                         pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
2033*cdf0e10cSrcweir                         "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
2034*cdf0e10cSrcweir 
2035*cdf0e10cSrcweir             // #i38887# reading from screen may sometimes fail
2036*cdf0e10cSrcweir             if( aBmp.ImplGetImpBitmap() )
2037*cdf0e10cSrcweir             {
2038*cdf0e10cSrcweir                 Bitmap aTmp;
2039*cdf0e10cSrcweir 
2040*cdf0e10cSrcweir                 if( mpAlphaVDev )
2041*cdf0e10cSrcweir                 {
2042*cdf0e10cSrcweir                     aTmp = ImplBlendWithAlpha(
2043*cdf0e10cSrcweir                         aBmp,pP,pA,
2044*cdf0e10cSrcweir                         aDstRect,
2045*cdf0e10cSrcweir                         nOffY,nDstHeight,
2046*cdf0e10cSrcweir                         nOffX,nDstWidth,
2047*cdf0e10cSrcweir                         pMapX,pMapY );
2048*cdf0e10cSrcweir                 }
2049*cdf0e10cSrcweir                 else
2050*cdf0e10cSrcweir                 {
2051*cdf0e10cSrcweir                     aTmp = ImplBlend(
2052*cdf0e10cSrcweir                         aBmp,pP,pA,
2053*cdf0e10cSrcweir                         nOffY,nDstHeight,
2054*cdf0e10cSrcweir                         nOffX,nDstWidth,
2055*cdf0e10cSrcweir                         aBmpRect,aOutSz,
2056*cdf0e10cSrcweir                         bHMirr,bVMirr,
2057*cdf0e10cSrcweir                         pMapX,pMapY );
2058*cdf0e10cSrcweir                 }
2059*cdf0e10cSrcweir 
2060*cdf0e10cSrcweir                 // #110958# Disable alpha VDev, we're doing the necessary
2061*cdf0e10cSrcweir                 // stuff explicitely furher below
2062*cdf0e10cSrcweir                 if( mpAlphaVDev )
2063*cdf0e10cSrcweir                     mpAlphaVDev = NULL;
2064*cdf0e10cSrcweir 
2065*cdf0e10cSrcweir                 DrawBitmap( aDstRect.TopLeft(),
2066*cdf0e10cSrcweir                             aTmp );
2067*cdf0e10cSrcweir 
2068*cdf0e10cSrcweir                 // #110958# Enable alpha VDev again
2069*cdf0e10cSrcweir                 mpAlphaVDev = pOldVDev;
2070*cdf0e10cSrcweir             }
2071*cdf0e10cSrcweir 
2072*cdf0e10cSrcweir             ( (Bitmap&) rBmp ).ReleaseAccess( pP );
2073*cdf0e10cSrcweir             ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
2074*cdf0e10cSrcweir 
2075*cdf0e10cSrcweir 			delete[] pMapX;
2076*cdf0e10cSrcweir 			delete[] pMapY;
2077*cdf0e10cSrcweir 			mbMap = bOldMap;
2078*cdf0e10cSrcweir 			mpMetaFile = pOldMetaFile;
2079*cdf0e10cSrcweir 		}
2080*cdf0e10cSrcweir 	}
2081*cdf0e10cSrcweir }
2082*cdf0e10cSrcweir 
2083*cdf0e10cSrcweir // ------------------------------------------------------------------------
2084*cdf0e10cSrcweir 
2085*cdf0e10cSrcweir void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
2086*cdf0e10cSrcweir 										 const Point& rDestPt, const Size& rDestSize,
2087*cdf0e10cSrcweir 										 const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2088*cdf0e10cSrcweir {
2089*cdf0e10cSrcweir 	Point		aPt;
2090*cdf0e10cSrcweir 	Point		aDestPt( LogicToPixel( rDestPt ) );
2091*cdf0e10cSrcweir 	Size		aDestSz( LogicToPixel( rDestSize ) );
2092*cdf0e10cSrcweir 	Rectangle	aSrcRect( rSrcPtPixel, rSrcSizePixel );
2093*cdf0e10cSrcweir 
2094*cdf0e10cSrcweir 	aSrcRect.Justify();
2095*cdf0e10cSrcweir 
2096*cdf0e10cSrcweir 	if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2097*cdf0e10cSrcweir 	{
2098*cdf0e10cSrcweir 		Bitmap	aPaint( rBmp ), aMask( rMask );
2099*cdf0e10cSrcweir 		sal_uLong	nMirrFlags = 0UL;
2100*cdf0e10cSrcweir 
2101*cdf0e10cSrcweir 		if( aMask.GetBitCount() > 1 )
2102*cdf0e10cSrcweir 			aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2103*cdf0e10cSrcweir 
2104*cdf0e10cSrcweir 		// mirrored horizontically
2105*cdf0e10cSrcweir 		if( aDestSz.Width() < 0L )
2106*cdf0e10cSrcweir 		{
2107*cdf0e10cSrcweir 			aDestSz.Width() = -aDestSz.Width();
2108*cdf0e10cSrcweir 			aDestPt.X() -= ( aDestSz.Width() - 1L );
2109*cdf0e10cSrcweir 			nMirrFlags |= BMP_MIRROR_HORZ;
2110*cdf0e10cSrcweir 		}
2111*cdf0e10cSrcweir 
2112*cdf0e10cSrcweir 		// mirrored vertically
2113*cdf0e10cSrcweir 		if( aDestSz.Height() < 0L )
2114*cdf0e10cSrcweir 		{
2115*cdf0e10cSrcweir 			aDestSz.Height() = -aDestSz.Height();
2116*cdf0e10cSrcweir 			aDestPt.Y() -= ( aDestSz.Height() - 1L );
2117*cdf0e10cSrcweir 			nMirrFlags |= BMP_MIRROR_VERT;
2118*cdf0e10cSrcweir 		}
2119*cdf0e10cSrcweir 
2120*cdf0e10cSrcweir 		// source cropped?
2121*cdf0e10cSrcweir 		if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
2122*cdf0e10cSrcweir 		{
2123*cdf0e10cSrcweir 			aPaint.Crop( aSrcRect );
2124*cdf0e10cSrcweir 			aMask.Crop( aSrcRect );
2125*cdf0e10cSrcweir 		}
2126*cdf0e10cSrcweir 
2127*cdf0e10cSrcweir 		// destination mirrored
2128*cdf0e10cSrcweir 		if( nMirrFlags )
2129*cdf0e10cSrcweir 		{
2130*cdf0e10cSrcweir 			aPaint.Mirror( nMirrFlags );
2131*cdf0e10cSrcweir 			aMask.Mirror( nMirrFlags );
2132*cdf0e10cSrcweir 		}
2133*cdf0e10cSrcweir 
2134*cdf0e10cSrcweir 		// we always want to have a mask
2135*cdf0e10cSrcweir 		if( aMask.IsEmpty() )
2136*cdf0e10cSrcweir 		{
2137*cdf0e10cSrcweir 			aMask = Bitmap( aSrcRect.GetSize(), 1 );
2138*cdf0e10cSrcweir 			aMask.Erase( Color( COL_BLACK ) );
2139*cdf0e10cSrcweir 		}
2140*cdf0e10cSrcweir 
2141*cdf0e10cSrcweir 		// do painting
2142*cdf0e10cSrcweir         const long		nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2143*cdf0e10cSrcweir 		long			nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2144*cdf0e10cSrcweir 		long*			pMapX = new long[ nSrcWidth + 1 ];
2145*cdf0e10cSrcweir 		long*			pMapY = new long[ nSrcHeight + 1 ];
2146*cdf0e10cSrcweir 		const sal_Bool		bOldMap = mbMap;
2147*cdf0e10cSrcweir 
2148*cdf0e10cSrcweir 		mbMap = sal_False;
2149*cdf0e10cSrcweir 
2150*cdf0e10cSrcweir 		// create forward mapping tables
2151*cdf0e10cSrcweir 		for( nX = 0L; nX <= nSrcWidth; nX++ )
2152*cdf0e10cSrcweir 			pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2153*cdf0e10cSrcweir 
2154*cdf0e10cSrcweir 		for( nY = 0L; nY <= nSrcHeight; nY++ )
2155*cdf0e10cSrcweir 			pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2156*cdf0e10cSrcweir 
2157*cdf0e10cSrcweir         // walk through all rectangles of mask
2158*cdf0e10cSrcweir         Region          aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2159*cdf0e10cSrcweir 		ImplRegionInfo	aInfo;
2160*cdf0e10cSrcweir 		sal_Bool            bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2161*cdf0e10cSrcweir 
2162*cdf0e10cSrcweir 		while( bRgnRect )
2163*cdf0e10cSrcweir 		{
2164*cdf0e10cSrcweir 			Bitmap          aBandBmp( aPaint );
2165*cdf0e10cSrcweir             const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) );
2166*cdf0e10cSrcweir             const Point     aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2167*cdf0e10cSrcweir             const Size      aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2168*cdf0e10cSrcweir 
2169*cdf0e10cSrcweir 			aBandBmp.Crop( aBandRect );
2170*cdf0e10cSrcweir             ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION );
2171*cdf0e10cSrcweir             bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2172*cdf0e10cSrcweir 		}
2173*cdf0e10cSrcweir 
2174*cdf0e10cSrcweir         mbMap = bOldMap;
2175*cdf0e10cSrcweir 
2176*cdf0e10cSrcweir         delete[] pMapX;
2177*cdf0e10cSrcweir         delete[] pMapY;
2178*cdf0e10cSrcweir 	}
2179*cdf0e10cSrcweir }
2180*cdf0e10cSrcweir 
2181*cdf0e10cSrcweir // ------------------------------------------------------------------------
2182*cdf0e10cSrcweir 
2183*cdf0e10cSrcweir void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
2184*cdf0e10cSrcweir 								  const Point& rDestPt, const Size& rDestSize,
2185*cdf0e10cSrcweir 								  const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2186*cdf0e10cSrcweir {
2187*cdf0e10cSrcweir     Point		aPt;
2188*cdf0e10cSrcweir 	Point		aDestPt( LogicToPixel( rDestPt ) );
2189*cdf0e10cSrcweir 	Size		aDestSz( LogicToPixel( rDestSize ) );
2190*cdf0e10cSrcweir 	Rectangle	aSrcRect( rSrcPtPixel, rSrcSizePixel );
2191*cdf0e10cSrcweir 
2192*cdf0e10cSrcweir 	aSrcRect.Justify();
2193*cdf0e10cSrcweir 
2194*cdf0e10cSrcweir 	if( !rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2195*cdf0e10cSrcweir 	{
2196*cdf0e10cSrcweir 		Bitmap	aMask( rMask );
2197*cdf0e10cSrcweir 		sal_uLong	nMirrFlags = 0UL;
2198*cdf0e10cSrcweir 
2199*cdf0e10cSrcweir 		if( aMask.GetBitCount() > 1 )
2200*cdf0e10cSrcweir 			aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2201*cdf0e10cSrcweir 
2202*cdf0e10cSrcweir 		// mirrored horizontically
2203*cdf0e10cSrcweir 		if( aDestSz.Width() < 0L )
2204*cdf0e10cSrcweir 		{
2205*cdf0e10cSrcweir 			aDestSz.Width() = -aDestSz.Width();
2206*cdf0e10cSrcweir 			aDestPt.X() -= ( aDestSz.Width() - 1L );
2207*cdf0e10cSrcweir 			nMirrFlags |= BMP_MIRROR_HORZ;
2208*cdf0e10cSrcweir 		}
2209*cdf0e10cSrcweir 
2210*cdf0e10cSrcweir 		// mirrored vertically
2211*cdf0e10cSrcweir 		if( aDestSz.Height() < 0L )
2212*cdf0e10cSrcweir 		{
2213*cdf0e10cSrcweir 			aDestSz.Height() = -aDestSz.Height();
2214*cdf0e10cSrcweir 			aDestPt.Y() -= ( aDestSz.Height() - 1L );
2215*cdf0e10cSrcweir 			nMirrFlags |= BMP_MIRROR_VERT;
2216*cdf0e10cSrcweir 		}
2217*cdf0e10cSrcweir 
2218*cdf0e10cSrcweir 		// source cropped?
2219*cdf0e10cSrcweir 		if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) )
2220*cdf0e10cSrcweir 			aMask.Crop( aSrcRect );
2221*cdf0e10cSrcweir 
2222*cdf0e10cSrcweir 		// destination mirrored
2223*cdf0e10cSrcweir 		if( nMirrFlags )
2224*cdf0e10cSrcweir 			aMask.Mirror( nMirrFlags );
2225*cdf0e10cSrcweir 
2226*cdf0e10cSrcweir 		// do painting
2227*cdf0e10cSrcweir         const long		nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2228*cdf0e10cSrcweir 		long			nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2229*cdf0e10cSrcweir 		long*			pMapX = new long[ nSrcWidth + 1 ];
2230*cdf0e10cSrcweir 		long*			pMapY = new long[ nSrcHeight + 1 ];
2231*cdf0e10cSrcweir         GDIMetaFile*    pOldMetaFile = mpMetaFile;
2232*cdf0e10cSrcweir 		const sal_Bool		bOldMap = mbMap;
2233*cdf0e10cSrcweir 
2234*cdf0e10cSrcweir 		mpMetaFile = NULL;
2235*cdf0e10cSrcweir 		mbMap = sal_False;
2236*cdf0e10cSrcweir 		Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
2237*cdf0e10cSrcweir 		SetLineColor( rMaskColor );
2238*cdf0e10cSrcweir 		SetFillColor( rMaskColor );
2239*cdf0e10cSrcweir 		ImplInitLineColor();
2240*cdf0e10cSrcweir 		ImplInitFillColor();
2241*cdf0e10cSrcweir 
2242*cdf0e10cSrcweir 		// create forward mapping tables
2243*cdf0e10cSrcweir 		for( nX = 0L; nX <= nSrcWidth; nX++ )
2244*cdf0e10cSrcweir 			pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2245*cdf0e10cSrcweir 
2246*cdf0e10cSrcweir 		for( nY = 0L; nY <= nSrcHeight; nY++ )
2247*cdf0e10cSrcweir 			pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2248*cdf0e10cSrcweir 
2249*cdf0e10cSrcweir         // walk through all rectangles of mask
2250*cdf0e10cSrcweir         Region          aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2251*cdf0e10cSrcweir 		ImplRegionInfo	aInfo;
2252*cdf0e10cSrcweir 		sal_Bool            bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2253*cdf0e10cSrcweir 
2254*cdf0e10cSrcweir 		while( bRgnRect )
2255*cdf0e10cSrcweir 		{
2256*cdf0e10cSrcweir             const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2257*cdf0e10cSrcweir             const Size  aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2258*cdf0e10cSrcweir 
2259*cdf0e10cSrcweir 			DrawRect( Rectangle( aMapPt, aMapSz ) );
2260*cdf0e10cSrcweir 			bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2261*cdf0e10cSrcweir 		}
2262*cdf0e10cSrcweir 
2263*cdf0e10cSrcweir 		Pop();
2264*cdf0e10cSrcweir 		delete[] pMapX;
2265*cdf0e10cSrcweir 		delete[] pMapY;
2266*cdf0e10cSrcweir 		mbMap = bOldMap;
2267*cdf0e10cSrcweir 		mpMetaFile = pOldMetaFile;
2268*cdf0e10cSrcweir 	}
2269*cdf0e10cSrcweir }
2270