1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <XMLImageMapContext.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <com/sun/star/uno/Reference.h>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/beans/XPropertySetInfo.hpp>
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/container/XIndexContainer.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/document/XEventsSupplier.hpp>
29 #include <com/sun/star/awt/Rectangle.hpp>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xexptran.hxx>
35 #include <xmloff/xmlerror.hxx>
36 #include <xmloff/XMLEventsImportContext.hxx>
37 #include <XMLStringBufferImportContext.hxx>
38 #include <tools/debug.hxx>
39 #include <basegfx/polygon/b2dpolygon.hxx>
40 #include <basegfx/polygon/b2dpolygontools.hxx>
41 #include <sal/log.hxx>
43 using namespace ::com::sun::star
;
44 using namespace ::xmloff::token
;
46 using ::com::sun::star::beans::XPropertySet
;
47 using ::com::sun::star::beans::XPropertySetInfo
;
48 using ::com::sun::star::container::XIndexContainer
;
49 using ::com::sun::star::lang::XMultiServiceFactory
;
50 using ::com::sun::star::uno::Reference
;
51 using ::com::sun::star::uno::UNO_QUERY
;
52 using ::com::sun::star::uno::XInterface
;
53 using ::com::sun::star::uno::Any
;
54 using ::com::sun::star::document::XEventsSupplier
;
58 class XMLImageMapObjectContext
: public SvXMLImportContext
63 Reference
<XIndexContainer
> xImageMap
; /// the image map
64 Reference
<XPropertySet
> xMapEntry
; /// one map-entry (one area)
68 OUStringBuffer sDescriptionBuffer
;
69 OUStringBuffer sTitleBuffer
;
77 XMLImageMapObjectContext(
79 css::uno::Reference
<css::container::XIndexContainer
> const & xMap
,
80 const char* pServiceName
);
82 virtual void SAL_CALL
startFastElement( sal_Int32 nElement
,
83 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
) override
;
85 virtual void SAL_CALL
endFastElement(sal_Int32 nElement
) override
;
87 virtual css::uno::Reference
< css::xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
89 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& AttrList
) override
;
93 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter
&);
96 css::uno::Reference
<css::beans::XPropertySet
> & rPropertySet
);
101 XMLImageMapObjectContext::XMLImageMapObjectContext(
102 SvXMLImport
& rImport
,
103 Reference
<XIndexContainer
> const & xMap
,
104 const char* pServiceName
) :
105 SvXMLImportContext(rImport
),
110 DBG_ASSERT(nullptr != pServiceName
,
111 "Please supply the image map object service name");
113 Reference
<XMultiServiceFactory
> xFactory(GetImport().GetModel(),UNO_QUERY
);
117 Reference
<XInterface
> xIfc
= xFactory
->createInstance(
118 OUString::createFromAscii(pServiceName
));
119 DBG_ASSERT(xIfc
.is(), "can't create image map object!");
121 xMapEntry
.set(xIfc
, UNO_QUERY
);
122 // else: can't create service -> ignore
123 // else: can't even get factory -> ignore
126 void XMLImageMapObjectContext::startFastElement( sal_Int32
/*nElement*/,
127 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
129 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
130 ProcessAttribute(aIter
);
133 void XMLImageMapObjectContext::endFastElement(sal_Int32
)
135 // only create and insert image map object if validity flag is set
136 // (and we actually have an image map)
137 if ( bValid
&& xImageMap
.is() && xMapEntry
.is() )
140 Prepare( xMapEntry
);
142 // insert into image map
143 xImageMap
->insertByIndex( xImageMap
->getCount(), Any(xMapEntry
) );
145 // else: not valid -> don't create and insert
148 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLImageMapObjectContext::createFastChildContext(
150 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& )
154 case XML_ELEMENT(OFFICE
, XML_EVENT_LISTENERS
):
156 Reference
<XEventsSupplier
> xEvents( xMapEntry
, UNO_QUERY
);
157 return new XMLEventsImportContext(
158 GetImport(), xEvents
);
160 case XML_ELEMENT(SVG
, XML_TITLE
):
161 case XML_ELEMENT(SVG_COMPAT
, XML_TITLE
):
162 return new XMLStringBufferImportContext(
163 GetImport(), sTitleBuffer
);
164 case XML_ELEMENT(SVG
, XML_DESC
):
165 case XML_ELEMENT(SVG_COMPAT
, XML_DESC
):
166 return new XMLStringBufferImportContext(
167 GetImport(), sDescriptionBuffer
);
169 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
173 void XMLImageMapObjectContext::ProcessAttribute(
174 const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
176 switch (aIter
.getToken())
178 case XML_ELEMENT(XLINK
, XML_HREF
):
179 sUrl
= GetImport().GetAbsoluteReference(aIter
.toString());
182 case XML_ELEMENT(OFFICE
, XML_TARGET_FRAME_NAME
):
183 sTargt
= aIter
.toString();
186 case XML_ELEMENT(DRAW
, XML_NOHREF
):
187 bIsActive
= ! IsXMLToken(aIter
, XML_NOHREF
);
190 case XML_ELEMENT(OFFICE
, XML_NAME
):
191 sNam
= aIter
.toString();
195 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
200 void XMLImageMapObjectContext::Prepare(
201 Reference
<XPropertySet
> & rPropertySet
)
203 rPropertySet
->setPropertyValue( u
"URL"_ustr
, Any( sUrl
) );
204 rPropertySet
->setPropertyValue( u
"Title"_ustr
, Any( sTitleBuffer
.makeStringAndClear() ) );
205 rPropertySet
->setPropertyValue( u
"Description"_ustr
, Any( sDescriptionBuffer
.makeStringAndClear() ) );
206 rPropertySet
->setPropertyValue( u
"Target"_ustr
, Any( sTargt
) );
207 rPropertySet
->setPropertyValue( u
"IsActive"_ustr
, Any( bIsActive
) );
208 rPropertySet
->setPropertyValue( u
"Name"_ustr
, Any( sNam
) );
213 class XMLImageMapRectangleContext
: public XMLImageMapObjectContext
215 awt::Rectangle aRectangle
;
224 XMLImageMapRectangleContext(
225 SvXMLImport
& rImport
,
226 css::uno::Reference
<css::container::XIndexContainer
> const & xMap
);
229 virtual void ProcessAttribute(
230 const sax_fastparser::FastAttributeList::FastAttributeIter
&) override
;
232 virtual void Prepare(
233 css::uno::Reference
<css::beans::XPropertySet
> & rPropertySet
) override
;
238 XMLImageMapRectangleContext::XMLImageMapRectangleContext(
239 SvXMLImport
& rImport
,
240 Reference
<XIndexContainer
> const & xMap
) :
241 XMLImageMapObjectContext(rImport
, xMap
,
242 "com.sun.star.image.ImageMapRectangleObject"),
250 void XMLImageMapRectangleContext::ProcessAttribute(
251 const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
254 switch (aIter
.getToken())
256 case XML_ELEMENT(SVG
, XML_X
):
257 case XML_ELEMENT(SVG_COMPAT
, XML_X
):
258 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
265 case XML_ELEMENT(SVG
, XML_Y
):
266 case XML_ELEMENT(SVG_COMPAT
, XML_Y
):
267 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
274 case XML_ELEMENT(SVG
, XML_WIDTH
):
275 case XML_ELEMENT(SVG_COMPAT
, XML_WIDTH
):
276 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
279 aRectangle
.Width
= nTmp
;
283 case XML_ELEMENT(SVG
, XML_HEIGHT
):
284 case XML_ELEMENT(SVG_COMPAT
, XML_HEIGHT
):
285 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
288 aRectangle
.Height
= nTmp
;
293 XMLImageMapObjectContext::ProcessAttribute(aIter
);
296 bValid
= bHeightOK
&& bXOK
&& bYOK
&& bWidthOK
;
299 void XMLImageMapRectangleContext::Prepare(
300 Reference
<XPropertySet
> & rPropertySet
)
302 rPropertySet
->setPropertyValue( u
"Boundary"_ustr
, uno::Any(aRectangle
) );
304 // common properties handled by super class
305 XMLImageMapObjectContext::Prepare(rPropertySet
);
310 class XMLImageMapPolygonContext
: public XMLImageMapObjectContext
312 OUString sViewBoxString
;
313 OUString sPointsString
;
320 XMLImageMapPolygonContext(
321 SvXMLImport
& rImport
,
322 css::uno::Reference
<css::container::XIndexContainer
> const & xMap
);
325 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter
&) override
;
327 virtual void Prepare(
328 css::uno::Reference
<css::beans::XPropertySet
> & rPropertySet
) override
;
333 XMLImageMapPolygonContext::XMLImageMapPolygonContext(
334 SvXMLImport
& rImport
,
335 Reference
<XIndexContainer
> const & xMap
) :
336 XMLImageMapObjectContext(rImport
, xMap
,
337 "com.sun.star.image.ImageMapPolygonObject"),
343 void XMLImageMapPolygonContext::ProcessAttribute(
344 const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
346 switch (aIter
.getToken())
348 case XML_ELEMENT(DRAW
, XML_POINTS
):
349 sPointsString
= aIter
.toString();
352 case XML_ELEMENT(SVG
, XML_VIEWBOX
):
353 case XML_ELEMENT(SVG_COMPAT
, XML_VIEWBOX
):
354 sViewBoxString
= aIter
.toString();
358 XMLImageMapObjectContext::ProcessAttribute(aIter
);
362 bValid
= bViewBoxOK
&& bPointsOK
;
365 void XMLImageMapPolygonContext::Prepare(Reference
<XPropertySet
> & rPropertySet
)
368 SdXMLImExViewBox
aViewBox(sViewBoxString
, GetImport().GetMM100UnitConverter());
370 // get polygon sequence
371 basegfx::B2DPolygon aPolygon
;
373 if(basegfx::utils::importFromSvgPoints(aPolygon
, sPointsString
))
377 css::drawing::PointSequence aPointSequence
;
378 basegfx::utils::B2DPolygonToUnoPointSequence(aPolygon
, aPointSequence
);
379 rPropertySet
->setPropertyValue(u
"Polygon"_ustr
, Any(aPointSequence
));
384 XMLImageMapObjectContext::Prepare(rPropertySet
);
389 class XMLImageMapCircleContext
: public XMLImageMapObjectContext
400 XMLImageMapCircleContext(
401 SvXMLImport
& rImport
,
402 css::uno::Reference
<css::container::XIndexContainer
> const & xMap
);
405 virtual void ProcessAttribute(
406 const sax_fastparser::FastAttributeList::FastAttributeIter
&) override
;
408 virtual void Prepare(
409 css::uno::Reference
<css::beans::XPropertySet
> & rPropertySet
) override
;
414 XMLImageMapCircleContext::XMLImageMapCircleContext(
415 SvXMLImport
& rImport
,
416 Reference
<XIndexContainer
> const & xMap
)
417 : XMLImageMapObjectContext(rImport
, xMap
,
418 "com.sun.star.image.ImageMapCircleObject")
426 void XMLImageMapCircleContext::ProcessAttribute(
427 const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
430 switch (aIter
.getToken())
432 case XML_ELEMENT(SVG
, XML_CX
):
433 case XML_ELEMENT(SVG_COMPAT
, XML_CX
):
434 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
441 case XML_ELEMENT(SVG
, XML_CY
):
442 case XML_ELEMENT(SVG_COMPAT
, XML_CY
):
443 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
450 case XML_ELEMENT(SVG
, XML_R
):
451 case XML_ELEMENT(SVG_COMPAT
, XML_R
):
452 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp
,
460 XMLImageMapObjectContext::ProcessAttribute(aIter
);
463 bValid
= bRadiusOK
&& bXOK
&& bYOK
;
466 void XMLImageMapCircleContext::Prepare(
467 Reference
<XPropertySet
> & rPropertySet
)
470 rPropertySet
->setPropertyValue( u
"Center"_ustr
, uno::Any(aCenter
) );
472 rPropertySet
->setPropertyValue( u
"Radius"_ustr
, uno::Any(nRadius
) );
474 // common properties handled by super class
475 XMLImageMapObjectContext::Prepare(rPropertySet
);
479 constexpr OUString
gsImageMap(u
"ImageMap"_ustr
);
481 XMLImageMapContext::XMLImageMapContext(
482 SvXMLImport
& rImport
,
483 Reference
<XPropertySet
> const & rPropertySet
) :
484 SvXMLImportContext(rImport
),
485 xPropertySet(rPropertySet
)
489 Reference
< XPropertySetInfo
> xInfo
=
490 xPropertySet
->getPropertySetInfo();
491 if( xInfo
.is() && xInfo
->hasPropertyByName( gsImageMap
) )
492 xPropertySet
->getPropertyValue(gsImageMap
) >>= xImageMap
;
494 catch(const css::uno::Exception
& e
)
496 rImport
.SetError( XMLERROR_FLAG_WARNING
| XMLERROR_API
, {}, e
.Message
, nullptr );
500 XMLImageMapContext::~XMLImageMapContext()
504 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLImageMapContext::createFastChildContext(
506 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& )
510 case XML_ELEMENT(DRAW
, XML_AREA_RECTANGLE
):
511 return new XMLImageMapRectangleContext(
512 GetImport(), xImageMap
);
513 case XML_ELEMENT(DRAW
, XML_AREA_POLYGON
):
514 return new XMLImageMapPolygonContext(
515 GetImport(), xImageMap
);
516 case XML_ELEMENT(DRAW
, XML_AREA_CIRCLE
):
517 return new XMLImageMapCircleContext(
518 GetImport(), xImageMap
);
520 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
526 void XMLImageMapContext::endFastElement(sal_Int32
)
528 Reference
< XPropertySetInfo
> xInfo
=
529 xPropertySet
->getPropertySetInfo();
530 if( xInfo
.is() && xInfo
->hasPropertyByName( gsImageMap
) )
531 xPropertySet
->setPropertyValue(gsImageMap
, uno::Any( xImageMap
) );
534 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */