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