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