diff options
Diffstat (limited to 'vcl/source/gdi/impprn.cxx')
-rw-r--r-- | vcl/source/gdi/impprn.cxx | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/vcl/source/gdi/impprn.cxx b/vcl/source/gdi/impprn.cxx new file mode 100644 index 000000000000..539c879c89ea --- /dev/null +++ b/vcl/source/gdi/impprn.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: impprn.cxx,v $ + * $Revision: 1.18.86.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#define _SPOOLPRINTER_EXT +#include "tools/queue.hxx" +#include "vcl/svapp.hxx" +#include "vcl/metaact.hxx" +#include "vcl/gdimtf.hxx" +#include "vcl/timer.hxx" +#include "vcl/impprn.hxx" +#include "vcl/jobset.h" + +#include "vcl/svdata.hxx" +#include "vcl/salprn.hxx" + +// ----------- +// - Defines - +// ----------- + +#define OPTIMAL_BMP_RESOLUTION 300 +#define NORMAL_BMP_RESOLUTION 200 + +// ======================================================================= + +struct QueuePage +{ + GDIMetaFile* mpMtf; + JobSetup* mpSetup; + USHORT mnPage; + BOOL mbEndJob; + + QueuePage() { mpMtf = NULL; mpSetup = NULL; } + ~QueuePage() { delete mpMtf; if ( mpSetup ) delete mpSetup; } +}; + +// ======================================================================= + +ImplQPrinter::ImplQPrinter( Printer* pParent ) : + Printer( pParent->GetName() ), + mpParent( pParent ), + mbAborted( false ), + mbUserCopy( false ), + mbDestroyAllowed( true ), + mbDestroyed( false ), + mnMaxBmpDPIX( mnDPIX ), + mnMaxBmpDPIY( mnDPIY ), + mnCurCopyCount( 0 ) +{ + SetSelfAsQueuePrinter( TRUE ); + SetPrinterProps( pParent ); + SetPageQueueSize( 0 ); + mnCopyCount = pParent->mnCopyCount; + mbCollateCopy = pParent->mbCollateCopy; +} + +// ----------------------------------------------------------------------- + +ImplQPrinter::~ImplQPrinter() +{ + for( std::vector< QueuePage* >::iterator it = maQueue.begin(); + it != maQueue.end(); ++it ) + delete (*it); +} + +// ----------------------------------------------------------------------------- + +void ImplQPrinter::Destroy() +{ + if( mbDestroyAllowed ) + delete this; + else + mbDestroyed = TRUE; +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::ImplPrintMtf( GDIMetaFile& rPrtMtf, long nMaxBmpDPIX, long nMaxBmpDPIY ) +{ + for( MetaAction* pAct = rPrtMtf.FirstAction(); pAct && !mbAborted; pAct = rPrtMtf.NextAction() ) + { + const ULONG nType = pAct->GetType(); + sal_Bool bExecuted = sal_False; + + if( nType == META_COMMENT_ACTION ) + { + // search for special comments ( ..._BEGIN/..._END ) + MetaCommentAction* pComment = (MetaCommentAction*) pAct; + + if( pComment->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL ) + { + pAct = rPrtMtf.NextAction(); + + // if next action is a GradientEx action, execute this and + // skip actions until a XGRAD_SEQ_END comment is found + if( pAct && ( pAct->GetType() == META_GRADIENTEX_ACTION ) ) + { + MetaGradientExAction* pGradientExAction = (MetaGradientExAction*) pAct; + DrawGradientEx( this, pGradientExAction->GetPolyPolygon(), pGradientExAction->GetGradient() ); + + // seek to end of this comment + do + { + pAct = rPrtMtf.NextAction(); + } + while( pAct && + ( ( pAct->GetType() != META_COMMENT_ACTION ) || + ( ( (MetaCommentAction*) pAct )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) != COMPARE_EQUAL ) ) ); + + bExecuted = sal_True; + } + } + else if( pComment->GetComment().CompareIgnoreCaseToAscii( "PRNSPOOL_TRANSPARENTBITMAP_BEGIN" ) == COMPARE_EQUAL ) + { + pAct = rPrtMtf.NextAction(); + + if( pAct && ( pAct->GetType() == META_BMPSCALE_ACTION ) ) + { + // execute action here to avoid DPI processing of bitmap; + pAct->Execute( this ); + +#ifdef VERBOSE_DEBUG + Push(); + SetLineColor(COL_RED); + SetFillColor(); + DrawRect( Rectangle( + static_cast<MetaBmpScaleAction*>(pAct)->GetPoint(), + static_cast<MetaBmpScaleAction*>(pAct)->GetSize()) ); + Pop(); +#endif + + // seek to end of this comment + do + { + pAct = rPrtMtf.NextAction(); + } + while( pAct && + ( ( pAct->GetType() != META_COMMENT_ACTION ) || + ( ( (MetaCommentAction*) pAct )->GetComment().CompareIgnoreCaseToAscii( "PRNSPOOL_TRANSPARENTBITMAP_END" ) != COMPARE_EQUAL ) ) ); + + bExecuted = sal_True; + } + } + } + else if( nType == META_GRADIENT_ACTION ) + { + MetaGradientAction* pGradientAction = (MetaGradientAction*) pAct; + DrawGradientEx( this, pGradientAction->GetRect(), pGradientAction->GetGradient() ); + bExecuted = sal_True; + } + else if( nType == META_BMPSCALE_ACTION ) + { + MetaBmpScaleAction* pBmpScaleAction = (MetaBmpScaleAction*) pAct; + const Bitmap& rBmp = pBmpScaleAction->GetBitmap(); + + DrawBitmap( pBmpScaleAction->GetPoint(), pBmpScaleAction->GetSize(), + GetDownsampledBitmap( pBmpScaleAction->GetSize(), + Point(), rBmp.GetSizePixel(), + rBmp, nMaxBmpDPIX, nMaxBmpDPIY ) ); + + bExecuted = sal_True; + } + else if( nType == META_BMPSCALEPART_ACTION ) + { + MetaBmpScalePartAction* pBmpScalePartAction = (MetaBmpScalePartAction*) pAct; + const Bitmap& rBmp = pBmpScalePartAction->GetBitmap(); + + DrawBitmap( pBmpScalePartAction->GetDestPoint(), pBmpScalePartAction->GetDestSize(), + GetDownsampledBitmap( pBmpScalePartAction->GetDestSize(), + pBmpScalePartAction->GetSrcPoint(), pBmpScalePartAction->GetSrcSize(), + rBmp, nMaxBmpDPIX, nMaxBmpDPIY ) ); + + bExecuted = sal_True; + } + else if( nType == META_BMPEXSCALE_ACTION ) + { + MetaBmpExScaleAction* pBmpExScaleAction = (MetaBmpExScaleAction*) pAct; + const BitmapEx& rBmpEx = pBmpExScaleAction->GetBitmapEx(); + + DrawBitmapEx( pBmpExScaleAction->GetPoint(), pBmpExScaleAction->GetSize(), + GetDownsampledBitmapEx( pBmpExScaleAction->GetSize(), + Point(), rBmpEx.GetSizePixel(), + rBmpEx, nMaxBmpDPIX, nMaxBmpDPIY ) ); + + bExecuted = sal_True; + } + else if( nType == META_BMPEXSCALEPART_ACTION ) + { + MetaBmpExScalePartAction* pBmpExScalePartAction = (MetaBmpExScalePartAction*) pAct; + const BitmapEx& rBmpEx = pBmpExScalePartAction->GetBitmapEx(); + + DrawBitmapEx( pBmpExScalePartAction->GetDestPoint(), pBmpExScalePartAction->GetDestSize(), + GetDownsampledBitmapEx( pBmpExScalePartAction->GetDestSize(), + pBmpExScalePartAction->GetSrcPoint(), pBmpExScalePartAction->GetSrcSize(), + rBmpEx, nMaxBmpDPIX, nMaxBmpDPIY ) ); + + bExecuted = sal_True; + } + else if( nType == META_TRANSPARENT_ACTION ) + { + MetaTransparentAction* pTransAct = static_cast<MetaTransparentAction*>(pAct); + USHORT nTransparency( pTransAct->GetTransparence() ); + + // #i10613# Respect transparency for draw color + if( nTransparency ) + { + Push( PUSH_LINECOLOR|PUSH_FILLCOLOR ); + + // assume white background for alpha blending + Color aLineColor( GetLineColor() ); + aLineColor.SetRed( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetRed()) / 100L ) ); + aLineColor.SetGreen( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetGreen()) / 100L ) ); + aLineColor.SetBlue( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetBlue()) / 100L ) ); + SetLineColor( aLineColor ); + + Color aFillColor( GetFillColor() ); + aFillColor.SetRed( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetRed()) / 100L ) ); + aFillColor.SetGreen( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetGreen()) / 100L ) ); + aFillColor.SetBlue( static_cast<UINT8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetBlue()) / 100L ) ); + SetFillColor( aFillColor ); + } + + DrawPolyPolygon( pTransAct->GetPolyPolygon() ); + + if( nTransparency ) + Pop(); + + bExecuted = sal_True; + } + else if( nType == META_FLOATTRANSPARENT_ACTION ) + { + MetaFloatTransparentAction* pFloatAction = (MetaFloatTransparentAction*) pAct; + GDIMetaFile& rMtf = (GDIMetaFile&) pFloatAction->GetGDIMetaFile(); + MapMode aDrawMap( rMtf.GetPrefMapMode() ); + Point aDestPoint( LogicToPixel( pFloatAction->GetPoint() ) ); + Size aDestSize( LogicToPixel( pFloatAction->GetSize() ) ); + + if( aDestSize.Width() && aDestSize.Height() ) + { + Size aTmpPrefSize( LogicToPixel( rMtf.GetPrefSize(), aDrawMap ) ); + + if( !aTmpPrefSize.Width() ) + aTmpPrefSize.Width() = aDestSize.Width(); + + if( !aTmpPrefSize.Height() ) + aTmpPrefSize.Height() = aDestSize.Height(); + + Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() ); + Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() ); + + aDrawMap.SetScaleX( aScaleX *= aDrawMap.GetScaleX() ); + aDrawMap.SetScaleY( aScaleY *= aDrawMap.GetScaleY() ); + aDrawMap.SetOrigin( PixelToLogic( aDestPoint, aDrawMap ) ); + + Push(); + SetMapMode( aDrawMap ); + ImplPrintMtf( rMtf, nMaxBmpDPIX, nMaxBmpDPIY ); + Pop(); + } + + bExecuted = sal_True; + } + + if( !bExecuted && pAct ) + pAct->Execute( this ); + + if( ! ImplGetSVData()->maGDIData.mbPrinterPullModel ) + Application::Reschedule(); + } +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::PrePrintPage( QueuePage* pPage ) +{ + mnRestoreDrawMode = GetDrawMode(); + mnMaxBmpDPIX = mnDPIX; + mnMaxBmpDPIY = mnDPIY; + + const PrinterOptions& rPrinterOptions = GetPrinterOptions(); + + if( rPrinterOptions.IsReduceBitmaps() ) + { + // calculate maximum resolution for bitmap graphics + if( PRINTER_BITMAP_OPTIMAL == rPrinterOptions.GetReducedBitmapMode() ) + { + mnMaxBmpDPIX = Min( (long) OPTIMAL_BMP_RESOLUTION, mnMaxBmpDPIX ); + mnMaxBmpDPIY = Min( (long) OPTIMAL_BMP_RESOLUTION, mnMaxBmpDPIY ); + } + else if( PRINTER_BITMAP_NORMAL == rPrinterOptions.GetReducedBitmapMode() ) + { + mnMaxBmpDPIX = Min( (long) NORMAL_BMP_RESOLUTION, mnMaxBmpDPIX ); + mnMaxBmpDPIY = Min( (long) NORMAL_BMP_RESOLUTION, mnMaxBmpDPIY ); + } + else + { + mnMaxBmpDPIX = Min( (long) rPrinterOptions.GetReducedBitmapResolution(), mnMaxBmpDPIX ); + mnMaxBmpDPIY = Min( (long) rPrinterOptions.GetReducedBitmapResolution(), mnMaxBmpDPIY ); + } + } + + // convert to greysacles + if( rPrinterOptions.IsConvertToGreyscales() ) + { + SetDrawMode( GetDrawMode() | ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT | + DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) ); + } + + // disable transparency output + if( rPrinterOptions.IsReduceTransparency() && ( PRINTER_TRANSPARENCY_NONE == rPrinterOptions.GetReducedTransparencyMode() ) ) + { + SetDrawMode( GetDrawMode() | DRAWMODE_NOTRANSPARENCY ); + } + + maCurPageMetaFile = GDIMetaFile(); + RemoveTransparenciesFromMetaFile( *pPage->mpMtf, maCurPageMetaFile, mnMaxBmpDPIX, mnMaxBmpDPIY, + rPrinterOptions.IsReduceTransparency(), + rPrinterOptions.GetReducedTransparencyMode() == PRINTER_TRANSPARENCY_AUTO, + rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency() + ); +} + +void ImplQPrinter::PostPrintPage() +{ + SetDrawMode( mnRestoreDrawMode ); +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::PrintPage( unsigned int nPage ) +{ + if( nPage >= maQueue.size() ) + return; + mnCurCopyCount = (mbUserCopy && !mbCollateCopy) ? mnCopyCount : 1; + QueuePage* pActPage = maQueue[nPage]; + PrePrintPage( pActPage ); + if ( pActPage->mpSetup ) + SetJobSetup( *pActPage->mpSetup ); + + StartPage(); + ImplPrintMtf( maCurPageMetaFile, mnMaxBmpDPIX, mnMaxBmpDPIY ); + EndPage(); + + mnCurCopyCount--; + if( mnCurCopyCount == 0 ) + PostPrintPage(); +} + +// ----------------------------------------------------------------------- + +ImplJobSetup* ImplQPrinter::GetPageSetup( unsigned int nPage ) const +{ + return nPage >= maQueue.size() ? NULL : + ( maQueue[nPage]->mpSetup ? maQueue[nPage]->mpSetup->ImplGetData() : NULL ); +} + +// ----------------------------------------------------------------------- +ULONG ImplQPrinter::GetPrintPageCount() const +{ + ULONG nPageCount = maQueue.size() * ((mbUserCopy && !mbCollateCopy) ? mnCopyCount : 1); + return nPageCount; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ImplQPrinter, ImplPrintHdl, Timer*, EMPTYARG ) +{ + // Ist Drucken abgebrochen wurden? + if( !IsPrinting() || ( mpParent->IsJobActive() && ( maQueue.size() < (ULONG)mpParent->GetPageQueueSize() ) ) ) + return 0; + + // Druck-Job zuende? + QueuePage* pActPage = maQueue.front(); + maQueue.erase( maQueue.begin() ); + + + vcl::DeletionListener aDel( this ); + if ( pActPage->mbEndJob ) + { + maTimer.Stop(); + delete pActPage; + if( ! EndJob() ) + mpParent->Error(); + if( ! aDel.isDeleted() ) + mpParent->ImplEndPrint(); + } + else + { + mbDestroyAllowed = FALSE; + + PrePrintPage( pActPage ); + + USHORT nCopyCount = 1; + if( mbUserCopy && !mbCollateCopy ) + nCopyCount = mnCopyCount; + + for ( USHORT i = 0; i < nCopyCount; i++ ) + { + if ( pActPage->mpSetup ) + { + SetJobSetup( *pActPage->mpSetup ); + if ( mbAborted ) + break; + } + + StartPage(); + + if ( mbAborted ) + break; + + ImplPrintMtf( maCurPageMetaFile, mnMaxBmpDPIX, mnMaxBmpDPIY ); + + if( !mbAborted ) + EndPage(); + else + break; + } + + PostPrintPage(); + + delete pActPage; + mbDestroyAllowed = TRUE; + + if( mbDestroyed ) + Destroy(); + } + + return 0; +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::StartQueuePrint() +{ + if( ! ImplGetSVData()->maGDIData.mbPrinterPullModel ) + { + maTimer.SetTimeout( 50 ); + maTimer.SetTimeoutHdl( LINK( this, ImplQPrinter, ImplPrintHdl ) ); + maTimer.Start(); + } +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::EndQueuePrint() +{ + if( ImplGetSVData()->maGDIData.mbPrinterPullModel ) + { + DBG_ASSERT( mpPrinter, "no SalPrinter in ImplQPrinter" ); + if( mpPrinter ) + { + mpPrinter->StartJob( mbPrintFile ? &maPrintFile : NULL, + Application::GetDisplayName(), + maJobSetup.ImplGetConstData(), + this ); + EndJob(); + mpParent->ImplEndPrint(); + } + } + else + { + QueuePage* pQueuePage = new QueuePage; + pQueuePage->mbEndJob = TRUE; + maQueue.push_back( pQueuePage ); + } +} + +// ----------------------------------------------------------------------- + +bool ImplQPrinter::GetPaperRanges( std::vector< ULONG >& o_rRanges, bool i_bIncludeOrientationChanges ) const +{ + bool bRet = false; + + if( ImplGetSVData()->maGDIData.mbPrinterPullModel ) + { + bRet = true; + o_rRanges.clear(); + + if( ! maQueue.empty() ) + { + ULONG nCurPage = 0; + + // get first job data + const ImplJobSetup* pLastFormat = NULL; + if( maQueue.front()->mpSetup ) + pLastFormat = maQueue.front()->mpSetup->ImplGetConstData(); + + // begin first range + o_rRanges.push_back( 0 ); + for( std::vector< QueuePage* >::const_iterator it = maQueue.begin(); + it != maQueue.end(); ++it, ++nCurPage ) + { + const ImplJobSetup* pNewSetup = (*it)->mpSetup ? (*it)->mpSetup->ImplGetConstData() : NULL; + if( pNewSetup && pNewSetup != pLastFormat ) + { + bool bChange = false; + if( pLastFormat == NULL ) + { + bChange = true; + } + else if( ! i_bIncludeOrientationChanges && + pNewSetup->meOrientation != pLastFormat->meOrientation ) + { + bChange = true; + } + else if( pNewSetup->mePaperFormat != pLastFormat->mePaperFormat || + ( pNewSetup->mePaperFormat == PAPER_USER && + ( pNewSetup->mnPaperWidth != pLastFormat->mnPaperWidth || + pNewSetup->mnPaperHeight != pLastFormat->mnPaperHeight ) ) ) + { + bChange = true; + } + else if( pNewSetup->mnPaperBin != pLastFormat->mnPaperBin ) + { + bChange = true; + } + if( bChange ) + { + o_rRanges.push_back( nCurPage ); + pLastFormat = pNewSetup; + } + } + } + + o_rRanges.push_back( nCurPage ); + } + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::AbortQueuePrint() +{ + maTimer.Stop(); + mbAborted = TRUE; + AbortJob(); +} + +// ----------------------------------------------------------------------- + +void ImplQPrinter::AddQueuePage( GDIMetaFile* pPage, USHORT nPage, BOOL bNewJobSetup ) +{ + QueuePage* pQueuePage = new QueuePage; + pQueuePage->mpMtf = pPage; + pQueuePage->mnPage = nPage; + pQueuePage->mbEndJob = FALSE; + // ensure that the first page has a valid setup, this is needed + // in GetPaperRanges (used in pullmodel) + // caution: this depends on mnCurPage in Printer being + // 0: not printing 1: after StartJob, 2 after first EndPage, 3+ at following EndPage calls + if ( bNewJobSetup || (nPage == 2 && ImplGetSVData()->maGDIData.mbPrinterPullModel) ) + pQueuePage->mpSetup = new JobSetup( mpParent->GetJobSetup() ); + maQueue.push_back( pQueuePage ); +} |