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 "ximpcustomshape.hxx"
21 #include <o3tl/any.hxx>
22 #include <rtl/ustrbuf.hxx>
23 #include <rtl/ustring.hxx>
24 #include <com/sun/star/uno/Reference.h>
25 #include <com/sun/star/awt/Rectangle.hpp>
26 #include <xmloff/xmltoken.hxx>
27 #include <EnhancedCustomShapeToken.hxx>
28 #include <xmloff/xmlimp.hxx>
29 #include <xmloff/xmluconv.hxx>
30 #include <xmloff/xmlement.hxx>
31 #include <xexptran.hxx>
32 #include <com/sun/star/drawing/Direction3D.hpp>
33 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
34 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
35 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
36 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
37 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
38 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
39 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
40 #include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
41 #include <com/sun/star/drawing/ProjectionMode.hpp>
42 #include <com/sun/star/drawing/Position3D.hpp>
43 #include <sax/tools/converter.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <o3tl/string_view.hxx>
46 #include <string_view>
47 #include <unordered_map>
49 using namespace ::com::sun::star
;
50 using namespace ::xmloff::token
;
51 using namespace ::xmloff::EnhancedCustomShapeToken
;
54 XMLEnhancedCustomShapeContext::XMLEnhancedCustomShapeContext( SvXMLImport
& rImport
,
55 css::uno::Reference
< css::drawing::XShape
>& rxShape
,
56 std::vector
< css::beans::PropertyValue
>& rCustomShapeGeometry
) :
57 SvXMLImportContext( rImport
),
58 mrUnitConverter( rImport
.GetMM100UnitConverter() ),
60 mrCustomShapeGeometry( rCustomShapeGeometry
)
64 const SvXMLEnumMapEntry
<sal_uInt16
> aXML_GluePointEnumMap
[] =
70 { XML_TOKEN_INVALID
, 0 }
72 static void GetBool( std::vector
< css::beans::PropertyValue
>& rDest
,
73 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
76 if (::sax::Converter::convertBool( bAttrBool
, rValue
))
78 beans::PropertyValue aProp
;
79 aProp
.Name
= EASGet( eDestProp
);
80 aProp
.Value
<<= bAttrBool
;
81 rDest
.push_back( aProp
);
85 static void GetInt32( std::vector
< css::beans::PropertyValue
>& rDest
,
86 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
88 sal_Int32 nAttrNumber
;
89 if (::sax::Converter::convertNumber( nAttrNumber
, rValue
))
91 beans::PropertyValue aProp
;
92 aProp
.Name
= EASGet( eDestProp
);
93 aProp
.Value
<<= nAttrNumber
;
94 rDest
.push_back( aProp
);
98 static void GetDouble( std::vector
< css::beans::PropertyValue
>& rDest
,
99 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
102 if (::sax::Converter::convertDouble( fAttrDouble
, rValue
))
104 beans::PropertyValue aProp
;
105 aProp
.Name
= EASGet( eDestProp
);
106 aProp
.Value
<<= fAttrDouble
;
107 rDest
.push_back( aProp
);
111 static void GetString( std::vector
< css::beans::PropertyValue
>& rDest
,
112 const OUString
& rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
114 beans::PropertyValue aProp
;
115 aProp
.Name
= EASGet( eDestProp
);
116 aProp
.Value
<<= rValue
;
117 rDest
.push_back( aProp
);
120 template<typename EnumT
>
121 static void GetEnum( std::vector
< css::beans::PropertyValue
>& rDest
,
122 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
,
123 const SvXMLEnumMapEntry
<EnumT
>& rMap
)
126 if( SvXMLUnitConverter::convertEnum( eKind
, rValue
, &rMap
) )
128 beans::PropertyValue aProp
;
129 aProp
.Name
= EASGet( eDestProp
);
130 aProp
.Value
<<= static_cast<sal_Int16
>(eKind
);
131 rDest
.push_back( aProp
);
135 static void GetDoublePercentage( std::vector
< css::beans::PropertyValue
>& rDest
,
136 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
138 sal_Int16
const eSrcUnit
= ::sax::Converter::GetUnitFromString(
139 rValue
, util::MeasureUnit::MM_100TH
);
140 if (util::MeasureUnit::PERCENT
!= eSrcUnit
)
143 rtl_math_ConversionStatus eStatus
;
144 double fAttrDouble
= rtl_math_stringToDouble(rValue
.data(),
145 rValue
.data() + rValue
.size(),
146 '.', ',', &eStatus
, nullptr);
147 if ( eStatus
== rtl_math_ConversionStatus_Ok
)
149 beans::PropertyValue aProp
;
150 aProp
.Name
= EASGet( eDestProp
);
151 aProp
.Value
<<= fAttrDouble
;
152 rDest
.push_back( aProp
);
156 static void GetB3DVector( std::vector
< css::beans::PropertyValue
>& rDest
,
157 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
159 ::basegfx::B3DVector aB3DVector
;
160 if ( SvXMLUnitConverter::convertB3DVector( aB3DVector
, rValue
) )
162 drawing::Direction3D
aDirection3D( aB3DVector
.getX(), aB3DVector
.getY(), aB3DVector
.getZ() );
163 beans::PropertyValue aProp
;
164 aProp
.Name
= EASGet( eDestProp
);
165 aProp
.Value
<<= aDirection3D
;
166 rDest
.push_back( aProp
);
170 static bool GetEquationName( std::u16string_view rEquation
, const sal_Int32 nStart
, OUString
& rEquationName
)
172 sal_Int32 nIndex
= nStart
;
173 while( nIndex
< static_cast<sal_Int32
>(rEquation
.size()) )
175 sal_Unicode nChar
= rEquation
[ nIndex
];
177 ( ( nChar
>= 'a' ) && ( nChar
<= 'z' ) )
178 || ( ( nChar
>= 'A' ) && ( nChar
<= 'Z' ) )
179 || ( ( nChar
>= '0' ) && ( nChar
<= '9' ) )
187 bool bValid
= ( nIndex
- nStart
) != 0;
189 rEquationName
= rEquation
.substr( nStart
, nIndex
- nStart
);
193 static bool GetNextParameter( css::drawing::EnhancedCustomShapeParameter
& rParameter
, sal_Int32
& nIndex
, std::u16string_view rParaString
)
195 if ( nIndex
>= static_cast<sal_Int32
>(rParaString
.size()) )
199 bool bNumberRequired
= true;
200 bool bMustBePositiveWholeNumbered
= false;
202 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::NORMAL
;
203 if ( rParaString
[ nIndex
] == '$' )
205 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT
;
206 bMustBePositiveWholeNumbered
= true;
209 else if ( rParaString
[ nIndex
] == '?' )
212 bNumberRequired
= false;
213 OUString aEquationName
;
214 bValid
= GetEquationName( rParaString
, nIndex
, aEquationName
);
217 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::EQUATION
;
218 rParameter
.Value
<<= aEquationName
;
219 nIndex
+= aEquationName
.getLength();
222 else if ( rParaString
[ nIndex
] > '9' )
224 bNumberRequired
= false;
225 if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"left", nIndex
) )
227 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::LEFT
;
230 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"top", nIndex
) )
232 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::TOP
;
235 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"right", nIndex
) )
237 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::RIGHT
;
240 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"bottom", nIndex
) )
242 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::BOTTOM
;
245 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"xstretch", nIndex
) )
247 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::XSTRETCH
;
250 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"ystretch", nIndex
) )
252 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::YSTRETCH
;
255 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"hasstroke", nIndex
) )
257 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::HASSTROKE
;
260 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"hasfill", nIndex
) )
262 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::HASFILL
;
265 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"width", nIndex
) )
267 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::WIDTH
;
270 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"height", nIndex
) )
272 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::HEIGHT
;
275 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"logwidth", nIndex
) )
277 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::LOGWIDTH
;
280 else if ( o3tl::matchIgnoreAsciiCase( rParaString
, u
"logheight", nIndex
) )
282 rParameter
.Type
= css::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT
;
290 if ( bNumberRequired
)
292 sal_Int32 nStartIndex
= nIndex
;
293 sal_Int32 nEIndex
= 0; // index of "E" in double
295 bool bE
= false; // set if a double is including a "E" statement
296 bool bENum
= false; // there is at least one number after "E"
297 bool bDot
= false; // set if there is a dot included
298 bool bEnd
= false; // set for each value that can not be part of a double/integer
300 while( ( nIndex
< static_cast<sal_Int32
>(rParaString
.size()) ) && bValid
)
302 switch( rParaString
[ nIndex
] )
306 if ( bMustBePositiveWholeNumbered
)
319 if ( bMustBePositiveWholeNumbered
)
323 if ( nStartIndex
== nIndex
)
327 if ( nEIndex
+ 1 == nIndex
)
341 if ( bMustBePositiveWholeNumbered
)
378 if ( nIndex
== nStartIndex
)
382 std::u16string_view
aNumber( rParaString
.substr( nStartIndex
, nIndex
- nStartIndex
) );
386 if (::sax::Converter::convertDouble(fAttrDouble
, aNumber
))
387 rParameter
.Value
<<= fAttrDouble
;
394 if (::sax::Converter::convertNumber(nValue
, aNumber
))
395 rParameter
.Value
<<= nValue
;
404 // skipping white spaces and commas (#i121507#)
405 const sal_Unicode
aSpace(' ');
406 const sal_Unicode
aCommata(',');
408 while(nIndex
< static_cast<sal_Int32
>(rParaString
.size()))
410 const sal_Unicode
aCandidate(rParaString
[nIndex
]);
412 if(aSpace
== aCandidate
|| aCommata
== aCandidate
)
425 static void GetPosition3D( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:extrusion-viewpoint
426 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
,
427 const SvXMLUnitConverter
& rUnitConverter
)
429 drawing::Position3D aPosition3D
;
430 if ( rUnitConverter
.convertPosition3D( aPosition3D
, rValue
) )
432 beans::PropertyValue aProp
;
433 aProp
.Name
= EASGet( eDestProp
);
434 aProp
.Value
<<= aPosition3D
;
435 rDest
.push_back( aProp
);
439 static void GetDoubleSequence( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:glue-point-leaving-directions
440 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
442 std::vector
< double > vDirection
;
443 sal_Int32 nIndex
= 0;
447 std::string_view
aToken( o3tl::getToken(rValue
, 0, ',', nIndex
) );
448 if (!::sax::Converter::convertDouble( fAttrDouble
, aToken
))
451 vDirection
.push_back( fAttrDouble
);
453 while ( nIndex
>= 0 );
455 if ( !vDirection
.empty() )
457 beans::PropertyValue aProp
;
458 aProp
.Name
= EASGet( eDestProp
);
459 aProp
.Value
<<= comphelper::containerToSequence(vDirection
);
460 rDest
.push_back( aProp
);
464 static void GetSizeSequence( std::vector
< css::beans::PropertyValue
>& rDest
,
465 std::string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
467 std::vector
< sal_Int32
> vNum
;
468 sal_Int32 nIndex
= 0;
472 std::string_view
aToken( o3tl::getToken(rValue
, 0, ' ', nIndex
) );
473 if (!::sax::Converter::convertNumber( n
, aToken
))
478 while ( nIndex
>= 0 );
483 uno::Sequence
< awt::Size
> aSizeSeq((vNum
.size() + 1) / 2);
484 std::vector
< sal_Int32
>::const_iterator aIter
= vNum
.begin();
485 std::vector
< sal_Int32
>::const_iterator aEnd
= vNum
.end();
486 awt::Size
* pValues
= aSizeSeq
.getArray();
488 while ( aIter
!= aEnd
) {
489 pValues
->Width
= *aIter
++;
491 pValues
->Height
= *aIter
++;
495 beans::PropertyValue aProp
;
496 aProp
.Name
= EASGet( eDestProp
);
497 aProp
.Value
<<= aSizeSeq
;
498 rDest
.push_back( aProp
);
501 static void GetEnhancedParameter( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:handle-position
502 std::u16string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
504 sal_Int32 nIndex
= 0;
505 css::drawing::EnhancedCustomShapeParameter aParameter
;
506 if ( GetNextParameter( aParameter
, nIndex
, rValue
) )
508 beans::PropertyValue aProp
;
509 aProp
.Name
= EASGet( eDestProp
);
510 aProp
.Value
<<= aParameter
;
511 rDest
.push_back( aProp
);
515 static void GetEnhancedParameterPair( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:handle-position
516 std::u16string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
518 sal_Int32 nIndex
= 0;
519 css::drawing::EnhancedCustomShapeParameterPair aParameterPair
;
520 if ( GetNextParameter( aParameterPair
.First
, nIndex
, rValue
)
521 && GetNextParameter( aParameterPair
.Second
, nIndex
, rValue
) )
523 beans::PropertyValue aProp
;
524 aProp
.Name
= EASGet( eDestProp
);
525 aProp
.Value
<<= aParameterPair
;
526 rDest
.push_back( aProp
);
530 static sal_Int32
GetEnhancedParameterPairSequence( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:glue-points
531 std::u16string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
533 std::vector
< css::drawing::EnhancedCustomShapeParameterPair
> vParameter
;
534 css::drawing::EnhancedCustomShapeParameterPair aParameter
;
536 sal_Int32 nIndex
= 0;
537 while ( GetNextParameter( aParameter
.First
, nIndex
, rValue
)
538 && GetNextParameter( aParameter
.Second
, nIndex
, rValue
) )
540 vParameter
.push_back( aParameter
);
542 if ( !vParameter
.empty() )
544 beans::PropertyValue aProp
;
545 aProp
.Name
= EASGet( eDestProp
);
546 aProp
.Value
<<= comphelper::containerToSequence(vParameter
);
547 rDest
.push_back( aProp
);
549 return vParameter
.size();
552 static void GetEnhancedRectangleSequence( std::vector
< css::beans::PropertyValue
>& rDest
, // e.g. draw:text-areas
553 std::u16string_view rValue
, const EnhancedCustomShapeTokenEnum eDestProp
)
555 std::vector
< css::drawing::EnhancedCustomShapeTextFrame
> vTextFrame
;
556 css::drawing::EnhancedCustomShapeTextFrame aParameter
;
558 sal_Int32 nIndex
= 0;
560 while ( GetNextParameter( aParameter
.TopLeft
.First
, nIndex
, rValue
)
561 && GetNextParameter( aParameter
.TopLeft
.Second
, nIndex
, rValue
)
562 && GetNextParameter( aParameter
.BottomRight
.First
, nIndex
, rValue
)
563 && GetNextParameter( aParameter
.BottomRight
.Second
, nIndex
, rValue
) )
565 vTextFrame
.push_back( aParameter
);
567 if ( !vTextFrame
.empty() )
569 beans::PropertyValue aProp
;
570 aProp
.Name
= EASGet( eDestProp
);
571 aProp
.Value
<<= comphelper::containerToSequence(vTextFrame
);
572 rDest
.push_back( aProp
);
577 GetEnhancedPath(std::vector
<css::beans::PropertyValue
>& rDest
, // e.g. draw:enhanced-path
578 std::u16string_view rValue
, std::u16string_view rType
)
580 std::vector
< css::drawing::EnhancedCustomShapeParameterPair
> vCoordinates
;
581 std::vector
< css::drawing::EnhancedCustomShapeSegment
> vSegments
;
583 sal_Int32 nIndex
= 0;
584 sal_Int32 nParameterCount
= 0;
586 sal_Int32 nParametersNeeded
= 1;
587 sal_Int16 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
;
591 while( bValid
&& ( nIndex
< static_cast<sal_Int32
>(rValue
.size()) ) )
593 switch( rValue
[ nIndex
] )
597 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
;
598 nParametersNeeded
= 1;
604 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::LINETO
;
605 nParametersNeeded
= 1;
611 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::CURVETO
;
612 nParametersNeeded
= 3;
618 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
;
619 nParametersNeeded
= 0;
625 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH
;
626 nParametersNeeded
= 0;
632 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::NOFILL
;
633 nParametersNeeded
= 0;
639 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE
;
640 nParametersNeeded
= 0;
646 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO
;
647 nParametersNeeded
= 3;
653 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE
;
654 nParametersNeeded
= 3;
660 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO
;
661 nParametersNeeded
= 4;
667 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ARC
;
668 nParametersNeeded
= 4;
674 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO
;
675 nParametersNeeded
= 2;
681 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::DARKEN
;
682 nParametersNeeded
= 0;
688 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS
;
689 nParametersNeeded
= 0;
695 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN
;
696 nParametersNeeded
= 0;
702 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS
;
703 nParametersNeeded
= 0;
709 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
;
710 nParametersNeeded
= 4;
716 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
;
717 nParametersNeeded
= 4;
723 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX
;
724 nParametersNeeded
= 1;
730 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY
;
731 nParametersNeeded
= 1;
737 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO
;
738 nParametersNeeded
= 2;
763 css::drawing::EnhancedCustomShapeParameterPair aPair
;
764 if ( GetNextParameter( aPair
.First
, nIndex
, rValue
) &&
765 GetNextParameter( aPair
.Second
, nIndex
, rValue
) )
767 vCoordinates
.push_back( aPair
);
778 if ( !nParameterCount
&& !nParametersNeeded
)
780 css::drawing::EnhancedCustomShapeSegment aSegment
;
781 aSegment
.Command
= nLatestSegmentCommand
;
783 vSegments
.push_back( aSegment
);
784 nParametersNeeded
= 0x7fffffff;
786 else if ( nParameterCount
>= nParametersNeeded
)
788 // Special rule for moveto in ODF 1.2 section 19.145
789 // "If a moveto is followed by multiple pairs of coordinates, they are treated as lineto."
790 if ( nLatestSegmentCommand
== css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
)
792 css::drawing::EnhancedCustomShapeSegment aSegment
;
793 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
;
795 vSegments
.push_back( aSegment
);
797 nLatestSegmentCommand
= css::drawing::EnhancedCustomShapeSegmentCommand::LINETO
;
798 nParametersNeeded
= 1;
802 // General rule in ODF 1.2. section 19.145
803 // "If a command is repeated multiple times, all repeated command characters
804 // except the first one may be omitted." Thus check if the last command is identical,
805 // if so, we just need to increment the count
806 if ( !vSegments
.empty() && ( vSegments
[ vSegments
.size() - 1 ].Command
== nLatestSegmentCommand
) )
807 vSegments
[ vSegments
.size() -1 ].Count
++;
810 css::drawing::EnhancedCustomShapeSegment aSegment
;
811 aSegment
.Command
= nLatestSegmentCommand
;
813 vSegments
.push_back( aSegment
);
820 // Corrections for wrong paths in curvedArrow shapes written by older LO versions
821 if (!vSegments
.empty()
822 && (rType
== u
"mso-spt102" || rType
== u
"mso-spt103" || rType
== u
"mso-spt104"
823 || rType
== u
"mso-spt105")
824 && vSegments
[0].Count
== 2)
826 vSegments
[0].Count
= 1;
827 css::drawing::EnhancedCustomShapeSegment aSegment
;
830 = vSegments
[0].Command
== css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
831 ? css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
832 : css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO
;
833 vSegments
.insert(vSegments
.begin() + 1, aSegment
);
836 // adding the Coordinates property
837 beans::PropertyValue aProp
;
838 aProp
.Name
= EASGet( EAS_Coordinates
);
839 aProp
.Value
<<= comphelper::containerToSequence(vCoordinates
);
840 rDest
.push_back( aProp
);
842 // adding the Segments property
843 aProp
.Name
= EASGet( EAS_Segments
);
844 aProp
.Value
<<= comphelper::containerToSequence(vSegments
);
845 rDest
.push_back( aProp
);
848 static void GetAdjustmentValues( std::vector
< css::beans::PropertyValue
>& rDest
, // draw:adjustments
849 std::u16string_view rValue
)
851 std::vector
< css::drawing::EnhancedCustomShapeAdjustmentValue
> vAdjustmentValue
;
852 css::drawing::EnhancedCustomShapeParameter aParameter
;
853 sal_Int32 nIndex
= 0;
854 while ( GetNextParameter( aParameter
, nIndex
, rValue
) )
856 css::drawing::EnhancedCustomShapeAdjustmentValue aAdj
;
857 if ( aParameter
.Type
== css::drawing::EnhancedCustomShapeParameterType::NORMAL
)
859 aAdj
.Value
= aParameter
.Value
;
860 aAdj
.State
= beans::PropertyState_DIRECT_VALUE
;
863 aAdj
.State
= beans::PropertyState_DEFAULT_VALUE
; // this should not be, but better than setting nothing
865 vAdjustmentValue
.push_back( aAdj
);
868 sal_Int32 nAdjustmentValues
= vAdjustmentValue
.size();
869 if ( nAdjustmentValues
)
871 beans::PropertyValue aProp
;
872 aProp
.Name
= EASGet( EAS_AdjustmentValues
);
873 aProp
.Value
<<= comphelper::containerToSequence(vAdjustmentValue
);
874 rDest
.push_back( aProp
);
878 void XMLEnhancedCustomShapeContext::startFastElement(
879 sal_Int32
/*nElement*/,
880 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
882 sal_Int32 nAttrNumber
;
883 std::optional
<std::string_view
> oSpecularityValue
; // for postpone extrusion-specularity
884 std::optional
<OUString
> oPathValue
; // for postpone GetEnhancedPath;
885 OUString
sType(u
"non-primitive"_ustr
); // default in ODF
886 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
888 switch( EASGet( aIter
.getToken() ) )
892 sType
= aIter
.toString();
893 GetString( mrCustomShapeGeometry
, sType
, EAS_Type
);
896 case EAS_mirror_horizontal
:
897 GetBool( mrCustomShapeGeometry
, aIter
.toView(), EAS_MirroredX
);
899 case EAS_mirror_vertical
:
900 GetBool( mrCustomShapeGeometry
, aIter
.toView(), EAS_MirroredY
);
904 SdXMLImExViewBox
aViewBox( aIter
.toString(), GetImport().GetMM100UnitConverter() );
905 awt::Rectangle
aRect( aViewBox
.GetX(), aViewBox
.GetY(), aViewBox
.GetWidth(), aViewBox
.GetHeight() );
906 beans::PropertyValue aProp
;
907 aProp
.Name
= EASGet( EAS_ViewBox
);
908 aProp
.Value
<<= aRect
;
909 mrCustomShapeGeometry
.push_back( aProp
);
912 case EAS_sub_view_size
:
913 GetSizeSequence( maPath
, aIter
.toView(), EAS_SubViewSize
);
915 case EAS_text_rotate_angle
:
916 GetDouble( mrCustomShapeGeometry
, aIter
.toView(), EAS_TextRotateAngle
);
918 case EAS_extrusion_allowed
:
919 GetBool( maPath
, aIter
.toView(), EAS_ExtrusionAllowed
);
921 case EAS_text_path_allowed
:
922 GetBool( maPath
, aIter
.toView(), EAS_TextPathAllowed
);
924 case EAS_concentric_gradient_fill_allowed
:
925 GetBool( maPath
, aIter
.toView(), EAS_ConcentricGradientFillAllowed
);
928 GetBool( maExtrusion
, aIter
.toView(), EAS_Extrusion
);
930 case EAS_extrusion_brightness
:
931 GetDoublePercentage( maExtrusion
, aIter
.toView(), EAS_Brightness
);
933 case EAS_extrusion_depth
:
935 OUString rValue
= aIter
.toString();
936 sal_Int32 nIndex
= 0;
937 css::drawing::EnhancedCustomShapeParameterPair aParameterPair
;
938 css::drawing::EnhancedCustomShapeParameter
& rDepth
= aParameterPair
.First
;
939 if ( GetNextParameter( rDepth
, nIndex
, rValue
) )
941 css::drawing::EnhancedCustomShapeParameter
& rFraction
= aParameterPair
.Second
;
942 // try to catch the unit for the depth
943 sal_Int16
const eSrcUnit(
944 ::sax::Converter::GetUnitFromString(
945 rValue
, util::MeasureUnit::MM_100TH
));
947 OUStringBuffer aUnitStr
;
948 double fFactor
= ::sax::Converter::GetConversionFactor(
949 aUnitStr
, util::MeasureUnit::MM_100TH
, eSrcUnit
);
950 if ( ( fFactor
!= 1.0 ) && ( fFactor
!= 0.0 ) )
953 if ( rDepth
.Value
>>= fDepth
)
956 rDepth
.Value
<<= fDepth
;
959 if ( rValue
.matchIgnoreAsciiCase( aUnitStr
, nIndex
) )
960 nIndex
+= aUnitStr
.getLength();
962 // skipping white spaces
963 while( ( nIndex
< rValue
.getLength() ) && rValue
[ nIndex
] == ' ' )
966 if ( GetNextParameter( rFraction
, nIndex
, rValue
) )
968 beans::PropertyValue aProp
;
969 aProp
.Name
= EASGet( EAS_Depth
);
970 aProp
.Value
<<= aParameterPair
;
971 maExtrusion
.push_back( aProp
);
976 case EAS_extrusion_diffusion
:
977 GetDoublePercentage( maExtrusion
, aIter
.toView(), EAS_Diffusion
);
979 case EAS_extrusion_number_of_line_segments
:
980 GetInt32( maExtrusion
, aIter
.toView(), EAS_NumberOfLineSegments
);
982 case EAS_extrusion_light_face
:
983 GetBool( maExtrusion
, aIter
.toView(), EAS_LightFace
);
985 case EAS_extrusion_first_light_harsh
:
986 GetBool( maExtrusion
, aIter
.toView(), EAS_FirstLightHarsh
);
988 case EAS_extrusion_second_light_harsh
:
989 GetBool( maExtrusion
, aIter
.toView(), EAS_SecondLightHarsh
);
991 case EAS_extrusion_first_light_level
:
992 GetDoublePercentage( maExtrusion
, aIter
.toView(), EAS_FirstLightLevel
);
994 case EAS_extrusion_second_light_level
:
995 GetDoublePercentage( maExtrusion
, aIter
.toView(), EAS_SecondLightLevel
);
997 case EAS_extrusion_first_light_direction
:
998 GetB3DVector( maExtrusion
, aIter
.toView(), EAS_FirstLightDirection
);
1000 case EAS_extrusion_second_light_direction
:
1001 GetB3DVector( maExtrusion
, aIter
.toView(), EAS_SecondLightDirection
);
1003 case EAS_extrusion_metal
:
1004 GetBool( maExtrusion
, aIter
.toView(), EAS_Metal
);
1006 case EAS_extrusion_metal_type
:
1008 OUString rValue
= aIter
.toString();
1009 sal_Int16
eMetalType(drawing::EnhancedCustomShapeMetalType::MetalODF
);
1010 if (rValue
== "loext:MetalMSCompatible")
1011 eMetalType
= drawing::EnhancedCustomShapeMetalType::MetalMSCompatible
;
1012 beans::PropertyValue aProp
;
1013 aProp
.Name
= EASGet(EAS_MetalType
);
1014 aProp
.Value
<<= eMetalType
;
1015 maExtrusion
.push_back(aProp
);
1018 case EAS_shade_mode
:
1020 drawing::ShadeMode
eShadeMode( drawing::ShadeMode_FLAT
);
1021 if( IsXMLToken( aIter
, XML_PHONG
) )
1022 eShadeMode
= drawing::ShadeMode_PHONG
;
1023 else if ( IsXMLToken( aIter
, XML_GOURAUD
) )
1024 eShadeMode
= drawing::ShadeMode_SMOOTH
;
1025 else if ( IsXMLToken( aIter
, XML_DRAFT
) )
1026 eShadeMode
= drawing::ShadeMode_DRAFT
;
1028 beans::PropertyValue aProp
;
1029 aProp
.Name
= EASGet( EAS_ShadeMode
);
1030 aProp
.Value
<<= eShadeMode
;
1031 maExtrusion
.push_back( aProp
);
1034 case EAS_extrusion_rotation_angle
:
1035 GetEnhancedParameterPair( maExtrusion
, aIter
.toString(), EAS_RotateAngle
);
1037 case EAS_extrusion_rotation_center
:
1038 GetB3DVector( maExtrusion
, aIter
.toView(), EAS_RotationCenter
);
1040 case EAS_extrusion_shininess
:
1041 GetDoublePercentage( maExtrusion
, aIter
.toView(), EAS_Shininess
);
1043 case EAS_extrusion_skew
:
1044 GetEnhancedParameterPair( maExtrusion
, aIter
.toString(), EAS_Skew
);
1046 case EAS_extrusion_specularity
:
1047 if (!oSpecularityValue
)
1048 oSpecularityValue
= aIter
.toView();
1050 case EAS_extrusion_specularity_loext
:
1051 oSpecularityValue
= aIter
.toView();
1053 case EAS_projection
:
1055 drawing::ProjectionMode
eProjectionMode( drawing::ProjectionMode_PERSPECTIVE
);
1056 if( IsXMLToken( aIter
, XML_PARALLEL
) )
1057 eProjectionMode
= drawing::ProjectionMode_PARALLEL
;
1059 beans::PropertyValue aProp
;
1060 aProp
.Name
= EASGet( EAS_ProjectionMode
);
1061 aProp
.Value
<<= eProjectionMode
;
1062 maExtrusion
.push_back( aProp
);
1065 case EAS_extrusion_viewpoint
:
1066 GetPosition3D( maExtrusion
, aIter
.toView(), EAS_ViewPoint
, mrUnitConverter
);
1068 case EAS_extrusion_origin
:
1069 GetEnhancedParameterPair( maExtrusion
, aIter
.toString(), EAS_Origin
);
1071 case EAS_extrusion_color
:
1072 GetBool( maExtrusion
, aIter
.toView(), EAS_Color
);
1074 case EAS_enhanced_path
:
1075 oPathValue
= aIter
.toString();
1077 case EAS_path_stretchpoint_x
:
1079 if (::sax::Converter::convertNumber(nAttrNumber
, aIter
.toView()))
1081 beans::PropertyValue aProp
;
1082 aProp
.Name
= EASGet( EAS_StretchX
);
1083 aProp
.Value
<<= nAttrNumber
;
1084 maPath
.push_back( aProp
);
1088 case EAS_path_stretchpoint_y
:
1090 if (::sax::Converter::convertNumber(nAttrNumber
, aIter
.toView()))
1092 beans::PropertyValue aProp
;
1093 aProp
.Name
= EASGet( EAS_StretchY
);
1094 aProp
.Value
<<= nAttrNumber
;
1095 maPath
.push_back( aProp
);
1099 case EAS_text_areas
:
1100 GetEnhancedRectangleSequence( maPath
, aIter
.toString(), EAS_TextFrames
);
1102 case EAS_glue_points
:
1104 sal_Int32 i
, nPairs
= GetEnhancedParameterPairSequence( maPath
, aIter
.toString(), EAS_GluePoints
);
1105 GetImport().GetShapeImport()->moveGluePointMapping( mrxShape
, nPairs
);
1106 for ( i
= 0; i
< nPairs
; i
++ )
1107 GetImport().GetShapeImport()->addGluePointMapping( mrxShape
, i
+ 4, i
+ 4 );
1110 case EAS_glue_point_type
:
1111 GetEnum( maPath
, aIter
.toView(), EAS_GluePointType
, *aXML_GluePointEnumMap
);
1113 case EAS_glue_point_leaving_directions
:
1114 GetDoubleSequence( maPath
, aIter
.toView(), EAS_GluePointLeavingDirections
);
1116 case EAS_text_path
:
1117 GetBool( maTextPath
, aIter
.toView(), EAS_TextPath
);
1119 case EAS_text_path_mode
:
1121 css::drawing::EnhancedCustomShapeTextPathMode
eTextPathMode( css::drawing::EnhancedCustomShapeTextPathMode_NORMAL
);
1122 if( IsXMLToken( aIter
, XML_PATH
) )
1123 eTextPathMode
= css::drawing::EnhancedCustomShapeTextPathMode_PATH
;
1124 else if ( IsXMLToken( aIter
, XML_SHAPE
) )
1125 eTextPathMode
= css::drawing::EnhancedCustomShapeTextPathMode_SHAPE
;
1127 beans::PropertyValue aProp
;
1128 aProp
.Name
= EASGet( EAS_TextPathMode
);
1129 aProp
.Value
<<= eTextPathMode
;
1130 maTextPath
.push_back( aProp
);
1133 case EAS_text_path_scale
:
1135 bool bScaleX
= IsXMLToken( aIter
, XML_SHAPE
);
1136 beans::PropertyValue aProp
;
1137 aProp
.Name
= EASGet( EAS_ScaleX
);
1138 aProp
.Value
<<= bScaleX
;
1139 maTextPath
.push_back( aProp
);
1142 case EAS_text_path_same_letter_heights
:
1143 GetBool( maTextPath
, aIter
.toView(), EAS_SameLetterHeights
);
1145 case EAS_modifiers
:
1146 GetAdjustmentValues( mrCustomShapeGeometry
, aIter
.toString() );
1152 if (oSpecularityValue
)
1153 GetDouble( maExtrusion
, *oSpecularityValue
, EAS_Specularity
);
1155 GetEnhancedPath(maPath
, *oPathValue
, sType
);
1158 static void SdXMLCustomShapePropertyMerge( std::vector
< css::beans::PropertyValue
>& rPropVec
,
1159 const std::vector
< beans::PropertyValues
>& rElement
,
1160 const OUString
& rElementName
)
1162 if ( !rElement
.empty() )
1164 beans::PropertyValue aProp
;
1165 aProp
.Name
= rElementName
;
1166 aProp
.Value
<<= comphelper::containerToSequence(rElement
);
1167 rPropVec
.push_back( aProp
);
1171 static void SdXMLCustomShapePropertyMerge( std::vector
< css::beans::PropertyValue
>& rPropVec
,
1172 const std::vector
< OUString
>& rElement
,
1173 const OUString
& rElementName
)
1175 if ( !rElement
.empty() )
1177 beans::PropertyValue aProp
;
1178 aProp
.Name
= rElementName
;
1179 aProp
.Value
<<= comphelper::containerToSequence(rElement
);
1180 rPropVec
.push_back( aProp
);
1184 static void SdXMLCustomShapePropertyMerge( std::vector
< css::beans::PropertyValue
>& rPropVec
,
1185 const std::vector
< css::beans::PropertyValue
>& rElement
,
1186 const OUString
& rElementName
)
1188 if ( !rElement
.empty() )
1190 beans::PropertyValue aProp
;
1191 aProp
.Name
= rElementName
;
1192 aProp
.Value
<<= comphelper::containerToSequence(rElement
);
1193 rPropVec
.push_back( aProp
);
1197 typedef std::unordered_map
< OUString
, sal_Int32
> EquationHashMap
;
1199 /* if rPara.Type is from type EnhancedCustomShapeParameterType::EQUATION, the name of the equation
1200 will be converted from OUString to index */
1201 static void CheckAndResolveEquationParameter( css::drawing::EnhancedCustomShapeParameter
& rPara
, EquationHashMap
* pH
)
1203 if ( rPara
.Type
== css::drawing::EnhancedCustomShapeParameterType::EQUATION
)
1205 OUString aEquationName
;
1206 if ( rPara
.Value
>>= aEquationName
)
1208 sal_Int32 nIndex
= 0;
1209 EquationHashMap::iterator
aHashIter( pH
->find( aEquationName
) );
1210 if ( aHashIter
!= pH
->end() )
1211 nIndex
= (*aHashIter
).second
;
1212 rPara
.Value
<<= nIndex
;
1217 void XMLEnhancedCustomShapeContext::endFastElement(sal_Int32
)
1219 // resolve properties that are indexing an Equation
1220 if ( !maEquations
.empty() )
1222 // creating hash map containing the name and index of each equation
1224 std::vector
< OUString
>::iterator aEquationNameIter
= maEquationNames
.begin();
1225 std::vector
< OUString
>::iterator aEquationNameEnd
= maEquationNames
.end();
1226 while( aEquationNameIter
!= aEquationNameEnd
)
1228 aH
[ *aEquationNameIter
] = static_cast<sal_Int32
>( aEquationNameIter
- maEquationNames
.begin() );
1229 ++aEquationNameIter
;
1233 for( auto& rEquation
: maEquations
)
1235 sal_Int32 nIndexOf
= 0;
1238 nIndexOf
= rEquation
.indexOf( '?', nIndexOf
);
1239 if ( nIndexOf
!= -1 )
1241 OUString aEquationName
;
1242 if ( GetEquationName( rEquation
, nIndexOf
+ 1, aEquationName
) )
1244 // copying first characters inclusive '?'
1245 sal_Int32 nIndex
= 0;
1246 EquationHashMap::iterator
aHashIter( aH
.find( aEquationName
) );
1247 if ( aHashIter
!= aH
.end() )
1248 nIndex
= (*aHashIter
).second
;
1249 rEquation
= rEquation
.subView( 0, nIndexOf
+ 1 ) +
1250 OUString::number( nIndex
) +
1251 rEquation
.subView( nIndexOf
+ aEquationName
.getLength() + 1 );
1256 while( nIndexOf
!= -1 );
1260 for ( const beans::PropertyValue
& rPathItem
: maPath
)
1262 switch( EASGet( rPathItem
.Name
) )
1264 case EAS_Coordinates
:
1265 case EAS_GluePoints
:
1267 uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> const & rSeq
=
1268 *o3tl::doAccess
<uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> >(
1270 for ( const auto& rElem
: rSeq
)
1272 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.First
), &aH
);
1273 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.Second
), &aH
);
1277 case EAS_TextFrames
:
1279 uno::Sequence
< css::drawing::EnhancedCustomShapeTextFrame
> const & rSeq
=
1280 *o3tl::doAccess
<uno::Sequence
< css::drawing::EnhancedCustomShapeTextFrame
> >(
1282 for ( const auto& rElem
: rSeq
)
1284 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.TopLeft
.First
), &aH
);
1285 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.TopLeft
.Second
), &aH
);
1286 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.BottomRight
.First
), &aH
);
1287 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(rElem
.BottomRight
.Second
), &aH
);
1295 for ( css::beans::PropertyValues
const & aHandle
: maHandles
)
1297 for ( beans::PropertyValue
const & propValue
: aHandle
)
1299 switch( EASGet( propValue
.Name
) )
1301 case EAS_RangeYMinimum
:
1302 case EAS_RangeYMaximum
:
1303 case EAS_RangeXMinimum
:
1304 case EAS_RangeXMaximum
:
1305 case EAS_RadiusRangeMinimum
:
1306 case EAS_RadiusRangeMaximum
:
1308 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>(*o3tl::doAccess
<css::drawing::EnhancedCustomShapeParameter
>(
1309 propValue
.Value
)), &aH
);
1316 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>((*o3tl::doAccess
<css::drawing::EnhancedCustomShapeParameterPair
>(
1317 propValue
.Value
)).First
), &aH
);
1318 CheckAndResolveEquationParameter( const_cast<css::drawing::EnhancedCustomShapeParameter
&>((*o3tl::doAccess
<css::drawing::EnhancedCustomShapeParameterPair
>(
1319 propValue
.Value
)).Second
), &aH
);
1329 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry
, maExtrusion
, EASGet( EAS_Extrusion
) );
1330 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry
, maPath
, EASGet( EAS_Path
) );
1331 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry
, maTextPath
, EASGet( EAS_TextPath
) );
1332 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry
, maEquations
, EASGet( EAS_Equations
) );
1333 if ( !maHandles
.empty() )
1334 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry
, maHandles
, EASGet( EAS_Handles
) );
1337 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLEnhancedCustomShapeContext::createFastChildContext(
1339 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
1341 EnhancedCustomShapeTokenEnum aTokenEnum
= EASGet( nElement
);
1342 if ( aTokenEnum
== EAS_equation
)
1345 OUString aFormulaName
;
1346 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
1348 OUString sValue
= aIter
.toString();
1349 switch( EASGet( aIter
.getToken() ) )
1355 aFormulaName
= sValue
;
1361 if ( !aFormulaName
.isEmpty() || !aFormula
.isEmpty() )
1363 maEquations
.push_back( aFormula
);
1364 maEquationNames
.push_back( aFormulaName
);
1367 else if ( aTokenEnum
== EAS_handle
)
1369 // handle-position and handle-polar too is as pair in LO, ODF 1.4 has single values for
1370 // x-coordinate, y-coordinate, angle and radius. Postpone creation until all attributes
1373 OUString sPositionX
;
1374 OUString sPositionY
;
1376 OUString sPolarRadius
;
1377 OUString sPolarAngle
;
1378 OUString sPolarPoleX
;
1379 OUString sPolarPoleY
;
1380 std::vector
< css::beans::PropertyValue
> aHandle
;
1381 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
1383 switch( EASGet( aIter
.getToken() ) )
1385 case EAS_handle_mirror_vertical
:
1386 GetBool( aHandle
, aIter
.toView(), EAS_MirroredY
);
1388 case EAS_handle_mirror_horizontal
:
1389 GetBool( aHandle
, aIter
.toView(), EAS_MirroredX
);
1391 case EAS_handle_switched
:
1392 GetBool( aHandle
, aIter
.toView(), EAS_Switched
);
1394 case EAS_handle_position
:
1395 sPosition
= aIter
.toString();
1397 case EAS_handle_position_x
:
1398 sPositionX
= aIter
.toString();
1400 case EAS_handle_position_y
:
1401 sPositionY
= aIter
.toString();
1403 case EAS_handle_range_x_minimum
:
1404 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RangeXMinimum
);
1406 case EAS_handle_range_x_maximum
:
1407 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RangeXMaximum
);
1409 case EAS_handle_range_y_minimum
:
1410 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RangeYMinimum
);
1412 case EAS_handle_range_y_maximum
:
1413 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RangeYMaximum
);
1415 case EAS_handle_polar
:
1416 sPolar
= aIter
.toString();
1418 case EAS_handle_polar_angle
:
1419 sPolarAngle
= aIter
.toString();
1421 case EAS_handle_polar_radius
:
1422 sPolarRadius
= aIter
.toString();
1424 case EAS_handle_polar_pole_x
:
1425 sPolarPoleX
= aIter
.toString();
1427 case EAS_handle_polar_pole_y
:
1428 sPolarPoleY
= aIter
.toString();
1430 case EAS_handle_radius_range_minimum
:
1431 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RadiusRangeMinimum
);
1433 case EAS_handle_radius_range_maximum
:
1434 GetEnhancedParameter( aHandle
, aIter
.toString(), EAS_RadiusRangeMaximum
);
1441 // Use the new handle attributes if exists and ignore the old ones in that case.
1442 if (!sPositionX
.isEmpty() && !sPositionY
.isEmpty())
1445 sPosition
= sPositionX
+ u
" " + sPositionY
; // XY-handle
1447 if (!sPolarAngle
.isEmpty() && !sPolarRadius
.isEmpty())
1449 // a polar handle. It has attributes handle-position and handle-polar.
1450 sPosition
= sPolarRadius
+ u
" " + sPolarAngle
;
1451 sPolar
= sPolarPoleX
+ u
" " + sPolarPoleY
;
1453 if (!sPolar
.isEmpty())
1455 GetEnhancedParameterPair( aHandle
, sPolar
, EAS_Polar
);
1457 if (!sPosition
.isEmpty())
1459 GetEnhancedParameterPair( aHandle
, sPosition
, EAS_Position
);
1462 maHandles
.push_back( comphelper::containerToSequence(aHandle
) );
1467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */