/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "unointerfacetouniqueidentifiermapper.hxx"
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/ConnectorType.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <com/sun/star/media/ZoomLevel.hpp>
#include "anim.hxx"
#include <xmloff/shapeexport.hxx>
#include "sdpropls.hxx"
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <rtl/ustrbuf.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmluconv.hxx>
#include "XMLImageMapExport.hxx"
#include "xexptran.hxx"
#include <tools/gen.hxx>		// FRound
#include <xmloff/xmltoken.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;

using namespace ::com::sun::star;
using namespace ::xmloff::token;


//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportNewTrans(const uno::Reference< beans::XPropertySet >& xPropSet,
	sal_Int32 nFeatures, awt::Point* pRefPoint)
{
	// get matrix
	::basegfx::B2DHomMatrix aMatrix;
	ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);

	// decompose and correct abour pRefPoint
	::basegfx::B2DTuple aTRScale;
	double fTRShear(0.0);
	double fTRRotate(0.0);
	::basegfx::B2DTuple aTRTranslate;
	ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);

	// use features and write
	ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
}

void XMLShapeExport::ImpExportNewTrans_GetB2DHomMatrix(::basegfx::B2DHomMatrix& rMatrix,
    const uno::Reference< beans::XPropertySet >& xPropSet)
{
    // --> OD 2004-08-09 #i28749# - Get <TransformationInHoriL2R>, if it exist
    // and if the document is exported into the OpenOffice.org file format.
    // This property only exists at service com::sun::star::text::Shape - the
    // Writer UNO service for shapes.
    // This code is needed, because the positioning attributes in the
    // OpenOffice.org file format are given in horizontal left-to-right layout
    // regardless the layout direction the shape is in. In the OASIS Open Office
    // file format the positioning attributes are correctly given in the layout
    // direction the shape is in. Thus, this code provides the conversion from
    // the OASIS Open Office file format to the OpenOffice.org file format.
    uno::Any aAny;
    if ( ( GetExport().getExportFlags() & EXPORT_OASIS ) == 0 &&
         xPropSet->getPropertySetInfo()->hasPropertyByName(
            OUString(RTL_CONSTASCII_USTRINGPARAM("TransformationInHoriL2R"))) )
    {
        aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TransformationInHoriL2R")));
    }
    else
    {
        aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
    }
    // <--
    drawing::HomogenMatrix3 aMatrix;
    aAny >>= aMatrix;
    rMatrix = basegfx::tools::UnoHomogenMatrix3ToB2DHomMatrix(aMatrix);
}

void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix& rMatrix, ::basegfx::B2DTuple& rTRScale,
    double& fTRShear, double& fTRRotate, ::basegfx::B2DTuple& rTRTranslate, com::sun::star::awt::Point* pRefPoint)
{
    // decompose matrix
    rMatrix.decompose(rTRScale, rTRTranslate, fTRRotate, fTRShear);

    // correct translation about pRefPoint
    if(pRefPoint)
    {
        rTRTranslate -= ::basegfx::B2DTuple(pRefPoint->X, pRefPoint->Y);
    }
}

void XMLShapeExport::ImpExportNewTrans_FeaturesAndWrite(::basegfx::B2DTuple& rTRScale, double fTRShear,
    double fTRRotate, ::basegfx::B2DTuple& rTRTranslate, const sal_Int32 nFeatures)
{
    // allways write Size (rTRScale) since this statement carries the union
    // of the object
    OUString aStr;
    OUStringBuffer sStringBuffer;
    ::basegfx::B2DTuple aTRScale(rTRScale);

    // svg: width
    if(!(nFeatures & SEF_EXPORT_WIDTH))
    {
        aTRScale.setX(1.0);
    }

    // svg: height
    if(!(nFeatures & SEF_EXPORT_HEIGHT))
    {
        aTRScale.setY(1.0);
    }

    // svg:width and svg:height are not allowed negative, extract that and
    // set back to absolute values
    bool bMirrorX(basegfx::fTools::less(aTRScale.getX(), 0.0));
    bool bMirrorY(basegfx::fTools::less(aTRScale.getY(), 0.0));

    if(bMirrorX)
    {
        aTRScale.setX(-aTRScale.getX());
    }

    if(bMirrorY)
    {
        aTRScale.setY(-aTRScale.getY());
    }

    // write positive svg:width
    mrExport.GetMM100UnitConverter().convertDoubleAndUnit(sStringBuffer, aTRScale.getX());
    //mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(aTRScale.getX()));
    aStr = sStringBuffer.makeStringAndClear();
    mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStr);

    // write positive svg:height
    mrExport.GetMM100UnitConverter().convertDoubleAndUnit(sStringBuffer, aTRScale.getY());
    //mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(aTRScale.getY()));
    aStr = sStringBuffer.makeStringAndClear();
    mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStr);

    // decide if transformation is neccessary, new is that mirrorings are now
    // part of this to not write negative svg:width or svg:height entries
    const bool bTransformationIsNeccessary(fTRShear != 0.0 || fTRRotate != 0.0 || bMirrorX || bMirrorY);

    if(bTransformationIsNeccessary)
    {
        // write transformation, but WITHOUT scale which is exported as size above
        SdXMLImExTransform2D aTransform;

        if(bMirrorX || bMirrorY)
        {
            // add mirrorings if used
            aTransform.AddScale(basegfx::B2DTuple(bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0));
        }

        // Export Shear mirrored to stay compatible to ODF1.3
        if(!basegfx::fTools::equalZero(fTRShear))
        {
            aTransform.AddSkewX(atan(-fTRShear));
        }

        // #i78696# 
        // fTRRotate is mathematically correct, but due to the error
        // we export/import it mirrored. Since the API implementation is fixed and
        // uses the correctly oriented angle, it is necessary for compatibility to
        // mirror the angle here to stay at the old behaviour. There is a follow-up
        // task (#i78698#) to fix this in the next ODF FileFormat version
        if(!basegfx::fTools::equalZero(fTRRotate))
        {
            aTransform.AddRotate(-fTRRotate);
        }

        // process translation; copy and evtl. detect non-writes
        ::basegfx::B2DTuple aTRTranslate(rTRTranslate);

        if(!(nFeatures & SEF_EXPORT_X))
        {
            aTRTranslate.setX(0.0);
        }

        if(!(nFeatures & SEF_EXPORT_Y))
        {
            aTRTranslate.setY(0.0);
        }

        if(!basegfx::fTools::equalZero(aTRTranslate.getX()) || !basegfx::fTools::equalZero(aTRTranslate.getY()))
        {
            aTransform.AddTranslate(aTRTranslate);
        }

        // does transformation need to be exported?
        if(aTransform.NeedsAction())
        {
            mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
        }
    }
    else
    {
        // no shear, no rotate, no mirror; just add object position to export and we are done
        if(nFeatures & SEF_EXPORT_X)
        {
            // svg: x
            mrExport.GetMM100UnitConverter().convertDoubleAndUnit(sStringBuffer, rTRTranslate.getX());
            //mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(rTRTranslate.getX()));
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, aStr);
        }

        if(nFeatures & SEF_EXPORT_Y)
        {
            // svg: y
            mrExport.GetMM100UnitConverter().convertDoubleAndUnit(sStringBuffer, rTRTranslate.getY());
            //mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(rTRTranslate.getY()));
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y, aStr);
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

sal_Bool XMLShapeExport::ImpExportPresentationAttributes( const uno::Reference< beans::XPropertySet >& xPropSet, const rtl::OUString& rClass )
{
	sal_Bool bIsEmpty = sal_False;

	OUStringBuffer sStringBuffer;

	// write presentation class entry
	mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_CLASS, rClass);

	if( xPropSet.is() )
	{
		uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );

		sal_Bool bTemp = false;

		// is empty pes shape?
		if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IsEmptyPresentationObject"))))
		{
			xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("IsEmptyPresentationObject"))) >>= bIsEmpty;
			if( bIsEmpty )
				mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_PLACEHOLDER, XML_TRUE);
		}

		// is user-transformed?
		if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IsPlaceholderDependent"))))
		{
			xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("IsPlaceholderDependent"))) >>= bTemp;
			if(!bTemp)
				mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_USER_TRANSFORMED, XML_TRUE);
		}
	}

	return bIsEmpty;
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportText( const uno::Reference< drawing::XShape >& xShape )
{
	uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
	if( xText.is() )
	{
		uno::Reference< container::XEnumerationAccess > xEnumAccess( xShape, uno::UNO_QUERY );
		if( xEnumAccess.is() && xEnumAccess->hasElements() )
			mrExport.GetTextParagraphExport()->exportText( xText );
	}
}

//////////////////////////////////////////////////////////////////////////////
#include <com/sun/star/presentation/ClickAction.hpp>
#include <com/sun/star/presentation/AnimationSpeed.hpp>

namespace {

const sal_Int32 FOUND_CLICKACTION       = 0x00000001;
const sal_Int32 FOUND_BOOKMARK          = 0x00000002;
const sal_Int32 FOUND_EFFECT            = 0x00000004;
const sal_Int32 FOUND_PLAYFULL          = 0x00000008;
const sal_Int32 FOUND_VERB              = 0x00000010;
const sal_Int32 FOUND_SOUNDURL          = 0x00000020;
const sal_Int32 FOUND_SPEED             = 0x00000040;
const sal_Int32 FOUND_CLICKEVENTTYPE    = 0x00000080;
const sal_Int32 FOUND_MACRO             = 0x00000100;
const sal_Int32 FOUND_LIBRARY           = 0x00000200;
const sal_Int32 FOUND_ACTIONEVENTTYPE   = 0x00000400;
#ifdef ISSUE66550_HLINK_FOR_SHAPES
const sal_Int32 FOUND_URL               = 0x00000800;
#endif

} // namespace

