diff options
-rw-r--r-- | include/svx/sdr/overlay/overlayanimatedbitmapex.hxx | 12 | ||||
-rw-r--r-- | include/svx/sdr/overlay/overlaybitmapex.hxx | 16 | ||||
-rw-r--r-- | include/svx/sdr/overlay/overlaytools.hxx | 10 | ||||
-rw-r--r-- | include/svx/svdhdl.hxx | 20 | ||||
-rw-r--r-- | include/svx/svdograf.hxx | 3 | ||||
-rw-r--r-- | svx/source/sdr/overlay/overlayanimatedbitmapex.cxx | 14 | ||||
-rw-r--r-- | svx/source/sdr/overlay/overlaybitmapex.cxx | 14 | ||||
-rw-r--r-- | svx/source/sdr/overlay/overlaytools.cxx | 35 | ||||
-rw-r--r-- | svx/source/svdraw/svddrgm1.hxx | 5 | ||||
-rw-r--r-- | svx/source/svdraw/svddrgmt.cxx | 220 | ||||
-rw-r--r-- | svx/source/svdraw/svdhdl.cxx | 50 | ||||
-rw-r--r-- | svx/source/svdraw/svdmrkv.cxx | 146 | ||||
-rw-r--r-- | svx/source/svdraw/svdograf.cxx | 113 |
13 files changed, 503 insertions, 155 deletions
diff --git a/include/svx/sdr/overlay/overlayanimatedbitmapex.hxx b/include/svx/sdr/overlay/overlayanimatedbitmapex.hxx index e895bfb71c15..5182f93a8f48 100644 --- a/include/svx/sdr/overlay/overlayanimatedbitmapex.hxx +++ b/include/svx/sdr/overlay/overlayanimatedbitmapex.hxx @@ -45,6 +45,10 @@ namespace sdr // #i53216# added CursorBlinkTime (in ms) sal_uInt32 mnBlinkTime; + // optional shear and rotation + double mfShearX; + double mfRotation; + /// bitfield // Flag to remember which state to draw. Inited with false (0) bool mbOverlayState : 1; @@ -61,7 +65,9 @@ namespace sdr sal_uInt16 nCenX1 = 0, sal_uInt16 nCenY1 = 0, sal_uInt16 nCenX2 = 0, - sal_uInt16 nCenY2 = 0); + sal_uInt16 nCenY2 = 0, + double fShearX = 0.0, + double fRotation = 0.0); virtual ~OverlayAnimatedBitmapEx(); const BitmapEx& getBitmapEx1() const { return maBitmapEx1; } @@ -78,6 +84,10 @@ namespace sdr // execute event from base class ::sdr::animation::Event. Default // implementation does nothing and does not create a new event. virtual void Trigger(sal_uInt32 nTime); + + // get shearX and rotation + double getShearX() const { return mfShearX; } + double getRotation() const { return mfRotation; } }; } // end of namespace overlay } // end of namespace sdr diff --git a/include/svx/sdr/overlay/overlaybitmapex.hxx b/include/svx/sdr/overlay/overlaybitmapex.hxx index 045c9645f8a0..c984c3093345 100644 --- a/include/svx/sdr/overlay/overlaybitmapex.hxx +++ b/include/svx/sdr/overlay/overlaybitmapex.hxx @@ -39,8 +39,10 @@ namespace sdr sal_uInt16 mnCenterX; sal_uInt16 mnCenterY; - // optional transparency - double mfAlpha; + // optional transparency, shear and rotation + double mfAlpha; + double mfShearX; + double mfRotation; virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence(); @@ -48,13 +50,21 @@ namespace sdr OverlayBitmapEx( const basegfx::B2DPoint& rBasePos, const BitmapEx& rBitmapEx, - sal_uInt16 nCenX = 0, sal_uInt16 nCenY = 0, double fAlpha = 0.0 ); + sal_uInt16 nCenX = 0, + sal_uInt16 nCenY = 0, + double fAlpha = 0.0, + double fShearX = 0.0, + double fRotation = 0.0); virtual ~OverlayBitmapEx(); const BitmapEx& getBitmapEx() const { return maBitmapEx; } sal_uInt16 getCenterX() const { return mnCenterX; } sal_uInt16 getCenterY() const { return mnCenterY; } + + // get shearX and rotation + double getShearX() const { return mfShearX; } + double getRotation() const { return mfRotation; } }; } // end of namespace overlay } // end of namespace sdr diff --git a/include/svx/sdr/overlay/overlaytools.hxx b/include/svx/sdr/overlay/overlaytools.hxx index f57d6a8a52bf..181f8950db9f 100644 --- a/include/svx/sdr/overlay/overlaytools.hxx +++ b/include/svx/sdr/overlay/overlaytools.hxx @@ -46,6 +46,10 @@ namespace drawinglayer sal_uInt16 mnCenterX; sal_uInt16 mnCenterY; + // evtl. rotation and shear around center + double mfShearX; + double mfRotation; + protected: virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; @@ -54,13 +58,17 @@ namespace drawinglayer const BitmapEx& rBitmapEx, const basegfx::B2DPoint& rBasePosition, sal_uInt16 nCenterX, - sal_uInt16 nCenterY); + sal_uInt16 nCenterY, + double fShearX = 0.0, + double fRotation = 0.0); // data access const BitmapEx& getBitmapEx() const { return maBitmapEx; } const basegfx::B2DPoint& getBasePosition() const { return maBasePosition; } sal_uInt16 getCenterX() const { return mnCenterX; } sal_uInt16 getCenterY() const { return mnCenterY; } + double getShearX() const { return mfShearX; } + double getRotation() const { return mfRotation; } // compare operator virtual bool operator==( const BasePrimitive2D& rPrimitive ) const; diff --git a/include/svx/svdhdl.hxx b/include/svx/svdhdl.hxx index 599ff9f3232c..fc7382d417a9 100644 --- a/include/svx/svdhdl.hxx +++ b/include/svx/svdhdl.hxx @@ -502,8 +502,18 @@ public: class SVX_DLLPUBLIC SdrCropHdl : public SdrHdl { +private: + // evtl. shear and rotation, equal to the object's one to allow adaption of + // the visualization handles + double mfShearX; + double mfRotation; + public: - SdrCropHdl(const Point& rPnt, SdrHdlKind eNewKind); + SdrCropHdl( + const Point& rPnt, + SdrHdlKind eNewKind, + double fShearX, + double fRotation); protected: // create marker for this kind @@ -526,11 +536,6 @@ private: double mfCropRight; double mfCropBottom; - // Argh! The old geometry stuff expresses Y-Mirror using 180 degree rotaton - // and the bMirrored bool at the SdrGrafObj, so for now I have to give - // this info here. I am sooo looking forward to aw080 and real transformations :-( - bool mbExtraMirrorXFromGraphic; - public: SdrCropViewHdl( const basegfx::B2DHomMatrix& rObjectTransform, @@ -538,8 +543,7 @@ public: double fCropLeft, double fCropTop, double fCropRight, - double fCropBottom, - bool bExtraMirrorXFromGraphic); + double fCropBottom); protected: // create marker for this kind diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx index 20151dde4a9a..eab2bf82d81c 100644 --- a/include/svx/svdograf.hxx +++ b/include/svx/svdograf.hxx @@ -197,6 +197,9 @@ public: // #i103116# FullDrag support virtual SdrObject* getFullDragClone() const; + + // add handles for crop mode when selected + void addCropHandles(SdrHdlList& rTarget) const; }; #endif // INCLUDED_SVX_SVDOGRAF_HXX diff --git a/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx b/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx index ff4d97b8c9d2..7ea80b607a6f 100644 --- a/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx +++ b/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx @@ -38,7 +38,9 @@ namespace sdr getBitmapEx1(), getBasePosition(), getCenterX1(), - getCenterY1())); + getCenterY1(), + getShearX(), + getRotation())); return drawinglayer::primitive2d::Primitive2DSequence(&aPrimitive, 1); } @@ -49,7 +51,9 @@ namespace sdr getBitmapEx2(), getBasePosition(), getCenterX2(), - getCenterY2())); + getCenterY2(), + getShearX(), + getRotation())); return drawinglayer::primitive2d::Primitive2DSequence(&aPrimitive, 1); } @@ -63,13 +67,17 @@ namespace sdr sal_uInt16 nCenX1, sal_uInt16 nCenY1, sal_uInt16 nCenX2, - sal_uInt16 nCenY2) + sal_uInt16 nCenY2, + double fShearX, + double fRotation) : OverlayObjectWithBasePosition(rBasePos, Color(COL_WHITE)), maBitmapEx1(rBitmapEx1), maBitmapEx2(rBitmapEx2), mnCenterX1(nCenX1), mnCenterY1(nCenY1), mnCenterX2(nCenX2), mnCenterY2(nCenY2), mnBlinkTime(nBlinkTime), + mfShearX(fShearX), + mfRotation(fRotation), mbOverlayState(false) { // set AllowsAnimation flag to mark this object as animation capable diff --git a/svx/source/sdr/overlay/overlaybitmapex.cxx b/svx/source/sdr/overlay/overlaybitmapex.cxx index d117603f5d83..31aca7ab198a 100644 --- a/svx/source/sdr/overlay/overlaybitmapex.cxx +++ b/svx/source/sdr/overlay/overlaybitmapex.cxx @@ -36,7 +36,9 @@ namespace sdr getBitmapEx(), getBasePosition(), getCenterX(), - getCenterY())); + getCenterY(), + getShearX(), + getRotation())); if(basegfx::fTools::more(mfAlpha, 0.0)) { @@ -51,12 +53,18 @@ namespace sdr OverlayBitmapEx::OverlayBitmapEx( const basegfx::B2DPoint& rBasePos, const BitmapEx& rBitmapEx, - sal_uInt16 nCenX, sal_uInt16 nCenY, double fAlpha) + sal_uInt16 nCenX, + sal_uInt16 nCenY, + double fAlpha, + double fShearX, + double fRotation) : OverlayObjectWithBasePosition(rBasePos, Color(COL_WHITE)), maBitmapEx(rBitmapEx), mnCenterX(nCenX), mnCenterY(nCenY), - mfAlpha(fAlpha) + mfAlpha(fAlpha), + mfShearX(fShearX), + mfRotation(fRotation) { } diff --git a/svx/source/sdr/overlay/overlaytools.cxx b/svx/source/sdr/overlay/overlaytools.cxx index d3ae3f97694c..71fc7682ea3b 100644 --- a/svx/source/sdr/overlay/overlaytools.cxx +++ b/svx/source/sdr/overlay/overlaytools.cxx @@ -41,12 +41,16 @@ namespace drawinglayer const BitmapEx& rBitmapEx, const basegfx::B2DPoint& rBasePosition, sal_uInt16 nCenterX, - sal_uInt16 nCenterY) + sal_uInt16 nCenterY, + double fShearX, + double fRotation) : DiscreteMetricDependentPrimitive2D(), maBitmapEx(rBitmapEx), maBasePosition(rBasePosition), mnCenterX(nCenterX), - mnCenterY(nCenterY) + mnCenterY(nCenterY), + mfShearX(fShearX), + mfRotation(fRotation) {} Primitive2DSequence OverlayBitmapExPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const @@ -61,10 +65,10 @@ namespace drawinglayer // the prepared one which expresses how many logic units form a discrete unit) // for this step. This primitive is to be displayed always unscaled (in it's pixel size) // and unrotated, more like a marker - const double fLeft(((0.0 - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX()); - const double fTop(((0.0 - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY()); - const double fRight(((aBitmapSize.getWidth() - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX()); - const double fBottom(((aBitmapSize.getHeight() - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY()); + const double fLeft((0.0 - getCenterX()) * getDiscreteUnit()); + const double fTop((0.0 - getCenterY()) * getDiscreteUnit()); + const double fRight((aBitmapSize.getWidth() - getCenterX()) * getDiscreteUnit()); + const double fBottom((aBitmapSize.getHeight() - getCenterY()) * getDiscreteUnit()); // create a BitmapPrimitive2D using those positions basegfx::B2DHomMatrix aTransform; @@ -74,6 +78,21 @@ namespace drawinglayer aTransform.set(0, 2, fLeft); aTransform.set(1, 2, fTop); + // if shearX is used, apply it, too + if(!basegfx::fTools::equalZero(getShearX())) + { + aTransform.shearX(getShearX()); + } + + // if rotation is used, apply it, too + if(!basegfx::fTools::equalZero(getRotation())) + { + aTransform.rotate(getRotation()); + } + + // add BasePosition + aTransform.translate(getBasePosition().getX(), getBasePosition().getY()); + const Primitive2DReference aPrimitive(new BitmapPrimitive2D(getBitmapEx(), aTransform)); aRetval = Primitive2DSequence(&aPrimitive, 1); } @@ -90,7 +109,9 @@ namespace drawinglayer return (getBitmapEx() == rCompare.getBitmapEx() && getBasePosition() == rCompare.getBasePosition() && getCenterX() == rCompare.getCenterX() - && getCenterY() == rCompare.getCenterY()); + && getCenterY() == rCompare.getCenterY() + && getShearX() == rCompare.getShearX() + && getRotation() == rCompare.getRotation()); } return false; diff --git a/svx/source/svdraw/svddrgm1.hxx b/svx/source/svdraw/svddrgm1.hxx index e4a2b334c2d9..83572a43cadc 100644 --- a/svx/source/svdraw/svddrgm1.hxx +++ b/svx/source/svdraw/svddrgm1.hxx @@ -248,13 +248,16 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////// // SdrDragCrop -class SdrDragCrop : public SdrDragResize +// derive from SdrDragObjOwn to have handles aligned to object when it +// is sheared or rotated +class SdrDragCrop : public SdrDragObjOwn { public: TYPEINFO(); SdrDragCrop(SdrDragView& rNewView); virtual void TakeSdrDragComment(OUString& rStr) const; + virtual bool BeginSdrDrag(); virtual bool EndSdrDrag(bool bCopy); virtual Pointer GetSdrDragPointer() const; }; diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx index 5a6cba41b9de..df1f835767d7 100644 --- a/svx/source/svdraw/svddrgmt.cxx +++ b/svx/source/svdraw/svddrgmt.cxx @@ -3644,7 +3644,7 @@ void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPol TYPEINIT1(SdrDragCrop,SdrDragResize); SdrDragCrop::SdrDragCrop(SdrDragView& rNewView) -: SdrDragResize(rNewView) +: SdrDragObjOwn(rNewView) { // switch off solid dragging for crop; it just makes no sense since showing // a 50% transparent object above the original will not be visible @@ -3667,7 +3667,21 @@ void SdrDragCrop::TakeSdrDragComment(OUString& rStr) const rStr += ImpGetResStr(STR_EditWithCopy); } -bool SdrDragCrop::EndSdrDrag(bool bCopy) +bool SdrDragCrop::BeginSdrDrag() +{ + // call parent + bool bRetval(SdrDragObjOwn::BeginSdrDrag()); + + if(!GetDragHdl()) + { + // we need the DragHdl, break if not there + bRetval = false; + } + + return bRetval; +} + +bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/) { Hide(); @@ -3706,34 +3720,204 @@ bool SdrDragCrop::EndSdrDrag(bool bCopy) ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr); getSdrDragView().BegUndo( aUndoStr ); - getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) ); + getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + // also need attr undo, the SdrGrafCropItem will be changed + getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj)); } - Rectangle aOldRect( pObj->GetLogicRect() ); - getSdrDragView().ResizeMarkedObj(DragStat().Ref1(),aXFact,aYFact,bCopy); - Rectangle aNewRect( pObj->GetLogicRect() ); + // new part to comute the user's drag activities + // get the original objects transformation + basegfx::B2DHomMatrix aOriginalMatrix; + basegfx::B2DPolyPolygon aPolyPolygon; + bool bShearCorrected(false); - double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth(); - double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight(); + // get transformation from object + pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon); + + { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080 + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate(0.0), fShearX(0.0); + + aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + if(!basegfx::fTools::equalZero(fShearX)) + { + bShearCorrected = true; + aOriginalMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + -fShearX, + fRotate, + aTranslate); + } + } + + // invert it to be able to work on unit coordinates + basegfx::B2DHomMatrix aInverse(aOriginalMatrix); + + aInverse.invert(); + + // gererate start point of original drag vector in unit coordinates (the + // vis-a-vis of the drag point) + basegfx::B2DPoint aLocalStart(0.0, 0.0); + bool bOnAxis(false); + + switch(GetDragHdlKind()) + { + case HDL_UPLFT: aLocalStart.setX(1.0); aLocalStart.setY(1.0); break; + case HDL_UPPER: aLocalStart.setX(0.5); aLocalStart.setY(1.0); bOnAxis = true; break; + case HDL_UPRGT: aLocalStart.setX(0.0); aLocalStart.setY(1.0); break; + case HDL_LEFT : aLocalStart.setX(1.0); aLocalStart.setY(0.5); bOnAxis = true; break; + case HDL_RIGHT: aLocalStart.setX(0.0); aLocalStart.setY(0.5); bOnAxis = true; break; + case HDL_LWLFT: aLocalStart.setX(1.0); aLocalStart.setY(0.0); break; + case HDL_LOWER: aLocalStart.setX(0.5); aLocalStart.setY(0.0); bOnAxis = true; break; + case HDL_LWRGT: aLocalStart.setX(0.0); aLocalStart.setY(0.0); break; + default: break; + } + + // create the current drag position in unit coordinates + basegfx::B2DPoint aLocalCurrent(aInverse * basegfx::B2DPoint(DragStat().GetNow().X(), DragStat().GetNow().Y())); + + // if one of the edge handles is used, limit to X or Y drag only + if(bOnAxis) + { + if(basegfx::fTools::equal(aLocalStart.getX(), 0.5)) + { + aLocalCurrent.setX(aLocalStart.getX()); + } + else + { + aLocalCurrent.setY(aLocalStart.getY()); + } + } + + // create internal change in unit coordinates + basegfx::B2DHomMatrix aDiscreteChangeMatrix; - // to correct the never working combination of cropped images and mirroring - // I have to correct the rectangles the calculation is based on here. In the current - // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All - // this can be removed again when aw080 will have cleaned up the old - // (non-)transformation mess in the core. - if(18000 == pObj->GetGeoStat().nDrehWink) + if(!basegfx::fTools::equal(aLocalCurrent.getX(), aLocalStart.getX())) { - // old notation of vertical mirror, need to correct diffs since both rects - // are rotated by 180 degrees - aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft()); - aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft()); + if(aLocalStart.getX() < 0.5) + { + aDiscreteChangeMatrix.scale(aLocalCurrent.getX(), 1.0); + } + else + { + aDiscreteChangeMatrix.scale(1.0 - aLocalCurrent.getX(), 1.0); + aDiscreteChangeMatrix.translate(aLocalCurrent.getX(), 0.0); + } + } + + if(!basegfx::fTools::equal(aLocalCurrent.getY(), aLocalStart.getY())) + { + if(aLocalStart.getY() < 0.5) + { + aDiscreteChangeMatrix.scale(1.0, aLocalCurrent.getY()); + } + else + { + aDiscreteChangeMatrix.scale(1.0, 1.0 - aLocalCurrent.getY()); + aDiscreteChangeMatrix.translate(0.0, aLocalCurrent.getY()); + } } + // preparematrix to apply to object; evtl. back-correct shear + basegfx::B2DHomMatrix aNewObjectMatrix(aOriginalMatrix * aDiscreteChangeMatrix); + + if(bShearCorrected) + { + // TTTT back-correct shear + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate(0.0), fShearX(0.0); + + aNewObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + aNewObjectMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + -fShearX, + fRotate, + aTranslate); + } + + // apply change to object by applying the unit coordinate change followed + // by the original change + pObj->TRSetBaseGeometry(aNewObjectMatrix, aPolyPolygon); + + // the following old code uses aOldRect/aNewRect to calculate the crop change for + // the crop item. It implies unrotated objects, so create the unrotated original + // erctangle and the unrotated modified rectangle. Latter can in case of shear and/or + // rotation not be fetched by using + // + //Rectangle aNewRect( pObj->GetLogicRect() ); + // + // as it was done before because the top-left of that new rect *will* have an offset + // caused by the evtl. existing shear and/or rotation, so calculate a unrotated + // rectangle how it would be as a result when appling the unit coordinate change + // to the unrotated original transformation. + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + + // get access to scale and translate + aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // prepare unsheared/unrotated versions of the old and new transformation + const basegfx::B2DHomMatrix aMatrixOriginalNoShearNoRotate( + basegfx::tools::createScaleTranslateB2DHomMatrix( + basegfx::absolute(aScale), + aTranslate)); + + // create the ranges for these + basegfx::B2DRange aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0); + basegfx::B2DRange aRangeNewNoShearNoRotate(0.0, 0.0, 1.0, 1.0); + + aRangeOriginalNoShearNoRotate.transform(aMatrixOriginalNoShearNoRotate); + aRangeNewNoShearNoRotate.transform(aMatrixOriginalNoShearNoRotate * aDiscreteChangeMatrix); + + // extract the old Rectangle structures + Rectangle aOldRect( + basegfx::fround(aRangeOriginalNoShearNoRotate.getMinX()), + basegfx::fround(aRangeOriginalNoShearNoRotate.getMinY()), + basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxX()), + basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxY())); + Rectangle aNewRect( + basegfx::fround(aRangeNewNoShearNoRotate.getMinX()), + basegfx::fround(aRangeNewNoShearNoRotate.getMinY()), + basegfx::fround(aRangeNewNoShearNoRotate.getMaxX()), + basegfx::fround(aRangeNewNoShearNoRotate.getMaxY())); + + // continue with the old original stuff + double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth(); + double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight(); + + // not needed since the modification is done in unit coordinates, free from shear/rotate and mirror + // // TTTT may be removed or exhanged by other stuff in aw080 + // // to correct the never working combination of cropped images and mirroring + // // I have to correct the rectangles the calculation is based on here. In the current + // // core geometry stuff a vertical mirror is expressed as 180 degree rotation. All + // // this can be removed again when aw080 will have cleaned up the old + // // (non-)transformation mess in the core. + // if(18000 == pObj->GetGeoStat().nDrehWink) + // { + // // old notation of vertical mirror, need to correct diffs since both rects + // // are rotated by 180 degrees + // aOldRect = Rectangle(aOldRect.TopLeft() - (aOldRect.BottomRight() - aOldRect.TopLeft()), aOldRect.TopLeft()); + // aNewRect = Rectangle(aNewRect.TopLeft() - (aNewRect.BottomRight() - aNewRect.TopLeft()), aNewRect.TopLeft()); + // } + sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left(); sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top(); sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right(); sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom(); + if(pObj->IsMirrored()) + { + // mirrored X or Y, for old stuff, exchange X + // TTTT: check for aw080 + sal_Int32 nTmp(nDiffLeft); + nDiffLeft = -nDiffRight; + nDiffRight = -nTmp; + } + sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX ); sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY ); sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX ); diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx index 64b56e57c0e0..a461882394ed 100644 --- a/svx/source/svdraw/svdhdl.cxx +++ b/svx/source/svdraw/svdhdl.cxx @@ -2212,8 +2212,14 @@ SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const // SdrCropHdl // -------------------------------------------------------------------- -SdrCropHdl::SdrCropHdl(const Point& rPnt, SdrHdlKind eNewKind) -: SdrHdl( rPnt, eNewKind ) +SdrCropHdl::SdrCropHdl( + const Point& rPnt, + SdrHdlKind eNewKind, + double fShearX, + double fRotation) +: SdrHdl(rPnt, eNewKind), + mfShearX(fShearX), + mfRotation(fRotation) { } @@ -2310,18 +2316,29 @@ void SdrCropHdl::CreateB2dIAObject() const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime()); - pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBmpEx1, aBmpEx2, nBlinkTime, + pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx( + aPosition, + aBmpEx1, + aBmpEx2, + nBlinkTime, (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, (sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1, - (sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1); + (sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1, + mfShearX, + mfRotation); } else { // create centered handle as default - pOverlayObject = new ::sdr::overlay::OverlayBitmapEx(aPosition, aBmpEx1, + pOverlayObject = new ::sdr::overlay::OverlayBitmapEx( + aPosition, + aBmpEx1, (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, - (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1); + (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, + 0.0, + mfShearX, + mfRotation); } // OVERLAYMANAGER @@ -2337,6 +2354,8 @@ void SdrCropHdl::CreateB2dIAObject() } //////////////////////////////////////////////////////////////////////////////////////////////////// +// with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff +// accordingly SdrCropViewHdl::SdrCropViewHdl( const basegfx::B2DHomMatrix& rObjectTransform, @@ -2344,16 +2363,14 @@ SdrCropViewHdl::SdrCropViewHdl( double fCropLeft, double fCropTop, double fCropRight, - double fCropBottom, - bool bExtraMirrorXFromGraphic) + double fCropBottom) : SdrHdl(Point(), HDL_USER), maObjectTransform(rObjectTransform), maGraphic(rGraphic), mfCropLeft(fCropLeft), mfCropTop(fCropTop), mfCropRight(fCropRight), - mfCropBottom(fCropBottom), - mbExtraMirrorXFromGraphic(bExtraMirrorXFromGraphic) + mfCropBottom(fCropBottom) { } @@ -2405,15 +2422,11 @@ void SdrCropViewHdl::CreateB2dIAObject() if(bMirroredX) { aScale.setX(-aScale.getX()); - fCropLeft = mfCropRight; - fCropRight = mfCropLeft; } if(bMirroredY) { aScale.setY(-aScale.getY()); - fCropTop = mfCropBottom; - fCropBottom = mfCropTop; } // create target translate and scale @@ -2478,14 +2491,13 @@ void SdrCropViewHdl::CreateB2dIAObject() // create cropped transformation basegfx::B2DHomMatrix aCroppedTransform; - const bool bCombinedMirrorX(mbExtraMirrorXFromGraphic || bMirroredX); aCroppedTransform.scale( - bCombinedMirrorX ? -aCropped.getWidth() : aCropped.getWidth(), - bMirroredY ? -aCropped.getHeight() : aCropped.getHeight()); + aCropped.getWidth(), + aCropped.getHeight()); aCroppedTransform.translate( - bCombinedMirrorX ? aCropped.getMaxX() : aCropped.getMinX(), - bMirroredY ? aCropped.getMaxY() : aCropped.getMinY()); + aCropped.getMinX(), + aCropped.getMinY()); aCroppedTransform = maObjectTransform * aCroppedTransform; // prepare graphic primitive (tranformed) diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx index 2124482569be..46433c12d9f6 100644 --- a/svx/source/svdraw/svdmrkv.cxx +++ b/svx/source/svdraw/svdmrkv.cxx @@ -593,6 +593,13 @@ sal_Bool SdrMarkView::ImpIsFrameHandles() const bFrmHdl=!pObj->hasSpecialDrag(); } } + + // no FrameHdl for crop + if(bFrmHdl && SDRDRAG_CROP == eDragMode) + { + bFrmHdl = sal_False; + } + return bFrmHdl; } @@ -712,67 +719,6 @@ void SdrMarkView::SetMarkHandles() pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); } } - else if( eDragMode==SDRDRAG_CROP ) - { - const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pMarkedObj); - - if(pSdrGrafObj) - { - const SdrGrafCropItem& rCrop = static_cast< const SdrGrafCropItem& >(pSdrGrafObj->GetMergedItem(SDRATTR_GRAFCROP)); - - if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom()) - { - basegfx::B2DHomMatrix aMatrix; - basegfx::B2DPolyPolygon aPolyPolygon; - - pSdrGrafObj->TRGetBaseGeometry(aMatrix, aPolyPolygon); - - // decompose to have current translate and scale - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - - aMatrix.decompose(aScale, aTranslate, fRotate, fShearX); - - if(!aScale.equalZero()) - { - // get crop scale - const basegfx::B2DVector aCropScaleFactor( - pSdrGrafObj->GetGraphicObject().calculateCropScaling( - aScale.getX(), - aScale.getY(), - rCrop.GetLeft(), - rCrop.GetTop(), - rCrop.GetRight(), - rCrop.GetBottom())); - - // apply crop scale - const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX()); - const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY()); - const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX()); - const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY()); - - aHdl.AddHdl( - new SdrCropViewHdl( - aMatrix, - pSdrGrafObj->GetGraphicObject().GetGraphic(), - fCropLeft, - fCropTop, - fCropRight, - fCropBottom, - pSdrGrafObj->IsMirrored())); - } - } - } - - aHdl.AddHdl(new SdrCropHdl(aRect.TopLeft() ,HDL_UPLFT)); - aHdl.AddHdl(new SdrCropHdl(aRect.TopCenter() ,HDL_UPPER)); - aHdl.AddHdl(new SdrCropHdl(aRect.TopRight() ,HDL_UPRGT)); - aHdl.AddHdl(new SdrCropHdl(aRect.LeftCenter() ,HDL_LEFT )); - aHdl.AddHdl(new SdrCropHdl(aRect.RightCenter() ,HDL_RIGHT)); - aHdl.AddHdl(new SdrCropHdl(aRect.BottomLeft() ,HDL_LWLFT)); - aHdl.AddHdl(new SdrCropHdl(aRect.BottomCenter(),HDL_LOWER)); - aHdl.AddHdl(new SdrCropHdl(aRect.BottomRight() ,HDL_LWRGT)); - } else { bool bWdt0=aRect.Left()==aRect.Right(); @@ -802,47 +748,65 @@ void SdrMarkView::SetMarkHandles() } else { - for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) + bool bDone(false); + + // moved crop handling to non-frame part and the handle creation to SdrGrafObj + if(1 == nMarkAnz && pMarkedObj && SDRDRAG_CROP == eDragMode) { - const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); - SdrObject* pObj=pM->GetMarkedSdrObj(); - SdrPageView* pPV=pM->GetPageView(); - const sal_uIntPtr nSiz0=aHdl.GetHdlCount(); - pObj->AddToHdlList(aHdl); - const sal_uIntPtr nSiz1=aHdl.GetHdlCount(); - bool bPoly=pObj->IsPolyObj(); - const SdrUShortCont* pMrkPnts=pM->GetMarkedPoints(); - for (sal_uIntPtr i=nSiz0; i<nSiz1; i++) + const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pMarkedObj); + + if(pSdrGrafObj) + { + pSdrGrafObj->addCropHandles(aHdl); + bDone = true; + } + } + + if(!bDone) + { + for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) { - SdrHdl* pHdl=aHdl.GetHdl(i); - pHdl->SetPos( pHdl->GetPos() + aGridOff ); - pHdl->SetObj(pObj); - pHdl->SetPageView(pPV); - pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); - if (bPoly) + const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); + SdrObject* pObj=pM->GetMarkedSdrObj(); + SdrPageView* pPV=pM->GetPageView(); + const sal_uIntPtr nSiz0=aHdl.GetHdlCount(); + pObj->AddToHdlList(aHdl); + const sal_uIntPtr nSiz1=aHdl.GetHdlCount(); + bool bPoly=pObj->IsPolyObj(); + const SdrUShortCont* pMrkPnts=pM->GetMarkedPoints(); + for (sal_uIntPtr i=nSiz0; i<nSiz1; i++) { - sal_Bool bSelected=pMrkPnts!=NULL - && pMrkPnts->find( sal_uInt16(i-nSiz0) ) != pMrkPnts->end(); - pHdl->SetSelected(bSelected); - if (bPlusHdlAlways || bSelected) + SdrHdl* pHdl=aHdl.GetHdl(i); + pHdl->SetPos( pHdl->GetPos() + aGridOff ); + pHdl->SetObj(pObj); + pHdl->SetPageView(pPV); + pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); + + if (bPoly) { - sal_uInt32 nPlusAnz=pObj->GetPlusHdlCount(*pHdl); - for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusAnz; nPlusNum++) + sal_Bool bSelected=pMrkPnts!=NULL + && pMrkPnts->find( sal_uInt16(i-nSiz0) ) != pMrkPnts->end(); + pHdl->SetSelected(bSelected); + if (bPlusHdlAlways || bSelected) { - SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,nPlusNum); - if (pPlusHdl!=NULL) + sal_uInt32 nPlusAnz=pObj->GetPlusHdlCount(*pHdl); + for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusAnz; nPlusNum++) { - pPlusHdl->SetObj(pObj); - pPlusHdl->SetPageView(pPV); - pPlusHdl->SetPlusHdl(sal_True); - aHdl.AddHdl(pPlusHdl); + SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,nPlusNum); + if (pPlusHdl!=NULL) + { + pPlusHdl->SetObj(pObj); + pPlusHdl->SetPageView(pPV); + pPlusHdl->SetPlusHdl(sal_True); + aHdl.AddHdl(pPlusHdl); + } } } } } } - } // for nMarkNum - } // if bFrmHdl else + } + } // GluePoint handles for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index 00f28e30b6c4..58688bc3c7c5 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -55,6 +55,7 @@ #include <editeng/eeitem.hxx> #include <svx/sdr/properties/graphicproperties.hxx> #include <svx/sdr/contact/viewcontactofgraphic.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <osl/thread.hxx> @@ -1499,4 +1500,116 @@ Reference< XInputStream > SdrGrafObj::getInputStream() return xStream; } +// moved crop handle creation here; this is the object type using them +void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const +{ + basegfx::B2DHomMatrix aMatrix; + basegfx::B2DPolyPolygon aPolyPolygon; + + // get object transformation + TRGetBaseGeometry(aMatrix, aPolyPolygon); + + // part of object transformation correction, but used later, so defined outside next scope + double fShearX(0.0), fRotate(0.0); + + { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080 + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + + aMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + if(!basegfx::fTools::equalZero(fShearX)) + { + // shearX is used, correct it + fShearX = -fShearX; + } + + aMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + fShearX, + fRotate, + aTranslate); + } + + // get crop values + const SdrGrafCropItem& rCrop = static_cast< const SdrGrafCropItem& >(GetMergedItem(SDRATTR_GRAFCROP)); + + if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom()) + { + // decompose object transformation to have current translate and scale + basegfx::B2DVector aScale, aTranslate; + double fLclRotate, fLclShearX; + + aMatrix.decompose(aScale, aTranslate, fLclRotate, fLclShearX); + + if(!aScale.equalZero()) + { + // get crop scale + const basegfx::B2DVector aCropScaleFactor( + GetGraphicObject().calculateCropScaling( + aScale.getX(), + aScale.getY(), + rCrop.GetLeft(), + rCrop.GetTop(), + rCrop.GetRight(), + rCrop.GetBottom())); + + // apply crop scale + const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX()); + const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY()); + const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX()); + const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY()); + basegfx::B2DHomMatrix aMatrixForCropViewHdl(aMatrix); + + if(IsMirrored()) + { + // create corrected new matrix, TTTT can be removed with aw080 + // the old mirror only can mirror horizontally; the vertical mirror + // is faked by using the horizontal and 180 degree rotation. Since + // the object can be rotated differently from 180 degree, this is + // not safe to detect. Just correct horizontal mirror (which is + // in IsMirrored()) and keep the rotation angle + // caution: Do not modify aMatrix, it is used below to calculate + // the exact handle positions + basegfx::B2DHomMatrix aPreMultiply; + + // mirrored X, apply + aPreMultiply.translate(-0.5, 0.0); + aPreMultiply.scale(-1.0, 1.0); + aPreMultiply.translate(0.5, 0.0); + + aMatrixForCropViewHdl = aMatrixForCropViewHdl * aPreMultiply; + } + + rTarget.AddHdl( + new SdrCropViewHdl( + aMatrixForCropViewHdl, + GetGraphicObject().GetGraphic(), + fCropLeft, + fCropTop, + fCropRight, + fCropBottom)); + } + } + + basegfx::B2DPoint aPos; + + aPos = aMatrix * basegfx::B2DPoint(0.0, 0.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPLFT, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPPER, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPRGT, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LEFT , fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_RIGHT, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LWLFT, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LOWER, fShearX, fRotate)); + aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0); + rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LWRGT, fShearX, fRotate)); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |