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