void XMLShapeExport::ImpExportEvents( const uno::Reference< drawing::XShape >& xShape )
{
    uno::Reference< document::XEventsSupplier > xEventsSupplier( xShape, uno::UNO_QUERY );
    if( !xEventsSupplier.is() )
        return;

    uno::Reference< container::XNameAccess > xEvents( xEventsSupplier->getEvents(), uno::UNO_QUERY );
    DBG_ASSERT( xEvents.is(), "XEventsSupplier::getEvents() returned NULL" );
    if( !xEvents.is() )
        return;

    sal_Int32 nFound = 0;

    // extract properties from "OnClick" event --------------------------------

    OUString aClickEventType;
    presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
    presentation::AnimationEffect eEffect = presentation::AnimationEffect_NONE;
    presentation::AnimationSpeed eSpeed = presentation::AnimationSpeed_SLOW;
    OUString aStrSoundURL;
    sal_Bool bPlayFull = false;
    sal_Int32 nVerb = 0;
    OUString aStrMacro;
    OUString aStrLibrary;
    OUString aStrBookmark;

    uno::Sequence< beans::PropertyValue > aClickProperties;
    if( xEvents->hasByName( msOnClick ) && (xEvents->getByName( msOnClick ) >>= aClickProperties) )
    {
        const beans::PropertyValue* pProperty = aClickProperties.getConstArray();
        const beans::PropertyValue* pPropertyEnd = pProperty + aClickProperties.getLength();
        for( ; pProperty != pPropertyEnd; ++pProperty )
        {
            if( ( ( nFound & FOUND_CLICKEVENTTYPE ) == 0 ) && pProperty->Name == msEventType )
            {
                if( pProperty->Value >>= aClickEventType )
                    nFound |= FOUND_CLICKEVENTTYPE;
            }
            else if( ( ( nFound & FOUND_CLICKACTION ) == 0 ) && pProperty->Name == msClickAction )
            {
                if( pProperty->Value >>= eClickAction )
                    nFound |= FOUND_CLICKACTION;
            }
            else if( ( ( nFound & FOUND_MACRO ) == 0 ) && ( pProperty->Name == msMacroName || pProperty->Name == msScript ) )
            {
                if( pProperty->Value >>= aStrMacro )
                    nFound |= FOUND_MACRO;
            }
            else if( ( ( nFound & FOUND_LIBRARY ) == 0 ) && pProperty->Name == msLibrary )
            {
                if( pProperty->Value >>= aStrLibrary )
                    nFound |= FOUND_LIBRARY;
            }
            else if( ( ( nFound & FOUND_EFFECT ) == 0 ) && pProperty->Name == msEffect )
            {
                if( pProperty->Value >>= eEffect )
                    nFound |= FOUND_EFFECT;
            }
            else if( ( ( nFound & FOUND_BOOKMARK ) == 0 ) && pProperty->Name == msBookmark )
            {
                if( pProperty->Value >>= aStrBookmark )
                    nFound |= FOUND_BOOKMARK;
            }
            else if( ( ( nFound & FOUND_SPEED ) == 0 ) && pProperty->Name == msSpeed )
            {
                if( pProperty->Value >>= eSpeed )
                    nFound |= FOUND_SPEED;
            }
            else if( ( ( nFound & FOUND_SOUNDURL ) == 0 ) && pProperty->Name == msSoundURL )
            {
                if( pProperty->Value >>= aStrSoundURL )
                    nFound |= FOUND_SOUNDURL;
            }
            else if( ( ( nFound & FOUND_PLAYFULL ) == 0 ) && pProperty->Name == msPlayFull )
            {
                if( pProperty->Value >>= bPlayFull )
                    nFound |= FOUND_PLAYFULL;
            }
            else if( ( ( nFound & FOUND_VERB ) == 0 ) && pProperty->Name == msVerb )
            {
                if( pProperty->Value >>= nVerb )
                    nFound |= FOUND_VERB;
            }
        }
    }

#ifdef ISSUE66550_HLINK_FOR_SHAPES
    // extract properties from "OnAction" event -------------------------------

    OUString aActionEventType;
    OUString aHyperURL;

    uno::Sequence< beans::PropertyValue > aActionProperties;
    if( xEvents->hasByName( msOnAction ) && (xEvents->getByName( msOnAction ) >>= aActionProperties) )
    {
        const beans::PropertyValue* pProperty = aActionProperties.getConstArray();
        const beans::PropertyValue* pPropertyEnd = pProperty + aActionProperties.getLength();
        for( ; pProperty != pPropertyEnd; ++pProperty )
        {
            if( ( ( nFound & FOUND_ACTIONEVENTTYPE ) == 0 ) && pProperty->Name == msEventType )
            {
                if( pProperty->Value >>= aActionEventType )
                    nFound |= FOUND_ACTIONEVENTTYPE;
            }
            else if( ( ( nFound & FOUND_URL ) == 0 ) && ( pProperty->Name == msURL  ) )
            {
                if( pProperty->Value >>= aHyperURL )
                    nFound |= FOUND_URL;
            }
        }
    }
#endif

    // create the XML elements

    if( aClickEventType == msPresentation )
    {
        if( ((nFound & FOUND_CLICKACTION) == 0) || (eClickAction == presentation::ClickAction_NONE) )
            return;

        SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_OFFICE, XML_EVENT_LISTENERS, sal_True, sal_True);

        enum XMLTokenEnum eStrAction;

        switch( eClickAction )
        {
            case presentation::ClickAction_PREVPAGE:        eStrAction = XML_PREVIOUS_PAGE; break;
            case presentation::ClickAction_NEXTPAGE:        eStrAction = XML_NEXT_PAGE; break;
            case presentation::ClickAction_FIRSTPAGE:       eStrAction = XML_FIRST_PAGE; break;
            case presentation::ClickAction_LASTPAGE:        eStrAction = XML_LAST_PAGE; break;
            case presentation::ClickAction_INVISIBLE:       eStrAction = XML_HIDE; break;
            case presentation::ClickAction_STOPPRESENTATION:eStrAction = XML_STOP; break;
            case presentation::ClickAction_PROGRAM:         eStrAction = XML_EXECUTE; break;
            case presentation::ClickAction_BOOKMARK:        eStrAction = XML_SHOW; break;
            case presentation::ClickAction_DOCUMENT:        eStrAction = XML_SHOW; break;
            case presentation::ClickAction_MACRO:           eStrAction = XML_EXECUTE_MACRO; break;
            case presentation::ClickAction_VERB:            eStrAction = XML_VERB; break;
            case presentation::ClickAction_VANISH:          eStrAction = XML_FADE_OUT; break;
            case presentation::ClickAction_SOUND:           eStrAction = XML_SOUND; break;
            default:
                DBG_ERROR( "unknown presentation::ClickAction found!" );
                eStrAction = XML_UNKNOWN;
        }

        OUString aEventQName(
            mrExport.GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_DOM, OUString( RTL_CONSTASCII_USTRINGPARAM( "click" ) ) ) );
        mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, aEventQName );
        mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_ACTION, eStrAction );

        if( eClickAction == presentation::ClickAction_VANISH )
        {
            if( nFound & FOUND_EFFECT )
            {
                XMLEffect eKind;
                XMLEffectDirection eDirection;
                sal_Int16 nStartScale;
                sal_Bool bIn;

                SdXMLImplSetEffect( eEffect, eKind, eDirection, nStartScale, bIn );

                if( eKind != EK_none )
                {
                    SvXMLUnitConverter::convertEnum( msBuffer, eKind, aXML_AnimationEffect_EnumMap );
                    mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_EFFECT, msBuffer.makeStringAndClear() );
                }

                if( eDirection != ED_none )
                {
                    SvXMLUnitConverter::convertEnum( msBuffer, eDirection, aXML_AnimationDirection_EnumMap );
                    mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_DIRECTION, msBuffer.makeStringAndClear() );
                }

                if( nStartScale != -1 )
                {
                    SvXMLUnitConverter::convertPercent( msBuffer, nStartScale );
                    mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_START_SCALE, msBuffer.makeStringAndClear() );
                }
            }

            if( nFound & FOUND_SPEED && eEffect != presentation::AnimationEffect_NONE )
            {
                 if( eSpeed != presentation::AnimationSpeed_MEDIUM )
                    {
                    SvXMLUnitConverter::convertEnum( msBuffer, eSpeed, aXML_AnimationSpeed_EnumMap );
                    mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_SPEED, msBuffer.makeStringAndClear() );
                }
            }
        }

        if( eClickAction == presentation::ClickAction_PROGRAM ||
            eClickAction == presentation::ClickAction_BOOKMARK ||
            eClickAction == presentation::ClickAction_DOCUMENT )
        {
            if( eClickAction == presentation::ClickAction_BOOKMARK )
                msBuffer.append( sal_Unicode('#') );

            msBuffer.append( aStrBookmark );
            mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(msBuffer.makeStringAndClear()) );
            mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
            mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
            mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONREQUEST );
        }

        if( ( nFound & FOUND_VERB ) && eClickAction == presentation::ClickAction_VERB )
        {
            msBuffer.append( nVerb );
            mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_VERB, msBuffer.makeStringAndClear());
        }

        SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_PRESENTATION, XML_EVENT_LISTENER, sal_True, sal_True);

        if( eClickAction == presentation::ClickAction_VANISH || eClickAction == presentation::ClickAction_SOUND )
        {
            if( ( nFound & FOUND_SOUNDURL ) && aStrSoundURL.getLength() != 0 )
            {
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStrSoundURL) );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_NEW );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONREQUEST );
                if( nFound & FOUND_PLAYFULL && bPlayFull )
                    mrExport.AddAttribute( XML_NAMESPACE_PRESENTATION, XML_PLAY_FULL, XML_TRUE );

                SvXMLElementExport aElem( mrExport, XML_NAMESPACE_PRESENTATION, XML_SOUND, sal_True, sal_True );
            }
       }
    }
    else if( aClickEventType == msStarBasic )
    {
        if( nFound & FOUND_MACRO )
        {
            SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_OFFICE, XML_EVENT_LISTENERS, sal_True, sal_True);

            mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_LANGUAGE,
                        mrExport.GetNamespaceMap().GetQNameByKey(
                            XML_NAMESPACE_OOO,
                            OUString( RTL_CONSTASCII_USTRINGPARAM(
                                            "starbasic" ) ) ) );
            OUString aEventQName(
                mrExport.GetNamespaceMap().GetQNameByKey(
                        XML_NAMESPACE_DOM, OUString( RTL_CONSTASCII_USTRINGPARAM( "click" ) ) ) );
            mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, aEventQName );

            if( nFound & FOUND_LIBRARY )
            {
                OUString sLocation( GetXMLToken(
                    (aStrLibrary.equalsIgnoreAsciiCaseAscii("StarOffice") ||
                     aStrLibrary.equalsIgnoreAsciiCaseAscii("application") ) ? XML_APPLICATION
                                                                       : XML_DOCUMENT ) );
                OUStringBuffer sTmp( sLocation.getLength() + aStrMacro.getLength() + 1 );
                sTmp = sLocation;
                sTmp.append( sal_Unicode( ':' ) );
                sTmp.append( aStrMacro );
                mrExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_MACRO_NAME,
                                     sTmp.makeStringAndClear());
            }
            else
            {
                mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_MACRO_NAME, aStrMacro );
            }

            SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SCRIPT, XML_EVENT_LISTENER, sal_True, sal_True);
        }
    }
#ifdef ISSUE66550_HLINK_FOR_SHAPES
    else if( aClickEventType == msScript || aActionEventType == msAction )
    {
        if( nFound & ( FOUND_MACRO | FOUND_URL ) )
#else
    else if( aClickEventType == msScript )
    {
        if( nFound & FOUND_MACRO )
#endif
        {
            SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_OFFICE, XML_EVENT_LISTENERS, sal_True, sal_True);
            if ( nFound & FOUND_MACRO )
            {
                mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_LANGUAGE, mrExport.GetNamespaceMap().GetQNameByKey(
                         XML_NAMESPACE_OOO, GetXMLToken(XML_SCRIPT) ) );
                OUString aEventQName(
                    mrExport.GetNamespaceMap().GetQNameByKey(
                            XML_NAMESPACE_DOM, OUString( RTL_CONSTASCII_USTRINGPARAM( "click" ) ) ) );
                mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, aEventQName );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStrMacro );

                SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SCRIPT, XML_EVENT_LISTENER, sal_True, sal_True);
            }
