1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 #include <com/sun/star/graphic/XGraphic.hpp>
32 #include <com/sun/star/graphic/XGraphicProvider.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/embed/XTransactedObject.hpp>
35 #include <com/sun/star/io/XSeekableInputStream.hpp>
36 #include <com/sun/star/drawing/HomogenMatrix.hpp>
37 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
38 #include <com/sun/star/drawing/ProjectionMode.hpp>
39 #include <com/sun/star/drawing/ShadeMode.hpp>
40 #include <com/sun/star/drawing/Direction3D.hpp>
41 #include <com/sun/star/drawing/Position3D.hpp>
42 #include <com/sun/star/drawing/CameraGeometry.hpp>
43 #include <com/sun/star/drawing/DoubleSequence.hpp>
44 
45 #include <com/sun/star/table/XColumnRowRange.hpp>
46 
47 #ifndef _XMLOFF_SHAPEEXPORT_HXX
48 #include <xmloff/shapeexport.hxx>
49 #endif
50 #include "sdpropls.hxx"
51 #include <tools/debug.hxx>
52 #include <rtl/ustrbuf.hxx>
53 #include <xmloff/xmlexp.hxx>
54 #include <xmloff/xmluconv.hxx>
55 #include "xexptran.hxx"
56 #include <xmloff/xmltoken.hxx>
57 #include "EnhancedCustomShapeToken.hxx"
58 #include <com/sun/star/container/XIdentifierContainer.hpp>
59 #include <com/sun/star/drawing/ShadeMode.hpp>
60 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
61 #ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEPARAMETERPARI_HPP_
62 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
63 #endif
64 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
65 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
66 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
67 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
68 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
69 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
70 #include <com/sun/star/beans/PropertyValues.hpp>
71 #include <rtl/math.hxx>
72 #include <tools/string.hxx>
73 #include <basegfx/vector/b3dvector.hxx>
74 
75 #include "xmloff/xmlnmspe.hxx"
76 #include "XMLBase64Export.hxx"
77 
78 using ::rtl::OUString;
79 using ::rtl::OUStringBuffer;
80 
81 using namespace ::com::sun::star;
82 using namespace ::com::sun::star::io;
83 using namespace ::xmloff::token;
84 using namespace ::xmloff::EnhancedCustomShapeToken;
85 
86 using ::com::sun::star::embed::XStorage;
87 using ::com::sun::star::uno::UNO_QUERY;
88 using ::com::sun::star::uno::UNO_QUERY_THROW;
89 using ::com::sun::star::uno::Reference;
90 using ::com::sun::star::uno::Sequence;
91 
92 //////////////////////////////////////////////////////////////////////////////
93 
94 void ExportParameter( rtl::OUStringBuffer& rStrBuffer, const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter )
95 {
96 	if ( rStrBuffer.getLength() )
97 		rStrBuffer.append( (sal_Unicode)' ' );
98 	if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
99 	{
100 		double fNumber = 0.0;
101 		rParameter.Value >>= fNumber;
102 		::rtl::math::doubleToUStringBuffer( rStrBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True );
103 	}
104 	else
105 	{
106 		sal_Int32 nValue = 0;
107 		rParameter.Value >>= nValue;
108 
109 		switch( rParameter.Type )
110 		{
111 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
112 			{
113 				rStrBuffer.append( (sal_Unicode)'?' );
114 				rStrBuffer.append( (sal_Unicode)'f' );
115 				rStrBuffer.append( rtl::OUString::valueOf( nValue ) );
116 			}
117 			break;
118 
119 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
120 			{
121 				rStrBuffer.append( (sal_Unicode)'$' );
122 				rStrBuffer.append( rtl::OUString::valueOf( nValue ) );
123 			}
124 			break;
125 
126 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
127 				rStrBuffer.append( GetXMLToken( XML_BOTTOM ) ); break;
128 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
129 				rStrBuffer.append( GetXMLToken( XML_RIGHT ) ); break;
130 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
131 				rStrBuffer.append( GetXMLToken( XML_TOP ) ); break;
132 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
133 				rStrBuffer.append( GetXMLToken( XML_LEFT ) ); break;
134 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::XSTRETCH :
135 				rStrBuffer.append( GetXMLToken( XML_XSTRETCH ) ); break;
136 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::YSTRETCH :
137 				rStrBuffer.append( GetXMLToken( XML_YSTRETCH ) ); break;
138 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::HASSTROKE :
139 				rStrBuffer.append( GetXMLToken( XML_HASSTROKE ) ); break;
140 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::HASFILL :
141 				rStrBuffer.append( GetXMLToken( XML_HASFILL ) ); break;
142 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::WIDTH :
143 				rStrBuffer.append( GetXMLToken( XML_WIDTH ) ); break;
144 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::HEIGHT :
145 				rStrBuffer.append( GetXMLToken( XML_HEIGHT ) ); break;
146 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGWIDTH :
147 				rStrBuffer.append( GetXMLToken( XML_LOGWIDTH ) ); break;
148 			case com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT :
149 				rStrBuffer.append( GetXMLToken( XML_LOGHEIGHT ) ); break;
150 			default :
151 				rStrBuffer.append( rtl::OUString::valueOf( nValue ) );
152 		}
153 	}
154 }
155 
156 void ImpExportEquations( SvXMLExport& rExport, const uno::Sequence< rtl::OUString >& rEquations )
157 {
158 	sal_Int32 i;
159 	for ( i = 0; i < rEquations.getLength(); i++ )
160 	{
161 		rtl::OUString aStr( String( 'f' ) );
162 		aStr += rtl::OUString::valueOf( i );
163 		rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aStr );
164 
165 		aStr = rEquations[ i ];
166 		sal_Int32 nIndex = 0;
167 		do
168 		{
169 			nIndex = aStr.indexOf( (sal_Unicode)'?', nIndex );
170 			if ( nIndex != -1 )
171 			{
172 				rtl::OUString aNew( aStr.copy( 0, nIndex + 1 ) );
173 				aNew += String( 'f' );
174 				aNew += aStr.copy( nIndex + 1, ( aStr.getLength() - nIndex ) - 1 );
175 				aStr = aNew;
176 				nIndex++;
177 			}
178 		} while( nIndex != -1 );
179 		rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FORMULA, aStr );
180 		SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_EQUATION, sal_True, sal_True );
181 	}
182 }
183 
184 void ImpExportHandles( SvXMLExport& rExport, const uno::Sequence< beans::PropertyValues >& rHandles )
185 {
186 	sal_uInt32 i, j, nElements = rHandles.getLength();
187 	if ( nElements )
188 	{
189 		rtl::OUString		aStr;
190 		rtl::OUStringBuffer aStrBuffer;
191 
192 		for ( i = 0; i < nElements; i++ )
193 		{
194 			sal_Bool bPosition = sal_False;
195 			const uno::Sequence< beans::PropertyValue >& rPropSeq = rHandles[ i ];
196 			for ( j = 0; j < (sal_uInt32)rPropSeq.getLength(); j++ )
197 			{
198 				const beans::PropertyValue& rPropVal = rPropSeq[ j ];
199 				switch( EASGet( rPropVal.Name ) )
200 				{
201 					case EAS_Position :
202 					{
203 						com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
204 						if ( rPropVal.Value >>= aPosition )
205 						{
206 							ExportParameter( aStrBuffer, aPosition.First );
207 							ExportParameter( aStrBuffer, aPosition.Second );
208 							aStr = aStrBuffer.makeStringAndClear();
209 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_POSITION, aStr );
210 							bPosition = sal_True;
211 						}
212 					}
213 					break;
214 					case EAS_MirroredX :
215 					{
216 						sal_Bool bMirroredX = sal_Bool();
217 						if ( rPropVal.Value >>= bMirroredX )
218 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_MIRROR_HORIZONTAL,
219 								bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
220 					}
221 					break;
222 					case EAS_MirroredY :
223 					{
224 						sal_Bool bMirroredY = sal_Bool();
225 						if ( rPropVal.Value >>= bMirroredY )
226 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_MIRROR_VERTICAL,
227 								bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
228 					}
229 					break;
230 					case EAS_Switched :
231 					{
232 						sal_Bool bSwitched = sal_Bool();
233 						if ( rPropVal.Value >>= bSwitched )
234 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_SWITCHED,
235 								bSwitched ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
236 					}
237 					break;
238 					case EAS_Polar :
239 					{
240 						com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar;
241 						if ( rPropVal.Value >>= aPolar )
242 						{
243 							ExportParameter( aStrBuffer, aPolar.First );
244 							ExportParameter( aStrBuffer, aPolar.Second );
245 							aStr = aStrBuffer.makeStringAndClear();
246 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_POLAR, aStr );
247 						}
248 					}
249 					break;
250 					case EAS_RadiusRangeMinimum :
251 					{
252 						com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
253 						if ( rPropVal.Value >>= aRadiusRangeMinimum )
254 						{
255 							ExportParameter( aStrBuffer, aRadiusRangeMinimum );
256 							aStr = aStrBuffer.makeStringAndClear();
257 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RADIUS_RANGE_MINIMUM, aStr );
258 						}
259 					}
260 					break;
261 					case EAS_RadiusRangeMaximum :
262 					{
263 						com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
264 						if ( rPropVal.Value >>= aRadiusRangeMaximum )
265 						{
266 							ExportParameter( aStrBuffer, aRadiusRangeMaximum );
267 							aStr = aStrBuffer.makeStringAndClear();
268 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RADIUS_RANGE_MAXIMUM, aStr );
269 						}
270 					}
271 					break;
272 					case EAS_RangeXMinimum :
273 					{
274 						com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
275 						if ( rPropVal.Value >>= aXRangeMinimum )
276 						{
277 							ExportParameter( aStrBuffer, aXRangeMinimum );
278 							aStr = aStrBuffer.makeStringAndClear();
279 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RANGE_X_MINIMUM, aStr );
280 						}
281 					}
282 					break;
283 					case EAS_RangeXMaximum :
284 					{
285 						com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
286 						if ( rPropVal.Value >>= aXRangeMaximum )
287 						{
288 							ExportParameter( aStrBuffer, aXRangeMaximum );
289 							aStr = aStrBuffer.makeStringAndClear();
290 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RANGE_X_MAXIMUM, aStr );
291 						}
292 					}
293 					break;
294 					case EAS_RangeYMinimum :
295 					{
296 						com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
297 						if ( rPropVal.Value >>= aYRangeMinimum )
298 						{
299 							ExportParameter( aStrBuffer, aYRangeMinimum );
300 							aStr = aStrBuffer.makeStringAndClear();
301 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RANGE_Y_MINIMUM, aStr );
302 						}
303 					}
304 					break;
305 					case EAS_RangeYMaximum :
306 					{
307 						com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
308 						if ( rPropVal.Value >>= aYRangeMaximum )
309 						{
310 							ExportParameter( aStrBuffer, aYRangeMaximum );
311 							aStr = aStrBuffer.makeStringAndClear();
312 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_HANDLE_RANGE_Y_MAXIMUM, aStr );
313 						}
314 					}
315 					break;
316 					default:
317 						break;
318 				}
319 			}
320 			if ( bPosition )
321 				SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_HANDLE, sal_True, sal_True );
322 			else
323 				rExport.ClearAttrList();
324 		}
325 	}
326 }
327 
328 void ImpExportEnhancedPath( SvXMLExport& rExport,
329 	const uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >& rCoordinates,
330 		const uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment >& rSegments )
331 {
332 
333 	rtl::OUString		aStr;
334 	rtl::OUStringBuffer aStrBuffer;
335 
336 	sal_Int32 i, j, k, l;
337 
338 	sal_Int32 nCoords = rCoordinates.getLength();
339 	sal_Int32 nSegments = rSegments.getLength();
340 	sal_Bool bSimpleSegments = nSegments == 0;
341 	if ( bSimpleSegments )
342 		nSegments = 4;
343 	for ( j = i = 0; j < nSegments; j++ )
344 	{
345 		com::sun::star::drawing::EnhancedCustomShapeSegment aSegment;
346 		if ( bSimpleSegments )
347 		{
348 			// if there are not enough segments we will default them
349 			switch( j )
350 			{
351 				case 0 :
352 				{
353 					aSegment.Count = 1;
354 					aSegment.Command = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
355 				}
356 				break;
357 				case 1 :
358 				{
359 					aSegment.Count = (sal_Int16)Min( nCoords - 1, (sal_Int32)32767 );
360 					aSegment.Command = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
361 				}
362 				break;
363 				case 2 :
364 				{
365 					aSegment.Count = 1;
366 					aSegment.Command = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
367 				}
368 				break;
369 				case 3 :
370 				{
371 					aSegment.Count = 1;
372 					aSegment.Command = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
373 				}
374 				break;
375 			}
376 		}
377 		else
378 			aSegment = rSegments[ j ];
379 
380 		if ( aStrBuffer.getLength() )
381 			aStrBuffer.append( (sal_Unicode)' ' );
382 
383 		sal_Int32 nParameter = 0;
384 		switch( aSegment.Command )
385 		{
386 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
387 				aStrBuffer.append( (sal_Unicode)'Z' ); break;
388 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
389 				aStrBuffer.append( (sal_Unicode)'N' ); break;
390 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
391 				aStrBuffer.append( (sal_Unicode)'F' ); break;
392 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
393 				aStrBuffer.append( (sal_Unicode)'S' ); break;
394 
395 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
396 				aStrBuffer.append( (sal_Unicode)'M' ); nParameter = 1; break;
397 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO :
398 				aStrBuffer.append( (sal_Unicode)'L' ); nParameter = 1; break;
399 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
400 				aStrBuffer.append( (sal_Unicode)'C' ); nParameter = 3; break;
401 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
402 				aStrBuffer.append( (sal_Unicode)'T' ); nParameter = 3; break;
403 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
404 				aStrBuffer.append( (sal_Unicode)'U' ); nParameter = 3; break;
405 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
406 				aStrBuffer.append( (sal_Unicode)'A' ); nParameter = 4; break;
407 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
408 				aStrBuffer.append( (sal_Unicode)'B' ); nParameter = 4; break;
409 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
410 				aStrBuffer.append( (sal_Unicode)'W' ); nParameter = 4; break;
411 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
412 				aStrBuffer.append( (sal_Unicode)'V' ); nParameter = 4; break;
413 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
414 				aStrBuffer.append( (sal_Unicode)'X' ); nParameter = 1; break;
415 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
416 				aStrBuffer.append( (sal_Unicode)'Y' ); nParameter = 1; break;
417 			case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO :
418 				aStrBuffer.append( (sal_Unicode)'Q' ); nParameter = 2; break;
419 
420 			default : // ups, seems to be something wrong
421 			{
422 				aSegment.Count = 1;
423 				aSegment.Command = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
424 			}
425 			break;
426 		}
427 		if ( nParameter )
428 		{
429 			for ( k = 0; k < aSegment.Count; k++ )
430 			{
431 				if ( ( i + nParameter ) <= nCoords )
432 				{
433 					for ( l = 0; l < nParameter; l++ )
434 					{
435 						ExportParameter( aStrBuffer, rCoordinates[ i ].First );
436 						ExportParameter( aStrBuffer, rCoordinates[ i++ ].Second );
437 					}
438 				}
439 				else
440 				{
441 					j = nSegments;	// error -> exiting
442 					break;
443 				}
444 			}
445 		}
446 	}
447 	aStr = aStrBuffer.makeStringAndClear();
448 	rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ENHANCED_PATH, aStr );
449 }
450 
451 void ImpExportEnhancedGeometry( SvXMLExport& rExport, const uno::Reference< beans::XPropertySet >& xPropSet )
452 {
453 	sal_Bool bEquations = sal_False;
454 	uno::Sequence< rtl::OUString > aEquations;
455 
456 	sal_Bool bHandles = sal_False;
457 	uno::Sequence< beans::PropertyValues > aHandles;
458 
459 	sal_Bool bCoordinates = sal_False;
460 	uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments;
461 	uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
462 
463 	uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentValues;
464 
465 	rtl::OUString		aStr;
466 	rtl::OUStringBuffer aStrBuffer;
467 	SvXMLUnitConverter& rUnitConverter = rExport.GetMM100UnitConverter();
468 
469 	uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
470 
471 	// geometry
472 	const rtl::OUString	sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
473 	if ( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( sCustomShapeGeometry ) )
474 	{
475 		uno::Any aGeoPropSet( xPropSet->getPropertyValue( sCustomShapeGeometry ) );
476 		uno::Sequence< beans::PropertyValue > aGeoPropSeq;
477 
478 		if ( aGeoPropSet >>= aGeoPropSeq )
479 		{
480 			const rtl::OUString	sCustomShapeType( RTL_CONSTASCII_USTRINGPARAM( "NonPrimitive" ) );
481 			rtl::OUString aCustomShapeType( sCustomShapeType );
482 
483 			sal_Int32 j, nGeoPropCount = aGeoPropSeq.getLength();
484 			for ( j = 0; j < nGeoPropCount; j++ )
485 			{
486 				const beans::PropertyValue& rGeoProp = aGeoPropSeq[ j ];
487 				switch( EASGet( rGeoProp.Name ) )
488 				{
489 					case EAS_Type :
490 					{
491 						rGeoProp.Value >>= aCustomShapeType;
492 					}
493 					break;
494 					case EAS_MirroredX :
495 					{
496 						sal_Bool bMirroredX = sal_Bool();
497 						if ( rGeoProp.Value >>= bMirroredX )
498 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIRROR_HORIZONTAL,
499 								bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
500 					}
501 					break;
502 					case EAS_MirroredY :
503 					{
504 						sal_Bool bMirroredY = sal_Bool();
505 						if ( rGeoProp.Value >>= bMirroredY )
506 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIRROR_VERTICAL,
507 								bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
508 					}
509 					break;
510 					case EAS_ViewBox :
511 					{
512 						awt::Rectangle aRect;
513 						if ( rGeoProp.Value >>= aRect )
514 						{
515 							SdXMLImExViewBox aViewBox( aRect.X, aRect.Y, aRect.Width, aRect.Height );
516 							rExport.AddAttribute( XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString() );
517 						}
518 					}
519 					break;
520 					case EAS_TextRotateAngle :
521 					{
522 						double fTextRotateAngle = 0;
523 						if ( rGeoProp.Value >>= fTextRotateAngle )
524 						{
525 							rUnitConverter.convertDouble( aStrBuffer, fTextRotateAngle );
526 							aStr = aStrBuffer.makeStringAndClear();
527 							rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_ROTATE_ANGLE, aStr );
528 						}
529 					}
530 					break;
531 					case EAS_Extrusion :
532 					{
533 						uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
534 						if ( rGeoProp.Value >>= aExtrusionPropSeq )
535 						{
536 							sal_Int32 i, nCount = aExtrusionPropSeq.getLength();
537 							for ( i = 0; i < nCount; i++ )
538 							{
539 								const beans::PropertyValue& rProp = aExtrusionPropSeq[ i ];
540 								switch( EASGet( rProp.Name ) )
541 								{
542 									case EAS_Extrusion :
543 									{
544 										sal_Bool bExtrusionOn = sal_Bool();
545 										if ( rProp.Value >>= bExtrusionOn )
546 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION,
547 												bExtrusionOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
548 									}
549 									break;
550 									case EAS_Brightness :
551 									{
552 										double fExtrusionBrightness = 0;
553 										if ( rProp.Value >>= fExtrusionBrightness )
554 										{
555 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionBrightness, sal_False, MAP_RELATIVE, MAP_RELATIVE );
556 											aStrBuffer.append( (sal_Unicode)'%' );
557 											aStr = aStrBuffer.makeStringAndClear();
558 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_BRIGHTNESS, aStr );
559 										}
560 									}
561 									break;
562 									case EAS_Depth :
563 									{
564 										com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
565 										if ( rProp.Value >>= aDepthParaPair )
566 										{
567 											double fDepth = 0;
568 											if ( aDepthParaPair.First.Value >>= fDepth )
569 											{
570 												rExport.GetMM100UnitConverter().convertDouble( aStrBuffer, fDepth, sal_True );
571 												ExportParameter( aStrBuffer, aDepthParaPair.Second );
572 												aStr = aStrBuffer.makeStringAndClear();
573 												rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_DEPTH, aStr );
574 											}
575 										}
576 									}
577 									break;
578 									case EAS_Diffusion :
579 									{
580 										double fExtrusionDiffusion = 0;
581 										if ( rProp.Value >>= fExtrusionDiffusion )
582 										{
583 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionDiffusion, sal_False, MAP_RELATIVE, MAP_RELATIVE );
584 											aStrBuffer.append( (sal_Unicode)'%' );
585 											aStr = aStrBuffer.makeStringAndClear();
586 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_DIFFUSION, aStr );
587 										}
588 									}
589 									break;
590 									case EAS_NumberOfLineSegments :
591 									{
592 										sal_Int32 nExtrusionNumberOfLineSegments = 0;
593 										if ( rProp.Value >>= nExtrusionNumberOfLineSegments )
594 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_NUMBER_OF_LINE_SEGMENTS, rtl::OUString::valueOf( nExtrusionNumberOfLineSegments ) );
595 									}
596 									break;
597 									case EAS_LightFace :
598 									{
599 										sal_Bool bExtrusionLightFace = sal_Bool();
600 										if ( rProp.Value >>= bExtrusionLightFace )
601 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_LIGHT_FACE,
602 												bExtrusionLightFace ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
603 									}
604 									break;
605 									case EAS_FirstLightHarsh :
606 									{
607 										sal_Bool bExtrusionFirstLightHarsh = sal_Bool();
608 										if ( rProp.Value >>= bExtrusionFirstLightHarsh )
609 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_FIRST_LIGHT_HARSH,
610 												bExtrusionFirstLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
611 									}
612 									break;
613 									case EAS_SecondLightHarsh :
614 									{
615 										sal_Bool bExtrusionSecondLightHarsh = sal_Bool();
616 										if ( rProp.Value >>= bExtrusionSecondLightHarsh )
617 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SECOND_LIGHT_HARSH,
618 												bExtrusionSecondLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
619 									}
620 									break;
621 									case EAS_FirstLightLevel :
622 									{
623 										double fExtrusionFirstLightLevel = 0;
624 										if ( rProp.Value >>= fExtrusionFirstLightLevel )
625 										{
626 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionFirstLightLevel, sal_False, MAP_RELATIVE, MAP_RELATIVE );
627 											aStrBuffer.append( (sal_Unicode)'%' );
628 											aStr = aStrBuffer.makeStringAndClear();
629 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_FIRST_LIGHT_LEVEL, aStr );
630 										}
631 									}
632 									break;
633 									case EAS_SecondLightLevel :
634 									{
635 										double fExtrusionSecondLightLevel = 0;
636 										if ( rProp.Value >>= fExtrusionSecondLightLevel )
637 										{
638 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionSecondLightLevel, sal_False, MAP_RELATIVE, MAP_RELATIVE );
639 											aStrBuffer.append( (sal_Unicode)'%' );
640 											aStr = aStrBuffer.makeStringAndClear();
641 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SECOND_LIGHT_LEVEL, aStr );
642 										}
643 									}
644 									break;
645 									case EAS_FirstLightDirection :
646 									{
647 										drawing::Direction3D aExtrusionFirstLightDirection;
648 										if ( rProp.Value >>= aExtrusionFirstLightDirection )
649 										{
650 											::basegfx::B3DVector aVec3D( aExtrusionFirstLightDirection.DirectionX, aExtrusionFirstLightDirection.DirectionY,
651 												aExtrusionFirstLightDirection.DirectionZ );
652 											rUnitConverter.convertB3DVector( aStrBuffer, aVec3D );
653 											aStr = aStrBuffer.makeStringAndClear();
654 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_FIRST_LIGHT_DIRECTION, aStr );
655 										}
656 									}
657 									break;
658 									case EAS_SecondLightDirection :
659 									{
660 										drawing::Direction3D aExtrusionSecondLightDirection;
661 										if ( rProp.Value >>= aExtrusionSecondLightDirection )
662 										{
663 											::basegfx::B3DVector aVec3D( aExtrusionSecondLightDirection.DirectionX, aExtrusionSecondLightDirection.DirectionY,
664 												aExtrusionSecondLightDirection.DirectionZ );
665 											rUnitConverter.convertB3DVector( aStrBuffer, aVec3D );
666 											aStr = aStrBuffer.makeStringAndClear();
667 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SECOND_LIGHT_DIRECTION, aStr );
668 										}
669 									}
670 									break;
671 									case EAS_Metal :
672 									{
673 										sal_Bool bExtrusionMetal = sal_Bool();
674 										if ( rProp.Value >>= bExtrusionMetal )
675 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_METAL,
676 												bExtrusionMetal ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
677 									}
678 									break;
679 									case EAS_ShadeMode :
680 									{
681 										// shadeMode
682 										drawing::ShadeMode eShadeMode;
683 										if( rProp.Value >>= eShadeMode )
684 										{
685 											if( eShadeMode == drawing::ShadeMode_FLAT )
686 												aStr = GetXMLToken( XML_FLAT );
687 											else if( eShadeMode == drawing::ShadeMode_PHONG )
688 												aStr = GetXMLToken( XML_PHONG );
689 											else if( eShadeMode == drawing::ShadeMode_SMOOTH )
690 												aStr = GetXMLToken( XML_GOURAUD );
691 											else
692 												aStr = GetXMLToken( XML_DRAFT );
693 										}
694 										else
695 										{
696 											// ShadeMode enum not there, write default
697 											aStr = GetXMLToken( XML_FLAT);
698 										}
699 										rExport.AddAttribute( XML_NAMESPACE_DR3D, XML_SHADE_MODE, aStr );
700 									}
701 									break;
702 									case EAS_RotateAngle :
703 									{
704 										com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAngleParaPair;
705 										if ( rProp.Value >>= aRotateAngleParaPair )
706 										{
707 											ExportParameter( aStrBuffer, aRotateAngleParaPair.First );
708 											ExportParameter( aStrBuffer, aRotateAngleParaPair.Second );
709 											aStr = aStrBuffer.makeStringAndClear();
710 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_ROTATION_ANGLE, aStr );
711 										}
712 									}
713 									break;
714 									case EAS_RotationCenter :
715 									{
716 										drawing::Direction3D aExtrusionRotationCenter;
717 										if ( rProp.Value >>= aExtrusionRotationCenter )
718 										{
719 											::basegfx::B3DVector aVec3D( aExtrusionRotationCenter.DirectionX, aExtrusionRotationCenter.DirectionY,
720 												aExtrusionRotationCenter.DirectionZ );
721 											rUnitConverter.convertB3DVector( aStrBuffer, aVec3D );
722 											aStr = aStrBuffer.makeStringAndClear();
723 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_ROTATION_CENTER, aStr );
724 										}
725 									}
726 									break;
727 									case EAS_Shininess :
728 									{
729 										double fExtrusionShininess = 0;
730 										if ( rProp.Value >>= fExtrusionShininess )
731 										{
732 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionShininess, sal_False, MAP_RELATIVE, MAP_RELATIVE );
733 											aStrBuffer.append( (sal_Unicode)'%' );
734 											aStr = aStrBuffer.makeStringAndClear();
735 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SHININESS, aStr );
736 										}
737 									}
738 									break;
739 									case EAS_Skew :
740 									{
741 										com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
742 										if ( rProp.Value >>= aSkewParaPair )
743 										{
744 											ExportParameter( aStrBuffer, aSkewParaPair.First );
745 											ExportParameter( aStrBuffer, aSkewParaPair.Second );
746 											aStr = aStrBuffer.makeStringAndClear();
747 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SKEW, aStr );
748 										}
749 									}
750 									break;
751 									case EAS_Specularity :
752 									{
753 										double fExtrusionSpecularity = 0;
754 										if ( rProp.Value >>= fExtrusionSpecularity )
755 										{
756 											rUnitConverter.convertDouble( aStrBuffer, fExtrusionSpecularity, sal_False, MAP_RELATIVE, MAP_RELATIVE );
757 											aStrBuffer.append( (sal_Unicode)'%' );
758 											aStr = aStrBuffer.makeStringAndClear();
759 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SPECULARITY, aStr );
760 										}
761 									}
762 									break;
763 									case EAS_ProjectionMode :
764 									{
765 										drawing::ProjectionMode eProjectionMode;
766 										if ( rProp.Value >>= eProjectionMode )
767 											rExport.AddAttribute( XML_NAMESPACE_DR3D, XML_PROJECTION,
768 												eProjectionMode == drawing::ProjectionMode_PARALLEL ? GetXMLToken( XML_PARALLEL ) : GetXMLToken( XML_PERSPECTIVE ) );
769 									}
770 									break;
771 									case EAS_ViewPoint :
772 									{
773 										drawing::Position3D aExtrusionViewPoint;
774 										if ( rProp.Value >>= aExtrusionViewPoint )
775 										{
776 											rUnitConverter.convertPosition3D( aStrBuffer, aExtrusionViewPoint );
777 											aStr = aStrBuffer.makeStringAndClear();
778 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_VIEWPOINT, aStr );
779 										}
780 									}
781 									break;
782 									case EAS_Origin :
783 									{
784 										com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginParaPair;
785 										if ( rProp.Value >>= aOriginParaPair )
786 										{
787 											ExportParameter( aStrBuffer, aOriginParaPair.First );
788 											ExportParameter( aStrBuffer, aOriginParaPair.Second );
789 											aStr = aStrBuffer.makeStringAndClear();
790 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_ORIGIN, aStr );
791 										}
792 									}
793 									break;
794 									case EAS_Color :
795 									{
796 										sal_Bool bExtrusionColor = sal_Bool();
797 										if ( rProp.Value >>= bExtrusionColor )
798 										{
799 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_COLOR,
800 												bExtrusionColor ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
801 										}
802 									}
803 									break;
804 									default:
805 										break;
806 								}
807 							}
808 						}
809 					}
810 					break;
811 					case EAS_TextPath :
812 					{
813 						uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
814 						if ( rGeoProp.Value >>= aTextPathPropSeq )
815 						{
816 							sal_Int32 i, nCount = aTextPathPropSeq.getLength();
817 							for ( i = 0; i < nCount; i++ )
818 							{
819 								const beans::PropertyValue& rProp = aTextPathPropSeq[ i ];
820 								switch( EASGet( rProp.Name ) )
821 								{
822 									case EAS_TextPath :
823 									{
824 										sal_Bool bTextPathOn = sal_Bool();
825 										if ( rProp.Value >>= bTextPathOn )
826 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_PATH,
827 												bTextPathOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
828 									}
829 									break;
830 									case EAS_TextPathMode :
831 									{
832 										com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
833 										if ( rProp.Value >>= eTextPathMode )
834 										{
835 											switch ( eTextPathMode )
836 											{
837 												case com::sun::star::drawing::EnhancedCustomShapeTextPathMode_NORMAL: aStr = GetXMLToken( XML_NORMAL ); break;
838 												case com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH	: aStr = GetXMLToken( XML_PATH );   break;
839 												case com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE : aStr = GetXMLToken( XML_SHAPE );  break;
840 												default:
841 													break;
842 											}
843 											if ( aStr.getLength() )
844 												rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_PATH_MODE, aStr );
845 										}
846 									}
847 									break;
848 									case EAS_ScaleX :
849 									{
850 										sal_Bool bScaleX = sal_Bool();
851 										if ( rProp.Value >>= bScaleX )
852 										{
853 											aStr = bScaleX ? GetXMLToken( XML_SHAPE ) : GetXMLToken( XML_PATH );
854 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_PATH_SCALE, aStr );
855 										}
856 									}
857 									break;
858 									case EAS_SameLetterHeights :
859 									{
860 										sal_Bool bSameLetterHeights = sal_Bool();
861 										if ( rProp.Value >>= bSameLetterHeights )
862 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_PATH_SAME_LETTER_HEIGHTS,
863 												bSameLetterHeights ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
864 									}
865 									break;
866 									default:
867 										break;
868 								}
869 							}
870 						}
871 					}
872 					break;
873 					case EAS_Path :
874 					{
875 						uno::Sequence< beans::PropertyValue > aPathPropSeq;
876 						if ( rGeoProp.Value >>= aPathPropSeq )
877 						{
878 							sal_Int32 i, nCount = aPathPropSeq.getLength();
879 							for ( i = 0; i < nCount; i++ )
880 							{
881 								const beans::PropertyValue& rProp = aPathPropSeq[ i ];
882 								switch( EASGet( rProp.Name ) )
883 								{
884 									case EAS_ExtrusionAllowed :
885 									{
886 										sal_Bool bExtrusionAllowed = sal_Bool();
887 										if ( rProp.Value >>= bExtrusionAllowed )
888 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_ALLOWED,
889 												bExtrusionAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
890 									}
891 									break;
892 									case EAS_ConcentricGradientFillAllowed :
893 									{
894 										sal_Bool bConcentricGradientFillAllowed = sal_Bool();
895 										if ( rProp.Value >>= bConcentricGradientFillAllowed )
896 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CONCENTRIC_GRADIENT_FILL_ALLOWED,
897 												bConcentricGradientFillAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
898 									}
899 									break;
900 									case EAS_TextPathAllowed  :
901 									{
902 										sal_Bool bTextPathAllowed = sal_Bool();
903 										if ( rProp.Value >>= bTextPathAllowed )
904 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_PATH_ALLOWED,
905 												bTextPathAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
906 									}
907 									break;
908 									case EAS_GluePoints :
909 									{
910 										com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
911 										if ( rProp.Value >>= aGluePoints )
912 										{
913 											sal_Int32 k, nElements = aGluePoints.getLength();
914 											if ( nElements )
915 											{
916 												for( k = 0; k < nElements; k++ )
917 												{
918 													ExportParameter( aStrBuffer, aGluePoints[ k ].First );
919 													ExportParameter( aStrBuffer, aGluePoints[ k ].Second );
920 												}
921 												aStr = aStrBuffer.makeStringAndClear();
922 											}
923 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GLUE_POINTS, aStr );
924 										}
925 									}
926 									break;
927 									case EAS_GluePointType :
928 									{
929 										sal_Int16 nGluePointType = sal_Int16();
930 										if ( rProp.Value >>= nGluePointType )
931 										{
932 											switch ( nGluePointType )
933 											{
934 												case com::sun::star::drawing::EnhancedCustomShapeGluePointType::NONE     : aStr = GetXMLToken( XML_NONE );    break;
935 												case com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS : aStr = GetXMLToken( XML_SEGMENTS ); break;
936 												case com::sun::star::drawing::EnhancedCustomShapeGluePointType::RECT     : aStr = GetXMLToken( XML_RECTANGLE ); break;
937 											}
938 											if ( aStr.getLength() )
939 												rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GLUE_POINT_TYPE, aStr );
940 										}
941 									}
942 									break;
943 									case EAS_Coordinates :
944 									{
945 										bCoordinates = ( rProp.Value >>= aCoordinates );
946 									}
947 									break;
948 									case EAS_Segments :
949 									{
950 										rProp.Value >>= aSegments;
951 									}
952 									break;
953 									case EAS_StretchX :
954 									{
955 										sal_Int32 nStretchPoint = 0;
956 										if ( rProp.Value >>= nStretchPoint )
957 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_X, rtl::OUString::valueOf( nStretchPoint ) );
958 									}
959 									break;
960 									case EAS_StretchY :
961 									{
962 										sal_Int32 nStretchPoint = 0;
963 										if ( rProp.Value >>= nStretchPoint )
964 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_Y, rtl::OUString::valueOf( nStretchPoint ) );
965 									}
966 									break;
967 									case EAS_TextFrames :
968 									{
969 										com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
970 										if ( rProp.Value >>= aPathTextFrames )
971 										{
972 											if ( (sal_uInt16)aPathTextFrames.getLength() )
973 											{
974 												sal_uInt16 k, nElements = (sal_uInt16)aPathTextFrames.getLength();
975 												for ( k = 0; k < nElements; k++ )
976 												{
977 													ExportParameter( aStrBuffer, aPathTextFrames[ k ].TopLeft.First );
978 													ExportParameter( aStrBuffer, aPathTextFrames[ k ].TopLeft.Second );
979 													ExportParameter( aStrBuffer, aPathTextFrames[ k ].BottomRight.First );
980 													ExportParameter( aStrBuffer, aPathTextFrames[ k ].BottomRight.Second );
981 												}
982 												aStr = aStrBuffer.makeStringAndClear();
983 											}
984 											rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TEXT_AREAS, aStr );
985 										}
986 									}
987 									break;
988 									default:
989 										break;
990 								}
991 							}
992 						}
993 					}
994 					break;
995 					case EAS_Equations :
996 					{
997 						bEquations = ( rGeoProp.Value >>= aEquations );
998 					}
999 					break;
1000 					case EAS_Handles :
1001 					{
1002 						bHandles = ( rGeoProp.Value >>= aHandles );
1003 					}
1004 					break;
1005 					case EAS_AdjustmentValues :
1006 					{
1007 						rGeoProp.Value >>= aAdjustmentValues;
1008 					}
1009 					break;
1010 					default:
1011 						break;
1012 				}
1013 			}	// for
1014 			rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TYPE, aCustomShapeType );
1015 
1016 			// adjustments
1017 			sal_Int32 nAdjustmentValues = aAdjustmentValues.getLength();
1018 			if ( nAdjustmentValues )
1019 			{
1020 				sal_Int32 i, nValue = 0;
1021 				for ( i = 0; i < nAdjustmentValues; i++ )
1022 				{
1023 					if ( i )
1024 						aStrBuffer.append( (sal_Unicode)' ' );
1025 
1026 					const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue& rAdj = aAdjustmentValues[ i ];
1027 					if ( rAdj.State == beans::PropertyState_DIRECT_VALUE )
1028 					{
1029 						if ( rAdj.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
1030 						{
1031 							double fValue = 0.0;
1032 							rAdj.Value >>= fValue;
1033 							rUnitConverter.convertDouble( aStrBuffer, fValue );
1034 						}
1035 						else
1036 						{
1037 							rAdj.Value >>= nValue;
1038 							rUnitConverter.convertNumber( aStrBuffer, nValue );
1039 						}
1040 					}
1041 					else
1042 						rUnitConverter.convertNumber( aStrBuffer, 0 );			// this should not be, but better than setting nothing
1043 				}
1044 				aStr = aStrBuffer.makeStringAndClear();
1045 				rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MODIFIERS, aStr );
1046 			}
1047 			if ( bCoordinates )
1048 				ImpExportEnhancedPath( rExport, aCoordinates, aSegments );
1049 		}
1050 	}
1051 	SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_ENHANCED_GEOMETRY, sal_True, sal_True );
1052 	if ( bEquations )
1053 		ImpExportEquations( rExport, aEquations );
1054 	if ( bHandles )
1055 		ImpExportHandles( rExport, aHandles );
1056 }
1057 
1058 void XMLShapeExport::ImpExportCustomShape(
1059 	const uno::Reference< drawing::XShape >& xShape,
1060 	XmlShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint )
1061 {
1062 	const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
1063 	if ( xPropSet.is() )
1064 	{
1065 		rtl::OUString aStr;
1066 		uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
1067 
1068 		// Transformation
1069 		ImpExportNewTrans( xPropSet, nFeatures, pRefPoint );
1070 
1071 		if ( xPropSetInfo.is() )
1072 		{
1073 			const rtl::OUString	sCustomShapeEngine( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeEngine" ) );
1074 			if ( xPropSetInfo->hasPropertyByName( sCustomShapeEngine ) )
1075 			{
1076 				uno::Any aEngine( xPropSet->getPropertyValue( sCustomShapeEngine ) );
1077 				if ( ( aEngine >>= aStr ) && aStr.getLength() )
1078 					mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ENGINE, aStr );
1079 			}
1080 			const rtl::OUString	sCustomShapeData( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeData" ) );
1081 			if ( xPropSetInfo->hasPropertyByName( sCustomShapeData ) )
1082 			{
1083 				uno::Any aData( xPropSet->getPropertyValue( sCustomShapeData ) );
1084 				if ( ( aData >>= aStr ) && aStr.getLength() )
1085 					mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DATA, aStr );
1086 			}
1087 		}
1088 		sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
1089 		SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, bCreateNewline, sal_True );
1090 		ImpExportDescription( xShape ); // #i68101#
1091 		ImpExportEvents( xShape );
1092 		ImpExportGluePoints( xShape );
1093 		ImpExportText( xShape );
1094 		ImpExportEnhancedGeometry( mrExport, xPropSet );
1095 	}
1096 }
1097 
1098 void XMLShapeExport::ImpExportTableShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType eShapeType, sal_Int32 nFeatures, com::sun::star::awt::Point* pRefPoint )
1099 {
1100 	uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
1101 	uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);
1102 
1103 	DBG_ASSERT( xPropSet.is() && xNamed.is(), "xmloff::XMLShapeExport::ImpExportTableShape(), tabe shape is not implementing needed interfaces");
1104 	if(xPropSet.is() && xNamed.is()) try
1105 	{
1106 		// Transformation
1107 		ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
1108 
1109 		sal_Bool bIsEmptyPresObj = sal_False;
1110 
1111 		// presentation settings
1112 		if(eShapeType == XmlShapeTypePresTableShape)
1113 			bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_TABLE) );
1114 
1115 		const bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 );
1116 		const bool bExportEmbedded(0 != (mrExport.getExportFlags() & EXPORT_EMBEDDED));
1117 
1118 		SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW, XML_FRAME, bCreateNewline, sal_True );
1119 
1120 		// do not export in ODF 1.1 or older
1121 		if( mrExport.getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
1122 		{
1123 			if( !bIsEmptyPresObj )
1124 			{
1125 				uno::Reference< container::XNamed > xTemplate( xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TableTemplate" ) ) ), uno::UNO_QUERY );
1126 				if( xTemplate.is() )
1127 				{
1128 					const OUString sTemplate( xTemplate->getName() );
1129 					if( sTemplate.getLength() )
1130 					{
1131 						mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TEMPLATE_NAME, sTemplate );
1132 
1133 						for( const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0]; pEntry->msApiName; pEntry++ )
1134 						{
1135 							try
1136 							{
1137 								sal_Bool bBool = sal_False;
1138 								const OUString sAPIPropertyName( OUString(pEntry->msApiName, pEntry->nApiNameLength, RTL_TEXTENCODING_ASCII_US ) );
1139 
1140 								xPropSet->getPropertyValue( sAPIPropertyName ) >>= bBool;
1141 								if( bBool )
1142 									mrExport.AddAttribute(pEntry->mnNameSpace, pEntry->meXMLName, XML_TRUE );
1143 							}
1144 							catch( uno::Exception& )
1145 							{
1146 								DBG_ERROR("XMLShapeExport::ImpExportTableShape(), exception caught!");
1147 							}
1148 						}
1149 					}
1150 				}
1151 
1152 
1153 				uno::Reference< table::XColumnRowRange > xRange( xPropSet->getPropertyValue( msModel ), uno::UNO_QUERY_THROW );
1154 				GetShapeTableExport()->exportTable( xRange );
1155 			}
1156 		}
1157 
1158 		if( !bIsEmptyPresObj )
1159 		{
1160 			uno::Reference< graphic::XGraphic > xGraphic( xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ReplacementGraphic" ) ) ), uno::UNO_QUERY );
1161 			if( xGraphic.is() ) try
1162 			{
1163 				Reference< lang::XMultiServiceFactory > xSM( GetExport().getServiceFactory(), UNO_QUERY_THROW );
1164 
1165 				uno::Reference< embed::XStorage > xPictureStorage;
1166 				uno::Reference< embed::XStorage > xStorage;
1167 				uno::Reference< io::XStream > xPictureStream;
1168 
1169 				OUString sPictureName;
1170 				if( bExportEmbedded )
1171 				{
1172 					xPictureStream.set( xSM->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.MemoryStream" ) ) ), UNO_QUERY_THROW );
1173 				}
1174 				else
1175 				{
1176 					xStorage.set( GetExport().GetTargetStorage(), UNO_QUERY_THROW );
1177 
1178 					xPictureStorage.set( xStorage->openStorageElement( OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ), ::embed::ElementModes::READWRITE ), uno::UNO_QUERY_THROW );
1179 					const OUString sPrefix( RTL_CONSTASCII_USTRINGPARAM("TablePreview") );
1180 					const OUString sSuffix( RTL_CONSTASCII_USTRINGPARAM(".svm") );
1181 
1182 					sal_Int32 nIndex = 0;
1183 					do
1184 					{
1185 						sPictureName = sPrefix;
1186 						sPictureName += OUString::valueOf( ++nIndex );
1187 						sPictureName += sSuffix;
1188 					}
1189 					while( xPictureStorage->hasByName( sPictureName ) );
1190 
1191 					xPictureStream.set( xPictureStorage->openStreamElement( sPictureName, ::embed::ElementModes::READWRITE ), UNO_QUERY_THROW );
1192 				}
1193 
1194 				Reference< graphic::XGraphicProvider > xProvider( xSM->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) ) ), UNO_QUERY_THROW );
1195 				Sequence< beans::PropertyValue > aArgs( 2 );
1196 				aArgs[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "MimeType" ) );
1197 				aArgs[ 0 ].Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "image/x-vclgraphic" ) );
1198 				aArgs[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "OutputStream" ) );
1199 				aArgs[ 1 ].Value <<= xPictureStream->getOutputStream();
1200 				xProvider->storeGraphic( xGraphic, aArgs );
1201 
1202 				if( xPictureStorage.is() )
1203 				{
1204 					Reference< embed::XTransactedObject > xTrans( xPictureStorage, UNO_QUERY );
1205 					if( xTrans.is() )
1206 						xTrans->commit();
1207 				}
1208 
1209 				if( !bExportEmbedded )
1210 				{
1211 					OUString sURL( RTL_CONSTASCII_USTRINGPARAM( "Pictures/" ) );
1212 					sURL += sPictureName;
1213 					mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL );
1214 					mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
1215 					mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
1216 					mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
1217 				}
1218 
1219 				SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, sal_False, sal_True );
1220 
1221 				if( bExportEmbedded )
1222 				{
1223 					Reference< XSeekableInputStream > xSeekable( xPictureStream, UNO_QUERY_THROW );
1224 					xSeekable->seek(0);
1225 
1226 					XMLBase64Export aBase64Exp( GetExport() );
1227 					aBase64Exp.exportOfficeBinaryDataElement( Reference < XInputStream >( xPictureStream, UNO_QUERY_THROW ) );
1228 				}
1229 			}
1230 			catch( uno::Exception& )
1231 			{
1232 				DBG_ERROR("xmloff::XMLShapeExport::ImpExportTableShape(), exception caught!");
1233 			}
1234 		}
1235 
1236 		ImpExportEvents( xShape );
1237 		ImpExportGluePoints( xShape );
1238 		ImpExportDescription( xShape ); // #i68101#
1239 	}
1240 	catch( uno::Exception& )
1241 	{
1242 		DBG_ERROR( "xmloff::XMLShapeExport::ImpExportTableShape(), exception caught!" );
1243 	}
1244 }
1245