xref: /trunk/main/vcl/source/gdi/outdev.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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/ref.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/poly.hxx>
34 
35 #include <vcl/svapp.hxx>
36 #include <vcl/ctrl.hxx>
37 #include <vcl/region.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/window.hxx>
40 #include <vcl/metaact.hxx>
41 #include <vcl/gdimtf.hxx>
42 #include <vcl/print.hxx>
43 #include <vcl/outdev.hxx>
44 #include <vcl/unowrap.hxx>
45 // declare system types in sysdata.hxx
46 #include <svsys.h>
47 #include <vcl/sysdata.hxx>
48 
49 #include <salgdi.hxx>
50 #include <sallayout.hxx>
51 #include <salframe.hxx>
52 #include <salvd.hxx>
53 #include <salprn.hxx>
54 #include <svdata.hxx>
55 #include <window.h>
56 #include <outdev.h>
57 #include <region.h>
58 #include <outdata.hxx>
59 
60 #include <basegfx/point/b2dpoint.hxx>
61 #include <basegfx/vector/b2dvector.hxx>
62 #include <basegfx/polygon/b2dpolygon.hxx>
63 #include <basegfx/polygon/b2dpolypolygon.hxx>
64 #include <basegfx/matrix/b2dhommatrix.hxx>
65 #include <basegfx/polygon/b2dpolygontools.hxx>
66 #include <basegfx/polygon/b2dpolypolygontools.hxx>
67 #include <basegfx/polygon/b2dlinegeometry.hxx>
68 
69 #include <com/sun/star/awt/XGraphics.hpp>
70 #include <com/sun/star/uno/Sequence.hxx>
71 #include <com/sun/star/rendering/XCanvas.hpp>
72 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
73 #include <vcl/unohelp.hxx>
74 
75 #include <numeric>
76 
77 using namespace ::com::sun::star;
78 
79 DBG_NAME( OutputDevice )
80 DBG_NAME( Polygon )
81 DBG_NAME( PolyPolygon )
82 DBG_NAMEEX( Region )
83 
84 // -----------------------------------------------------------------------
85 
86 #ifdef DBG_UTIL
87 const char* ImplDbgCheckOutputDevice( const void* pObj )
88 {
89     DBG_TESTSOLARMUTEX();
90 
91     const OutputDevice* pOutDev = (OutputDevice*)pObj;
92 
93     if ( (pOutDev->GetOutDevType() != OUTDEV_DONTKNOW) &&
94          (pOutDev->GetOutDevType() != OUTDEV_WINDOW) &&
95          (pOutDev->GetOutDevType() != OUTDEV_PRINTER) &&
96          (pOutDev->GetOutDevType() != OUTDEV_VIRDEV) )
97         return "OutputDevice data overwrite";
98 
99     return NULL;
100 }
101 #endif
102 
103 // =======================================================================
104 
105 #define OUTDEV_POLYPOLY_STACKBUF        32
106 
107 // =======================================================================
108 
109 struct ImplObjStack
110 {
111     ImplObjStack*   mpPrev;
112     MapMode*        mpMapMode;
113     Region*         mpClipRegion;
114     Color*          mpLineColor;
115     Color*          mpFillColor;
116     Font*           mpFont;
117     Color*          mpTextColor;
118     Color*          mpTextFillColor;
119     Color*          mpTextLineColor;
120     Color*          mpOverlineColor;
121     Point*          mpRefPoint;
122     TextAlign       meTextAlign;
123     RasterOp        meRasterOp;
124     sal_uLong           mnTextLayoutMode;
125     LanguageType    meTextLanguage;
126     sal_uInt16          mnFlags;
127 };
128 
129 // -----------------------------------------------------------------------
130 
131 static void ImplDeleteObjStack( ImplObjStack* pObjStack )
132 {
133     if ( pObjStack->mnFlags & PUSH_LINECOLOR )
134     {
135         if ( pObjStack->mpLineColor )
136             delete pObjStack->mpLineColor;
137     }
138     if ( pObjStack->mnFlags & PUSH_FILLCOLOR )
139     {
140         if ( pObjStack->mpFillColor )
141             delete pObjStack->mpFillColor;
142     }
143     if ( pObjStack->mnFlags & PUSH_FONT )
144         delete pObjStack->mpFont;
145     if ( pObjStack->mnFlags & PUSH_TEXTCOLOR )
146         delete pObjStack->mpTextColor;
147     if ( pObjStack->mnFlags & PUSH_TEXTFILLCOLOR )
148     {
149         if ( pObjStack->mpTextFillColor )
150             delete pObjStack->mpTextFillColor;
151     }
152     if ( pObjStack->mnFlags & PUSH_TEXTLINECOLOR )
153     {
154         if ( pObjStack->mpTextLineColor )
155             delete pObjStack->mpTextLineColor;
156     }
157     if ( pObjStack->mnFlags & PUSH_OVERLINECOLOR )
158     {
159         if ( pObjStack->mpOverlineColor )
160             delete pObjStack->mpOverlineColor;
161     }
162     if ( pObjStack->mnFlags & PUSH_MAPMODE )
163     {
164         if ( pObjStack->mpMapMode )
165             delete pObjStack->mpMapMode;
166     }
167     if ( pObjStack->mnFlags & PUSH_CLIPREGION )
168     {
169         if ( pObjStack->mpClipRegion )
170             delete pObjStack->mpClipRegion;
171     }
172     if ( pObjStack->mnFlags & PUSH_REFPOINT )
173     {
174         if ( pObjStack->mpRefPoint )
175             delete pObjStack->mpRefPoint;
176     }
177 
178     delete pObjStack;
179 }
180 
181 // -----------------------------------------------------------------------
182 
183 bool OutputDevice::ImplIsAntiparallel() const
184 {
185     bool bRet = false;
186     if( ImplGetGraphics() )
187     {
188         if( ( (mpGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL) && ! IsRTLEnabled() ) ||
189             ( ! (mpGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL) && IsRTLEnabled() ) )
190         {
191             bRet = true;
192         }
193     }
194     return bRet;
195 }
196 
197 // -----------------------------------------------------------------------
198 
199 
200 bool OutputDevice::ImplSelectClipRegion( const Region& rRegion, SalGraphics* pGraphics )
201 {
202     DBG_TESTSOLARMUTEX();
203 
204     if( !pGraphics )
205     {
206         if( !mpGraphics )
207             if( !ImplGetGraphics() )
208                 return false;
209         pGraphics = mpGraphics;
210     }
211 
212     bool bClipRegion = pGraphics->SetClipRegion( rRegion, this );
213     OSL_ENSURE( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't cerate region" );
214     return bClipRegion;
215 }
216 
217 
218 // =======================================================================
219 
220 Polygon ImplSubdivideBezier( const Polygon& rPoly )
221 {
222     Polygon aPoly;
223 
224     // #100127# Use adaptive subdivide instead of fixed 25 segments
225     rPoly.AdaptiveSubdivide( aPoly );
226 
227     return aPoly;
228 }
229 
230 // =======================================================================
231 
232 PolyPolygon ImplSubdivideBezier( const PolyPolygon& rPolyPoly )
233 {
234     sal_uInt16 i, nPolys = rPolyPoly.Count();
235     PolyPolygon aPolyPoly( nPolys );
236     for( i=0; i<nPolys; ++i )
237         aPolyPoly.Insert( ImplSubdivideBezier( rPolyPoly.GetObject(i) ) );
238 
239     return aPolyPoly;
240 }
241 
242 // =======================================================================
243 
244 // #100127# Extracted from OutputDevice::DrawPolyPolygon()
245 void OutputDevice::ImplDrawPolyPolygon( sal_uInt16 nPoly, const PolyPolygon& rPolyPoly )
246 {
247     // AW: This crashes on empty PolyPolygons, avoid that
248     if(!nPoly)
249         return;
250 
251     sal_uInt32          aStackAry1[OUTDEV_POLYPOLY_STACKBUF];
252     PCONSTSALPOINT      aStackAry2[OUTDEV_POLYPOLY_STACKBUF];
253     sal_uInt8*              aStackAry3[OUTDEV_POLYPOLY_STACKBUF];
254     sal_uInt32*         pPointAry;
255     PCONSTSALPOINT*     pPointAryAry;
256     const sal_uInt8**       pFlagAryAry;
257     sal_uInt16              i = 0, j = 0, last = 0;
258     sal_Bool                bHaveBezier = sal_False;
259     if ( nPoly > OUTDEV_POLYPOLY_STACKBUF )
260     {
261         pPointAry       = new sal_uInt32[nPoly];
262         pPointAryAry    = new PCONSTSALPOINT[nPoly];
263         pFlagAryAry     = new const sal_uInt8*[nPoly];
264     }
265     else
266     {
267         pPointAry       = aStackAry1;
268         pPointAryAry    = aStackAry2;
269         pFlagAryAry     = (const sal_uInt8**)aStackAry3;
270     }
271     do
272     {
273         const Polygon&  rPoly = rPolyPoly.GetObject( i );
274         sal_uInt16          nSize = rPoly.GetSize();
275         if ( nSize )
276         {
277             pPointAry[j]    = nSize;
278             pPointAryAry[j] = (PCONSTSALPOINT)rPoly.GetConstPointAry();
279             pFlagAryAry[j]  = rPoly.GetConstFlagAry();
280             last            = i;
281 
282             if( pFlagAryAry[j] )
283                 bHaveBezier = sal_True;
284 
285             ++j;
286         }
287 
288         ++i;
289     }
290     while ( i < nPoly );
291 
292     if ( j == 1 )
293     {
294         // #100127# Forward beziers to sal, if any
295         if( bHaveBezier )
296         {
297             if( !mpGraphics->DrawPolygonBezier( *pPointAry, *pPointAryAry, *pFlagAryAry, this ) )
298             {
299                 Polygon aPoly = ImplSubdivideBezier( rPolyPoly.GetObject( last ) );
300                 mpGraphics->DrawPolygon( aPoly.GetSize(), (const SalPoint*)aPoly.GetConstPointAry(), this );
301             }
302         }
303         else
304         {
305             mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry, this );
306         }
307     }
308     else
309     {
310         // #100127# Forward beziers to sal, if any
311         if( bHaveBezier )
312         {
313             if( !mpGraphics->DrawPolyPolygonBezier( j, pPointAry, pPointAryAry, pFlagAryAry, this ) )
314             {
315                 PolyPolygon aPolyPoly = ImplSubdivideBezier( rPolyPoly );
316                 ImplDrawPolyPolygon( aPolyPoly.Count(), aPolyPoly );
317             }
318         }
319         else
320         {
321             mpGraphics->DrawPolyPolygon( j, pPointAry, pPointAryAry, this );
322         }
323     }
324 
325     if ( pPointAry != aStackAry1 )
326     {
327         delete[] pPointAry;
328         delete[] pPointAryAry;
329         delete[] pFlagAryAry;
330     }
331 }
332 
333 // =======================================================================
334 
335 OutputDevice::OutputDevice() :
336     maRegion( REGION_NULL ),
337     maFillColor( COL_WHITE ),
338     maTextLineColor( COL_TRANSPARENT ),
339     maSettings( Application::GetSettings() )
340 {
341     DBG_CTOR( OutputDevice, ImplDbgCheckOutputDevice );
342 
343     mpGraphics          = NULL;
344     mpUnoGraphicsList   = NULL;
345     mpPrevGraphics      = NULL;
346     mpNextGraphics      = NULL;
347     mpMetaFile          = NULL;
348     mpFontEntry         = NULL;
349     mpFontCache         = NULL;
350     mpFontList          = NULL;
351     mpGetDevFontList    = NULL;
352     mpGetDevSizeList    = NULL;
353     mpObjStack          = NULL;
354     mpOutDevData        = NULL;
355     mpPDFWriter         = NULL;
356     mpAlphaVDev         = NULL;
357     mpExtOutDevData     = NULL;
358     mnOutOffX           = 0;
359     mnOutOffY           = 0;
360     mnOutWidth          = 0;
361     mnOutHeight         = 0;
362     mnDPIX              = 0;
363     mnDPIY              = 0;
364     mnTextOffX          = 0;
365     mnTextOffY          = 0;
366     mnOutOffOrigX       = 0;
367     mnOutOffLogicX      = 0;
368     mnOutOffOrigY       = 0;
369     mnOutOffLogicY      = 0;
370     mnEmphasisAscent    = 0;
371     mnEmphasisDescent   = 0;
372     mnDrawMode          = 0;
373     mnTextLayoutMode        = TEXT_LAYOUT_DEFAULT;
374     if( Application::GetSettings().GetLayoutRTL() ) //#i84553# tip BiDi preference to RTL
375         mnTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
376     meOutDevType        = OUTDEV_DONTKNOW;
377     meOutDevViewType    = OUTDEV_VIEWTYPE_DONTKNOW;
378     mbMap               = sal_False;
379     mbMapIsDefault      = sal_True;
380     mbClipRegion        = sal_False;
381     mbBackground        = sal_False;
382     mbOutput            = sal_True;
383     mbDevOutput         = sal_False;
384     mbOutputClipped     = sal_False;
385     maTextColor         = Color( COL_BLACK );
386     maOverlineColor     = Color( COL_TRANSPARENT );
387     meTextAlign         = maFont.GetAlign();
388     meRasterOp          = ROP_OVERPAINT;
389     mnAntialiasing      = 0;
390     meTextLanguage      = 0;  // TODO: get default from configuration?
391     mbLineColor         = sal_True;
392     mbFillColor         = sal_True;
393     mbInitLineColor     = sal_True;
394     mbInitFillColor     = sal_True;
395     mbInitFont          = sal_True;
396     mbInitTextColor     = sal_True;
397     mbInitClipRegion    = sal_True;
398     mbClipRegionSet     = sal_False;
399     mbKerning           = sal_False;
400     mbNewFont           = sal_True;
401     mbTextLines         = sal_False;
402     mbTextSpecial       = sal_False;
403     mbRefPoint          = sal_False;
404     mbEnableRTL         = sal_False;    // mirroring must be explicitly allowed (typically for windows only)
405 
406     // struct ImplMapRes
407     maMapRes.mnMapOfsX          = 0;
408     maMapRes.mnMapOfsY          = 0;
409     maMapRes.mnMapScNumX        = 1;
410     maMapRes.mnMapScNumY        = 1;
411     maMapRes.mnMapScDenomX      = 1;
412     maMapRes.mnMapScDenomY      = 1;
413     // struct ImplThresholdRes
414     maThresRes.mnThresLogToPixX = 0;
415     maThresRes.mnThresLogToPixY = 0;
416     maThresRes.mnThresPixToLogX = 0;
417     maThresRes.mnThresPixToLogY = 0;
418 }
419 
420 // -----------------------------------------------------------------------
421 
422 OutputDevice::~OutputDevice()
423 {
424     DBG_DTOR( OutputDevice, ImplDbgCheckOutputDevice );
425 
426     if ( GetUnoGraphicsList() )
427     {
428         UnoWrapperBase* pWrapper = Application::GetUnoWrapper( sal_False );
429         if ( pWrapper )
430             pWrapper->ReleaseAllGraphics( this );
431         delete mpUnoGraphicsList;
432         mpUnoGraphicsList = NULL;
433     }
434 
435     if ( mpOutDevData )
436         ImplDeInitOutDevData();
437 
438     ImplObjStack* pData = mpObjStack;
439     if ( pData )
440     {
441         DBG_ERRORFILE( "OutputDevice::~OutputDevice(): OutputDevice::Push() calls != OutputDevice::Pop() calls" );
442         while ( pData )
443         {
444             ImplObjStack* pTemp = pData;
445             pData = pData->mpPrev;
446             ImplDeleteObjStack( pTemp );
447         }
448     }
449 
450     // release the active font instance
451     if( mpFontEntry )
452         mpFontCache->Release( mpFontEntry );
453     // remove cached results of GetDevFontList/GetDevSizeList
454     // TODO: use smart pointers for them
455     if( mpGetDevFontList )
456         delete mpGetDevFontList;
457     if( mpGetDevSizeList )
458         delete mpGetDevSizeList;
459 
460     // release ImplFontCache specific to this OutputDevice
461     // TODO: refcount ImplFontCache
462     if( mpFontCache
463     && (mpFontCache != ImplGetSVData()->maGDIData.mpScreenFontCache)
464     && (ImplGetSVData()->maGDIData.mpScreenFontCache != NULL) )
465     {
466         delete mpFontCache;
467         mpFontCache = NULL;
468     }
469 
470     // release ImplFontList specific to this OutputDevice
471     // TODO: refcount ImplFontList
472     if( mpFontList
473     && (mpFontList != ImplGetSVData()->maGDIData.mpScreenFontList)
474     && (ImplGetSVData()->maGDIData.mpScreenFontList != NULL) )
475     {
476         mpFontList->Clear();
477         delete mpFontList;
478         mpFontList = NULL;
479     }
480 
481     delete mpAlphaVDev;
482 }
483 
484 bool OutputDevice::supportsOperation( OutDevSupportType eType ) const
485 {
486     if( !mpGraphics )
487         if( !ImplGetGraphics() )
488             return false;
489     const bool bHasSupport = mpGraphics->supportsOperation( eType );
490     return bHasSupport;
491 }
492 
493 // -----------------------------------------------------------------------
494 
495 void OutputDevice::EnableRTL( sal_Bool bEnable )
496 {
497     mbEnableRTL = (bEnable != 0);
498     if( meOutDevType == OUTDEV_VIRDEV )
499     {
500         // virdevs default to not mirroring, they will only be set to mirroring
501         // under rare circumstances in the UI, eg the valueset control
502         // because each virdev has its own SalGraphics we can safely switch the SalGraphics here
503         // ...hopefully
504         if( ImplGetGraphics() )
505             mpGraphics->SetLayout( mbEnableRTL ? SAL_LAYOUT_BIDI_RTL : 0 );
506     }
507 
508     // convenience: for controls also switch layout mode
509     if( dynamic_cast<Control*>(this) != 0 )
510         SetLayoutMode( bEnable ? TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT : TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_TEXTORIGIN_LEFT);
511 
512     Window* pWin = dynamic_cast<Window*>(this);
513     if( pWin )
514         pWin->StateChanged( STATE_CHANGE_MIRRORING );
515 
516     if( mpAlphaVDev )
517         mpAlphaVDev->EnableRTL( bEnable );
518 }
519 
520 sal_Bool OutputDevice::ImplHasMirroredGraphics()
521 {
522    // HOTFIX for #i55719#
523    if( meOutDevType == OUTDEV_PRINTER )
524        return sal_False;
525 
526    return ( ImplGetGraphics() && (mpGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL) );
527 }
528 
529 // note: the coordiantes to be remirrored are in frame coordiantes !
530 
531 void    OutputDevice::ImplReMirror( Point &rPoint ) const
532 {
533     rPoint.X() = mnOutOffX + mnOutWidth - 1 - rPoint.X() + mnOutOffX;
534 }
535 void    OutputDevice::ImplReMirror( Rectangle &rRect ) const
536 {
537     long nWidth = rRect.nRight - rRect.nLeft;
538 
539     //long lc_x = rRect.nLeft - mnOutOffX;    // normalize
540     //lc_x = mnOutWidth - nWidth - 1 - lc_x;  // mirror
541     //rRect.nLeft = lc_x + mnOutOffX;         // re-normalize
542 
543     rRect.nLeft = mnOutOffX + mnOutWidth - nWidth - 1 - rRect.nLeft + mnOutOffX;
544     rRect.nRight = rRect.nLeft + nWidth;
545 }
546 void    OutputDevice::ImplReMirror( Region &rRegion ) const
547 {
548     long                nX;
549     long                nY;
550     long                nWidth;
551     long                nHeight;
552     ImplRegionInfo      aInfo;
553     sal_Bool                bRegionRect;
554     Region              aMirroredRegion;
555 
556     bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
557     while ( bRegionRect )
558     {
559         Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
560         ImplReMirror( aRect );
561         aMirroredRegion.Union( aRect );
562         bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
563     }
564     rRegion = aMirroredRegion;
565 }
566 
567 
568 // -----------------------------------------------------------------------
569 
570 int OutputDevice::ImplGetGraphics() const
571 {
572     DBG_TESTSOLARMUTEX();
573 
574     if ( mpGraphics )
575         return sal_True;
576 
577     mbInitLineColor     = sal_True;
578     mbInitFillColor     = sal_True;
579     mbInitFont          = sal_True;
580     mbInitTextColor     = sal_True;
581     mbInitClipRegion    = sal_True;
582 
583     ImplSVData* pSVData = ImplGetSVData();
584     if ( meOutDevType == OUTDEV_WINDOW )
585     {
586         Window* pWindow = (Window*)this;
587 
588         mpGraphics = pWindow->mpWindowImpl->mpFrame->GetGraphics();
589         // try harder if no wingraphics was available directly
590         if ( !mpGraphics )
591         {
592             // find another output device in the same frame
593             OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
594             while ( pReleaseOutDev )
595             {
596                 if ( ((Window*)pReleaseOutDev)->mpWindowImpl->mpFrame == pWindow->mpWindowImpl->mpFrame )
597                     break;
598                 pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
599             }
600 
601             if ( pReleaseOutDev )
602             {
603                 // steal the wingraphics from the other outdev
604                 mpGraphics = pReleaseOutDev->mpGraphics;
605                 pReleaseOutDev->ImplReleaseGraphics( sal_False );
606             }
607             else
608             {
609                 // if needed retry after releasing least recently used wingraphics
610                 while ( !mpGraphics )
611                 {
612                     if ( !pSVData->maGDIData.mpLastWinGraphics )
613                         break;
614                     pSVData->maGDIData.mpLastWinGraphics->ImplReleaseGraphics();
615                     mpGraphics = pWindow->mpWindowImpl->mpFrame->GetGraphics();
616                 }
617             }
618         }
619 
620         // update global LRU list of wingraphics
621         if ( mpGraphics )
622         {
623             mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
624             pSVData->maGDIData.mpFirstWinGraphics = const_cast<OutputDevice*>(this);
625             if ( mpNextGraphics )
626                 mpNextGraphics->mpPrevGraphics = const_cast<OutputDevice*>(this);
627             if ( !pSVData->maGDIData.mpLastWinGraphics )
628                 pSVData->maGDIData.mpLastWinGraphics = const_cast<OutputDevice*>(this);
629         }
630     }
631     else if ( meOutDevType == OUTDEV_VIRDEV )
632     {
633         const VirtualDevice* pVirDev = (const VirtualDevice*)this;
634 
635         if ( pVirDev->mpVirDev )
636         {
637             mpGraphics = pVirDev->mpVirDev->GetGraphics();
638             // if needed retry after releasing least recently used virtual device graphics
639             while ( !mpGraphics )
640             {
641                 if ( !pSVData->maGDIData.mpLastVirGraphics )
642                     break;
643                 pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
644                 mpGraphics = pVirDev->mpVirDev->GetGraphics();
645             }
646             // update global LRU list of virtual device graphics
647             if ( mpGraphics )
648             {
649                 mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
650                 pSVData->maGDIData.mpFirstVirGraphics = const_cast<OutputDevice*>(this);
651                 if ( mpNextGraphics )
652                     mpNextGraphics->mpPrevGraphics = const_cast<OutputDevice*>(this);
653                 if ( !pSVData->maGDIData.mpLastVirGraphics )
654                     pSVData->maGDIData.mpLastVirGraphics = const_cast<OutputDevice*>(this);
655             }
656         }
657     }
658     else if ( meOutDevType == OUTDEV_PRINTER )
659     {
660         const Printer* pPrinter = (const Printer*)this;
661 
662         if ( pPrinter->mpJobGraphics )
663             mpGraphics = pPrinter->mpJobGraphics;
664         else if ( pPrinter->mpDisplayDev )
665         {
666             const VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
667             mpGraphics = pVirDev->mpVirDev->GetGraphics();
668             // if needed retry after releasing least recently used virtual device graphics
669             while ( !mpGraphics )
670             {
671                 if ( !pSVData->maGDIData.mpLastVirGraphics )
672                     break;
673                 pSVData->maGDIData.mpLastVirGraphics->ImplReleaseGraphics();
674                 mpGraphics = pVirDev->mpVirDev->GetGraphics();
675             }
676             // update global LRU list of virtual device graphics
677             if ( mpGraphics )
678             {
679                 mpNextGraphics = pSVData->maGDIData.mpFirstVirGraphics;
680                 pSVData->maGDIData.mpFirstVirGraphics = const_cast<OutputDevice*>(this);
681                 if ( mpNextGraphics )
682                     mpNextGraphics->mpPrevGraphics = const_cast<OutputDevice*>(this);
683                 if ( !pSVData->maGDIData.mpLastVirGraphics )
684                     pSVData->maGDIData.mpLastVirGraphics = const_cast<OutputDevice*>(this);
685             }
686         }
687         else
688         {
689             mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
690             // if needed retry after releasing least recently used printer graphics
691             while ( !mpGraphics )
692             {
693                 if ( !pSVData->maGDIData.mpLastPrnGraphics )
694                     break;
695                 pSVData->maGDIData.mpLastPrnGraphics->ImplReleaseGraphics();
696                 mpGraphics = pPrinter->mpInfoPrinter->GetGraphics();
697             }
698             // update global LRU list of printer graphics
699             if ( mpGraphics )
700             {
701                 mpNextGraphics = pSVData->maGDIData.mpFirstPrnGraphics;
702                 pSVData->maGDIData.mpFirstPrnGraphics = const_cast<OutputDevice*>(this);
703                 if ( mpNextGraphics )
704                     mpNextGraphics->mpPrevGraphics = const_cast<OutputDevice*>(this);
705                 if ( !pSVData->maGDIData.mpLastPrnGraphics )
706                     pSVData->maGDIData.mpLastPrnGraphics = const_cast<OutputDevice*>(this);
707             }
708         }
709     }
710 
711     if ( mpGraphics )
712     {
713         mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp), ROP_INVERT == meRasterOp );
714         mpGraphics->setAntiAliasB2DDraw(mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW);
715         return sal_True;
716     }
717 
718     return sal_False;
719 }
720 
721 // -----------------------------------------------------------------------
722 
723 void OutputDevice::ImplReleaseGraphics( sal_Bool bRelease )
724 {
725     DBG_TESTSOLARMUTEX();
726 
727     if ( !mpGraphics )
728         return;
729 
730     // release the fonts of the physically released graphics device
731     if( bRelease )
732     {
733 #ifndef UNX
734         // HACK to fix an urgent P1 printing issue fast
735         // WinSalPrinter does not respect GetGraphics/ReleaseGraphics conventions
736         // so Printer::mpGraphics often points to a dead WinSalGraphics
737         // TODO: fix WinSalPrinter's GetGraphics/ReleaseGraphics handling
738         if( meOutDevType != OUTDEV_PRINTER )
739 #endif
740         mpGraphics->ReleaseFonts();
741 
742         mbNewFont = true;
743         mbInitFont = true;
744 
745         if ( mpFontEntry )
746         {
747             mpFontCache->Release( mpFontEntry );
748             mpFontEntry = NULL;
749         }
750 
751         if ( mpGetDevFontList )
752         {
753             delete mpGetDevFontList;
754             mpGetDevFontList = NULL;
755         }
756 
757         if ( mpGetDevSizeList )
758         {
759             delete mpGetDevSizeList;
760             mpGetDevSizeList = NULL;
761         }
762     }
763 
764     ImplSVData* pSVData = ImplGetSVData();
765     if ( meOutDevType == OUTDEV_WINDOW )
766     {
767         Window* pWindow = (Window*)this;
768 
769         if ( bRelease )
770             pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
771         // remove from global LRU list of window graphics
772         if ( mpPrevGraphics )
773             mpPrevGraphics->mpNextGraphics = mpNextGraphics;
774         else
775             pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
776         if ( mpNextGraphics )
777             mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
778         else
779             pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
780     }
781     else if ( meOutDevType == OUTDEV_VIRDEV )
782     {
783         VirtualDevice* pVirDev = (VirtualDevice*)this;
784 
785         if ( bRelease )
786             pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
787         // remove from global LRU list of virtual device graphics
788         if ( mpPrevGraphics )
789             mpPrevGraphics->mpNextGraphics = mpNextGraphics;
790         else
791             pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
792         if ( mpNextGraphics )
793             mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
794         else
795             pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
796     }
797     else if ( meOutDevType == OUTDEV_PRINTER )
798     {
799         Printer* pPrinter = (Printer*)this;
800 
801         if ( !pPrinter->mpJobGraphics )
802         {
803             if ( pPrinter->mpDisplayDev )
804             {
805                 VirtualDevice* pVirDev = pPrinter->mpDisplayDev;
806                 if ( bRelease )
807                     pVirDev->mpVirDev->ReleaseGraphics( mpGraphics );
808                 // remove from global LRU list of virtual device graphics
809                 if ( mpPrevGraphics )
810                     mpPrevGraphics->mpNextGraphics = mpNextGraphics;
811                 else
812                     pSVData->maGDIData.mpFirstVirGraphics = mpNextGraphics;
813                 if ( mpNextGraphics )
814                     mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
815                 else
816                     pSVData->maGDIData.mpLastVirGraphics = mpPrevGraphics;
817             }
818             else
819             {
820                 if ( bRelease )
821                     pPrinter->mpInfoPrinter->ReleaseGraphics( mpGraphics );
822                 // remove from global LRU list of printer graphics
823                 if ( mpPrevGraphics )
824                     mpPrevGraphics->mpNextGraphics = mpNextGraphics;
825                 else
826                     pSVData->maGDIData.mpFirstPrnGraphics = mpNextGraphics;
827                 if ( mpNextGraphics )
828                     mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
829                 else
830                     pSVData->maGDIData.mpLastPrnGraphics = mpPrevGraphics;
831            }
832         }
833     }
834 
835     mpGraphics      = NULL;
836     mpPrevGraphics  = NULL;
837     mpNextGraphics  = NULL;
838 }
839 
840 // -----------------------------------------------------------------------
841 
842 void OutputDevice::ImplInitOutDevData()
843 {
844     if ( !mpOutDevData )
845     {
846         mpOutDevData = new ImplOutDevData;
847         mpOutDevData->mpRotateDev = NULL;
848         mpOutDevData->mpRecordLayout = NULL;
849 
850         // #i75163#
851         mpOutDevData->mpViewTransform = NULL;
852         mpOutDevData->mpInverseViewTransform = NULL;
853     }
854 }
855 
856 // -----------------------------------------------------------------------
857 
858 // #i75163#
859 void OutputDevice::ImplInvalidateViewTransform()
860 {
861     if(mpOutDevData)
862     {
863         if(mpOutDevData->mpViewTransform)
864         {
865             delete mpOutDevData->mpViewTransform;
866             mpOutDevData->mpViewTransform = NULL;
867         }
868 
869         if(mpOutDevData->mpInverseViewTransform)
870         {
871             delete mpOutDevData->mpInverseViewTransform;
872             mpOutDevData->mpInverseViewTransform = NULL;
873         }
874     }
875 }
876 
877 // -----------------------------------------------------------------------
878 
879 sal_Bool OutputDevice::ImplIsRecordLayout() const
880 {
881     return mpOutDevData && mpOutDevData->mpRecordLayout;
882 }
883 
884 // -----------------------------------------------------------------------
885 
886 void OutputDevice::ImplDeInitOutDevData()
887 {
888     if ( mpOutDevData )
889     {
890         if ( mpOutDevData->mpRotateDev )
891             delete mpOutDevData->mpRotateDev;
892 
893         // #i75163#
894         ImplInvalidateViewTransform();
895 
896         delete mpOutDevData;
897     }
898 }
899 
900 // -----------------------------------------------------------------------
901 
902 void OutputDevice::ImplInitLineColor()
903 {
904     DBG_TESTSOLARMUTEX();
905 
906     if( mbLineColor )
907     {
908         if( ROP_0 == meRasterOp )
909             mpGraphics->SetROPLineColor( SAL_ROP_0 );
910         else if( ROP_1 == meRasterOp )
911             mpGraphics->SetROPLineColor( SAL_ROP_1 );
912         else if( ROP_INVERT == meRasterOp )
913             mpGraphics->SetROPLineColor( SAL_ROP_INVERT );
914         else
915             mpGraphics->SetLineColor( ImplColorToSal( maLineColor ) );
916     }
917     else
918         mpGraphics->SetLineColor();
919 
920     mbInitLineColor = sal_False;
921 }
922 
923 // -----------------------------------------------------------------------
924 
925 void OutputDevice::ImplInitFillColor()
926 {
927     DBG_TESTSOLARMUTEX();
928 
929     if( mbFillColor )
930     {
931         if( ROP_0 == meRasterOp )
932             mpGraphics->SetROPFillColor( SAL_ROP_0 );
933         else if( ROP_1 == meRasterOp )
934             mpGraphics->SetROPFillColor( SAL_ROP_1 );
935         else if( ROP_INVERT == meRasterOp )
936             mpGraphics->SetROPFillColor( SAL_ROP_INVERT );
937         else
938             mpGraphics->SetFillColor( ImplColorToSal( maFillColor ) );
939     }
940     else
941         mpGraphics->SetFillColor();
942 
943     mbInitFillColor = sal_False;
944 }
945 
946 // -----------------------------------------------------------------------
947 
948 void OutputDevice::ImplInitClipRegion()
949 {
950     DBG_TESTSOLARMUTEX();
951 
952     if ( GetOutDevType() == OUTDEV_WINDOW )
953     {
954         Window* pWindow = (Window*)this;
955         Region  aRegion;
956 
957         // Hintergrund-Sicherung zuruecksetzen
958         if ( pWindow->mpWindowImpl->mpFrameData->mpFirstBackWin )
959             pWindow->ImplInvalidateAllOverlapBackgrounds();
960         if ( pWindow->mpWindowImpl->mbInPaint )
961             aRegion = *(pWindow->mpWindowImpl->mpPaintRegion);
962         else
963         {
964             aRegion = *(pWindow->ImplGetWinChildClipRegion());
965             // --- RTL -- only this region is in frame coordinates, so re-mirror it
966             // the mpWindowImpl->mpPaintRegion above is already correct (see ImplCallPaint()) !
967             if( ImplIsAntiparallel() )
968                 ImplReMirror ( aRegion );
969         }
970         if ( mbClipRegion )
971             aRegion.Intersect( ImplPixelToDevicePixel( maRegion ) );
972         if ( aRegion.IsEmpty() )
973             mbOutputClipped = sal_True;
974         else
975         {
976             mbOutputClipped = sal_False;
977             ImplSelectClipRegion( aRegion );
978         }
979         mbClipRegionSet = sal_True;
980     }
981     else
982     {
983         if ( mbClipRegion )
984         {
985             if ( maRegion.IsEmpty() )
986                 mbOutputClipped = sal_True;
987             else
988             {
989                 mbOutputClipped = sal_False;
990 
991                 // #102532# Respect output offset also for clip region
992                 Region aRegion( ImplPixelToDevicePixel( maRegion ) );
993                 const bool bClipDeviceBounds( ! GetPDFWriter()
994                                               && GetOutDevType() != OUTDEV_PRINTER );
995                 if( bClipDeviceBounds )
996                 {
997                     // #b6520266# Perform actual rect clip against outdev
998                     // dimensions, to generate empty clips whenever one of the
999                     // values is completely off the device.
1000                     Rectangle aDeviceBounds( mnOutOffX, mnOutOffY,
1001                                              mnOutOffX+GetOutputWidthPixel()-1,
1002                                              mnOutOffY+GetOutputHeightPixel()-1 );
1003                     aRegion.Intersect( aDeviceBounds );
1004                 }
1005                 ImplSelectClipRegion( aRegion );
1006             }
1007 
1008             mbClipRegionSet = sal_True;
1009         }
1010         else
1011         {
1012             if ( mbClipRegionSet )
1013             {
1014                 mpGraphics->ResetClipRegion();
1015                 mbClipRegionSet = sal_False;
1016             }
1017 
1018             mbOutputClipped = sal_False;
1019         }
1020     }
1021 
1022     mbInitClipRegion = sal_False;
1023 }
1024 
1025 // -----------------------------------------------------------------------
1026 
1027 void OutputDevice::ImplSetClipRegion( const Region* pRegion )
1028 {
1029     DBG_TESTSOLARMUTEX();
1030 
1031     if ( !pRegion )
1032     {
1033         if ( mbClipRegion )
1034         {
1035             maRegion            = Region( REGION_NULL );
1036             mbClipRegion        = sal_False;
1037             mbInitClipRegion    = sal_True;
1038         }
1039     }
1040     else
1041     {
1042         maRegion            = *pRegion;
1043         mbClipRegion        = sal_True;
1044         mbInitClipRegion    = sal_True;
1045     }
1046 }
1047 
1048 // -----------------------------------------------------------------------
1049 
1050 void OutputDevice::SetClipRegion()
1051 {
1052     DBG_TRACE( "OutputDevice::SetClipRegion()" );
1053     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1054 
1055     if ( mpMetaFile )
1056         mpMetaFile->AddAction( new MetaClipRegionAction( Region(), sal_False ) );
1057 
1058     ImplSetClipRegion( NULL );
1059 
1060     if( mpAlphaVDev )
1061         mpAlphaVDev->SetClipRegion();
1062 }
1063 
1064 // -----------------------------------------------------------------------
1065 
1066 void OutputDevice::SetClipRegion( const Region& rRegion )
1067 {
1068     DBG_TRACE( "OutputDevice::SetClipRegion( rRegion )" );
1069     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1070     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
1071 
1072     if ( mpMetaFile )
1073         mpMetaFile->AddAction( new MetaClipRegionAction( rRegion, sal_True ) );
1074 
1075     if ( rRegion.GetType() == REGION_NULL )
1076         ImplSetClipRegion( NULL );
1077     else
1078     {
1079         Region aRegion = LogicToPixel( rRegion );
1080         ImplSetClipRegion( &aRegion );
1081     }
1082 
1083     if( mpAlphaVDev )
1084         mpAlphaVDev->SetClipRegion( rRegion );
1085 }
1086 
1087 // -----------------------------------------------------------------------
1088 
1089 Region OutputDevice::GetClipRegion() const
1090 {
1091     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1092 
1093     return PixelToLogic( maRegion );
1094 }
1095 
1096 // -----------------------------------------------------------------------
1097 
1098 Region OutputDevice::GetActiveClipRegion() const
1099 {
1100     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1101 
1102     if ( GetOutDevType() == OUTDEV_WINDOW )
1103     {
1104         Region aRegion( REGION_NULL );
1105         Window* pWindow = (Window*)this;
1106         if ( pWindow->mpWindowImpl->mbInPaint )
1107         {
1108             aRegion = *(pWindow->mpWindowImpl->mpPaintRegion);
1109             aRegion.Move( -mnOutOffX, -mnOutOffY );
1110         }
1111         if ( mbClipRegion )
1112             aRegion.Intersect( maRegion );
1113         return PixelToLogic( aRegion );
1114     }
1115     else
1116         return GetClipRegion();
1117 }
1118 
1119 // -----------------------------------------------------------------------
1120 
1121 void OutputDevice::MoveClipRegion( long nHorzMove, long nVertMove )
1122 {
1123     DBG_TRACE( "OutputDevice::MoveClipRegion()" );
1124     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1125 
1126     if ( mbClipRegion )
1127     {
1128         if( mpMetaFile )
1129             mpMetaFile->AddAction( new MetaMoveClipRegionAction( nHorzMove, nVertMove ) );
1130 
1131         maRegion.Move( ImplLogicWidthToDevicePixel( nHorzMove ),
1132                        ImplLogicHeightToDevicePixel( nVertMove ) );
1133         mbInitClipRegion = sal_True;
1134     }
1135 
1136     if( mpAlphaVDev )
1137         mpAlphaVDev->MoveClipRegion( nHorzMove, nVertMove );
1138 }
1139 
1140 // -----------------------------------------------------------------------
1141 
1142 void OutputDevice::IntersectClipRegion( const Rectangle& rRect )
1143 {
1144     DBG_TRACE( "OutputDevice::IntersectClipRegion( rRect )" );
1145     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1146 
1147     if ( mpMetaFile )
1148         mpMetaFile->AddAction( new MetaISectRectClipRegionAction( rRect ) );
1149 
1150     Rectangle aRect = LogicToPixel( rRect );
1151     maRegion.Intersect( aRect );
1152     mbClipRegion        = sal_True;
1153     mbInitClipRegion    = sal_True;
1154 
1155     if( mpAlphaVDev )
1156         mpAlphaVDev->IntersectClipRegion( rRect );
1157 }
1158 
1159 // -----------------------------------------------------------------------
1160 
1161 void OutputDevice::IntersectClipRegion( const Region& rRegion )
1162 {
1163     DBG_TRACE( "OutputDevice::IntersectClipRegion( rRegion )" );
1164     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1165     DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
1166 
1167     RegionType eType = rRegion.GetType();
1168 
1169     if ( eType != REGION_NULL )
1170     {
1171         if ( mpMetaFile )
1172             mpMetaFile->AddAction( new MetaISectRegionClipRegionAction( rRegion ) );
1173 
1174         Region aRegion = LogicToPixel( rRegion );
1175         maRegion.Intersect( aRegion );
1176         mbClipRegion        = sal_True;
1177         mbInitClipRegion    = sal_True;
1178     }
1179 
1180     if( mpAlphaVDev )
1181         mpAlphaVDev->IntersectClipRegion( rRegion );
1182 }
1183 
1184 // -----------------------------------------------------------------------
1185 
1186 void OutputDevice::SetDrawMode( sal_uLong nDrawMode )
1187 {
1188     DBG_TRACE1( "OutputDevice::SetDrawMode( %lx )", nDrawMode );
1189     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1190 
1191     mnDrawMode = nDrawMode;
1192 
1193     if( mpAlphaVDev )
1194         mpAlphaVDev->SetDrawMode( nDrawMode );
1195 }
1196 
1197 // -----------------------------------------------------------------------
1198 
1199 void OutputDevice::SetRasterOp( RasterOp eRasterOp )
1200 {
1201     DBG_TRACE1( "OutputDevice::SetRasterOp( %d )", (int)eRasterOp );
1202     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1203 
1204     if ( mpMetaFile )
1205         mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) );
1206 
1207     if ( meRasterOp != eRasterOp )
1208     {
1209         meRasterOp = eRasterOp;
1210         mbInitLineColor = mbInitFillColor = sal_True;
1211 
1212         if( mpGraphics || ImplGetGraphics() )
1213             mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp), ROP_INVERT == meRasterOp );
1214     }
1215 
1216     if( mpAlphaVDev )
1217         mpAlphaVDev->SetRasterOp( eRasterOp );
1218 }
1219 
1220 // -----------------------------------------------------------------------
1221 
1222 void OutputDevice::SetLineColor()
1223 {
1224     DBG_TRACE( "OutputDevice::SetLineColor()" );
1225     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1226 
1227     if ( mpMetaFile )
1228         mpMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) );
1229 
1230     if ( mbLineColor )
1231     {
1232         mbInitLineColor = sal_True;
1233         mbLineColor = sal_False;
1234         maLineColor = Color( COL_TRANSPARENT );
1235     }
1236 
1237     if( mpAlphaVDev )
1238         mpAlphaVDev->SetLineColor();
1239 }
1240 
1241 // -----------------------------------------------------------------------
1242 
1243 void OutputDevice::SetLineColor( const Color& rColor )
1244 {
1245     DBG_TRACE1( "OutputDevice::SetLineColor( %lx )", rColor.GetColor() );
1246     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1247 
1248     Color aColor( rColor );
1249 
1250     if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
1251                        DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE |
1252                        DRAWMODE_SETTINGSLINE ) )
1253     {
1254         if( !ImplIsColorTransparent( aColor ) )
1255         {
1256             if( mnDrawMode & DRAWMODE_BLACKLINE )
1257             {
1258                 aColor = Color( COL_BLACK );
1259             }
1260             else if( mnDrawMode & DRAWMODE_WHITELINE )
1261             {
1262                 aColor = Color( COL_WHITE );
1263             }
1264             else if( mnDrawMode & DRAWMODE_GRAYLINE )
1265             {
1266                 const sal_uInt8 cLum = aColor.GetLuminance();
1267                 aColor = Color( cLum, cLum, cLum );
1268             }
1269             else if( mnDrawMode & DRAWMODE_SETTINGSLINE )
1270             {
1271                 aColor = GetSettings().GetStyleSettings().GetFontColor();
1272             }
1273 
1274             if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
1275             {
1276                 aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
1277                                 ( aColor.GetGreen() >> 1 ) | 0x80,
1278                                 ( aColor.GetBlue() >> 1 ) | 0x80);
1279             }
1280         }
1281     }
1282 
1283     if( mpMetaFile )
1284         mpMetaFile->AddAction( new MetaLineColorAction( aColor, sal_True ) );
1285 
1286     if( ImplIsColorTransparent( aColor ) )
1287     {
1288         if ( mbLineColor )
1289         {
1290             mbInitLineColor = sal_True;
1291             mbLineColor = sal_False;
1292             maLineColor = Color( COL_TRANSPARENT );
1293         }
1294     }
1295     else
1296     {
1297         if( maLineColor != aColor )
1298         {
1299             mbInitLineColor = sal_True;
1300             mbLineColor = sal_True;
1301             maLineColor = aColor;
1302         }
1303     }
1304 
1305     if( mpAlphaVDev )
1306         mpAlphaVDev->SetLineColor( COL_BLACK );
1307 }
1308 
1309 // -----------------------------------------------------------------------
1310 
1311 void OutputDevice::SetFillColor()
1312 {
1313     DBG_TRACE( "OutputDevice::SetFillColor()" );
1314     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1315 
1316     if ( mpMetaFile )
1317         mpMetaFile->AddAction( new MetaFillColorAction( Color(), sal_False ) );
1318 
1319     if ( mbFillColor )
1320     {
1321         mbInitFillColor = sal_True;
1322         mbFillColor = sal_False;
1323         maFillColor = Color( COL_TRANSPARENT );
1324     }
1325 
1326     if( mpAlphaVDev )
1327         mpAlphaVDev->SetFillColor();
1328 }
1329 
1330 // -----------------------------------------------------------------------
1331 
1332 void OutputDevice::SetFillColor( const Color& rColor )
1333 {
1334     DBG_TRACE1( "OutputDevice::SetFillColor( %lx )", rColor.GetColor() );
1335     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1336 
1337     Color aColor( rColor );
1338 
1339     if( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL |
1340                        DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
1341                        DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
1342     {
1343         if( !ImplIsColorTransparent( aColor ) )
1344         {
1345             if( mnDrawMode & DRAWMODE_BLACKFILL )
1346             {
1347                 aColor = Color( COL_BLACK );
1348             }
1349             else if( mnDrawMode & DRAWMODE_WHITEFILL )
1350             {
1351                 aColor = Color( COL_WHITE );
1352             }
1353             else if( mnDrawMode & DRAWMODE_GRAYFILL )
1354             {
1355                 const sal_uInt8 cLum = aColor.GetLuminance();
1356                 aColor = Color( cLum, cLum, cLum );
1357             }
1358             else if( mnDrawMode & DRAWMODE_NOFILL )
1359             {
1360                 aColor = Color( COL_TRANSPARENT );
1361             }
1362             else if( mnDrawMode & DRAWMODE_SETTINGSFILL )
1363             {
1364                 aColor = GetSettings().GetStyleSettings().GetWindowColor();
1365             }
1366 
1367             if( mnDrawMode & DRAWMODE_GHOSTEDFILL )
1368             {
1369                 aColor = Color( (aColor.GetRed() >> 1) | 0x80,
1370                                 (aColor.GetGreen() >> 1) | 0x80,
1371                                 (aColor.GetBlue() >> 1) | 0x80);
1372             }
1373         }
1374     }
1375 
1376     if ( mpMetaFile )
1377         mpMetaFile->AddAction( new MetaFillColorAction( aColor, sal_True ) );
1378 
1379     if ( ImplIsColorTransparent( aColor ) )
1380     {
1381         if ( mbFillColor )
1382         {
1383             mbInitFillColor = sal_True;
1384             mbFillColor = sal_False;
1385             maFillColor = Color( COL_TRANSPARENT );
1386         }
1387     }
1388     else
1389     {
1390         if ( maFillColor != aColor )
1391         {
1392             mbInitFillColor = sal_True;
1393             mbFillColor = sal_True;
1394             maFillColor = aColor;
1395         }
1396     }
1397 
1398     if( mpAlphaVDev )
1399         mpAlphaVDev->SetFillColor( COL_BLACK );
1400 }
1401 
1402 // -----------------------------------------------------------------------
1403 
1404 void OutputDevice::SetBackground()
1405 {
1406     DBG_TRACE( "OutputDevice::SetBackground()" );
1407     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1408 
1409     maBackground = Wallpaper();
1410     mbBackground = sal_False;
1411 
1412     if( mpAlphaVDev )
1413         mpAlphaVDev->SetBackground();
1414 }
1415 
1416 // -----------------------------------------------------------------------
1417 
1418 void OutputDevice::SetBackground( const Wallpaper& rBackground )
1419 {
1420     DBG_TRACE( "OutputDevice::SetBackground( rBackground )" );
1421     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1422 
1423     maBackground = rBackground;
1424 
1425     if( rBackground.GetStyle() == WALLPAPER_NULL )
1426         mbBackground = sal_False;
1427     else
1428         mbBackground = sal_True;
1429 
1430     if( mpAlphaVDev )
1431         mpAlphaVDev->SetBackground( rBackground );
1432 }
1433 
1434 // -----------------------------------------------------------------------
1435 
1436 void OutputDevice::SetRefPoint()
1437 {
1438     DBG_TRACE( "OutputDevice::SetRefPoint()" );
1439     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1440 
1441     if ( mpMetaFile )
1442         mpMetaFile->AddAction( new MetaRefPointAction( Point(), sal_False ) );
1443 
1444     mbRefPoint = sal_False;
1445     maRefPoint.X() = maRefPoint.Y() = 0L;
1446 
1447     if( mpAlphaVDev )
1448         mpAlphaVDev->SetRefPoint();
1449 }
1450 
1451 // -----------------------------------------------------------------------
1452 
1453 void OutputDevice::SetRefPoint( const Point& rRefPoint )
1454 {
1455     DBG_TRACE( "OutputDevice::SetRefPoint( rRefPoint )" );
1456     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1457 
1458     if ( mpMetaFile )
1459         mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, sal_True ) );
1460 
1461     mbRefPoint = sal_True;
1462     maRefPoint = rRefPoint;
1463 
1464     if( mpAlphaVDev )
1465         mpAlphaVDev->SetRefPoint( rRefPoint );
1466 }
1467 
1468 // -----------------------------------------------------------------------
1469 
1470 void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
1471 {
1472     DBG_TRACE( "OutputDevice::DrawLine()" );
1473     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1474 
1475     if ( mpMetaFile )
1476         mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt ) );
1477 
1478     if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
1479         return;
1480 
1481     if ( !mpGraphics )
1482     {
1483         if ( !ImplGetGraphics() )
1484             return;
1485     }
1486 
1487     if ( mbInitClipRegion )
1488         ImplInitClipRegion();
1489     if ( mbOutputClipped )
1490         return;
1491 
1492     if ( mbInitLineColor )
1493         ImplInitLineColor();
1494 
1495     // #i101598# support AA and snap for lines, too
1496     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
1497         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
1498         && ROP_OVERPAINT == GetRasterOp()
1499         && IsLineColor())
1500     {
1501         // at least transform with double precision to device coordinates; this will
1502         // avoid pixel snap of single, appended lines
1503         const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
1504         const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
1505         basegfx::B2DPolygon aB2DPolyLine;
1506 
1507         aB2DPolyLine.append(basegfx::B2DPoint(rStartPt.X(), rStartPt.Y()));
1508         aB2DPolyLine.append(basegfx::B2DPoint(rEndPt.X(), rEndPt.Y()));
1509         aB2DPolyLine.transform( aTransform );
1510 
1511         if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
1512         {
1513             aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
1514         }
1515 
1516         if( mpGraphics->DrawPolyLine( aB2DPolyLine, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
1517         {
1518             return;
1519         }
1520     }
1521 
1522     const Point aStartPt(ImplLogicToDevicePixel(rStartPt));
1523     const Point aEndPt(ImplLogicToDevicePixel(rEndPt));
1524 
1525     mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this );
1526 
1527     if( mpAlphaVDev )
1528         mpAlphaVDev->DrawLine( rStartPt, rEndPt );
1529 }
1530 
1531 // -----------------------------------------------------------------------
1532 
1533 void OutputDevice::impPaintLineGeometryWithEvtlExpand(
1534     const LineInfo& rInfo,
1535     basegfx::B2DPolyPolygon aLinePolyPolygon)
1536 {
1537     const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
1538         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
1539         && ROP_OVERPAINT == GetRasterOp()
1540         && IsLineColor());
1541     basegfx::B2DPolyPolygon aFillPolyPolygon;
1542     const bool bDashUsed(LINE_DASH == rInfo.GetStyle());
1543     const bool bLineWidthUsed(rInfo.GetWidth() > 1);
1544 
1545     if(bDashUsed && aLinePolyPolygon.count())
1546     {
1547         ::std::vector< double > fDotDashArray;
1548         const double fDashLen(rInfo.GetDashLen());
1549         const double fDotLen(rInfo.GetDotLen());
1550         const double fDistance(rInfo.GetDistance());
1551 
1552         for(sal_uInt16 a(0); a < rInfo.GetDashCount(); a++)
1553         {
1554             fDotDashArray.push_back(fDashLen);
1555             fDotDashArray.push_back(fDistance);
1556         }
1557 
1558         for(sal_uInt16 b(0); b < rInfo.GetDotCount(); b++)
1559         {
1560             fDotDashArray.push_back(fDotLen);
1561             fDotDashArray.push_back(fDistance);
1562         }
1563 
1564         const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
1565 
1566         if(fAccumulated > 0.0)
1567         {
1568             basegfx::B2DPolyPolygon aResult;
1569 
1570             for(sal_uInt32 c(0); c < aLinePolyPolygon.count(); c++)
1571             {
1572                 basegfx::B2DPolyPolygon aLineTraget;
1573                 basegfx::tools::applyLineDashing(
1574                     aLinePolyPolygon.getB2DPolygon(c),
1575                     fDotDashArray,
1576                     &aLineTraget);
1577                 aResult.append(aLineTraget);
1578             }
1579 
1580             aLinePolyPolygon = aResult;
1581         }
1582     }
1583 
1584     if(bLineWidthUsed && aLinePolyPolygon.count())
1585     {
1586         const double fHalfLineWidth((rInfo.GetWidth() * 0.5) + 0.5);
1587 
1588         if(aLinePolyPolygon.areControlPointsUsed())
1589         {
1590             // #i110768# When area geometry has to be created, do not
1591             // use the fallback bezier decomposition inside createAreaGeometry,
1592             // but one that is at least as good as ImplSubdivideBezier was.
1593             // There, Polygon::AdaptiveSubdivide was used with default parameter
1594             // 1.0 as quality index.
1595             aLinePolyPolygon = basegfx::tools::adaptiveSubdivideByDistance(aLinePolyPolygon, 1.0);
1596         }
1597 
1598         for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
1599         {
1600             aFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
1601                 aLinePolyPolygon.getB2DPolygon(a),
1602                 fHalfLineWidth,
1603                 rInfo.GetLineJoin()));
1604         }
1605 
1606         aLinePolyPolygon.clear();
1607     }
1608 
1609     GDIMetaFile* pOldMetaFile = mpMetaFile;
1610     mpMetaFile = NULL;
1611 
1612     if(aLinePolyPolygon.count())
1613     {
1614         for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
1615         {
1616             const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
1617             bool bDone(false);
1618 
1619             if(bTryAA)
1620             {
1621                 bDone = mpGraphics->DrawPolyLine( aCandidate, 0.0, basegfx::B2DVector(1.0,1.0), basegfx::B2DLINEJOIN_NONE, this);
1622             }
1623 
1624             if(!bDone)
1625             {
1626                 const Polygon aPolygon(aCandidate);
1627                 mpGraphics->DrawPolyLine(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this);
1628             }
1629         }
1630     }
1631 
1632     if(aFillPolyPolygon.count())
1633     {
1634         const Color     aOldLineColor( maLineColor );
1635         const Color     aOldFillColor( maFillColor );
1636 
1637         SetLineColor();
1638         ImplInitLineColor();
1639         SetFillColor( aOldLineColor );
1640         ImplInitFillColor();
1641 
1642         bool bDone(false);
1643 
1644         if(bTryAA)
1645         {
1646             bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this);
1647         }
1648 
1649         if(!bDone)
1650         {
1651             for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
1652             {
1653                 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
1654                 mpGraphics->DrawPolygon(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this);
1655             }
1656         }
1657 
1658         SetFillColor( aOldFillColor );
1659         SetLineColor( aOldLineColor );
1660     }
1661 
1662     mpMetaFile = pOldMetaFile;
1663 }
1664 
1665 // -----------------------------------------------------------------------
1666 
1667 void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt,
1668                              const LineInfo& rLineInfo )
1669 {
1670     DBG_TRACE( "OutputDevice::DrawLine()" );
1671     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1672 
1673     if ( rLineInfo.IsDefault() )
1674     {
1675         DrawLine( rStartPt, rEndPt );
1676         return;
1677     }
1678 
1679     if ( mpMetaFile )
1680         mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt, rLineInfo ) );
1681 
1682     if ( !IsDeviceOutputNecessary() || !mbLineColor || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() )
1683         return;
1684 
1685     if( !mpGraphics && !ImplGetGraphics() )
1686         return;
1687 
1688     if ( mbInitClipRegion )
1689         ImplInitClipRegion();
1690 
1691     if ( mbOutputClipped )
1692         return;
1693 
1694     const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) );
1695     const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) );
1696     const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
1697     const bool bDashUsed(LINE_DASH == aInfo.GetStyle());
1698     const bool bLineWidthUsed(aInfo.GetWidth() > 1);
1699 
1700     if ( mbInitLineColor )
1701         ImplInitLineColor();
1702 
1703     if(bDashUsed || bLineWidthUsed)
1704     {
1705         basegfx::B2DPolygon aLinePolygon;
1706         aLinePolygon.append(basegfx::B2DPoint(aStartPt.X(), aStartPt.Y()));
1707         aLinePolygon.append(basegfx::B2DPoint(aEndPt.X(), aEndPt.Y()));
1708 
1709         impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aLinePolygon));
1710     }
1711     else
1712     {
1713         mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this );
1714     }
1715 
1716     if( mpAlphaVDev )
1717         mpAlphaVDev->DrawLine( rStartPt, rEndPt, rLineInfo );
1718 }
1719 
1720 // -----------------------------------------------------------------------
1721 
1722 void OutputDevice::DrawRect( const Rectangle& rRect )
1723 {
1724     DBG_TRACE( "OutputDevice::DrawRect()" );
1725     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1726 
1727     if ( mpMetaFile )
1728         mpMetaFile->AddAction( new MetaRectAction( rRect ) );
1729 
1730     if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() )
1731         return;
1732 
1733     Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
1734 
1735     if ( aRect.IsEmpty() )
1736         return;
1737     aRect.Justify();
1738 
1739     if ( !mpGraphics )
1740     {
1741         if ( !ImplGetGraphics() )
1742             return;
1743     }
1744 
1745     if ( mbInitClipRegion )
1746         ImplInitClipRegion();
1747     if ( mbOutputClipped )
1748         return;
1749 
1750     if ( mbInitLineColor )
1751         ImplInitLineColor();
1752     if ( mbInitFillColor )
1753         ImplInitFillColor();
1754 
1755     mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this );
1756 
1757     if( mpAlphaVDev )
1758         mpAlphaVDev->DrawRect( rRect );
1759 }
1760 
1761 // -----------------------------------------------------------------------
1762 
1763 void OutputDevice::DrawPolyLine( const Polygon& rPoly )
1764 {
1765     DBG_TRACE( "OutputDevice::DrawPolyLine()" );
1766     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1767     DBG_CHKOBJ( &rPoly, Polygon, NULL );
1768 
1769     if( mpMetaFile )
1770         mpMetaFile->AddAction( new MetaPolyLineAction( rPoly ) );
1771 
1772     sal_uInt16 nPoints = rPoly.GetSize();
1773 
1774     if ( !IsDeviceOutputNecessary() || !mbLineColor || (nPoints < 2) || ImplIsRecordLayout() )
1775         return;
1776 
1777     // we need a graphics
1778     if ( !mpGraphics )
1779         if ( !ImplGetGraphics() )
1780             return;
1781 
1782     if ( mbInitClipRegion )
1783         ImplInitClipRegion();
1784     if ( mbOutputClipped )
1785         return;
1786 
1787     if ( mbInitLineColor )
1788         ImplInitLineColor();
1789 
1790     const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
1791         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
1792         && ROP_OVERPAINT == GetRasterOp()
1793         && IsLineColor());
1794 
1795     // use b2dpolygon drawing if possible
1796     if(bTryAA && ImpTryDrawPolyLineDirect(rPoly.getB2DPolygon(), 0.0, basegfx::B2DLINEJOIN_NONE))
1797     {
1798         basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon());
1799         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
1800         const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
1801 
1802         // transform the polygon
1803         aB2DPolyLine.transform( aTransform );
1804 
1805         if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
1806         {
1807             aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
1808         }
1809 
1810         if(mpGraphics->DrawPolyLine( aB2DPolyLine, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
1811         {
1812             return;
1813         }
1814     }
1815 
1816     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
1817     const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
1818 
1819     // #100127# Forward beziers to sal, if any
1820     if( aPoly.HasFlags() )
1821     {
1822         const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry();
1823         if( !mpGraphics->DrawPolyLineBezier( nPoints, pPtAry, pFlgAry, this ) )
1824         {
1825             aPoly = ImplSubdivideBezier(aPoly);
1826             pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
1827             mpGraphics->DrawPolyLine( aPoly.GetSize(), pPtAry, this );
1828         }
1829     }
1830     else
1831     {
1832         mpGraphics->DrawPolyLine( nPoints, pPtAry, this );
1833     }
1834 
1835     if( mpAlphaVDev )
1836         mpAlphaVDev->DrawPolyLine( rPoly );
1837 }
1838 
1839 // -----------------------------------------------------------------------
1840 
1841 void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo )
1842 {
1843     DBG_TRACE( "OutputDevice::DrawPolyLine()" );
1844     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1845     DBG_CHKOBJ( &rPoly, Polygon, NULL );
1846 
1847     if ( rLineInfo.IsDefault() )
1848     {
1849         DrawPolyLine( rPoly );
1850         return;
1851     }
1852 
1853     // #i101491#
1854     // Try direct Fallback to B2D-Version of DrawPolyLine
1855     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
1856         && LINE_SOLID == rLineInfo.GetStyle())
1857     {
1858         DrawPolyLine( rPoly.getB2DPolygon(), (double)rLineInfo.GetWidth(), rLineInfo.GetLineJoin());
1859         return;
1860     }
1861 
1862     if ( mpMetaFile )
1863         mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) );
1864 
1865     ImpDrawPolyLineWithLineInfo(rPoly, rLineInfo);
1866 }
1867 
1868 void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineInfo& rLineInfo)
1869 {
1870     sal_uInt16 nPoints(rPoly.GetSize());
1871 
1872     if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() )
1873         return;
1874 
1875     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
1876 
1877     // #100127# LineInfo is not curve-safe, subdivide always
1878     //
1879     // What shall this mean? It's wrong to subdivide here when the
1880     // polygon is a fat line. In that case, the painted geometry
1881     // WILL be much different.
1882     // I also have no idea how this could be related to the given ID
1883     // which reads 'consolidate boost versions' in the task description.
1884     // Removing.
1885     //
1886     //if( aPoly.HasFlags() )
1887     //{
1888     //    aPoly = ImplSubdivideBezier( aPoly );
1889     //    nPoints = aPoly.GetSize();
1890     //}
1891 
1892     // we need a graphics
1893     if ( !mpGraphics && !ImplGetGraphics() )
1894         return;
1895 
1896     if ( mbInitClipRegion )
1897         ImplInitClipRegion();
1898 
1899     if ( mbOutputClipped )
1900         return;
1901 
1902     if ( mbInitLineColor )
1903         ImplInitLineColor();
1904 
1905     const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
1906     const bool bDashUsed(LINE_DASH == aInfo.GetStyle());
1907     const bool bLineWidthUsed(aInfo.GetWidth() > 1);
1908 
1909     if(bDashUsed || bLineWidthUsed)
1910     {
1911         impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aPoly.getB2DPolygon()));
1912     }
1913     else
1914     {
1915         // #100127# the subdivision HAS to be done here since only a pointer
1916         // to an array of points is given to the DrawPolyLine method, there is
1917         // NO way to find out there that it's a curve.
1918         if( aPoly.HasFlags() )
1919         {
1920             aPoly = ImplSubdivideBezier( aPoly );
1921             nPoints = aPoly.GetSize();
1922         }
1923 
1924         mpGraphics->DrawPolyLine(nPoints, (const SalPoint*)aPoly.GetConstPointAry(), this);
1925     }
1926 
1927     if( mpAlphaVDev )
1928         mpAlphaVDev->DrawPolyLine( rPoly, rLineInfo );
1929 }
1930 
1931 // -----------------------------------------------------------------------
1932 
1933 void OutputDevice::DrawPolygon( const Polygon& rPoly )
1934 {
1935     DBG_TRACE( "OutputDevice::DrawPolygon()" );
1936     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1937     DBG_CHKOBJ( &rPoly, Polygon, NULL );
1938 
1939     if( mpMetaFile )
1940         mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
1941 
1942     sal_uInt16 nPoints = rPoly.GetSize();
1943 
1944     if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) || ImplIsRecordLayout() )
1945         return;
1946 
1947     // we need a graphics
1948     if ( !mpGraphics )
1949         if ( !ImplGetGraphics() )
1950             return;
1951 
1952     if ( mbInitClipRegion )
1953         ImplInitClipRegion();
1954     if ( mbOutputClipped )
1955         return;
1956 
1957     if ( mbInitLineColor )
1958         ImplInitLineColor();
1959     if ( mbInitFillColor )
1960         ImplInitFillColor();
1961 
1962     // use b2dpolygon drawing if possible
1963     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
1964         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
1965         && ROP_OVERPAINT == GetRasterOp()
1966         && (IsLineColor() || IsFillColor()))
1967     {
1968         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
1969         basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon());
1970         bool bSuccess(true);
1971 
1972         // transform the polygon and ensure closed
1973         aB2DPolygon.transform(aTransform);
1974         aB2DPolygon.setClosed(true);
1975 
1976         if(IsFillColor())
1977         {
1978             bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this);
1979         }
1980 
1981         if(bSuccess && IsLineColor())
1982         {
1983             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
1984 
1985             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
1986             {
1987                 aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
1988             }
1989 
1990             bSuccess = mpGraphics->DrawPolyLine( aB2DPolygon, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
1991         }
1992 
1993         if(bSuccess)
1994         {
1995             return;
1996         }
1997     }
1998 
1999     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
2000     const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
2001 
2002     // #100127# Forward beziers to sal, if any
2003     if( aPoly.HasFlags() )
2004     {
2005         const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry();
2006         if( !mpGraphics->DrawPolygonBezier( nPoints, pPtAry, pFlgAry, this ) )
2007         {
2008             aPoly = ImplSubdivideBezier(aPoly);
2009             pPtAry = (const SalPoint*)aPoly.GetConstPointAry();
2010             mpGraphics->DrawPolygon( aPoly.GetSize(), pPtAry, this );
2011         }
2012     }
2013     else
2014     {
2015         mpGraphics->DrawPolygon( nPoints, pPtAry, this );
2016     }
2017     if( mpAlphaVDev )
2018         mpAlphaVDev->DrawPolygon( rPoly );
2019 }
2020 
2021 // -----------------------------------------------------------------------
2022 
2023 void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
2024 {
2025     DBG_TRACE( "OutputDevice::DrawPolyPolygon()" );
2026     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2027     DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
2028 
2029     if( mpMetaFile )
2030         mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
2031 
2032     sal_uInt16 nPoly = rPolyPoly.Count();
2033 
2034     if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly || ImplIsRecordLayout() )
2035         return;
2036 
2037     // we need a graphics
2038     if ( !mpGraphics )
2039         if ( !ImplGetGraphics() )
2040             return;
2041 
2042     if ( mbInitClipRegion )
2043         ImplInitClipRegion();
2044     if ( mbOutputClipped )
2045         return;
2046 
2047     if ( mbInitLineColor )
2048         ImplInitLineColor();
2049     if ( mbInitFillColor )
2050         ImplInitFillColor();
2051 
2052     // use b2dpolygon drawing if possible
2053     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
2054         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
2055         && ROP_OVERPAINT == GetRasterOp()
2056         && (IsLineColor() || IsFillColor()))
2057     {
2058         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
2059         basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
2060         bool bSuccess(true);
2061 
2062         // transform the polygon and ensure closed
2063         aB2DPolyPolygon.transform(aTransform);
2064         aB2DPolyPolygon.setClosed(true);
2065 
2066         if(IsFillColor())
2067         {
2068             bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
2069         }
2070 
2071         if(bSuccess && IsLineColor())
2072         {
2073             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
2074 
2075             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
2076             {
2077                 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
2078             }
2079 
2080             for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++)
2081             {
2082                 bSuccess = mpGraphics->DrawPolyLine( aB2DPolyPolygon.getB2DPolygon(a), 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
2083             }
2084         }
2085 
2086         if(bSuccess)
2087         {
2088             return;
2089         }
2090     }
2091 
2092     if ( nPoly == 1 )
2093     {
2094         // #100127# Map to DrawPolygon
2095         Polygon aPoly = rPolyPoly.GetObject( 0 );
2096         if( aPoly.GetSize() >= 2 )
2097         {
2098             GDIMetaFile* pOldMF = mpMetaFile;
2099             mpMetaFile = NULL;
2100 
2101             DrawPolygon( aPoly );
2102 
2103             mpMetaFile = pOldMF;
2104         }
2105     }
2106     else
2107     {
2108         // #100127# moved real PolyPolygon draw to separate method,
2109         // have to call recursively, avoiding duplicate
2110         // ImplLogicToDevicePixel calls
2111         ImplDrawPolyPolygon( nPoly, ImplLogicToDevicePixel( rPolyPoly ) );
2112     }
2113     if( mpAlphaVDev )
2114         mpAlphaVDev->DrawPolyPolygon( rPolyPoly );
2115 }
2116 
2117 // -----------------------------------------------------------------------
2118 
2119 void OutputDevice::DrawPolygon( const ::basegfx::B2DPolygon& rB2DPolygon)
2120 {
2121     // AW: Do NOT paint empty polygons
2122     if(rB2DPolygon.count())
2123     {
2124         ::basegfx::B2DPolyPolygon aPP( rB2DPolygon );
2125         DrawPolyPolygon( aPP );
2126     }
2127 }
2128 
2129 // -----------------------------------------------------------------------
2130 // Caution: This method is nearly the same as
2131 // OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency),
2132 // so when changes are made here do not forget to make change sthere, too
2133 
2134 void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
2135 {
2136     DBG_TRACE( "OutputDevice::DrawPolyPolygon(B2D&)" );
2137     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2138 
2139 #if 0
2140     // MetaB2DPolyPolygonAction is not implemented yet:
2141     // according to AW adding it is very dangerous since there is a lot
2142     // of code that uses the metafile actions directly and unless every
2143     // place that does this knows about the new action we need to fallback
2144     if( mpMetaFile )
2145         mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) );
2146 #else
2147     if( mpMetaFile )
2148         mpMetaFile->AddAction( new MetaPolyPolygonAction( PolyPolygon( rB2DPolyPoly ) ) );
2149 #endif
2150 
2151     // call helper
2152     ImpDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly);
2153 }
2154 
2155 void OutputDevice::ImpDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly)
2156 {
2157     // AW: Do NOT paint empty PolyPolygons
2158     if(!rB2DPolyPoly.count())
2159         return;
2160 
2161     // we need a graphics
2162     if( !mpGraphics )
2163         if( !ImplGetGraphics() )
2164             return;
2165 
2166     if( mbInitClipRegion )
2167         ImplInitClipRegion();
2168     if( mbOutputClipped )
2169         return;
2170 
2171     if( mbInitLineColor )
2172         ImplInitLineColor();
2173     if( mbInitFillColor )
2174         ImplInitFillColor();
2175 
2176     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
2177         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
2178         && ROP_OVERPAINT == GetRasterOp()
2179         && (IsLineColor() || IsFillColor()))
2180     {
2181         const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
2182         basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
2183         bool bSuccess(true);
2184 
2185         // transform the polygon and ensure closed
2186         aB2DPolyPolygon.transform(aTransform);
2187         aB2DPolyPolygon.setClosed(true);
2188 
2189         if(IsFillColor())
2190         {
2191             bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
2192         }
2193 
2194         if(bSuccess && IsLineColor())
2195         {
2196             const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
2197 
2198             if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
2199             {
2200                 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
2201             }
2202 
2203             for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++)
2204             {
2205                 bSuccess = mpGraphics->DrawPolyLine( aB2DPolyPolygon.getB2DPolygon(a), 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
2206             }
2207         }
2208 
2209         if(bSuccess)
2210         {
2211             return;
2212         }
2213     }
2214 
2215     // fallback to old polygon drawing if needed
2216     const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly );
2217     const PolyPolygon aPixelPolyPolygon = ImplLogicToDevicePixel( aToolsPolyPolygon );
2218     ImplDrawPolyPolygon( aPixelPolyPolygon.Count(), aPixelPolyPolygon );
2219 }
2220 
2221 // -----------------------------------------------------------------------
2222 
2223 bool OutputDevice::ImpTryDrawPolyLineDirect(
2224     const basegfx::B2DPolygon& rB2DPolygon,
2225     double fLineWidth,
2226     basegfx::B2DLineJoin eLineJoin)
2227 {
2228     const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
2229     basegfx::B2DVector aB2DLineWidth(1.0, 1.0);
2230 
2231     // transform the line width if used
2232     if( fLineWidth != 0.0 )
2233     {
2234         aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth );
2235     }
2236 
2237     // transform the polygon
2238     basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
2239     aB2DPolygon.transform(aTransform);
2240 
2241     if((mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
2242         && aB2DPolygon.count() < 1000)
2243     {
2244         // #i98289#, #i101491#
2245         // better to remove doubles on device coordinates. Also assume from a given amount
2246         // of points that the single edges are not long enough to smooth
2247         aB2DPolygon.removeDoublePoints();
2248         aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
2249     }
2250 
2251     // draw the polyline
2252     return mpGraphics->DrawPolyLine( aB2DPolygon, 0.0, aB2DLineWidth, eLineJoin, this);
2253 }
2254 
2255 void OutputDevice::DrawPolyLine(
2256     const basegfx::B2DPolygon& rB2DPolygon,
2257     double fLineWidth,
2258     basegfx::B2DLineJoin eLineJoin)
2259 {
2260     DBG_TRACE( "OutputDevice::DrawPolyLine(B2D&)" );
2261     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2262     (void)eLineJoin; // ATM used in UNX, but not in WNT, access it for warning-free
2263 
2264 #if 0 // MetaB2DPolyLineAction is not implemented yet:
2265       // according to AW adding it is very dangerous since there is a lot
2266       // of code that uses the metafile actions directly and unless every
2267       // place that does this knows about the new action we need to fallback
2268     if( mpMetaFile )
2269         mpMetaFile->AddAction( new MetaB2DPolyLineAction( rB2DPolygon ) );
2270 #else
2271     if( mpMetaFile )
2272     {
2273         LineInfo aLineInfo;
2274         if( fLineWidth != 0.0 )
2275             aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) );
2276         const Polygon aToolsPolygon( rB2DPolygon );
2277         mpMetaFile->AddAction( new MetaPolyLineAction( aToolsPolygon, aLineInfo ) );
2278     }
2279 #endif
2280 
2281     // AW: Do NOT paint empty PolyPolygons
2282     if(!rB2DPolygon.count())
2283         return;
2284 
2285     // we need a graphics
2286     if( !mpGraphics )
2287         if( !ImplGetGraphics() )
2288             return;
2289 
2290     if( mbInitClipRegion )
2291         ImplInitClipRegion();
2292     if( mbOutputClipped )
2293         return;
2294 
2295     if( mbInitLineColor )
2296         ImplInitLineColor();
2297 
2298     const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
2299         && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
2300         && ROP_OVERPAINT == GetRasterOp()
2301         && IsLineColor());
2302 
2303     // use b2dpolygon drawing if possible
2304     if(bTryAA && ImpTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, eLineJoin))
2305     {
2306         return;
2307     }
2308 
2309     // #i101491#
2310     // no output yet; fallback to geometry decomposition and use filled polygon paint
2311     // when line is fat and not too complex. ImpDrawPolyPolygonWithB2DPolyPolygon
2312     // will do internal needed AA checks etc.
2313     if(fLineWidth >= 2.5
2314         && rB2DPolygon.count()
2315         && rB2DPolygon.count() <= 1000)
2316     {
2317         const double fHalfLineWidth((fLineWidth * 0.5) + 0.5);
2318         const basegfx::B2DPolyPolygon aAreaPolyPolygon(basegfx::tools::createAreaGeometry(
2319             rB2DPolygon, fHalfLineWidth, eLineJoin));
2320 
2321         const Color aOldLineColor(maLineColor);
2322         const Color aOldFillColor(maFillColor);
2323 
2324         SetLineColor();
2325         ImplInitLineColor();
2326         SetFillColor(aOldLineColor);
2327         ImplInitFillColor();
2328 
2329         // draw usig a loop; else the topology will paint a PolyPolygon
2330         for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++)
2331         {
2332             ImpDrawPolyPolygonWithB2DPolyPolygon(
2333                 basegfx::B2DPolyPolygon(aAreaPolyPolygon.getB2DPolygon(a)));
2334         }
2335 
2336         SetLineColor(aOldLineColor);
2337         ImplInitLineColor();
2338         SetFillColor(aOldFillColor);
2339         ImplInitFillColor();
2340 
2341         if(bTryAA)
2342         {
2343             // when AA it is necessary to also paint the filled polygon's outline
2344             // to avoid optical gaps
2345             for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++)
2346             {
2347                 ImpTryDrawPolyLineDirect(aAreaPolyPolygon.getB2DPolygon(a), 0.0, basegfx::B2DLINEJOIN_NONE);
2348             }
2349         }
2350     }
2351     else
2352     {
2353         // fallback to old polygon drawing if needed
2354         const Polygon aToolsPolygon( rB2DPolygon );
2355         LineInfo aLineInfo;
2356         if( fLineWidth != 0.0 )
2357             aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) );
2358         ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo );
2359     }
2360 }
2361 
2362 // -----------------------------------------------------------------------
2363 
2364 sal_uInt32 OutputDevice::GetGCStackDepth() const
2365 {
2366     const ImplObjStack* pData = mpObjStack;
2367     sal_uInt32 nDepth = 0;
2368     while( pData )
2369     {
2370         nDepth++;
2371         pData = pData->mpPrev;
2372     }
2373     return nDepth;
2374 }
2375 
2376 // -----------------------------------------------------------------------
2377 
2378 void OutputDevice::Push( sal_uInt16 nFlags )
2379 {
2380     DBG_TRACE( "OutputDevice::Push()" );
2381     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2382 
2383     if ( mpMetaFile )
2384         mpMetaFile->AddAction( new MetaPushAction( nFlags ) );
2385 
2386     ImplObjStack* pData = new ImplObjStack;
2387     pData->mpPrev = mpObjStack;
2388     mpObjStack = pData;
2389 
2390     pData->mnFlags = nFlags;
2391 
2392     if ( nFlags & PUSH_LINECOLOR )
2393     {
2394         if ( mbLineColor )
2395             pData->mpLineColor = new Color( maLineColor );
2396         else
2397             pData->mpLineColor = NULL;
2398     }
2399     if ( nFlags & PUSH_FILLCOLOR )
2400     {
2401         if ( mbFillColor )
2402             pData->mpFillColor = new Color( maFillColor );
2403         else
2404             pData->mpFillColor = NULL;
2405     }
2406     if ( nFlags & PUSH_FONT )
2407         pData->mpFont = new Font( maFont );
2408     if ( nFlags & PUSH_TEXTCOLOR )
2409         pData->mpTextColor = new Color( GetTextColor() );
2410     if ( nFlags & PUSH_TEXTFILLCOLOR )
2411     {
2412         if ( IsTextFillColor() )
2413             pData->mpTextFillColor = new Color( GetTextFillColor() );
2414         else
2415             pData->mpTextFillColor = NULL;
2416     }
2417     if ( nFlags & PUSH_TEXTLINECOLOR )
2418     {
2419         if ( IsTextLineColor() )
2420             pData->mpTextLineColor = new Color( GetTextLineColor() );
2421         else
2422             pData->mpTextLineColor = NULL;
2423     }
2424     if ( nFlags & PUSH_OVERLINECOLOR )
2425     {
2426         if ( IsOverlineColor() )
2427             pData->mpOverlineColor = new Color( GetOverlineColor() );
2428         else
2429             pData->mpOverlineColor = NULL;
2430     }
2431     if ( nFlags & PUSH_TEXTALIGN )
2432         pData->meTextAlign = GetTextAlign();
2433     if( nFlags & PUSH_TEXTLAYOUTMODE )
2434         pData->mnTextLayoutMode = GetLayoutMode();
2435     if( nFlags & PUSH_TEXTLANGUAGE )
2436         pData->meTextLanguage = GetDigitLanguage();
2437     if ( nFlags & PUSH_RASTEROP )
2438         pData->meRasterOp = GetRasterOp();
2439     if ( nFlags & PUSH_MAPMODE )
2440     {
2441         if ( mbMap )
2442             pData->mpMapMode = new MapMode( maMapMode );
2443         else
2444             pData->mpMapMode = NULL;
2445     }
2446     if ( nFlags & PUSH_CLIPREGION )
2447     {
2448         if ( mbClipRegion )
2449             pData->mpClipRegion = new Region( maRegion );
2450         else
2451             pData->mpClipRegion = NULL;
2452     }
2453     if ( nFlags & PUSH_REFPOINT )
2454     {
2455         if ( mbRefPoint )
2456             pData->mpRefPoint = new Point( maRefPoint );
2457         else
2458             pData->mpRefPoint = NULL;
2459     }
2460 
2461     if( mpAlphaVDev )
2462         mpAlphaVDev->Push();
2463 }
2464 
2465 // -----------------------------------------------------------------------
2466 
2467 void OutputDevice::Pop()
2468 {
2469     DBG_TRACE( "OutputDevice::Pop()" );
2470     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2471 
2472     if( mpMetaFile )
2473         mpMetaFile->AddAction( new MetaPopAction() );
2474 
2475     GDIMetaFile*    pOldMetaFile = mpMetaFile;
2476     ImplObjStack*   pData = mpObjStack;
2477     mpMetaFile = NULL;
2478 
2479     if ( !pData )
2480     {
2481         DBG_ERRORFILE( "OutputDevice::Pop() without OutputDevice::Push()" );
2482         return;
2483     }
2484 
2485     if( mpAlphaVDev )
2486         mpAlphaVDev->Pop();
2487 
2488     mpObjStack = pData->mpPrev;
2489 
2490     if ( pData->mnFlags & PUSH_LINECOLOR )
2491     {
2492         if ( pData->mpLineColor )
2493             SetLineColor( *pData->mpLineColor );
2494         else
2495             SetLineColor();
2496     }
2497     if ( pData->mnFlags & PUSH_FILLCOLOR )
2498     {
2499         if ( pData->mpFillColor )
2500             SetFillColor( *pData->mpFillColor );
2501         else
2502             SetFillColor();
2503     }
2504     if ( pData->mnFlags & PUSH_FONT )
2505         SetFont( *pData->mpFont );
2506     if ( pData->mnFlags & PUSH_TEXTCOLOR )
2507         SetTextColor( *pData->mpTextColor );
2508     if ( pData->mnFlags & PUSH_TEXTFILLCOLOR )
2509     {
2510         if ( pData->mpTextFillColor )
2511             SetTextFillColor( *pData->mpTextFillColor );
2512         else
2513             SetTextFillColor();
2514     }
2515     if ( pData->mnFlags & PUSH_TEXTLINECOLOR )
2516     {
2517         if ( pData->mpTextLineColor )
2518             SetTextLineColor( *pData->mpTextLineColor );
2519         else
2520             SetTextLineColor();
2521     }
2522     if ( pData->mnFlags & PUSH_OVERLINECOLOR )
2523     {
2524         if ( pData->mpOverlineColor )
2525             SetOverlineColor( *pData->mpOverlineColor );
2526         else
2527             SetOverlineColor();
2528     }
2529     if ( pData->mnFlags & PUSH_TEXTALIGN )
2530         SetTextAlign( pData->meTextAlign );
2531     if( pData->mnFlags & PUSH_TEXTLAYOUTMODE )
2532         SetLayoutMode( pData->mnTextLayoutMode );
2533     if( pData->mnFlags & PUSH_TEXTLANGUAGE )
2534         SetDigitLanguage( pData->meTextLanguage );
2535     if ( pData->mnFlags & PUSH_RASTEROP )
2536         SetRasterOp( pData->meRasterOp );
2537     if ( pData->mnFlags & PUSH_MAPMODE )
2538     {
2539         if ( pData->mpMapMode )
2540             SetMapMode( *pData->mpMapMode );
2541         else
2542             SetMapMode();
2543     }
2544     if ( pData->mnFlags & PUSH_CLIPREGION )
2545         ImplSetClipRegion( pData->mpClipRegion );
2546     if ( pData->mnFlags & PUSH_REFPOINT )
2547     {
2548         if ( pData->mpRefPoint )
2549             SetRefPoint( *pData->mpRefPoint );
2550         else
2551             SetRefPoint();
2552     }
2553 
2554     ImplDeleteObjStack( pData );
2555 
2556     mpMetaFile = pOldMetaFile;
2557 }
2558 
2559 // -----------------------------------------------------------------------
2560 
2561 void OutputDevice::SetConnectMetaFile( GDIMetaFile* pMtf )
2562 {
2563     mpMetaFile = pMtf;
2564 }
2565 
2566 // -----------------------------------------------------------------------
2567 
2568 void OutputDevice::EnableOutput( sal_Bool bEnable )
2569 {
2570     mbOutput = (bEnable != 0);
2571 
2572     if( mpAlphaVDev )
2573         mpAlphaVDev->EnableOutput( bEnable );
2574 }
2575 
2576 // -----------------------------------------------------------------------
2577 
2578 void OutputDevice::SetSettings( const AllSettings& rSettings )
2579 {
2580     maSettings = rSettings;
2581 
2582     if( mpAlphaVDev )
2583         mpAlphaVDev->SetSettings( rSettings );
2584 }
2585 
2586 // -----------------------------------------------------------------------
2587 
2588 sal_uInt16 OutputDevice::GetBitCount() const
2589 {
2590     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2591 
2592     if ( meOutDevType == OUTDEV_VIRDEV )
2593         return ((VirtualDevice*)this)->mnBitCount;
2594 
2595     // we need a graphics
2596     if ( !mpGraphics )
2597     {
2598         if ( !((OutputDevice*)this)->ImplGetGraphics() )
2599             return 0;
2600     }
2601 
2602     return (sal_uInt16)mpGraphics->GetBitCount();
2603 }
2604 
2605 // -----------------------------------------------------------------------
2606 
2607 sal_uInt16 OutputDevice::GetAlphaBitCount() const
2608 {
2609     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2610 
2611     if ( meOutDevType == OUTDEV_VIRDEV &&
2612         mpAlphaVDev != NULL )
2613     {
2614         return mpAlphaVDev->GetBitCount();
2615     }
2616 
2617     return 0;
2618 }
2619 
2620 // -----------------------------------------------------------------------
2621 
2622 sal_uLong OutputDevice::GetColorCount() const
2623 {
2624     DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
2625 
2626     const sal_uInt16 nBitCount = GetBitCount();
2627     return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (sal_uLong) 1 ) << nBitCount) );
2628 }
2629 
2630 // -----------------------------------------------------------------------
2631 
2632 sal_Bool OutputDevice::HasAlpha()
2633 {
2634     return mpAlphaVDev != NULL;
2635 }
2636 
2637 // -----------------------------------------------------------------------
2638 
2639 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > OutputDevice::CreateUnoGraphics()
2640 {
2641     UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
2642     return pWrapper ? pWrapper->CreateGraphics( this ) : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >();
2643 }
2644 
2645 // -----------------------------------------------------------------------
2646 
2647 SystemGraphicsData OutputDevice::GetSystemGfxData() const
2648 {
2649     if ( !mpGraphics )
2650     {
2651         if ( !ImplGetGraphics() )
2652             return SystemGraphicsData();
2653     }
2654 
2655     return mpGraphics->GetGraphicsData();
2656 }
2657 
2658 // -----------------------------------------------------------------------
2659 
2660 ::com::sun::star::uno::Any OutputDevice::GetSystemGfxDataAny() const
2661 {
2662     ::com::sun::star::uno::Any aRet;
2663     const SystemGraphicsData aSysData = GetSystemGfxData();
2664     ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)&aSysData,
2665                                                       aSysData.nSize );
2666 
2667     return uno::makeAny(aSeq);
2668 }
2669 
2670 // -----------------------------------------------------------------------
2671 
2672 ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > OutputDevice::GetCanvas() const
2673 {
2674     uno::Sequence< uno::Any > aArg(6);
2675 
2676     aArg[ 0 ] = uno::makeAny( reinterpret_cast<sal_Int64>(this) );
2677     aArg[ 2 ] = uno::makeAny( ::com::sun::star::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
2678     aArg[ 3 ] = uno::makeAny( sal_False );
2679     aArg[ 5 ] = GetSystemGfxDataAny();
2680 
2681     uno::Reference<lang::XMultiServiceFactory> xFactory = vcl::unohelper::GetMultiServiceFactory();
2682 
2683     uno::Reference<rendering::XCanvas> xCanvas;
2684 
2685     // Create canvas instance with window handle
2686     // =========================================
2687     if ( xFactory.is() )
2688     {
2689         static uno::Reference<lang::XMultiServiceFactory> xCanvasFactory(
2690             xFactory->createInstance(
2691                 OUString( RTL_CONSTASCII_USTRINGPARAM(
2692                               "com.sun.star."
2693                               "rendering.CanvasFactory") ) ),
2694             uno::UNO_QUERY );
2695         if(xCanvasFactory.is())
2696         {
2697             xCanvas.set(
2698                 xCanvasFactory->createInstanceWithArguments(
2699                     OUString( RTL_CONSTASCII_USTRINGPARAM(
2700                                   "com.sun.star.rendering.Canvas" )),
2701                     aArg ),
2702                 uno::UNO_QUERY );
2703         }
2704     }
2705 
2706     return xCanvas;
2707 }
2708 
2709 // -----------------------------------------------------------------------
2710