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