#ifdef ISSUE66550_HLINK_FOR_SHAPES
            if ( nFound & FOUND_URL )
            {
                OUString aEventQName(
                    mrExport.GetNamespaceMap().GetQNameByKey(
                            XML_NAMESPACE_DOM, OUString( RTL_CONSTASCII_USTRINGPARAM( "action" ) ) ) );
                mrExport.AddAttribute( XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, aEventQName );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aHyperURL );

                SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_PRESENTATION, XML_EVENT_LISTENER, sal_True, sal_True);
            }
#endif
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

/** #i68101# export shape Title and Description */
void XMLShapeExport::ImpExportDescription( const uno::Reference< drawing::XShape >& xShape )
{
	try
	{
		OUString aTitle;
		OUString aDescription;

		uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW );
		xProps->getPropertyValue( OUString::createFromAscii( "Title" ) ) >>= aTitle;
		xProps->getPropertyValue( OUString::createFromAscii( "Description" ) ) >>= aDescription;

		if(aTitle.getLength())
		{
			SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, sal_True, sal_False);
			mrExport.Characters( aTitle );
		}

		if(aDescription.getLength())
		{
			SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_DESC, sal_True, sal_False );
			mrExport.Characters( aDescription );
		}
	}
	catch( uno::Exception& )
	{
		DBG_ERROR( "could not export Title and/or Description for shape!" );
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportGroupShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
	uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
	if(xShapes.is() && xShapes->getCount())
	{
		// write group shape
		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aPGR(mrExport, XML_NAMESPACE_DRAW, XML_G, bCreateNewline, sal_True);

		ImpExportDescription( xShape ); // #i68101#
		ImpExportEvents( xShape );
		ImpExportGluePoints( xShape );

		// #89764# if export of position is suppressed for group shape,
		// positions of contained objects should be written relative to
		// the upper left edge of the group.
		awt::Point aUpperLeft;

		if(!(nFeatures & SEF_EXPORT_POSITION))
		{
			nFeatures |= SEF_EXPORT_POSITION;
			aUpperLeft = xShape->getPosition();
			pRefPoint = &aUpperLeft;
		}

		// write members
		exportShapes( xShapes, nFeatures, pRefPoint );
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportTextBoxShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType eShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );

		// presentation attribute (if presentation)
		sal_Bool bIsPresShape(sal_False);
		sal_Bool bIsEmptyPresObj(sal_False);
		OUString aStr;

		switch(eShapeType)
		{
			case XmlShapeTypePresSubtitleShape:
			{
				aStr = GetXMLToken(XML_PRESENTATION_SUBTITLE);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresTitleTextShape:
			{
				aStr = GetXMLToken(XML_PRESENTATION_TITLE);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresOutlinerShape:
			{
				aStr = GetXMLToken(XML_PRESENTATION_OUTLINE);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresNotesShape:
			{
				aStr = GetXMLToken(XML_PRESENTATION_NOTES);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresHeaderShape:
			{
				aStr = GetXMLToken(XML_HEADER);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresFooterShape:
			{
				aStr = GetXMLToken(XML_FOOTER);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresSlideNumberShape:
			{
				aStr = GetXMLToken(XML_PAGE_NUMBER);
				bIsPresShape = sal_True;
				break;
			}
			case XmlShapeTypePresDateTimeShape:
			{
				aStr = GetXMLToken(XML_DATE_TIME);
				bIsPresShape = sal_True;
				break;
			}
			default:
				break;
		}

		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		if(bIsPresShape)
			bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, aStr );


		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		// evtl. corner radius?
		sal_Int32 nCornerRadius(0L);
		xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CornerRadius"))) >>= nCornerRadius;
		if(nCornerRadius)
		{
			OUStringBuffer sStringBuffer;
			mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nCornerRadius);
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
		}

		{
			// write text-box
			SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_TEXT_BOX, sal_True, sal_True);
			if(!bIsEmptyPresObj)
				ImpExportText( xShape );
		}

		ImpExportDescription( xShape ); // #i68101#
		ImpExportEvents( xShape );
		ImpExportGluePoints( xShape );
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportRectangleShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		// evtl. corner radius?
		sal_Int32 nCornerRadius(0L);
		xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CornerRadius"))) >>= nCornerRadius;
		if(nCornerRadius)
		{
			OUStringBuffer sStringBuffer;
			mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nCornerRadius);
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
		}

		// write rectangle
		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_RECT, bCreateNewline, sal_True);

		ImpExportDescription( xShape ); // #i68101#
		ImpExportEvents( xShape );
		ImpExportGluePoints( xShape );
		ImpExportText( xShape );
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportLineShape(
    const uno::Reference< drawing::XShape >& xShape,
    XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
    const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
    if(xPropSet.is())
    {
        OUString aStr;
        OUStringBuffer sStringBuffer;

        // get matrix
        basegfx::B2DHomMatrix aMatrix;
        ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);

        // Create the two points directy using the transformation
        basegfx::B2DPoint aB2DStart(aMatrix * basegfx::B2DPoint(0.0, 0.0));
        basegfx::B2DPoint aB2DEnd(aMatrix * basegfx::B2DPoint(1.0, 0.0));

        if(pRefPoint)
        {
            const basegfx::B2DPoint aRefPoint(pRefPoint->X, pRefPoint->Y);
            aB2DStart -= aRefPoint;
            aB2DEnd -= aRefPoint;
        }

        awt::Point aStart(basegfx::fround(aB2DStart.getX()), basegfx::fround(aB2DStart.getY()));
        awt::Point aEnd(basegfx::fround(aB2DEnd.getX()), basegfx::fround(aB2DEnd.getY()));

        if( nFeatures & SEF_EXPORT_X )
        {
            // svg: x1
            mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.X);
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X1, aStr);
        }
        else
        {
            aEnd.X -= aStart.X;
        }

        if( nFeatures & SEF_EXPORT_Y )
        {
            // svg: y1
            mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.Y);
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y1, aStr);
        }
        else
        {
            aEnd.Y -= aStart.Y;
        }

        // svg: x2
        mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.X);
        aStr = sStringBuffer.makeStringAndClear();
        mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X2, aStr);

        // svg: y2
        mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.Y);
        aStr = sStringBuffer.makeStringAndClear();
        mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y2, aStr);

        // write line
        sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
        SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_LINE, bCreateNewline, sal_True);

        ImpExportDescription( xShape ); // #i68101#
        ImpExportEvents( xShape );
        ImpExportGluePoints( xShape );
        ImpExportText( xShape );
    }
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportEllipseShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// get size to decide between Circle and Ellipse
		awt::Size aSize = xShape->getSize();
		sal_Int32 nRx((aSize.Width + 1) / 2);
		sal_Int32 nRy((aSize.Height + 1) / 2);
		sal_Bool bCircle(nRx == nRy);

		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		drawing::CircleKind eKind = drawing::CircleKind_FULL;
		xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("CircleKind")) ) >>= eKind;
		if( eKind != drawing::CircleKind_FULL )
		{
			OUStringBuffer sStringBuffer;
			sal_Int32 nStartAngle = 0;
			sal_Int32 nEndAngle = 0;
			xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("CircleStartAngle")) ) >>= nStartAngle;
			xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("CircleEndAngle")) ) >>= nEndAngle;

			const double dStartAngle = nStartAngle / 100.0;
			const double dEndAngle = nEndAngle / 100.0;

			// export circle kind
			SvXMLUnitConverter::convertEnum( sStringBuffer, (sal_uInt16)eKind, aXML_CircleKind_EnumMap );
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_KIND, sStringBuffer.makeStringAndClear() );

			// export start angle
			SvXMLUnitConverter::convertDouble( sStringBuffer, dStartAngle );
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_ANGLE, sStringBuffer.makeStringAndClear() );

			// export end angle
			SvXMLUnitConverter::convertDouble( sStringBuffer, dEndAngle );
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_ANGLE, sStringBuffer.makeStringAndClear() );
		}

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#

        // prepare name (with most used)
        enum ::xmloff::token::XMLTokenEnum eName(XML_CIRCLE);

        if(bCircle)
        {
            // name already set
        }
        else
        {
            // set name
            eName = XML_ELLIPSE;
        }

        // write ellipse or circle
        SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, eName, bCreateNewline, sal_True);

        ImpExportDescription( xShape ); // #i68101#
        ImpExportEvents( xShape );
        ImpExportGluePoints( xShape );
        ImpExportText( xShape );
    }
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportPolygonShape(
    const uno::Reference< drawing::XShape >& xShape,
    XmlShapeType /*eShapeType*/, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
    const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);

    if(xPropSet.is())
    {
        // get matrix
        ::basegfx::B2DHomMatrix aMatrix;
        ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);

        // decompose and correct about pRefPoint
        ::basegfx::B2DTuple aTRScale;
        double fTRShear(0.0);
        double fTRRotate(0.0);
        ::basegfx::B2DTuple aTRTranslate;
        ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);

        // use features and write
        ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);

        // create and export ViewBox. caution! for svg:ViewBox, use the absolute values (!)
        SdXMLImExViewBox aViewBox(0.0, 0.0, fabs(aTRScale.getX()), fabs(aTRScale.getY()));

        mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());

        // get polygon data
        const uno::Any aAny(xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Geometry"))));
        basegfx::B2DPolyPolygon aPolyPolygon;
        const bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#

        // prepare name (with most used)
        enum ::xmloff::token::XMLTokenEnum eName(XML_PATH);

        if(aAny.getValueType().equals(getCppuType((drawing::PolyPolygonBezierCoords*)0)))
        {
            aPolyPolygon = basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*(drawing::PolyPolygonBezierCoords*)aAny.getValue());
        }
        else if(aAny.getValueType().equals(getCppuType((drawing::PointSequenceSequence*)0)))
        {
            aPolyPolygon = basegfx::tools::UnoPointSequenceSequenceToB2DPolyPolygon(*(drawing::PointSequenceSequence*)aAny.getValue());
        }

        if(!aPolyPolygon.areControlPointsUsed() && 1 == aPolyPolygon.count())
        {
            // simple polygon shape, can be written as svg:points sequence
            const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0));
            const ::rtl::OUString aPointString(basegfx::tools::exportToSvgPoints(aPolygon));

            // write point array
            mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);

            // set name
            eName = aPolygon.isClosed() ? XML_POLYGON : XML_POLYLINE;
        }
        else
        {
            // complex polygon shape, write as svg:d
            const ::rtl::OUString aPolygonString(
                basegfx::tools::exportToSvgD(
                    aPolyPolygon,
                    true,       // bUseRelativeCoordinates
                    false,      // bDetectQuadraticBeziers: not used in old, but maybe activated now
                    true));     // bHandleRelativeNextPointCompatible

            // write point array
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
        }

        // write object, but after attributes are added since this call will
        // consume all of these added attributes and the destructor will close the 
        // scope. Also before text is added; this may add sub-scopes as needed
        SvXMLElementExport aOBJ(
            mrExport, 
            XML_NAMESPACE_DRAW, 
            eName, 
            bCreateNewline, 
            sal_True);

        ImpExportDescription( xShape ); // #i68101#
        ImpExportEvents( xShape );
        ImpExportGluePoints( xShape );
        ImpExportText( xShape );
    }
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportGraphicObjectShape(
    const uno::Reference< drawing::XShape >& xShape,
    XmlShapeType eShapeType,
    sal_Int32 nFeatures,
    awt::Point* pRefPoint )
{
    const uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
    if ( xPropSet.is() )
    {
        sal_Bool bIsEmptyPresObj = sal_False;
        uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );

        // Transformation
        ImpExportNewTrans( xPropSet, nFeatures, pRefPoint );

        OUString sImageURL;

        if ( eShapeType == XmlShapeTypePresGraphicObjectShape )
            bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken( XML_PRESENTATION_GRAPHIC ) );

        sal_Bool bCreateNewline( ( nFeatures & SEF_EXPORT_NO_WS ) == 0 ); // #86116#/#92210#
        SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_FRAME, bCreateNewline, sal_True );

        const bool bSaveBackwardsCompatible = ( mrExport.getExportFlags() & EXPORT_SAVEBACKWARDCOMPATIBLE );

        if ( !bIsEmptyPresObj || bSaveBackwardsCompatible )
        {
            if ( !bIsEmptyPresObj )
            {
                OUString aReplacementUrl;
                xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("ReplacementGraphicURL"))) >>= aReplacementUrl;

                // If there is no url, then then graphic is empty
                if ( aReplacementUrl.getLength() )
                {
                    const OUString aStr = mrExport.AddEmbeddedGraphicObject(aReplacementUrl);

                    if(aStr.getLength())
                    {
                        mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aStr);
                        mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                        mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                        mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );

                        // xlink:href for replacement, only written for Svg content
                        SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, sal_True, sal_True);

                        // optional office:binary-data
                        mrExport.AddEmbeddedGraphicObjectAsBase64(aReplacementUrl);
                    }
                }

                OUString aStreamURL;
                xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStreamURL" ) ) ) >>= aStreamURL;
                xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) ) >>= sImageURL;

                OUString aResolveURL( sImageURL );
                const rtl::OUString sPackageURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package:" ) );

                // sj: trying to preserve the filename
                if ( aStreamURL.match( sPackageURL, 0 ) )
                {
                    rtl::OUString sRequestedName( aStreamURL.copy( sPackageURL.getLength(), aStreamURL.getLength() - sPackageURL.getLength() ) );
                    sal_Int32 nLastIndex = sRequestedName.lastIndexOf( '/' ) + 1;
                    if ( ( nLastIndex > 0 ) && ( nLastIndex < sRequestedName.getLength() ) )
                        sRequestedName = sRequestedName.copy( nLastIndex, sRequestedName.getLength() - nLastIndex );
                    nLastIndex = sRequestedName.lastIndexOf( '.' );
                    if ( nLastIndex >= 0 )
                        sRequestedName = sRequestedName.copy( 0, nLastIndex );
                    if ( sRequestedName.getLength() )
                    {
                        aResolveURL = aResolveURL.concat( OUString( RTL_CONSTASCII_USTRINGPARAM( "?requestedName=" ) ) );
                        aResolveURL = aResolveURL.concat( sRequestedName );
                    }
                }

                const OUString aStr = mrExport.AddEmbeddedGraphicObject( aResolveURL );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStr );

                if ( !aStr.isEmpty() )
                {
                    aStreamURL = sPackageURL;
                    if ( aStr[0] == '#' )
                    {
                        aStreamURL = aStreamURL.concat( aStr.copy( 1, aStr.getLength() - 1 ) );
                    }
                    else
                    {
                        aStreamURL = aStreamURL.concat( aStr );
                    }

                    // update stream URL for load on demand
                    uno::Any aAny;
                    aAny <<= aStreamURL;
                    xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStreamURL" ) ), aAny );

                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
                }
            }
            else
            {
                OUString aStr;
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStr );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
            }

            {
                SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, sal_True, sal_True );

                if ( sImageURL.getLength() )
                {
                    // optional office:binary-data
                    mrExport.AddEmbeddedGraphicObjectAsBase64( sImageURL );
                }
                if ( !bIsEmptyPresObj )
                    ImpExportText( xShape );
            }
        }

        ImpExportEvents( xShape );
        ImpExportGluePoints( xShape );

        // image map
        GetExport().GetImageMapExport().Export( xPropSet );
        ImpExportDescription( xShape ); // #i68101#
    }
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportChartShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType eShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint,
    SvXMLAttributeList* pAttrList )
{
	ImpExportOLE2Shape( xShape, eShapeType, nFeatures, pRefPoint, pAttrList );
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportControlShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
	}

	uno::Reference< drawing::XControlShape > xControl( xShape, uno::UNO_QUERY );
	DBG_ASSERT( xControl.is(), "Control shape is not supporting XControlShape" );
	if( xControl.is() )
	{
		uno::Reference< beans::XPropertySet > xControlModel( xControl->getControl(), uno::UNO_QUERY );
		DBG_ASSERT( xControlModel.is(), "Control shape has not XControlModel" );
		if( xControlModel.is() )
		{
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CONTROL, mrExport.GetFormExport()->getControlId( xControlModel ) );
		}
	}

	sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
	SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONTROL, bCreateNewline, sal_True);

	ImpExportDescription( xShape ); // #i68101#
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportConnectorShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
{
	uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );

	OUString aStr;
	OUStringBuffer sStringBuffer;

	// export connection kind
	drawing::ConnectorType eType = drawing::ConnectorType_STANDARD;
	uno::Any aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EdgeKind")));
	aAny >>= eType;

	if( eType != drawing::ConnectorType_STANDARD )
	{
		SvXMLUnitConverter::convertEnum( sStringBuffer, (sal_uInt16)eType, aXML_ConnectionKind_EnumMap );
		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_TYPE, aStr);
	}

	// export line skew
	sal_Int32 nDelta1 = 0, nDelta2 = 0, nDelta3 = 0;

	aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EdgeLine1Delta")));
	aAny >>= nDelta1;
	aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EdgeLine2Delta")));
	aAny >>= nDelta2;
	aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EdgeLine3Delta")));
	aAny >>= nDelta3;

	if( nDelta1 != 0 || nDelta2 != 0 || nDelta3 != 0 )
	{
		mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDelta1);
		if( nDelta2 != 0 || nDelta3 != 0 )
		{
			const char aSpace = ' ';
			sStringBuffer.appendAscii( &aSpace, 1 );
			mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDelta2);
			if( nDelta3 != 0 )
			{
				sStringBuffer.appendAscii( &aSpace, 1 );
				mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDelta3);
			}
		}

		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_LINE_SKEW, aStr);
	}

	// export start and end point
	awt::Point aStart(0,0);
	awt::Point aEnd(1,1);

    // --> OD 2004-08-09 #i36248# - Get <StartPositionInHoriL2R> and
    // <EndPositionInHoriL2R>, if they exist and if the document is exported
    // into the OpenOffice.org file format.
    // These properties only exist at service com::sun::star::text::Shape - the
    // Writer UNO service for shapes.
    // This code is needed, because the positioning attributes in the
    // OpenOffice.org file format are given in horizontal left-to-right layout
    // regardless the layout direction the shape is in. In the OASIS Open Office
    // file format the positioning attributes are correctly given in the layout
    // direction the shape is in. Thus, this code provides the conversion from
    // the OASIS Open Office file format to the OpenOffice.org file format.
    if ( ( GetExport().getExportFlags() & EXPORT_OASIS ) == 0 &&
         xProps->getPropertySetInfo()->hasPropertyByName(
            OUString(RTL_CONSTASCII_USTRINGPARAM("StartPositionInHoriL2R"))) &&
         xProps->getPropertySetInfo()->hasPropertyByName(
            OUString(RTL_CONSTASCII_USTRINGPARAM("EndPositionInHoriL2R"))) )
    {
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartPositionInHoriL2R"))) >>= aStart;
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndPositionInHoriL2R"))) >>= aEnd;
    }
    else
    {
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition"))) >>= aStart;
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition"))) >>= aEnd;
    }
    // <--

	if( pRefPoint )
	{
		aStart.X -= pRefPoint->X;
		aStart.Y -= pRefPoint->Y;
		aEnd.X -= pRefPoint->X;
		aEnd.Y -= pRefPoint->Y;
	}

	if( nFeatures & SEF_EXPORT_X )
	{
		// svg: x1
		mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.X);
		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X1, aStr);
	}
	else
	{
		aEnd.X -= aStart.X;
	}

	if( nFeatures & SEF_EXPORT_Y )
	{
		// svg: y1
		mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.Y);
		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y1, aStr);
	}
	else
	{
		aEnd.Y -= aStart.Y;
	}

	// svg: x2
	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.X);
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X2, aStr);

	// svg: y2
	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.Y);
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y2, aStr);

	// #i39320#
	uno::Reference< uno::XInterface > xRefS;
	uno::Reference< uno::XInterface > xRefE;

	// export start connection
	xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartShape") ) ) >>= xRefS;
	if( xRefS.is() )
	{
		const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefS );
		mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_SHAPE, rShapeId);

		aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartGluePointIndex")) );
		sal_Int32 nGluePointId = 0;
		if( aAny >>= nGluePointId )
		{
			if( nGluePointId != -1 )
			{
				mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_GLUE_POINT, OUString::valueOf( nGluePointId ));
			}
		}
	}

	// export end connection
	xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndShape")) ) >>= xRefE;
	if( xRefE.is() )
	{
		const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefE );
		mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_SHAPE, rShapeId);

		aAny = xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndGluePointIndex")) );
		sal_Int32 nGluePointId = 0;
		if( aAny >>= nGluePointId )
		{
			if( nGluePointId != -1 )
			{
				mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_GLUE_POINT, OUString::valueOf( nGluePointId ));
			}
		}
	}

    if( xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("PolyPolygonBezier") ) ) >>= aAny )
    {
        // get PolygonBezier
        drawing::PolyPolygonBezierCoords* pSourcePolyPolygon = (drawing::PolyPolygonBezierCoords*)aAny.getValue();

        if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
        {
            const basegfx::B2DPolyPolygon aPolyPolygon(
                basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
                    *pSourcePolyPolygon));
            const ::rtl::OUString aPolygonString(
                basegfx::tools::exportToSvgD(
                    aPolyPolygon,
                    true,           // bUseRelativeCoordinates
                    false,          // bDetectQuadraticBeziers: not used in old, but maybe activated now
                    true));         // bHandleRelativeNextPointCompatible

            // write svg:d
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
        }
    }

	// write connector shape. Add Export later.
	sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
	SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONNECTOR, bCreateNewline, sal_True);

	ImpExportDescription( xShape ); // #i68101#
	ImpExportEvents( xShape );
	ImpExportGluePoints( xShape );
	ImpExportText( xShape );
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportMeasureShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
{
	uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );

	OUString aStr;
	OUStringBuffer sStringBuffer;

	// export start and end point
	awt::Point aStart(0,0);
	awt::Point aEnd(1,1);

    // --> OD 2004-08-09 #i36248# - Get <StartPositionInHoriL2R> and
    // <EndPositionInHoriL2R>, if they exist and if the document is exported
    // into the OpenOffice.org file format.
    // These properties only exist at service com::sun::star::text::Shape - the
    // Writer UNO service for shapes.
    // This code is needed, because the positioning attributes in the
    // OpenOffice.org file format are given in horizontal left-to-right layout
    // regardless the layout direction the shape is in. In the OASIS Open Office
    // file format the positioning attributes are correctly given in the layout
    // direction the shape is in. Thus, this code provides the conversion from
    // the OASIS Open Office file format to the OpenOffice.org file format.
    if ( ( GetExport().getExportFlags() & EXPORT_OASIS ) == 0 &&
         xProps->getPropertySetInfo()->hasPropertyByName(
            OUString(RTL_CONSTASCII_USTRINGPARAM("StartPositionInHoriL2R"))) &&
         xProps->getPropertySetInfo()->hasPropertyByName(
            OUString(RTL_CONSTASCII_USTRINGPARAM("EndPositionInHoriL2R"))) )
    {
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartPositionInHoriL2R"))) >>= aStart;
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndPositionInHoriL2R"))) >>= aEnd;
    }
    else
    {
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition"))) >>= aStart;
        xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition"))) >>= aEnd;
    }
    // <--

	if( pRefPoint )
	{
		aStart.X -= pRefPoint->X;
		aStart.Y -= pRefPoint->Y;
		aEnd.X -= pRefPoint->X;
		aEnd.Y -= pRefPoint->Y;
	}

	if( nFeatures & SEF_EXPORT_X )
	{
		// svg: x1
		mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.X);
		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X1, aStr);
	}
	else
	{
		aEnd.X -= aStart.X;
	}

	if( nFeatures & SEF_EXPORT_Y )
	{
		// svg: y1
		mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aStart.Y);
		aStr = sStringBuffer.makeStringAndClear();
		mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y1, aStr);
	}
	else
	{
		aEnd.Y -= aStart.Y;
	}

	// svg: x2
	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.X);
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X2, aStr);

	// svg: y2
	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, aEnd.Y);
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y2, aStr);

	// write measure shape
	sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
	SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_MEASURE, bCreateNewline, sal_True);

	ImpExportDescription( xShape ); // #i68101#
	ImpExportEvents( xShape );
	ImpExportGluePoints( xShape );

	uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
	if( xText.is() )
		mrExport.GetTextParagraphExport()->exportText( xText );
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportOLE2Shape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType eShapeType, sal_Int32 nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */,
    SvXMLAttributeList* pAttrList /* = NULL */ )
{
	uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);

	DBG_ASSERT( xPropSet.is() && xNamed.is(), "ole shape is not implementing needed interfaces");
	if(xPropSet.is() && xNamed.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		sal_Bool bIsEmptyPresObj = sal_False;

		// presentation settings
		if(eShapeType == XmlShapeTypePresOLE2Shape)
			bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_OBJECT) );
		else if(eShapeType == XmlShapeTypePresChartShape)
			bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_CHART) );
		else if(eShapeType == XmlShapeTypePresSheetShape)
			bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_TABLE) );

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		sal_Bool bExportEmbedded(0 != (mrExport.getExportFlags() & EXPORT_EMBEDDED));
		OUString sPersistName;
		SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		const bool bSaveBackwardsCompatible = ( mrExport.getExportFlags() & EXPORT_SAVEBACKWARDCOMPATIBLE );

		if( !bIsEmptyPresObj || bSaveBackwardsCompatible )
		{
            if (pAttrList)
            {
                mrExport.AddAttributeList(pAttrList);
            }

			OUString sClassId;
			OUString sURL;
			sal_Bool bInternal = false;
			xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("IsInternal"))) >>= bInternal;

			if( !bIsEmptyPresObj )
			{

				if ( bInternal )
				{
					// OOo internal links have no storage persistence, URL is stored in the XML file
					// the result LinkURL is empty in case the object is not a link
					xPropSet->getPropertyValue( OUString::createFromAscii( "LinkURL" ) ) >>= sURL;
				}

				xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM( "PersistName" ) ) ) >>= sPersistName;
				if ( !sURL.getLength() )
				{
					if( sPersistName.getLength() )
					{
						sURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.EmbeddedObject:" ) );
						sURL += sPersistName;
					}
				}

				if( !bInternal )
					xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CLSID"))) >>= sClassId;

				if( sClassId.getLength() )
					mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CLASS_ID, sClassId );
				if(!bExportEmbedded)
				{
					// xlink:href
					if( sURL.getLength() )
					{
						// #96717# in theorie, if we don't have a url we shouldn't even
						// export this ole shape. But practical its to risky right now
						// to change this so we better dispose this on load
						sURL = mrExport.AddEmbeddedObject( sURL );

						mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL );
						mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
						mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
						mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
					}
				}
			}
			else
			{
				// export empty href for empty placeholders to be valid odf
				OUString sEmptyURL;

				mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sEmptyURL );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
			}

			enum XMLTokenEnum eElem = sClassId.getLength() ? XML_OBJECT_OLE : XML_OBJECT;
			SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, eElem, sal_True, sal_True );

            // #i118485# Add text export, the draw OLE shape allows text now
            ImpExportText( xShape );

			if(bExportEmbedded && !bIsEmptyPresObj)
			{
				// #100592#
				if(bInternal)
				{
					// embedded XML
					uno::Reference< lang::XComponent > xComp;
					xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("Model") ) ) >>= xComp;
					DBG_ASSERT( xComp.is(), "no xModel for own OLE format" );
					mrExport.ExportEmbeddedOwnObject( xComp );
				}
				else
				{
					// embed as Base64
					// this is an alien object ( currently MSOLE is the only supported type of such objects )
					// in case it is not an OASIS format the object should be asked to store replacement image if possible

					::rtl::OUString sURLRequest( sURL );
    				if ( ( mrExport.getExportFlags() & EXPORT_OASIS ) == 0 )
						sURLRequest += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?oasis=false" ) );
					mrExport.AddEmbeddedObjectAsBase64( sURLRequest );
				}
			}
		}
		if( !bIsEmptyPresObj )
		{
			OUString sURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
			sURL += sPersistName;
			if( !bExportEmbedded )
			{
				sURL = GetExport().AddEmbeddedObject( sURL );
				mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
				mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
			}

			SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
									  XML_IMAGE, sal_False, sal_True );

			if( bExportEmbedded )
				GetExport().AddEmbeddedObjectAsBase64( sURL );
		}

        ImpExportEvents( xShape );
		ImpExportGluePoints( xShape );
		ImpExportDescription( xShape ); // #i68101#
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportPageShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType eShapeType, sal_Int32 nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// #86163# Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		// export page number used for this page
		uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
		const OUString aPageNumberStr(RTL_CONSTASCII_USTRINGPARAM("PageNumber"));
		if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(aPageNumberStr))
		{
			sal_Int32 nPageNumber = 0;
			xPropSet->getPropertyValue(aPageNumberStr) >>= nPageNumber;
			if( nPageNumber )
				mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_PAGE_NUMBER, OUString::valueOf(nPageNumber));
		}

		// a presentation page shape, normally used on notes pages only. If
		// it is used not as presentation shape, it may have been created with
		// copy-paste exchange between draw and impress (this IS possible...)
		if(eShapeType == XmlShapeTypePresPageShape)
		{
			mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_CLASS,
                                 XML_PRESENTATION_PAGE);
		}

		// write Page shape
		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PAGE_THUMBNAIL, bCreateNewline, sal_True);
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportCaptionShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		// evtl. corner radius?
		sal_Int32 nCornerRadius(0L);
		xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CornerRadius"))) >>= nCornerRadius;
		if(nCornerRadius)
		{
			OUStringBuffer sStringBuffer;
			mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nCornerRadius);
			mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
		}

		awt::Point aCaptionPoint;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" ) ) ) >>= aCaptionPoint;

		mrExport.GetMM100UnitConverter().convertMeasure(msBuffer, aCaptionPoint.X);
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CAPTION_POINT_X, msBuffer.makeStringAndClear() );
		mrExport.GetMM100UnitConverter().convertMeasure(msBuffer, aCaptionPoint.Y);
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CAPTION_POINT_Y, msBuffer.makeStringAndClear() );

		// write Caption shape. Add export later.
		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		sal_Bool bAnnotation( (nFeatures & SEF_EXPORT_ANNOTATION) == SEF_EXPORT_ANNOTATION );

        SvXMLElementExport aObj( mrExport,
								 (bAnnotation ? XML_NAMESPACE_OFFICE
								 			  : XML_NAMESPACE_DRAW),
								 (bAnnotation ?	XML_ANNOTATION : XML_CAPTION),
								 bCreateNewline, sal_True );

		ImpExportDescription( xShape ); // #i68101#
		ImpExportEvents( xShape );
		ImpExportGluePoints( xShape );
		if( bAnnotation )
			mrExport.exportAnnotationMeta( xShape );
		ImpExportText( xShape );
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportFrameShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		// export frame url
		OUString aStr;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "FrameURL" ) ) ) >>= aStr;
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );

		// export name
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "FrameName" ) ) ) >>= aStr;
		if( aStr.getLength() )
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FRAME_NAME, aStr );

		// write floating frame
		{
			SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_FLOATING_FRAME, sal_True, sal_True);
		}
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportAppletShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		// export frame url
		OUString aStr;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "AppletCodeBase" ) ) ) >>= aStr;
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );

		// export draw:applet-name
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "AppletName" ) ) ) >>= aStr;
		if( aStr.getLength() )
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_APPLET_NAME, aStr );

		// export draw:code
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "AppletCode" ) ) ) >>= aStr;
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CODE, aStr );

		// export draw:may-script
		sal_Bool bIsScript = false;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "AppletIsScript" ) ) ) >>= bIsScript;
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MAY_SCRIPT, bIsScript ? XML_TRUE : XML_FALSE );

		{
			// write applet
			SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_APPLET, sal_True, sal_True);

			// export parameters
			uno::Sequence< beans::PropertyValue > aCommands;
			xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "AppletCommands" ) ) ) >>= aCommands;
			const sal_Int32 nCount = aCommands.getLength();
			for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
			{
				aCommands[nIndex].Value >>= aStr;
				mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aCommands[nIndex].Name );
				mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
				SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True );
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportPluginShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		// export plugin url
		OUString aStr;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "PluginURL" ) ) ) >>= aStr;
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );


		// export mime-type
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "PluginMimeType" ) ) ) >>= aStr;
		if(aStr.getLength())
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, aStr );

		{
			// write plugin
			SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, sal_True, sal_True);

			// export parameters
			uno::Sequence< beans::PropertyValue > aCommands;
			xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "PluginCommands" ) ) ) >>= aCommands;
			const sal_Int32 nCount = aCommands.getLength();
			for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
			{
				aCommands[nIndex].Value >>= aStr;
				mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aCommands[nIndex].Name );
				mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aStr );
				SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True );
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////////

