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 "XMLImageMapExport.hxx"
21 #include <rtl/ustring.hxx>
22 #include <rtl/ustrbuf.hxx>
23 #include <tools/debug.hxx>
24 #include <com/sun/star/uno/Reference.h>
25 #include <com/sun/star/uno/Sequence.h>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #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/awt/Size.hpp>
34 #include <com/sun/star/drawing/PointSequence.hpp>
35 #include <xmloff/xmlexp.hxx>
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/XMLEventExport.hxx>
39 #include <xmloff/xmluconv.hxx>
40 #include "xexptran.hxx"
44 using namespace ::com::sun::star
;
45 using namespace ::xmloff::token
;
47 using ::rtl::OUString
;
48 using ::rtl::OUStringBuffer
;
49 using ::com::sun::star::uno::Any
;
50 using ::com::sun::star::uno::UNO_QUERY
;
51 using ::com::sun::star::uno::Sequence
;
52 using ::com::sun::star::uno::Reference
;
53 using ::com::sun::star::beans::XPropertySet
;
54 using ::com::sun::star::container::XIndexContainer
;
55 using ::com::sun::star::document::XEventsSupplier
;
56 using ::com::sun::star::lang::XServiceInfo
;
57 using ::com::sun::star::drawing::PointSequence
;
60 const sal_Char sAPI_ImageMapRectangleObject
[] = "com.sun.star.image.ImageMapRectangleObject";
61 const sal_Char sAPI_ImageMapCircleObject
[] = "com.sun.star.image.ImageMapCircleObject";
62 const sal_Char sAPI_ImageMapPolygonObject
[] = "com.sun.star.image.ImageMapPolygonObject";
64 XMLImageMapExport::XMLImageMapExport(SvXMLExport
& rExp
) :
65 msBoundary(RTL_CONSTASCII_USTRINGPARAM("Boundary")),
66 msCenter(RTL_CONSTASCII_USTRINGPARAM("Center")),
67 msDescription(RTL_CONSTASCII_USTRINGPARAM("Description")),
68 msImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap")),
69 msIsActive(RTL_CONSTASCII_USTRINGPARAM("IsActive")),
70 msName(RTL_CONSTASCII_USTRINGPARAM("Name")),
71 msPolygon(RTL_CONSTASCII_USTRINGPARAM("Polygon")),
72 msRadius(RTL_CONSTASCII_USTRINGPARAM("Radius")),
73 msTarget(RTL_CONSTASCII_USTRINGPARAM("Target")),
74 msURL(RTL_CONSTASCII_USTRINGPARAM("URL")),
75 msTitle(RTL_CONSTASCII_USTRINGPARAM("Title")),
77 mbWhiteSpace(sal_True
)
81 XMLImageMapExport::~XMLImageMapExport()
86 void XMLImageMapExport::Export(
87 const Reference
<XPropertySet
> & rPropertySet
)
89 if (rPropertySet
->getPropertySetInfo()->hasPropertyByName(msImageMap
))
91 Any aAny
= rPropertySet
->getPropertyValue(msImageMap
);
92 Reference
<XIndexContainer
> aContainer
;
97 // else: no ImageMap property -> nothing to do
100 void XMLImageMapExport::Export(
101 const Reference
<XIndexContainer
> & rContainer
)
105 if (rContainer
->hasElements())
107 // image map container element
108 SvXMLElementExport
aImageMapElement(
109 mrExport
, XML_NAMESPACE_DRAW
, XML_IMAGE_MAP
,
110 mbWhiteSpace
, mbWhiteSpace
);
112 // iterate over image map elements and call ExportMapEntry(...)
114 sal_Int32 nLength
= rContainer
->getCount();
115 for(sal_Int32 i
= 0; i
< nLength
; i
++)
117 Any aAny
= rContainer
->getByIndex(i
);
118 Reference
<XPropertySet
> rElement
;
121 DBG_ASSERT(rElement
.is(), "Image map element is empty!");
124 ExportMapEntry(rElement
);
128 // else: container is empty -> nothing to do
130 // else: no container -> nothign to do
134 void XMLImageMapExport::ExportMapEntry(
135 const Reference
<XPropertySet
> & rPropertySet
)
137 Reference
<XServiceInfo
> xServiceInfo(rPropertySet
, UNO_QUERY
);
138 if (xServiceInfo
.is())
140 enum XMLTokenEnum eType
= XML_TOKEN_INVALID
;
142 // distinguish map entries by their service name
143 Sequence
<OUString
> sServiceNames
=
144 xServiceInfo
->getSupportedServiceNames();
145 sal_Int32 nLength
= sServiceNames
.getLength();
146 for( sal_Int32 i
=0; i
<nLength
; i
++ )
148 OUString
& rName
= sServiceNames
[i
];
150 if ( rName
.equalsAsciiL(sAPI_ImageMapRectangleObject
,
151 sizeof(sAPI_ImageMapRectangleObject
)-1) )
153 eType
= XML_AREA_RECTANGLE
;
156 else if ( rName
.equalsAsciiL(sAPI_ImageMapCircleObject
,
157 sizeof(sAPI_ImageMapCircleObject
)-1) )
159 eType
= XML_AREA_CIRCLE
;
162 else if ( rName
.equalsAsciiL(sAPI_ImageMapPolygonObject
,
163 sizeof(sAPI_ImageMapPolygonObject
)-1))
165 eType
= XML_AREA_POLYGON
;
170 // return from method if no proper service is found!
171 DBG_ASSERT(XML_TOKEN_INVALID
!= eType
,
172 "Image map element doesn't support appropriate service!");
173 if (XML_TOKEN_INVALID
== eType
)
176 // now: handle ImageMapObject properties (those for all types)
178 // XLINK (URL property)
179 Any aAny
= rPropertySet
->getPropertyValue(msURL
);
182 if (!sHref
.isEmpty())
184 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, mrExport
.GetRelativeReference(sHref
));
186 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
188 // Target property (and xlink:show)
189 aAny
= rPropertySet
->getPropertyValue(msTarget
);
192 if (!sTargt
.isEmpty())
194 mrExport
.AddAttribute(
195 XML_NAMESPACE_OFFICE
, XML_TARGET_FRAME_NAME
, sTargt
);
197 mrExport
.AddAttribute(
198 XML_NAMESPACE_XLINK
, XML_SHOW
,
199 sTargt
.equalsAsciiL( "_blank", sizeof("_blank")-1 )
200 ? XML_NEW
: XML_REPLACE
);
204 aAny
= rPropertySet
->getPropertyValue(msName
);
207 if (!sItemName
.isEmpty())
209 mrExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_NAME
, sItemName
);
213 aAny
= rPropertySet
->getPropertyValue(msIsActive
);
214 if (! *(sal_Bool
*)aAny
.getValue())
216 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_NOHREF
, XML_NOHREF
);
219 // call specific rectangle/circle/... method
220 // also prepare element name
223 case XML_AREA_RECTANGLE
:
224 ExportRectangle(rPropertySet
);
226 case XML_AREA_CIRCLE
:
227 ExportCircle(rPropertySet
);
229 case XML_AREA_POLYGON
:
230 ExportPolygon(rPropertySet
);
237 DBG_ASSERT(XML_TOKEN_INVALID
!= eType
,
238 "No name?! How did this happen?");
239 SvXMLElementExport
aAreaElement(mrExport
, XML_NAMESPACE_DRAW
, eType
,
240 mbWhiteSpace
, mbWhiteSpace
);
242 // title property (as <svg:title> element)
244 rPropertySet
->getPropertyValue(msTitle
) >>= sTitle
;
245 if(!sTitle
.isEmpty())
247 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_SVG
, XML_TITLE
, mbWhiteSpace
, sal_False
);
248 mrExport
.Characters(sTitle
);
251 // description property (as <svg:desc> element)
252 OUString sDescription
;
253 rPropertySet
->getPropertyValue(msDescription
) >>= sDescription
;
254 if (!sDescription
.isEmpty())
256 SvXMLElementExport
aDesc(mrExport
, XML_NAMESPACE_SVG
, XML_DESC
, mbWhiteSpace
, sal_False
);
257 mrExport
.Characters(sDescription
);
260 // export events attached to this
261 Reference
<XEventsSupplier
> xSupplier(rPropertySet
, UNO_QUERY
);
262 mrExport
.GetEventExport().Export(xSupplier
, mbWhiteSpace
);
264 // else: no service info -> can't determine type -> ignore entry
267 void XMLImageMapExport::ExportRectangle(
268 const Reference
<XPropertySet
> & rPropertySet
)
270 // get boundary rectangle
271 Any aAny
= rPropertySet
->getPropertyValue(msBoundary
);
272 awt::Rectangle aRectangle
;
275 // parameters svg:x, svg:y, svg:width, svg:height
276 OUStringBuffer aBuffer
;
277 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, aRectangle
.X
);
278 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_X
,
279 aBuffer
.makeStringAndClear() );
280 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, aRectangle
.Y
);
281 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_Y
,
282 aBuffer
.makeStringAndClear() );
283 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
,
285 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_WIDTH
,
286 aBuffer
.makeStringAndClear() );
287 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
,
289 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_HEIGHT
,
290 aBuffer
.makeStringAndClear() );
293 void XMLImageMapExport::ExportCircle(
294 const Reference
<XPropertySet
> & rPropertySet
)
296 // get boundary rectangle
297 Any aAny
= rPropertySet
->getPropertyValue(msCenter
);
301 // parameters svg:cx, svg:cy
302 OUStringBuffer aBuffer
;
303 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, aCenter
.X
);
304 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_CX
,
305 aBuffer
.makeStringAndClear() );
306 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, aCenter
.Y
);
307 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_CY
,
308 aBuffer
.makeStringAndClear() );
311 aAny
= rPropertySet
->getPropertyValue(msRadius
);
312 sal_Int32 nRadius
= 0;
314 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, nRadius
);
315 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_R
,
316 aBuffer
.makeStringAndClear() );
319 void XMLImageMapExport::ExportPolygon(
320 const Reference
<XPropertySet
> & rPropertySet
)
322 // polygons get exported as bounding box, viewbox, and coordinate
323 // pair sequence. The bounding box is always the entire image.
325 // get polygon point sequence
326 Any aAny
= rPropertySet
->getPropertyValue(msPolygon
);
330 // get bounding box (assume top-left to be 0,0)
331 sal_Int32 nWidth
= 0;
332 sal_Int32 nHeight
= 0;
333 sal_Int32 nLength
= aPoly
.getLength();
334 const struct awt::Point
* pPointPtr
= aPoly
.getConstArray();
335 for ( sal_Int32 i
= 0; i
< nLength
; i
++ )
337 sal_Int32 nPolyX
= pPointPtr
->X
;
338 sal_Int32 nPolyY
= pPointPtr
->Y
;
340 if ( nPolyX
> nWidth
)
342 if ( nPolyY
> nHeight
)
347 DBG_ASSERT(nWidth
> 0, "impossible Polygon found");
348 DBG_ASSERT(nHeight
> 0, "impossible Polygon found");
350 // parameters svg:x, svg:y, svg:width, svg:height
351 OUStringBuffer aBuffer
;
352 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, 0);
353 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_X
,
354 aBuffer
.makeStringAndClear() );
355 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, 0);
356 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_Y
,
357 aBuffer
.makeStringAndClear() );
358 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, nWidth
);
359 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_WIDTH
,
360 aBuffer
.makeStringAndClear() );
361 mrExport
.GetMM100UnitConverter().convertMeasureToXML(aBuffer
, nHeight
);
362 mrExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_HEIGHT
,
363 aBuffer
.makeStringAndClear() );
366 SdXMLImExViewBox
aViewBox(0, 0, nWidth
, nHeight
);
367 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_VIEWBOX
,
368 aViewBox
.GetExportString());
370 // export point sequence
371 awt::Point
aPoint(0, 0);
372 awt::Size
aSize(nWidth
, nHeight
);
373 SdXMLImExPointsElement
aPoints( &aPoly
, aViewBox
, aPoint
, aSize
);
374 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_POINTS
,
375 aPoints
.GetExportString());
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */