diff options
author | Vladimir Glazounov <vg@openoffice.org> | 2008-10-01 13:31:44 +0000 |
---|---|---|
committer | Vladimir Glazounov <vg@openoffice.org> | 2008-10-01 13:31:44 +0000 |
commit | 46a63a2af38e694327c5308168f499a549fb724e (patch) | |
tree | 6e80cfea121ed9231141a56153e9208f553863cb /vcl/source/gdi/print2.cxx | |
parent | 248539e2fa8ac0f5271a83f26fe71d0dcc4a5a67 (diff) |
CWS-TOOLING: integrate CWS vcl92
Diffstat (limited to 'vcl/source/gdi/print2.cxx')
-rw-r--r-- | vcl/source/gdi/print2.cxx | 577 |
1 files changed, 409 insertions, 168 deletions
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx index e0764595583d..685f68fe7af3 100644 --- a/vcl/source/gdi/print2.cxx +++ b/vcl/source/gdi/print2.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: print2.cxx,v $ - * $Revision: 1.24 $ + * $Revision: 1.24.86.3 $ * * This file is part of OpenOffice.org. * @@ -38,6 +38,8 @@ #include <utility> #include <list> #include <vector> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> #include <tools/debug.hxx> #include <vcl/virdev.hxx> #include <vcl/metaact.hxx> @@ -49,6 +51,8 @@ #include <vcl/sallayout.hxx> #include <vcl/bmpacc.hxx> +#include "pdfwriter_impl.hxx" + // ----------- // - Defines - // ----------- @@ -56,11 +60,43 @@ #define MAX_TILE_WIDTH 1024 #define MAX_TILE_HEIGHT 1024 +// --------- +// - Types - +// --------- + +typedef ::std::pair< MetaAction*, int > Component; // MetaAction plus index in metafile + +typedef ::std::list< Component > ComponentList; + +// List of (intersecting) actions, plus overall bounds +struct ConnectedComponents +{ + ConnectedComponents() : + aComponentList(), + aBounds(), + aBgColor(COL_WHITE), + bIsSpecial(false), + bIsFullyTransparent(false) + {} + + ComponentList aComponentList; + Rectangle aBounds; + Color aBgColor; + bool bIsSpecial; + bool bIsFullyTransparent; +}; + +typedef ::std::list< ConnectedComponents > ConnectedComponentsList; + + // ----------- // - Printer - // ----------- -// #i10613# Extracted from Printer::GetPreparedMetaFile +/** #i10613# Extracted from Printer::GetPreparedMetaFile. Returns true + if given action requires special handling (usually because of + transparency) +*/ static bool ImplIsActionSpecial( const MetaAction& rAct ) { switch( rAct.GetType() ) @@ -72,99 +108,181 @@ static bool ImplIsActionSpecial( const MetaAction& rAct ) return true; case META_BMPEX_ACTION: - return static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx().IsAlpha() != 0; + return static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx().IsTransparent(); case META_BMPEXSCALE_ACTION: - return static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx().IsAlpha() != 0; + return static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx().IsTransparent(); case META_BMPEXSCALEPART_ACTION: - return static_cast<const MetaBmpExScalePartAction&>(rAct).GetBitmapEx().IsAlpha() != 0; + return static_cast<const MetaBmpExScalePartAction&>(rAct).GetBitmapEx().IsTransparent(); default: return false; } } -// #107169# Check whether given metaaction is a masked bitmap -static bool ImplIsActionMaskedBitmap( const MetaAction& rAct ) +/** Check whether rCurrRect rectangle fully covers io_rPrevRect - if + yes, return true and update o_rBgColor + */ +static bool checkRect( Rectangle& io_rPrevRect, + Color& o_rBgColor, + const Rectangle& rCurrRect, + OutputDevice& rMapModeVDev ) { - switch( rAct.GetType() ) - { - case META_BMPEX_ACTION: - return static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx().IsAlpha() == 0; - - case META_BMPEXSCALE_ACTION: - return static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx().IsAlpha() == 0; + // shape needs to fully cover previous content, and have uniform + // color + const bool bRet( + rMapModeVDev.LogicToPixel(rCurrRect).IsInside(io_rPrevRect) && + rMapModeVDev.IsFillColor() ); - case META_BMPEXSCALEPART_ACTION: - return static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx().IsAlpha() == 0; - - default: - return false; + if( bRet ) + { + io_rPrevRect = rCurrRect; + o_rBgColor = rMapModeVDev.GetFillColor(); } + + return bRet; } -// #107169# Convert BitmapEx with mask to Bitmap with white background at masked-out places -static Bitmap ImplConvertBmpEx2Bmp( const MetaAction& rAct ) +/** #107169# Convert BitmapEx to Bitmap with appropriately blended + color. Convert MetaTransparentAction to plain polygon, + appropriately colored + + @param o_rMtf + Add converted actions to this metafile +*/ +static void ImplConvertTransparentAction( GDIMetaFile& o_rMtf, + const MetaAction& rAct, + const OutputDevice& rStateOutDev, + Color aBgColor ) { - BitmapEx aBmpEx; - - switch( rAct.GetType() ) + if( rAct.GetType() == META_TRANSPARENT_ACTION ) { - case META_BMPEX_ACTION: - aBmpEx = static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx(); - break; + const MetaTransparentAction* pTransAct = static_cast<const MetaTransparentAction*>(&rAct); + USHORT nTransparency( pTransAct->GetTransparence() ); - case META_BMPEXSCALE_ACTION: - aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx(); - break; + // #i10613# Respect transparency for draw color + if( nTransparency ) + { + o_rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR|PUSH_FILLCOLOR ) ); + + // assume white background for alpha blending + Color aLineColor( rStateOutDev.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 ) ); + o_rMtf.AddAction( new MetaLineColorAction(aLineColor, TRUE) ); + + Color aFillColor( rStateOutDev.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 ) ); + o_rMtf.AddAction( new MetaFillColorAction(aFillColor, TRUE) ); + } - case META_BMPEXSCALEPART_ACTION: - aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx(); - break; + o_rMtf.AddAction( new MetaPolyPolygonAction(pTransAct->GetPolyPolygon()) ); - default: - DBG_ERROR("Printer::GetPreparedMetafile impossible state reached"); - break; + if( nTransparency ) + o_rMtf.AddAction( new MetaPopAction() ); } + else + { + BitmapEx aBmpEx; - Bitmap aBmp( aBmpEx.GetBitmap() ); - BitmapReadAccess* pRA = aBmp.AcquireReadAccess(); + switch( rAct.GetType() ) + { + case META_BMPEX_ACTION: + aBmpEx = static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx(); + break; - if( !pRA ) - return aBmp; // what else should I do? + case META_BMPEXSCALE_ACTION: + aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx(); + break; - Color aWhite( COL_WHITE ); + case META_BMPEXSCALEPART_ACTION: + aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx(); + break; - if( pRA->HasPalette() ) - aWhite = pRA->GetBestPaletteColor( Color( COL_WHITE ) ).operator Color(); + case META_TRANSPARENT_ACTION: - aBmp.ReleaseAccess(pRA); + default: + DBG_ERROR("Printer::GetPreparedMetafile impossible state reached"); + break; + } - // did we get true white? - if( aWhite.GetColorError( Color( COL_WHITE ) ) ) - { - // no, create truecolor bitmap, then - aBmp.Convert( BMP_CONVERSION_24BIT ); + Bitmap aBmp( aBmpEx.GetBitmap() ); + if( !aBmpEx.IsAlpha() ) + { + // blend with mask + BitmapReadAccess* pRA = aBmp.AcquireReadAccess(); - // fill masked out areas white - aBmp.Replace( aBmpEx.GetMask(), COL_WHITE ); - } - else - { - // fill masked out areas white - aBmp.Replace( aBmpEx.GetMask(), aWhite ); - } + if( !pRA ) + return; // what else should I do? - return aBmp; + Color aActualColor( aBgColor ); + + if( pRA->HasPalette() ) + aActualColor = pRA->GetBestPaletteColor( aBgColor ).operator Color(); + + aBmp.ReleaseAccess(pRA); + + // did we get true white? + if( aActualColor.GetColorError( aBgColor ) ) + { + // no, create truecolor bitmap, then + aBmp.Convert( BMP_CONVERSION_24BIT ); + + // fill masked out areas white + aBmp.Replace( aBmpEx.GetMask(), aBgColor ); + } + else + { + // fill masked out areas white + aBmp.Replace( aBmpEx.GetMask(), aActualColor ); + } + } + else + { + // blend with alpha channel + aBmp.Convert( BMP_CONVERSION_24BIT ); + aBmp.Blend(aBmpEx.GetAlpha(),aBgColor); + } + + // add corresponding action + switch( rAct.GetType() ) + { + case META_BMPEX_ACTION: + o_rMtf.AddAction( new MetaBmpAction( + static_cast<const MetaBmpExAction&>(rAct).GetPoint(), + aBmp )); + break; + case META_BMPEXSCALE_ACTION: + o_rMtf.AddAction( new MetaBmpScaleAction( + static_cast<const MetaBmpExScaleAction&>(rAct).GetPoint(), + static_cast<const MetaBmpExScaleAction&>(rAct).GetSize(), + aBmp )); + break; + case META_BMPEXSCALEPART_ACTION: + o_rMtf.AddAction( new MetaBmpScalePartAction( + static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestPoint(), + static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestSize(), + static_cast<const MetaBmpExScalePartAction&>(rAct).GetSrcPoint(), + static_cast<const MetaBmpExScalePartAction&>(rAct).GetSrcSize(), + aBmp )); + break; + default: + DBG_ERROR("Unexpected case"); + break; + } + } } // #i10613# Extracted from ImplCheckRect::ImplCreate // Returns true, if given action creates visible (i.e. non-transparent) output static bool ImplIsNotTransparent( const MetaAction& rAct, const OutputDevice& rOut ) { - const bool bLineTransparency( rOut.GetLineColor().GetTransparency() == 255 ); - const bool bFillTransparency( rOut.GetFillColor().GetTransparency() == 255 ); + const bool bLineTransparency( rOut.IsLineColor() ? rOut.GetLineColor().GetTransparency() == 255 : true ); + const bool bFillTransparency( rOut.IsFillColor() ? rOut.GetFillColor().GetTransparency() == 255 : true ); bool bRet( false ); switch( rAct.GetType() ) @@ -526,46 +644,18 @@ static bool ImplIsActionHandlingTransparency( const MetaAction& rAct ) } } -// predicate functor for checking whether given element is fully transparent -class Impl_IsTransparent : public ::std::unary_function< ::std::pair< const MetaAction*, int >, bool > -{ -public: - Impl_IsTransparent( const OutputDevice& rOut ) : mrOut(rOut) {} - bool operator()( ::std::pair< const MetaAction*, int > rElem ) - { - return !ImplIsNotTransparent( *rElem.first, mrOut ); - } - -private: - const OutputDevice& mrOut; -}; - -typedef ::std::pair< const MetaAction*, int > Component; // MetaAction plus index in metafile - -// List of (intersecting) actions, plus overall bounds -struct ConnectedComponents -{ - ::std::list< Component > aComponentList; - Rectangle aBounds; - bool bIsSpecial; - bool bIsFullyTransparent; -}; - -typedef ::std::list< ConnectedComponents > ConnectedComponentsList; - // remove comment to enable highlighting of generated output - -void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutMtf, - long nMaxBmpDPIX, long nMaxBmpDPIY ) +bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutMtf, + long nMaxBmpDPIX, long nMaxBmpDPIY, + bool bReduceTransparency, bool bTransparencyAutoMode, + bool bDownsampleBitmaps ) { - const PrinterOptions& rPrinterOptions = GetPrinterOptions(); MetaAction* pCurrAct; bool bTransparent( false ); rOutMtf.Clear(); - if( !rPrinterOptions.IsReduceTransparency() || - ( PRINTER_TRANSPARENCY_AUTO == rPrinterOptions.GetReducedTransparencyMode() ) ) + if( ! bReduceTransparency || bTransparencyAutoMode ) { // watch for transparent drawing actions for( pCurrAct = ( (GDIMetaFile&) rInMtf ).FirstAction(); @@ -581,8 +671,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // of uniform opacity): if a masked bitmap is printed over // empty background, we convert to a plain bitmap with // white background. - if( ImplIsActionMaskedBitmap( *pCurrAct ) || - ImplIsActionSpecial( *pCurrAct ) ) + if( ImplIsActionSpecial( *pCurrAct ) ) { bTransparent = true; } @@ -624,8 +713,14 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // algorithm was designed by AF. // - ConnectedComponentsList aCCList; // list containing distinct sets of connected components as elements. - int nActionNum; + // + // STAGE 1: Detect background + // ========================== + // + + // Receives uniform background content, and is _not_ merged + // nor checked for intersection against other aCCList elements + ConnectedComponents aBackgroundComponent; // create an OutputDevice to record mapmode changes and the like VirtualDevice aMapModeVDev; @@ -633,21 +728,140 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM aMapModeVDev.mnDPIY = mnDPIY; aMapModeVDev.EnableOutput(FALSE); + int nLastBgAction, nActionNum; + + // weed out page-filling background objects (if they are + // uniformly coloured). Keeping them outside the other + // connected components often prevents whole-page bitmap + // generation. + bool bStillBackground=true; // true until first non-bg action + nActionNum=0; nLastBgAction=-1; + pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(); + while( pCurrAct && bStillBackground ) + { + switch( pCurrAct->GetType() ) + { + case META_RECT_ACTION: + { + if( !checkRect( + aBackgroundComponent.aBounds, + aBackgroundComponent.aBgColor, + static_cast<const MetaRectAction*>(pCurrAct)->GetRect(), + aMapModeVDev) ) + bStillBackground=false; // incomplete occlusion of background + else + nLastBgAction=nActionNum; // this _is_ background + break; + } + case META_POLYGON_ACTION: + { + const Polygon aPoly( + static_cast<const MetaPolygonAction*>(pCurrAct)->GetPolygon()); + if( !basegfx::tools::isRectangle( + aPoly.getB2DPolygon()) || + !checkRect( + aBackgroundComponent.aBounds, + aBackgroundComponent.aBgColor, + aPoly.GetBoundRect(), + aMapModeVDev) ) + bStillBackground=false; // incomplete occlusion of background + else + nLastBgAction=nActionNum; // this _is_ background + break; + } + case META_POLYPOLYGON_ACTION: + { + const PolyPolygon aPoly( + static_cast<const MetaPolyPolygonAction*>(pCurrAct)->GetPolyPolygon()); + if( aPoly.Count() != 1 || + !basegfx::tools::isRectangle( + aPoly[0].getB2DPolygon()) || + !checkRect( + aBackgroundComponent.aBounds, + aBackgroundComponent.aBgColor, + aPoly.GetBoundRect(), + aMapModeVDev) ) + bStillBackground=false; // incomplete occlusion of background + else + nLastBgAction=nActionNum; // this _is_ background + break; + } + case META_WALLPAPER_ACTION: + { + if( !checkRect( + aBackgroundComponent.aBounds, + aBackgroundComponent.aBgColor, + static_cast<const MetaWallpaperAction*>(pCurrAct)->GetRect(), + aMapModeVDev) ) + bStillBackground=false; // incomplete occlusion of background + else + nLastBgAction=nActionNum; // this _is_ background + break; + } + default: + { + if( ImplIsNotTransparent( *pCurrAct, + aMapModeVDev ) ) + bStillBackground=false; // non-transparent action, possibly + // not uniform + else + // extend current bounds (next uniform action + // needs to fully cover this area) + aBackgroundComponent.aBounds.Union( + ImplCalcActionBounds(*pCurrAct, aMapModeVDev) ); + break; + } + } + + // execute action to get correct MapModes etc. + pCurrAct->Execute( &aMapModeVDev ); + + pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(); + ++nActionNum; + } + + ConnectedComponentsList aCCList; // list containing distinct sets of connected components as elements. + + // create an OutputDevice to record mapmode changes and the like + VirtualDevice aMapModeVDev2; + aMapModeVDev2.mnDPIX = mnDPIX; + aMapModeVDev2.mnDPIY = mnDPIY; + aMapModeVDev2.EnableOutput(FALSE); + + // fast-forward until one after the last background action + // (need to reconstruct map mode vdev state) + nActionNum=0; + pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(); + while( pCurrAct && nActionNum<=nLastBgAction ) + { + // up to and including last ink-generating background + // action go to background component + aBackgroundComponent.aComponentList.push_back( + ::std::make_pair( + pCurrAct, nActionNum) ); + + // execute action to get correct MapModes etc. + pCurrAct->Execute( &aMapModeVDev2 ); + pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(); + ++nActionNum; + } + // - // STAGE 1: Generate connected components list + // STAGE 2: Generate connected components list // =========================================== // - // iterate over all actions - for( pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(), nActionNum=0; + // iterate over all actions (start where background action + // search left off) + for( ; pCurrAct; pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(), ++nActionNum ) { // execute action to get correct MapModes etc. - pCurrAct->Execute( &aMapModeVDev ); + pCurrAct->Execute( &aMapModeVDev2 ); // cache bounds of current action - const Rectangle aBBCurrAct( ImplCalcActionBounds(*pCurrAct, aMapModeVDev) ); + const Rectangle aBBCurrAct( ImplCalcActionBounds(*pCurrAct, aMapModeVDev2) ); // accumulate collected bounds here, initialize with current action Rectangle aTotalBounds( aBBCurrAct ); // thus, @@ -661,7 +875,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM ConnectedComponents aTotalComponents; // - // STAGE 1.1: Search for intersecting cc entries + // STAGE 2.1: Search for intersecting cc entries // ============================================= // @@ -669,18 +883,33 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // aCCList member. Thus, we can safe us the check. // Furthermore, this ensures that non-output-generating // actions get their own aCCList entry, which is necessary - // when copying them to the output metafile (see stage 3 + // when copying them to the output metafile (see stage 4 // below). // #107169# Wholly transparent objects need // not be considered for connected components, // too. Just put each of them into a separate // component. - aTotalComponents.bIsFullyTransparent = !ImplIsNotTransparent(*pCurrAct, aMapModeVDev); + aTotalComponents.bIsFullyTransparent = !ImplIsNotTransparent(*pCurrAct, aMapModeVDev2); if( !aBBCurrAct.IsEmpty() && !aTotalComponents.bIsFullyTransparent ) { + if( !aBackgroundComponent.aComponentList.empty() && + !aBackgroundComponent.aBounds.IsInside(aTotalBounds) ) + { + // it seems the background is not large enough. to + // be on the safe side, combine with this component. + aTotalBounds.Union( aBackgroundComponent.aBounds ); + + // extract all aCurr actions to aTotalComponents + aTotalComponents.aComponentList.splice( aTotalComponents.aComponentList.end(), + aBackgroundComponent.aComponentList ); + + if( aBackgroundComponent.bIsSpecial ) + bTreatSpecial = true; + } + ConnectedComponentsList::iterator aCurrCC; const ConnectedComponentsList::iterator aLastCC( aCCList.end() ); bool bSomeComponentsChanged; @@ -741,7 +970,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM } // - // STAGE 1.2: Determine special state for cc element + // STAGE 2.2: Determine special state for cc element // ================================================= // @@ -790,7 +1019,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // check whether we're on white background if( aTotalComponents.aComponentList.empty() ) { - // nothing between pCurrAct and empty page + // nothing between pCurrAct and page // background -> don't be special aTotalComponents.bIsSpecial = false; } @@ -812,14 +1041,15 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // - // STAGE 1.3: Add newly generated CC list element + // STAGE 2.3: Add newly generated CC list element // ============================================== // // set new bounds and add action to list aTotalComponents.aBounds = aTotalBounds; - aTotalComponents.aComponentList.push_back( ::std::make_pair( - const_cast<const MetaAction*>(pCurrAct), nActionNum) ); + aTotalComponents.aComponentList.push_back( + ::std::make_pair( + pCurrAct, nActionNum) ); // add aTotalComponents as a new entry to aCCList aCCList.push_back( aTotalComponents ); @@ -851,22 +1081,47 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM const ConnectedComponentsList::iterator aLast( aCCList.end() ); for( ; aCurr != aLast; ++aCurr ) { - ::std::list< Component >::iterator aCurrAct( aCurr->aComponentList.begin() ); - const ::std::list< Component >::iterator aLastAct( aCurr->aComponentList.end() ); - for( ; aCurrAct != aLastAct; ++aCurrAct ) + ComponentList::iterator aCurrentAction( aCurr->aComponentList.begin() ); + const ComponentList::iterator aLastAction( aCurr->aComponentList.end() ); + for( ; aCurrentAction != aLastAction; ++aCurrentAction ) { // set pointer to aCCList element for corresponding index - aCCList_MemberMap[ aCurrAct->second ] = &(*aCurr); + aCCList_MemberMap[ aCurrentAction->second ] = &(*aCurr); } } // - // STAGE 2: Generate banded bitmaps for special regions + // STAGE 3.1: Output background mtf actions (if there are any) + // =========================================================== + // + + ComponentList::iterator aCurrAct( aBackgroundComponent.aComponentList.begin() ); + const ComponentList::iterator aLastAct( aBackgroundComponent.aComponentList.end() ); + for( ; aCurrAct != aLastAct; ++aCurrAct ) + { + // simply add this action (above, we inserted the actions + // starting at index 0 up to and including nLastBgAction) + rOutMtf.AddAction( ( aCurrAct->first->Duplicate(), aCurrAct->first ) ); + } + + + // + // STAGE 3.2: Generate banded bitmaps for special regions // ==================================================== // Point aTmpPoint; - const Rectangle aOutputRect( aTmpPoint, GetOutputSizePixel() ); + Size aTmpSize( GetOutputSizePixel() ); + if( mpPDFWriter ) + { + aTmpSize = mpPDFWriter->getCurPageSize(); + aTmpSize = LogicToPixel( aTmpSize, MapMode( MAP_POINT ) ); + + // also add error code to PDFWriter + mpPDFWriter->insertError( vcl::PDFWriter::Warning_Transparency_Converted ); + } + const Rectangle aOutputRect( aTmpPoint, aTmpSize ); + bool bTiling = dynamic_cast<Printer*>(this) != NULL; // iterate over all aCCList members and generate bitmaps for the special ones for( aCurr = aCCList.begin(); aCurr != aLast; ++aCurr ) @@ -880,9 +1135,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM const double fOutArea( (double) aOutputRect.GetWidth() * aOutputRect.GetHeight() ); // check if output doesn't exceed given size - if( rPrinterOptions.IsReduceTransparency() && - ( PRINTER_TRANSPARENCY_AUTO == rPrinterOptions.GetReducedTransparencyMode() ) && - ( fBmpArea > ( 0.25 * fOutArea ) ) ) + if( bReduceTransparency && bTransparencyAutoMode && ( fBmpArea > ( 0.25 * fOutArea ) ) ) { // output normally. Therefore, we simply clear the // special attribute, as everything non-special is @@ -910,7 +1163,7 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM while( aDstPtPix.Y() <= aBoundRect.Bottom() ) { aDstPtPix.X() = aBoundRect.Left(); - aDstSzPix = Size( MAX_TILE_WIDTH, MAX_TILE_HEIGHT ); + aDstSzPix = bTiling ? Size( MAX_TILE_WIDTH, MAX_TILE_HEIGHT ) : aBoundRect.GetSize(); if( ( aDstPtPix.Y() + aDstSzPix.Height() - 1L ) > aBoundRect.Bottom() ) aDstSzPix.Height() = aBoundRect.Bottom() - aDstPtPix.Y() + 1L; @@ -964,7 +1217,11 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM else if( META_GRADIENT_ACTION == nType ) { MetaGradientAction* pGradientAction = static_cast<MetaGradientAction*>(pCurrAct); - DrawGradientEx( &aPaintVDev, pGradientAction->GetRect(), pGradientAction->GetGradient() ); + Printer* pPrinter = dynamic_cast< Printer* >(this); + if( pPrinter ) + pPrinter->DrawGradientEx( &aPaintVDev, pGradientAction->GetRect(), pGradientAction->GetGradient() ); + else + DrawGradient( pGradientAction->GetRect(), pGradientAction->GetGradient() ); } else { @@ -981,11 +1238,11 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM Bitmap aBandBmp( aPaintVDev.GetBitmap( Point(), aDstSzPix ) ); // scale down bitmap, if requested - if( rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency() ) + if( bDownsampleBitmaps ) { - aBandBmp = GetPreparedBitmap( aDstSzPix, - Point(), aBandBmp.GetSizePixel(), - aBandBmp, nMaxBmpDPIX, nMaxBmpDPIY ); + aBandBmp = GetDownsampledBitmap( aDstSzPix, + Point(), aBandBmp.GetSizePixel(), + aBandBmp, nMaxBmpDPIX, nMaxBmpDPIY ); } rOutMtf.AddAction( new MetaCommentAction( "PRNSPOOL_TRANSPARENTBITMAP_BEGIN" ) ); @@ -1013,10 +1270,17 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM } // - // STAGE 3: Copy actions to output metafile + // STAGE 4: Copy actions to output metafile // ======================================== // + // create an OutputDevice to record color settings, mapmode + // changes and the like + VirtualDevice aMapModeVDev3; + aMapModeVDev3.mnDPIX = mnDPIX; + aMapModeVDev3.mnDPIY = mnDPIY; + aMapModeVDev3.EnableOutput(FALSE); + // iterate over all actions and duplicate the ones not in a // special aCCList member into rOutMtf for( pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(), nActionNum=0; @@ -1027,70 +1291,47 @@ void Printer::GetPreparedMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutM // NOTE: This relies on the fact that map-mode or draw // mode changing actions are solitary aCCList elements and - // have empty bounding boxes, see comment on stage 1.1 + // have empty bounding boxes, see comment on stage 2.1 // above if( pCurrAssociatedComponent && (pCurrAssociatedComponent->aBounds.IsEmpty() || !pCurrAssociatedComponent->bIsSpecial) ) { - // #107169# Treat masked bitmaps special, if they are - // the first (or sole) action in their bounds + // #107169# Treat transparent bitmaps special, if they + // are the first (or sole) action in their bounds // list. Note that we previously ensured that no // fully-transparent objects are before us here. - if( ImplIsActionMaskedBitmap( *pCurrAct ) && + if( ImplIsActionHandlingTransparency( *pCurrAct ) && pCurrAssociatedComponent->aComponentList.begin()->first == pCurrAct ) { - // convert to plain Bitmap, where masked-out parts are white - Bitmap aBmp( ImplConvertBmpEx2Bmp(*pCurrAct) ); - - // add corresponding action - switch( pCurrAct->GetType() ) - { - case META_BMPEX_ACTION: - rOutMtf.AddAction( new MetaBmpExAction( - static_cast<const MetaBmpExAction*>(pCurrAct)->GetPoint(), - aBmp ) ); - break; - - case META_BMPEXSCALE_ACTION: - rOutMtf.AddAction( new MetaBmpExScaleAction( - static_cast<const MetaBmpExScaleAction*>(pCurrAct)->GetPoint(), - static_cast<const MetaBmpExScaleAction*>(pCurrAct)->GetSize(), - aBmp ) ); - break; - - case META_BMPEXSCALEPART_ACTION: - rOutMtf.AddAction( new MetaBmpExScalePartAction( - static_cast<const MetaBmpExScalePartAction*>(pCurrAct)->GetDestPoint(), - static_cast<const MetaBmpExScalePartAction*>(pCurrAct)->GetDestSize(), - static_cast<const MetaBmpExScalePartAction*>(pCurrAct)->GetSrcPoint(), - static_cast<const MetaBmpExScalePartAction*>(pCurrAct)->GetSrcSize(), - aBmp ) ); - break; - - default: - DBG_ERROR("Printer::GetPreparedMetafile impossible state reached"); - break; - } + // convert actions, where masked-out parts are of + // given background color + ImplConvertTransparentAction(rOutMtf, + *pCurrAct, + aMapModeVDev3, + aBackgroundComponent.aBgColor); } else { // simply add this action rOutMtf.AddAction( ( pCurrAct->Duplicate(), pCurrAct ) ); } + + pCurrAct->Execute(&aMapModeVDev3); } } rOutMtf.SetPrefMapMode( rInMtf.GetPrefMapMode() ); rOutMtf.SetPrefSize( rInMtf.GetPrefSize() ); } + return bTransparent; } // ----------------------------------------------------------------------------- -Bitmap Printer::GetPreparedBitmap( const Size& rDstSz, - const Point& rSrcPt, const Size& rSrcSz, - const Bitmap& rBmp, long nMaxBmpDPIX, long nMaxBmpDPIY ) +Bitmap OutputDevice::GetDownsampledBitmap( const Size& rDstSz, + const Point& rSrcPt, const Size& rSrcSz, + const Bitmap& rBmp, long nMaxBmpDPIX, long nMaxBmpDPIY ) { Bitmap aBmp( rBmp ); @@ -1157,9 +1398,9 @@ Bitmap Printer::GetPreparedBitmap( const Size& rDstSz, // ----------------------------------------------------------------------------- -BitmapEx Printer::GetPreparedBitmapEx( const Size& rDstSz, - const Point& rSrcPt, const Size& rSrcSz, - const BitmapEx& rBmpEx, long nMaxBmpDPIX, long nMaxBmpDPIY ) +BitmapEx OutputDevice::GetDownsampledBitmapEx( const Size& rDstSz, + const Point& rSrcPt, const Size& rSrcSz, + const BitmapEx& rBmpEx, long nMaxBmpDPIX, long nMaxBmpDPIY ) { BitmapEx aBmpEx( rBmpEx ); |