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 <com/sun/star/geometry/RealSize2D.hpp>
21 #include <com/sun/star/geometry/RealPoint2D.hpp>
22 #include <com/sun/star/geometry/RealRectangle2D.hpp>
23 #include <com/sun/star/geometry/RealRectangle3D.hpp>
24 #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
25 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
26 #include <com/sun/star/geometry/AffineMatrix3D.hpp>
27 #include <com/sun/star/geometry/IntegerSize2D.hpp>
28 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
31 #include <com/sun/star/rendering/XGraphicDevice.hpp>
32 #include <com/sun/star/awt/Rectangle.hpp>
33 #include <basegfx/utils/unopolypolygon.hxx>
34 #include <basegfx/matrix/b2dhommatrix.hxx>
35 #include <basegfx/matrix/b3dhommatrix.hxx>
36 #include <basegfx/point/b2dpoint.hxx>
37 #include <basegfx/vector/b2dsize.hxx>
38 #include <basegfx/vector/b2ivector.hxx>
39 #include <basegfx/range/b3drange.hxx>
40 #include <basegfx/range/b2irange.hxx>
41 #include <basegfx/polygon/b2dpolygon.hxx>
42 #include <basegfx/polygon/b2dpolypolygon.hxx>
43 #include <basegfx/utils/canvastools.hxx>
45 using namespace ::com::sun::star
;
47 namespace basegfx::unotools
51 uno::Sequence
< geometry::RealBezierSegment2D
> bezierSequenceFromB2DPolygon(const ::basegfx::B2DPolygon
& rPoly
)
53 const sal_uInt32
nPointCount(rPoly
.count());
54 uno::Sequence
< geometry::RealBezierSegment2D
> outputSequence(nPointCount
);
55 geometry::RealBezierSegment2D
* pOutput
= outputSequence
.getArray();
57 // fill sequences and imply closed polygon on this implementation layer
58 for(sal_uInt32
a(0); a
< nPointCount
; a
++)
60 const basegfx::B2DPoint
aStart(rPoly
.getB2DPoint(a
));
61 const basegfx::B2DPoint
aControlA(rPoly
.getNextControlPoint(a
));
62 const basegfx::B2DPoint
aControlB(rPoly
.getPrevControlPoint((a
+ 1) % nPointCount
));
64 pOutput
[a
] = geometry::RealBezierSegment2D(
65 aStart
.getX(), aStart
.getY(),
66 aControlA
.getX(), aControlA
.getY(),
67 aControlB
.getX(), aControlB
.getY());
70 return outputSequence
;
73 uno::Sequence
< geometry::RealPoint2D
> pointSequenceFromB2DPolygon( const ::basegfx::B2DPolygon
& rPoly
)
75 const sal_uInt32
nNumPoints( rPoly
.count() );
77 uno::Sequence
< geometry::RealPoint2D
> outputSequence( nNumPoints
);
78 geometry::RealPoint2D
* pOutput
= outputSequence
.getArray();
80 // fill sequence from polygon
82 for( i
=0; i
<nNumPoints
; ++i
)
84 const ::basegfx::B2DPoint
aPoint( rPoly
.getB2DPoint(i
) );
86 pOutput
[i
] = geometry::RealPoint2D( aPoint
.getX(),
90 return outputSequence
;
94 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
96 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
99 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence( nNumPolies
);
100 uno::Sequence
< geometry::RealBezierSegment2D
>* pOutput
= outputSequence
.getArray();
102 for( i
=0; i
<nNumPolies
; ++i
)
104 pOutput
[i
] = bezierSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
107 return outputSequence
;
110 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
112 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
115 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence( nNumPolies
);
116 uno::Sequence
< geometry::RealPoint2D
>* pOutput
= outputSequence
.getArray();
118 for( i
=0; i
<nNumPolies
; ++i
)
120 pOutput
[i
] = pointSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
123 return outputSequence
;
126 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
127 const ::basegfx::B2DPolygon
& rPoly
)
129 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
131 if( !xGraphicDevice
.is() )
134 if( rPoly
.areControlPointsUsed() )
136 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence
{ bezierSequenceFromB2DPolygon( rPoly
)};
138 xRes
= xGraphicDevice
->createCompatibleBezierPolyPolygon( outputSequence
);
142 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence
{
143 pointSequenceFromB2DPolygon( rPoly
)};
145 xRes
= xGraphicDevice
->createCompatibleLinePolyPolygon( outputSequence
);
148 if( xRes
.is() && rPoly
.isClosed() )
149 xRes
->setClosed( 0, true );
154 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolyPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
155 const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
157 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
159 if( !xGraphicDevice
.is() )
162 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
165 if( rPolyPoly
.areControlPointsUsed() )
167 xRes
= xGraphicDevice
->createCompatibleBezierPolyPolygon(
168 bezierSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) );
172 xRes
= xGraphicDevice
->createCompatibleLinePolyPolygon(
173 pointSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) );
176 for( i
=0; i
<nNumPolies
; ++i
)
178 xRes
->setClosed( i
, rPolyPoly
.getB2DPolygon(i
).isClosed() );
184 ::basegfx::B2DPolygon
polygonFromPoint2DSequence( const uno::Sequence
< geometry::RealPoint2D
>& points
)
186 const sal_Int32
nCurrSize( points
.getLength() );
188 ::basegfx::B2DPolygon aPoly
;
190 for( sal_Int32 nCurrPoint
=0; nCurrPoint
<nCurrSize
; ++nCurrPoint
)
191 aPoly
.append( b2DPointFromRealPoint2D( points
[nCurrPoint
] ) );
196 ::basegfx::B2DPolyPolygon
polyPolygonFromPoint2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> >& points
)
198 ::basegfx::B2DPolyPolygon aRes
;
200 for( const auto & p
: points
)
202 aRes
.append( polygonFromPoint2DSequence( p
) );
208 ::basegfx::B2DPolygon
polygonFromBezier2DSequence( const uno::Sequence
< geometry::RealBezierSegment2D
>& curves
)
210 const sal_Int32
nSize(curves
.getLength());
211 basegfx::B2DPolygon aRetval
;
215 // prepare start with providing a start point. Use the first point from
216 // the sequence for this
217 const geometry::RealBezierSegment2D
& rFirstSegment(curves
[0]); // #i79917# first segment, not last
218 aRetval
.append(basegfx::B2DPoint(rFirstSegment
.Px
, rFirstSegment
.Py
));
220 for(sal_Int32
a(0); a
< nSize
; a
++)
222 const geometry::RealBezierSegment2D
& rCurrSegment(curves
[a
]);
223 const geometry::RealBezierSegment2D
& rNextSegment(curves
[(a
+ 1) % nSize
]);
225 // append curved edge with the control points and the next point
226 aRetval
.appendBezierSegment(
227 basegfx::B2DPoint(rCurrSegment
.C1x
, rCurrSegment
.C1y
),
228 basegfx::B2DPoint(rCurrSegment
.C2x
, rCurrSegment
.C2y
), // #i79917# Argh! An x for an y!!
229 basegfx::B2DPoint(rNextSegment
.Px
, rNextSegment
.Py
));
232 // rescue the control point and remove the now double-added point
233 aRetval
.setPrevControlPoint(0, aRetval
.getPrevControlPoint(aRetval
.count() - 1));
234 aRetval
.remove(aRetval
.count() - 1);
240 ::basegfx::B2DPolyPolygon
polyPolygonFromBezier2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> >& curves
)
242 ::basegfx::B2DPolyPolygon aRes
;
244 for( const auto & c
: curves
)
246 aRes
.append( polygonFromBezier2DSequence( c
) );
252 ::basegfx::B2DPolyPolygon
b2DPolyPolygonFromXPolyPolygon2D( const uno::Reference
< rendering::XPolyPolygon2D
>& xPoly
)
254 ::basegfx::unotools::UnoPolyPolygon
* pPolyImpl
=
255 dynamic_cast< ::basegfx::unotools::UnoPolyPolygon
* >( xPoly
.get() );
259 return pPolyImpl
->getPolyPolygon();
263 // not a known implementation object - try data source
265 const sal_Int32
nPolys( xPoly
->getNumberOfPolygons() );
267 uno::Reference
< rendering::XBezierPolyPolygon2D
> xBezierPoly(
271 if( xBezierPoly
.is() )
273 return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
274 xBezierPoly
->getBezierSegments( 0,
281 uno::Reference
< rendering::XLinePolyPolygon2D
> xLinePoly(
285 // no implementation class and no data provider
286 // found - contract violation.
287 if( !xLinePoly
.is() )
289 throw lang::IllegalArgumentException(
290 "basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(): Invalid input"
291 "poly-polygon, cannot retrieve vertex data",
292 uno::Reference
< uno::XInterface
>(),
296 return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
297 xLinePoly
->getPoints( 0,
305 ::basegfx::B2DHomMatrix
& homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix
& output
,
306 const geometry::AffineMatrix2D
& input
)
308 // ensure last row is [0,0,1] (and optimized away)
311 output
.set(0,0, input
.m00
);
312 output
.set(0,1, input
.m01
);
313 output
.set(0,2, input
.m02
);
314 output
.set(1,0, input
.m10
);
315 output
.set(1,1, input
.m11
);
316 output
.set(1,2, input
.m12
);
321 ::basegfx::B3DHomMatrix
homMatrixFromAffineMatrix3D( const ::css::geometry::AffineMatrix3D
& input
)
323 ::basegfx::B3DHomMatrix output
;
325 output
.set(0,0, input
.m00
);
326 output
.set(0,1, input
.m01
);
327 output
.set(0,2, input
.m02
);
328 output
.set(0,3, input
.m03
);
330 output
.set(1,0, input
.m10
);
331 output
.set(1,1, input
.m11
);
332 output
.set(1,2, input
.m12
);
333 output
.set(1,3, input
.m13
);
335 output
.set(2,0, input
.m20
);
336 output
.set(2,1, input
.m21
);
337 output
.set(2,2, input
.m22
);
338 output
.set(2,3, input
.m23
);
343 geometry::AffineMatrix2D
& affineMatrixFromHomMatrix( geometry::AffineMatrix2D
& output
,
344 const ::basegfx::B2DHomMatrix
& input
)
346 output
.m00
= input
.get(0,0);
347 output
.m01
= input
.get(0,1);
348 output
.m02
= input
.get(0,2);
349 output
.m10
= input
.get(1,0);
350 output
.m11
= input
.get(1,1);
351 output
.m12
= input
.get(1,2);
356 geometry::AffineMatrix3D
& affineMatrixFromHomMatrix3D(
357 geometry::AffineMatrix3D
& output
,
358 const ::basegfx::B3DHomMatrix
& input
)
360 output
.m00
= input
.get(0,0);
361 output
.m01
= input
.get(0,1);
362 output
.m02
= input
.get(0,2);
363 output
.m03
= input
.get(0,3);
365 output
.m10
= input
.get(1,0);
366 output
.m11
= input
.get(1,1);
367 output
.m12
= input
.get(1,2);
368 output
.m13
= input
.get(1,3);
370 output
.m20
= input
.get(2,0);
371 output
.m21
= input
.get(2,1);
372 output
.m22
= input
.get(2,2);
373 output
.m23
= input
.get(2,3);
378 geometry::RealSize2D
size2DFromB2DSize(const ::basegfx::B2DSize
& rSize
)
380 return geometry::RealSize2D(rSize
.getWidth(), rSize
.getHeight());
383 geometry::RealPoint2D
point2DFromB2DPoint( const ::basegfx::B2DPoint
& rPoint
)
385 return geometry::RealPoint2D( rPoint
.getX(),
389 geometry::RealRectangle2D
rectangle2DFromB2DRectangle( const ::basegfx::B2DRange
& rRect
)
391 return geometry::RealRectangle2D( rRect
.getMinX(),
397 geometry::RealRectangle3D
rectangle3DFromB3DRectangle( const ::basegfx::B3DRange
& rRect
)
399 return geometry::RealRectangle3D( rRect
.getMinX(),
407 ::basegfx::B2DPoint
b2DPointFromRealPoint2D( const geometry::RealPoint2D
& rPoint
)
409 return ::basegfx::B2DPoint( rPoint
.X
,
413 ::basegfx::B2DRange
b2DRectangleFromRealRectangle2D( const geometry::RealRectangle2D
& rRect
)
415 return ::basegfx::B2DRange( rRect
.X1
,
421 ::basegfx::B3DRange
b3DRectangleFromRealRectangle3D( const geometry::RealRectangle3D
& rRect
)
423 return ::basegfx::B3DRange( rRect
.X1
,
431 geometry::IntegerSize2D
integerSize2DFromB2ISize( const ::basegfx::B2ISize
& rSize
)
433 return geometry::IntegerSize2D( rSize
.getWidth(),
437 basegfx::B2ISize
b2ISizeFromIntegerSize2D( const geometry::IntegerSize2D
& rSize
)
439 return basegfx::B2ISize(rSize
.Width
, rSize
.Height
);
442 ::basegfx::B2IRange
b2IRectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D
& rRectangle
)
444 return ::basegfx::B2IRange( rRectangle
.X1
, rRectangle
.Y1
,
445 rRectangle
.X2
, rRectangle
.Y2
);
448 ::basegfx::B2IRange
b2IRectangleFromAwtRectangle( const awt::Rectangle
& rRect
)
450 return ::basegfx::B2IRange( rRect
.X
,
452 rRect
.X
+ rRect
.Width
,
453 rRect
.Y
+ rRect
.Height
);
456 ::basegfx::B2IRange
b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
458 return ::basegfx::B2IRange( static_cast<sal_Int32
>( floor(rRange
.getMinX()) ),
459 static_cast<sal_Int32
>( floor(rRange
.getMinY()) ),
460 static_cast<sal_Int32
>( ceil(rRange
.getMaxX()) ),
461 static_cast<sal_Int32
>( ceil(rRange
.getMaxY()) ) );
464 ::basegfx::B2DRange
b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
466 return ::basegfx::B2DRange( floor(rRange
.getMinX()),
467 floor(rRange
.getMinY()),
468 ceil(rRange
.getMaxX()),
469 ceil(rRange
.getMaxY()) );
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */