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