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