xref: /AOO41X/main/xmloff/source/draw/XMLImageMapExport.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include "XMLImageMapExport.hxx"
27 #include <rtl/ustring.hxx>
28 #include <rtl/ustrbuf.hxx>
29 #include <tools/debug.hxx>
30 #include <com/sun/star/uno/Reference.h>
31 #include <com/sun/star/uno/Sequence.h>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/container/XIndexContainer.hpp>
35 
36 #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP
37 #include <com/sun/star/document/XEventsSupplier.hpp>
38 #endif
39 #include <com/sun/star/awt/Rectangle.hpp>
40 #include <com/sun/star/awt/Point.hpp>
41 #include <com/sun/star/awt/Size.hpp>
42 #include <com/sun/star/drawing/PointSequence.hpp>
43 #include <xmloff/xmlexp.hxx>
44 #include "xmloff/xmlnmspe.hxx"
45 #include <xmloff/xmltoken.hxx>
46 #include <xmloff/XMLEventExport.hxx>
47 #include <xmloff/xmluconv.hxx>
48 #include "xexptran.hxx"
49 
50 
51 
52 using namespace ::com::sun::star;
53 using namespace ::xmloff::token;
54 
55 using ::rtl::OUString;
56 using ::rtl::OUStringBuffer;
57 using ::com::sun::star::uno::Any;
58 using ::com::sun::star::uno::UNO_QUERY;
59 using ::com::sun::star::uno::Sequence;
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::beans::XPropertySet;
62 using ::com::sun::star::container::XIndexContainer;
63 using ::com::sun::star::document::XEventsSupplier;
64 using ::com::sun::star::lang::XServiceInfo;
65 using ::com::sun::star::drawing::PointSequence;
66 
67 
68 const sal_Char sAPI_ImageMapRectangleObject[] = "com.sun.star.image.ImageMapRectangleObject";
69 const sal_Char sAPI_ImageMapCircleObject[] = "com.sun.star.image.ImageMapCircleObject";
70 const sal_Char sAPI_ImageMapPolygonObject[] = "com.sun.star.image.ImageMapPolygonObject";
71 
72 XMLImageMapExport::XMLImageMapExport(SvXMLExport& rExp) :
73     msBoundary(RTL_CONSTASCII_USTRINGPARAM("Boundary")),
74     msCenter(RTL_CONSTASCII_USTRINGPARAM("Center")),
75     msDescription(RTL_CONSTASCII_USTRINGPARAM("Description")),
76     msImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap")),
77     msIsActive(RTL_CONSTASCII_USTRINGPARAM("IsActive")),
78     msName(RTL_CONSTASCII_USTRINGPARAM("Name")),
79     msPolygon(RTL_CONSTASCII_USTRINGPARAM("Polygon")),
80     msRadius(RTL_CONSTASCII_USTRINGPARAM("Radius")),
81     msTarget(RTL_CONSTASCII_USTRINGPARAM("Target")),
82     msURL(RTL_CONSTASCII_USTRINGPARAM("URL")),
83     msTitle(RTL_CONSTASCII_USTRINGPARAM("Title")),
84     mrExport(rExp),
85     mbWhiteSpace(sal_True)
86 {
87 }
88 
89 XMLImageMapExport::~XMLImageMapExport()
90 {
91 
92 }
93 
94 void XMLImageMapExport::Export(
95     const Reference<XPropertySet> & rPropertySet)
96 {
97     if (rPropertySet->getPropertySetInfo()->hasPropertyByName(msImageMap))
98     {
99         Any aAny = rPropertySet->getPropertyValue(msImageMap);
100         Reference<XIndexContainer> aContainer;
101         aAny >>= aContainer;
102 
103         Export(aContainer);
104     }
105     // else: no ImageMap property -> nothing to do
106 }
107 
108 void XMLImageMapExport::Export(
109     const Reference<XIndexContainer> & rContainer)
110 {
111     if (rContainer.is())
112     {
113         if (rContainer->hasElements())
114         {
115             // image map container element
116             SvXMLElementExport aImageMapElement(
117                 mrExport, XML_NAMESPACE_DRAW, XML_IMAGE_MAP,
118                 mbWhiteSpace, mbWhiteSpace);
119 
120             // iterate over image map elements and call ExportMapEntry(...)
121             // for each
122             sal_Int32 nLength = rContainer->getCount();
123             for(sal_Int32 i = 0; i < nLength; i++)
124             {
125                 Any aAny = rContainer->getByIndex(i);
126                 Reference<XPropertySet> rElement;
127                 aAny >>= rElement;
128 
129                 DBG_ASSERT(rElement.is(), "Image map element is empty!");
130                 if (rElement.is())
131                 {
132                     ExportMapEntry(rElement);
133                 }
134             }
135         }
136         // else: container is empty -> nothing to do
137     }
138     // else: no container -> nothign to do
139 }
140 
141 
142 void XMLImageMapExport::ExportMapEntry(
143     const Reference<XPropertySet> & rPropertySet)
144 {
145     Reference<XServiceInfo> xServiceInfo(rPropertySet, UNO_QUERY);
146     if (xServiceInfo.is())
147     {
148         enum XMLTokenEnum eType = XML_TOKEN_INVALID;
149 
150         // distinguish map entries by their service name
151         Sequence<OUString> sServiceNames =
152             xServiceInfo->getSupportedServiceNames();
153         sal_Int32 nLength = sServiceNames.getLength();
154         for( sal_Int32 i=0; i<nLength; i++ )
155         {
156             OUString& rName = sServiceNames[i];
157 
158             if ( rName.equalsAsciiL(sAPI_ImageMapRectangleObject,
159                                     sizeof(sAPI_ImageMapRectangleObject)-1) )
160             {
161                 eType = XML_AREA_RECTANGLE;
162                 break;
163             }
164             else if ( rName.equalsAsciiL(sAPI_ImageMapCircleObject,
165                                          sizeof(sAPI_ImageMapCircleObject)-1) )
166             {
167                 eType = XML_AREA_CIRCLE;
168                 break;
169             }
170             else if ( rName.equalsAsciiL(sAPI_ImageMapPolygonObject,
171                                          sizeof(sAPI_ImageMapPolygonObject)-1))
172             {
173                 eType = XML_AREA_POLYGON;
174                 break;
175             }
176         }
177 
178         // return from method if no proper service is found!
179         DBG_ASSERT(XML_TOKEN_INVALID != eType,
180                    "Image map element doesn't support appropriate service!");
181         if (XML_TOKEN_INVALID == eType)
182             return;
183 
184         // now: handle ImageMapObject properties (those for all types)
185 
186         // XLINK (URL property)
187         Any aAny = rPropertySet->getPropertyValue(msURL);
188         OUString sHref;
189         aAny >>= sHref;
190         if (sHref.getLength() > 0)
191         {
192             mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, mrExport.GetRelativeReference(sHref));
193         }
194         mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
195 
196         // Target property (and xlink:show)
197         aAny = rPropertySet->getPropertyValue(msTarget);
198         OUString sTargt;
199         aAny >>= sTargt;
200         if (sTargt.getLength() > 0)
201         {
202             mrExport.AddAttribute(
203                 XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, sTargt);
204 
205             mrExport.AddAttribute(
206                 XML_NAMESPACE_XLINK, XML_SHOW,
207                 sTargt.equalsAsciiL( "_blank", sizeof("_blank")-1 )
208                                         ? XML_NEW : XML_REPLACE );
209         }
210 
211         // name
212         aAny = rPropertySet->getPropertyValue(msName);
213         OUString sItemName;
214         aAny >>= sItemName;
215         if (sItemName.getLength() > 0)
216         {
217             mrExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, sItemName);
218         }
219 
220         // is-active
221         aAny = rPropertySet->getPropertyValue(msIsActive);
222         if (! *(sal_Bool*)aAny.getValue())
223         {
224             mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NOHREF, XML_NOHREF);
225         }
226 
227         // call specific rectangle/circle/... method
228         // also prepare element name
229         switch (eType)
230         {
231             case XML_AREA_RECTANGLE:
232                 ExportRectangle(rPropertySet);
233                 break;
234             case XML_AREA_CIRCLE:
235                 ExportCircle(rPropertySet);
236                 break;
237             case XML_AREA_POLYGON:
238                 ExportPolygon(rPropertySet);
239                 break;
240             default:
241                 break;
242         }
243 
244         // write element
245         DBG_ASSERT(XML_TOKEN_INVALID != eType,
246                    "No name?! How did this happen?");
247         SvXMLElementExport aAreaElement(mrExport, XML_NAMESPACE_DRAW, eType,
248                                         mbWhiteSpace, mbWhiteSpace);
249 
250         // title property (as <svg:title> element)
251         OUString sTitle;
252         rPropertySet->getPropertyValue(msTitle) >>= sTitle;
253         if(sTitle.getLength())
254         {
255             SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, mbWhiteSpace, sal_False);
256             mrExport.Characters(sTitle);
257         }
258 
259         // description property (as <svg:desc> element)
260         OUString sDescription;
261         rPropertySet->getPropertyValue(msDescription) >>= sDescription;
262         if (sDescription.getLength() > 0)
263         {
264             SvXMLElementExport aDesc(mrExport, XML_NAMESPACE_SVG, XML_DESC, mbWhiteSpace, sal_False);
265             mrExport.Characters(sDescription);
266         }
267 
268         // export events attached to this
269         Reference<XEventsSupplier> xSupplier(rPropertySet, UNO_QUERY);
270         mrExport.GetEventExport().Export(xSupplier, mbWhiteSpace);
271     }
272     // else: no service info -> can't determine type -> ignore entry
273 }
274 
275 void XMLImageMapExport::ExportRectangle(
276     const Reference<XPropertySet> & rPropertySet)
277 {
278     // get boundary rectangle
279     Any aAny = rPropertySet->getPropertyValue(msBoundary);
280     awt::Rectangle aRectangle;
281     aAny >>= aRectangle;
282 
283     // parameters svg:x, svg:y, svg:width, svg:height
284     OUStringBuffer aBuffer;
285     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.X);
286     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X,
287                           aBuffer.makeStringAndClear() );
288     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Y);
289     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y,
290                           aBuffer.makeStringAndClear() );
291     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Width);
292     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
293                           aBuffer.makeStringAndClear() );
294     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aRectangle.Height);
295     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
296                           aBuffer.makeStringAndClear() );
297 }
298 
299 void XMLImageMapExport::ExportCircle(
300     const Reference<XPropertySet> & rPropertySet)
301 {
302     // get boundary rectangle
303     Any aAny = rPropertySet->getPropertyValue(msCenter);
304     awt::Point aCenter;
305     aAny >>= aCenter;
306 
307     // parameters svg:cx, svg:cy
308     OUStringBuffer aBuffer;
309     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aCenter.X);
310     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_CX,
311                           aBuffer.makeStringAndClear() );
312     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, aCenter.Y);
313     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_CY,
314                           aBuffer.makeStringAndClear() );
315 
316     // radius
317     aAny = rPropertySet->getPropertyValue(msRadius);
318     sal_Int32 nRadius = 0;
319     aAny >>= nRadius;
320     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, nRadius);
321     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_R,
322                           aBuffer.makeStringAndClear() );
323 }
324 
325 void XMLImageMapExport::ExportPolygon(
326     const Reference<XPropertySet> & rPropertySet)
327 {
328     // polygons get exported as bounding box, viewbox, and coordinate
329     // pair sequence. The bounding box is always the entire image.
330 
331     // get polygon point sequence
332     Any aAny = rPropertySet->getPropertyValue(msPolygon);
333     PointSequence aPoly;
334     aAny >>= aPoly;
335 
336     // get bounding box (assume top-left to be 0,0)
337     sal_Int32 nWidth = 0;
338     sal_Int32 nHeight = 0;
339     sal_Int32 nLength = aPoly.getLength();
340     const struct awt::Point* pPointPtr = aPoly.getConstArray();
341     for ( sal_Int32 i = 0; i < nLength; i++ )
342     {
343         sal_Int32 nPolyX = pPointPtr->X;
344         sal_Int32 nPolyY = pPointPtr->Y;
345 
346         if ( nPolyX > nWidth )
347             nWidth = nPolyX;
348         if ( nPolyY > nHeight )
349             nHeight = nPolyY;
350 
351         pPointPtr++;
352     }
353     DBG_ASSERT(nWidth > 0, "impossible Polygon found");
354     DBG_ASSERT(nHeight > 0, "impossible Polygon found");
355 
356     // parameters svg:x, svg:y, svg:width, svg:height
357     OUStringBuffer aBuffer;
358     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, 0);
359     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X,
360                           aBuffer.makeStringAndClear() );
361     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, 0);
362     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y,
363                           aBuffer.makeStringAndClear() );
364     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, nWidth);
365     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
366                           aBuffer.makeStringAndClear() );
367     mrExport.GetMM100UnitConverter().convertMeasure(aBuffer, nHeight);
368     mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
369                           aBuffer.makeStringAndClear() );
370 
371     // svg:viewbox
372     SdXMLImExViewBox aViewBox(0, 0, nWidth, nHeight);
373     mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
374                 aViewBox.GetExportString());
375 
376     // export point sequence
377     awt::Point aPoint(0, 0);
378     awt::Size aSize(nWidth, nHeight);
379     SdXMLImExPointsElement aPoints( &aPoly, aViewBox, aPoint, aSize );
380     mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_POINTS,
381                           aPoints.GetExportString());
382 }
383