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::xml::sax::XAttributeList;
56using ::com::sun::star::uno::XInterface;
57using ::com::sun::star::uno::Any;
58using ::com::sun::star::document::XEventsSupplier;
59
60namespace {
61
62class XMLImageMapObjectContext : public SvXMLImportContext
63{
64
65protected:
66
67 Reference<XIndexContainer> xImageMap;
68 Reference<XPropertySet> xMapEntry;
69
70 OUString sUrl;
71 OUString sTargt;
72 OUStringBuffer sDescriptionBuffer;
73 OUStringBuffer sTitleBuffer;
74 OUString sNam;
75 bool bIsActive;
76
77 bool bValid;
78
79public:
80
81 XMLImageMapObjectContext(
82 SvXMLImport& rImport,
83 css::uno::Reference<css::container::XIndexContainer> const & xMap,
84 const char* pServiceName);
85
86 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
87 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
88
89 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
90
91 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
92 sal_Int32 nElement,
93 const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
94
95protected:
96
97 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter &);
98
99 virtual void Prepare(
100 css::uno::Reference<css::beans::XPropertySet> & rPropertySet);
101};
102
103}
104
105XMLImageMapObjectContext::XMLImageMapObjectContext(
106 SvXMLImport& rImport,
107 Reference<XIndexContainer> const & xMap,
108 const char* pServiceName) :
109 SvXMLImportContext(rImport),
110 xImageMap(xMap),
111 bIsActive(true),
112 bValid(false)
113{
114 DBG_ASSERT(nullptr != pServiceName,
115 "Please supply the image map object service name");
116
117 Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
118 if( !xFactory.is() )
119 return;
120
121 Reference<XInterface> xIfc = xFactory->createInstance(
122 OUString::createFromAscii(pServiceName));
123 DBG_ASSERT(xIfc.is(), "can't create image map object!");
124 if( xIfc.is() )
125 {
126 Reference<XPropertySet> xPropertySet( xIfc, UNO_QUERY );
127
128 xMapEntry = xPropertySet;
129 }
130 // else: can't create service -> ignore
131 // else: can't even get factory -> ignore
132}
133
134void XMLImageMapObjectContext::startFastElement( sal_Int32 /*nElement*/,
135 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
136{
137 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
138 ProcessAttribute(aIter);
139}
140
141void XMLImageMapObjectContext::endFastElement(sal_Int32 )
142{
143 // only create and insert image map object if validity flag is set
144 // (and we actually have an image map)
145 if ( bValid && xImageMap.is() && xMapEntry.is() )
146 {
147 // set values
148 Prepare( xMapEntry );
149
150 // insert into image map
151 xImageMap->insertByIndex( xImageMap->getCount(), Any(xMapEntry) );
152 }
153 // else: not valid -> don't create and insert
154}
155
156css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImageMapObjectContext::createFastChildContext(
157 sal_Int32 nElement,
158 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
159{
160 switch (nElement)
161 {
162 case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
163 {
164 Reference<XEventsSupplier> xEvents( xMapEntry, UNO_QUERY );
165 return new XMLEventsImportContext(
166 GetImport(), xEvents);
167 }
168 case XML_ELEMENT(SVG, XML_TITLE):
169 case XML_ELEMENT(SVG_COMPAT, XML_TITLE):
171 GetImport(), sTitleBuffer);
172 case XML_ELEMENT(SVG, XML_DESC):
173 case XML_ELEMENT(SVG_COMPAT, XML_DESC):
175 GetImport(), sDescriptionBuffer);
176 }
177 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
178 return nullptr;
179}
180
181void XMLImageMapObjectContext::ProcessAttribute(
183{
184 switch (aIter.getToken())
185 {
186 case XML_ELEMENT(XLINK, XML_HREF):
187 sUrl = GetImport().GetAbsoluteReference(aIter.toString());
188 break;
189
191 sTargt = aIter.toString();
192 break;
193
194 case XML_ELEMENT(DRAW, XML_NOHREF):
195 bIsActive = ! IsXMLToken(aIter, XML_NOHREF);
196 break;
197
198 case XML_ELEMENT(OFFICE, XML_NAME):
199 sNam = aIter.toString();
200 break;
201 default:
202 // do nothing
203 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
204 break;
205 }
206}
207
208void XMLImageMapObjectContext::Prepare(
209 Reference<XPropertySet> & rPropertySet)
210{
211 rPropertySet->setPropertyValue( "URL", Any( sUrl ) );
212 rPropertySet->setPropertyValue( "Title", Any( sTitleBuffer.makeStringAndClear() ) );
213 rPropertySet->setPropertyValue( "Description", Any( sDescriptionBuffer.makeStringAndClear() ) );
214 rPropertySet->setPropertyValue( "Target", Any( sTargt ) );
215 rPropertySet->setPropertyValue( "IsActive", Any( bIsActive ) );
216 rPropertySet->setPropertyValue( "Name", Any( sNam ) );
217}
218
219namespace {
220
221class XMLImageMapRectangleContext : public XMLImageMapObjectContext
222{
223 awt::Rectangle aRectangle;
224
225 bool bXOK;
226 bool bYOK;
227 bool bWidthOK;
228 bool bHeightOK;
229
230public:
231
232 XMLImageMapRectangleContext(
233 SvXMLImport& rImport,
234 css::uno::Reference<css::container::XIndexContainer> const & xMap);
235
236protected:
237 virtual void ProcessAttribute(
239
240 virtual void Prepare(
241 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
242};
243
244}
245
246XMLImageMapRectangleContext::XMLImageMapRectangleContext(
247 SvXMLImport& rImport,
248 Reference<XIndexContainer> const & xMap) :
249 XMLImageMapObjectContext(rImport, xMap,
250 "com.sun.star.image.ImageMapRectangleObject"),
251 bXOK(false),
252 bYOK(false),
253 bWidthOK(false),
254 bHeightOK(false)
255{
256}
257
258void XMLImageMapRectangleContext::ProcessAttribute(
260{
261 sal_Int32 nTmp;
262 switch (aIter.getToken())
263 {
264 case XML_ELEMENT(SVG, XML_X):
265 case XML_ELEMENT(SVG_COMPAT, XML_X):
266 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
267 aIter.toView()))
268 {
269 aRectangle.X = nTmp;
270 bXOK = true;
271 }
272 break;
273 case XML_ELEMENT(SVG, XML_Y):
274 case XML_ELEMENT(SVG_COMPAT, XML_Y):
275 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
276 aIter.toView()))
277 {
278 aRectangle.Y = nTmp;
279 bYOK = true;
280 }
281 break;
282 case XML_ELEMENT(SVG, XML_WIDTH):
283 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
284 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
285 aIter.toView()))
286 {
287 aRectangle.Width = nTmp;
288 bWidthOK = true;
289 }
290 break;
291 case XML_ELEMENT(SVG, XML_HEIGHT):
292 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
293 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
294 aIter.toView()))
295 {
296 aRectangle.Height = nTmp;
297 bHeightOK = true;
298 }
299 break;
300 default:
301 XMLImageMapObjectContext::ProcessAttribute(aIter);
302 }
303
304 bValid = bHeightOK && bXOK && bYOK && bWidthOK;
305}
306
307void XMLImageMapRectangleContext::Prepare(
308 Reference<XPropertySet> & rPropertySet)
309{
310 rPropertySet->setPropertyValue( "Boundary", uno::Any(aRectangle) );
311
312 // common properties handled by super class
313 XMLImageMapObjectContext::Prepare(rPropertySet);
314}
315
316namespace {
317
318class XMLImageMapPolygonContext : public XMLImageMapObjectContext
319{
320 OUString sViewBoxString;
321 OUString sPointsString;
322
323 bool bViewBoxOK;
324 bool bPointsOK;
325
326public:
327
328 XMLImageMapPolygonContext(
329 SvXMLImport& rImport,
330 css::uno::Reference<css::container::XIndexContainer> const & xMap);
331
332protected:
333 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter &) override;
334
335 virtual void Prepare(
336 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
337};
338
339}
340
341XMLImageMapPolygonContext::XMLImageMapPolygonContext(
342 SvXMLImport& rImport,
343 Reference<XIndexContainer> const & xMap) :
344 XMLImageMapObjectContext(rImport, xMap,
345 "com.sun.star.image.ImageMapPolygonObject"),
346 bViewBoxOK(false),
347 bPointsOK(false)
348{
349}
350
351void XMLImageMapPolygonContext::ProcessAttribute(
353{
354 switch (aIter.getToken())
355 {
356 case XML_ELEMENT(DRAW, XML_POINTS):
357 sPointsString = aIter.toString();
358 bPointsOK = true;
359 break;
360 case XML_ELEMENT(SVG, XML_VIEWBOX):
361 case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
362 sViewBoxString = aIter.toString();
363 bViewBoxOK = true;
364 break;
365 default:
366 XMLImageMapObjectContext::ProcessAttribute(aIter);
367 break;
368 }
369
370 bValid = bViewBoxOK && bPointsOK;
371}
372
373void XMLImageMapPolygonContext::Prepare(Reference<XPropertySet> & rPropertySet)
374{
375 // process view box
376 SdXMLImExViewBox aViewBox(sViewBoxString, GetImport().GetMM100UnitConverter());
377
378 // get polygon sequence
379 basegfx::B2DPolygon aPolygon;
380
381 if(basegfx::utils::importFromSvgPoints(aPolygon, sPointsString))
382 {
383 if(aPolygon.count())
384 {
385 css::drawing::PointSequence aPointSequence;
386 basegfx::utils::B2DPolygonToUnoPointSequence(aPolygon, aPointSequence);
387 rPropertySet->setPropertyValue("Polygon", Any(aPointSequence));
388 }
389 }
390
391 // parent properties
392 XMLImageMapObjectContext::Prepare(rPropertySet);
393}
394
395namespace {
396
397class XMLImageMapCircleContext : public XMLImageMapObjectContext
398{
399 awt::Point aCenter;
400 sal_Int32 nRadius;
401
402 bool bXOK;
403 bool bYOK;
404 bool bRadiusOK;
405
406public:
407
408 XMLImageMapCircleContext(
409 SvXMLImport& rImport,
410 css::uno::Reference<css::container::XIndexContainer> const & xMap);
411
412protected:
413 virtual void ProcessAttribute(
415
416 virtual void Prepare(
417 css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
418};
419
420}
421
422XMLImageMapCircleContext::XMLImageMapCircleContext(
423 SvXMLImport& rImport,
424 Reference<XIndexContainer> const & xMap)
425 : XMLImageMapObjectContext(rImport, xMap,
426 "com.sun.star.image.ImageMapCircleObject")
427 , nRadius(0)
428 , bXOK(false)
429 , bYOK(false)
430 , bRadiusOK(false)
431{
432}
433
434void XMLImageMapCircleContext::ProcessAttribute(
436{
437 sal_Int32 nTmp;
438 switch (aIter.getToken())
439 {
440 case XML_ELEMENT(SVG, XML_CX):
441 case XML_ELEMENT(SVG_COMPAT, XML_CX):
442 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
443 aIter.toView()))
444 {
445 aCenter.X = nTmp;
446 bXOK = true;
447 }
448 break;
449 case XML_ELEMENT(SVG, XML_CY):
450 case XML_ELEMENT(SVG_COMPAT, XML_CY):
451 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
452 aIter.toView()))
453 {
454 aCenter.Y = nTmp;
455 bYOK = true;
456 }
457 break;
458 case XML_ELEMENT(SVG, XML_R):
459 case XML_ELEMENT(SVG_COMPAT, XML_R):
460 if (GetImport().GetMM100UnitConverter().convertMeasureToCore(nTmp,
461 aIter.toView()))
462 {
463 nRadius = nTmp;
464 bRadiusOK = true;
465 }
466 break;
467 default:
468 XMLImageMapObjectContext::ProcessAttribute(aIter);
469 }
470
471 bValid = bRadiusOK && bXOK && bYOK;
472}
473
474void XMLImageMapCircleContext::Prepare(
475 Reference<XPropertySet> & rPropertySet)
476{
477 // center (x,y)
478 rPropertySet->setPropertyValue( "Center", uno::Any(aCenter) );
479 // radius
480 rPropertySet->setPropertyValue( "Radius", uno::Any(nRadius) );
481
482 // common properties handled by super class
483 XMLImageMapObjectContext::Prepare(rPropertySet);
484}
485
486
487constexpr OUStringLiteral gsImageMap(u"ImageMap");
488
490 SvXMLImport& rImport,
491 Reference<XPropertySet> const & rPropertySet) :
492 SvXMLImportContext(rImport),
493 xPropertySet(rPropertySet)
494{
495 try
496 {
497 Reference < XPropertySetInfo > xInfo =
498 xPropertySet->getPropertySetInfo();
499 if( xInfo.is() && xInfo->hasPropertyByName( gsImageMap ) )
500 xPropertySet->getPropertyValue(gsImageMap) >>= xImageMap;
501 }
502 catch(const css::uno::Exception& e)
503 {
504 rImport.SetError( XMLERROR_FLAG_WARNING | XMLERROR_API, {}, e.Message, nullptr );
505 }
506}
507
509{
510}
511
512css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImageMapContext::createFastChildContext(
513 sal_Int32 nElement,
514 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
515{
516 switch (nElement)
517 {
519 return new XMLImageMapRectangleContext(
522 return new XMLImageMapPolygonContext(
525 return new XMLImageMapCircleContext(
527 default:
528 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
529 }
530
531 return nullptr;
532}
533
535{
536 Reference < XPropertySetInfo > xInfo =
537 xPropertySet->getPropertySetInfo();
538 if( xInfo.is() && xInfo->hasPropertyByName( gsImageMap ) )
539 xPropertySet->setPropertyValue(gsImageMap, uno::Any( xImageMap ) );
540}
541
542/* 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:3585
#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