1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <drawingml/customshapegeometry.hxx>
21 #include <drawingml/customshapeproperties.hxx>
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>
30 #include <oox/helper/attributelist.hxx>
31 #include <oox/token/namespaces.hxx>
32 #include <oox/token/tokens.hxx>
33 #include <unordered_map>
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
;
40 namespace oox::drawingml
{
66 struct FormulaCommandNameTable
74 const FormulaCommandNameTable pFormulaCommandNameTable
[] =
77 { "+-", FC_PLUSMINUS
},
79 { "ifelse", FC_IFELSE
},
96 typedef std::unordered_map
< OUString
, FormulaCommand
> FormulaCommandHMap
;
98 static const FormulaCommandHMap
* pCommandHashMap
;
100 static OUString
GetFormulaParameter( const EnhancedCustomShapeParameter
& rParameter
)
103 switch( rParameter
.Type
)
105 case EnhancedCustomShapeParameterType::NORMAL
:
107 if ( rParameter
.Value
.getValueTypeClass() == TypeClass_DOUBLE
)
110 if ( rParameter
.Value
>>= fValue
)
111 aRet
= OUString::number( fValue
);
115 sal_Int32 nValue
= 0;
116 if ( rParameter
.Value
>>= nValue
)
117 aRet
= OUString::number( nValue
);
121 case EnhancedCustomShapeParameterType::EQUATION
:
123 if ( rParameter
.Value
.getValueTypeClass() == TypeClass_LONG
)
125 sal_Int32 nFormulaIndex
;
126 if ( rParameter
.Value
>>= nFormulaIndex
)
129 + OUString::number( nFormulaIndex
)
135 // ups... we should have an index here and not the formula name
139 case EnhancedCustomShapeParameterType::ADJUSTMENT
:
141 if ( rParameter
.Value
.getValueTypeClass() == TypeClass_LONG
)
143 sal_Int32 nAdjustmentIndex
;
144 if ( rParameter
.Value
>>= nAdjustmentIndex
)
147 + OUString::number( nAdjustmentIndex
)
153 // ups... we should have an index here and not the formula name
157 case EnhancedCustomShapeParameterType::LEFT
:
160 case EnhancedCustomShapeParameterType::TOP
:
163 case EnhancedCustomShapeParameterType::RIGHT
:
166 case EnhancedCustomShapeParameterType::BOTTOM
:
169 case EnhancedCustomShapeParameterType::XSTRETCH
:
172 case EnhancedCustomShapeParameterType::YSTRETCH
:
175 case EnhancedCustomShapeParameterType::HASSTROKE
:
178 case EnhancedCustomShapeParameterType::HASFILL
:
181 case EnhancedCustomShapeParameterType::WIDTH
:
184 case EnhancedCustomShapeParameterType::HEIGHT
:
187 case EnhancedCustomShapeParameterType::LOGWIDTH
:
190 case EnhancedCustomShapeParameterType::LOGHEIGHT
:
197 static EnhancedCustomShapeParameter
GetAdjCoordinate( CustomShapeProperties
& rCustomShapeProperties
, const OUString
& rValue
, bool bNoSymbols
= true )
199 css::drawing::EnhancedCustomShapeParameter aRet
;
200 if ( !rValue
.isEmpty() )
202 bool bConstant
= true;
203 sal_Int32 nConstant
= -1;
204 sal_Int32 nIntVal
= 0;
206 // first check if it's a constant value
207 switch( AttributeConversion::decodeToken( rValue
) )
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;
218 case XML_b
: // variable height of the shape defined in spPr
223 CustomShapeGuide aGuide
;
224 aGuide
.maName
= rValue
;
225 aGuide
.maFormula
= "logheight" ;
227 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
228 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
231 aRet
.Type
= EnhancedCustomShapeParameterType::LOGHEIGHT
; // TODO: HEIGHT needs to be implemented
236 nIntVal
+= 2; // */ h 1.0 10.0
238 case XML_hd8
: // */ h 1.0 8.0
241 case XML_hd6
: // */ h 1.0 6.0
244 case XML_hd5
: // */ h 1.0 5.0
247 case XML_hd4
: // */ h 1.0 4.0
250 case XML_hd3
: // */ h 1.0 3.0
253 case XML_hd2
: // */ h 1.0 2.0
254 case XML_vc
: // */ h 1.0 2.0
258 CustomShapeGuide aGuide
;
259 aGuide
.maName
= rValue
;
260 aGuide
.maFormula
= "logheight/" + OUString::number( nIntVal
);
262 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
263 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
271 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
275 case XML_ls
: // longest side: max w h
277 CustomShapeGuide aGuide
;
278 aGuide
.maName
= rValue
;
279 aGuide
.maFormula
= "max(logwidth,logheight)";
281 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
282 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
285 case XML_ss
: // shortest side: min w h
287 CustomShapeGuide aGuide
;
288 aGuide
.maName
= rValue
;
289 aGuide
.maFormula
= "min(logwidth,logheight)";
291 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
292 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
295 case XML_ssd32
: // */ ss 1.0 32.0
298 case XML_ssd16
: // */ ss 1.0 16.0
301 case XML_ssd8
: // */ ss 1.0 8.0
304 case XML_ssd6
: // */ ss 1.0 6.0
307 case XML_ssd4
: // */ ss 1.0 4.0
310 case XML_ssd2
: // */ ss 1.0 2.0
314 CustomShapeGuide aGuide
;
315 aGuide
.maName
= rValue
;
316 aGuide
.maFormula
= "min(logwidth,logheight)/" + OUString::number( nIntVal
);
318 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
319 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
323 case XML_r
: // variable width of the shape defined in spPr
328 CustomShapeGuide aGuide
;
329 aGuide
.maName
= rValue
;
330 aGuide
.maFormula
= "logwidth" ;
332 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
333 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
336 aRet
.Type
= EnhancedCustomShapeParameterType::LOGWIDTH
;
340 case XML_wd32
: // */ w 1.0 32.0
343 case XML_wd12
: // */ w 1.0 12.0
346 case XML_wd10
: // */ w 1.0 10.0
349 case XML_wd8
: // */ w 1.0 8.0
352 case XML_wd6
: // */ w 1.0 6.0
355 case XML_wd5
: // */ w 1.0 5.0
358 case XML_wd4
: // */ w 1.0 4.0
361 case XML_wd3
: // */ w 1.0 3.0
364 case XML_hc
: // */ w 1.0 2.0
365 case XML_wd2
: // */ w 1.0 2.0
369 CustomShapeGuide aGuide
;
370 aGuide
.maName
= rValue
;
371 aGuide
.maFormula
= "logwidth/" + OUString::number( nIntVal
);
373 aRet
.Value
<<= rCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);;
374 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
384 if (nConstant
!= -1) {
385 aRet
.Value
<<= nConstant
;
386 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
391 sal_Unicode n
= rValue
[ 0 ];
392 if ( ( n
== '+' ) || ( n
== '-' ) )
394 if ( rValue
.getLength() > 1 )
397 if ( ( n
>= '0' ) && ( n
<= '9' ) )
398 { // seems to be a ST_Coordinate
399 aRet
.Value
<<= rValue
.toInt32();
400 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
404 sal_Int32 nGuideIndex
= rCustomShapeProperties
.getAdjustmentGuideList().GetCustomShapeGuideValue( rValue
);
405 if ( nGuideIndex
>= 0 )
407 aRet
.Value
<<= nGuideIndex
;
408 aRet
.Type
= EnhancedCustomShapeParameterType::ADJUSTMENT
;
412 nGuideIndex
= rCustomShapeProperties
.getGuideList().GetCustomShapeGuideValue( rValue
);
413 if ( nGuideIndex
>= 0 )
415 aRet
.Value
<<= nGuideIndex
;
416 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
420 SAL_WARN("oox", "error: unhandled value " << rValue
);
421 aRet
.Value
<<= rValue
;
433 class GeomGuideListContext
: public ContextHandler2
436 GeomGuideListContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, CustomShapeGuideContainer
& rGuideList
);
437 virtual ::oox::core::ContextHandlerRef
onCreateContext( sal_Int32 aElementToken
, const ::oox::AttributeList
& rAttribs
) override
;
440 CustomShapeGuideContainer
& mrGuideList
;
441 CustomShapeProperties
& mrCustomShapeProperties
;
446 GeomGuideListContext::GeomGuideListContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, CustomShapeGuideContainer
& rGuideList
)
447 : ContextHandler2( rParent
)
448 , mrGuideList( rGuideList
)
449 , mrCustomShapeProperties( rCustomShapeProperties
)
453 static OUString
convertToOOEquation( CustomShapeProperties
& rCustomShapeProperties
, std::u16string_view rSource
)
455 if ( !pCommandHashMap
)
457 FormulaCommandHMap
* pHM
= new FormulaCommandHMap
;
458 for(const FormulaCommandNameTable
& i
: pFormulaCommandNameTable
)
459 (*pHM
)[ OUString::createFromAscii( i
.pS
) ] = i
.pE
;
460 pCommandHashMap
= pHM
;
463 std::vector
< OUString
> aTokens
;
464 sal_Int32 nIndex
= 0;
467 OUString
aToken( o3tl::getToken(rSource
, 0, ' ', nIndex
) );
468 if ( !aToken
.isEmpty() )
469 aTokens
.push_back( aToken
);
471 while ( nIndex
>= 0 );
474 if ( !aTokens
.empty() )
476 sal_Int32 i
, nParameters
= aTokens
.size() - 1;
477 if ( nParameters
> 3 )
480 OUString sParameters
[ 3 ];
482 for ( i
= 0; i
< nParameters
; i
++ )
483 sParameters
[ i
] = GetFormulaParameter( GetAdjCoordinate( rCustomShapeProperties
, aTokens
[ i
+ 1 ], false ) );
485 const FormulaCommandHMap::const_iterator
aIter( pCommandHashMap
->find( aTokens
[ 0 ] ) );
486 if ( aIter
!= pCommandHashMap
->end() )
488 switch( aIter
->second
)
492 if ( nParameters
== 3 )
493 aEquation
= sParameters
[ 0 ] + "*" + sParameters
[ 1 ]
494 + "/" + sParameters
[ 2 ];
499 if ( nParameters
== 3 )
500 aEquation
= sParameters
[ 0 ] + "+" + sParameters
[ 1 ]
501 + "-" + sParameters
[ 2 ];
506 if ( nParameters
== 3 )
507 aEquation
= "(" + sParameters
[ 0 ] + "+"
508 + sParameters
[ 1 ] + ")/" + sParameters
[ 2 ];
514 if ( nParameters
== 3 )
515 aEquation
= "if(" + sParameters
[ 0 ] + ","
516 + sParameters
[ 1 ] + "," + sParameters
[ 2 ] + ")";
521 if ( nParameters
== 1 )
522 aEquation
= "abs(" + sParameters
[ 0 ] + ")";
527 if ( nParameters
== 2 )
528 aEquation
= "(10800000*atan2(" + sParameters
[ 1 ] + ","
529 + sParameters
[ 0 ] + "))/pi";
534 if ( nParameters
== 3 )
535 aEquation
= sParameters
[ 0 ] + "*(cos(atan2(" +
536 sParameters
[ 2 ] + "," + sParameters
[ 1 ] + ")))";
541 if ( nParameters
== 2 )
542 aEquation
= sParameters
[ 0 ] + "*cos(pi*(" +
543 sParameters
[ 1 ] + ")/10800000)";
548 if ( nParameters
== 2 )
549 aEquation
= "max(" + sParameters
[ 0 ] + "," +
550 sParameters
[ 1 ] + ")";
555 if ( nParameters
== 2 )
556 aEquation
= "min(" + sParameters
[ 0 ] + "," +
557 sParameters
[ 1 ] + ")";
562 if ( nParameters
== 3 )
564 + sParameters
[ 0 ] + "*" + sParameters
[ 0 ] + "+"
565 + sParameters
[ 1 ] + "*" + sParameters
[ 1 ] + "+"
566 + sParameters
[ 2 ] + "*" + sParameters
[ 2 ] + ")";
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 ] + "))";
580 if ( nParameters
== 3 )
581 aEquation
= sParameters
[ 0 ] + "*(sin(atan2(" +
582 sParameters
[ 2 ] + "," + sParameters
[ 1 ] + ")))";
587 if ( nParameters
== 2 )
588 aEquation
= sParameters
[ 0 ] + "*sin(pi*(" +
589 sParameters
[ 1 ] + ")/10800000)";
594 if ( nParameters
== 1 )
595 aEquation
= "sqrt(" + sParameters
[ 0 ] + ")";
600 if ( nParameters
== 2 )
601 aEquation
= sParameters
[ 0 ] + "*tan(pi*(" +
602 sParameters
[ 1 ] + ")/10800000)";
607 if ( nParameters
== 1 )
608 aEquation
= sParameters
[ 0 ];
619 ContextHandlerRef
GeomGuideListContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
621 if ( aElementToken
== A_TOKEN( gd
) ) // CT_GeomGuide
623 CustomShapeGuide aGuide
;
624 aGuide
.maName
= rAttribs
.getStringDefaulted( XML_name
);
625 aGuide
.maFormula
= convertToOOEquation( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_fmla
) );
626 mrGuideList
.push_back( aGuide
);
631 static const OUString
& GetGeomGuideName( const OUString
& rValue
)
639 class AdjPoint2DContext
: public ContextHandler2
642 AdjPoint2DContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
);
647 AdjPoint2DContext::AdjPoint2DContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
)
648 : ContextHandler2( rParent
)
650 rAdjPoint2D
.First
= GetAdjCoordinate( rCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_x
) );
651 rAdjPoint2D
.Second
= GetAdjCoordinate( rCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_y
) );
657 class XYAdjustHandleContext
: public ContextHandler2
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
;
664 AdjustHandle
& mrAdjustHandle
;
665 CustomShapeProperties
& mrCustomShapeProperties
;
670 XYAdjustHandleContext::XYAdjustHandleContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, AdjustHandle
& rAdjustHandle
)
671 : ContextHandler2( rParent
)
672 , mrAdjustHandle( rAdjustHandle
)
673 , mrCustomShapeProperties( rCustomShapeProperties
)
675 if ( rAttribs
.hasAttribute( XML_gdRefX
) )
677 mrAdjustHandle
.gdRef1
= GetGeomGuideName( rAttribs
.getStringDefaulted( XML_gdRefX
) );
679 if ( rAttribs
.hasAttribute( XML_minX
) )
681 mrAdjustHandle
.min1
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_minX
) );
683 if ( rAttribs
.hasAttribute( XML_maxX
) )
685 mrAdjustHandle
.max1
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_maxX
) );
687 if ( rAttribs
.hasAttribute( XML_gdRefY
) )
689 mrAdjustHandle
.gdRef2
= GetGeomGuideName( rAttribs
.getStringDefaulted( XML_gdRefY
) );
691 if ( rAttribs
.hasAttribute( XML_minY
) )
693 mrAdjustHandle
.min2
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_minY
) );
695 if ( rAttribs
.hasAttribute( XML_maxY
) )
697 mrAdjustHandle
.max2
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_maxY
) );
701 ContextHandlerRef
XYAdjustHandleContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
703 if ( aElementToken
== A_TOKEN( pos
) )
704 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjustHandle
.pos
); // CT_AdjPoint2D
710 // CT_PolarAdjustHandle
711 class PolarAdjustHandleContext
: public ContextHandler2
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
;
718 AdjustHandle
& mrAdjustHandle
;
719 CustomShapeProperties
& mrCustomShapeProperties
;
724 PolarAdjustHandleContext::PolarAdjustHandleContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, AdjustHandle
& rAdjustHandle
)
725 : ContextHandler2( rParent
)
726 , mrAdjustHandle( rAdjustHandle
)
727 , mrCustomShapeProperties( rCustomShapeProperties
)
729 if ( rAttribs
.hasAttribute( XML_gdRefR
) )
731 mrAdjustHandle
.polar
= true ;
732 mrAdjustHandle
.gdRef1
= GetGeomGuideName( rAttribs
.getStringDefaulted( XML_gdRefR
) );
734 if ( rAttribs
.hasAttribute( XML_minR
) )
736 mrAdjustHandle
.min1
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_minR
) );
738 if ( rAttribs
.hasAttribute( XML_maxR
) )
740 mrAdjustHandle
.max1
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_maxR
) );
742 if ( rAttribs
.hasAttribute( XML_gdRefAng
) )
744 mrAdjustHandle
.polar
= true ;
745 mrAdjustHandle
.gdRef2
= GetGeomGuideName( rAttribs
.getStringDefaulted( XML_gdRefAng
) );
747 if ( rAttribs
.hasAttribute( XML_minAng
) )
749 mrAdjustHandle
.min2
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_minAng
) );
751 if ( rAttribs
.hasAttribute( XML_maxAng
) )
753 mrAdjustHandle
.max2
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_maxAng
) );
757 ContextHandlerRef
PolarAdjustHandleContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
759 // mrAdjustHandle.pos uses planar coordinates.
760 if ( aElementToken
== A_TOKEN( pos
) )
761 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjustHandle
.pos
); // CT_AdjPoint2D
767 // CT_AdjustHandleList
768 class AdjustHandleListContext
: public ContextHandler2
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
;
775 std::vector
< AdjustHandle
>& mrAdjustHandleList
;
776 CustomShapeProperties
& mrCustomShapeProperties
;
781 AdjustHandleListContext::AdjustHandleListContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, std::vector
< AdjustHandle
>& rAdjustHandleList
)
782 : ContextHandler2( rParent
)
783 , mrAdjustHandleList( rAdjustHandleList
)
784 , mrCustomShapeProperties( rCustomShapeProperties
)
788 ContextHandlerRef
AdjustHandleListContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
790 if ( aElementToken
== A_TOKEN( ahXY
) ) // CT_XYAdjustHandle
792 AdjustHandle
aAdjustHandle( false );
793 mrAdjustHandleList
.push_back( aAdjustHandle
);
794 return new XYAdjustHandleContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjustHandleList
.back() );
796 else if ( aElementToken
== A_TOKEN( ahPolar
) ) // CT_PolarAdjustHandle
798 AdjustHandle
aAdjustHandle( true );
799 mrAdjustHandleList
.push_back( aAdjustHandle
);
800 return new PolarAdjustHandleContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjustHandleList
.back() );
808 class ConnectionSiteContext
: public ContextHandler2
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
;
815 ConnectionSite
& mrConnectionSite
;
816 CustomShapeProperties
& mrCustomShapeProperties
;
821 ConnectionSiteContext::ConnectionSiteContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, ConnectionSite
& rConnectionSite
)
822 : ContextHandler2( rParent
)
823 , mrConnectionSite( rConnectionSite
)
824 , mrCustomShapeProperties( rCustomShapeProperties
)
826 mrConnectionSite
.ang
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_ang
) );
829 ContextHandlerRef
ConnectionSiteContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
831 if ( aElementToken
== A_TOKEN( pos
) )
832 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrConnectionSite
.pos
); // CT_AdjPoint2D
839 class Path2DMoveToContext
: public ContextHandler2
842 Path2DMoveToContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
);
843 virtual ::oox::core::ContextHandlerRef
onCreateContext( sal_Int32 aElementToken
, const ::oox::AttributeList
& rAttribs
) override
;
846 EnhancedCustomShapeParameterPair
& mrAdjPoint2D
;
847 CustomShapeProperties
& mrCustomShapeProperties
;
852 Path2DMoveToContext::Path2DMoveToContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
)
853 : ContextHandler2( rParent
)
854 , mrAdjPoint2D( rAdjPoint2D
)
855 , mrCustomShapeProperties( rCustomShapeProperties
)
859 ContextHandlerRef
Path2DMoveToContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
861 if ( aElementToken
== A_TOKEN( pt
) )
862 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjPoint2D
); // CT_AdjPoint2D
869 class Path2DLineToContext
: public ContextHandler2
872 Path2DLineToContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
);
873 virtual ::oox::core::ContextHandlerRef
onCreateContext( sal_Int32 aElementToken
, const ::oox::AttributeList
& rAttribs
) override
;
876 EnhancedCustomShapeParameterPair
& mrAdjPoint2D
;
877 CustomShapeProperties
& mrCustomShapeProperties
;
882 Path2DLineToContext::Path2DLineToContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, EnhancedCustomShapeParameterPair
& rAdjPoint2D
)
883 : ContextHandler2( rParent
)
884 , mrAdjPoint2D( rAdjPoint2D
)
885 , mrCustomShapeProperties( rCustomShapeProperties
)
889 ContextHandlerRef
Path2DLineToContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
891 if ( aElementToken
== A_TOKEN( pt
) )
892 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrAdjPoint2D
); // CT_AdjPoint2D
898 // CT_Path2DQuadBezierTo
899 class Path2DQuadBezierToContext
: public ContextHandler2
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
;
906 EnhancedCustomShapeParameterPair
& mrPt1
;
907 EnhancedCustomShapeParameterPair
& mrPt2
;
909 CustomShapeProperties
& mrCustomShapeProperties
;
914 Path2DQuadBezierToContext::Path2DQuadBezierToContext( ContextHandler2Helper
const & rParent
,
915 CustomShapeProperties
& rCustomShapeProperties
,
916 EnhancedCustomShapeParameterPair
& rPt1
,
917 EnhancedCustomShapeParameterPair
& rPt2
)
918 : ContextHandler2( rParent
)
922 , mrCustomShapeProperties( rCustomShapeProperties
)
926 ContextHandlerRef
Path2DQuadBezierToContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
928 if ( aElementToken
== A_TOKEN( pt
) )
929 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
, nCount
++ ? mrPt2
: mrPt1
); // CT_AdjPoint2D
935 // CT_Path2DCubicBezierTo
936 class Path2DCubicBezierToContext
: public ContextHandler2
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
;
944 CustomShapeProperties
& mrCustomShapeProperties
;
945 EnhancedCustomShapeParameterPair
& mrControlPt1
;
946 EnhancedCustomShapeParameterPair
& mrControlPt2
;
947 EnhancedCustomShapeParameterPair
& mrEndPt
;
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
)
966 ContextHandlerRef
Path2DCubicBezierToContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
968 if ( aElementToken
== A_TOKEN( pt
) )
969 return new AdjPoint2DContext( *this, rAttribs
, mrCustomShapeProperties
,
970 nCount
++ ? nCount
== 2 ? mrControlPt2
: mrEndPt
: mrControlPt1
); // CT_AdjPoint2D
977 class Path2DContext
: public ContextHandler2
980 Path2DContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
, std::vector
< css::drawing::EnhancedCustomShapeSegment
>& rSegments
, Path2D
& rPath2D
);
981 virtual void onEndElement() override
;
982 virtual ::oox::core::ContextHandlerRef
983 onCreateContext( sal_Int32 aElementToken
, const ::oox::AttributeList
& rAttribs
) override
;
987 std::vector
< css::drawing::EnhancedCustomShapeSegment
>& mrSegments
;
988 CustomShapeProperties
& mrCustomShapeProperties
;
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
)
999 rPath2D
.w
= rAttribs
.getHyper( XML_w
, 0 );
1000 rPath2D
.h
= rAttribs
.getHyper( XML_h
, 0 );
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 );
1006 void Path2DContext::onEndElement()
1008 EnhancedCustomShapeSegment aNewSegment
;
1009 switch ( mrPath2D
.fill
)
1012 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::NOFILL
;
1015 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::DARKEN
;
1017 case XML_darkenLess
:
1018 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::DARKENLESS
;
1021 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::LIGHTEN
;
1023 case XML_lightenLess
:
1024 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::LIGHTENLESS
;
1027 if (mrPath2D
.fill
!= XML_norm
) {
1028 aNewSegment
.Count
= 0;
1029 mrSegments
.push_back( aNewSegment
);
1031 if ( !mrPath2D
.stroke
)
1033 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::NOSTROKE
;
1034 aNewSegment
.Count
= 0;
1035 mrSegments
.push_back( aNewSegment
);
1037 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::ENDSUBPATH
;
1038 aNewSegment
.Count
= 0;
1039 mrSegments
.push_back( aNewSegment
);
1043 ContextHandlerRef
Path2DContext::onCreateContext( sal_Int32 aElementToken
,
1044 const AttributeList
& rAttribs
)
1046 switch( aElementToken
)
1048 case A_TOKEN( close
) :
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
);
1059 case A_TOKEN( moveTo
) :
1061 EnhancedCustomShapeSegment aNewSegment
;
1062 aNewSegment
.Command
= EnhancedCustomShapeSegmentCommand::MOVETO
;
1063 aNewSegment
.Count
= 1;
1064 mrSegments
.push_back( aNewSegment
);
1066 EnhancedCustomShapeParameterPair aAdjPoint2D
;
1067 mrPath2D
.parameter
.push_back( aAdjPoint2D
);
1068 return new Path2DMoveToContext( *this, mrCustomShapeProperties
, mrPath2D
.parameter
.back() );
1071 case A_TOKEN( lnTo
) :
1073 if ( !mrSegments
.empty() && ( mrSegments
.back().Command
== EnhancedCustomShapeSegmentCommand::LINETO
) )
1074 mrSegments
.back().Count
++;
1077 EnhancedCustomShapeSegment aSegment
;
1078 aSegment
.Command
= EnhancedCustomShapeSegmentCommand::LINETO
;
1080 mrSegments
.push_back( aSegment
);
1082 EnhancedCustomShapeParameterPair aAdjPoint2D
;
1083 mrPath2D
.parameter
.push_back( aAdjPoint2D
);
1084 return new Path2DLineToContext( *this, mrCustomShapeProperties
, mrPath2D
.parameter
.back() );
1087 case A_TOKEN( arcTo
) : // CT_Path2DArcTo
1089 if ( !mrSegments
.empty() && ( mrSegments
.back().Command
== EnhancedCustomShapeSegmentCommand::ARCANGLETO
) )
1090 mrSegments
.back().Count
++;
1093 EnhancedCustomShapeSegment aSegment
;
1094 aSegment
.Command
= EnhancedCustomShapeSegmentCommand::ARCANGLETO
;
1096 mrSegments
.push_back( aSegment
);
1099 EnhancedCustomShapeParameterPair aScale
;
1100 EnhancedCustomShapeParameterPair aAngles
;
1102 aScale
.First
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_wR
) );
1103 aScale
.Second
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_hR
) );
1105 CustomShapeGuide aGuide
;
1106 sal_Int32 nArcNum
= mrCustomShapeProperties
.getArcNum();
1109 aGuide
.maName
= "arctosa" + OUString::number( nArcNum
);
1110 aGuide
.maFormula
= "("
1111 + GetFormulaParameter( GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_stAng
) ) )
1113 aAngles
.First
.Value
<<= mrCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
1114 aAngles
.First
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
1117 aGuide
.maName
= "arctosw" + OUString::number( nArcNum
);
1118 aGuide
.maFormula
= "("
1119 + GetFormulaParameter( GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_swAng
) ) )
1121 aAngles
.Second
.Value
<<= mrCustomShapeProperties
.getGuideList().SetCustomShapeGuideValue( aGuide
);
1122 aAngles
.Second
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
1124 mrPath2D
.parameter
.push_back( aScale
);
1125 mrPath2D
.parameter
.push_back( aAngles
);
1128 case A_TOKEN( quadBezTo
) :
1130 if ( !mrSegments
.empty() && ( mrSegments
.back().Command
== EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO
) )
1131 mrSegments
.back().Count
++;
1134 EnhancedCustomShapeSegment aSegment
;
1135 aSegment
.Command
= EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO
;
1137 mrSegments
.push_back( aSegment
);
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() );
1148 case A_TOKEN( cubicBezTo
) :
1150 if ( !mrSegments
.empty() && ( mrSegments
.back().Command
== EnhancedCustomShapeSegmentCommand::CURVETO
) )
1151 mrSegments
.back().Count
++;
1154 EnhancedCustomShapeSegment aSegment
;
1155 aSegment
.Command
= EnhancedCustomShapeSegmentCommand::CURVETO
;
1157 mrSegments
.push_back( aSegment
);
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() );
1178 class Path2DListContext
: public ContextHandler2
1181 Path2DListContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
, std::vector
< EnhancedCustomShapeSegment
>& rSegments
,
1182 std::vector
< Path2D
>& rPath2DList
);
1184 virtual ::oox::core::ContextHandlerRef
onCreateContext( sal_Int32 aElementToken
, const ::oox::AttributeList
& rAttribs
) override
;
1188 CustomShapeProperties
& mrCustomShapeProperties
;
1189 std::vector
< css::drawing::EnhancedCustomShapeSegment
>& mrSegments
;
1190 std::vector
< Path2D
>& mrPath2DList
;
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
)
1204 ContextHandlerRef
Path2DListContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
1206 if ( aElementToken
== A_TOKEN( path
) )
1209 mrPath2DList
.push_back( aPath2D
);
1210 return new Path2DContext( *this, rAttribs
, mrCustomShapeProperties
, mrSegments
, mrPath2DList
.back() );
1215 // CT_CustomGeometry2D
1216 CustomShapeGeometryContext::CustomShapeGeometryContext( ContextHandler2Helper
const & rParent
, CustomShapeProperties
& rCustomShapeProperties
)
1217 : ContextHandler2( rParent
)
1218 , mrCustomShapeProperties( rCustomShapeProperties
)
1222 ContextHandlerRef
CustomShapeGeometryContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& rAttribs
)
1224 switch( aElementToken
)
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
1234 case A_TOKEN( rect
): // CT_GeomRectList geometry rect list
1237 aGeomRect
.l
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_l
) );
1238 aGeomRect
.t
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_t
) );
1239 aGeomRect
.r
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_r
) );
1240 aGeomRect
.b
= GetAdjCoordinate( mrCustomShapeProperties
, rAttribs
.getStringDefaulted( XML_b
) );
1241 mrCustomShapeProperties
.getTextRect() = aGeomRect
;
1244 case A_TOKEN( pathLst
): // CT_Path2DList 2d path list
1245 return new Path2DListContext( *this, mrCustomShapeProperties
, mrCustomShapeProperties
.getSegments(), mrCustomShapeProperties
.getPath2DList() );
1248 case A_TOKEN( cxn
): // CT_ConnectionSite
1250 ConnectionSite aConnectionSite
;
1251 mrCustomShapeProperties
.getConnectionSiteList().push_back( aConnectionSite
);
1252 return new ConnectionSiteContext( *this, rAttribs
, mrCustomShapeProperties
, mrCustomShapeProperties
.getConnectionSiteList().back() );
1258 // CT_PresetGeometry2D
1259 PresetShapeGeometryContext::PresetShapeGeometryContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
)
1260 : ContextHandler2( rParent
)
1261 , mrCustomShapeProperties( rCustomShapeProperties
)
1263 sal_Int32 nShapeType
= rAttribs
.getToken( XML_prst
, FastToken::DONTKNOW
);
1264 OSL_ENSURE( nShapeType
!= FastToken::DONTKNOW
, "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" );
1265 mrCustomShapeProperties
.setShapePresetType( nShapeType
);
1268 ContextHandlerRef
PresetShapeGeometryContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& )
1270 if ( aElementToken
== A_TOKEN( avLst
) )
1271 return new GeomGuideListContext( *this, mrCustomShapeProperties
, mrCustomShapeProperties
.getAdjustmentGuideList() );
1276 // CT_PresetTextShape
1277 PresetTextShapeContext::PresetTextShapeContext( ContextHandler2Helper
const & rParent
, const AttributeList
& rAttribs
, CustomShapeProperties
& rCustomShapeProperties
)
1278 : ContextHandler2( rParent
)
1279 , mrCustomShapeProperties( rCustomShapeProperties
)
1281 sal_Int32 nShapeType
= rAttribs
.getToken( XML_prst
, FastToken::DONTKNOW
);
1282 OSL_ENSURE( nShapeType
!= FastToken::DONTKNOW
, "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" );
1283 mrCustomShapeProperties
.setShapePresetType( nShapeType
);
1286 ContextHandlerRef
PresetTextShapeContext::onCreateContext( sal_Int32 aElementToken
, const AttributeList
& )
1288 if ( aElementToken
== A_TOKEN( avLst
) )
1289 return new GeomGuideListContext( *this, mrCustomShapeProperties
, mrCustomShapeProperties
.getAdjustmentGuideList() );
1296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */