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 
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/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>
34 #include <xmloff/xmlnamespace.hxx>
35 #include <xmloff/namespacemap.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 
46 using namespace ::com::sun::star;
47 using namespace ::xmloff::token;
48 
49 using ::com::sun::star::beans::XPropertySet;
50 using ::com::sun::star::beans::XPropertySetInfo;
51 using ::com::sun::star::container::XIndexContainer;
52 using ::com::sun::star::lang::XMultiServiceFactory;
53 using ::com::sun::star::uno::Reference;
54 using ::com::sun::star::uno::UNO_QUERY;
55 using ::com::sun::star::xml::sax::XAttributeList;
56 using ::com::sun::star::uno::XInterface;
57 using ::com::sun::star::uno::Any;
58 using ::com::sun::star::document::XEventsSupplier;
59 
60 namespace {
61 
62 class XMLImageMapObjectContext : public SvXMLImportContext
63 {
64 
65 protected:
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 
79 public:
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 
95 protected:
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 
105 XMLImageMapObjectContext::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 
134 void 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 
141 void 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 
156 css::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):
170  return new XMLStringBufferImportContext(
171  GetImport(), sTitleBuffer);
172  case XML_ELEMENT(SVG, XML_DESC):
173  case XML_ELEMENT(SVG_COMPAT, XML_DESC):
174  return new XMLStringBufferImportContext(
175  GetImport(), sDescriptionBuffer);
176  }
177  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
178  return nullptr;
179 }
180 
181 void XMLImageMapObjectContext::ProcessAttribute(
183 {
184  switch (aIter.getToken())
185  {
186  case XML_ELEMENT(XLINK, XML_HREF):
187  sUrl = GetImport().GetAbsoluteReference(aIter.toString());
188  break;
189 
190  case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
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 
208 void 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 
219 namespace {
220 
221 class XMLImageMapRectangleContext : public XMLImageMapObjectContext
222 {
223  awt::Rectangle aRectangle;
224 
225  bool bXOK;
226  bool bYOK;
227  bool bWidthOK;
228  bool bHeightOK;
229 
230 public:
231 
232  XMLImageMapRectangleContext(
233  SvXMLImport& rImport,
234  css::uno::Reference<css::container::XIndexContainer> const & xMap);
235 
236 protected:
237  virtual void ProcessAttribute(
239 
240  virtual void Prepare(
241  css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
242 };
243 
244 }
245 
246 XMLImageMapRectangleContext::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 
258 void 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 
307 void 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 
316 namespace {
317 
318 class XMLImageMapPolygonContext : public XMLImageMapObjectContext
319 {
320  OUString sViewBoxString;
321  OUString sPointsString;
322 
323  bool bViewBoxOK;
324  bool bPointsOK;
325 
326 public:
327 
328  XMLImageMapPolygonContext(
329  SvXMLImport& rImport,
330  css::uno::Reference<css::container::XIndexContainer> const & xMap);
331 
332 protected:
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 
341 XMLImageMapPolygonContext::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 
351 void 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 
373 void 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 
395 namespace {
396 
397 class XMLImageMapCircleContext : public XMLImageMapObjectContext
398 {
399  awt::Point aCenter;
400  sal_Int32 nRadius;
401 
402  bool bXOK;
403  bool bYOK;
404  bool bRadiusOK;
405 
406 public:
407 
408  XMLImageMapCircleContext(
409  SvXMLImport& rImport,
410  css::uno::Reference<css::container::XIndexContainer> const & xMap);
411 
412 protected:
413  virtual void ProcessAttribute(
415 
416  virtual void Prepare(
417  css::uno::Reference<css::beans::XPropertySet> & rPropertySet) override;
418 };
419 
420 }
421 
422 XMLImageMapCircleContext::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 
434 void 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 
474 void 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 
487 constexpr 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  uno::Sequence<OUString> aSeq(0);
505  rImport.SetError( XMLERROR_FLAG_WARNING | XMLERROR_API, aSeq, e.Message, nullptr );
506  }
507 }
508 
510 {
511 }
512 
513 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImageMapContext::createFastChildContext(
514  sal_Int32 nElement,
515  const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
516 {
517  switch (nElement)
518  {
520  return new XMLImageMapRectangleContext(
521  GetImport(), xImageMap);
523  return new XMLImageMapPolygonContext(
524  GetImport(), xImageMap);
526  return new XMLImageMapCircleContext(
527  GetImport(), xImageMap);
528  default:
529  XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
530  }
531 
532  return nullptr;
533 }
534 
536 {
537  Reference < XPropertySetInfo > xInfo =
538  xPropertySet->getPropertySetInfo();
539  if( xInfo.is() && xInfo->hasPropertyByName( gsImageMap ) )
540  xPropertySet->setPropertyValue(gsImageMap, uno::makeAny( xImageMap ) );
541 }
542 
543 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool importFromSvgPoints(B2DPolygon &o_rPoly, const OUString &rSvgPointsAttribute)
void B2DPolygonToUnoPointSequence(const B2DPolygon &rPolygon, css::drawing::PointSequence &rPointSequenceRetval)
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
Definition: xmlimp.cxx:840
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:56
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3462
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
#define XMLERROR_API
Definition: xmlerror.hxx:71
css::uno::Reference< css::container::XIndexContainer > xImageMap
the image map to be imported
DRAW
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:110
#define XMLERROR_FLAG_WARNING
Definition: xmlerror.hxx:35
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlimp.cxx:744
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlimp.cxx:869
#define DBG_ASSERT(sCon, aError)
XMLImageMapContext(SvXMLImport &rImport, css::uno::Reference< css::beans::XPropertySet > const &rPropertySet)
virtual ~XMLImageMapContext() override
Import all text into a string buffer.
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:45
Handling of tokens in XML:
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:96
void SetError(sal_Int32 nId, const css::uno::Sequence< OUString > &rMsgParams, const OUString &rExceptionMessage, const css::uno::Reference< css::xml::sax::XLocator > &rLocator)
Record an error condition that occurred during import.
Sequence< sal_Int8 > aSeq
Reference< XSingleServiceFactory > xFactory
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:116
css::uno::Reference< css::beans::XPropertySet > xPropertySet
the property set from which to get and where eventually to set the image map
if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
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 ...
OUString toString(OptionInfo const *info)
sal_uInt32 count() const
constexpr OUStringLiteral gsImageMap(u"ImageMap")
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override