diff options
author | Armin Le Grand <alg@apache.org> | 2013-05-17 16:29:11 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2013-06-17 15:39:48 +0100 |
commit | 3a8dbb63197c5b9298015cbd5b15e607ec9a3705 (patch) | |
tree | d7edd0ed73a7d7ebafd449c924bd54ea0aad9065 | |
parent | 997cc4804d947fdd751e457fda47f95ecf3ac909 (diff) |
Resolves: #i74211# Correct crop of bitmap data when...
logical size and MapMode do not match real pixel size
(cherry picked from commit a24965371f7e881671182bc51432c08cbf667b56)
Conflicts:
svtools/inc/svtools/grfmgr.hxx
svtools/source/graphic/grfmgr.cxx
svx/inc/svx/svdhdl.hxx
svx/inc/svx/svdograf.hxx
svx/source/svdraw/svdhdl.cxx
Change-Id: Icfb9091b55e50081e8daf697c9f00f5b5a10531a
-rw-r--r-- | drawinglayer/source/primitive2d/cropprimitive2d.cxx | 2 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/graphicprimitive2d.cxx | 48 | ||||
-rw-r--r-- | include/svtools/grfmgr.hxx | 11 | ||||
-rw-r--r-- | include/svx/svdhdl.hxx | 36 | ||||
-rw-r--r-- | svtools/source/graphic/grfmgr.cxx | 107 | ||||
-rw-r--r-- | svx/source/svdraw/svdhdl.cxx | 203 | ||||
-rw-r--r-- | svx/source/svdraw/svdmrkv.cxx | 51 | ||||
-rw-r--r-- | svx/source/unodraw/UnoGraphicExporter.cxx | 3 |
8 files changed, 403 insertions, 58 deletions
diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx index 8ce933afffe2..042710c516e3 100644 --- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx @@ -85,7 +85,7 @@ namespace drawinglayer // 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(fRotate, F_PI, 0.000000001)) + if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001)) { aScale.setX(aScale.getX() * -1.0); aScale.setY(aScale.getY() * -1.0); diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx index 778245ff12bc..df69a36cdd94 100644 --- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -85,47 +85,25 @@ namespace drawinglayer { // calculate scalings between real image size and logic object size. This // is necessary since the crop values are relative to original bitmap size - double fFactorX(1.0); - double fFactorY(1.0); - - { - const MapMode aMapMode100thmm(MAP_100TH_MM); - Size aBitmapSize(rGraphicObject.GetPrefSize()); - - // #i95968# better support PrefMapMode; special for MAP_PIXEL was missing - if(MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit()) - { - aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm); - } - else - { - aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm); - } - - const double fDivX(aBitmapSize.Width() - getGraphicAttr().GetLeftCrop() - getGraphicAttr().GetRightCrop()); - const double fDivY(aBitmapSize.Height() - getGraphicAttr().GetTopCrop() - getGraphicAttr().GetBottomCrop()); - const basegfx::B2DVector aScale(aTransform * basegfx::B2DVector(1.0, 1.0)); - - if(!basegfx::fTools::equalZero(fDivX)) - { - fFactorX = fabs(aScale.getX()) / fDivX; - } - - if(!basegfx::fTools::equalZero(fDivY)) - { - fFactorY = fabs(aScale.getY()) / fDivY; - } - } + const basegfx::B2DVector aObjectScale(aTransform * basegfx::B2DVector(1.0, 1.0)); + const basegfx::B2DVector aCropScaleFactor( + rGraphicObject.calculateCropScaling( + aObjectScale.getX(), + aObjectScale.getY(), + getGraphicAttr().GetLeftCrop(), + getGraphicAttr().GetTopCrop(), + getGraphicAttr().GetRightCrop(), + getGraphicAttr().GetBottomCrop())); // embed content in cropPrimitive Primitive2DReference xPrimitive( new CropPrimitive2D( aRetval, aTransform, - getGraphicAttr().GetLeftCrop() * fFactorX, - getGraphicAttr().GetTopCrop() * fFactorY, - getGraphicAttr().GetRightCrop() * fFactorX, - getGraphicAttr().GetBottomCrop() * fFactorY)); + getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(), + getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(), + getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(), + getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY())); aRetval = Primitive2DSequence(&xPrimitive, 1); } diff --git a/include/svtools/grfmgr.hxx b/include/svtools/grfmgr.hxx index 9a3bd8c1d1ff..0523cc24d804 100644 --- a/include/svtools/grfmgr.hxx +++ b/include/svtools/grfmgr.hxx @@ -493,6 +493,17 @@ public: // will cater for XNameContainer objects and deepinspect any containees // if they exist static void InspectForGraphicObjectImageURL( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIf, std::vector< OUString >& rvEmbedImgUrls ); + + // create CropScaling information + // fWidth, fHeight: object size + // f*Crop: crop values relative to original bitmap size + basegfx::B2DVector calculateCropScaling( + double fWidth, + double fHeight, + double fLeftCrop, + double fTopCrop, + double fRightCrop, + double fBottomCrop) const; }; typedef ::std::vector< GraphicObject* > GraphicObjectList_impl; diff --git a/include/svx/svdhdl.hxx b/include/svx/svdhdl.hxx index 207b3f494967..ce8dad2712f1 100644 --- a/include/svx/svdhdl.hxx +++ b/include/svx/svdhdl.hxx @@ -28,6 +28,8 @@ #include <svx/xpoly.hxx> #include <svx/svdoedge.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <svx/sdgcpitm.hxx> #include <svx/sdr/overlay/overlayobjectlist.hxx> #include "svx/svxdllapi.h" @@ -512,6 +514,40 @@ protected: static BitmapEx GetHandlesBitmap(); }; +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class SVX_DLLPUBLIC SdrCropViewHdl : public SdrHdl +{ +private: + basegfx::B2DHomMatrix maObjectTransform; + Graphic maGraphic; + double mfCropLeft; + double mfCropTop; + 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, + const Graphic& rGraphic, + double fCropLeft, + double fCropTop, + double fCropRight, + double fCropBottom, + bool bExtraMirrorXFromGraphic); + +protected: + // create marker for this kind + virtual void CreateB2dIAObject(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + #endif //_SVDHDL_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx index 136aa578e961..6577c0ef1d89 100644 --- a/svtools/source/graphic/grfmgr.cxx +++ b/svtools/source/graphic/grfmgr.cxx @@ -842,24 +842,53 @@ Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMo } else if( GRAPHIC_BITMAP == eType ) { - BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() ); - - // convert crops to pixel - aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetLeftCrop(), - rAttr.GetTopCrop() ), - aMap100 ); - aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( Size( rAttr.GetRightCrop(), - rAttr.GetBottomCrop() ), - aMap100 ); + BitmapEx aBitmapEx( aTransGraphic.GetBitmapEx() ); + Rectangle aCropRect; - // convert from prefmapmode to pixel - const Size aSrcSizePixel( Application::GetDefaultDevice()->LogicToPixel( aSrcSize, - aMapGraph ) ); + // convert crops to pixel (crops are always in GraphicObject units) + if(rAttr.IsCropped()) + { + aCropLeftTop = Application::GetDefaultDevice()->LogicToPixel( + Size(rAttr.GetLeftCrop(), rAttr.GetTopCrop()), + aMapGraph); + aCropRightBottom = Application::GetDefaultDevice()->LogicToPixel( + Size(rAttr.GetRightCrop(), rAttr.GetBottomCrop()), + aMapGraph); + + // convert from prefmapmode to pixel + Size aSrcSizePixel( + Application::GetDefaultDevice()->LogicToPixel( + aSrcSize, + aMapGraph)); + + if(rAttr.IsCropped() + && (aSrcSizePixel.Width() != aBitmapEx.GetSizePixel().Width() || aSrcSizePixel.Height() != aBitmapEx.GetSizePixel().Height()) + && aSrcSizePixel.Width()) + { + // the size in pixels calculated from Graphic's internal MapMode (aTransGraphic.GetPrefMapMode()) + // and it's internal size (aTransGraphic.GetPrefSize()) is different from it's real pixel size. + // This can be interpreted as this values to be set wrong, but needs to be corrected since e.g. + // existing cropping is calculated based on this logic values already. + // aBitmapEx.Scale(aSrcSizePixel); + + // another possibility is to adapt the values created so far with a factor; this + // will keep the original Bitmap untouched and thus quality will not change + const double fFactorX(aBitmapEx.GetSizePixel().Width() / aSrcSizePixel.Width()); + const double fFactorY(aBitmapEx.GetSizePixel().Height() / aSrcSizePixel.Height()); + + aCropLeftTop.Width() = basegfx::fround(aCropLeftTop.Width() * fFactorX); + aCropLeftTop.Height() = basegfx::fround(aCropLeftTop.Height() * fFactorY); + aCropRightBottom.Width() = basegfx::fround(aCropRightBottom.Width() * fFactorX); + aCropRightBottom.Height() = basegfx::fround(aCropRightBottom.Height() * fFactorY); + + aSrcSizePixel = aBitmapEx.GetSizePixel(); + } - // setup crop rectangle in pixel - Rectangle aCropRect( aCropLeftTop.Width(), aCropLeftTop.Height(), - aSrcSizePixel.Width() - aCropRightBottom.Width(), - aSrcSizePixel.Height() - aCropRightBottom.Height() ); + // setup crop rectangle in pixel + aCropRect = Rectangle( aCropLeftTop.Width(), aCropLeftTop.Height(), + aSrcSizePixel.Width() - aCropRightBottom.Width(), + aSrcSizePixel.Height() - aCropRightBottom.Height() ); + } // #105641# Also crop animations if( aTransGraphic.IsAnimated() ) @@ -925,12 +954,10 @@ Graphic GraphicObject::GetTransformedGraphic( const Size& rDestSize, const MapMo } else { - BitmapEx aBmpEx( aTransGraphic.GetBitmapEx() ); - - ImplTransformBitmap( aBmpEx, rAttr, aCropLeftTop, aCropRightBottom, + ImplTransformBitmap( aBitmapEx, rAttr, aCropLeftTop, aCropRightBottom, aCropRect, rDestSize, sal_True ); - aTransGraphic = aBmpEx; + aTransGraphic = aBitmapEx; } aTransGraphic.SetPrefSize( rDestSize ); @@ -1175,4 +1202,44 @@ GraphicObject::InspectForGraphicObjectImageURL( const Reference< XInterface >& x } } +// calculate scalings between real image size and logic object size. This +// is necessary since the crop values are relative to original bitmap size +basegfx::B2DVector GraphicObject::calculateCropScaling( + double fWidth, + double fHeight, + double fLeftCrop, + double fTopCrop, + double fRightCrop, + double fBottomCrop) const +{ + const MapMode aMapMode100thmm(MAP_100TH_MM); + Size aBitmapSize(GetPrefSize()); + double fFactorX(1.0); + double fFactorY(1.0); + + if(MAP_PIXEL == GetPrefMapMode().GetMapUnit()) + { + aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm); + } + else + { + aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, GetPrefMapMode(), aMapMode100thmm); + } + + const double fDivX(aBitmapSize.Width() - fLeftCrop - fRightCrop); + const double fDivY(aBitmapSize.Height() - fTopCrop - fBottomCrop); + + if(!basegfx::fTools::equalZero(fDivX)) + { + fFactorX = fabs(fWidth) / fDivX; + } + + if(!basegfx::fTools::equalZero(fDivY)) + { + fFactorY = fabs(fHeight) / fDivY; + } + + return basegfx::B2DVector(fFactorX,fFactorY); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx index 5a03983b0c64..323deaf76a6d 100644 --- a/svx/source/svdraw/svdhdl.cxx +++ b/svx/source/svdraw/svdhdl.cxx @@ -57,6 +57,13 @@ #include <svx/sdr/overlay/overlaypolypolygon.hxx> #include <vcl/lazydelete.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> +#include <drawinglayer/primitive2d/graphicprimitive2d.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> + //////////////////////////////////////////////////////////////////////////////////////////////////// // #i15222# // Due to the resource problems in Win95/98 with bitmap resources I @@ -2329,6 +2336,200 @@ void SdrCropHdl::CreateB2dIAObject() } } -// -------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrCropViewHdl::SdrCropViewHdl( + const basegfx::B2DHomMatrix& rObjectTransform, + const Graphic& rGraphic, + double fCropLeft, + double fCropTop, + double fCropRight, + double fCropBottom, + bool bExtraMirrorXFromGraphic) +: SdrHdl(Point(), HDL_USER), + maObjectTransform(rObjectTransform), + maGraphic(rGraphic), + mfCropLeft(fCropLeft), + mfCropTop(fCropTop), + mfCropRight(fCropRight), + mfCropBottom(fCropBottom), + mbExtraMirrorXFromGraphic(bExtraMirrorXFromGraphic) +{ +} + +void SdrCropViewHdl::CreateB2dIAObject() +{ + GetRidOfIAObject(); + SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0; + SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0; + + if(pPageView && pView->areMarkHandlesHidden()) + { + return; + } + + // decompose to have current translate and scale + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); + + if(aScale.equalZero()) + { + return; + } + + // 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; + } + + // remember mirroring, reset at Scale and adapt crop values for usage; + // mirroring can stay in the object transformation, so do not have to + // cope with it here (except later for the CroppedImage transformation, + // see below) + const bool bMirroredX(aScale.getX() < 0.0); + const bool bMirroredY(aScale.getY() < 0.0); + double fCropLeft(mfCropLeft); + double fCropTop(mfCropTop); + double fCropRight(mfCropRight); + double fCropBottom(mfCropBottom); + + 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 + const basegfx::B2DVector aTargetScale( + aScale.getX() + fCropRight + fCropLeft, + aScale.getY() + fCropBottom + fCropTop); + const basegfx::B2DVector aTargetTranslate( + aTranslate.getX() - fCropLeft, + aTranslate.getY() - fCropTop); + + // create ranges to make comparisons + const basegfx::B2DRange aCurrentForCompare( + aTranslate.getX(), aTranslate.getY(), + aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); + basegfx::B2DRange aCropped( + aTargetTranslate.getX(), aTargetTranslate.getY(), + aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); + + if(aCropped.isEmpty()) + { + // nothing to return since cropped content is completely empty + return; + } + + if(aCurrentForCompare.equal(aCropped)) + { + // no crop at all + return; + } + + // back-transform to have values in unit coordinates + basegfx::B2DHomMatrix aBackToUnit; + aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY()); + aBackToUnit.scale( + basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(), + basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY()); + + // transform cropped back to unit coordinates + aCropped.transform(aBackToUnit); + + // prepare crop PolyPolygon + basegfx::B2DPolyPolygon aCropPolyPolygon( + basegfx::tools::createPolygonFromRect( + aCropped)); + + // current range is unit range + basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0); + + aOverlap.intersect(aCropped); + + if(!aOverlap.isEmpty()) + { + aCropPolyPolygon.append( + basegfx::tools::createPolygonFromRect( + aOverlap)); + } + + // transform to object coordinates to prepare for clip + aCropPolyPolygon.transform(maObjectTransform); + + // create cropped transformation + basegfx::B2DHomMatrix aCroppedTransform; + const bool bCombinedMirrorX(mbExtraMirrorXFromGraphic || bMirroredX); + + aCroppedTransform.scale( + bCombinedMirrorX ? -aCropped.getWidth() : aCropped.getWidth(), + bMirroredY ? -aCropped.getHeight() : aCropped.getHeight()); + aCroppedTransform.translate( + bCombinedMirrorX ? aCropped.getMaxX() : aCropped.getMinX(), + bMirroredY ? aCropped.getMaxY() : aCropped.getMinY()); + aCroppedTransform = maObjectTransform * aCroppedTransform; + + // prepare graphic primitive (tranformed) + const drawinglayer::primitive2d::Primitive2DReference aGraphic( + new drawinglayer::primitive2d::GraphicPrimitive2D( + aCroppedTransform, + maGraphic)); + + // embed to MaskPrimitive2D + const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic( + new drawinglayer::primitive2d::MaskPrimitive2D( + aCropPolyPolygon, + drawinglayer::primitive2d::Primitive2DSequence(&aGraphic, 1))); + + // embed to UnifiedTransparencePrimitive2D + const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic( + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + drawinglayer::primitive2d::Primitive2DSequence(&aMaskedGraphic, 1), + 0.8)); + + const drawinglayer::primitive2d::Primitive2DSequence aSequence(&aTransparenceMaskedGraphic, 1); + + for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++) + { + // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b]; + const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b); + + if(rPageWindow.GetPaintWindow().OutputToWindow()) + { + rtl::Reference< ::sdr::overlay::OverlayManager > xManager = rPageWindow.GetOverlayManager(); + if(xManager.is()) + { + ::sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence); + DBG_ASSERT(pNew, "Got NO new IAO!"); + + if(pNew) + { + // only informative object, no hit + pNew->setHittable(false); + + xManager->add(*pNew); + maOverlayGroup.append(*pNew); + } + } + } + } +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx index ff27728c1d09..cefe73b1cf8b 100644 --- a/svx/source/svdraw/svdmrkv.cxx +++ b/svx/source/svdraw/svdmrkv.cxx @@ -48,6 +48,7 @@ #include <svx/sdrpagewindow.hxx> #include <svx/sdrhittesthelper.hxx> #include <svx/svdocapt.hxx> +#include <svx/svdograf.hxx> #include <editeng/editdata.hxx> @@ -667,6 +668,56 @@ void SdrMarkView::SetMarkHandles() } 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)); diff --git a/svx/source/unodraw/UnoGraphicExporter.cxx b/svx/source/unodraw/UnoGraphicExporter.cxx index fb9e790bd308..69ac409fe9e3 100644 --- a/svx/source/unodraw/UnoGraphicExporter.cxx +++ b/svx/source/unodraw/UnoGraphicExporter.cxx @@ -822,7 +822,8 @@ bool GraphicExporter::GetGraphic( ExportSettings& rSettings, Graphic& aGraphic, ( rSettings.mnHeight != aSizePixel.Height() ) ) ) { BitmapEx aBmpEx( aGraphic.GetBitmapEx() ); - aBmpEx.Scale( Size( rSettings.mnWidth, rSettings.mnHeight ) ); + // export: use highest quality + aBmpEx.Scale( Size( rSettings.mnWidth, rSettings.mnHeight ), BMP_SCALE_LANCZOS ); aGraphic = aBmpEx; } |