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