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