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 circuit 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 // #121591# 306 // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices 307 // should be used when printing. Normally this is avoided by the printer being 308 // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary 309 // to add (OUTDEV_PRINTER != meOutDevType) to the entering if statement, thus 310 // using the fallbacl some lines below (which is not very good, though). For 311 // now, WinSalGraphics::drawPolyPolygon will detect printer usage and correct 312 // the wrong mapping (see there for details) 313 bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this ); 314 } 315 316 if( mbLineColor ) 317 { 318 // disable the fill color for now 319 mpGraphics->SetFillColor(); 320 // draw the border line 321 const basegfx::B2DVector aLineWidths( 1, 1 ); 322 const int nPolyCount = aB2DPolyPolygon.count(); 323 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 324 { 325 const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx ); 326 bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this ); 327 } 328 // prepare to restore the fill color 329 mbInitFillColor = mbFillColor; 330 } 331 } 332 333 if( bDrawn ) 334 return; 335 336 if( 1 ) 337 { 338 VirtualDevice* pOldAlphaVDev = mpAlphaVDev; 339 340 // #110958# Disable alpha VDev, we perform the necessary 341 // operation explicitely further below. 342 if( mpAlphaVDev ) 343 mpAlphaVDev = NULL; 344 345 GDIMetaFile* pOldMetaFile = mpMetaFile; 346 mpMetaFile = NULL; 347 348 if( OUTDEV_PRINTER == meOutDevType ) 349 { 350 if(100 <= nTransparencePercent) 351 { 352 // #i112959# 100% transparent, draw nothing 353 return; 354 } 355 356 Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() ); 357 const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) ); 358 const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L ); 359 long nMove; 360 const sal_uInt16 nTrans = ( nTransparencePercent < 13 ) ? 0 : 361 ( nTransparencePercent < 38 ) ? 25 : 362 ( nTransparencePercent < 63 ) ? 50 : 363 ( nTransparencePercent < 88 ) ? 75 : 100; 364 365 switch( nTrans ) 366 { 367 case( 25 ): nMove = nBaseExtent * 3; break; 368 case( 50 ): nMove = nBaseExtent * 4; break; 369 case( 75 ): nMove = nBaseExtent * 6; break; 370 371 // #i112959# very transparent (88 < nTransparencePercent <= 99) 372 case( 100 ): nMove = nBaseExtent * 8; break; 373 374 // #i112959# not transparent (nTransparencePercent < 13) 375 default: nMove = 0; break; 376 } 377 378 Push( PUSH_CLIPREGION | PUSH_LINECOLOR ); 379 IntersectClipRegion( rPolyPoly ); 380 SetLineColor( GetFillColor() ); 381 const sal_Bool bOldMap = mbMap; 382 EnableMapMode( sal_False ); 383 384 if(nMove) 385 { 386 Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) ); 387 while( aRect.Top() <= aPolyRect.Bottom() ) 388 { 389 DrawRect( aRect ); 390 aRect.Move( 0, nMove ); 391 } 392 393 aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) ); 394 while( aRect.Left() <= aPolyRect.Right() ) 395 { 396 DrawRect( aRect ); 397 aRect.Move( nMove, 0 ); 398 } 399 } 400 else 401 { 402 // #i112959# if not transparent, draw full rectangle in clip region 403 DrawRect( aPolyRect ); 404 } 405 406 EnableMapMode( bOldMap ); 407 Pop(); 408 } 409 else 410 { 411 PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) ); 412 Rectangle aPolyRect( aPolyPoly.GetBoundRect() ); 413 Point aPoint; 414 Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 415 416 aDstRect.Intersection( aPolyRect ); 417 418 if( OUTDEV_WINDOW == meOutDevType ) 419 { 420 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 421 422 if( !aPaintRgn.IsNull() ) 423 aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() ); 424 } 425 426 if( !aDstRect.IsEmpty() ) 427 { 428 // #i66849# Added fast path for exactly rectangular 429 // polygons 430 // #i83087# Naturally, system alpha blending cannot 431 // work with separate alpha VDev 432 if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() ) 433 { 434 // setup Graphics only here (other cases delegate 435 // to basic OutDev methods) 436 if( 1 ) 437 { 438 if ( mbInitClipRegion ) 439 ImplInitClipRegion(); 440 if ( mbInitLineColor ) 441 ImplInitLineColor(); 442 if ( mbInitFillColor ) 443 ImplInitFillColor(); 444 445 Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() ); 446 Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) ); 447 448 if( !mbOutputClipped ) 449 { 450 bDrawn = mpGraphics->DrawAlphaRect( 451 aPixelRect.Left(), aPixelRect.Top(), 452 // #i98405# use methods with small g, else one pixel too much will be painted. 453 // This is because the source is a polygon which when painted would not paint 454 // the rightmost and lowest pixel line(s), so use one pixel less for the 455 // rectangle, too. 456 aPixelRect.getWidth(), aPixelRect.getHeight(), 457 sal::static_int_cast<sal_uInt8>(nTransparencePercent), 458 this ); 459 } 460 else 461 bDrawn = true; 462 } 463 } 464 465 if( !bDrawn ) 466 { 467 VirtualDevice aVDev( *this, 1 ); 468 const Size aDstSz( aDstRect.GetSize() ); 469 const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 ); 470 471 if( aDstRect.Left() || aDstRect.Top() ) 472 aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() ); 473 474 if( aVDev.SetOutputSizePixel( aDstSz ) ) 475 { 476 const sal_Bool bOldMap = mbMap; 477 478 EnableMapMode( sal_False ); 479 480 aVDev.SetLineColor( COL_BLACK ); 481 aVDev.SetFillColor( COL_BLACK ); 482 aVDev.DrawPolyPolygon( aPolyPoly ); 483 484 Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) ); 485 Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) ); 486 487 // #107766# check for non-empty bitmaps before accessing them 488 if( !!aPaint && !!aPolyMask ) 489 { 490 BitmapWriteAccess* pW = aPaint.AcquireWriteAccess(); 491 BitmapReadAccess* pR = aPolyMask.AcquireReadAccess(); 492 493 if( pW && pR ) 494 { 495 BitmapColor aPixCol; 496 const BitmapColor aFillCol( GetFillColor() ); 497 const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) ); 498 const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) ); 499 const long nWidth = pW->Width(), nHeight = pW->Height(); 500 const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue(); 501 long nX, nY; 502 503 if( aPaint.GetBitCount() <= 8 ) 504 { 505 const BitmapPalette& rPal = pW->GetPalette(); 506 const sal_uInt16 nCount = rPal.GetEntryCount(); 507 BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ]; 508 509 for( sal_uInt16 i = 0; i < nCount; i++ ) 510 { 511 BitmapColor aCol( rPal[ i ] ); 512 pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) ); 513 } 514 515 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 516 pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 517 { 518 const sal_uInt8 cBlack = aBlack.GetIndex(); 519 520 for( nY = 0; nY < nHeight; nY++ ) 521 { 522 Scanline pWScan = pW->GetScanline( nY ); 523 Scanline pRScan = pR->GetScanline( nY ); 524 sal_uInt8 cBit = 128; 525 526 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ ) 527 { 528 if( !cBit ) 529 cBit = 128, pRScan++; 530 531 if( ( *pRScan & cBit ) == cBlack ) 532 *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex(); 533 } 534 } 535 } 536 else 537 { 538 for( nY = 0; nY < nHeight; nY++ ) 539 for( nX = 0; nX < nWidth; nX++ ) 540 if( pR->GetPixel( nY, nX ) == aBlack ) 541 pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] ); 542 } 543 544 delete[] (sal_uInt8*) pMap; 545 } 546 else 547 { 548 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 549 pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 550 { 551 const sal_uInt8 cBlack = aBlack.GetIndex(); 552 553 for( nY = 0; nY < nHeight; nY++ ) 554 { 555 Scanline pWScan = pW->GetScanline( nY ); 556 Scanline pRScan = pR->GetScanline( nY ); 557 sal_uInt8 cBit = 128; 558 559 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 ) 560 { 561 if( !cBit ) 562 cBit = 128, pRScan++; 563 564 if( ( *pRScan & cBit ) == cBlack ) 565 { 566 pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans ); 567 pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans ); 568 pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans ); 569 } 570 } 571 } 572 } 573 else 574 { 575 for( nY = 0; nY < nHeight; nY++ ) 576 { 577 for( nX = 0; nX < nWidth; nX++ ) 578 { 579 if( pR->GetPixel( nY, nX ) == aBlack ) 580 { 581 aPixCol = pW->GetColor( nY, nX ); 582 pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) ); 583 } 584 } 585 } 586 } 587 } 588 } 589 590 aPolyMask.ReleaseAccess( pR ); 591 aPaint.ReleaseAccess( pW ); 592 593 DrawBitmap( aDstRect.TopLeft(), aPaint ); 594 595 EnableMapMode( bOldMap ); 596 597 if( mbLineColor ) 598 { 599 Push( PUSH_FILLCOLOR ); 600 SetFillColor(); 601 DrawPolyPolygon( rPolyPoly ); 602 Pop(); 603 } 604 } 605 } 606 else 607 DrawPolyPolygon( rPolyPoly ); 608 } 609 } 610 } 611 612 mpMetaFile = pOldMetaFile; 613 614 // #110958# Restore disabled alpha VDev 615 mpAlphaVDev = pOldAlphaVDev; 616 617 // #110958# Apply alpha value also to VDev alpha channel 618 if( mpAlphaVDev ) 619 { 620 const Color aFillCol( mpAlphaVDev->GetFillColor() ); 621 mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 622 sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 623 sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) ); 624 625 mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent ); 626 627 mpAlphaVDev->SetFillColor( aFillCol ); 628 } 629 } 630 } 631 632 // ----------------------------------------------------------------------- 633 634 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, 635 const Size& rSize, const Gradient& rTransparenceGradient ) 636 { 637 DBG_TRACE( "OutputDevice::DrawTransparent()" ); 638 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 639 640 const Color aBlack( COL_BLACK ); 641 642 if( mpMetaFile ) 643 { 644 // missing here is to map the data using the DeviceTransformation 645 mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) ); 646 } 647 648 if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) || 649 ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) ) 650 { 651 ( (GDIMetaFile&) rMtf ).WindStart(); 652 ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize ); 653 ( (GDIMetaFile&) rMtf ).WindStart(); 654 } 655 else 656 { 657 GDIMetaFile* pOldMetaFile = mpMetaFile; 658 Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) ); 659 Point aPoint; 660 Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 661 662 mpMetaFile = NULL; 663 aDstRect.Intersection( aOutRect ); 664 665 if( OUTDEV_WINDOW == meOutDevType ) 666 { 667 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 668 669 if( !aPaintRgn.IsNull() ) 670 aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 671 } 672 673 if( !aDstRect.IsEmpty() ) 674 { 675 VirtualDevice* pVDev = new VirtualDevice; 676 677 ((OutputDevice*)pVDev)->mnDPIX = mnDPIX; 678 ((OutputDevice*)pVDev)->mnDPIY = mnDPIY; 679 680 if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) ) 681 { 682 if(GetAntialiasing()) 683 { 684 // #i102109# 685 // For MetaFile replay (see task) it may now be necessary to take 686 // into account that the content is AntiAlialised and needs to be masked 687 // like that. Instead of masking, i will use a copy-modify-paste cycle 688 // here (as i already use in the VclPrimiziveRenderer with successs) 689 pVDev->SetAntialiasing(GetAntialiasing()); 690 691 // create MapMode for buffer (offset needed) and set 692 MapMode aMap(GetMapMode()); 693 const Point aOutPos(PixelToLogic(aDstRect.TopLeft())); 694 aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y())); 695 pVDev->SetMapMode(aMap); 696 697 // copy MapMode state and disable for target 698 const bool bOrigMapModeEnabled(IsMapModeEnabled()); 699 EnableMapMode(false); 700 701 // copy MapMode state and disable for buffer 702 const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled()); 703 pVDev->EnableMapMode(false); 704 705 // copy content from original to buffer 706 pVDev->DrawOutDev( 707 aPoint, pVDev->GetOutputSizePixel(), // dest 708 aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source 709 *this); 710 711 // draw MetaFile to buffer 712 pVDev->EnableMapMode(bBufferMapModeEnabled); 713 ((GDIMetaFile&)rMtf).WindStart(); 714 ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize); 715 ((GDIMetaFile&)rMtf).WindStart(); 716 717 // get content bitmap from buffer 718 pVDev->EnableMapMode(false); 719 const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 720 721 // create alpha mask from gradient and get as Bitmap 722 pVDev->EnableMapMode(bBufferMapModeEnabled); 723 pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT); 724 pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient); 725 pVDev->SetDrawMode(DRAWMODE_DEFAULT); 726 pVDev->EnableMapMode(false); 727 const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 728 729 // draw masked content to target and restore MapMode 730 DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha)); 731 EnableMapMode(bOrigMapModeEnabled); 732 } 733 else 734 { 735 Bitmap aPaint, aMask; 736 AlphaMask aAlpha; 737 MapMode aMap( GetMapMode() ); 738 Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) ); 739 const sal_Bool bOldMap = mbMap; 740 741 aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) ); 742 pVDev->SetMapMode( aMap ); 743 const sal_Bool bVDevOldMap = pVDev->IsMapModeEnabled(); 744 745 // create paint bitmap 746 ( (GDIMetaFile&) rMtf ).WindStart(); 747 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 748 ( (GDIMetaFile&) rMtf ).WindStart(); 749 pVDev->EnableMapMode( sal_False ); 750 aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 751 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 752 753 // create mask bitmap 754 pVDev->SetLineColor( COL_BLACK ); 755 pVDev->SetFillColor( COL_BLACK ); 756 pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) ); 757 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT | 758 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT ); 759 ( (GDIMetaFile&) rMtf ).WindStart(); 760 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 761 ( (GDIMetaFile&) rMtf ).WindStart(); 762 pVDev->EnableMapMode( sal_False ); 763 aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 764 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 765 766 // create alpha mask from gradient 767 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT ); 768 pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient ); 769 pVDev->SetDrawMode( DRAWMODE_DEFAULT ); 770 pVDev->EnableMapMode( sal_False ); 771 pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) ); 772 773 aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 774 775 delete pVDev; 776 777 EnableMapMode( sal_False ); 778 DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) ); 779 EnableMapMode( bOldMap ); 780 } 781 } 782 else 783 delete pVDev; 784 } 785 786 mpMetaFile = pOldMetaFile; 787 } 788 } 789 790 // ----------------------------------------------------------------------- 791 792 void OutputDevice::ImplDrawColorWallpaper( long nX, long nY, 793 long nWidth, long nHeight, 794 const Wallpaper& rWallpaper ) 795 { 796 // Wallpaper ohne Umrandung zeichnen 797 Color aOldLineColor = GetLineColor(); 798 Color aOldFillColor = GetFillColor(); 799 SetLineColor(); 800 SetFillColor( rWallpaper.GetColor() ); 801 sal_Bool bMap = mbMap; 802 EnableMapMode( sal_False ); 803 DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 804 SetLineColor( aOldLineColor ); 805 SetFillColor( aOldFillColor ); 806 EnableMapMode( bMap ); 807 } 808 809 // ----------------------------------------------------------------------- 810 811 void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY, 812 long nWidth, long nHeight, 813 const Wallpaper& rWallpaper ) 814 { 815 BitmapEx aBmpEx; 816 const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap(); 817 Point aPos; 818 Size aSize; 819 GDIMetaFile* pOldMetaFile = mpMetaFile; 820 const WallpaperStyle eStyle = rWallpaper.GetStyle(); 821 const sal_Bool bOldMap = mbMap; 822 sal_Bool bDrawn = sal_False; 823 sal_Bool bDrawGradientBackground = sal_False; 824 sal_Bool bDrawColorBackground = sal_False; 825 826 if( pCached ) 827 aBmpEx = *pCached; 828 else 829 aBmpEx = rWallpaper.GetBitmap(); 830 831 const long nBmpWidth = aBmpEx.GetSizePixel().Width(); 832 const long nBmpHeight = aBmpEx.GetSizePixel().Height(); 833 const sal_Bool bTransparent = aBmpEx.IsTransparent(); 834 835 // draw background 836 if( bTransparent ) 837 { 838 if( rWallpaper.IsGradient() ) 839 bDrawGradientBackground = sal_True; 840 else 841 { 842 if( !pCached && !rWallpaper.GetColor().GetTransparency() ) 843 { 844 VirtualDevice aVDev( *this ); 845 aVDev.SetBackground( rWallpaper.GetColor() ); 846 aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) ); 847 aVDev.DrawBitmapEx( Point(), aBmpEx ); 848 aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 849 } 850 851 bDrawColorBackground = sal_True; 852 } 853 } 854 else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE ) 855 { 856 if( rWallpaper.IsGradient() ) 857 bDrawGradientBackground = sal_True; 858 else 859 bDrawColorBackground = sal_True; 860 } 861 862 // background of bitmap? 863 if( bDrawGradientBackground ) 864 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 865 else if( bDrawColorBackground && bTransparent ) 866 { 867 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 868 bDrawColorBackground = sal_False; 869 } 870 871 // calc pos and size 872 if( rWallpaper.IsRect() ) 873 { 874 const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) ); 875 aPos = aBound.TopLeft(); 876 aSize = aBound.GetSize(); 877 } 878 else 879 { 880 aPos = Point( nX, nY ); 881 aSize = Size( nWidth, nHeight ); 882 } 883 884 mpMetaFile = NULL; 885 EnableMapMode( sal_False ); 886 Push( PUSH_CLIPREGION ); 887 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 888 889 switch( eStyle ) 890 { 891 case( WALLPAPER_SCALE ): 892 { 893 if( !pCached || ( pCached->GetSizePixel() != aSize ) ) 894 { 895 if( pCached ) 896 rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap(); 897 898 aBmpEx = rWallpaper.GetBitmap(); 899 aBmpEx.Scale( aSize ); 900 aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() ); 901 } 902 } 903 break; 904 905 case( WALLPAPER_TOPLEFT ): 906 break; 907 908 case( WALLPAPER_TOP ): 909 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 910 break; 911 912 case( WALLPAPER_TOPRIGHT ): 913 aPos.X() += ( aSize.Width() - nBmpWidth ); 914 break; 915 916 case( WALLPAPER_LEFT ): 917 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 918 break; 919 920 case( WALLPAPER_CENTER ): 921 { 922 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 923 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 924 } 925 break; 926 927 case( WALLPAPER_RIGHT ): 928 { 929 aPos.X() += ( aSize.Width() - nBmpWidth ); 930 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 931 } 932 break; 933 934 case( WALLPAPER_BOTTOMLEFT ): 935 aPos.Y() += ( aSize.Height() - nBmpHeight ); 936 break; 937 938 case( WALLPAPER_BOTTOM ): 939 { 940 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 941 aPos.Y() += ( aSize.Height() - nBmpHeight ); 942 } 943 break; 944 945 case( WALLPAPER_BOTTOMRIGHT ): 946 { 947 aPos.X() += ( aSize.Width() - nBmpWidth ); 948 aPos.Y() += ( aSize.Height() - nBmpHeight ); 949 } 950 break; 951 952 default: 953 { 954 const long nRight = nX + nWidth - 1L; 955 const long nBottom = nY + nHeight - 1L; 956 long nFirstX; 957 long nFirstY; 958 959 if( eStyle == WALLPAPER_TILE ) 960 { 961 nFirstX = aPos.X(); 962 nFirstY = aPos.Y(); 963 } 964 else 965 { 966 nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 ); 967 nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 ); 968 } 969 970 const long nOffX = ( nFirstX - nX ) % nBmpWidth; 971 const long nOffY = ( nFirstY - nY ) % nBmpHeight; 972 long nStartX = nX + nOffX; 973 long nStartY = nY + nOffY; 974 975 if( nOffX > 0L ) 976 nStartX -= nBmpWidth; 977 978 if( nOffY > 0L ) 979 nStartY -= nBmpHeight; 980 981 for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight ) 982 for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth ) 983 DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx ); 984 985 bDrawn = sal_True; 986 } 987 break; 988 } 989 990 if( !bDrawn ) 991 { 992 // optimized for non-transparent bitmaps 993 if( bDrawColorBackground ) 994 { 995 const Size aBmpSize( aBmpEx.GetSizePixel() ); 996 const Point aTmpPoint; 997 const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() ); 998 const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 999 Rectangle aWorkRect; 1000 1001 aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L ); 1002 aWorkRect.Justify(); 1003 aWorkRect.Intersection( aColRect ); 1004 if( !aWorkRect.IsEmpty() ) 1005 { 1006 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1007 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1008 rWallpaper ); 1009 } 1010 1011 aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L ); 1012 aWorkRect.Justify(); 1013 aWorkRect.Intersection( aColRect ); 1014 if( !aWorkRect.IsEmpty() ) 1015 { 1016 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1017 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1018 rWallpaper ); 1019 } 1020 1021 aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L ); 1022 aWorkRect.Justify(); 1023 aWorkRect.Intersection( aColRect ); 1024 if( !aWorkRect.IsEmpty() ) 1025 { 1026 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1027 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1028 rWallpaper ); 1029 } 1030 1031 aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() ); 1032 aWorkRect.Justify(); 1033 aWorkRect.Intersection( aColRect ); 1034 if( !aWorkRect.IsEmpty() ) 1035 { 1036 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1037 aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1038 rWallpaper ); 1039 } 1040 } 1041 1042 DrawBitmapEx( aPos, aBmpEx ); 1043 } 1044 1045 rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx ); 1046 1047 Pop(); 1048 EnableMapMode( bOldMap ); 1049 mpMetaFile = pOldMetaFile; 1050 } 1051 1052 // ----------------------------------------------------------------------- 1053 1054 void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY, 1055 long nWidth, long nHeight, 1056 const Wallpaper& rWallpaper ) 1057 { 1058 Rectangle aBound; 1059 GDIMetaFile* pOldMetaFile = mpMetaFile; 1060 const sal_Bool bOldMap = mbMap; 1061 sal_Bool bNeedGradient = sal_True; 1062 1063 /* 1064 if ( rWallpaper.IsRect() ) 1065 aBound = LogicToPixel( rWallpaper.GetRect() ); 1066 else 1067 */ 1068 aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); 1069 1070 mpMetaFile = NULL; 1071 EnableMapMode( sal_False ); 1072 Push( PUSH_CLIPREGION ); 1073 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 1074 1075 if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT ) 1076 { 1077 Window *pWin = dynamic_cast< Window* >( this ); 1078 if( pWin ) 1079 { 1080 // limit gradient to useful size, so that it still can be noticed 1081 // in maximized windows 1082 long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width(); 1083 if( gradientWidth > 1024 ) 1084 gradientWidth = 1024; 1085 if( mnOutOffX+nWidth > gradientWidth ) 1086 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() ); 1087 if( mnOutOffX > gradientWidth ) 1088 bNeedGradient = sal_False; 1089 else 1090 aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) ); 1091 } 1092 } 1093 1094 if( bNeedGradient ) 1095 DrawGradient( aBound, rWallpaper.GetGradient() ); 1096 1097 Pop(); 1098 EnableMapMode( bOldMap ); 1099 mpMetaFile = pOldMetaFile; 1100 } 1101 1102 // ----------------------------------------------------------------------- 1103 1104 void OutputDevice::ImplDrawWallpaper( long nX, long nY, 1105 long nWidth, long nHeight, 1106 const Wallpaper& rWallpaper ) 1107 { 1108 if( rWallpaper.IsBitmap() ) 1109 ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1110 else if( rWallpaper.IsGradient() ) 1111 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1112 else 1113 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1114 } 1115 1116 // ----------------------------------------------------------------------- 1117 1118 void OutputDevice::DrawWallpaper( const Rectangle& rRect, 1119 const Wallpaper& rWallpaper ) 1120 { 1121 if ( mpMetaFile ) 1122 mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) ); 1123 1124 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1125 return; 1126 1127 if ( rWallpaper.GetStyle() != WALLPAPER_NULL ) 1128 { 1129 Rectangle aRect = LogicToPixel( rRect ); 1130 aRect.Justify(); 1131 1132 if ( !aRect.IsEmpty() ) 1133 { 1134 ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1135 rWallpaper ); 1136 } 1137 } 1138 1139 if( mpAlphaVDev ) 1140 mpAlphaVDev->DrawWallpaper( rRect, rWallpaper ); 1141 } 1142 1143 // ----------------------------------------------------------------------- 1144 1145 void OutputDevice::Erase() 1146 { 1147 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1148 return; 1149 1150 sal_Bool bNativeOK = sal_False; 1151 1152 if( meOutDevType == OUTDEV_WINDOW ) 1153 { 1154 Window* pWindow = static_cast<Window*>(this); 1155 ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground; 1156 if( aCtrlPart != 0 && ! pWindow->IsControlBackground() ) 1157 { 1158 ImplControlValue aControlValue; 1159 Point aGcc3WorkaroundTemporary; 1160 Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() ); 1161 ControlState nState = 0; 1162 1163 if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1164 bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion, 1165 nState, aControlValue, rtl::OUString() ); 1166 } 1167 } 1168 1169 if ( mbBackground && ! bNativeOK ) 1170 { 1171 RasterOp eRasterOp = GetRasterOp(); 1172 if ( eRasterOp != ROP_OVERPAINT ) 1173 SetRasterOp( ROP_OVERPAINT ); 1174 ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground ); 1175 if ( eRasterOp != ROP_OVERPAINT ) 1176 SetRasterOp( eRasterOp ); 1177 } 1178 1179 if( mpAlphaVDev ) 1180 mpAlphaVDev->Erase(); 1181 } 1182 1183 // ----------------------------------------------------------------------- 1184 1185 void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect, 1186 const Color& rLeftTopColor, 1187 const Color& rRightBottomColor ) 1188 { 1189 SetFillColor( rLeftTopColor ); 1190 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) ); 1191 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) ); 1192 SetFillColor( rRightBottomColor ); 1193 DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) ); 1194 DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) ); 1195 } 1196 1197 // ----------------------------------------------------------------------- 1198 1199 bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize, 1200 const GfxLink& rGfxLink, GDIMetaFile* pSubst ) 1201 { 1202 DBG_TRACE( "OutputDevice::DrawEPS()" ); 1203 1204 bool bDrawn(true); 1205 1206 if ( mpMetaFile ) 1207 { 1208 GDIMetaFile aSubst; 1209 1210 if( pSubst ) 1211 aSubst = *pSubst; 1212 1213 mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) ); 1214 } 1215 1216 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1217 return bDrawn; 1218 1219 if( mbOutputClipped ) 1220 return bDrawn; 1221 1222 Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) ); 1223 1224 if( !aRect.IsEmpty() ) 1225 { 1226 // draw the real EPS graphics 1227 if( rGfxLink.GetData() && rGfxLink.GetDataSize() ) 1228 { 1229 if( !mpGraphics && !ImplGetGraphics() ) 1230 return bDrawn; 1231 1232 if( mbInitClipRegion ) 1233 ImplInitClipRegion(); 1234 1235 aRect.Justify(); 1236 bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1237 (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this ); 1238 } 1239 1240 // else draw the substitution graphics 1241 if( !bDrawn && pSubst ) 1242 { 1243 GDIMetaFile* pOldMetaFile = mpMetaFile; 1244 1245 mpMetaFile = NULL; 1246 Graphic( *pSubst ).Draw( this, rPoint, rSize ); 1247 mpMetaFile = pOldMetaFile; 1248 } 1249 } 1250 1251 if( mpAlphaVDev ) 1252 mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst ); 1253 1254 return bDrawn; 1255 } 1256 1257 // ----------------------------------------------------------------------- 1258 1259 void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd) 1260 { 1261 const sal_uInt32 nMaxX(rPos.X() + rSize.Width()); 1262 const sal_uInt32 nMaxY(rPos.Y() + rSize.Height()); 1263 1264 Push(PUSH_LINECOLOR|PUSH_FILLCOLOR); 1265 SetLineColor(); 1266 1267 for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen) 1268 { 1269 const sal_uInt32 nRight(std::min(nMaxX, nX + nLen)); 1270 1271 for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen) 1272 { 1273 const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen)); 1274 1275 SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd); 1276 DrawRect(Rectangle(nX, nY, nRight, nBottom)); 1277 } 1278 } 1279 1280 Pop(); 1281 } 1282 1283 // ----------------------------------------------------------------------- 1284 // eof 1285