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 29 #include <vcl/settings.hxx> 30 #include <vcl/svapp.hxx> 31 #include <vcl/wrkwin.hxx> 32 #include <vcl/virdev.hxx> 33 34 #include <salinst.hxx> 35 #include <salgdi.hxx> 36 #include <salframe.hxx> 37 #include <salvd.hxx> 38 #include <outdev.h> 39 #include <svdata.hxx> 40 41 using namespace ::com::sun::star::uno; 42 43 // ======================================================================= 44 45 void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev, 46 long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) 47 { 48 DBG_ASSERT( nBitCount <= 1, 49 "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" ); 50 51 if ( nDX < 1 ) 52 nDX = 1; 53 54 if ( nDY < 1 ) 55 nDY = 1; 56 57 ImplSVData* pSVData = ImplGetSVData(); 58 59 if ( !pOutDev ) 60 pOutDev = ImplGetDefaultWindow(); 61 if( !pOutDev ) 62 return; 63 64 SalGraphics* pGraphics; 65 if ( !pOutDev->mpGraphics ) 66 ((OutputDevice*)pOutDev)->ImplGetGraphics(); 67 pGraphics = pOutDev->mpGraphics; 68 if ( pGraphics ) 69 mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData ); 70 else 71 mpVirDev = NULL; 72 if ( !mpVirDev ) 73 { 74 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario) 75 throw ::com::sun::star::uno::RuntimeException( 76 OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system bitmap!" ) ), 77 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 78 //GetpApp()->Exception( EXC_SYSOBJNOTCREATED ); 79 } 80 81 mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() ); 82 mnOutWidth = nDX; 83 mnOutHeight = nDY; 84 mbScreenComp = sal_True; 85 mnAlphaDepth = -1; 86 87 // #i59315# init vdev size from system object, when passed a 88 // SystemGraphicsData. Otherwise, output size will always 89 // incorrectly stay at (1,1) 90 if( pData && mpVirDev ) 91 mpVirDev->GetSize(mnOutWidth,mnOutHeight); 92 93 if( mnBitCount < 8 ) 94 SetAntialiasing( ANTIALIASING_DISABLE_TEXT ); 95 96 if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER ) 97 mbScreenComp = sal_False; 98 else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV ) 99 mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp; 100 101 meOutDevType = OUTDEV_VIRDEV; 102 mbDevOutput = sal_True; 103 mpFontList = pSVData->maGDIData.mpScreenFontList; 104 mpFontCache = pSVData->maGDIData.mpScreenFontCache; 105 mnDPIX = pOutDev->mnDPIX; 106 mnDPIY = pOutDev->mnDPIY; 107 maFont = pOutDev->maFont; 108 109 if( maTextColor != pOutDev->maTextColor ) 110 { 111 maTextColor = pOutDev->maTextColor; 112 mbInitTextColor = true; 113 } 114 115 // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund 116 SetBackground( Wallpaper( Color( COL_WHITE ) ) ); 117 118 // #i59283# don't erase user-provided surface 119 if( !pData ) 120 Erase(); 121 122 // VirDev in Liste eintragen 123 mpNext = pSVData->maGDIData.mpFirstVirDev; 124 mpPrev = NULL; 125 if ( mpNext ) 126 mpNext->mpPrev = this; 127 else 128 pSVData->maGDIData.mpLastVirDev = this; 129 pSVData->maGDIData.mpFirstVirDev = this; 130 } 131 132 // ----------------------------------------------------------------------- 133 134 VirtualDevice::VirtualDevice( sal_uInt16 nBitCount ) 135 : mpVirDev( NULL ), 136 meRefDevMode( REFDEV_NONE ) 137 { 138 DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); 139 140 ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount ); 141 } 142 143 // ----------------------------------------------------------------------- 144 145 VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount ) 146 : mpVirDev( NULL ), 147 meRefDevMode( REFDEV_NONE ) 148 { 149 DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); 150 151 ImplInitVirDev( &rCompDev, 1, 1, nBitCount ); 152 } 153 154 // ----------------------------------------------------------------------- 155 156 VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount, sal_uInt16 nAlphaBitCount ) 157 : mpVirDev( NULL ), 158 meRefDevMode( REFDEV_NONE ) 159 { 160 DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); 161 162 ImplInitVirDev( &rCompDev, 1, 1, nBitCount ); 163 164 // #110958# Enable alpha channel 165 mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount); 166 } 167 168 // ----------------------------------------------------------------------- 169 170 VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, sal_uInt16 nBitCount ) 171 : mpVirDev( NULL ), 172 meRefDevMode( REFDEV_NONE ) 173 { 174 DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); 175 176 ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData ); 177 } 178 179 // ----------------------------------------------------------------------- 180 181 VirtualDevice::~VirtualDevice() 182 { 183 DBG_TRACE( "VirtualDevice::~VirtualDevice()" ); 184 185 ImplSVData* pSVData = ImplGetSVData(); 186 187 ImplReleaseGraphics(); 188 189 if ( mpVirDev ) 190 pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev ); 191 192 // remove this VirtualDevice from the double-linked global list 193 if( mpPrev ) 194 mpPrev->mpNext = mpNext; 195 else 196 pSVData->maGDIData.mpFirstVirDev = mpNext; 197 198 if( mpNext ) 199 mpNext->mpPrev = mpPrev; 200 else 201 pSVData->maGDIData.mpLastVirDev = mpPrev; 202 } 203 204 // ----------------------------------------------------------------------- 205 206 sal_Bool VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, sal_Bool bErase ) 207 { 208 DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase ); 209 210 if ( !mpVirDev ) 211 return sal_False; 212 else if ( rNewSize == GetOutputSizePixel() ) 213 { 214 if ( bErase ) 215 Erase(); 216 return sal_True; 217 } 218 219 sal_Bool bRet; 220 long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height(); 221 222 if ( nNewWidth < 1 ) 223 nNewWidth = 1; 224 225 if ( nNewHeight < 1 ) 226 nNewHeight = 1; 227 228 if ( bErase ) 229 { 230 bRet = mpVirDev->SetSize( nNewWidth, nNewHeight ); 231 232 if ( bRet ) 233 { 234 mnOutWidth = rNewSize.Width(); 235 mnOutHeight = rNewSize.Height(); 236 Erase(); 237 } 238 } 239 else 240 { 241 SalVirtualDevice* pNewVirDev; 242 ImplSVData* pSVData = ImplGetSVData(); 243 244 // we need a graphics 245 if ( !mpGraphics ) 246 { 247 if ( !ImplGetGraphics() ) 248 return sal_False; 249 } 250 251 pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount ); 252 if ( pNewVirDev ) 253 { 254 SalGraphics* pGraphics = pNewVirDev->GetGraphics(); 255 if ( pGraphics ) 256 { 257 SalTwoRect aPosAry; 258 long nWidth; 259 long nHeight; 260 if ( mnOutWidth < nNewWidth ) 261 nWidth = mnOutWidth; 262 else 263 nWidth = nNewWidth; 264 if ( mnOutHeight < nNewHeight ) 265 nHeight = mnOutHeight; 266 else 267 nHeight = nNewHeight; 268 aPosAry.mnSrcX = 0; 269 aPosAry.mnSrcY = 0; 270 aPosAry.mnSrcWidth = nWidth; 271 aPosAry.mnSrcHeight = nHeight; 272 aPosAry.mnDestX = 0; 273 aPosAry.mnDestY = 0; 274 aPosAry.mnDestWidth = nWidth; 275 aPosAry.mnDestHeight = nHeight; 276 277 pGraphics->CopyBits( &aPosAry, mpGraphics, this, this ); 278 pNewVirDev->ReleaseGraphics( pGraphics ); 279 ImplReleaseGraphics(); 280 pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev ); 281 mpVirDev = pNewVirDev; 282 mnOutWidth = rNewSize.Width(); 283 mnOutHeight = rNewSize.Height(); 284 bRet = sal_True; 285 } 286 else 287 { 288 bRet = sal_False; 289 pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev ); 290 } 291 } 292 else 293 bRet = sal_False; 294 } 295 296 return bRet; 297 } 298 299 // ----------------------------------------------------------------------- 300 301 // #i32109#: Fill opaque areas correctly (without relying on 302 // fill/linecolor state) 303 void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect ) 304 { 305 // Set line and fill color to black (->opaque), 306 // fill rect with that (linecolor, too, because of 307 // those pesky missing pixel problems) 308 Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 309 SetLineColor( COL_BLACK ); 310 SetFillColor( COL_BLACK ); 311 DrawRect( rRect ); 312 Pop(); 313 } 314 315 // ----------------------------------------------------------------------- 316 317 sal_Bool VirtualDevice::SetOutputSizePixel( const Size& rNewSize, sal_Bool bErase ) 318 { 319 if( ImplSetOutputSizePixel(rNewSize, bErase) ) 320 { 321 if( mnAlphaDepth != -1 ) 322 { 323 // #110958# Setup alpha bitmap 324 if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize) 325 { 326 delete mpAlphaVDev; 327 mpAlphaVDev = 0L; 328 } 329 330 if( !mpAlphaVDev ) 331 { 332 mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth ); 333 mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase); 334 } 335 336 // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev 337 if( GetLineColor() != Color( COL_TRANSPARENT ) ) 338 mpAlphaVDev->SetLineColor( COL_BLACK ); 339 340 if( GetFillColor() != Color( COL_TRANSPARENT ) ) 341 mpAlphaVDev->SetFillColor( COL_BLACK ); 342 343 mpAlphaVDev->SetMapMode( GetMapMode() ); 344 } 345 346 return sal_True; 347 } 348 349 return sal_False; 350 } 351 352 // ----------------------------------------------------------------------- 353 354 void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode ) 355 { 356 sal_Int32 nDPIX = 600, nDPIY = 600; 357 switch( i_eRefDevMode ) 358 { 359 case REFDEV_NONE: 360 default: 361 DBG_ASSERT( sal_False, "VDev::SetRefDev illegal argument!" ); 362 break; 363 case REFDEV_MODE06: 364 nDPIX = nDPIY = 600; 365 break; 366 case REFDEV_MODE48: 367 nDPIX = nDPIY = 4800; 368 break; 369 case REFDEV_MODE_MSO1: 370 nDPIX = nDPIY = 6*1440; 371 break; 372 case REFDEV_MODE_PDF1: 373 nDPIX = nDPIY = 720; 374 break; 375 } 376 ImplSetReferenceDevice( i_eRefDevMode, nDPIX, nDPIY ); 377 } 378 379 void VirtualDevice::SetReferenceDevice( sal_Int32 i_nDPIX, sal_Int32 i_nDPIY ) 380 { 381 ImplSetReferenceDevice( REFDEV_CUSTOM, i_nDPIX, i_nDPIY ); 382 } 383 384 void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode, sal_Int32 i_nDPIX, sal_Int32 i_nDPIY ) 385 { 386 mnDPIX = i_nDPIX; 387 mnDPIY = i_nDPIY; 388 389 EnableOutput( sal_False ); // prevent output on reference device 390 mbScreenComp = sal_False; 391 392 // invalidate currently selected fonts 393 mbInitFont = sal_True; 394 mbNewFont = sal_True; 395 396 // avoid adjusting font lists when already in refdev mode 397 sal_uInt8 nOldRefDevMode = meRefDevMode; 398 sal_uInt8 nOldCompatFlag = (sal_uInt8)meRefDevMode & REFDEV_FORCE_ZERO_EXTLEAD; 399 meRefDevMode = (sal_uInt8)(i_eRefDevMode | nOldCompatFlag); 400 if( (nOldRefDevMode ^ nOldCompatFlag) != REFDEV_NONE ) 401 return; 402 403 // the reference device should have only scalable fonts 404 // => clean up the original font lists before getting new ones 405 if ( mpFontEntry ) 406 { 407 mpFontCache->Release( mpFontEntry ); 408 mpFontEntry = NULL; 409 } 410 if ( mpGetDevFontList ) 411 { 412 delete mpGetDevFontList; 413 mpGetDevFontList = NULL; 414 } 415 if ( mpGetDevSizeList ) 416 { 417 delete mpGetDevSizeList; 418 mpGetDevSizeList = NULL; 419 } 420 421 // preserve global font lists 422 ImplSVData* pSVData = ImplGetSVData(); 423 if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) ) 424 delete mpFontList; 425 if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) ) 426 delete mpFontCache; 427 428 // get font list with scalable fonts only 429 ImplGetGraphics(); 430 mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false ); 431 432 // prepare to use new font lists 433 mpFontCache = new ImplFontCache( false ); 434 } 435 436 // ----------------------------------------------------------------------- 437 438 void VirtualDevice::Compat_ZeroExtleadBug() 439 { 440 meRefDevMode = (sal_uInt8)meRefDevMode | REFDEV_FORCE_ZERO_EXTLEAD; 441 } 442 443 // ----------------------------------------------------------------------- 444 445