xref: /trunk/main/vcl/source/gdi/outdev6.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <tools/debug.hxx>
32 #include <vcl/outdev.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/bmpacc.hxx>
35 #include <vcl/metaact.hxx>
36 #include <vcl/gdimtf.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/wrkwin.hxx>
39 #include <vcl/graph.hxx>
40 #include <vcl/rendergraphicrasterizer.hxx>
41 
42 #include <wall2.hxx>
43 #include <salgdi.hxx>
44 #include <window.h>
45 #include <svdata.hxx>
46 #include <outdev.h>
47 
48 #include <com/sun/star/uno/Sequence.hxx>
49 
50 #include <basegfx/vector/b2dvector.hxx>
51 #include <basegfx/polygon/b2dpolypolygon.hxx>
52 #include <basegfx/polygon/b2dpolygon.hxx>
53 #include <basegfx/matrix/b2dhommatrix.hxx>
54 
55 #include <math.h>
56 
57 // ========================================================================
58 
59 DBG_NAMEEX( OutputDevice )
60 
61 // ------------------------------------------------------------------------
62 
63 void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags )
64 {
65     DBG_TRACE( "OutputDevice::DrawGrid()" );
66     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
67 
68     Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
69     aDstRect.Intersection( rRect );
70 
71     if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
72         return;
73 
74     if( !mpGraphics && !ImplGetGraphics() )
75         return;
76 
77     if( mbInitClipRegion )
78         ImplInitClipRegion();
79 
80     if( mbOutputClipped )
81         return;
82 
83     const long  nDistX = Max( rDist.Width(), 1L );
84     const long  nDistY = Max( rDist.Height(), 1L );
85     long        nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
86     long        nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
87     const long  nRight = aDstRect.Right();
88     const long  nBottom = aDstRect.Bottom();
89     const long  nStartX = ImplLogicXToDevicePixel( nX );
90     const long  nEndX = ImplLogicXToDevicePixel( nRight );
91     const long  nStartY = ImplLogicYToDevicePixel( nY );
92     const long  nEndY = ImplLogicYToDevicePixel( nBottom );
93     long        nHorzCount = 0L;
94     long        nVertCount = 0L;
95 
96     ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
97     ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
98 
99     if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
100     {
101         aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
102         aVertBuf[ nVertCount++ ] = nStartY;
103         while( ( nY += nDistY ) <= nBottom )
104             aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
105     }
106 
107     if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
108     {
109         aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
110         aHorzBuf[ nHorzCount++ ] = nStartX;
111         while( ( nX += nDistX ) <= nRight )
112             aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
113     }
114 
115     if( mbInitLineColor )
116         ImplInitLineColor();
117 
118     if( mbInitFillColor )
119         ImplInitFillColor();
120 
121     const sal_Bool bOldMap = mbMap;
122     EnableMapMode( sal_False );
123 
124     if( nFlags & GRID_DOTS )
125     {
126         for( long i = 0L; i < nVertCount; i++ )
127             for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
128                 mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
129     }
130     else
131     {
132         if( nFlags & GRID_HORZLINES )
133         {
134             for( long i = 0L; i < nVertCount; i++ )
135             {
136                 nY = aVertBuf[ i ];
137                 mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
138             }
139         }
140 
141         if( nFlags & GRID_VERTLINES )
142         {
143             for( long i = 0L; i < nHorzCount; i++ )
144             {
145                 nX = aHorzBuf[ i ];
146                 mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
147             }
148         }
149     }
150 
151     EnableMapMode( bOldMap );
152 
153     if( mpAlphaVDev )
154         mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
155 }
156 
157 // ------------------------------------------------------------------------
158 // Caution: This method is nearly the same as
159 // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
160 // so when changes are made here do not forget to make change sthere, too
161 
162 void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
163 {
164     DBG_TRACE( "OutputDevice::DrawTransparent(B2D&,transparency)" );
165     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
166 
167     // AW: Do NOT paint empty PolyPolygons
168     if(!rB2DPolyPoly.count())
169         return;
170 
171     // we need a graphics
172     if( !mpGraphics )
173         if( !ImplGetGraphics() )
174             return;
175 
176     if( mbInitClipRegion )
177         ImplInitClipRegion();
178     if( mbOutputClipped )
179         return;
180 
181     if( mbInitLineColor )
182         ImplInitLineColor();
183     if( mbInitFillColor )
184         ImplInitFillColor();
185 
186     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
187         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
188         && ROP_OVERPAINT == GetRasterOp() )
189     {
190         // b2dpolygon support not implemented yet on non-UNX platforms
191         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
192         basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
193 
194         // transform the polygon into device space and ensure it is closed
195         aB2DPolyPolygon.transform( aTransform );
196         aB2DPolyPolygon.setClosed( true );
197 
198         bool bDrawnOk = true;
199         if( IsFillColor() )
200             bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
201         if( bDrawnOk && IsLineColor() )
202         {
203             const basegfx::B2DVector aHairlineWidth(1,1);
204             const int nPolyCount = aB2DPolyPolygon.count();
205             for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
206             {
207                 const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
208                 mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, this );
209             }
210         }
211 
212         if( bDrawnOk )
213         {
214 #if 0
215             // MetaB2DPolyPolygonAction is not implemented yet:
216             // according to AW adding it is very dangerous since there is a lot
217             // of code that uses the metafile actions directly and unless every
218             // place that does this knows about the new action we need to fallback
219             if( mpMetaFile )
220                 mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) );
221 #else
222             if( mpMetaFile )
223                 mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
224 #endif
225             return;
226         }
227     }
228 
229     // fallback to old polygon drawing if needed
230     const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly );
231     DrawTransparent(PolyPolygon(rB2DPolyPoly), static_cast< sal_uInt16 >(fTransparency * 100.0));
232 }
233 
234 // ------------------------------------------------------------------------
235 
236 void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
237                                     sal_uInt16 nTransparencePercent )
238 {
239     DBG_TRACE( "OutputDevice::DrawTransparent()" );
240     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
241 
242     // short circuit for drawing an opaque polygon
243     if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
244     {
245         DrawPolyPolygon( rPolyPoly );
246         return;
247     }
248 
249     // short circut for drawing an invisible polygon
250     if( !mbFillColor || (nTransparencePercent >= 100) )
251     {
252         // short circuit if the polygon border is invisible too
253         if( !mbLineColor )
254             return;
255 
256         // DrawTransparent() assumes that the border is NOT to be drawn transparently???
257         Push( PUSH_FILLCOLOR );
258         SetFillColor();
259         DrawPolyPolygon( rPolyPoly );
260         Pop();
261         return;
262     }
263 
264     // handle metafile recording
265     if( mpMetaFile )
266         mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
267 
268     bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
269     if( bDrawn )
270         return;
271 
272     // get the device graphics as drawing target
273     if( !mpGraphics )
274         if( !ImplGetGraphics() )
275             return;
276 
277     // debug helper:
278     static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
279 
280     // try hard to draw it directly, because the emulation layers are slower
281     if( !pDisableNative
282         && mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
283 #if defined UNX && ! defined QUARTZ
284             && GetBitCount() > 8
285 #endif
286 #ifdef WIN32
287         // workaround bad dithering on remote displaying when using GDI+ with toolbar buttoin hilighting
288         && !rPolyPoly.IsRect()
289 #endif
290         )
291     {
292         // prepare the graphics device
293         if( mbInitClipRegion )
294             ImplInitClipRegion();
295         if( mbOutputClipped )
296             return;
297         if( mbInitLineColor )
298             ImplInitLineColor();
299         if( mbInitFillColor )
300             ImplInitFillColor();
301 
302         // get the polygon in device coordinates
303         basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
304         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
305         aB2DPolyPolygon.transform( aTransform );
306 
307         const double fTransparency = 0.01 * nTransparencePercent;
308         if( mbFillColor )
309         {
310             // draw the transparent polygon
311             // NOTE: filled polygons are assumed to be drawn as if they were always closed
312             bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
313         }
314 
315         if( mbLineColor )
316         {
317             // disable the fill color for now
318             mpGraphics->SetFillColor();
319             // draw the border line
320             const basegfx::B2DVector aLineWidths( 1, 1 );
321             const int nPolyCount = aB2DPolyPolygon.count();
322             for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
323             {
324                 const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
325                 bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, this );
326             }
327             // prepare to restore the fill color
328             mbInitFillColor = mbFillColor;
329         }
330     }
331 
332     if( bDrawn )
333         return;
334 
335     if( 1 )
336     {
337         VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
338 
339         // #110958# Disable alpha VDev, we perform the necessary
340         // operation explicitely further below.
341         if( mpAlphaVDev )
342             mpAlphaVDev = NULL;
343 
344         GDIMetaFile* pOldMetaFile = mpMetaFile;
345         mpMetaFile = NULL;
346 
347         if( OUTDEV_PRINTER == meOutDevType )
348         {
349             if(100 <= nTransparencePercent)
350             {
351                 // #i112959# 100% transparent, draw nothing
352                 return;
353             }
354 
355             Rectangle       aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
356             const Size      aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
357             const long      nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L );
358             long            nMove;
359             const sal_uInt16    nTrans = ( nTransparencePercent < 13 ) ? 0 :
360                                      ( nTransparencePercent < 38 ) ? 25 :
361                                      ( nTransparencePercent < 63 ) ? 50 :
362                                      ( nTransparencePercent < 88 ) ? 75 : 100;
363 
364             switch( nTrans )
365             {
366                 case( 25 ): nMove = nBaseExtent * 3; break;
367                 case( 50 ): nMove = nBaseExtent * 4; break;
368                 case( 75 ): nMove = nBaseExtent * 6; break;
369 
370                 // #i112959#  very transparent (88 < nTransparencePercent <= 99)
371                 case( 100 ): nMove = nBaseExtent * 8; break;
372 
373                 // #i112959# not transparent (nTransparencePercent < 13)
374                 default:    nMove = 0; break;
375             }
376 
377             Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
378             IntersectClipRegion( rPolyPoly );
379             SetLineColor( GetFillColor() );
380             const sal_Bool bOldMap = mbMap;
381             EnableMapMode( sal_False );
382 
383             if(nMove)
384             {
385                 Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
386                 while( aRect.Top() <= aPolyRect.Bottom() )
387                 {
388                     DrawRect( aRect );
389                     aRect.Move( 0, nMove );
390                 }
391 
392                 aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
393                 while( aRect.Left() <= aPolyRect.Right() )
394                 {
395                     DrawRect( aRect );
396                     aRect.Move( nMove, 0 );
397                 }
398             }
399             else
400             {
401                 // #i112959# if not transparent, draw full rectangle in clip region
402                 DrawRect( aPolyRect );
403             }
404 
405             EnableMapMode( bOldMap );
406             Pop();
407         }
408         else
409         {
410             PolyPolygon     aPolyPoly( LogicToPixel( rPolyPoly ) );
411             Rectangle       aPolyRect( aPolyPoly.GetBoundRect() );
412             Point           aPoint;
413             Rectangle       aDstRect( aPoint, GetOutputSizePixel() );
414 
415             aDstRect.Intersection( aPolyRect );
416 
417             if( OUTDEV_WINDOW == meOutDevType )
418             {
419                 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
420 
421                 if( !aPaintRgn.IsNull() )
422                     aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
423             }
424 
425             if( !aDstRect.IsEmpty() )
426             {
427                 // #i66849# Added fast path for exactly rectangular
428                 // polygons
429                 // #i83087# Naturally, system alpha blending cannot
430                 // work with separate alpha VDev
431                 if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
432                 {
433                     // setup Graphics only here (other cases delegate
434                     // to basic OutDev methods)
435                     if( 1 )
436                     {
437                         if ( mbInitClipRegion )
438                             ImplInitClipRegion();
439                         if ( mbInitLineColor )
440                             ImplInitLineColor();
441                         if ( mbInitFillColor )
442                             ImplInitFillColor();
443 
444                         Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
445                         Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
446 
447                         if( !mbOutputClipped )
448                         {
449                             bDrawn = mpGraphics->DrawAlphaRect(
450                                aPixelRect.Left(), aPixelRect.Top(),
451                                // #i98405# use methods with small g, else one pixel too much will be painted.
452                                // This is because the source is a polygon which when painted would not paint
453                                // the rightmost and lowest pixel line(s), so use one pixel less for the
454                                // rectangle, too.
455                                aPixelRect.getWidth(), aPixelRect.getHeight(),
456                                sal::static_int_cast<sal_uInt8>(nTransparencePercent),
457                                this );
458                         }
459                         else
460                             bDrawn = true;
461                     }
462                 }
463 
464                 if( !bDrawn )
465                 {
466                     VirtualDevice   aVDev( *this, 1 );
467                     const Size      aDstSz( aDstRect.GetSize() );
468                     const sal_uInt8     cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
469 
470                     if( aDstRect.Left() || aDstRect.Top() )
471                         aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
472 
473                     if( aVDev.SetOutputSizePixel( aDstSz ) )
474                     {
475                         const sal_Bool bOldMap = mbMap;
476 
477                         EnableMapMode( sal_False );
478 
479                         aVDev.SetLineColor( COL_BLACK );
480                         aVDev.SetFillColor( COL_BLACK );
481                         aVDev.DrawPolyPolygon( aPolyPoly );
482 
483                         Bitmap              aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
484                         Bitmap              aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
485 
486                         // #107766# check for non-empty bitmaps before accessing them
487                         if( !!aPaint && !!aPolyMask )
488                         {
489                             BitmapWriteAccess*  pW = aPaint.AcquireWriteAccess();
490                             BitmapReadAccess*   pR = aPolyMask.AcquireReadAccess();
491 
492                             if( pW && pR )
493                             {
494                                 BitmapColor         aPixCol;
495                                 const BitmapColor   aFillCol( GetFillColor() );
496                                 const BitmapColor   aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
497                                 const BitmapColor   aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
498                                 const long          nWidth = pW->Width(), nHeight = pW->Height();
499                                 const long          nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
500                                 long                nX, nY;
501 
502                                 if( aPaint.GetBitCount() <= 8 )
503                                 {
504                                     const BitmapPalette&    rPal = pW->GetPalette();
505                                     const sal_uInt16            nCount = rPal.GetEntryCount();
506                                     BitmapColor*            pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ];
507 
508                                     for( sal_uInt16 i = 0; i < nCount; i++ )
509                                     {
510                                         BitmapColor aCol( rPal[ i ] );
511                                         pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
512                                     }
513 
514                                     if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
515                                         pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
516                                     {
517                                         const sal_uInt8 cBlack = aBlack.GetIndex();
518 
519                                         for( nY = 0; nY < nHeight; nY++ )
520                                         {
521                                             Scanline    pWScan = pW->GetScanline( nY );
522                                             Scanline    pRScan = pR->GetScanline( nY );
523                                             sal_uInt8       cBit = 128;
524 
525                                             for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
526                                             {
527                                                 if( !cBit )
528                                                     cBit = 128, pRScan++;
529 
530                                                 if( ( *pRScan & cBit ) == cBlack )
531                                                     *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex();
532                                             }
533                                         }
534                                     }
535                                     else
536                                     {
537                                         for( nY = 0; nY < nHeight; nY++ )
538                                             for( nX = 0; nX < nWidth; nX++ )
539                                                 if( pR->GetPixel( nY, nX ) == aBlack )
540                                                     pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
541                                     }
542 
543                                     delete[] (sal_uInt8*) pMap;
544                                 }
545                                 else
546                                 {
547                                     if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
548                                         pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
549                                     {
550                                         const sal_uInt8 cBlack = aBlack.GetIndex();
551 
552                                         for( nY = 0; nY < nHeight; nY++ )
553                                         {
554                                             Scanline    pWScan = pW->GetScanline( nY );
555                                             Scanline    pRScan = pR->GetScanline( nY );
556                                             sal_uInt8       cBit = 128;
557 
558                                             for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
559                                             {
560                                                 if( !cBit )
561                                                     cBit = 128, pRScan++;
562 
563                                                 if( ( *pRScan & cBit ) == cBlack )
564                                                 {
565                                                     pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
566                                                     pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
567                                                     pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
568                                                 }
569                                             }
570                                         }
571                                     }
572                                     else
573                                     {
574                                         for( nY = 0; nY < nHeight; nY++ )
575                                         {
576                                             for( nX = 0; nX < nWidth; nX++ )
577                                             {
578                                                 if( pR->GetPixel( nY, nX ) == aBlack )
579                                                 {
580                                                     aPixCol = pW->GetColor( nY, nX );
581                                                     pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
582                                                 }
583                                             }
584                                         }
585                                     }
586                                 }
587                             }
588 
589                             aPolyMask.ReleaseAccess( pR );
590                             aPaint.ReleaseAccess( pW );
591 
592                             DrawBitmap( aDstRect.TopLeft(), aPaint );
593 
594                             EnableMapMode( bOldMap );
595 
596                             if( mbLineColor )
597                             {
598                                 Push( PUSH_FILLCOLOR );
599                                 SetFillColor();
600                                 DrawPolyPolygon( rPolyPoly );
601                                 Pop();
602                             }
603                         }
604                     }
605                     else
606                         DrawPolyPolygon( rPolyPoly );
607                 }
608             }
609         }
610 
611         mpMetaFile = pOldMetaFile;
612 
613         // #110958# Restore disabled alpha VDev
614         mpAlphaVDev = pOldAlphaVDev;
615 
616         // #110958# Apply alpha value also to VDev alpha channel
617         if( mpAlphaVDev )
618         {
619             const Color aFillCol( mpAlphaVDev->GetFillColor() );
620             mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
621                                              sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
622                                              sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
623 
624             mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
625 
626             mpAlphaVDev->SetFillColor( aFillCol );
627         }
628     }
629 }
630 
631 // -----------------------------------------------------------------------
632 
633 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
634                                     const Size& rSize, const Gradient& rTransparenceGradient )
635 {
636     DBG_TRACE( "OutputDevice::DrawTransparent()" );
637     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
638 
639     const Color aBlack( COL_BLACK );
640 
641     if( mpMetaFile )
642         mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
643 
644     if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
645         ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
646     {
647         ( (GDIMetaFile&) rMtf ).WindStart();
648         ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
649         ( (GDIMetaFile&) rMtf ).WindStart();
650     }
651     else
652     {
653         GDIMetaFile*    pOldMetaFile = mpMetaFile;
654         Rectangle       aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
655         Point           aPoint;
656         Rectangle       aDstRect( aPoint, GetOutputSizePixel() );
657 
658         mpMetaFile = NULL;
659         aDstRect.Intersection( aOutRect );
660 
661         if( OUTDEV_WINDOW == meOutDevType )
662         {
663             const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
664 
665             if( !aPaintRgn.IsNull() )
666                 aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
667         }
668 
669         if( !aDstRect.IsEmpty() )
670         {
671             VirtualDevice* pVDev = new VirtualDevice;
672 
673             ((OutputDevice*)pVDev)->mnDPIX = mnDPIX;
674             ((OutputDevice*)pVDev)->mnDPIY = mnDPIY;
675 
676             if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
677             {
678                 if(GetAntialiasing())
679                 {
680                     // #i102109#
681                     // For MetaFile replay (see task) it may now be neccessary to take
682                     // into account that the content is AntiAlialised and needs to be masked
683                     // like that. Instead of masking, i will use a copy-modify-paste cycle
684                     // here (as i already use in the VclPrimiziveRenderer with successs)
685                     pVDev->SetAntialiasing(GetAntialiasing());
686 
687                     // create MapMode for buffer (offset needed) and set
688                     MapMode aMap(GetMapMode());
689                     const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
690                     aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
691                     pVDev->SetMapMode(aMap);
692 
693                     // copy MapMode state and disable for target
694                     const bool bOrigMapModeEnabled(IsMapModeEnabled());
695                     EnableMapMode(false);
696 
697                     // copy MapMode state and disable for buffer
698                     const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
699                     pVDev->EnableMapMode(false);
700 
701                     // copy content from original to buffer
702                     pVDev->DrawOutDev(
703                         aPoint, pVDev->GetOutputSizePixel(), // dest
704                         aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
705                         *this);
706 
707                     // draw MetaFile to buffer
708                     pVDev->EnableMapMode(bBufferMapModeEnabled);
709                     ((GDIMetaFile&)rMtf).WindStart();
710                     ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize);
711                     ((GDIMetaFile&)rMtf).WindStart();
712 
713                     // get content bitmap from buffer
714                     pVDev->EnableMapMode(false);
715                     const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
716 
717                     // create alpha mask from gradient and get as Bitmap
718                     pVDev->EnableMapMode(bBufferMapModeEnabled);
719                     pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
720                     pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
721                     pVDev->SetDrawMode(DRAWMODE_DEFAULT);
722                     pVDev->EnableMapMode(false);
723                     const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
724 
725                     // draw masked content to target and restore MapMode
726                     DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
727                     EnableMapMode(bOrigMapModeEnabled);
728                 }
729                 else
730                 {
731                     Bitmap      aPaint, aMask;
732                     AlphaMask   aAlpha;
733                     MapMode     aMap( GetMapMode() );
734                     Point       aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
735                     const sal_Bool  bOldMap = mbMap;
736 
737                     aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
738                     pVDev->SetMapMode( aMap );
739                     const sal_Bool  bVDevOldMap = pVDev->IsMapModeEnabled();
740 
741                     // create paint bitmap
742                     ( (GDIMetaFile&) rMtf ).WindStart();
743                     ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
744                     ( (GDIMetaFile&) rMtf ).WindStart();
745                     pVDev->EnableMapMode( sal_False );
746                     aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
747                     pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
748 
749                     // create mask bitmap
750                     pVDev->SetLineColor( COL_BLACK );
751                     pVDev->SetFillColor( COL_BLACK );
752                     pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
753                     pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
754                                         DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
755                     ( (GDIMetaFile&) rMtf ).WindStart();
756                     ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
757                     ( (GDIMetaFile&) rMtf ).WindStart();
758                     pVDev->EnableMapMode( sal_False );
759                     aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
760                     pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
761 
762                     // create alpha mask from gradient
763                     pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
764                     pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
765                     pVDev->SetDrawMode( DRAWMODE_DEFAULT );
766                     pVDev->EnableMapMode( sal_False );
767                     pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
768 
769                     aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
770 
771                     delete pVDev;
772 
773                     EnableMapMode( sal_False );
774                     DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
775                     EnableMapMode( bOldMap );
776                 }
777             }
778             else
779                 delete pVDev;
780         }
781 
782         mpMetaFile = pOldMetaFile;
783     }
784 }
785 
786 // -----------------------------------------------------------------------
787 
788 void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
789                                            long nWidth, long nHeight,
790                                            const Wallpaper& rWallpaper )
791 {
792     // Wallpaper ohne Umrandung zeichnen
793     Color aOldLineColor = GetLineColor();
794     Color aOldFillColor = GetFillColor();
795     SetLineColor();
796     SetFillColor( rWallpaper.GetColor() );
797     sal_Bool bMap = mbMap;
798     EnableMapMode( sal_False );
799     DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
800     SetLineColor( aOldLineColor );
801     SetFillColor( aOldFillColor );
802     EnableMapMode( bMap );
803 }
804 
805 // -----------------------------------------------------------------------
806 
807 void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
808                                             long nWidth, long nHeight,
809                                             const Wallpaper& rWallpaper )
810 {
811     BitmapEx                aBmpEx;
812     const BitmapEx*         pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
813     Point                   aPos;
814     Size                    aSize;
815     GDIMetaFile*            pOldMetaFile = mpMetaFile;
816     const WallpaperStyle    eStyle = rWallpaper.GetStyle();
817     const sal_Bool              bOldMap = mbMap;
818     sal_Bool                    bDrawn = sal_False;
819     sal_Bool                    bDrawGradientBackground = sal_False;
820     sal_Bool                    bDrawColorBackground = sal_False;
821 
822     if( pCached )
823         aBmpEx = *pCached;
824     else
825         aBmpEx = rWallpaper.GetBitmap();
826 
827     const long nBmpWidth = aBmpEx.GetSizePixel().Width();
828     const long nBmpHeight = aBmpEx.GetSizePixel().Height();
829     const sal_Bool bTransparent = aBmpEx.IsTransparent();
830 
831     // draw background
832     if( bTransparent )
833     {
834         if( rWallpaper.IsGradient() )
835             bDrawGradientBackground = sal_True;
836         else
837         {
838             if( !pCached && !rWallpaper.GetColor().GetTransparency() )
839             {
840                 VirtualDevice aVDev( *this );
841                 aVDev.SetBackground( rWallpaper.GetColor() );
842                 aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
843                 aVDev.DrawBitmapEx( Point(), aBmpEx );
844                 aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
845             }
846 
847             bDrawColorBackground = sal_True;
848         }
849     }
850     else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
851     {
852         if( rWallpaper.IsGradient() )
853             bDrawGradientBackground = sal_True;
854         else
855             bDrawColorBackground = sal_True;
856     }
857 
858     // background of bitmap?
859     if( bDrawGradientBackground )
860         ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
861     else if( bDrawColorBackground && bTransparent )
862     {
863         ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
864         bDrawColorBackground = sal_False;
865     }
866 
867     // calc pos and size
868     if( rWallpaper.IsRect() )
869     {
870         const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
871         aPos = aBound.TopLeft();
872         aSize = aBound.GetSize();
873     }
874     else
875     {
876         aPos = Point( nX, nY );
877         aSize = Size( nWidth, nHeight );
878     }
879 
880     mpMetaFile = NULL;
881     EnableMapMode( sal_False );
882     Push( PUSH_CLIPREGION );
883     IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
884 
885     switch( eStyle )
886     {
887         case( WALLPAPER_SCALE ):
888         {
889             if( !pCached || ( pCached->GetSizePixel() != aSize ) )
890             {
891                 if( pCached )
892                     rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
893 
894                 aBmpEx = rWallpaper.GetBitmap();
895                 aBmpEx.Scale( aSize );
896                 aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
897             }
898         }
899         break;
900 
901         case( WALLPAPER_TOPLEFT ):
902         break;
903 
904         case( WALLPAPER_TOP ):
905             aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
906         break;
907 
908         case( WALLPAPER_TOPRIGHT ):
909             aPos.X() += ( aSize.Width() - nBmpWidth );
910         break;
911 
912         case( WALLPAPER_LEFT ):
913             aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
914         break;
915 
916         case( WALLPAPER_CENTER ):
917         {
918             aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
919             aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
920         }
921         break;
922 
923         case( WALLPAPER_RIGHT ):
924         {
925             aPos.X() += ( aSize.Width() - nBmpWidth );
926             aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
927         }
928         break;
929 
930         case( WALLPAPER_BOTTOMLEFT ):
931             aPos.Y() += ( aSize.Height() - nBmpHeight );
932         break;
933 
934         case( WALLPAPER_BOTTOM ):
935         {
936             aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
937             aPos.Y() += ( aSize.Height() - nBmpHeight );
938         }
939         break;
940 
941         case( WALLPAPER_BOTTOMRIGHT ):
942         {
943             aPos.X() += ( aSize.Width() - nBmpWidth );
944             aPos.Y() += ( aSize.Height() - nBmpHeight );
945         }
946         break;
947 
948         default:
949         {
950             const long  nRight = nX + nWidth - 1L;
951             const long  nBottom = nY + nHeight - 1L;
952             long        nFirstX;
953             long        nFirstY;
954 
955             if( eStyle == WALLPAPER_TILE )
956             {
957                 nFirstX = aPos.X();
958                 nFirstY = aPos.Y();
959             }
960             else
961             {
962                 nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
963                 nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
964             }
965 
966             const long  nOffX = ( nFirstX - nX ) % nBmpWidth;
967             const long  nOffY = ( nFirstY - nY ) % nBmpHeight;
968             long        nStartX = nX + nOffX;
969             long        nStartY = nY + nOffY;
970 
971             if( nOffX > 0L )
972                 nStartX -= nBmpWidth;
973 
974             if( nOffY > 0L )
975                 nStartY -= nBmpHeight;
976 
977             for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
978                 for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
979                     DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
980 
981             bDrawn = sal_True;
982         }
983         break;
984     }
985 
986     if( !bDrawn )
987     {
988         // optimized for non-transparent bitmaps
989         if( bDrawColorBackground )
990         {
991             const Size      aBmpSize( aBmpEx.GetSizePixel() );
992             const Point     aTmpPoint;
993             const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
994             const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
995             Rectangle       aWorkRect;
996 
997             aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
998             aWorkRect.Justify();
999             aWorkRect.Intersection( aColRect );
1000             if( !aWorkRect.IsEmpty() )
1001             {
1002                 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1003                                         aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1004                                         rWallpaper );
1005             }
1006 
1007             aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
1008             aWorkRect.Justify();
1009             aWorkRect.Intersection( aColRect );
1010             if( !aWorkRect.IsEmpty() )
1011             {
1012                 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1013                                         aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1014                                         rWallpaper );
1015             }
1016 
1017             aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
1018             aWorkRect.Justify();
1019             aWorkRect.Intersection( aColRect );
1020             if( !aWorkRect.IsEmpty() )
1021             {
1022                 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1023                                         aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1024                                         rWallpaper );
1025             }
1026 
1027             aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
1028             aWorkRect.Justify();
1029             aWorkRect.Intersection( aColRect );
1030             if( !aWorkRect.IsEmpty() )
1031             {
1032                 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1033                                         aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1034                                         rWallpaper );
1035             }
1036         }
1037 
1038         DrawBitmapEx( aPos, aBmpEx );
1039     }
1040 
1041     rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
1042 
1043     Pop();
1044     EnableMapMode( bOldMap );
1045     mpMetaFile = pOldMetaFile;
1046 }
1047 
1048 // -----------------------------------------------------------------------
1049 
1050 void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
1051                                               long nWidth, long nHeight,
1052                                               const Wallpaper& rWallpaper )
1053 {
1054     Rectangle       aBound;
1055     GDIMetaFile*    pOldMetaFile = mpMetaFile;
1056     const sal_Bool      bOldMap = mbMap;
1057     sal_Bool            bNeedGradient = sal_True;
1058 
1059 /*
1060     if ( rWallpaper.IsRect() )
1061         aBound = LogicToPixel( rWallpaper.GetRect() );
1062     else
1063 */
1064         aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1065 
1066     mpMetaFile = NULL;
1067     EnableMapMode( sal_False );
1068     Push( PUSH_CLIPREGION );
1069     IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
1070 
1071     if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT )
1072     {
1073         Window *pWin = dynamic_cast< Window* >( this );
1074         if( pWin )
1075         {
1076             // limit gradient to useful size, so that it still can be noticed
1077             // in maximized windows
1078             long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width();
1079             if( gradientWidth > 1024 )
1080                 gradientWidth = 1024;
1081             if( mnOutOffX+nWidth > gradientWidth )
1082                 ImplDrawColorWallpaper(  nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() );
1083             if( mnOutOffX > gradientWidth )
1084                 bNeedGradient = sal_False;
1085             else
1086                 aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) );
1087         }
1088     }
1089 
1090     if( bNeedGradient )
1091         DrawGradient( aBound, rWallpaper.GetGradient() );
1092 
1093     Pop();
1094     EnableMapMode( bOldMap );
1095     mpMetaFile = pOldMetaFile;
1096 }
1097 
1098 // -----------------------------------------------------------------------
1099 
1100 void OutputDevice::ImplDrawWallpaper( long nX, long nY,
1101                                       long nWidth, long nHeight,
1102                                       const Wallpaper& rWallpaper )
1103 {
1104     if( rWallpaper.IsBitmap() )
1105         ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1106     else if( rWallpaper.IsGradient() )
1107         ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1108     else
1109         ImplDrawColorWallpaper(  nX, nY, nWidth, nHeight, rWallpaper );
1110 }
1111 
1112 // -----------------------------------------------------------------------
1113 
1114 void OutputDevice::DrawWallpaper( const Rectangle& rRect,
1115                                   const Wallpaper& rWallpaper )
1116 {
1117     if ( mpMetaFile )
1118         mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
1119 
1120     if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1121         return;
1122 
1123     if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
1124     {
1125         Rectangle aRect = LogicToPixel( rRect );
1126         aRect.Justify();
1127 
1128         if ( !aRect.IsEmpty() )
1129         {
1130             ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1131                                rWallpaper );
1132         }
1133     }
1134 
1135     if( mpAlphaVDev )
1136         mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
1137 }
1138 
1139 // -----------------------------------------------------------------------
1140 
1141 void OutputDevice::Erase()
1142 {
1143     if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1144         return;
1145 
1146     sal_Bool bNativeOK = sal_False;
1147 
1148     if( meOutDevType == OUTDEV_WINDOW )
1149     {
1150         Window* pWindow = static_cast<Window*>(this);
1151         ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground;
1152         if( aCtrlPart != 0 && ! pWindow->IsControlBackground() )
1153         {
1154             ImplControlValue    aControlValue;
1155             Point               aGcc3WorkaroundTemporary;
1156             Rectangle           aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() );
1157             ControlState        nState = 0;
1158 
1159             if( pWindow->IsEnabled() )              nState |= CTRL_STATE_ENABLED;
1160             bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
1161                                                     nState, aControlValue, rtl::OUString() );
1162         }
1163     }
1164 
1165     if ( mbBackground && ! bNativeOK )
1166     {
1167         RasterOp eRasterOp = GetRasterOp();
1168         if ( eRasterOp != ROP_OVERPAINT )
1169             SetRasterOp( ROP_OVERPAINT );
1170         ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
1171         if ( eRasterOp != ROP_OVERPAINT )
1172             SetRasterOp( eRasterOp );
1173     }
1174 
1175     if( mpAlphaVDev )
1176         mpAlphaVDev->Erase();
1177 }
1178 
1179 // -----------------------------------------------------------------------
1180 
1181 void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect,
1182                                         const Color& rLeftTopColor,
1183                                         const Color& rRightBottomColor )
1184 {
1185     SetFillColor( rLeftTopColor );
1186     DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
1187     DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
1188     SetFillColor( rRightBottomColor );
1189     DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
1190     DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
1191 }
1192 
1193 // -----------------------------------------------------------------------
1194 
1195 bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
1196                             const GfxLink& rGfxLink, GDIMetaFile* pSubst )
1197 {
1198     DBG_TRACE( "OutputDevice::DrawEPS()" );
1199 
1200     bool bDrawn(true);
1201 
1202     if ( mpMetaFile )
1203     {
1204         GDIMetaFile aSubst;
1205 
1206         if( pSubst )
1207             aSubst = *pSubst;
1208 
1209         mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
1210     }
1211 
1212     if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1213         return bDrawn;
1214 
1215     if( mbOutputClipped )
1216         return bDrawn;
1217 
1218     Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
1219 
1220     if( !aRect.IsEmpty() )
1221     {
1222         // draw the real EPS graphics
1223         if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
1224         {
1225             if( !mpGraphics && !ImplGetGraphics() )
1226                 return bDrawn;
1227 
1228             if( mbInitClipRegion )
1229                 ImplInitClipRegion();
1230 
1231             aRect.Justify();
1232             bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1233                          (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this );
1234         }
1235 
1236         // else draw the substitution graphics
1237         if( !bDrawn && pSubst )
1238         {
1239             GDIMetaFile* pOldMetaFile = mpMetaFile;
1240 
1241             mpMetaFile = NULL;
1242             Graphic( *pSubst ).Draw( this, rPoint, rSize );
1243             mpMetaFile = pOldMetaFile;
1244         }
1245     }
1246 
1247     if( mpAlphaVDev )
1248         mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
1249 
1250     return bDrawn;
1251 }
1252 
1253 // ------------------------------------------------------------------
1254 
1255 void OutputDevice::DrawRenderGraphic( const Point& rPoint, const Size& rSize,
1256                                       const ::vcl::RenderGraphic& rRenderGraphic )
1257 {
1258     DBG_TRACE( "OutputDevice::DrawRenderGraphic()" );
1259 
1260     if( mpMetaFile )
1261         mpMetaFile->AddAction( new MetaRenderGraphicAction( rPoint, rSize, rRenderGraphic ) );
1262 
1263     if( !rRenderGraphic.IsEmpty() )
1264     {
1265         ::vcl::RenderGraphicRasterizer  aRasterizer( rRenderGraphic );
1266         BitmapEx                        aBmpEx;
1267         const Size                      aSizePixel( LogicToPixel( rSize ) );
1268         GDIMetaFile*                    pOldMetaFile = mpMetaFile;
1269 
1270         mpMetaFile = NULL;
1271         DrawBitmapEx( rPoint, rSize, aRasterizer.Rasterize( aSizePixel ) );
1272         mpMetaFile = pOldMetaFile;
1273     }
1274 }
1275