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