| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <tools/debug.hxx> |
| |
| #include <vcl/settings.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/wrkwin.hxx> |
| #include <vcl/virdev.hxx> |
| |
| #include <salinst.hxx> |
| #include <salgdi.hxx> |
| #include <salframe.hxx> |
| #include <salvd.hxx> |
| #include <outdev.h> |
| #include <svdata.hxx> |
| |
| using namespace ::com::sun::star::uno; |
| |
| // ======================================================================= |
| |
| void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev, |
| long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData ) |
| { |
| DBG_ASSERT( nBitCount <= 1, |
| "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" ); |
| |
| if ( nDX < 1 ) |
| nDX = 1; |
| |
| if ( nDY < 1 ) |
| nDY = 1; |
| |
| ImplSVData* pSVData = ImplGetSVData(); |
| |
| if ( !pOutDev ) |
| pOutDev = ImplGetDefaultWindow(); |
| if( !pOutDev ) |
| return; |
| |
| SalGraphics* pGraphics; |
| if ( !pOutDev->mpGraphics ) |
| ((OutputDevice*)pOutDev)->ImplGetGraphics(); |
| pGraphics = pOutDev->mpGraphics; |
| if ( pGraphics ) |
| mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData ); |
| else |
| mpVirDev = NULL; |
| if ( !mpVirDev ) |
| { |
| // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario) |
| throw ::com::sun::star::uno::RuntimeException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system bitmap!" ) ), |
| ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); |
| //GetpApp()->Exception( EXC_SYSOBJNOTCREATED ); |
| } |
| |
| mnBitCount = ( nBitCount ? nBitCount : pOutDev->GetBitCount() ); |
| mnOutWidth = nDX; |
| mnOutHeight = nDY; |
| mbScreenComp = sal_True; |
| mnAlphaDepth = -1; |
| |
| // #i59315# init vdev size from system object, when passed a |
| // SystemGraphicsData. Otherwise, output size will always |
| // incorrectly stay at (1,1) |
| if( pData && mpVirDev ) |
| mpVirDev->GetSize(mnOutWidth,mnOutHeight); |
| |
| if( mnBitCount < 8 ) |
| SetAntialiasing( ANTIALIASING_DISABLE_TEXT ); |
| |
| if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER ) |
| mbScreenComp = sal_False; |
| else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV ) |
| mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp; |
| |
| meOutDevType = OUTDEV_VIRDEV; |
| mbDevOutput = sal_True; |
| mpFontList = pSVData->maGDIData.mpScreenFontList; |
| mpFontCache = pSVData->maGDIData.mpScreenFontCache; |
| mnDPIX = pOutDev->mnDPIX; |
| mnDPIY = pOutDev->mnDPIY; |
| maFont = pOutDev->maFont; |
| |
| if( maTextColor != pOutDev->maTextColor ) |
| { |
| maTextColor = pOutDev->maTextColor; |
| mbInitTextColor = true; |
| } |
| |
| // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund |
| SetBackground( Wallpaper( Color( COL_WHITE ) ) ); |
| |
| // #i59283# don't erase user-provided surface |
| if( !pData ) |
| Erase(); |
| |
| // VirDev in Liste eintragen |
| mpNext = pSVData->maGDIData.mpFirstVirDev; |
| mpPrev = NULL; |
| if ( mpNext ) |
| mpNext->mpPrev = this; |
| else |
| pSVData->maGDIData.mpLastVirDev = this; |
| pSVData->maGDIData.mpFirstVirDev = this; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| VirtualDevice::VirtualDevice( sal_uInt16 nBitCount ) |
| : mpVirDev( NULL ), |
| meRefDevMode( REFDEV_NONE ) |
| { |
| DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); |
| |
| ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount ) |
| : mpVirDev( NULL ), |
| meRefDevMode( REFDEV_NONE ) |
| { |
| DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); |
| |
| ImplInitVirDev( &rCompDev, 1, 1, nBitCount ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount, sal_uInt16 nAlphaBitCount ) |
| : mpVirDev( NULL ), |
| meRefDevMode( REFDEV_NONE ) |
| { |
| DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); |
| |
| ImplInitVirDev( &rCompDev, 1, 1, nBitCount ); |
| |
| // #110958# Enable alpha channel |
| mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, sal_uInt16 nBitCount ) |
| : mpVirDev( NULL ), |
| meRefDevMode( REFDEV_NONE ) |
| { |
| DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount ); |
| |
| ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| VirtualDevice::~VirtualDevice() |
| { |
| DBG_TRACE( "VirtualDevice::~VirtualDevice()" ); |
| |
| ImplSVData* pSVData = ImplGetSVData(); |
| |
| ImplReleaseGraphics(); |
| |
| if ( mpVirDev ) |
| pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev ); |
| |
| // remove this VirtualDevice from the double-linked global list |
| if( mpPrev ) |
| mpPrev->mpNext = mpNext; |
| else |
| pSVData->maGDIData.mpFirstVirDev = mpNext; |
| |
| if( mpNext ) |
| mpNext->mpPrev = mpPrev; |
| else |
| pSVData->maGDIData.mpLastVirDev = mpPrev; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, sal_Bool bErase ) |
| { |
| DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase ); |
| |
| if ( !mpVirDev ) |
| return sal_False; |
| else if ( rNewSize == GetOutputSizePixel() ) |
| { |
| if ( bErase ) |
| Erase(); |
| return sal_True; |
| } |
| |
| sal_Bool bRet; |
| long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height(); |
| |
| if ( nNewWidth < 1 ) |
| nNewWidth = 1; |
| |
| if ( nNewHeight < 1 ) |
| nNewHeight = 1; |
| |
| if ( bErase ) |
| { |
| bRet = mpVirDev->SetSize( nNewWidth, nNewHeight ); |
| |
| if ( bRet ) |
| { |
| mnOutWidth = rNewSize.Width(); |
| mnOutHeight = rNewSize.Height(); |
| Erase(); |
| } |
| } |
| else |
| { |
| SalVirtualDevice* pNewVirDev; |
| ImplSVData* pSVData = ImplGetSVData(); |
| |
| // we need a graphics |
| if ( !mpGraphics ) |
| { |
| if ( !ImplGetGraphics() ) |
| return sal_False; |
| } |
| |
| pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount ); |
| if ( pNewVirDev ) |
| { |
| SalGraphics* pGraphics = pNewVirDev->GetGraphics(); |
| if ( pGraphics ) |
| { |
| SalTwoRect aPosAry; |
| long nWidth; |
| long nHeight; |
| if ( mnOutWidth < nNewWidth ) |
| nWidth = mnOutWidth; |
| else |
| nWidth = nNewWidth; |
| if ( mnOutHeight < nNewHeight ) |
| nHeight = mnOutHeight; |
| else |
| nHeight = nNewHeight; |
| aPosAry.mnSrcX = 0; |
| aPosAry.mnSrcY = 0; |
| aPosAry.mnSrcWidth = nWidth; |
| aPosAry.mnSrcHeight = nHeight; |
| aPosAry.mnDestX = 0; |
| aPosAry.mnDestY = 0; |
| aPosAry.mnDestWidth = nWidth; |
| aPosAry.mnDestHeight = nHeight; |
| |
| pGraphics->CopyBits( aPosAry, mpGraphics, this, this ); |
| pNewVirDev->ReleaseGraphics( pGraphics ); |
| ImplReleaseGraphics(); |
| pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev ); |
| mpVirDev = pNewVirDev; |
| mnOutWidth = rNewSize.Width(); |
| mnOutHeight = rNewSize.Height(); |
| bRet = sal_True; |
| } |
| else |
| { |
| bRet = sal_False; |
| pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev ); |
| } |
| } |
| else |
| bRet = sal_False; |
| } |
| |
| return bRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| // #i32109#: Fill opaque areas correctly (without relying on |
| // fill/linecolor state) |
| void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect ) |
| { |
| // Set line and fill color to black (->opaque), |
| // fill rect with that (linecolor, too, because of |
| // those pesky missing pixel problems) |
| Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); |
| SetLineColor( COL_BLACK ); |
| SetFillColor( COL_BLACK ); |
| DrawRect( rRect ); |
| Pop(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool VirtualDevice::SetOutputSizePixel( const Size& rNewSize, sal_Bool bErase ) |
| { |
| if( ImplSetOutputSizePixel(rNewSize, bErase) ) |
| { |
| if( mnAlphaDepth != -1 ) |
| { |
| // #110958# Setup alpha bitmap |
| if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize) |
| { |
| delete mpAlphaVDev; |
| mpAlphaVDev = 0L; |
| } |
| |
| if( !mpAlphaVDev ) |
| { |
| mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth ); |
| mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase); |
| } |
| |
| // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev |
| if( GetLineColor() != Color( COL_TRANSPARENT ) ) |
| mpAlphaVDev->SetLineColor( COL_BLACK ); |
| |
| if( GetFillColor() != Color( COL_TRANSPARENT ) ) |
| mpAlphaVDev->SetFillColor( COL_BLACK ); |
| |
| mpAlphaVDev->SetMapMode( GetMapMode() ); |
| } |
| |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void VirtualDevice::SetReferenceDevice( RefDevMode i_eRefDevMode ) |
| { |
| sal_Int32 nDPIX = 600, nDPIY = 600; |
| switch( i_eRefDevMode ) |
| { |
| case REFDEV_NONE: |
| default: |
| DBG_ASSERT( sal_False, "VDev::SetRefDev illegal argument!" ); |
| break; |
| case REFDEV_MODE06: |
| nDPIX = nDPIY = 600; |
| break; |
| case REFDEV_MODE48: |
| nDPIX = nDPIY = 4800; |
| break; |
| case REFDEV_MODE_MSO1: |
| nDPIX = nDPIY = 6*1440; |
| break; |
| case REFDEV_MODE_PDF1: |
| nDPIX = nDPIY = 720; |
| break; |
| } |
| ImplSetReferenceDevice( i_eRefDevMode, nDPIX, nDPIY ); |
| } |
| |
| void VirtualDevice::SetReferenceDevice( sal_Int32 i_nDPIX, sal_Int32 i_nDPIY ) |
| { |
| ImplSetReferenceDevice( REFDEV_CUSTOM, i_nDPIX, i_nDPIY ); |
| } |
| |
| void VirtualDevice::ImplSetReferenceDevice( RefDevMode i_eRefDevMode, sal_Int32 i_nDPIX, sal_Int32 i_nDPIY ) |
| { |
| mnDPIX = i_nDPIX; |
| mnDPIY = i_nDPIY; |
| |
| EnableOutput( sal_False ); // prevent output on reference device |
| mbScreenComp = sal_False; |
| |
| // invalidate currently selected fonts |
| mbInitFont = sal_True; |
| mbNewFont = sal_True; |
| |
| // avoid adjusting font lists when already in refdev mode |
| sal_uInt8 nOldRefDevMode = meRefDevMode; |
| sal_uInt8 nOldCompatFlag = (sal_uInt8)meRefDevMode & REFDEV_FORCE_ZERO_EXTLEAD; |
| meRefDevMode = (sal_uInt8)(i_eRefDevMode | nOldCompatFlag); |
| if( (nOldRefDevMode ^ nOldCompatFlag) != REFDEV_NONE ) |
| return; |
| |
| // the reference device should have only scalable fonts |
| // => clean up the original font lists before getting new ones |
| if ( mpFontEntry ) |
| { |
| mpFontCache->Release( mpFontEntry ); |
| mpFontEntry = NULL; |
| } |
| if ( mpGetDevFontList ) |
| { |
| delete mpGetDevFontList; |
| mpGetDevFontList = NULL; |
| } |
| if ( mpGetDevSizeList ) |
| { |
| delete mpGetDevSizeList; |
| mpGetDevSizeList = NULL; |
| } |
| |
| // preserve global font lists |
| ImplSVData* pSVData = ImplGetSVData(); |
| if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) ) |
| delete mpFontList; |
| if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) ) |
| delete mpFontCache; |
| |
| // get font list with scalable fonts only |
| ImplGetGraphics(); |
| mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false ); |
| |
| // prepare to use new font lists |
| mpFontCache = new ImplFontCache( false ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void VirtualDevice::Compat_ZeroExtleadBug() |
| { |
| meRefDevMode = (sal_uInt8)meRefDevMode | REFDEV_FORCE_ZERO_EXTLEAD; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |