i124608 when exporting selection, use selection boundrect as svg canvas

Notes:

merged as: f864c09a9d6bc2c28b30b32c6a0825b5628826b2
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index 0a05141..a5746b38 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -31,6 +31,8 @@
#include "svgfilter.hxx"
#include "impsvgdialog.hxx"

#include <com/sun/star/graphic/XPrimitiveFactory2D.hpp>

#include <svx/unopage.hxx>
#include <svx/unoshape.hxx>
#include <svx/svdpage.hxx>
@@ -39,6 +41,8 @@
#include <editeng/flditem.hxx>
#include <editeng/numitem.hxx>

using namespace ::com::sun::star::graphic;
using namespace ::com::sun::star::geometry;
using ::rtl::OUString;

// -------------
@@ -398,6 +402,7 @@ sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterP
                "SVGFilter::implExportDocument: invalid parameter" );

    OUString        aAttr;
    sal_Int32       nDocX = 0, nDocY = 0; // #124608#
    sal_Int32       nDocWidth = 0, nDocHeight = 0;
    sal_Int32       nVisible = -1, nVisibleMaster = -1;
    sal_Bool        bRet = sal_False;
@@ -408,10 +413,61 @@ sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterP
    const Reference< XPropertySet >             xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
    const Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );

    if( xDefaultPagePropertySet.is() )
    // #124608#
    mbExportSelection = maShapeSelection.is() && maShapeSelection->getCount();

    if(xDefaultPagePropertySet.is())
    {
        xDefaultPagePropertySet->getPropertyValue( B2UCONST( "Width" ) ) >>= nDocWidth;
        xDefaultPagePropertySet->getPropertyValue( B2UCONST( "Height" ) ) >>= nDocHeight;
        xDefaultPagePropertySet->getPropertyValue(B2UCONST("Width")) >>= nDocWidth;
        xDefaultPagePropertySet->getPropertyValue(B2UCONST("Height")) >>= nDocHeight;
    }

    if(mbExportSelection)
    {
        // #124608# create BoundRange and set nDocX, nDocY, nDocWidth and nDocHeight
        basegfx::B2DRange aShapeRange;

        Reference< XPrimitiveFactory2D > xPrimitiveFactory(
            mxMSF->createInstance(
                String(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.graphic.PrimitiveFactory2D"))),
                UNO_QUERY);

        // use XPrimitiveFactory2D and go the way over getting the primitives; this
        // will give better precision (doubles) and be based on the true object
        // geometry. If needed aViewInformation may be expanded to carry a view
        // resolution for which to prepare the geometry.
        if(xPrimitiveFactory.is())
        {
            Reference< XShape > xShapeCandidate;
            const Sequence< PropertyValue > aViewInformation;
            const Sequence< PropertyValue > aParams;

            for(sal_Int32 a(0); a < maShapeSelection->getCount(); a++)
            {
                if((maShapeSelection->getByIndex(a) >>= xShapeCandidate) && xShapeCandidate.is())
                {
                    const Sequence< Reference< XPrimitive2D > > aPrimitiveSequence(
                        xPrimitiveFactory->createPrimitivesFromXShape( xShapeCandidate, aParams ));
                    const sal_Int32 nCount(aPrimitiveSequence.getLength());

                    for(sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
                    {
                        const RealRectangle2D aRect(aPrimitiveSequence[nIndex]->getRange(aViewInformation));

                        aShapeRange.expand(basegfx::B2DTuple(aRect.X1, aRect.Y1));
                        aShapeRange.expand(basegfx::B2DTuple(aRect.X2, aRect.Y2));
                    }
                }
            }
        }

        if(!aShapeRange.isEmpty())
        {
            nDocX = basegfx::fround(aShapeRange.getMinX());
            nDocY = basegfx::fround(aShapeRange.getMinY());
            nDocWidth  = basegfx::fround(aShapeRange.getWidth());
            nDocHeight = basegfx::fround(aShapeRange.getHeight());
        }
    }

    if( xExtDocHandler.is() && !mpSVGExport->IsUseTinyProfile() )
@@ -434,11 +490,23 @@ sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterP
    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
#endif

    aAttr = B2UCONST( "0 0 " );
    // #124608# set viewBox explicitely to the exported content
    if(mbExportSelection)
    {
        aAttr = OUString::valueOf( nDocX );
        aAttr += B2UCONST( " " );
        aAttr += OUString::valueOf( nDocY );
        aAttr += B2UCONST( " " );
    }
    else
    {
        aAttr = B2UCONST( "0 0 " );
    }

    aAttr += OUString::valueOf( nDocWidth );
    aAttr += B2UCONST( " " );
    aAttr += OUString::valueOf( nDocHeight );
    mpSVGExport->SetViewBox( Rectangle( Point(), Size( nDocWidth, nDocHeight ) ) );
    mpSVGExport->SetViewBox( Rectangle( Point(nDocX, nDocY), Size( nDocWidth, nDocHeight ) ) );
    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", B2UCONST( "xMidYMid" ) );
    mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", B2UCONST( "evenodd" ) );
@@ -514,7 +582,7 @@ sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterP
    {
        if(bSinglePage)
        {
            if(maShapeSelection.is() && maShapeSelection->getCount())
            if(mbExportSelection)
            {
                // #124608# export a given object selection, so no MasterPage export at all
            }
@@ -639,7 +707,7 @@ sal_Bool SVGFilter::implExportPages( const Reference< XDrawPages >& rxPages,
        {
            Reference< XShapes > xShapes;

            if(maShapeSelection.is() && maShapeSelection->getCount())
            if(mbExportSelection)
            {
                // #124608# export a given object selection
                xShapes = maShapeSelection;
@@ -924,7 +992,7 @@ sal_Bool SVGFilter::implCreateObjects( const Reference< XDrawPages >& rxMasterPa
        DBG_ASSERT( nPageToExport >= 0 && nPageToExport < rxDrawPages->getCount(),
                    "SVGFilter::implCreateObjects: invalid page number to export" );

        if(maShapeSelection.is() && maShapeSelection->getCount())
        if(mbExportSelection)
        {
            // #124608# export a given object selection
            implCreateObjectsFromShapes(maShapeSelection);
diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx
index 4b7bedd..4e4c5ab 100644
--- a/filter/source/svg/svgfilter.cxx
+++ b/filter/source/svg/svgfilter.cxx
@@ -52,7 +52,22 @@ SVGFilter::SVGFilter( const Reference< XMultiServiceFactory > &rxMSF ) :
    mpSVGWriter( NULL ),
    mpDefaultSdrPage( NULL ),
    mpSdrModel( NULL ),
    mbPresentation( sal_False )
    mbPresentation( sal_False ),
    mpObjects( NULL ),
    mxSrcDoc(),
#ifdef SOLAR_JAVA
    mxDstDoc(),
#endif
    mxDefaultPage(),
    maFilterData(),
    maShapeSelection(),
    mbExportSelection(false),
    maUniqueIdVector(),
    mnMasterSlideId(0),
    mnSlideId(0),
    mnDrawingGroupId(0),
    mnDrawingId(0),
    maOldFieldHdl()
{
}

diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
index e11e28f..b482207 100644
--- a/filter/source/svg/svgfilter.hxx
+++ b/filter/source/svg/svgfilter.hxx
@@ -249,6 +249,7 @@ private:

    // #124608# explicit ShapeSelection for export when export of the selection is wanted
    Reference< XShapes >                maShapeSelection;
    bool                                mbExportSelection;

    UniqueIdVector                      maUniqueIdVector;
    sal_Int32                           mnMasterSlideId;