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