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