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