LibreOffice Module xmloff (master)  1
XMLImageMapExport.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 <XMLImageMapExport.hxx>
21 #include <o3tl/any.hxx>
22 #include <rtl/ustring.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <tools/debug.hxx>
25 #include <com/sun/star/uno/Reference.h>
26 #include <com/sun/star/uno/Sequence.h>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/container/XIndexContainer.hpp>
30 #include <com/sun/star/document/XEventsSupplier.hpp>
31 #include <com/sun/star/awt/Rectangle.hpp>
32 #include <com/sun/star/awt/Point.hpp>
33 #include <com/sun/star/drawing/PointSequence.hpp>
34 #include <xmloff/xmlexp.hxx>
35 #include <xmloff/xmlnmspe.hxx>
36 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/xmluconv.hxx>
39 #include <xexptran.hxx>
42 
43 using namespace ::com::sun::star;
44 using namespace ::xmloff::token;
45 
46 using ::com::sun::star::uno::Any;
47 using ::com::sun::star::uno::UNO_QUERY;
48 using ::com::sun::star::uno::Sequence;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::beans::XPropertySet;
51 using ::com::sun::star::container::XIndexContainer;
52 using ::com::sun::star::document::XEventsSupplier;
53 using ::com::sun::star::lang::XServiceInfo;
54 using ::com::sun::star::drawing::PointSequence;
55 
56 const OUStringLiteral gsBoundary("Boundary");
57 const OUStringLiteral gsCenter("Center");
58 const OUStringLiteral gsDescription("Description");
59 const OUStringLiteral gsImageMap("ImageMap");
60 const OUStringLiteral gsIsActive("IsActive");
61 const OUStringLiteral gsName("Name");
62 const OUStringLiteral gsPolygon("Polygon");
63 const OUStringLiteral gsRadius("Radius");
64 const OUStringLiteral gsTarget("Target");
65 const OUStringLiteral gsURL("URL");
66 const OUStringLiteral gsTitle("Title");
67 
69  mrExport(rExp)
70 {
71 }
72 
74 {
75 
76 }
77 
79  const Reference<XPropertySet> & rPropertySet)
80 {
81  if (rPropertySet->getPropertySetInfo()->hasPropertyByName(gsImageMap))
82  {
83  Any aAny = rPropertySet->getPropertyValue(gsImageMap);
84  Reference<XIndexContainer> aContainer;
85  aAny >>= aContainer;
86 
87  Export(aContainer);
88  }
89  // else: no ImageMap property -> nothing to do
90 }
91 
93  const Reference<XIndexContainer> & rContainer)
94 {
95  if (!rContainer.is())
96  return;
97 
98  if (!rContainer->hasElements())
99  return;
100 
101  // image map container element
102  SvXMLElementExport aImageMapElement(
104  true/*bWhiteSpace*/, true/*bWhiteSpace*/);
105 
106  // iterate over image map elements and call ExportMapEntry(...)
107  // for each
108  sal_Int32 nLength = rContainer->getCount();
109  for(sal_Int32 i = 0; i < nLength; i++)
110  {
111  Any aAny = rContainer->getByIndex(i);
112  Reference<XPropertySet> rElement;
113  aAny >>= rElement;
114 
115  DBG_ASSERT(rElement.is(), "Image map element is empty!");
116  if (rElement.is())
117  {
118  ExportMapEntry(rElement);
119  }
120  }
121  // else: container is empty -> nothing to do
122  // else: no container -> nothing to do
123 }
124 
125 
127  const Reference<XPropertySet> & rPropertySet)
128 {
129  Reference<XServiceInfo> xServiceInfo(rPropertySet, UNO_QUERY);
130  if (!xServiceInfo.is())
131  return;
132 
134 
135  // distinguish map entries by their service name
136  const Sequence<OUString> sServiceNames =
137  xServiceInfo->getSupportedServiceNames();
138  for( const OUString& rName : sServiceNames )
139  {
140  if ( rName == "com.sun.star.image.ImageMapRectangleObject" )
141  {
142  eType = XML_AREA_RECTANGLE;
143  break;
144  }
145  else if ( rName == "com.sun.star.image.ImageMapCircleObject" )
146  {
147  eType = XML_AREA_CIRCLE;
148  break;
149  }
150  else if ( rName == "com.sun.star.image.ImageMapPolygonObject" )
151  {
152  eType = XML_AREA_POLYGON;
153  break;
154  }
155  }
156 
157  // return from method if no proper service is found!
158  DBG_ASSERT(XML_TOKEN_INVALID != eType,
159  "Image map element doesn't support appropriate service!");
160  if (XML_TOKEN_INVALID == eType)
161  return;
162 
163  // now: handle ImageMapObject properties (those for all types)
164 
165  // XLINK (URL property)
166  Any aAny = rPropertySet->getPropertyValue(gsURL);
167  OUString sHref;
168  aAny >>= sHref;
169  if (!sHref.isEmpty())
170  {
172  }
174 
175  // Target property (and xlink:show)
176  aAny = rPropertySet->getPropertyValue(gsTarget);
177  OUString sTargt;
178  aAny >>= sTargt;
179  if (!sTargt.isEmpty())
180  {
183 
186  sTargt == "_blank" ? XML_NEW : XML_REPLACE );
187  }
188 
189  // name
190  aAny = rPropertySet->getPropertyValue(gsName);
191  OUString sItemName;
192  aAny >>= sItemName;
193  if (!sItemName.isEmpty())
194  {
196  }
197 
198  // is-active
199  aAny = rPropertySet->getPropertyValue(gsIsActive);
200  if (! *o3tl::doAccess<bool>(aAny))
201  {
203  }
204 
205  // call specific rectangle/circle/... method
206  // also prepare element name
207  switch (eType)
208  {
209  case XML_AREA_RECTANGLE:
210  ExportRectangle(rPropertySet);
211  break;
212  case XML_AREA_CIRCLE:
213  ExportCircle(rPropertySet);
214  break;
215  case XML_AREA_POLYGON:
216  ExportPolygon(rPropertySet);
217  break;
218  default:
219  break;
220  }
221 
222  // write element
223  DBG_ASSERT(XML_TOKEN_INVALID != eType,
224  "No name?! How did this happen?");
225  SvXMLElementExport aAreaElement(mrExport, XML_NAMESPACE_DRAW, eType,
226  true/*bWhiteSpace*/, true/*bWhiteSpace*/);
227 
228  // title property (as <svg:title> element)
229  OUString sTitle;
230  rPropertySet->getPropertyValue(gsTitle) >>= sTitle;
231  if(!sTitle.isEmpty())
232  {
233  SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, true/*bWhiteSpace*/, false);
234  mrExport.Characters(sTitle);
235  }
236 
237  // description property (as <svg:desc> element)
238  OUString sDescription;
239  rPropertySet->getPropertyValue(gsDescription) >>= sDescription;
240  if (!sDescription.isEmpty())
241  {
242  SvXMLElementExport aDesc(mrExport, XML_NAMESPACE_SVG, XML_DESC, true/*bWhiteSpace*/, false);
243  mrExport.Characters(sDescription);
244  }
245 
246  // export events attached to this
247  Reference<XEventsSupplier> xSupplier(rPropertySet, UNO_QUERY);
248  mrExport.GetEventExport().Export(xSupplier);
249 
250  // else: no service info -> can't determine type -> ignore entry
251 }
252 
254  const Reference<XPropertySet> & rPropertySet)
255 {
256  // get boundary rectangle
257  Any aAny = rPropertySet->getPropertyValue(gsBoundary);
258  awt::Rectangle aRectangle;
259  aAny >>= aRectangle;
260 
261  // parameters svg:x, svg:y, svg:width, svg:height
262  OUStringBuffer aBuffer;
263  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, aRectangle.X);
265  aBuffer.makeStringAndClear() );
266  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, aRectangle.Y);
268  aBuffer.makeStringAndClear() );
270  aRectangle.Width);
272  aBuffer.makeStringAndClear() );
274  aRectangle.Height);
276  aBuffer.makeStringAndClear() );
277 }
278 
280  const Reference<XPropertySet> & rPropertySet)
281 {
282  // get boundary rectangle
283  Any aAny = rPropertySet->getPropertyValue(gsCenter);
284  awt::Point aCenter;
285  aAny >>= aCenter;
286 
287  // parameters svg:cx, svg:cy
288  OUStringBuffer aBuffer;
289  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, aCenter.X);
291  aBuffer.makeStringAndClear() );
292  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, aCenter.Y);
294  aBuffer.makeStringAndClear() );
295 
296  // radius
297  aAny = rPropertySet->getPropertyValue(gsRadius);
298  sal_Int32 nRadius = 0;
299  aAny >>= nRadius;
302  aBuffer.makeStringAndClear() );
303 }
304 
305 void XMLImageMapExport::ExportPolygon(const Reference<XPropertySet> & rPropertySet)
306 {
307  // polygons get exported as bounding box, viewbox, and coordinate
308  // pair sequence. The bounding box is always the entire image.
309 
310  // get polygon point sequence
311  Any aAny = rPropertySet->getPropertyValue(gsPolygon);
312  PointSequence aPoly;
313  aAny >>= aPoly;
314 
315  const basegfx::B2DPolygon aPolygon(
317  aPoly));
318  const basegfx::B2DRange aPolygonRange(aPolygon.getB2DRange());
319 
320  // parameters svg:x, svg:y, svg:width, svg:height
321  OUStringBuffer aBuffer;
322 
324  mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, aBuffer.makeStringAndClear() );
326  mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, aBuffer.makeStringAndClear() );
327  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, basegfx::fround(aPolygonRange.getWidth()));
328  mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, aBuffer.makeStringAndClear() );
329  mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, basegfx::fround(aPolygonRange.getHeight()));
330  mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, aBuffer.makeStringAndClear() );
331 
332  // svg:viewbox
333  SdXMLImExViewBox aViewBox(0.0, 0.0, aPolygonRange.getWidth(), aPolygonRange.getHeight());
334  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
335 
336  // export point sequence
337  const OUString aPointString(
339  aPolygon));
340 
342 }
343 
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUStringLiteral gsPolygon("Polygon")
const OUStringLiteral gsTarget("Target")
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlexp.hxx:394
const OUStringLiteral gsName("Name")
const OUStringLiteral gsBoundary("Boundary")
void ExportMapEntry(const css::uno::Reference< css::beans::XPropertySet > &rPropertySet)
Export a single, named map entry.
const OUStringLiteral gsIsActive("IsActive")
const OUStringLiteral gsDescription("Description")
const OUStringLiteral gsImageMap("ImageMap")
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:909
const OUStringLiteral gsTitle("Title")
OUString GetRelativeReference(const OUString &rValue)
Definition: xmlexp.cxx:2089
B2IRange fround(const B2DRange &rRange)
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
DocumentType eType
constexpr sal_uInt16 XML_NAMESPACE_DRAW
Definition: xmlnmspe.hxx:33
B2DPolygon UnoPointSequenceToB2DPolygon(const css::drawing::PointSequence &rPointSequenceSource)
const OUStringLiteral gsCenter("Center")
#define DBG_ASSERT(sCon, aError)
int i
XMLEventExport & GetEventExport()
get Event export, with handlers for script types "None" and "StarBasic" already registered; other han...
Definition: xmlexp.cxx:2009
void Export(const css::uno::Reference< css::beans::XPropertySet > &rPropertySet)
Get the ImageMap object from the "ImageMap" property and subsequently export the map (if present)...
void ExportCircle(const css::uno::Reference< css::beans::XPropertySet > &rPropertySet)
Export the specifics of a circular image map entry.
XMLImageMapExport(SvXMLExport &rExport)
const OUStringLiteral gsURL("URL")
constexpr sal_uInt16 XML_NAMESPACE_XLINK
Definition: xmlnmspe.hxx:35
B2DRange const & getB2DRange() const
std::unique_ptr< char[]> aBuffer
SvXMLExport & mrExport
Handling of tokens in XML:
void Characters(const OUString &rChars)
Definition: xmlexp.cxx:2158
OUString exportToSvgPoints(const B2DPolygon &rPoly)
void ExportRectangle(const css::uno::Reference< css::beans::XPropertySet > &rPropertySet)
Export the specifics of a rectangular image map entry.
const OUStringLiteral gsRadius("Radius")
sal_Int32 nLength
Definition: xmltoken.cxx:36
constexpr sal_uInt16 XML_NAMESPACE_SVG
Definition: xmlnmspe.hxx:40
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
Definition: xmluconv.cxx:181
void ExportPolygon(const css::uno::Reference< css::beans::XPropertySet > &rPropertySet)
Export the specifics of a polygonal image map entry; To be called by ExportMapEntry.
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
Definition: xmlnmspe.hxx:29
void Export(css::uno::Reference< css::document::XEventsSupplier > const &xAccess, bool bUseWhitespace=true)
export the events (calls EventExport::Export(Reference) )