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