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