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