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