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 "ximpcustomshape.hxx"
27 #include "ximpshap.hxx"
28 #include "xmlehelp.hxx"
29 #include <rtl/math.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include <rtl/ustring.hxx>
32 #include <com/sun/star/uno/Reference.h>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/xml/sax/XAttributeList.hpp>
35 #include <com/sun/star/container/XIndexContainer.hpp>
36 #include <xmloff/xmltoken.hxx>
37 #include "EnhancedCustomShapeToken.hxx"
38 #include <xmloff/xmlimp.hxx>
39 #include <xmloff/xmltkmap.hxx>
40 #include "xmloff/xmlnmspe.hxx"
41 #include <xmloff/nmspmap.hxx>
42 #include <xmloff/xmluconv.hxx>
43 #include "xexptran.hxx"
44 #include "xmloff/xmlerror.hxx"
45 #include <tools/debug.hxx>
46 #include <com/sun/star/drawing/Direction3D.hpp>
47 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
48 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
49 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
50 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
51 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
52 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
53 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
54 #include <com/sun/star/drawing/ProjectionMode.hpp>
55 #include <basegfx/vector/b2dvector.hxx>
56 #include <hash_map>
57 
58 using namespace ::com::sun::star;
59 using namespace ::xmloff::token;
60 using namespace ::xmloff::EnhancedCustomShapeToken;
61 
62 TYPEINIT1( XMLEnhancedCustomShapeContext, SvXMLImportContext );
63 
64 XMLEnhancedCustomShapeContext::XMLEnhancedCustomShapeContext( SvXMLImport& rImport,
65 			::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape,
66 				sal_uInt16 nPrefix, const rtl::OUString& rLocalName,
67 					std::vector< com::sun::star::beans::PropertyValue >& rCustomShapeGeometry ) :
68 		SvXMLImportContext( rImport, nPrefix, rLocalName ),
69 		mrUnitConverter( rImport.GetMM100UnitConverter() ),
70 		mrxShape( rxShape ),
71 		mrCustomShapeGeometry( rCustomShapeGeometry )
72 {
73 }
74 
75 const SvXMLEnumMapEntry aXML_GluePointEnumMap[] =
76 {
77 	{ XML_NONE,			0 },
78 	{ XML_SEGMENTS, 	1 },
79 	{ XML_NONE,			2 },
80 	{ XML_RECTANGLE,	3 },
81 	{ XML_TOKEN_INVALID, 0 }
82 };
83 void GetBool( std::vector< com::sun::star::beans::PropertyValue >& rDest,
84 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
85 {
86 	sal_Bool bAttrBool;
87 	if ( SvXMLUnitConverter::convertBool( bAttrBool, rValue ) )
88 	{
89 		beans::PropertyValue aProp;
90 		aProp.Name = EASGet( eDestProp );
91 		aProp.Value <<= bAttrBool;
92 		rDest.push_back( aProp );
93 	}
94 }
95 
96 void GetInt32( std::vector< com::sun::star::beans::PropertyValue >& rDest,
97 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
98 {
99 	sal_Int32 nAttrNumber;
100 	if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) )
101 	{
102 		beans::PropertyValue aProp;
103 		aProp.Name = EASGet( eDestProp );
104 		aProp.Value <<= nAttrNumber;
105 		rDest.push_back( aProp );
106 	}
107 }
108 
109 void GetDouble( std::vector< com::sun::star::beans::PropertyValue >& rDest,
110 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
111 {
112 	double fAttrDouble;
113 	if ( SvXMLUnitConverter::convertDouble( fAttrDouble, rValue ) )
114 	{
115 		beans::PropertyValue aProp;
116 		aProp.Name = EASGet( eDestProp );
117 		aProp.Value <<= fAttrDouble;
118 		rDest.push_back( aProp );
119 	}
120 }
121 
122 void GetDistance( std::vector< com::sun::star::beans::PropertyValue >& rDest,
123 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
124 {
125 	double fAttrDouble;
126 	MapUnit eSrcUnit( SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM ) );
127 	if ( SvXMLUnitConverter::convertDouble( fAttrDouble, rValue, eSrcUnit, MAP_100TH_MM ) )
128 	{
129 		beans::PropertyValue aProp;
130 		aProp.Name = EASGet( eDestProp );
131 		aProp.Value <<= fAttrDouble;
132 		rDest.push_back( aProp );
133 	}
134 }
135 
136 void GetString( std::vector< com::sun::star::beans::PropertyValue >& rDest,
137 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
138 {
139 	beans::PropertyValue aProp;
140 	aProp.Name = EASGet( eDestProp );
141 	aProp.Value <<= rValue;
142 	rDest.push_back( aProp );
143 }
144 
145 void GetEnum( std::vector< com::sun::star::beans::PropertyValue >& rDest,
146 			 			const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp,
147 						const SvXMLEnumMapEntry& rMap )
148 {
149 	sal_uInt16 eKind;
150 	if( SvXMLUnitConverter::convertEnum( eKind, rValue, &rMap ) )
151 	{
152 		sal_Int16 nEnum = (sal_Int16)eKind;
153 		beans::PropertyValue aProp;
154 		aProp.Name = EASGet( eDestProp );
155 		aProp.Value <<= nEnum;
156 		rDest.push_back( aProp );
157 	}
158 }
159 
160 void GetDoublePercentage( std::vector< com::sun::star::beans::PropertyValue >& rDest,
161 						 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
162 {
163 	MapUnit eSrcUnit = SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM );
164 	if ( eSrcUnit == MAP_RELATIVE )
165 	{
166 		rtl_math_ConversionStatus eStatus;
167 		double fAttrDouble = ::rtl::math::stringToDouble( rValue,
168 			(sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
169 		if ( eStatus == rtl_math_ConversionStatus_Ok )
170 		{
171 			beans::PropertyValue aProp;
172 			aProp.Name = EASGet( eDestProp );
173 			aProp.Value <<= fAttrDouble;
174 			rDest.push_back( aProp );
175 		}
176 	}
177 }
178 
179 void GetB3DVector( std::vector< com::sun::star::beans::PropertyValue >& rDest,
180 						 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
181 {
182 	::basegfx::B3DVector aB3DVector;
183 	if ( SvXMLUnitConverter::convertB3DVector( aB3DVector, rValue ) )
184 	{
185 		drawing::Direction3D aDirection3D( aB3DVector.getX(), aB3DVector.getY(), aB3DVector.getZ() );
186 		beans::PropertyValue aProp;
187 		aProp.Name = EASGet( eDestProp );
188 		aProp.Value <<= aDirection3D;
189 		rDest.push_back( aProp );
190 	}
191 }
192 
193 sal_Bool GetEquationName( const rtl::OUString& rEquation, const sal_Int32 nStart, rtl::OUString& rEquationName )
194 {
195 	sal_Int32 nIndex = nStart;
196 	while( nIndex < rEquation.getLength() )
197 	{
198 		sal_Unicode nChar = rEquation[ nIndex ];
199 		if (
200 			( ( nChar >= 'a' ) && ( nChar <= 'z' ) )
201 			|| ( ( nChar >= 'A' ) && ( nChar <= 'Z' ) )
202 			|| ( ( nChar >= '0' ) && ( nChar <= '9' ) )
203 			)
204 		{
205 			nIndex++;
206 		}
207 		else
208 			break;
209 	}
210 	sal_Bool bValid = ( nIndex - nStart ) != 0;
211 	if ( bValid )
212 		rEquationName = rEquation.copy( nStart, nIndex - nStart );
213 	return bValid;
214 }
215 
216 sal_Bool GetNextParameter( com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter, sal_Int32& nIndex, const rtl::OUString& rParaString )
217 {
218 	if ( nIndex >= rParaString.getLength() )
219 		return sal_False;
220 
221 	sal_Bool bValid = sal_True;
222 	sal_Bool bNumberRequired = sal_True;
223 	sal_Bool bMustBePositiveWholeNumbered = sal_False;
224 
225 	rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL;
226 	if ( rParaString[ nIndex ] == (sal_Unicode)'$' )
227 	{
228 		rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT;
229 		bMustBePositiveWholeNumbered = sal_True;
230 		nIndex++;
231 	}
232 	else if ( rParaString[ nIndex ] == (sal_Unicode)'?' )
233 	{
234 		nIndex++;
235 		bNumberRequired = sal_False;
236 		rtl::OUString aEquationName;
237 		bValid = GetEquationName( rParaString, nIndex, aEquationName );
238 		if ( bValid )
239 		{
240 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION;
241 			rParameter.Value <<= aEquationName;
242 			nIndex += aEquationName.getLength();
243 		}
244 	}
245 	else if ( rParaString[ nIndex ] > (sal_Unicode)'9' )
246 	{
247 		bNumberRequired = sal_False;
248 		if ( rParaString.matchIgnoreAsciiCaseAsciiL( "left", 4, nIndex ) )
249 		{
250 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT;
251 			nIndex += 4;
252 		}
253 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "top", 3, nIndex ) )
254 		{
255 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP;
256 			nIndex += 3;
257 		}
258 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "right", 5, nIndex ) )
259 		{
260 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT;
261 			nIndex += 5;
262 		}
263 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "bottom", 6, nIndex ) )
264 		{
265 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM;
266 			nIndex += 6;
267 		}
268 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "xstretch", 8, nIndex ) )
269 		{
270 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::XSTRETCH;
271 			nIndex += 8;
272 		}
273 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "ystretch", 8, nIndex ) )
274 		{
275 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::YSTRETCH;
276 			nIndex += 8;
277 		}
278 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "hasstroke", 9, nIndex ) )
279 		{
280 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HASSTROKE;
281 			nIndex += 9;
282 		}
283 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "hasfill", 7, nIndex ) )
284 		{
285 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HASFILL;
286 			nIndex += 7;
287 		}
288 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "width", 5, nIndex ) )
289 		{
290 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::WIDTH;
291 			nIndex += 5;
292 		}
293 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "height", 6, nIndex ) )
294 		{
295 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HEIGHT;
296 			nIndex += 6;
297 		}
298 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "logwidth", 8, nIndex ) )
299 		{
300 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGWIDTH;
301 			nIndex += 8;
302 		}
303 		else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "logheight", 9, nIndex ) )
304 		{
305 			rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT;
306 			nIndex += 9;
307 		}
308 		else
309 			bValid = sal_False;
310 	}
311 	if ( bValid )
312 	{
313 		if ( bNumberRequired )
314 		{
315 			sal_Int32 nStartIndex = nIndex;
316 
317 			sal_Bool bM = sal_False;	// set if the value is negative
318 			sal_Bool bE = sal_False;	// set if a double is including a "E" statement
319 			sal_Bool bEM = sal_False;	// set if a double is including a "E-"statement
320 			sal_Bool bDot = sal_False;	// set if there is a dot included
321 			sal_Bool bEnd = sal_False;	// set for each value that can not be part of a double/integer
322 
323 			while( ( nIndex < rParaString.getLength() ) && bValid )
324 			{
325 				switch( rParaString[ nIndex ] )
326 				{
327 					case '.' :
328 					{
329 						if ( bMustBePositiveWholeNumbered )
330 							bValid = sal_False;
331 						else
332 						{
333 							if ( bDot )
334 								bValid = sal_False;
335 							else
336 								bDot = sal_True;
337 						}
338 					}
339 					break;
340 					case '-' :
341 					{
342 						if ( bMustBePositiveWholeNumbered )
343 							bValid = sal_False;
344 						else
345 						{
346 							if ( nStartIndex == nIndex )
347 								bM = sal_True;
348 							else if ( bE )
349 								bEM = sal_True;
350 							else
351 								bValid = sal_False;
352 						}
353 					}
354 					break;
355 
356 					case 'e' :
357 					case 'E' :
358 					{
359 						if ( bMustBePositiveWholeNumbered )
360 							bEnd = sal_True;
361 						else
362 						{
363 							if ( !bE )
364 								bE = sal_True;
365 							else
366 								bEnd = sal_True;
367 						}
368 					}
369 					break;
370 					case '0' :
371 					case '1' :
372 					case '2' :
373 					case '3' :
374 					case '4' :
375 					case '5' :
376 					case '6' :
377 					case '7' :
378 					case '8' :
379 					case '9' :
380 					break;
381 					default:
382 						bEnd = sal_True;
383 				}
384 				if ( !bEnd )
385 					nIndex++;
386 				else
387 					break;
388 			}
389 			if ( nIndex == nStartIndex )
390 				bValid = sal_False;
391 			if ( bValid )
392 			{
393 				rtl::OUString aNumber( rParaString.copy( nStartIndex, nIndex - nStartIndex ) );
394 				if ( bE || bDot )
395 				{
396 					double fAttrDouble;
397 					if ( SvXMLUnitConverter::convertDouble( fAttrDouble, aNumber ) )
398 						rParameter.Value <<= fAttrDouble;
399 					else
400 						bValid = sal_False;
401 				}
402 				else
403 				{
404 					sal_Int32 nValue;
405 					if ( SvXMLUnitConverter::convertNumber( nValue, aNumber ) )
406 						rParameter.Value <<= nValue;
407 					else
408 						bValid = sal_False;
409 				}
410 			}
411 		}
412 	}
413 	if ( bValid )
414 	{
415         // skipping white spaces and commatas (#121507#)
416         const sal_Unicode aSpace(sal_Unicode(' '));
417         const sal_Unicode aCommata(sal_Unicode(','));
418 
419         while(nIndex < rParaString.getLength())
420         {
421             const sal_Unicode aCandidate(rParaString[nIndex]);
422 
423             if(aSpace == aCandidate || aCommata == aCandidate)
424             {
425                 nIndex++;
426             }
427             else
428             {
429                 break;
430             }
431         }
432 	}
433 	return bValid;
434 }
435 
436 void GetPosition3D( std::vector< com::sun::star::beans::PropertyValue >& rDest,						// e.g. draw:extrusion-viewpoint
437 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp,
438 						SvXMLUnitConverter& rUnitConverter )
439 {
440 	drawing::Position3D aPosition3D;
441 	if ( rUnitConverter.convertPosition3D( aPosition3D, rValue ) )
442 	{
443 		beans::PropertyValue aProp;
444 		aProp.Name = EASGet( eDestProp );
445 		aProp.Value <<= aPosition3D;
446 		rDest.push_back( aProp );
447 	}
448 }
449 
450 void GetDoubleSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest,					// e.g. draw:glue-point-leaving-directions
451 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
452 {
453 	std::vector< double > vDirection;
454     sal_Int32 nIndex = 0;
455     do
456     {
457 		double fAttrDouble;
458 		rtl::OUString aToken( rValue.getToken( 0, ',', nIndex ) );
459 		if ( !SvXMLUnitConverter::convertDouble( fAttrDouble, aToken ) )
460 			break;
461 		else
462 			vDirection.push_back( fAttrDouble );
463     }
464     while ( nIndex >= 0 );
465 
466 	if ( !vDirection.empty() )
467 	{
468 		uno::Sequence< double > aDirectionsSeq( vDirection.size() );
469 		std::vector< double >::const_iterator aIter = vDirection.begin();
470 		std::vector< double >::const_iterator aEnd = vDirection.end();
471 		double* pValues = aDirectionsSeq.getArray();
472 
473 		while ( aIter != aEnd )
474 			*pValues++ = *aIter++;
475 
476 		beans::PropertyValue aProp;
477 		aProp.Name = EASGet( eDestProp );
478 		aProp.Value <<= aDirectionsSeq;
479 		rDest.push_back( aProp );
480 	}
481 }
482 
483 void GetEnhancedParameter( std::vector< com::sun::star::beans::PropertyValue >& rDest,				// e.g. draw:handle-position
484 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
485 {
486 	sal_Int32 nIndex = 0;
487 	com::sun::star::drawing::EnhancedCustomShapeParameter aParameter;
488 	if ( GetNextParameter( aParameter, nIndex, rValue ) )
489 	{
490 		beans::PropertyValue aProp;
491 		aProp.Name = EASGet( eDestProp );
492 		aProp.Value <<= aParameter;
493 		rDest.push_back( aProp );
494 	}
495 }
496 
497 void GetEnhancedParameterPair( std::vector< com::sun::star::beans::PropertyValue >& rDest,			// e.g. draw:handle-position
498 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
499 {
500 	sal_Int32 nIndex = 0;
501 	com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameterPair;
502 	if ( GetNextParameter( aParameterPair.First, nIndex, rValue )
503 		&& GetNextParameter( aParameterPair.Second, nIndex, rValue ) )
504 	{
505 		beans::PropertyValue aProp;
506 		aProp.Name = EASGet( eDestProp );
507 		aProp.Value <<= aParameterPair;
508 		rDest.push_back( aProp );
509 	}
510 }
511 
512 sal_Int32 GetEnhancedParameterPairSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest,		// e.g. draw:glue-points
513 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
514 {
515 	std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair > vParameter;
516 	com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameter;
517 
518 	sal_Int32 nIndex = 0;
519 	while ( GetNextParameter( aParameter.First, nIndex, rValue )
520 			&& GetNextParameter( aParameter.Second, nIndex, rValue ) )
521 	{
522 		vParameter.push_back( aParameter );
523 	}
524 	if ( !vParameter.empty() )
525 	{
526 		uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aParameterSeq( vParameter.size() );
527 		std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aIter = vParameter.begin();
528 		std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aEnd = vParameter.end();
529 		com::sun::star::drawing::EnhancedCustomShapeParameterPair* pValues = aParameterSeq.getArray();
530 
531 		while ( aIter != aEnd )
532 			*pValues++ = *aIter++;
533 
534 		beans::PropertyValue aProp;
535 		aProp.Name = EASGet( eDestProp );
536 		aProp.Value <<= aParameterSeq;
537 		rDest.push_back( aProp );
538 	}
539 	return vParameter.size();
540 }
541 
542 void GetEnhancedRectangleSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest,		// e.g. draw:text-areas
543 						const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
544 {
545 	std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame > vTextFrame;
546 	com::sun::star::drawing::EnhancedCustomShapeTextFrame aParameter;
547 
548 	sal_Int32 nIndex = 0;
549 
550 	while ( GetNextParameter( aParameter.TopLeft.First, nIndex, rValue )
551 			&& GetNextParameter( aParameter.TopLeft.Second, nIndex, rValue )
552 			&& GetNextParameter( aParameter.BottomRight.First, nIndex, rValue )
553 			&& GetNextParameter( aParameter.BottomRight.Second, nIndex, rValue ) )
554 	{
555 		vTextFrame.push_back( aParameter );
556 	}
557 	if ( !vTextFrame.empty() )
558 	{
559 		uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aTextFrameSeq( vTextFrame.size() );
560 		std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame >::const_iterator aIter = vTextFrame.begin();
561 		std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame >::const_iterator aEnd = vTextFrame.end();
562 		com::sun::star::drawing::EnhancedCustomShapeTextFrame* pValues = aTextFrameSeq.getArray();
563 
564 		while ( aIter != aEnd )
565 			*pValues++ = *aIter++;
566 
567 		beans::PropertyValue aProp;
568 		aProp.Name = EASGet( eDestProp );
569 		aProp.Value <<= aTextFrameSeq;
570 		rDest.push_back( aProp );
571 	}
572 }
573 
574 void GetEnhancedPath( std::vector< com::sun::star::beans::PropertyValue >& rDest,					// e.g. draw:enhanced-path
575 						const rtl::OUString& rValue )
576 {
577 	std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >	vCoordinates;
578 	std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >		vSegments;
579 
580 	sal_Int32 nIndex = 0;
581 	sal_Int32 nParameterCount = 0;
582 
583 	sal_Int32 nParametersNeeded = 1;
584 	sal_Int16 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
585 
586 	sal_Bool bValid = sal_True;
587 
588 	while( bValid && ( nIndex < rValue.getLength() ) )
589 	{
590 		switch( rValue[ nIndex ] )
591 		{
592 			case 'M' :
593 			{
594 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
595 				nParametersNeeded = 1;
596 				nIndex++;
597 			}
598 			break;
599 			case 'L' :
600 			{
601 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
602 				nParametersNeeded = 1;
603 				nIndex++;
604 			}
605 			break;
606 			case 'C' :
607 			{
608 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
609 				nParametersNeeded = 3;
610 				nIndex++;
611 			}
612 			break;
613 			case 'Z' :
614 			{
615 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
616 				nParametersNeeded = 0;
617 				nIndex++;
618 			}
619 			break;
620 			case 'N' :
621 			{
622 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
623 				nParametersNeeded = 0;
624 				nIndex++;
625 			}
626 			break;
627 			case 'F' :
628 			{
629 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL;
630 				nParametersNeeded = 0;
631 				nIndex++;
632 			}
633 			break;
634 			case 'S' :
635 			{
636 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE;
637 				nParametersNeeded = 0;
638 				nIndex++;
639 			}
640 			break;
641 			case 'T' :
642 			{
643 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
644 				nParametersNeeded = 3;
645 				nIndex++;
646 			}
647 			break;
648 			case 'U' :
649 			{
650 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
651 				nParametersNeeded = 3;
652 				nIndex++;
653 			}
654 			break;
655 			case 'A' :
656 			{
657 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
658 				nParametersNeeded = 4;
659 				nIndex++;
660 			}
661 			break;
662 			case 'B' :
663 			{
664 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC;
665 				nParametersNeeded = 4;
666 				nIndex++;
667 			}
668 			break;
669 			case 'W' :
670 			{
671 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
672 				nParametersNeeded = 4;
673 				nIndex++;
674 			}
675 			break;
676 			case 'V' :
677 			{
678 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
679 				nParametersNeeded = 4;
680 				nIndex++;
681 			}
682 			break;
683 			case 'X' :
684 			{
685 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
686 				nParametersNeeded = 1;
687 				nIndex++;
688 			}
689 			break;
690 			case 'Y' :
691 			{
692 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
693 				nParametersNeeded = 1;
694 				nIndex++;
695 			}
696 			break;
697 			case 'Q' :
698 			{
699 				nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO;
700 				nParametersNeeded = 2;
701 				nIndex++;
702 			}
703 			break;
704 			case ' ' :
705 			{
706 				nIndex++;
707 			}
708 			break;
709 
710 			case '$' :
711 			case '?' :
712 			case '0' :
713 			case '1' :
714 			case '2' :
715 			case '3' :
716 			case '4' :
717 			case '5' :
718 			case '6' :
719 			case '7' :
720 			case '8' :
721 			case '9' :
722 			case '.' :
723 			case '-' :
724 			{
725 				com::sun::star::drawing::EnhancedCustomShapeParameterPair aPair;
726 				if ( GetNextParameter( aPair.First, nIndex, rValue ) &&
727 						GetNextParameter( aPair.Second, nIndex, rValue ) )
728 				{
729 					vCoordinates.push_back( aPair );
730 					nParameterCount++;
731 				}
732 				else
733 					bValid = sal_False;
734 			}
735 			break;
736 			default:
737 				nIndex++;
738 			break;
739 		}
740 		if ( !nParameterCount && !nParametersNeeded )
741 		{
742 			com::sun::star::drawing::EnhancedCustomShapeSegment aSegment;
743 			aSegment.Command = nLatestSegmentCommand;
744 			aSegment.Count = 0;
745 			vSegments.push_back( aSegment );
746 			nParametersNeeded = 0x7fffffff;
747 		}
748 		else if ( nParameterCount >= nParametersNeeded )
749 		{
750 			// check if the last command is identical,
751 			// if so, we just need to increment the count
752 			if ( !vSegments.empty() && ( vSegments[ vSegments.size() - 1 ].Command == nLatestSegmentCommand ) )
753 				vSegments[ vSegments.size() -1 ].Count++;
754 			else
755 			{
756 				com::sun::star::drawing::EnhancedCustomShapeSegment aSegment;
757 				aSegment.Command = nLatestSegmentCommand;
758 				aSegment.Count = 1;
759 				vSegments.push_back( aSegment );
760 			}
761 			nParameterCount = 0;
762 		}
763 	}
764 	// adding the Coordinates property
765 	uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > seqCoordinates( vCoordinates.size() );
766 	std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aCoordinatesIter = vCoordinates.begin();
767 	std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aCoordinatesEnd = vCoordinates.end();
768 	com::sun::star::drawing::EnhancedCustomShapeParameterPair* pCoordinateValues = seqCoordinates.getArray();
769 
770 	while ( aCoordinatesIter != aCoordinatesEnd )
771 		*pCoordinateValues++ = *aCoordinatesIter++;
772 
773 	beans::PropertyValue aProp;
774 	aProp.Name = EASGet( EAS_Coordinates );
775 	aProp.Value <<= seqCoordinates;
776 	rDest.push_back( aProp );
777 
778 
779 	// adding the Segments property
780 	uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments( vSegments.size() );
781 	std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >::const_iterator aSegmentsIter = vSegments.begin();
782 	std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >::const_iterator aSegmentsEnd = vSegments.end();
783 	com::sun::star::drawing::EnhancedCustomShapeSegment* pSegmentValues = seqSegments.getArray();
784 
785 	while ( aSegmentsIter != aSegmentsEnd )
786 		*pSegmentValues++ = *aSegmentsIter++;
787 
788 	aProp.Name = EASGet( EAS_Segments );
789 	aProp.Value <<= seqSegments;
790 	rDest.push_back( aProp );
791 }
792 
793 void GetAdjustmentValues( std::vector< com::sun::star::beans::PropertyValue >& rDest,				// draw:adjustments
794 						const rtl::OUString& rValue )
795 {
796 	std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > vAdjustmentValue;
797 	com::sun::star::drawing::EnhancedCustomShapeParameter aParameter;
798 	sal_Int32 nIndex = 0;
799 	while ( GetNextParameter( aParameter, nIndex, rValue ) )
800 	{
801 		com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue aAdj;
802 		if ( aParameter.Type == com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
803 		{
804 			aAdj.Value <<= aParameter.Value;
805 			aAdj.State = beans::PropertyState_DIRECT_VALUE;
806 		}
807 		else
808 			aAdj.State = beans::PropertyState_DEFAULT_VALUE;	// this should not be, but better than setting nothing
809 
810 		vAdjustmentValue.push_back( aAdj );
811 	}
812 
813 	sal_Int32 nAdjustmentValues = vAdjustmentValue.size();
814 	if ( nAdjustmentValues )
815 	{
816 		uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( nAdjustmentValues );
817 		std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue >::const_iterator aIter = vAdjustmentValue.begin();
818 		std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue >::const_iterator aEnd = vAdjustmentValue.end();
819 		com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue* pValues = aAdjustmentValues.getArray();
820 
821 		while ( aIter != aEnd )
822 			*pValues++ = *aIter++;
823 
824 		beans::PropertyValue aProp;
825 		aProp.Name = EASGet( EAS_AdjustmentValues );
826 		aProp.Value <<= aAdjustmentValues;
827 		rDest.push_back( aProp );
828 	}
829 }
830 
831 void XMLEnhancedCustomShapeContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
832 {
833 	sal_Int16 nLength = xAttrList->getLength();
834 	if ( nLength )
835 	{
836 		sal_Int32				nAttrNumber;
837 		for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
838 		{
839 			rtl::OUString aLocalName;
840 			const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr );
841 			/* sven fixme, this must be checked! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
842 
843 			switch( EASGet( aLocalName ) )
844 			{
845 				case EAS_type :
846 					GetString( mrCustomShapeGeometry, rValue, EAS_Type );
847 				break;
848 				case EAS_mirror_horizontal :
849 					GetBool( mrCustomShapeGeometry, rValue, EAS_MirroredX );
850 				break;
851 				case EAS_mirror_vertical :
852 					GetBool( mrCustomShapeGeometry, rValue, EAS_MirroredY );
853 				break;
854 				case EAS_viewBox :
855 				{
856 					SdXMLImExViewBox aViewBox( rValue, GetImport().GetMM100UnitConverter() );
857                     awt::Rectangle aRect(
858                         basegfx::fround(aViewBox.GetX()),
859                         basegfx::fround(aViewBox.GetY()),
860                         basegfx::fround(aViewBox.GetWidth()),
861                         basegfx::fround(aViewBox.GetHeight()));
862 
863                     if(0 == aRect.Width && 0 == aRect.Height)
864                     {
865                         // #124452# If in svg:viewBox no width and height is given the objects should normally
866                         // not be visible at all, but in this case it is a bug in LO to write empty svg:viewBox
867                         // entries for CustomShapes. To allow for a better ODF user experience, just correct this
868                         // here by getting the real object scale from the already set transformation from the xShape.
869                         // Hopefully LO will fix that bug (but this will still leave the files with the error), but
870                         // even when not this will do no harm as long noone uses this state explicitely for some
871                         // purpose (e.g. to really have CustomShapes without content, but unlikely).
872                         // When they do fix this they will need this fix anyways to read their own misformed ODF files
873                         // again, so I guess it will be taken, too...
874                         uno::Reference< beans::XPropertySet > xProps(mrxShape, uno::UNO_QUERY_THROW);
875                         uno::Any aObjectTransform = xProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
876                         drawing::HomogenMatrix3 aTransformMatrix;
877                         aObjectTransform >>= aTransformMatrix;
878                         basegfx::B2DHomMatrix aMatrix;
879 
880                         aMatrix.set(0, 0, aTransformMatrix.Line1.Column1);
881                         aMatrix.set(0, 1, aTransformMatrix.Line1.Column2);
882                         aMatrix.set(0, 2, aTransformMatrix.Line1.Column3);
883                         aMatrix.set(1, 0, aTransformMatrix.Line2.Column1);
884                         aMatrix.set(1, 1, aTransformMatrix.Line2.Column2);
885                         aMatrix.set(1, 2, aTransformMatrix.Line2.Column3);
886                         aMatrix.set(2, 0, aTransformMatrix.Line3.Column1);
887                         aMatrix.set(2, 1, aTransformMatrix.Line3.Column2);
888                         aMatrix.set(2, 2, aTransformMatrix.Line3.Column3);
889 
890                         basegfx::B2DVector aScale, aTranslate;
891                         double fRotate, fShearX;
892 
893                         aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
894 
895                         aRect.Width = basegfx::fround(fabs(aScale.getX()));
896                         aRect.Height = basegfx::fround(fabs(aScale.getY()));
897                     }
898 
899 					beans::PropertyValue aProp;
900 					aProp.Name = EASGet( EAS_ViewBox );
901 					aProp.Value <<= aRect;
902 					mrCustomShapeGeometry.push_back( aProp );
903 				}
904 				break;
905 				case EAS_text_rotate_angle :
906 					GetDouble( mrCustomShapeGeometry, rValue, EAS_TextRotateAngle );
907 				break;
908 				case EAS_extrusion_allowed :
909 					GetBool( maPath, rValue, EAS_ExtrusionAllowed );
910 				break;
911 				case EAS_text_path_allowed :
912 					GetBool( maPath, rValue, EAS_TextPathAllowed );
913 				break;
914 				case EAS_concentric_gradient_fill_allowed :
915 					GetBool( maPath, rValue, EAS_ConcentricGradientFillAllowed );
916 				break;
917 				case EAS_extrusion :
918 					GetBool( maExtrusion, rValue, EAS_Extrusion );
919 				break;
920 				case EAS_extrusion_brightness :
921 					GetDoublePercentage( maExtrusion, rValue, EAS_Brightness );
922 				break;
923 				case EAS_extrusion_depth :
924 				{
925 					sal_Int32 nIndex = 0;
926 					com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameterPair;
927 					com::sun::star::drawing::EnhancedCustomShapeParameter& rDepth = aParameterPair.First;
928 					com::sun::star::drawing::EnhancedCustomShapeParameter& rFraction = aParameterPair.Second;
929 					if ( GetNextParameter( rDepth, nIndex, rValue ) )
930 					{
931 						// try to catch the unit for the depth
932 						MapUnit eSrcUnit( SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM ) );
933 
934 						rtl::OUStringBuffer aUnitStr;
935 						double fFactor = SvXMLExportHelper::GetConversionFactor( aUnitStr, MAP_100TH_MM, eSrcUnit );
936 						if ( ( fFactor != 1.0 ) && ( fFactor != 0.0 ) )
937 						{
938 							double fDepth;
939 							if ( rDepth.Value >>= fDepth )
940 							{
941 								fDepth /= fFactor;
942 								rDepth.Value <<= fDepth;
943 							}
944 						}
945 						if ( rValue.matchIgnoreAsciiCase( rtl::OUString( aUnitStr ), nIndex ) )
946 							nIndex += aUnitStr.getLength();
947 
948 						// skipping white spaces
949 						while( ( nIndex < rValue.getLength() ) && rValue[ nIndex ] == (sal_Unicode)' ' )
950 							nIndex++;
951 
952 						if ( GetNextParameter( rFraction, nIndex, rValue ) )
953 						{
954 							beans::PropertyValue aProp;
955 							aProp.Name = EASGet( EAS_Depth );
956 							aProp.Value <<= aParameterPair;
957 							maExtrusion.push_back( aProp );
958 						}
959 					}
960 				}
961 				break;
962 				case EAS_extrusion_diffusion :
963 					GetDoublePercentage( maExtrusion, rValue, EAS_Diffusion );
964 				break;
965 				case EAS_extrusion_number_of_line_segments :
966 					GetInt32( maExtrusion, rValue, EAS_NumberOfLineSegments );
967 				break;
968 				case EAS_extrusion_light_face :
969 					GetBool( maExtrusion, rValue, EAS_LightFace );
970 				break;
971 				case EAS_extrusion_first_light_harsh :
972 					GetBool( maExtrusion, rValue, EAS_FirstLightHarsh );
973 				break;
974 				case EAS_extrusion_second_light_harsh :
975 					GetBool( maExtrusion, rValue, EAS_SecondLightHarsh );
976 				break;
977 				case EAS_extrusion_first_light_level :
978 					GetDoublePercentage( maExtrusion, rValue, EAS_FirstLightLevel );
979 				break;
980 				case EAS_extrusion_second_light_level :
981 					GetDoublePercentage( maExtrusion, rValue, EAS_SecondLightLevel );
982 				break;
983 				case EAS_extrusion_first_light_direction :
984 					GetB3DVector( maExtrusion, rValue, EAS_FirstLightDirection );
985 				break;
986 				case EAS_extrusion_second_light_direction :
987 					GetB3DVector( maExtrusion, rValue, EAS_SecondLightDirection );
988 				break;
989 				case EAS_extrusion_metal :
990 					GetBool( maExtrusion, rValue, EAS_Metal );
991 				break;
992 				case EAS_shade_mode :
993 				{
994 					drawing::ShadeMode eShadeMode( drawing::ShadeMode_FLAT );
995 					if( IsXMLToken( rValue, XML_PHONG ) )
996 						eShadeMode = drawing::ShadeMode_PHONG;
997 					else if ( IsXMLToken( rValue, XML_GOURAUD ) )
998 						eShadeMode = drawing::ShadeMode_SMOOTH;
999 					else if ( IsXMLToken( rValue, XML_DRAFT ) )
1000 						eShadeMode = drawing::ShadeMode_DRAFT;
1001 
1002 					beans::PropertyValue aProp;
1003 					aProp.Name = EASGet( EAS_ShadeMode );
1004 					aProp.Value <<= eShadeMode;
1005 					maExtrusion.push_back( aProp );
1006 				}
1007 				break;
1008 				case EAS_extrusion_rotation_angle :
1009 					GetEnhancedParameterPair( maExtrusion, rValue, EAS_RotateAngle );
1010 				break;
1011 				case EAS_extrusion_rotation_center :
1012 					GetB3DVector( maExtrusion, rValue, EAS_RotationCenter );
1013 				break;
1014 				case EAS_extrusion_shininess :
1015 					GetDoublePercentage( maExtrusion, rValue, EAS_Shininess );
1016 				break;
1017 				case EAS_extrusion_skew :
1018 					GetEnhancedParameterPair( maExtrusion, rValue, EAS_Skew );
1019 				break;
1020 				case EAS_extrusion_specularity :
1021 					GetDoublePercentage( maExtrusion, rValue, EAS_Specularity );
1022 				break;
1023 				case EAS_projection :
1024 				{
1025 					drawing::ProjectionMode eProjectionMode( drawing::ProjectionMode_PERSPECTIVE );
1026 					if( IsXMLToken( rValue, XML_PARALLEL ) )
1027 						eProjectionMode = drawing::ProjectionMode_PARALLEL;
1028 
1029 					beans::PropertyValue aProp;
1030 					aProp.Name = EASGet( EAS_ProjectionMode );
1031 					aProp.Value <<= eProjectionMode;
1032 					maExtrusion.push_back( aProp );
1033 				}
1034 				break;
1035 				case EAS_extrusion_viewpoint :
1036 					GetPosition3D( maExtrusion, rValue, EAS_ViewPoint, mrUnitConverter );
1037 				break;
1038 				case EAS_extrusion_origin :
1039 					GetEnhancedParameterPair( maExtrusion, rValue, EAS_Origin );
1040 				break;
1041 				case EAS_extrusion_color :
1042 					GetBool( maExtrusion, rValue, EAS_Color );
1043 				break;
1044 				case EAS_enhanced_path :
1045 					GetEnhancedPath( maPath, rValue );
1046 				break;
1047 				case EAS_path_stretchpoint_x :
1048 				{
1049 					if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) )
1050 					{
1051 						beans::PropertyValue aProp;
1052 						aProp.Name = EASGet( EAS_StretchX );
1053 						aProp.Value <<= nAttrNumber;
1054 						maPath.push_back( aProp );
1055 					}
1056 				}
1057 				break;
1058 				case EAS_path_stretchpoint_y :
1059 				{
1060 					if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) )
1061 					{
1062 						beans::PropertyValue aProp;
1063 						aProp.Name = EASGet( EAS_StretchY );
1064 						aProp.Value <<= nAttrNumber;
1065 						maPath.push_back( aProp );
1066 					}
1067 				}
1068 				break;
1069 				case EAS_text_areas :
1070 					GetEnhancedRectangleSequence( maPath, rValue, EAS_TextFrames );
1071 				break;
1072 				case EAS_glue_points :
1073 				{
1074 					sal_Int32 i, nPairs = GetEnhancedParameterPairSequence( maPath, rValue, EAS_GluePoints );
1075 					GetImport().GetShapeImport()->moveGluePointMapping( mrxShape, nPairs );
1076 					for ( i = 0; i < nPairs; i++ )
1077 						GetImport().GetShapeImport()->addGluePointMapping( mrxShape, i + 4, i + 4 );
1078 				}
1079 				break;
1080 				case EAS_glue_point_type :
1081 					GetEnum( maPath, rValue, EAS_GluePointType, *aXML_GluePointEnumMap );
1082 				break;
1083 				case EAS_glue_point_leaving_directions :
1084 					GetDoubleSequence( maPath, rValue, EAS_GluePointLeavingDirections );
1085 				break;
1086 				case EAS_text_path :
1087 					GetBool( maTextPath, rValue, EAS_TextPath );
1088 				break;
1089 				case EAS_text_path_mode :
1090 				{
1091 					com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode( com::sun::star::drawing::EnhancedCustomShapeTextPathMode_NORMAL );
1092 					if( IsXMLToken( rValue, XML_PATH ) )
1093 						eTextPathMode = com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH;
1094 					else if ( IsXMLToken( rValue, XML_SHAPE ) )
1095 						eTextPathMode = com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE;
1096 
1097 					beans::PropertyValue aProp;
1098 					aProp.Name = EASGet( EAS_TextPathMode );
1099 					aProp.Value <<= eTextPathMode;
1100 					maTextPath.push_back( aProp );
1101 				}
1102 				break;
1103 				case EAS_text_path_scale :
1104 				{
1105 					sal_Bool bScaleX = IsXMLToken( rValue, XML_SHAPE );
1106 					beans::PropertyValue aProp;
1107 					aProp.Name = EASGet( EAS_ScaleX );
1108 					aProp.Value <<= bScaleX;
1109 					maTextPath.push_back( aProp );
1110 				}
1111 				break;
1112 				case EAS_text_path_same_letter_heights :
1113 					GetBool( maTextPath, rValue, EAS_SameLetterHeights );
1114 				break;
1115 				case EAS_modifiers :
1116 					GetAdjustmentValues( mrCustomShapeGeometry, rValue );
1117 				break;
1118 				default:
1119 					break;
1120 			}
1121 		}
1122 	}
1123 }
1124 
1125 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec,
1126 									const std::vector< beans::PropertyValues >& rElement,
1127 										const rtl::OUString& rElementName )
1128 {
1129 	if ( !rElement.empty() )
1130 	{
1131 		uno::Sequence< beans::PropertyValues > aPropSeq( rElement.size() );
1132 		std::vector< beans::PropertyValues >::const_iterator aIter = rElement.begin();
1133 		std::vector< beans::PropertyValues >::const_iterator aEnd = rElement.end();
1134 		beans::PropertyValues* pValues = aPropSeq.getArray();
1135 
1136 		while ( aIter != aEnd )
1137 			*pValues++ = *aIter++;
1138 
1139 		beans::PropertyValue aProp;
1140 		aProp.Name = rElementName;
1141 		aProp.Value <<= aPropSeq;
1142 		rPropVec.push_back( aProp );
1143 	}
1144 }
1145 
1146 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec,
1147 									const std::vector< rtl::OUString >& rElement,
1148 										const rtl::OUString& rElementName )
1149 {
1150 	if ( !rElement.empty() )
1151 	{
1152 		uno::Sequence< rtl::OUString > aPropSeq( rElement.size() );
1153 		std::vector< rtl::OUString >::const_iterator aIter = rElement.begin();
1154 		std::vector< rtl::OUString >::const_iterator aEnd = rElement.end();
1155 		rtl::OUString* pValues = aPropSeq.getArray();
1156 
1157 		while ( aIter != aEnd )
1158 			*pValues++ = *aIter++;
1159 
1160 		beans::PropertyValue aProp;
1161 		aProp.Name = rElementName;
1162 		aProp.Value <<= aPropSeq;
1163 		rPropVec.push_back( aProp );
1164 	}
1165 }
1166 
1167 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec,
1168 									const std::vector< com::sun::star::beans::PropertyValue >& rElement,
1169 										const rtl::OUString& rElementName )
1170 {
1171 	if ( !rElement.empty() )
1172 	{
1173 		uno::Sequence< beans::PropertyValue > aPropSeq( rElement.size() );
1174 		std::vector< beans::PropertyValue >::const_iterator aIter = rElement.begin();
1175 		std::vector< beans::PropertyValue >::const_iterator aEnd = rElement.end();
1176 		beans::PropertyValue* pValues = aPropSeq.getArray();
1177 
1178 		while ( aIter != aEnd )
1179 			*pValues++ = *aIter++;
1180 
1181 		beans::PropertyValue aProp;
1182 		aProp.Name = rElementName;
1183 		aProp.Value <<= aPropSeq;
1184 		rPropVec.push_back( aProp );
1185 	}
1186 }
1187 
1188 typedef std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash, OUStringEqFunc> EquationHashMap;
1189 
1190 /* if rPara.Type is from type EnhancedCustomShapeParameterType::EQUATION, the name of the equation
1191    will be converted from rtl::OUString to index */
1192 void CheckAndResolveEquationParameter( com::sun::star::drawing::EnhancedCustomShapeParameter& rPara, EquationHashMap* pH )
1193 {
1194 	if ( rPara.Type == com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION )
1195 	{
1196 		rtl::OUString aEquationName;
1197 		if ( rPara.Value >>= aEquationName )
1198 		{
1199 			sal_Int32 nIndex = 0;
1200 			EquationHashMap::iterator aHashIter( pH->find( aEquationName ) );
1201 			if ( aHashIter != pH->end() )
1202 				nIndex = (*aHashIter).second;
1203 			rPara.Value <<= nIndex;
1204 		}
1205 	}
1206 }
1207 
1208 void XMLEnhancedCustomShapeContext::EndElement()
1209 {
1210 	// resolve properties that are indexing a Equation
1211 	if ( !maEquations.empty() )
1212 	{
1213 		// creating hash map containing the name and index of each equation
1214 		EquationHashMap* pH = new EquationHashMap;
1215 		std::vector< rtl::OUString >::iterator aEquationNameIter = maEquationNames.begin();
1216 		std::vector< rtl::OUString >::iterator aEquationNameEnd  = maEquationNames.end();
1217 		while( aEquationNameIter != aEquationNameEnd )
1218 		{
1219 			(*pH)[ *aEquationNameIter ] = (sal_Int32)( aEquationNameIter - maEquationNames.begin() );
1220 			aEquationNameIter++;
1221 		}
1222 
1223 		// resolve equation
1224 		std::vector< rtl::OUString >::iterator aEquationIter = maEquations.begin();
1225 		std::vector< rtl::OUString >::iterator aEquationEnd  = maEquations.end();
1226 		while( aEquationIter != aEquationEnd )
1227 		{
1228 			sal_Int32 nIndexOf = 0;
1229 			do
1230 			{
1231 				nIndexOf = aEquationIter->indexOf( '?', nIndexOf );
1232 				if ( nIndexOf != -1 )
1233 				{
1234 					rtl::OUString aEquationName;
1235 					if ( GetEquationName( *aEquationIter, nIndexOf + 1, aEquationName ) )
1236 					{
1237 						// copying first characters inclusive '?'
1238 						rtl::OUString aNew( aEquationIter->copy( 0, nIndexOf + 1 ) );
1239 						sal_Int32 nIndex = 0;
1240 						EquationHashMap::iterator aHashIter( pH->find( aEquationName ) );
1241 						if ( aHashIter != pH->end() )
1242 							nIndex = (*aHashIter).second;
1243 						aNew += rtl::OUString::valueOf( nIndex );
1244 						aNew += aEquationIter->copy( nIndexOf + aEquationName.getLength() + 1 );
1245 						*aEquationIter = aNew;
1246 					}
1247 					nIndexOf++;
1248 				}
1249 			}
1250 			while( nIndexOf != -1 );
1251 			aEquationIter++;
1252 		}
1253 
1254 		// Path
1255 		sal_Int32 i;
1256 		std::vector< beans::PropertyValue >::iterator aPathIter = maPath.begin();
1257 		std::vector< beans::PropertyValue >::iterator aPathEnd  = maPath.end();
1258 		while ( aPathIter != aPathEnd )
1259 		{
1260 			switch( EASGet( aPathIter->Name ) )
1261 			{
1262 				case EAS_Coordinates :
1263 				case EAS_GluePoints :
1264 				{
1265 					uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >& rSeq =
1266 						*((uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >*)
1267 							aPathIter->Value.getValue());
1268 					for ( i = 0; i < rSeq.getLength(); i++ )
1269 					{
1270 						CheckAndResolveEquationParameter( rSeq[ i ].First, pH );
1271 						CheckAndResolveEquationParameter( rSeq[ i ].Second, pH );
1272 					}
1273 				}
1274 				break;
1275 				case EAS_TextFrames :
1276 				{
1277 					uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame >& rSeq =
1278 						*((uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame >*)
1279 							aPathIter->Value.getValue());
1280 					for ( i = 0; i < rSeq.getLength(); i++ )
1281 					{
1282 						CheckAndResolveEquationParameter( rSeq[ i ].TopLeft.First, pH );
1283 						CheckAndResolveEquationParameter( rSeq[ i ].TopLeft.Second, pH );
1284 						CheckAndResolveEquationParameter( rSeq[ i ].BottomRight.First, pH );
1285 						CheckAndResolveEquationParameter( rSeq[ i ].BottomRight.Second, pH );
1286 					}
1287 				}
1288 				break;
1289 				default:
1290 					break;
1291 			}
1292 			aPathIter++;
1293 		}
1294 		std::vector< beans::PropertyValues >::iterator aHandleIter = maHandles.begin();
1295 		std::vector< beans::PropertyValues >::iterator aHandleEnd  = maHandles.end();
1296 		while ( aHandleIter != aHandleEnd )
1297 		{
1298 			beans::PropertyValue* pValues = aHandleIter->getArray();
1299 			for ( i = 0; i < aHandleIter->getLength(); i++ )
1300 			{
1301 				switch( EASGet( pValues->Name ) )
1302 				{
1303 					case EAS_RangeYMinimum :
1304 					case EAS_RangeYMaximum :
1305 					case EAS_RangeXMinimum :
1306 					case EAS_RangeXMaximum :
1307 					case EAS_RadiusRangeMinimum :
1308 					case EAS_RadiusRangeMaximum :
1309 					{
1310 						CheckAndResolveEquationParameter( *((com::sun::star::drawing::EnhancedCustomShapeParameter*)
1311 							pValues->Value.getValue()), pH );
1312 					}
1313 					break;
1314 
1315 					case EAS_Position :
1316 					case EAS_Polar :
1317 					{
1318 						CheckAndResolveEquationParameter( (*((com::sun::star::drawing::EnhancedCustomShapeParameterPair*)
1319 							pValues->Value.getValue())).First, pH );
1320 						CheckAndResolveEquationParameter( (*((com::sun::star::drawing::EnhancedCustomShapeParameterPair*)
1321 							pValues->Value.getValue())).Second, pH );
1322 					}
1323 					break;
1324 					default:
1325 						break;
1326 				}
1327 				pValues++;
1328 			}
1329 			aHandleIter++;
1330 		}
1331 		delete pH;
1332 	}
1333 
1334 	SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maExtrusion, EASGet( EAS_Extrusion ) );
1335 	SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maPath,      EASGet( EAS_Path ) );
1336 	SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maTextPath,  EASGet( EAS_TextPath ) );
1337 	SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maEquations, EASGet( EAS_Equations ) );
1338 	if  ( !maHandles.empty() )
1339 		SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maHandles, EASGet( EAS_Handles ) );
1340 }
1341 
1342 SvXMLImportContext* XMLEnhancedCustomShapeContext::CreateChildContext( sal_uInt16 nPrefix,const rtl::OUString& rLocalName,
1343 																	const uno::Reference< xml::sax::XAttributeList> & xAttrList )
1344 {
1345 	EnhancedCustomShapeTokenEnum aTokenEnum = EASGet( rLocalName );
1346 	if ( aTokenEnum == EAS_equation )
1347 	{
1348 		sal_Int16 nLength = xAttrList->getLength();
1349 		if ( nLength )
1350 		{
1351 			rtl::OUString aFormula;
1352 			rtl::OUString aFormulaName;
1353 			for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
1354 			{
1355 				rtl::OUString aLocalName;
1356 				const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr );
1357 				/* fixme sven, this needs to be chekced! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
1358 
1359 				switch( EASGet( aLocalName ) )
1360 				{
1361 					case EAS_formula :
1362 						aFormula = rValue;
1363 					break;
1364 					case EAS_name :
1365 						aFormulaName = rValue;
1366 					break;
1367 					default:
1368 						break;
1369 				}
1370 			}
1371 			if ( aFormulaName.getLength() || aFormula.getLength() )
1372 			{
1373 				maEquations.push_back( aFormula );
1374 				maEquationNames.push_back( aFormulaName );
1375 			}
1376 		}
1377 	}
1378 	else if ( aTokenEnum == EAS_handle )
1379 	{
1380 		std::vector< com::sun::star::beans::PropertyValue > aHandle;
1381         const sal_Int16 nLength = xAttrList->getLength();
1382 		for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
1383 		{
1384 			rtl::OUString aLocalName;
1385 			const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr );
1386 			/* fixme sven, this needs to be chekced! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
1387 			switch( EASGet( aLocalName ) )
1388 			{
1389 				case EAS_handle_mirror_vertical :
1390 					GetBool( aHandle, rValue, EAS_MirroredY );
1391 				break;
1392 				case EAS_handle_mirror_horizontal :
1393 					GetBool( aHandle, rValue, EAS_MirroredX );
1394 				break;
1395 				case EAS_handle_switched :
1396 					GetBool( aHandle, rValue, EAS_Switched );
1397 				break;
1398 				case EAS_handle_position :
1399 					GetEnhancedParameterPair( aHandle, rValue, EAS_Position );
1400 				break;
1401 				case EAS_handle_range_x_minimum :
1402 					GetEnhancedParameter( aHandle, rValue, EAS_RangeXMinimum );
1403 				break;
1404 				case EAS_handle_range_x_maximum :
1405 					GetEnhancedParameter( aHandle, rValue, EAS_RangeXMaximum );
1406 				break;
1407 				case EAS_handle_range_y_minimum :
1408 					GetEnhancedParameter( aHandle, rValue, EAS_RangeYMinimum );
1409 				break;
1410 				case EAS_handle_range_y_maximum :
1411 					GetEnhancedParameter( aHandle, rValue, EAS_RangeYMaximum );
1412 				break;
1413 				case EAS_handle_polar :
1414 					GetEnhancedParameterPair( aHandle, rValue, EAS_Polar );
1415 				break;
1416 				case EAS_handle_radius_range_minimum :
1417 					GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMinimum );
1418 				break;
1419 				case EAS_handle_radius_range_maximum :
1420 					GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMaximum );
1421 				break;
1422 				default:
1423 					break;
1424 			}
1425 		}
1426 		beans::PropertyValues aPropSeq( aHandle.size() );
1427 		std::vector< beans::PropertyValue >::const_iterator aIter = aHandle.begin();
1428 		std::vector< beans::PropertyValue >::const_iterator aEnd = aHandle.end();
1429 		beans::PropertyValue* pValues = aPropSeq.getArray();
1430 
1431 		while ( aIter != aEnd )
1432 			*pValues++ = *aIter++;
1433 
1434 		maHandles.push_back( aPropSeq );
1435 	}
1436 	return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
1437 }
1438