diff options
author | Oliver Bolte <obo@openoffice.org> | 2005-04-18 08:59:07 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2005-04-18 08:59:07 +0000 |
commit | 17ac8d1cbd97c502f8b8aac77d787b8e09e8ff46 (patch) | |
tree | 4626fd1caa205bcb6fe0964995402f327ba9a68a /cppcanvas/source/mtfrenderer/implrenderer.cxx | |
parent | 277bc8faffc7c42e0109b07f79f70904a449f83b (diff) |
INTEGRATION: CWS presfixes03 (1.8.2); FILE MERGED
2005/04/07 10:29:45 thb 1.8.2.3: #i36190# Fixed gross error: refactored code did not change local variables, but method-internals only
2005/04/03 19:21:16 thb 1.8.2.2: #i36190# Removed warning (inconsistend method return behaviour); fixed gcc build breakage (temporary does not work as template argument deducible type
2005/04/01 16:09:43 thb 1.8.2.1: #i36190#, #i39245# Changed uno::Sequence::operator[] for nonconst sequences to use naked ptr; added support for true bezier polygons (and removed subdivision, where it was added because of that canvas deficiency); overhauled mtf renderer to provide faithful bounds also for subsetted meta files
Diffstat (limited to 'cppcanvas/source/mtfrenderer/implrenderer.cxx')
-rw-r--r-- | cppcanvas/source/mtfrenderer/implrenderer.cxx | 446 |
1 files changed, 286 insertions, 160 deletions
diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index 94e285794ff9..ce07f266c628 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -2,9 +2,9 @@ * * $RCSfile: implrenderer.cxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: rt $ $Date: 2005-03-30 08:27:39 $ + * last change: $Author: obo $ $Date: 2005-04-18 09:59:07 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -254,6 +254,7 @@ namespace 2*rLineInfo.GetDotCount() ); o_rStrokeAttributes.DashArray.realloc( nNumArryEntries ); + double* pDashArray = o_rStrokeAttributes.DashArray.getArray(); // iteratively fill dash array, first with dashs, then @@ -264,13 +265,13 @@ namespace for( sal_Int32 i=0; i<rLineInfo.GetDashCount(); ++i ) { - o_rStrokeAttributes.DashArray[nCurrEntry++] = nDashLen; - o_rStrokeAttributes.DashArray[nCurrEntry++] = nDistance; + pDashArray[nCurrEntry++] = nDashLen; + pDashArray[nCurrEntry++] = nDistance; } for( sal_Int32 i=0; i<rLineInfo.GetDotCount(); ++i ) { - o_rStrokeAttributes.DashArray[nCurrEntry++] = nDotLen; - o_rStrokeAttributes.DashArray[nCurrEntry++] = nDistance; + pDashArray[nCurrEntry++] = nDotLen; + pDashArray[nCurrEntry++] = nDistance; } } } @@ -414,7 +415,6 @@ namespace rStates.pop_back(); } } - } @@ -1719,14 +1719,6 @@ namespace cppcanvas ::PolyPolygon aPath; aFill.getPath( aPath ); - // subdivide if polygon has curves - basegfx::B2DPolyPolygon aTmpPolyPolygon( aPath.getB2DPolyPolygon() ); - if (aTmpPolyPolygon.areControlVectorsUsed()) - { - aTmpPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle( aTmpPolyPolygon ); - aPath = ::PolyPolygon( aTmpPolyPolygon ); - } - ActionSharedPtr pPolyAction( internal::PolyPolyActionFactory::createPolyPolyAction( rVDev.LogicToPixel( aPath ), @@ -1943,6 +1935,8 @@ namespace cppcanvas MetaPolyLineAction* pPolyLineAct = static_cast<MetaPolyLineAction*>(pCurrAct); const LineInfo& rLineInfo( pPolyLineAct->GetLineInfo() ); + ::Polygon aPoly( rVDev.LogicToPixel( + pPolyLineAct->GetPolygon() ) ); ActionSharedPtr pLineAction; @@ -1951,7 +1945,7 @@ namespace cppcanvas // plain hair line polygon pLineAction = internal::PolyPolyActionFactory::createLinePolyPolyAction( - rVDev.LogicToPixel( pPolyLineAct->GetPolygon() ), + aPoly, rCanvas, rState ); @@ -1976,7 +1970,7 @@ namespace cppcanvas pLineAction = internal::PolyPolyActionFactory::createPolyPolyAction( - rVDev.LogicToPixel( pPolyLineAct->GetPolygon() ), + aPoly, rCanvas, rState, aStrokeAttributes ) ; @@ -2488,6 +2482,240 @@ namespace cppcanvas return true; } + + namespace + { + class ActionRenderer + { + public: + ActionRenderer( const ::basegfx::B2DHomMatrix& rTransformation ) : + maTransformation( rTransformation ), + mbRet( true ) + { + } + + bool result() + { + return mbRet; + } + + void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction ) + { + // ANDing the result. We want to fail if at least + // one action failed. + mbRet &= rAction.mpAction->render( maTransformation ); + } + + void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction, + const Action::Subset& rSubset ) + { + // ANDing the result. We want to fail if at least + // one action failed. + mbRet &= rAction.mpAction->render( maTransformation, + rSubset ); + } + + private: + const ::basegfx::B2DHomMatrix maTransformation; + bool mbRet; + }; + + class AreaQuery + { + public: + AreaQuery( const ::basegfx::B2DHomMatrix& rTransformation ) : + maTransformation( rTransformation ), + maBounds() + { + } + + bool result() + { + return true; // nothing can fail here + } + + void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction ) + { + maBounds.expand( rAction.mpAction->getBounds( maTransformation ) ); + } + + void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction, + const Action::Subset& rSubset ) + { + maBounds.expand( rAction.mpAction->getBounds( maTransformation, + rSubset ) ); + } + + ::basegfx::B2DRange getBounds() const + { + return maBounds; + } + + private: + const ::basegfx::B2DHomMatrix maTransformation; + ::basegfx::B2DRange maBounds; + }; + + // Doing that via inline class. Compilers tend to not inline free + // functions. + struct UpperBoundActionIndexComparator + { + bool operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rLHS, + const ::cppcanvas::internal::ImplRenderer::MtfAction& rRHS ) + { + const sal_Int32 nLHSCount( rLHS.mpAction ? + rLHS.mpAction->getActionCount() : 0 ); + const sal_Int32 nRHSCount( rRHS.mpAction ? + rRHS.mpAction->getActionCount() : 0 ); + + // compare end of action range, to have an action selected + // by lower_bound even if the requested index points in + // the middle of the action's range + return rLHS.mnOrigIndex + nLHSCount < rRHS.mnOrigIndex + nRHSCount; + } + }; + + /** Algorithm to apply given functor to a subset range + + @tpl Functor + + Functor to call for each element of the subset + range. Must provide the following method signatures: + bool result() (returning false if operation failed) + + */ + template< typename Functor > bool + forSubsetRange( Functor& rFunctor, + ImplRenderer::ActionVector::const_iterator aRangeBegin, + ImplRenderer::ActionVector::const_iterator aRangeEnd, + sal_Int32 nStartIndex, + sal_Int32 nEndIndex, + const ImplRenderer::ActionVector::const_iterator& rEnd ) + { + if( aRangeBegin == aRangeEnd ) + { + // only a single action. Setup subset, and call functor + Action::Subset aSubset; + aSubset.mnSubsetBegin = ::std::max( 0L, + nStartIndex - aRangeBegin->mnOrigIndex ); + aSubset.mnSubsetEnd = ::std::min( aRangeBegin->mpAction->getActionCount(), + nEndIndex - aRangeBegin->mnOrigIndex ); + + ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, + "ImplRenderer::forSubsetRange(): Invalid indices" ); + + rFunctor( *aRangeBegin, aSubset ); + + return rFunctor.result(); + } + else + { + // more than one action. + + // render partial first, full intermediate, and + // partial last action + Action::Subset aSubset; + aSubset.mnSubsetBegin = ::std::max( 0L, + nStartIndex - aRangeBegin->mnOrigIndex ); + aSubset.mnSubsetEnd = aRangeBegin->mpAction->getActionCount(); + + ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, + "ImplRenderer::forSubsetRange(): Invalid indices" ); + + rFunctor( *aRangeBegin, aSubset ); + + if( !rFunctor.result() ) + return false; + + // first action rendered, skip to next + ++aRangeBegin; + + // render full middle actions + if( !::std::for_each( aRangeBegin, + aRangeEnd, + rFunctor ).result() ) + { + return false; + } + + if( aRangeEnd == rEnd || + aRangeEnd->mnOrigIndex > nEndIndex ) + { + // aRangeEnd denotes end of action vector, + // + // or + // + // nEndIndex references something _after_ + // aRangeBegin, but _before_ aRangeEnd + // + // either way: no partial action left + return true; + } + + aSubset.mnSubsetBegin = 0; + aSubset.mnSubsetEnd = nEndIndex - aRangeEnd->mnOrigIndex; + + ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, + "ImplRenderer::forSubsetRange(): Invalid indices" ); + + rFunctor( *aRangeEnd, aSubset ); + + return rFunctor.result(); + } + } + } + + bool ImplRenderer::getSubsetIndices( sal_Int32& io_rStartIndex, + sal_Int32& io_rEndIndex, + ActionVector::const_iterator& o_rRangeBegin, + ActionVector::const_iterator& o_rRangeEnd ) const + { + ENSURE_AND_RETURN( io_rStartIndex<=io_rEndIndex, + "ImplRenderer::getSubsetIndices(): invalid action range" ); + + ENSURE_AND_RETURN( !maActions.empty(), + "ImplRenderer::getSubsetIndices(): no actions to render" ); + + const sal_Int32 nMinActionIndex( maActions.front().mnOrigIndex ); + const sal_Int32 nMaxActionIndex( maActions.back().mnOrigIndex + + maActions.back().mpAction->getActionCount() ); + + // clip given range to permissible values (there might be + // ranges before and behind the valid indices) + io_rStartIndex = ::std::max( nMinActionIndex, + io_rStartIndex ); + io_rEndIndex = ::std::min( nMaxActionIndex, + io_rEndIndex ); + + if( io_rStartIndex == io_rEndIndex || + io_rStartIndex > io_rEndIndex ) + { + // empty range, don't render anything. The second + // condition e.g. happens if the requested range lies + // fully before or behind the valid action indices. + return false; + } + + + const ActionVector::const_iterator aBegin( maActions.begin() ); + const ActionVector::const_iterator aEnd( maActions.end() ); + + + // find start and end action + // ========================= + o_rRangeBegin = ::std::lower_bound( aBegin, aEnd, + MtfAction( ActionSharedPtr(), io_rStartIndex ), + UpperBoundActionIndexComparator() ); + o_rRangeEnd = ::std::lower_bound( aBegin, aEnd, + MtfAction( ActionSharedPtr(), io_rEndIndex ), + UpperBoundActionIndexComparator() ); + return true; + } + + + // Public methods + // ==================================================================== + ImplRenderer::ImplRenderer( const CanvasSharedPtr& rCanvas, const GDIMetaFile& rMtf, const Parameters& rParams ) : @@ -2647,100 +2875,17 @@ namespace cppcanvas { } - namespace - { - class ActionRenderer - { - public: - ActionRenderer( const ::basegfx::B2DHomMatrix& rTransformation ) : - maTransformation( rTransformation ), - mbRet( true ) - { - } - - bool result() - { - return mbRet; - } - - void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction ) - { - // ANDing the result. We want to fail if at least - // one action failed. - mbRet &= rAction.mpAction->render( maTransformation ); - } - - private: - const ::basegfx::B2DHomMatrix maTransformation; - bool mbRet; - }; - - // Doing that via inline class. Compilers tend to not inline free - // functions. - struct UpperBoundActionIndexComparator - { - bool operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rLHS, - const ::cppcanvas::internal::ImplRenderer::MtfAction& rRHS ) - { - const sal_Int32 nLHSCount( rLHS.mpAction ? - rLHS.mpAction->getActionCount() : 0 ); - const sal_Int32 nRHSCount( rRHS.mpAction ? - rRHS.mpAction->getActionCount() : 0 ); - - // compare end of action range, to have an action selected - // by lower_bound even if the requested index points in - // the middle of the action's range - return rLHS.mnOrigIndex + nLHSCount < rRHS.mnOrigIndex + nRHSCount; - } - }; - - } - bool ImplRenderer::drawSubset( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const { - RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::draw()" ); - - ENSURE_AND_RETURN( nStartIndex<=nEndIndex, - "ImplRenderer::drawSubset(): invalid action range" ); - - ENSURE_AND_RETURN( !maActions.empty(), - "ImplRenderer::drawSubset(): no actions to render" ); - - const sal_Int32 nMinActionIndex( maActions.front().mnOrigIndex ); - const sal_Int32 nMaxActionIndex( maActions.back().mnOrigIndex + - maActions.back().mpAction->getActionCount() ); - - // clip given range to permissible values (there might be - // ranges before and behind the valid indices) - nStartIndex = ::std::max( nMinActionIndex, - nStartIndex ); - nEndIndex = ::std::min( nMaxActionIndex, - nEndIndex ); - - if( nStartIndex == nEndIndex || - nStartIndex > nEndIndex ) - { - // empty range, rendered 'nothing' successfully. The - // second condition e.g. happens if the requested - // range lies fully before or behind the valid action - // indices. - return true; - } - - - const ActionVector::const_iterator aBegin( maActions.begin() ); - const ActionVector::const_iterator aEnd( maActions.end() ); + RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::drawSubset()" ); + ActionVector::const_iterator aRangeBegin; + ActionVector::const_iterator aRangeEnd; - // find start and end action - // ========================= - ActionVector::const_iterator aRangeBegin( ::std::lower_bound( aBegin, aEnd, - MtfAction( ActionSharedPtr(), nStartIndex ), - UpperBoundActionIndexComparator() ) ); - ActionVector::const_iterator aRangeEnd( ::std::lower_bound( aBegin, aEnd, - MtfAction( ActionSharedPtr(), nEndIndex ), - UpperBoundActionIndexComparator() ) ); + if( !getSubsetIndices( nStartIndex, nEndIndex, + aRangeBegin, aRangeEnd ) ) + return true; // nothing to render (but _that_ was successful) // now, aRangeBegin references the action in which the // subset rendering must start, and aRangeEnd references @@ -2756,70 +2901,51 @@ namespace cppcanvas ::basegfx::B2DHomMatrix aMatrix; ::canvas::tools::getRenderStateTransform( aMatrix, maRenderState ); - if( aRangeBegin == aRangeEnd ) - { - // only a single action. Setup subset, and render - Action::Subset aSubset; - aSubset.mnSubsetBegin = ::std::max( 0L, - nStartIndex - aRangeBegin->mnOrigIndex ); - aSubset.mnSubsetEnd = ::std::min( aRangeBegin->mpAction->getActionCount(), - nEndIndex - aRangeBegin->mnOrigIndex ); - - ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, - "ImplRenderer::drawSubset(): Invalid indices" ); + ActionRenderer aRenderer( aMatrix ); - return aRangeBegin->mpAction->render( aMatrix, aSubset ); - } - else - { - // more than one action. + return forSubsetRange( aRenderer, + aRangeBegin, + aRangeEnd, + nStartIndex, + nEndIndex, + maActions.end() ); + } - // render partial first, full intermediate, and - // partial last action - Action::Subset aSubset; - aSubset.mnSubsetBegin = ::std::max( 0L, - nStartIndex - aRangeBegin->mnOrigIndex ); - aSubset.mnSubsetEnd = aRangeBegin->mpAction->getActionCount(); + ::basegfx::B2DRange ImplRenderer::getSubsetArea( sal_Int32 nStartIndex, + sal_Int32 nEndIndex ) const + { + RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::getSubsetArea()" ); - ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, - "ImplRenderer::drawSubset(): Invalid indices" ); + ActionVector::const_iterator aRangeBegin; + ActionVector::const_iterator aRangeEnd; - if( !aRangeBegin->mpAction->render( aMatrix, aSubset ) ) - return false; + if( !getSubsetIndices( nStartIndex, nEndIndex, + aRangeBegin, aRangeEnd ) ) + return ::basegfx::B2DRange(); // nothing to render -> empty range - // first action rendered, skip to next - ++aRangeBegin; + // now, aRangeBegin references the action in which the + // subset querying must start, and aRangeEnd references + // the action in which the subset querying must end (it + // might also end right at the start of the referenced + // action, such that zero of that action needs to be + // queried). - // render full middle actions - if( !::std::for_each( aRangeBegin, - aRangeEnd, - ActionRenderer( aMatrix ) ).result() ) - { - return false; - } - if( aRangeEnd == aEnd || - aRangeEnd->mnOrigIndex > nEndIndex ) - { - // aRangeEnd denotes end of action vector, - // - // or - // - // nEndIndex references something _after_ - // aRangeBegin, but _before_ aRangeEnd - // - // either way: no partial action left - return true; - } + // query bounds for subset of actions + // ================================== - aSubset.mnSubsetBegin = 0; - aSubset.mnSubsetEnd = nEndIndex - aRangeEnd->mnOrigIndex; + ::basegfx::B2DHomMatrix aMatrix; + ::canvas::tools::getRenderStateTransform( aMatrix, maRenderState ); - ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0, - "ImplRenderer::drawSubset(): Invalid indices" ); + AreaQuery aQuery( aMatrix ); + forSubsetRange( aQuery, + aRangeBegin, + aRangeEnd, + nStartIndex, + nEndIndex, + maActions.end() ); - return aRangeEnd->mpAction->render( aMatrix, aSubset ); - } + return aQuery.getBounds(); } bool ImplRenderer::draw() const |