void XMLShapeExport::ImpExportMediaShape(
	const uno::Reference< drawing::XShape >& xShape,
	XmlShapeType eShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint)
{
	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
	if(xPropSet.is())
	{
		// Transformation
		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);

		if(eShapeType == XmlShapeTypePresMediaShape)
			ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_OBJECT) );

		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
		SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW,
								  XML_FRAME, bCreateNewline, sal_True );

		// export media url
		OUString aMediaURL;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaURL" ) ) ) >>= aMediaURL;
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( aMediaURL ) );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
        mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );

		// export mime-type
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.media" ) ) );

		// write plugin
		SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & SEF_EXPORT_NO_WS ), sal_True);

		// export parameters
		const OUString aFalseStr( RTL_CONSTASCII_USTRINGPARAM( "false" ) ), aTrueStr( RTL_CONSTASCII_USTRINGPARAM( "true" ) );

		sal_Bool bLoop = false;
		const OUString aLoopStr( RTL_CONSTASCII_USTRINGPARAM( "Loop" ) );
		xPropSet->getPropertyValue( aLoopStr ) >>= bLoop;
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aLoopStr );
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, bLoop ? aTrueStr : aFalseStr );
		delete( new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ) );

		sal_Bool bMute = false;
		const OUString aMuteStr( RTL_CONSTASCII_USTRINGPARAM( "Mute" ) );
		xPropSet->getPropertyValue( aMuteStr ) >>= bMute;
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aMuteStr );
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, bMute ? aTrueStr : aFalseStr );
		delete( new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ) );

		sal_Int16 nVolumeDB = 0;
		const OUString aVolumeDBStr( RTL_CONSTASCII_USTRINGPARAM( "VolumeDB" ) );
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "VolumeDB" ) ) ) >>= nVolumeDB;
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aVolumeDBStr );
		mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, OUString::valueOf( static_cast< sal_Int32 >( nVolumeDB ) ) );
		delete( new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ) );

		media::ZoomLevel eZoom;
		const OUString aZoomStr( RTL_CONSTASCII_USTRINGPARAM( "Zoom" ) );
		OUString aZoomValue;
		xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Zoom" ) ) ) >>= eZoom;
		switch( eZoom )
		{
			case( media::ZoomLevel_ZOOM_1_TO_4 ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "25%" ) ); break;
			case( media::ZoomLevel_ZOOM_1_TO_2 ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "50%" ) ); break;
			case( media::ZoomLevel_ORIGINAL ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "100%" ) ); break;
			case( media::ZoomLevel_ZOOM_2_TO_1 ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "200%" ) ); break;
			case( media::ZoomLevel_ZOOM_4_TO_1 ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "400%" ) ); break;
		    case( media::ZoomLevel_FIT_TO_WINDOW ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "fit" ) ); break;
		    case( media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "fixedfit" ) ); break;
		    case( media::ZoomLevel_FULLSCREEN ): aZoomValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "fullscreen" ) ); break;

			default:
			break;
		}

		if( aZoomValue.getLength() )
		{
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aZoomStr );
			mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, aZoomValue );
			delete( new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, sal_False, sal_True ) );
		}
	}
}
