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