summaryrefslogtreecommitdiff
path: root/basegfx
diff options
context:
space:
mode:
authorsb <sb@openoffice.org>2010-01-09 21:01:14 +0100
committersb <sb@openoffice.org>2010-01-09 21:01:14 +0100
commita57ae685bcc342e1cd2d4e9d261704839ecf1996 (patch)
tree2494a7580014d7aba39983e6117fe084f3fa5561 /basegfx
parent7397e8c1bb3d3f5562590c07a535d9749dca4279 (diff)
parent8765a3bf9f2926a50d0f644e4263782269abe023 (diff)
sb118: merged in DEV300_m69
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/inc/basegfx/matrix/b2dhommatrix.hxx10
-rw-r--r--basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx205
-rw-r--r--basegfx/inc/basegfx/polygon/b2dpolygontools.hxx61
-rw-r--r--basegfx/source/matrix/b2dhommatrix.cxx174
-rw-r--r--basegfx/source/matrix/b2dhommatrixtools.cxx333
-rw-r--r--basegfx/source/polygon/b2dlinegeometry.cxx9
-rw-r--r--basegfx/source/polygon/b2dpolygonclipper.cxx7
-rw-r--r--basegfx/source/polygon/b2dpolygontools.cxx311
-rw-r--r--basegfx/source/polygon/b2dsvgpolypolygon.cxx6
-rw-r--r--basegfx/source/tools/gradienttools.cxx17
-rwxr-xr-xbasegfx/source/tools/unopolypolygon.cxx6
-rw-r--r--basegfx/test/basegfx2d.cxx7
12 files changed, 708 insertions, 438 deletions
diff --git a/basegfx/inc/basegfx/matrix/b2dhommatrix.hxx b/basegfx/inc/basegfx/matrix/b2dhommatrix.hxx
index c7c79d0cd6e9..10b023c5f68c 100644
--- a/basegfx/inc/basegfx/matrix/b2dhommatrix.hxx
+++ b/basegfx/inc/basegfx/matrix/b2dhommatrix.hxx
@@ -52,12 +52,22 @@ namespace basegfx
B2DHomMatrix(const B2DHomMatrix& rMat);
~B2DHomMatrix();
+ /** constructor to allow setting all needed values for a 3x2 matrix at once. The
+ parameter f_0x1 e.g. is the same as using set(0, 1, f)
+ */
+ B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2);
+
/// unshare this matrix with all internally shared instances
void makeUnique();
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const;
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue);
+ /** allow setting all needed values for a 3x2 matrix in one call. The
+ parameter f_0x1 e.g. is the same as using set(0, 1, f)
+ */
+ void set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2);
+
// test if last line is default to see if last line needs to be
// involved in calculations
bool isLastLineDefault() const;
diff --git a/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx b/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx
index 0b200b812bed..c90f673a8194 100644
--- a/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx
+++ b/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx
@@ -40,45 +40,190 @@
namespace basegfx
{
- class DecomposedB2DHomMatrixContainer
+ namespace tools
{
- private:
- B2DHomMatrix maB2DHomMatrix;
- B2DVector maScale;
- B2DVector maTranslate;
- double mfRotate;
- double mfShearX;
+ /** If the rotation angle is an approximate multiple of pi/2,
+ force fSin/fCos to -1/0/1, to maintain orthogonality (which
+ might also be advantageous for the other cases, but: for
+ multiples of pi/2, the exact values _can_ be attained. It
+ would be largely unintuitive, if a 180 degrees rotation
+ would introduce slight roundoff errors, instead of exactly
+ mirroring the coordinate system)
+ */
+ void createSinCosOrthogonal(double& o_rSin, double& rCos, double fRadiant);
- // bitfield
- unsigned mbDecomposed : 1;
+ /** Tooling methods for on-the-fly matrix generation e.g. for inline
+ multiplications
+ */
+ B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY);
+ B2DHomMatrix createShearXB2DHomMatrix(double fShearX);
+ B2DHomMatrix createShearYB2DHomMatrix(double fShearY);
+ B2DHomMatrix createRotateB2DHomMatrix(double fRadiant);
+ B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY);
- void impCheckDecompose()
+ /// inline versions for parameters as tuples
+ inline B2DHomMatrix createScaleB2DHomMatrix(const B2DTuple& rScale)
{
- if(!mbDecomposed)
- {
- maB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX);
- mbDecomposed = true;
- }
+ return createScaleB2DHomMatrix(rScale.getX(), rScale.getY());
+ }
+
+ inline B2DHomMatrix createTranslateB2DHomMatrix(const B2DTuple& rTranslate)
+ {
+ return createTranslateB2DHomMatrix(rTranslate.getX(), rTranslate.getY());
+ }
+
+ /** Tooling methods for faster completely combined matrix creation
+ when scale, shearX, rotation and translation needs to be done in
+ exactly that order. It's faster since it direcly calculates
+ each matrix value based on a symbolic calculation of the three
+ matrix multiplications.
+ Inline versions for parameters as tuples added, too.
+ */
+ B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY);
+ inline B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
+ const B2DTuple& rScale,
+ double fShearX,
+ double fRadiant,
+ const B2DTuple& rTranslate)
+ {
+ return createScaleShearXRotateTranslateB2DHomMatrix(
+ rScale.getX(), rScale.getY(),
+ fShearX,
+ fRadiant,
+ rTranslate.getX(), rTranslate.getY());
+ }
+
+ B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY);
+ inline B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
+ double fShearX,
+ double fRadiant,
+ const B2DTuple& rTranslate)
+ {
+ return createShearXRotateTranslateB2DHomMatrix(
+ fShearX,
+ fRadiant,
+ rTranslate.getX(), rTranslate.getY());
}
- public:
- DecomposedB2DHomMatrixContainer(const B2DHomMatrix& rB2DHomMatrix)
- : maB2DHomMatrix(rB2DHomMatrix),
- maScale(),
- maTranslate(),
- mfRotate(0.0),
- mfShearX(0.0),
- mbDecomposed(false)
+ B2DHomMatrix createScaleTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fTranslateX, double fTranslateY);
+ inline B2DHomMatrix createScaleTranslateB2DHomMatrix(
+ const B2DTuple& rScale,
+ const B2DTuple& rTranslate)
{
+ return createScaleTranslateB2DHomMatrix(
+ rScale.getX(), rScale.getY(),
+ rTranslate.getX(), rTranslate.getY());
}
- // data access
- const B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; }
- const B2DVector& getScale() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return maScale; }
- const B2DVector& getTranslate() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return maTranslate; }
- double getRotate() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfRotate; }
- double getShearX() const { const_cast< DecomposedB2DHomMatrixContainer* >(this)->impCheckDecompose(); return mfShearX; }
- };
+ /// special for the often used case of rotation around a point
+ B2DHomMatrix createRotateAroundPoint(
+ double fPointX, double fPointY,
+ double fRadiant);
+ inline B2DHomMatrix createRotateAroundPoint(
+ const B2DTuple& rPoint,
+ double fRadiant)
+ {
+ return createRotateAroundPoint(
+ rPoint.getX(), rPoint.getY(),
+ fRadiant);
+ }
+ } // end of namespace tools
+} // end of namespace basegfx
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+ namespace tools
+ {
+ class B2DHomMatrixBufferedDecompose
+ {
+ private:
+ B2DVector maScale;
+ B2DVector maTranslate;
+ double mfRotate;
+ double mfShearX;
+
+ public:
+ B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix)
+ : maScale(),
+ maTranslate(),
+ mfRotate(0.0),
+ mfShearX(0.0)
+ {
+ rB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX);
+ }
+
+ // data access
+ B2DHomMatrix getB2DHomMatrix() const
+ {
+ return createScaleShearXRotateTranslateB2DHomMatrix(
+ maScale, mfShearX, mfRotate, maTranslate);
+ }
+
+ const B2DVector& getScale() const { return maScale; }
+ const B2DVector& getTranslate() const { return maTranslate; }
+ double getRotate() const { return mfRotate; }
+ double getShearX() const { return mfShearX; }
+ };
+ } // end of namespace tools
+} // end of namespace basegfx
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+ namespace tools
+ {
+ class B2DHomMatrixBufferedOnDemandDecompose
+ {
+ private:
+ B2DHomMatrix maB2DHomMatrix;
+ B2DVector maScale;
+ B2DVector maTranslate;
+ double mfRotate;
+ double mfShearX;
+
+ // bitfield
+ unsigned mbDecomposed : 1;
+
+ void impCheckDecompose()
+ {
+ if(!mbDecomposed)
+ {
+ maB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX);
+ mbDecomposed = true;
+ }
+ }
+
+ public:
+ B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix& rB2DHomMatrix)
+ : maB2DHomMatrix(rB2DHomMatrix),
+ maScale(),
+ maTranslate(),
+ mfRotate(0.0),
+ mfShearX(0.0),
+ mbDecomposed(false)
+ {
+ }
+
+ // data access
+ const B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; }
+ const B2DVector& getScale() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maScale; }
+ const B2DVector& getTranslate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maTranslate; }
+ double getRotate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfRotate; }
+ double getShearX() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfShearX; }
+ };
+ } // end of namespace tools
} // end of namespace basegfx
///////////////////////////////////////////////////////////////////////////////
diff --git a/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
index 5eff6b0b9cc1..47ff41b75e70 100644
--- a/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
+++ b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
@@ -288,14 +288,6 @@ namespace basegfx
*/
B2DPolygon createPolygonFromCircle( const B2DPoint& rCenter, double fRadius );
- /** append a unit circle with one point and the control vectors to the given polygon
- */
- void appendUnitCircleQuadrant(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, bool bEndPoint);
-
- /** append a segment of unit circle with one point and the control vectors to the given polygon
- */
- void appendUnitCircleQuadrantSegment(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, double fStart, double fEnd, bool bEndPoint);
-
/** create a polygon which describes the unit circle and close it
@param nStartQuadrant
@@ -325,59 +317,6 @@ namespace basegfx
*/
B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY );
- /** append a unit circle with one point and the control vectors to the given polygon
- */
- void appendUnitCircleQuadrant(B2DPolygon& rPolygon, sal_uInt32 nQuadrant);
-
- /** append a segment of unit circle with start point, the control vectors and end point to the given polygon
- */
- void appendUnitCircleQuadrantSegment(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, double fStart, double fEnd);
-
- /** Create an ellipse polygon with given radii.
-
- This method creates an ellipse approximation consisting of
- four cubic bezier segments, which approximate the given
- ellipse with an error of less than 0.5 percent.
-
- @param rCenter
- Center point of the circle
-
- @param fRadiusX
- Radius of the ellipse in X direction
-
- @param fRadiusY
- Radius of the ellipse in Y direction
-
- @param fStart
- Start angle where the ellipe segment starts in the range [0.0 .. 2PI[
-
- @param fEnd
- End angle where the ellipe segment ends in the range [0.0 .. 2PI[
- */
- B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY );
-
- /** Create an ellipse polygon with given radii and the given angles, from start to end
-
- This method creates an ellipse approximation consisting of
- four cubic bezier segments, which approximate the given
- ellipse with an error of less than 0.5 percent.
-
- @param rCenter
- Center point of the circle
-
- @param fRadiusX
- Radius of the ellipse in X direction
-
- @param fRadiusY
- Radius of the ellipse in Y direction
-
- @param fStart
- Start angle where the ellipe segment starts in the range [0.0 .. 2PI[
-
- @param fEnd
- End angle where the ellipe segment ends in the range [0.0 .. 2PI[
- */
-
/** Create an unit ellipse polygon with the given angles, from start to end
*/
B2DPolygon createPolygonFromEllipseSegment( const B2DPoint& rCenter, double fRadiusX, double fRadiusY, double fStart, double fEnd );
diff --git a/basegfx/source/matrix/b2dhommatrix.cxx b/basegfx/source/matrix/b2dhommatrix.cxx
index 352113fa8ed3..a7777352effb 100644
--- a/basegfx/source/matrix/b2dhommatrix.cxx
+++ b/basegfx/source/matrix/b2dhommatrix.cxx
@@ -36,6 +36,9 @@
#include <hommatrixtemplate.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+///////////////////////////////////////////////////////////////////////////////
namespace basegfx
{
@@ -60,6 +63,17 @@ namespace basegfx
{
}
+ B2DHomMatrix::B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
+ : mpImpl( IdentityMatrix::get() ) // use common identity matrix, will be made unique with 1st set-call
+ {
+ mpImpl->set(0, 0, f_0x0);
+ mpImpl->set(0, 1, f_0x1);
+ mpImpl->set(0, 2, f_0x2);
+ mpImpl->set(1, 0, f_1x0);
+ mpImpl->set(1, 1, f_1x1);
+ mpImpl->set(1, 2, f_1x2);
+ }
+
B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
{
mpImpl = rMat.mpImpl;
@@ -81,6 +95,16 @@ namespace basegfx
mpImpl->set(nRow, nColumn, fValue);
}
+ void B2DHomMatrix::set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
+ {
+ mpImpl->set(0, 0, f_0x0);
+ mpImpl->set(0, 1, f_0x1);
+ mpImpl->set(0, 2, f_0x2);
+ mpImpl->set(1, 0, f_1x0);
+ mpImpl->set(1, 1, f_1x1);
+ mpImpl->set(1, 2, f_1x2);
+ }
+
bool B2DHomMatrix::isLastLineDefault() const
{
return mpImpl->isLastLineDefault();
@@ -206,56 +230,9 @@ namespace basegfx
if(!fTools::equalZero(fRadiant))
{
double fSin(0.0);
- double fCos(0.0);
-
- // is the rotation angle an approximate multiple of pi/2?
- // If yes, force fSin/fCos to -1/0/1, to maintain
- // orthogonality (which might also be advantageous for the
- // other cases, but: for multiples of pi/2, the exact
- // values _can_ be attained. It would be largely
- // unintuitive, if a 180 degrees rotation would introduce
- // slight roundoff errors, instead of exactly mirroring
- // the coordinate system).
- if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
- {
- // determine quadrant
- const sal_Int32 nQuad(
- (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
- switch( nQuad )
- {
- case 0: // -2pi,0,2pi
- fSin = 0.0;
- fCos = 1.0;
- break;
-
- case 1: // -3/2pi,1/2pi
- fSin = 1.0;
- fCos = 0.0;
- break;
-
- case 2: // -pi,pi
- fSin = 0.0;
- fCos = -1.0;
- break;
-
- case 3: // -1/2pi,3/2pi
- fSin = -1.0;
- fCos = 0.0;
- break;
-
- default:
- OSL_ENSURE( false,
- "B2DHomMatrix::rotate(): Impossible case reached" );
- }
- }
- else
- {
- // TODO(P1): Maybe use glibc's sincos here (though
- // that's kinda non-portable...)
- fSin = sin(fRadiant);
- fCos = cos(fRadiant);
- }
+ double fCos(1.0);
+ tools::createSinCosOrthogonal(fSin, fCos, fRadiant);
Impl2DHomMatrix aRotMat;
aRotMat.set(0, 0, fCos);
@@ -474,104 +451,7 @@ namespace basegfx
return true;
}
-
-/* Old version: Used 3D decompose when shaer was involved and also a determinant test
- (but only in that case). Keeping as comment since it also worked and to allow a
- fallback in case the new version makes trouble somehow. Definitely missing in the 2nd
- case is the sign correction for Y-Scale, this would need to be added following the above
- pattern
-
- bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
- {
- // when perspective is used, decompose is not made here
- if(!mpImpl->isLastLineDefault())
- return false;
-
- // test for rotation and shear
- if(fTools::equalZero(get(0, 1))
- && fTools::equalZero(get(1, 0)))
- {
- // no rotation and shear, direct value extraction
- rRotate = rShearX = 0.0;
-
- // copy scale values
- rScale.setX(get(0, 0));
- rScale.setY(get(1, 1));
-
- // copy translation values
- rTranslate.setX(get(0, 2));
- rTranslate.setY(get(1, 2));
-
- return true;
- }
- else
- {
- // test if shear is zero. That's the case, if the unit vectors in the matrix
- // are perpendicular -> scalar is zero
- const ::basegfx::B2DVector aUnitVecX(get(0, 0), get(1, 0));
- const ::basegfx::B2DVector aUnitVecY(get(0, 1), get(1, 1));
-
- if(fTools::equalZero(aUnitVecX.scalar(aUnitVecY)))
- {
- // no shear, direct value extraction
- rShearX = 0.0;
-
- // calculate rotation
- rShearX = 0.0;
- rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());
-
- // calculate scale values
- rScale.setX(aUnitVecX.getLength());
- rScale.setY(aUnitVecY.getLength());
-
- // copy translation values
- rTranslate.setX(get(0, 2));
- rTranslate.setY(get(1, 2));
-
- return true;
- }
- else
- {
- // If determinant is zero, decomposition is not possible
- if(0.0 == determinant())
- return false;
-
- // copy 2x2 matrix and translate vector to 3x3 matrix
- ::basegfx::B3DHomMatrix a3DHomMat;
-
- a3DHomMat.set(0, 0, get(0, 0));
- a3DHomMat.set(0, 1, get(0, 1));
- a3DHomMat.set(1, 0, get(1, 0));
- a3DHomMat.set(1, 1, get(1, 1));
- a3DHomMat.set(0, 3, get(0, 2));
- a3DHomMat.set(1, 3, get(1, 2));
-
- ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;
-
- if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
- {
- // copy scale values
- rScale.setX(r3DScale.getX());
- rScale.setY(r3DScale.getY());
-
- // copy shear
- rShearX = r3DShear.getX();
-
- // copy rotate
- rRotate = r3DRotate.getZ();
-
- // copy translate
- rTranslate.setX(r3DTranslate.getX());
- rTranslate.setY(r3DTranslate.getY());
-
- return true;
- }
- }
- }
-
- return false;
- } */
-
} // end of namespace basegfx
+///////////////////////////////////////////////////////////////////////////////
// eof
diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx b/basegfx/source/matrix/b2dhommatrixtools.cxx
index 59a1ff432fc7..2c71193f6352 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -38,6 +38,339 @@
namespace basegfx
{
+ namespace tools
+ {
+ void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double fRadiant)
+ {
+ if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
+ {
+ // determine quadrant
+ const sal_Int32 nQuad(
+ (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
+ switch( nQuad )
+ {
+ case 0: // -2pi,0,2pi
+ o_rSin = 0.0;
+ o_rCos = 1.0;
+ break;
+
+ case 1: // -3/2pi,1/2pi
+ o_rSin = 1.0;
+ o_rCos = 0.0;
+ break;
+
+ case 2: // -pi,pi
+ o_rSin = 0.0;
+ o_rCos = -1.0;
+ break;
+
+ case 3: // -1/2pi,3/2pi
+ o_rSin = -1.0;
+ o_rCos = 0.0;
+ break;
+
+ default:
+ OSL_ENSURE( false, "createSinCos: Impossible case reached" );
+ }
+ }
+ else
+ {
+ // TODO(P1): Maybe use glibc's sincos here (though
+ // that's kinda non-portable...)
+ o_rSin = sin(fRadiant);
+ o_rCos = cos(fRadiant);
+ }
+ }
+
+ B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
+ {
+ B2DHomMatrix aRetval;
+ const double fOne(1.0);
+
+ if(!fTools::equal(fScaleX, fOne))
+ {
+ aRetval.set(0, 0, fScaleX);
+ }
+
+ if(!fTools::equal(fScaleY, fOne))
+ {
+ aRetval.set(1, 1, fScaleY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createShearXB2DHomMatrix(double fShearX)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fShearX))
+ {
+ aRetval.set(0, 1, fShearX);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createShearYB2DHomMatrix(double fShearY)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fShearY))
+ {
+ aRetval.set(1, 0, fShearY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createRotateB2DHomMatrix(double fRadiant)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fRadiant))
+ {
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+ aRetval.set(0, 0, fCos);
+ aRetval.set(1, 1, fCos);
+ aRetval.set(1, 0, fSin);
+ aRetval.set(0, 1, -fSin);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY)))
+ {
+ aRetval.set(0, 2, fTranslateX);
+ aRetval.set(1, 2, fTranslateY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY)
+ {
+ const double fOne(1.0);
+
+ if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
+ {
+ /// no scale, take shortcut
+ return createShearXRotateTranslateB2DHomMatrix(fShearX, fRadiant, fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// scale used
+ if(fTools::equalZero(fShearX))
+ {
+ /// no shear
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no rotate, take shortcut
+ return createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// rotate and scale used, no shear
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos * fScaleX,
+ /* Row 0, Column 1 */ fScaleY * -fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin * fScaleX,
+ /* Row 1, Column 1 */ fScaleY * fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ else
+ {
+ /// scale and shear used
+ if(fTools::equalZero(fRadiant))
+ {
+ /// scale and shear, but no rotate
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fScaleX,
+ /* Row 0, Column 1 */ fScaleY * fShearX,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ fScaleY,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// scale, shear and rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos * fScaleX,
+ /* Row 0, Column 1 */ fScaleY * ((fCos * fShearX) - fSin),
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin * fScaleX,
+ /* Row 1, Column 1 */ fScaleY * ((fSin * fShearX) + fCos),
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+ }
+
+ B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY)
+ {
+ if(fTools::equalZero(fShearX))
+ {
+ /// no shear
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no shear, no rotate, take shortcut
+ return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// no shear, but rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ -fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ else
+ {
+ /// shear used
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no rotate, but shear used
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ 1.0,
+ /* Row 0, Column 1 */ fShearX,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ 1.0,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// shear and rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ (fCos * fShearX) - fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ (fSin * fShearX) + fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+
+ B2DHomMatrix createScaleTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fTranslateX, double fTranslateY)
+ {
+ const double fOne(1.0);
+
+ if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
+ {
+ /// no scale, take shortcut
+ return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// scale used
+ if(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY))
+ {
+ /// no translate, but scale.
+ B2DHomMatrix aRetval;
+
+ aRetval.set(0, 0, fScaleX);
+ aRetval.set(1, 1, fScaleY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// translate and scale
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fScaleX,
+ /* Row 0, Column 1 */ 0.0,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ fScaleY,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+
+ B2DHomMatrix createRotateAroundPoint(
+ double fPointX, double fPointY,
+ double fRadiant)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fRadiant))
+ {
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ aRetval.set3x2(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ -fSin,
+ /* Row 0, Column 2 */ (fPointX * (1.0 - fCos)) + (fSin * fPointY),
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ fCos,
+ /* Row 1, Column 2 */ (fPointY * (1.0 - fCos)) - (fSin * fPointX));
+ }
+
+ return aRetval;
+ }
+ } // end of namespace tools
} // end of namespace basegfx
///////////////////////////////////////////////////////////////////////////////
diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx
index 1a9264ab769e..c22b5ea94011 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -40,6 +40,7 @@
#include <basegfx/range/b2drange.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -85,11 +86,9 @@ namespace basegfx
// get size of the arrow
const B2DRange aArrowSize(getRange(rArrow));
- // build ArrowTransform
- B2DHomMatrix aArrowTransform;
-
- // center in X, align with axis in Y
- aArrowTransform.translate(-aArrowSize.getCenter().getX(), -aArrowSize.getMinimum().getY());
+ // build ArrowTransform; center in X, align with axis in Y
+ B2DHomMatrix aArrowTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ -aArrowSize.getCenter().getX(), -aArrowSize.getMinimum().getY()));
// scale to target size
const double fArrowScale(fWidth / (aArrowSize.getRange().getX()));
diff --git a/basegfx/source/polygon/b2dpolygonclipper.cxx b/basegfx/source/polygon/b2dpolygonclipper.cxx
index f0d325942c07..87e44ed3d063 100644
--- a/basegfx/source/polygon/b2dpolygonclipper.cxx
+++ b/basegfx/source/polygon/b2dpolygonclipper.cxx
@@ -40,6 +40,7 @@
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <basegfx/tools/rectcliptools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -361,11 +362,10 @@ namespace basegfx
else if(rCandidate.count())
{
const B2DVector aEdge(rPointB - rPointA);
- B2DHomMatrix aMatrixTransform;
B2DPolygon aCandidate(rCandidate);
// translate and rotate polygon so that given edge is on x axis
- aMatrixTransform.translate(-rPointA.getX(), -rPointA.getY());
+ B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(-rPointA.getX(), -rPointA.getY()));
aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
aCandidate.transform(aMatrixTransform);
@@ -395,11 +395,10 @@ namespace basegfx
else if(rCandidate.count())
{
const B2DVector aEdge(rPointB - rPointA);
- B2DHomMatrix aMatrixTransform;
B2DPolyPolygon aCandidate(rCandidate);
// translate and rotate polygon so that given edge is on x axis
- aMatrixTransform.translate(-rPointA.getX(), -rPointA.getY());
+ B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(-rPointA.getX(), -rPointA.getY()));
aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
aCandidate.transform(aMatrixTransform);
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index 7485387c6cb9..d62462b8c097 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -33,7 +33,6 @@
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <osl/diagnose.h>
#include <rtl/math.hxx>
-
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/range/b2drange.hxx>
@@ -43,6 +42,8 @@
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/curve/b2dbeziertools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <osl/mutex.hxx>
#include <numeric>
#include <limits>
@@ -54,6 +55,7 @@
#ifdef DBG_UTIL
static double fAngleBoundStartValue = ANGLE_BOUND_START_VALUE;
#endif
+#define STEPSPERQUARTER (3)
//////////////////////////////////////////////////////////////////////////////
@@ -1840,145 +1842,106 @@ namespace basegfx
return createPolygonFromEllipse( rCenter, fRadius, fRadius );
}
- void appendUnitCircleQuadrant(B2DPolygon& rPolygon, sal_uInt32 nQuadrant)
+ B2DPolygon impCreateUnitCircle(sal_uInt32 nStartQuadrant)
{
- const double fZero(0.0);
- const double fOne(1.0);
+ B2DPolygon aUnitCircle;
const double fKappa((M_SQRT2 - 1.0) * 4.0 / 3.0);
+ const double fScaledKappa(fKappa * (1.0 / STEPSPERQUARTER));
+ const B2DHomMatrix aRotateMatrix(createRotateB2DHomMatrix(F_PI2 / STEPSPERQUARTER));
+
+ B2DPoint aPoint(1.0, 0.0);
+ B2DPoint aForward(1.0, fScaledKappa);
+ B2DPoint aBackward(1.0, -fScaledKappa);
- // create closed unit-circle with 4 segments
- switch(nQuadrant)
+ if(0 != nStartQuadrant)
{
- case 0 : // first quadrant
- {
- rPolygon.append(B2DPoint(fOne, fZero));
- rPolygon.appendBezierSegment(B2DPoint(fOne, fKappa), B2DPoint(fKappa, fOne), B2DPoint(fZero, fOne));
- break;
- }
- case 1 : // second quadrant
- {
- rPolygon.append(B2DPoint(fZero, fOne));
- rPolygon.appendBezierSegment(B2DPoint(-fKappa, fOne), B2DPoint(-fOne, fKappa), B2DPoint(-fOne, fZero));
- break;
- }
- case 2 : // third quadrant
- {
- rPolygon.append(B2DPoint(-fOne, fZero));
- rPolygon.appendBezierSegment(B2DPoint(-fOne, -fKappa), B2DPoint(-fKappa, -fOne), B2DPoint(fZero, -fOne));
- break;
- }
- default : // last quadrant
- {
- rPolygon.append(B2DPoint(fZero, -fOne));
- rPolygon.appendBezierSegment(B2DPoint(fKappa, -fOne), B2DPoint(fOne, -fKappa), B2DPoint(fOne, fZero));
- break;
- }
+ const B2DHomMatrix aQuadrantMatrix(createRotateB2DHomMatrix(F_PI2 * (nStartQuadrant % 4)));
+ aPoint *= aQuadrantMatrix;
+ aBackward *= aQuadrantMatrix;
+ aForward *= aQuadrantMatrix;
}
- }
- B2DPolygon createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant)
- {
- B2DPolygon aRetval;
+ aUnitCircle.append(aPoint);
- // create unit-circle with all 4 segments, close it
- appendUnitCircleQuadrant(aRetval, nStartQuadrant % 4); nStartQuadrant++;
- appendUnitCircleQuadrant(aRetval, nStartQuadrant % 4); nStartQuadrant++;
- appendUnitCircleQuadrant(aRetval, nStartQuadrant % 4); nStartQuadrant++;
- appendUnitCircleQuadrant(aRetval, nStartQuadrant % 4); nStartQuadrant++;
- aRetval.setClosed(true);
+ for(sal_uInt32 a(0); a < STEPSPERQUARTER * 4; a++)
+ {
+ aPoint *= aRotateMatrix;
+ aBackward *= aRotateMatrix;
+ aUnitCircle.appendBezierSegment(aForward, aBackward, aPoint);
+ aForward *= aRotateMatrix;
+ }
- // remove double points between segments created by segmented creation
- aRetval.removeDoublePoints();
+ aUnitCircle.setClosed(true);
+ aUnitCircle.removeDoublePoints();
- return aRetval;
+ return aUnitCircle;
}
- B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY )
+ B2DPolygon createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant)
{
- const double fOne(1.0);
- B2DPolygon aRetval(createPolygonFromUnitCircle());
-
- // transformation necessary?
- const sal_Bool bScale(!fTools::equal(fRadiusX, fOne) || !fTools::equal(fRadiusY, fOne));
- const sal_Bool bTranslate(!rCenter.equalZero());
-
- if(bScale || bTranslate)
+ switch(nStartQuadrant % 4)
{
- B2DHomMatrix aMatrix;
-
- if(bScale)
- {
- aMatrix.scale(fRadiusX, fRadiusY);
- }
-
- if(bTranslate)
+ case 1 :
{
- aMatrix.translate(rCenter.getX(), rCenter.getY());
- }
-
- aRetval.transform(aMatrix);
- }
-
- return aRetval;
- }
-
- void appendUnitCircleQuadrantSegment(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, double fStart, double fEnd)
- {
- OSL_ENSURE(fStart >= 0.0 && fStart <= 1.0, "appendUnitCircleQuadrantSegment: Access out of range (!)");
- OSL_ENSURE(fEnd >= 0.0 && fEnd <= 1.0, "appendUnitCircleQuadrantSegment: Access out of range (!)");
- OSL_ENSURE(fEnd >= fStart, "appendUnitCircleQuadrantSegment: Access out of range (!)");
- const double fOne(1.0);
- const bool bStartIsZero(fTools::equalZero(fStart));
- const bool bEndIsOne(fTools::equal(fEnd, fOne));
+ static B2DPolygon aUnitCircleStartQuadrantOne;
- if(bStartIsZero && bEndIsOne)
- {
- // add completely
- appendUnitCircleQuadrant(rPolygon, nQuadrant);
- }
- else
- {
- // split and add
- B2DPolygon aQuadrant;
- appendUnitCircleQuadrant(aQuadrant, nQuadrant);
- const bool bStartEndEqual(fTools::equal(fStart, fEnd));
+ if(!aUnitCircleStartQuadrantOne.count())
+ {
+ ::osl::Mutex m_mutex;
+ aUnitCircleStartQuadrantOne = impCreateUnitCircle(1);
+ }
- if(bStartEndEqual)
+ return aUnitCircleStartQuadrantOne;
+ }
+ case 2 :
{
- if(bStartIsZero)
+ static B2DPolygon aUnitCircleStartQuadrantTwo;
+
+ if(!aUnitCircleStartQuadrantTwo.count())
{
- // both zero, add start point
- rPolygon.append(aQuadrant.getB2DPoint(0L));
+ ::osl::Mutex m_mutex;
+ aUnitCircleStartQuadrantTwo = impCreateUnitCircle(2);
}
- else if(bEndIsOne)
+
+ return aUnitCircleStartQuadrantTwo;
+ }
+ case 3 :
+ {
+ static B2DPolygon aUnitCircleStartQuadrantThree;
+
+ if(!aUnitCircleStartQuadrantThree.count())
{
- // both one, add end point
- rPolygon.append(aQuadrant.getB2DPoint(1L));
+ ::osl::Mutex m_mutex;
+ aUnitCircleStartQuadrantThree = impCreateUnitCircle(3);
}
- else
- {
- // both equal but not zero, add split point
- B2DCubicBezier aCubicBezier(
- aQuadrant.getB2DPoint(0L), aQuadrant.getNextControlPoint(0L),
- aQuadrant.getPrevControlPoint(1L), aQuadrant.getB2DPoint(1L));
- aCubicBezier.split(fStart, &aCubicBezier, 0);
- rPolygon.append(aCubicBezier.getEndPoint());
- }
+ return aUnitCircleStartQuadrantThree;
}
- else
+ default : // case 0 :
{
- B2DCubicBezier aCubicBezier(
- aQuadrant.getB2DPoint(0L), aQuadrant.getNextControlPoint(0L),
- aQuadrant.getPrevControlPoint(1L), aQuadrant.getB2DPoint(1L));
+ static B2DPolygon aUnitCircleStartQuadrantZero;
+
+ if(!aUnitCircleStartQuadrantZero.count())
+ {
+ ::osl::Mutex m_mutex;
+ aUnitCircleStartQuadrantZero = impCreateUnitCircle(0);
+ }
- aCubicBezier = aCubicBezier.snippet(fStart, fEnd);
- rPolygon.append(aCubicBezier.getStartPoint());
- rPolygon.appendBezierSegment(aCubicBezier.getControlPointA(), aCubicBezier.getControlPointB(), aCubicBezier.getEndPoint());
+ return aUnitCircleStartQuadrantZero;
}
}
}
+ B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY )
+ {
+ B2DPolygon aRetval(createPolygonFromUnitCircle());
+ const B2DHomMatrix aMatrix(createScaleTranslateB2DHomMatrix(fRadiusX, fRadiusY, rCenter.getX(), rCenter.getY()));
+
+ aRetval.transform(aMatrix);
+
+ return aRetval;
+ }
+
B2DPolygon createPolygonFromUnitEllipseSegment( double fStart, double fEnd )
{
B2DPolygon aRetval;
@@ -2005,49 +1968,74 @@ namespace basegfx
fEnd = 0.0;
}
- const sal_uInt32 nQuadrantStart(sal_uInt32(fStart / F_PI2) % 4L);
- const sal_uInt32 nQuadrantEnd(sal_uInt32(fEnd / F_PI2) % 4L);
- sal_uInt32 nCurrentQuadrant(nQuadrantStart);
- bool bStartDone(false);
- bool bEndDone(false);
-
- do
+ if(fTools::equal(fStart, fEnd))
{
- if(!bStartDone && nQuadrantStart == nCurrentQuadrant)
- {
- if(nQuadrantStart == nQuadrantEnd && fTools::moreOrEqual(fEnd, fStart))
- {
- // both in one quadrant and defining the complete segment, create start to end
- double fSplitOffsetStart((fStart - (nCurrentQuadrant * F_PI2)) / F_PI2);
- double fSplitOffsetEnd((fEnd - (nCurrentQuadrant * F_PI2)) / F_PI2);
- appendUnitCircleQuadrantSegment(aRetval, nCurrentQuadrant, fSplitOffsetStart, fSplitOffsetEnd);
- bStartDone = bEndDone = true;
- }
- else
- {
- // create start to quadrant end
- const double fSplitOffsetStart((fStart - (nCurrentQuadrant * F_PI2)) / F_PI2);
- appendUnitCircleQuadrantSegment(aRetval, nCurrentQuadrant, fSplitOffsetStart, 1.0);
- bStartDone = true;
- }
- }
- else if(!bEndDone && nQuadrantEnd == nCurrentQuadrant)
+ // same start and end angle, add single point
+ aRetval.append(B2DPoint(cos(fStart), sin(fStart)));
+ }
+ else
+ {
+ const sal_uInt32 nSegments(STEPSPERQUARTER * 4);
+ const double fAnglePerSegment(F_PI2 / STEPSPERQUARTER);
+ const sal_uInt32 nStartSegment(sal_uInt32(fStart / fAnglePerSegment) % nSegments);
+ const sal_uInt32 nEndSegment(sal_uInt32(fEnd / fAnglePerSegment) % nSegments);
+ const double fKappa((M_SQRT2 - 1.0) * 4.0 / 3.0);
+ const double fScaledKappa(fKappa * (1.0 / STEPSPERQUARTER));
+
+ B2DPoint aSegStart(cos(fStart), sin(fStart));
+ aRetval.append(aSegStart);
+
+ if(nStartSegment == nEndSegment && fTools::more(fEnd, fStart))
{
- // create quadrant start to end
- const double fSplitOffsetEnd((fEnd - (nCurrentQuadrant * F_PI2)) / F_PI2);
- appendUnitCircleQuadrantSegment(aRetval, nCurrentQuadrant, 0.0, fSplitOffsetEnd);
- bEndDone = true;
+ // start and end in one sector and in the right order, create in one segment
+ const B2DPoint aSegEnd(cos(fEnd), sin(fEnd));
+ const double fFactor(fScaledKappa * ((fEnd - fStart) / fAnglePerSegment));
+
+ aRetval.appendBezierSegment(
+ aSegStart + (B2DPoint(-aSegStart.getY(), aSegStart.getX()) * fFactor),
+ aSegEnd - (B2DPoint(-aSegEnd.getY(), aSegEnd.getX()) * fFactor),
+ aSegEnd);
}
else
{
- // add quadrant completely
- appendUnitCircleQuadrant(aRetval, nCurrentQuadrant);
- }
+ double fSegEndRad((nStartSegment + 1) * fAnglePerSegment);
+ double fFactor(fScaledKappa * ((fSegEndRad - fStart) / fAnglePerSegment));
+ B2DPoint aSegEnd(cos(fSegEndRad), sin(fSegEndRad));
- // next step
- nCurrentQuadrant = (nCurrentQuadrant + 1L) % 4L;
+ aRetval.appendBezierSegment(
+ aSegStart + (B2DPoint(-aSegStart.getY(), aSegStart.getX()) * fFactor),
+ aSegEnd - (B2DPoint(-aSegEnd.getY(), aSegEnd.getX()) * fFactor),
+ aSegEnd);
+
+ sal_uInt32 nSegment((nStartSegment + 1) % nSegments);
+ aSegStart = aSegEnd;
+
+ while(nSegment != nEndSegment)
+ {
+ // No end in this sector, add full sector.
+ fSegEndRad = (nSegment + 1) * fAnglePerSegment;
+ aSegEnd = B2DPoint(cos(fSegEndRad), sin(fSegEndRad));
+
+ aRetval.appendBezierSegment(
+ aSegStart + (B2DPoint(-aSegStart.getY(), aSegStart.getX()) * fScaledKappa),
+ aSegEnd - (B2DPoint(-aSegEnd.getY(), aSegEnd.getX()) * fScaledKappa),
+ aSegEnd);
+
+ nSegment = (nSegment + 1) % nSegments;
+ aSegStart = aSegEnd;
+ }
+
+ // End in this sector
+ const double fSegStartRad(nSegment * fAnglePerSegment);
+ fFactor = fScaledKappa * ((fEnd - fSegStartRad) / fAnglePerSegment);
+ aSegEnd = B2DPoint(cos(fEnd), sin(fEnd));
+
+ aRetval.appendBezierSegment(
+ aSegStart + (B2DPoint(-aSegStart.getY(), aSegStart.getX()) * fFactor),
+ aSegEnd - (B2DPoint(-aSegEnd.getY(), aSegEnd.getX()) * fFactor),
+ aSegEnd);
+ }
}
- while(!(bStartDone && bEndDone));
// remove double points between segments created by segmented creation
aRetval.removeDoublePoints();
@@ -2058,28 +2046,9 @@ namespace basegfx
B2DPolygon createPolygonFromEllipseSegment( const B2DPoint& rCenter, double fRadiusX, double fRadiusY, double fStart, double fEnd )
{
B2DPolygon aRetval(createPolygonFromUnitEllipseSegment(fStart, fEnd));
+ const B2DHomMatrix aMatrix(createScaleTranslateB2DHomMatrix(fRadiusX, fRadiusY, rCenter.getX(), rCenter.getY()));
- // transformation necessary?
- const double fOne(1.0);
- const sal_Bool bScale(!fTools::equal(fRadiusX, fOne) || !fTools::equal(fRadiusY, fOne));
- const sal_Bool bTranslate(!rCenter.equalZero());
-
- if(bScale || bTranslate)
- {
- B2DHomMatrix aMatrix;
-
- if(bScale)
- {
- aMatrix.scale(fRadiusX, fRadiusY);
- }
-
- if(bTranslate)
- {
- aMatrix.translate(rCenter.getX(), rCenter.getY());
- }
-
- aRetval.transform(aMatrix);
- }
+ aRetval.transform(aMatrix);
return aRetval;
}
@@ -2709,11 +2678,7 @@ namespace basegfx
if(nPointCount)
{
- B2DHomMatrix aMatrix;
-
- aMatrix.translate(-rCenter.getX(), -rCenter.getY());
- aMatrix.rotate(fAngle);
- aMatrix.translate(rCenter.getX(), rCenter.getY());
+ const B2DHomMatrix aMatrix(basegfx::tools::createRotateAroundPoint(rCenter, fAngle));
aRetval.transform(aMatrix);
}
diff --git a/basegfx/source/polygon/b2dsvgpolypolygon.cxx b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
index 2247c237d90f..e38ec3809fb1 100644
--- a/basegfx/source/polygon/b2dsvgpolypolygon.cxx
+++ b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
@@ -36,6 +36,7 @@
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <rtl/ustring.hxx>
#include <rtl/math.hxx>
@@ -705,7 +706,7 @@ namespace basegfx
// |y1'| = |-sin phi cos phi| |(y1 - y2)/2|
const B2DPoint p1(nLastX, nLastY);
const B2DPoint p2(nX, nY);
- B2DHomMatrix aTransform; aTransform.rotate(-fPhi*M_PI/180);
+ B2DHomMatrix aTransform(basegfx::tools::createRotateB2DHomMatrix(-fPhi*M_PI/180));
const B2DPoint p1_prime( aTransform * B2DPoint(((p1-p2)/2.0)) );
@@ -797,8 +798,7 @@ namespace basegfx
fTheta1, fTheta2 ));
// transform ellipse by rotation & move to final center
- aTransform.identity();
- aTransform.scale(fRX,fRY);
+ aTransform = basegfx::tools::createScaleB2DHomMatrix(fRX, fRY);
aTransform.translate(aCenter_prime.getX(),
aCenter_prime.getY());
aTransform.rotate(fPhi*M_PI/180);
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
index 9e78039cd590..51989899ebf4 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -32,9 +32,9 @@
#include "precompiled_basegfx.hxx"
#include <basegfx/tools/gradienttools.hxx>
-
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
namespace basegfx
{
@@ -79,9 +79,8 @@ namespace basegfx
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());
+ o_rGradientInfo.maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
+ * o_rGradientInfo.maTextureTransform;
}
// add object translate
@@ -158,9 +157,8 @@ namespace basegfx
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());
+ o_rGradientInfo.maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
+ * o_rGradientInfo.maTextureTransform;
}
}
@@ -232,9 +230,8 @@ namespace basegfx
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());
+ o_rGradientInfo.maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
+ * o_rGradientInfo.maTextureTransform;
}
// add defined offsets after rotation
diff --git a/basegfx/source/tools/unopolypolygon.cxx b/basegfx/source/tools/unopolypolygon.cxx
index 6d8fcd83edb0..05dbe5b1c823 100755
--- a/basegfx/source/tools/unopolypolygon.cxx
+++ b/basegfx/source/tools/unopolypolygon.cxx
@@ -44,8 +44,8 @@
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
-
#include <basegfx/tools/unopolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace ::com::sun::star;
@@ -138,9 +138,7 @@ namespace unotools
if( !aOffset.equalZero() )
{
- B2DHomMatrix aTranslate;
- aTranslate.translate( aOffset.getX(), aOffset.getY() );
-
+ const B2DHomMatrix aTranslate(tools::createTranslateB2DHomMatrix(aOffset));
aSrcPoly.transform( aTranslate );
}
diff --git a/basegfx/test/basegfx2d.cxx b/basegfx/test/basegfx2d.cxx
index 0e0159dfab08..115b33303ee6 100644
--- a/basegfx/test/basegfx2d.cxx
+++ b/basegfx/test/basegfx2d.cxx
@@ -486,8 +486,13 @@ public:
}
while ( nIndex >= 0 );
+ // Adapted number of spaces to 50 and 67 because of the new circle construction
+ // methods which produce more points and thus more spaces, too. Use both since
+ // depending on float precision and the getContinuity() implemetation using
+ // fTools::equal, linux and mac produce more 'C' than 'S' statements, while WIN32
+ // uses more 'S' statements (as it should be for circles)
CPPUNIT_ASSERT_MESSAGE("exporting to circle does not produce the expected number of coordinates",
- nCount==18);
+ nCount==67 || nCount==50);
const B2DPolygon aRect(
tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));