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