#i105937# Much improved gradient support for canvas/basegfx/drawinglayer.
See http://blog.thebehrens.net/2009/07/28/hackweek-iv-canvas-convwatch/ for more background information
This commit is contained in:
@@ -36,6 +36,8 @@
|
|||||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||||
#include <basegfx/vector/b2dvector.hxx>
|
#include <basegfx/vector/b2dvector.hxx>
|
||||||
|
|
||||||
|
namespace rtl { class OUString; }
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace basegfx
|
namespace basegfx
|
||||||
@@ -79,6 +81,10 @@ namespace basegfx
|
|||||||
double getRotate() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfRotate; }
|
double getRotate() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfRotate; }
|
||||||
double getShearX() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfShearX; }
|
double getShearX() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfShearX; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Returns a string with svg's "matrix(m00,m10,m01,m11,m02,m12)" representation
|
||||||
|
::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix );
|
||||||
|
|
||||||
} // end of namespace basegfx
|
} // end of namespace basegfx
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@@ -112,7 +112,7 @@ namespace basegfx
|
|||||||
|
|
||||||
/** clamp given value against given minimum and maximum values
|
/** clamp given value against given minimum and maximum values
|
||||||
*/
|
*/
|
||||||
template <class T> const T& clamp(const T& value, const T& minimum, const T& maximum)
|
template <class T> inline const T& clamp(const T& value, const T& minimum, const T& maximum)
|
||||||
{
|
{
|
||||||
if(value < minimum)
|
if(value < minimum)
|
||||||
{
|
{
|
||||||
|
@@ -37,6 +37,9 @@
|
|||||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||||
#include <basegfx/numeric/ftools.hxx>
|
#include <basegfx/numeric/ftools.hxx>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace basegfx
|
namespace basegfx
|
||||||
{
|
{
|
||||||
/** Gradient definition as used in ODF 1.2
|
/** Gradient definition as used in ODF 1.2
|
||||||
@@ -78,6 +81,8 @@ namespace basegfx
|
|||||||
{
|
{
|
||||||
/** Create matrix for ODF's linear gradient definition
|
/** Create matrix for ODF's linear gradient definition
|
||||||
|
|
||||||
|
Note that odf linear gradients are varying in y direction.
|
||||||
|
|
||||||
@param o_rGradientInfo
|
@param o_rGradientInfo
|
||||||
Receives the calculated texture transformation matrix (for
|
Receives the calculated texture transformation matrix (for
|
||||||
use with standard [0,1]x[0,1] texture coordinates)
|
use with standard [0,1]x[0,1] texture coordinates)
|
||||||
@@ -109,7 +114,7 @@ namespace basegfx
|
|||||||
|
|
||||||
@param rUV
|
@param rUV
|
||||||
Current uv coordinate. Values outside [0,1] will be
|
Current uv coordinate. Values outside [0,1] will be
|
||||||
clamped.
|
clamped. Assumes gradient color varies along the y axis.
|
||||||
|
|
||||||
@param rGradInfo
|
@param rGradInfo
|
||||||
Gradient info, for transformation and number of steps
|
Gradient info, for transformation and number of steps
|
||||||
@@ -129,6 +134,14 @@ namespace basegfx
|
|||||||
|
|
||||||
/** Create matrix for ODF's axial gradient definition
|
/** Create matrix for ODF's axial gradient definition
|
||||||
|
|
||||||
|
Note that odf axial gradients are varying in y
|
||||||
|
direction. Note further that you can map the axial
|
||||||
|
gradient to a linear gradient (in case you want or need to
|
||||||
|
avoid an extra gradient renderer), by using
|
||||||
|
createLinearODFGradientInfo() instead, shifting the
|
||||||
|
resulting texture transformation by 0.5 to the top and
|
||||||
|
appending the same stop colors again, but mirrored.
|
||||||
|
|
||||||
@param o_rGradientInfo
|
@param o_rGradientInfo
|
||||||
Receives the calculated texture transformation matrix (for
|
Receives the calculated texture transformation matrix (for
|
||||||
use with standard [0,1]x[0,1] texture coordinates)
|
use with standard [0,1]x[0,1] texture coordinates)
|
||||||
@@ -160,7 +173,7 @@ namespace basegfx
|
|||||||
|
|
||||||
@param rUV
|
@param rUV
|
||||||
Current uv coordinate. Values outside [0,1] will be
|
Current uv coordinate. Values outside [0,1] will be
|
||||||
clamped.
|
clamped. Assumes gradient color varies along the y axis.
|
||||||
|
|
||||||
@param rGradInfo
|
@param rGradInfo
|
||||||
Gradient info, for transformation and number of steps
|
Gradient info, for transformation and number of steps
|
||||||
@@ -394,7 +407,6 @@ namespace basegfx
|
|||||||
{
|
{
|
||||||
return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs
|
return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
100
basegfx/inc/basegfx/tools/keystoplerp.hxx
Normal file
100
basegfx/inc/basegfx/tools/keystoplerp.hxx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* 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: canvastools.hxx,v $
|
||||||
|
* $Revision: 1.10 $
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _BGFX_TOOLS_KEYSTOPLERP_HXX
|
||||||
|
#define _BGFX_TOOLS_KEYSTOPLERP_HXX
|
||||||
|
|
||||||
|
#include <basegfx/numeric/ftools.hxx>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace com{ namespace sun{ namespace star{ namespace uno {
|
||||||
|
template<typename T> class Sequence;
|
||||||
|
}}}}
|
||||||
|
|
||||||
|
namespace basegfx
|
||||||
|
{
|
||||||
|
namespace tools
|
||||||
|
{
|
||||||
|
/** Lerp in a vector of key stops
|
||||||
|
|
||||||
|
This class holds a key stop vector and provides the
|
||||||
|
functionality to lerp inside it. Useful e.g. for
|
||||||
|
multi-stop gradients, or the SMIL key time activity.
|
||||||
|
|
||||||
|
For those, given a global [0,1] lerp alpha, one need to
|
||||||
|
find the suitable bucket index from key stop vector, and
|
||||||
|
then calculate the relative alpha between the two buckets
|
||||||
|
found.
|
||||||
|
*/
|
||||||
|
class KeyStopLerp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::pair<std::ptrdiff_t,double> ResultType;
|
||||||
|
|
||||||
|
/** Create lerper with given vector of stops
|
||||||
|
|
||||||
|
@param rKeyStops
|
||||||
|
|
||||||
|
Vector of stops, must contain at least two elements
|
||||||
|
(though preferrably more, otherwise you probably don't
|
||||||
|
need key stop lerping in the first place). All
|
||||||
|
elements must be of monotonically increasing value.
|
||||||
|
*/
|
||||||
|
explicit KeyStopLerp( const std::vector<double>& rKeyStops );
|
||||||
|
|
||||||
|
/** Create lerper with given sequence of stops
|
||||||
|
|
||||||
|
@param rKeyStops
|
||||||
|
|
||||||
|
Sequence of stops, must contain at least two elements
|
||||||
|
(though preferrably more, otherwise you probably don't
|
||||||
|
need key stop lerping in the first place). All
|
||||||
|
elements must be of monotonically increasing value.
|
||||||
|
*/
|
||||||
|
explicit KeyStopLerp( const ::com::sun::star::uno::Sequence<double>& rKeyStops );
|
||||||
|
|
||||||
|
/** Find two nearest bucket index & interpolate
|
||||||
|
|
||||||
|
@param fAlpha
|
||||||
|
Find bucket index i, with keyStops[i] < fAlpha <=
|
||||||
|
keyStops[i+1]. Return new alpha value in [0,1),
|
||||||
|
proportional to fAlpha's position between keyStops[i]
|
||||||
|
and keyStops[i+1]
|
||||||
|
*/
|
||||||
|
ResultType lerp(double fAlpha) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<double> maKeyStops;
|
||||||
|
mutable std::ptrdiff_t mnLastIndex;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
60
basegfx/inc/basegfx/tools/lerp.hxx
Normal file
60
basegfx/inc/basegfx/tools/lerp.hxx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* 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: lerp.hxx,v $
|
||||||
|
* $Revision: 1.6 $
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _BGFX_TOOLS_LERP_HXX
|
||||||
|
#define _BGFX_TOOLS_LERP_HXX
|
||||||
|
|
||||||
|
#include <sal/types.h>
|
||||||
|
|
||||||
|
namespace basegfx
|
||||||
|
{
|
||||||
|
namespace tools
|
||||||
|
{
|
||||||
|
/** Generic linear interpolator
|
||||||
|
|
||||||
|
@tpl ValueType
|
||||||
|
Must have operator+ and operator* defined, and should
|
||||||
|
have value semantics.
|
||||||
|
|
||||||
|
@param t
|
||||||
|
As usual, t must be in the [0,1] range
|
||||||
|
*/
|
||||||
|
template< typename ValueType > ValueType lerp( const ValueType& rFrom,
|
||||||
|
const ValueType& rTo,
|
||||||
|
double t )
|
||||||
|
{
|
||||||
|
// This is only to suppress a double->int warning. All other
|
||||||
|
// types should be okay here.
|
||||||
|
return static_cast<ValueType>( (1.0-t)*rFrom + t*rTo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BGFX_TOOLS_LERP_HXX */
|
@@ -89,6 +89,8 @@ mkdir: %_DEST%\inc%_EXT%\basegfx\tuple
|
|||||||
|
|
||||||
mkdir: %_DEST%\inc%_EXT%\basegfx\tools
|
mkdir: %_DEST%\inc%_EXT%\basegfx\tools
|
||||||
..\inc\basegfx\tools\canvastools.hxx %_DEST%\inc%_EXT%\basegfx\tools\canvastools.hxx
|
..\inc\basegfx\tools\canvastools.hxx %_DEST%\inc%_EXT%\basegfx\tools\canvastools.hxx
|
||||||
|
..\inc\basegfx\tools\keystoplerp.hxx %_DEST%\inc%_EXT%\basegfx\tools\keystoplerp.hxx
|
||||||
|
..\inc\basegfx\tools\lerp.hxx %_DEST%\inc%_EXT%\basegfx\tools\lerp.hxx
|
||||||
..\inc\basegfx\tools\unopolypolygon.hxx %_DEST%\inc%_EXT%\basegfx\tools\unopolypolygon.hxx
|
..\inc\basegfx\tools\unopolypolygon.hxx %_DEST%\inc%_EXT%\basegfx\tools\unopolypolygon.hxx
|
||||||
..\inc\basegfx\tools\rectcliptools.hxx %_DEST%\inc%_EXT%\basegfx\tools\rectcliptools.hxx
|
..\inc\basegfx\tools\rectcliptools.hxx %_DEST%\inc%_EXT%\basegfx\tools\rectcliptools.hxx
|
||||||
..\inc\basegfx\tools\tools.hxx %_DEST%\inc%_EXT%\basegfx\tools\tools.hxx
|
..\inc\basegfx\tools\tools.hxx %_DEST%\inc%_EXT%\basegfx\tools\tools.hxx
|
||||||
|
@@ -33,11 +33,39 @@
|
|||||||
#include "precompiled_basegfx.hxx"
|
#include "precompiled_basegfx.hxx"
|
||||||
|
|
||||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||||
|
#include <rtl/ustring.hxx>
|
||||||
|
#include <rtl/ustrbuf.hxx>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace basegfx
|
namespace basegfx
|
||||||
{
|
{
|
||||||
|
::rtl::OUString exportToSvg( const B2DHomMatrix& rMatrix )
|
||||||
|
{
|
||||||
|
rtl::OUStringBuffer aStrBuf;
|
||||||
|
aStrBuf.appendAscii("matrix(");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(0,0));
|
||||||
|
aStrBuf.appendAscii(", ");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(1,0));
|
||||||
|
aStrBuf.appendAscii(", ");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(0,1));
|
||||||
|
aStrBuf.appendAscii(", ");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(1,1));
|
||||||
|
aStrBuf.appendAscii(", ");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(0,2));
|
||||||
|
aStrBuf.appendAscii(", ");
|
||||||
|
|
||||||
|
aStrBuf.append(rMatrix.get(1,2));
|
||||||
|
aStrBuf.appendAscii(")");
|
||||||
|
|
||||||
|
return aStrBuf.makeStringAndClear();
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace basegfx
|
} // end of namespace basegfx
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@@ -52,6 +52,8 @@ namespace basegfx
|
|||||||
o_rGradientInfo.maBackTextureTransform.identity();
|
o_rGradientInfo.maBackTextureTransform.identity();
|
||||||
o_rGradientInfo.mnSteps = nSteps;
|
o_rGradientInfo.mnSteps = nSteps;
|
||||||
|
|
||||||
|
fAngle = -fAngle;
|
||||||
|
|
||||||
double fTargetSizeX(rTargetRange.getWidth());
|
double fTargetSizeX(rTargetRange.getWidth());
|
||||||
double fTargetSizeY(rTargetRange.getHeight());
|
double fTargetSizeY(rTargetRange.getHeight());
|
||||||
double fTargetOffsetX(rTargetRange.getMinX());
|
double fTargetOffsetX(rTargetRange.getMinX());
|
||||||
@@ -70,7 +72,23 @@ namespace basegfx
|
|||||||
fTargetSizeY = fNewY;
|
fTargetSizeY = fNewY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add object scale before rotate
|
double fSizeWithoutBorder=0;
|
||||||
|
double fTranslateY=0;
|
||||||
|
if( bAxial )
|
||||||
|
{
|
||||||
|
fSizeWithoutBorder = (1.0 - fBorder) * 0.5;
|
||||||
|
fTranslateY = 0.5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fSizeWithoutBorder = 1.0 - fBorder;
|
||||||
|
fTranslateY = fBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fTools::equal(fSizeWithoutBorder, 0.0))
|
||||||
|
o_rGradientInfo.maTextureTransform.scale(1.0, fSizeWithoutBorder);
|
||||||
|
|
||||||
|
o_rGradientInfo.maTextureTransform.translate(0.0, fTranslateY);
|
||||||
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
||||||
|
|
||||||
// add texture rotate after scale to keep perpendicular angles
|
// add texture rotate after scale to keep perpendicular angles
|
||||||
@@ -90,24 +108,9 @@ namespace basegfx
|
|||||||
// prepare aspect for texture
|
// prepare aspect for texture
|
||||||
o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
|
o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
|
||||||
|
|
||||||
// build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
|
// build transform from u,v to [0.0 .. 1.0].
|
||||||
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
||||||
o_rGradientInfo.maBackTextureTransform.invert();
|
o_rGradientInfo.maBackTextureTransform.invert();
|
||||||
|
|
||||||
double fSizeWithoutBorder=0;
|
|
||||||
if( bAxial )
|
|
||||||
{
|
|
||||||
fSizeWithoutBorder = (1.0 - fBorder) * 0.5;
|
|
||||||
o_rGradientInfo.maBackTextureTransform.translate(0.0, -0.5);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fSizeWithoutBorder = 1.0 - fBorder;
|
|
||||||
o_rGradientInfo.maBackTextureTransform.translate(0.0, -fBorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!fTools::equal(fSizeWithoutBorder, 0.0))
|
|
||||||
o_rGradientInfo.maBackTextureTransform.scale(1.0, 1.0 / fSizeWithoutBorder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Most of the setup for radial & ellipsoidal gradient is the same,
|
/** Most of the setup for radial & ellipsoidal gradient is the same,
|
||||||
@@ -125,6 +128,8 @@ namespace basegfx
|
|||||||
o_rGradientInfo.maBackTextureTransform.identity();
|
o_rGradientInfo.maBackTextureTransform.identity();
|
||||||
o_rGradientInfo.mnSteps = nSteps;
|
o_rGradientInfo.mnSteps = nSteps;
|
||||||
|
|
||||||
|
fAngle = -fAngle;
|
||||||
|
|
||||||
double fTargetSizeX(rTargetRange.getWidth());
|
double fTargetSizeX(rTargetRange.getWidth());
|
||||||
double fTargetSizeY(rTargetRange.getHeight());
|
double fTargetSizeY(rTargetRange.getHeight());
|
||||||
double fTargetOffsetX(rTargetRange.getMinX());
|
double fTargetOffsetX(rTargetRange.getMinX());
|
||||||
@@ -147,7 +152,11 @@ namespace basegfx
|
|||||||
fTargetSizeY = 1.4142 * fTargetSizeY;
|
fTargetSizeY = 1.4142 * fTargetSizeY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add object scale before rotate
|
const double fHalfBorder((1.0 - fBorder) * 0.5);
|
||||||
|
if(!fTools::equal(fHalfBorder, 0.0))
|
||||||
|
o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
|
||||||
|
|
||||||
|
o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
|
||||||
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
||||||
|
|
||||||
if( !bCircular )
|
if( !bCircular )
|
||||||
@@ -155,9 +164,8 @@ namespace basegfx
|
|||||||
// add texture rotate after scale to keep perpendicular angles
|
// add texture rotate after scale to keep perpendicular angles
|
||||||
if(0.0 != fAngle)
|
if(0.0 != fAngle)
|
||||||
{
|
{
|
||||||
B2DPoint aCenter(0.5, 0.5);
|
const B2DPoint aCenter(0.5*fTargetSizeX,
|
||||||
aCenter *= o_rGradientInfo.maTextureTransform;
|
0.5*fTargetSizeY);
|
||||||
|
|
||||||
o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
|
o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
|
||||||
o_rGradientInfo.maTextureTransform.rotate(fAngle);
|
o_rGradientInfo.maTextureTransform.rotate(fAngle);
|
||||||
o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
|
o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
|
||||||
@@ -178,17 +186,9 @@ namespace basegfx
|
|||||||
// prepare aspect for texture
|
// prepare aspect for texture
|
||||||
o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
|
o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
|
||||||
|
|
||||||
// build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
|
// build transform from u,v to [0.0 .. 1.0].
|
||||||
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
||||||
o_rGradientInfo.maBackTextureTransform.invert();
|
o_rGradientInfo.maBackTextureTransform.invert();
|
||||||
o_rGradientInfo.maBackTextureTransform.translate(-0.5, -0.5);
|
|
||||||
const double fHalfBorder((1.0 - fBorder) * 0.5);
|
|
||||||
|
|
||||||
if(!fTools::equal(fHalfBorder, 0.0))
|
|
||||||
{
|
|
||||||
const double fFactor(1.0 / fHalfBorder);
|
|
||||||
o_rGradientInfo.maBackTextureTransform.scale(fFactor, fFactor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Setup for rect & square gradient is exactly the same. Factored out
|
/** Setup for rect & square gradient is exactly the same. Factored out
|
||||||
@@ -205,6 +205,8 @@ namespace basegfx
|
|||||||
o_rGradientInfo.maBackTextureTransform.identity();
|
o_rGradientInfo.maBackTextureTransform.identity();
|
||||||
o_rGradientInfo.mnSteps = nSteps;
|
o_rGradientInfo.mnSteps = nSteps;
|
||||||
|
|
||||||
|
fAngle = -fAngle;
|
||||||
|
|
||||||
double fTargetSizeX(rTargetRange.getWidth());
|
double fTargetSizeX(rTargetRange.getWidth());
|
||||||
double fTargetSizeY(rTargetRange.getHeight());
|
double fTargetSizeY(rTargetRange.getHeight());
|
||||||
double fTargetOffsetX(rTargetRange.getMinX());
|
double fTargetOffsetX(rTargetRange.getMinX());
|
||||||
@@ -223,15 +225,18 @@ namespace basegfx
|
|||||||
fTargetSizeY = fNewY;
|
fTargetSizeY = fNewY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add object scale before rotate
|
const double fHalfBorder((1.0 - fBorder) * 0.5);
|
||||||
|
if(!fTools::equal(fHalfBorder, 0.0))
|
||||||
|
o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
|
||||||
|
|
||||||
|
o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
|
||||||
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
|
||||||
|
|
||||||
// add texture rotate after scale to keep perpendicular angles
|
// add texture rotate after scale to keep perpendicular angles
|
||||||
if(0.0 != fAngle)
|
if(0.0 != fAngle)
|
||||||
{
|
{
|
||||||
B2DPoint aCenter(0.5, 0.5);
|
const B2DPoint aCenter(0.5*fTargetSizeX,
|
||||||
aCenter *= o_rGradientInfo.maTextureTransform;
|
0.5*fTargetSizeY);
|
||||||
|
|
||||||
o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
|
o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
|
||||||
o_rGradientInfo.maTextureTransform.rotate(fAngle);
|
o_rGradientInfo.maTextureTransform.rotate(fAngle);
|
||||||
o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
|
o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
|
||||||
@@ -254,14 +259,6 @@ namespace basegfx
|
|||||||
// build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
|
// build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
|
||||||
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
|
||||||
o_rGradientInfo.maBackTextureTransform.invert();
|
o_rGradientInfo.maBackTextureTransform.invert();
|
||||||
o_rGradientInfo.maBackTextureTransform.translate(-0.5, -0.5);
|
|
||||||
const double fHalfBorder((1.0 - fBorder) * 0.5);
|
|
||||||
|
|
||||||
if(!fTools::equal(fHalfBorder, 0.0))
|
|
||||||
{
|
|
||||||
const double fFactor(1.0 / fHalfBorder);
|
|
||||||
o_rGradientInfo.maBackTextureTransform.scale(fFactor, fFactor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace tools
|
namespace tools
|
||||||
|
104
basegfx/source/tools/keystoplerp.cxx
Normal file
104
basegfx/source/tools/keystoplerp.cxx
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* 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: canvastools.hxx,v $
|
||||||
|
* $Revision: 1.10 $
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "basegfx/tools/keystoplerp.hxx"
|
||||||
|
#include <com/sun/star/uno/Sequence.hxx>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
static void validateInput(const std::vector<double>& rKeyStops)
|
||||||
|
{
|
||||||
|
(void)rKeyStops;
|
||||||
|
#ifdef DBG_UTIL
|
||||||
|
OSL_ENSURE( rKeyStops.size() > 1,
|
||||||
|
"KeyStopLerp::KeyStopLerp(): key stop vector must have two entries or more" );
|
||||||
|
|
||||||
|
// rKeyStops must be sorted in ascending order
|
||||||
|
for( ::std::size_t i=1, len=rKeyStops.size(); i<len; ++i )
|
||||||
|
{
|
||||||
|
if( rKeyStops[i-1] > rKeyStops[i] )
|
||||||
|
OSL_ENSURE( false,
|
||||||
|
"KeyStopLerp::KeyStopLerp(): time vector is not sorted in ascending order!" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace basegfx
|
||||||
|
{
|
||||||
|
namespace tools
|
||||||
|
{
|
||||||
|
KeyStopLerp::KeyStopLerp( const std::vector<double>& rKeyStops ) :
|
||||||
|
maKeyStops(rKeyStops),
|
||||||
|
mnLastIndex(0)
|
||||||
|
{
|
||||||
|
validateInput(maKeyStops);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyStopLerp::KeyStopLerp( const ::com::sun::star::uno::Sequence<double>& rKeyStops ) :
|
||||||
|
maKeyStops(rKeyStops.getLength()),
|
||||||
|
mnLastIndex(0)
|
||||||
|
{
|
||||||
|
std::copy( rKeyStops.getConstArray(),
|
||||||
|
rKeyStops.getConstArray()+rKeyStops.getLength(),
|
||||||
|
maKeyStops.begin() );
|
||||||
|
validateInput(maKeyStops);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyStopLerp::ResultType KeyStopLerp::lerp(double fAlpha) const
|
||||||
|
{
|
||||||
|
// cached value still okay?
|
||||||
|
if( maKeyStops.at(mnLastIndex) < fAlpha ||
|
||||||
|
maKeyStops.at(mnLastIndex+1) >= fAlpha )
|
||||||
|
{
|
||||||
|
// nope, find new index
|
||||||
|
mnLastIndex = std::min<std::ptrdiff_t>(
|
||||||
|
maKeyStops.size()-2,
|
||||||
|
// range is ensured by max below
|
||||||
|
std::max<std::ptrdiff_t>(
|
||||||
|
0,
|
||||||
|
std::distance( maKeyStops.begin(),
|
||||||
|
std::lower_bound( maKeyStops.begin(),
|
||||||
|
maKeyStops.end(),
|
||||||
|
fAlpha )) - 1 ));
|
||||||
|
}
|
||||||
|
|
||||||
|
// lerp between stop and stop+1
|
||||||
|
const double fRawLerp=
|
||||||
|
(fAlpha-maKeyStops.at(mnLastIndex)) /
|
||||||
|
(maKeyStops.at(mnLastIndex+1) - maKeyStops.at(mnLastIndex));
|
||||||
|
|
||||||
|
// clamp to permissible range (input fAlpha might be
|
||||||
|
// everything)
|
||||||
|
return ResultType(
|
||||||
|
mnLastIndex,
|
||||||
|
clamp(fRawLerp,0.0,1.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -44,6 +44,7 @@ ENABLE_EXCEPTIONS=TRUE
|
|||||||
SLOFILES= $(SLO)$/canvastools.obj \
|
SLOFILES= $(SLO)$/canvastools.obj \
|
||||||
$(SLO)$/gradienttools.obj \
|
$(SLO)$/gradienttools.obj \
|
||||||
$(SLO)$/debugplotter.obj \
|
$(SLO)$/debugplotter.obj \
|
||||||
|
$(SLO)$/keystoplerp.obj \
|
||||||
$(SLO)$/liangbarsky.obj \
|
$(SLO)$/liangbarsky.obj \
|
||||||
$(SLO)$/tools.obj \
|
$(SLO)$/tools.obj \
|
||||||
$(SLO)$/unopolypolygon.obj
|
$(SLO)$/unopolypolygon.obj
|
||||||
|
119
basegfx/test/basegfxtools.cxx
Normal file
119
basegfx/test/basegfxtools.cxx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* 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: basegfx2d.cxx,v $
|
||||||
|
* $Revision: 1.14 $
|
||||||
|
*
|
||||||
|
* 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_basegfx.hxx"
|
||||||
|
// autogenerated file with codegen.pl
|
||||||
|
|
||||||
|
#include <cppunit/simpleheader.hxx>
|
||||||
|
|
||||||
|
#include <basegfx/tools/keystoplerp.hxx>
|
||||||
|
#include <basegfx/numeric/ftools.hxx>
|
||||||
|
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
|
using namespace ::basegfx;
|
||||||
|
using namespace ::boost::tuples;
|
||||||
|
|
||||||
|
namespace basegfxtools
|
||||||
|
{
|
||||||
|
|
||||||
|
class KeyStopLerpTest : public CppUnit::TestFixture
|
||||||
|
{
|
||||||
|
tools::KeyStopLerp maKeyStops;
|
||||||
|
|
||||||
|
static std::vector<double> getTestVector()
|
||||||
|
{
|
||||||
|
std::vector<double> aStops(3);
|
||||||
|
aStops[0] = 0.1;
|
||||||
|
aStops[1] = 0.5;
|
||||||
|
aStops[2] = 0.9;
|
||||||
|
return aStops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
KeyStopLerpTest() :
|
||||||
|
maKeyStops(getTestVector())
|
||||||
|
{}
|
||||||
|
|
||||||
|
void setUp()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
double fAlpha;
|
||||||
|
std::ptrdiff_t nIndex;
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(-1.0);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("-1.0", nIndex==0 && fAlpha==0.0);
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(0.1);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.1", nIndex==0 && fAlpha==0.0);
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(0.3);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.3", nIndex==0 && fTools::equal(fAlpha,0.5));
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(0.5);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.5", nIndex==0 && fTools::equal(fAlpha,1.0));
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(0.51);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fTools::equal(fAlpha,0.025));
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(0.9);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fTools::equal(fAlpha,1.0));
|
||||||
|
|
||||||
|
tie(nIndex,fAlpha) = maKeyStops.lerp(1.0);
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fAlpha==1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the following lines only, if you add, remove or rename
|
||||||
|
// member functions of the current class,
|
||||||
|
// because these macros are need by auto register mechanism.
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE(KeyStopLerpTest);
|
||||||
|
CPPUNIT_TEST(test);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfxtools::KeyStopLerpTest, "basegfxtools");
|
||||||
|
} // namespace basegfxtools
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// this macro creates an empty function, which will called by the RegisterAllFunctions()
|
||||||
|
// to let the user the possibility to also register some functions by hand.
|
||||||
|
// NOADDITIONAL;
|
||||||
|
|
@@ -46,6 +46,7 @@ SHL1OBJS= \
|
|||||||
$(SLO)$/basegfx1d.obj \
|
$(SLO)$/basegfx1d.obj \
|
||||||
$(SLO)$/basegfx2d.obj \
|
$(SLO)$/basegfx2d.obj \
|
||||||
$(SLO)$/basegfx3d.obj \
|
$(SLO)$/basegfx3d.obj \
|
||||||
|
$(SLO)$/basegfxtools.obj \
|
||||||
$(SLO)$/testtools.obj
|
$(SLO)$/testtools.obj
|
||||||
|
|
||||||
# linking statically against basegfx parts
|
# linking statically against basegfx parts
|
||||||
|
@@ -33,11 +33,11 @@
|
|||||||
|
|
||||||
#include <rtl/ref.hxx>
|
#include <rtl/ref.hxx>
|
||||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||||
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||||
#include <com/sun/star/util/XUpdatable.hpp>
|
#include <com/sun/star/util/XUpdatable.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XColorSpace.hpp>
|
#include <com/sun/star/rendering/XColorSpace.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
|
|
||||||
#include <canvas/parametricpolypolygon.hxx>
|
#include <canvas/parametricpolypolygon.hxx>
|
||||||
#include <canvas/propertysethelper.hxx>
|
#include <canvas/propertysethelper.hxx>
|
||||||
@@ -50,8 +50,7 @@ namespace canvas
|
|||||||
/** Helper template base class for XGraphicDevice implementations.
|
/** Helper template base class for XGraphicDevice implementations.
|
||||||
|
|
||||||
This base class provides partial implementations of the
|
This base class provides partial implementations of the
|
||||||
XGraphicDevice-related interface, such as
|
XGraphicDevice-related interface, such as XColorSpace.
|
||||||
XParametricPolyPolygon2DFactory and XColorSpace.
|
|
||||||
|
|
||||||
This template basically interposes itself between the full
|
This template basically interposes itself between the full
|
||||||
interface you implement (i.e. not restricted to XGraphicDevice
|
interface you implement (i.e. not restricted to XGraphicDevice
|
||||||
@@ -249,7 +248,7 @@ namespace canvas
|
|||||||
return maDeviceHelper.createVolatileAlphaBitmap( this, size );
|
return maDeviceHelper.createVolatileAlphaBitmap( this, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2DFactory > SAL_CALL getParametricPolyPolygonFactory( ) throw (::com::sun::star::uno::RuntimeException)
|
virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > SAL_CALL getParametricPolyPolygonFactory( ) throw (::com::sun::star::uno::RuntimeException)
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -268,79 +267,26 @@ namespace canvas
|
|||||||
return maDeviceHelper.enterFullScreenMode( bEnter );
|
return maDeviceHelper.enterFullScreenMode( bEnter );
|
||||||
}
|
}
|
||||||
|
|
||||||
// XParametricPolyPolygon2DFactory
|
// XMultiServiceFactory
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createLinearHorizontalGradient( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors, const ::com::sun::star::uno::Sequence< double >& stops ) throw (::com::sun::star::lang::IllegalArgumentException,
|
virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
{
|
||||||
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
||||||
ParametricPolyPolygon::createLinearHorizontalGradient( this,
|
ParametricPolyPolygon::create(this,
|
||||||
colors,
|
aServiceSpecifier,
|
||||||
stops ) );
|
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createAxialHorizontalGradient( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors, const ::com::sun::star::uno::Sequence< double >& stops ) throw (::com::sun::star::lang::IllegalArgumentException,
|
virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::rtl::OUString& aServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
{
|
||||||
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
||||||
ParametricPolyPolygon::createAxialHorizontalGradient( this,
|
ParametricPolyPolygon::create(this,
|
||||||
colors,
|
aServiceSpecifier,
|
||||||
stops ) );
|
Arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createEllipticalGradient( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors, const ::com::sun::star::uno::Sequence< double >& stops, const ::com::sun::star::geometry::RealRectangle2D& boundRect ) throw (::com::sun::star::lang::IllegalArgumentException,
|
virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames( ) throw (::com::sun::star::uno::RuntimeException)
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
{
|
||||||
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
return ParametricPolyPolygon::getAvailableServiceNames();
|
||||||
ParametricPolyPolygon::createEllipticalGradient( this,
|
|
||||||
colors,
|
|
||||||
stops,
|
|
||||||
boundRect ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createRectangularGradient( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors, const ::com::sun::star::uno::Sequence< double >& stops, const ::com::sun::star::geometry::RealRectangle2D& boundRect ) throw (::com::sun::star::lang::IllegalArgumentException,
|
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
|
||||||
return ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D >(
|
|
||||||
ParametricPolyPolygon::createRectangularGradient( this,
|
|
||||||
colors,
|
|
||||||
stops,
|
|
||||||
boundRect ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createVerticalLinesHatch( const ::com::sun::star::uno::Sequence< double >& /*leftColor*/,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& /*rightColor*/ ) throw (::com::sun::star::lang::IllegalArgumentException,
|
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
|
||||||
// TODO(F1): hatch factory NYI
|
|
||||||
return ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2D >();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createOrthogonalLinesHatch( const ::com::sun::star::uno::Sequence< double >& /*leftTopColor*/,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& /*rightBottomColor*/ ) throw (::com::sun::star::lang::IllegalArgumentException,
|
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
|
||||||
// TODO(F1): hatch factory NYI
|
|
||||||
return ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2D >();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createThreeCrossingLinesHatch( const ::com::sun::star::uno::Sequence< double >& /*startColor*/,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& /*endColor*/ ) throw (::com::sun::star::lang::IllegalArgumentException,
|
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
|
||||||
// TODO(F1): hatch factory NYI
|
|
||||||
return ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2D >();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XParametricPolyPolygon2D > SAL_CALL createFourCrossingLinesHatch( const ::com::sun::star::uno::Sequence< double >& /*startColor*/,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& /*endColor*/ ) throw (::com::sun::star::lang::IllegalArgumentException,
|
|
||||||
::com::sun::star::uno::RuntimeException)
|
|
||||||
{
|
|
||||||
// TODO(F1): hatch factory NYI
|
|
||||||
return ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2D >();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -417,28 +417,6 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange );
|
::basegfx::B2IRange spritePixelAreaFromB2DRange( const ::basegfx::B2DRange& rRange );
|
||||||
|
|
||||||
/** This method clamps the given value to the specified range
|
|
||||||
|
|
||||||
@param val
|
|
||||||
The value to clamp
|
|
||||||
|
|
||||||
@param minVal
|
|
||||||
The minimal value val is allowed to attain
|
|
||||||
|
|
||||||
@param maxVal
|
|
||||||
The maximal value val is allowed to attain
|
|
||||||
|
|
||||||
@return the clamped value
|
|
||||||
*/
|
|
||||||
template< typename T > T clamp( T val,
|
|
||||||
T minVal,
|
|
||||||
T maxVal )
|
|
||||||
{
|
|
||||||
return ::std::max( minVal,
|
|
||||||
::std::min( maxVal,
|
|
||||||
val ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve various internal properties of the actual canvas implementation.
|
/** Retrieve various internal properties of the actual canvas implementation.
|
||||||
|
|
||||||
This method retrieves a bunch of internal, implementation-
|
This method retrieves a bunch of internal, implementation-
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#include <com/sun/star/lang/XServiceInfo.hpp>
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
#include <com/sun/star/rendering/XParametricPolyPolygon2D.hpp>
|
||||||
#include <cppuhelper/compbase2.hxx>
|
#include <cppuhelper/compbase2.hxx>
|
||||||
#include <comphelper/broadcasthelper.hxx>
|
#include <comphelper/broadcasthelper.hxx>
|
||||||
#include <basegfx/polygon/b2dpolygon.hxx>
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
||||||
@@ -62,7 +62,6 @@ namespace canvas
|
|||||||
enum GradientType
|
enum GradientType
|
||||||
{
|
{
|
||||||
GRADIENT_LINEAR,
|
GRADIENT_LINEAR,
|
||||||
GRADIENT_AXIAL,
|
|
||||||
GRADIENT_ELLIPTICAL,
|
GRADIENT_ELLIPTICAL,
|
||||||
GRADIENT_RECTANGULAR
|
GRADIENT_RECTANGULAR
|
||||||
};
|
};
|
||||||
@@ -103,24 +102,11 @@ namespace canvas
|
|||||||
const GradientType meType;
|
const GradientType meType;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ParametricPolyPolygon* createLinearHorizontalGradient( const ::com::sun::star::uno::Reference<
|
static ::com::sun::star::uno::Sequence< ::rtl::OUString > getAvailableServiceNames();
|
||||||
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
static ParametricPolyPolygon* create(
|
||||||
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
||||||
const ::com::sun::star::uno::Sequence< double >& stops );
|
const ::rtl::OUString& rServiceName,
|
||||||
static ParametricPolyPolygon* createAxialHorizontalGradient( const ::com::sun::star::uno::Reference<
|
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rArgs );
|
||||||
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
|
||||||
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& stops );
|
|
||||||
static ParametricPolyPolygon* createEllipticalGradient( const ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
|
||||||
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& stops,
|
|
||||||
const ::com::sun::star::geometry::RealRectangle2D& boundRect );
|
|
||||||
static ParametricPolyPolygon* createRectangularGradient( const ::com::sun::star::uno::Reference<
|
|
||||||
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
|
||||||
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
|
||||||
const ::com::sun::star::uno::Sequence< double >& stops,
|
|
||||||
const ::com::sun::star::geometry::RealRectangle2D& boundRect );
|
|
||||||
|
|
||||||
/// Dispose all internal references
|
/// Dispose all internal references
|
||||||
virtual void SAL_CALL disposing();
|
virtual void SAL_CALL disposing();
|
||||||
@@ -143,6 +129,20 @@ namespace canvas
|
|||||||
~ParametricPolyPolygon(); // we're a ref-counted UNO class. _We_ destroy ourselves.
|
~ParametricPolyPolygon(); // we're a ref-counted UNO class. _We_ destroy ourselves.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static ParametricPolyPolygon* createLinearHorizontalGradient( const ::com::sun::star::uno::Reference<
|
||||||
|
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
||||||
|
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
||||||
|
const ::com::sun::star::uno::Sequence< double >& stops );
|
||||||
|
static ParametricPolyPolygon* createEllipticalGradient( const ::com::sun::star::uno::Reference<
|
||||||
|
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
||||||
|
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
||||||
|
const ::com::sun::star::uno::Sequence< double >& stops,
|
||||||
|
double fAspect );
|
||||||
|
static ParametricPolyPolygon* createRectangularGradient( const ::com::sun::star::uno::Reference<
|
||||||
|
::com::sun::star::rendering::XGraphicDevice >& rDevice,
|
||||||
|
const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& colors,
|
||||||
|
const ::com::sun::star::uno::Sequence< double >& stops,
|
||||||
|
double fAspect );
|
||||||
|
|
||||||
/// Private, because objects can only be created from the static factories
|
/// Private, because objects can only be created from the static factories
|
||||||
ParametricPolyPolygon( const ::com::sun::star::uno::Reference<
|
ParametricPolyPolygon( const ::com::sun::star::uno::Reference<
|
||||||
|
@@ -44,7 +44,6 @@
|
|||||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
|
|
||||||
#include <cppuhelper/compbase7.hxx>
|
#include <cppuhelper/compbase7.hxx>
|
||||||
#include <comphelper/uno3.hxx>
|
#include <comphelper/uno3.hxx>
|
||||||
@@ -68,7 +67,7 @@ namespace cairocanvas
|
|||||||
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
|
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
|
||||||
::com::sun::star::rendering::XIntegerBitmap,
|
::com::sun::star::rendering::XIntegerBitmap,
|
||||||
::com::sun::star::rendering::XGraphicDevice,
|
::com::sun::star::rendering::XGraphicDevice,
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
|
::com::sun::star::lang::XMultiServiceFactory,
|
||||||
::com::sun::star::util::XUpdatable,
|
::com::sun::star::util::XUpdatable,
|
||||||
::com::sun::star::beans::XPropertySet,
|
::com::sun::star::beans::XPropertySet,
|
||||||
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
|
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
|
||||||
|
@@ -56,6 +56,8 @@
|
|||||||
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
||||||
#include <basegfx/polygon/b2dpolygontools.hxx>
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
||||||
#include <basegfx/tools/canvastools.hxx>
|
#include <basegfx/tools/canvastools.hxx>
|
||||||
|
#include <basegfx/tools/keystoplerp.hxx>
|
||||||
|
#include <basegfx/tools/lerp.hxx>
|
||||||
|
|
||||||
#include <comphelper/sequence.hxx>
|
#include <comphelper/sequence.hxx>
|
||||||
#include <cppuhelper/compbase1.hxx>
|
#include <cppuhelper/compbase1.hxx>
|
||||||
@@ -73,6 +75,7 @@
|
|||||||
#include "cairo_canvashelper.hxx"
|
#include "cairo_canvashelper.hxx"
|
||||||
#include "cairo_canvasbitmap.hxx"
|
#include "cairo_canvasbitmap.hxx"
|
||||||
|
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace ::cairo;
|
using namespace ::cairo;
|
||||||
@@ -122,9 +125,29 @@ namespace cairocanvas
|
|||||||
mpCairo = pSurface->getCairo();
|
mpCairo = pSurface->getCairo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setColor( Cairo* pCairo,
|
||||||
|
const uno::Sequence<double>& rColor )
|
||||||
|
{
|
||||||
|
if( rColor.getLength() > 3 )
|
||||||
|
{
|
||||||
|
const double alpha = rColor[3];
|
||||||
|
|
||||||
|
cairo_set_source_rgba( pCairo,
|
||||||
|
alpha*rColor[0],
|
||||||
|
alpha*rColor[1],
|
||||||
|
alpha*rColor[2],
|
||||||
|
alpha );
|
||||||
|
}
|
||||||
|
else if( rColor.getLength() == 3 )
|
||||||
|
cairo_set_source_rgb( pCairo,
|
||||||
|
rColor[0],
|
||||||
|
rColor[1],
|
||||||
|
rColor[2] );
|
||||||
|
}
|
||||||
|
|
||||||
void CanvasHelper::useStates( const rendering::ViewState& viewState,
|
void CanvasHelper::useStates( const rendering::ViewState& viewState,
|
||||||
const rendering::RenderState& renderState,
|
const rendering::RenderState& renderState,
|
||||||
bool setColor )
|
bool bSetColor )
|
||||||
{
|
{
|
||||||
Matrix aViewMatrix;
|
Matrix aViewMatrix;
|
||||||
Matrix aRenderMatrix;
|
Matrix aRenderMatrix;
|
||||||
@@ -158,19 +181,8 @@ namespace cairocanvas
|
|||||||
OSL_TRACE ("render clip END");
|
OSL_TRACE ("render clip END");
|
||||||
}
|
}
|
||||||
|
|
||||||
if( setColor ) {
|
if( bSetColor )
|
||||||
if( renderState.DeviceColor.getLength() > 3 )
|
setColor(mpCairo.get(),renderState.DeviceColor);
|
||||||
cairo_set_source_rgba( mpCairo.get(),
|
|
||||||
renderState.DeviceColor [0],
|
|
||||||
renderState.DeviceColor [1],
|
|
||||||
renderState.DeviceColor [2],
|
|
||||||
renderState.DeviceColor [3] );
|
|
||||||
else if (renderState.DeviceColor.getLength() == 3)
|
|
||||||
cairo_set_source_rgb( mpCairo.get(),
|
|
||||||
renderState.DeviceColor [0],
|
|
||||||
renderState.DeviceColor [1],
|
|
||||||
renderState.DeviceColor [2] );
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER );
|
cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER );
|
||||||
switch( renderState.CompositeOperation )
|
switch( renderState.CompositeOperation )
|
||||||
@@ -665,11 +677,33 @@ namespace cairocanvas
|
|||||||
double alpha = rColor[3];
|
double alpha = rColor[3];
|
||||||
// cairo expects premultiplied alpha
|
// cairo expects premultiplied alpha
|
||||||
cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha );
|
cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha );
|
||||||
//cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0], rColor[1], rColor[2], alpha );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha)
|
||||||
|
{
|
||||||
|
if( rLeft.getLength() == 3 )
|
||||||
|
{
|
||||||
|
uno::Sequence<double> aRes(3);
|
||||||
|
aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
|
||||||
|
aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
|
||||||
|
aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
|
||||||
|
return aRes;
|
||||||
|
}
|
||||||
|
else if( rLeft.getLength() == 4 )
|
||||||
|
{
|
||||||
|
uno::Sequence<double> aRes(4);
|
||||||
|
aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
|
||||||
|
aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
|
||||||
|
aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
|
||||||
|
aRes[3] = basegfx::tools::lerp(rLeft[3],rRight[3],fAlpha);
|
||||||
|
return aRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uno::Sequence<double>();
|
||||||
|
}
|
||||||
|
|
||||||
static Pattern* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon& rPolygon )
|
static Pattern* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon& rPolygon )
|
||||||
{
|
{
|
||||||
Pattern* pPattern = NULL;
|
Pattern* pPattern = NULL;
|
||||||
@@ -678,7 +712,6 @@ namespace cairocanvas
|
|||||||
|
|
||||||
// undef macros from vclenum.hxx which conflicts with GradientType enum values
|
// undef macros from vclenum.hxx which conflicts with GradientType enum values
|
||||||
#undef GRADIENT_LINEAR
|
#undef GRADIENT_LINEAR
|
||||||
#undef GRADIENT_AXIAL
|
|
||||||
#undef GRADIENT_ELLIPTICAL
|
#undef GRADIENT_ELLIPTICAL
|
||||||
|
|
||||||
switch( aValues.meType ) {
|
switch( aValues.meType ) {
|
||||||
@@ -691,26 +724,17 @@ namespace cairocanvas
|
|||||||
addColorStops( pPattern, aValues.maColors, aValues.maStops );
|
addColorStops( pPattern, aValues.maColors, aValues.maStops );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// FIXME: NYI
|
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
|
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL:
|
|
||||||
x0 = 0;
|
|
||||||
y0 = 0;
|
|
||||||
x1 = 1;
|
|
||||||
y1 = 0;
|
|
||||||
pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 );
|
|
||||||
addColorStops( pPattern, aValues.maColors, aValues.maStops );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
|
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
|
||||||
cx = 0.5;
|
cx = 0;
|
||||||
cy = 0.5;
|
cy = 0;
|
||||||
r0 = 0;
|
r0 = 0;
|
||||||
r1 = 0.5;
|
r1 = 1;
|
||||||
|
|
||||||
pPattern = cairo_pattern_create_radial( cx, cy, r0, cx, cy, r1 );
|
pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 );
|
||||||
addColorStops( pPattern, aValues.maColors, aValues.maStops, true );
|
addColorStops( pPattern, aValues.maColors, aValues.maStops, true );
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pPattern;
|
return pPattern;
|
||||||
@@ -719,7 +743,8 @@ namespace cairocanvas
|
|||||||
static void doOperation( Operation aOperation,
|
static void doOperation( Operation aOperation,
|
||||||
Cairo* pCairo,
|
Cairo* pCairo,
|
||||||
const uno::Sequence< rendering::Texture >* pTextures,
|
const uno::Sequence< rendering::Texture >* pTextures,
|
||||||
const SurfaceProviderRef& pDevice )
|
const SurfaceProviderRef& pDevice,
|
||||||
|
const basegfx::B2DRange& rBounds )
|
||||||
{
|
{
|
||||||
switch( aOperation ) {
|
switch( aOperation ) {
|
||||||
case Fill:
|
case Fill:
|
||||||
@@ -790,19 +815,70 @@ namespace cairocanvas
|
|||||||
cairo_matrix_init( &aTextureMatrix,
|
cairo_matrix_init( &aTextureMatrix,
|
||||||
aTransform.m00, aTransform.m10, aTransform.m01,
|
aTransform.m00, aTransform.m10, aTransform.m01,
|
||||||
aTransform.m11, aTransform.m02, aTransform.m12);
|
aTransform.m11, aTransform.m02, aTransform.m12);
|
||||||
Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
|
if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR )
|
||||||
|
{
|
||||||
if( pPattern ) {
|
// no general path gradient yet in cairo; emulate then
|
||||||
OSL_TRACE( "filling with pattern" );
|
|
||||||
|
|
||||||
cairo_save( pCairo );
|
cairo_save( pCairo );
|
||||||
|
cairo_clip( pCairo );
|
||||||
|
|
||||||
|
// fill bound rect with start color
|
||||||
|
cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(),
|
||||||
|
rBounds.getWidth(), rBounds.getHeight() );
|
||||||
|
setColor(pCairo,pPolyImpl->getValues().maColors[0]);
|
||||||
|
cairo_fill(pCairo);
|
||||||
|
|
||||||
|
cairo_transform( pCairo, &aTextureMatrix );
|
||||||
|
|
||||||
|
// longest line in gradient bound rect
|
||||||
|
const unsigned int nGradientSize(
|
||||||
|
static_cast<unsigned int>(
|
||||||
|
::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) );
|
||||||
|
|
||||||
|
// typical number for pixel of the same color (strip size)
|
||||||
|
const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 );
|
||||||
|
|
||||||
|
// use at least three steps, and at utmost the number of color
|
||||||
|
// steps
|
||||||
|
const unsigned int nStepCount(
|
||||||
|
::std::max(
|
||||||
|
3U,
|
||||||
|
::std::min(
|
||||||
|
nGradientSize / nStripSize,
|
||||||
|
128U )) + 1 );
|
||||||
|
|
||||||
|
const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0];
|
||||||
|
basegfx::tools::KeyStopLerp aLerper(pPolyImpl->getValues().maStops);
|
||||||
|
for( unsigned int i=1; i<nStepCount; ++i )
|
||||||
|
{
|
||||||
|
const double fT( i/double(nStepCount) );
|
||||||
|
|
||||||
|
std::ptrdiff_t nIndex;
|
||||||
|
double fAlpha;
|
||||||
|
boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
|
||||||
|
|
||||||
|
setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha));
|
||||||
|
cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT );
|
||||||
|
cairo_fill(pCairo);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_transform( pCairo, &aTextureMatrix );
|
|
||||||
cairo_set_source( pCairo, pPattern );
|
|
||||||
cairo_fill( pCairo );
|
|
||||||
cairo_restore( pCairo );
|
cairo_restore( pCairo );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
|
||||||
|
|
||||||
cairo_pattern_destroy( pPattern );
|
if( pPattern ) {
|
||||||
|
OSL_TRACE( "filling with pattern" );
|
||||||
|
|
||||||
|
cairo_save( pCairo );
|
||||||
|
|
||||||
|
cairo_transform( pCairo, &aTextureMatrix );
|
||||||
|
cairo_set_source( pCairo, pPattern );
|
||||||
|
cairo_fill( pCairo );
|
||||||
|
cairo_restore( pCairo );
|
||||||
|
|
||||||
|
cairo_pattern_destroy( pPattern );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -935,7 +1011,7 @@ namespace cairocanvas
|
|||||||
|
|
||||||
if( aOperation == Fill && pTextures ) {
|
if( aOperation == Fill && pTextures ) {
|
||||||
cairo_set_matrix( pCairo, &aOrigMatrix );
|
cairo_set_matrix( pCairo, &aOrigMatrix );
|
||||||
doOperation( aOperation, pCairo, pTextures, pDevice );
|
doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
|
||||||
cairo_set_matrix( pCairo, &aIdentityMatrix );
|
cairo_set_matrix( pCairo, &aIdentityMatrix );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -948,7 +1024,7 @@ namespace cairocanvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( bOpToDo && ( aOperation != Fill || !pTextures ) )
|
if( bOpToDo && ( aOperation != Fill || !pTextures ) )
|
||||||
doOperation( aOperation, pCairo, pTextures, pDevice );
|
doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
|
||||||
|
|
||||||
cairo_set_matrix( pCairo, &aOrigMatrix );
|
cairo_set_matrix( pCairo, &aOrigMatrix );
|
||||||
|
|
||||||
@@ -1171,12 +1247,12 @@ namespace cairocanvas
|
|||||||
const rendering::ViewState& viewState,
|
const rendering::ViewState& viewState,
|
||||||
const rendering::RenderState& renderState,
|
const rendering::RenderState& renderState,
|
||||||
const geometry::IntegerSize2D& rSize,
|
const geometry::IntegerSize2D& rSize,
|
||||||
bool /*bModulateColors*/,
|
bool bModulateColors,
|
||||||
bool bHasAlpha )
|
bool bHasAlpha )
|
||||||
{
|
{
|
||||||
SurfaceSharedPtr pSurface=pInputSurface;
|
SurfaceSharedPtr pSurface=pInputSurface;
|
||||||
uno::Reference< rendering::XCachedPrimitive > rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
|
uno::Reference< rendering::XCachedPrimitive > rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
|
||||||
geometry::IntegerSize2D aBitmapSize = rSize;
|
geometry::IntegerSize2D aBitmapSize = rSize;
|
||||||
|
|
||||||
if( mpCairo ) {
|
if( mpCairo ) {
|
||||||
cairo_save( mpCairo.get() );
|
cairo_save( mpCairo.get() );
|
||||||
@@ -1198,38 +1274,38 @@ namespace cairocanvas
|
|||||||
::rtl::math::approxEqual( aMatrix.y0, 0 ) &&
|
::rtl::math::approxEqual( aMatrix.y0, 0 ) &&
|
||||||
basegfx::fround( rSize.Width * aMatrix.xx ) > 8 &&
|
basegfx::fround( rSize.Width * aMatrix.xx ) > 8 &&
|
||||||
basegfx::fround( rSize.Height* aMatrix.yy ) > 8 )
|
basegfx::fround( rSize.Height* aMatrix.yy ) > 8 )
|
||||||
{
|
{
|
||||||
double dWidth, dHeight;
|
double dWidth, dHeight;
|
||||||
|
|
||||||
dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
|
dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
|
||||||
dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
|
dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
|
||||||
aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
|
aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
|
||||||
aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
|
aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
|
||||||
|
|
||||||
SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
|
SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
|
||||||
::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
|
::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
|
||||||
bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
|
bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
|
||||||
CairoSharedPtr pCairo = pScaledSurface->getCairo();
|
CairoSharedPtr pCairo = pScaledSurface->getCairo();
|
||||||
|
|
||||||
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
|
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||||
// add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
|
// add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
|
||||||
cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
|
cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
|
||||||
cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
|
cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
|
||||||
cairo_paint( pCairo.get() );
|
cairo_paint( pCairo.get() );
|
||||||
|
|
||||||
pSurface = pScaledSurface;
|
pSurface = pScaledSurface;
|
||||||
|
|
||||||
aMatrix.xx = aMatrix.yy = 1;
|
aMatrix.xx = aMatrix.yy = 1;
|
||||||
cairo_set_matrix( mpCairo.get(), &aMatrix );
|
cairo_set_matrix( mpCairo.get(), &aMatrix );
|
||||||
|
|
||||||
rv = uno::Reference< rendering::XCachedPrimitive >(
|
rv = uno::Reference< rendering::XCachedPrimitive >(
|
||||||
new CachedBitmap( pSurface, viewState, renderState,
|
new CachedBitmap( pSurface, viewState, renderState,
|
||||||
// cast away const, need to
|
// cast away const, need to
|
||||||
// change refcount (as this is
|
// change refcount (as this is
|
||||||
// ~invisible to client code,
|
// ~invisible to client code,
|
||||||
// still logically const)
|
// still logically const)
|
||||||
const_cast< rendering::XCanvas* >(pCanvas)) );
|
const_cast< rendering::XCanvas* >(pCanvas)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !bHasAlpha && mbHaveAlpha )
|
if( !bHasAlpha && mbHaveAlpha )
|
||||||
{
|
{
|
||||||
@@ -1270,7 +1346,11 @@ namespace cairocanvas
|
|||||||
cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
|
cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
|
||||||
cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height );
|
cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height );
|
||||||
cairo_clip( mpCairo.get() );
|
cairo_clip( mpCairo.get() );
|
||||||
cairo_paint( mpCairo.get() );
|
|
||||||
|
if( bModulateColors )
|
||||||
|
cairo_paint_with_alpha( mpCairo.get(), renderState.DeviceColor[3] );
|
||||||
|
else
|
||||||
|
cairo_paint( mpCairo.get() );
|
||||||
cairo_restore( mpCairo.get() );
|
cairo_restore( mpCairo.get() );
|
||||||
} else
|
} else
|
||||||
OSL_TRACE ("CanvasHelper called after it was disposed");
|
OSL_TRACE ("CanvasHelper called after it was disposed");
|
||||||
@@ -1309,15 +1389,35 @@ namespace cairocanvas
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* ,
|
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
|
||||||
const uno::Reference< rendering::XBitmap >& /*xBitmap*/,
|
const uno::Reference< rendering::XBitmap >& xBitmap,
|
||||||
const rendering::ViewState& /*viewState*/,
|
const rendering::ViewState& viewState,
|
||||||
const rendering::RenderState& /*renderState*/ )
|
const rendering::RenderState& renderState )
|
||||||
{
|
{
|
||||||
// TODO(F3): Implement modulated bitmap!
|
#ifdef CAIRO_CANVAS_PERF_TRACE
|
||||||
|
struct timespec aTimer;
|
||||||
|
mxDevice->startPerfTrace( &aTimer );
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO(P1): Provide caching here.
|
uno::Reference< rendering::XCachedPrimitive > rv;
|
||||||
return uno::Reference< rendering::XCachedPrimitive >(NULL);
|
unsigned char* data = NULL;
|
||||||
|
bool bHasAlpha = false;
|
||||||
|
SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
|
||||||
|
geometry::IntegerSize2D aSize = xBitmap->getSize();
|
||||||
|
|
||||||
|
if( pSurface ) {
|
||||||
|
rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, true, bHasAlpha );
|
||||||
|
|
||||||
|
if( data )
|
||||||
|
free( data );
|
||||||
|
} else
|
||||||
|
rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
|
||||||
|
|
||||||
|
#ifdef CAIRO_CANVAS_PERF_TRACE
|
||||||
|
mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
|
uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
|
|
||||||
#include <cppuhelper/compbase9.hxx>
|
#include <cppuhelper/compbase9.hxx>
|
||||||
#include <comphelper/uno3.hxx>
|
#include <comphelper/uno3.hxx>
|
||||||
@@ -66,7 +65,7 @@ namespace cairocanvas
|
|||||||
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
|
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
|
||||||
::com::sun::star::rendering::XIntegerBitmap,
|
::com::sun::star::rendering::XIntegerBitmap,
|
||||||
::com::sun::star::rendering::XGraphicDevice,
|
::com::sun::star::rendering::XGraphicDevice,
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
|
::com::sun::star::lang::XMultiServiceFactory,
|
||||||
::com::sun::star::rendering::XBufferController,
|
::com::sun::star::rendering::XBufferController,
|
||||||
::com::sun::star::awt::XWindowListener,
|
::com::sun::star::awt::XWindowListener,
|
||||||
::com::sun::star::util::XUpdatable,
|
::com::sun::star::util::XUpdatable,
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||||
|
|
||||||
#include <cppuhelper/compbase8.hxx>
|
#include <cppuhelper/compbase8.hxx>
|
||||||
#include <comphelper/uno3.hxx>
|
#include <comphelper/uno3.hxx>
|
||||||
@@ -60,7 +60,7 @@ namespace nullcanvas
|
|||||||
typedef ::cppu::WeakComponentImplHelper8< ::com::sun::star::rendering::XSpriteCanvas,
|
typedef ::cppu::WeakComponentImplHelper8< ::com::sun::star::rendering::XSpriteCanvas,
|
||||||
::com::sun::star::rendering::XIntegerBitmap,
|
::com::sun::star::rendering::XIntegerBitmap,
|
||||||
::com::sun::star::rendering::XGraphicDevice,
|
::com::sun::star::rendering::XGraphicDevice,
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
|
::com::sun::star::lang::XMultiServiceFactory,
|
||||||
::com::sun::star::rendering::XBufferController,
|
::com::sun::star::rendering::XBufferController,
|
||||||
::com::sun::star::awt::XWindowListener,
|
::com::sun::star::awt::XWindowListener,
|
||||||
::com::sun::star::beans::XPropertySet,
|
::com::sun::star::beans::XPropertySet,
|
||||||
|
@@ -53,6 +53,87 @@ using namespace ::com::sun::star;
|
|||||||
|
|
||||||
namespace canvas
|
namespace canvas
|
||||||
{
|
{
|
||||||
|
uno::Sequence<rtl::OUString> ParametricPolyPolygon::getAvailableServiceNames()
|
||||||
|
{
|
||||||
|
uno::Sequence<rtl::OUString> aRet(3);
|
||||||
|
aRet[0] = rtl::OUString::createFromAscii("LinearGradient");
|
||||||
|
aRet[1] = rtl::OUString::createFromAscii("EllipticalGradient");
|
||||||
|
aRet[2] = rtl::OUString::createFromAscii("RectangularGradient");
|
||||||
|
|
||||||
|
return aRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParametricPolyPolygon* ParametricPolyPolygon::create(
|
||||||
|
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||||
|
const ::rtl::OUString& rServiceName,
|
||||||
|
const uno::Sequence< uno::Any >& rArgs )
|
||||||
|
{
|
||||||
|
uno::Sequence< uno::Sequence< double > > colorSequence(2);
|
||||||
|
uno::Sequence< double > colorStops(2);
|
||||||
|
double fAspectRatio=1.0;
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
uno::Sequence< rendering::RGBColor > rgbColors(1);
|
||||||
|
rgbColors[0] = rendering::RGBColor(0,0,0);
|
||||||
|
colorSequence[0] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
|
||||||
|
rgbColors[0] = rendering::RGBColor(1,1,1);
|
||||||
|
colorSequence[1] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
|
||||||
|
colorStops[0] = 0;
|
||||||
|
colorStops[1] = 1;
|
||||||
|
|
||||||
|
// extract args
|
||||||
|
for( sal_Int32 i=0; i<rArgs.getLength(); ++i )
|
||||||
|
{
|
||||||
|
beans::PropertyValue aProp;
|
||||||
|
if( (rArgs[i] >>= aProp) )
|
||||||
|
{
|
||||||
|
if( aProp.Name.equalsAscii("Colors") )
|
||||||
|
{
|
||||||
|
aProp.Value >>= colorSequence;
|
||||||
|
}
|
||||||
|
else if( aProp.Name.equalsAscii("Stops") )
|
||||||
|
{
|
||||||
|
aProp.Value >>= colorStops;
|
||||||
|
}
|
||||||
|
else if( aProp.Name.equalsAscii("AspectRatio") )
|
||||||
|
{
|
||||||
|
aProp.Value >>= fAspectRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rServiceName.equalsAscii("LinearGradient") )
|
||||||
|
{
|
||||||
|
return createLinearHorizontalGradient(rDevice, colorSequence, colorStops);
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("EllipticalGradient") )
|
||||||
|
{
|
||||||
|
return createEllipticalGradient(rDevice, colorSequence, colorStops, fAspectRatio);
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("RectangularGradient") )
|
||||||
|
{
|
||||||
|
return createRectangularGradient(rDevice, colorSequence, colorStops, fAspectRatio);
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("VerticalLineHatch") )
|
||||||
|
{
|
||||||
|
// TODO: NYI
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("OrthogonalLinesHatch") )
|
||||||
|
{
|
||||||
|
// TODO: NYI
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("ThreeCrossingLinesHatch") )
|
||||||
|
{
|
||||||
|
// TODO: NYI
|
||||||
|
}
|
||||||
|
else if( rServiceName.equalsAscii("FourCrossingLinesHatch") )
|
||||||
|
{
|
||||||
|
// TODO: NYI
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ParametricPolyPolygon* ParametricPolyPolygon::createLinearHorizontalGradient(
|
ParametricPolyPolygon* ParametricPolyPolygon::createLinearHorizontalGradient(
|
||||||
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||||
const uno::Sequence< uno::Sequence< double > >& colors,
|
const uno::Sequence< uno::Sequence< double > >& colors,
|
||||||
@@ -63,58 +144,35 @@ namespace canvas
|
|||||||
return new ParametricPolyPolygon( rDevice, GRADIENT_LINEAR, colors, stops );
|
return new ParametricPolyPolygon( rDevice, GRADIENT_LINEAR, colors, stops );
|
||||||
}
|
}
|
||||||
|
|
||||||
ParametricPolyPolygon* ParametricPolyPolygon::createAxialHorizontalGradient(
|
|
||||||
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
|
||||||
const uno::Sequence< uno::Sequence< double > >& colors,
|
|
||||||
const uno::Sequence< double >& stops )
|
|
||||||
{
|
|
||||||
// TODO(P2): hold gradient brush statically, and only setup
|
|
||||||
// the colors
|
|
||||||
return new ParametricPolyPolygon( rDevice, GRADIENT_AXIAL, colors, stops );
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
double calcAspectRatio( const geometry::RealRectangle2D& rBoundRect )
|
|
||||||
{
|
|
||||||
const double nWidth( rBoundRect.X2 - rBoundRect.X1 );
|
|
||||||
const double nHeight( rBoundRect.Y2 - rBoundRect.Y1 );
|
|
||||||
|
|
||||||
return ::basegfx::fTools::equalZero( nHeight ) ? 1.0 : fabs( nWidth / nHeight );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParametricPolyPolygon* ParametricPolyPolygon::createEllipticalGradient(
|
ParametricPolyPolygon* ParametricPolyPolygon::createEllipticalGradient(
|
||||||
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||||
const uno::Sequence< uno::Sequence< double > >& colors,
|
const uno::Sequence< uno::Sequence< double > >& colors,
|
||||||
const uno::Sequence< double >& stops,
|
const uno::Sequence< double >& stops,
|
||||||
const geometry::RealRectangle2D& boundRect )
|
double fAspectRatio )
|
||||||
{
|
{
|
||||||
// TODO(P2): hold gradient polygon statically, and only setup
|
// TODO(P2): hold gradient polygon statically, and only setup
|
||||||
// the colors
|
// the colors
|
||||||
return new ParametricPolyPolygon(
|
return new ParametricPolyPolygon(
|
||||||
rDevice,
|
rDevice,
|
||||||
::basegfx::tools::createPolygonFromCircle(
|
::basegfx::tools::createPolygonFromCircle(
|
||||||
::basegfx::B2DPoint( 0.5, 0.5), 0.5 ),
|
::basegfx::B2DPoint(0,0), 1 ),
|
||||||
GRADIENT_ELLIPTICAL,
|
GRADIENT_ELLIPTICAL,
|
||||||
colors, stops,
|
colors, stops, fAspectRatio );
|
||||||
calcAspectRatio( boundRect ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParametricPolyPolygon* ParametricPolyPolygon::createRectangularGradient( const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
ParametricPolyPolygon* ParametricPolyPolygon::createRectangularGradient( const uno::Reference< rendering::XGraphicDevice >& rDevice,
|
||||||
const uno::Sequence< uno::Sequence< double > >& colors,
|
const uno::Sequence< uno::Sequence< double > >& colors,
|
||||||
const uno::Sequence< double >& stops,
|
const uno::Sequence< double >& stops,
|
||||||
const geometry::RealRectangle2D& boundRect )
|
double fAspectRatio )
|
||||||
{
|
{
|
||||||
// TODO(P2): hold gradient polygon statically, and only setup
|
// TODO(P2): hold gradient polygon statically, and only setup
|
||||||
// the colors
|
// the colors
|
||||||
return new ParametricPolyPolygon(
|
return new ParametricPolyPolygon(
|
||||||
rDevice,
|
rDevice,
|
||||||
::basegfx::tools::createPolygonFromRect(
|
::basegfx::tools::createPolygonFromRect(
|
||||||
::basegfx::B2DRectangle( 0.0, 0.0, 1.0, 1.0 ) ),
|
::basegfx::B2DRectangle( -1, -1, 1, 1 ) ),
|
||||||
GRADIENT_RECTANGULAR,
|
GRADIENT_RECTANGULAR,
|
||||||
colors, stops,
|
colors, stops, fAspectRatio );
|
||||||
calcAspectRatio( boundRect ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAL_CALL ParametricPolyPolygon::disposing()
|
void SAL_CALL ParametricPolyPolygon::disposing()
|
||||||
|
@@ -41,7 +41,6 @@
|
|||||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
|
|
||||||
#include <cppuhelper/compbase7.hxx>
|
#include <cppuhelper/compbase7.hxx>
|
||||||
#include <comphelper/uno3.hxx>
|
#include <comphelper/uno3.hxx>
|
||||||
@@ -63,7 +62,7 @@ namespace vclcanvas
|
|||||||
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
|
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
|
||||||
::com::sun::star::rendering::XIntegerBitmap,
|
::com::sun::star::rendering::XIntegerBitmap,
|
||||||
::com::sun::star::rendering::XGraphicDevice,
|
::com::sun::star::rendering::XGraphicDevice,
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
|
::com::sun::star::lang::XMultiServiceFactory,
|
||||||
::com::sun::star::util::XUpdatable,
|
::com::sun::star::util::XUpdatable,
|
||||||
::com::sun::star::beans::XPropertySet,
|
::com::sun::star::beans::XPropertySet,
|
||||||
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
|
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
|
||||||
|
@@ -57,6 +57,8 @@
|
|||||||
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
||||||
#include <basegfx/polygon/b2dlinegeometry.hxx>
|
#include <basegfx/polygon/b2dlinegeometry.hxx>
|
||||||
#include <basegfx/tools/tools.hxx>
|
#include <basegfx/tools/tools.hxx>
|
||||||
|
#include <basegfx/tools/lerp.hxx>
|
||||||
|
#include <basegfx/tools/keystoplerp.hxx>
|
||||||
#include <basegfx/tools/canvastools.hxx>
|
#include <basegfx/tools/canvastools.hxx>
|
||||||
#include <basegfx/numeric/ftools.hxx>
|
#include <basegfx/numeric/ftools.hxx>
|
||||||
|
|
||||||
@@ -65,6 +67,9 @@
|
|||||||
#include <canvas/canvastools.hxx>
|
#include <canvas/canvastools.hxx>
|
||||||
#include <canvas/parametricpolypolygon.hxx>
|
#include <canvas/parametricpolypolygon.hxx>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
#include "spritecanvas.hxx"
|
#include "spritecanvas.hxx"
|
||||||
#include "canvashelper.hxx"
|
#include "canvashelper.hxx"
|
||||||
#include "impltools.hxx"
|
#include "impltools.hxx"
|
||||||
@@ -118,17 +123,13 @@ namespace vclcanvas
|
|||||||
Since most of the code for linear and axial gradients are
|
Since most of the code for linear and axial gradients are
|
||||||
the same, we've a unified method here
|
the same, we've a unified method here
|
||||||
*/
|
*/
|
||||||
void fillGeneralLinearGradient( OutputDevice& rOutDev,
|
void fillLinearGradient( OutputDevice& rOutDev,
|
||||||
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
||||||
const ::Rectangle& rBounds,
|
const ::Rectangle& rBounds,
|
||||||
int nStepCount,
|
unsigned int nStepCount,
|
||||||
const ::Color& rColor1,
|
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||||
const ::Color& rColor2,
|
const std::vector< ::Color >& rColors )
|
||||||
bool bFillNonOverlapping,
|
|
||||||
bool bAxialGradient )
|
|
||||||
{
|
{
|
||||||
(void)bFillNonOverlapping;
|
|
||||||
|
|
||||||
// determine general position of gradient in relation to
|
// determine general position of gradient in relation to
|
||||||
// the bound rect
|
// the bound rect
|
||||||
// =====================================================
|
// =====================================================
|
||||||
@@ -207,36 +208,26 @@ namespace vclcanvas
|
|||||||
// iteratively render all other strips
|
// iteratively render all other strips
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
||||||
// ensure that nStepCount is odd, to have a well-defined
|
// ensure that nStepCount matches color stop parity, to
|
||||||
// middle index for axial gradients.
|
// have a well-defined middle color e.g. for axial
|
||||||
if( bAxialGradient && !(nStepCount % 2) )
|
// gradients.
|
||||||
|
if( (rColors.size() % 2) != (nStepCount % 2) )
|
||||||
++nStepCount;
|
++nStepCount;
|
||||||
|
|
||||||
const int nStepCountHalved( nStepCount / 2 );
|
basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
|
||||||
|
|
||||||
// only iterate nStepCount-1 steps, as the last strip is
|
// only iterate nStepCount-1 steps, as the last strip is
|
||||||
// explicitely painted below
|
// explicitely painted below
|
||||||
for( int i=0; i<nStepCount-1; ++i )
|
for( unsigned int i=0; i<nStepCount-1; ++i )
|
||||||
{
|
{
|
||||||
// lerp color
|
std::ptrdiff_t nIndex;
|
||||||
if( bAxialGradient )
|
double fAlpha;
|
||||||
{
|
boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(double(i)/nStepCount);
|
||||||
// axial gradient has a triangle-like interpolation function
|
|
||||||
const int iPrime( i<=nStepCountHalved ? i : nStepCount-i-1);
|
|
||||||
|
|
||||||
rOutDev.SetFillColor(
|
rOutDev.SetFillColor(
|
||||||
Color( (UINT8)(((nStepCountHalved - iPrime)*rColor1.GetRed() + iPrime*rColor2.GetRed())/nStepCountHalved),
|
Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
|
||||||
(UINT8)(((nStepCountHalved - iPrime)*rColor1.GetGreen() + iPrime*rColor2.GetGreen())/nStepCountHalved),
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
|
||||||
(UINT8)(((nStepCountHalved - iPrime)*rColor1.GetBlue() + iPrime*rColor2.GetBlue())/nStepCountHalved) ) );
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// linear gradient has a plain lerp between start and end color
|
|
||||||
rOutDev.SetFillColor(
|
|
||||||
Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
|
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
|
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy right egde of polygon to left edge (and also
|
// copy right egde of polygon to left edge (and also
|
||||||
// copy the closing point)
|
// copy the closing point)
|
||||||
@@ -283,59 +274,18 @@ namespace vclcanvas
|
|||||||
aTempPoly[3] = ::Point( ::basegfx::fround( rPoint4.getX() ),
|
aTempPoly[3] = ::Point( ::basegfx::fround( rPoint4.getX() ),
|
||||||
::basegfx::fround( rPoint4.getY() ) );
|
::basegfx::fround( rPoint4.getY() ) );
|
||||||
|
|
||||||
if( bAxialGradient )
|
rOutDev.SetFillColor( rColors.back() );
|
||||||
rOutDev.SetFillColor( rColor1 );
|
|
||||||
else
|
|
||||||
rOutDev.SetFillColor( rColor2 );
|
|
||||||
|
|
||||||
rOutDev.DrawPolygon( aTempPoly );
|
rOutDev.DrawPolygon( aTempPoly );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void fillLinearGradient( OutputDevice& rOutDev,
|
|
||||||
const ::Color& rColor1,
|
|
||||||
const ::Color& rColor2,
|
|
||||||
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
|
||||||
const ::Rectangle& rBounds,
|
|
||||||
int nStepCount,
|
|
||||||
bool bFillNonOverlapping )
|
|
||||||
{
|
|
||||||
fillGeneralLinearGradient( rOutDev,
|
|
||||||
rTextureTransform,
|
|
||||||
rBounds,
|
|
||||||
nStepCount,
|
|
||||||
rColor1,
|
|
||||||
rColor2,
|
|
||||||
bFillNonOverlapping,
|
|
||||||
false );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void fillAxialGradient( OutputDevice& rOutDev,
|
|
||||||
const ::Color& rColor1,
|
|
||||||
const ::Color& rColor2,
|
|
||||||
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
|
||||||
const ::Rectangle& rBounds,
|
|
||||||
int nStepCount,
|
|
||||||
bool bFillNonOverlapping )
|
|
||||||
{
|
|
||||||
fillGeneralLinearGradient( rOutDev,
|
|
||||||
rTextureTransform,
|
|
||||||
rBounds,
|
|
||||||
nStepCount,
|
|
||||||
rColor1,
|
|
||||||
rColor2,
|
|
||||||
bFillNonOverlapping,
|
|
||||||
true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void fillPolygonalGradient( OutputDevice& rOutDev,
|
void fillPolygonalGradient( OutputDevice& rOutDev,
|
||||||
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
|
||||||
const ::Color& rColor1,
|
|
||||||
const ::Color& rColor2,
|
|
||||||
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
||||||
const ::Rectangle& rBounds,
|
const ::Rectangle& rBounds,
|
||||||
int nStepCount,
|
unsigned int nStepCount,
|
||||||
bool bFillNonOverlapping )
|
bool bFillNonOverlapping,
|
||||||
|
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||||
|
const std::vector< ::Color >& rColors )
|
||||||
{
|
{
|
||||||
const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
|
const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
|
||||||
|
|
||||||
@@ -369,9 +319,6 @@ namespace vclcanvas
|
|||||||
// apply scaling (possibly anisotrophic) to inner polygon
|
// apply scaling (possibly anisotrophic) to inner polygon
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
// move center of scaling to origin
|
|
||||||
aInnerPolygonTransformMatrix.translate( -0.5, -0.5 );
|
|
||||||
|
|
||||||
// scale inner polygon according to aspect ratio: for
|
// scale inner polygon according to aspect ratio: for
|
||||||
// wider-than-tall bounds (nAspectRatio > 1.0), the inner
|
// wider-than-tall bounds (nAspectRatio > 1.0), the inner
|
||||||
// polygon, representing the gradient focus, must have
|
// polygon, representing the gradient focus, must have
|
||||||
@@ -396,9 +343,6 @@ namespace vclcanvas
|
|||||||
aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
|
aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// move origin back to former center of polygon
|
|
||||||
aInnerPolygonTransformMatrix.translate( 0.5, 0.5 );
|
|
||||||
|
|
||||||
// and finally, add texture transform to it.
|
// and finally, add texture transform to it.
|
||||||
aInnerPolygonTransformMatrix *= rTextureTransform;
|
aInnerPolygonTransformMatrix *= rTextureTransform;
|
||||||
|
|
||||||
@@ -406,8 +350,8 @@ namespace vclcanvas
|
|||||||
aInnerPoly.transform( aInnerPolygonTransformMatrix );
|
aInnerPoly.transform( aInnerPolygonTransformMatrix );
|
||||||
|
|
||||||
|
|
||||||
const sal_Int32 nNumPoints( aOuterPoly.count() );
|
const sal_uInt32 nNumPoints( aOuterPoly.count() );
|
||||||
::Polygon aTempPoly( static_cast<USHORT>(nNumPoints+1) );
|
::Polygon aTempPoly( static_cast<USHORT>(nNumPoints+1) );
|
||||||
|
|
||||||
// increase number of steps by one: polygonal gradients have
|
// increase number of steps by one: polygonal gradients have
|
||||||
// the outermost polygon rendered in rColor2, and the
|
// the outermost polygon rendered in rColor2, and the
|
||||||
@@ -425,37 +369,42 @@ namespace vclcanvas
|
|||||||
// color).
|
// color).
|
||||||
++nStepCount;
|
++nStepCount;
|
||||||
|
|
||||||
|
basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
|
||||||
|
|
||||||
if( !bFillNonOverlapping )
|
if( !bFillNonOverlapping )
|
||||||
{
|
{
|
||||||
// fill background
|
// fill background
|
||||||
rOutDev.SetFillColor( rColor1 );
|
rOutDev.SetFillColor( rColors.front() );
|
||||||
rOutDev.DrawRect( rBounds );
|
rOutDev.DrawRect( rBounds );
|
||||||
|
|
||||||
// render polygon
|
// render polygon
|
||||||
// ==============
|
// ==============
|
||||||
|
|
||||||
for( int i=1,p; i<nStepCount; ++i )
|
for( unsigned int i=1,p; i<nStepCount; ++i )
|
||||||
{
|
{
|
||||||
|
const double fT( i/double(nStepCount) );
|
||||||
|
|
||||||
|
std::ptrdiff_t nIndex;
|
||||||
|
double fAlpha;
|
||||||
|
boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
|
||||||
|
|
||||||
// lerp color
|
// lerp color
|
||||||
rOutDev.SetFillColor(
|
rOutDev.SetFillColor(
|
||||||
Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
|
Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
|
||||||
|
|
||||||
// scale and render polygon, by interpolating between
|
// scale and render polygon, by interpolating between
|
||||||
// outer and inner polygon.
|
// outer and inner polygon.
|
||||||
|
|
||||||
// calc interpolation parameter in [0,1] range
|
|
||||||
const double nT( (nStepCount-i)/double(nStepCount) );
|
|
||||||
|
|
||||||
for( p=0; p<nNumPoints; ++p )
|
for( p=0; p<nNumPoints; ++p )
|
||||||
{
|
{
|
||||||
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
|
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
|
||||||
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
|
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
|
||||||
|
|
||||||
aTempPoly[(USHORT)p] = ::Point(
|
aTempPoly[(USHORT)p] = ::Point(
|
||||||
basegfx::fround( (1.0-nT)*rInnerPoint.getX() + nT*rOuterPoint.getX() ),
|
basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
|
||||||
basegfx::fround( (1.0-nT)*rInnerPoint.getY() + nT*rOuterPoint.getY() ) );
|
basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// close polygon explicitely
|
// close polygon explicitely
|
||||||
@@ -489,13 +438,19 @@ namespace vclcanvas
|
|||||||
aTempPolyPoly.Insert( aTempPoly );
|
aTempPolyPoly.Insert( aTempPoly );
|
||||||
aTempPolyPoly.Insert( aTempPoly2 );
|
aTempPolyPoly.Insert( aTempPoly2 );
|
||||||
|
|
||||||
for( int i=0,p; i<nStepCount; ++i )
|
for( unsigned int i=0,p; i<nStepCount; ++i )
|
||||||
{
|
{
|
||||||
|
const double fT( (i+1)/double(nStepCount) );
|
||||||
|
|
||||||
|
std::ptrdiff_t nIndex;
|
||||||
|
double fAlpha;
|
||||||
|
boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
|
||||||
|
|
||||||
// lerp color
|
// lerp color
|
||||||
rOutDev.SetFillColor(
|
rOutDev.SetFillColor(
|
||||||
Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
|
Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
|
||||||
(UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
|
(UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
|
||||||
|
|
||||||
#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
|
#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
|
||||||
if( i && !(i % 10) )
|
if( i && !(i % 10) )
|
||||||
@@ -506,17 +461,14 @@ namespace vclcanvas
|
|||||||
// calculate the inner polygon, which is actually the
|
// calculate the inner polygon, which is actually the
|
||||||
// start of the _next_ color strip. Thus, i+1
|
// start of the _next_ color strip. Thus, i+1
|
||||||
|
|
||||||
// calc interpolation parameter in [0,1] range
|
|
||||||
const double nT( (nStepCount-i-1)/double(nStepCount) );
|
|
||||||
|
|
||||||
for( p=0; p<nNumPoints; ++p )
|
for( p=0; p<nNumPoints; ++p )
|
||||||
{
|
{
|
||||||
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
|
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
|
||||||
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
|
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
|
||||||
|
|
||||||
aTempPoly[(USHORT)p] = ::Point(
|
aTempPoly[(USHORT)p] = ::Point(
|
||||||
basegfx::fround( (1.0-nT)*rInnerPoint.getX() + nT*rOuterPoint.getX() ),
|
basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
|
||||||
basegfx::fround( (1.0-nT)*rInnerPoint.getY() + nT*rOuterPoint.getY() ) );
|
basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// close polygon explicitely
|
// close polygon explicitely
|
||||||
@@ -549,46 +501,33 @@ namespace vclcanvas
|
|||||||
|
|
||||||
void doGradientFill( OutputDevice& rOutDev,
|
void doGradientFill( OutputDevice& rOutDev,
|
||||||
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||||
const ::Color& rColor1,
|
const std::vector< ::Color >& rColors,
|
||||||
const ::Color& rColor2,
|
|
||||||
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
const ::basegfx::B2DHomMatrix& rTextureTransform,
|
||||||
const ::Rectangle& rBounds,
|
const ::Rectangle& rBounds,
|
||||||
int nStepCount,
|
unsigned int nStepCount,
|
||||||
bool bFillNonOverlapping )
|
bool bFillNonOverlapping )
|
||||||
{
|
{
|
||||||
switch( rValues.meType )
|
switch( rValues.meType )
|
||||||
{
|
{
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
|
case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
|
||||||
fillLinearGradient( rOutDev,
|
fillLinearGradient( rOutDev,
|
||||||
rColor1,
|
|
||||||
rColor2,
|
|
||||||
rTextureTransform,
|
rTextureTransform,
|
||||||
rBounds,
|
rBounds,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
bFillNonOverlapping );
|
rValues,
|
||||||
break;
|
rColors );
|
||||||
|
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL:
|
|
||||||
fillAxialGradient( rOutDev,
|
|
||||||
rColor1,
|
|
||||||
rColor2,
|
|
||||||
rTextureTransform,
|
|
||||||
rBounds,
|
|
||||||
nStepCount,
|
|
||||||
bFillNonOverlapping );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
|
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
|
||||||
// FALLTHROUGH intended
|
// FALLTHROUGH intended
|
||||||
case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
|
case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
|
||||||
fillPolygonalGradient( rOutDev,
|
fillPolygonalGradient( rOutDev,
|
||||||
rValues,
|
|
||||||
rColor1,
|
|
||||||
rColor2,
|
|
||||||
rTextureTransform,
|
rTextureTransform,
|
||||||
rBounds,
|
rBounds,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
bFillNonOverlapping );
|
bFillNonOverlapping,
|
||||||
|
rValues,
|
||||||
|
rColors );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -597,11 +536,19 @@ namespace vclcanvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numColorSteps( const ::Color& rColor1, const ::Color& rColor2 )
|
||||||
|
{
|
||||||
|
return ::std::max(
|
||||||
|
labs( rColor1.GetRed() - rColor2.GetRed() ),
|
||||||
|
::std::max(
|
||||||
|
labs( rColor1.GetGreen() - rColor2.GetGreen() ),
|
||||||
|
labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
bool gradientFill( OutputDevice& rOutDev,
|
bool gradientFill( OutputDevice& rOutDev,
|
||||||
OutputDevice* p2ndOutDev,
|
OutputDevice* p2ndOutDev,
|
||||||
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
const ::canvas::ParametricPolyPolygon::Values& rValues,
|
||||||
const ::Color& rColor1,
|
const std::vector< ::Color >& rColors,
|
||||||
const ::Color& rColor2,
|
|
||||||
const PolyPolygon& rPoly,
|
const PolyPolygon& rPoly,
|
||||||
const rendering::ViewState& viewState,
|
const rendering::ViewState& viewState,
|
||||||
const rendering::RenderState& renderState,
|
const rendering::RenderState& renderState,
|
||||||
@@ -646,12 +593,9 @@ namespace vclcanvas
|
|||||||
|
|
||||||
// calc step size
|
// calc step size
|
||||||
// --------------
|
// --------------
|
||||||
const int nColorSteps(
|
int nColorSteps = 0;
|
||||||
::std::max(
|
for( size_t i=0; i<rColors.size()-1; ++i )
|
||||||
labs( rColor1.GetRed() - rColor2.GetRed() ),
|
nColorSteps += numColorSteps(rColors[i],rColors[i+1]);
|
||||||
::std::max(
|
|
||||||
labs( rColor1.GetGreen() - rColor2.GetGreen() ),
|
|
||||||
labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) ) );
|
|
||||||
|
|
||||||
// longest line in gradient bound rect
|
// longest line in gradient bound rect
|
||||||
const int nGradientSize(
|
const int nGradientSize(
|
||||||
@@ -690,8 +634,7 @@ namespace vclcanvas
|
|||||||
rOutDev.IntersectClipRegion( aPolygonDeviceRectOrig );
|
rOutDev.IntersectClipRegion( aPolygonDeviceRectOrig );
|
||||||
doGradientFill( rOutDev,
|
doGradientFill( rOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -704,8 +647,7 @@ namespace vclcanvas
|
|||||||
p2ndOutDev->IntersectClipRegion( aPolygonDeviceRectOrig );
|
p2ndOutDev->IntersectClipRegion( aPolygonDeviceRectOrig );
|
||||||
doGradientFill( *p2ndOutDev,
|
doGradientFill( *p2ndOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -723,8 +665,7 @@ namespace vclcanvas
|
|||||||
|
|
||||||
doGradientFill( rOutDev,
|
doGradientFill( rOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -737,8 +678,7 @@ namespace vclcanvas
|
|||||||
p2ndOutDev->SetClipRegion( aPolyClipRegion );
|
p2ndOutDev->SetClipRegion( aPolyClipRegion );
|
||||||
doGradientFill( *p2ndOutDev,
|
doGradientFill( *p2ndOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -753,8 +693,7 @@ namespace vclcanvas
|
|||||||
rOutDev.SetRasterOp( ROP_XOR );
|
rOutDev.SetRasterOp( ROP_XOR );
|
||||||
doGradientFill( rOutDev,
|
doGradientFill( rOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -765,8 +704,7 @@ namespace vclcanvas
|
|||||||
rOutDev.SetRasterOp( ROP_XOR );
|
rOutDev.SetRasterOp( ROP_XOR );
|
||||||
doGradientFill( rOutDev,
|
doGradientFill( rOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -779,8 +717,7 @@ namespace vclcanvas
|
|||||||
p2ndOutDev->SetRasterOp( ROP_XOR );
|
p2ndOutDev->SetRasterOp( ROP_XOR );
|
||||||
doGradientFill( *p2ndOutDev,
|
doGradientFill( *p2ndOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -791,8 +728,7 @@ namespace vclcanvas
|
|||||||
p2ndOutDev->SetRasterOp( ROP_XOR );
|
p2ndOutDev->SetRasterOp( ROP_XOR );
|
||||||
doGradientFill( *p2ndOutDev,
|
doGradientFill( *p2ndOutDev,
|
||||||
rValues,
|
rValues,
|
||||||
rColor1,
|
rColors,
|
||||||
rColor2,
|
|
||||||
aTextureTransform,
|
aTextureTransform,
|
||||||
aPolygonDeviceRectOrig,
|
aPolygonDeviceRectOrig,
|
||||||
nStepCount,
|
nStepCount,
|
||||||
@@ -855,33 +791,41 @@ namespace vclcanvas
|
|||||||
::canvas::ParametricPolyPolygon* pGradient =
|
::canvas::ParametricPolyPolygon* pGradient =
|
||||||
dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
|
dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
|
||||||
|
|
||||||
if( pGradient )
|
if( pGradient && pGradient->getValues().maColors.getLength() )
|
||||||
{
|
{
|
||||||
// copy state from Gradient polypoly locally
|
// copy state from Gradient polypoly locally
|
||||||
// (given object might change!)
|
// (given object might change!)
|
||||||
const ::canvas::ParametricPolyPolygon::Values& rValues(
|
const ::canvas::ParametricPolyPolygon::Values& rValues(
|
||||||
pGradient->getValues() );
|
pGradient->getValues() );
|
||||||
|
|
||||||
// TODO: use all the colors and place them on given positions/stops
|
if( rValues.maColors.getLength() < 2 )
|
||||||
const ::Color aColor1(
|
{
|
||||||
::vcl::unotools::stdColorSpaceSequenceToColor(
|
rendering::RenderState aTempState=renderState;
|
||||||
rValues.maColors [0] ) );
|
aTempState.DeviceColor = rValues.maColors[0];
|
||||||
const ::Color aColor2(
|
fillPolyPolygon(pCanvas, xPolyPolygon, viewState, aTempState);
|
||||||
::vcl::unotools::stdColorSpaceSequenceToColor(
|
}
|
||||||
rValues.maColors [rValues.maColors.getLength () - 1] ) );
|
else
|
||||||
|
{
|
||||||
|
std::vector< ::Color > aColors(rValues.maColors.getLength());
|
||||||
|
std::transform(&rValues.maColors[0],
|
||||||
|
&rValues.maColors[0]+rValues.maColors.getLength(),
|
||||||
|
aColors.begin(),
|
||||||
|
boost::bind(
|
||||||
|
&vcl::unotools::stdColorSpaceSequenceToColor,
|
||||||
|
_1));
|
||||||
|
|
||||||
// TODO(E1): Return value
|
// TODO(E1): Return value
|
||||||
// TODO(F1): FillRule
|
// TODO(F1): FillRule
|
||||||
gradientFill( mpOutDev->getOutDev(),
|
gradientFill( mpOutDev->getOutDev(),
|
||||||
mp2ndOutDev.get() ? &mp2ndOutDev->getOutDev() : (OutputDevice*)NULL,
|
mp2ndOutDev.get() ? &mp2ndOutDev->getOutDev() : (OutputDevice*)NULL,
|
||||||
rValues,
|
rValues,
|
||||||
aColor1,
|
aColors,
|
||||||
aColor2,
|
aPolyPoly,
|
||||||
aPolyPoly,
|
viewState,
|
||||||
viewState,
|
renderState,
|
||||||
renderState,
|
textures[0],
|
||||||
textures[0],
|
nTransparency );
|
||||||
nTransparency );
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/XBufferController.hpp>
|
#include <com/sun/star/rendering/XBufferController.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
|
|
||||||
#include <cppuhelper/compbase9.hxx>
|
#include <cppuhelper/compbase9.hxx>
|
||||||
#include <comphelper/uno3.hxx>
|
#include <comphelper/uno3.hxx>
|
||||||
@@ -65,7 +64,7 @@ namespace vclcanvas
|
|||||||
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
|
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
|
||||||
::com::sun::star::rendering::XIntegerBitmap,
|
::com::sun::star::rendering::XIntegerBitmap,
|
||||||
::com::sun::star::rendering::XGraphicDevice,
|
::com::sun::star::rendering::XGraphicDevice,
|
||||||
::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
|
::com::sun::star::lang::XMultiServiceFactory,
|
||||||
::com::sun::star::rendering::XBufferController,
|
::com::sun::star::rendering::XBufferController,
|
||||||
::com::sun::star::awt::XWindowListener,
|
::com::sun::star::awt::XWindowListener,
|
||||||
::com::sun::star::util::XUpdatable,
|
::com::sun::star::util::XUpdatable,
|
||||||
|
@@ -49,7 +49,6 @@
|
|||||||
|
|
||||||
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
||||||
#include <com/sun/star/rendering/TexturingMode.hpp>
|
#include <com/sun/star/rendering/TexturingMode.hpp>
|
||||||
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
|
||||||
#include <com/sun/star/uno/Sequence.hxx>
|
#include <com/sun/star/uno/Sequence.hxx>
|
||||||
#include <com/sun/star/geometry/RealPoint2D.hpp>
|
#include <com/sun/star/geometry/RealPoint2D.hpp>
|
||||||
#include <com/sun/star/rendering/ViewState.hpp>
|
#include <com/sun/star/rendering/ViewState.hpp>
|
||||||
@@ -61,6 +60,7 @@
|
|||||||
#include <com/sun/star/rendering/PathJoinType.hpp>
|
#include <com/sun/star/rendering/PathJoinType.hpp>
|
||||||
|
|
||||||
#include <basegfx/tools/canvastools.hxx>
|
#include <basegfx/tools/canvastools.hxx>
|
||||||
|
#include <basegfx/tools/gradienttools.hxx>
|
||||||
#include <basegfx/numeric/ftools.hxx>
|
#include <basegfx/numeric/ftools.hxx>
|
||||||
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
||||||
#include <basegfx/polygon/b2dpolygontools.hxx>
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
||||||
@@ -590,13 +590,12 @@ namespace cppcanvas
|
|||||||
// discernible difference should be visible.
|
// discernible difference should be visible.
|
||||||
nSteps > 64 )
|
nSteps > 64 )
|
||||||
{
|
{
|
||||||
uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory(
|
uno::Reference< lang::XMultiServiceFactory> xFactory(
|
||||||
rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
|
rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
|
||||||
|
|
||||||
if( xFactory.is() )
|
if( xFactory.is() )
|
||||||
{
|
{
|
||||||
::basegfx::B2DHomMatrix aTextureTransformation;
|
rendering::Texture aTexture;
|
||||||
rendering::Texture aTexture;
|
|
||||||
|
|
||||||
aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
|
aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
|
||||||
aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
|
aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
|
||||||
@@ -631,242 +630,118 @@ namespace cppcanvas
|
|||||||
uno::Sequence< uno::Sequence < double > > aColors(2);
|
uno::Sequence< uno::Sequence < double > > aColors(2);
|
||||||
uno::Sequence< double > aStops(2);
|
uno::Sequence< double > aStops(2);
|
||||||
|
|
||||||
aStops[0] = 0.0;
|
if( rGradient.GetStyle() == GRADIENT_AXIAL )
|
||||||
aStops[1] = 1.0;
|
{
|
||||||
|
aStops.realloc(3);
|
||||||
|
aColors.realloc(3);
|
||||||
|
|
||||||
aColors[0] = aStartColor;
|
aStops[0] = 0.0;
|
||||||
aColors[1] = aEndColor;
|
aStops[1] = 0.5;
|
||||||
|
aStops[2] = 1.0;
|
||||||
|
|
||||||
|
aColors[0] = aEndColor;
|
||||||
|
aColors[1] = aStartColor;
|
||||||
|
aColors[2] = aEndColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aStops[0] = 0.0;
|
||||||
|
aStops[1] = 1.0;
|
||||||
|
|
||||||
// Setup texture transformation
|
aColors[0] = aStartColor;
|
||||||
// ----------------------------
|
aColors[1] = aEndColor;
|
||||||
|
}
|
||||||
|
|
||||||
const ::basegfx::B2DRectangle aBounds(
|
const ::basegfx::B2DRectangle aBounds(
|
||||||
::basegfx::tools::getRange(aDevicePoly) );
|
::basegfx::tools::getRange(aDevicePoly) );
|
||||||
|
const ::basegfx::B2DVector aOffset(
|
||||||
|
rGradient.GetOfsX() / 100.0,
|
||||||
|
rGradient.GetOfsY() / 100.0);
|
||||||
|
double fRotation( rGradient.GetAngle() * M_PI / 1800.0 );
|
||||||
|
const double fBorder( rGradient.GetBorder() / 100.0 );
|
||||||
|
|
||||||
// setup rotation angle. VCL rotates
|
basegfx::B2DHomMatrix aRot90;
|
||||||
// counter-clockwise, while canvas transformation
|
aRot90.rotate(M_PI_2);
|
||||||
// rotates clockwise
|
|
||||||
double nRotation( -rGradient.GetAngle() * M_PI / 1800.0 );
|
|
||||||
|
|
||||||
|
basegfx::ODFGradientInfo aGradInfo;
|
||||||
|
rtl::OUString aGradientService;
|
||||||
switch( rGradient.GetStyle() )
|
switch( rGradient.GetStyle() )
|
||||||
{
|
{
|
||||||
case GRADIENT_LINEAR:
|
case GRADIENT_LINEAR:
|
||||||
// FALLTHROUGH intended
|
basegfx::tools::createLinearODFGradientInfo(aGradInfo,
|
||||||
|
aBounds,
|
||||||
|
nSteps,
|
||||||
|
fBorder,
|
||||||
|
fRotation);
|
||||||
|
// map odf to svg gradient orientation - x
|
||||||
|
// instead of y direction
|
||||||
|
aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
|
||||||
|
aGradientService = rtl::OUString::createFromAscii("LinearGradient");
|
||||||
|
break;
|
||||||
|
|
||||||
case GRADIENT_AXIAL:
|
case GRADIENT_AXIAL:
|
||||||
{
|
{
|
||||||
// standard orientation for VCL linear
|
basegfx::tools::createLinearODFGradientInfo(aGradInfo,
|
||||||
// gradient is vertical, thus, rotate 90
|
aBounds,
|
||||||
// degrees
|
nSteps,
|
||||||
nRotation += M_PI/2.0;
|
fBorder,
|
||||||
|
fRotation);
|
||||||
|
// map odf to svg gradient orientation - x
|
||||||
|
// instead of y direction
|
||||||
|
aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90;
|
||||||
|
|
||||||
const double nBorder(
|
// map odf axial gradient to 3-stop linear
|
||||||
::basegfx::pruneScaleValue(
|
// gradient - shift left by 0.5
|
||||||
(1.0 - rGradient.GetBorder() / 100.0) ) );
|
basegfx::B2DHomMatrix aShift;
|
||||||
|
aShift.translate(-0.5,0);
|
||||||
|
aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aShift;
|
||||||
|
|
||||||
// shrink texture, to account for border
|
aGradientService = rtl::OUString::createFromAscii("LinearGradient");
|
||||||
// (only in x direction, linear gradient
|
break;
|
||||||
// is constant in y direction, anyway)
|
|
||||||
aTextureTransformation.scale( nBorder,
|
|
||||||
1.0 );
|
|
||||||
|
|
||||||
// linear gradients don't respect offsets
|
|
||||||
// (they are implicitely assumed to be
|
|
||||||
// 50%). linear gradients don't have
|
|
||||||
// border on both sides, only on the
|
|
||||||
// startColor side, axial gradients have
|
|
||||||
// border on both sides. As both gradients
|
|
||||||
// are invariant in y direction: leave y
|
|
||||||
// offset alone.
|
|
||||||
double nOffsetX( rGradient.GetBorder() / 200.0 );
|
|
||||||
|
|
||||||
// determine type of gradient (and necessary
|
|
||||||
// transformation matrix, should it be emulated by a
|
|
||||||
// generic gradient)
|
|
||||||
switch( rGradient.GetStyle() )
|
|
||||||
{
|
|
||||||
case GRADIENT_LINEAR:
|
|
||||||
nOffsetX = rGradient.GetBorder() / 100.0;
|
|
||||||
aTexture.Gradient = xFactory->createLinearHorizontalGradient( aColors,
|
|
||||||
aStops );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GRADIENT_AXIAL:
|
|
||||||
// vcl considers center color as start color
|
|
||||||
::std::swap(aColors[0],aColors[1]);
|
|
||||||
aTexture.Gradient = xFactory->createAxialHorizontalGradient( aColors,
|
|
||||||
aStops );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // other cases can't happen
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply border offset values
|
|
||||||
aTextureTransformation.translate( nOffsetX,
|
|
||||||
0.0 );
|
|
||||||
|
|
||||||
// rotate texture according to gradient rotation
|
|
||||||
aTextureTransformation.translate( -0.5, -0.5 );
|
|
||||||
aTextureTransformation.rotate( nRotation );
|
|
||||||
|
|
||||||
// to let the first strip of a rotated
|
|
||||||
// gradient start at the _edge_ of the
|
|
||||||
// bound rect (and not, due to rotation,
|
|
||||||
// slightly inside), slightly enlarge the
|
|
||||||
// gradient:
|
|
||||||
//
|
|
||||||
// y/2 sin(alpha) + x/2 cos(alpha)
|
|
||||||
//
|
|
||||||
// (values to change are not actual
|
|
||||||
// gradient scales, but original bound
|
|
||||||
// rect dimensions. Since we still want
|
|
||||||
// the border setting to apply after that,
|
|
||||||
// we multiply with that as above for
|
|
||||||
// nScaleX)
|
|
||||||
const double nScale(
|
|
||||||
::basegfx::pruneScaleValue(
|
|
||||||
fabs( aBounds.getHeight()*sin(nRotation) ) +
|
|
||||||
fabs( aBounds.getWidth()*cos(nRotation) )));
|
|
||||||
|
|
||||||
aTextureTransformation.scale( nScale, nScale );
|
|
||||||
|
|
||||||
// translate back origin to center of
|
|
||||||
// primitive
|
|
||||||
aTextureTransformation.translate( 0.5*aBounds.getWidth(),
|
|
||||||
0.5*aBounds.getHeight() );
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case GRADIENT_RADIAL:
|
case GRADIENT_RADIAL:
|
||||||
// FALLTHROUGH intended
|
basegfx::tools::createRadialODFGradientInfo(aGradInfo,
|
||||||
|
aBounds,
|
||||||
|
aOffset,
|
||||||
|
nSteps,
|
||||||
|
fBorder);
|
||||||
|
aGradientService = rtl::OUString::createFromAscii("EllipticalGradient");
|
||||||
|
break;
|
||||||
|
|
||||||
case GRADIENT_ELLIPTICAL:
|
case GRADIENT_ELLIPTICAL:
|
||||||
// FALLTHROUGH intended
|
basegfx::tools::createEllipticalODFGradientInfo(aGradInfo,
|
||||||
|
aBounds,
|
||||||
|
aOffset,
|
||||||
|
nSteps,
|
||||||
|
fBorder,
|
||||||
|
fRotation);
|
||||||
|
aGradientService = rtl::OUString::createFromAscii("EllipticalGradient");
|
||||||
|
break;
|
||||||
|
|
||||||
case GRADIENT_SQUARE:
|
case GRADIENT_SQUARE:
|
||||||
// FALLTHROUGH intended
|
basegfx::tools::createSquareODFGradientInfo(aGradInfo,
|
||||||
|
aBounds,
|
||||||
|
aOffset,
|
||||||
|
nSteps,
|
||||||
|
fBorder,
|
||||||
|
fRotation);
|
||||||
|
aGradientService = rtl::OUString::createFromAscii("RectangularGradient");
|
||||||
|
break;
|
||||||
|
|
||||||
case GRADIENT_RECT:
|
case GRADIENT_RECT:
|
||||||
{
|
basegfx::tools::createRectangularODFGradientInfo(aGradInfo,
|
||||||
// determine scale factors for the gradient (must
|
aBounds,
|
||||||
// be scaled up from [0,1]x[0,1] rect to object
|
aOffset,
|
||||||
// bounds). Will potentially changed in switch
|
nSteps,
|
||||||
// statement below.
|
fBorder,
|
||||||
// Respect border value, while doing so, the VCL
|
fRotation);
|
||||||
// gradient's border will effectively shrink the
|
aGradientService = rtl::OUString::createFromAscii("RectangularGradient");
|
||||||
// resulting gradient.
|
break;
|
||||||
double nScaleX( aBounds.getWidth() * (1.0 - rGradient.GetBorder() / 100.0) );
|
|
||||||
double nScaleY( aBounds.getHeight()* (1.0 - rGradient.GetBorder() / 100.0) );
|
|
||||||
|
|
||||||
// determine offset values. Since the border is
|
|
||||||
// divided half-by-half to both sides of the
|
|
||||||
// gradient, divide translation offset by an
|
|
||||||
// additional 2. Also respect offset here, but
|
|
||||||
// since VCL gradients have their center at [0,0]
|
|
||||||
// for zero offset, but canvas gradients have
|
|
||||||
// their top, left edge aligned with the
|
|
||||||
// primitive, and offset of 50% effectively must
|
|
||||||
// yield zero shift. Both values will potentially
|
|
||||||
// be adapted in switch statement below.
|
|
||||||
double nOffsetX( aBounds.getWidth() *
|
|
||||||
(2.0 * rGradient.GetOfsX() - 100.0 + rGradient.GetBorder()) / 200.0 );
|
|
||||||
double nOffsetY( aBounds.getHeight() *
|
|
||||||
(2.0 * rGradient.GetOfsY() - 100.0 + rGradient.GetBorder()) / 200.0 );
|
|
||||||
|
|
||||||
// determine type of gradient (and necessary
|
|
||||||
// transformation matrix, should it be emulated by a
|
|
||||||
// generic gradient)
|
|
||||||
switch( rGradient.GetStyle() )
|
|
||||||
{
|
|
||||||
case GRADIENT_RADIAL:
|
|
||||||
{
|
|
||||||
// create isotrophic scaling
|
|
||||||
if( nScaleX > nScaleY )
|
|
||||||
{
|
|
||||||
nOffsetY -= (nScaleX - nScaleY) * 0.5;
|
|
||||||
nScaleY = nScaleX;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nOffsetX -= (nScaleY - nScaleX) * 0.5;
|
|
||||||
nScaleX = nScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enlarge gradient to match bound rect diagonal
|
|
||||||
aTextureTransformation.translate( -0.5, -0.5 );
|
|
||||||
const double nScale( hypot(aBounds.getWidth(), aBounds.getHeight()) / nScaleX );
|
|
||||||
aTextureTransformation.scale( nScale, nScale );
|
|
||||||
aTextureTransformation.translate( 0.5, 0.5 );
|
|
||||||
|
|
||||||
aTexture.Gradient = xFactory->createEllipticalGradient( aColors,
|
|
||||||
aStops,
|
|
||||||
geometry::RealRectangle2D(0.0,0.0,
|
|
||||||
1.0,1.0) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GRADIENT_ELLIPTICAL:
|
|
||||||
{
|
|
||||||
// enlarge gradient slightly
|
|
||||||
aTextureTransformation.translate( -0.5, -0.5 );
|
|
||||||
const double nSqrt2( sqrt(2.0) );
|
|
||||||
aTextureTransformation.scale( nSqrt2,nSqrt2 );
|
|
||||||
aTextureTransformation.translate( 0.5, 0.5 );
|
|
||||||
|
|
||||||
aTexture.Gradient = xFactory->createEllipticalGradient(
|
|
||||||
aColors,
|
|
||||||
aStops,
|
|
||||||
::basegfx::unotools::rectangle2DFromB2DRectangle(
|
|
||||||
aBounds ));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GRADIENT_SQUARE:
|
|
||||||
// create isotrophic scaling
|
|
||||||
if( nScaleX > nScaleY )
|
|
||||||
{
|
|
||||||
nOffsetY -= (nScaleX - nScaleY) * 0.5;
|
|
||||||
nScaleY = nScaleX;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nOffsetX -= (nScaleY - nScaleX) * 0.5;
|
|
||||||
nScaleX = nScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
aTexture.Gradient = xFactory->createRectangularGradient( aColors,
|
|
||||||
aStops,
|
|
||||||
geometry::RealRectangle2D(0.0,0.0,
|
|
||||||
1.0,1.0) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GRADIENT_RECT:
|
|
||||||
aTexture.Gradient = xFactory->createRectangularGradient(
|
|
||||||
aColors,
|
|
||||||
aStops,
|
|
||||||
::basegfx::unotools::rectangle2DFromB2DRectangle(
|
|
||||||
aBounds ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // other cases can't happen
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nScaleX = ::basegfx::pruneScaleValue( nScaleX );
|
|
||||||
nScaleY = ::basegfx::pruneScaleValue( nScaleY );
|
|
||||||
|
|
||||||
aTextureTransformation.scale( nScaleX, nScaleY );
|
|
||||||
|
|
||||||
// rotate texture according to gradient rotation
|
|
||||||
aTextureTransformation.translate( -0.5*nScaleX, -0.5*nScaleY );
|
|
||||||
aTextureTransformation.rotate( nRotation );
|
|
||||||
aTextureTransformation.translate( 0.5*nScaleX, 0.5*nScaleY );
|
|
||||||
|
|
||||||
aTextureTransformation.translate( nOffsetX, nOffsetY );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ENSURE_OR_THROW( false,
|
ENSURE_OR_THROW( false,
|
||||||
"ImplRenderer::createGradientAction(): Unexpected gradient type" );
|
"ImplRenderer::createGradientAction(): Unexpected gradient type" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,31 +752,49 @@ namespace cppcanvas
|
|||||||
// gradient will always display at the origin, and
|
// gradient will always display at the origin, and
|
||||||
// not within the polygon bound (which might be
|
// not within the polygon bound (which might be
|
||||||
// miles away from the origin).
|
// miles away from the origin).
|
||||||
aTextureTransformation.translate( aBounds.getMinX(),
|
aGradInfo.maTextureTransform.translate( aBounds.getMinX(),
|
||||||
aBounds.getMinY() );
|
aBounds.getMinY() );
|
||||||
|
|
||||||
::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
|
::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
|
||||||
aTextureTransformation );
|
aGradInfo.maTextureTransform );
|
||||||
|
|
||||||
ActionSharedPtr pPolyAction(
|
uno::Sequence<uno::Any> args(3);
|
||||||
internal::PolyPolyActionFactory::createPolyPolyAction(
|
beans::PropertyValue aProp;
|
||||||
aDevicePoly,
|
aProp.Name = rtl::OUString::createFromAscii("Colors");
|
||||||
rParms.mrCanvas,
|
aProp.Value <<= aColors;
|
||||||
getState( rParms.mrStates ),
|
args[0] <<= aProp;
|
||||||
aTexture ) );
|
aProp.Name = rtl::OUString::createFromAscii("Stops");
|
||||||
|
aProp.Value <<= aStops;
|
||||||
|
args[1] <<= aProp;
|
||||||
|
aProp.Name = rtl::OUString::createFromAscii("AspectRatio");
|
||||||
|
aProp.Value <<= aGradInfo.mfAspectRatio;
|
||||||
|
args[2] <<= aProp;
|
||||||
|
|
||||||
if( pPolyAction )
|
aTexture.Gradient.set(
|
||||||
|
xFactory->createInstanceWithArguments(aGradientService,
|
||||||
|
args),
|
||||||
|
uno::UNO_QUERY);
|
||||||
|
if( aTexture.Gradient.is() )
|
||||||
{
|
{
|
||||||
maActions.push_back(
|
ActionSharedPtr pPolyAction(
|
||||||
MtfAction(
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
||||||
pPolyAction,
|
aDevicePoly,
|
||||||
rParms.mrCurrActionIndex ) );
|
rParms.mrCanvas,
|
||||||
|
getState( rParms.mrStates ),
|
||||||
|
aTexture ) );
|
||||||
|
|
||||||
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
|
if( pPolyAction )
|
||||||
|
{
|
||||||
|
maActions.push_back(
|
||||||
|
MtfAction(
|
||||||
|
pPolyAction,
|
||||||
|
rParms.mrCurrActionIndex ) );
|
||||||
|
|
||||||
|
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done, using native gradients
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// done, using native gradients
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user