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 <CommonConverters.hxx>
21 #include <com/sun/star/awt/Rectangle.hpp>
22 #include <com/sun/star/drawing/DoubleSequence.hpp>
23 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
24 #include <com/sun/star/chart2/data/XDataSequence.hpp>
25 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
26 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
27 #include <o3tl/safeint.hxx>
28 #include <osl/diagnose.h>
29 #include <basegfx/matrix/b3dhommatrix.hxx>
30 #include <basegfx/polygon/b2dpolygontools.hxx>
38 using namespace ::com::sun::star
;
40 // diverse methods for class conversions; e.g. ::basegfx::B3DHomMatrix to HomogenMatrix
42 drawing::HomogenMatrix
B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatrix
& rM
)
44 drawing::HomogenMatrix aHM
;
45 aHM
.Line1
.Column1
= rM
.get(0, 0);
46 aHM
.Line1
.Column2
= rM
.get(0, 1);
47 aHM
.Line1
.Column3
= rM
.get(0, 2);
48 aHM
.Line1
.Column4
= rM
.get(0, 3);
49 aHM
.Line2
.Column1
= rM
.get(1, 0);
50 aHM
.Line2
.Column2
= rM
.get(1, 1);
51 aHM
.Line2
.Column3
= rM
.get(1, 2);
52 aHM
.Line2
.Column4
= rM
.get(1, 3);
53 aHM
.Line3
.Column1
= rM
.get(2, 0);
54 aHM
.Line3
.Column2
= rM
.get(2, 1);
55 aHM
.Line3
.Column3
= rM
.get(2, 2);
56 aHM
.Line3
.Column4
= rM
.get(2, 3);
57 aHM
.Line4
.Column1
= rM
.get(3, 0);
58 aHM
.Line4
.Column2
= rM
.get(3, 1);
59 aHM
.Line4
.Column3
= rM
.get(3, 2);
60 aHM
.Line4
.Column4
= rM
.get(3, 3);
64 ::basegfx::B3DHomMatrix
HomogenMatrixToB3DHomMatrix( const drawing::HomogenMatrix
& rHM
)
66 ::basegfx::B3DHomMatrix aM
;
67 aM
.set(0, 0, rHM
.Line1
.Column1
);
68 aM
.set(0, 1, rHM
.Line1
.Column2
);
69 aM
.set(0, 2, rHM
.Line1
.Column3
);
70 aM
.set(0, 3, rHM
.Line1
.Column4
);
71 aM
.set(1, 0, rHM
.Line2
.Column1
);
72 aM
.set(1, 1, rHM
.Line2
.Column2
);
73 aM
.set(1, 2, rHM
.Line2
.Column3
);
74 aM
.set(1, 3, rHM
.Line2
.Column4
);
75 aM
.set(2, 0, rHM
.Line3
.Column1
);
76 aM
.set(2, 1, rHM
.Line3
.Column2
);
77 aM
.set(2, 2, rHM
.Line3
.Column3
);
78 aM
.set(2, 3, rHM
.Line3
.Column4
);
79 aM
.set(3, 0, rHM
.Line4
.Column1
);
80 aM
.set(3, 1, rHM
.Line4
.Column2
);
81 aM
.set(3, 2, rHM
.Line4
.Column3
);
82 aM
.set(3, 3, rHM
.Line4
.Column4
);
86 ::basegfx::B2DHomMatrix
IgnoreZ( const ::basegfx::B3DHomMatrix
& rM
)
88 ::basegfx::B2DHomMatrix aM
;
89 aM
.set(0, 0, rM
.get(0, 0));
90 aM
.set(0, 1, rM
.get(0, 1));
91 aM
.set(0, 2, rM
.get(0, 3));
92 aM
.set(1, 0, rM
.get(1, 0));
93 aM
.set(1, 1, rM
.get(1, 1));
94 aM
.set(1, 2, rM
.get(1, 3));
95 // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
96 assert( rM
.get(3, 0) == 0 );
97 assert( rM
.get(3, 1) == 0 );
98 assert( rM
.get(3, 3) == 1 );
102 drawing::HomogenMatrix3
B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMatrix
& rM
)
104 drawing::HomogenMatrix3 aHM
;
105 aHM
.Line1
.Column1
= rM
.get(0, 0);
106 aHM
.Line1
.Column2
= rM
.get(0, 1);
107 aHM
.Line1
.Column3
= rM
.get(0, 2);
108 aHM
.Line2
.Column1
= rM
.get(1, 0);
109 aHM
.Line2
.Column2
= rM
.get(1, 1);
110 aHM
.Line2
.Column3
= rM
.get(1, 2);
111 aHM
.Line3
.Column1
= 0;
112 aHM
.Line3
.Column2
= 0;
113 aHM
.Line3
.Column3
= 1;
117 ::basegfx::B3DPoint
Position3DToB3DPoint( const drawing::Position3D
& rPosition
)
119 return ::basegfx::B3DPoint(
120 rPosition
.PositionX
,
121 rPosition
.PositionY
,
122 rPosition
.PositionZ
);
125 drawing::Direction3D
B3DVectorToDirection3D( const ::basegfx::B3DVector
& rVector
)
127 return drawing::Direction3D(
134 drawing::Position3D
B3DPointToPosition3D( const ::basegfx::B3DPoint
& rPoint
)
136 return drawing::Position3D(
143 ::basegfx::B3DVector
Direction3DToB3DVector( const drawing::Direction3D
& rDirection
)
145 return ::basegfx::B3DVector(
146 rDirection
.DirectionX
147 , rDirection
.DirectionY
148 , rDirection
.DirectionZ
152 void AddPointToPoly( drawing::PolyPolygonShape3D
& rPoly
, const drawing::Position3D
& rPos
, sal_Int32 nPolygonIndex
)
156 OSL_FAIL( "The polygon index needs to be > 0");
160 //make sure that we have enough polygons
161 if(nPolygonIndex
>= rPoly
.SequenceX
.getLength() )
163 rPoly
.SequenceX
.realloc(nPolygonIndex
+1);
164 rPoly
.SequenceY
.realloc(nPolygonIndex
+1);
165 rPoly
.SequenceZ
.realloc(nPolygonIndex
+1);
168 drawing::DoubleSequence
* pOuterSequenceX
= &rPoly
.SequenceX
.getArray()[nPolygonIndex
];
169 drawing::DoubleSequence
* pOuterSequenceY
= &rPoly
.SequenceY
.getArray()[nPolygonIndex
];
170 drawing::DoubleSequence
* pOuterSequenceZ
= &rPoly
.SequenceZ
.getArray()[nPolygonIndex
];
172 sal_Int32 nOldPointCount
= pOuterSequenceX
->getLength();
174 pOuterSequenceX
->realloc(nOldPointCount
+1);
175 pOuterSequenceY
->realloc(nOldPointCount
+1);
176 pOuterSequenceZ
->realloc(nOldPointCount
+1);
178 double* pInnerSequenceX
= pOuterSequenceX
->getArray();
179 double* pInnerSequenceY
= pOuterSequenceY
->getArray();
180 double* pInnerSequenceZ
= pOuterSequenceZ
->getArray();
182 pInnerSequenceX
[nOldPointCount
] = rPos
.PositionX
;
183 pInnerSequenceY
[nOldPointCount
] = rPos
.PositionY
;
184 pInnerSequenceZ
[nOldPointCount
] = rPos
.PositionZ
;
187 void AddPointToPoly( std::vector
<std::vector
<css::drawing::Position3D
>>& rPoly
, const drawing::Position3D
& rPos
, sal_Int32 nPolygonIndex
)
191 OSL_FAIL( "The polygon index needs to be > 0");
195 //make sure that we have enough polygons
196 if(o3tl::make_unsigned(nPolygonIndex
) >= rPoly
.size() )
198 rPoly
.resize(nPolygonIndex
+1);
201 std::vector
<css::drawing::Position3D
>* pOuterSequence
= &rPoly
[nPolygonIndex
];
202 pOuterSequence
->push_back(rPos
);
205 drawing::Position3D
getPointFromPoly( const drawing::PolyPolygonShape3D
& rPolygon
, sal_Int32 nPointIndex
, sal_Int32 nPolyIndex
)
207 drawing::Position3D
aRet(0.0,0.0,0.0);
209 if( nPolyIndex
>=0 && nPolyIndex
<rPolygon
.SequenceX
.getLength())
211 if(nPointIndex
<rPolygon
.SequenceX
[nPolyIndex
].getLength())
213 aRet
.PositionX
= rPolygon
.SequenceX
[nPolyIndex
][nPointIndex
];
214 aRet
.PositionY
= rPolygon
.SequenceY
[nPolyIndex
][nPointIndex
];
215 aRet
.PositionZ
= rPolygon
.SequenceZ
[nPolyIndex
][nPointIndex
];
219 OSL_FAIL("polygon was accessed with a wrong index");
224 OSL_FAIL("polygon was accessed with a wrong index");
229 drawing::Position3D
getPointFromPoly( const std::vector
<std::vector
<css::drawing::Position3D
>>& rPolygon
, sal_Int32 nPointIndex
, sal_Int32 nPolyIndex
)
231 drawing::Position3D
aRet(0.0,0.0,0.0);
233 if( nPolyIndex
>=0 && o3tl::make_unsigned(nPolyIndex
)<rPolygon
.size())
235 if(nPointIndex
<static_cast<sal_Int32
>(rPolygon
[nPolyIndex
].size()))
237 aRet
= rPolygon
[nPolyIndex
][nPointIndex
];
241 OSL_FAIL("polygon was accessed with a wrong index");
246 OSL_FAIL("polygon was accessed with a wrong index");
251 void addPolygon( std::vector
<std::vector
<css::drawing::Position3D
>>& rRet
, const std::vector
<std::vector
<css::drawing::Position3D
>>& rAdd
)
253 sal_Int32 nAddOuterCount
= rAdd
.size();
254 sal_Int32 nOuterCount
= rRet
.size() + nAddOuterCount
;
255 rRet
.resize( nOuterCount
);
256 auto pSequence
= rRet
.data();
258 sal_Int32 nIndex
= 0;
259 sal_Int32 nOuter
= nOuterCount
- nAddOuterCount
;
260 for( ; nOuter
< nOuterCount
; nOuter
++ )
262 if( nIndex
>= nAddOuterCount
)
265 pSequence
[nOuter
] = rAdd
[nIndex
];
271 void appendPoly( std::vector
<std::vector
<css::drawing::Position3D
>>& rRet
, const std::vector
<std::vector
<css::drawing::Position3D
>>& rAdd
)
273 std::size_t nOuterCount
= std::max( rRet
.size(), rAdd
.size() );
274 rRet
.resize(nOuterCount
);
275 auto pSequence
= rRet
.data();
277 for( std::size_t nOuter
=0;nOuter
<nOuterCount
;nOuter
++ )
279 sal_Int32 nOldPointCount
= rRet
[nOuter
].size();
280 sal_Int32 nAddPointCount
= 0;
281 if(nOuter
<rAdd
.size())
282 nAddPointCount
= rAdd
[nOuter
].size();
286 sal_Int32 nNewPointCount
= nOldPointCount
+ nAddPointCount
;
288 pSequence
[nOuter
].resize(nNewPointCount
);
289 auto pSequence_nOuter
= pSequence
[nOuter
].data();
291 sal_Int32 nPointTarget
=nOldPointCount
;
292 sal_Int32 nPointSource
=nAddPointCount
;
293 for( ; nPointSource
-- ; nPointTarget
++ )
295 pSequence_nOuter
[nPointTarget
] = rAdd
[nOuter
][nPointSource
];
300 drawing::PolyPolygonShape3D
BezierToPoly(
301 const drawing::PolyPolygonBezierCoords
& rBezier
)
303 const drawing::PointSequenceSequence
& rPointSequence
= rBezier
.Coordinates
;
305 drawing::PolyPolygonShape3D aRet
;
306 aRet
.SequenceX
.realloc( rPointSequence
.getLength() );
307 auto pSequenceX
= aRet
.SequenceX
.getArray();
308 aRet
.SequenceY
.realloc( rPointSequence
.getLength() );
309 auto pSequenceY
= aRet
.SequenceY
.getArray();
310 aRet
.SequenceZ
.realloc( rPointSequence
.getLength() );
311 auto pSequenceZ
= aRet
.SequenceZ
.getArray();
313 sal_Int32 nRealOuter
= 0;
314 for(sal_Int32 nN
= 0; nN
< rPointSequence
.getLength(); nN
++)
316 sal_Int32 nInnerLength
= rPointSequence
[nN
].getLength();
317 pSequenceX
[nRealOuter
].realloc( nInnerLength
);
318 auto pSequenceX_nRealOuter
= pSequenceX
[nRealOuter
].getArray();
319 pSequenceY
[nRealOuter
].realloc( nInnerLength
);
320 auto pSequenceY_nRealOuter
= pSequenceY
[nRealOuter
].getArray();
321 pSequenceZ
[nRealOuter
].realloc( nInnerLength
);
322 auto pSequenceZ_nRealOuter
= pSequenceZ
[nRealOuter
].getArray();
324 bool bHasOuterFlags
= nN
< rBezier
.Flags
.getLength();
326 sal_Int32 nRealInner
= 0;
327 for( sal_Int32 nM
= 0; nM
< nInnerLength
; nM
++)
329 bool bHasInnerFlags
= bHasOuterFlags
&& (nM
< rBezier
.Flags
[nN
].getLength());
331 if( !bHasInnerFlags
|| (rBezier
.Flags
[nN
][nM
] == drawing::PolygonFlags_NORMAL
) )
333 pSequenceX_nRealOuter
[nRealInner
] = rPointSequence
[nN
][nM
].X
;
334 pSequenceY_nRealOuter
[nRealInner
] = rPointSequence
[nN
][nM
].Y
;
335 pSequenceZ_nRealOuter
[nRealInner
] = 0.0;
340 pSequenceX
[nRealOuter
].realloc( nRealInner
);
341 pSequenceY
[nRealOuter
].realloc( nRealInner
);
342 pSequenceZ
[nRealOuter
].realloc( nRealInner
);
348 aRet
.SequenceX
.realloc( nRealOuter
);
349 aRet
.SequenceY
.realloc( nRealOuter
);
350 aRet
.SequenceZ
.realloc( nRealOuter
);
355 drawing::PointSequenceSequence
PolyToPointSequence(
356 const drawing::PolyPolygonShape3D
& rPolyPolygon
)
358 drawing::PointSequenceSequence aRet
;
359 aRet
.realloc( rPolyPolygon
.SequenceX
.getLength() );
360 auto pRet
= aRet
.getArray();
362 for(sal_Int32 nN
= 0; nN
< rPolyPolygon
.SequenceX
.getLength(); nN
++)
364 sal_Int32 nInnerLength
= rPolyPolygon
.SequenceX
[nN
].getLength();
365 pRet
[nN
].realloc( nInnerLength
);
366 auto pRet_nN
= pRet
[nN
].getArray();
367 for( sal_Int32 nM
= 0; nM
< nInnerLength
; nM
++)
369 pRet_nN
[nM
].X
= static_cast<sal_Int32
>(rPolyPolygon
.SequenceX
[nN
][nM
]);
370 pRet_nN
[nM
].Y
= static_cast<sal_Int32
>(rPolyPolygon
.SequenceY
[nN
][nM
]);
376 drawing::PointSequenceSequence
PolyToPointSequence(
377 const std::vector
<std::vector
<css::drawing::Position3D
>>& rPolyPolygon
)
379 drawing::PointSequenceSequence aRet
;
380 aRet
.realloc( rPolyPolygon
.size() );
381 auto pRet
= aRet
.getArray();
383 for(std::size_t nN
= 0; nN
< rPolyPolygon
.size(); nN
++)
385 sal_Int32 nInnerLength
= rPolyPolygon
[nN
].size();
386 pRet
[nN
].realloc( nInnerLength
);
387 auto pRet_nN
= pRet
[nN
].getArray();
388 for( sal_Int32 nM
= 0; nM
< nInnerLength
; nM
++)
390 pRet_nN
[nM
].X
= static_cast<sal_Int32
>(rPolyPolygon
[nN
][nM
].PositionX
);
391 pRet_nN
[nM
].Y
= static_cast<sal_Int32
>(rPolyPolygon
[nN
][nM
].PositionY
);
397 basegfx::B2DPolyPolygon
PolyToB2DPolyPolygon(
398 const std::vector
<std::vector
<css::drawing::Position3D
>>& rPolyPolygon
)
400 basegfx::B2DPolyPolygon aRetval
;
402 for(auto const & nN
: rPolyPolygon
)
404 basegfx::B2DPolygon aNewPolygon
;
405 sal_Int32 nInnerLength
= nN
.size();
408 aNewPolygon
.reserve(nInnerLength
);
409 for( sal_Int32 nM
= 0; nM
< nInnerLength
; nM
++)
411 auto X
= static_cast<sal_Int32
>(nN
[nM
].PositionX
);
412 auto Y
= static_cast<sal_Int32
>(nN
[nM
].PositionY
);
413 aNewPolygon
.append(basegfx::B2DPoint(X
, Y
));
415 // check for closed state flag
416 basegfx::utils::checkClosed(aNewPolygon
);
418 aRetval
.append(std::move(aNewPolygon
));
424 void appendPointSequence( drawing::PointSequenceSequence
& rTarget
425 , const drawing::PointSequenceSequence
& rAdd
)
427 sal_Int32 nAddCount
= rAdd
.getLength();
430 sal_Int32 nOldCount
= rTarget
.getLength();
432 rTarget
.realloc(nOldCount
+nAddCount
);
433 auto pTarget
= rTarget
.getArray();
434 for(sal_Int32 nS
=0; nS
<nAddCount
; nS
++ )
435 pTarget
[nOldCount
+nS
]=rAdd
[nS
];
438 drawing::Position3D
operator+( const drawing::Position3D
& rPos
439 , const drawing::Direction3D
& rDirection
)
441 return drawing::Position3D(
442 rPos
.PositionX
+ rDirection
.DirectionX
443 , rPos
.PositionY
+ rDirection
.DirectionY
444 , rPos
.PositionZ
+ rDirection
.DirectionZ
448 drawing::Direction3D
operator-( const drawing::Position3D
& rPos1
449 , const drawing::Position3D
& rPos2
)
451 return drawing::Direction3D(
452 rPos1
.PositionX
- rPos2
.PositionX
453 , rPos1
.PositionY
- rPos2
.PositionY
454 , rPos1
.PositionZ
- rPos2
.PositionZ
458 awt::Point
Position3DToAWTPoint( const drawing::Position3D
& rPos
)
461 aRet
.X
= static_cast<sal_Int32
>(rPos
.PositionX
);
462 aRet
.Y
= static_cast<sal_Int32
>(rPos
.PositionY
);
466 awt::Point
ToPoint( const awt::Rectangle
& rRectangle
)
468 return awt::Point( rRectangle
.X
, rRectangle
.Y
);
471 awt::Size
ToSize( const awt::Rectangle
& rRectangle
)
473 return awt::Size( rRectangle
.Width
, rRectangle
.Height
);
476 awt::Size
Direction3DToAWTSize( const drawing::Direction3D
& rDirection
)
479 aRet
.Width
= static_cast<sal_Int32
>(rDirection
.DirectionX
);
480 aRet
.Height
= static_cast<sal_Int32
>(rDirection
.DirectionY
);
484 drawing::Position3D
SequenceToPosition3D( const uno::Sequence
< double >& rSeq
)
486 OSL_ENSURE(rSeq
.getLength()==3,"The sequence needs to have length 3 for conversion into vector");
488 drawing::Position3D aRet
;
489 aRet
.PositionX
= rSeq
.getLength()>0?rSeq
[0]:0.0;
490 aRet
.PositionY
= rSeq
.getLength()>1?rSeq
[1]:0.0;
491 aRet
.PositionZ
= rSeq
.getLength()>2?rSeq
[2]:0.0;
495 using namespace ::com::sun::star::chart2
;
497 uno::Sequence
< double > DataSequenceToDoubleSequence(
498 const uno::Reference
< data::XDataSequence
>& xDataSequence
)
500 uno::Sequence
< double > aResult
;
501 OSL_ASSERT( xDataSequence
.is());
502 if(!xDataSequence
.is())
505 uno::Reference
< data::XNumericalDataSequence
> xNumericalDataSequence( xDataSequence
, uno::UNO_QUERY
);
506 if( xNumericalDataSequence
.is() )
508 aResult
= xNumericalDataSequence
->getNumericalData();
512 uno::Sequence
< uno::Any
> aValues
= xDataSequence
->getData();
513 aResult
.realloc(aValues
.getLength());
514 auto pResult
= aResult
.getArray();
515 for(sal_Int32 nN
=aValues
.getLength();nN
--;)
517 if( !(aValues
[nN
] >>= pResult
[nN
]) )
518 pResult
[nN
] = std::numeric_limits
<double>::quiet_NaN();
525 uno::Sequence
< OUString
> DataSequenceToStringSequence(
526 const uno::Reference
< data::XDataSequence
>& xDataSequence
)
528 uno::Sequence
< OUString
> aResult
;
529 if(!xDataSequence
.is())
532 uno::Reference
< data::XTextualDataSequence
> xTextualDataSequence( xDataSequence
, uno::UNO_QUERY
);
533 if( xTextualDataSequence
.is() )
535 aResult
= xTextualDataSequence
->getTextualData();
539 uno::Sequence
< uno::Any
> aValues
= xDataSequence
->getData();
540 aResult
.realloc(aValues
.getLength());
541 auto pResult
= aResult
.getArray();
543 for(sal_Int32 nN
=aValues
.getLength();nN
--;)
544 aValues
[nN
] >>= pResult
[nN
];
550 bool hasDoubleValue( const uno::Any
& rAny
)
554 if( rAny
>>= fValue
)
559 bool hasLongOrShortValue( const uno::Any
& rAny
)
573 sal_Int16
getShortForLongAlso( const uno::Any
& rAny
)
577 if( !(rAny
>>= nRet
) )
581 nRet
= static_cast<sal_Int16
>(n32
);
586 bool replaceParamterInString( OUString
& rInOutResourceString
,
587 std::u16string_view rParamToReplace
,
588 std::u16string_view rReplaceWith
)
590 sal_Int32 nPos
= rInOutResourceString
.indexOf( rParamToReplace
);
594 rInOutResourceString
= rInOutResourceString
.replaceAt( nPos
595 , rParamToReplace
.size(), rReplaceWith
);
601 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */