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 1002 if ( aRegion.IsEmpty() ) 1003 { 1004 mbOutputClipped = sal_True; 1005 } 1006 else 1007 { 1008 mbOutputClipped = sal_False; 1009 ImplSelectClipRegion( aRegion ); 1010 } 1011 } 1012 1013 mbClipRegionSet = sal_True; 1014 } 1015 else 1016 { 1017 if ( mbClipRegionSet ) 1018 { 1019 mpGraphics->ResetClipRegion(); 1020 mbClipRegionSet = sal_False; 1021 } 1022 1023 mbOutputClipped = sal_False; 1024 } 1025 } 1026 1027 mbInitClipRegion = sal_False; 1028 } 1029 1030 // ----------------------------------------------------------------------- 1031 1032 void OutputDevice::ImplSetClipRegion( const Region* pRegion ) 1033 { 1034 DBG_TESTSOLARMUTEX(); 1035 1036 if ( !pRegion ) 1037 { 1038 if ( mbClipRegion ) 1039 { 1040 maRegion = Region( REGION_NULL ); 1041 mbClipRegion = sal_False; 1042 mbInitClipRegion = sal_True; 1043 } 1044 } 1045 else 1046 { 1047 maRegion = *pRegion; 1048 mbClipRegion = sal_True; 1049 mbInitClipRegion = sal_True; 1050 } 1051 } 1052 1053 // ----------------------------------------------------------------------- 1054 1055 void OutputDevice::SetClipRegion() 1056 { 1057 DBG_TRACE( "OutputDevice::SetClipRegion()" ); 1058 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1059 1060 if ( mpMetaFile ) 1061 mpMetaFile->AddAction( new MetaClipRegionAction( Region(), sal_False ) ); 1062 1063 ImplSetClipRegion( NULL ); 1064 1065 if( mpAlphaVDev ) 1066 mpAlphaVDev->SetClipRegion(); 1067 } 1068 1069 // ----------------------------------------------------------------------- 1070 1071 void OutputDevice::SetClipRegion( const Region& rRegion ) 1072 { 1073 DBG_TRACE( "OutputDevice::SetClipRegion( rRegion )" ); 1074 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1075 DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion ); 1076 1077 if ( mpMetaFile ) 1078 mpMetaFile->AddAction( new MetaClipRegionAction( rRegion, sal_True ) ); 1079 1080 if ( rRegion.GetType() == REGION_NULL ) 1081 ImplSetClipRegion( NULL ); 1082 else 1083 { 1084 Region aRegion = LogicToPixel( rRegion ); 1085 ImplSetClipRegion( &aRegion ); 1086 } 1087 1088 if( mpAlphaVDev ) 1089 mpAlphaVDev->SetClipRegion( rRegion ); 1090 } 1091 1092 // ----------------------------------------------------------------------- 1093 1094 Region OutputDevice::GetClipRegion() const 1095 { 1096 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1097 1098 return PixelToLogic( maRegion ); 1099 } 1100 1101 // ----------------------------------------------------------------------- 1102 1103 Region OutputDevice::GetActiveClipRegion() const 1104 { 1105 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1106 1107 if ( GetOutDevType() == OUTDEV_WINDOW ) 1108 { 1109 Region aRegion( REGION_NULL ); 1110 Window* pWindow = (Window*)this; 1111 if ( pWindow->mpWindowImpl->mbInPaint ) 1112 { 1113 aRegion = *(pWindow->mpWindowImpl->mpPaintRegion); 1114 aRegion.Move( -mnOutOffX, -mnOutOffY ); 1115 } 1116 if ( mbClipRegion ) 1117 aRegion.Intersect( maRegion ); 1118 return PixelToLogic( aRegion ); 1119 } 1120 else 1121 return GetClipRegion(); 1122 } 1123 1124 // ----------------------------------------------------------------------- 1125 1126 void OutputDevice::MoveClipRegion( long nHorzMove, long nVertMove ) 1127 { 1128 DBG_TRACE( "OutputDevice::MoveClipRegion()" ); 1129 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1130 1131 if ( mbClipRegion ) 1132 { 1133 if( mpMetaFile ) 1134 mpMetaFile->AddAction( new MetaMoveClipRegionAction( nHorzMove, nVertMove ) ); 1135 1136 maRegion.Move( ImplLogicWidthToDevicePixel( nHorzMove ), 1137 ImplLogicHeightToDevicePixel( nVertMove ) ); 1138 mbInitClipRegion = sal_True; 1139 } 1140 1141 if( mpAlphaVDev ) 1142 mpAlphaVDev->MoveClipRegion( nHorzMove, nVertMove ); 1143 } 1144 1145 // ----------------------------------------------------------------------- 1146 1147 void OutputDevice::IntersectClipRegion( const Rectangle& rRect ) 1148 { 1149 DBG_TRACE( "OutputDevice::IntersectClipRegion( rRect )" ); 1150 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1151 1152 if ( mpMetaFile ) 1153 mpMetaFile->AddAction( new MetaISectRectClipRegionAction( rRect ) ); 1154 1155 Rectangle aRect = LogicToPixel( rRect ); 1156 maRegion.Intersect( aRect ); 1157 mbClipRegion = sal_True; 1158 mbInitClipRegion = sal_True; 1159 1160 if( mpAlphaVDev ) 1161 mpAlphaVDev->IntersectClipRegion( rRect ); 1162 } 1163 1164 // ----------------------------------------------------------------------- 1165 1166 void OutputDevice::IntersectClipRegion( const Region& rRegion ) 1167 { 1168 DBG_TRACE( "OutputDevice::IntersectClipRegion( rRegion )" ); 1169 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1170 DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion ); 1171 1172 RegionType eType = rRegion.GetType(); 1173 1174 if ( eType != REGION_NULL ) 1175 { 1176 if ( mpMetaFile ) 1177 mpMetaFile->AddAction( new MetaISectRegionClipRegionAction( rRegion ) ); 1178 1179 Region aRegion = LogicToPixel( rRegion ); 1180 maRegion.Intersect( aRegion ); 1181 mbClipRegion = sal_True; 1182 mbInitClipRegion = sal_True; 1183 } 1184 1185 if( mpAlphaVDev ) 1186 mpAlphaVDev->IntersectClipRegion( rRegion ); 1187 } 1188 1189 // ----------------------------------------------------------------------- 1190 1191 void OutputDevice::SetDrawMode( sal_uLong nDrawMode ) 1192 { 1193 DBG_TRACE1( "OutputDevice::SetDrawMode( %lx )", nDrawMode ); 1194 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1195 1196 mnDrawMode = nDrawMode; 1197 1198 if( mpAlphaVDev ) 1199 mpAlphaVDev->SetDrawMode( nDrawMode ); 1200 } 1201 1202 // ----------------------------------------------------------------------- 1203 1204 void OutputDevice::SetRasterOp( RasterOp eRasterOp ) 1205 { 1206 DBG_TRACE1( "OutputDevice::SetRasterOp( %d )", (int)eRasterOp ); 1207 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1208 1209 if ( mpMetaFile ) 1210 mpMetaFile->AddAction( new MetaRasterOpAction( eRasterOp ) ); 1211 1212 if ( meRasterOp != eRasterOp ) 1213 { 1214 meRasterOp = eRasterOp; 1215 mbInitLineColor = mbInitFillColor = sal_True; 1216 1217 if( mpGraphics || ImplGetGraphics() ) 1218 mpGraphics->SetXORMode( (ROP_INVERT == meRasterOp) || (ROP_XOR == meRasterOp), ROP_INVERT == meRasterOp ); 1219 } 1220 1221 if( mpAlphaVDev ) 1222 mpAlphaVDev->SetRasterOp( eRasterOp ); 1223 } 1224 1225 // ----------------------------------------------------------------------- 1226 1227 void OutputDevice::SetLineColor() 1228 { 1229 DBG_TRACE( "OutputDevice::SetLineColor()" ); 1230 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1231 1232 if ( mpMetaFile ) 1233 mpMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) ); 1234 1235 if ( mbLineColor ) 1236 { 1237 mbInitLineColor = sal_True; 1238 mbLineColor = sal_False; 1239 maLineColor = Color( COL_TRANSPARENT ); 1240 } 1241 1242 if( mpAlphaVDev ) 1243 mpAlphaVDev->SetLineColor(); 1244 } 1245 1246 // ----------------------------------------------------------------------- 1247 1248 void OutputDevice::SetLineColor( const Color& rColor ) 1249 { 1250 DBG_TRACE1( "OutputDevice::SetLineColor( %lx )", rColor.GetColor() ); 1251 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1252 1253 Color aColor( rColor ); 1254 1255 if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE | 1256 DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE | 1257 DRAWMODE_SETTINGSLINE ) ) 1258 { 1259 if( !ImplIsColorTransparent( aColor ) ) 1260 { 1261 if( mnDrawMode & DRAWMODE_BLACKLINE ) 1262 { 1263 aColor = Color( COL_BLACK ); 1264 } 1265 else if( mnDrawMode & DRAWMODE_WHITELINE ) 1266 { 1267 aColor = Color( COL_WHITE ); 1268 } 1269 else if( mnDrawMode & DRAWMODE_GRAYLINE ) 1270 { 1271 const sal_uInt8 cLum = aColor.GetLuminance(); 1272 aColor = Color( cLum, cLum, cLum ); 1273 } 1274 else if( mnDrawMode & DRAWMODE_SETTINGSLINE ) 1275 { 1276 aColor = GetSettings().GetStyleSettings().GetFontColor(); 1277 } 1278 1279 if( mnDrawMode & DRAWMODE_GHOSTEDLINE ) 1280 { 1281 aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80, 1282 ( aColor.GetGreen() >> 1 ) | 0x80, 1283 ( aColor.GetBlue() >> 1 ) | 0x80); 1284 } 1285 } 1286 } 1287 1288 if( mpMetaFile ) 1289 mpMetaFile->AddAction( new MetaLineColorAction( aColor, sal_True ) ); 1290 1291 if( ImplIsColorTransparent( aColor ) ) 1292 { 1293 if ( mbLineColor ) 1294 { 1295 mbInitLineColor = sal_True; 1296 mbLineColor = sal_False; 1297 maLineColor = Color( COL_TRANSPARENT ); 1298 } 1299 } 1300 else 1301 { 1302 if( maLineColor != aColor ) 1303 { 1304 mbInitLineColor = sal_True; 1305 mbLineColor = sal_True; 1306 maLineColor = aColor; 1307 } 1308 } 1309 1310 if( mpAlphaVDev ) 1311 mpAlphaVDev->SetLineColor( COL_BLACK ); 1312 } 1313 1314 // ----------------------------------------------------------------------- 1315 1316 void OutputDevice::SetFillColor() 1317 { 1318 DBG_TRACE( "OutputDevice::SetFillColor()" ); 1319 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1320 1321 if ( mpMetaFile ) 1322 mpMetaFile->AddAction( new MetaFillColorAction( Color(), sal_False ) ); 1323 1324 if ( mbFillColor ) 1325 { 1326 mbInitFillColor = sal_True; 1327 mbFillColor = sal_False; 1328 maFillColor = Color( COL_TRANSPARENT ); 1329 } 1330 1331 if( mpAlphaVDev ) 1332 mpAlphaVDev->SetFillColor(); 1333 } 1334 1335 // ----------------------------------------------------------------------- 1336 1337 void OutputDevice::SetFillColor( const Color& rColor ) 1338 { 1339 DBG_TRACE1( "OutputDevice::SetFillColor( %lx )", rColor.GetColor() ); 1340 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1341 1342 Color aColor( rColor ); 1343 1344 if( mnDrawMode & ( DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | 1345 DRAWMODE_GRAYFILL | DRAWMODE_NOFILL | 1346 DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) ) 1347 { 1348 if( !ImplIsColorTransparent( aColor ) ) 1349 { 1350 if( mnDrawMode & DRAWMODE_BLACKFILL ) 1351 { 1352 aColor = Color( COL_BLACK ); 1353 } 1354 else if( mnDrawMode & DRAWMODE_WHITEFILL ) 1355 { 1356 aColor = Color( COL_WHITE ); 1357 } 1358 else if( mnDrawMode & DRAWMODE_GRAYFILL ) 1359 { 1360 const sal_uInt8 cLum = aColor.GetLuminance(); 1361 aColor = Color( cLum, cLum, cLum ); 1362 } 1363 else if( mnDrawMode & DRAWMODE_NOFILL ) 1364 { 1365 aColor = Color( COL_TRANSPARENT ); 1366 } 1367 else if( mnDrawMode & DRAWMODE_SETTINGSFILL ) 1368 { 1369 aColor = GetSettings().GetStyleSettings().GetWindowColor(); 1370 } 1371 1372 if( mnDrawMode & DRAWMODE_GHOSTEDFILL ) 1373 { 1374 aColor = Color( (aColor.GetRed() >> 1) | 0x80, 1375 (aColor.GetGreen() >> 1) | 0x80, 1376 (aColor.GetBlue() >> 1) | 0x80); 1377 } 1378 } 1379 } 1380 1381 if ( mpMetaFile ) 1382 mpMetaFile->AddAction( new MetaFillColorAction( aColor, sal_True ) ); 1383 1384 if ( ImplIsColorTransparent( aColor ) ) 1385 { 1386 if ( mbFillColor ) 1387 { 1388 mbInitFillColor = sal_True; 1389 mbFillColor = sal_False; 1390 maFillColor = Color( COL_TRANSPARENT ); 1391 } 1392 } 1393 else 1394 { 1395 if ( maFillColor != aColor ) 1396 { 1397 mbInitFillColor = sal_True; 1398 mbFillColor = sal_True; 1399 maFillColor = aColor; 1400 } 1401 } 1402 1403 if( mpAlphaVDev ) 1404 mpAlphaVDev->SetFillColor( COL_BLACK ); 1405 } 1406 1407 // ----------------------------------------------------------------------- 1408 1409 void OutputDevice::SetBackground() 1410 { 1411 DBG_TRACE( "OutputDevice::SetBackground()" ); 1412 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1413 1414 maBackground = Wallpaper(); 1415 mbBackground = sal_False; 1416 1417 if( mpAlphaVDev ) 1418 mpAlphaVDev->SetBackground(); 1419 } 1420 1421 // ----------------------------------------------------------------------- 1422 1423 void OutputDevice::SetBackground( const Wallpaper& rBackground ) 1424 { 1425 DBG_TRACE( "OutputDevice::SetBackground( rBackground )" ); 1426 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1427 1428 maBackground = rBackground; 1429 1430 if( rBackground.GetStyle() == WALLPAPER_NULL ) 1431 mbBackground = sal_False; 1432 else 1433 mbBackground = sal_True; 1434 1435 if( mpAlphaVDev ) 1436 mpAlphaVDev->SetBackground( rBackground ); 1437 } 1438 1439 // ----------------------------------------------------------------------- 1440 1441 void OutputDevice::SetRefPoint() 1442 { 1443 DBG_TRACE( "OutputDevice::SetRefPoint()" ); 1444 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1445 1446 if ( mpMetaFile ) 1447 mpMetaFile->AddAction( new MetaRefPointAction( Point(), sal_False ) ); 1448 1449 mbRefPoint = sal_False; 1450 maRefPoint.X() = maRefPoint.Y() = 0L; 1451 1452 if( mpAlphaVDev ) 1453 mpAlphaVDev->SetRefPoint(); 1454 } 1455 1456 // ----------------------------------------------------------------------- 1457 1458 void OutputDevice::SetRefPoint( const Point& rRefPoint ) 1459 { 1460 DBG_TRACE( "OutputDevice::SetRefPoint( rRefPoint )" ); 1461 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1462 1463 if ( mpMetaFile ) 1464 mpMetaFile->AddAction( new MetaRefPointAction( rRefPoint, sal_True ) ); 1465 1466 mbRefPoint = sal_True; 1467 maRefPoint = rRefPoint; 1468 1469 if( mpAlphaVDev ) 1470 mpAlphaVDev->SetRefPoint( rRefPoint ); 1471 } 1472 1473 // ----------------------------------------------------------------------- 1474 1475 void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt ) 1476 { 1477 DBG_TRACE( "OutputDevice::DrawLine()" ); 1478 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1479 1480 if ( mpMetaFile ) 1481 mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt ) ); 1482 1483 if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() ) 1484 return; 1485 1486 if ( !mpGraphics ) 1487 { 1488 if ( !ImplGetGraphics() ) 1489 return; 1490 } 1491 1492 if ( mbInitClipRegion ) 1493 ImplInitClipRegion(); 1494 if ( mbOutputClipped ) 1495 return; 1496 1497 if ( mbInitLineColor ) 1498 ImplInitLineColor(); 1499 1500 // #i101598# support AA and snap for lines, too 1501 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 1502 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 1503 && ROP_OVERPAINT == GetRasterOp() 1504 && IsLineColor()) 1505 { 1506 // at least transform with double precision to device coordinates; this will 1507 // avoid pixel snap of single, appended lines 1508 const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation()); 1509 const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 1510 basegfx::B2DPolygon aB2DPolyLine; 1511 1512 aB2DPolyLine.append(basegfx::B2DPoint(rStartPt.X(), rStartPt.Y())); 1513 aB2DPolyLine.append(basegfx::B2DPoint(rEndPt.X(), rEndPt.Y())); 1514 aB2DPolyLine.transform( aTransform ); 1515 1516 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 1517 { 1518 aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine); 1519 } 1520 1521 if( mpGraphics->DrawPolyLine( aB2DPolyLine, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this)) 1522 { 1523 return; 1524 } 1525 } 1526 1527 const Point aStartPt(ImplLogicToDevicePixel(rStartPt)); 1528 const Point aEndPt(ImplLogicToDevicePixel(rEndPt)); 1529 1530 mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this ); 1531 1532 if( mpAlphaVDev ) 1533 mpAlphaVDev->DrawLine( rStartPt, rEndPt ); 1534 } 1535 1536 // ----------------------------------------------------------------------- 1537 1538 void OutputDevice::impPaintLineGeometryWithEvtlExpand( 1539 const LineInfo& rInfo, 1540 basegfx::B2DPolyPolygon aLinePolyPolygon) 1541 { 1542 const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 1543 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 1544 && ROP_OVERPAINT == GetRasterOp() 1545 && IsLineColor()); 1546 basegfx::B2DPolyPolygon aFillPolyPolygon; 1547 const bool bDashUsed(LINE_DASH == rInfo.GetStyle()); 1548 const bool bLineWidthUsed(rInfo.GetWidth() > 1); 1549 1550 if(bDashUsed && aLinePolyPolygon.count()) 1551 { 1552 ::std::vector< double > fDotDashArray; 1553 const double fDashLen(rInfo.GetDashLen()); 1554 const double fDotLen(rInfo.GetDotLen()); 1555 const double fDistance(rInfo.GetDistance()); 1556 1557 for(sal_uInt16 a(0); a < rInfo.GetDashCount(); a++) 1558 { 1559 fDotDashArray.push_back(fDashLen); 1560 fDotDashArray.push_back(fDistance); 1561 } 1562 1563 for(sal_uInt16 b(0); b < rInfo.GetDotCount(); b++) 1564 { 1565 fDotDashArray.push_back(fDotLen); 1566 fDotDashArray.push_back(fDistance); 1567 } 1568 1569 const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0)); 1570 1571 if(fAccumulated > 0.0) 1572 { 1573 basegfx::B2DPolyPolygon aResult; 1574 1575 for(sal_uInt32 c(0); c < aLinePolyPolygon.count(); c++) 1576 { 1577 basegfx::B2DPolyPolygon aLineTraget; 1578 basegfx::tools::applyLineDashing( 1579 aLinePolyPolygon.getB2DPolygon(c), 1580 fDotDashArray, 1581 &aLineTraget); 1582 aResult.append(aLineTraget); 1583 } 1584 1585 aLinePolyPolygon = aResult; 1586 } 1587 } 1588 1589 if(bLineWidthUsed && aLinePolyPolygon.count()) 1590 { 1591 const double fHalfLineWidth((rInfo.GetWidth() * 0.5) + 0.5); 1592 1593 if(aLinePolyPolygon.areControlPointsUsed()) 1594 { 1595 // #i110768# When area geometry has to be created, do not 1596 // use the fallback bezier decomposition inside createAreaGeometry, 1597 // but one that is at least as good as ImplSubdivideBezier was. 1598 // There, Polygon::AdaptiveSubdivide was used with default parameter 1599 // 1.0 as quality index. 1600 aLinePolyPolygon = basegfx::tools::adaptiveSubdivideByDistance(aLinePolyPolygon, 1.0); 1601 } 1602 1603 for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) 1604 { 1605 aFillPolyPolygon.append(basegfx::tools::createAreaGeometry( 1606 aLinePolyPolygon.getB2DPolygon(a), 1607 fHalfLineWidth, 1608 rInfo.GetLineJoin(), 1609 rInfo.GetLineCap())); 1610 } 1611 1612 aLinePolyPolygon.clear(); 1613 } 1614 1615 GDIMetaFile* pOldMetaFile = mpMetaFile; 1616 mpMetaFile = NULL; 1617 1618 if(aLinePolyPolygon.count()) 1619 { 1620 for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) 1621 { 1622 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); 1623 bool bDone(false); 1624 1625 if(bTryAA) 1626 { 1627 bDone = mpGraphics->DrawPolyLine( aCandidate, 0.0, basegfx::B2DVector(1.0,1.0), basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this); 1628 } 1629 1630 if(!bDone) 1631 { 1632 const Polygon aPolygon(aCandidate); 1633 mpGraphics->DrawPolyLine(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this); 1634 } 1635 } 1636 } 1637 1638 if(aFillPolyPolygon.count()) 1639 { 1640 const Color aOldLineColor( maLineColor ); 1641 const Color aOldFillColor( maFillColor ); 1642 1643 SetLineColor(); 1644 ImplInitLineColor(); 1645 SetFillColor( aOldLineColor ); 1646 ImplInitFillColor(); 1647 1648 bool bDone(false); 1649 1650 if(bTryAA) 1651 { 1652 bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this); 1653 } 1654 1655 if(!bDone) 1656 { 1657 for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) 1658 { 1659 Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a)); 1660 1661 // need to subdivide, mpGraphics->DrawPolygon ignores curves 1662 aPolygon.AdaptiveSubdivide(aPolygon); 1663 mpGraphics->DrawPolygon(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this); 1664 } 1665 } 1666 1667 SetFillColor( aOldFillColor ); 1668 SetLineColor( aOldLineColor ); 1669 } 1670 1671 mpMetaFile = pOldMetaFile; 1672 } 1673 1674 // ----------------------------------------------------------------------- 1675 1676 void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt, 1677 const LineInfo& rLineInfo ) 1678 { 1679 DBG_TRACE( "OutputDevice::DrawLine()" ); 1680 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1681 1682 if ( rLineInfo.IsDefault() ) 1683 { 1684 DrawLine( rStartPt, rEndPt ); 1685 return; 1686 } 1687 1688 if ( mpMetaFile ) 1689 mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt, rLineInfo ) ); 1690 1691 if ( !IsDeviceOutputNecessary() || !mbLineColor || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() ) 1692 return; 1693 1694 if( !mpGraphics && !ImplGetGraphics() ) 1695 return; 1696 1697 if ( mbInitClipRegion ) 1698 ImplInitClipRegion(); 1699 1700 if ( mbOutputClipped ) 1701 return; 1702 1703 const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) ); 1704 const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) ); 1705 const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) ); 1706 const bool bDashUsed(LINE_DASH == aInfo.GetStyle()); 1707 const bool bLineWidthUsed(aInfo.GetWidth() > 1); 1708 1709 if ( mbInitLineColor ) 1710 ImplInitLineColor(); 1711 1712 if(bDashUsed || bLineWidthUsed) 1713 { 1714 basegfx::B2DPolygon aLinePolygon; 1715 aLinePolygon.append(basegfx::B2DPoint(aStartPt.X(), aStartPt.Y())); 1716 aLinePolygon.append(basegfx::B2DPoint(aEndPt.X(), aEndPt.Y())); 1717 1718 impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aLinePolygon)); 1719 } 1720 else 1721 { 1722 mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this ); 1723 } 1724 1725 if( mpAlphaVDev ) 1726 mpAlphaVDev->DrawLine( rStartPt, rEndPt, rLineInfo ); 1727 } 1728 1729 // ----------------------------------------------------------------------- 1730 1731 void OutputDevice::DrawRect( const Rectangle& rRect ) 1732 { 1733 DBG_TRACE( "OutputDevice::DrawRect()" ); 1734 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1735 1736 if ( mpMetaFile ) 1737 mpMetaFile->AddAction( new MetaRectAction( rRect ) ); 1738 1739 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) 1740 return; 1741 1742 Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); 1743 1744 if ( aRect.IsEmpty() ) 1745 return; 1746 aRect.Justify(); 1747 1748 if ( !mpGraphics ) 1749 { 1750 if ( !ImplGetGraphics() ) 1751 return; 1752 } 1753 1754 if ( mbInitClipRegion ) 1755 ImplInitClipRegion(); 1756 if ( mbOutputClipped ) 1757 return; 1758 1759 if ( mbInitLineColor ) 1760 ImplInitLineColor(); 1761 if ( mbInitFillColor ) 1762 ImplInitFillColor(); 1763 1764 mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); 1765 1766 if( mpAlphaVDev ) 1767 mpAlphaVDev->DrawRect( rRect ); 1768 } 1769 1770 // ----------------------------------------------------------------------- 1771 1772 void OutputDevice::DrawPolyLine( const Polygon& rPoly ) 1773 { 1774 DBG_TRACE( "OutputDevice::DrawPolyLine()" ); 1775 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1776 DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1777 1778 if( mpMetaFile ) 1779 mpMetaFile->AddAction( new MetaPolyLineAction( rPoly ) ); 1780 1781 sal_uInt16 nPoints = rPoly.GetSize(); 1782 1783 if ( !IsDeviceOutputNecessary() || !mbLineColor || (nPoints < 2) || ImplIsRecordLayout() ) 1784 return; 1785 1786 // we need a graphics 1787 if ( !mpGraphics ) 1788 if ( !ImplGetGraphics() ) 1789 return; 1790 1791 if ( mbInitClipRegion ) 1792 ImplInitClipRegion(); 1793 if ( mbOutputClipped ) 1794 return; 1795 1796 if ( mbInitLineColor ) 1797 ImplInitLineColor(); 1798 1799 const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 1800 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 1801 && ROP_OVERPAINT == GetRasterOp() 1802 && IsLineColor()); 1803 1804 // use b2dpolygon drawing if possible 1805 if(bTryAA && ImpTryDrawPolyLineDirect(rPoly.getB2DPolygon())) 1806 { 1807 basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon()); 1808 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 1809 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 1810 1811 // transform the polygon 1812 aB2DPolyLine.transform( aTransform ); 1813 1814 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 1815 { 1816 aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine); 1817 } 1818 1819 if(mpGraphics->DrawPolyLine( aB2DPolyLine, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this)) 1820 { 1821 return; 1822 } 1823 } 1824 1825 Polygon aPoly = ImplLogicToDevicePixel( rPoly ); 1826 const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 1827 1828 // #100127# Forward beziers to sal, if any 1829 if( aPoly.HasFlags() ) 1830 { 1831 const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry(); 1832 if( !mpGraphics->DrawPolyLineBezier( nPoints, pPtAry, pFlgAry, this ) ) 1833 { 1834 aPoly = ImplSubdivideBezier(aPoly); 1835 pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 1836 mpGraphics->DrawPolyLine( aPoly.GetSize(), pPtAry, this ); 1837 } 1838 } 1839 else 1840 { 1841 mpGraphics->DrawPolyLine( nPoints, pPtAry, this ); 1842 } 1843 1844 if( mpAlphaVDev ) 1845 mpAlphaVDev->DrawPolyLine( rPoly ); 1846 } 1847 1848 // ----------------------------------------------------------------------- 1849 1850 void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo ) 1851 { 1852 DBG_TRACE( "OutputDevice::DrawPolyLine()" ); 1853 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1854 DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1855 1856 if ( rLineInfo.IsDefault() ) 1857 { 1858 DrawPolyLine( rPoly ); 1859 return; 1860 } 1861 1862 // #i101491# 1863 // Try direct Fallback to B2D-Version of DrawPolyLine 1864 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 1865 && LINE_SOLID == rLineInfo.GetStyle()) 1866 { 1867 DrawPolyLine( rPoly.getB2DPolygon(), (double)rLineInfo.GetWidth(), rLineInfo.GetLineJoin(), rLineInfo.GetLineCap()); 1868 return; 1869 } 1870 1871 if ( mpMetaFile ) 1872 mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) ); 1873 1874 ImpDrawPolyLineWithLineInfo(rPoly, rLineInfo); 1875 } 1876 1877 void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineInfo& rLineInfo) 1878 { 1879 sal_uInt16 nPoints(rPoly.GetSize()); 1880 1881 if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() ) 1882 return; 1883 1884 Polygon aPoly = ImplLogicToDevicePixel( rPoly ); 1885 1886 // #100127# LineInfo is not curve-safe, subdivide always 1887 // 1888 // What shall this mean? It's wrong to subdivide here when the 1889 // polygon is a fat line. In that case, the painted geometry 1890 // WILL be much different. 1891 // I also have no idea how this could be related to the given ID 1892 // which reads 'consolidate boost versions' in the task description. 1893 // Removing. 1894 // 1895 //if( aPoly.HasFlags() ) 1896 //{ 1897 // aPoly = ImplSubdivideBezier( aPoly ); 1898 // nPoints = aPoly.GetSize(); 1899 //} 1900 1901 // we need a graphics 1902 if ( !mpGraphics && !ImplGetGraphics() ) 1903 return; 1904 1905 if ( mbInitClipRegion ) 1906 ImplInitClipRegion(); 1907 1908 if ( mbOutputClipped ) 1909 return; 1910 1911 if ( mbInitLineColor ) 1912 ImplInitLineColor(); 1913 1914 const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) ); 1915 const bool bDashUsed(LINE_DASH == aInfo.GetStyle()); 1916 const bool bLineWidthUsed(aInfo.GetWidth() > 1); 1917 1918 if(bDashUsed || bLineWidthUsed) 1919 { 1920 impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aPoly.getB2DPolygon())); 1921 } 1922 else 1923 { 1924 // #100127# the subdivision HAS to be done here since only a pointer 1925 // to an array of points is given to the DrawPolyLine method, there is 1926 // NO way to find out there that it's a curve. 1927 if( aPoly.HasFlags() ) 1928 { 1929 aPoly = ImplSubdivideBezier( aPoly ); 1930 nPoints = aPoly.GetSize(); 1931 } 1932 1933 mpGraphics->DrawPolyLine(nPoints, (const SalPoint*)aPoly.GetConstPointAry(), this); 1934 } 1935 1936 if( mpAlphaVDev ) 1937 mpAlphaVDev->DrawPolyLine( rPoly, rLineInfo ); 1938 } 1939 1940 // ----------------------------------------------------------------------- 1941 1942 void OutputDevice::DrawPolygon( const Polygon& rPoly ) 1943 { 1944 DBG_TRACE( "OutputDevice::DrawPolygon()" ); 1945 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1946 DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1947 1948 if( mpMetaFile ) 1949 mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) ); 1950 1951 sal_uInt16 nPoints = rPoly.GetSize(); 1952 1953 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) || ImplIsRecordLayout() ) 1954 return; 1955 1956 // we need a graphics 1957 if ( !mpGraphics ) 1958 if ( !ImplGetGraphics() ) 1959 return; 1960 1961 if ( mbInitClipRegion ) 1962 ImplInitClipRegion(); 1963 if ( mbOutputClipped ) 1964 return; 1965 1966 if ( mbInitLineColor ) 1967 ImplInitLineColor(); 1968 if ( mbInitFillColor ) 1969 ImplInitFillColor(); 1970 1971 // use b2dpolygon drawing if possible 1972 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 1973 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 1974 && ROP_OVERPAINT == GetRasterOp() 1975 && (IsLineColor() || IsFillColor())) 1976 { 1977 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 1978 basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon()); 1979 bool bSuccess(true); 1980 1981 // transform the polygon and ensure closed 1982 aB2DPolygon.transform(aTransform); 1983 aB2DPolygon.setClosed(true); 1984 1985 if(IsFillColor()) 1986 { 1987 bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this); 1988 } 1989 1990 if(bSuccess && IsLineColor()) 1991 { 1992 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 1993 1994 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 1995 { 1996 aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon); 1997 } 1998 1999 bSuccess = mpGraphics->DrawPolyLine( 2000 aB2DPolygon, 2001 0.0, 2002 aB2DLineWidth, 2003 basegfx::B2DLINEJOIN_NONE, 2004 com::sun::star::drawing::LineCap_BUTT, 2005 this); 2006 } 2007 2008 if(bSuccess) 2009 { 2010 return; 2011 } 2012 } 2013 2014 Polygon aPoly = ImplLogicToDevicePixel( rPoly ); 2015 const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 2016 2017 // #100127# Forward beziers to sal, if any 2018 if( aPoly.HasFlags() ) 2019 { 2020 const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry(); 2021 if( !mpGraphics->DrawPolygonBezier( nPoints, pPtAry, pFlgAry, this ) ) 2022 { 2023 aPoly = ImplSubdivideBezier(aPoly); 2024 pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); 2025 mpGraphics->DrawPolygon( aPoly.GetSize(), pPtAry, this ); 2026 } 2027 } 2028 else 2029 { 2030 mpGraphics->DrawPolygon( nPoints, pPtAry, this ); 2031 } 2032 if( mpAlphaVDev ) 2033 mpAlphaVDev->DrawPolygon( rPoly ); 2034 } 2035 2036 // ----------------------------------------------------------------------- 2037 2038 void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly ) 2039 { 2040 DBG_TRACE( "OutputDevice::DrawPolyPolygon()" ); 2041 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2042 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL ); 2043 2044 if( mpMetaFile ) 2045 mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) ); 2046 2047 sal_uInt16 nPoly = rPolyPoly.Count(); 2048 2049 if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly || ImplIsRecordLayout() ) 2050 return; 2051 2052 // we need a graphics 2053 if ( !mpGraphics ) 2054 if ( !ImplGetGraphics() ) 2055 return; 2056 2057 if ( mbInitClipRegion ) 2058 ImplInitClipRegion(); 2059 if ( mbOutputClipped ) 2060 return; 2061 2062 if ( mbInitLineColor ) 2063 ImplInitLineColor(); 2064 if ( mbInitFillColor ) 2065 ImplInitFillColor(); 2066 2067 // use b2dpolygon drawing if possible 2068 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2069 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2070 && ROP_OVERPAINT == GetRasterOp() 2071 && (IsLineColor() || IsFillColor())) 2072 { 2073 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 2074 basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon()); 2075 bool bSuccess(true); 2076 2077 // transform the polygon and ensure closed 2078 aB2DPolyPolygon.transform(aTransform); 2079 aB2DPolyPolygon.setClosed(true); 2080 2081 if(IsFillColor()) 2082 { 2083 bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this); 2084 } 2085 2086 if(bSuccess && IsLineColor()) 2087 { 2088 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 2089 2090 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2091 { 2092 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon); 2093 } 2094 2095 for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++) 2096 { 2097 bSuccess = mpGraphics->DrawPolyLine( 2098 aB2DPolyPolygon.getB2DPolygon(a), 2099 0.0, 2100 aB2DLineWidth, 2101 basegfx::B2DLINEJOIN_NONE, 2102 com::sun::star::drawing::LineCap_BUTT, 2103 this); 2104 } 2105 } 2106 2107 if(bSuccess) 2108 { 2109 return; 2110 } 2111 } 2112 2113 if ( nPoly == 1 ) 2114 { 2115 // #100127# Map to DrawPolygon 2116 Polygon aPoly = rPolyPoly.GetObject( 0 ); 2117 if( aPoly.GetSize() >= 2 ) 2118 { 2119 GDIMetaFile* pOldMF = mpMetaFile; 2120 mpMetaFile = NULL; 2121 2122 DrawPolygon( aPoly ); 2123 2124 mpMetaFile = pOldMF; 2125 } 2126 } 2127 else 2128 { 2129 // #100127# moved real PolyPolygon draw to separate method, 2130 // have to call recursively, avoiding duplicate 2131 // ImplLogicToDevicePixel calls 2132 ImplDrawPolyPolygon( nPoly, ImplLogicToDevicePixel( rPolyPoly ) ); 2133 } 2134 if( mpAlphaVDev ) 2135 mpAlphaVDev->DrawPolyPolygon( rPolyPoly ); 2136 } 2137 2138 // ----------------------------------------------------------------------- 2139 2140 void OutputDevice::DrawPolygon( const ::basegfx::B2DPolygon& rB2DPolygon) 2141 { 2142 // AW: Do NOT paint empty polygons 2143 if(rB2DPolygon.count()) 2144 { 2145 ::basegfx::B2DPolyPolygon aPP( rB2DPolygon ); 2146 DrawPolyPolygon( aPP ); 2147 } 2148 } 2149 2150 // ----------------------------------------------------------------------- 2151 // Caution: This method is nearly the same as 2152 // OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency), 2153 // so when changes are made here do not forget to make change sthere, too 2154 2155 void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly ) 2156 { 2157 DBG_TRACE( "OutputDevice::DrawPolyPolygon(B2D&)" ); 2158 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2159 2160 #if 0 2161 // MetaB2DPolyPolygonAction is not implemented yet: 2162 // according to AW adding it is very dangerous since there is a lot 2163 // of code that uses the metafile actions directly and unless every 2164 // place that does this knows about the new action we need to fallback 2165 if( mpMetaFile ) 2166 mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) ); 2167 #else 2168 if( mpMetaFile ) 2169 mpMetaFile->AddAction( new MetaPolyPolygonAction( PolyPolygon( rB2DPolyPoly ) ) ); 2170 #endif 2171 2172 // call helper 2173 ImpDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly); 2174 } 2175 2176 void OutputDevice::ImpDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly) 2177 { 2178 // AW: Do NOT paint empty PolyPolygons 2179 if(!rB2DPolyPoly.count()) 2180 return; 2181 2182 // we need a graphics 2183 if( !mpGraphics ) 2184 if( !ImplGetGraphics() ) 2185 return; 2186 2187 if( mbInitClipRegion ) 2188 ImplInitClipRegion(); 2189 if( mbOutputClipped ) 2190 return; 2191 2192 if( mbInitLineColor ) 2193 ImplInitLineColor(); 2194 if( mbInitFillColor ) 2195 ImplInitFillColor(); 2196 2197 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2198 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2199 && ROP_OVERPAINT == GetRasterOp() 2200 && (IsLineColor() || IsFillColor())) 2201 { 2202 const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation()); 2203 basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly); 2204 bool bSuccess(true); 2205 2206 // transform the polygon and ensure closed 2207 aB2DPolyPolygon.transform(aTransform); 2208 aB2DPolyPolygon.setClosed(true); 2209 2210 if(IsFillColor()) 2211 { 2212 bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this); 2213 } 2214 2215 if(bSuccess && IsLineColor()) 2216 { 2217 const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); 2218 2219 if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2220 { 2221 aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon); 2222 } 2223 2224 for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++) 2225 { 2226 bSuccess = mpGraphics->DrawPolyLine( 2227 aB2DPolyPolygon.getB2DPolygon(a), 2228 0.0, 2229 aB2DLineWidth, 2230 basegfx::B2DLINEJOIN_NONE, 2231 com::sun::star::drawing::LineCap_BUTT, 2232 this); 2233 } 2234 } 2235 2236 if(bSuccess) 2237 { 2238 return; 2239 } 2240 } 2241 2242 // fallback to old polygon drawing if needed 2243 const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly ); 2244 const PolyPolygon aPixelPolyPolygon = ImplLogicToDevicePixel( aToolsPolyPolygon ); 2245 ImplDrawPolyPolygon( aPixelPolyPolygon.Count(), aPixelPolyPolygon ); 2246 } 2247 2248 // ----------------------------------------------------------------------- 2249 2250 bool OutputDevice::ImpTryDrawPolyLineDirect( 2251 const basegfx::B2DPolygon& rB2DPolygon, 2252 double fLineWidth, 2253 basegfx::B2DLineJoin eLineJoin, 2254 com::sun::star::drawing::LineCap eLineCap) 2255 { 2256 const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 2257 basegfx::B2DVector aB2DLineWidth(1.0, 1.0); 2258 2259 // transform the line width if used 2260 if( fLineWidth != 0.0 ) 2261 { 2262 aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth ); 2263 } 2264 2265 // transform the polygon 2266 basegfx::B2DPolygon aB2DPolygon(rB2DPolygon); 2267 aB2DPolygon.transform(aTransform); 2268 2269 if((mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) 2270 && aB2DPolygon.count() < 1000) 2271 { 2272 // #i98289#, #i101491# 2273 // better to remove doubles on device coordinates. Also assume from a given amount 2274 // of points that the single edges are not long enough to smooth 2275 aB2DPolygon.removeDoublePoints(); 2276 aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon); 2277 } 2278 2279 // draw the polyline 2280 return mpGraphics->DrawPolyLine( 2281 aB2DPolygon, 2282 0.0, 2283 aB2DLineWidth, 2284 eLineJoin, 2285 eLineCap, 2286 this); 2287 } 2288 2289 void OutputDevice::DrawPolyLine( 2290 const basegfx::B2DPolygon& rB2DPolygon, 2291 double fLineWidth, 2292 basegfx::B2DLineJoin eLineJoin, 2293 com::sun::star::drawing::LineCap eLineCap) 2294 { 2295 DBG_TRACE( "OutputDevice::DrawPolyLine(B2D&)" ); 2296 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2297 (void)eLineJoin; // ATM used in UNX, but not in WNT, access it for warning-free 2298 (void)eLineCap; 2299 2300 #if 0 // MetaB2DPolyLineAction is not implemented yet: 2301 // according to AW adding it is very dangerous since there is a lot 2302 // of code that uses the metafile actions directly and unless every 2303 // place that does this knows about the new action we need to fallback 2304 if( mpMetaFile ) 2305 mpMetaFile->AddAction( new MetaB2DPolyLineAction( rB2DPolygon ) ); 2306 #else 2307 if( mpMetaFile ) 2308 { 2309 LineInfo aLineInfo; 2310 if( fLineWidth != 0.0 ) 2311 aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); 2312 const Polygon aToolsPolygon( rB2DPolygon ); 2313 mpMetaFile->AddAction( new MetaPolyLineAction( aToolsPolygon, aLineInfo ) ); 2314 } 2315 #endif 2316 2317 // AW: Do NOT paint empty PolyPolygons 2318 if(!rB2DPolygon.count()) 2319 return; 2320 2321 // we need a graphics 2322 if( !mpGraphics ) 2323 if( !ImplGetGraphics() ) 2324 return; 2325 2326 if( mbInitClipRegion ) 2327 ImplInitClipRegion(); 2328 if( mbOutputClipped ) 2329 return; 2330 2331 if( mbInitLineColor ) 2332 ImplInitLineColor(); 2333 2334 const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 2335 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 2336 && ROP_OVERPAINT == GetRasterOp() 2337 && IsLineColor()); 2338 2339 // use b2dpolygon drawing if possible 2340 if(bTryAA && ImpTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, eLineJoin, eLineCap)) 2341 { 2342 return; 2343 } 2344 2345 // #i101491# 2346 // no output yet; fallback to geometry decomposition and use filled polygon paint 2347 // when line is fat and not too complex. ImpDrawPolyPolygonWithB2DPolyPolygon 2348 // will do internal needed AA checks etc. 2349 if(fLineWidth >= 2.5 2350 && rB2DPolygon.count() 2351 && rB2DPolygon.count() <= 1000) 2352 { 2353 const double fHalfLineWidth((fLineWidth * 0.5) + 0.5); 2354 const basegfx::B2DPolyPolygon aAreaPolyPolygon( 2355 basegfx::tools::createAreaGeometry( 2356 rB2DPolygon, 2357 fHalfLineWidth, 2358 eLineJoin, 2359 eLineCap)); 2360 const Color aOldLineColor(maLineColor); 2361 const Color aOldFillColor(maFillColor); 2362 2363 SetLineColor(); 2364 ImplInitLineColor(); 2365 SetFillColor(aOldLineColor); 2366 ImplInitFillColor(); 2367 2368 // draw usig a loop; else the topology will paint a PolyPolygon 2369 for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++) 2370 { 2371 ImpDrawPolyPolygonWithB2DPolyPolygon( 2372 basegfx::B2DPolyPolygon(aAreaPolyPolygon.getB2DPolygon(a))); 2373 } 2374 2375 SetLineColor(aOldLineColor); 2376 ImplInitLineColor(); 2377 SetFillColor(aOldFillColor); 2378 ImplInitFillColor(); 2379 2380 if(bTryAA) 2381 { 2382 // when AA it is necessary to also paint the filled polygon's outline 2383 // to avoid optical gaps 2384 for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++) 2385 { 2386 ImpTryDrawPolyLineDirect(aAreaPolyPolygon.getB2DPolygon(a)); 2387 } 2388 } 2389 } 2390 else 2391 { 2392 // fallback to old polygon drawing if needed 2393 const Polygon aToolsPolygon( rB2DPolygon ); 2394 LineInfo aLineInfo; 2395 if( fLineWidth != 0.0 ) 2396 aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); 2397 ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo ); 2398 } 2399 } 2400 2401 // ----------------------------------------------------------------------- 2402 2403 sal_uInt32 OutputDevice::GetGCStackDepth() const 2404 { 2405 const ImplObjStack* pData = mpObjStack; 2406 sal_uInt32 nDepth = 0; 2407 while( pData ) 2408 { 2409 nDepth++; 2410 pData = pData->mpPrev; 2411 } 2412 return nDepth; 2413 } 2414 2415 // ----------------------------------------------------------------------- 2416 2417 void OutputDevice::Push( sal_uInt16 nFlags ) 2418 { 2419 DBG_TRACE( "OutputDevice::Push()" ); 2420 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2421 2422 if ( mpMetaFile ) 2423 mpMetaFile->AddAction( new MetaPushAction( nFlags ) ); 2424 2425 ImplObjStack* pData = new ImplObjStack; 2426 pData->mpPrev = mpObjStack; 2427 mpObjStack = pData; 2428 2429 pData->mnFlags = nFlags; 2430 2431 if ( nFlags & PUSH_LINECOLOR ) 2432 { 2433 if ( mbLineColor ) 2434 pData->mpLineColor = new Color( maLineColor ); 2435 else 2436 pData->mpLineColor = NULL; 2437 } 2438 if ( nFlags & PUSH_FILLCOLOR ) 2439 { 2440 if ( mbFillColor ) 2441 pData->mpFillColor = new Color( maFillColor ); 2442 else 2443 pData->mpFillColor = NULL; 2444 } 2445 if ( nFlags & PUSH_FONT ) 2446 pData->mpFont = new Font( maFont ); 2447 if ( nFlags & PUSH_TEXTCOLOR ) 2448 pData->mpTextColor = new Color( GetTextColor() ); 2449 if ( nFlags & PUSH_TEXTFILLCOLOR ) 2450 { 2451 if ( IsTextFillColor() ) 2452 pData->mpTextFillColor = new Color( GetTextFillColor() ); 2453 else 2454 pData->mpTextFillColor = NULL; 2455 } 2456 if ( nFlags & PUSH_TEXTLINECOLOR ) 2457 { 2458 if ( IsTextLineColor() ) 2459 pData->mpTextLineColor = new Color( GetTextLineColor() ); 2460 else 2461 pData->mpTextLineColor = NULL; 2462 } 2463 if ( nFlags & PUSH_OVERLINECOLOR ) 2464 { 2465 if ( IsOverlineColor() ) 2466 pData->mpOverlineColor = new Color( GetOverlineColor() ); 2467 else 2468 pData->mpOverlineColor = NULL; 2469 } 2470 if ( nFlags & PUSH_TEXTALIGN ) 2471 pData->meTextAlign = GetTextAlign(); 2472 if( nFlags & PUSH_TEXTLAYOUTMODE ) 2473 pData->mnTextLayoutMode = GetLayoutMode(); 2474 if( nFlags & PUSH_TEXTLANGUAGE ) 2475 pData->meTextLanguage = GetDigitLanguage(); 2476 if ( nFlags & PUSH_RASTEROP ) 2477 pData->meRasterOp = GetRasterOp(); 2478 if ( nFlags & PUSH_MAPMODE ) 2479 { 2480 if ( mbMap ) 2481 pData->mpMapMode = new MapMode( maMapMode ); 2482 else 2483 pData->mpMapMode = NULL; 2484 } 2485 if ( nFlags & PUSH_CLIPREGION ) 2486 { 2487 if ( mbClipRegion ) 2488 pData->mpClipRegion = new Region( maRegion ); 2489 else 2490 pData->mpClipRegion = NULL; 2491 } 2492 if ( nFlags & PUSH_REFPOINT ) 2493 { 2494 if ( mbRefPoint ) 2495 pData->mpRefPoint = new Point( maRefPoint ); 2496 else 2497 pData->mpRefPoint = NULL; 2498 } 2499 2500 if( mpAlphaVDev ) 2501 mpAlphaVDev->Push(); 2502 } 2503 2504 // ----------------------------------------------------------------------- 2505 2506 void OutputDevice::Pop() 2507 { 2508 DBG_TRACE( "OutputDevice::Pop()" ); 2509 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2510 2511 if( mpMetaFile ) 2512 mpMetaFile->AddAction( new MetaPopAction() ); 2513 2514 GDIMetaFile* pOldMetaFile = mpMetaFile; 2515 ImplObjStack* pData = mpObjStack; 2516 mpMetaFile = NULL; 2517 2518 if ( !pData ) 2519 { 2520 DBG_ERRORFILE( "OutputDevice::Pop() without OutputDevice::Push()" ); 2521 return; 2522 } 2523 2524 if( mpAlphaVDev ) 2525 mpAlphaVDev->Pop(); 2526 2527 mpObjStack = pData->mpPrev; 2528 2529 if ( pData->mnFlags & PUSH_LINECOLOR ) 2530 { 2531 if ( pData->mpLineColor ) 2532 SetLineColor( *pData->mpLineColor ); 2533 else 2534 SetLineColor(); 2535 } 2536 if ( pData->mnFlags & PUSH_FILLCOLOR ) 2537 { 2538 if ( pData->mpFillColor ) 2539 SetFillColor( *pData->mpFillColor ); 2540 else 2541 SetFillColor(); 2542 } 2543 if ( pData->mnFlags & PUSH_FONT ) 2544 SetFont( *pData->mpFont ); 2545 if ( pData->mnFlags & PUSH_TEXTCOLOR ) 2546 SetTextColor( *pData->mpTextColor ); 2547 if ( pData->mnFlags & PUSH_TEXTFILLCOLOR ) 2548 { 2549 if ( pData->mpTextFillColor ) 2550 SetTextFillColor( *pData->mpTextFillColor ); 2551 else 2552 SetTextFillColor(); 2553 } 2554 if ( pData->mnFlags & PUSH_TEXTLINECOLOR ) 2555 { 2556 if ( pData->mpTextLineColor ) 2557 SetTextLineColor( *pData->mpTextLineColor ); 2558 else 2559 SetTextLineColor(); 2560 } 2561 if ( pData->mnFlags & PUSH_OVERLINECOLOR ) 2562 { 2563 if ( pData->mpOverlineColor ) 2564 SetOverlineColor( *pData->mpOverlineColor ); 2565 else 2566 SetOverlineColor(); 2567 } 2568 if ( pData->mnFlags & PUSH_TEXTALIGN ) 2569 SetTextAlign( pData->meTextAlign ); 2570 if( pData->mnFlags & PUSH_TEXTLAYOUTMODE ) 2571 SetLayoutMode( pData->mnTextLayoutMode ); 2572 if( pData->mnFlags & PUSH_TEXTLANGUAGE ) 2573 SetDigitLanguage( pData->meTextLanguage ); 2574 if ( pData->mnFlags & PUSH_RASTEROP ) 2575 SetRasterOp( pData->meRasterOp ); 2576 if ( pData->mnFlags & PUSH_MAPMODE ) 2577 { 2578 if ( pData->mpMapMode ) 2579 SetMapMode( *pData->mpMapMode ); 2580 else 2581 SetMapMode(); 2582 } 2583 if ( pData->mnFlags & PUSH_CLIPREGION ) 2584 ImplSetClipRegion( pData->mpClipRegion ); 2585 if ( pData->mnFlags & PUSH_REFPOINT ) 2586 { 2587 if ( pData->mpRefPoint ) 2588 SetRefPoint( *pData->mpRefPoint ); 2589 else 2590 SetRefPoint(); 2591 } 2592 2593 ImplDeleteObjStack( pData ); 2594 2595 mpMetaFile = pOldMetaFile; 2596 } 2597 2598 // ----------------------------------------------------------------------- 2599 2600 void OutputDevice::SetConnectMetaFile( GDIMetaFile* pMtf ) 2601 { 2602 mpMetaFile = pMtf; 2603 } 2604 2605 // ----------------------------------------------------------------------- 2606 2607 void OutputDevice::EnableOutput( sal_Bool bEnable ) 2608 { 2609 mbOutput = (bEnable != 0); 2610 2611 if( mpAlphaVDev ) 2612 mpAlphaVDev->EnableOutput( bEnable ); 2613 } 2614 2615 // ----------------------------------------------------------------------- 2616 2617 void OutputDevice::SetSettings( const AllSettings& rSettings ) 2618 { 2619 maSettings = rSettings; 2620 2621 if( mpAlphaVDev ) 2622 mpAlphaVDev->SetSettings( rSettings ); 2623 } 2624 2625 // ----------------------------------------------------------------------- 2626 2627 sal_uInt16 OutputDevice::GetBitCount() const 2628 { 2629 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2630 2631 if ( meOutDevType == OUTDEV_VIRDEV ) 2632 return ((VirtualDevice*)this)->mnBitCount; 2633 2634 // we need a graphics 2635 if ( !mpGraphics ) 2636 { 2637 if ( !((OutputDevice*)this)->ImplGetGraphics() ) 2638 return 0; 2639 } 2640 2641 return (sal_uInt16)mpGraphics->GetBitCount(); 2642 } 2643 2644 // ----------------------------------------------------------------------- 2645 2646 sal_uInt16 OutputDevice::GetAlphaBitCount() const 2647 { 2648 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2649 2650 if ( meOutDevType == OUTDEV_VIRDEV && 2651 mpAlphaVDev != NULL ) 2652 { 2653 return mpAlphaVDev->GetBitCount(); 2654 } 2655 2656 return 0; 2657 } 2658 2659 // ----------------------------------------------------------------------- 2660 2661 sal_uLong OutputDevice::GetColorCount() const 2662 { 2663 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 2664 2665 const sal_uInt16 nBitCount = GetBitCount(); 2666 return( ( nBitCount > 31 ) ? ULONG_MAX : ( ( (sal_uLong) 1 ) << nBitCount) ); 2667 } 2668 2669 // ----------------------------------------------------------------------- 2670 2671 sal_Bool OutputDevice::HasAlpha() 2672 { 2673 return mpAlphaVDev != NULL; 2674 } 2675 2676 // ----------------------------------------------------------------------- 2677 2678 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics > OutputDevice::CreateUnoGraphics() 2679 { 2680 UnoWrapperBase* pWrapper = Application::GetUnoWrapper(); 2681 return pWrapper ? pWrapper->CreateGraphics( this ) : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >(); 2682 } 2683 2684 // ----------------------------------------------------------------------- 2685 2686 SystemGraphicsData OutputDevice::GetSystemGfxData() const 2687 { 2688 if ( !mpGraphics ) 2689 { 2690 if ( !ImplGetGraphics() ) 2691 return SystemGraphicsData(); 2692 } 2693 2694 return mpGraphics->GetGraphicsData(); 2695 } 2696 2697 // ----------------------------------------------------------------------- 2698 2699 ::com::sun::star::uno::Any OutputDevice::GetSystemGfxDataAny() const 2700 { 2701 ::com::sun::star::uno::Any aRet; 2702 const SystemGraphicsData aSysData = GetSystemGfxData(); 2703 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)&aSysData, 2704 aSysData.nSize ); 2705 2706 return uno::makeAny(aSeq); 2707 } 2708 2709 // ----------------------------------------------------------------------- 2710 2711 ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvas > OutputDevice::GetCanvas() const 2712 { 2713 uno::Sequence< uno::Any > aArg(6); 2714 2715 aArg[ 0 ] = uno::makeAny( reinterpret_cast<sal_Int64>(this) ); 2716 aArg[ 2 ] = uno::makeAny( ::com::sun::star::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) ); 2717 aArg[ 3 ] = uno::makeAny( sal_False ); 2718 aArg[ 5 ] = GetSystemGfxDataAny(); 2719 2720 uno::Reference<lang::XMultiServiceFactory> xFactory = vcl::unohelper::GetMultiServiceFactory(); 2721 2722 uno::Reference<rendering::XCanvas> xCanvas; 2723 2724 // Create canvas instance with window handle 2725 // ========================================= 2726 if ( xFactory.is() ) 2727 { 2728 static uno::Reference<lang::XMultiServiceFactory> xCanvasFactory( 2729 xFactory->createInstance( 2730 OUString( RTL_CONSTASCII_USTRINGPARAM( 2731 "com.sun.star." 2732 "rendering.CanvasFactory") ) ), 2733 uno::UNO_QUERY ); 2734 if(xCanvasFactory.is()) 2735 { 2736 xCanvas.set( 2737 xCanvasFactory->createInstanceWithArguments( 2738 OUString( RTL_CONSTASCII_USTRINGPARAM( 2739 "com.sun.star.rendering.Canvas" )), 2740 aArg ), 2741 uno::UNO_QUERY ); 2742 } 2743 } 2744 2745 return xCanvas; 2746 } 2747 2748 // ----------------------------------------------------------------------- 2749