LibreOffice Module oox (master)  1
customshapegeometry.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 
22 
23 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
24 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
25 #include <com/sun/star/xml/sax/FastToken.hpp>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <oox/helper/helper.hxx>
30 #include <oox/token/namespaces.hxx>
31 #include <oox/token/tokens.hxx>
32 #include <unordered_map>
33 
34 using namespace ::oox::core;
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::drawing;
37 using namespace ::com::sun::star::xml::sax;
38 
39 namespace oox::drawingml {
40 
41 namespace {
42 
43 enum FormulaCommand
44 {
45  FC_MULDIV = 0,
46  FC_PLUSMINUS,
47  FC_PLUSDIV,
48  FC_IFELSE,
49  FC_IFELSE1,
50  FC_ABS,
51  FC_AT2,
52  FC_CAT2,
53  FC_COS,
54  FC_MAX,
55  FC_MIN,
56  FC_MOD,
57  FC_PIN,
58  FC_SAT2,
59  FC_SIN,
60  FC_SQRT,
61  FC_TAN,
62  FC_VAL
63 };
64 
65 struct FormulaCommandNameTable
66 {
67  const char* pS;
68  FormulaCommand pE;
69 };
70 
71 }
72 
73 const FormulaCommandNameTable pFormulaCommandNameTable[] =
74 {
75  { "*/", FC_MULDIV },
76  { "+-", FC_PLUSMINUS },
77  { "+/", FC_PLUSDIV },
78  { "ifelse", FC_IFELSE },
79  { "?:", FC_IFELSE1 },
80  { "abs", FC_ABS },
81  { "at2", FC_AT2 },
82  { "cat2", FC_CAT2 },
83  { "cos", FC_COS },
84  { "max", FC_MAX },
85  { "min", FC_MIN },
86  { "mod", FC_MOD },
87  { "pin", FC_PIN },
88  { "sat2", FC_SAT2 },
89  { "sin", FC_SIN },
90  { "sqrt", FC_SQRT },
91  { "tan", FC_TAN },
92  { "val", FC_VAL }
93 
94 };
95 typedef std::unordered_map< OUString, FormulaCommand > FormulaCommandHMap;
96 
97 static const FormulaCommandHMap* pCommandHashMap;
98 
99 static OUString GetFormulaParameter( const EnhancedCustomShapeParameter& rParameter )
100 {
101  OUString aRet;
102  switch( rParameter.Type )
103  {
104  case EnhancedCustomShapeParameterType::NORMAL :
105  {
106  if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
107  {
108  double fValue = 0.0;
109  if ( rParameter.Value >>= fValue )
110  aRet = OUString::number( fValue );
111  }
112  else
113  {
114  sal_Int32 nValue = 0;
115  if ( rParameter.Value >>= nValue )
116  aRet = OUString::number( nValue );
117  }
118  }
119  break;
120  case EnhancedCustomShapeParameterType::EQUATION :
121  {
122  if ( rParameter.Value.getValueTypeClass() == TypeClass_LONG )
123  {
124  sal_Int32 nFormulaIndex;
125  if ( rParameter.Value >>= nFormulaIndex )
126  {
127  aRet = "?"
128  + OUString::number( nFormulaIndex )
129  + " ";
130  }
131  }
132  else
133  {
134  // ups... we should have an index here and not the formula name
135  }
136  }
137  break;
138  case EnhancedCustomShapeParameterType::ADJUSTMENT :
139  {
140  if ( rParameter.Value.getValueTypeClass() == TypeClass_LONG )
141  {
142  sal_Int32 nAdjustmentIndex;
143  if ( rParameter.Value >>= nAdjustmentIndex )
144  {
145  aRet = "$"
146  + OUString::number( nAdjustmentIndex )
147  + " ";
148  }
149  }
150  else
151  {
152  // ups... we should have an index here and not the formula name
153  }
154  }
155  break;
156  case EnhancedCustomShapeParameterType::LEFT :
157  aRet = "left";
158  break;
159  case EnhancedCustomShapeParameterType::TOP :
160  aRet = "top";
161  break;
162  case EnhancedCustomShapeParameterType::RIGHT :
163  aRet = "right";
164  break;
165  case EnhancedCustomShapeParameterType::BOTTOM :
166  aRet = "bottom";
167  break;
168  case EnhancedCustomShapeParameterType::XSTRETCH :
169  aRet = "xstretch";
170  break;
171  case EnhancedCustomShapeParameterType::YSTRETCH :
172  aRet = "ystretch";
173  break;
174  case EnhancedCustomShapeParameterType::HASSTROKE :
175  aRet = "hasstroke";
176  break;
177  case EnhancedCustomShapeParameterType::HASFILL :
178  aRet = "hasfill";
179  break;
180  case EnhancedCustomShapeParameterType::WIDTH :
181  aRet = "width";
182  break;
183  case EnhancedCustomShapeParameterType::HEIGHT :
184  aRet = "height";
185  break;
186  case EnhancedCustomShapeParameterType::LOGWIDTH :
187  aRet = "logwidth";
188  break;
189  case EnhancedCustomShapeParameterType::LOGHEIGHT :
190  aRet = "logheight";
191  break;
192  }
193  return aRet;
194 }
195 
196 static EnhancedCustomShapeParameter GetAdjCoordinate( CustomShapeProperties& rCustomShapeProperties, const OUString& rValue, bool bNoSymbols = true )
197 {
198  css::drawing::EnhancedCustomShapeParameter aRet;
199  if ( !rValue.isEmpty() )
200  {
201  bool bConstant = true;
202  sal_Int32 nConstant = -1;
203  sal_Int32 nIntVal = 0;
204 
205  // first check if it's a constant value
206  switch( AttributeConversion::decodeToken( rValue ) )
207  {
208  case XML_3cd4 : nConstant = 270 * 60000; break;
209  case XML_3cd8 : nConstant = 135 * 60000; break;
210  case XML_5cd8 : nConstant = 225 * 60000; break;
211  case XML_7cd8 : nConstant = 315 * 60000; break;
212  case XML_cd2 : nConstant = 180 * 60000; break;
213  case XML_cd3 : nConstant = 120 * 60000; break;
214  case XML_cd4 : nConstant = 90 * 60000; break;
215  case XML_cd8 : nConstant = 45 * 60000; break;
216 
217  case XML_b : // variable height of the shape defined in spPr
218  case XML_h :
219  {
220  if ( bNoSymbols )
221  {
222  CustomShapeGuide aGuide;
223  aGuide.maName = rValue;
224  aGuide.maFormula = "logheight" ;
225 
226  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
227  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
228  }
229  else
230  aRet.Type = EnhancedCustomShapeParameterType::LOGHEIGHT; // TODO: HEIGHT needs to be implemented
231  }
232  break;
233 
234  case XML_hd10 :
235  nIntVal += 2; // */ h 1.0 10.0
236  [[fallthrough]];
237  case XML_hd8 : // */ h 1.0 8.0
238  nIntVal += 2;
239  [[fallthrough]];
240  case XML_hd6 : // */ h 1.0 6.0
241  nIntVal++;
242  [[fallthrough]];
243  case XML_hd5 : // */ h 1.0 5.0
244  nIntVal++;
245  [[fallthrough]];
246  case XML_hd4 : // */ h 1.0 4.0
247  nIntVal++;
248  [[fallthrough]];
249  case XML_hd3 : // */ h 1.0 3.0
250  nIntVal++;
251  [[fallthrough]];
252  case XML_hd2 : // */ h 1.0 2.0
253  case XML_vc : // */ h 1.0 2.0
254  {
255  nIntVal += 2;
256 
257  CustomShapeGuide aGuide;
258  aGuide.maName = rValue;
259  aGuide.maFormula = "logheight/" + OUString::number( nIntVal );
260 
261  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
262  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
263  }
264  break;
265 
266  case XML_t :
267  case XML_l :
268  {
269  nConstant = 0;
270  aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
271  }
272  break;
273 
274  case XML_ls : // longest side: max w h
275  {
276  CustomShapeGuide aGuide;
277  aGuide.maName = rValue;
278  aGuide.maFormula = "max(logwidth,logheight)";
279 
280  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
281  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
282  }
283  break;
284  case XML_ss : // shortest side: min w h
285  {
286  CustomShapeGuide aGuide;
287  aGuide.maName = rValue;
288  aGuide.maFormula = "min(logwidth,logheight)";
289 
290  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
291  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
292  }
293  break;
294  case XML_ssd32 : // */ ss 1.0 32.0
295  nIntVal += 16;
296  [[fallthrough]];
297  case XML_ssd16 : // */ ss 1.0 16.0
298  nIntVal += 8;
299  [[fallthrough]];
300  case XML_ssd8 : // */ ss 1.0 8.0
301  nIntVal += 2;
302  [[fallthrough]];
303  case XML_ssd6 : // */ ss 1.0 6.0
304  nIntVal += 2;
305  [[fallthrough]];
306  case XML_ssd4 : // */ ss 1.0 4.0
307  nIntVal += 2;
308  [[fallthrough]];
309  case XML_ssd2 : // */ ss 1.0 2.0
310  {
311  nIntVal += 2;
312 
313  CustomShapeGuide aGuide;
314  aGuide.maName = rValue;
315  aGuide.maFormula = "min(logwidth,logheight)/" + OUString::number( nIntVal );
316 
317  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
318  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
319  }
320  break;
321 
322  case XML_r : // variable width of the shape defined in spPr
323  case XML_w :
324  {
325  if ( bNoSymbols )
326  {
327  CustomShapeGuide aGuide;
328  aGuide.maName = rValue;
329  aGuide.maFormula = "logwidth" ;
330 
331  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
332  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
333  }
334  else
335  aRet.Type = EnhancedCustomShapeParameterType::LOGWIDTH;
336  }
337  break;
338 
339  case XML_wd32 : // */ w 1.0 32.0
340  nIntVal += 20;
341  [[fallthrough]];
342  case XML_wd12 : // */ w 1.0 12.0
343  nIntVal += 2;
344  [[fallthrough]];
345  case XML_wd10 : // */ w 1.0 10.0
346  nIntVal += 2;
347  [[fallthrough]];
348  case XML_wd8 : // */ w 1.0 8.0
349  nIntVal += 2;
350  [[fallthrough]];
351  case XML_wd6 : // */ w 1.0 6.0
352  nIntVal++;
353  [[fallthrough]];
354  case XML_wd5 : // */ w 1.0 5.0
355  nIntVal++;
356  [[fallthrough]];
357  case XML_wd4 : // */ w 1.0 4.0
358  nIntVal++;
359  [[fallthrough]];
360  case XML_wd3 : // */ w 1.0 3.0
361  nIntVal++;
362  [[fallthrough]];
363  case XML_hc : // */ w 1.0 2.0
364  case XML_wd2 : // */ w 1.0 2.0
365  {
366  nIntVal += 2;
367 
368  CustomShapeGuide aGuide;
369  aGuide.maName = rValue;
370  aGuide.maFormula = "logwidth/" + OUString::number( nIntVal );
371 
372  aRet.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide );
373  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
374  }
375  break;
376 
377  default:
378  bConstant = false;
379  break;
380  }
381  if ( bConstant )
382  {
383  if (nConstant != -1) {
384  aRet.Value <<= nConstant;
385  aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
386  }
387  }
388  else
389  {
390  sal_Unicode n = rValue[ 0 ];
391  if ( ( n == '+' ) || ( n == '-' ) )
392  {
393  if ( rValue.getLength() > 1 )
394  n = rValue[ 1 ];
395  }
396  if ( ( n >= '0' ) && ( n <= '9' ) )
397  { // seems to be a ST_Coordinate
398  aRet.Value <<= rValue.toInt32();
399  aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
400  }
401  else
402  {
403  sal_Int32 nGuideIndex = CustomShapeProperties::GetCustomShapeGuideValue( rCustomShapeProperties.getAdjustmentGuideList(), rValue );
404  if ( nGuideIndex >= 0 )
405  {
406  aRet.Value <<= nGuideIndex;
407  aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
408  }
409  else
410  {
411  nGuideIndex = CustomShapeProperties::GetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), rValue );
412  if ( nGuideIndex >= 0 )
413  {
414  aRet.Value <<= nGuideIndex;
415  aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
416  }
417  else
418  {
419  SAL_WARN("oox", "error: unhandled value " << rValue);
420  aRet.Value <<= rValue;
421  }
422  }
423  }
424  }
425  }
426  return aRet;
427 }
428 
429 namespace {
430 
431 // CT_GeomGuideList
432 class GeomGuideListContext : public ContextHandler2
433 {
434 public:
435  GeomGuideListContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< CustomShapeGuide >& rGuideList );
436  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
437 
438 protected:
439  std::vector< CustomShapeGuide >& mrGuideList;
440  CustomShapeProperties& mrCustomShapeProperties;
441 };
442 
443 }
444 
445 GeomGuideListContext::GeomGuideListContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< CustomShapeGuide >& rGuideList )
446 : ContextHandler2( rParent )
447 , mrGuideList( rGuideList )
448 , mrCustomShapeProperties( rCustomShapeProperties )
449 {
450 }
451 
452 static OUString convertToOOEquation( CustomShapeProperties& rCustomShapeProperties, const OUString& rSource )
453 {
454  if ( !pCommandHashMap )
455  {
456  FormulaCommandHMap* pHM = new FormulaCommandHMap;
457  for(const FormulaCommandNameTable& i : pFormulaCommandNameTable)
458  (*pHM)[ OUString::createFromAscii( i.pS ) ] = i.pE;
459  pCommandHashMap = pHM;
460  }
461 
462  std::vector< OUString > aTokens;
463  sal_Int32 nIndex = 0;
464  do
465  {
466  OUString aToken( rSource.getToken( 0, ' ', nIndex ) );
467  if ( !aToken.isEmpty() )
468  aTokens.push_back( aToken );
469  }
470  while ( nIndex >= 0 );
471 
472  OUString aEquation;
473  if ( !aTokens.empty() )
474  {
475  sal_Int32 i, nParameters = aTokens.size() - 1;
476  if ( nParameters > 3 )
477  nParameters = 3;
478 
479  OUString sParameters[ 3 ];
480 
481  for ( i = 0; i < nParameters; i++ )
482  sParameters[ i ] = GetFormulaParameter( GetAdjCoordinate( rCustomShapeProperties, aTokens[ i + 1 ], false ) );
483 
484  const FormulaCommandHMap::const_iterator aIter( pCommandHashMap->find( aTokens[ 0 ] ) );
485  if ( aIter != pCommandHashMap->end() )
486  {
487  switch( aIter->second )
488  {
489  case FC_MULDIV :
490  {
491  if ( nParameters == 3 )
492  aEquation = sParameters[ 0 ] + "*" + sParameters[ 1 ]
493  + "/" + sParameters[ 2 ];
494  }
495  break;
496  case FC_PLUSMINUS :
497  {
498  if ( nParameters == 3 )
499  aEquation = sParameters[ 0 ] + "+" + sParameters[ 1 ]
500  + "-" + sParameters[ 2 ];
501  }
502  break;
503  case FC_PLUSDIV :
504  {
505  if ( nParameters == 3 )
506  aEquation = "(" + sParameters[ 0 ] + "+"
507  + sParameters[ 1 ] + ")/" + sParameters[ 2 ];
508  }
509  break;
510  case FC_IFELSE :
511  case FC_IFELSE1 :
512  {
513  if ( nParameters == 3 )
514  aEquation = "if(" + sParameters[ 0 ] + ","
515  + sParameters[ 1 ] + "," + sParameters[ 2 ] + ")";
516  }
517  break;
518  case FC_ABS :
519  {
520  if ( nParameters == 1 )
521  aEquation = "abs(" + sParameters[ 0 ] + ")";
522  }
523  break;
524  case FC_AT2 :
525  {
526  if ( nParameters == 2 )
527  aEquation = "(10800000*atan2(" + sParameters[ 1 ] + ","
528  + sParameters[ 0 ] + "))/pi";
529  }
530  break;
531  case FC_CAT2 :
532  {
533  if ( nParameters == 3 )
534  aEquation = sParameters[ 0 ] + "*(cos(atan2(" +
535  sParameters[ 2 ] + "," + sParameters[ 1 ] + ")))";
536  }
537  break;
538  case FC_COS :
539  {
540  if ( nParameters == 2 )
541  aEquation = sParameters[ 0 ] + "*cos(pi*(" +
542  sParameters[ 1 ] + ")/10800000)";
543  }
544  break;
545  case FC_MAX :
546  {
547  if ( nParameters == 2 )
548  aEquation = "max(" + sParameters[ 0 ] + "," +
549  sParameters[ 1 ] + ")";
550  }
551  break;
552  case FC_MIN :
553  {
554  if ( nParameters == 2 )
555  aEquation = "min(" + sParameters[ 0 ] + "," +
556  sParameters[ 1 ] + ")";
557  }
558  break;
559  case FC_MOD :
560  {
561  if ( nParameters == 3 )
562  aEquation = "sqrt("
563  + sParameters[ 0 ] + "*" + sParameters[ 0 ] + "+"
564  + sParameters[ 1 ] + "*" + sParameters[ 1 ] + "+"
565  + sParameters[ 2 ] + "*" + sParameters[ 2 ] + ")";
566  }
567  break;
568  case FC_PIN :
569  {
570  if ( nParameters == 3 ) // if(x-y,x,if(y-z,z,y))
571  aEquation = "if(" + sParameters[ 0 ] + "-" + sParameters[ 1 ]
572  + "," + sParameters[ 0 ] + ",if(" + sParameters[ 2 ]
573  + "-" + sParameters[ 1 ] + "," + sParameters[ 1 ]
574  + "," + sParameters[ 2 ] + "))";
575  }
576  break;
577  case FC_SAT2 :
578  {
579  if ( nParameters == 3 )
580  aEquation = sParameters[ 0 ] + "*(sin(atan2(" +
581  sParameters[ 2 ] + "," + sParameters[ 1 ] + ")))";
582  }
583  break;
584  case FC_SIN :
585  {
586  if ( nParameters == 2 )
587  aEquation = sParameters[ 0 ] + "*sin(pi*(" +
588  sParameters[ 1 ] + ")/10800000)";
589  }
590  break;
591  case FC_SQRT :
592  {
593  if ( nParameters == 1 )
594  aEquation = "sqrt(" + sParameters[ 0 ] + ")";
595  }
596  break;
597  case FC_TAN :
598  {
599  if ( nParameters == 2 )
600  aEquation = sParameters[ 0 ] + "*tan(pi*(" +
601  sParameters[ 1 ] + ")/10800000)";
602  }
603  break;
604  case FC_VAL :
605  {
606  if ( nParameters == 1 )
607  aEquation = sParameters[ 0 ];
608  }
609  break;
610  default :
611  break;
612  }
613  }
614  }
615  return aEquation;
616 }
617 
618 ContextHandlerRef GeomGuideListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
619 {
620  if ( aElementToken == A_TOKEN( gd ) ) // CT_GeomGuide
621  {
622  CustomShapeGuide aGuide;
623  aGuide.maName = rAttribs.getString( XML_name ).get();
624  aGuide.maFormula = convertToOOEquation( mrCustomShapeProperties, rAttribs.getString( XML_fmla ).get() );
625  mrGuideList.push_back( aGuide );
626  }
627  return this;
628 }
629 
630 static const OUString& GetGeomGuideName( const OUString& rValue )
631 {
632  return rValue;
633 }
634 
635 namespace {
636 
637 // CT_AdjPoint2D
638 class AdjPoint2DContext : public ContextHandler2
639 {
640 public:
641  AdjPoint2DContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D );
642 };
643 
644 }
645 
646 AdjPoint2DContext::AdjPoint2DContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D )
647 : ContextHandler2( rParent )
648 {
649  rAdjPoint2D.First = GetAdjCoordinate( rCustomShapeProperties, rAttribs.getString( XML_x ).get() );
650  rAdjPoint2D.Second = GetAdjCoordinate( rCustomShapeProperties, rAttribs.getString( XML_y ).get() );
651 }
652 
653 namespace {
654 
655 // CT_XYAdjustHandle
656 class XYAdjustHandleContext : public ContextHandler2
657 {
658 public:
659  XYAdjustHandleContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle );
660  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
661 
662 protected:
663  AdjustHandle& mrAdjustHandle;
664  CustomShapeProperties& mrCustomShapeProperties;
665 };
666 
667 }
668 
669 XYAdjustHandleContext::XYAdjustHandleContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle )
670 : ContextHandler2( rParent )
671 , mrAdjustHandle( rAdjustHandle )
672 , mrCustomShapeProperties( rCustomShapeProperties )
673 {
674  if ( rAttribs.hasAttribute( XML_gdRefX ) )
675  {
676  mrAdjustHandle.gdRef1 = GetGeomGuideName( rAttribs.getString( XML_gdRefX, "" ) );
677  }
678  if ( rAttribs.hasAttribute( XML_minX ) )
679  {
680  mrAdjustHandle.min1 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_minX, "" ) );
681  }
682  if ( rAttribs.hasAttribute( XML_maxX ) )
683  {
684  mrAdjustHandle.max1 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_maxX, "" ) );
685  }
686  if ( rAttribs.hasAttribute( XML_gdRefY ) )
687  {
688  mrAdjustHandle.gdRef2 = GetGeomGuideName( rAttribs.getString( XML_gdRefY, "" ) );
689  }
690  if ( rAttribs.hasAttribute( XML_minY ) )
691  {
692  mrAdjustHandle.min2 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_minY, "" ) );
693  }
694  if ( rAttribs.hasAttribute( XML_maxY ) )
695  {
696  mrAdjustHandle.max2 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_maxY, "" ) );
697  }
698 }
699 
700 ContextHandlerRef XYAdjustHandleContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
701 {
702  if ( aElementToken == A_TOKEN( pos ) )
703  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, mrAdjustHandle.pos ); // CT_AdjPoint2D
704  return nullptr;
705 }
706 
707 namespace {
708 
709 // CT_PolarAdjustHandle
710 class PolarAdjustHandleContext : public ContextHandler2
711 {
712 public:
713  PolarAdjustHandleContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle );
714  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
715 
716 protected:
717  AdjustHandle& mrAdjustHandle;
718  CustomShapeProperties& mrCustomShapeProperties;
719 };
720 
721 }
722 
723 PolarAdjustHandleContext::PolarAdjustHandleContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle )
724 : ContextHandler2( rParent )
725 , mrAdjustHandle( rAdjustHandle )
726 , mrCustomShapeProperties( rCustomShapeProperties )
727 {
728  if ( rAttribs.hasAttribute( XML_gdRefR ) )
729  {
730  mrAdjustHandle.polar = true ;
731  mrAdjustHandle.gdRef1 = GetGeomGuideName( rAttribs.getString( XML_gdRefR, "" ) );
732  }
733  if ( rAttribs.hasAttribute( XML_minR ) )
734  {
735  mrAdjustHandle.min1 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_minR, "" ) );
736  }
737  if ( rAttribs.hasAttribute( XML_maxR ) )
738  {
739  mrAdjustHandle.max1 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_maxR, "" ) );
740  }
741  if ( rAttribs.hasAttribute( XML_gdRefAng ) )
742  {
743  mrAdjustHandle.polar = true ;
744  mrAdjustHandle.gdRef2 = GetGeomGuideName( rAttribs.getString( XML_gdRefAng, "" ) );
745  }
746  if ( rAttribs.hasAttribute( XML_minAng ) )
747  {
748  mrAdjustHandle.min2 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_minAng, "" ) );
749  }
750  if ( rAttribs.hasAttribute( XML_maxAng ) )
751  {
752  mrAdjustHandle.max2 = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_maxAng, "" ) );
753  }
754 }
755 
756 ContextHandlerRef PolarAdjustHandleContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
757 {
758  // mrAdjustHandle.pos uses planar coordinates.
759  if ( aElementToken == A_TOKEN( pos ) )
760  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, mrAdjustHandle.pos ); // CT_AdjPoint2D
761  return nullptr;
762 }
763 
764 namespace {
765 
766 // CT_AdjustHandleList
767 class AdjustHandleListContext : public ContextHandler2
768 {
769 public:
770  AdjustHandleListContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< AdjustHandle >& rAdjustHandleList );
771  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
772 
773 protected:
774  std::vector< AdjustHandle >& mrAdjustHandleList;
775  CustomShapeProperties& mrCustomShapeProperties;
776 };
777 
778 }
779 
780 AdjustHandleListContext::AdjustHandleListContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< AdjustHandle >& rAdjustHandleList )
781 : ContextHandler2( rParent )
782 , mrAdjustHandleList( rAdjustHandleList )
783 , mrCustomShapeProperties( rCustomShapeProperties )
784 {
785 }
786 
787 ContextHandlerRef AdjustHandleListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
788 {
789  if ( aElementToken == A_TOKEN( ahXY ) ) // CT_XYAdjustHandle
790  {
791  AdjustHandle aAdjustHandle( false );
792  mrAdjustHandleList.push_back( aAdjustHandle );
793  return new XYAdjustHandleContext( *this, rAttribs, mrCustomShapeProperties, mrAdjustHandleList.back() );
794  }
795  else if ( aElementToken == A_TOKEN( ahPolar ) ) // CT_PolarAdjustHandle
796  {
797  AdjustHandle aAdjustHandle( true );
798  mrAdjustHandleList.push_back( aAdjustHandle );
799  return new PolarAdjustHandleContext( *this, rAttribs, mrCustomShapeProperties, mrAdjustHandleList.back() );
800  }
801  return nullptr;
802 }
803 
804 namespace {
805 
806 // CT_ConnectionSite
807 class ConnectionSiteContext : public ContextHandler2
808 {
809 public:
810  ConnectionSiteContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, ConnectionSite& rConnectionSite );
811  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
812 
813 protected:
814  ConnectionSite& mrConnectionSite;
815  CustomShapeProperties& mrCustomShapeProperties;
816 };
817 
818 }
819 
820 ConnectionSiteContext::ConnectionSiteContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, ConnectionSite& rConnectionSite )
821 : ContextHandler2( rParent )
822 , mrConnectionSite( rConnectionSite )
823 , mrCustomShapeProperties( rCustomShapeProperties )
824 {
825  mrConnectionSite.ang = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_ang ).get() );
826 }
827 
828 ContextHandlerRef ConnectionSiteContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
829 {
830  if ( aElementToken == A_TOKEN( pos ) )
831  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, mrConnectionSite.pos ); // CT_AdjPoint2D
832  return nullptr;
833 }
834 
835 namespace {
836 
837 // CT_Path2DMoveTo
838 class Path2DMoveToContext : public ContextHandler2
839 {
840 public:
841  Path2DMoveToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D );
842  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
843 
844 protected:
845  EnhancedCustomShapeParameterPair& mrAdjPoint2D;
846  CustomShapeProperties& mrCustomShapeProperties;
847 };
848 
849 }
850 
851 Path2DMoveToContext::Path2DMoveToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D )
852 : ContextHandler2( rParent )
853 , mrAdjPoint2D( rAdjPoint2D )
854 , mrCustomShapeProperties( rCustomShapeProperties )
855 {
856 }
857 
858 ContextHandlerRef Path2DMoveToContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
859 {
860  if ( aElementToken == A_TOKEN( pt ) )
861  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, mrAdjPoint2D ); // CT_AdjPoint2D
862  return nullptr;
863 }
864 
865 namespace {
866 
867 // CT_Path2DLineTo
868 class Path2DLineToContext : public ContextHandler2
869 {
870 public:
871  Path2DLineToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D );
872  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
873 
874 protected:
875  EnhancedCustomShapeParameterPair& mrAdjPoint2D;
876  CustomShapeProperties& mrCustomShapeProperties;
877 };
878 
879 }
880 
881 Path2DLineToContext::Path2DLineToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D )
882 : ContextHandler2( rParent )
883 , mrAdjPoint2D( rAdjPoint2D )
884 , mrCustomShapeProperties( rCustomShapeProperties )
885 {
886 }
887 
888 ContextHandlerRef Path2DLineToContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
889 {
890  if ( aElementToken == A_TOKEN( pt ) )
891  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, mrAdjPoint2D ); // CT_AdjPoint2D
892  return nullptr;
893 }
894 
895 namespace {
896 
897 // CT_Path2DQuadBezierTo
898 class Path2DQuadBezierToContext : public ContextHandler2
899 {
900 public:
901  Path2DQuadBezierToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rPt1, EnhancedCustomShapeParameterPair& rPt2 );
902  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
903 
904 protected:
905  EnhancedCustomShapeParameterPair& mrPt1;
906  EnhancedCustomShapeParameterPair& mrPt2;
907  int nCount;
908  CustomShapeProperties& mrCustomShapeProperties;
909 };
910 
911 }
912 
913 Path2DQuadBezierToContext::Path2DQuadBezierToContext( ContextHandler2Helper const & rParent,
914  CustomShapeProperties& rCustomShapeProperties,
915  EnhancedCustomShapeParameterPair& rPt1,
916  EnhancedCustomShapeParameterPair& rPt2 )
917 : ContextHandler2( rParent )
918 , mrPt1( rPt1 )
919 , mrPt2( rPt2 )
920 , nCount( 0 )
921 , mrCustomShapeProperties( rCustomShapeProperties )
922 {
923 }
924 
925 ContextHandlerRef Path2DQuadBezierToContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
926 {
927  if ( aElementToken == A_TOKEN( pt ) )
928  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties, nCount++ ? mrPt2 : mrPt1 ); // CT_AdjPoint2D
929  return nullptr;
930 }
931 
932 namespace {
933 
934 // CT_Path2DCubicBezierTo
935 class Path2DCubicBezierToContext : public ContextHandler2
936 {
937 public:
938  Path2DCubicBezierToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties,
939  EnhancedCustomShapeParameterPair&, EnhancedCustomShapeParameterPair&, EnhancedCustomShapeParameterPair& );
940  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
941 
942 protected:
943  CustomShapeProperties& mrCustomShapeProperties;
944  EnhancedCustomShapeParameterPair& mrControlPt1;
945  EnhancedCustomShapeParameterPair& mrControlPt2;
946  EnhancedCustomShapeParameterPair& mrEndPt;
947  int nCount;
948 };
949 
950 }
951 
952 Path2DCubicBezierToContext::Path2DCubicBezierToContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties,
953  EnhancedCustomShapeParameterPair& rControlPt1,
954  EnhancedCustomShapeParameterPair& rControlPt2,
955  EnhancedCustomShapeParameterPair& rEndPt )
956 : ContextHandler2( rParent )
957 , mrCustomShapeProperties( rCustomShapeProperties )
958 , mrControlPt1( rControlPt1 )
959 , mrControlPt2( rControlPt2 )
960 , mrEndPt( rEndPt )
961 , nCount( 0 )
962 {
963 }
964 
965 ContextHandlerRef Path2DCubicBezierToContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
966 {
967  if ( aElementToken == A_TOKEN( pt ) )
968  return new AdjPoint2DContext( *this, rAttribs, mrCustomShapeProperties,
969  nCount++ ? nCount == 2 ? mrControlPt2 : mrEndPt : mrControlPt1 ); // CT_AdjPoint2D
970  return nullptr;
971 }
972 
973 namespace {
974 
975 // CT_Path2DContext
976 class Path2DContext : public ContextHandler2
977 {
978 public:
979  Path2DContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, std::vector< css::drawing::EnhancedCustomShapeSegment >& rSegments, Path2D& rPath2D );
980  virtual void onEndElement() override;
982  onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
983 
984 protected:
985  Path2D& mrPath2D;
986  std::vector< css::drawing::EnhancedCustomShapeSegment >& mrSegments;
987  CustomShapeProperties& mrCustomShapeProperties;
988 };
989 
990 }
991 
992 Path2DContext::Path2DContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, CustomShapeProperties& rCustomShapeProperties, std::vector< css::drawing::EnhancedCustomShapeSegment >& rSegments, Path2D& rPath2D )
993 : ContextHandler2( rParent )
994 , mrPath2D( rPath2D )
995 , mrSegments( rSegments )
996 , mrCustomShapeProperties( rCustomShapeProperties )
997 {
998  rPath2D.w = rAttribs.getString( XML_w, "" ).toInt64();
999  rPath2D.h = rAttribs.getString( XML_h, "" ).toInt64();
1000  rPath2D.fill = rAttribs.getToken( XML_fill, XML_norm );
1001  rPath2D.stroke = rAttribs.getBool( XML_stroke, true );
1002  rPath2D.extrusionOk = rAttribs.getBool( XML_extrusionOk, true );
1003 }
1004 
1005 void Path2DContext::onEndElement()
1006 {
1007  EnhancedCustomShapeSegment aNewSegment;
1008  switch ( mrPath2D.fill )
1009  {
1010  case XML_none:
1011  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
1012  break;
1013  case XML_darken:
1014  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::DARKEN;
1015  break;
1016  case XML_darkenLess:
1017  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::DARKENLESS;
1018  break;
1019  case XML_lighten:
1020  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::LIGHTEN;
1021  break;
1022  case XML_lightenLess:
1023  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::LIGHTENLESS;
1024  break;
1025  }
1026  if (mrPath2D.fill != XML_norm) {
1027  aNewSegment.Count = 0;
1028  mrSegments.push_back( aNewSegment );
1029  }
1030  if ( !mrPath2D.stroke )
1031  {
1032  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
1033  aNewSegment.Count = 0;
1034  mrSegments.push_back( aNewSegment );
1035  }
1036  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
1037  aNewSegment.Count = 0;
1038  mrSegments.push_back( aNewSegment );
1039 }
1040 
1041 
1042 ContextHandlerRef Path2DContext::onCreateContext( sal_Int32 aElementToken,
1043  const AttributeList& rAttribs )
1044 {
1045  switch( aElementToken )
1046  {
1047  case A_TOKEN( close ) :
1048  {
1049  // ignore close after move to (ppt does seems to do the same, see accentCallout2 preset for example)
1050  if ( mrSegments.empty() || ( mrSegments.back().Command != EnhancedCustomShapeSegmentCommand::MOVETO ) ) {
1051  EnhancedCustomShapeSegment aNewSegment;
1052  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
1053  aNewSegment.Count = 0;
1054  mrSegments.push_back( aNewSegment );
1055  }
1056  }
1057  break;
1058  case A_TOKEN( moveTo ) :
1059  {
1060  EnhancedCustomShapeSegment aNewSegment;
1061  aNewSegment.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
1062  aNewSegment.Count = 1;
1063  mrSegments.push_back( aNewSegment );
1064 
1065  EnhancedCustomShapeParameterPair aAdjPoint2D;
1066  mrPath2D.parameter.push_back( aAdjPoint2D );
1067  return new Path2DMoveToContext( *this, mrCustomShapeProperties, mrPath2D.parameter.back() );
1068  }
1069  break;
1070  case A_TOKEN( lnTo ) :
1071  {
1072  if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::LINETO ) )
1073  mrSegments.back().Count++;
1074  else
1075  {
1076  EnhancedCustomShapeSegment aSegment;
1077  aSegment.Command = EnhancedCustomShapeSegmentCommand::LINETO;
1078  aSegment.Count = 1;
1079  mrSegments.push_back( aSegment );
1080  }
1081  EnhancedCustomShapeParameterPair aAdjPoint2D;
1082  mrPath2D.parameter.push_back( aAdjPoint2D );
1083  return new Path2DLineToContext( *this, mrCustomShapeProperties, mrPath2D.parameter.back() );
1084  }
1085  break;
1086  case A_TOKEN( arcTo ) : // CT_Path2DArcTo
1087  {
1088  if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::ARCANGLETO ) )
1089  mrSegments.back().Count++;
1090  else
1091  {
1092  EnhancedCustomShapeSegment aSegment;
1093  aSegment.Command = EnhancedCustomShapeSegmentCommand::ARCANGLETO;
1094  aSegment.Count = 1;
1095  mrSegments.push_back( aSegment );
1096  }
1097 
1098  EnhancedCustomShapeParameterPair aScale;
1099  EnhancedCustomShapeParameterPair aAngles;
1100 
1101  aScale.First = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_wR ).get() );
1102  aScale.Second = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_hR ).get() );
1103 
1104  CustomShapeGuide aGuide;
1105  sal_Int32 nArcNum = mrCustomShapeProperties.getArcNum();
1106 
1107  // start angle
1108  aGuide.maName = "arctosa" + OUString::number( nArcNum );
1109  aGuide.maFormula = "("
1110  + GetFormulaParameter( GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_stAng ).get() ) )
1111  + ")/60000.0";
1112  aAngles.First.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( mrCustomShapeProperties.getGuideList(), aGuide );
1113  aAngles.First.Type = EnhancedCustomShapeParameterType::EQUATION;
1114 
1115  // swing angle
1116  aGuide.maName = "arctosw" + OUString::number( nArcNum );
1117  aGuide.maFormula = "("
1118  + GetFormulaParameter( GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_swAng ).get() ) )
1119  + ")/60000.0";
1120  aAngles.Second.Value <<= CustomShapeProperties::SetCustomShapeGuideValue( mrCustomShapeProperties.getGuideList(), aGuide );
1121  aAngles.Second.Type = EnhancedCustomShapeParameterType::EQUATION;
1122 
1123  mrPath2D.parameter.push_back( aScale );
1124  mrPath2D.parameter.push_back( aAngles );
1125  }
1126  break;
1127  case A_TOKEN( quadBezTo ) :
1128  {
1129  if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO ) )
1130  mrSegments.back().Count++;
1131  else
1132  {
1133  EnhancedCustomShapeSegment aSegment;
1134  aSegment.Command = EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO;
1135  aSegment.Count = 1;
1136  mrSegments.push_back( aSegment );
1137  }
1138  EnhancedCustomShapeParameterPair aPt1;
1139  EnhancedCustomShapeParameterPair aPt2;
1140  mrPath2D.parameter.push_back( aPt1 );
1141  mrPath2D.parameter.push_back( aPt2 );
1142  return new Path2DQuadBezierToContext( *this, mrCustomShapeProperties,
1143  mrPath2D.parameter[ mrPath2D.parameter.size() - 2 ],
1144  mrPath2D.parameter.back() );
1145  }
1146  break;
1147  case A_TOKEN( cubicBezTo ) :
1148  {
1149  if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::CURVETO ) )
1150  mrSegments.back().Count++;
1151  else
1152  {
1153  EnhancedCustomShapeSegment aSegment;
1154  aSegment.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
1155  aSegment.Count = 1;
1156  mrSegments.push_back( aSegment );
1157  }
1158  EnhancedCustomShapeParameterPair aControlPt1;
1159  EnhancedCustomShapeParameterPair aControlPt2;
1160  EnhancedCustomShapeParameterPair aEndPt;
1161  mrPath2D.parameter.push_back( aControlPt1 );
1162  mrPath2D.parameter.push_back( aControlPt2 );
1163  mrPath2D.parameter.push_back( aEndPt );
1164  return new Path2DCubicBezierToContext( *this, mrCustomShapeProperties,
1165  mrPath2D.parameter[ mrPath2D.parameter.size() - 3 ],
1166  mrPath2D.parameter[ mrPath2D.parameter.size() - 2 ],
1167  mrPath2D.parameter.back() );
1168  }
1169  break;
1170  }
1171  return nullptr;
1172 }
1173 
1174 namespace {
1175 
1176 // CT_Path2DList
1177 class Path2DListContext : public ContextHandler2
1178 {
1179 public:
1180  Path2DListContext( ContextHandler2Helper const & rParent, CustomShapeProperties & rCustomShapeProperties, std::vector< EnhancedCustomShapeSegment >& rSegments,
1181  std::vector< Path2D >& rPath2DList );
1182 
1183  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const ::oox::AttributeList& rAttribs ) override;
1184 
1185 protected:
1186 
1187  CustomShapeProperties& mrCustomShapeProperties;
1188  std::vector< css::drawing::EnhancedCustomShapeSegment >& mrSegments;
1189  std::vector< Path2D >& mrPath2DList;
1190 };
1191 
1192 }
1193 
1194 Path2DListContext:: Path2DListContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< EnhancedCustomShapeSegment >& rSegments,
1195  std::vector< Path2D >& rPath2DList )
1196 : ContextHandler2( rParent )
1197 , mrCustomShapeProperties( rCustomShapeProperties )
1198 , mrSegments( rSegments )
1199 , mrPath2DList( rPath2DList )
1200 {
1201 }
1202 
1203 ContextHandlerRef Path2DListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
1204 {
1205  if ( aElementToken == A_TOKEN( path ) )
1206  {
1207  Path2D aPath2D;
1208  mrPath2DList.push_back( aPath2D );
1209  return new Path2DContext( *this, rAttribs, mrCustomShapeProperties, mrSegments, mrPath2DList.back() );
1210  }
1211  return nullptr;
1212 }
1213 
1214 // CT_CustomGeometry2D
1215 CustomShapeGeometryContext::CustomShapeGeometryContext( ContextHandler2Helper const & rParent, CustomShapeProperties& rCustomShapeProperties )
1216 : ContextHandler2( rParent )
1217 , mrCustomShapeProperties( rCustomShapeProperties )
1218 {
1219 }
1220 
1222 {
1223  switch( aElementToken )
1224  {
1225  case A_TOKEN( avLst ): // CT_GeomGuideList adjust value list
1226  return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() );
1227  case A_TOKEN( gdLst ): // CT_GeomGuideList guide list
1228  return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getGuideList() );
1229  case A_TOKEN( ahLst ): // CT_AdjustHandleList adjust handle list
1230  return new AdjustHandleListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustHandleList() );
1231  case A_TOKEN( cxnLst ): // CT_ConnectionSiteList connection site list
1232  return this;
1233  case A_TOKEN( rect ): // CT_GeomRectList geometry rect list
1234  {
1235  GeomRect aGeomRect;
1236  aGeomRect.l = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_l ).get() );
1237  aGeomRect.t = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_t ).get() );
1238  aGeomRect.r = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_r ).get() );
1239  aGeomRect.b = GetAdjCoordinate( mrCustomShapeProperties, rAttribs.getString( XML_b ).get() );
1240  mrCustomShapeProperties.getTextRect() = aGeomRect;
1241  }
1242  break;
1243  case A_TOKEN( pathLst ): // CT_Path2DList 2d path list
1245 
1246  // from cxnLst:
1247  case A_TOKEN( cxn ): // CT_ConnectionSite
1248  {
1249  ConnectionSite aConnectionSite;
1250  mrCustomShapeProperties.getConnectionSiteList().push_back( aConnectionSite );
1251  return new ConnectionSiteContext( *this, rAttribs, mrCustomShapeProperties, mrCustomShapeProperties.getConnectionSiteList().back() );
1252  }
1253  }
1254  return nullptr;
1255 }
1256 
1257 // CT_PresetGeometry2D
1259 : ContextHandler2( rParent )
1260 , mrCustomShapeProperties( rCustomShapeProperties )
1261 {
1262  sal_Int32 nShapeType = rAttribs.getToken( XML_prst, FastToken::DONTKNOW );
1263  OSL_ENSURE( nShapeType != FastToken::DONTKNOW, "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" );
1265 }
1266 
1268 {
1269  if ( aElementToken == A_TOKEN( avLst ) )
1270  return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() );
1271  else
1272  return this;
1273 }
1274 
1275 // CT_PresetTextShape
1277 : ContextHandler2( rParent )
1278 , mrCustomShapeProperties( rCustomShapeProperties )
1279 {
1280  sal_Int32 nShapeType = rAttribs.getToken( XML_prst, FastToken::DONTKNOW );
1281  OSL_ENSURE( nShapeType != FastToken::DONTKNOW, "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" );
1283 }
1284 
1286 {
1287  if ( aElementToken == A_TOKEN( avLst ) )
1288  return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() );
1289  else
1290  return this;
1291 }
1292 
1293 }
1294 
1295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< AdjustHandle > & getAdjustHandleList()
EnhancedCustomShapeParameterPair & mrPt2
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 aElementToken, const ::oox::AttributeList &rAttribs) override
EnhancedCustomShapeParameterPair & mrAdjPoint2D
sal_Int32 nIndex
css::drawing::EnhancedCustomShapeParameter b
FormulaCommand pE
static sal_Int32 GetCustomShapeGuideValue(const std::vector< CustomShapeGuide > &rGuideList, std::u16string_view rFormulaName)
sal_Int64 n
std::vector< CustomShapeGuide > & getGuideList()
OptValue< OUString > getString(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute.
static const FormulaCommandHMap * pCommandHashMap
void setShapePresetType(sal_Int32 nShapePresetType)
static EnhancedCustomShapeParameter GetAdjCoordinate(CustomShapeProperties &rCustomShapeProperties, const OUString &rValue, bool bNoSymbols=true)
sal_uInt16 sal_Unicode
EnhancedCustomShapeParameterPair & mrEndPt
int nCount
const Type & get() const
Definition: helper.hxx:185
std::vector< ConnectionSite > & getConnectionSiteList()
static sal_Int32 decodeToken(std::u16string_view rValue)
Returns the XML token identifier from the passed string.
EnhancedCustomShapeParameterPair & mrControlPt2
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 aElementToken, const ::oox::AttributeList &rAttribs) override
std::vector< css::drawing::EnhancedCustomShapeSegment > & mrSegments
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 aElementToken, const ::oox::AttributeList &rAttribs) override
std::unordered_map< OUString, FormulaCommand > FormulaCommandHMap
EnhancedCustomShapeParameterPair & mrControlPt1
AdjustHandle & mrAdjustHandle
Provides access to attribute values of an element.
const char * pS
css::drawing::EnhancedCustomShapeParameter t
std::vector< AdjustHandle > & mrAdjustHandleList
std::vector< CustomShapeGuide > & getAdjustmentGuideList()
css::drawing::EnhancedCustomShapeParameter r
static const OUString & GetGeomGuideName(const OUString &rValue)
static OUString convertToOOEquation(CustomShapeProperties &rCustomShapeProperties, const OUString &rSource)
const FormulaCommandNameTable pFormulaCommandNameTable[]
::rtl::Reference< ContextHandler > ContextHandlerRef
EnhancedCustomShapeParameterPair & mrPt1
PresetTextShapeContext(::oox::core::ContextHandler2Helper const &rParent, const ::oox::AttributeList &rAttributes, CustomShapeProperties &rCustomShapeProperties)
static sal_Int32 SetCustomShapeGuideValue(std::vector< CustomShapeGuide > &rGuideList, const CustomShapeGuide &rGuide)
PresetShapeGeometryContext(::oox::core::ContextHandler2Helper const &rParent, const ::oox::AttributeList &rAttributes, CustomShapeProperties &rCustomShapeProperties)
#define SAL_WARN(area, stream)
std::vector< Path2D > & mrPath2DList
std::vector< css::drawing::EnhancedCustomShapeSegment > & getSegments()
Path2D & mrPath2D
Helper class that provides a context stack.
ConnectionSite & mrConnectionSite
static OUString GetFormulaParameter(const EnhancedCustomShapeParameter &rParameter)
CustomShapeProperties & mrCustomShapeProperties
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
Returns the token identifier of the value of the specified attribute.
css::drawing::EnhancedCustomShapeParameter l
sal_Int16 nValue
std::vector< CustomShapeGuide > & mrGuideList