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