1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include <tools/debug.hxx> 32 #include <vcl/outdev.hxx> 33 #include <vcl/virdev.hxx> 34 #include <vcl/bmpacc.hxx> 35 #include <vcl/metaact.hxx> 36 #include <vcl/gdimtf.hxx> 37 #include <vcl/svapp.hxx> 38 #include <vcl/wrkwin.hxx> 39 #include <vcl/graph.hxx> 40 #include <vcl/rendergraphicrasterizer.hxx> 41 42 #include <wall2.hxx> 43 #include <salgdi.hxx> 44 #include <window.h> 45 #include <svdata.hxx> 46 #include <outdev.h> 47 48 #include <com/sun/star/uno/Sequence.hxx> 49 50 #include <basegfx/vector/b2dvector.hxx> 51 #include <basegfx/polygon/b2dpolypolygon.hxx> 52 #include <basegfx/polygon/b2dpolygon.hxx> 53 #include <basegfx/matrix/b2dhommatrix.hxx> 54 55 #include <math.h> 56 57 // ======================================================================== 58 59 DBG_NAMEEX( OutputDevice ) 60 61 // ------------------------------------------------------------------------ 62 63 void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags ) 64 { 65 DBG_TRACE( "OutputDevice::DrawGrid()" ); 66 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 67 68 Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() ); 69 aDstRect.Intersection( rRect ); 70 71 if( aDstRect.IsEmpty() || ImplIsRecordLayout() ) 72 return; 73 74 if( !mpGraphics && !ImplGetGraphics() ) 75 return; 76 77 if( mbInitClipRegion ) 78 ImplInitClipRegion(); 79 80 if( mbOutputClipped ) 81 return; 82 83 const long nDistX = Max( rDist.Width(), 1L ); 84 const long nDistY = Max( rDist.Height(), 1L ); 85 long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX ); 86 long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY ); 87 const long nRight = aDstRect.Right(); 88 const long nBottom = aDstRect.Bottom(); 89 const long nStartX = ImplLogicXToDevicePixel( nX ); 90 const long nEndX = ImplLogicXToDevicePixel( nRight ); 91 const long nStartY = ImplLogicYToDevicePixel( nY ); 92 const long nEndY = ImplLogicYToDevicePixel( nBottom ); 93 long nHorzCount = 0L; 94 long nVertCount = 0L; 95 96 ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf; 97 ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf; 98 99 if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) ) 100 { 101 aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L ); 102 aVertBuf[ nVertCount++ ] = nStartY; 103 while( ( nY += nDistY ) <= nBottom ) 104 aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY ); 105 } 106 107 if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) ) 108 { 109 aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L ); 110 aHorzBuf[ nHorzCount++ ] = nStartX; 111 while( ( nX += nDistX ) <= nRight ) 112 aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX ); 113 } 114 115 if( mbInitLineColor ) 116 ImplInitLineColor(); 117 118 if( mbInitFillColor ) 119 ImplInitFillColor(); 120 121 const sal_Bool bOldMap = mbMap; 122 EnableMapMode( sal_False ); 123 124 if( nFlags & GRID_DOTS ) 125 { 126 for( long i = 0L; i < nVertCount; i++ ) 127 for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ ) 128 mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this ); 129 } 130 else 131 { 132 if( nFlags & GRID_HORZLINES ) 133 { 134 for( long i = 0L; i < nVertCount; i++ ) 135 { 136 nY = aVertBuf[ i ]; 137 mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this ); 138 } 139 } 140 141 if( nFlags & GRID_VERTLINES ) 142 { 143 for( long i = 0L; i < nHorzCount; i++ ) 144 { 145 nX = aHorzBuf[ i ]; 146 mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this ); 147 } 148 } 149 } 150 151 EnableMapMode( bOldMap ); 152 153 if( mpAlphaVDev ) 154 mpAlphaVDev->DrawGrid( rRect, rDist, nFlags ); 155 } 156 157 // ------------------------------------------------------------------------ 158 // Caution: This method is nearly the same as 159 // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly ) 160 // so when changes are made here do not forget to make change sthere, too 161 162 void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency) 163 { 164 DBG_TRACE( "OutputDevice::DrawTransparent(B2D&,transparency)" ); 165 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 166 167 // AW: Do NOT paint empty PolyPolygons 168 if(!rB2DPolyPoly.count()) 169 return; 170 171 // we need a graphics 172 if( !mpGraphics ) 173 if( !ImplGetGraphics() ) 174 return; 175 176 if( mbInitClipRegion ) 177 ImplInitClipRegion(); 178 if( mbOutputClipped ) 179 return; 180 181 if( mbInitLineColor ) 182 ImplInitLineColor(); 183 if( mbInitFillColor ) 184 ImplInitFillColor(); 185 186 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 187 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 188 && ROP_OVERPAINT == GetRasterOp() ) 189 { 190 // b2dpolygon support not implemented yet on non-UNX platforms 191 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 192 basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly); 193 194 // transform the polygon into device space and ensure it is closed 195 aB2DPolyPolygon.transform( aTransform ); 196 aB2DPolyPolygon.setClosed( true ); 197 198 bool bDrawnOk = true; 199 if( IsFillColor() ) 200 bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this ); 201 if( bDrawnOk && IsLineColor() ) 202 { 203 const basegfx::B2DVector aHairlineWidth(1,1); 204 const int nPolyCount = aB2DPolyPolygon.count(); 205 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 206 { 207 const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx ); 208 mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, this ); 209 } 210 } 211 212 if( bDrawnOk ) 213 { 214 #if 0 215 // MetaB2DPolyPolygonAction is not implemented yet: 216 // according to AW adding it is very dangerous since there is a lot 217 // of code that uses the metafile actions directly and unless every 218 // place that does this knows about the new action we need to fallback 219 if( mpMetaFile ) 220 mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) ); 221 #else 222 if( mpMetaFile ) 223 mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0))); 224 #endif 225 return; 226 } 227 } 228 229 // fallback to old polygon drawing if needed 230 const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly ); 231 DrawTransparent(PolyPolygon(rB2DPolyPoly), static_cast< sal_uInt16 >(fTransparency * 100.0)); 232 } 233 234 // ------------------------------------------------------------------------ 235 236 void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly, 237 sal_uInt16 nTransparencePercent ) 238 { 239 DBG_TRACE( "OutputDevice::DrawTransparent()" ); 240 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 241 242 // short circuit for drawing an opaque polygon 243 if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) ) 244 { 245 DrawPolyPolygon( rPolyPoly ); 246 return; 247 } 248 249 // short circut for drawing an invisible polygon 250 if( !mbFillColor || (nTransparencePercent >= 100) ) 251 { 252 // short circuit if the polygon border is invisible too 253 if( !mbLineColor ) 254 return; 255 256 // DrawTransparent() assumes that the border is NOT to be drawn transparently??? 257 Push( PUSH_FILLCOLOR ); 258 SetFillColor(); 259 DrawPolyPolygon( rPolyPoly ); 260 Pop(); 261 return; 262 } 263 264 // handle metafile recording 265 if( mpMetaFile ) 266 mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) ); 267 268 bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout(); 269 if( bDrawn ) 270 return; 271 272 // get the device graphics as drawing target 273 if( !mpGraphics ) 274 if( !ImplGetGraphics() ) 275 return; 276 277 // debug helper: 278 static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); 279 280 // try hard to draw it directly, because the emulation layers are slower 281 if( !pDisableNative 282 && mpGraphics->supportsOperation( OutDevSupport_B2DDraw ) 283 #if defined UNX && ! defined QUARTZ 284 && GetBitCount() > 8 285 #endif 286 #ifdef WIN32 287 // workaround bad dithering on remote displaying when using GDI+ with toolbar buttoin hilighting 288 && !rPolyPoly.IsRect() 289 #endif 290 ) 291 { 292 // prepare the graphics device 293 if( mbInitClipRegion ) 294 ImplInitClipRegion(); 295 if( mbOutputClipped ) 296 return; 297 if( mbInitLineColor ) 298 ImplInitLineColor(); 299 if( mbInitFillColor ) 300 ImplInitFillColor(); 301 302 // get the polygon in device coordinates 303 basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() ); 304 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 305 aB2DPolyPolygon.transform( aTransform ); 306 307 const double fTransparency = 0.01 * nTransparencePercent; 308 if( mbFillColor ) 309 { 310 // draw the transparent polygon 311 // NOTE: filled polygons are assumed to be drawn as if they were always closed 312 bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this ); 313 } 314 315 if( mbLineColor ) 316 { 317 // disable the fill color for now 318 mpGraphics->SetFillColor(); 319 // draw the border line 320 const basegfx::B2DVector aLineWidths( 1, 1 ); 321 const int nPolyCount = aB2DPolyPolygon.count(); 322 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 323 { 324 const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx ); 325 bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, this ); 326 } 327 // prepare to restore the fill color 328 mbInitFillColor = mbFillColor; 329 } 330 } 331 332 if( bDrawn ) 333 return; 334 335 if( 1 ) 336 { 337 VirtualDevice* pOldAlphaVDev = mpAlphaVDev; 338 339 // #110958# Disable alpha VDev, we perform the necessary 340 // operation explicitely further below. 341 if( mpAlphaVDev ) 342 mpAlphaVDev = NULL; 343 344 GDIMetaFile* pOldMetaFile = mpMetaFile; 345 mpMetaFile = NULL; 346 347 if( OUTDEV_PRINTER == meOutDevType ) 348 { 349 if(100 <= nTransparencePercent) 350 { 351 // #i112959# 100% transparent, draw nothing 352 return; 353 } 354 355 Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() ); 356 const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) ); 357 const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L ); 358 long nMove; 359 const sal_uInt16 nTrans = ( nTransparencePercent < 13 ) ? 0 : 360 ( nTransparencePercent < 38 ) ? 25 : 361 ( nTransparencePercent < 63 ) ? 50 : 362 ( nTransparencePercent < 88 ) ? 75 : 100; 363 364 switch( nTrans ) 365 { 366 case( 25 ): nMove = nBaseExtent * 3; break; 367 case( 50 ): nMove = nBaseExtent * 4; break; 368 case( 75 ): nMove = nBaseExtent * 6; break; 369 370 // #i112959# very transparent (88 < nTransparencePercent <= 99) 371 case( 100 ): nMove = nBaseExtent * 8; break; 372 373 // #i112959# not transparent (nTransparencePercent < 13) 374 default: nMove = 0; break; 375 } 376 377 Push( PUSH_CLIPREGION | PUSH_LINECOLOR ); 378 IntersectClipRegion( rPolyPoly ); 379 SetLineColor( GetFillColor() ); 380 const sal_Bool bOldMap = mbMap; 381 EnableMapMode( sal_False ); 382 383 if(nMove) 384 { 385 Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) ); 386 while( aRect.Top() <= aPolyRect.Bottom() ) 387 { 388 DrawRect( aRect ); 389 aRect.Move( 0, nMove ); 390 } 391 392 aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) ); 393 while( aRect.Left() <= aPolyRect.Right() ) 394 { 395 DrawRect( aRect ); 396 aRect.Move( nMove, 0 ); 397 } 398 } 399 else 400 { 401 // #i112959# if not transparent, draw full rectangle in clip region 402 DrawRect( aPolyRect ); 403 } 404 405 EnableMapMode( bOldMap ); 406 Pop(); 407 } 408 else 409 { 410 PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) ); 411 Rectangle aPolyRect( aPolyPoly.GetBoundRect() ); 412 Point aPoint; 413 Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 414 415 aDstRect.Intersection( aPolyRect ); 416 417 if( OUTDEV_WINDOW == meOutDevType ) 418 { 419 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 420 421 if( !aPaintRgn.IsNull() ) 422 aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() ); 423 } 424 425 if( !aDstRect.IsEmpty() ) 426 { 427 // #i66849# Added fast path for exactly rectangular 428 // polygons 429 // #i83087# Naturally, system alpha blending cannot 430 // work with separate alpha VDev 431 if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() ) 432 { 433 // setup Graphics only here (other cases delegate 434 // to basic OutDev methods) 435 if( 1 ) 436 { 437 if ( mbInitClipRegion ) 438 ImplInitClipRegion(); 439 if ( mbInitLineColor ) 440 ImplInitLineColor(); 441 if ( mbInitFillColor ) 442 ImplInitFillColor(); 443 444 Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() ); 445 Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) ); 446 447 if( !mbOutputClipped ) 448 { 449 bDrawn = mpGraphics->DrawAlphaRect( 450 aPixelRect.Left(), aPixelRect.Top(), 451 // #i98405# use methods with small g, else one pixel too much will be painted. 452 // This is because the source is a polygon which when painted would not paint 453 // the rightmost and lowest pixel line(s), so use one pixel less for the 454 // rectangle, too. 455 aPixelRect.getWidth(), aPixelRect.getHeight(), 456 sal::static_int_cast<sal_uInt8>(nTransparencePercent), 457 this ); 458 } 459 else 460 bDrawn = true; 461 } 462 } 463 464 if( !bDrawn ) 465 { 466 VirtualDevice aVDev( *this, 1 ); 467 const Size aDstSz( aDstRect.GetSize() ); 468 const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 ); 469 470 if( aDstRect.Left() || aDstRect.Top() ) 471 aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() ); 472 473 if( aVDev.SetOutputSizePixel( aDstSz ) ) 474 { 475 const sal_Bool bOldMap = mbMap; 476 477 EnableMapMode( sal_False ); 478 479 aVDev.SetLineColor( COL_BLACK ); 480 aVDev.SetFillColor( COL_BLACK ); 481 aVDev.DrawPolyPolygon( aPolyPoly ); 482 483 Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) ); 484 Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) ); 485 486 // #107766# check for non-empty bitmaps before accessing them 487 if( !!aPaint && !!aPolyMask ) 488 { 489 BitmapWriteAccess* pW = aPaint.AcquireWriteAccess(); 490 BitmapReadAccess* pR = aPolyMask.AcquireReadAccess(); 491 492 if( pW && pR ) 493 { 494 BitmapColor aPixCol; 495 const BitmapColor aFillCol( GetFillColor() ); 496 const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) ); 497 const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) ); 498 const long nWidth = pW->Width(), nHeight = pW->Height(); 499 const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue(); 500 long nX, nY; 501 502 if( aPaint.GetBitCount() <= 8 ) 503 { 504 const BitmapPalette& rPal = pW->GetPalette(); 505 const sal_uInt16 nCount = rPal.GetEntryCount(); 506 BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ]; 507 508 for( sal_uInt16 i = 0; i < nCount; i++ ) 509 { 510 BitmapColor aCol( rPal[ i ] ); 511 pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) ); 512 } 513 514 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 515 pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 516 { 517 const sal_uInt8 cBlack = aBlack.GetIndex(); 518 519 for( nY = 0; nY < nHeight; nY++ ) 520 { 521 Scanline pWScan = pW->GetScanline( nY ); 522 Scanline pRScan = pR->GetScanline( nY ); 523 sal_uInt8 cBit = 128; 524 525 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ ) 526 { 527 if( !cBit ) 528 cBit = 128, pRScan++; 529 530 if( ( *pRScan & cBit ) == cBlack ) 531 *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex(); 532 } 533 } 534 } 535 else 536 { 537 for( nY = 0; nY < nHeight; nY++ ) 538 for( nX = 0; nX < nWidth; nX++ ) 539 if( pR->GetPixel( nY, nX ) == aBlack ) 540 pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] ); 541 } 542 543 delete[] (sal_uInt8*) pMap; 544 } 545 else 546 { 547 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 548 pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 549 { 550 const sal_uInt8 cBlack = aBlack.GetIndex(); 551 552 for( nY = 0; nY < nHeight; nY++ ) 553 { 554 Scanline pWScan = pW->GetScanline( nY ); 555 Scanline pRScan = pR->GetScanline( nY ); 556 sal_uInt8 cBit = 128; 557 558 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 ) 559 { 560 if( !cBit ) 561 cBit = 128, pRScan++; 562 563 if( ( *pRScan & cBit ) == cBlack ) 564 { 565 pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans ); 566 pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans ); 567 pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans ); 568 } 569 } 570 } 571 } 572 else 573 { 574 for( nY = 0; nY < nHeight; nY++ ) 575 { 576 for( nX = 0; nX < nWidth; nX++ ) 577 { 578 if( pR->GetPixel( nY, nX ) == aBlack ) 579 { 580 aPixCol = pW->GetColor( nY, nX ); 581 pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) ); 582 } 583 } 584 } 585 } 586 } 587 } 588 589 aPolyMask.ReleaseAccess( pR ); 590 aPaint.ReleaseAccess( pW ); 591 592 DrawBitmap( aDstRect.TopLeft(), aPaint ); 593 594 EnableMapMode( bOldMap ); 595 596 if( mbLineColor ) 597 { 598 Push( PUSH_FILLCOLOR ); 599 SetFillColor(); 600 DrawPolyPolygon( rPolyPoly ); 601 Pop(); 602 } 603 } 604 } 605 else 606 DrawPolyPolygon( rPolyPoly ); 607 } 608 } 609 } 610 611 mpMetaFile = pOldMetaFile; 612 613 // #110958# Restore disabled alpha VDev 614 mpAlphaVDev = pOldAlphaVDev; 615 616 // #110958# Apply alpha value also to VDev alpha channel 617 if( mpAlphaVDev ) 618 { 619 const Color aFillCol( mpAlphaVDev->GetFillColor() ); 620 mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 621 sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 622 sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) ); 623 624 mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent ); 625 626 mpAlphaVDev->SetFillColor( aFillCol ); 627 } 628 } 629 } 630 631 // ----------------------------------------------------------------------- 632 633 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, 634 const Size& rSize, const Gradient& rTransparenceGradient ) 635 { 636 DBG_TRACE( "OutputDevice::DrawTransparent()" ); 637 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 638 639 const Color aBlack( COL_BLACK ); 640 641 if( mpMetaFile ) 642 mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) ); 643 644 if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) || 645 ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) ) 646 { 647 ( (GDIMetaFile&) rMtf ).WindStart(); 648 ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize ); 649 ( (GDIMetaFile&) rMtf ).WindStart(); 650 } 651 else 652 { 653 GDIMetaFile* pOldMetaFile = mpMetaFile; 654 Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) ); 655 Point aPoint; 656 Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 657 658 mpMetaFile = NULL; 659 aDstRect.Intersection( aOutRect ); 660 661 if( OUTDEV_WINDOW == meOutDevType ) 662 { 663 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 664 665 if( !aPaintRgn.IsNull() ) 666 aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 667 } 668 669 if( !aDstRect.IsEmpty() ) 670 { 671 VirtualDevice* pVDev = new VirtualDevice; 672 673 ((OutputDevice*)pVDev)->mnDPIX = mnDPIX; 674 ((OutputDevice*)pVDev)->mnDPIY = mnDPIY; 675 676 if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) ) 677 { 678 if(GetAntialiasing()) 679 { 680 // #i102109# 681 // For MetaFile replay (see task) it may now be neccessary to take 682 // into account that the content is AntiAlialised and needs to be masked 683 // like that. Instead of masking, i will use a copy-modify-paste cycle 684 // here (as i already use in the VclPrimiziveRenderer with successs) 685 pVDev->SetAntialiasing(GetAntialiasing()); 686 687 // create MapMode for buffer (offset needed) and set 688 MapMode aMap(GetMapMode()); 689 const Point aOutPos(PixelToLogic(aDstRect.TopLeft())); 690 aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y())); 691 pVDev->SetMapMode(aMap); 692 693 // copy MapMode state and disable for target 694 const bool bOrigMapModeEnabled(IsMapModeEnabled()); 695 EnableMapMode(false); 696 697 // copy MapMode state and disable for buffer 698 const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled()); 699 pVDev->EnableMapMode(false); 700 701 // copy content from original to buffer 702 pVDev->DrawOutDev( 703 aPoint, pVDev->GetOutputSizePixel(), // dest 704 aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source 705 *this); 706 707 // draw MetaFile to buffer 708 pVDev->EnableMapMode(bBufferMapModeEnabled); 709 ((GDIMetaFile&)rMtf).WindStart(); 710 ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize); 711 ((GDIMetaFile&)rMtf).WindStart(); 712 713 // get content bitmap from buffer 714 pVDev->EnableMapMode(false); 715 const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 716 717 // create alpha mask from gradient and get as Bitmap 718 pVDev->EnableMapMode(bBufferMapModeEnabled); 719 pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT); 720 pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient); 721 pVDev->SetDrawMode(DRAWMODE_DEFAULT); 722 pVDev->EnableMapMode(false); 723 const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 724 725 // draw masked content to target and restore MapMode 726 DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha)); 727 EnableMapMode(bOrigMapModeEnabled); 728 } 729 else 730 { 731 Bitmap aPaint, aMask; 732 AlphaMask aAlpha; 733 MapMode aMap( GetMapMode() ); 734 Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) ); 735 const sal_Bool bOldMap = mbMap; 736 737 aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) ); 738 pVDev->SetMapMode( aMap ); 739 const sal_Bool bVDevOldMap = pVDev->IsMapModeEnabled(); 740 741 // create paint bitmap 742 ( (GDIMetaFile&) rMtf ).WindStart(); 743 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 744 ( (GDIMetaFile&) rMtf ).WindStart(); 745 pVDev->EnableMapMode( sal_False ); 746 aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 747 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 748 749 // create mask bitmap 750 pVDev->SetLineColor( COL_BLACK ); 751 pVDev->SetFillColor( COL_BLACK ); 752 pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) ); 753 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT | 754 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT ); 755 ( (GDIMetaFile&) rMtf ).WindStart(); 756 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 757 ( (GDIMetaFile&) rMtf ).WindStart(); 758 pVDev->EnableMapMode( sal_False ); 759 aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 760 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 761 762 // create alpha mask from gradient 763 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT ); 764 pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient ); 765 pVDev->SetDrawMode( DRAWMODE_DEFAULT ); 766 pVDev->EnableMapMode( sal_False ); 767 pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) ); 768 769 aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 770 771 delete pVDev; 772 773 EnableMapMode( sal_False ); 774 DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) ); 775 EnableMapMode( bOldMap ); 776 } 777 } 778 else 779 delete pVDev; 780 } 781 782 mpMetaFile = pOldMetaFile; 783 } 784 } 785 786 // ----------------------------------------------------------------------- 787 788 void OutputDevice::ImplDrawColorWallpaper( long nX, long nY, 789 long nWidth, long nHeight, 790 const Wallpaper& rWallpaper ) 791 { 792 // Wallpaper ohne Umrandung zeichnen 793 Color aOldLineColor = GetLineColor(); 794 Color aOldFillColor = GetFillColor(); 795 SetLineColor(); 796 SetFillColor( rWallpaper.GetColor() ); 797 sal_Bool bMap = mbMap; 798 EnableMapMode( sal_False ); 799 DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 800 SetLineColor( aOldLineColor ); 801 SetFillColor( aOldFillColor ); 802 EnableMapMode( bMap ); 803 } 804 805 // ----------------------------------------------------------------------- 806 807 void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY, 808 long nWidth, long nHeight, 809 const Wallpaper& rWallpaper ) 810 { 811 BitmapEx aBmpEx; 812 const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap(); 813 Point aPos; 814 Size aSize; 815 GDIMetaFile* pOldMetaFile = mpMetaFile; 816 const WallpaperStyle eStyle = rWallpaper.GetStyle(); 817 const sal_Bool bOldMap = mbMap; 818 sal_Bool bDrawn = sal_False; 819 sal_Bool bDrawGradientBackground = sal_False; 820 sal_Bool bDrawColorBackground = sal_False; 821 822 if( pCached ) 823 aBmpEx = *pCached; 824 else 825 aBmpEx = rWallpaper.GetBitmap(); 826 827 const long nBmpWidth = aBmpEx.GetSizePixel().Width(); 828 const long nBmpHeight = aBmpEx.GetSizePixel().Height(); 829 const sal_Bool bTransparent = aBmpEx.IsTransparent(); 830 831 // draw background 832 if( bTransparent ) 833 { 834 if( rWallpaper.IsGradient() ) 835 bDrawGradientBackground = sal_True; 836 else 837 { 838 if( !pCached && !rWallpaper.GetColor().GetTransparency() ) 839 { 840 VirtualDevice aVDev( *this ); 841 aVDev.SetBackground( rWallpaper.GetColor() ); 842 aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) ); 843 aVDev.DrawBitmapEx( Point(), aBmpEx ); 844 aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 845 } 846 847 bDrawColorBackground = sal_True; 848 } 849 } 850 else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE ) 851 { 852 if( rWallpaper.IsGradient() ) 853 bDrawGradientBackground = sal_True; 854 else 855 bDrawColorBackground = sal_True; 856 } 857 858 // background of bitmap? 859 if( bDrawGradientBackground ) 860 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 861 else if( bDrawColorBackground && bTransparent ) 862 { 863 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 864 bDrawColorBackground = sal_False; 865 } 866 867 // calc pos and size 868 if( rWallpaper.IsRect() ) 869 { 870 const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) ); 871 aPos = aBound.TopLeft(); 872 aSize = aBound.GetSize(); 873 } 874 else 875 { 876 aPos = Point( nX, nY ); 877 aSize = Size( nWidth, nHeight ); 878 } 879 880 mpMetaFile = NULL; 881 EnableMapMode( sal_False ); 882 Push( PUSH_CLIPREGION ); 883 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 884 885 switch( eStyle ) 886 { 887 case( WALLPAPER_SCALE ): 888 { 889 if( !pCached || ( pCached->GetSizePixel() != aSize ) ) 890 { 891 if( pCached ) 892 rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap(); 893 894 aBmpEx = rWallpaper.GetBitmap(); 895 aBmpEx.Scale( aSize ); 896 aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() ); 897 } 898 } 899 break; 900 901 case( WALLPAPER_TOPLEFT ): 902 break; 903 904 case( WALLPAPER_TOP ): 905 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 906 break; 907 908 case( WALLPAPER_TOPRIGHT ): 909 aPos.X() += ( aSize.Width() - nBmpWidth ); 910 break; 911 912 case( WALLPAPER_LEFT ): 913 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 914 break; 915 916 case( WALLPAPER_CENTER ): 917 { 918 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 919 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 920 } 921 break; 922 923 case( WALLPAPER_RIGHT ): 924 { 925 aPos.X() += ( aSize.Width() - nBmpWidth ); 926 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 927 } 928 break; 929 930 case( WALLPAPER_BOTTOMLEFT ): 931 aPos.Y() += ( aSize.Height() - nBmpHeight ); 932 break; 933 934 case( WALLPAPER_BOTTOM ): 935 { 936 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 937 aPos.Y() += ( aSize.Height() - nBmpHeight ); 938 } 939 break; 940 941 case( WALLPAPER_BOTTOMRIGHT ): 942 { 943 aPos.X() += ( aSize.Width() - nBmpWidth ); 944 aPos.Y() += ( aSize.Height() - nBmpHeight ); 945 } 946 break; 947 948 default: 949 { 950 const long nRight = nX + nWidth - 1L; 951 const long nBottom = nY + nHeight - 1L; 952 long nFirstX; 953 long nFirstY; 954 955 if( eStyle == WALLPAPER_TILE ) 956 { 957 nFirstX = aPos.X(); 958 nFirstY = aPos.Y(); 959 } 960 else 961 { 962 nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 ); 963 nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 ); 964 } 965 966 const long nOffX = ( nFirstX - nX ) % nBmpWidth; 967 const long nOffY = ( nFirstY - nY ) % nBmpHeight; 968 long nStartX = nX + nOffX; 969 long nStartY = nY + nOffY; 970 971 if( nOffX > 0L ) 972 nStartX -= nBmpWidth; 973 974 if( nOffY > 0L ) 975 nStartY -= nBmpHeight; 976 977 for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight ) 978 for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth ) 979 DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx ); 980 981 bDrawn = sal_True; 982 } 983 break; 984 } 985 986 if( !bDrawn ) 987 { 988 // optimized for non-transparent bitmaps 989 if( bDrawColorBackground ) 990 { 991 const Size aBmpSize( aBmpEx.GetSizePixel() ); 992 const Point aTmpPoint; 993 const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() ); 994 const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 995 Rectangle aWorkRect; 996 997 aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L ); 998 aWorkRect.Justify(); 999 aWorkRect.Intersection( aColRect ); 1000 if( !aWorkRect.IsEmpty() ) 1001 { 1002 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1003 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1004 rWallpaper ); 1005 } 1006 1007 aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L ); 1008 aWorkRect.Justify(); 1009 aWorkRect.Intersection( aColRect ); 1010 if( !aWorkRect.IsEmpty() ) 1011 { 1012 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1013 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1014 rWallpaper ); 1015 } 1016 1017 aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L ); 1018 aWorkRect.Justify(); 1019 aWorkRect.Intersection( aColRect ); 1020 if( !aWorkRect.IsEmpty() ) 1021 { 1022 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1023 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1024 rWallpaper ); 1025 } 1026 1027 aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() ); 1028 aWorkRect.Justify(); 1029 aWorkRect.Intersection( aColRect ); 1030 if( !aWorkRect.IsEmpty() ) 1031 { 1032 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1033 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1034 rWallpaper ); 1035 } 1036 } 1037 1038 DrawBitmapEx( aPos, aBmpEx ); 1039 } 1040 1041 rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx ); 1042 1043 Pop(); 1044 EnableMapMode( bOldMap ); 1045 mpMetaFile = pOldMetaFile; 1046 } 1047 1048 // ----------------------------------------------------------------------- 1049 1050 void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY, 1051 long nWidth, long nHeight, 1052 const Wallpaper& rWallpaper ) 1053 { 1054 Rectangle aBound; 1055 GDIMetaFile* pOldMetaFile = mpMetaFile; 1056 const sal_Bool bOldMap = mbMap; 1057 sal_Bool bNeedGradient = sal_True; 1058 1059 /* 1060 if ( rWallpaper.IsRect() ) 1061 aBound = LogicToPixel( rWallpaper.GetRect() ); 1062 else 1063 */ 1064 aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); 1065 1066 mpMetaFile = NULL; 1067 EnableMapMode( sal_False ); 1068 Push( PUSH_CLIPREGION ); 1069 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 1070 1071 if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT ) 1072 { 1073 Window *pWin = dynamic_cast< Window* >( this ); 1074 if( pWin ) 1075 { 1076 // limit gradient to useful size, so that it still can be noticed 1077 // in maximized windows 1078 long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width(); 1079 if( gradientWidth > 1024 ) 1080 gradientWidth = 1024; 1081 if( mnOutOffX+nWidth > gradientWidth ) 1082 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() ); 1083 if( mnOutOffX > gradientWidth ) 1084 bNeedGradient = sal_False; 1085 else 1086 aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) ); 1087 } 1088 } 1089 1090 if( bNeedGradient ) 1091 DrawGradient( aBound, rWallpaper.GetGradient() ); 1092 1093 Pop(); 1094 EnableMapMode( bOldMap ); 1095 mpMetaFile = pOldMetaFile; 1096 } 1097 1098 // ----------------------------------------------------------------------- 1099 1100 void OutputDevice::ImplDrawWallpaper( long nX, long nY, 1101 long nWidth, long nHeight, 1102 const Wallpaper& rWallpaper ) 1103 { 1104 if( rWallpaper.IsBitmap() ) 1105 ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1106 else if( rWallpaper.IsGradient() ) 1107 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1108 else 1109 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1110 } 1111 1112 // ----------------------------------------------------------------------- 1113 1114 void OutputDevice::DrawWallpaper( const Rectangle& rRect, 1115 const Wallpaper& rWallpaper ) 1116 { 1117 if ( mpMetaFile ) 1118 mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) ); 1119 1120 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1121 return; 1122 1123 if ( rWallpaper.GetStyle() != WALLPAPER_NULL ) 1124 { 1125 Rectangle aRect = LogicToPixel( rRect ); 1126 aRect.Justify(); 1127 1128 if ( !aRect.IsEmpty() ) 1129 { 1130 ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1131 rWallpaper ); 1132 } 1133 } 1134 1135 if( mpAlphaVDev ) 1136 mpAlphaVDev->DrawWallpaper( rRect, rWallpaper ); 1137 } 1138 1139 // ----------------------------------------------------------------------- 1140 1141 void OutputDevice::Erase() 1142 { 1143 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1144 return; 1145 1146 sal_Bool bNativeOK = sal_False; 1147 1148 if( meOutDevType == OUTDEV_WINDOW ) 1149 { 1150 Window* pWindow = static_cast<Window*>(this); 1151 ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground; 1152 if( aCtrlPart != 0 && ! pWindow->IsControlBackground() ) 1153 { 1154 ImplControlValue aControlValue; 1155 Point aGcc3WorkaroundTemporary; 1156 Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() ); 1157 ControlState nState = 0; 1158 1159 if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1160 bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion, 1161 nState, aControlValue, rtl::OUString() ); 1162 } 1163 } 1164 1165 if ( mbBackground && ! bNativeOK ) 1166 { 1167 RasterOp eRasterOp = GetRasterOp(); 1168 if ( eRasterOp != ROP_OVERPAINT ) 1169 SetRasterOp( ROP_OVERPAINT ); 1170 ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground ); 1171 if ( eRasterOp != ROP_OVERPAINT ) 1172 SetRasterOp( eRasterOp ); 1173 } 1174 1175 if( mpAlphaVDev ) 1176 mpAlphaVDev->Erase(); 1177 } 1178 1179 // ----------------------------------------------------------------------- 1180 1181 void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect, 1182 const Color& rLeftTopColor, 1183 const Color& rRightBottomColor ) 1184 { 1185 SetFillColor( rLeftTopColor ); 1186 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) ); 1187 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) ); 1188 SetFillColor( rRightBottomColor ); 1189 DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) ); 1190 DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) ); 1191 } 1192 1193 // ----------------------------------------------------------------------- 1194 1195 bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize, 1196 const GfxLink& rGfxLink, GDIMetaFile* pSubst ) 1197 { 1198 DBG_TRACE( "OutputDevice::DrawEPS()" ); 1199 1200 bool bDrawn(true); 1201 1202 if ( mpMetaFile ) 1203 { 1204 GDIMetaFile aSubst; 1205 1206 if( pSubst ) 1207 aSubst = *pSubst; 1208 1209 mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) ); 1210 } 1211 1212 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1213 return bDrawn; 1214 1215 if( mbOutputClipped ) 1216 return bDrawn; 1217 1218 Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) ); 1219 1220 if( !aRect.IsEmpty() ) 1221 { 1222 // draw the real EPS graphics 1223 if( rGfxLink.GetData() && rGfxLink.GetDataSize() ) 1224 { 1225 if( !mpGraphics && !ImplGetGraphics() ) 1226 return bDrawn; 1227 1228 if( mbInitClipRegion ) 1229 ImplInitClipRegion(); 1230 1231 aRect.Justify(); 1232 bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1233 (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this ); 1234 } 1235 1236 // else draw the substitution graphics 1237 if( !bDrawn && pSubst ) 1238 { 1239 GDIMetaFile* pOldMetaFile = mpMetaFile; 1240 1241 mpMetaFile = NULL; 1242 Graphic( *pSubst ).Draw( this, rPoint, rSize ); 1243 mpMetaFile = pOldMetaFile; 1244 } 1245 } 1246 1247 if( mpAlphaVDev ) 1248 mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst ); 1249 1250 return bDrawn; 1251 } 1252 1253 // ------------------------------------------------------------------ 1254 1255 void OutputDevice::DrawRenderGraphic( const Point& rPoint, const Size& rSize, 1256 const ::vcl::RenderGraphic& rRenderGraphic ) 1257 { 1258 DBG_TRACE( "OutputDevice::DrawRenderGraphic()" ); 1259 1260 if( mpMetaFile ) 1261 mpMetaFile->AddAction( new MetaRenderGraphicAction( rPoint, rSize, rRenderGraphic ) ); 1262 1263 if( !rRenderGraphic.IsEmpty() ) 1264 { 1265 ::vcl::RenderGraphicRasterizer aRasterizer( rRenderGraphic ); 1266 BitmapEx aBmpEx; 1267 const Size aSizePixel( LogicToPixel( rSize ) ); 1268 GDIMetaFile* pOldMetaFile = mpMetaFile; 1269 1270 mpMetaFile = NULL; 1271 DrawBitmapEx( rPoint, rSize, aRasterizer.Rasterize( aSizePixel ) ); 1272 mpMetaFile = pOldMetaFile; 1273 } 1274 } 1275