xref: /trunk/main/xmloff/source/draw/ximpcustomshape.cxx (revision a893be29343ee97512d484e6e8fefa91df2b44cb)
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 
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 };
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 noone uses this state explicitely 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 
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 
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 
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 */
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 
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 
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