diff options
author | Armin Le Grand <alg@apache.org> | 2014-03-23 17:33:53 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2014-03-23 17:33:53 +0000 |
commit | 6ca3a9faca825e0e3c44de9f47f4c684d31f86b1 (patch) | |
tree | 429288b4ad763b7b12ab5712f88f0dd4e4ebb9b6 /drawinglayer | |
parent | 812e2a8bf64274e47db572b8ca592f49b1263ad7 (diff) |
aw080 resync to trunk, win build working, no checks yet
Diffstat (limited to 'drawinglayer')
19 files changed, 787 insertions, 347 deletions
diff --git a/drawinglayer/inc/drawinglayer/attribute/sdrfillgraphicattribute.hxx b/drawinglayer/inc/drawinglayer/attribute/sdrfillgraphicattribute.hxx index 3a4acac21a80..095d407010f3 100755 --- a/drawinglayer/inc/drawinglayer/attribute/sdrfillgraphicattribute.hxx +++ b/drawinglayer/inc/drawinglayer/attribute/sdrfillgraphicattribute.hxx @@ -56,6 +56,7 @@ namespace drawinglayer /// constructors/assignmentoperator/destructor SdrFillGraphicAttribute( const Graphic& rFillGraphic, + const basegfx::B2DVector& rGraphicLogicSize, const basegfx::B2DVector& rSize, const basegfx::B2DVector& rOffset, const basegfx::B2DVector& rOffsetPosition, @@ -76,6 +77,7 @@ namespace drawinglayer // data read access const Graphic& getFillGraphic() const; + const basegfx::B2DVector& getGraphicLogicSize() const; const basegfx::B2DVector& getSize() const; const basegfx::B2DVector& getOffset() const; const basegfx::B2DVector& getOffsetPosition() const; diff --git a/drawinglayer/inc/drawinglayer/primitive2d/fillgradientprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/fillgradientprimitive2d.hxx index 9bd066e56e7f..d8c6388dd034 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/fillgradientprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/fillgradientprimitive2d.hxx @@ -58,8 +58,12 @@ namespace drawinglayer class DRAWINGLAYER_DLLPUBLIC FillGradientPrimitive2D : public BufferedDecompositionPrimitive2D { private: - /// the geometric definition - basegfx::B2DRange maObjectRange; + /// the geometrically visible area + basegfx::B2DRange maOutputRange; + + /// the area the gradient definition is based on + /// in the simplest case identical to OutputRange + basegfx::B2DRange maDefinitionRange; /// the gradient definition attribute::FillGradientAttribute maFillGradient; @@ -67,14 +71,14 @@ namespace drawinglayer /// local helpers void generateMatricesAndColors( std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) const; + basegfx::BColor& rOuterColor) const; Primitive2DSequence createOverlappingFill( const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - const basegfx::BColor& rOutmostColor, + const basegfx::BColor& rOuterColor, const basegfx::B2DPolygon& rUnitPolygon) const; Primitive2DSequence createNonOverlappingFill( const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - const basegfx::BColor& rOutmostColor, + const basegfx::BColor& rOuterColor, const basegfx::B2DPolygon& rUnitPolygon) const; protected: @@ -85,13 +89,18 @@ namespace drawinglayer virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; public: - /// constructor + /// constructors. The one without definition range will use output range as definition range + FillGradientPrimitive2D( + const basegfx::B2DRange& rOutputRange, + const attribute::FillGradientAttribute& rFillGradient); FillGradientPrimitive2D( - const basegfx::B2DRange& rObjectRange, + const basegfx::B2DRange& rOutputRange, + const basegfx::B2DRange& rDefinitionRange, const attribute::FillGradientAttribute& rFillGradient); /// data read access - const basegfx::B2DRange& getObjectRange() const { return maObjectRange; } + const basegfx::B2DRange& getOutputRange() const { return maOutputRange; } + const basegfx::B2DRange& getDefinitionRange() const { return maDefinitionRange; } const attribute::FillGradientAttribute& getFillGradient() const { return maFillGradient; } /// get range diff --git a/drawinglayer/inc/drawinglayer/primitive2d/fillhatchprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/fillhatchprimitive2d.hxx index 70e5d707691d..d8409b96c524 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/fillhatchprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/fillhatchprimitive2d.hxx @@ -53,8 +53,12 @@ namespace drawinglayer class DRAWINGLAYER_DLLPUBLIC FillHatchPrimitive2D : public DiscreteMetricDependentPrimitive2D { private: - /// the geometric definition - basegfx::B2DRange maObjectRange; + /// the geometrically visible area + basegfx::B2DRange maOutputRange; + + /// the area the gradient definition is based on + /// in the simplest case identical to OutputRange + basegfx::B2DRange maDefinitionRange; /// the hatch definition attribute::FillHatchAttribute maFillHatch; @@ -67,14 +71,20 @@ namespace drawinglayer virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; public: - /// constructor + /// constructors. The one without definition range will use output range as definition range + FillHatchPrimitive2D( + const basegfx::B2DRange& rOutputRange, + const basegfx::BColor& rBColor, + const attribute::FillHatchAttribute& rFillHatch); FillHatchPrimitive2D( - const basegfx::B2DRange& rObjectRange, + const basegfx::B2DRange& rOutputRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rBColor, const attribute::FillHatchAttribute& rFillHatch); /// data read access - const basegfx::B2DRange& getObjectRange() const { return maObjectRange; } + const basegfx::B2DRange& getOutputRange() const { return maOutputRange; } + const basegfx::B2DRange& getDefinitionRange() const { return maDefinitionRange; } const attribute::FillHatchAttribute& getFillHatch() const { return maFillHatch; } const basegfx::BColor& getBColor() const { return maBColor; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx index 18e34bdc4156..10d9685be373 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx @@ -47,7 +47,7 @@ namespace drawinglayer This primitive defines a multi-PolygonHairlinePrimitive2D and is just for convenience. The definition is not different from the single - defined PolygonHairlinePrimitive2Ds. + defined PolygonHairlinePrimitive2Ds. */ class DRAWINGLAYER_DLLPUBLIC PolyPolygonHairlinePrimitive2D : public BufferedDecompositionPrimitive2D { @@ -300,6 +300,9 @@ namespace drawinglayer /// the PolyPolygon geometry basegfx::B2DPolyPolygon maPolyPolygon; + /// the definition range + basegfx::B2DRange maDefinitionRange; + /// the gradient definition attribute::FillGradientAttribute maFillGradient; @@ -308,13 +311,18 @@ namespace drawinglayer virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; public: - /// constructor + /// constructors. The one without definition range will use output range as definition range + PolyPolygonGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::FillGradientAttribute& rFillGradient); PolyPolygonGradientPrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, const attribute::FillGradientAttribute& rFillGradient); /// data read access const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DRange& getDefinitionRange() const { return maDefinitionRange; } const attribute::FillGradientAttribute& getFillGradient() const { return maFillGradient; } /// provide unique ID @@ -342,6 +350,9 @@ namespace drawinglayer /// the PolyPolygon geometry basegfx::B2DPolyPolygon maPolyPolygon; + /// the definition range + basegfx::B2DRange maDefinitionRange; + /// the hatch background color (if used) basegfx::BColor maBackgroundColor; @@ -353,14 +364,20 @@ namespace drawinglayer virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; public: - /// constructor + /// constructors. The one without definition range will use output range as definition range + PolyPolygonHatchPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rBackgroundColor, + const attribute::FillHatchAttribute& rFillHatch); PolyPolygonHatchPrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rBackgroundColor, const attribute::FillHatchAttribute& rFillHatch); /// data read access const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DRange& getDefinitionRange() const { return maDefinitionRange; } const basegfx::BColor& getBackgroundColor() const { return maBackgroundColor; } const attribute::FillHatchAttribute& getFillHatch() const { return maFillHatch; } @@ -389,6 +406,9 @@ namespace drawinglayer /// the PolyPolygon geometry basegfx::B2DPolyPolygon maPolyPolygon; + /// the definition range + basegfx::B2DRange maDefinitionRange; + /// the bitmap fill definition (may include tiling) attribute::FillGraphicAttribute maFillGraphic; @@ -397,13 +417,18 @@ namespace drawinglayer virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; public: - /// constructor + /// constructors. The one without definition range will use output range as definition range + PolyPolygonGraphicPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const attribute::FillGraphicAttribute& rFillGraphic); PolyPolygonGraphicPrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, const attribute::FillGraphicAttribute& rFillGraphic); /// data read access const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::B2DRange& getDefinitionRange() const { return maDefinitionRange; } const attribute::FillGraphicAttribute& getFillGraphic() const { return maFillGraphic; } /// provide unique ID diff --git a/drawinglayer/inc/drawinglayer/texture/texture.hxx b/drawinglayer/inc/drawinglayer/texture/texture.hxx index aa62d1eb3d58..ce1e97d702a9 100644 --- a/drawinglayer/inc/drawinglayer/texture/texture.hxx +++ b/drawinglayer/inc/drawinglayer/texture/texture.hxx @@ -79,14 +79,14 @@ namespace drawinglayer { protected: basegfx::ODFGradientInfo maGradientInfo; - basegfx::B2DRange maTargetRange; + basegfx::B2DRange maDefinitionRange; basegfx::BColor maStart; basegfx::BColor maEnd; double mfBorder; public: GeoTexSvxGradient( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -99,7 +99,7 @@ namespace drawinglayer // virtual base methods virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) = 0; + basegfx::BColor& rOuterColor) = 0; // data access const basegfx::BColor& getStart() const { return maStart; } @@ -116,9 +116,15 @@ namespace drawinglayer { class DRAWINGLAYER_DLLPUBLIC GeoTexSvxGradientLinear : public GeoTexSvxGradient { + protected: + double mfUnitMinX; + double mfUnitWidth; + double mfUnitMaxY; + public: GeoTexSvxGradientLinear( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -128,7 +134,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -142,9 +148,14 @@ namespace drawinglayer { class DRAWINGLAYER_DLLPUBLIC GeoTexSvxGradientAxial : public GeoTexSvxGradient { + protected: + double mfUnitMinX; + double mfUnitWidth; + public: GeoTexSvxGradientAxial( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -154,7 +165,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -170,7 +181,7 @@ namespace drawinglayer { public: GeoTexSvxGradientRadial( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -181,7 +192,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -197,7 +208,7 @@ namespace drawinglayer { public: GeoTexSvxGradientElliptical( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -209,7 +220,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -225,7 +236,7 @@ namespace drawinglayer { public: GeoTexSvxGradientSquare( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -237,7 +248,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -253,7 +264,7 @@ namespace drawinglayer { public: GeoTexSvxGradientRect( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -265,7 +276,7 @@ namespace drawinglayer virtual void appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor); + basegfx::BColor& rOuterColor); virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; }; } // end of namespace texture @@ -280,15 +291,20 @@ namespace drawinglayer class DRAWINGLAYER_DLLPUBLIC GeoTexSvxHatch : public GeoTexSvx { protected: + basegfx::B2DRange maOutputRange; basegfx::B2DHomMatrix maTextureTransform; basegfx::B2DHomMatrix maBackTextureTransform; double mfDistance; double mfAngle; sal_uInt32 mnSteps; + /// bitfield + bool mbDefinitionRangeEqualsOutputRange : 1; + public: GeoTexSvxHatch( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, double fDistance, double fAngle); virtual ~GeoTexSvxHatch(); @@ -296,7 +312,7 @@ namespace drawinglayer // compare operator virtual bool operator==(const GeoTexSvx& rGeoTexSvx) const; - virtual void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices); + void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices); double getDistanceToHatch(const basegfx::B2DPoint& rUV) const; const basegfx::B2DHomMatrix& getBackTextureTransform() const; }; @@ -335,7 +351,7 @@ namespace drawinglayer // compare operator virtual bool operator==(const GeoTexSvx& rGeoTexSvx) const; - virtual void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices); + void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices); }; } // end of namespace texture } // end of namespace drawinglayer diff --git a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx index 77fa080158ee..174b9484c2da 100755 --- a/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx +++ b/drawinglayer/source/attribute/sdrfillgraphicattribute.cxx @@ -42,6 +42,7 @@ namespace drawinglayer // data definitions Graphic maFillGraphic; + basegfx::B2DVector maGraphicLogicSize; basegfx::B2DVector maSize; basegfx::B2DVector maOffset; basegfx::B2DVector maOffsetPosition; @@ -54,6 +55,7 @@ namespace drawinglayer ImpSdrFillGraphicAttribute( const Graphic& rFillGraphic, + const basegfx::B2DVector& rGraphicLogicSize, const basegfx::B2DVector& rSize, const basegfx::B2DVector& rOffset, const basegfx::B2DVector& rOffsetPosition, @@ -63,6 +65,7 @@ namespace drawinglayer bool bLogSize) : mnRefCount(0), maFillGraphic(rFillGraphic), + maGraphicLogicSize(rGraphicLogicSize), maSize(rSize), maOffset(rOffset), maOffsetPosition(rOffsetPosition), @@ -75,6 +78,7 @@ namespace drawinglayer // data read access const Graphic& getFillGraphic() const { return maFillGraphic; } + const basegfx::B2DVector& getGraphicLogicSize() const { return maGraphicLogicSize; } const basegfx::B2DVector& getSize() const { return maSize; } const basegfx::B2DVector& getOffset() const { return maOffset; } const basegfx::B2DVector& getOffsetPosition() const { return maOffsetPosition; } @@ -86,6 +90,7 @@ namespace drawinglayer bool operator==(const ImpSdrFillGraphicAttribute& rCandidate) const { return (getFillGraphic() == rCandidate.getFillGraphic() + && getGraphicLogicSize() == rCandidate.getGraphicLogicSize() && getSize() == rCandidate.getSize() && getOffset() == rCandidate.getOffset() && getOffsetPosition() == rCandidate.getOffsetPosition() @@ -107,6 +112,7 @@ namespace drawinglayer basegfx::B2DVector(), basegfx::B2DVector(), basegfx::B2DVector(), + basegfx::B2DVector(), false, false, false); @@ -121,6 +127,7 @@ namespace drawinglayer SdrFillGraphicAttribute::SdrFillGraphicAttribute( const Graphic& rFillGraphic, + const basegfx::B2DVector& rGraphicLogicSize, const basegfx::B2DVector& rSize, const basegfx::B2DVector& rOffset, const basegfx::B2DVector& rOffsetPosition, @@ -131,6 +138,7 @@ namespace drawinglayer : mpSdrFillGraphicAttribute( new ImpSdrFillGraphicAttribute( rFillGraphic, + rGraphicLogicSize, rSize, rOffset, rOffsetPosition, @@ -210,6 +218,11 @@ namespace drawinglayer return mpSdrFillGraphicAttribute->getFillGraphic(); } + const basegfx::B2DVector& SdrFillGraphicAttribute::getGraphicLogicSize() const + { + return mpSdrFillGraphicAttribute->getGraphicLogicSize(); + } + const basegfx::B2DVector& SdrFillGraphicAttribute::getSize() const { return mpSdrFillGraphicAttribute->getSize(); @@ -249,13 +262,12 @@ namespace drawinglayer { // get logical size of bitmap (before expanding eventually) Graphic aGraphic(getFillGraphic()); - const basegfx::B2DVector aLogicalSize(aGraphic.GetPrefSize().getWidth(), aGraphic.GetPrefSize().getHeight()); - // init values with defaults + // init values with defaults for stretched basegfx::B2DPoint aBitmapSize(1.0, 1.0); basegfx::B2DVector aBitmapTopLeft(0.0, 0.0); - // are changes needed? + //UUUU are changes needed? When streched we are already done, all other values will have no influence if(getTiling() || !getStretch()) { // init values with range sizes @@ -277,7 +289,9 @@ namespace drawinglayer } else { - aBitmapSize.setX(aLogicalSize.getX()); + // #124002# use GraphicLogicSize directly, do not try to use GetPrefSize + // of the graphic, that may not be adapted to the MapMode of the target + aBitmapSize.setX(getGraphicLogicSize().getX()); } if(0.0 != getSize().getY()) @@ -293,37 +307,38 @@ namespace drawinglayer } else { - aBitmapSize.setY(aLogicalSize.getY()); + // #124002# use GraphicLogicSize directly, do not try to use GetPrefSize + // of the graphic, that may not be adapted to the MapMode of the target + aBitmapSize.setY(getGraphicLogicSize().getY()); } - // get values, force to centered if necessary - const basegfx::B2DVector aRectPoint(getTiling() ? getRectPoint() : basegfx::B2DVector(0.0, 0.0)); - // position changes X - if(0.0 == aRectPoint.getX()) + if(0.0 == getRectPoint().getX()) { aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5); } - else if(1.0 == aRectPoint.getX()) + else if(1.0 == getRectPoint().getX()) { aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX()); } + // offset positions are only meaningful when tiled if(getTiling() && 0.0 != getOffsetPosition().getX()) { aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (getOffsetPosition().getX() * 0.01))); } // position changes Y - if(0.0 == aRectPoint.getY()) + if(0.0 == getRectPoint().getY()) { aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5); } - else if(1.0 == aRectPoint.getY()) + else if(1.0 == getRectPoint().getY()) { aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY()); } + // offset positions are only meaningful when tiled if(getTiling() && 0.0 != getOffsetPosition().getY()) { aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (getOffsetPosition().getY() * 0.01))); diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx index c77693ee449c..2d6d4c4fdbaf 100644 --- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx @@ -63,112 +63,78 @@ namespace drawinglayer if(getChildren().hasElements()) { - // decompose to have current translate and scale - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - - getTransformation().decompose(aScale, aTranslate, fRotate, fShearX); - - // detect 180 degree rotation, this is the same as mirrored in X and Y, - // thus change to mirroring. Prefer mirroring here. Use the equal call - // with getSmallValue here, the original which uses rtl::math::approxEqual - // is too correct here. Maybe this changes with enhanced precision in aw080 - // to the better so that this can be reduced to the more precise call again - if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001)) - { - aScale.setX(aScale.getX() * -1.0); - aScale.setY(aScale.getY() * -1.0); - fRotate = 0.0; - } - - // create target translate and scale - const bool bMirroredX(aScale.getX() < 0.0); - const bool bMirroredY(aScale.getY() < 0.0); - basegfx::B2DVector aTargetScale(aScale); - basegfx::B2DVector aTargetTranslate(aTranslate); - - if(bMirroredX) - { - aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight()); - aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight()); - } - else - { - aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft()); - aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft()); - } - - if(bMirroredY) - { - aTargetTranslate.setY(aTargetTranslate.getY() + getCropBottom()); - aTargetScale.setY(aTargetScale.getY() - getCropTop() - getCropBottom()); - } - else - { - aTargetTranslate.setY(aTargetTranslate.getY() - getCropTop()); - aTargetScale.setY(aTargetScale.getY() + getCropBottom() + getCropTop()); - } - - // create ranges to make comparisons - const basegfx::B2DRange aCurrent( - aTranslate.getX(), aTranslate.getY(), - aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); - const basegfx::B2DRange aCropped( - aTargetTranslate.getX(), aTargetTranslate.getY(), - aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); + // get original object scale in unit coordinates (no mirroring) + const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0))); - if(aCropped.isEmpty()) + // we handle cropping, so when no width or no height, content will be empty, + // so only do something when we have a width and a height + if(!aObjectScale.equalZero()) { - // nothing to return since cropped content is completely empty - } - else if(aCurrent.equal(aCropped)) - { - // no crop, just use content - xRetval = getChildren(); - } - else - { - // build new combined content transformation - basegfx::B2DHomMatrix aNewObjectTransform(getTransformation()); - - // remove content transform by inverting - aNewObjectTransform.invert(); - - // add target values and original shear/rotate - aNewObjectTransform = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( - aTargetScale.getX(), - aTargetScale.getY(), - fShearX, - fRotate, - aTargetTranslate.getX(), - aTargetTranslate.getY()) - * aNewObjectTransform; - - // prepare TransformPrimitive2D with xPrimitive - const Primitive2DReference xTransformPrimitive( - new TransformPrimitive2D( - aNewObjectTransform, - getChildren())); - - if(aCurrent.isInside(aCropped)) - { - // crop just shrunk so that its inside content, - // no need to use a mask since not really cropped. - xRetval = Primitive2DSequence(&xTransformPrimitive, 1); - } - else + // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus + // are relative only to object scale + const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX())); + const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY())); + const double fLeft(getCropLeft() * fBackScaleX); + const double fTop(getCropTop() * fBackScaleY); + const double fRight(getCropRight() * fBackScaleX); + const double fBottom(getCropBottom() * fBackScaleY); + + // calc new unit range for comparisons; the original range is the unit range + const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + const basegfx::B2DRange aNewRange( + -fLeft, + -fTop, + 1.0 + fRight, + 1.0 + fBottom); + + // if we have no overlap the crop has removed everything, so we do only + // have to create content if this is not the case + if(aNewRange.overlaps(aUnitRange)) { - // mask with original object's bounds - basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); - aMaskPolyPolygon.transform(getTransformation()); - - // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector - const Primitive2DReference xMask( - new MaskPrimitive2D( - aMaskPolyPolygon, - Primitive2DSequence(&xTransformPrimitive, 1))); - - xRetval = Primitive2DSequence(&xMask, 1); + // create new transform; first take out old transform to get + // to unit coordinates by inverting. Inverting should be flawless + // since we already cheched that object size is not zero in X or Y + basegfx::B2DHomMatrix aNewTransform(getTransformation()); + + aNewTransform.invert(); + + // apply crop enlargement in unit coordinates + aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix( + aNewRange.getRange(), + aNewRange.getMinimum()) * aNewTransform; + + // apply original transformation. Since we have manipulated the crop + // in unit coordinates we do not need to care about mirroring or + // a corrected point for eventual shear or rotation, this all comes for + // free + aNewTransform = getTransformation() * aNewTransform; + + // prepare TransformPrimitive2D with xPrimitive + const Primitive2DReference xTransformPrimitive( + new TransformPrimitive2D( + aNewTransform, + getChildren())); + + if(aUnitRange.isInside(aNewRange)) + { + // the new range is completely inside the old range (unit range), + // so no masking is needed + xRetval = Primitive2DSequence(&xTransformPrimitive, 1); + } + else + { + // mask with original object's bounds + basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); + aMaskPolyPolygon.transform(getTransformation()); + + // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector + const Primitive2DReference xMask( + new MaskPrimitive2D( + aMaskPolyPolygon, + Primitive2DSequence(&xTransformPrimitive, 1))); + + xRetval = Primitive2DSequence(&xMask, 1); + } } } } diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx index 018fcd962bc3..baa28afeb354 100644 --- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx @@ -44,7 +44,7 @@ namespace drawinglayer { void FillGradientPrimitive2D::generateMatricesAndColors( std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) const + basegfx::BColor& rOuterColor) const { rEntries.clear(); @@ -73,38 +73,83 @@ namespace drawinglayer { case attribute::GRADIENTSTYLE_LINEAR: { - texture::GeoTexSvxGradientLinear aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getAngle()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientLinear aGradient( + getDefinitionRange(), + getOutputRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getAngle()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } case attribute::GRADIENTSTYLE_AXIAL: { - texture::GeoTexSvxGradientAxial aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getAngle()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientAxial aGradient( + getDefinitionRange(), + getOutputRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getAngle()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } case attribute::GRADIENTSTYLE_RADIAL: { - texture::GeoTexSvxGradientRadial aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getOffsetX(), getFillGradient().getOffsetY()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientRadial aGradient( + getDefinitionRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getOffsetX(), + getFillGradient().getOffsetY()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } case attribute::GRADIENTSTYLE_ELLIPTICAL: { - texture::GeoTexSvxGradientElliptical aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getOffsetX(), getFillGradient().getOffsetY(), getFillGradient().getAngle()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientElliptical aGradient( + getDefinitionRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getOffsetX(), + getFillGradient().getOffsetY(), + getFillGradient().getAngle()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } case attribute::GRADIENTSTYLE_SQUARE: { - texture::GeoTexSvxGradientSquare aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getOffsetX(), getFillGradient().getOffsetY(), getFillGradient().getAngle()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientSquare aGradient( + getDefinitionRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getOffsetX(), + getFillGradient().getOffsetY(), + getFillGradient().getAngle()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } case attribute::GRADIENTSTYLE_RECT: { - texture::GeoTexSvxGradientRect aGradient(getObjectRange(), aStart, aEnd, nSteps, getFillGradient().getBorder(), getFillGradient().getOffsetX(), getFillGradient().getOffsetY(), getFillGradient().getAngle()); - aGradient.appendTransformationsAndColors(rEntries, rOutmostColor); + texture::GeoTexSvxGradientRect aGradient( + getDefinitionRange(), + aStart, + aEnd, + nSteps, + getFillGradient().getBorder(), + getFillGradient().getOffsetX(), + getFillGradient().getOffsetY(), + getFillGradient().getAngle()); + aGradient.appendTransformationsAndColors(rEntries, rOuterColor); break; } } @@ -112,7 +157,7 @@ namespace drawinglayer Primitive2DSequence FillGradientPrimitive2D::createOverlappingFill( const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - const basegfx::BColor& rOutmostColor, + const basegfx::BColor& rOuterColor, const basegfx::B2DPolygon& rUnitPolygon) const { // prepare return value @@ -121,8 +166,9 @@ namespace drawinglayer // create solid fill with outmost color aRetval[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(getObjectRange())), - rOutmostColor)); + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(getOutputRange())), + rOuterColor)); // create solid fill steps for(sal_uInt32 a(0); a < rEntries.size(); a++) @@ -144,14 +190,14 @@ namespace drawinglayer Primitive2DSequence FillGradientPrimitive2D::createNonOverlappingFill( const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries, - const basegfx::BColor& rOutmostColor, + const basegfx::BColor& rOuterColor, const basegfx::B2DPolygon& rUnitPolygon) const { // prepare return value Primitive2DSequence aRetval(rEntries.size() + 1); - // get outmost range from object - basegfx::B2DRange aOutmostRange(getObjectRange()); + // get outmost viusible range from object + basegfx::B2DRange aOutmostRange(getOutputRange()); basegfx::B2DPolyPolygon aCombinedPolyPoly; if(rEntries.size()) @@ -169,7 +215,7 @@ namespace drawinglayer aRetval[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D( aCombinedPolyPoly, - rOutmostColor)); + rOuterColor)); if(rEntries.size()) { @@ -227,17 +273,17 @@ namespace drawinglayer // get the transform matrices and colors (where colors // will have one more entry that matrices) std::vector< drawinglayer::texture::B2DHomMatrixAndBColor > aEntries; - basegfx::BColor aOutmostColor; + basegfx::BColor aOuterColor; - generateMatricesAndColors(aEntries, aOutmostColor); + generateMatricesAndColors(aEntries, aOuterColor); if(bOverlapping) { - return createOverlappingFill(aEntries, aOutmostColor, aUnitPolygon); + return createOverlappingFill(aEntries, aOuterColor, aUnitPolygon); } else { - return createNonOverlappingFill(aEntries, aOutmostColor, aUnitPolygon); + return createNonOverlappingFill(aEntries, aOuterColor, aUnitPolygon); } } @@ -263,18 +309,30 @@ namespace drawinglayer } FillGradientPrimitive2D::FillGradientPrimitive2D( - const basegfx::B2DRange& rObjectRange, + const basegfx::B2DRange& rOutputRange, const attribute::FillGradientAttribute& rFillGradient) : BufferedDecompositionPrimitive2D(), - maObjectRange(rObjectRange), + maOutputRange(rOutputRange), + maDefinitionRange(rOutputRange), + maFillGradient(rFillGradient) + { + } + + FillGradientPrimitive2D::FillGradientPrimitive2D( + const basegfx::B2DRange& rOutputRange, + const basegfx::B2DRange& rDefinitionRange, + const attribute::FillGradientAttribute& rFillGradient) + : BufferedDecompositionPrimitive2D(), + maOutputRange(rOutputRange), + maDefinitionRange(rDefinitionRange), maFillGradient(rFillGradient) { } basegfx::B2DRange FillGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { - // return ObjectRange - return getObjectRange(); + // return the geometrically visible area + return getOutputRange(); } // provide unique ID diff --git a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx index 5491bfe2107f..1be04fe08bca 100644 --- a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx @@ -74,7 +74,12 @@ namespace drawinglayer case attribute::HATCHSTYLE_TRIPLE: { // rotated 45 degrees - texture::GeoTexSvxHatch aHatch(getObjectRange(), fDistance, fAngle - F_PI4); + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle - F_PI4); + aHatch.appendTransformations(aMatrices); // fall-through by purpose @@ -82,7 +87,12 @@ namespace drawinglayer case attribute::HATCHSTYLE_DOUBLE: { // rotated 90 degrees - texture::GeoTexSvxHatch aHatch(getObjectRange(), fDistance, fAngle - F_PI2); + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle - F_PI2); + aHatch.appendTransformations(aMatrices); // fall-through by purpose @@ -90,7 +100,12 @@ namespace drawinglayer case attribute::HATCHSTYLE_SINGLE: { // angle as given - texture::GeoTexSvxHatch aHatch(getObjectRange(), fDistance, fAngle); + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle); + aHatch.appendTransformations(aMatrices); } } @@ -106,7 +121,7 @@ namespace drawinglayer const Primitive2DReference xRef( new PolyPolygonColorPrimitive2D( basegfx::B2DPolyPolygon( - basegfx::tools::createPolygonFromRect(getObjectRange())), getBColor())); + basegfx::tools::createPolygonFromRect(getOutputRange())), getBColor())); aRetval[0] = xRef; } @@ -132,11 +147,25 @@ namespace drawinglayer } FillHatchPrimitive2D::FillHatchPrimitive2D( - const basegfx::B2DRange& rObjectRange, + const basegfx::B2DRange& rOutputRange, + const basegfx::BColor& rBColor, + const attribute::FillHatchAttribute& rFillHatch) + : DiscreteMetricDependentPrimitive2D(), + maOutputRange(rOutputRange), + maDefinitionRange(rOutputRange), + maFillHatch(rFillHatch), + maBColor(rBColor) + { + } + + FillHatchPrimitive2D::FillHatchPrimitive2D( + const basegfx::B2DRange& rOutputRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rBColor, const attribute::FillHatchAttribute& rFillHatch) : DiscreteMetricDependentPrimitive2D(), - maObjectRange(rObjectRange), + maOutputRange(rOutputRange), + maDefinitionRange(rDefinitionRange), maFillHatch(rFillHatch), maBColor(rBColor) { @@ -144,8 +173,8 @@ namespace drawinglayer basegfx::B2DRange FillHatchPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { - // return ObjectRange - return getObjectRange(); + // return the geometrically visible area + return getOutputRange(); } Primitive2DSequence FillHatchPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx index 7bbe1804546a..58036702d76c 100755 --- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx @@ -759,9 +759,23 @@ namespace drawinglayer basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon()); aMaskPolygon.transform(rTransform); - aRetval[0] = new MaskPrimitive2D( + // #124073# the clde below was compiler-dependent. Normally, + // a compiler will + // - alloc mem + // - ececute the constructor + // - do the assignment + // but the mac compiler does alloc-assign-constructor, thus + // modifying aRetval[0] befure aRetval gets used in the + // constructor. This creates an endless loop in the primitive + // stack. Thus do it the safe way. + // + // aRetval[0] = new MaskPrimitive2D( + // basegfx::B2DPolyPolygon(aMaskPolygon), + // aRetval); + MaskPrimitive2D* pMaskPrimitive2D = new MaskPrimitive2D( basegfx::B2DPolyPolygon(aMaskPolygon), aRetval); + aRetval[0] = pMaskPrimitive2D; } #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE } diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index e5a7ca0fa9a5..d4a5344dc6b0 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -481,6 +481,8 @@ namespace drawinglayer const double fPolyLength(basegfx::tools::getLength(aLocalPolygon)); double fStart(0.0); double fEnd(0.0); + double fStartOverlap(0.0); + double fEndOverlap(0.0); if(!getStart().isDefault() && getStart().isActive()) { @@ -489,8 +491,9 @@ namespace drawinglayer aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(), fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart); - // create some overlapping - fStart *= 0.8; + // create some overlapping, compromise between straight and peaked markers + // best for marker width 0.3cm and marker line width 0.02cm + fStartOverlap = getStart().getWidth() / 15.0; } if(!getEnd().isDefault() && getEnd().isActive()) @@ -501,13 +504,13 @@ namespace drawinglayer fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd); // create some overlapping - fEnd *= 0.8; + fEndOverlap = getEnd().getWidth() / 15.0; } if(0.0 != fStart || 0.0 != fEnd) { // build new poly, consume something from old poly - aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength); + aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart-fStartOverlap, fPolyLength - fEnd + fEndOverlap, fPolyLength); } } diff --git a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx index 2ac65c0396a3..7dbbdd023258 100644 --- a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx @@ -180,7 +180,7 @@ namespace drawinglayer PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, - const attribute::LineAttribute& rLineAttribute, + const attribute::LineAttribute& rLineAttribute, const attribute::StrokeAttribute& rStrokeAttribute) : BufferedDecompositionPrimitive2D(), maPolyPolygon(rPolyPolygon), @@ -191,7 +191,7 @@ namespace drawinglayer PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, - const attribute::LineAttribute& rLineAttribute) + const attribute::LineAttribute& rLineAttribute) : BufferedDecompositionPrimitive2D(), maPolyPolygon(rPolyPolygon), maLineAttribute(rLineAttribute), @@ -262,7 +262,7 @@ namespace drawinglayer PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, - const attribute::LineAttribute& rLineAttribute, + const attribute::LineAttribute& rLineAttribute, const attribute::StrokeAttribute& rStrokeAttribute, const attribute::LineStartEndAttribute& rStart, const attribute::LineStartEndAttribute& rEnd) @@ -274,7 +274,7 @@ namespace drawinglayer PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D( const basegfx::B2DPolyPolygon& rPolyPolygon, - const attribute::LineAttribute& rLineAttribute, + const attribute::LineAttribute& rLineAttribute, const attribute::LineStartEndAttribute& rStart, const attribute::LineStartEndAttribute& rEnd) : PolyPolygonStrokePrimitive2D(rPolyPolygon, rLineAttribute), @@ -344,7 +344,10 @@ namespace drawinglayer { // create SubSequence with FillGradientPrimitive2D const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); - FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(aPolyPolygonRange, getFillGradient()); + FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D( + aPolyPolygonRange, + getDefinitionRange(), + getFillGradient()); const Primitive2DReference xSubRef(pNewGradient); const Primitive2DSequence aSubSequence(&xSubRef, 1L); @@ -365,6 +368,18 @@ namespace drawinglayer const attribute::FillGradientAttribute& rFillGradient) : BufferedDecompositionPrimitive2D(), maPolyPolygon(rPolyPolygon), + maDefinitionRange(rPolyPolygon.getB2DRange()), + maFillGradient(rFillGradient) + { + } + + PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, + const attribute::FillGradientAttribute& rFillGradient) + : BufferedDecompositionPrimitive2D(), + maPolyPolygon(rPolyPolygon), + maDefinitionRange(rDefinitionRange), maFillGradient(rFillGradient) { } @@ -387,7 +402,11 @@ namespace drawinglayer { // create SubSequence with FillHatchPrimitive2D const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); - FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(aPolyPolygonRange, getBackgroundColor(), getFillHatch()); + FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D( + aPolyPolygonRange, + getDefinitionRange(), + getBackgroundColor(), + getFillHatch()); const Primitive2DReference xSubRef(pNewHatch); const Primitive2DSequence aSubSequence(&xSubRef, 1L); @@ -409,6 +428,20 @@ namespace drawinglayer const attribute::FillHatchAttribute& rFillHatch) : BufferedDecompositionPrimitive2D(), maPolyPolygon(rPolyPolygon), + maDefinitionRange(rPolyPolygon.getB2DRange()), + maBackgroundColor(rBackgroundColor), + maFillHatch(rFillHatch) + { + } + + PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::BColor& rBackgroundColor, + const attribute::FillHatchAttribute& rFillHatch) + : BufferedDecompositionPrimitive2D(), + maPolyPolygon(rPolyPolygon), + maDefinitionRange(rDefinitionRange), maBackgroundColor(rBackgroundColor), maFillHatch(rFillHatch) { @@ -442,15 +475,56 @@ namespace drawinglayer if(aPrefSize.Width() && aPrefSize.Height()) { // create SubSequence with FillGraphicPrimitive2D based on polygon range - const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange()); const basegfx::B2DHomMatrix aNewObjectTransform( basegfx::tools::createScaleTranslateB2DHomMatrix( - aPolyPolygonRange.getRange(), - aPolyPolygonRange.getMinimum())); - const Primitive2DReference xSubRef( - new FillGraphicPrimitive2D( + aOutRange.getRange(), + aOutRange.getMinimum())); + Primitive2DReference xSubRef; + + if(aOutRange != getDefinitionRange()) + { + // we want to paint (tiled) content which is defined relative to DefinitionRange + // with the same tiling and offset(s) in the traget range of the geometry (the + // polygon). The range given in the local FillGraphicAttribute defines the position + // of the graphic in unit coordinates relative to the DefinitionRange. Transform + // this using DefinitionRange to get to the global definition and then with the + // inverse transformation from the target range to go to unit coordinates relative + // to that traget coordinate system. + basegfx::B2DRange aAdaptedRange(getFillGraphic().getGraphicRange()); + + const basegfx::B2DHomMatrix aFromDefinitionRangeToGlobal( + basegfx::tools::createScaleTranslateB2DHomMatrix( + getDefinitionRange().getRange(), + getDefinitionRange().getMinimum())); + + aAdaptedRange.transform(aFromDefinitionRangeToGlobal); + + basegfx::B2DHomMatrix aFromGlobalToOutRange( + basegfx::tools::createScaleTranslateB2DHomMatrix( + aOutRange.getRange(), + aOutRange.getMinimum())); + aFromGlobalToOutRange.invert(); + + aAdaptedRange.transform(aFromGlobalToOutRange); + + const drawinglayer::attribute::FillGraphicAttribute aAdaptedFillGraphicAttribute( + getFillGraphic().getGraphic(), + aAdaptedRange, + getFillGraphic().getTiling(), + getFillGraphic().getOffsetX(), + getFillGraphic().getOffsetY()); + + xSubRef = new FillGraphicPrimitive2D( + aNewObjectTransform, + aAdaptedFillGraphicAttribute); + } + else + { + xSubRef = new FillGraphicPrimitive2D( aNewObjectTransform, - getFillGraphic())); + getFillGraphic()); + } // embed to mask primitive const Primitive2DReference xRef( @@ -471,6 +545,18 @@ namespace drawinglayer const attribute::FillGraphicAttribute& rFillGraphic) : BufferedDecompositionPrimitive2D(), maPolyPolygon(rPolyPolygon), + maDefinitionRange(rPolyPolygon.getB2DRange()), + maFillGraphic(rFillGraphic) + { + } + + PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D( + const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::B2DRange& rDefinitionRange, + const attribute::FillGraphicAttribute& rFillGraphic) + : BufferedDecompositionPrimitive2D(), + maPolyPolygon(rPolyPolygon), + maDefinitionRange(rDefinitionRange), maFillGraphic(rFillGraphic) { } diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 54995d83434d..7f2e695a1190 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -342,12 +342,12 @@ namespace drawinglayer if(nTextLength) { aRetval.reserve(nTextLength); - sal_Int32* pArray = new sal_Int32[nTextLength]; - mrDevice.GetTextArray(rText, pArray, nIndex, nLength); + ::std::vector<sal_Int32> aDXArray( nTextLength); + mrDevice.GetTextArray(rText, &aDXArray[0], nIndex, nLength); for(sal_uInt32 a(0); a < nTextLength; a++) { - aRetval.push_back(pArray[a]); + aRetval.push_back(aDXArray[a]); } } diff --git a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx index 099067a3f5f7..e4478abf4038 100644 --- a/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx @@ -152,19 +152,34 @@ namespace drawinglayer case attribute::HATCHSTYLE_TRIPLE: { // rotated 45 degrees - texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI4); + texture::GeoTexSvxHatch aHatch( + aOutlineRange, + aOutlineRange, + getHatch().getDistance(), + fAngle - F_PI4); + aHatch.appendTransformations(aMatrices); } case attribute::HATCHSTYLE_DOUBLE: { // rotated 90 degrees - texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI2); + texture::GeoTexSvxHatch aHatch( + aOutlineRange, + aOutlineRange, + getHatch().getDistance(), + fAngle - F_PI2); + aHatch.appendTransformations(aMatrices); } case attribute::HATCHSTYLE_SINGLE: { // angle as given - texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle); + texture::GeoTexSvxHatch aHatch( + aOutlineRange, + aOutlineRange, + getHatch().getDistance(), + fAngle); + aHatch.appendTransformations(aMatrices); } } diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 1529fe96bf7f..38a949e95a73 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -797,7 +797,19 @@ namespace drawinglayer sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())), sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY()))); const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr(); - Rectangle aCropRect; + + // #123295# As described below this is the expanded, uncropped region + // and needs to be given in any case, especially when no cropping it is + // equal to the current rect. To make clear: normally the uncropped region + // (aka the aCropRect) is bigger than the CurrentRect. Or in other words: + // The current rect is the object area. This internal crop definition is + // somewhat crude, but used (and defined in graphic-dependent units what + // leads to even more problems, percentages would have been better). All + // in all this is a place that makes clear that a pure PDF export which does + // not use Metafile and the associated hacks (like this one) but is based on + // Primitves and uses a Primitive Renderer would be the better choice for + // the future. + Rectangle aCropRect(aCurrentRect); if(rAttr.IsCropped()) { @@ -1453,6 +1465,15 @@ namespace drawinglayer const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); + if(aLocalPolyPolygon.getB2DRange() != rHatchCandidate.getDefinitionRange()) + { + // the range which defines the hatch is different from the range of the + // geometry (used for writer frames). This cannot be done calling vcl, thus use + // decomposition here + process(rCandidate.get2DDecomposition(getViewInformation2D())); + break; + } + // #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)) @@ -1575,78 +1596,86 @@ namespace drawinglayer // BTW: One more example how useful the principles of primitives are; the decomposition // is by definition a simpler, maybe more expensive representation of the same content. process(rCandidate.get2DDecomposition(getViewInformation2D())); + break; } - else + + const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); + + if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange()) { - const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); + // the range which defines the gradient is different from the range of the + // geometry (used for writer frames). This cannot be done calling vcl, thus use + // decomposition here + process(rCandidate.get2DDecomposition(getViewInformation2D())); + break; + } - // #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); - aLocalPolyPolygon.transform(maCurrentTransformation); - - // #i82145# ATM VCL printing of gradients using curved shapes does not work, - // i submitted the bug with the given ID to THB. When that task is fixed it is - // necessary to again remove this subdivision since it decreases possible - // printing quality (not even resolution-dependent for now). THB will tell - // me when that task is fixed in the master - const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)); - - // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support - SvtGraphicFill* pSvtGraphicFill = 0; + // #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)) + ; - if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) - { - // setup gradient stuff like in like in impgrfll - SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear); + // 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); + aLocalPolyPolygon.transform(maCurrentTransformation); - switch(aVCLGradient.GetStyle()) - { - default : // GRADIENT_LINEAR: - case GRADIENT_AXIAL: - eGrad = SvtGraphicFill::gradientLinear; - break; - case GRADIENT_RADIAL: - case GRADIENT_ELLIPTICAL: - eGrad = SvtGraphicFill::gradientRadial; - break; - case GRADIENT_SQUARE: - case GRADIENT_RECT: - eGrad = SvtGraphicFill::gradientRectangular; - break; - } + // #i82145# ATM VCL printing of gradients using curved shapes does not work, + // i submitted the bug with the given ID to THB. When that task is fixed it is + // necessary to again remove this subdivision since it decreases possible + // printing quality (not even resolution-dependent for now). THB will tell + // me when that task is fixed in the master + const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)); - pSvtGraphicFill = new SvtGraphicFill( - aToolsPolyPolygon, - Color(), - 0.0, - SvtGraphicFill::fillEvenOdd, - SvtGraphicFill::fillGradient, - SvtGraphicFill::Transform(), - false, - SvtGraphicFill::hatchSingle, - Color(), - eGrad, - aVCLGradient.GetStartColor(), - aVCLGradient.GetEndColor(), - aVCLGradient.GetSteps(), - Graphic()); + // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support + SvtGraphicFill* pSvtGraphicFill = 0; + + if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) + { + // setup gradient stuff like in like in impgrfll + SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear); + + switch(aVCLGradient.GetStyle()) + { + default : // GRADIENT_LINEAR: + case GRADIENT_AXIAL: + eGrad = SvtGraphicFill::gradientLinear; + break; + case GRADIENT_RADIAL: + case GRADIENT_ELLIPTICAL: + eGrad = SvtGraphicFill::gradientRadial; + break; + case GRADIENT_SQUARE: + case GRADIENT_RECT: + eGrad = SvtGraphicFill::gradientRectangular; + break; } - // call VCL directly; encapsulate with SvtGraphicFill - impStartSvtGraphicFill(pSvtGraphicFill); - mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient); - impEndSvtGraphicFill(pSvtGraphicFill); + pSvtGraphicFill = new SvtGraphicFill( + aToolsPolyPolygon, + Color(), + 0.0, + SvtGraphicFill::fillEvenOdd, + SvtGraphicFill::fillGradient, + SvtGraphicFill::Transform(), + false, + SvtGraphicFill::hatchSingle, + Color(), + eGrad, + aVCLGradient.GetStartColor(), + aVCLGradient.GetEndColor(), + aVCLGradient.GetSteps(), + Graphic()); } + // call VCL directly; encapsulate with SvtGraphicFill + impStartSvtGraphicFill(pSvtGraphicFill); + mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient); + impEndSvtGraphicFill(pSvtGraphicFill); + break; } case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 0dd8466ba2dd..9f628493f047 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -707,7 +707,7 @@ namespace drawinglayer const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch(); // create hatch polygon in range size and discrete coordinates - basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getObjectRange()); + basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getOutputRange()); aHatchRange.transform(maCurrentTransformation); const basegfx::B2DPolygon aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange)); diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx b/drawinglayer/source/processor3d/defaultprocessor3d.cxx index 22e41ba707a3..0e49177be8ae 100644 --- a/drawinglayer/source/processor3d/defaultprocessor3d.cxx +++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx @@ -98,32 +98,83 @@ namespace drawinglayer { case attribute::GRADIENTSTYLE_LINEAR: { - pNewTex.reset(new texture::GeoTexSvxGradientLinear(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getAngle())); + pNewTex.reset( + new texture::GeoTexSvxGradientLinear( + aOutlineRange, + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getAngle())); break; } case attribute::GRADIENTSTYLE_AXIAL: { - pNewTex.reset(new texture::GeoTexSvxGradientAxial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getAngle())); + pNewTex.reset( + new texture::GeoTexSvxGradientAxial( + aOutlineRange, + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getAngle())); break; } case attribute::GRADIENTSTYLE_RADIAL: { - pNewTex.reset(new texture::GeoTexSvxGradientRadial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY())); + pNewTex.reset( + new texture::GeoTexSvxGradientRadial( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY())); break; } case attribute::GRADIENTSTYLE_ELLIPTICAL: { - pNewTex.reset(new texture::GeoTexSvxGradientElliptical(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), rFillGradient.getAngle())); + pNewTex.reset( + new texture::GeoTexSvxGradientElliptical( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle())); break; } case attribute::GRADIENTSTYLE_SQUARE: { - pNewTex.reset(new texture::GeoTexSvxGradientSquare(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), rFillGradient.getAngle())); + pNewTex.reset( + new texture::GeoTexSvxGradientSquare( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle())); break; } case attribute::GRADIENTSTYLE_RECT: { - pNewTex.reset(new texture::GeoTexSvxGradientRect(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), rFillGradient.getAngle())); + pNewTex.reset( + new texture::GeoTexSvxGradientRect( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle())); break; } } diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx index 937018c7ecde..909869b52086 100644 --- a/drawinglayer/source/texture/texture.cxx +++ b/drawinglayer/source/texture/texture.cxx @@ -74,14 +74,14 @@ namespace drawinglayer namespace texture { GeoTexSvxGradient::GeoTexSvxGradient( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 /* nSteps */, double fBorder) : GeoTexSvx(), maGradientInfo(), - maTargetRange(rTargetRange), + maDefinitionRange(rDefinitionRange), maStart(rStart), maEnd(rEnd), mfBorder(fBorder) @@ -98,7 +98,7 @@ namespace drawinglayer return (pCompare && maGradientInfo == pCompare->maGradientInfo - && maTargetRange == pCompare->maTargetRange + && maDefinitionRange == pCompare->maDefinitionRange && mfBorder == pCompare->mfBorder); } } // end of namespace texture @@ -111,19 +111,33 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientLinear::GeoTexSvxGradientLinear( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder), + mfUnitMinX(0.0), + mfUnitWidth(1.0), + mfUnitMaxY(1.0) { maGradientInfo = basegfx::tools::createLinearODFGradientInfo( - rTargetRange, + rDefinitionRange, nSteps, fBorder, fAngle); + + if(rDefinitionRange != rOutputRange) + { + basegfx::B2DRange aInvOutputRange(rOutputRange); + + aInvOutputRange.transform(maGradientInfo.getBackTextureTransform()); + mfUnitMinX = aInvOutputRange.getMinX(); + mfUnitWidth = aInvOutputRange.getWidth(); + mfUnitMaxY = aInvOutputRange.getMaxY(); + } } GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear() @@ -132,29 +146,46 @@ namespace drawinglayer void GeoTexSvxGradientLinear::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maStart; + rOuterColor = maStart; if(maGradientInfo.getSteps()) { const double fStripeWidth(1.0 / maGradientInfo.getSteps()); B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + basegfx::B2DHomMatrix aPattern; + + // bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] + aPattern.scale(0.5, 0.5); + aPattern.translate(0.5, 0.5); + + // scale and translate in X + aPattern.scale(mfUnitWidth, 1.0); + aPattern.translate(mfUnitMinX, 0.0); for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) { const double fPos(fStripeWidth * a); - // optimized below... - // - // basegfx::B2DHomMatrix aNew; - // aNew.scale(0.5, 0.5); - // aNew.translate(0.5, 0.5); - // aNew.scale(1.0, (1.0 - fPos)); - // aNew.translate(0.0, fPos); - // aNew = maGradientInfo.getTextureTransform() * aNew; - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * - basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5 * (1.0 - fPos), 0.5, 0.5 * (1.0 + fPos)); + basegfx::B2DHomMatrix aNew(aPattern); + + // scale and translate in Y + double fHeight(1.0 - fPos); + + if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0) + { + fHeight += mfUnitMaxY - 1.0; + } + + aNew.scale(1.0, fHeight); + aNew.translate(0.0, fPos); + + // set at target + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; + + // interpolate and set color aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -176,19 +207,31 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientAxial::GeoTexSvxGradientAxial( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder), + mfUnitMinX(0.0), + mfUnitWidth(1.0) { maGradientInfo = basegfx::tools::createAxialODFGradientInfo( - rTargetRange, + rDefinitionRange, nSteps, fBorder, fAngle); + + if(rDefinitionRange != rOutputRange) + { + basegfx::B2DRange aInvOutputRange(rOutputRange); + + aInvOutputRange.transform(maGradientInfo.getBackTextureTransform()); + mfUnitMinX = aInvOutputRange.getMinX(); + mfUnitWidth = aInvOutputRange.getWidth(); + } } GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial() @@ -197,9 +240,9 @@ namespace drawinglayer void GeoTexSvxGradientAxial::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maEnd; + rOuterColor = maEnd; if(maGradientInfo.getSteps()) { @@ -208,16 +251,26 @@ namespace drawinglayer for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) { - // const double fPos(fStripeWidth * a); - // optimized below... - // - // basegfx::B2DHomMatrix aNew; - // aNew.scale(0.50, (1.0 - fPos)); - // aNew.translate(0.5, 0.0); - // aNew = maGradientInfo.getTextureTransform() * aNew; - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * - basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 1.0 - (fStripeWidth * a), 0.5, 0.0); + const double fPos(fStripeWidth * a); + basegfx::B2DHomMatrix aNew; + + // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] + aNew.scale(0.5, 1.0); + aNew.translate(0.5, 0.0); + + // scale/translate in X + aNew.scale(mfUnitWidth, 1.0); + aNew.translate(mfUnitMinX, 0.0); + + // already centerd in Y on X-Axis, just scale in Y + aNew.scale(1.0, 1.0 - fPos); + + // set at target + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; + + // interpolate and set color aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -239,17 +292,17 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientRadial::GeoTexSvxGradientRadial( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) { maGradientInfo = basegfx::tools::createRadialODFGradientInfo( - rTargetRange, + rDefinitionRange, basegfx::B2DVector(fOffsetX,fOffsetY), nSteps, fBorder); @@ -261,9 +314,9 @@ namespace drawinglayer void GeoTexSvxGradientRadial::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maStart; + rOuterColor = maStart; if(maGradientInfo.getSteps()) { @@ -296,7 +349,7 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -304,10 +357,10 @@ namespace drawinglayer double fOffsetX, double fOffsetY, double fAngle) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) { maGradientInfo = basegfx::tools::createEllipticalODFGradientInfo( - rTargetRange, + rDefinitionRange, basegfx::B2DVector(fOffsetX,fOffsetY), nSteps, fBorder, @@ -320,9 +373,9 @@ namespace drawinglayer void GeoTexSvxGradientElliptical::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maStart; + rOuterColor = maStart; if(maGradientInfo.getSteps()) { @@ -373,7 +426,7 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientSquare::GeoTexSvxGradientSquare( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -381,10 +434,10 @@ namespace drawinglayer double fOffsetX, double fOffsetY, double fAngle) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) { maGradientInfo = basegfx::tools::createSquareODFGradientInfo( - rTargetRange, + rDefinitionRange, basegfx::B2DVector(fOffsetX,fOffsetY), nSteps, fBorder, @@ -397,9 +450,9 @@ namespace drawinglayer void GeoTexSvxGradientSquare::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maStart; + rOuterColor = maStart; if(maGradientInfo.getSteps()) { @@ -432,7 +485,7 @@ namespace drawinglayer namespace texture { GeoTexSvxGradientRect::GeoTexSvxGradientRect( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, @@ -440,10 +493,10 @@ namespace drawinglayer double fOffsetX, double fOffsetY, double fAngle) - : GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) { maGradientInfo = basegfx::tools::createRectangularODFGradientInfo( - rTargetRange, + rDefinitionRange, basegfx::B2DVector(fOffsetX,fOffsetY), nSteps, fBorder, @@ -456,9 +509,9 @@ namespace drawinglayer void GeoTexSvxGradientRect::appendTransformationsAndColors( std::vector< B2DHomMatrixAndBColor >& rEntries, - basegfx::BColor& rOutmostColor) + basegfx::BColor& rOuterColor) { - rOutmostColor = maStart; + rOuterColor = maStart; if(maGradientInfo.getSteps()) { @@ -509,17 +562,22 @@ namespace drawinglayer namespace texture { GeoTexSvxHatch::GeoTexSvxHatch( - const basegfx::B2DRange& rTargetRange, + const basegfx::B2DRange& rDefinitionRange, + const basegfx::B2DRange& rOutputRange, double fDistance, double fAngle) - : mfDistance(0.1), + : maOutputRange(rOutputRange), + maTextureTransform(), + maBackTextureTransform(), + mfDistance(0.1), mfAngle(fAngle), - mnSteps(10L) + mnSteps(10), + mbDefinitionRangeEqualsOutputRange(rDefinitionRange == rOutputRange) { - double fTargetSizeX(rTargetRange.getWidth()); - double fTargetSizeY(rTargetRange.getHeight()); - double fTargetOffsetX(rTargetRange.getMinX()); - double fTargetOffsetY(rTargetRange.getMinY()); + double fTargetSizeX(rDefinitionRange.getWidth()); + double fTargetSizeY(rDefinitionRange.getHeight()); + double fTargetOffsetX(rDefinitionRange.getMinX()); + double fTargetOffsetY(rDefinitionRange.getMinY()); fAngle = -fAngle; @@ -566,6 +624,7 @@ namespace drawinglayer { const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx); return (pCompare + && maOutputRange == pCompare->maOutputRange && maTextureTransform == pCompare->maTextureTransform && mfDistance == pCompare->mfDistance && mfAngle == pCompare->mfAngle @@ -574,13 +633,54 @@ namespace drawinglayer void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) { - for(sal_uInt32 a(1L); a < mnSteps; a++) + if(mbDefinitionRangeEqualsOutputRange) { - // create matrix - const double fOffset(mfDistance * (double)a); - basegfx::B2DHomMatrix aNew; - aNew.set(1, 2, fOffset); - rMatrices.push_back(maTextureTransform * aNew); + // simple hatch where the definition area equals the output area + for(sal_uInt32 a(1); a < mnSteps; a++) + { + // create matrix + const double fOffset(mfDistance * (double)a); + basegfx::B2DHomMatrix aNew; + aNew.set(1, 2, fOffset); + rMatrices.push_back(maTextureTransform * aNew); + } + } + else + { + // output area is different from definition area, back-transform to get + // the output area in unit coordinates and fill this with hatch lines + // using the settings derived from the definition area + basegfx::B2DRange aBackUnitRange(maOutputRange); + + aBackUnitRange.transform(getBackTextureTransform()); + + // calculate vertical start value and a security maximum integer value to avoid death loops + double fStart(basegfx::snapToNearestMultiple(aBackUnitRange.getMinY(), mfDistance)); + const sal_uInt32 nNeededIntegerSteps(basegfx::fround((aBackUnitRange.getHeight() / mfDistance) + 0.5)); + sal_uInt32 nMaxIntegerSteps(::std::min(nNeededIntegerSteps, sal_uInt32(10000))); + + while(fStart < aBackUnitRange.getMaxY() && nMaxIntegerSteps) + { + // create new transform for + basegfx::B2DHomMatrix aNew; + + // adapt x scale and position + //aNew.scale(aBackUnitRange.getWidth(), 1.0); + //aNew.translate(aBackUnitRange.getMinX(), 0.0); + aNew.set(0, 0, aBackUnitRange.getWidth()); + aNew.set(0, 2, aBackUnitRange.getMinX()); + + // adapt y position to current step + aNew.set(1, 2, fStart); + //aNew.translate(0.0, fStart); + + // add new transformation + rMatrices.push_back(maTextureTransform * aNew); + + // next step + fStart += mfDistance; + nMaxIntegerSteps--; + } } } diff --git a/drawinglayer/source/texture/texture3d.cxx b/drawinglayer/source/texture/texture3d.cxx index db7ce8ad94d8..0c6ae78b78d5 100644 --- a/drawinglayer/source/texture/texture3d.cxx +++ b/drawinglayer/source/texture/texture3d.cxx @@ -341,16 +341,28 @@ namespace drawinglayer const double fAngleA(rHatch.getAngle()); maColor = rHatch.getColor(); mbFillBackground = rHatch.isFillBackground(); - mp0 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA); + mp0 = new GeoTexSvxHatch( + aOutlineRange, + aOutlineRange, + rHatch.getDistance(), + fAngleA); if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle()) { - mp1 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI2); + mp1 = new GeoTexSvxHatch( + aOutlineRange, + aOutlineRange, + rHatch.getDistance(), + fAngleA + F_PI2); } if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle()) { - mp2 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI4); + mp2 = new GeoTexSvxHatch( + aOutlineRange, + aOutlineRange, + rHatch.getDistance(), + fAngleA + F_PI4); } } |