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/range/b3drange.hxx>
38 #include <basegfx/range/b2irange.hxx>
39 #include <basegfx/polygon/b2dpolygon.hxx>
40 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 #include <basegfx/utils/canvastools.hxx>
43 using namespace ::com::sun::star
;
52 uno::Sequence
< geometry::RealBezierSegment2D
> bezierSequenceFromB2DPolygon(const ::basegfx::B2DPolygon
& rPoly
)
54 const sal_uInt32
nPointCount(rPoly
.count());
55 uno::Sequence
< geometry::RealBezierSegment2D
> outputSequence(nPointCount
);
56 geometry::RealBezierSegment2D
* pOutput
= outputSequence
.getArray();
58 // fill sequences and imply closed polygon on this implementation layer
59 for(sal_uInt32
a(0); a
< nPointCount
; a
++)
61 const basegfx::B2DPoint
aStart(rPoly
.getB2DPoint(a
));
62 const basegfx::B2DPoint
aControlA(rPoly
.getNextControlPoint(a
));
63 const basegfx::B2DPoint
aControlB(rPoly
.getPrevControlPoint((a
+ 1) % nPointCount
));
65 pOutput
[a
] = geometry::RealBezierSegment2D(
66 aStart
.getX(), aStart
.getY(),
67 aControlA
.getX(), aControlA
.getY(),
68 aControlB
.getX(), aControlB
.getY());
71 return outputSequence
;
74 uno::Sequence
< geometry::RealPoint2D
> pointSequenceFromB2DPolygon( const ::basegfx::B2DPolygon
& rPoly
)
76 const sal_uInt32
nNumPoints( rPoly
.count() );
78 uno::Sequence
< geometry::RealPoint2D
> outputSequence( nNumPoints
);
79 geometry::RealPoint2D
* pOutput
= outputSequence
.getArray();
81 // fill sequence from polygon
83 for( i
=0; i
<nNumPoints
; ++i
)
85 const ::basegfx::B2DPoint
aPoint( rPoly
.getB2DPoint(i
) );
87 pOutput
[i
] = geometry::RealPoint2D( aPoint
.getX(),
91 return outputSequence
;
95 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
97 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
100 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence( nNumPolies
);
101 uno::Sequence
< geometry::RealBezierSegment2D
>* pOutput
= outputSequence
.getArray();
103 for( i
=0; i
<nNumPolies
; ++i
)
105 pOutput
[i
] = bezierSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
108 return outputSequence
;
111 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
113 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
116 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence( nNumPolies
);
117 uno::Sequence
< geometry::RealPoint2D
>* pOutput
= outputSequence
.getArray();
119 for( i
=0; i
<nNumPolies
; ++i
)
121 pOutput
[i
] = pointSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
124 return outputSequence
;
127 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
128 const ::basegfx::B2DPolygon
& rPoly
)
130 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
132 if( !xGraphicDevice
.is() )
135 if( rPoly
.areControlPointsUsed() )
137 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence( 1 );
138 outputSequence
[0] = bezierSequenceFromB2DPolygon( rPoly
);
140 xRes
= xGraphicDevice
->createCompatibleBezierPolyPolygon( outputSequence
);
144 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence( 1 );
145 outputSequence
[0] = pointSequenceFromB2DPolygon( rPoly
);
147 xRes
= xGraphicDevice
->createCompatibleLinePolyPolygon( outputSequence
);
150 if( xRes
.is() && rPoly
.isClosed() )
151 xRes
->setClosed( 0, true );
156 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolyPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
157 const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
159 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
161 if( !xGraphicDevice
.is() )
164 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
167 if( rPolyPoly
.areControlPointsUsed() )
169 xRes
= xGraphicDevice
->createCompatibleBezierPolyPolygon(
170 bezierSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) );
174 xRes
= xGraphicDevice
->createCompatibleLinePolyPolygon(
175 pointSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) );
178 for( i
=0; i
<nNumPolies
; ++i
)
180 xRes
->setClosed( i
, rPolyPoly
.getB2DPolygon(i
).isClosed() );
186 ::basegfx::B2DPolygon
polygonFromPoint2DSequence( const uno::Sequence
< geometry::RealPoint2D
>& points
)
188 const sal_Int32
nCurrSize( points
.getLength() );
190 ::basegfx::B2DPolygon aPoly
;
192 for( sal_Int32 nCurrPoint
=0; nCurrPoint
<nCurrSize
; ++nCurrPoint
)
193 aPoly
.append( b2DPointFromRealPoint2D( points
[nCurrPoint
] ) );
198 ::basegfx::B2DPolyPolygon
polyPolygonFromPoint2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> >& points
)
200 ::basegfx::B2DPolyPolygon aRes
;
202 for( sal_Int32 nCurrPoly
=0; nCurrPoly
<points
.getLength(); ++nCurrPoly
)
204 aRes
.append( polygonFromPoint2DSequence( points
[nCurrPoly
] ) );
210 ::basegfx::B2DPolygon
polygonFromBezier2DSequence( const uno::Sequence
< geometry::RealBezierSegment2D
>& curves
)
212 const sal_Int32
nSize(curves
.getLength());
213 basegfx::B2DPolygon aRetval
;
217 // prepare start with providing a start point. Use the first point from
218 // the sequence for this
219 const geometry::RealBezierSegment2D
& rFirstSegment(curves
[0]); // #i79917# first segment, not last
220 aRetval
.append(basegfx::B2DPoint(rFirstSegment
.Px
, rFirstSegment
.Py
));
222 for(sal_Int32
a(0); a
< nSize
; a
++)
224 const geometry::RealBezierSegment2D
& rCurrSegment(curves
[a
]);
225 const geometry::RealBezierSegment2D
& rNextSegment(curves
[(a
+ 1) % nSize
]);
227 // append curved edge with the control points and the next point
228 aRetval
.appendBezierSegment(
229 basegfx::B2DPoint(rCurrSegment
.C1x
, rCurrSegment
.C1y
),
230 basegfx::B2DPoint(rCurrSegment
.C2x
, rCurrSegment
.C2y
), // #i79917# Argh! An x for an y!!
231 basegfx::B2DPoint(rNextSegment
.Px
, rNextSegment
.Py
));
234 // rescue the control point and remove the now double-added point
235 aRetval
.setPrevControlPoint(0, aRetval
.getPrevControlPoint(aRetval
.count() - 1));
236 aRetval
.remove(aRetval
.count() - 1);
242 ::basegfx::B2DPolyPolygon
polyPolygonFromBezier2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> >& curves
)
244 ::basegfx::B2DPolyPolygon aRes
;
246 for( sal_Int32 nCurrPoly
=0; nCurrPoly
<curves
.getLength(); ++nCurrPoly
)
248 aRes
.append( polygonFromBezier2DSequence( curves
[nCurrPoly
] ) );
254 ::basegfx::B2DPolyPolygon
b2DPolyPolygonFromXPolyPolygon2D( const uno::Reference
< rendering::XPolyPolygon2D
>& xPoly
)
256 ::basegfx::unotools::UnoPolyPolygon
* pPolyImpl
=
257 dynamic_cast< ::basegfx::unotools::UnoPolyPolygon
* >( xPoly
.get() );
261 return pPolyImpl
->getPolyPolygon();
265 // not a known implementation object - try data source
267 const sal_Int32
nPolys( xPoly
->getNumberOfPolygons() );
269 uno::Reference
< rendering::XBezierPolyPolygon2D
> xBezierPoly(
273 if( xBezierPoly
.is() )
275 return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
276 xBezierPoly
->getBezierSegments( 0,
283 uno::Reference
< rendering::XLinePolyPolygon2D
> xLinePoly(
287 // no implementation class and no data provider
288 // found - contract violation.
289 if( !xLinePoly
.is() )
291 throw lang::IllegalArgumentException(
292 "basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(): Invalid input"
293 "poly-polygon, cannot retrieve vertex data",
294 uno::Reference
< uno::XInterface
>(),
298 return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
299 xLinePoly
->getPoints( 0,
307 ::basegfx::B2DHomMatrix
& homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix
& output
,
308 const geometry::AffineMatrix2D
& input
)
310 // ensure last row is [0,0,1] (and optimized away)
313 output
.set(0,0, input
.m00
);
314 output
.set(0,1, input
.m01
);
315 output
.set(0,2, input
.m02
);
316 output
.set(1,0, input
.m10
);
317 output
.set(1,1, input
.m11
);
318 output
.set(1,2, input
.m12
);
323 ::basegfx::B3DHomMatrix
homMatrixFromAffineMatrix3D( const ::css::geometry::AffineMatrix3D
& input
)
325 ::basegfx::B3DHomMatrix output
;
327 output
.set(0,0, input
.m00
);
328 output
.set(0,1, input
.m01
);
329 output
.set(0,2, input
.m02
);
330 output
.set(0,3, input
.m03
);
332 output
.set(1,0, input
.m10
);
333 output
.set(1,1, input
.m11
);
334 output
.set(1,2, input
.m12
);
335 output
.set(1,3, input
.m13
);
337 output
.set(2,0, input
.m20
);
338 output
.set(2,1, input
.m21
);
339 output
.set(2,2, input
.m22
);
340 output
.set(2,3, input
.m23
);
345 geometry::AffineMatrix2D
& affineMatrixFromHomMatrix( geometry::AffineMatrix2D
& output
,
346 const ::basegfx::B2DHomMatrix
& input
)
348 output
.m00
= input
.get(0,0);
349 output
.m01
= input
.get(0,1);
350 output
.m02
= input
.get(0,2);
351 output
.m10
= input
.get(1,0);
352 output
.m11
= input
.get(1,1);
353 output
.m12
= input
.get(1,2);
358 geometry::AffineMatrix3D
& affineMatrixFromHomMatrix3D(
359 geometry::AffineMatrix3D
& output
,
360 const ::basegfx::B3DHomMatrix
& input
)
362 output
.m00
= input
.get(0,0);
363 output
.m01
= input
.get(0,1);
364 output
.m02
= input
.get(0,2);
365 output
.m03
= input
.get(0,3);
367 output
.m10
= input
.get(1,0);
368 output
.m11
= input
.get(1,1);
369 output
.m12
= input
.get(1,2);
370 output
.m13
= input
.get(1,3);
372 output
.m20
= input
.get(2,0);
373 output
.m21
= input
.get(2,1);
374 output
.m22
= input
.get(2,2);
375 output
.m23
= input
.get(2,3);
380 geometry::RealSize2D
size2DFromB2DSize( const ::basegfx::B2DVector
& rVec
)
382 return geometry::RealSize2D( rVec
.getX(),
386 geometry::RealPoint2D
point2DFromB2DPoint( const ::basegfx::B2DPoint
& rPoint
)
388 return geometry::RealPoint2D( rPoint
.getX(),
392 geometry::RealRectangle2D
rectangle2DFromB2DRectangle( const ::basegfx::B2DRange
& rRect
)
394 return geometry::RealRectangle2D( rRect
.getMinX(),
400 geometry::RealRectangle3D
rectangle3DFromB3DRectangle( const ::basegfx::B3DRange
& rRect
)
402 return geometry::RealRectangle3D( rRect
.getMinX(),
410 ::basegfx::B2DPoint
b2DPointFromRealPoint2D( const geometry::RealPoint2D
& rPoint
)
412 return ::basegfx::B2DPoint( rPoint
.X
,
416 ::basegfx::B2DRange
b2DRectangleFromRealRectangle2D( const geometry::RealRectangle2D
& rRect
)
418 return ::basegfx::B2DRange( rRect
.X1
,
424 ::basegfx::B3DRange
b3DRectangleFromRealRectangle3D( const geometry::RealRectangle3D
& rRect
)
426 return ::basegfx::B3DRange( rRect
.X1
,
434 geometry::IntegerSize2D
integerSize2DFromB2ISize( const ::basegfx::B2IVector
& rSize
)
436 return geometry::IntegerSize2D( rSize
.getX(),
440 ::basegfx::B2IVector
b2ISizeFromIntegerSize2D( const geometry::IntegerSize2D
& rSize
)
442 return ::basegfx::B2IVector( rSize
.Width
,
446 ::basegfx::B2IRange
b2IRectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D
& rRectangle
)
448 return ::basegfx::B2IRange( rRectangle
.X1
, rRectangle
.Y1
,
449 rRectangle
.X2
, rRectangle
.Y2
);
452 ::basegfx::B2IRange
b2IRectangleFromAwtRectangle( const awt::Rectangle
& rRect
)
454 return ::basegfx::B2IRange( rRect
.X
,
456 rRect
.X
+ rRect
.Width
,
457 rRect
.Y
+ rRect
.Height
);
460 ::basegfx::B2IRange
b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
462 return ::basegfx::B2IRange( static_cast<sal_Int32
>( floor(rRange
.getMinX()) ),
463 static_cast<sal_Int32
>( floor(rRange
.getMinY()) ),
464 static_cast<sal_Int32
>( ceil(rRange
.getMaxX()) ),
465 static_cast<sal_Int32
>( ceil(rRange
.getMaxY()) ) );
468 ::basegfx::B2DRange
b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
470 return ::basegfx::B2DRange( floor(rRange
.getMinX()),
471 floor(rRange
.getMinY()),
472 ceil(rRange
.getMaxX()),
473 ceil(rRange
.getMaxY()) );
476 } // namespace bgfxtools
478 } // namespace canvas
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */