diff options
Diffstat (limited to 'drawinglayer')
16 files changed, 865 insertions, 195 deletions
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/chartprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/chartprimitive2d.hxx index bd8c3be1fbbd..71c4cc6ffe1e 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/chartprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/chartprimitive2d.hxx @@ -56,7 +56,7 @@ namespace drawinglayer const basegfx::B2DHomMatrix& rTransformation, const Primitive2DSequence& rChildren); - // get data + /// data read access const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& getChartModel() const { return mxChartModel; } const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/discreteshadowprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/discreteshadowprimitive2d.hxx new file mode 100644 index 000000000000..c30bff545ddb --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/discreteshadowprimitive2d.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 INCLUDED_DRAWINGLAYER_PRIMITIVE2D_QUADRATICSHADOWPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_QUADRATICSHADOWPRIMITIVE2D_HXX + +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <vcl/bitmapex.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> + +////////////////////////////////////////////////////////////////////////////// +// DiscreteShadowPrimitive2D class + +namespace drawinglayer +{ + namespace primitive2d + { + /** DiscreteShadow data class + + */ + class DiscreteShadow + { + private: + /// the original shadow BitmapEx in a special form + BitmapEx maBitmapEx; + + /// buffered extracted parts of CombinedShadow for easier usage + BitmapEx maTopLeft; + BitmapEx maTop; + BitmapEx maTopRight; + BitmapEx maRight; + BitmapEx maBottomRight; + BitmapEx maBottom; + BitmapEx maBottomLeft; + BitmapEx maLeft; + + public: + /// constructor + DiscreteShadow(const BitmapEx& rBitmapEx); + + /// data read access + const BitmapEx& getBitmapEx() const { return maBitmapEx; } + + /// compare operator + bool operator==(const DiscreteShadow& rCompare) const + { + return getBitmapEx() == rCompare.getBitmapEx(); + } + + /// helper accesses which create on-demand needed segments + const BitmapEx& getTopLeft() const; + const BitmapEx& getTop() const; + const BitmapEx& getTopRight() const; + const BitmapEx& getRight() const; + const BitmapEx& getBottomRight() const; + const BitmapEx& getBottom() const; + const BitmapEx& getBottomLeft() const; + const BitmapEx& getLeft() const; + }; + + /** DiscreteShadowPrimitive2D class + + */ + class DiscreteShadowPrimitive2D : public DiscreteMetricDependentPrimitive2D + { + private: + // the object transformation of the rectangular object + basegfx::B2DHomMatrix maTransform; + + // the bitmap shadow data + DiscreteShadow maDiscreteShadow; + + protected: + /// create local decomposition + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + /// constructor + DiscreteShadowPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const DiscreteShadow& rDiscreteShadow); + + /// data read access + const basegfx::B2DHomMatrix& getTransform() const { return maTransform; } + const DiscreteShadow& getDiscreteShadow() const { return maDiscreteShadow; } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + /// get range + virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; + + /// provide unique ID + DeclPrimitrive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif // INCLUDED_DRAWINGLAYER_PRIMITIVE2D_QUADRATICSHADOWPRIMITIVE2D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx index 7872ad825496..87aae8cb768f 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -90,17 +90,19 @@ #define PRIMITIVE2D_ID_EXECUTEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 47) #define PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 48) #define PRIMITIVE2D_ID_CHARTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 49) -#define PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 50) +#define PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 50) #define PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 51) #define PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 52) -#define PRIMITIVE2D_ID_INVERTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 53) -#define PRIMITIVE2D_ID_DISCRETEBITMAPPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 54) -#define PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 55) -#define PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 56) -#define PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 57) -#define PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 58) -#define PRIMITIVE2D_ID_EPSPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 59) -#define PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 60) +#define PRIMITIVE2D_ID_HITTESTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 53) +#define PRIMITIVE2D_ID_INVERTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 54) +#define PRIMITIVE2D_ID_DISCRETEBITMAPPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 55) +#define PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 56) +#define PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 57) +#define PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 58) +#define PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 59) +#define PRIMITIVE2D_ID_EPSPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 60) +#define PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 61) +#define PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 62) ////////////////////////////////////////////////////////////////////////////// diff --git a/drawinglayer/inc/drawinglayer/primitive2d/embedded3dprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/embedded3dprimitive2d.hxx index ce49995c999d..d651af24047d 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/embedded3dprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/embedded3dprimitive2d.hxx @@ -101,7 +101,7 @@ namespace drawinglayer double fShadowSlant, const basegfx::B3DRange& rScene3DRange); - /// get data + /// data read access const primitive3d::Primitive3DSequence& getChildren3D() const { return mxChildren3D; } const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } const geometry::ViewInformation3D& getViewInformation3D() const { return maViewInformation3D; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/helplineprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/helplineprimitive2d.hxx index 237ae00a4642..e2323765b2e5 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/helplineprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/helplineprimitive2d.hxx @@ -94,8 +94,8 @@ namespace drawinglayer double fDiscreteDashLength); /// data read access - const basegfx::B2DPoint getPosition() const { return maPosition; } - const basegfx::B2DVector getDirection() const { return maDirection; } + const basegfx::B2DPoint& getPosition() const { return maPosition; } + const basegfx::B2DVector& getDirection() const { return maDirection; } HelplineStyle2D getStyle() const { return meStyle; } const basegfx::BColor& getRGBColA() const { return maRGBColA; } const basegfx::BColor& getRGBColB() const { return maRGBColB; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx index 80e281ede05c..ee5de781be86 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx @@ -189,7 +189,7 @@ namespace drawinglayer const attribute::LineAttribute& rLineAttribute); /// data read access - basegfx::B2DPolygon getB2DPolygon() const { return maPolygon; } + const basegfx::B2DPolygon& getB2DPolygon() const { return maPolygon; } const attribute::LineAttribute& getLineAttribute() const { return maLineAttribute; } const attribute::StrokeAttribute& getStrokeAttribute() const { return maStrokeAttribute; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx index 18743937b6bc..4a48ae0d3e59 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx @@ -69,7 +69,7 @@ namespace drawinglayer PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor); /// data read access - basegfx::B2DPolyPolygon getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } const basegfx::BColor& getBColor() const { return maBColor; } /// compare operator @@ -123,7 +123,7 @@ namespace drawinglayer double fDiscreteDashLength); // data read access - basegfx::B2DPolyPolygon getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } const basegfx::BColor& getRGBColorA() const { return maRGBColorA; } const basegfx::BColor& getRGBColorB() const { return maRGBColorB; } double getDiscreteDashLength() const { return mfDiscreteDashLength; } @@ -182,7 +182,7 @@ namespace drawinglayer const attribute::LineAttribute& rLineAttribute); /// data read access - basegfx::B2DPolyPolygon getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } const attribute::LineAttribute& getLineAttribute() const { return maLineAttribute; } const attribute::StrokeAttribute& getStrokeAttribute() const { return maStrokeAttribute; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx index 4c95972ca67d..278a1b0bfff2 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx @@ -136,7 +136,7 @@ namespace drawinglayer const basegfx::B2DHomMatrix& rObjectTransformation, const geometry::ViewInformation3D& rViewInformation3D); - /// data ead access + /// data read access const primitive3d::Primitive3DSequence& getChildren3D() const { return mxChildren3D; } const attribute::SdrSceneAttribute& getSdrSceneAttribute() const { return maSdrSceneAttribute; } const attribute::SdrLightingAttribute& getSdrLightingAttribute() const { return maSdrLightingAttribute; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx index 6ae691cbcff9..5c1093bc333a 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx @@ -129,8 +129,8 @@ namespace drawinglayer TextStrikeout getTextStrikeout() const { return meTextStrikeout; } TextEmphasisMark getTextEmphasisMark() const { return meTextEmphasisMark; } TextRelief getTextRelief() const { return meTextRelief; } - basegfx::BColor getOverlineColor() const { return maOverlineColor; } - basegfx::BColor getTextlineColor() const { return maTextlineColor; } + const basegfx::BColor& getOverlineColor() const { return maOverlineColor; } + const basegfx::BColor& getTextlineColor() const { return maTextlineColor; } bool getUnderlineAbove() const { return mbUnderlineAbove; } bool getWordLineMode() const { return mbWordLineMode; } bool getEmphasisMarkAbove() const { return mbEmphasisMarkAbove; } diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst index e863e47a3b18..54f087d317e4 100644 --- a/drawinglayer/prj/d.lst +++ b/drawinglayer/prj/d.lst @@ -16,6 +16,8 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\primitive2d ..\inc\drawinglayer\primitive2d\borderlineprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\borderlineprimitive2d.hxx ..\inc\drawinglayer\primitive2d\chartprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\chartprimitive2d.hxx ..\inc\drawinglayer\primitive2d\controlprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\controlprimitive2d.hxx +..\inc\drawinglayer\primitive2d\discretebitmapprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\discretebitmapprimitive2d.hxx +..\inc\drawinglayer\primitive2d\discreteshadowprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\discreteshadowprimitive2d.hxx ..\inc\drawinglayer\primitive2d\embedded3dprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\embedded3dprimitive2d.hxx ..\inc\drawinglayer\primitive2d\fillbitmapprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\fillbitmapprimitive2d.hxx ..\inc\drawinglayer\primitive2d\fillgradientprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\fillgradientprimitive2d.hxx diff --git a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx new file mode 100644 index 000000000000..a4afd501728b --- /dev/null +++ b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx @@ -0,0 +1,339 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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_drawinglayer.hxx" + +#include <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + DiscreteShadow::DiscreteShadow(const BitmapEx& rBitmapEx) + : maBitmapEx(rBitmapEx), + maTopLeft(), + maTop(), + maTopRight(), + maRight(), + maBottomRight(), + maBottom(), + maBottomLeft(), + maLeft() + { + const Size& rBitmapSize = getBitmapEx().GetSizePixel(); + + if(rBitmapSize.Width() != rBitmapSize.Height() || rBitmapSize.Width() < 7) + { + OSL_ENSURE(false, "DiscreteShadowPrimitive2D: wrong bitmap format (!)"); + maBitmapEx = BitmapEx(); + } + } + + const BitmapEx& DiscreteShadow::getTopLeft() const + { + if(maTopLeft.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maTopLeft = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maTopLeft.Crop( + Rectangle(Point(0,0),Size(nQuarter*2+1,nQuarter*2+1))); + } + + return maTopLeft; + } + + const BitmapEx& DiscreteShadow::getTop() const + { + if(maTop.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maTop = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maTop.Crop( + Rectangle(Point(nQuarter*2+1,0),Size(1,nQuarter+1))); + } + + return maTop; + } + + const BitmapEx& DiscreteShadow::getTopRight() const + { + if(maTopRight.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maTopRight = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maTopRight.Crop( + Rectangle(Point(nQuarter*2+2,0),Size(nQuarter*2+1,nQuarter*2+1))); + } + + return maTopRight; + } + + const BitmapEx& DiscreteShadow::getRight() const + { + if(maRight.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maRight = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maRight.Crop( + Rectangle(Point(nQuarter*3+2,nQuarter*2+1),Size(nQuarter+1,1))); + } + + return maRight; + } + + const BitmapEx& DiscreteShadow::getBottomRight() const + { + if(maBottomRight.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maBottomRight = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maBottomRight.Crop( + Rectangle(Point(nQuarter*2+2,nQuarter*2+2),Size(nQuarter*2+1,nQuarter*2+1))); + } + + return maBottomRight; + } + + const BitmapEx& DiscreteShadow::getBottom() const + { + if(maBottom.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maBottom = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maBottom.Crop( + Rectangle(Point(nQuarter*2+1,nQuarter*3+2),Size(1,nQuarter+1))); + } + + return maBottom; + } + + const BitmapEx& DiscreteShadow::getBottomLeft() const + { + if(maBottomLeft.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maBottomLeft = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maBottomLeft.Crop( + Rectangle(Point(0,nQuarter*2+2),Size(nQuarter*2+1,nQuarter*2+1))); + } + + return maBottomLeft; + } + + const BitmapEx& DiscreteShadow::getLeft() const + { + if(maLeft.IsEmpty()) + { + const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const_cast< DiscreteShadow* >(this)->maLeft = getBitmapEx(); + const_cast< DiscreteShadow* >(this)->maLeft.Crop( + Rectangle(Point(0,nQuarter*2+1),Size(nQuarter+1,1))); + } + + return maLeft; + } + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + Primitive2DSequence DiscreteShadowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + Primitive2DSequence xRetval; + + if(!getDiscreteShadow().getBitmapEx().IsEmpty()) + { + const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0)); + const double fSingleX(getDiscreteUnit() / aScale.getX()); + const double fSingleY(getDiscreteUnit() / aScale.getY()); + const double fBorderX(fSingleX * nQuarter); + const double fBorderY(fSingleY * nQuarter); + const double fBigLenX((fBorderX * 2.0) + fSingleX); + const double fBigLenY((fBorderY * 2.0) + fSingleY); + + xRetval.realloc(8); + + // TopLeft + xRetval[0] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getTopLeft(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + -fBorderX, + -fBorderY))); + + // Top + xRetval[1] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getTop(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + 1.0 - (2.0 * fBorderX) - fSingleX, + fBorderY + fSingleY, + fBorderX + fSingleX, + -fBorderY))); + + // TopRight + xRetval[2] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getTopRight(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + 1.0 - fBorderX, + -fBorderY))); + + // Right + xRetval[3] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getRight(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBorderX + fSingleX, + 1.0 - (2.0 * fBorderY) - fSingleY, + 1.0, + fBorderY + fSingleY))); + + // BottomRight + xRetval[4] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getBottomRight(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + 1.0 - fBorderX, + 1.0 - fBorderY))); + + // Bottom + xRetval[5] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getBottom(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + 1.0 - (2.0 * fBorderX) - fSingleX, + fBorderY + fSingleY, + fBorderX + fSingleX, + 1.0))); + + // BottomLeft + xRetval[6] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getBottomLeft(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + -fBorderX, + 1.0 - fBorderY))); + + // Left + xRetval[7] = Primitive2DReference( + new BitmapPrimitive2D( + getDiscreteShadow().getLeft(), + basegfx::tools::createScaleTranslateB2DHomMatrix( + fBorderX + fSingleX, + 1.0 - (2.0 * fBorderY) - fSingleY, + -fBorderX, + fBorderY + fSingleY))); + + // put all in object transformation to get to target positions + const Primitive2DReference xTransformed( + new TransformPrimitive2D( + getTransform(), + xRetval)); + + xRetval = Primitive2DSequence(&xTransformed, 1); + } + + return xRetval; + } + + DiscreteShadowPrimitive2D::DiscreteShadowPrimitive2D( + const basegfx::B2DHomMatrix& rTransform, + const DiscreteShadow& rDiscreteShadow) + : DiscreteMetricDependentPrimitive2D(), + maTransform(rTransform), + maDiscreteShadow(rDiscreteShadow) + { + } + + bool DiscreteShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const DiscreteShadowPrimitive2D& rCompare = (DiscreteShadowPrimitive2D&)rPrimitive; + + return (getTransform() == rCompare.getTransform() + && getDiscreteShadow() == rCompare.getDiscreteShadow()); + } + + return false; + } + + basegfx::B2DRange DiscreteShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + if(getDiscreteShadow().getBitmapEx().IsEmpty()) + { + // no graphics without valid bitmap definition + return basegfx::B2DRange(); + } + else + { + // prepare normal objectrange + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(getTransform()); + + // extract discrete shadow size and grow + const basegfx::B2DVector aScale(rViewInformation.getViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const double fGrowX((1.0 / aScale.getX()) * nQuarter); + const double fGrowY((1.0 / aScale.getY()) * nQuarter); + aRetval.grow(std::max(fGrowX, fGrowY)); + + return aRetval; + } + } + + // provide unique ID + ImplPrimitrive2DIDBlock(DiscreteShadowPrimitive2D, PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/makefile.mk b/drawinglayer/source/primitive2d/makefile.mk index bca5805ae6eb..720769a0efd5 100644 --- a/drawinglayer/source/primitive2d/makefile.mk +++ b/drawinglayer/source/primitive2d/makefile.mk @@ -46,6 +46,7 @@ SLOFILES= \ $(SLO)$/chartprimitive2d.obj \ $(SLO)$/controlprimitive2d.obj \ $(SLO)$/discretebitmapprimitive2d.obj \ + $(SLO)$/discreteshadowprimitive2d.obj \ $(SLO)$/embedded3dprimitive2d.obj \ $(SLO)$/epsprimitive2d.obj \ $(SLO)$/fillbitmapprimitive2d.obj \ diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx index 6fa1cef2d23f..0d57e566ef8a 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -2301,35 +2301,48 @@ namespace { const Gradient& rGradient = pA->GetGradient(); const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient)); + basegfx::B2DPolyPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); if(aAttribute.getStartColor() == aAttribute.getEndColor()) { // not really a gradient. Create filled rectangle - const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); - createFillPrimitive(basegfx::B2DPolyPolygon(aOutline), rTargetHolders.Current(), rPropertyHolders.Current()); + createFillPrimitive( + aOutline, + rTargetHolders.Current(), + rPropertyHolders.Current()); } else { // really a gradient aRange.transform(rPropertyHolders.Current().getTransformation()); + drawinglayer::primitive2d::Primitive2DSequence xGradient(1); if(rPropertyHolders.Current().isRasterOpInvert()) { // use a special version of FillGradientPrimitive2D which creates // non-overlapping geometry on decomposition to makethe old XOR // paint 'trick' work. - rTargetHolders.Current().append( + xGradient[0] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::NonOverlappingFillGradientPrimitive2D( aRange, aAttribute)); } else { - rTargetHolders.Current().append( + xGradient[0] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::FillGradientPrimitive2D( aRange, aAttribute)); } + + // #i112300# clip against polygon representing the rectangle from + // the action. This is implicitely done using a temp Clipping in VCL + // when a MetaGradientAction is executed + aOutline.transform(rPropertyHolders.Current().getTransformation()); + rTargetHolders.Current().append( + new drawinglayer::primitive2d::MaskPrimitive2D( + aOutline, + xGradient)); } } } diff --git a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx index 0ead7302ba38..8adcb6a10b82 100644 --- a/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/structuretagprimitive2d.cxx @@ -50,7 +50,7 @@ namespace drawinglayer } // provide unique ID - ImplPrimitrive2DIDBlock(StructureTagPrimitive2D, PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D) + ImplPrimitrive2DIDBlock(StructureTagPrimitive2D, PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D) } // end of namespace primitive2d } // end of namespace drawinglayer diff --git a/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx b/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx index db61e0721ef0..80e34ba27701 100644 --- a/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx +++ b/drawinglayer/source/processor2d/vclhelperbitmaprender.cxx @@ -85,9 +85,13 @@ namespace drawinglayer } // prepare dest coor + const sal_uInt32 nDiscreteWidth(basegfx::fround(aOutlineRange.getMaxX())); + const sal_uInt32 nDiscreteHeight(basegfx::fround(aOutlineRange.getMaxY())); const Rectangle aDestRectPixel( - basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()), - basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY())); + basegfx::fround(aOutlineRange.getMinX()), + basegfx::fround(aOutlineRange.getMinY()), + nDiscreteWidth > 0 ? nDiscreteWidth - 1 : 0, + nDiscreteHeight > 0 ? nDiscreteHeight - 1 : 0); // paint it using GraphicManager Graphic aGraphic(rBitmapEx); @@ -106,9 +110,13 @@ namespace drawinglayer // prepare dest coor. Necessary to expand since vcl's DrawBitmapEx draws one pix less basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0); aOutlineRange.transform(rTransform); + const sal_uInt32 nDiscreteWidth(basegfx::fround(aOutlineRange.getMaxX())); + const sal_uInt32 nDiscreteHeight(basegfx::fround(aOutlineRange.getMaxY())); const Rectangle aDestRectPixel( - basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()), - basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY())); + basegfx::fround(aOutlineRange.getMinX()), + basegfx::fround(aOutlineRange.getMinY()), + nDiscreteWidth > 0 ? nDiscreteWidth - 1 : 0, + nDiscreteHeight > 0 ? nDiscreteHeight - 1 : 0); // decompose matrix to check for shear, rotate and mirroring basegfx::B2DVector aScale, aTranslate; @@ -145,9 +153,13 @@ namespace drawinglayer // process self with free transformation (containing shear and rotate). Get dest rect in pixels. basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0); aOutlineRange.transform(rTransform); + const sal_uInt32 nDiscreteWidth(basegfx::fround(aOutlineRange.getMaxX())); + const sal_uInt32 nDiscreteHeight(basegfx::fround(aOutlineRange.getMaxY())); const Rectangle aDestRectLogic( - basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()), - basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY())); + basegfx::fround(aOutlineRange.getMinX()), + basegfx::fround(aOutlineRange.getMinY()), + nDiscreteWidth > 0 ? nDiscreteWidth - 1 : 0, + nDiscreteHeight > 0 ? nDiscreteHeight - 1 : 0); const Rectangle aDestRectPixel(rOutDev.LogicToPixel(aDestRectLogic)); // #i96708# check if Metafile is recorded @@ -161,18 +173,19 @@ namespace drawinglayer if(!aCroppedRectPixel.IsEmpty()) { - // as maximum for destination, orientate at SourceSizePixel, but + // as maximum for destination, orientate at aOutputRectPixel, but // take a rotation of 45 degrees (sqrt(2)) as maximum expansion into account const Size aSourceSizePixel(rBitmapEx.GetSizePixel()); const double fMaximumArea( - (double)aSourceSizePixel.getWidth() * - (double)aSourceSizePixel.getHeight() * + (double)aOutputRectPixel.getWidth() * + (double)aOutputRectPixel.getHeight() * 1.4142136); // 1.4142136 taken as sqrt(2.0) // test if discrete view size (pixel) maybe too big and limit it const double fArea(aCroppedRectPixel.getWidth() * aCroppedRectPixel.getHeight()); const bool bNeedToReduce(fArea > fMaximumArea); double fReduceFactor(1.0); + const Size aDestSizePixel(aCroppedRectPixel.GetSize()); if(bNeedToReduce) { @@ -219,11 +232,6 @@ namespace drawinglayer if(bNeedToReduce) { // paint in target size - const double fFactor(1.0 / fReduceFactor); - const Size aDestSizePixel( - basegfx::fround(aCroppedRectPixel.getWidth() * fFactor), - basegfx::fround(aCroppedRectPixel.getHeight() * fFactor)); - if(bRecordToMetaFile) { rOutDev.DrawBitmapEx( diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 983cc8f58d4f..0d2be85f9872 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -94,6 +94,147 @@ using namespace com::sun::star; ////////////////////////////////////////////////////////////////////////////// +// #112245# definition for maximum allowed point count due to Metafile target. +// To be on the safe side with the old tools polygon, use slightly less then +// the theoretical maximum (bad experiences with tools polygon) + +#define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0) + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + // #112245# helper to split line polygon in half + void splitLinePolygon( + const basegfx::B2DPolygon& rBasePolygon, + basegfx::B2DPolygon& o_aLeft, + basegfx::B2DPolygon& o_aRight) + { + const sal_uInt32 nCount(rBasePolygon.count()); + + if(nCount) + { + const sal_uInt32 nHalfCount((nCount - 1) >> 1); + + o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1); + o_aLeft.setClosed(false); + + o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount); + o_aRight.setClosed(false); + + if(rBasePolygon.isClosed()) + { + o_aRight.append(rBasePolygon.getB2DPoint(0)); + + if(rBasePolygon.areControlPointsUsed()) + { + o_aRight.setControlPoints( + o_aRight.count() - 1, + rBasePolygon.getPrevControlPoint(0), + rBasePolygon.getNextControlPoint(0)); + } + } + } + else + { + o_aLeft.clear(); + o_aRight.clear(); + } + } + + // #112245# helper to evtl. split filled polygons to maximum metafile point count + bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon) + { + bool bRetval(false); + const sal_uInt32 nPolyCount(rPolyPolygon.count()); + + if(nPolyCount) + { + basegfx::B2DPolyPolygon aSplitted; + + for(sal_uInt32 a(0); a < nPolyCount; a++) + { + const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aCandidate.count()); + bool bNeedToSplit(false); + + if(aCandidate.areControlPointsUsed()) + { + // compare with the maximum for bezier curved polygons + bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L); + } + else + { + // compare with the maximum for simple point polygons + bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); + } + + if(bNeedToSplit) + { + // need to split the partial polygon + const basegfx::B2DRange aRange(aCandidate.getB2DRange()); + const basegfx::B2DPoint aCenter(aRange.getCenter()); + + if(aRange.getWidth() > aRange.getHeight()) + { + // clip in left and right + const basegfx::B2DPolyPolygon aLeft( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + false, + true, + aCenter.getX(), + false)); + const basegfx::B2DPolyPolygon aRight( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + false, + false, + aCenter.getX(), + false)); + + aSplitted.append(aLeft); + aSplitted.append(aRight); + } + else + { + // clip in top and bottom + const basegfx::B2DPolyPolygon aTop( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + true, + true, + aCenter.getY(), + false)); + const basegfx::B2DPolyPolygon aBottom( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + true, + false, + aCenter.getY(), + false)); + + aSplitted.append(aTop); + aSplitted.append(aBottom); + } + } + else + { + aSplitted.append(aCandidate); + } + } + + if(aSplitted.count() != nPolyCount) + { + rPolyPolygon = aSplitted; + } + } + + return bRetval; + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// namespace drawinglayer { @@ -982,26 +1123,65 @@ namespace drawinglayer } case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D : { - // direct draw of hairline; use default processing - // also support SvtGraphicStroke MetaCommentAction const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate); - const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor())); - SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rHairlinePrimitive.getB2DPolygon(), &aLineColor, 0, 0, 0, 0); + const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon(); - impStartSvtGraphicStroke(pSvtGraphicStroke); - RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false); - impEndSvtGraphicStroke(pSvtGraphicStroke); + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) + { + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. If there are more, split the polygon in half and call recursively + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); + const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor()); + const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor()); + + processBasePrimitive2D(aPLeft); + processBasePrimitive2D(aPRight); + } + else + { + // direct draw of hairline; use default processing + // support SvtGraphicStroke MetaCommentAction + const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor())); + SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( + rHairlinePrimitive.getB2DPolygon(), + &aLineColor, + 0, 0, 0, 0); + + impStartSvtGraphicStroke(pSvtGraphicStroke); + RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false); + impEndSvtGraphicStroke(pSvtGraphicStroke); + } break; } case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D : { - // support SvtGraphicStroke MetaCommentAction const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); - SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rStrokePrimitive.getB2DPolygon(), 0, &rStrokePrimitive.getLineAttribute(), - &rStrokePrimitive.getStrokeAttribute(), 0, 0); + const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon(); - if(true) + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) { + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. If there are more, split the polygon in half and call recursively + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); + const primitive2d::PolygonStrokePrimitive2D aPLeft( + aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); + const primitive2d::PolygonStrokePrimitive2D aPRight( + aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); + + processBasePrimitive2D(aPLeft); + processBasePrimitive2D(aPRight); + } + else + { + // support SvtGraphicStroke MetaCommentAction + SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( + rBasePolygon, 0, + &rStrokePrimitive.getLineAttribute(), + &rStrokePrimitive.getStrokeAttribute(), + 0, 0); + impStartSvtGraphicStroke(pSvtGraphicStroke); const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute(); @@ -1013,12 +1193,12 @@ namespace drawinglayer if(0.0 == rStroke.getFullDotDashLen()) { - aHairLinePolyPolygon.append(rStrokePrimitive.getB2DPolygon()); + aHairLinePolyPolygon.append(rBasePolygon); } else { basegfx::tools::applyLineDashing( - rStrokePrimitive.getB2DPolygon(), rStroke.getDotDashArray(), + rBasePolygon, rStroke.getDotDashArray(), &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen()); } @@ -1026,7 +1206,12 @@ namespace drawinglayer mpOutputDevice->SetLineColor(Color(aHairlineColor)); mpOutputDevice->SetFillColor(); aHairLinePolyPolygon.transform(maCurrentTransformation); - LineInfo aLineInfo(LINE_SOLID, basegfx::fround(rLine.getWidth())); + + // #i113922# LineWidth needs to be transformed, too + const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0)); + const double fDiscreteLineWidth(aDiscreteUnit.getLength()); + + LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth)); aLineInfo.SetLineJoin(rLine.getLineJoin()); for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++) @@ -1048,93 +1233,52 @@ namespace drawinglayer impEndSvtGraphicStroke(pSvtGraphicStroke); } - else - { - // Adapt OutDev's DrawMode if special ones were used - const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode()); - adaptLineToFillDrawMode(); - - impStartSvtGraphicStroke(pSvtGraphicStroke); - - // #i101491# - // Change default of fat line generation for MetaFiles: Create MetaPolyLineAction - // instead of decomposing all geometries when the polygon has more than given amount of - // points; else the decomposition will get too expensive quiclky. OTOH - // the decomposition provides the better quality e.g. taking edge roundings - // into account which will NOT be taken into account with LineInfo-based actions - const sal_uInt32 nSubPolygonCount(rStrokePrimitive.getB2DPolygon().count()); - bool bDone(0 == nSubPolygonCount); - - if(!bDone && nSubPolygonCount > 1000) - { - // create MetaPolyLineActions, but without LINE_DASH - const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute(); - - if(basegfx::fTools::more(rLine.getWidth(), 0.0)) - { - const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute(); - basegfx::B2DPolyPolygon aHairLinePolyPolygon; - - if(0.0 == rStroke.getFullDotDashLen()) - { - aHairLinePolyPolygon.append(rStrokePrimitive.getB2DPolygon()); - } - else - { - basegfx::tools::applyLineDashing( - rStrokePrimitive.getB2DPolygon(), rStroke.getDotDashArray(), - &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen()); - } - - const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor())); - mpOutputDevice->SetLineColor(Color(aHairlineColor)); - mpOutputDevice->SetFillColor(); - - aHairLinePolyPolygon.transform(maCurrentTransformation); - - const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(rLine.getWidth())); - - for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++) - { - const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a)); - - if(aCandidate.count() > 1) - { - const Polygon aToolsPolygon(aCandidate); - - mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo)); - } - } - - bDone = true; - } - } - - if(!bDone) - { - // use decomposition (creates line geometry as filled polygon - // geometry) - process(rCandidate.get2DDecomposition(getViewInformation2D())); - } - - impEndSvtGraphicStroke(pSvtGraphicStroke); - - // restore DrawMode - mpOutputDevice->SetDrawMode(nOriginalDrawMode); - } break; } case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D : { - // support SvtGraphicStroke MetaCommentAction const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate); - SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(rStrokeArrowPrimitive.getB2DPolygon(), 0, &rStrokeArrowPrimitive.getLineAttribute(), - &rStrokeArrowPrimitive.getStrokeAttribute(), &rStrokeArrowPrimitive.getStart(), &rStrokeArrowPrimitive.getEnd()); + const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon(); + + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) + { + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. If there are more, split the polygon in half and call recursively + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); + const attribute::LineStartEndAttribute aEmpty; + const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft( + aLeft, + rStrokeArrowPrimitive.getLineAttribute(), + rStrokeArrowPrimitive.getStrokeAttribute(), + rStrokeArrowPrimitive.getStart(), + aEmpty); + const primitive2d::PolygonStrokeArrowPrimitive2D aPRight( + aRight, + rStrokeArrowPrimitive.getLineAttribute(), + rStrokeArrowPrimitive.getStrokeAttribute(), + aEmpty, + rStrokeArrowPrimitive.getEnd()); + + processBasePrimitive2D(aPLeft); + processBasePrimitive2D(aPRight); + } + else + { + // support SvtGraphicStroke MetaCommentAction + SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( + rBasePolygon, 0, + &rStrokeArrowPrimitive.getLineAttribute(), + &rStrokeArrowPrimitive.getStrokeAttribute(), + &rStrokeArrowPrimitive.getStart(), + &rStrokeArrowPrimitive.getEnd()); + + impStartSvtGraphicStroke(pSvtGraphicStroke); + process(rCandidate.get2DDecomposition(getViewInformation2D())); + impEndSvtGraphicStroke(pSvtGraphicStroke); + } - impStartSvtGraphicStroke(pSvtGraphicStroke); - process(rCandidate.get2DDecomposition(getViewInformation2D())); - impEndSvtGraphicStroke(pSvtGraphicStroke); break; } case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : @@ -1146,16 +1290,26 @@ namespace drawinglayer case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D : { // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END - SvtGraphicFill* pSvtGraphicFill = 0; + const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); - if(!mnSvtGraphicFillCount) + if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) { - const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); - aLocalPolyPolygon.transform(maCurrentTransformation); + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. If there are more use the splitted polygon and call recursively + const primitive2d::PolyPolygonBitmapPrimitive2D aSplitted( + aLocalPolyPolygon, + rBitmapCandidate.getFillBitmap()); - if(aLocalPolyPolygon.count()) + processBasePrimitive2D(aSplitted); + } + else + { + SvtGraphicFill* pSvtGraphicFill = 0; + + if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) { + aLocalPolyPolygon.transform(maCurrentTransformation); // calculate transformation. Get real object size, all values in FillBitmapAttribute // are relative to the unified object const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap(); @@ -1212,78 +1366,81 @@ namespace drawinglayer 0, aFillGraphic); } - } - // Do use decomposition; encapsulate with SvtGraphicFill - impStartSvtGraphicFill(pSvtGraphicFill); - process(rCandidate.get2DDecomposition(getViewInformation2D())); - impEndSvtGraphicFill(pSvtGraphicFill); + // Do use decomposition; encapsulate with SvtGraphicFill + impStartSvtGraphicFill(pSvtGraphicFill); + process(rCandidate.get2DDecomposition(getViewInformation2D())); + impEndSvtGraphicFill(pSvtGraphicFill); + } break; } case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D : { // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END - SvtGraphicFill* pSvtGraphicFill = 0; const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate); - const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + + SvtGraphicFill* pSvtGraphicFill = 0; + const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); aLocalPolyPolygon.transform(maCurrentTransformation); - if(!mnSvtGraphicFillCount) + if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) { - if(aLocalPolyPolygon.count()) - { - // re-create a VCL hatch as base data - SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); + // re-create a VCL hatch as base data + SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); - switch(rFillHatchAttribute.getStyle()) + switch(rFillHatchAttribute.getStyle()) + { + default: // attribute::HATCHSTYLE_SINGLE : { - default: // attribute::HATCHSTYLE_SINGLE : - { - eHatch = SvtGraphicFill::hatchSingle; - break; - } - case attribute::HATCHSTYLE_DOUBLE : - { - eHatch = SvtGraphicFill::hatchDouble; - break; - } - case attribute::HATCHSTYLE_TRIPLE : - { - eHatch = SvtGraphicFill::hatchTriple; - break; - } + eHatch = SvtGraphicFill::hatchSingle; + break; + } + case attribute::HATCHSTYLE_DOUBLE : + { + eHatch = SvtGraphicFill::hatchDouble; + break; } + case attribute::HATCHSTYLE_TRIPLE : + { + eHatch = SvtGraphicFill::hatchTriple; + break; + } + } - SvtGraphicFill::Transform aTransform; + SvtGraphicFill::Transform aTransform; - // scale - aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); - aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); + // scale + aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); + aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); - // rotate (was never correct in impgrfll anyways, use correct angle now) - aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); - aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); - aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); - aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); + // rotate (was never correct in impgrfll anyways, use correct angle now) + aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); + aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); + aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); + aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); - pSvtGraphicFill = new SvtGraphicFill( - PolyPolygon(aLocalPolyPolygon), - Color(), - 0.0, - SvtGraphicFill::fillEvenOdd, - SvtGraphicFill::fillHatch, - aTransform, - false, - eHatch, - Color(rFillHatchAttribute.getColor()), - SvtGraphicFill::gradientLinear, - Color(), - Color(), - 0, - Graphic()); - } + pSvtGraphicFill = new SvtGraphicFill( + PolyPolygon(aLocalPolyPolygon), + Color(), + 0.0, + SvtGraphicFill::fillEvenOdd, + SvtGraphicFill::fillHatch, + aTransform, + false, + eHatch, + Color(rFillHatchAttribute.getColor()), + SvtGraphicFill::gradientLinear, + Color(), + Color(), + 0, + Graphic()); } // Do use decomposition; encapsulate with SvtGraphicFill @@ -1304,18 +1461,24 @@ namespace drawinglayer basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800))); impEndSvtGraphicFill(pSvtGraphicFill); + break; } case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D : { const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END // it is safest to use the VCL OutputDevice::DrawGradient method which creates those. // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon Gradient aVCLGradient; impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); aLocalPolyPolygon.transform(maCurrentTransformation); // #i82145# ATM VCL printing of gradients using curved shapes does not work, @@ -1373,13 +1536,20 @@ namespace drawinglayer // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate)); + break; } case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : { const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate)); - const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); aLocalPolyPolygon.transform(maCurrentTransformation); // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support @@ -1547,6 +1717,13 @@ namespace drawinglayer // single transparent PolyPolygon identified, use directly const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + + // now transform aLocalPolyPolygon.transform(maCurrentTransformation); // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support @@ -1796,7 +1973,7 @@ namespace drawinglayer } break; } - case PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D : + case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D : { // structured tag primitive const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate); |