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, com::sun::star::drawing::LineCap_BUTT, 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 rInfo.GetLineCap())); 1601 } 1602 1603 aLinePolyPolygon.clear(); 1604 } 1605 1606 GDIMetaFile* pOldMetaFile = mpMetaFile; 1607 mpMetaFile = NULL; 1608 1609 if(aLinePolyPolygon.count()) 1610 { 1611 for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) 1612 { 1613 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); 1614 bool bDone(false); 1615 1616 if(bTryAA) 1617 { 1618 bDone = mpGraphics->DrawPolyLine( aCandidate, 0.0, basegfx::B2DVector(1.0,1.0), basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this); 1619 } 1620 1621 if(!bDone) 1622 { 1623 const Polygon aPolygon(aCandidate); 1624 mpGraphics->DrawPolyLine(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this); 1625 } 1626 } 1627 } 1628 1629 if(aFillPolyPolygon.count()) 1630 { 1631 const Color aOldLineColor( maLineColor ); 1632 const Color aOldFillColor( maFillColor ); 1633 1634 SetLineColor(); 1635 ImplInitLineColor(); 1636 SetFillColor( aOldLineColor ); 1637 ImplInitFillColor(); 1638 1639 bool bDone(false); 1640 1641 if(bTryAA) 1642 { 1643 bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this); 1644 } 1645 1646 if(!bDone) 1647 { 1648 for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) 1649 { 1650 Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a)); 1651 1652 // need to subdivide, mpGraphics->DrawPolygon ignores curves 1653 aPolygon.AdaptiveSubdivide(aPolygon); 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())) 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, com::sun::star::drawing::LineCap_BUTT, 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(), rLineInfo.GetLineCap()); 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( 1991 aB2DPolygon, 1992 0.0, 1993 aB2DLineWidth, 1994 basegfx::B2DLINEJOIN_NONE, 1995 com::sun::star::drawing::LineCap_BUTT, 1996 this); 1997 } 1998 1999 if(bSuccess) 2000 { 2001 return; 2002 } 2003 } 2004 2005 Polygon aPoly = ImplLogicToDevicePixel( rPoly ); 2006 const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 2007 2008 // #100127# Forward beziers to sal, if any 2009 if( aPoly.HasFlags() ) 2010 { 2011 const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry(); 2012 if( !mpGraphics->DrawPolygonBezier( nPoints, pPtAry, pFlgAry, this ) ) 2013 { 2014 aPoly = ImplSubdivideBezier(aPoly); 2015 pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 2016 mpGraphics->DrawPolygon( aPoly.GetSize(), pPtAry, this ); 2017 } 2018 } 2019 else 2020 { 2021 mpGraphics->DrawPolygon( nPoints, pPtAry, this ); 2022 } 2023 if( mpAlphaVDev ) 2024 mpAlphaVDev->DrawPolygon( rPoly ); 2025 } 2026 2027 // ----------------------------------------------------------------------- 2028 2029 void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly ) 2030 { 2031 DBG_TRACE( "OutputDevice::DrawPolyPolygon()" ); 2032 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2033 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL ); 2034 2035 if( mpMetaFile ) 2036 mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) ); 2037 2038 sal_uInt16 nPoly = rPolyPoly.Count(); 2039 2040 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly || ImplIsRecordLayout() ) 2041 return; 2042 2043 // we need a graphics 2044 if ( !mpGraphics ) 2045 if ( !ImplGetGraphics() ) 2046 return; 2047 2048 if ( mbInitClipRegion ) 2049 ImplInitClipRegion(); 2050 if ( mbOutputClipped ) 2051 return; 2052 2053 if ( mbInitLineColor ) 2054 ImplInitLineColor(); 2055 if ( mbInitFillColor ) 2056 ImplInitFillColor(); 2057 2058 // use b2dpolygon drawing if possible 2059 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2060 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2061 && ROP_OVERPAINT == GetRasterOp() 2062 && (IsLineColor() || IsFillColor())) 2063 { 2064 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 2065 basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon()); 2066 bool bSuccess(true); 2067 2068 // transform the polygon and ensure closed 2069 aB2DPolyPolygon.transform(aTransform); 2070 aB2DPolyPolygon.setClosed(true); 2071 2072 if(IsFillColor()) 2073 { 2074 bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this); 2075 } 2076 2077 if(bSuccess && IsLineColor()) 2078 { 2079 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 2080 2081 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2082 { 2083 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon); 2084 } 2085 2086 for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++) 2087 { 2088 bSuccess = mpGraphics->DrawPolyLine( 2089 aB2DPolyPolygon.getB2DPolygon(a), 2090 0.0, 2091 aB2DLineWidth, 2092 basegfx::B2DLINEJOIN_NONE, 2093 com::sun::star::drawing::LineCap_BUTT, 2094 this); 2095 } 2096 } 2097 2098 if(bSuccess) 2099 { 2100 return; 2101 } 2102 } 2103 2104 if ( nPoly == 1 ) 2105 { 2106 // #100127# Map to DrawPolygon 2107 Polygon aPoly = rPolyPoly.GetObject( 0 ); 2108 if( aPoly.GetSize() >= 2 ) 2109 { 2110 GDIMetaFile* pOldMF = mpMetaFile; 2111 mpMetaFile = NULL; 2112 2113 DrawPolygon( aPoly ); 2114 2115 mpMetaFile = pOldMF; 2116 } 2117 } 2118 else 2119 { 2120 // #100127# moved real PolyPolygon draw to separate method, 2121 // have to call recursively, avoiding duplicate 2122 // ImplLogicToDevicePixel calls 2123 ImplDrawPolyPolygon( nPoly, ImplLogicToDevicePixel( rPolyPoly ) ); 2124 } 2125 if( mpAlphaVDev ) 2126 mpAlphaVDev->DrawPolyPolygon( rPolyPoly ); 2127 } 2128 2129 // ----------------------------------------------------------------------- 2130 2131 void OutputDevice::DrawPolygon( const ::basegfx::B2DPolygon& rB2DPolygon) 2132 { 2133 // AW: Do NOT paint empty polygons 2134 if(rB2DPolygon.count()) 2135 { 2136 ::basegfx::B2DPolyPolygon aPP( rB2DPolygon ); 2137 DrawPolyPolygon( aPP ); 2138 } 2139 } 2140 2141 // ----------------------------------------------------------------------- 2142 // Caution: This method is nearly the same as 2143 // OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency), 2144 // so when changes are made here do not forget to make change sthere, too 2145 2146 void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly ) 2147 { 2148 DBG_TRACE( "OutputDevice::DrawPolyPolygon(B2D&)" ); 2149 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2150 2151 #if 0 2152 // MetaB2DPolyPolygonAction is not implemented yet: 2153 // according to AW adding it is very dangerous since there is a lot 2154 // of code that uses the metafile actions directly and unless every 2155 // place that does this knows about the new action we need to fallback 2156 if( mpMetaFile ) 2157 mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) ); 2158 #else 2159 if( mpMetaFile ) 2160 mpMetaFile->AddAction( new MetaPolyPolygonAction( PolyPolygon( rB2DPolyPoly ) ) ); 2161 #endif 2162 2163 // call helper 2164 ImpDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly); 2165 } 2166 2167 void OutputDevice::ImpDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly) 2168 { 2169 // AW: Do NOT paint empty PolyPolygons 2170 if(!rB2DPolyPoly.count()) 2171 return; 2172 2173 // we need a graphics 2174 if( !mpGraphics ) 2175 if( !ImplGetGraphics() ) 2176 return; 2177 2178 if( mbInitClipRegion ) 2179 ImplInitClipRegion(); 2180 if( mbOutputClipped ) 2181 return; 2182 2183 if( mbInitLineColor ) 2184 ImplInitLineColor(); 2185 if( mbInitFillColor ) 2186 ImplInitFillColor(); 2187 2188 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2189 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2190 && ROP_OVERPAINT == GetRasterOp() 2191 && (IsLineColor() || IsFillColor())) 2192 { 2193 const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation()); 2194 basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly); 2195 bool bSuccess(true); 2196 2197 // transform the polygon and ensure closed 2198 aB2DPolyPolygon.transform(aTransform); 2199 aB2DPolyPolygon.setClosed(true); 2200 2201 if(IsFillColor()) 2202 { 2203 bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this); 2204 } 2205 2206 if(bSuccess && IsLineColor()) 2207 { 2208 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 2209 2210 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2211 { 2212 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon); 2213 } 2214 2215 for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++) 2216 { 2217 bSuccess = mpGraphics->DrawPolyLine( 2218 aB2DPolyPolygon.getB2DPolygon(a), 2219 0.0, 2220 aB2DLineWidth, 2221 basegfx::B2DLINEJOIN_NONE, 2222 com::sun::star::drawing::LineCap_BUTT, 2223 this); 2224 } 2225 } 2226 2227 if(bSuccess) 2228 { 2229 return; 2230 } 2231 } 2232 2233 // fallback to old polygon drawing if needed 2234 const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly ); 2235 const PolyPolygon aPixelPolyPolygon = ImplLogicToDevicePixel( aToolsPolyPolygon ); 2236 ImplDrawPolyPolygon( aPixelPolyPolygon.Count(), aPixelPolyPolygon ); 2237 } 2238 2239 // ----------------------------------------------------------------------- 2240 2241 bool OutputDevice::ImpTryDrawPolyLineDirect( 2242 const basegfx::B2DPolygon& rB2DPolygon, 2243 double fLineWidth, 2244 basegfx::B2DLineJoin eLineJoin, 2245 com::sun::star::drawing::LineCap eLineCap) 2246 { 2247 const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 2248 basegfx::B2DVector aB2DLineWidth(1.0, 1.0); 2249 2250 // transform the line width if used 2251 if( fLineWidth != 0.0 ) 2252 { 2253 aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth ); 2254 } 2255 2256 // transform the polygon 2257 basegfx::B2DPolygon aB2DPolygon(rB2DPolygon); 2258 aB2DPolygon.transform(aTransform); 2259 2260 if((mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2261 && aB2DPolygon.count() < 1000) 2262 { 2263 // #i98289#, #i101491# 2264 // better to remove doubles on device coordinates. Also assume from a given amount 2265 // of points that the single edges are not long enough to smooth 2266 aB2DPolygon.removeDoublePoints(); 2267 aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon); 2268 } 2269 2270 // draw the polyline 2271 return mpGraphics->DrawPolyLine( 2272 aB2DPolygon, 2273 0.0, 2274 aB2DLineWidth, 2275 eLineJoin, 2276 eLineCap, 2277 this); 2278 } 2279 2280 void OutputDevice::DrawPolyLine( 2281 const basegfx::B2DPolygon& rB2DPolygon, 2282 double fLineWidth, 2283 basegfx::B2DLineJoin eLineJoin, 2284 com::sun::star::drawing::LineCap eLineCap) 2285 { 2286 DBG_TRACE( "OutputDevice::DrawPolyLine(B2D&)" ); 2287 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2288 (void)eLineJoin; // ATM used in UNX, but not in WNT, access it for warning-free 2289 (void)eLineCap; 2290 2291 #if 0 // MetaB2DPolyLineAction is not implemented yet: 2292 // according to AW adding it is very dangerous since there is a lot 2293 // of code that uses the metafile actions directly and unless every 2294 // place that does this knows about the new action we need to fallback 2295 if( mpMetaFile ) 2296 mpMetaFile->AddAction( new MetaB2DPolyLineAction( rB2DPolygon ) ); 2297 #else 2298 if( mpMetaFile ) 2299 { 2300 LineInfo aLineInfo; 2301 if( fLineWidth != 0.0 ) 2302 aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); 2303 const Polygon aToolsPolygon( rB2DPolygon ); 2304 mpMetaFile->AddAction( new MetaPolyLineAction( aToolsPolygon, aLineInfo ) ); 2305 } 2306 #endif 2307 2308 // AW: Do NOT paint empty PolyPolygons 2309 if(!rB2DPolygon.count()) 2310 return; 2311 2312 // we need a graphics 2313 if( !mpGraphics ) 2314 if( !ImplGetGraphics() ) 2315 return; 2316 2317 if( mbInitClipRegion ) 2318 ImplInitClipRegion(); 2319 if( mbOutputClipped ) 2320 return; 2321 2322 if( mbInitLineColor ) 2323 ImplInitLineColor(); 2324 2325 const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2326 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2327 && ROP_OVERPAINT == GetRasterOp() 2328 && IsLineColor()); 2329 2330 // use b2dpolygon drawing if possible 2331 if(bTryAA && ImpTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, eLineJoin, eLineCap)) 2332 { 2333 return; 2334 } 2335 2336 // #i101491# 2337 // no output yet; fallback to geometry decomposition and use filled polygon paint 2338 // when line is fat and not too complex. ImpDrawPolyPolygonWithB2DPolyPolygon 2339 // will do internal needed AA checks etc. 2340 if(fLineWidth >= 2.5 2341 && rB2DPolygon.count() 2342 && rB2DPolygon.count() <= 1000) 2343 { 2344 const double fHalfLineWidth((fLineWidth * 0.5) + 0.5); 2345 const basegfx::B2DPolyPolygon aAreaPolyPolygon( 2346 basegfx::tools::createAreaGeometry( 2347 rB2DPolygon, 2348 fHalfLineWidth, 2349 eLineJoin, 2350 eLineCap)); 2351 const Color aOldLineColor(maLineColor); 2352 const Color aOldFillColor(maFillColor); 2353 2354 SetLineColor(); 2355 ImplInitLineColor(); 2356 SetFillColor(aOldLineColor); 2357 ImplInitFillColor(); 2358 2359 // draw usig a loop; else the topology will paint a PolyPolygon 2360 for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++) 2361 { 2362 ImpDrawPolyPolygonWithB2DPolyPolygon( 2363 basegfx::B2DPolyPolygon(aAreaPolyPolygon.getB2DPolygon(a))); 2364 } 2365 2366 SetLineColor(aOldLineColor); 2367 ImplInitLineColor(); 2368 SetFillColor(aOldFillColor); 2369 ImplInitFillColor(); 2370 2371 if(bTryAA) 2372 { 2373 // when AA it is necessary to also paint the filled polygon's outline 2374 // to avoid optical gaps 2375 for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++) 2376 { 2377 ImpTryDrawPolyLineDirect(aAreaPolyPolygon.getB2DPolygon(a)); 2378 } 2379 } 2380 } 2381 else 2382 { 2383 // fallback to old polygon drawing if needed 2384 const Polygon aToolsPolygon( rB2DPolygon ); 2385 LineInfo aLineInfo; 2386 if( fLineWidth != 0.0 ) 2387 aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); 2388 ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo ); 2389 } 2390 } 2391 2392 // ----------------------------------------------------------------------- 2393 2394 sal_uInt32 OutputDevice::GetGCStackDepth() const 2395 { 2396 const ImplObjStack* pData = mpObjStack; 2397 sal_uInt32 nDepth = 0; 2398 while( pData ) 2399 { 2400 nDepth++; 2401 pData = pData->mpPrev; 2402 } 2403 return nDepth; 2404 } 2405 2406 // ----------------------------------------------------------------------- 2407 2408 void OutputDevice::Push( sal_uInt16 nFlags ) 2409 { 2410 DBG_TRACE( "OutputDevice::Push()" ); 2411 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2412 2413 if ( mpMetaFile ) 2414 mpMetaFile->AddAction( new MetaPushAction( nFlags ) ); 2415 2416 ImplObjStack* pData = new ImplObjStack; 2417 pData->mpPrev = mpObjStack; 2418 mpObjStack = pData; 2419 2420 pData->mnFlags = nFlags; 2421 2422 if ( nFlags & PUSH_LINECOLOR ) 2423 { 2424 if ( mbLineColor ) 2425 pData->mpLineColor = new Color( maLineColor ); 2426 else 2427 pData->mpLineColor = NULL; 2428 } 2429 if ( nFlags & PUSH_FILLCOLOR ) 2430 { 2431 if ( mbFillColor ) 2432 pData->mpFillColor = new Color( maFillColor ); 2433 else 2434 pData->mpFillColor = NULL; 2435 } 2436 if ( nFlags & PUSH_FONT ) 2437 pData->mpFont = new Font( maFont ); 2438 if ( nFlags & PUSH_TEXTCOLOR ) 2439 pData->mpTextColor = new Color( GetTextColor() ); 2440 if ( nFlags & PUSH_TEXTFILLCOLOR ) 2441 { 2442 if ( IsTextFillColor() ) 2443 pData->mpTextFillColor = new Color( GetTextFillColor() ); 2444 else 2445 pData->mpTextFillColor = NULL; 2446 } 2447 if ( nFlags & PUSH_TEXTLINECOLOR ) 2448 { 2449 if ( IsTextLineColor() ) 2450 pData->mpTextLineColor = new Color( GetTextLineColor() ); 2451 else 2452 pData->mpTextLineColor = NULL; 2453 } 2454 if ( nFlags & PUSH_OVERLINECOLOR ) 2455 { 2456 if ( IsOverlineColor() ) 2457 pData->mpOverlineColor = new Color( GetOverlineColor() ); 2458 else 2459 pData->mpOverlineColor = NULL; 2460 } 2461 if ( nFlags & PUSH_TEXTALIGN ) 2462 pData->meTextAlign = GetTextAlign(); 2463 if( nFlags & PUSH_TEXTLAYOUTMODE ) 2464 pData->mnTextLayoutMode = GetLayoutMode(); 2465 if( nFlags & PUSH_TEXTLANGUAGE ) 2466 pData->meTextLanguage = GetDigitLanguage(); 2467 if ( nFlags & PUSH_RASTEROP ) 2468 pData->meRasterOp = GetRasterOp(); 2469 if ( nFlags & PUSH_MAPMODE ) 2470 { 2471 if ( mbMap ) 2472 pData->mpMapMode = new MapMode( maMapMode ); 2473 else 2474 pData->mpMapMode = NULL; 2475 } 2476 if ( nFlags & PUSH_CLIPREGION ) 2477 { 2478 if ( mbClipRegion ) 2479 pData->mpClipRegion = new Region( maRegion ); 2480 else 2481 pData->mpClipRegion = NULL; 2482 } 2483 if ( nFlags & PUSH_REFPOINT ) 2484 { 2485 if ( mbRefPoint ) 2486 pData->mpRefPoint = new Point( maRefPoint ); 2487 else 2488 pData->mpRefPoint = NULL; 2489 } 2490 2491 if( mpAlphaVDev ) 2492 mpAlphaVDev->Push(); 2493 } 2494 2495 // ----------------------------------------------------------------------- 2496 2497 void OutputDevice::Pop() 2498 { 2499 DBG_TRACE( "OutputDevice::Pop()" ); 2500 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2501 2502 if( mpMetaFile ) 2503 mpMetaFile->AddAction( new MetaPopAction() ); 2504 2505 GDIMetaFile* pOldMetaFile = mpMetaFile; 2506 ImplObjStack* pData = mpObjStack; 2507 mpMetaFile = NULL; 2508 2509 if ( !pData ) 2510 { 2511 DBG_ERRORFILE( "OutputDevice::Pop() without OutputDevice::Push()" ); 2512 return; 2513 } 2514 2515 if( mpAlphaVDev ) 2516 mpAlphaVDev->Pop(); 2517 2518 mpObjStack = pData->mpPrev; 2519 2520 if ( pData->mnFlags & PUSH_LINECOLOR ) 2521 { 2522 if ( pData->mpLineColor ) 2523 SetLineColor( *pData->mpLineColor ); 2524 else 2525 SetLineColor(); 2526 } 2527 if ( pData->mnFlags & PUSH_FILLCOLOR ) 2528 { 2529 if ( pData->mpFillColor ) 2530 SetFillColor( *pData->mpFillColor ); 2531 else 2532 SetFillColor(); 2533 } 2534 if ( pData->mnFlags & PUSH_FONT ) 2535 SetFont( *pData->mpFont ); 2536 if ( pData->mnFlags & PUSH_TEXTCOLOR ) 2537 SetTextColor( *pData->mpTextColor ); 2538 if ( pData->mnFlags & PUSH_TEXTFILLCOLOR ) 2539 { 2540 if ( pData->mpTextFillColor ) 2541 SetTextFillColor( *pData->mpTextFillColor ); 2542 else 2543 SetTextFillColor(); 2544 } 2545 if ( pData->mnFlags & PUSH_TEXTLINECOLOR ) 2546 { 2547 if ( pData->mpTextLineColor ) 2548 SetTextLineColor( *pData->mpTextLineColor ); 2549 else 2550 SetTextLineColor(); 2551 } 2552 if ( pData->mnFlags & PUSH_OVERLINECOLOR ) 2553 { 2554 if ( pData->mpOverlineColor ) 2555 SetOverlineColor( *pData->mpOverlineColor ); 2556 else 2557 SetOverlineColor(); 2558 } 2559 if ( pData->mnFlags & PUSH_TEXTALIGN ) 2560 SetTextAlign( pData->meTextAlign ); 2561 if( pData->mnFlags & PUSH_TEXTLAYOUTMODE ) 2562 SetLayoutMode( pData->mnTextLayoutMode ); 2563 if( pData->mnFlags & PUSH_TEXTLANGUAGE ) 2564 SetDigitLanguage( pData->meTextLanguage ); 2565 if ( pData->mnFlags & PUSH_RASTEROP ) 2566 SetRasterOp( pData->meRasterOp ); 2567 if ( pData->mnFlags & PUSH_MAPMODE ) 2568 { 2569 if ( pData->mpMapMode ) 2570 SetMapMode( *pData->mpMapMode ); 2571 else 2572 SetMapMode(); 2573 } 2574 if ( pData->mnFlags & PUSH_CLIPREGION ) 2575 ImplSetClipRegion( pData->mpClipRegion ); 2576 if ( pData->mnFlags & PUSH_REFPOINT ) 2577 { 2578 if ( pData->mpRefPoint ) 2579 SetRefPoint( *pData->mpRefPoint ); 2580 else 2581 SetRefPoint(); 2582 } 2583 2584 ImplDeleteObjStack( pData ); 2585 2586 mpMetaFile = pOldMetaFile; 2587 } 2588 2589 // ----------------------------------------------------------------------- 2590 2591 void OutputDevice::SetConnectMetaFile( GDIMetaFile* pMtf ) 2592 { 2593 mpMetaFile = pMtf; 2594 } 2595 2596 // ----------------------------------------------------------------------- 2597 2598 void OutputDevice::EnableOutput( sal_Bool bEnable ) 2599 { 2600 mbOutput = (bEnable != 0); 2601 2602 if( mpAlphaVDev ) 2603 mpAlphaVDev->EnableOutput( bEnable ); 2604 } 2605 2606 // ----------------------------------------------------------------------- 2607 2608 void OutputDevice::SetSettings( const AllSettings& rSettings ) 2609 { 2610 maSettings = rSettings; 2611 2612 if( mpAlphaVDev ) 2613 mpAlphaVDev->SetSettings( rSettings ); 2614 } 2615 2616 // ----------------------------------------------------------------------- 2617 2618 sal_uInt16 OutputDevice::GetBitCount() const 2619 { 2620 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2621 2622 if ( meOutDevType == OUTDEV_VIRDEV ) 2623 return ((VirtualDevice*)this)->mnBitCount; 2624 2625 // we need a graphics 2626 if ( !mpGraphics ) 2627 { 2628 if ( !((OutputDevice*)this)->ImplGetGraphics() ) 2629 return 0; 2630 } 2631 2632 return (sal_uInt16)mpGraphics->GetBitCount(); 2633 } 2634 2635 // ----------------------------------------------------------------------- 2636 2637 sal_uInt16 OutputDevice::GetAlphaBitCount() const 2638 { 2639 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2640 2641 if ( meOutDevType == OUTDEV_VIRDEV && 2642 mpAlphaVDev != NULL ) 2643 { 2644 return mpAlphaVDev->GetBitCount(); 2645 } 2646 2647 return 0; 2648 } 2649 2650 // ----------------------------------------------------------------------- 2651 2652 sal_uLong OutputDevice::GetColorCount() const 2653 { 2654 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2655 2656 const sal_uInt16 nBitCount = GetBitCount(); 2657 return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (sal_uLong) 1 ) << nBitCount) ); 2658 } 2659 2660 // ----------------------------------------------------------------------- 2661 2662 sal_Bool OutputDevice::HasAlpha() 2663 { 2664 return mpAlphaVDev != NULL; 2665 } 2666 2667 // ----------------------------------------------------------------------- 2668 2669 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > OutputDevice::CreateUnoGraphics() 2670 { 2671 UnoWrapperBase* pWrapper = Application::GetUnoWrapper(); 2672 return pWrapper ? pWrapper->CreateGraphics( this ) : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >(); 2673 } 2674 2675 // ----------------------------------------------------------------------- 2676 2677 SystemGraphicsData OutputDevice::GetSystemGfxData() const 2678 { 2679 if ( !mpGraphics ) 2680 { 2681 if ( !ImplGetGraphics() ) 2682 return SystemGraphicsData(); 2683 } 2684 2685 return mpGraphics->GetGraphicsData(); 2686 } 2687 2688 // ----------------------------------------------------------------------- 2689 2690 ::com::sun::star::uno::Any OutputDevice::GetSystemGfxDataAny() const 2691 { 2692 ::com::sun::star::uno::Any aRet; 2693 const SystemGraphicsData aSysData = GetSystemGfxData(); 2694 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)&aSysData, 2695 aSysData.nSize ); 2696 2697 return uno::makeAny(aSeq); 2698 } 2699 2700 // ----------------------------------------------------------------------- 2701 2702 ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > OutputDevice::GetCanvas() const 2703 { 2704 uno::Sequence< uno::Any > aArg(6); 2705 2706 aArg[ 0 ] = uno::makeAny( reinterpret_cast<sal_Int64>(this) ); 2707 aArg[ 2 ] = uno::makeAny( ::com::sun::star::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) ); 2708 aArg[ 3 ] = uno::makeAny( sal_False ); 2709 aArg[ 5 ] = GetSystemGfxDataAny(); 2710 2711 uno::Reference<lang::XMultiServiceFactory> xFactory = vcl::unohelper::GetMultiServiceFactory(); 2712 2713 uno::Reference<rendering::XCanvas> xCanvas; 2714 2715 // Create canvas instance with window handle 2716 // ========================================= 2717 if ( xFactory.is() ) 2718 { 2719 static uno::Reference<lang::XMultiServiceFactory> xCanvasFactory( 2720 xFactory->createInstance( 2721 OUString( RTL_CONSTASCII_USTRINGPARAM( 2722 "com.sun.star." 2723 "rendering.CanvasFactory") ) ), 2724 uno::UNO_QUERY ); 2725 if(xCanvasFactory.is()) 2726 { 2727 xCanvas.set( 2728 xCanvasFactory->createInstanceWithArguments( 2729 OUString( RTL_CONSTASCII_USTRINGPARAM( 2730 "com.sun.star.rendering.Canvas" )), 2731 aArg ), 2732 uno::UNO_QUERY ); 2733 } 2734 } 2735 2736 return xCanvas; 2737 } 2738 2739 // ----------------------------------------------------------------------- 2740