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