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