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