summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basegfx/inc/basegfx/tools/gradienttools.hxx401
-rw-r--r--basegfx/prj/d.lst1
-rw-r--r--basegfx/source/polygon/b2dpolygontools.cxx10
-rw-r--r--basegfx/source/tools/gradienttools.cxx366
-rwxr-xr-xbasegfx/source/tools/makefile.mk1
5 files changed, 775 insertions, 4 deletions
diff --git a/basegfx/inc/basegfx/tools/gradienttools.hxx b/basegfx/inc/basegfx/tools/gradienttools.hxx
new file mode 100644
index 000000000000..0c7f2ab2c060
--- /dev/null
+++ b/basegfx/inc/basegfx/tools/gradienttools.hxx
@@ -0,0 +1,401 @@
+/*************************************************************************
+ *
+ * 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_GRADIENTTOOLS_HXX
+#define _BGFX_TOOLS_GRADIENTTOOLS_HXX
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+namespace basegfx
+{
+ /** Gradient definition as used in ODF 1.2
+
+ This struct collects all data necessary for rendering ODF
+ 1.2-compatible gradients. Use the createXXXODFGradientInfo()
+ methods below for initializing from ODF attributes.
+ */
+ struct ODFGradientInfo
+ {
+ /** transformation mapping from [0,1]^2 texture coordinate
+ space to [0,1]^2 shape coordinate space
+ */
+ B2DHomMatrix maTextureTransform;
+
+ /** transformation mapping from [0,1]^2 shape coordinate space
+ to [0,1]^2 texture coordinate space. This is the
+ transformation commonly used to create gradients from a
+ scanline rasterizer (put shape u/v coordinates into it, get
+ texture s/t coordinates out of it)
+ */
+ B2DHomMatrix maBackTextureTransform;
+
+ /** Aspect ratio of the gradient. Only used in drawinglayer
+ for generating nested gradient polygons currently. Already
+ catered for in the transformations above.
+ */
+ double mfAspectRatio;
+
+ /** Requested gradient steps to render. See the
+ implementations of the getXXXGradientAlpha() methods below,
+ the semantic differs slightly for the different gradient
+ types.
+ */
+ sal_uInt32 mnSteps;
+ };
+
+ namespace tools
+ {
+ /** Create matrix for ODF's linear gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle);
+
+ /** Calculate linear gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getLinearGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
+ const double t(clamp(aCoor.getY(), 0.0, 1.0));
+ const sal_uInt32 nSteps(rGradInfo.mnSteps);
+
+ if(nSteps > 2L && nSteps < 128L)
+ return floor(t * nSteps) / double(nSteps + 1L);
+
+ return t;
+ }
+
+ /** Create matrix for ODF's axial gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle);
+
+ /** Calculate axial gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getAxialGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
+ const double t(clamp(fabs(aCoor.getY()), 0.0, 1.0));
+ const sal_uInt32 nSteps(rGradInfo.mnSteps);
+ const double fInternalSteps((nSteps * 2L) - 1L);
+
+ if(nSteps > 2L && nSteps < 128L)
+ return floor(((t * fInternalSteps) + 1.0) / 2.0) / double(nSteps - 1L);
+
+ return t;
+ }
+
+ /** Create matrix for ODF's radial gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param rOffset
+ Gradient offset value (from ODF)
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder);
+
+ /** Calculate radial gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getRadialGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
+ const double fDist(
+ clamp(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY(),
+ 0.0,
+ 1.0));
+
+ const double t(1.0 - sqrt(fDist));
+ const sal_uInt32 nSteps(rGradInfo.mnSteps);
+
+ if(nSteps > 2L && nSteps < 128L)
+ return floor(t * nSteps) / double(nSteps - 1L);
+
+ return t;
+ }
+
+ /** Create matrix for ODF's elliptical gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param rOffset
+ Gradient offset value (from ODF)
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle);
+
+ /** Calculate elliptical gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getEllipticalGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ return getRadialGradientAlpha(rUV,rGradInfo); // only matrix setup differs
+ }
+
+ /** Create matrix for ODF's square gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param rOffset
+ Gradient offset value (from ODF)
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle);
+
+ /** Calculate square gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getSquareGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV);
+ const double fAbsX(fabs(aCoor.getX()));
+ const double fAbsY(fabs(aCoor.getY()));
+
+ if(fTools::moreOrEqual(fAbsX, 1.0) || fTools::moreOrEqual(fAbsY, 1.0))
+ return 0.0;
+
+ const double t(1.0 - (fAbsX > fAbsY ? fAbsX : fAbsY));
+ const sal_uInt32 nSteps(rGradInfo.mnSteps);
+
+ if(nSteps > 2L && nSteps < 128L)
+ return floor(t * nSteps) / double(nSteps - 1L);
+
+ return t;
+ }
+
+ /** Create matrix for ODF's rectangular gradient definition
+
+ @param o_rGradientInfo
+ Receives the calculated texture transformation matrix (for
+ use with standard [0,1]x[0,1] texture coordinates)
+
+ @param rTargetArea
+ Output area, needed for aspect ratio calculations and
+ texture transformation
+
+ @param rOffset
+ Gradient offset value (from ODF)
+
+ @param nSteps
+ Number of gradient steps (from ODF)
+
+ @param fBorder
+ Width of gradient border (from ODF)
+
+ @param fAngle
+ Gradient angle (from ODF)
+ */
+ ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle);
+
+ /** Calculate rectangular gradient blend value
+
+ This method generates you the lerp alpha value for
+ blending linearly between gradient start and end color,
+ according to the formula (startCol*(1.0-alpha) + endCol*alpha)
+
+ @param rUV
+ Current uv coordinate. Values outside [0,1] will be
+ clamped.
+
+ @param rGradInfo
+ Gradient info, for transformation and number of steps
+ */
+ inline double getRectangularGradientAlpha(const B2DPoint& rUV,
+ const ODFGradientInfo& rGradInfo )
+ {
+ return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs
+ }
+
+ }
+}
+
+#endif
diff --git a/basegfx/prj/d.lst b/basegfx/prj/d.lst
index 7168e6b4c495..9dd6085bbc7f 100644
--- a/basegfx/prj/d.lst
+++ b/basegfx/prj/d.lst
@@ -92,6 +92,7 @@ mkdir: %_DEST%\inc%_EXT%\basegfx\tools
..\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\tools.hxx %_DEST%\inc%_EXT%\basegfx\tools\tools.hxx
+..\inc\basegfx\tools\gradienttools.hxx %_DEST%\inc%_EXT%\basegfx\tools\gradienttools.hxx
mkdir: %_DEST%\inc%_EXT%\basegfx\color
..\inc\basegfx\color\bcolor.hxx %_DEST%\inc%_EXT%\basegfx\color\bcolor.hxx
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index 7a7a60ae37b5..f4d1f992ad6b 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -1975,14 +1975,16 @@ namespace basegfx
{
B2DPolygon aRetval;
+ // truncate fStart, fEnd to a range of [0.0 .. F_2PI[ where F_2PI
+ // falls back to 0.0 to ensure a unique definition
if(fTools::less(fStart, 0.0))
{
fStart = 0.0;
}
- if(fTools::more(fStart, F_2PI))
+ if(fTools::moreOrEqual(fStart, F_2PI))
{
- fStart = F_2PI;
+ fStart = 0.0;
}
if(fTools::less(fEnd, 0.0))
@@ -1990,9 +1992,9 @@ namespace basegfx
fEnd = 0.0;
}
- if(fTools::more(fEnd, F_2PI))
+ if(fTools::moreOrEqual(fEnd, F_2PI))
{
- fEnd = F_2PI;
+ fEnd = 0.0;
}
const sal_uInt32 nQuadrantStart(sal_uInt32(fStart / F_PI2) % 4L);
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
new file mode 100644
index 000000000000..9e78039cd590
--- /dev/null
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -0,0 +1,366 @@
+/*************************************************************************
+ *
+ * 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.cxx,v $
+ * $Revision: 1.12 $
+ *
+ * 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"
+
+#include <basegfx/tools/gradienttools.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+namespace basegfx
+{
+ /** Most of the setup for linear & axial gradient is the same, except
+ for the border treatment. Factored out here.
+ */
+ static void init1DGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetRange,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle,
+ bool bAxial)
+ {
+ o_rGradientInfo.maTextureTransform.identity();
+ o_rGradientInfo.maBackTextureTransform.identity();
+ o_rGradientInfo.mnSteps = nSteps;
+
+ double fTargetSizeX(rTargetRange.getWidth());
+ double fTargetSizeY(rTargetRange.getHeight());
+ double fTargetOffsetX(rTargetRange.getMinX());
+ double fTargetOffsetY(rTargetRange.getMinY());
+
+ // add object expansion
+ if(0.0 != fAngle)
+ {
+ const double fAbsCos(fabs(cos(fAngle)));
+ const double fAbsSin(fabs(sin(fAngle)));
+ const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
+ const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
+ fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
+ fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
+ fTargetSizeX = fNewX;
+ fTargetSizeY = fNewY;
+ }
+
+ // add object scale before rotate
+ o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
+
+ // add texture rotate after scale to keep perpendicular angles
+ if(0.0 != fAngle)
+ {
+ B2DPoint aCenter(0.5, 0.5);
+ aCenter *= o_rGradientInfo.maTextureTransform;
+
+ o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
+ o_rGradientInfo.maTextureTransform.rotate(fAngle);
+ o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
+ }
+
+ // add object translate
+ o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
+
+ // prepare aspect for texture
+ 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
+ o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
+ 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,
+ except for the border treatment. Factored out here.
+ */
+ static void initEllipticalGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetRange,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle,
+ bool bCircular)
+ {
+ o_rGradientInfo.maTextureTransform.identity();
+ o_rGradientInfo.maBackTextureTransform.identity();
+ o_rGradientInfo.mnSteps = nSteps;
+
+ double fTargetSizeX(rTargetRange.getWidth());
+ double fTargetSizeY(rTargetRange.getHeight());
+ double fTargetOffsetX(rTargetRange.getMinX());
+ double fTargetOffsetY(rTargetRange.getMinY());
+
+ // add object expansion
+ if( bCircular )
+ {
+ const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY)));
+ fTargetOffsetX -= (fOriginalDiag - fTargetSizeX) / 2.0;
+ fTargetOffsetY -= (fOriginalDiag - fTargetSizeY) / 2.0;
+ fTargetSizeX = fOriginalDiag;
+ fTargetSizeY = fOriginalDiag;
+ }
+ else
+ {
+ fTargetOffsetX -= (0.4142 / 2.0 ) * fTargetSizeX;
+ fTargetOffsetY -= (0.4142 / 2.0 ) * fTargetSizeY;
+ fTargetSizeX = 1.4142 * fTargetSizeX;
+ fTargetSizeY = 1.4142 * fTargetSizeY;
+ }
+
+ // add object scale before rotate
+ o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
+
+ if( !bCircular )
+ {
+ // add texture rotate after scale to keep perpendicular angles
+ if(0.0 != fAngle)
+ {
+ B2DPoint aCenter(0.5, 0.5);
+ aCenter *= o_rGradientInfo.maTextureTransform;
+
+ o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
+ o_rGradientInfo.maTextureTransform.rotate(fAngle);
+ o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
+ }
+ }
+
+ // add defined offsets after rotation
+ if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
+ {
+ // use original target size
+ fTargetOffsetX += (rOffset.getX() - 0.5) * rTargetRange.getWidth();
+ fTargetOffsetY += (rOffset.getY() - 0.5) * rTargetRange.getHeight();
+ }
+
+ // add object translate
+ o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
+
+ // prepare aspect for texture
+ 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
+ o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
+ 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
+ here.
+ */
+ static void initRectGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetRange,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ o_rGradientInfo.maTextureTransform.identity();
+ o_rGradientInfo.maBackTextureTransform.identity();
+ o_rGradientInfo.mnSteps = nSteps;
+
+ double fTargetSizeX(rTargetRange.getWidth());
+ double fTargetSizeY(rTargetRange.getHeight());
+ double fTargetOffsetX(rTargetRange.getMinX());
+ double fTargetOffsetY(rTargetRange.getMinY());
+
+ // add object expansion
+ if(0.0 != fAngle)
+ {
+ const double fAbsCos(fabs(cos(fAngle)));
+ const double fAbsSin(fabs(sin(fAngle)));
+ const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
+ const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
+ fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
+ fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
+ fTargetSizeX = fNewX;
+ fTargetSizeY = fNewY;
+ }
+
+ // add object scale before rotate
+ o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
+
+ // add texture rotate after scale to keep perpendicular angles
+ if(0.0 != fAngle)
+ {
+ B2DPoint aCenter(0.5, 0.5);
+ aCenter *= o_rGradientInfo.maTextureTransform;
+
+ o_rGradientInfo.maTextureTransform.translate(-aCenter.getX(), -aCenter.getY());
+ o_rGradientInfo.maTextureTransform.rotate(fAngle);
+ o_rGradientInfo.maTextureTransform.translate(aCenter.getX(), aCenter.getY());
+ }
+
+ // add defined offsets after rotation
+ if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
+ {
+ // use scaled target size
+ fTargetOffsetX += (rOffset.getX() - 0.5) * fTargetSizeX;
+ fTargetOffsetY += (rOffset.getY() - 0.5) * fTargetSizeY;
+ }
+
+ // add object translate
+ o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
+
+ // prepare aspect for texture
+ 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
+ o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
+ 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
+ {
+ ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ init1DGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ nSteps,
+ fBorder,
+ fAngle,
+ false);
+ return o_rGradientInfo;
+ }
+
+ ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ init1DGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ nSteps,
+ fBorder,
+ fAngle,
+ true);
+ return o_rGradientInfo;
+ }
+
+ ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder)
+ {
+ initEllipticalGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ rOffset,
+ nSteps,
+ fBorder,
+ 0.0,
+ true);
+ return o_rGradientInfo;
+ }
+
+ ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ initEllipticalGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ rOffset,
+ nSteps,
+ fBorder,
+ fAngle,
+ false);
+ return o_rGradientInfo;
+ }
+
+ ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ initRectGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ rOffset,
+ nSteps,
+ fBorder,
+ fAngle);
+ return o_rGradientInfo;
+ }
+
+ ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
+ const B2DRange& rTargetArea,
+ const B2DVector& rOffset,
+ sal_uInt32 nSteps,
+ double fBorder,
+ double fAngle)
+ {
+ initRectGradientInfo(o_rGradientInfo,
+ rTargetArea,
+ rOffset,
+ nSteps,
+ fBorder,
+ fAngle);
+ return o_rGradientInfo;
+ }
+
+ } // namespace tools
+
+} // namespace basegfx
diff --git a/basegfx/source/tools/makefile.mk b/basegfx/source/tools/makefile.mk
index bd233ffbcfc0..1bede8b22d88 100755
--- a/basegfx/source/tools/makefile.mk
+++ b/basegfx/source/tools/makefile.mk
@@ -42,6 +42,7 @@ ENABLE_EXCEPTIONS=TRUE
# --- Files -------------------------------------
SLOFILES= $(SLO)$/canvastools.obj \
+ $(SLO)$/gradienttools.obj \
$(SLO)$/debugplotter.obj \
$(SLO)$/liangbarsky.obj \
$(SLO)$/tools.obj \