summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--canvas/source/cairo/cairo_canvashelper.cxx50
-rw-r--r--canvas/source/cairo/cairo_canvashelper.hxx1
-rwxr-xr-xcanvas/source/directx/dx_canvashelper.cxx24
-rwxr-xr-xcanvas/source/directx/dx_canvashelper_texturefill.cxx4
-rwxr-xr-xcanvas/source/directx/dx_impltools.cxx67
-rwxr-xr-xcanvas/source/directx/dx_impltools.hxx15
-rwxr-xr-xcanvas/source/directx/dx_linepolypolygon.cxx4
-rwxr-xr-xcanvas/source/directx/dx_linepolypolygon.hxx2
-rw-r--r--canvas/source/simplecanvas/simplecanvasimpl.cxx11
-rw-r--r--canvas/source/tools/canvastools.cxx11
-rw-r--r--canvas/source/tools/surface.cxx11
-rw-r--r--cppcanvas/source/mtfrenderer/bitmapaction.cxx19
-rw-r--r--cppcanvas/source/mtfrenderer/implrenderer.cxx46
-rw-r--r--cppcanvas/source/mtfrenderer/mtftools.cxx11
-rw-r--r--cppcanvas/source/mtfrenderer/textaction.cxx5
-rw-r--r--goodies/inc/grfmgr.hxx2
-rw-r--r--goodies/source/filter.vcl/epict/epict.cxx120
-rw-r--r--goodies/source/filter.vcl/epict/makefile.mk2
-rw-r--r--goodies/source/filter.vcl/eps/eps.cxx61
-rw-r--r--goodies/source/graphic/grfmgr.cxx4
-rw-r--r--svtools/source/filter.vcl/wmf/emfwr.cxx93
-rw-r--r--svtools/source/filter.vcl/wmf/emfwr.hxx4
-rw-r--r--svtools/source/filter.vcl/wmf/wmfwr.cxx84
-rw-r--r--svtools/source/filter.vcl/wmf/wmfwr.hxx4
-rw-r--r--svtools/util/makefile.mk1
-rw-r--r--tools/source/generic/poly.cxx11
-rw-r--r--vcl/aqua/source/gdi/salgdi.cxx5
-rw-r--r--vcl/inc/vcl/cvtsvm.hxx4
-rw-r--r--vcl/inc/vcl/lineinfo.hxx37
-rw-r--r--vcl/inc/vcl/outdev.hxx10
-rw-r--r--vcl/os2/source/gdi/salgdi3.cxx6
-rw-r--r--vcl/source/gdi/cvtsvm.cxx354
-rw-r--r--vcl/source/gdi/implncvt.cxx577
-rw-r--r--vcl/source/gdi/implncvt.hxx78
-rw-r--r--vcl/source/gdi/lineinfo.cxx109
-rwxr-xr-xvcl/source/gdi/makefile.mk2
-rw-r--r--vcl/source/gdi/metaact.cxx77
-rw-r--r--vcl/source/gdi/outdev.cxx284
-rw-r--r--vcl/source/gdi/outdev6.cxx14
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx4
-rw-r--r--vcl/source/gdi/region.cxx9
-rw-r--r--vcl/source/gdi/salgdilayout.cxx1
-rwxr-xr-xvcl/source/gdi/sallayout.cxx7
-rw-r--r--vcl/source/glyphs/gcach_ftyp.cxx5
-rw-r--r--vcl/unx/source/gdi/salgdi.cxx12
-rw-r--r--vcl/win/source/gdi/salgdi3.cxx6
-rw-r--r--vcl/win/source/gdi/salgdi_gdiplus.cxx74
-rwxr-xr-x[-rw-r--r--]vcl/win/source/gdi/winlayout.cxx0
60 files changed, 2012 insertions, 1476 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 ab6715467dba..1bd15702e143 100644
--- a/basegfx/test/basegfx2d.cxx
+++ b/basegfx/test/basegfx2d.cxx
@@ -484,8 +484,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) ));
diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx
index 9cf2dd978759..5469010f2745 100644
--- a/canvas/source/cairo/cairo_canvashelper.cxx
+++ b/canvas/source/cairo/cairo_canvashelper.cxx
@@ -958,6 +958,7 @@ namespace cairocanvas
void CanvasHelper::doPolyPolygonPath( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
Operation aOperation,
+ bool bNoLineJoin,
const uno::Sequence< rendering::Texture >* pTextures,
Cairo* pCairo ) const
{
@@ -967,10 +968,46 @@ namespace cairocanvas
if( !pCairo )
pCairo = mpCairo.get();
- doPolyPolygonImplementation( rPolyPoly, aOperation,
- pCairo, pTextures,
- mpSurfaceProvider,
- xPolyPolygon->getFillRule() );
+ if(bNoLineJoin && Stroke == aOperation)
+ {
+ // emulate rendering::PathJoinType::NONE by painting single edges
+ for(sal_uInt32 a(0); a < rPolyPoly.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(rPolyPoly.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(aCandidate.count());
+
+ if(nPointCount)
+ {
+ const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1: nPointCount);
+ basegfx::B2DPolygon aEdge;
+ aEdge.append(aCandidate.getB2DPoint(0));
+ aEdge.append(basegfx::B2DPoint(0.0, 0.0));
+
+ for(sal_uInt32 a(0); a < nEdgeCount; a++)
+ {
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ aEdge.setB2DPoint(1, aCandidate.getB2DPoint(nNextIndex));
+ aEdge.setNextControlPoint(0, aCandidate.getNextControlPoint(a));
+ aEdge.setPrevControlPoint(1, aCandidate.getPrevControlPoint(nNextIndex));
+
+ doPolyPolygonImplementation( aEdge, aOperation,
+ pCairo, pTextures,
+ mpSurfaceProvider,
+ xPolyPolygon->getFillRule() );
+
+ // prepare next step
+ aEdge.setB2DPoint(0, aEdge.getB2DPoint(1));
+ }
+ }
+ }
+ }
+ else
+ {
+ doPolyPolygonImplementation( rPolyPoly, aOperation,
+ pCairo, pTextures,
+ mpSurfaceProvider,
+ xPolyPolygon->getFillRule() );
+ }
}
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,
@@ -1039,9 +1076,12 @@ namespace cairocanvas
break;
}
+ bool bNoLineJoin(false);
+
switch( strokeAttributes.JoinType ) {
// cairo doesn't have join type NONE so we use MITER as it's pretty close
case rendering::PathJoinType::NONE:
+ bNoLineJoin = true;
case rendering::PathJoinType::MITER:
cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_MITER );
break;
@@ -1063,7 +1103,7 @@ namespace cairocanvas
// TODO(rodo) use LineArray of strokeAttributes
- doPolyPolygonPath( xPolyPolygon, Stroke );
+ doPolyPolygonPath( xPolyPolygon, Stroke, bNoLineJoin );
cairo_restore( mpCairo.get() );
} else
diff --git a/canvas/source/cairo/cairo_canvashelper.hxx b/canvas/source/cairo/cairo_canvashelper.hxx
index 1e69a9f41e5b..90d365d63b3c 100644
--- a/canvas/source/cairo/cairo_canvashelper.hxx
+++ b/canvas/source/cairo/cairo_canvashelper.hxx
@@ -276,6 +276,7 @@ namespace cairocanvas
void doPolyPolygonPath( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
Operation aOperation,
+ bool bNoLineJoin = false,
const ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::Texture >* pTextures=NULL,
::cairo::Cairo* pCairo=NULL ) const;
diff --git a/canvas/source/directx/dx_canvashelper.cxx b/canvas/source/directx/dx_canvashelper.cxx
index 0642b6c50efb..607f7c076e21 100755
--- a/canvas/source/directx/dx_canvashelper.cxx
+++ b/canvas/source/directx/dx_canvashelper.cxx
@@ -46,6 +46,7 @@
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <comphelper/sequence.hxx>
#include <canvas/canvastools.hxx>
@@ -367,7 +368,11 @@ namespace dxcanvas
pGraphics->GetPixelOffsetMode() );
pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
- aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) );
+ const bool bIsMiter(rendering::PathJoinType::MITER == strokeAttributes.JoinType);
+ const bool bIsNone(rendering::PathJoinType::NONE == strokeAttributes.JoinType);
+
+ if(bIsMiter)
+ aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) );
const ::std::vector< Gdiplus::REAL >& rDashArray(
::comphelper::sequenceToContainer< ::std::vector< Gdiplus::REAL > >(
@@ -380,9 +385,10 @@ namespace dxcanvas
aPen.SetLineCap( gdiCapFromCap(strokeAttributes.StartCapType),
gdiCapFromCap(strokeAttributes.EndCapType),
Gdiplus::DashCapFlat );
- aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
+ if(!bIsNone)
+ aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
- GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon, bIsNone ) );
// TODO(E1): Return value
Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
@@ -733,10 +739,8 @@ namespace dxcanvas
// add output offset
if( !maOutputOffset.equalZero() )
{
- ::basegfx::B2DHomMatrix aOutputOffset;
- aOutputOffset.translate( maOutputOffset.getX(),
- maOutputOffset.getY() );
-
+ const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix(
+ maOutputOffset.getX(), maOutputOffset.getY()));
aTransform = aOutputOffset * aTransform;
}
@@ -774,10 +778,8 @@ namespace dxcanvas
// add output offset
if( !maOutputOffset.equalZero() )
{
- ::basegfx::B2DHomMatrix aOutputOffset;
- aOutputOffset.translate( maOutputOffset.getX(),
- maOutputOffset.getY() );
-
+ const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix(
+ maOutputOffset.getX(), maOutputOffset.getY()));
aTransform = aOutputOffset * aTransform;
}
diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx
index f291d197c4de..73a2d49bfb62 100755
--- a/canvas/source/directx/dx_canvashelper_texturefill.cxx
+++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx
@@ -43,6 +43,7 @@
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/tools/tools.hxx>
#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <canvas/parametricpolypolygon.hxx>
@@ -452,8 +453,7 @@ namespace dxcanvas
aFillBrush.SetColor( aFillColor );
const double nCurrScale( (nStepCount-i)/(double)nStepCount );
- aScaleMatrix.identity();
- aScaleMatrix.translate( -0.5, -0.5 );
+ aScaleMatrix = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5);
// handle anisotrophic polygon scaling
if( rValues.mnAspectRatio < 1.0 )
diff --git a/canvas/source/directx/dx_impltools.cxx b/canvas/source/directx/dx_impltools.cxx
index 40164c9a1d87..4f5b92d6bcb5 100755
--- a/canvas/source/directx/dx_impltools.cxx
+++ b/canvas/source/directx/dx_impltools.cxx
@@ -194,7 +194,8 @@ namespace dxcanvas
void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr& rOutput,
::std::vector< Gdiplus::PointF >& rPoints,
- const ::basegfx::B2DPolygon& rPoly )
+ const ::basegfx::B2DPolygon& rPoly,
+ bool bNoLineJoin)
{
const sal_uInt32 nPoints( rPoly.count() );
@@ -241,7 +242,18 @@ namespace dxcanvas
rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
static_cast<Gdiplus::REAL>(rPoint.getY()) );
- rOutput->AddBeziers( &rPoints[0], nCurrOutput );
+ if(bNoLineJoin && nCurrOutput > 7)
+ {
+ for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
+ {
+ rOutput->StartFigure();
+ rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
+ }
+ }
+ else
+ {
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput );
+ }
}
else
{
@@ -251,7 +263,20 @@ namespace dxcanvas
// Therefore, simply don't pass the last two
// points here.
if( nCurrOutput > 3 )
- rOutput->AddBeziers( &rPoints[0], nCurrOutput-2 );
+ {
+ if(bNoLineJoin && nCurrOutput > 7)
+ {
+ for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
+ {
+ rOutput->StartFigure();
+ rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
+ }
+ }
+ else
+ {
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput-2 );
+ }
+ }
}
}
else
@@ -267,10 +292,27 @@ namespace dxcanvas
static_cast<Gdiplus::REAL>(rPoint.getY()) );
}
- rOutput->AddLines( &rPoints[0], nPoints );
+ if(bNoLineJoin && nPoints > 2)
+ {
+ for(sal_uInt32 a(1); a < nPoints; a++)
+ {
+ rOutput->StartFigure();
+ rOutput->AddLine(rPoints[a - 1], rPoints[a]);
+ }
+
+ if(bClosedPolygon)
+ {
+ rOutput->StartFigure();
+ rOutput->AddLine(rPoints[nPoints - 1], rPoints[0]);
+ }
+ }
+ else
+ {
+ rOutput->AddLines( &rPoints[0], nPoints );
+ }
}
- if( bClosedPolygon )
+ if( bClosedPolygon && !bNoLineJoin )
rOutput->CloseFigure();
}
}
@@ -426,17 +468,17 @@ namespace dxcanvas
return pRes;
}
- GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly )
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly, bool bNoLineJoin )
{
GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
::std::vector< Gdiplus::PointF > aPoints;
- graphicsPathFromB2DPolygon( pRes, aPoints, rPoly );
+ graphicsPathFromB2DPolygon( pRes, aPoints, rPoly, bNoLineJoin );
return pRes;
}
- GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, bool bNoLineJoin )
{
GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
::std::vector< Gdiplus::PointF > aPoints;
@@ -446,24 +488,25 @@ namespace dxcanvas
{
graphicsPathFromB2DPolygon( pRes,
aPoints,
- rPoly.getB2DPolygon( nCurrPoly ) );
+ rPoly.getB2DPolygon( nCurrPoly ),
+ bNoLineJoin);
}
return pRes;
}
- GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly, bool bNoLineJoin )
{
LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
if( pPolyImpl )
{
- return pPolyImpl->getGraphicsPath();
+ return pPolyImpl->getGraphicsPath( bNoLineJoin );
}
else
{
return tools::graphicsPathFromB2DPolyPolygon(
- polyPolygonFromXPolyPolygon2D( xPoly ) );
+ polyPolygonFromXPolyPolygon2D( xPoly ), bNoLineJoin );
}
}
diff --git a/canvas/source/directx/dx_impltools.hxx b/canvas/source/directx/dx_impltools.hxx
index 072d1063235d..222b1a927305 100755
--- a/canvas/source/directx/dx_impltools.hxx
+++ b/canvas/source/directx/dx_impltools.hxx
@@ -107,11 +107,18 @@ namespace dxcanvas
GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const ::com::sun::star::uno::Sequence<
::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& );
- GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly );
- GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly );
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon(
+ const ::basegfx::B2DPolygon& rPoly,
+ bool bNoLineJoin = false);
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon(
+ const ::basegfx::B2DPolyPolygon& rPoly,
+ bool bNoLineJoin = false);
+
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >&,
+ bool bNoLineJoin = false );
- GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const ::com::sun::star::uno::Reference<
- ::com::sun::star::rendering::XPolyPolygon2D >& );
bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
const BitmapSharedPtr& rBitmap );
bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
diff --git a/canvas/source/directx/dx_linepolypolygon.cxx b/canvas/source/directx/dx_linepolypolygon.cxx
index e63adc3dc613..9a5569384eae 100755
--- a/canvas/source/directx/dx_linepolypolygon.cxx
+++ b/canvas/source/directx/dx_linepolypolygon.cxx
@@ -46,14 +46,14 @@ namespace dxcanvas
{
}
- GraphicsPathSharedPtr LinePolyPolygon::getGraphicsPath() const
+ GraphicsPathSharedPtr LinePolyPolygon::getGraphicsPath( bool bNoLineJoin ) const
{
// generate GraphicsPath only on demand (gets deleted as soon
// as any of the modifying methods above touches the
// B2DPolyPolygon).
if( !mpPath )
{
- mpPath = tools::graphicsPathFromB2DPolyPolygon( getPolyPolygonUnsafe() );
+ mpPath = tools::graphicsPathFromB2DPolyPolygon( getPolyPolygonUnsafe(), bNoLineJoin );
mpPath->SetFillMode( const_cast<LinePolyPolygon*>(this)->getFillRule() == rendering::FillRule_EVEN_ODD ?
Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding );
}
diff --git a/canvas/source/directx/dx_linepolypolygon.hxx b/canvas/source/directx/dx_linepolypolygon.hxx
index 431cd1b87b4f..3e061d76e768 100755
--- a/canvas/source/directx/dx_linepolypolygon.hxx
+++ b/canvas/source/directx/dx_linepolypolygon.hxx
@@ -45,7 +45,7 @@ namespace dxcanvas
public:
explicit LinePolyPolygon( const ::basegfx::B2DPolyPolygon& );
- GraphicsPathSharedPtr getGraphicsPath() const;
+ GraphicsPathSharedPtr getGraphicsPath( bool bNoLineJoin = false) const;
private:
// overridden, to clear mpPath
diff --git a/canvas/source/simplecanvas/simplecanvasimpl.cxx b/canvas/source/simplecanvas/simplecanvasimpl.cxx
index 185979b0220e..7ca251458d22 100644
--- a/canvas/source/simplecanvas/simplecanvasimpl.cxx
+++ b/canvas/source/simplecanvas/simplecanvasimpl.cxx
@@ -46,6 +46,7 @@
#include <comphelper/servicedecl.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include "canvas/canvastools.hxx"
@@ -287,10 +288,7 @@ namespace
::sal_Int8 nTextDirection ) throw (uno::RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
-
- basegfx::B2DHomMatrix offsetTransform;
- offsetTransform.translate(aOutPos.X,aOutPos.Y);
-
+ const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aOutPos.X,aOutPos.Y));
rendering::RenderState aRenderState( createStrokingRenderState() );
tools::appendToRenderState(aRenderState, offsetTransform);
@@ -305,10 +303,7 @@ namespace
const geometry::RealPoint2D& aLeftTop ) throw (uno::RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
-
- basegfx::B2DHomMatrix offsetTransform;
- offsetTransform.translate(aLeftTop.X,aLeftTop.Y);
-
+ const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aLeftTop.X,aLeftTop.Y));
rendering::RenderState aRenderState( createStrokingRenderState() );
tools::appendToRenderState(aRenderState, offsetTransform);
diff --git a/canvas/source/tools/canvastools.cxx b/canvas/source/tools/canvastools.cxx
index 23d6124e4cb8..278789637c72 100644
--- a/canvas/source/tools/canvastools.cxx
+++ b/canvas/source/tools/canvastools.cxx
@@ -63,6 +63,7 @@
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <cppuhelper/compbase1.hxx>
#include <rtl/instance.hxx>
@@ -679,9 +680,8 @@ namespace canvas
i_transformation );
// now move resulting left,top point of bounds to (0,0)
- ::basegfx::B2DHomMatrix aCorrectedTransform;
- aCorrectedTransform.translate( -aTransformedRect.getMinX(),
- -aTransformedRect.getMinY() );
+ const basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
// prepend to original transformation
o_transform = aCorrectedTransform * i_transformation;
@@ -745,9 +745,8 @@ namespace canvas
transformation );
// now move resulting left,top point of bounds to (0,0)
- ::basegfx::B2DHomMatrix aCorrectedTransform;
- aCorrectedTransform.translate( -aTransformedRect.getMinX(),
- -aTransformedRect.getMinY() );
+ basegfx::B2DHomMatrix aCorrectedTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ -aTransformedRect.getMinX(), -aTransformedRect.getMinY()));
// scale to match outRect
const double xDenom( aTransformedRect.getWidth() );
diff --git a/canvas/source/tools/surface.cxx b/canvas/source/tools/surface.cxx
index c3161758ea3e..96162f6d78af 100644
--- a/canvas/source/tools/surface.cxx
+++ b/canvas/source/tools/surface.cxx
@@ -33,6 +33,7 @@
#include "surface.hxx"
#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <comphelper/scopeguard.hxx>
#include <boost/bind.hpp>
@@ -150,9 +151,8 @@ namespace canvas
// 4) scale to normalized device coordinates
// 5) flip y-axis
// 6) translate to account for viewport transform
- ::basegfx::B2DHomMatrix aTransform;
- aTransform.translate(maSourceOffset.getX(),
- maSourceOffset.getY());
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ maSourceOffset.getX(), maSourceOffset.getY()));
aTransform = aTransform * rTransform;
aTransform.translate(::basegfx::fround(rPos.getX()),
::basegfx::fround(rPos.getY()));
@@ -277,8 +277,7 @@ namespace canvas
// 1) offset of surface subarea
// 2) surface transform
// 3) translation to output position [rPos]
- ::basegfx::B2DHomMatrix aTransform;
- aTransform.translate(aPos1.getX(),aPos1.getY());
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(aPos1.getX(), aPos1.getY()));
aTransform = aTransform * rTransform;
aTransform.translate(::basegfx::fround(rPos.getX()),
::basegfx::fround(rPos.getY()));
@@ -380,7 +379,7 @@ namespace canvas
// be transformed by the overall transform and uv coordinates will
// be calculated from the result, and this is why we need to use
// integer coordinates here...
- ::basegfx::B2DHomMatrix aTransform;
+ basegfx::B2DHomMatrix aTransform;
aTransform = aTransform * rTransform;
aTransform.translate(::basegfx::fround(rPos.getX()),
::basegfx::fround(rPos.getY()));
diff --git a/cppcanvas/source/mtfrenderer/bitmapaction.cxx b/cppcanvas/source/mtfrenderer/bitmapaction.cxx
index 355dd336e2c5..4f54b10c4879 100644
--- a/cppcanvas/source/mtfrenderer/bitmapaction.cxx
+++ b/cppcanvas/source/mtfrenderer/bitmapaction.cxx
@@ -35,25 +35,21 @@
#include <com/sun/star/rendering/XBitmap.hpp>
#include <com/sun/star/rendering/RepaintResult.hpp>
#include <com/sun/star/rendering/XCachedPrimitive.hpp>
-
#include <vcl/bitmapex.hxx>
#include <tools/gen.hxx>
#include <vcl/canvastools.hxx>
-
#include <canvas/canvastools.hxx>
-
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/tools/canvastools.hxx>
-
#include <boost/utility.hpp>
-
#include "cachedprimitivebase.hxx"
#include "bitmapaction.hxx"
#include "outdevstate.hxx"
#include "mtftools.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace ::com::sun::star;
@@ -112,9 +108,7 @@ namespace cppcanvas
// Setup transformation such that the next render call is
// moved rPoint away.
- ::basegfx::B2DHomMatrix aLocalTransformation;
- aLocalTransformation.translate( rDstPoint.getX(),
- rDstPoint.getY() );
+ const basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createTranslateB2DHomMatrix(rDstPoint));
::canvas::tools::appendToRenderState( maState,
aLocalTransformation );
@@ -144,15 +138,12 @@ namespace cppcanvas
// moved rPoint away, and scaled according to the ratio
// given by src and dst size.
const ::Size aBmpSize( rBmpEx.GetSizePixel() );
- ::basegfx::B2DHomMatrix aLocalTransformation;
const ::basegfx::B2DVector aScale( rDstSize.getX() / aBmpSize.Width(),
rDstSize.getY() / aBmpSize.Height() );
- aLocalTransformation.scale( aScale.getX(), aScale.getY() );
- aLocalTransformation.translate( rDstPoint.getX(),
- rDstPoint.getY() );
- ::canvas::tools::appendToRenderState( maState,
- aLocalTransformation );
+ const basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aScale, rDstPoint));
+ ::canvas::tools::appendToRenderState( maState, aLocalTransformation );
// correct clip (which is relative to original transform)
tools::modifyClip( maState,
diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx
index c6f9a295b332..8ea2ae453a97 100644
--- a/cppcanvas/source/mtfrenderer/implrenderer.cxx
+++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx
@@ -34,19 +34,14 @@
#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>
#include <canvas/verbosetrace.hxx>
-
#include <osl/mutex.hxx>
#include <vos/mutex.hxx>
#include <vcl/svapp.hxx>
-
#include <rtl/logfile.hxx>
-
#include <comphelper/sequence.hxx>
#include <comphelper/anytostring.hxx>
#include <cppuhelper/exc_hlp.hxx>
-
#include <cppcanvas/canvas.hxx>
-
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/TexturingMode.hpp>
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
@@ -59,7 +54,6 @@
#include <com/sun/star/rendering/XCanvas.hpp>
#include <com/sun/star/rendering/PathCapType.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
-
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
@@ -73,7 +67,6 @@
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
-
#include <canvas/canvastools.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/salbtype.hxx>
@@ -84,11 +77,9 @@
#include <vcl/graphictools.hxx>
#include <tools/poly.hxx>
#include <i18npool/mslangid.hxx>
-
#include <implrenderer.hxx>
#include <tools.hxx>
#include <outdevstate.hxx>
-
#include <action.hxx>
#include <bitmapaction.hxx>
#include <lineaction.hxx>
@@ -96,15 +87,13 @@
#include <polypolyaction.hxx>
#include <textaction.hxx>
#include <transparencygroupaction.hxx>
-
#include <vector>
#include <algorithm>
#include <iterator>
-
#include <boost/scoped_array.hpp>
-
#include "mtftools.hxx"
#include "outdevstate.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace ::com::sun::star;
@@ -286,10 +275,25 @@ namespace
(getState( rParms.mrStates ).mapModeTransform * aWidth).getX();
// setup reasonable defaults
- o_rStrokeAttributes.MiterLimit = 1.0;
+ o_rStrokeAttributes.MiterLimit = 15.0; // 1.0 was no good default; GDI+'s limit is 10.0, our's is 15.0
o_rStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
o_rStrokeAttributes.EndCapType = rendering::PathCapType::BUTT;
- o_rStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
+
+ switch(rLineInfo.GetLineJoin())
+ {
+ default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::NONE;
+ break;
+ case basegfx::B2DLINEJOIN_BEVEL:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::BEVEL;
+ break;
+ case basegfx::B2DLINEJOIN_MITER:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
+ break;
+ case basegfx::B2DLINEJOIN_ROUND:
+ o_rStrokeAttributes.JoinType = rendering::PathJoinType::ROUND;
+ break;
+ }
if( LINE_DASH == rLineInfo.GetStyle() )
{
@@ -729,12 +733,11 @@ namespace cppcanvas
fabs( aBounds.getHeight()*sin(nRotation) ) +
fabs( aBounds.getWidth()*cos(nRotation) )));
- aTextureTransformation.scale( nScale, nScale );
-
- // translate back origin to center of
+ // scale and translate back origin to center of
// primitive
- aTextureTransformation.translate( 0.5*aBounds.getWidth(),
- 0.5*aBounds.getHeight() );
+ aTextureTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(
+ nScale, nScale, 0.5*aBounds.getWidth(), 0.5*aBounds.getHeight())
+ * aTextureTransformation;
}
break;
@@ -856,9 +859,8 @@ namespace cppcanvas
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 = basegfx::tools::createRotateAroundPoint(0.5*nScaleX, 0.5*nScaleY, nRotation)
+ * aTextureTransformation;
aTextureTransformation.translate( nOffsetX, nOffsetY );
}
diff --git a/cppcanvas/source/mtfrenderer/mtftools.cxx b/cppcanvas/source/mtfrenderer/mtftools.cxx
index e4e227955da6..b6a548aa49be 100644
--- a/cppcanvas/source/mtfrenderer/mtftools.cxx
+++ b/cppcanvas/source/mtfrenderer/mtftools.cxx
@@ -34,10 +34,8 @@
#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>
#include <canvas/verbosetrace.hxx>
-
#include <com/sun/star/rendering/RenderState.hpp>
#include <com/sun/star/rendering/XCanvas.hpp>
-
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
@@ -45,16 +43,15 @@
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <canvas/canvastools.hxx>
-
#include <vcl/gdimtf.hxx>
#include <vcl/metaact.hxx>
#include <vcl/virdev.hxx>
#include <vcl/metric.hxx>
#include <tools/poly.hxx>
-
#include "mtftools.hxx"
#include "outdevstate.hxx"
#include "polypolyaction.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
@@ -111,9 +108,9 @@ namespace cppcanvas
const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) );
- o_rMatrix.identity();
- o_rMatrix.scale( aSizePixel.Width() / (double)aSizeLogic.Width(),
- aSizePixel.Height() / (double)aSizeLogic.Height() );
+ o_rMatrix = basegfx::tools::createScaleB2DHomMatrix(
+ aSizePixel.Width() / (double)aSizeLogic.Width(),
+ aSizePixel.Height() / (double)aSizeLogic.Height() );
return o_rMatrix;
}
diff --git a/cppcanvas/source/mtfrenderer/textaction.cxx b/cppcanvas/source/mtfrenderer/textaction.cxx
index f1191e6e57f3..038b68c3008e 100644
--- a/cppcanvas/source/mtfrenderer/textaction.cxx
+++ b/cppcanvas/source/mtfrenderer/textaction.cxx
@@ -48,6 +48,7 @@
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <tools/gen.hxx>
#include <vcl/canvastools.hxx>
@@ -93,9 +94,7 @@ namespace cppcanvas
NULL,
&rState.fontRotation );
- ::basegfx::B2DHomMatrix aLocalTransformation;
-
- aLocalTransformation.rotate( rState.fontRotation );
+ basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState.fontRotation));
aLocalTransformation.translate( rStartPoint.getX(),
rStartPoint.getY() );
::canvas::tools::appendToRenderState( o_rRenderState,
diff --git a/goodies/inc/grfmgr.hxx b/goodies/inc/grfmgr.hxx
index b44c27ea65e3..1ef351ae6d32 100644
--- a/goodies/inc/grfmgr.hxx
+++ b/goodies/inc/grfmgr.hxx
@@ -353,7 +353,7 @@ public:
void ReleaseFromCache();
const Graphic& GetGraphic() const;
- void SetGraphic( const Graphic& rGraphic );
+ void SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj = 0);
void SetGraphic( const Graphic& rGraphic, const String& rLink );
/** Get graphic transformed according to given attributes
diff --git a/goodies/source/filter.vcl/epict/epict.cxx b/goodies/source/filter.vcl/epict/epict.cxx
index 3e4dca455d05..cd9e33edd5d9 100644
--- a/goodies/source/filter.vcl/epict/epict.cxx
+++ b/goodies/source/filter.vcl/epict/epict.cxx
@@ -55,6 +55,9 @@
#include "dlgepct.hrc"
#include "dlgepct.hxx"
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
//============================== PictWriter ===================================
struct PictWriterAttrStackMember {
@@ -77,7 +80,6 @@ struct PictPattern {
sal_uInt32 nLo, nHi;
};
-
class PictWriter {
private:
@@ -178,6 +180,7 @@ private:
void WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry);
+ void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
void WriteOpcodes(const GDIMetaFile & rMTF);
void WriteHeader(const GDIMetaFile & rMTF);
@@ -1371,6 +1374,65 @@ void PictWriter::WriteTextArray(Point & rPoint, const String& rString, const sal
}
}
+void PictWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
+{
+ if(rLinePolygon.count())
+ {
+ basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+
+ rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
+
+ if(aLinePolyPolygon.count())
+ {
+ aLinePolyPolygon = aLinePolyPolygon.getDefaultAdaptiveSubdivision();
+ const sal_uInt32 nPolyCount(aLinePolyPolygon.count());
+ SetAttrForFrame();
+
+ for(sal_uInt32 a(0); a < nPolyCount; a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(aCandidate.count());
+
+ if(nPointCount)
+ {
+ const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount);
+ const basegfx::B2DPoint aCurr(aCandidate.getB2DPoint(0));
+ Point nCurr(basegfx::fround(aCurr.getX()), basegfx::fround(aCurr.getY()));
+
+ for(sal_uInt32 b(0); b < nEdgeCount; b++)
+ {
+ const sal_uInt32 nNextIndex((b + 1) % nPointCount);
+ const basegfx::B2DPoint aNext(aCandidate.getB2DPoint(nNextIndex));
+ const Point nNext(basegfx::fround(aNext.getX()), basegfx::fround(aNext.getY()));
+
+ WriteOpcode_Line(nCurr, nNext);
+ nCurr = nNext;
+ }
+ }
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(aLineColor);
+ const Color aOldFillColor(aFillColor);
+
+ aLineColor = Color( COL_TRANSPARENT );
+ aFillColor = aOldLineColor;
+ SetAttrForPaint();
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a).getDefaultAdaptiveSubdivision());
+ WriteOpcode_Poly(PDM_PAINT, aPolygon);
+ }
+
+ aLineColor = aOldLineColor;
+ aFillColor = aOldFillColor;
+ }
+ }
+}
void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
{
@@ -1417,8 +1479,19 @@ void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
if( aLineColor != Color( COL_TRANSPARENT ) )
{
- SetAttrForFrame();
- WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() );
+ if(pA->GetLineInfo().IsDefault())
+ {
+ SetAttrForFrame();
+ WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
+ aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
}
break;
}
@@ -1571,24 +1644,35 @@ void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF )
{
const Polygon& rPoly = pA->GetPolygon();
- Polygon aSimplePoly;
- if ( rPoly.HasFlags() )
- rPoly.AdaptiveSubdivide( aSimplePoly );
- else
- aSimplePoly = rPoly;
-
- const USHORT nSize = aSimplePoly.GetSize();
- Point aLast;
-
- if ( nSize )
+ if( rPoly.GetSize() )
{
- SetAttrForFrame();
- aLast = aSimplePoly[0];
+ if(pA->GetLineInfo().IsDefault())
+ {
+ Polygon aSimplePoly;
+ if ( rPoly.HasFlags() )
+ rPoly.AdaptiveSubdivide( aSimplePoly );
+ else
+ aSimplePoly = rPoly;
- for ( USHORT i = 1; i < nSize; i++ )
+ const USHORT nSize = aSimplePoly.GetSize();
+ Point aLast;
+
+ if ( nSize )
+ {
+ SetAttrForFrame();
+ aLast = aSimplePoly[0];
+
+ for ( USHORT i = 1; i < nSize; i++ )
+ {
+ WriteOpcode_Line( aLast, aSimplePoly[i] );
+ aLast = aSimplePoly[i];
+ }
+ }
+ }
+ else
{
- WriteOpcode_Line( aLast, aSimplePoly[i] );
- aLast = aSimplePoly[i];
+ // LineInfo used; handle Dash/Dot and fat lines
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
}
}
}
diff --git a/goodies/source/filter.vcl/epict/makefile.mk b/goodies/source/filter.vcl/epict/makefile.mk
index 4aa4bab80ffc..9f25a562488a 100644
--- a/goodies/source/filter.vcl/epict/makefile.mk
+++ b/goodies/source/filter.vcl/epict/makefile.mk
@@ -61,7 +61,7 @@ RESLIB1SRSFILES=$(SRS)$/$(TARGET).srs
.IF "$(L10N_framework)"==""
SHL1TARGET= ept$(DLLPOSTFIX)
SHL1IMPLIB= epict
-SHL1STDLIBS= $(TOOLSLIB) $(VCLLIB) $(SVTOOLLIB) $(CPPULIB) $(SALLIB)
+SHL1STDLIBS= $(TOOLSLIB) $(VCLLIB) $(SVTOOLLIB) $(CPPULIB) $(SALLIB) $(BASEGFXLIB)
SHL1LIBS= $(SLB)$/epict.lib
diff --git a/goodies/source/filter.vcl/eps/eps.cxx b/goodies/source/filter.vcl/eps/eps.cxx
index dc8e407b178e..83b5a94f97f2 100644
--- a/goodies/source/filter.vcl/eps/eps.cxx
+++ b/goodies/source/filter.vcl/eps/eps.cxx
@@ -388,7 +388,7 @@ BOOL PSWriter::WritePS( const Graphic& rGraphic, SvStream& rTargetStream, Filter
bTextFillColor = TRUE;
aTextFillColor = Color( COL_BLACK );
fLineWidth = 1;
- fMiterLimit = 10;
+ fMiterLimit = 15; // use same limit as most graphic systems and basegfx
eLineCap = SvtGraphicStroke::capButt;
eJoinType = SvtGraphicStroke::joinMiter;
aBackgroundColor = Color( COL_WHITE );
@@ -701,7 +701,40 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
Polygon aPoly( ( (const MetaPolyLineAction*) pMA )->GetPolygon() );
const LineInfo& rLineInfo = ( ( const MetaPolyLineAction*)pMA )->GetLineInfo();
ImplWriteLineInfo( rLineInfo );
- ImplPolyLine( aPoly );
+
+ if(basegfx::B2DLINEJOIN_NONE == rLineInfo.GetLineJoin()
+ && rLineInfo.GetWidth() > 1)
+ {
+ // emulate B2DLINEJOIN_NONE by creating single edges
+ const sal_uInt16 nPoints(aPoly.GetSize());
+ const bool bCurve(aPoly.HasFlags());
+
+ for(sal_uInt16 a(0); a + 1 < nPoints; a++)
+ {
+ if(bCurve
+ && POLY_NORMAL != aPoly.GetFlags(a + 1)
+ && a + 2 < nPoints
+ && POLY_NORMAL != aPoly.GetFlags(a + 2)
+ && a + 3 < nPoints)
+ {
+ const Polygon aSnippet(4,
+ aPoly.GetConstPointAry() + a,
+ aPoly.GetConstFlagAry() + a);
+ ImplPolyLine(aSnippet);
+ a += 2;
+ }
+ else
+ {
+ const Polygon aSnippet(2,
+ aPoly.GetConstPointAry() + a);
+ ImplPolyLine(aSnippet);
+ }
+ }
+ }
+ else
+ {
+ ImplPolyLine( aPoly );
+ }
}
break;
@@ -2343,8 +2376,28 @@ void PSWriter::ImplWriteLineInfo( const LineInfo& rLineInfo )
SvtGraphicStroke::DashArray l_aDashArray;
if ( rLineInfo.GetStyle() == LINE_DASH )
l_aDashArray.push_back( 2 );
- double fLWidth = ( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5;
- ImplWriteLineInfo( fLWidth, 10.0, SvtGraphicStroke::capButt, SvtGraphicStroke::joinMiter, l_aDashArray );
+ const double fLWidth(( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5);
+ SvtGraphicStroke::JoinType aJoinType(SvtGraphicStroke::joinMiter);
+
+ switch(rLineInfo.GetLineJoin())
+ {
+ default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
+ // do NOT use SvtGraphicStroke::joinNone here
+ // since it will be written as numerical value directly
+ // and is NOT a valid EPS value
+ break;
+ case basegfx::B2DLINEJOIN_MITER:
+ aJoinType = SvtGraphicStroke::joinMiter;
+ break;
+ case basegfx::B2DLINEJOIN_BEVEL:
+ aJoinType = SvtGraphicStroke::joinBevel;
+ break;
+ case basegfx::B2DLINEJOIN_ROUND:
+ aJoinType = SvtGraphicStroke::joinRound;
+ break;
+ }
+
+ ImplWriteLineInfo( fLWidth, fMiterLimit, SvtGraphicStroke::capButt, aJoinType, l_aDashArray );
}
//---------------------------------------------------------------------------------
diff --git a/goodies/source/graphic/grfmgr.cxx b/goodies/source/graphic/grfmgr.cxx
index 39c1e53e7184..7f5970383075 100644
--- a/goodies/source/graphic/grfmgr.cxx
+++ b/goodies/source/graphic/grfmgr.cxx
@@ -845,7 +845,7 @@ const Graphic& GraphicObject::GetGraphic() const
// -----------------------------------------------------------------------------
-void GraphicObject::SetGraphic( const Graphic& rGraphic )
+void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pCopyObj )
{
mpMgr->ImplUnregisterObj( *this );
@@ -858,7 +858,7 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic )
delete mpLink, mpLink = NULL;
delete mpSimpleCache, mpSimpleCache = NULL;
- mpMgr->ImplRegisterObj( *this, maGraphic );
+ mpMgr->ImplRegisterObj( *this, maGraphic, 0, pCopyObj);
if( mpSwapOutTimer )
mpSwapOutTimer->Start();
diff --git a/svtools/source/filter.vcl/wmf/emfwr.cxx b/svtools/source/filter.vcl/wmf/emfwr.cxx
index df56afc4a250..f516c2eefbd0 100644
--- a/svtools/source/filter.vcl/wmf/emfwr.cxx
+++ b/svtools/source/filter.vcl/wmf/emfwr.cxx
@@ -33,6 +33,8 @@
#include "emfwr.hxx"
#include <vcl/salbtype.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
// -----------
// - Defines -
@@ -829,6 +831,46 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, const String rText, cons
// -----------------------------------------------------------------------------
+void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
+{
+ if(rLinePolygon.count())
+ {
+ basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+
+ rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
+
+ if(aLinePolyPolygon.count())
+ {
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ ImplWritePolygonRecord( Polygon(aCandidate), FALSE );
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(maVDev.GetLineColor());
+ const Color aOldFillColor(maVDev.GetFillColor());
+
+ maVDev.SetLineColor();
+ maVDev.SetFillColor(aOldLineColor);
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ ImplWritePolyPolygonRecord(PolyPolygon(Polygon(aPolygon)));
+ }
+
+ maVDev.SetLineColor(aOldLineColor);
+ maVDev.SetFillColor(aOldFillColor);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
{
for( ULONG j = 0, nActionCount = rMtf.GetActionCount(); j < nActionCount; j++ )
@@ -871,20 +913,31 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
{
const MetaLineAction* pA = (const MetaLineAction*) pAction;
- ImplCheckLineAttr();
+ if(pA->GetLineInfo().IsDefault())
+ {
+ ImplCheckLineAttr();
- ImplBeginRecord( WIN_EMR_MOVETOEX );
- ImplWritePoint( pA->GetStartPoint() );
- ImplEndRecord();
+ ImplBeginRecord( WIN_EMR_MOVETOEX );
+ ImplWritePoint( pA->GetStartPoint() );
+ ImplEndRecord();
- ImplBeginRecord( WIN_EMR_LINETO );
- ImplWritePoint( pA->GetEndPoint() );
- ImplEndRecord();
+ ImplBeginRecord( WIN_EMR_LINETO );
+ ImplWritePoint( pA->GetEndPoint() );
+ ImplEndRecord();
- ImplBeginRecord( WIN_EMR_SETPIXELV );
- ImplWritePoint( pA->GetEndPoint() );
- ImplWriteColor( maVDev.GetLineColor() );
- ImplEndRecord();
+ ImplBeginRecord( WIN_EMR_SETPIXELV );
+ ImplWritePoint( pA->GetEndPoint() );
+ ImplWriteColor( maVDev.GetLineColor() );
+ ImplEndRecord();
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
+ aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
+ Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
}
}
break;
@@ -983,7 +1036,23 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
case( META_POLYLINE_ACTION ):
{
if( maVDev.IsLineColor() )
- ImplWritePolygonRecord( ( (const MetaPolyLineAction*) pAction )->GetPolygon(), FALSE );
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ if(pA->GetLineInfo().IsDefault())
+ {
+ ImplWritePolygonRecord( rPoly, FALSE );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
+ }
+ }
+ }
}
break;
diff --git a/svtools/source/filter.vcl/wmf/emfwr.hxx b/svtools/source/filter.vcl/wmf/emfwr.hxx
index 150aa1692ade..2d3c8801ba49 100644
--- a/svtools/source/filter.vcl/wmf/emfwr.hxx
+++ b/svtools/source/filter.vcl/wmf/emfwr.hxx
@@ -42,6 +42,9 @@
// - EMFWriter -
// -------------
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
class EMFWriter
{
private:
@@ -86,6 +89,7 @@ private:
void ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, const Size& rSz, UINT32 nROP );
void ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth );
+ void Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
void ImplWrite( const GDIMetaFile& rMtf );
public:
diff --git a/svtools/source/filter.vcl/wmf/wmfwr.cxx b/svtools/source/filter.vcl/wmf/wmfwr.cxx
index d25d4e94f97a..30d4ff06c0d2 100644
--- a/svtools/source/filter.vcl/wmf/wmfwr.cxx
+++ b/svtools/source/filter.vcl/wmf/wmfwr.cxx
@@ -42,8 +42,9 @@
#include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
#endif
-
#include <vcl/metric.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
//====================== MS-Windows-defines ===============================
@@ -1136,6 +1137,49 @@ void WMFWriter::SetAllAttr()
}
+void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
+{
+ if(rLinePolygon.count())
+ {
+ basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+
+ rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
+
+ if(aLinePolyPolygon.count())
+ {
+ aSrcLineInfo = rInfo;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ WMFRecord_PolyLine(Polygon(aCandidate));
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(aSrcLineColor);
+ const Color aOldFillColor(aSrcFillColor);
+
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ aSrcFillColor = aOldLineColor;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ WMFRecord_Polygon(Polygon(aPolygon));
+ }
+
+ aSrcLineColor = aOldLineColor;
+ aSrcFillColor = aOldFillColor;
+ SetLineAndFillAttr();
+ }
+ }
+}
+
void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
{
ULONG nA, nACount;
@@ -1176,10 +1220,21 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
case META_LINE_ACTION:
{
const MetaLineAction* pA = (const MetaLineAction *) pMA;
- aSrcLineInfo = pA->GetLineInfo();
- SetLineAndFillAttr();
- WMFRecord_MoveTo( pA->GetStartPoint() );
- WMFRecord_LineTo( pA->GetEndPoint() );
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_MoveTo( pA->GetStartPoint() );
+ WMFRecord_LineTo( pA->GetEndPoint() );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
+ aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
}
break;
@@ -1241,9 +1296,22 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
case META_POLYLINE_ACTION:
{
const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
- aSrcLineInfo = pA->GetLineInfo();
- SetLineAndFillAttr();
- WMFRecord_PolyLine( pA->GetPolygon() );
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyLine( rPoly );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
+ }
+ }
}
break;
diff --git a/svtools/source/filter.vcl/wmf/wmfwr.hxx b/svtools/source/filter.vcl/wmf/wmfwr.hxx
index 48986a280404..03ca14e7633f 100644
--- a/svtools/source/filter.vcl/wmf/wmfwr.hxx
+++ b/svtools/source/filter.vcl/wmf/wmfwr.hxx
@@ -65,6 +65,9 @@ struct WMFWriterAttrStackMember
// -------------
class StarSymbolToMSMultiFont;
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
class WMFWriter
{
private:
@@ -202,6 +205,7 @@ private:
void SetLineAndFillAttr();
void SetAllAttr();
+ void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
void WriteRecords(const GDIMetaFile & rMTF);
void WriteHeader(const GDIMetaFile & rMTF, BOOL bPlaceable);
diff --git a/svtools/util/makefile.mk b/svtools/util/makefile.mk
index 51ea7a9fef31..22be04f95d3f 100644
--- a/svtools/util/makefile.mk
+++ b/svtools/util/makefile.mk
@@ -112,6 +112,7 @@ SHL1STDLIBS+= \
$(VCLLIB) \
$(SVLLIB) \
$(SOTLIB) \
+ $(BASEGFXLIB) \
$(UNOTOOLSLIB) \
$(TOOLSLIB) \
$(I18NISOLANGLIB) \
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index 7f1eb94b646d..509d2ab4969d 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -1615,7 +1615,16 @@ void Polygon::Clip( const Rectangle& rRect, BOOL bPolygon )
Rectangle Polygon::GetBoundRect() const
{
DBG_CHKTHIS( Polygon, NULL );
- DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetBoundRect could fail with beziers!" );
+ // Removing the assert. Bezier curves have the attribute that each single
+ // curve segment defined by four points can not exit the four-point polygon
+ // defined by that points. This allows to say that the curve segment can also
+ // never leave the Range of it's defining points.
+ // The result is that Polygon::GetBoundRect() may not create the minimal
+ // BoundRect of the Polygon (to get that, use basegfx::B2DPolygon classes),
+ // but will always create a valid BoundRect, at least as long as this method
+ // 'blindly' travels over all points, including control points.
+ //
+ // DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetBoundRect could fail with beziers!" );
USHORT nCount = mpImplPolygon->mnPoints;
if( ! nCount )
diff --git a/vcl/aqua/source/gdi/salgdi.cxx b/vcl/aqua/source/gdi/salgdi.cxx
index 1c9bdda3fbdb..263a5b6e6803 100644
--- a/vcl/aqua/source/gdi/salgdi.cxx
+++ b/vcl/aqua/source/gdi/salgdi.cxx
@@ -54,6 +54,7 @@
#include "basegfx/polygon/b2dpolygon.hxx"
#include "basegfx/polygon/b2dpolygontools.hxx"
#include "basegfx/matrix/b2dhommatrix.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace vcl;
@@ -1768,9 +1769,7 @@ BOOL AquaSalGraphics::GetGlyphOutline( long nGlyphId, basegfx::B2DPolyPolygon& r
GgoClosePathProc( &aGgoData );
if( mfFontScale != 1.0 ) {
- basegfx::B2DHomMatrix aScale;
- aScale.scale( +mfFontScale, +mfFontScale );
- rPolyPoly.transform( aScale );
+ rPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(+mfFontScale, +mfFontScale));
}
return true;
}
diff --git a/vcl/inc/vcl/cvtsvm.hxx b/vcl/inc/vcl/cvtsvm.hxx
index 8a17015d99cf..c6f4f2c9a126 100644
--- a/vcl/inc/vcl/cvtsvm.hxx
+++ b/vcl/inc/vcl/cvtsvm.hxx
@@ -85,6 +85,10 @@
#define GDI_COMMENT_COMMENT 1031
#define GDI_UNICODE_COMMENT 1032
+#define GDI_LINEJOIN_ACTION 1033
+#define GDI_EXTENDEDPOLYGON_ACTION 1034
+#define GDI_LINEDASHDOT_ACTION 1035
+
// ----------------
// - SVMConverter -
// ----------------
diff --git a/vcl/inc/vcl/lineinfo.hxx b/vcl/inc/vcl/lineinfo.hxx
index 60fdc3a3a0b0..33758046c41e 100644
--- a/vcl/inc/vcl/lineinfo.hxx
+++ b/vcl/inc/vcl/lineinfo.hxx
@@ -32,26 +32,29 @@
#define _SV_LINEINFO_HXX
#include <vcl/dllapi.h>
-
#include <tools/gen.hxx>
#include <vcl/vclenum.hxx>
+#include <basegfx/vector/b2enums.hxx>
// ----------------
// - ImplLineInfo -
// ----------------
class SvStream;
+namespace basegfx { class B2DPolyPolygon; }
struct ImplLineInfo
{
- ULONG mnRefCount;
- LineStyle meStyle;
- long mnWidth;
- USHORT mnDashCount;
- long mnDashLen;
- USHORT mnDotCount;
- long mnDotLen;
- long mnDistance;
+ ULONG mnRefCount;
+ LineStyle meStyle;
+ long mnWidth;
+ USHORT mnDashCount;
+ long mnDashLen;
+ USHORT mnDotCount;
+ long mnDotLen;
+ long mnDistance;
+
+ basegfx::B2DLineJoin meLineJoin;
ImplLineInfo();
ImplLineInfo( const ImplLineInfo& rImplLineInfo );
@@ -107,10 +110,26 @@ public:
void SetDistance( long nDistance );
long GetDistance() const { return mpImplLineInfo->mnDistance; }
+ void SetLineJoin(basegfx::B2DLineJoin eLineJoin);
+ basegfx::B2DLineJoin GetLineJoin() const { return mpImplLineInfo->meLineJoin; }
+
BOOL IsDefault() const { return( !mpImplLineInfo->mnWidth && ( LINE_SOLID == mpImplLineInfo->meStyle ) ); }
friend VCL_DLLPUBLIC SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo );
friend VCL_DLLPUBLIC SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo );
+
+ // helper to check if line width or DashDot is used
+ bool isDashDotOrFatLineUsed() const;
+
+ // helper to get decomposed polygon data with the LineInfo applied. The source
+ // hairline polygon is given in io_rLinePolyPolygon. Both given polygons may
+ // contain results; e.g. when no fat line but DasDot is defined, the resut will
+ // be in io_rLinePolyPolygon while o_rFillPolyPolygon will be empty. When fat line
+ // is defined, it will be vice-versa. If none is defined, io_rLinePolyPolygon will
+ // not be changed (but o_rFillPolyPolygon will be freed)
+ void applyToB2DPolyPolygon(
+ basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
+ basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const;
};
#endif // _SV_LINEINFO_HXX
diff --git a/vcl/inc/vcl/outdev.hxx b/vcl/inc/vcl/outdev.hxx
index 1e1f784f0f49..4a5b92444c21 100644
--- a/vcl/inc/vcl/outdev.hxx
+++ b/vcl/inc/vcl/outdev.hxx
@@ -562,6 +562,9 @@ public:
// Helper who tries to use SalGDI's DrawPolyLine direct and returns it's bool. Contains no AA check.
SAL_DLLPRIVATE bool ImpTryDrawPolyLineDirect(const basegfx::B2DPolygon& rB2DPolygon, double fLineWidth, basegfx::B2DLineJoin eLineJoin);
+ // Helper for line geometry paint with support for graphic expansion (pattern and fat_to_area)
+ void impPaintLineGeometryWithEvtlExpand(const LineInfo& rInfo, basegfx::B2DPolyPolygon aLinePolyPolygon);
+
protected:
OutputDevice();
@@ -1088,7 +1091,12 @@ public:
*/
BOOL HasAlpha();
- void DrawEPS( const Point& rPt, const Size& rSz,
+ /** Added return value to see if EPS could be painted directly.
+ Theoreticaly, handing over a matrix would be needed to handle
+ painting rotated EPS files (e.g. contained mín Metafiles). This
+ would then need to be supported for Mac and PS printers, but
+ that's too much for now, wrote #i107046# for this */
+ bool DrawEPS( const Point& rPt, const Size& rSz,
const GfxLink& rGfxLink, GDIMetaFile* pSubst = NULL );
/// request XCanvas render interface for this OutputDevice
diff --git a/vcl/os2/source/gdi/salgdi3.cxx b/vcl/os2/source/gdi/salgdi3.cxx
index 573fa7336fb0..b25feee266e4 100644
--- a/vcl/os2/source/gdi/salgdi3.cxx
+++ b/vcl/os2/source/gdi/salgdi3.cxx
@@ -1361,10 +1361,8 @@ BOOL Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB
// rescaling needed for the PolyPolygon conversion
if( rB2DPolyPoly.count() )
{
- ::basegfx::B2DHomMatrix aMatrix;
- aMatrix.scale( 1.0/256, 1.0/256 );
- aMatrix.scale( mfFontScale, mfFontScale );
- rB2DPolyPoly.transform( aMatrix );
+ const double fFactor((1.0/256) * mfFontScale);
+ rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor));
}
return bRet;
diff --git a/vcl/source/gdi/cvtsvm.cxx b/vcl/source/gdi/cvtsvm.cxx
index 4ecb89ec5a8e..8c4b6f1a2cb2 100644
--- a/vcl/source/gdi/cvtsvm.cxx
+++ b/vcl/source/gdi/cvtsvm.cxx
@@ -88,23 +88,6 @@ void ImplReadPoly( SvStream& rIStm, Polygon& rPoly )
// ------------------------------------------------------------------------
-void ImplWritePoly( SvStream& rOStm, const Polygon& rPoly )
-{
- // #i102224# Here the evtl. curved nature of Polygon was
- // ignored (for all those Years). Adapted to at least write
- // a polygon representing the curve as good as possible
- Polygon aSimplePoly;
- rPoly.AdaptiveSubdivide(aSimplePoly);
- INT32 nSize = aSimplePoly.GetSize();
-
- rOStm << nSize;
-
- for( INT32 i = 0; i < nSize; i++ )
- rOStm << aSimplePoly[ (USHORT) i ];
-}
-
-// ------------------------------------------------------------------------
-
void ImplReadPolyPoly( SvStream& rIStm, PolyPolygon& rPolyPoly )
{
Polygon aPoly;
@@ -139,10 +122,9 @@ void ImplWritePolyPolyAction( SvStream& rOStm, const PolyPolygon& rPolyPoly )
// #i102224# Here the evtl. curved nature of Polygon was
// ignored (for all those Years). Adapted to at least write
// a polygon representing the curve as good as possible
- const Polygon& rPoly = rPolyPoly[ n ];
- Polygon aSimplePoly;
- rPoly.AdaptiveSubdivide(aSimplePoly);
- const USHORT nSize = aSimplePoly.GetSize();
+ Polygon aSimplePoly;
+ rPolyPoly[n].AdaptiveSubdivide(aSimplePoly);
+ const USHORT nSize(aSimplePoly.GetSize());
rOStm << (INT32) nSize;
@@ -388,6 +370,128 @@ void ImplSkipActions( SvStream& rIStm, ULONG nSkipCount )
}
}
+// ------------------------------------------------------------------------
+
+bool ImplWriteExtendedPolyPolygonAction(SvStream& rOStm, const PolyPolygon& rPolyPolygon, bool bOnlyWhenCurve)
+{
+ const sal_uInt16 nPolygonCount(rPolyPolygon.Count());
+
+ if(nPolygonCount)
+ {
+ sal_uInt32 nAllPolygonCount(0);
+ sal_uInt32 nAllPointCount(0);
+ sal_uInt32 nAllFlagCount(0);
+ sal_uInt16 a(0);
+
+ for(a = 0; a < nPolygonCount; a++)
+ {
+ const Polygon& rCandidate = rPolyPolygon.GetObject(a);
+ const sal_uInt16 nPointCount(rCandidate.GetSize());
+
+ if(nPointCount)
+ {
+ nAllPolygonCount++;
+ nAllPointCount += nPointCount;
+
+ if(rCandidate.HasFlags())
+ {
+ nAllFlagCount += nPointCount;
+ }
+ }
+ }
+
+ if((bOnlyWhenCurve && nAllFlagCount) || (!bOnlyWhenCurve && nAllPointCount))
+ {
+ rOStm << (INT16) GDI_EXTENDEDPOLYGON_ACTION;
+
+ const sal_Int32 nActionSize(
+ 4 + // Action size
+ 2 + // PolygonCount
+ (nAllPolygonCount * 2) + // Points per polygon
+ (nAllPointCount << 3) + // Points themselves
+ nAllPolygonCount + // Bool if (when poly has points) it has flags, too
+ nAllFlagCount); // Flags themselves
+
+ rOStm << nActionSize;
+ rOStm << (sal_uInt16)nAllPolygonCount;
+
+ for(a = 0; a < nPolygonCount; a++)
+ {
+ const Polygon& rCandidate = rPolyPolygon.GetObject(a);
+ const sal_uInt16 nPointCount(rCandidate.GetSize());
+
+ if(nPointCount)
+ {
+ rOStm << nPointCount;
+
+ for(sal_uInt16 b(0); b < nPointCount; b++)
+ {
+ rOStm << rCandidate[b];
+ }
+
+ if(rCandidate.HasFlags())
+ {
+ rOStm << (BYTE)true;
+
+ for(sal_uInt16 c(0); c < nPointCount; c++)
+ {
+ rOStm << (BYTE)rCandidate.GetFlags(c);
+ }
+ }
+ else
+ {
+ rOStm << (BYTE)false;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// ------------------------------------------------------------------------
+
+void ImplReadExtendedPolyPolygonAction(SvStream& rIStm, PolyPolygon& rPolyPoly)
+{
+ rPolyPoly.Clear();
+ sal_uInt16 nPolygonCount(0);
+ rIStm >> nPolygonCount;
+
+ for(sal_uInt16 a(0); a < nPolygonCount; a++)
+ {
+ sal_uInt16 nPointCount(0);
+ rIStm >> nPointCount;
+ Polygon aCandidate(nPointCount);
+
+ if(nPointCount)
+ {
+ for(sal_uInt16 b(0); b < nPointCount; b++)
+ {
+ rIStm >> aCandidate[b];
+ }
+
+ BYTE bHasFlags(false);
+ rIStm >> bHasFlags;
+
+ if(bHasFlags)
+ {
+ BYTE aPolyFlags(0);
+
+ for(sal_uInt16 c(0); c < nPointCount; c++)
+ {
+ rIStm >> aPolyFlags;
+ aCandidate.SetFlags(c, (PolyFlags)aPolyFlags);
+ }
+ }
+ }
+
+ rPolyPoly.Insert(aCandidate);
+ }
+}
+
// ----------------
// - SVMConverter -
// ----------------
@@ -460,6 +564,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
rMtf.SetPrefSize( aPrefSz );
rMtf.SetPrefMapMode( aMapMode );
+ sal_uInt32 nLastPolygonAction(0);
for( INT32 i = 0L; i < nActions; i++ )
{
@@ -493,6 +598,99 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
}
break;
+ case (GDI_LINEJOIN_ACTION) :
+ {
+ INT16 nLineJoin(0);
+ rIStm >> nLineJoin;
+ aLineInfo.SetLineJoin((basegfx::B2DLineJoin)nLineJoin);
+ }
+ break;
+
+ case (GDI_LINEDASHDOT_ACTION) :
+ {
+ INT16 a(0);
+ INT32 b(0);
+
+ rIStm >> a; aLineInfo.SetDashCount(a);
+ rIStm >> b; aLineInfo.SetDashLen(b);
+ rIStm >> a; aLineInfo.SetDotCount(a);
+ rIStm >> b; aLineInfo.SetDotLen(b);
+ rIStm >> b; aLineInfo.SetDistance(b);
+
+ if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
+ || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
+ && aLineInfo.GetDistance())
+ {
+ aLineInfo.SetStyle(LINE_DASH);
+ }
+ }
+ break;
+
+ case (GDI_EXTENDEDPOLYGON_ACTION) :
+ {
+ // read the PolyPolygon in every case
+ PolyPolygon aInputPolyPolygon;
+ ImplReadExtendedPolyPolygonAction(rIStm, aInputPolyPolygon);
+
+ // now check if it can be set somewhere
+ if(nLastPolygonAction < rMtf.GetActionCount())
+ {
+ MetaPolyLineAction* pPolyLineAction = dynamic_cast< MetaPolyLineAction* >(rMtf.GetAction(nLastPolygonAction));
+
+ if(pPolyLineAction)
+ {
+ // replace MetaPolyLineAction when we have a single polygon. Do not rely on the
+ // same point count; the originally written GDI_POLYLINE_ACTION may have been
+ // Subdivided for better quality for older usages
+ if(1 == aInputPolyPolygon.Count())
+ {
+ rMtf.ReplaceAction(
+ new MetaPolyLineAction(
+ aInputPolyPolygon.GetObject(0),
+ pPolyLineAction->GetLineInfo()),
+ nLastPolygonAction);
+ pPolyLineAction->Delete();
+ }
+ }
+ else
+ {
+ MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast< MetaPolyPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
+
+ if(pPolyPolygonAction)
+ {
+ // replace MetaPolyPolygonAction when we have a curved polygon. Do rely on the
+ // same sub-polygon count
+ if(pPolyPolygonAction->GetPolyPolygon().Count() == aInputPolyPolygon.Count())
+ {
+ rMtf.ReplaceAction(
+ new MetaPolyPolygonAction(
+ aInputPolyPolygon),
+ nLastPolygonAction);
+ pPolyPolygonAction->Delete();
+ }
+ }
+ else
+ {
+ MetaPolygonAction* pPolygonAction = dynamic_cast< MetaPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
+
+ if(pPolygonAction)
+ {
+ // replace MetaPolygonAction
+ if(1 == aInputPolyPolygon.Count())
+ {
+ rMtf.ReplaceAction(
+ new MetaPolygonAction(
+ aInputPolyPolygon.GetObject(0)),
+ nLastPolygonAction);
+ pPolygonAction->Delete();
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
case( GDI_RECT_ACTION ):
{
ImplReadRect( rIStm, aRect );
@@ -583,6 +781,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
case( GDI_POLYLINE_ACTION ):
{
ImplReadPoly( rIStm, aActionPoly );
+ nLastPolygonAction = rMtf.GetActionCount();
if( bFatLine )
rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
@@ -604,7 +803,10 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
}
else
+ {
+ nLastPolygonAction = rMtf.GetActionCount();
rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
+ }
}
break;
@@ -625,7 +827,10 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
}
else
+ {
+ nLastPolygonAction = rMtf.GetActionCount();
rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
+ }
}
break;
@@ -1257,12 +1462,32 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
{
MetaLineAction* pAct = (MetaLineAction*) pAction;
const LineInfo& rInfo = pAct->GetLineInfo();
- const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+ const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
+ const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
+ const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
if( bFatLine )
{
ImplWritePushAction( rOStm );
ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+
+ if(bLineJoin)
+ {
+ rOStm << (INT16) GDI_LINEJOIN_ACTION;
+ rOStm << (INT32) 6;
+ rOStm << (INT16) rInfo.GetLineJoin();
+ }
+
+ if(bLineDashDot)
+ {
+ rOStm << (INT16) GDI_LINEDASHDOT_ACTION;
+ rOStm << (INT32) 4 + 16;
+ rOStm << (INT16)rInfo.GetDashCount();
+ rOStm << (INT32)rInfo.GetDashLen();
+ rOStm << (INT16)rInfo.GetDotCount();
+ rOStm << (INT32)rInfo.GetDotLen();
+ rOStm << (INT32)rInfo.GetDistance();
+ }
}
rOStm << (INT16) GDI_LINE_ACTION;
@@ -1275,6 +1500,16 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
{
ImplWritePopAction( rOStm );
nCount += 3;
+
+ if(bLineJoin)
+ {
+ nCount += 1;
+ }
+
+ if(bLineDashDot)
+ {
+ nCount += 1;
+ }
}
}
break;
@@ -1355,30 +1590,47 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
for( USHORT n = 0; n < nPoints; n++ )
rOStm << aChordPoly[ n ];
-
nCount++;
}
break;
case( META_POLYLINE_ACTION ):
{
+ // #i102224#
MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
- const Polygon& rPoly = pAct->GetPolygon();
-
// #i102224# Here the evtl. curved nature of Polygon was
// ignored (for all those Years). Adapted to at least write
// a polygon representing the curve as good as possible
- Polygon aSimplePoly;
- rPoly.AdaptiveSubdivide(aSimplePoly);
-
- const LineInfo& rInfo = pAct->GetLineInfo();
- const USHORT nPoints = aSimplePoly.GetSize();
- const BOOL bFatLine = ( !rInfo.IsDefault() && ( LINE_NONE != rInfo.GetStyle() ) );
+ Polygon aSimplePoly;
+ pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
+ const LineInfo& rInfo = pAct->GetLineInfo();
+ const USHORT nPoints(aSimplePoly.GetSize());
+ const bool bFatLine(!rInfo.IsDefault() && (LINE_NONE != rInfo.GetStyle()));
+ const bool bLineJoin(bFatLine && basegfx::B2DLINEJOIN_ROUND != rInfo.GetLineJoin());
+ const bool bLineDashDot(LINE_DASH == rInfo.GetStyle());
if( bFatLine )
{
ImplWritePushAction( rOStm );
ImplWriteLineColor( rOStm, rLineCol, 1, rInfo.GetWidth() );
+
+ if(bLineJoin)
+ {
+ rOStm << (INT16) GDI_LINEJOIN_ACTION;
+ rOStm << (INT32) 6;
+ rOStm << (INT16) rInfo.GetLineJoin();
+ }
+ }
+
+ if(bLineDashDot)
+ {
+ rOStm << (INT16) GDI_LINEDASHDOT_ACTION;
+ rOStm << (INT32) 4 + 16;
+ rOStm << (INT16)rInfo.GetDashCount();
+ rOStm << (INT32)rInfo.GetDashLen();
+ rOStm << (INT16)rInfo.GetDotCount();
+ rOStm << (INT32)rInfo.GetDotLen();
+ rOStm << (INT32)rInfo.GetDistance();
}
rOStm << (INT16) GDI_POLYLINE_ACTION;
@@ -1386,30 +1638,45 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
rOStm << (INT32) nPoints;
for( USHORT n = 0; n < nPoints; n++ )
+ {
rOStm << aSimplePoly[ n ];
+ }
nCount++;
+ const PolyPolygon aPolyPolygon(pAct->GetPolygon());
+ if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
+ {
+ nCount++;
+ }
+
if( bFatLine )
{
ImplWritePopAction( rOStm );
nCount += 3;
+
+ if(bLineJoin)
+ {
+ nCount += 1;
+ }
+ }
+
+ if(bLineDashDot)
+ {
+ nCount += 1;
}
}
break;
case( META_POLYGON_ACTION ):
{
- MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
- const Polygon& rPoly = pAct->GetPolygon();
-
+ MetaPolygonAction* pAct = (MetaPolygonAction*)pAction;
// #i102224# Here the evtl. curved nature of Polygon was
// ignored (for all those Years). Adapted to at least write
// a polygon representing the curve as good as possible
- Polygon aSimplePoly;
- rPoly.AdaptiveSubdivide(aSimplePoly);
-
- const USHORT nPoints = aSimplePoly.GetSize();
+ Polygon aSimplePoly;
+ pAct->GetPolygon().AdaptiveSubdivide(aSimplePoly);
+ const USHORT nPoints(aSimplePoly.GetSize());
rOStm << (INT16) GDI_POLYGON_ACTION;
rOStm << (INT32) ( 8 + ( nPoints << 3 ) );
@@ -1419,6 +1686,12 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
rOStm << aSimplePoly[ n ];
nCount++;
+
+ const PolyPolygon aPolyPolygon(pAct->GetPolygon());
+ if(ImplWriteExtendedPolyPolygonAction(rOStm, aPolyPolygon, true))
+ {
+ nCount++;
+ }
}
break;
@@ -1427,6 +1700,11 @@ ULONG SVMConverter::ImplWriteActions( SvStream& rOStm, GDIMetaFile& rMtf,
MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
ImplWritePolyPolyAction( rOStm, pAct->GetPolyPolygon() );
nCount++;
+
+ if(ImplWriteExtendedPolyPolygonAction(rOStm, pAct->GetPolyPolygon(), true))
+ {
+ nCount++;
+ }
}
break;
diff --git a/vcl/source/gdi/implncvt.cxx b/vcl/source/gdi/implncvt.cxx
deleted file mode 100644
index e59fde15b5be..000000000000
--- a/vcl/source/gdi/implncvt.cxx
+++ /dev/null
@@ -1,577 +0,0 @@
-/*************************************************************************
- *
- * 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: implncvt.cxx,v $
- * $Revision: 1.10.136.1 $
- *
- * 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_vcl.hxx"
-#include <vcl/salbtype.hxx>
-#ifndef _SV_IMPLNCVT_HXX
-#include "implncvt.hxx"
-#endif
-
-// -----------
-// - Defines -
-// -----------
-
-#define CURVE_LEFT 1
-#define CURVE_RIGHT 2
-#define CURVE_STRAIGHTON 3
-
-// -----------------
-// - ImplFloatPoint
-// -----------------
-
-struct ImplFloatPoint
-{
- double fX;
- double fY;
-
- inline ImplFloatPoint() {}
- inline ImplFloatPoint( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
- inline ImplFloatPoint( double _fX, double _fY ) { fX = _fX; fY = _fY; }
- inline ImplFloatPoint( const ImplFloatPoint& rPoint ) { fX = rPoint.fX; fY = rPoint.fY; }
- inline ~ImplFloatPoint() {}
-
- void operator+=( const ImplFloatPoint& rPoint ) { fX += rPoint.fX; fY += rPoint.fY; }
- void operator-=( const ImplFloatPoint& rPoint ) { fX -= rPoint.fX; fY -= rPoint.fY; }
- void operator*=( const double& rD ) { fX *= rD; fY *= rD; }
- BOOL operator==( const ImplFloatPoint& rPoint ) const { return ( ( rPoint.fX == fX ) && ( rPoint.fY == fY ) ); }
- void operator=( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
-
- ImplFloatPoint GetOVec( const ImplFloatPoint& rPoint ) const;
- ImplFloatPoint GetNVec( const ImplFloatPoint& rPoint ) const;
-};
-
-// -----------------------------------------------------------------------------
-
-ImplFloatPoint ImplFloatPoint::GetOVec( const ImplFloatPoint& rPoint ) const
-{
- double fxt = rPoint.fX - fX;
- double fyt = rPoint.fY - fY;
- double fL;
-
- if( fyt != 0.0 )
- {
- fyt = -fxt / fyt;
- fL = sqrt( 1 + fyt * fyt );
-
- return ImplFloatPoint( 1.0 / fL, fyt / fL );
- }
- else
- return ImplFloatPoint( fyt, ( fxt > 0.0 ) ? 1.0 : -1.0 );
-};
-
-// -----------------------------------------------------------------------------
-
-ImplFloatPoint ImplFloatPoint::GetNVec( const ImplFloatPoint& rPoint ) const
-{
- const double fxt = rPoint.fX - fX;
- const double fyt = rPoint.fY - fY;
- const double fL = hypot( fxt, fyt );
-
- return ImplFloatPoint( fxt / fL, fyt / fL );
-};
-
-// --------------------
-// - ImplLineConverter
-// --------------------
-
-ImplLineConverter::ImplLineConverter( const Polygon& rPolygon, const LineInfo& rLineInfo, const Point* pRefPoint ) :
- mbRefPoint ( FALSE ),
- mfWidthHalf ( rLineInfo.GetWidth() >> 1 ),
- maLineInfo ( rLineInfo ),
- mpFloat0 ( new ImplFloatPoint[ 6 ] ),
- mpFloat1 ( new ImplFloatPoint[ 6 ] ),
- mnLines ( 0 ),
- mpFloatPoint ( NULL )
-{
- UINT16 nIndex, nPolySize = rPolygon.GetSize();
- if ( nPolySize )
- {
- if( rPolygon.GetFlags( 0 ) == POLY_NORMAL )
- {
- mpFloatPoint = new ImplFloatPoint[ nPolySize ];
- mpFloatPoint[ 0 ] = rPolygon[ 0 ];
-
- nIndex = 0;
-
- while( ++nIndex < nPolySize ) // doppelte Punkte eliminieren und ein FloatPointArray anlegen
- {
- if( rPolygon.GetFlags( nIndex ) == POLY_NORMAL )
- {
- double nxt = mpFloatPoint[ mnLines ].fX;
- double nyt = mpFloatPoint[ mnLines ].fY;
-
- if ( ( nxt == rPolygon[ nIndex ].X() ) && ( nyt == rPolygon[ nIndex ].Y() ) )
- continue;
-
- mpFloatPoint[ ++mnLines ] = rPolygon[ nIndex ];
- }
- else
- {
- DBG_ERROR( "Bezier points not supported!" );
- }
- }
- mbClosed = ( mpFloatPoint[ 0 ] == mpFloatPoint[ mnLines ] ) ;
-
- if ( ( mnLines == 1 ) && ( maLineInfo.GetStyle() == LINE_DASH ) )
- {
- BOOL bX = mpFloatPoint[ 0 ].fY == mpFloatPoint[ 1 ].fY;
- BOOL bY = mpFloatPoint[ 0 ].fX == mpFloatPoint[ 1 ].fX;
- mbRefPoint = pRefPoint && ( bX || bY );
- if ( mbRefPoint )
- {
- if ( !maLineInfo.GetDashCount() )
- {
- maLineInfo.SetDashCount( maLineInfo.GetDotCount() );
- maLineInfo.SetDashLen( maLineInfo.GetDotLen() );
- maLineInfo.SetDotCount( 0 );
- }
- INT32 nDistance = maLineInfo.GetDistance();
- INT32 nDashLen = maLineInfo.GetDashCount() * ( maLineInfo.GetDashLen() + nDistance );
- INT32 nDotLen = maLineInfo.GetDotCount() * ( maLineInfo.GetDotLen() + nDistance );
- if ( bX )
- {
- if ( mpFloatPoint[ 1 ].fX > mpFloatPoint[ 0 ].fX )
- {
- ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
- mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
- mpFloatPoint[ 1 ] = aFloat;
- }
- mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X();
- }
- else
- {
- if ( mpFloatPoint[ 1 ].fY > mpFloatPoint[ 0 ].fY )
- {
- ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
- mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
- mpFloatPoint[ 1 ] = aFloat;
- }
- mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y();
- }
-
-// mnRefDistance = ( (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X() ) +
-// ( (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y() );
-
- mnRefDistance = mnRefDistance % ( nDashLen + nDotLen );
- if ( mnRefDistance < 0 )
- mnRefDistance = ( nDashLen + nDotLen ) + mnRefDistance;
- }
- }
- }
- }
-};
-
-//------------------------------------------------------------------------
-
-ImplLineConverter::~ImplLineConverter()
-{
- delete[] mpFloat0;
- delete[] mpFloat1;
- delete[] mpFloatPoint;
-};
-
-//------------------------------------------------------------------------
-
-const Polygon* ImplLineConverter::ImplGetFirst()
-{
- mnFloat1Points = 0;
- mnLinesAvailable = mnLines;
-
- if ( mnLines )
- {
- if ( maLineInfo.GetStyle() == LINE_DASH )
- {
- mnDashCount = maLineInfo.GetDashCount();
- mnDotCount = maLineInfo.GetDotCount();
- mfDashDotLenght = mnDashCount ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
-
- if ( mbRefPoint )
- {
- INT32 nDistance = maLineInfo.GetDistance();
- INT32 nDashLen = maLineInfo.GetDashLen() + nDistance;
- INT32 nDashesLen = maLineInfo.GetDashCount() * nDashLen;
- INT32 nDotLen = maLineInfo.GetDotLen() + nDistance;
-
- if ( mnRefDistance >= nDashesLen )
- {
- // get dotcount
- if ( nDotLen )
- {
- INT32 nLen = ( mnRefDistance - nDashesLen ) % nDotLen;
- if ( nLen >= maLineInfo.GetDotLen() )
- {
- mnDotCount -= 1 + ( mnRefDistance - nDashesLen ) / nDotLen;
- if ( mnDotCount )
- mnDashCount = 0;
- else
- mnDotCount = maLineInfo.GetDotCount();
- mfDashDotLenght = 0.0;
- mfDistanceLenght = ( maLineInfo.GetDotLen() + nDistance ) - nLen;
- }
- else
- {
- mnDashCount = 0;
- mfDashDotLenght = maLineInfo.GetDotLen() - nLen;
- mnDotCount -= ( mnRefDistance - nDashesLen ) / nDotLen;
- }
- }
- }
- else
- {
- if ( nDashLen )
- {
- // get dashcount
- INT32 nLen = mnRefDistance % nDashLen;
- if ( nLen >= maLineInfo.GetDashLen() )
- {
- mfDashDotLenght = 0.0;
- mfDistanceLenght = ( maLineInfo.GetDashLen() + nDistance ) - nLen;
- mnDashCount -= 1 + ( mnRefDistance / nDashLen );
- }
- else
- {
- mfDashDotLenght = maLineInfo.GetDashLen() - nLen;
- mnDashCount -= ( mnRefDistance / nDashLen );
- }
- }
- }
- if ( ! ( mnDashCount | mnDotCount ) )
- {
- mnDashCount = maLineInfo.GetDashCount();
- mnDotCount = maLineInfo.GetDotCount();
- }
- if ( ( mfDashDotLenght == 0.0 ) && ( mfDistanceLenght == 0.0 ) )
- mfDistanceLenght = maLineInfo.GetDistance();
- }
- }
- }
- return ImplGetNext();
-};
-
-//------------------------------------------------------------------------
-
-const Polygon* ImplLineConverter::ImplGetNext()
-{
- while( mnFloat1Points || mnLinesAvailable )
- {
- if ( maLineInfo.GetWidth() > 1 )
- {
- if ( !mnFloat1Points )
- {
- ImplFloatPoint aPointA( mpFloatPoint[ mnLinesAvailable-- ] );
- ImplFloatPoint aPointB( mpFloatPoint[ mnLinesAvailable ] );
- ImplFloatPoint aOVecAB( aPointA.GetOVec( aPointB ) );
- ImplFloatPoint aN1Vec( aPointA.GetNVec( aPointB ) );
- aN1Vec *= mfWidthHalf;
-
- if ( !mbClosed && ( ( mnLinesAvailable + 1 ) == mnLines ) )
- aPointA -= aN1Vec;
-
- aOVecAB *= mfWidthHalf;
- mpFloat0[ 0 ] = aPointA;
- mpFloat0[ 0 ] -= aOVecAB;
- mpFloat0[ 3 ] = aPointA;
- mpFloat0[ 3 ] += aOVecAB;
- mpFloat0[ 1 ] = aPointB;
- mpFloat0[ 1 ] -= aOVecAB;
- mpFloat0[ 2 ] = aPointB;
- mpFloat0[ 2 ] += aOVecAB;
-
- double f1D = ( aN1Vec.fX == 0 ) ? 1 : ( aN1Vec.fY / aN1Vec.fX );
- double f2D = -f1D;
-
- mnFloat0Points = 4;
-
- int nDirection;
-
- BOOL bContinues = ( mnLinesAvailable || mbClosed );
- if ( bContinues )
- {
- ImplFloatPoint aPointC;
-
- if ( mnLinesAvailable )
- aPointC = mpFloatPoint[ mnLinesAvailable - 1 ];
- else
- aPointC = mpFloatPoint[ mnLines - 1 ];
-
- ImplFloatPoint aOVecBC( aPointB.GetOVec( aPointC ) );
- aOVecBC *= mfWidthHalf;
- ImplFloatPoint aPointR0( aPointB );
- aPointR0 -= aOVecBC;
- ImplFloatPoint aPointR1( aPointB );
- aPointR1 += aOVecBC;
- ImplFloatPoint aN2Vec( aPointB.GetNVec( aPointC ) );
- aN2Vec *= mfWidthHalf;
-
- f2D = ( fabs( aN2Vec.fX ) < 0.00000001 ) ? 1 : ( aN2Vec.fY / aN2Vec.fX );
- if ( fabs( f1D - f2D ) < 0.00000001 )
- nDirection = CURVE_STRAIGHTON;
- else
- {
- if ( ( aN1Vec.fX * aN2Vec.fY - aN1Vec.fY * aN2Vec.fX ) > 0 )
- nDirection = CURVE_LEFT;
- else
- nDirection = CURVE_RIGHT;
- }
- if ( nDirection != CURVE_STRAIGHTON )
- {
- double fWidth;
- ImplFloatPoint aDestPoint;
- if ( hypot( aPointR0.fX - aPointA.fX, aPointR0.fY - aPointA.fY ) > hypot( aPointR1.fX - aPointA.fX, aPointR1.fY - aPointA.fY ) )
- aDestPoint = aPointR0;
- else
- aDestPoint = aPointR1;
-
- UINT16 nFirst = 0;
- if ( aN1Vec.fY > 0 )
- {
- if ( nDirection != CURVE_RIGHT )
- nFirst++;
- }
- else
- {
- if ( nDirection == CURVE_RIGHT )
- nFirst++;
- }
- fWidth = hypot( mpFloat0[ 1 + nFirst ].fX - aDestPoint.fX, mpFloat0[ 1 + nFirst ].fY - aDestPoint.fY );
- fWidth = sqrt( fWidth * fWidth / 2 );
- if ( fWidth > mfWidthHalf )
- {
- // Spitzer Winkel :
- mnFloat0Points = 6;
- mpFloat0[ (4 + nFirst) ^ 1 ] = aDestPoint;
- aDestPoint -= aN2Vec;
- mpFloat0[ 4 + nFirst ] = aDestPoint;
- mpFloat0[ 1 + nFirst ] += aN1Vec;
- }
- else
- {
- // Stumpferwinkel : Schnittpunkt wird berechnet
- mnFloat0Points = 5;
- ImplFloatPoint aSourcePoint;
- double fX = 0;
- double fY;
- double fBDest = 0;
- double fBSource = 0;
- aSourcePoint = mpFloat0[ 1 + nFirst ];
-
- int nValid = 0;
-
- if ( fabs( aN2Vec.fX ) < 0.00000001 )
- {
- fX = aDestPoint.fX;
- nValid = 1;
- }
- else
- fBDest = aDestPoint.fY - ( aN2Vec.fY / aN2Vec.fX * aDestPoint.fX );
-
- if ( fabs( aN1Vec.fX ) < 0.000000001 )
- {
- fX = aSourcePoint.fX;
- nValid = 2;
- }
- else
- fBSource = aSourcePoint.fY - ( aN1Vec.fY / aN1Vec.fX * aSourcePoint.fX );
-
- if ( !nValid )
- fX = ( fBSource - fBDest ) / ( aN2Vec.fY / aN2Vec.fX - aN1Vec.fY / aN1Vec.fX );
- if ( nValid < 2 )
- fY = aN1Vec.fY / aN1Vec.fX * fX + fBSource;
- else
- fY = aN2Vec.fY / aN2Vec.fX * fX + fBDest;
-
- mpFloat0[ 1 + nFirst ].fX = fX;
- mpFloat0[ 1 + nFirst ].fY = fY;
- mpFloat0[ 4 ] = aDestPoint;
- }
- }
- else if ( ( aN1Vec.fX - aN2Vec.fX + aN1Vec.fY - aN2Vec.fY ) != 0 ) // besitzt zweiter Richtungsvektor die gleiche Steigung aber andere
- bContinues = FALSE; // Richtung, dann wird hinten noch eine halbe Linienbreite angehaengt
- }
- if ( !bContinues )
- {
- mpFloat0[ 1 ] += aN1Vec;
- mpFloat0[ 2 ] += aN1Vec;
- }
- }
- else
- {
- mnFloat0Points = mnFloat1Points;
- ImplFloatPoint* pTemp = mpFloat1;
- mpFloat1 = mpFloat0;
- mpFloat0 = pTemp;
- }
- if ( maLineInfo.GetStyle() == LINE_DASH )
- {
- double fLenghtDone = 0;
- double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
-
- double fDistance;
-
- fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
- if ( mnFloat0Points == 5 )
- {
- double fDist = hypot( mpFloat0[ 2 ].fX - mpFloat0[ 3 ].fX, mpFloat0[ 2 ].fY - mpFloat0[ 3 ].fY );
- if ( fDist < fDistance )
- fDistance = fDist;
- }
-
- if ( fDistance > fLenght )
- {
- fLenghtDone = fLenght;
-
- ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
- aNVec *= fLenght;
- mnFloat1Points = mnFloat0Points;
- ImplFloatPoint* pTemp = mpFloat1;
- mpFloat1 = mpFloat0;
- mpFloat0 = pTemp;
- mnFloat0Points = 4;
- mpFloat0[ 0 ] = mpFloat0[ 1 ] = mpFloat1[ 0 ];
- mpFloat0[ 1 ] += aNVec;
- mpFloat0[ 2 ] = mpFloat0[ 3 ] = mpFloat1[ 3 ];
- mpFloat0[ 2 ] += aNVec;
-
- mpFloat1[ 0 ] = mpFloat0[ 1 ];
- mpFloat1[ 3 ] = mpFloat0[ 2 ];
- }
- else
- {
- mnFloat1Points = 0;
- fLenghtDone = fDistance;
- }
-
- if ( mfDashDotLenght > 0.0 )
- { // Ein Dash oder Dot wurde erzeugt
- mfDashDotLenght -= fLenghtDone;
- if ( mfDashDotLenght == 0.0 )
- { // Komplett erzeugt
- if ( mnDashCount )
- mnDashCount--;
- else
- mnDotCount--;
-
- if ( ! ( mnDashCount | mnDotCount ) )
- {
- mnDashCount = maLineInfo.GetDashCount();
- mnDotCount = maLineInfo.GetDotCount();
- }
- mfDistanceLenght = maLineInfo.GetDistance();
- }
- }
- else
- { // Das erzeugte Polygon muessen wir ignorieren
- mfDistanceLenght -= fLenghtDone;
- if ( mfDistanceLenght == 0.0 )
- mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
- continue;
- }
- }
- maPolygon.SetSize( (UINT16)mnFloat0Points );
- UINT16 i = 0;
- maPolygon[ i++ ] = Point( FRound( mpFloat0[ 0 ].fX ), FRound( mpFloat0[ 0 ].fY ) );
- maPolygon[ i++ ] = Point( FRound( mpFloat0[ 1 ].fX ), FRound( mpFloat0[ 1 ].fY ) );
- if ( mnFloat0Points > 4 )
- maPolygon[ i++ ] = Point( FRound( mpFloat0[ 4 ].fX ), FRound( mpFloat0[ 4 ].fY ) );
- if ( mnFloat0Points > 5 )
- maPolygon[ i++ ] = Point( FRound( mpFloat0[ 5 ].fX ), FRound( mpFloat0[ 5 ].fY ) );
- maPolygon[ i++ ] = Point( FRound( mpFloat0[ 2 ].fX ), FRound( mpFloat0[ 2 ].fY ) );
- maPolygon[ i ] = Point( FRound( mpFloat0[ 3 ].fX ), FRound( mpFloat0[ 3 ].fY ) );
-
- }
- else
- {
- if ( !mnFloat1Points )
- {
- mpFloat0[ 0 ] = mpFloatPoint[ mnLinesAvailable-- ];
- mpFloat0[ 1 ] = mpFloatPoint[ mnLinesAvailable ];
- }
- else
- {
- mpFloat0[ 0 ] = mpFloat1[ 0 ];
- mpFloat0[ 1 ] = mpFloat1[ 1 ];
- }
- if ( maLineInfo.GetStyle() == LINE_DASH )
- {
- double fLenghtDone = 0;
- double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
- double fDistance;
- fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
- if ( fDistance > fLenght )
- {
- fLenghtDone = fLenght;
- ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
- aNVec *= fLenght;
- mpFloat1[ 1 ] = mpFloat0[ 1 ];
- mpFloat0[ 1 ] = mpFloat0[ 0 ];
- mpFloat0[ 1 ] += aNVec;
- mpFloat1[ 0 ] = mpFloat0[ 1 ];
- mnFloat1Points = 2;
- }
- else
- {
- mnFloat1Points = 0;
- fLenghtDone = fDistance;
- }
- if ( mfDashDotLenght > 0.0 )
- { // Ein Dash oder Dot wurde erzeugt
- mfDashDotLenght -= fLenghtDone;
- if ( mfDashDotLenght == 0.0 )
- { // Komplett erzeugt
- if ( mnDashCount )
- mnDashCount--;
- else
- mnDotCount--;
-
- if ( ! ( mnDashCount | mnDotCount ) )
- {
- mnDashCount = maLineInfo.GetDashCount();
- mnDotCount = maLineInfo.GetDotCount();
- }
- mfDistanceLenght = maLineInfo.GetDistance();
- }
- }
- else
- { // Das erzeugte Polygon muessen wir ignorieren
- mfDistanceLenght -= fLenghtDone;
- if ( mfDistanceLenght == 0.0 )
- mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
- continue;
- }
- }
- maPolygon.SetSize( 2 );
- maPolygon[ 0 ] = Point( (long)mpFloat0[ 0 ].fX, (long)mpFloat0[ 0 ].fY );
- maPolygon[ 1 ] = Point( (long)mpFloat0[ 1 ].fX, (long)mpFloat0[ 1 ].fY );
- }
- return &maPolygon;
- }
- return NULL;
-};
diff --git a/vcl/source/gdi/implncvt.hxx b/vcl/source/gdi/implncvt.hxx
deleted file mode 100644
index 2d369d12f253..000000000000
--- a/vcl/source/gdi/implncvt.hxx
+++ /dev/null
@@ -1,78 +0,0 @@
-/*************************************************************************
- *
- * 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: implncvt.hxx,v $
- * $Revision: 1.5 $
- *
- * 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 _SV_LINECONV_HXX
-#define _SV_LINECONV_HXX
-
-#include <tools/poly.hxx>
-#include <vcl/lineinfo.hxx>
-
-// --------------------
-// - ImplLineConverter
-// --------------------
-
-struct ImplFloatPoint;
-
-class ImplLineConverter
-{
- BOOL mbClosed;
- BOOL mbRefPoint;
- INT32 mnRefDistance;
-
- double mfWidthHalf;
- LineInfo maLineInfo;
-
- double mfDashDotLenght;
- double mfDistanceLenght;
-
- UINT32 mnDashCount;
- UINT32 mnDotCount;
-
- Polygon maPolygon;
- UINT32 mnFloat0Points;
- ImplFloatPoint* mpFloat0;
- UINT32 mnFloat1Points;
- ImplFloatPoint* mpFloat1;
-
- UINT32 mnLinesAvailable;
- UINT32 mnLines;
-
- ImplFloatPoint* mpFloatPoint;
-
- public:
-
- ImplLineConverter( const Polygon& rPoly, const LineInfo& rLineInfo, const Point* pRefPoint );
- ~ImplLineConverter();
-
- const Polygon* ImplGetFirst();
- const Polygon* ImplGetNext();
-};
-
-#endif
diff --git a/vcl/source/gdi/lineinfo.cxx b/vcl/source/gdi/lineinfo.cxx
index 98f16713a145..7aa50811106b 100644
--- a/vcl/source/gdi/lineinfo.cxx
+++ b/vcl/source/gdi/lineinfo.cxx
@@ -34,6 +34,10 @@
#include <tools/vcompat.hxx>
#include <tools/debug.hxx>
#include <vcl/lineinfo.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <numeric>
DBG_NAME( LineInfo )
@@ -49,7 +53,8 @@ ImplLineInfo::ImplLineInfo() :
mnDashLen ( 0 ),
mnDotCount ( 0 ),
mnDotLen ( 0 ),
- mnDistance ( 0 )
+ mnDistance ( 0 ),
+ meLineJoin ( basegfx::B2DLINEJOIN_ROUND )
{
}
@@ -63,7 +68,8 @@ ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
mnDashLen ( rImplLineInfo.mnDashLen ),
mnDotCount ( rImplLineInfo.mnDotCount ),
mnDotLen ( rImplLineInfo.mnDotLen ),
- mnDistance ( rImplLineInfo.mnDistance )
+ mnDistance ( rImplLineInfo.mnDistance ),
+ meLineJoin ( rImplLineInfo.meLineJoin )
{
}
@@ -209,6 +215,19 @@ void LineInfo::SetDistance( long nDistance )
// -----------------------------------------------------------------------
+void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
+{
+ DBG_CHKTHIS( LineInfo, NULL );
+
+ if(eLineJoin != mpImplLineInfo->meLineJoin)
+ {
+ ImplMakeUnique();
+ mpImplLineInfo->meLineJoin = eLineJoin;
+ }
+}
+
+// -----------------------------------------------------------------------
+
SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
{
VersionCompat aCompat( rIStm, STREAM_READ );
@@ -225,6 +244,12 @@ SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
rIStm >> rImplLineInfo.mnDistance;
}
+ if( aCompat.GetVersion() >= 3 )
+ {
+ // version 3
+ rIStm >> nTmp16; rImplLineInfo.meLineJoin = (basegfx::B2DLineJoin) nTmp16;
+ }
+
return rIStm;
}
@@ -232,7 +257,7 @@ SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
{
- VersionCompat aCompat( rOStm, STREAM_WRITE, 2 );
+ VersionCompat aCompat( rOStm, STREAM_WRITE, 3 );
// version 1
rOStm << (UINT16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
@@ -242,6 +267,9 @@ SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
rOStm << rImplLineInfo.mnDistance;
+ // since version3
+ rOStm << (UINT16) rImplLineInfo.meLineJoin;
+
return rOStm;
}
@@ -259,3 +287,78 @@ SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
{
return( rOStm << *rLineInfo.mpImplLineInfo );
}
+
+// -----------------------------------------------------------------------
+
+bool LineInfo::isDashDotOrFatLineUsed() const
+{
+ return (LINE_DASH == GetStyle() || GetWidth() > 1);
+}
+
+// -----------------------------------------------------------------------
+
+void LineInfo::applyToB2DPolyPolygon(
+ basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
+ basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
+{
+ o_rFillPolyPolygon.clear();
+
+ if(io_rLinePolyPolygon.count())
+ {
+ if(LINE_DASH == GetStyle())
+ {
+ ::std::vector< double > fDotDashArray;
+ const double fDashLen(GetDashLen());
+ const double fDotLen(GetDotLen());
+ const double fDistance(GetDistance());
+
+ for(sal_uInt16 a(0); a < GetDashCount(); a++)
+ {
+ fDotDashArray.push_back(fDashLen);
+ fDotDashArray.push_back(fDistance);
+ }
+
+ for(sal_uInt16 b(0); b < GetDotCount(); b++)
+ {
+ fDotDashArray.push_back(fDotLen);
+ fDotDashArray.push_back(fDistance);
+ }
+
+ const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
+
+ if(fAccumulated > 0.0)
+ {
+ basegfx::B2DPolyPolygon aResult;
+
+ for(sal_uInt32 c(0); c < io_rLinePolyPolygon.count(); c++)
+ {
+ basegfx::B2DPolyPolygon aLineTraget;
+ basegfx::tools::applyLineDashing(
+ io_rLinePolyPolygon.getB2DPolygon(c),
+ fDotDashArray,
+ &aLineTraget);
+ aResult.append(aLineTraget);
+ }
+
+ io_rLinePolyPolygon = aResult;
+ }
+ }
+
+ if(GetWidth() > 1 && io_rLinePolyPolygon.count())
+ {
+ const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
+
+ for(sal_uInt32 a(0); a < io_rLinePolyPolygon.count(); a++)
+ {
+ o_rFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
+ io_rLinePolyPolygon.getB2DPolygon(a),
+ fHalfLineWidth,
+ GetLineJoin()));
+ }
+
+ io_rLinePolyPolygon.clear();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
index 421505a3d500..ae90d5bd1461 100755
--- a/vcl/source/gdi/makefile.mk
+++ b/vcl/source/gdi/makefile.mk
@@ -100,7 +100,7 @@ SLOFILES= $(EXCEPTIONSFILES) \
$(SLO)$/impbmp.obj \
$(SLO)$/imagerepository.obj \
$(SLO)$/impvect.obj \
- $(SLO)$/implncvt.obj \
+ $(SLO)$/jobset.obj \
$(SLO)$/lineinfo.obj \
$(SLO)$/mapmod.obj \
$(SLO)$/metaact.obj \
diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx
index 82566b2b4362..1f27ad2afe7d 100644
--- a/vcl/source/gdi/metaact.cxx
+++ b/vcl/source/gdi/metaact.cxx
@@ -52,14 +52,6 @@ inline void ImplScalePoint( Point& rPt, double fScaleX, double fScaleY )
// ------------------------------------------------------------------------
-inline void ImplScaleSize( Size& rSz, double fScaleX, double fScaleY )
-{
- rSz.Width() = FRound( fScaleX * rSz.Width() );
- rSz.Height() = FRound( fScaleY * rSz.Height() );
-}
-
-// ------------------------------------------------------------------------
-
inline void ImplScaleRect( Rectangle& rRect, double fScaleX, double fScaleY )
{
Point aTL( rRect.TopLeft() );
@@ -69,6 +61,7 @@ inline void ImplScaleRect( Rectangle& rRect, double fScaleX, double fScaleY )
ImplScalePoint( aBR, fScaleX, fScaleY );
rRect = Rectangle( aTL, aBR );
+ rRect.Justify();
}
// ------------------------------------------------------------------------
@@ -85,7 +78,7 @@ inline void ImplScaleLineInfo( LineInfo& rLineInfo, double fScaleX, double fScal
{
if( !rLineInfo.IsDefault() )
{
- const double fScale = ( fScaleX + fScaleY ) * 0.5;
+ const double fScale = ( fabs(fScaleX) + fabs(fScaleY) ) * 0.5;
rLineInfo.SetWidth( FRound( fScale * rLineInfo.GetWidth() ) );
rLineInfo.SetDashLen( FRound( fScale * rLineInfo.GetDashLen() ) );
@@ -598,8 +591,8 @@ void MetaRoundRectAction::Move( long nHorzMove, long nVertMove )
void MetaRoundRectAction::Scale( double fScaleX, double fScaleY )
{
ImplScaleRect( maRect, fScaleX, fScaleY );
- mnHorzRound = FRound( mnHorzRound * fScaleX );
- mnVertRound = FRound( mnVertRound * fScaleY );
+ mnHorzRound = FRound( mnHorzRound * fabs(fScaleX) );
+ mnVertRound = FRound( mnVertRound * fabs(fScaleY) );
}
// ------------------------------------------------------------------------
@@ -1396,7 +1389,7 @@ void MetaTextArrayAction::Scale( double fScaleX, double fScaleY )
if ( mpDXAry && mnLen )
{
for ( USHORT i = 0, nCount = mnLen; i < nCount; i++ )
- mpDXAry[ i ] = FRound( mpDXAry[ i ] * fScaleX );
+ mpDXAry[ i ] = FRound( mpDXAry[ i ] * fabs(fScaleX) );
}
}
@@ -1524,7 +1517,7 @@ void MetaStretchTextAction::Move( long nHorzMove, long nVertMove )
void MetaStretchTextAction::Scale( double fScaleX, double fScaleY )
{
ImplScalePoint( maPt, fScaleX, fScaleY );
- mnWidth = (ULONG)FRound( mnWidth * fScaleX );
+ mnWidth = (ULONG)FRound( mnWidth * fabs(fScaleX) );
}
// ------------------------------------------------------------------------
@@ -1717,7 +1710,7 @@ void MetaTextLineAction::Move( long nHorzMove, long nVertMove )
void MetaTextLineAction::Scale( double fScaleX, double fScaleY )
{
ImplScalePoint( maPos, fScaleX, fScaleY );
- mnWidth = FRound( mnWidth * fScaleX );
+ mnWidth = FRound( mnWidth * fabs(fScaleX) );
}
// ------------------------------------------------------------------------
@@ -1876,8 +1869,10 @@ void MetaBmpScaleAction::Move( long nHorzMove, long nVertMove )
void MetaBmpScaleAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maPt, fScaleX, fScaleY );
- ImplScaleSize( maSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maPt, maSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maPt = aRectangle.TopLeft();
+ maSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -1953,8 +1948,10 @@ void MetaBmpScalePartAction::Move( long nHorzMove, long nVertMove )
void MetaBmpScalePartAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maDstPt, fScaleX, fScaleY );
- ImplScaleSize( maDstSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maDstPt, maDstSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maDstPt = aRectangle.TopLeft();
+ maDstSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -2099,8 +2096,10 @@ void MetaBmpExScaleAction::Move( long nHorzMove, long nVertMove )
void MetaBmpExScaleAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maPt, fScaleX, fScaleY );
- ImplScaleSize( maSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maPt, maSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maPt = aRectangle.TopLeft();
+ maSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -2176,8 +2175,10 @@ void MetaBmpExScalePartAction::Move( long nHorzMove, long nVertMove )
void MetaBmpExScalePartAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maDstPt, fScaleX, fScaleY );
- ImplScaleSize( maDstSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maDstPt, maDstSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maDstPt = aRectangle.TopLeft();
+ maDstSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -2328,8 +2329,10 @@ void MetaMaskScaleAction::Move( long nHorzMove, long nVertMove )
void MetaMaskScaleAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maPt, fScaleX, fScaleY );
- ImplScaleSize( maSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maPt, maSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maPt = aRectangle.TopLeft();
+ maSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -2408,8 +2411,10 @@ void MetaMaskScalePartAction::Move( long nHorzMove, long nVertMove )
void MetaMaskScalePartAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maDstPt, fScaleX, fScaleY );
- ImplScaleSize( maDstSz, fScaleX, fScaleY );
+ Rectangle aRectangle(maDstPt, maDstSz);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maDstPt = aRectangle.TopLeft();
+ maDstSz = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
@@ -3498,9 +3503,9 @@ MetaAction* MetaFontAction::Clone()
void MetaFontAction::Scale( double fScaleX, double fScaleY )
{
- Size aSize( maFont.GetSize() );
-
- ImplScaleSize( aSize, fScaleX, fScaleY );
+ const Size aSize(
+ FRound(maFont.GetSize().Width() * fabs(fScaleX)),
+ FRound(maFont.GetSize().Height() * fabs(fScaleY)));
maFont.SetSize( aSize );
}
@@ -3791,14 +3796,18 @@ MetaAction* MetaFloatTransparentAction::Clone()
void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove )
{
maPoint.Move( nHorzMove, nVertMove );
+ maMtf.Move(nHorzMove, nVertMove);
}
// ------------------------------------------------------------------------
void MetaFloatTransparentAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maPoint, fScaleX, fScaleY );
- ImplScaleSize( maSize, fScaleX, fScaleY );
+ Rectangle aRectangle(maPoint, maSize);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maPoint = aRectangle.TopLeft();
+ maSize = aRectangle.GetSize();
+ maMtf.Scale(fScaleX, fScaleY);
}
// ------------------------------------------------------------------------
@@ -3872,8 +3881,10 @@ void MetaEPSAction::Move( long nHorzMove, long nVertMove )
void MetaEPSAction::Scale( double fScaleX, double fScaleY )
{
- ImplScalePoint( maPoint, fScaleX, fScaleY );
- ImplScaleSize( maSize, fScaleX, fScaleY );
+ Rectangle aRectangle(maPoint, maSize);
+ ImplScaleRect( aRectangle, fScaleX, fScaleY );
+ maPoint = aRectangle.TopLeft();
+ maSize = aRectangle.GetSize();
}
// ------------------------------------------------------------------------
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 6298ff51a16a..91ea8419cba9 100644
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -56,7 +56,6 @@
#include <vcl/gdimtf.hxx>
#include <vcl/outdata.hxx>
#include <vcl/print.hxx>
-#include <implncvt.hxx>
#include <vcl/outdev.h>
#include <vcl/outdev.hxx>
#include <vcl/unowrap.hxx>
@@ -77,6 +76,8 @@
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <vcl/unohelp.hxx>
+#include <numeric>
+
using namespace ::com::sun::star;
DBG_NAME( OutputDevice )
@@ -2330,6 +2331,130 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
// -----------------------------------------------------------------------
+void OutputDevice::impPaintLineGeometryWithEvtlExpand(
+ const LineInfo& rInfo,
+ basegfx::B2DPolyPolygon aLinePolyPolygon)
+{
+ const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsLineColor());
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+ const bool bDashUsed(LINE_DASH == rInfo.GetStyle());
+ const bool bLineWidthUsed(rInfo.GetWidth() > 1);
+
+ if(bDashUsed && aLinePolyPolygon.count())
+ {
+ ::std::vector< double > fDotDashArray;
+ const double fDashLen(rInfo.GetDashLen());
+ const double fDotLen(rInfo.GetDotLen());
+ const double fDistance(rInfo.GetDistance());
+
+ for(sal_uInt16 a(0); a < rInfo.GetDashCount(); a++)
+ {
+ fDotDashArray.push_back(fDashLen);
+ fDotDashArray.push_back(fDistance);
+ }
+
+ for(sal_uInt16 b(0); b < rInfo.GetDotCount(); b++)
+ {
+ fDotDashArray.push_back(fDotLen);
+ fDotDashArray.push_back(fDistance);
+ }
+
+ const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
+
+ if(fAccumulated > 0.0)
+ {
+ basegfx::B2DPolyPolygon aResult;
+
+ for(sal_uInt32 c(0); c < aLinePolyPolygon.count(); c++)
+ {
+ basegfx::B2DPolyPolygon aLineTraget;
+ basegfx::tools::applyLineDashing(
+ aLinePolyPolygon.getB2DPolygon(c),
+ fDotDashArray,
+ &aLineTraget);
+ aResult.append(aLineTraget);
+ }
+
+ aLinePolyPolygon = aResult;
+ }
+ }
+
+ if(bLineWidthUsed && aLinePolyPolygon.count())
+ {
+ const double fHalfLineWidth((rInfo.GetWidth() * 0.5) + 0.5);
+
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ aFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
+ aLinePolyPolygon.getB2DPolygon(a),
+ fHalfLineWidth,
+ rInfo.GetLineJoin()));
+ }
+
+ aLinePolyPolygon.clear();
+ }
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ mpMetaFile = NULL;
+
+ if(aLinePolyPolygon.count())
+ {
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ bool bDone(false);
+
+ if(bTryAA)
+ {
+ bDone = mpGraphics->DrawPolyLine(aCandidate, basegfx::B2DVector(1.0, 1.0), basegfx::B2DLINEJOIN_NONE, this);
+ }
+
+ if(!bDone)
+ {
+ const Polygon aPolygon(aCandidate);
+ mpGraphics->DrawPolyLine(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this);
+ }
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor( maLineColor );
+ const Color aOldFillColor( maFillColor );
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor( aOldLineColor );
+ ImplInitFillColor();
+
+ bool bDone(false);
+
+ if(bTryAA)
+ {
+ bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this);
+ }
+
+ if(!bDone)
+ {
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ mpGraphics->DrawPolygon(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this);
+ }
+ }
+
+ SetFillColor( aOldFillColor );
+ SetLineColor( aOldLineColor );
+ }
+
+ mpMetaFile = pOldMetaFile;
+}
+
+// -----------------------------------------------------------------------
+
void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt,
const LineInfo& rLineInfo )
{
@@ -2357,47 +2482,22 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt,
if ( mbOutputClipped )
return;
+ const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) );
+ const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) );
const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+ const bool bDashUsed(LINE_DASH == aInfo.GetStyle());
+ const bool bLineWidthUsed(aInfo.GetWidth() > 1);
- if( ( aInfo.GetWidth() > 1L ) || ( LINE_DASH == aInfo.GetStyle() ) )
+ if(bDashUsed || bLineWidthUsed)
{
- Polygon aPoly( 2 ); aPoly[ 0 ] = rStartPt; aPoly[ 1 ] = rEndPt;
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- ImplLineConverter aLineCvt( ImplLogicToDevicePixel( aPoly ), aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
-
- mpMetaFile = NULL;
+ basegfx::B2DPolygon aLinePolygon;
+ aLinePolygon.append(basegfx::B2DPoint(aStartPt.X(), aStartPt.Y()));
+ aLinePolygon.append(basegfx::B2DPoint(aEndPt.X(), aEndPt.Y()));
- if ( aInfo.GetWidth() > 1 )
- {
- const Color aOldLineColor( maLineColor );
- const Color aOldFillColor( maFillColor );
-
- SetLineColor();
- ImplInitLineColor();
- SetFillColor( aOldLineColor );
- ImplInitFillColor();
-
- for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
- mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->GetConstPointAry(), this );
-
- SetFillColor( aOldFillColor );
- SetLineColor( aOldLineColor );
- }
- else
- {
- if ( mbInitLineColor )
- ImplInitLineColor();
-
- for ( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
- mpGraphics->DrawLine( (*pPoly)[ 0 ].X(), (*pPoly)[ 0 ].Y(), (*pPoly)[ 1 ].X(), (*pPoly)[ 1 ].Y(), this );
- }
- mpMetaFile = pOldMetaFile;
+ impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aLinePolygon));
}
else
{
- const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) );
- const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) );
-
if ( mbInitLineColor )
ImplInitLineColor();
@@ -2546,7 +2646,7 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo
if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
&& LINE_SOLID == rLineInfo.GetStyle())
{
- DrawPolyLine(rPoly.getB2DPolygon(), (double)rLineInfo.GetWidth(), basegfx::B2DLINEJOIN_ROUND);
+ DrawPolyLine(rPoly.getB2DPolygon(), (double)rLineInfo.GetWidth(), rLineInfo.GetLineJoin());
return;
}
@@ -2558,7 +2658,7 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo
void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineInfo& rLineInfo)
{
- USHORT nPoints = rPoly.GetSize();
+ USHORT nPoints(rPoly.GetSize());
if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() )
return;
@@ -2566,11 +2666,19 @@ void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineI
Polygon aPoly = ImplLogicToDevicePixel( rPoly );
// #100127# LineInfo is not curve-safe, subdivide always
- if( aPoly.HasFlags() )
- {
- aPoly = ImplSubdivideBezier( aPoly );
- nPoints = aPoly.GetSize();
- }
+ //
+ // What shall this mean? It's wrong to subdivide here when the
+ // polygon is a fat line. In that case, the painted geometry
+ // WILL be much different.
+ // I also have no idea how this could be related to the given ID
+ // which reads 'consolidate boost versions' in the task description.
+ // Removing.
+ //
+ //if( aPoly.HasFlags() )
+ //{
+ // aPoly = ImplSubdivideBezier( aPoly );
+ // nPoints = aPoly.GetSize();
+ //}
// we need a graphics
if ( !mpGraphics && !ImplGetGraphics() )
@@ -2582,67 +2690,29 @@ void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineI
if ( mbOutputClipped )
return;
- const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
- const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
- && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
- && ROP_OVERPAINT == GetRasterOp()
- && IsLineColor());
-
- if( aInfo.GetWidth() > 1L )
- {
- const Color aOldLineColor( maLineColor );
- const Color aOldFillColor( maFillColor );
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- ImplLineConverter aLineCvt( aPoly, aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
-
- mpMetaFile = NULL;
- SetLineColor();
+ if ( mbInitLineColor )
ImplInitLineColor();
- SetFillColor( aOldLineColor );
- ImplInitFillColor();
- bool bDone(false);
- if(bTryAA)
- {
- // #i101491# try AAed version
- // Use old on-the-fly geometry preparation, combine with AA
- bool bSuccess(true);
-
- for(const Polygon* pPoly = aLineCvt.ImplGetFirst(); bSuccess && pPoly; pPoly = aLineCvt.ImplGetNext())
- {
- bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(pPoly->getB2DPolygon()), 0.0, this);
- }
-
- if(bSuccess)
- {
- bDone = true;
- }
- }
-
- if(!bDone)
- {
- for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
- {
- mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->GetConstPointAry(), this );
- }
- }
+ const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+ const bool bDashUsed(LINE_DASH == aInfo.GetStyle());
+ const bool bLineWidthUsed(aInfo.GetWidth() > 1);
- SetLineColor( aOldLineColor );
- SetFillColor( aOldFillColor );
- mpMetaFile = pOldMetaFile;
+ if(bDashUsed || bLineWidthUsed)
+ {
+ impPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aPoly.getB2DPolygon()));
}
else
{
- if ( mbInitLineColor )
- ImplInitLineColor();
- if ( LINE_DASH == aInfo.GetStyle() )
+ // #100127# the subdivision HAS to be done here since only a pointer
+ // to an array of points is given to the DrawPolyLine method, there is
+ // NO way to find out there that it's a curve.
+ if( aPoly.HasFlags() )
{
- ImplLineConverter aLineCvt( aPoly, aInfo, ( mbRefPoint ) ? &maRefPoint : NULL );
- for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
- mpGraphics->DrawPolyLine( pPoly->GetSize(), (const SalPoint*)pPoly->GetConstPointAry(), this );
+ aPoly = ImplSubdivideBezier( aPoly );
+ nPoints = aPoly.GetSize();
}
- else
- mpGraphics->DrawPolyLine( nPoints, (const SalPoint*) aPoly.GetConstPointAry(), this );
+
+ mpGraphics->DrawPolyLine(nPoints, (const SalPoint*)aPoly.GetConstPointAry(), this);
}
if( mpAlphaVDev )
@@ -3047,7 +3117,12 @@ void OutputDevice::DrawPolyLine(
SetFillColor(aOldLineColor);
ImplInitFillColor();
- ImpDrawPolyPolygonWithB2DPolyPolygon(aAreaPolyPolygon);
+ // draw usig a loop; else the topology will paint a PolyPolygon
+ for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++)
+ {
+ ImpDrawPolyPolygonWithB2DPolyPolygon(
+ basegfx::B2DPolyPolygon(aAreaPolyPolygon.getB2DPolygon(a)));
+ }
SetLineColor(aOldLineColor);
ImplInitLineColor();
@@ -3064,14 +3139,15 @@ void OutputDevice::DrawPolyLine(
}
}
}
-
- // fallback to old polygon drawing if needed. This will really
- // use ImplLineConverter, but still try to AA lines
- const Polygon aToolsPolygon( rB2DPolygon );
- LineInfo aLineInfo;
- if( fLineWidth != 0.0 )
- aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) );
- ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo );
+ else
+ {
+ // fallback to old polygon drawing if needed
+ const Polygon aToolsPolygon( rB2DPolygon );
+ LineInfo aLineInfo;
+ if( fLineWidth != 0.0 )
+ aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) );
+ ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo );
+ }
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx
index 79986988afd7..2d436ea43659 100644
--- a/vcl/source/gdi/outdev6.cxx
+++ b/vcl/source/gdi/outdev6.cxx
@@ -1158,9 +1158,11 @@ void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect,
// -----------------------------------------------------------------------
-void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
+bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
const GfxLink& rGfxLink, GDIMetaFile* pSubst )
{
+ bool bDrawn(true);
+
if ( mpMetaFile )
{
GDIMetaFile aSubst;
@@ -1172,20 +1174,20 @@ void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
}
if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
- return;
+ return bDrawn;
if( mbOutputClipped )
- return;
+ return bDrawn;
Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
+
if( !aRect.IsEmpty() )
{
// draw the real EPS graphics
- bool bDrawn = FALSE;
if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
{
if( !mpGraphics && !ImplGetGraphics() )
- return;
+ return bDrawn;
if( mbInitClipRegion )
ImplInitClipRegion();
@@ -1208,4 +1210,6 @@ void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
if( mpAlphaVDev )
mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
+
+ return bDrawn;
}
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 4146f1764204..c0205f1f325d 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -61,11 +61,9 @@
#include <comphelper/processfactory.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/util/URL.hpp>
-
-#include "implncvt.hxx"
-
#include "cppuhelper/implbase1.hxx"
#include <icc/sRGB-IEC61966-2.1.hxx>
+#include <vcl/lineinfo.hxx>
using namespace vcl;
using namespace rtl;
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
index 66865759db4b..fefbf8cdcb08 100644
--- a/vcl/source/gdi/region.cxx
+++ b/vcl/source/gdi/region.cxx
@@ -49,6 +49,7 @@
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
// =======================================================================
//
@@ -1303,9 +1304,7 @@ void Region::Move( long nHorzMove, long nVertMove )
mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
else if( mpImplRegion->mpB2DPolyPoly )
{
- ::basegfx::B2DHomMatrix aTransform;
- aTransform.translate( nHorzMove, nVertMove );
- mpImplRegion->mpB2DPolyPoly->transform( aTransform );
+ mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
}
else
{
@@ -1346,9 +1345,7 @@ void Region::Scale( double fScaleX, double fScaleY )
mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
else if( mpImplRegion->mpB2DPolyPoly )
{
- ::basegfx::B2DHomMatrix aTransform;
- aTransform.scale( fScaleX, fScaleY );
- mpImplRegion->mpB2DPolyPoly->transform( aTransform );
+ mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
}
else
{
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index 1e9572887e0b..c1f987377c67 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -52,7 +52,6 @@
#include <vcl/gdimtf.hxx>
#include <vcl/outdata.hxx>
#include <vcl/print.hxx>
-#include <implncvt.hxx>
#include <vcl/outdev.h>
#include <vcl/outdev.hxx>
#include <vcl/unowrap.hxx>
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 1f44b823ce44..c8748c65e2d3 100755
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -44,6 +44,7 @@
#include <vcl/sallayout.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <i18npool/lang.h>
#ifndef _TL_DEBUG_HXX
@@ -893,10 +894,8 @@ bool SalLayout::GetOutline( SalGraphics& rSalGraphics,
{
if( aPos.X() || aPos.Y() )
{
- ::basegfx::B2DHomMatrix aMatrix;
- aMatrix.translate( aPos.X(), aPos.Y() );
- aGlyphOutline.transform( aMatrix );
- }
+ aGlyphOutline.transform(basegfx::tools::createTranslateB2DHomMatrix(aPos.X(), aPos.Y()));
+ }
// insert outline at correct position
rVector.push_back( aGlyphOutline );
diff --git a/vcl/source/glyphs/gcach_ftyp.cxx b/vcl/source/glyphs/gcach_ftyp.cxx
index 18857b94af8f..b92bea929c51 100644
--- a/vcl/source/glyphs/gcach_ftyp.cxx
+++ b/vcl/source/glyphs/gcach_ftyp.cxx
@@ -43,6 +43,7 @@
#include "tools/poly.hxx"
#include "basegfx/matrix/b2dhommatrix.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include "basegfx/polygon/b2dpolypolygon.hxx"
#include "osl/file.hxx"
@@ -2282,9 +2283,7 @@ bool FreetypeServerFont::GetGlyphOutline( int nGlyphIndex,
// convert to basegfx polypolygon
// TODO: get rid of the intermediate tools polypolygon
rB2DPolyPoly = aToolPolyPolygon.getB2DPolyPolygon();
- ::basegfx::B2DHomMatrix aMatrix;
- aMatrix.scale( +1.0/(1<<6), -1.0/(1<<6) );
- rB2DPolyPoly.transform( aMatrix );
+ rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix( +1.0/(1<<6), -1.0/(1<<6) ));
return true;
}
diff --git a/vcl/unx/source/gdi/salgdi.cxx b/vcl/unx/source/gdi/salgdi.cxx
index cb554bccea21..5fe2295a8fed 100644
--- a/vcl/unx/source/gdi/salgdi.cxx
+++ b/vcl/unx/source/gdi/salgdi.cxx
@@ -50,6 +50,7 @@
#include "basegfx/polygon/b2dpolygonclipper.hxx"
#include "basegfx/polygon/b2dlinegeometry.hxx"
#include "basegfx/matrix/b2dhommatrix.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include "basegfx/polygon/b2dpolypolygoncutter.hxx"
#include <vector>
@@ -1567,6 +1568,9 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const :
// the used basegfx::tools::createAreaGeometry is simply too
// expensive with very big polygons; fallback to caller (who
// should use ImplLineConverter normally)
+ // AW: ImplLineConverter had to be removed since it does not even
+ // know LineJoins, so the fallback will now prepare the line geometry
+ // the same way.
return false;
}
const XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
@@ -1579,9 +1583,7 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const :
&& !basegfx::fTools::equalZero( rLineWidth.getY() ) )
{
// prepare for createAreaGeometry() with anisotropic linewidth
- basegfx::B2DHomMatrix aAnisoMatrix;
- aAnisoMatrix.scale( 1.0, rLineWidth.getX() / rLineWidth.getY() );
- aPolygon.transform( aAnisoMatrix );
+ aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY()));
}
// special handling for hairlines to improve the drawing performance
@@ -1603,9 +1605,7 @@ bool X11SalGraphics::drawPolyLine(const ::basegfx::B2DPolygon& rPolygon, const :
&& !basegfx::fTools::equalZero( rLineWidth.getX() ) )
{
// postprocess createAreaGeometry() for anisotropic linewidth
- basegfx::B2DHomMatrix aAnisoMatrix;
- aAnisoMatrix.scale( 1.0, rLineWidth.getY() / rLineWidth.getX() );
- aPolygon.transform( aAnisoMatrix );
+ aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX()));
}
// temporarily adjust brush color to pen color
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index d82830a9022f..12fdad65dfb1 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -65,6 +65,7 @@
#include "basegfx/polygon/b2dpolygon.hxx"
#include "basegfx/polygon/b2dpolypolygon.hxx"
#include "basegfx/matrix/b2dhommatrix.hxx"
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include "sft.hxx"
@@ -2480,9 +2481,8 @@ BOOL WinSalGraphics::GetGlyphOutline( long nIndex,
// rescaling needed for the PolyPolygon conversion
if( rB2DPolyPoly.count() )
{
- ::basegfx::B2DHomMatrix aMatrix;
- aMatrix.scale( mfFontScale/256, mfFontScale/256 );
- rB2DPolyPoly.transform( aMatrix );
+ const double fFactor(mfFontScale/256);
+ rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor));
}
return bRet;
diff --git a/vcl/win/source/gdi/salgdi_gdiplus.cxx b/vcl/win/source/gdi/salgdi_gdiplus.cxx
index 5c00c786e22d..29e4ff1d801e 100644
--- a/vcl/win/source/gdi/salgdi_gdiplus.cxx
+++ b/vcl/win/source/gdi/salgdi_gdiplus.cxx
@@ -62,9 +62,9 @@
// -----------------------------------------------------------------------
-void impAddB2DPolygonToGDIPlusGraphicsPath(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon)
+void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
{
- const sal_uInt32 nCount(rPolygon.count());
+ sal_uInt32 nCount(rPolygon.count());
if(nCount)
{
@@ -97,8 +97,58 @@ void impAddB2DPolygonToGDIPlusGraphicsPath(Gdiplus::GraphicsPath& rPath, const b
if(a + 1 < nEdgeCount)
{
- aCurr = aNext;
aFCurr = aFNext;
+
+ if(bNoLineJoin)
+ {
+ rPath.StartFigure();
+ }
+ }
+ }
+ }
+}
+
+void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
+{
+ sal_uInt32 nCount(rPolygon.count());
+
+ if(nCount)
+ {
+ const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1);
+ const bool bControls(rPolygon.areControlPointsUsed());
+ basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
+ Gdiplus::Point aICurr(INT(aCurr.getX()), INT(aCurr.getY()));
+
+ for(sal_uInt32 a(0); a < nEdgeCount; a++)
+ {
+ const sal_uInt32 nNextIndex((a + 1) % nCount);
+ const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
+ const Gdiplus::Point aINext(INT(aNext.getX()), INT(aNext.getY()));
+
+ if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex)))
+ {
+ const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
+ const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
+
+ rPath.AddBezier(
+ aICurr,
+ Gdiplus::Point(INT(aCa.getX()), INT(aCa.getY())),
+ Gdiplus::Point(INT(aCb.getX()), INT(aCb.getY())),
+ aINext);
+ }
+ else
+ {
+ rPath.AddLine(aICurr, aINext);
+ }
+
+ if(a + 1 < nEdgeCount)
+ {
+ aICurr = aINext;
+
+ if(bNoLineJoin)
+ {
+ rPath.StartFigure();
+ }
}
}
}
@@ -123,7 +173,7 @@ bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly
aPath.StartFigure(); // #i101491# not needed for first run
}
- impAddB2DPolygonToGDIPlusGraphicsPath(aPath, rPolyPolygon.getB2DPolygon(a));
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolyPolygon.getB2DPolygon(a), false);
aPath.CloseFigure();
}
@@ -152,11 +202,16 @@ bool WinSalGraphics::drawPolyLine(const basegfx::B2DPolygon& rPolygon, const bas
Gdiplus::Color aTestColor(255, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor));
Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX()));
Gdiplus::GraphicsPath aPath;
+ bool bNoLineJoin(false);
switch(eLineJoin)
{
default : // basegfx::B2DLINEJOIN_NONE :
{
+ if(basegfx::fTools::more(rLineWidths.getX(), 0.0))
+ {
+ bNoLineJoin = true;
+ }
break;
}
case basegfx::B2DLINEJOIN_BEVEL :
@@ -179,9 +234,16 @@ bool WinSalGraphics::drawPolyLine(const basegfx::B2DPolygon& rPolygon, const bas
}
}
- impAddB2DPolygonToGDIPlusGraphicsPath(aPath, rPolygon);
+ if(nCount > 250 && basegfx::fTools::more(rLineWidths.getX(), 1.5))
+ {
+ impAddB2DPolygonToGDIPlusGraphicsPathInteger(aPath, rPolygon, bNoLineJoin);
+ }
+ else
+ {
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolygon, bNoLineJoin);
+ }
- if(rPolygon.isClosed())
+ if(rPolygon.isClosed() && !bNoLineJoin)
{
// #i101491# needed to create the correct line joins
aPath.CloseFigure();
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index bf56b2a1082b..bf56b2a1082b 100644..100755
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx