blob: b88f5913dbc57a63f9e25521a1158f9aac917569 [file] [log] [blame]
/**************************************************************
*
* 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 "XMLImageMapContext.hxx"
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmltkmap.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmluconv.hxx>
#include "xexptran.hxx"
#include "xmloff/xmlerror.hxx"
#include <xmloff/XMLEventsImportContext.hxx>
#include "XMLStringBufferImportContext.hxx"
#include <tools/debug.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
using namespace ::com::sun::star;
using namespace ::xmloff::token;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::XPropertySetInfo;
using ::com::sun::star::container::XIndexContainer;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::Any;
using ::com::sun::star::drawing::PointSequenceSequence;
using ::com::sun::star::document::XEventsSupplier;
enum XMLImageMapToken
{
XML_TOK_IMAP_URL,
XML_TOK_IMAP_X,
XML_TOK_IMAP_Y,
XML_TOK_IMAP_CENTER_X,
XML_TOK_IMAP_CENTER_Y,
XML_TOK_IMAP_WIDTH,
XML_TOK_IMAP_HEIGTH,
XML_TOK_IMAP_POINTS,
XML_TOK_IMAP_VIEWBOX,
XML_TOK_IMAP_NOHREF,
XML_TOK_IMAP_NAME,
XML_TOK_IMAP_RADIUS,
XML_TOK_IMAP_TARGET
};
static __FAR_DATA SvXMLTokenMapEntry aImageMapObjectTokenMap[] =
{
{ XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_IMAP_URL },
{ XML_NAMESPACE_OFFICE, XML_NAME, XML_TOK_IMAP_NAME },
{ XML_NAMESPACE_DRAW, XML_NOHREF, XML_TOK_IMAP_NOHREF },
{ XML_NAMESPACE_SVG, XML_X, XML_TOK_IMAP_X },
{ XML_NAMESPACE_SVG, XML_Y, XML_TOK_IMAP_Y },
{ XML_NAMESPACE_SVG, XML_CX, XML_TOK_IMAP_CENTER_X },
{ XML_NAMESPACE_SVG, XML_CY, XML_TOK_IMAP_CENTER_Y },
{ XML_NAMESPACE_SVG, XML_WIDTH, XML_TOK_IMAP_WIDTH },
{ XML_NAMESPACE_SVG, XML_HEIGHT, XML_TOK_IMAP_HEIGTH },
{ XML_NAMESPACE_SVG, XML_R, XML_TOK_IMAP_RADIUS },
{ XML_NAMESPACE_SVG, XML_VIEWBOX, XML_TOK_IMAP_VIEWBOX },
{ XML_NAMESPACE_DRAW, XML_POINTS, XML_TOK_IMAP_POINTS },
{ XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, XML_TOK_IMAP_TARGET },
XML_TOKEN_MAP_END
};
class XMLImageMapObjectContext : public SvXMLImportContext
{
protected:
const ::rtl::OUString sBoundary;
const ::rtl::OUString sCenter;
const ::rtl::OUString sTitle;
const ::rtl::OUString sDescription;
const ::rtl::OUString sImageMap;
const ::rtl::OUString sIsActive;
const ::rtl::OUString sName;
const ::rtl::OUString sPolygon;
const ::rtl::OUString sRadius;
const ::rtl::OUString sTarget;
const ::rtl::OUString sURL;
::rtl::OUString sServiceName;
Reference<XIndexContainer> xImageMap; /// the image map
Reference<XPropertySet> xMapEntry; /// one map-entry (one area)
::rtl::OUString sUrl;
::rtl::OUString sTargt;
::rtl::OUStringBuffer sDescriptionBuffer;
::rtl::OUStringBuffer sTitleBuffer;
::rtl::OUString sNam;
sal_Bool bIsActive;
sal_Bool bValid;
public:
TYPEINFO();
XMLImageMapObjectContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
::com::sun::star::uno::Reference<
::com::sun::star::container::XIndexContainer> xMap,
const sal_Char* pServiceName);
void StartElement(
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList >& xAttrList );
void EndElement();
SvXMLImportContext *CreateChildContext(
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
const ::com::sun::star::uno::Reference<
::com::sun::star::xml::sax::XAttributeList> & xAttrList );
protected:
virtual void ProcessAttribute(
enum XMLImageMapToken eToken,
const ::rtl::OUString& rValue);
virtual void Prepare(
::com::sun::star::uno::Reference<
::com::sun::star::beans::XPropertySet> & rPropertySet);
};
TYPEINIT1( XMLImageMapObjectContext, SvXMLImportContext );
XMLImageMapObjectContext::XMLImageMapObjectContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<XIndexContainer> xMap,
const sal_Char* pServiceName) :
SvXMLImportContext(rImport, nPrefix, rLocalName),
sBoundary(RTL_CONSTASCII_USTRINGPARAM("Boundary")),
sCenter(RTL_CONSTASCII_USTRINGPARAM("Center")),
sTitle(RTL_CONSTASCII_USTRINGPARAM("Title")),
sDescription(RTL_CONSTASCII_USTRINGPARAM("Description")),
sImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap")),
sIsActive(RTL_CONSTASCII_USTRINGPARAM("IsActive")),
sName(RTL_CONSTASCII_USTRINGPARAM("Name")),
sPolygon(RTL_CONSTASCII_USTRINGPARAM("Polygon")),
sRadius(RTL_CONSTASCII_USTRINGPARAM("Radius")),
sTarget(RTL_CONSTASCII_USTRINGPARAM("Target")),
sURL(RTL_CONSTASCII_USTRINGPARAM("URL")),
xImageMap(xMap),
bIsActive(sal_True),
bValid(sal_False)
{
DBG_ASSERT(NULL != pServiceName,
"Please supply the image map object service name");
Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
if( xFactory.is() )
{
Reference<XInterface> xIfc = xFactory->createInstance(
OUString::createFromAscii(pServiceName));
DBG_ASSERT(xIfc.is(), "can't create image map object!");
if( xIfc.is() )
{
Reference<XPropertySet> xPropertySet( xIfc, UNO_QUERY );
xMapEntry = xPropertySet;
}
// else: can't create service -> ignore
}
// else: can't even get factory -> ignore
}
void XMLImageMapObjectContext::StartElement(
const Reference<XAttributeList >& xAttrList )
{
SvXMLTokenMap aMap(aImageMapObjectTokenMap);
sal_Int16 nLength = xAttrList->getLength();
for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
{
OUString sLocalName;
sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
&sLocalName );
OUString sValue = xAttrList->getValueByIndex(nAttr);
ProcessAttribute(
(enum XMLImageMapToken)aMap.Get(nPrefix, sLocalName), sValue);
}
}
void XMLImageMapObjectContext::EndElement()
{
// only create and insert image map object if validity flag is set
// (and we actually have an image map)
if ( bValid && xImageMap.is() && xMapEntry.is() )
{
// set values
Prepare( xMapEntry );
// insert into image map
Any aAny;
aAny <<= xMapEntry;
xImageMap->insertByIndex( xImageMap->getCount(), aAny );
}
// else: not valid -> don't create and insert
}
SvXMLImportContext* XMLImageMapObjectContext::CreateChildContext(
sal_uInt16 nPrefix,
const OUString& rLocalName,
const Reference<XAttributeList> & xAttrList )
{
if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
IsXMLToken(rLocalName, XML_EVENT_LISTENERS) )
{
Reference<XEventsSupplier> xEvents( xMapEntry, UNO_QUERY );
return new XMLEventsImportContext(
GetImport(), nPrefix, rLocalName, xEvents);
}
else if ( (XML_NAMESPACE_SVG == nPrefix) &&
IsXMLToken(rLocalName, XML_TITLE) )
{
return new XMLStringBufferImportContext(
GetImport(), nPrefix, rLocalName, sTitleBuffer);
}
else if ( (XML_NAMESPACE_SVG == nPrefix) &&
IsXMLToken(rLocalName, XML_DESC) )
{
return new XMLStringBufferImportContext(
GetImport(), nPrefix, rLocalName, sDescriptionBuffer);
}
else
return SvXMLImportContext::CreateChildContext(nPrefix, rLocalName,
xAttrList);
}
void XMLImageMapObjectContext::ProcessAttribute(
enum XMLImageMapToken eToken,
const OUString& rValue)
{
switch (eToken)
{
case XML_TOK_IMAP_URL:
sUrl = GetImport().GetAbsoluteReference(rValue);
break;
case XML_TOK_IMAP_TARGET:
sTargt = rValue;
break;
case XML_TOK_IMAP_NOHREF:
bIsActive = ! IsXMLToken(rValue, XML_NOHREF);
break;
case XML_TOK_IMAP_NAME:
sNam = rValue;
break;
default:
// do nothing
break;
}
}
void XMLImageMapObjectContext::Prepare(
Reference<XPropertySet> & rPropertySet)
{
rPropertySet->setPropertyValue( sURL, Any( sUrl ) );
rPropertySet->setPropertyValue( sTitle, Any( sTitleBuffer.makeStringAndClear() ) );
rPropertySet->setPropertyValue( sDescription, Any( sDescriptionBuffer.makeStringAndClear() ) );
rPropertySet->setPropertyValue( sTarget, Any( sTargt ) );
rPropertySet->setPropertyValue( sIsActive, Any( bIsActive ) );
rPropertySet->setPropertyValue( sName, Any( sNam ) );
}
class XMLImageMapRectangleContext : public XMLImageMapObjectContext
{
awt::Rectangle aRectangle;
sal_Bool bXOK;
sal_Bool bYOK;
sal_Bool bWidthOK;
sal_Bool bHeightOK;
public:
TYPEINFO();
XMLImageMapRectangleContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
::com::sun::star::uno::Reference<
::com::sun::star::container::XIndexContainer> xMap);
virtual ~XMLImageMapRectangleContext();
protected:
virtual void ProcessAttribute(
enum XMLImageMapToken eToken,
const ::rtl::OUString& rValue);
virtual void Prepare(
::com::sun::star::uno::Reference<
::com::sun::star::beans::XPropertySet> & rPropertySet);
};
TYPEINIT1(XMLImageMapRectangleContext, XMLImageMapObjectContext);
XMLImageMapRectangleContext::XMLImageMapRectangleContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<XIndexContainer> xMap) :
XMLImageMapObjectContext(rImport, nPrefix, rLocalName, xMap,
"com.sun.star.image.ImageMapRectangleObject"),
bXOK(sal_False),
bYOK(sal_False),
bWidthOK(sal_False),
bHeightOK(sal_False)
{
}
XMLImageMapRectangleContext::~XMLImageMapRectangleContext()
{
}
void XMLImageMapRectangleContext::ProcessAttribute(
enum XMLImageMapToken eToken,
const OUString& rValue)
{
sal_Int32 nTmp;
switch (eToken)
{
case XML_TOK_IMAP_X:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aRectangle.X = nTmp;
bXOK = sal_True;
}
break;
case XML_TOK_IMAP_Y:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aRectangle.Y = nTmp;
bYOK = sal_True;
}
break;
case XML_TOK_IMAP_WIDTH:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aRectangle.Width = nTmp;
bWidthOK = sal_True;
}
break;
case XML_TOK_IMAP_HEIGTH:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aRectangle.Height = nTmp;
bHeightOK = sal_True;
}
break;
default:
XMLImageMapObjectContext::ProcessAttribute(eToken, rValue);
}
bValid = bHeightOK && bXOK && bYOK && bWidthOK;
}
void XMLImageMapRectangleContext::Prepare(
Reference<XPropertySet> & rPropertySet)
{
Any aAny;
aAny <<= aRectangle;
rPropertySet->setPropertyValue( sBoundary, aAny );
// common properties handled by super class
XMLImageMapObjectContext::Prepare(rPropertySet);
}
class XMLImageMapPolygonContext : public XMLImageMapObjectContext
{
::rtl::OUString sViewBoxString;
::rtl::OUString sPointsString;
sal_Bool bViewBoxOK;
sal_Bool bPointsOK;
public:
TYPEINFO();
XMLImageMapPolygonContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
::com::sun::star::uno::Reference<
::com::sun::star::container::XIndexContainer> xMap);
virtual ~XMLImageMapPolygonContext();
protected:
virtual void ProcessAttribute(
enum XMLImageMapToken eToken,
const ::rtl::OUString& rValue);
virtual void Prepare(
::com::sun::star::uno::Reference<
::com::sun::star::beans::XPropertySet> & rPropertySet);
};
TYPEINIT1(XMLImageMapPolygonContext, XMLImageMapObjectContext);
XMLImageMapPolygonContext::XMLImageMapPolygonContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<XIndexContainer> xMap) :
XMLImageMapObjectContext(rImport, nPrefix, rLocalName, xMap,
"com.sun.star.image.ImageMapPolygonObject"),
bViewBoxOK(sal_False),
bPointsOK(sal_False)
{
}
XMLImageMapPolygonContext::~XMLImageMapPolygonContext()
{
}
void XMLImageMapPolygonContext::ProcessAttribute(
enum XMLImageMapToken eToken,
const OUString& rValue)
{
switch (eToken)
{
case XML_TOK_IMAP_POINTS:
sPointsString = rValue;
bPointsOK = sal_True;
break;
case XML_TOK_IMAP_VIEWBOX:
sViewBoxString = rValue;
bViewBoxOK = sal_True;
break;
default:
XMLImageMapObjectContext::ProcessAttribute(eToken, rValue);
break;
}
bValid = bViewBoxOK && bPointsOK;
}
void XMLImageMapPolygonContext::Prepare(Reference<XPropertySet> & rPropertySet)
{
// process view box
SdXMLImExViewBox aViewBox(sViewBoxString, GetImport().GetMM100UnitConverter());
// get polygon sequence
basegfx::B2DPolygon aPolygon;
if(basegfx::tools::importFromSvgPoints(aPolygon, sPointsString))
{
if(aPolygon.count())
{
com::sun::star::drawing::PointSequence aPointSequence;
uno::Any aAny;
basegfx::tools::B2DPolygonToUnoPointSequence(aPolygon, aPointSequence);
aAny <<= aPointSequence;
rPropertySet->setPropertyValue(sPolygon, aAny);
}
}
// parent properties
XMLImageMapObjectContext::Prepare(rPropertySet);
}
class XMLImageMapCircleContext : public XMLImageMapObjectContext
{
awt::Point aCenter;
sal_Int32 nRadius;
sal_Bool bXOK;
sal_Bool bYOK;
sal_Bool bRadiusOK;
public:
TYPEINFO();
XMLImageMapCircleContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
::com::sun::star::uno::Reference<
::com::sun::star::container::XIndexContainer> xMap);
virtual ~XMLImageMapCircleContext();
protected:
virtual void ProcessAttribute(
enum XMLImageMapToken eToken,
const ::rtl::OUString& rValue);
virtual void Prepare(
::com::sun::star::uno::Reference<
::com::sun::star::beans::XPropertySet> & rPropertySet);
};
TYPEINIT1(XMLImageMapCircleContext, XMLImageMapObjectContext);
XMLImageMapCircleContext::XMLImageMapCircleContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<XIndexContainer> xMap) :
XMLImageMapObjectContext(rImport, nPrefix, rLocalName, xMap,
"com.sun.star.image.ImageMapCircleObject"),
bXOK(sal_False),
bYOK(sal_False),
bRadiusOK(sal_False)
{
}
XMLImageMapCircleContext::~XMLImageMapCircleContext()
{
}
void XMLImageMapCircleContext::ProcessAttribute(
enum XMLImageMapToken eToken,
const OUString& rValue)
{
sal_Int32 nTmp;
switch (eToken)
{
case XML_TOK_IMAP_CENTER_X:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aCenter.X = nTmp;
bXOK = sal_True;
}
break;
case XML_TOK_IMAP_CENTER_Y:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
aCenter.Y = nTmp;
bYOK = sal_True;
}
break;
case XML_TOK_IMAP_RADIUS:
if (GetImport().GetMM100UnitConverter().convertMeasure(nTmp,
rValue))
{
nRadius = nTmp;
bRadiusOK = sal_True;
}
break;
default:
XMLImageMapObjectContext::ProcessAttribute(eToken, rValue);
}
bValid = bRadiusOK && bXOK && bYOK;
}
void XMLImageMapCircleContext::Prepare(
Reference<XPropertySet> & rPropertySet)
{
// center (x,y)
Any aAny;
aAny <<= aCenter;
rPropertySet->setPropertyValue( sCenter, aAny );
// radius
aAny <<= nRadius;
rPropertySet->setPropertyValue( sRadius, aAny );
// common properties handled by super class
XMLImageMapObjectContext::Prepare(rPropertySet);
}
TYPEINIT1(XMLImageMapContext, SvXMLImportContext);
XMLImageMapContext::XMLImageMapContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<XPropertySet> & rPropertySet) :
SvXMLImportContext(rImport, nPrefix, rLocalName),
sImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap")),
xPropertySet(rPropertySet)
{
try
{
Reference < XPropertySetInfo > xInfo =
xPropertySet->getPropertySetInfo();
if( xInfo.is() && xInfo->hasPropertyByName( sImageMap ) )
xPropertySet->getPropertyValue(sImageMap) >>= xImageMap;
}
catch( com::sun::star::uno::Exception e )
{
uno::Sequence<OUString> aSeq(0);
rImport.SetError( XMLERROR_FLAG_WARNING | XMLERROR_API, aSeq, e.Message, NULL );
}
}
XMLImageMapContext::~XMLImageMapContext()
{
}
SvXMLImportContext *XMLImageMapContext::CreateChildContext(
sal_uInt16 nPrefix,
const OUString& rLocalName,
const Reference<XAttributeList> & xAttrList )
{
SvXMLImportContext* pContext = NULL;
if ( XML_NAMESPACE_DRAW == nPrefix )
{
if ( IsXMLToken(rLocalName, XML_AREA_RECTANGLE) )
{
pContext = new XMLImageMapRectangleContext(
GetImport(), nPrefix, rLocalName, xImageMap);
}
else if ( IsXMLToken(rLocalName, XML_AREA_POLYGON) )
{
pContext = new XMLImageMapPolygonContext(
GetImport(), nPrefix, rLocalName, xImageMap);
}
else if ( IsXMLToken(rLocalName, XML_AREA_CIRCLE) )
{
pContext = new XMLImageMapCircleContext(
GetImport(), nPrefix, rLocalName, xImageMap);
}
}
else
pContext = SvXMLImportContext::CreateChildContext(nPrefix, rLocalName,
xAttrList);
return pContext;
}
void XMLImageMapContext::EndElement()
{
Reference < XPropertySetInfo > xInfo =
xPropertySet->getPropertySetInfo();
if( xInfo.is() && xInfo->hasPropertyByName( sImageMap ) )
xPropertySet->setPropertyValue(sImageMap, uno::makeAny( xImageMap ) );
}