/**************************************************************
 *
 * 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.set(0, 0, aMatrix.Line1.Column1);
	rMatrix.set(0, 1, aMatrix.Line1.Column2);
	rMatrix.set(0, 2, aMatrix.Line1.Column3);
	rMatrix.set(1, 0, aMatrix.Line2.Column1);
	rMatrix.set(1, 1, aMatrix.Line2.Column2);
	rMatrix.set(1, 2, aMatrix.Line2.Column3);
	rMatrix.set(2, 0, aMatrix.Line3.Column1);
	rMatrix.set(2, 1, aMatrix.Line3.Column2);
	rMatrix.set(2, 2, aMatrix.Line3.Column3);
}

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)
{
	// always 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);
	}
	else
	{
		if( aTRScale.getX() > 0.0 )
			aTRScale.setX(aTRScale.getX() - 1.0);
		else if( aTRScale.getX() < 0.0 )
			aTRScale.setX(aTRScale.getX() + 1.0);
	}

	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(aTRScale.getX()));
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStr);

	// svg: height
	if(!(nFeatures & SEF_EXPORT_HEIGHT))
	{
		aTRScale.setY(1.0);
	}
	else
	{
		if( aTRScale.getY() > 0.0 )
			aTRScale.setY(aTRScale.getY() - 1.0);
		else if( aTRScale.getY() < 0.0 )
			aTRScale.setY(aTRScale.getY() + 1.0);
	}

	mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, FRound(aTRScale.getY()));
	aStr = sStringBuffer.makeStringAndClear();
	mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStr);

	// decide if transformation is necessary
	sal_Bool bTransformationIsNeccessary(fTRShear != 0.0 || fTRRotate != 0.0);

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

		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
		aTransform.AddRotate(-fTRRotate);

        aTransform.AddTranslate(rTRTranslate);

		// 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; just add object position to export and we are done
		if(nFeatures & SEF_EXPORT_X)
		{
			// svg: x
			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().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;
		awt::Point aStart(0,0);
		awt::Point aEnd(1,1);

		// #85920# use 'Geometry' to get the points of the line
		// since this slot take anchor pos into account.

		// 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);

		// create base position
		awt::Point aBasePosition(FRound(aTRTranslate.getX()), FRound(aTRTranslate.getY()));

		// get the two points
		uno::Any aAny(xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Geometry"))));
		drawing::PointSequenceSequence* pSourcePolyPolygon = (drawing::PointSequenceSequence*)aAny.getValue();

		if(pSourcePolyPolygon)
		{
		    drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
			if(pOuterSequence)
			{
		        drawing::PointSequence* pInnerSequence = pOuterSequence++;
				if(pInnerSequence)
				{
				    awt::Point* pArray = pInnerSequence->getArray();
					if(pArray)
					{
						if(pInnerSequence->getLength() > 0)
						{
							aStart = awt::Point(
								pArray->X + aBasePosition.X,
								pArray->Y + aBasePosition.Y);
							pArray++;
						}

						if(pInnerSequence->getLength() > 1)
						{
							aEnd = awt::Point(
								pArray->X + aBasePosition.X,
								pArray->Y + aBasePosition.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 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())
	{
		sal_Bool bBezier(eShapeType == XmlShapeTypeDrawClosedBezierShape
			|| eShapeType == XmlShapeTypeDrawOpenBezierShape);

		// 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);

		// create and export ViewBox
		awt::Point aPoint(0, 0);
		awt::Size aSize(FRound(aTRScale.getX()), FRound(aTRScale.getY()));
		SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
		mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());

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

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

        if(bBezier)
        {
            // get PolygonBezier
            uno::Any aAny( xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Geometry"))) );
            const basegfx::B2DPolyPolygon aPolyPolygon(
                basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*(drawing::PolyPolygonBezierCoords*)aAny.getValue()));

            if(aPolyPolygon.count())
            {
                // 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);
            }
        }
        else
        {
            // get non-bezier polygon
            uno::Any aAny( xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Geometry"))) );
            const basegfx::B2DPolyPolygon 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 for embedded images which already have its stream inside the package
                bool bIsEmbeddedImageWithExistingStreamInPackage = false;
                if ( aStreamURL.match( sPackageURL, 0 ) )
                {
                    bIsEmbeddedImageWithExistingStreamInPackage = true;

                    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() )
                {
                    // apply possible changed stream URL to embedded image object
                    if ( bIsEmbeddedImageWithExistingStreamInPackage )
                    {
                        aStreamURL = sPackageURL;
                        if ( aStr[0] == '#' )
                        {
                            aStreamURL = aStreamURL.concat( aStr.copy( 1, aStr.getLength() - 1 ) );
                        }
                        else
                        {
                            aStreamURL = aStreamURL.concat( aStr );
                        }

                        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 point array
            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 ) );
		}
	}
}
