xref: /trunk/main/vcl/source/gdi/outdev.cxx (revision cdf0e10c)
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