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
This commit is contained in:
Oliver Bolte
2005-04-18 08:59:07 +00:00
parent 277bc8faff
commit 17ac8d1cbd

View File

@@ -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()" );
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::drawSubset()" );
ENSURE_AND_RETURN( nStartIndex<=nEndIndex,
"ImplRenderer::drawSubset(): invalid action range" );
ActionVector::const_iterator aRangeBegin;
ActionVector::const_iterator aRangeEnd;
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() );
// 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 );
ActionRenderer aRenderer( aMatrix );
ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
"ImplRenderer::drawSubset(): Invalid indices" );
return forSubsetRange( aRenderer,
aRangeBegin,
aRangeEnd,
nStartIndex,
nEndIndex,
maActions.end() );
}
return aRangeBegin->mpAction->render( aMatrix, aSubset );
}
else
{
// more than one action.
::basegfx::B2DRange ImplRenderer::getSubsetArea( sal_Int32 nStartIndex,
sal_Int32 nEndIndex ) const
{
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::getSubsetArea()" );
// 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();
ActionVector::const_iterator aRangeBegin;
ActionVector::const_iterator aRangeEnd;
ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
"ImplRenderer::drawSubset(): Invalid indices" );
if( !getSubsetIndices( nStartIndex, nEndIndex,
aRangeBegin, aRangeEnd ) )
return ::basegfx::B2DRange(); // nothing to render -> empty range
if( !aRangeBegin->mpAction->render( aMatrix, aSubset ) )
return false;
// 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).
// first action rendered, skip to next
++aRangeBegin;
// render full middle actions
if( !::std::for_each( aRangeBegin,
aRangeEnd,
ActionRenderer( aMatrix ) ).result() )
{
return false;
}
// query bounds for subset of actions
// ==================================
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;
}
::basegfx::B2DHomMatrix aMatrix;
::canvas::tools::getRenderStateTransform( aMatrix, maRenderState );
aSubset.mnSubsetBegin = 0;
aSubset.mnSubsetEnd = nEndIndex - aRangeEnd->mnOrigIndex;
AreaQuery aQuery( aMatrix );
forSubsetRange( aQuery,
aRangeBegin,
aRangeEnd,
nStartIndex,
nEndIndex,
maActions.end() );
ENSURE_AND_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
"ImplRenderer::drawSubset(): Invalid indices" );
return aRangeEnd->mpAction->render( aMatrix, aSubset );
}
return aQuery.getBounds();
}
bool ImplRenderer::draw() const