LibreOffice Module xmloff (master)  1
ximpcustomshape.cxx
Go to the documentation of this file.
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 <o3tl/any.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/awt/Rectangle.hpp>
27 #include <com/sun/star/xml/sax/XAttributeList.hpp>
28 #include <xmloff/xmltoken.hxx>
30 #include <xmloff/xmlimp.hxx>
31 #include <xmloff/namespacemap.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/xmlement.hxx>
34 #include <xexptran.hxx>
35 #include <com/sun/star/drawing/Direction3D.hpp>
36 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
37 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
38 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
39 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
40 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
41 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
42 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
43 #include <com/sun/star/drawing/ProjectionMode.hpp>
44 #include <com/sun/star/drawing/Position3D.hpp>
45 #include <sax/tools/converter.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <memory>
48 #include <unordered_map>
49 
50 using namespace ::com::sun::star;
51 using namespace ::xmloff::token;
52 using namespace ::xmloff::EnhancedCustomShapeToken;
53 
54 
56  css::uno::Reference< css::drawing::XShape >& rxShape,
57  sal_uInt16 nPrefix, const OUString& rLocalName,
58  std::vector< css::beans::PropertyValue >& rCustomShapeGeometry ) :
59  SvXMLImportContext( rImport, nPrefix, rLocalName ),
60  mrUnitConverter( rImport.GetMM100UnitConverter() ),
61  mrxShape( rxShape ),
62  mrCustomShapeGeometry( rCustomShapeGeometry )
63 {
64 }
65 
67 {
68  { XML_NONE, 0 },
69  { XML_SEGMENTS, 1 },
70  { XML_NONE, 2 },
71  { XML_RECTANGLE, 3 },
72  { XML_TOKEN_INVALID, 0 }
73 };
74 static void GetBool( std::vector< css::beans::PropertyValue >& rDest,
75  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
76 {
77  bool bAttrBool;
78  if (::sax::Converter::convertBool( bAttrBool, rValue ))
79  {
80  beans::PropertyValue aProp;
81  aProp.Name = EASGet( eDestProp );
82  aProp.Value <<= bAttrBool;
83  rDest.push_back( aProp );
84  }
85 }
86 
87 static void GetInt32( std::vector< css::beans::PropertyValue >& rDest,
88  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
89 {
90  sal_Int32 nAttrNumber;
91  if (::sax::Converter::convertNumber( nAttrNumber, rValue ))
92  {
93  beans::PropertyValue aProp;
94  aProp.Name = EASGet( eDestProp );
95  aProp.Value <<= nAttrNumber;
96  rDest.push_back( aProp );
97  }
98 }
99 
100 static void GetDouble( std::vector< css::beans::PropertyValue >& rDest,
101  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
102 {
103  double fAttrDouble;
104  if (::sax::Converter::convertDouble( fAttrDouble, rValue ))
105  {
106  beans::PropertyValue aProp;
107  aProp.Name = EASGet( eDestProp );
108  aProp.Value <<= fAttrDouble;
109  rDest.push_back( aProp );
110  }
111 }
112 
113 static void GetString( std::vector< css::beans::PropertyValue >& rDest,
114  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
115 {
116  beans::PropertyValue aProp;
117  aProp.Name = EASGet( eDestProp );
118  aProp.Value <<= rValue;
119  rDest.push_back( aProp );
120 }
121 
122 template<typename EnumT>
123 static void GetEnum( std::vector< css::beans::PropertyValue >& rDest,
124  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp,
125  const SvXMLEnumMapEntry<EnumT>& rMap )
126 {
127  EnumT eKind;
128  if( SvXMLUnitConverter::convertEnum( eKind, rValue, &rMap ) )
129  {
130  beans::PropertyValue aProp;
131  aProp.Name = EASGet( eDestProp );
132  aProp.Value <<= static_cast<sal_Int16>(eKind);
133  rDest.push_back( aProp );
134  }
135 }
136 
137 static void GetDoublePercentage( std::vector< css::beans::PropertyValue >& rDest,
138  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
139 {
140  sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
141  rValue, util::MeasureUnit::MM_100TH);
142  if (util::MeasureUnit::PERCENT != eSrcUnit)
143  return;
144 
145  rtl_math_ConversionStatus eStatus;
146  double fAttrDouble = ::rtl::math::stringToDouble( rValue,
147  '.', ',', &eStatus );
148  if ( eStatus == rtl_math_ConversionStatus_Ok )
149  {
150  beans::PropertyValue aProp;
151  aProp.Name = EASGet( eDestProp );
152  aProp.Value <<= fAttrDouble;
153  rDest.push_back( aProp );
154  }
155 }
156 
157 static void GetB3DVector( std::vector< css::beans::PropertyValue >& rDest,
158  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
159 {
160  ::basegfx::B3DVector aB3DVector;
161  if ( SvXMLUnitConverter::convertB3DVector( aB3DVector, rValue ) )
162  {
163  drawing::Direction3D aDirection3D( aB3DVector.getX(), aB3DVector.getY(), aB3DVector.getZ() );
164  beans::PropertyValue aProp;
165  aProp.Name = EASGet( eDestProp );
166  aProp.Value <<= aDirection3D;
167  rDest.push_back( aProp );
168  }
169 }
170 
171 static bool GetEquationName( const OUString& rEquation, const sal_Int32 nStart, OUString& rEquationName )
172 {
173  sal_Int32 nIndex = nStart;
174  while( nIndex < rEquation.getLength() )
175  {
176  sal_Unicode nChar = rEquation[ nIndex ];
177  if (
178  ( ( nChar >= 'a' ) && ( nChar <= 'z' ) )
179  || ( ( nChar >= 'A' ) && ( nChar <= 'Z' ) )
180  || ( ( nChar >= '0' ) && ( nChar <= '9' ) )
181  )
182  {
183  nIndex++;
184  }
185  else
186  break;
187  }
188  bool bValid = ( nIndex - nStart ) != 0;
189  if ( bValid )
190  rEquationName = rEquation.copy( nStart, nIndex - nStart );
191  return bValid;
192 }
193 
194 static bool GetNextParameter( css::drawing::EnhancedCustomShapeParameter& rParameter, sal_Int32& nIndex, const OUString& rParaString )
195 {
196  if ( nIndex >= rParaString.getLength() )
197  return false;
198 
199  bool bValid = true;
200  bool bNumberRequired = true;
201  bool bMustBePositiveWholeNumbered = false;
202 
203  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::NORMAL;
204  if ( rParaString[ nIndex ] == '$' )
205  {
206  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT;
207  bMustBePositiveWholeNumbered = true;
208  nIndex++;
209  }
210  else if ( rParaString[ nIndex ] == '?' )
211  {
212  nIndex++;
213  bNumberRequired = false;
214  OUString aEquationName;
215  bValid = GetEquationName( rParaString, nIndex, aEquationName );
216  if ( bValid )
217  {
218  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::EQUATION;
219  rParameter.Value <<= aEquationName;
220  nIndex += aEquationName.getLength();
221  }
222  }
223  else if ( rParaString[ nIndex ] > '9' )
224  {
225  bNumberRequired = false;
226  if ( rParaString.matchIgnoreAsciiCase( "left", nIndex ) )
227  {
228  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::LEFT;
229  nIndex += 4;
230  }
231  else if ( rParaString.matchIgnoreAsciiCase( "top", nIndex ) )
232  {
233  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::TOP;
234  nIndex += 3;
235  }
236  else if ( rParaString.matchIgnoreAsciiCase( "right", nIndex ) )
237  {
238  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::RIGHT;
239  nIndex += 5;
240  }
241  else if ( rParaString.matchIgnoreAsciiCase( "bottom", nIndex ) )
242  {
243  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::BOTTOM;
244  nIndex += 6;
245  }
246  else if ( rParaString.matchIgnoreAsciiCase( "xstretch", nIndex ) )
247  {
248  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::XSTRETCH;
249  nIndex += 8;
250  }
251  else if ( rParaString.matchIgnoreAsciiCase( "ystretch", nIndex ) )
252  {
253  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::YSTRETCH;
254  nIndex += 8;
255  }
256  else if ( rParaString.matchIgnoreAsciiCase( "hasstroke", nIndex ) )
257  {
258  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::HASSTROKE;
259  nIndex += 9;
260  }
261  else if ( rParaString.matchIgnoreAsciiCase( "hasfill", nIndex ) )
262  {
263  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::HASFILL;
264  nIndex += 7;
265  }
266  else if ( rParaString.matchIgnoreAsciiCase( "width", nIndex ) )
267  {
268  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::WIDTH;
269  nIndex += 5;
270  }
271  else if ( rParaString.matchIgnoreAsciiCase( "height", nIndex ) )
272  {
273  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::HEIGHT;
274  nIndex += 6;
275  }
276  else if ( rParaString.matchIgnoreAsciiCase( "logwidth", nIndex ) )
277  {
278  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::LOGWIDTH;
279  nIndex += 8;
280  }
281  else if ( rParaString.matchIgnoreAsciiCase( "logheight", nIndex ) )
282  {
283  rParameter.Type = css::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT;
284  nIndex += 9;
285  }
286  else
287  bValid = false;
288  }
289  if ( bValid )
290  {
291  if ( bNumberRequired )
292  {
293  sal_Int32 nStartIndex = nIndex;
294  sal_Int32 nEIndex = 0; // index of "E" in double
295 
296  bool bE = false; // set if a double is including a "E" statement
297  bool bENum = false; // there is at least one number after "E"
298  bool bDot = false; // set if there is a dot included
299  bool bEnd = false; // set for each value that can not be part of a double/integer
300 
301  while( ( nIndex < rParaString.getLength() ) && bValid )
302  {
303  switch( rParaString[ nIndex ] )
304  {
305  case '.' :
306  {
307  if ( bMustBePositiveWholeNumbered )
308  bValid = false;
309  else
310  {
311  if ( bDot )
312  bValid = false;
313  else
314  bDot = true;
315  }
316  }
317  break;
318  case '-' :
319  {
320  if ( bMustBePositiveWholeNumbered )
321  bValid = false;
322  else
323  {
324  if ( nStartIndex == nIndex )
325  bValid = true;
326  else if ( bE )
327  {
328  if ( nEIndex + 1 == nIndex )
329  bValid = true;
330  else if ( bENum )
331  bEnd = true;
332  else
333  bValid = false;
334  }
335  }
336  }
337  break;
338 
339  case 'e' :
340  case 'E' :
341  {
342  if ( bMustBePositiveWholeNumbered )
343  bEnd = true;
344  else
345  {
346  if ( !bE )
347  {
348  bE = true;
349  nEIndex = nIndex;
350  }
351  else
352  bEnd = true;
353  }
354  }
355  break;
356  case '0' :
357  case '1' :
358  case '2' :
359  case '3' :
360  case '4' :
361  case '5' :
362  case '6' :
363  case '7' :
364  case '8' :
365  case '9' :
366  {
367  if ( bE && ! bENum )
368  bENum = true;
369  }
370  break;
371  default:
372  bEnd = true;
373  }
374  if ( !bEnd )
375  nIndex++;
376  else
377  break;
378  }
379  if ( nIndex == nStartIndex )
380  bValid = false;
381  if ( bValid )
382  {
383  OUString aNumber( rParaString.copy( nStartIndex, nIndex - nStartIndex ) );
384  if ( bE || bDot )
385  {
386  double fAttrDouble;
387  if (::sax::Converter::convertDouble(fAttrDouble, aNumber))
388  rParameter.Value <<= fAttrDouble;
389  else
390  bValid = false;
391  }
392  else
393  {
394  sal_Int32 nValue;
395  if (::sax::Converter::convertNumber(nValue, aNumber))
396  rParameter.Value <<= nValue;
397  else
398  bValid = false;
399  }
400  }
401  }
402  }
403  if ( bValid )
404  {
405  // skipping white spaces and commas (#i121507#)
406  const sal_Unicode aSpace(' ');
407  const sal_Unicode aCommata(',');
408 
409  while(nIndex < rParaString.getLength())
410  {
411  const sal_Unicode aCandidate(rParaString[nIndex]);
412 
413  if(aSpace == aCandidate || aCommata == aCandidate)
414  {
415  nIndex++;
416  }
417  else
418  {
419  break;
420  }
421  }
422  }
423  return bValid;
424 }
425 
426 static void GetPosition3D( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:extrusion-viewpoint
427  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp,
428  SvXMLUnitConverter& rUnitConverter )
429 {
430  drawing::Position3D aPosition3D;
431  if ( rUnitConverter.convertPosition3D( aPosition3D, rValue ) )
432  {
433  beans::PropertyValue aProp;
434  aProp.Name = EASGet( eDestProp );
435  aProp.Value <<= aPosition3D;
436  rDest.push_back( aProp );
437  }
438 }
439 
440 static void GetDoubleSequence( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:glue-point-leaving-directions
441  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
442 {
443  std::vector< double > vDirection;
444  sal_Int32 nIndex = 0;
445  do
446  {
447  double fAttrDouble;
448  OUString aToken( rValue.getToken( 0, ',', nIndex ) );
449  if (!::sax::Converter::convertDouble( fAttrDouble, aToken ))
450  break;
451  else
452  vDirection.push_back( fAttrDouble );
453  }
454  while ( nIndex >= 0 );
455 
456  if ( !vDirection.empty() )
457  {
458  beans::PropertyValue aProp;
459  aProp.Name = EASGet( eDestProp );
460  aProp.Value <<= comphelper::containerToSequence(vDirection);
461  rDest.push_back( aProp );
462  }
463 }
464 
465 static void GetSizeSequence( std::vector< css::beans::PropertyValue >& rDest,
466  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
467 {
468  std::vector< sal_Int32 > vNum;
469  sal_Int32 nIndex = 0;
470  do
471  {
472  sal_Int32 n;
473  OUString aToken( rValue.getToken( 0, ' ', nIndex ) );
474  if (!::sax::Converter::convertNumber( n, aToken ))
475  break;
476  else
477  vNum.push_back( n );
478  }
479  while ( nIndex >= 0 );
480 
481  if ( vNum.empty() )
482  return;
483 
484  uno::Sequence< awt::Size > aSizeSeq((vNum.size() + 1) / 2);
485  std::vector< sal_Int32 >::const_iterator aIter = vNum.begin();
486  std::vector< sal_Int32 >::const_iterator aEnd = vNum.end();
487  awt::Size* pValues = aSizeSeq.getArray();
488 
489  while ( aIter != aEnd ) {
490  pValues->Width = *aIter++;
491  if ( aIter != aEnd )
492  pValues->Height = *aIter++;
493  pValues ++;
494  }
495 
496  beans::PropertyValue aProp;
497  aProp.Name = EASGet( eDestProp );
498  aProp.Value <<= aSizeSeq;
499  rDest.push_back( aProp );
500 }
501 
502 static void GetEnhancedParameter( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:handle-position
503  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
504 {
505  sal_Int32 nIndex = 0;
506  css::drawing::EnhancedCustomShapeParameter aParameter;
507  if ( GetNextParameter( aParameter, nIndex, rValue ) )
508  {
509  beans::PropertyValue aProp;
510  aProp.Name = EASGet( eDestProp );
511  aProp.Value <<= aParameter;
512  rDest.push_back( aProp );
513  }
514 }
515 
516 static void GetEnhancedParameterPair( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:handle-position
517  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
518 {
519  sal_Int32 nIndex = 0;
520  css::drawing::EnhancedCustomShapeParameterPair aParameterPair;
521  if ( GetNextParameter( aParameterPair.First, nIndex, rValue )
522  && GetNextParameter( aParameterPair.Second, nIndex, rValue ) )
523  {
524  beans::PropertyValue aProp;
525  aProp.Name = EASGet( eDestProp );
526  aProp.Value <<= aParameterPair;
527  rDest.push_back( aProp );
528  }
529 }
530 
531 static sal_Int32 GetEnhancedParameterPairSequence( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:glue-points
532  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
533 {
534  std::vector< css::drawing::EnhancedCustomShapeParameterPair > vParameter;
535  css::drawing::EnhancedCustomShapeParameterPair aParameter;
536 
537  sal_Int32 nIndex = 0;
538  while ( GetNextParameter( aParameter.First, nIndex, rValue )
539  && GetNextParameter( aParameter.Second, nIndex, rValue ) )
540  {
541  vParameter.push_back( aParameter );
542  }
543  if ( !vParameter.empty() )
544  {
545  beans::PropertyValue aProp;
546  aProp.Name = EASGet( eDestProp );
547  aProp.Value <<= comphelper::containerToSequence(vParameter);
548  rDest.push_back( aProp );
549  }
550  return vParameter.size();
551 }
552 
553 static void GetEnhancedRectangleSequence( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:text-areas
554  const OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp )
555 {
556  std::vector< css::drawing::EnhancedCustomShapeTextFrame > vTextFrame;
557  css::drawing::EnhancedCustomShapeTextFrame aParameter;
558 
559  sal_Int32 nIndex = 0;
560 
561  while ( GetNextParameter( aParameter.TopLeft.First, nIndex, rValue )
562  && GetNextParameter( aParameter.TopLeft.Second, nIndex, rValue )
563  && GetNextParameter( aParameter.BottomRight.First, nIndex, rValue )
564  && GetNextParameter( aParameter.BottomRight.Second, nIndex, rValue ) )
565  {
566  vTextFrame.push_back( aParameter );
567  }
568  if ( !vTextFrame.empty() )
569  {
570  beans::PropertyValue aProp;
571  aProp.Name = EASGet( eDestProp );
572  aProp.Value <<= comphelper::containerToSequence(vTextFrame);
573  rDest.push_back( aProp );
574  }
575 }
576 
577 static void GetEnhancedPath( std::vector< css::beans::PropertyValue >& rDest, // e.g. draw:enhanced-path
578  const OUString& rValue )
579 {
580  std::vector< css::drawing::EnhancedCustomShapeParameterPair > vCoordinates;
581  std::vector< css::drawing::EnhancedCustomShapeSegment > vSegments;
582 
583  sal_Int32 nIndex = 0;
584  sal_Int32 nParameterCount = 0;
585 
586  sal_Int32 nParametersNeeded = 1;
587  sal_Int16 nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
588 
589  bool bValid = true;
590 
591  while( bValid && ( nIndex < rValue.getLength() ) )
592  {
593  switch( rValue[ nIndex ] )
594  {
595  case 'M' :
596  {
597  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
598  nParametersNeeded = 1;
599  nIndex++;
600  }
601  break;
602  case 'L' :
603  {
604  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
605  nParametersNeeded = 1;
606  nIndex++;
607  }
608  break;
609  case 'C' :
610  {
611  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
612  nParametersNeeded = 3;
613  nIndex++;
614  }
615  break;
616  case 'Z' :
617  {
618  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
619  nParametersNeeded = 0;
620  nIndex++;
621  }
622  break;
623  case 'N' :
624  {
625  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
626  nParametersNeeded = 0;
627  nIndex++;
628  }
629  break;
630  case 'F' :
631  {
632  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::NOFILL;
633  nParametersNeeded = 0;
634  nIndex++;
635  }
636  break;
637  case 'S' :
638  {
639  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE;
640  nParametersNeeded = 0;
641  nIndex++;
642  }
643  break;
644  case 'T' :
645  {
646  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
647  nParametersNeeded = 3;
648  nIndex++;
649  }
650  break;
651  case 'U' :
652  {
653  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
654  nParametersNeeded = 3;
655  nIndex++;
656  }
657  break;
658  case 'A' :
659  {
660  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
661  nParametersNeeded = 4;
662  nIndex++;
663  }
664  break;
665  case 'B' :
666  {
667  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ARC;
668  nParametersNeeded = 4;
669  nIndex++;
670  }
671  break;
672  case 'G' :
673  {
674  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO;
675  nParametersNeeded = 2;
676  nIndex++;
677  }
678  break;
679  case 'H' :
680  {
681  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::DARKEN;
682  nParametersNeeded = 0;
683  nIndex++;
684  }
685  break;
686  case 'I' :
687  {
688  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS;
689  nParametersNeeded = 0;
690  nIndex++;
691  }
692  break;
693  case 'J' :
694  {
695  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN;
696  nParametersNeeded = 0;
697  nIndex++;
698  }
699  break;
700  case 'K' :
701  {
702  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS;
703  nParametersNeeded = 0;
704  nIndex++;
705  }
706  break;
707  case 'W' :
708  {
709  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
710  nParametersNeeded = 4;
711  nIndex++;
712  }
713  break;
714  case 'V' :
715  {
716  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
717  nParametersNeeded = 4;
718  nIndex++;
719  }
720  break;
721  case 'X' :
722  {
723  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
724  nParametersNeeded = 1;
725  nIndex++;
726  }
727  break;
728  case 'Y' :
729  {
730  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
731  nParametersNeeded = 1;
732  nIndex++;
733  }
734  break;
735  case 'Q' :
736  {
737  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO;
738  nParametersNeeded = 2;
739  nIndex++;
740  }
741  break;
742  case ' ' :
743  {
744  nIndex++;
745  }
746  break;
747 
748  case '$' :
749  case '?' :
750  case '0' :
751  case '1' :
752  case '2' :
753  case '3' :
754  case '4' :
755  case '5' :
756  case '6' :
757  case '7' :
758  case '8' :
759  case '9' :
760  case '.' :
761  case '-' :
762  {
763  css::drawing::EnhancedCustomShapeParameterPair aPair;
764  if ( GetNextParameter( aPair.First, nIndex, rValue ) &&
765  GetNextParameter( aPair.Second, nIndex, rValue ) )
766  {
767  vCoordinates.push_back( aPair );
768  nParameterCount++;
769  }
770  else
771  bValid = false;
772  }
773  break;
774  default:
775  nIndex++;
776  break;
777  }
778  if ( !nParameterCount && !nParametersNeeded )
779  {
780  css::drawing::EnhancedCustomShapeSegment aSegment;
781  aSegment.Command = nLatestSegmentCommand;
782  aSegment.Count = 0;
783  vSegments.push_back( aSegment );
784  nParametersNeeded = 0x7fffffff;
785  }
786  else if ( nParameterCount >= nParametersNeeded )
787  {
788  // Special rule for moveto in ODF 1.2 section 19.145
789  // "If a moveto is followed by multiple pairs of coordinates, they are treated as lineto."
790  if ( nLatestSegmentCommand == css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO )
791  {
792  css::drawing::EnhancedCustomShapeSegment aSegment;
793  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
794  aSegment.Count = 1;
795  vSegments.push_back( aSegment );
796  nIndex--;
797  nLatestSegmentCommand = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
798  nParametersNeeded = 1;
799  }
800  else
801  {
802  // General rule in ODF 1.2. section 19.145
803  // "If a command is repeated multiple times, all repeated command characters
804  // except the first one may be omitted." Thus check if the last command is identical,
805  // if so, we just need to increment the count
806  if ( !vSegments.empty() && ( vSegments[ vSegments.size() - 1 ].Command == nLatestSegmentCommand ) )
807  vSegments[ vSegments.size() -1 ].Count++;
808  else
809  {
810  css::drawing::EnhancedCustomShapeSegment aSegment;
811  aSegment.Command = nLatestSegmentCommand;
812  aSegment.Count = 1;
813  vSegments.push_back( aSegment );
814  }
815  }
816  nParameterCount = 0;
817  }
818  }
819 
820  // adding the Coordinates property
821  beans::PropertyValue aProp;
822  aProp.Name = EASGet( EAS_Coordinates );
823  aProp.Value <<= comphelper::containerToSequence(vCoordinates);
824  rDest.push_back( aProp );
825 
826  // adding the Segments property
827  aProp.Name = EASGet( EAS_Segments );
828  aProp.Value <<= comphelper::containerToSequence(vSegments);
829  rDest.push_back( aProp );
830 }
831 
832 static void GetAdjustmentValues( std::vector< css::beans::PropertyValue >& rDest, // draw:adjustments
833  const OUString& rValue )
834 {
835  std::vector< css::drawing::EnhancedCustomShapeAdjustmentValue > vAdjustmentValue;
836  css::drawing::EnhancedCustomShapeParameter aParameter;
837  sal_Int32 nIndex = 0;
838  while ( GetNextParameter( aParameter, nIndex, rValue ) )
839  {
840  css::drawing::EnhancedCustomShapeAdjustmentValue aAdj;
841  if ( aParameter.Type == css::drawing::EnhancedCustomShapeParameterType::NORMAL )
842  {
843  aAdj.Value = aParameter.Value;
844  aAdj.State = beans::PropertyState_DIRECT_VALUE;
845  }
846  else
847  aAdj.State = beans::PropertyState_DEFAULT_VALUE; // this should not be, but better than setting nothing
848 
849  vAdjustmentValue.push_back( aAdj );
850  }
851 
852  sal_Int32 nAdjustmentValues = vAdjustmentValue.size();
853  if ( nAdjustmentValues )
854  {
855  beans::PropertyValue aProp;
856  aProp.Name = EASGet( EAS_AdjustmentValues );
857  aProp.Value <<= comphelper::containerToSequence(vAdjustmentValue);
858  rDest.push_back( aProp );
859  }
860 }
861 
862 void XMLEnhancedCustomShapeContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
863 {
864  sal_Int16 nLength = xAttrList->getLength();
865  if ( !nLength )
866  return;
867 
868  sal_Int32 nAttrNumber;
869  for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
870  {
871  OUString aLocalName;
872  const OUString& rValue = xAttrList->getValueByIndex( nAttr );
873  /* sven fixme, this must be checked! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
874 
875  switch( EASGet( aLocalName ) )
876  {
877  case EAS_type :
879  break;
880  case EAS_mirror_horizontal :
882  break;
883  case EAS_mirror_vertical :
885  break;
886  case EAS_viewBox :
887  {
888  SdXMLImExViewBox aViewBox( rValue, GetImport().GetMM100UnitConverter() );
889  awt::Rectangle aRect( aViewBox.GetX(), aViewBox.GetY(), aViewBox.GetWidth(), aViewBox.GetHeight() );
890  beans::PropertyValue aProp;
891  aProp.Name = EASGet( EAS_ViewBox );
892  aProp.Value <<= aRect;
893  mrCustomShapeGeometry.push_back( aProp );
894  }
895  break;
896  case EAS_sub_view_size:
898  break;
899  case EAS_text_rotate_angle :
901  break;
902  case EAS_extrusion_allowed :
903  GetBool( maPath, rValue, EAS_ExtrusionAllowed );
904  break;
905  case EAS_text_path_allowed :
906  GetBool( maPath, rValue, EAS_TextPathAllowed );
907  break;
910  break;
911  case EAS_extrusion :
912  GetBool( maExtrusion, rValue, EAS_Extrusion );
913  break;
916  break;
917  case EAS_extrusion_depth :
918  {
919  sal_Int32 nIndex = 0;
920  css::drawing::EnhancedCustomShapeParameterPair aParameterPair;
921  css::drawing::EnhancedCustomShapeParameter& rDepth = aParameterPair.First;
922  if ( GetNextParameter( rDepth, nIndex, rValue ) )
923  {
924  css::drawing::EnhancedCustomShapeParameter& rFraction = aParameterPair.Second;
925  // try to catch the unit for the depth
926  sal_Int16 const eSrcUnit(
928  rValue, util::MeasureUnit::MM_100TH));
929 
930  OUStringBuffer aUnitStr;
931  double fFactor = ::sax::Converter::GetConversionFactor(
932  aUnitStr, util::MeasureUnit::MM_100TH, eSrcUnit);
933  if ( ( fFactor != 1.0 ) && ( fFactor != 0.0 ) )
934  {
935  double fDepth(0.0);
936  if ( rDepth.Value >>= fDepth )
937  {
938  fDepth /= fFactor;
939  rDepth.Value <<= fDepth;
940  }
941  }
942  if ( rValue.matchIgnoreAsciiCase( aUnitStr.toString(), nIndex ) )
943  nIndex += aUnitStr.getLength();
944 
945  // skipping white spaces
946  while( ( nIndex < rValue.getLength() ) && rValue[ nIndex ] == ' ' )
947  nIndex++;
948 
949  if ( GetNextParameter( rFraction, nIndex, rValue ) )
950  {
951  beans::PropertyValue aProp;
952  aProp.Name = EASGet( EAS_Depth );
953  aProp.Value <<= aParameterPair;
954  maExtrusion.push_back( aProp );
955  }
956  }
957  }
958  break;
961  break;
964  break;
966  GetBool( maExtrusion, rValue, EAS_LightFace );
967  break;
970  break;
973  break;
976  break;
979  break;
982  break;
985  break;
986  case EAS_extrusion_metal :
987  GetBool( maExtrusion, rValue, EAS_Metal );
988  break;
989  case EAS_shade_mode :
990  {
991  drawing::ShadeMode eShadeMode( drawing::ShadeMode_FLAT );
992  if( IsXMLToken( rValue, XML_PHONG ) )
993  eShadeMode = drawing::ShadeMode_PHONG;
994  else if ( IsXMLToken( rValue, XML_GOURAUD ) )
995  eShadeMode = drawing::ShadeMode_SMOOTH;
996  else if ( IsXMLToken( rValue, XML_DRAFT ) )
997  eShadeMode = drawing::ShadeMode_DRAFT;
998 
999  beans::PropertyValue aProp;
1000  aProp.Name = EASGet( EAS_ShadeMode );
1001  aProp.Value <<= eShadeMode;
1002  maExtrusion.push_back( aProp );
1003  }
1004  break;
1007  break;
1010  break;
1013  break;
1014  case EAS_extrusion_skew :
1016  break;
1019  break;
1020  case EAS_projection :
1021  {
1022  drawing::ProjectionMode eProjectionMode( drawing::ProjectionMode_PERSPECTIVE );
1023  if( IsXMLToken( rValue, XML_PARALLEL ) )
1024  eProjectionMode = drawing::ProjectionMode_PARALLEL;
1025 
1026  beans::PropertyValue aProp;
1027  aProp.Name = EASGet( EAS_ProjectionMode );
1028  aProp.Value <<= eProjectionMode;
1029  maExtrusion.push_back( aProp );
1030  }
1031  break;
1034  break;
1035  case EAS_extrusion_origin :
1037  break;
1038  case EAS_extrusion_color :
1039  GetBool( maExtrusion, rValue, EAS_Color );
1040  break;
1041  case EAS_enhanced_path :
1042  GetEnhancedPath( maPath, rValue );
1043  break;
1045  {
1046  if (::sax::Converter::convertNumber(nAttrNumber, rValue))
1047  {
1048  beans::PropertyValue aProp;
1049  aProp.Name = EASGet( EAS_StretchX );
1050  aProp.Value <<= nAttrNumber;
1051  maPath.push_back( aProp );
1052  }
1053  }
1054  break;
1056  {
1057  if (::sax::Converter::convertNumber(nAttrNumber, rValue))
1058  {
1059  beans::PropertyValue aProp;
1060  aProp.Name = EASGet( EAS_StretchY );
1061  aProp.Value <<= nAttrNumber;
1062  maPath.push_back( aProp );
1063  }
1064  }
1065  break;
1066  case EAS_text_areas :
1068  break;
1069  case EAS_glue_points :
1070  {
1071  sal_Int32 i, nPairs = GetEnhancedParameterPairSequence( maPath, rValue, EAS_GluePoints );
1072  GetImport().GetShapeImport()->moveGluePointMapping( mrxShape, nPairs );
1073  for ( i = 0; i < nPairs; i++ )
1074  GetImport().GetShapeImport()->addGluePointMapping( mrxShape, i + 4, i + 4 );
1075  }
1076  break;
1077  case EAS_glue_point_type :
1078  GetEnum( maPath, rValue, EAS_GluePointType, *aXML_GluePointEnumMap );
1079  break;
1082  break;
1083  case EAS_text_path :
1084  GetBool( maTextPath, rValue, EAS_TextPath );
1085  break;
1086  case EAS_text_path_mode :
1087  {
1088  css::drawing::EnhancedCustomShapeTextPathMode eTextPathMode( css::drawing::EnhancedCustomShapeTextPathMode_NORMAL );
1089  if( IsXMLToken( rValue, XML_PATH ) )
1090  eTextPathMode = css::drawing::EnhancedCustomShapeTextPathMode_PATH;
1091  else if ( IsXMLToken( rValue, XML_SHAPE ) )
1092  eTextPathMode = css::drawing::EnhancedCustomShapeTextPathMode_SHAPE;
1093 
1094  beans::PropertyValue aProp;
1095  aProp.Name = EASGet( EAS_TextPathMode );
1096  aProp.Value <<= eTextPathMode;
1097  maTextPath.push_back( aProp );
1098  }
1099  break;
1100  case EAS_text_path_scale :
1101  {
1102  bool bScaleX = IsXMLToken( rValue, XML_SHAPE );
1103  beans::PropertyValue aProp;
1104  aProp.Name = EASGet( EAS_ScaleX );
1105  aProp.Value <<= bScaleX;
1106  maTextPath.push_back( aProp );
1107  }
1108  break;
1111  break;
1112  case EAS_modifiers :
1114  break;
1115  default:
1116  break;
1117  }
1118  }
1119 }
1120 
1121 static void SdXMLCustomShapePropertyMerge( std::vector< css::beans::PropertyValue >& rPropVec,
1122  const std::vector< beans::PropertyValues >& rElement,
1123  const OUString& rElementName )
1124 {
1125  if ( !rElement.empty() )
1126  {
1127  beans::PropertyValue aProp;
1128  aProp.Name = rElementName;
1129  aProp.Value <<= comphelper::containerToSequence(rElement);
1130  rPropVec.push_back( aProp );
1131  }
1132 }
1133 
1134 static void SdXMLCustomShapePropertyMerge( std::vector< css::beans::PropertyValue >& rPropVec,
1135  const std::vector< OUString >& rElement,
1136  const OUString& rElementName )
1137 {
1138  if ( !rElement.empty() )
1139  {
1140  beans::PropertyValue aProp;
1141  aProp.Name = rElementName;
1142  aProp.Value <<= comphelper::containerToSequence(rElement);
1143  rPropVec.push_back( aProp );
1144  }
1145 }
1146 
1147 static void SdXMLCustomShapePropertyMerge( std::vector< css::beans::PropertyValue >& rPropVec,
1148  const std::vector< css::beans::PropertyValue >& rElement,
1149  const OUString& rElementName )
1150 {
1151  if ( !rElement.empty() )
1152  {
1153  beans::PropertyValue aProp;
1154  aProp.Name = rElementName;
1155  aProp.Value <<= comphelper::containerToSequence(rElement);
1156  rPropVec.push_back( aProp );
1157  }
1158 }
1159 
1160 typedef std::unordered_map< OUString, sal_Int32 > EquationHashMap;
1161 
1162 /* if rPara.Type is from type EnhancedCustomShapeParameterType::EQUATION, the name of the equation
1163  will be converted from OUString to index */
1164 static void CheckAndResolveEquationParameter( css::drawing::EnhancedCustomShapeParameter& rPara, EquationHashMap* pH )
1165 {
1166  if ( rPara.Type == css::drawing::EnhancedCustomShapeParameterType::EQUATION )
1167  {
1168  OUString aEquationName;
1169  if ( rPara.Value >>= aEquationName )
1170  {
1171  sal_Int32 nIndex = 0;
1172  EquationHashMap::iterator aHashIter( pH->find( aEquationName ) );
1173  if ( aHashIter != pH->end() )
1174  nIndex = (*aHashIter).second;
1175  rPara.Value <<= nIndex;
1176  }
1177  }
1178 }
1179 
1181 {
1182  // resolve properties that are indexing an Equation
1183  if ( !maEquations.empty() )
1184  {
1185  // creating hash map containing the name and index of each equation
1186  std::unique_ptr<EquationHashMap> pH = std::make_unique<EquationHashMap>();
1187  std::vector< OUString >::iterator aEquationNameIter = maEquationNames.begin();
1188  std::vector< OUString >::iterator aEquationNameEnd = maEquationNames.end();
1189  while( aEquationNameIter != aEquationNameEnd )
1190  {
1191  (*pH)[ *aEquationNameIter ] = static_cast<sal_Int32>( aEquationNameIter - maEquationNames.begin() );
1192  ++aEquationNameIter;
1193  }
1194 
1195  // resolve equation
1196  for( auto& rEquation : maEquations )
1197  {
1198  sal_Int32 nIndexOf = 0;
1199  do
1200  {
1201  nIndexOf = rEquation.indexOf( '?', nIndexOf );
1202  if ( nIndexOf != -1 )
1203  {
1204  OUString aEquationName;
1205  if ( GetEquationName( rEquation, nIndexOf + 1, aEquationName ) )
1206  {
1207  // copying first characters inclusive '?'
1208  sal_Int32 nIndex = 0;
1209  EquationHashMap::iterator aHashIter( pH->find( aEquationName ) );
1210  if ( aHashIter != pH->end() )
1211  nIndex = (*aHashIter).second;
1212  OUString aNew = rEquation.copy( 0, nIndexOf + 1 ) +
1213  OUString::number( nIndex ) +
1214  rEquation.copy( nIndexOf + aEquationName.getLength() + 1 );
1215  rEquation = aNew;
1216  }
1217  nIndexOf++;
1218  }
1219  }
1220  while( nIndexOf != -1 );
1221  }
1222 
1223  // Path
1224  for ( const beans::PropertyValue& rPathItem : maPath )
1225  {
1226  switch( EASGet( rPathItem.Name ) )
1227  {
1228  case EAS_Coordinates :
1229  case EAS_GluePoints :
1230  {
1231  uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > const & rSeq =
1232  *o3tl::doAccess<uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > >(
1233  rPathItem.Value);
1234  for ( const auto& rElem : rSeq )
1235  {
1236  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.First), pH.get() );
1237  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.Second), pH.get() );
1238  }
1239  }
1240  break;
1241  case EAS_TextFrames :
1242  {
1243  uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > const & rSeq =
1244  *o3tl::doAccess<uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > >(
1245  rPathItem.Value);
1246  for ( const auto& rElem : rSeq )
1247  {
1248  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.TopLeft.First), pH.get() );
1249  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.TopLeft.Second), pH.get() );
1250  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.BottomRight.First), pH.get() );
1251  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(rElem.BottomRight.Second), pH.get() );
1252  }
1253  }
1254  break;
1255  default:
1256  break;
1257  }
1258  }
1259  for ( css::beans::PropertyValues const & aHandle : maHandles )
1260  {
1261  for ( beans::PropertyValue const & propValue : aHandle )
1262  {
1263  switch( EASGet( propValue.Name ) )
1264  {
1265  case EAS_RangeYMinimum :
1266  case EAS_RangeYMaximum :
1267  case EAS_RangeXMinimum :
1268  case EAS_RangeXMaximum :
1269  case EAS_RadiusRangeMinimum :
1270  case EAS_RadiusRangeMaximum :
1271  {
1272  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>(*o3tl::doAccess<css::drawing::EnhancedCustomShapeParameter>(
1273  propValue.Value)), pH.get() );
1274  }
1275  break;
1276 
1277  case EAS_Position :
1278  case EAS_Polar :
1279  {
1280  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>((*o3tl::doAccess<css::drawing::EnhancedCustomShapeParameterPair>(
1281  propValue.Value)).First), pH.get() );
1282  CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter &>((*o3tl::doAccess<css::drawing::EnhancedCustomShapeParameterPair>(
1283  propValue.Value)).Second), pH.get() );
1284  }
1285  break;
1286  default:
1287  break;
1288  }
1289  }
1290  }
1291  }
1292 
1297  if ( !maHandles.empty() )
1299 }
1300 
1301 SvXMLImportContextRef XMLEnhancedCustomShapeContext::CreateChildContext( sal_uInt16 /*nPrefix*/,const OUString& rLocalName,
1302  const uno::Reference< xml::sax::XAttributeList> & xAttrList )
1303 {
1304  EnhancedCustomShapeTokenEnum aTokenEnum = EASGet( rLocalName );
1305  if ( aTokenEnum == EAS_equation )
1306  {
1307  sal_Int16 nLength = xAttrList->getLength();
1308  if ( nLength )
1309  {
1310  OUString aFormula;
1311  OUString aFormulaName;
1312  for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
1313  {
1314  OUString aLocalName;
1315  const OUString& rValue = xAttrList->getValueByIndex( nAttr );
1316  /* fixme sven, this needs to be checked! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
1317 
1318  switch( EASGet( aLocalName ) )
1319  {
1320  case EAS_formula :
1321  aFormula = rValue;
1322  break;
1323  case EAS_name :
1324  aFormulaName = rValue;
1325  break;
1326  default:
1327  break;
1328  }
1329  }
1330  if ( !aFormulaName.isEmpty() || !aFormula.isEmpty() )
1331  {
1332  maEquations.push_back( aFormula );
1333  maEquationNames.push_back( aFormulaName );
1334  }
1335  }
1336  }
1337  else if ( aTokenEnum == EAS_handle )
1338  {
1339  std::vector< css::beans::PropertyValue > aHandle;
1340  const sal_Int16 nLength = xAttrList->getLength();
1341  for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ )
1342  {
1343  OUString aLocalName;
1344  const OUString& rValue = xAttrList->getValueByIndex( nAttr );
1345  /* fixme sven, this needs to be checked! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName );
1346  switch( EASGet( aLocalName ) )
1347  {
1349  GetBool( aHandle, rValue, EAS_MirroredY );
1350  break;
1352  GetBool( aHandle, rValue, EAS_MirroredX );
1353  break;
1354  case EAS_handle_switched :
1355  GetBool( aHandle, rValue, EAS_Switched );
1356  break;
1357  case EAS_handle_position :
1358  GetEnhancedParameterPair( aHandle, rValue, EAS_Position );
1359  break;
1361  GetEnhancedParameter( aHandle, rValue, EAS_RangeXMinimum );
1362  break;
1364  GetEnhancedParameter( aHandle, rValue, EAS_RangeXMaximum );
1365  break;
1367  GetEnhancedParameter( aHandle, rValue, EAS_RangeYMinimum );
1368  break;
1370  GetEnhancedParameter( aHandle, rValue, EAS_RangeYMaximum );
1371  break;
1372  case EAS_handle_polar :
1373  GetEnhancedParameterPair( aHandle, rValue, EAS_Polar );
1374  break;
1376  GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMinimum );
1377  break;
1379  GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMaximum );
1380  break;
1381  default:
1382  break;
1383  }
1384  }
1385  maHandles.push_back( comphelper::containerToSequence(aHandle) );
1386  }
1387  return nullptr;
1388 }
1389 
1390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
std::vector< OUString > maEquations
sal_Int32 nIndex
static bool convertEnum(EnumT &rEnum, const OUString &rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
convert string to enum using given enum map, if the enum is not found in the map, this method will re...
Definition: xmluconv.hxx:128
static bool convertBool(bool &rBool, const OUString &rString)
EnhancedCustomShapeTokenEnum EASGet(const OUString &rShapeType)
static void GetEnhancedParameter(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:77
static void GetSizeSequence(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
static void GetB3DVector(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
std::vector< css::beans::PropertyValue > maTextPath
SvXMLUnitConverter & mrUnitConverter
static bool GetNextParameter(css::drawing::EnhancedCustomShapeParameter &rParameter, sal_Int32 &nIndex, const OUString &rParaString)
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
double GetWidth() const
Definition: xexptran.hxx:97
sal_Int64 n
static sal_Int32 GetEnhancedParameterPairSequence(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
static void GetInt32(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:394
SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
static double GetConversionFactor(OUStringBuffer &rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
const SvXMLEnumMapEntry< sal_uInt16 > aXML_GluePointEnumMap[]
std::vector< css::beans::PropertyValues > maHandles
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
std::vector< css::beans::PropertyValue > maExtrusion
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
sal_uInt16 sal_Unicode
static void GetEnhancedRectangleSequence(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
static void SdXMLCustomShapePropertyMerge(std::vector< css::beans::PropertyValue > &rPropVec, const std::vector< beans::PropertyValues > &rElement, const OUString &rElementName)
static void GetPosition3D(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp, SvXMLUnitConverter &rUnitConverter)
css::uno::Reference< css::drawing::XShape > & mrxShape
std::vector< css::beans::PropertyValue > maPath
int i
XMLEnhancedCustomShapeContext(SvXMLImport &rImport, css::uno::Reference< css::drawing::XShape > &, sal_uInt16 nPrefix, const OUString &rLocalName, std::vector< css::beans::PropertyValue > &rCustomShapeGeometry)
std::vector< css::beans::PropertyValue > & mrCustomShapeGeometry
std::unordered_map< OUString, sal_Int32 > EquationHashMap
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
static bool convertB3DVector(::basegfx::B3DVector &rVector, const OUString &rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:507
const PropertyValue * pValues
static sal_Int16 GetUnitFromString(const OUString &rString, sal_Int16 nDefaultUnit)
static void CheckAndResolveEquationParameter(css::drawing::EnhancedCustomShapeParameter &rPara, EquationHashMap *pH)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Handling of tokens in XML:
static void GetAdjustmentValues(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue)
static void GetEnhancedPath(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue)
static bool GetEquationName(const OUString &rEquation, const sal_Int32 nStart, OUString &rEquationName)
bool convertPosition3D(css::drawing::Position3D &rPosition, const OUString &rValue)
convert string to Position3D
double GetHeight() const
Definition: xexptran.hxx:98
static void GetString(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
static void GetBool(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
static void GetDouble(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
sal_Int32 nLength
Definition: xmltoken.cxx:36
static void GetEnum(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp, const SvXMLEnumMapEntry< EnumT > &rMap)
double GetX() const
Definition: xexptran.hxx:95
static void GetDoubleSequence(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
double GetY() const
Definition: xexptran.hxx:96
static void GetEnhancedParameterPair(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
static void GetDoublePercentage(std::vector< css::beans::PropertyValue > &rDest, const OUString &rValue, const EnhancedCustomShapeTokenEnum eDestProp)
sal_Int16 nValue
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:600
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
std::vector< OUString > maEquationNames