LibreOffice Module xmloff (master) 1
XMLImageMapContext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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/xml/sax/XAttributeList.hpp>
27#include <com/sun/star/container/XIndexContainer.hpp>
28#include <com/sun/star/lang/XMultiServiceFactory.hpp>
29#include <com/sun/star/document/XEventsSupplier.hpp>
30#include <com/sun/star/awt/Rectangle.hpp>
31#include <xmloff/xmltoken.hxx>
32#include <xmloff/xmlimp.hxx>
33#include <xmloff/xmltkmap.hxx>
36#include <xmloff/xmluconv.hxx>
37#include <xexptran.hxx>
38#include <xmloff/xmlerror.hxx>
41#include <tools/debug.hxx>
44#include <sal/log.hxx>
45
46using namespace ::com::sun::star;
47using namespace ::xmloff::token;
48
49using ::com::sun::star::beans::XPropertySet;
50using ::com::sun::star::beans::XPropertySetInfo;
51using ::com::sun::star::container::XIndexContainer;
52using ::com::sun::star::lang::XMultiServiceFactory;
53using ::com::sun::star::uno::Reference;
54using ::com::sun::star::uno::UNO_QUERY;
55using ::com::sun::star::uno::XInterface;
56using ::com::sun::star::uno::Any;
57using ::com::sun::star::document::XEventsSupplier;
58
59namespace {
60
61class XMLImageMapObjectContext : public SvXMLImportContext
62{
63
64protected:
65
66 Reference<XIndexContainer> xImageMap;
67 Reference<XPropertySet> xMapEntry;
68
69 OUString sUrl;
70 OUString sTargt;
71 OUStringBuffer sDescriptionBuffer;
72 OUStringBuffer sTitleBuffer;
73 OUString sNam;
74 bool bIsActive;
75
76 bool bValid;
77
78public:
79
80 XMLImageMapObjectContext(
81 SvXMLImport& rImport,
82 css::uno::Reference<css::container::XIndexContainer> const & xMap,
83 const char* pServiceName);
84
85 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
86 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
87
88 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
89
90 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
91 sal_Int32 nElement,
92 const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
93
94protected:
95
96 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter &);
97
98 virtual void Prepare(
99 css::uno::Reference<css::beans::XPropertySet> & rPropertySet);
100};
101
102}
103
104XMLImageMapObjectContext::XMLImageMapObjectContext(
105 SvXMLImport& rImport,
106 Reference<XIndexContainer> const & xMap,
107 const char* pServiceName) :
108 SvXMLImportContext(rImport),
109 xImageMap(xMap),
110 bIsActive(true),
111 bValid(false)
112{
113 DBG_ASSERT(nullptr != pServiceName,
114 "Please supply the image map object service name");
115
116 Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
117 if( !xFactory.is() )
118 return;
119
120 Reference<XInterface> xIfc = xFactory->createInstance(
121 OUString::createFromAscii(pServiceName));
122 DBG_ASSERT(xIfc.is(), "can't create image map object!");
123 if( xIfc.is() )
124 {
125 Reference<XPropertySet> xPropertySet( xIfc, UNO_QUERY );
126
127 xMapEntry = xPropertySet;
128 }
129 // else: can't create service -> ignore
130 // else: can't even get factory -> ignore
131}
132
133void XMLImageMapObjectContext::startFastElement( sal_Int32 /*nElement*/,
134 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
135{
136 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
137 ProcessAttribute(aIter);
138}
139
140void XMLImageMapObjectContext::endFastElement(sal_Int32 )
141{
142 // only create and insert image map object if validity flag is set
143 // (and we actually have an image map)
144 if ( bValid && xImageMap.is() && xMapEntry.is() )
145 {
146 // set values
147 Prepare( xMapEntry );
148
149 // insert into image map
150 xImageMap->insertByIndex( xImageMap->getCount(), Any(xMapEntry) );
151 }
152 // else: not valid -> don't create and insert
153}
154
155css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImageMapObjectContext::createFastChildContext(
156 sal_Int32 nElement,
157 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
158{
159 switch (nElement)
160 {
161 case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
162 {
163 Reference<XEventsSupplier> xEvents( xMapEntry, UNO_QUERY );
164 return new XMLEventsImportContext(
165 GetImport(), xEvents);
166 }
167 case XML_ELEMENT(SVG, XML_TITLE):
168 case XML_ELEMENT(SVG_COMPAT, XML_TITLE):
170 GetImport(), sTitleBuffer);
171 case XML_ELEMENT(SVG, XML_DESC):
172 case XML_ELEMENT(SVG_COMPAT, XML_DESC):
174 GetImport(), sDescriptionBuffer);
175 }
176 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
177 return nullptr;
178}
179
180void XMLImageMapObjectContext::ProcessAttribute(
182{
183 switch (aIter.getToken())
184 {
185 case XML_ELEMENT(XLINK, XML_HREF):
186 sUrl = GetImport().GetAbsoluteReference(aIter.toString());
187 break;
188
190 sTargt = aIter.toString();
191 break;
192
193 case XML_ELEMENT(DRAW, XML_NOHREF):
194 bIsActive = ! IsXMLToken(aIter, XML_NOHREF);
195 break;
196
197 case XML_ELEMENT(OFFICE, XML_NAME):
198 sNam = aIter.toString();
199 break;
200 default:
201 // do nothing
202 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
203 break;
204 }
205}
206
207void XMLImageMapObjectContext::Prepare(
208 Reference<XPropertySet> & rPropertySet)
209{
210 rPropertySet->setPropertyValue( "URL", Any( sUrl ) );
211 rPropertySet->setPropertyValue( "Title", Any( sTitleBuffer.makeStringAndClear() ) );
212 rPropertySet->setPropertyValue( "Description", Any( sDescriptionBuffer.makeStringAndClear() ) );
213 rPropertySet->setPropertyValue( "Target", Any( sTargt ) );
214 rPropertySet->setPropertyValue( "IsActive", Any( bIsActive ) );
215 rPropertySet->setPropertyValue( "Name", Any( sNam ) );
216}
217
218namespace {
219
220class XMLImageMapRectangleContext : public XMLImageMapObjectContext
221{
222 awt::Rectangle aRectangle;
223
224 bool bXOK;
225 bool bYOK;
226 bool bWidthOK;
227 bool bHeightOK;
228
229public:
230
231 XMLImageMapRectangleContext(
232 SvXMLImport& rImport,
233 css::uno::Reference<css::container::XIndexContainer> const & xMap);
234
235protected:
236 virtual void ProcessAttribute(
238
239 virtual void Prepare(
240 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
241};
242
243}
244
245XMLImageMapRectangleContext::XMLImageMapRectangleContext(
246 SvXMLImport& rImport,
247 Reference<XIndexContainer> const & xMap) :
248 XMLImageMapObjectContext(rImport, xMap,
249 "com.sun.star.image.ImageMapRectangleObject"),
250 bXOK(false),
251 bYOK(false),
252 bWidthOK(false),
253 bHeightOK(false)
254{
255}
256
257void XMLImageMapRectangleContext::ProcessAttribute(
259{
260 sal_Int32 nTmp;
261 switch (aIter.getToken())
262 {
263 case XML_ELEMENT(SVG, XML_X):
264 case XML_ELEMENT(SVG_COMPAT, XML_X):
265 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
266 aIter.toView()))
267 {
268 aRectangle.X = nTmp;
269 bXOK = true;
270 }
271 break;
272 case XML_ELEMENT(SVG, XML_Y):
273 case XML_ELEMENT(SVG_COMPAT, XML_Y):
274 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
275 aIter.toView()))
276 {
277 aRectangle.Y = nTmp;
278 bYOK = true;
279 }
280 break;
281 case XML_ELEMENT(SVG, XML_WIDTH):
282 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
283 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
284 aIter.toView()))
285 {
286 aRectangle.Width = nTmp;
287 bWidthOK = true;
288 }
289 break;
290 case XML_ELEMENT(SVG, XML_HEIGHT):
291 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
292 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
293 aIter.toView()))
294 {
295 aRectangle.Height = nTmp;
296 bHeightOK = true;
297 }
298 break;
299 default:
300 XMLImageMapObjectContext::ProcessAttribute(aIter);
301 }
302
303 bValid = bHeightOK && bXOK && bYOK && bWidthOK;
304}
305
306void XMLImageMapRectangleContext::Prepare(
307 Reference<XPropertySet> & rPropertySet)
308{
309 rPropertySet->setPropertyValue( "Boundary", uno::Any(aRectangle) );
310
311 // common properties handled by super class
312 XMLImageMapObjectContext::Prepare(rPropertySet);
313}
314
315namespace {
316
317class XMLImageMapPolygonContext : public XMLImageMapObjectContext
318{
319 OUString sViewBoxString;
320 OUString sPointsString;
321
322 bool bViewBoxOK;
323 bool bPointsOK;
324
325public:
326
327 XMLImageMapPolygonContext(
328 SvXMLImport& rImport,
329 css::uno::Reference<css::container::XIndexContainer> const & xMap);
330
331protected:
332 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter &) override;
333
334 virtual void Prepare(
335 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
336};
337
338}
339
340XMLImageMapPolygonContext::XMLImageMapPolygonContext(
341 SvXMLImport& rImport,
342 Reference<XIndexContainer> const & xMap) :
343 XMLImageMapObjectContext(rImport, xMap,
344 "com.sun.star.image.ImageMapPolygonObject"),
345 bViewBoxOK(false),
346 bPointsOK(false)
347{
348}
349
350void XMLImageMapPolygonContext::ProcessAttribute(
352{
353 switch (aIter.getToken())
354 {
355 case XML_ELEMENT(DRAW, XML_POINTS):
356 sPointsString = aIter.toString();
357 bPointsOK = true;
358 break;
359 case XML_ELEMENT(SVG, XML_VIEWBOX):
360 case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
361 sViewBoxString = aIter.toString();
362 bViewBoxOK = true;
363 break;
364 default:
365 XMLImageMapObjectContext::ProcessAttribute(aIter);
366 break;
367 }
368
369 bValid = bViewBoxOK && bPointsOK;
370}
371
372void XMLImageMapPolygonContext::Prepare(Reference<XPropertySet> & rPropertySet)
373{
374 // process view box
375 SdXMLImExViewBox aViewBox(sViewBoxString, GetImport().GetMM100UnitConverter());
376
377 // get polygon sequence
378 basegfx::B2DPolygon aPolygon;
379
380 if(basegfx::utils::importFromSvgPoints(aPolygon, sPointsString))
381 {
382 if(aPolygon.count())
383 {
384 css::drawing::PointSequence aPointSequence;
385 basegfx::utils::B2DPolygonToUnoPointSequence(aPolygon, aPointSequence);
386 rPropertySet->setPropertyValue("Polygon", Any(aPointSequence));
387 }
388 }
389
390 // parent properties
391 XMLImageMapObjectContext::Prepare(rPropertySet);
392}
393
394namespace {
395
396class XMLImageMapCircleContext : public XMLImageMapObjectContext
397{
398 awt::Point aCenter;
399 sal_Int32 nRadius;
400
401 bool bXOK;
402 bool bYOK;
403 bool bRadiusOK;
404
405public:
406
407 XMLImageMapCircleContext(
408 SvXMLImport& rImport,
409 css::uno::Reference<css::container::XIndexContainer> const & xMap);
410
411protected:
412 virtual void ProcessAttribute(
414
415 virtual void Prepare(
416 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
417};
418
419}
420
421XMLImageMapCircleContext::XMLImageMapCircleContext(
422 SvXMLImport& rImport,
423 Reference<XIndexContainer> const & xMap)
424 : XMLImageMapObjectContext(rImport, xMap,
425 "com.sun.star.image.ImageMapCircleObject")
426 , nRadius(0)
427 , bXOK(false)
428 , bYOK(false)
429 , bRadiusOK(false)
430{
431}
432
433void XMLImageMapCircleContext::ProcessAttribute(
435{
436 sal_Int32 nTmp;
437 switch (aIter.getToken())
438 {
439 case XML_ELEMENT(SVG, XML_CX):
440 case XML_ELEMENT(SVG_COMPAT, XML_CX):
441 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
442 aIter.toView()))
443 {
444 aCenter.X = nTmp;
445 bXOK = true;
446 }
447 break;
448 case XML_ELEMENT(SVG, XML_CY):
449 case XML_ELEMENT(SVG_COMPAT, XML_CY):
450 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
451 aIter.toView()))
452 {
453 aCenter.Y = nTmp;
454 bYOK = true;
455 }
456 break;
457 case XML_ELEMENT(SVG, XML_R):
458 case XML_ELEMENT(SVG_COMPAT, XML_R):
459 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
460 aIter.toView()))
461 {
462 nRadius = nTmp;
463 bRadiusOK = true;
464 }
465 break;
466 default:
467 XMLImageMapObjectContext::ProcessAttribute(aIter);
468 }
469
470 bValid = bRadiusOK && bXOK && bYOK;
471}
472
473void XMLImageMapCircleContext::Prepare(
474 Reference<XPropertySet> & rPropertySet)
475{
476 // center (x,y)
477 rPropertySet->setPropertyValue( "Center", uno::Any(aCenter) );
478 // radius
479 rPropertySet->setPropertyValue( "Radius", uno::Any(nRadius) );
480
481 // common properties handled by super class
482 XMLImageMapObjectContext::Prepare(rPropertySet);
483}
484
485
486constexpr OUStringLiteral gsImageMap(u"ImageMap");
487
489 SvXMLImport& rImport,
490 Reference<XPropertySet> const & rPropertySet) :
491 SvXMLImportContext(rImport),
492 xPropertySet(rPropertySet)
493{
494 try
495 {
496 Reference < XPropertySetInfo > xInfo =
497 xPropertySet->getPropertySetInfo();
498 if( xInfo.is() && xInfo->hasPropertyByName( gsImageMap ) )
499 xPropertySet->getPropertyValue(gsImageMap) >>= xImageMap;
500 }
501 catch(const css::uno::Exception& e)
502 {
503 rImport.SetError( XMLERROR_FLAG_WARNING | XMLERROR_API, {}, e.Message, nullptr );
504 }
505}
506
508{
509}
510
511css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImageMapContext::createFastChildContext(
512 sal_Int32 nElement,
513 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
514{
515 switch (nElement)
516 {
518 return new XMLImageMapRectangleContext(
521 return new XMLImageMapPolygonContext(
524 return new XMLImageMapCircleContext(
526 default:
527 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
528 }
529
530 return nullptr;
531}
532
534{
535 Reference < XPropertySetInfo > xInfo =
536 xPropertySet->getPropertySetInfo();
537 if( xInfo.is() && xInfo->hasPropertyByName( gsImageMap ) )
538 xPropertySet->setPropertyValue(gsImageMap, uno::Any( xImageMap ) );
539}
540
541/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OUStringLiteral gsImageMap(u"ImageMap")
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:45
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
Definition: xmlictxt.cxx:40
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:59
Import <script:events> element.
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual ~XMLImageMapContext() override
css::uno::Reference< css::container::XIndexContainer > xImageMap
the image map to be imported
css::uno::Reference< css::beans::XPropertySet > xPropertySet
the property set from which to get and where eventually to set the image map
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
XMLImageMapContext(SvXMLImport &rImport, css::uno::Reference< css::beans::XPropertySet > const &rPropertySet)
Import all text into a string buffer.
sal_uInt32 count() const
#define DBG_ASSERT(sCon, aError)
Reference< XSingleServiceFactory > xFactory
DRAW
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
bool importFromSvgPoints(B2DPolygon &o_rPoly, std::u16string_view rSvgPointsAttribute)
void B2DPolygonToUnoPointSequence(const B2DPolygon &rPolygon, css::drawing::PointSequence &rPointSequenceRetval)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
OUString toString(OptionInfo const *info)
Handling of tokens in XML:
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3597
#define XMLERROR_API
Definition: xmlerror.hxx:71
#define XMLERROR_FLAG_WARNING
Definition: xmlerror.hxx:35
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97