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