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