[Libreoffice-commits] core.git: Branch 'aoo/trunk' - drawinglayer/source svtools/inc svtools/source svx/inc svx/source

Armin Le Grand alg at apache.org
Fri May 17 11:07:25 PDT 2013


 drawinglayer/source/primitive2d/cropprimitive2d.cxx    |    2 
 drawinglayer/source/primitive2d/graphicprimitive2d.cxx |   48 +--
 svtools/inc/svtools/grfmgr.hxx                         |   11 
 svtools/source/graphic/grfmgr.cxx                      |  109 +++++++--
 svx/inc/svx/svdhdl.hxx                                 |   38 +++
 svx/inc/svx/svdograf.hxx                               |    2 
 svx/source/svdraw/svdhdl.cxx                           |  205 ++++++++++++++++-
 svx/source/svdraw/svdmrkv.cxx                          |   51 ++++
 svx/source/unodraw/UnoGraphicExporter.cxx              |    3 
 9 files changed, 410 insertions(+), 59 deletions(-)

New commits:
commit a24965371f7e881671182bc51432c08cbf667b56
Author: Armin Le Grand <alg at apache.org>
Date:   Fri May 17 16:29:11 2013 +0000

    i74211 Correct crop of bitmap data when logical size and MapMode do not match real pixel size

diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
index f4b6e82..76dd206 100644
--- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
@@ -90,7 +90,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 088a315..b19c6c8 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -97,47 +97,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/svtools/inc/svtools/grfmgr.hxx b/svtools/inc/svtools/grfmgr.hxx
index 1155820..ca2e10b 100644
--- a/svtools/inc/svtools/grfmgr.hxx
+++ b/svtools/inc/svtools/grfmgr.hxx
@@ -470,6 +470,17 @@ public:
     friend SvStream&        operator>>( SvStream& rIStm, GraphicObject& rGraphicObj );
 
     static GraphicObject CreateGraphicObjectFromURL( const ::rtl::OUString &rURL );
+
+    // 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;
 };
 
 // ------------------
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx
index 795afab..425fe8b 100644
--- a/svtools/source/graphic/grfmgr.cxx
+++ b/svtools/source/graphic/grfmgr.cxx
@@ -1009,24 +1009,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() )
@@ -1092,12 +1121,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 );
@@ -1368,3 +1395,45 @@ GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &
         return GraphicObject( aGraphic );
     }
 }
+
+// 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);
+}
+
+// eof
diff --git a/svx/inc/svx/svdhdl.hxx b/svx/inc/svx/svdhdl.hxx
index e949431..e228515 100644
--- a/svx/inc/svx/svdhdl.hxx
+++ b/svx/inc/svx/svdhdl.hxx
@@ -42,6 +42,8 @@
 
 #include <svx/xpoly.hxx>
 #include <svx/svdoedge.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <svx/sdgcpitm.hxx>
 
 class VirtualDevice;
 class OutputDevice;
@@ -528,5 +530,41 @@ protected:
     static BitmapEx GetHandlesBitmap( bool bIsFineHdl, bool bIsHighContrast );
 };
 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+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
 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/svx/inc/svx/svdograf.hxx b/svx/inc/svx/svdograf.hxx
index a9751ed..a9fbb99 100644
--- a/svx/inc/svx/svdograf.hxx
+++ b/svx/inc/svx/svdograf.hxx
@@ -209,7 +209,7 @@ public:
 
     virtual void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
 
-    bool                    IsMirrored() { return bMirrored; }
+    bool                    IsMirrored() const { return bMirrored; }
     void                    SetMirrored( bool _bMirrored ) { bMirrored = _bMirrored; }
 
     // #111096#
diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx
index 41e1039..eaf28ae 100644
--- a/svx/source/svdraw/svdhdl.cxx
+++ b/svx/source/svdraw/svdhdl.cxx
@@ -63,6 +63,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 ressource problems in Win95/98 with bitmap ressources i
@@ -2433,4 +2440,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())
+        {
+            if(rPageWindow.GetOverlayManager())
+            {
+                ::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);
+
+                    rPageWindow.GetOverlayManager()->add(*pNew);
+                    maOverlayGroup.append(*pNew);
+                }
+            }
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// eof
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 5132140..bbf283b 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -55,6 +55,7 @@
 #include <svx/sdrpagewindow.hxx>
 #include <svx/sdrhittesthelper.hxx>
 #include <svx/svdocapt.hxx>
+#include <svx/svdograf.hxx>
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // predefines
@@ -761,6 +762,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 4b0e531..142874c 100644
--- a/svx/source/unodraw/UnoGraphicExporter.cxx
+++ b/svx/source/unodraw/UnoGraphicExporter.cxx
@@ -852,7 +852,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;
                         }
 


More information about the Libreoffice-commits mailing list