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, com::sun::star::drawing::LineCap_BUTT, 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, com::sun::star::drawing::LineCap_BUTT, 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 { 638 // missing here is to map the data using the DeviceTransformation 639 mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) ); 640 } 641 642 if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) || 643 ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) ) 644 { 645 ( (GDIMetaFile&) rMtf ).WindStart(); 646 ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize ); 647 ( (GDIMetaFile&) rMtf ).WindStart(); 648 } 649 else 650 { 651 GDIMetaFile* pOldMetaFile = mpMetaFile; 652 Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) ); 653 Point aPoint; 654 Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 655 656 mpMetaFile = NULL; 657 aDstRect.Intersection( aOutRect ); 658 659 if( OUTDEV_WINDOW == meOutDevType ) 660 { 661 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 662 663 if( !aPaintRgn.IsNull() ) 664 aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 665 } 666 667 if( !aDstRect.IsEmpty() ) 668 { 669 VirtualDevice* pVDev = new VirtualDevice; 670 671 ((OutputDevice*)pVDev)->mnDPIX = mnDPIX; 672 ((OutputDevice*)pVDev)->mnDPIY = mnDPIY; 673 674 if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) ) 675 { 676 if(GetAntialiasing()) 677 { 678 // #i102109# 679 // For MetaFile replay (see task) it may now be neccessary to take 680 // into account that the content is AntiAlialised and needs to be masked 681 // like that. Instead of masking, i will use a copy-modify-paste cycle 682 // here (as i already use in the VclPrimiziveRenderer with successs) 683 pVDev->SetAntialiasing(GetAntialiasing()); 684 685 // create MapMode for buffer (offset needed) and set 686 MapMode aMap(GetMapMode()); 687 const Point aOutPos(PixelToLogic(aDstRect.TopLeft())); 688 aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y())); 689 pVDev->SetMapMode(aMap); 690 691 // copy MapMode state and disable for target 692 const bool bOrigMapModeEnabled(IsMapModeEnabled()); 693 EnableMapMode(false); 694 695 // copy MapMode state and disable for buffer 696 const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled()); 697 pVDev->EnableMapMode(false); 698 699 // copy content from original to buffer 700 pVDev->DrawOutDev( 701 aPoint, pVDev->GetOutputSizePixel(), // dest 702 aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source 703 *this); 704 705 // draw MetaFile to buffer 706 pVDev->EnableMapMode(bBufferMapModeEnabled); 707 ((GDIMetaFile&)rMtf).WindStart(); 708 ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize); 709 ((GDIMetaFile&)rMtf).WindStart(); 710 711 // get content bitmap from buffer 712 pVDev->EnableMapMode(false); 713 const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 714 715 // create alpha mask from gradient and get as Bitmap 716 pVDev->EnableMapMode(bBufferMapModeEnabled); 717 pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT); 718 pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient); 719 pVDev->SetDrawMode(DRAWMODE_DEFAULT); 720 pVDev->EnableMapMode(false); 721 const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 722 723 // draw masked content to target and restore MapMode 724 DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha)); 725 EnableMapMode(bOrigMapModeEnabled); 726 } 727 else 728 { 729 Bitmap aPaint, aMask; 730 AlphaMask aAlpha; 731 MapMode aMap( GetMapMode() ); 732 Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) ); 733 const sal_Bool bOldMap = mbMap; 734 735 aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) ); 736 pVDev->SetMapMode( aMap ); 737 const sal_Bool bVDevOldMap = pVDev->IsMapModeEnabled(); 738 739 // create paint bitmap 740 ( (GDIMetaFile&) rMtf ).WindStart(); 741 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 742 ( (GDIMetaFile&) rMtf ).WindStart(); 743 pVDev->EnableMapMode( sal_False ); 744 aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 745 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 746 747 // create mask bitmap 748 pVDev->SetLineColor( COL_BLACK ); 749 pVDev->SetFillColor( COL_BLACK ); 750 pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) ); 751 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT | 752 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT ); 753 ( (GDIMetaFile&) rMtf ).WindStart(); 754 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 755 ( (GDIMetaFile&) rMtf ).WindStart(); 756 pVDev->EnableMapMode( sal_False ); 757 aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 758 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 759 760 // create alpha mask from gradient 761 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT ); 762 pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient ); 763 pVDev->SetDrawMode( DRAWMODE_DEFAULT ); 764 pVDev->EnableMapMode( sal_False ); 765 pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) ); 766 767 aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 768 769 delete pVDev; 770 771 EnableMapMode( sal_False ); 772 DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) ); 773 EnableMapMode( bOldMap ); 774 } 775 } 776 else 777 delete pVDev; 778 } 779 780 mpMetaFile = pOldMetaFile; 781 } 782 } 783 784 // ----------------------------------------------------------------------- 785 786 void OutputDevice::ImplDrawColorWallpaper( long nX, long nY, 787 long nWidth, long nHeight, 788 const Wallpaper& rWallpaper ) 789 { 790 // Wallpaper ohne Umrandung zeichnen 791 Color aOldLineColor = GetLineColor(); 792 Color aOldFillColor = GetFillColor(); 793 SetLineColor(); 794 SetFillColor( rWallpaper.GetColor() ); 795 sal_Bool bMap = mbMap; 796 EnableMapMode( sal_False ); 797 DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 798 SetLineColor( aOldLineColor ); 799 SetFillColor( aOldFillColor ); 800 EnableMapMode( bMap ); 801 } 802 803 // ----------------------------------------------------------------------- 804 805 void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY, 806 long nWidth, long nHeight, 807 const Wallpaper& rWallpaper ) 808 { 809 BitmapEx aBmpEx; 810 const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap(); 811 Point aPos; 812 Size aSize; 813 GDIMetaFile* pOldMetaFile = mpMetaFile; 814 const WallpaperStyle eStyle = rWallpaper.GetStyle(); 815 const sal_Bool bOldMap = mbMap; 816 sal_Bool bDrawn = sal_False; 817 sal_Bool bDrawGradientBackground = sal_False; 818 sal_Bool bDrawColorBackground = sal_False; 819 820 if( pCached ) 821 aBmpEx = *pCached; 822 else 823 aBmpEx = rWallpaper.GetBitmap(); 824 825 const long nBmpWidth = aBmpEx.GetSizePixel().Width(); 826 const long nBmpHeight = aBmpEx.GetSizePixel().Height(); 827 const sal_Bool bTransparent = aBmpEx.IsTransparent(); 828 829 // draw background 830 if( bTransparent ) 831 { 832 if( rWallpaper.IsGradient() ) 833 bDrawGradientBackground = sal_True; 834 else 835 { 836 if( !pCached && !rWallpaper.GetColor().GetTransparency() ) 837 { 838 VirtualDevice aVDev( *this ); 839 aVDev.SetBackground( rWallpaper.GetColor() ); 840 aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) ); 841 aVDev.DrawBitmapEx( Point(), aBmpEx ); 842 aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 843 } 844 845 bDrawColorBackground = sal_True; 846 } 847 } 848 else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE ) 849 { 850 if( rWallpaper.IsGradient() ) 851 bDrawGradientBackground = sal_True; 852 else 853 bDrawColorBackground = sal_True; 854 } 855 856 // background of bitmap? 857 if( bDrawGradientBackground ) 858 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 859 else if( bDrawColorBackground && bTransparent ) 860 { 861 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 862 bDrawColorBackground = sal_False; 863 } 864 865 // calc pos and size 866 if( rWallpaper.IsRect() ) 867 { 868 const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) ); 869 aPos = aBound.TopLeft(); 870 aSize = aBound.GetSize(); 871 } 872 else 873 { 874 aPos = Point( nX, nY ); 875 aSize = Size( nWidth, nHeight ); 876 } 877 878 mpMetaFile = NULL; 879 EnableMapMode( sal_False ); 880 Push( PUSH_CLIPREGION ); 881 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 882 883 switch( eStyle ) 884 { 885 case( WALLPAPER_SCALE ): 886 { 887 if( !pCached || ( pCached->GetSizePixel() != aSize ) ) 888 { 889 if( pCached ) 890 rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap(); 891 892 aBmpEx = rWallpaper.GetBitmap(); 893 aBmpEx.Scale( aSize ); 894 aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() ); 895 } 896 } 897 break; 898 899 case( WALLPAPER_TOPLEFT ): 900 break; 901 902 case( WALLPAPER_TOP ): 903 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 904 break; 905 906 case( WALLPAPER_TOPRIGHT ): 907 aPos.X() += ( aSize.Width() - nBmpWidth ); 908 break; 909 910 case( WALLPAPER_LEFT ): 911 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 912 break; 913 914 case( WALLPAPER_CENTER ): 915 { 916 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 917 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 918 } 919 break; 920 921 case( WALLPAPER_RIGHT ): 922 { 923 aPos.X() += ( aSize.Width() - nBmpWidth ); 924 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 925 } 926 break; 927 928 case( WALLPAPER_BOTTOMLEFT ): 929 aPos.Y() += ( aSize.Height() - nBmpHeight ); 930 break; 931 932 case( WALLPAPER_BOTTOM ): 933 { 934 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 935 aPos.Y() += ( aSize.Height() - nBmpHeight ); 936 } 937 break; 938 939 case( WALLPAPER_BOTTOMRIGHT ): 940 { 941 aPos.X() += ( aSize.Width() - nBmpWidth ); 942 aPos.Y() += ( aSize.Height() - nBmpHeight ); 943 } 944 break; 945 946 default: 947 { 948 const long nRight = nX + nWidth - 1L; 949 const long nBottom = nY + nHeight - 1L; 950 long nFirstX; 951 long nFirstY; 952 953 if( eStyle == WALLPAPER_TILE ) 954 { 955 nFirstX = aPos.X(); 956 nFirstY = aPos.Y(); 957 } 958 else 959 { 960 nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 ); 961 nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 ); 962 } 963 964 const long nOffX = ( nFirstX - nX ) % nBmpWidth; 965 const long nOffY = ( nFirstY - nY ) % nBmpHeight; 966 long nStartX = nX + nOffX; 967 long nStartY = nY + nOffY; 968 969 if( nOffX > 0L ) 970 nStartX -= nBmpWidth; 971 972 if( nOffY > 0L ) 973 nStartY -= nBmpHeight; 974 975 for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight ) 976 for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth ) 977 DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx ); 978 979 bDrawn = sal_True; 980 } 981 break; 982 } 983 984 if( !bDrawn ) 985 { 986 // optimized for non-transparent bitmaps 987 if( bDrawColorBackground ) 988 { 989 const Size aBmpSize( aBmpEx.GetSizePixel() ); 990 const Point aTmpPoint; 991 const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() ); 992 const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 993 Rectangle aWorkRect; 994 995 aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L ); 996 aWorkRect.Justify(); 997 aWorkRect.Intersection( aColRect ); 998 if( !aWorkRect.IsEmpty() ) 999 { 1000 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1001 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1002 rWallpaper ); 1003 } 1004 1005 aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L ); 1006 aWorkRect.Justify(); 1007 aWorkRect.Intersection( aColRect ); 1008 if( !aWorkRect.IsEmpty() ) 1009 { 1010 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1011 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1012 rWallpaper ); 1013 } 1014 1015 aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L ); 1016 aWorkRect.Justify(); 1017 aWorkRect.Intersection( aColRect ); 1018 if( !aWorkRect.IsEmpty() ) 1019 { 1020 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1021 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1022 rWallpaper ); 1023 } 1024 1025 aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() ); 1026 aWorkRect.Justify(); 1027 aWorkRect.Intersection( aColRect ); 1028 if( !aWorkRect.IsEmpty() ) 1029 { 1030 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1031 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1032 rWallpaper ); 1033 } 1034 } 1035 1036 DrawBitmapEx( aPos, aBmpEx ); 1037 } 1038 1039 rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx ); 1040 1041 Pop(); 1042 EnableMapMode( bOldMap ); 1043 mpMetaFile = pOldMetaFile; 1044 } 1045 1046 // ----------------------------------------------------------------------- 1047 1048 void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY, 1049 long nWidth, long nHeight, 1050 const Wallpaper& rWallpaper ) 1051 { 1052 Rectangle aBound; 1053 GDIMetaFile* pOldMetaFile = mpMetaFile; 1054 const sal_Bool bOldMap = mbMap; 1055 sal_Bool bNeedGradient = sal_True; 1056 1057 /* 1058 if ( rWallpaper.IsRect() ) 1059 aBound = LogicToPixel( rWallpaper.GetRect() ); 1060 else 1061 */ 1062 aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); 1063 1064 mpMetaFile = NULL; 1065 EnableMapMode( sal_False ); 1066 Push( PUSH_CLIPREGION ); 1067 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 1068 1069 if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT ) 1070 { 1071 Window *pWin = dynamic_cast< Window* >( this ); 1072 if( pWin ) 1073 { 1074 // limit gradient to useful size, so that it still can be noticed 1075 // in maximized windows 1076 long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width(); 1077 if( gradientWidth > 1024 ) 1078 gradientWidth = 1024; 1079 if( mnOutOffX+nWidth > gradientWidth ) 1080 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() ); 1081 if( mnOutOffX > gradientWidth ) 1082 bNeedGradient = sal_False; 1083 else 1084 aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) ); 1085 } 1086 } 1087 1088 if( bNeedGradient ) 1089 DrawGradient( aBound, rWallpaper.GetGradient() ); 1090 1091 Pop(); 1092 EnableMapMode( bOldMap ); 1093 mpMetaFile = pOldMetaFile; 1094 } 1095 1096 // ----------------------------------------------------------------------- 1097 1098 void OutputDevice::ImplDrawWallpaper( long nX, long nY, 1099 long nWidth, long nHeight, 1100 const Wallpaper& rWallpaper ) 1101 { 1102 if( rWallpaper.IsBitmap() ) 1103 ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1104 else if( rWallpaper.IsGradient() ) 1105 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1106 else 1107 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1108 } 1109 1110 // ----------------------------------------------------------------------- 1111 1112 void OutputDevice::DrawWallpaper( const Rectangle& rRect, 1113 const Wallpaper& rWallpaper ) 1114 { 1115 if ( mpMetaFile ) 1116 mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) ); 1117 1118 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1119 return; 1120 1121 if ( rWallpaper.GetStyle() != WALLPAPER_NULL ) 1122 { 1123 Rectangle aRect = LogicToPixel( rRect ); 1124 aRect.Justify(); 1125 1126 if ( !aRect.IsEmpty() ) 1127 { 1128 ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1129 rWallpaper ); 1130 } 1131 } 1132 1133 if( mpAlphaVDev ) 1134 mpAlphaVDev->DrawWallpaper( rRect, rWallpaper ); 1135 } 1136 1137 // ----------------------------------------------------------------------- 1138 1139 void OutputDevice::Erase() 1140 { 1141 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1142 return; 1143 1144 sal_Bool bNativeOK = sal_False; 1145 1146 if( meOutDevType == OUTDEV_WINDOW ) 1147 { 1148 Window* pWindow = static_cast<Window*>(this); 1149 ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground; 1150 if( aCtrlPart != 0 && ! pWindow->IsControlBackground() ) 1151 { 1152 ImplControlValue aControlValue; 1153 Point aGcc3WorkaroundTemporary; 1154 Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() ); 1155 ControlState nState = 0; 1156 1157 if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1158 bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion, 1159 nState, aControlValue, rtl::OUString() ); 1160 } 1161 } 1162 1163 if ( mbBackground && ! bNativeOK ) 1164 { 1165 RasterOp eRasterOp = GetRasterOp(); 1166 if ( eRasterOp != ROP_OVERPAINT ) 1167 SetRasterOp( ROP_OVERPAINT ); 1168 ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground ); 1169 if ( eRasterOp != ROP_OVERPAINT ) 1170 SetRasterOp( eRasterOp ); 1171 } 1172 1173 if( mpAlphaVDev ) 1174 mpAlphaVDev->Erase(); 1175 } 1176 1177 // ----------------------------------------------------------------------- 1178 1179 void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect, 1180 const Color& rLeftTopColor, 1181 const Color& rRightBottomColor ) 1182 { 1183 SetFillColor( rLeftTopColor ); 1184 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) ); 1185 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) ); 1186 SetFillColor( rRightBottomColor ); 1187 DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) ); 1188 DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) ); 1189 } 1190 1191 // ----------------------------------------------------------------------- 1192 1193 bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize, 1194 const GfxLink& rGfxLink, GDIMetaFile* pSubst ) 1195 { 1196 DBG_TRACE( "OutputDevice::DrawEPS()" ); 1197 1198 bool bDrawn(true); 1199 1200 if ( mpMetaFile ) 1201 { 1202 GDIMetaFile aSubst; 1203 1204 if( pSubst ) 1205 aSubst = *pSubst; 1206 1207 mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) ); 1208 } 1209 1210 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1211 return bDrawn; 1212 1213 if( mbOutputClipped ) 1214 return bDrawn; 1215 1216 Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) ); 1217 1218 if( !aRect.IsEmpty() ) 1219 { 1220 // draw the real EPS graphics 1221 if( rGfxLink.GetData() && rGfxLink.GetDataSize() ) 1222 { 1223 if( !mpGraphics && !ImplGetGraphics() ) 1224 return bDrawn; 1225 1226 if( mbInitClipRegion ) 1227 ImplInitClipRegion(); 1228 1229 aRect.Justify(); 1230 bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1231 (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this ); 1232 } 1233 1234 // else draw the substitution graphics 1235 if( !bDrawn && pSubst ) 1236 { 1237 GDIMetaFile* pOldMetaFile = mpMetaFile; 1238 1239 mpMetaFile = NULL; 1240 Graphic( *pSubst ).Draw( this, rPoint, rSize ); 1241 mpMetaFile = pOldMetaFile; 1242 } 1243 } 1244 1245 if( mpAlphaVDev ) 1246 mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst ); 1247 1248 return bDrawn; 1249 } 1250 1251 // ----------------------------------------------------------------------- 1252 1253 void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd) 1254 { 1255 const sal_uInt32 nMaxX(rPos.X() + rSize.Width()); 1256 const sal_uInt32 nMaxY(rPos.Y() + rSize.Height()); 1257 1258 Push(PUSH_LINECOLOR|PUSH_FILLCOLOR); 1259 SetLineColor(); 1260 1261 for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen) 1262 { 1263 const sal_uInt32 nRight(std::min(nMaxX, nX + nLen)); 1264 1265 for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen) 1266 { 1267 const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen)); 1268 1269 SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd); 1270 DrawRect(Rectangle(nX, nY, nRight, nBottom)); 1271 } 1272 } 1273 1274 Pop(); 1275 } 1276 1277 // ----------------------------------------------------------------------- 1278 // eof 1279