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/Matrix2D.hpp>
28 #include <com/sun/star/geometry/IntegerSize2D.hpp>
29 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
30 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
31 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
32 #include <com/sun/star/rendering/XGraphicDevice.hpp>
33 #include <com/sun/star/awt/Size.hpp>
34 #include <com/sun/star/awt/Point.hpp>
35 #include <com/sun/star/awt/Rectangle.hpp>
36 #include <basegfx/tools/unopolypolygon.hxx>
37 #include <basegfx/matrix/b2dhommatrix.hxx>
38 #include <basegfx/matrix/b3dhommatrix.hxx>
39 #include <basegfx/vector/b2dsize.hxx>
40 #include <basegfx/point/b2dpoint.hxx>
41 #include <basegfx/range/b2drectangle.hxx>
42 #include <basegfx/range/b3drange.hxx>
43 #include <basegfx/vector/b2isize.hxx>
44 #include <basegfx/point/b2ipoint.hxx>
45 #include <basegfx/range/b2irectangle.hxx>
46 #include <basegfx/range/b2ibox.hxx>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <basegfx/polygon/b2dpolypolygon.hxx>
49 #include <basegfx/tools/canvastools.hxx>
52 using namespace ::com::sun::star
;
61 uno::Sequence
< geometry::RealBezierSegment2D
> bezierSequenceFromB2DPolygon(const ::basegfx::B2DPolygon
& rPoly
)
63 const sal_uInt32
nPointCount(rPoly
.count());
64 uno::Sequence
< geometry::RealBezierSegment2D
> outputSequence(nPointCount
);
65 geometry::RealBezierSegment2D
* pOutput
= outputSequence
.getArray();
67 // fill sequences and imply clodes polygon on this implementation layer
68 for(sal_uInt32
a(0); a
< nPointCount
; a
++)
70 const basegfx::B2DPoint
aStart(rPoly
.getB2DPoint(a
));
71 const basegfx::B2DPoint
aControlA(rPoly
.getNextControlPoint(a
));
72 const basegfx::B2DPoint
aControlB(rPoly
.getPrevControlPoint((a
+ 1) % nPointCount
));
74 pOutput
[a
] = geometry::RealBezierSegment2D(
75 aStart
.getX(), aStart
.getY(),
76 aControlA
.getX(), aControlA
.getY(),
77 aControlB
.getX(), aControlB
.getY());
80 return outputSequence
;
83 uno::Sequence
< geometry::RealPoint2D
> pointSequenceFromB2DPolygon( const ::basegfx::B2DPolygon
& rPoly
)
85 const sal_uInt32
nNumPoints( rPoly
.count() );
87 uno::Sequence
< geometry::RealPoint2D
> outputSequence( nNumPoints
);
88 geometry::RealPoint2D
* pOutput
= outputSequence
.getArray();
90 // fill sequence from polygon
92 for( i
=0; i
<nNumPoints
; ++i
)
94 const ::basegfx::B2DPoint
aPoint( rPoly
.getB2DPoint(i
) );
96 pOutput
[i
] = geometry::RealPoint2D( aPoint
.getX(),
100 return outputSequence
;
104 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
106 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
109 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence( nNumPolies
);
110 uno::Sequence
< geometry::RealBezierSegment2D
>* pOutput
= outputSequence
.getArray();
112 for( i
=0; i
<nNumPolies
; ++i
)
114 pOutput
[i
] = bezierSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
117 return outputSequence
;
120 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
122 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
125 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence( nNumPolies
);
126 uno::Sequence
< geometry::RealPoint2D
>* pOutput
= outputSequence
.getArray();
128 for( i
=0; i
<nNumPolies
; ++i
)
130 pOutput
[i
] = pointSequenceFromB2DPolygon( rPolyPoly
.getB2DPolygon(i
) );
133 return outputSequence
;
136 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
137 const ::basegfx::B2DPolygon
& rPoly
)
139 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
141 if( !xGraphicDevice
.is() )
144 if( rPoly
.areControlPointsUsed() )
146 uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> > outputSequence( 1 );
147 outputSequence
[0] = bezierSequenceFromB2DPolygon( rPoly
);
149 xRes
.set( xGraphicDevice
->createCompatibleBezierPolyPolygon( outputSequence
),
154 uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> > outputSequence( 1 );
155 outputSequence
[0] = pointSequenceFromB2DPolygon( rPoly
);
157 xRes
.set( xGraphicDevice
->createCompatibleLinePolyPolygon( outputSequence
),
161 if( xRes
.is() && rPoly
.isClosed() )
162 xRes
->setClosed( 0, true );
167 uno::Reference
< rendering::XPolyPolygon2D
> xPolyPolygonFromB2DPolyPolygon( const uno::Reference
< rendering::XGraphicDevice
>& xGraphicDevice
,
168 const ::basegfx::B2DPolyPolygon
& rPolyPoly
)
170 uno::Reference
< rendering::XPolyPolygon2D
> xRes
;
172 if( !xGraphicDevice
.is() )
175 const sal_uInt32
nNumPolies( rPolyPoly
.count() );
178 if( rPolyPoly
.areControlPointsUsed() )
180 xRes
.set( xGraphicDevice
->createCompatibleBezierPolyPolygon(
181 bezierSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) ),
186 xRes
.set( xGraphicDevice
->createCompatibleLinePolyPolygon(
187 pointSequenceSequenceFromB2DPolyPolygon( rPolyPoly
) ),
191 for( i
=0; i
<nNumPolies
; ++i
)
193 xRes
->setClosed( i
, rPolyPoly
.getB2DPolygon(i
).isClosed() );
199 ::basegfx::B2DPolygon
polygonFromPoint2DSequence( const uno::Sequence
< geometry::RealPoint2D
>& points
)
201 const sal_Int32
nCurrSize( points
.getLength() );
203 ::basegfx::B2DPolygon aPoly
;
205 for( sal_Int32 nCurrPoint
=0; nCurrPoint
<nCurrSize
; ++nCurrPoint
)
206 aPoly
.append( b2DPointFromRealPoint2D( points
[nCurrPoint
] ) );
211 ::basegfx::B2DPolyPolygon
polyPolygonFromPoint2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealPoint2D
> >& points
)
213 ::basegfx::B2DPolyPolygon aRes
;
215 for( sal_Int32 nCurrPoly
=0; nCurrPoly
<points
.getLength(); ++nCurrPoly
)
217 aRes
.append( polygonFromPoint2DSequence( points
[nCurrPoly
] ) );
223 ::basegfx::B2DPolygon
polygonFromBezier2DSequence( const uno::Sequence
< geometry::RealBezierSegment2D
>& curves
)
225 const sal_Int32
nSize(curves
.getLength());
226 basegfx::B2DPolygon aRetval
;
230 // prepare start with providing a start point. Use the first point from
231 // the sequence for this
232 const geometry::RealBezierSegment2D
& rFirstSegment(curves
[0]); // #i79917# first segment, not last
233 aRetval
.append(basegfx::B2DPoint(rFirstSegment
.Px
, rFirstSegment
.Py
));
235 for(sal_Int32
a(0); a
< nSize
; a
++)
237 const geometry::RealBezierSegment2D
& rCurrSegment(curves
[a
]);
238 const geometry::RealBezierSegment2D
& rNextSegment(curves
[(a
+ 1) % nSize
]);
240 // append curved edge with the control points and the next point
241 aRetval
.appendBezierSegment(
242 basegfx::B2DPoint(rCurrSegment
.C1x
, rCurrSegment
.C1y
),
243 basegfx::B2DPoint(rCurrSegment
.C2x
, rCurrSegment
.C2y
), // #i79917# Argh! An x for an y!!
244 basegfx::B2DPoint(rNextSegment
.Px
, rNextSegment
.Py
));
247 // rescue the control point and remove the now double-added point
248 aRetval
.setPrevControlPoint(0, aRetval
.getPrevControlPoint(aRetval
.count() - 1));
249 aRetval
.remove(aRetval
.count() - 1);
255 ::basegfx::B2DPolyPolygon
polyPolygonFromBezier2DSequenceSequence( const uno::Sequence
< uno::Sequence
< geometry::RealBezierSegment2D
> >& curves
)
257 ::basegfx::B2DPolyPolygon aRes
;
259 for( sal_Int32 nCurrPoly
=0; nCurrPoly
<curves
.getLength(); ++nCurrPoly
)
261 aRes
.append( polygonFromBezier2DSequence( curves
[nCurrPoly
] ) );
267 ::basegfx::B2DPolyPolygon
b2DPolyPolygonFromXPolyPolygon2D( const uno::Reference
< rendering::XPolyPolygon2D
>& xPoly
)
269 ::basegfx::unotools::UnoPolyPolygon
* pPolyImpl
=
270 dynamic_cast< ::basegfx::unotools::UnoPolyPolygon
* >( xPoly
.get() );
274 return pPolyImpl
->getPolyPolygon();
278 // not a known implementation object - try data source
280 const sal_Int32
nPolys( xPoly
->getNumberOfPolygons() );
282 uno::Reference
< rendering::XBezierPolyPolygon2D
> xBezierPoly(
286 if( xBezierPoly
.is() )
288 return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
289 xBezierPoly
->getBezierSegments( 0,
296 uno::Reference
< rendering::XLinePolyPolygon2D
> xLinePoly(
300 // no implementation class and no data provider
301 // found - contract violation.
302 if( !xLinePoly
.is() )
304 throw lang::IllegalArgumentException(
306 "basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(): Invalid input"
307 "poly-polygon, cannot retrieve vertex data"),
308 uno::Reference
< uno::XInterface
>(),
312 return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
313 xLinePoly
->getPoints( 0,
321 ::basegfx::B2DHomMatrix
& homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix
& output
,
322 const geometry::AffineMatrix2D
& input
)
324 // ensure last row is [0,0,1] (and optimized away)
327 output
.set(0,0, input
.m00
);
328 output
.set(0,1, input
.m01
);
329 output
.set(0,2, input
.m02
);
330 output
.set(1,0, input
.m10
);
331 output
.set(1,1, input
.m11
);
332 output
.set(1,2, input
.m12
);
337 ::basegfx::B3DHomMatrix
homMatrixFromAffineMatrix3D( const ::com::sun::star::geometry::AffineMatrix3D
& input
)
339 ::basegfx::B3DHomMatrix output
;
341 output
.set(0,0, input
.m00
);
342 output
.set(0,1, input
.m01
);
343 output
.set(0,2, input
.m02
);
344 output
.set(0,3, input
.m03
);
346 output
.set(1,0, input
.m10
);
347 output
.set(1,1, input
.m11
);
348 output
.set(1,2, input
.m12
);
349 output
.set(1,3, input
.m13
);
351 output
.set(2,0, input
.m20
);
352 output
.set(2,1, input
.m21
);
353 output
.set(2,2, input
.m22
);
354 output
.set(2,3, input
.m23
);
359 geometry::AffineMatrix2D
& affineMatrixFromHomMatrix( geometry::AffineMatrix2D
& output
,
360 const ::basegfx::B2DHomMatrix
& input
)
362 output
.m00
= input
.get(0,0);
363 output
.m01
= input
.get(0,1);
364 output
.m02
= input
.get(0,2);
365 output
.m10
= input
.get(1,0);
366 output
.m11
= input
.get(1,1);
367 output
.m12
= input
.get(1,2);
372 geometry::AffineMatrix3D
& affineMatrixFromHomMatrix3D(
373 geometry::AffineMatrix3D
& output
,
374 const ::basegfx::B3DHomMatrix
& input
)
376 output
.m00
= input
.get(0,0);
377 output
.m01
= input
.get(0,1);
378 output
.m02
= input
.get(0,2);
379 output
.m03
= input
.get(0,3);
381 output
.m10
= input
.get(1,0);
382 output
.m11
= input
.get(1,1);
383 output
.m12
= input
.get(1,2);
384 output
.m13
= input
.get(1,3);
386 output
.m20
= input
.get(2,0);
387 output
.m21
= input
.get(2,1);
388 output
.m22
= input
.get(2,2);
389 output
.m23
= input
.get(2,3);
394 geometry::RealSize2D
size2DFromB2DSize( const ::basegfx::B2DVector
& rVec
)
396 return geometry::RealSize2D( rVec
.getX(),
400 geometry::RealPoint2D
point2DFromB2DPoint( const ::basegfx::B2DPoint
& rPoint
)
402 return geometry::RealPoint2D( rPoint
.getX(),
406 geometry::RealRectangle2D
rectangle2DFromB2DRectangle( const ::basegfx::B2DRange
& rRect
)
408 return geometry::RealRectangle2D( rRect
.getMinX(),
414 geometry::RealRectangle3D
rectangle3DFromB3DRectangle( const ::basegfx::B3DRange
& rRect
)
416 return geometry::RealRectangle3D( rRect
.getMinX(),
424 ::basegfx::B2DPoint
b2DPointFromRealPoint2D( const geometry::RealPoint2D
& rPoint
)
426 return ::basegfx::B2DPoint( rPoint
.X
,
430 ::basegfx::B2DRange
b2DRectangleFromRealRectangle2D( const geometry::RealRectangle2D
& rRect
)
432 return ::basegfx::B2DRange( rRect
.X1
,
438 ::basegfx::B3DRange
b3DRectangleFromRealRectangle3D( const geometry::RealRectangle3D
& rRect
)
440 return ::basegfx::B3DRange( rRect
.X1
,
448 geometry::IntegerSize2D
integerSize2DFromB2ISize( const ::basegfx::B2IVector
& rSize
)
450 return geometry::IntegerSize2D( rSize
.getX(),
454 ::basegfx::B2IVector
b2ISizeFromIntegerSize2D( const geometry::IntegerSize2D
& rSize
)
456 return ::basegfx::B2IVector( rSize
.Width
,
460 ::basegfx::B2IRange
b2IRectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D
& rRectangle
)
462 return ::basegfx::B2IRange( rRectangle
.X1
, rRectangle
.Y1
,
463 rRectangle
.X2
, rRectangle
.Y2
);
466 ::basegfx::B2IRange
b2IRectangleFromAwtRectangle( const awt::Rectangle
& rRect
)
468 return ::basegfx::B2IRange( rRect
.X
,
470 rRect
.X
+ rRect
.Width
,
471 rRect
.Y
+ rRect
.Height
);
474 ::basegfx::B2IBox
b2ISurroundingBoxFromB2DRange( const ::basegfx::B2DRange
& rRange
)
476 return ::basegfx::B2IBox( static_cast<sal_Int32
>( floor(rRange
.getMinX()) ),
477 static_cast<sal_Int32
>( floor(rRange
.getMinY()) ),
478 static_cast<sal_Int32
>( ceil(rRange
.getMaxX()) ),
479 static_cast<sal_Int32
>( ceil(rRange
.getMaxY()) ) );
482 ::basegfx::B2IRange
b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
484 return ::basegfx::B2IRange( static_cast<sal_Int32
>( floor(rRange
.getMinX()) ),
485 static_cast<sal_Int32
>( floor(rRange
.getMinY()) ),
486 static_cast<sal_Int32
>( ceil(rRange
.getMaxX()) ),
487 static_cast<sal_Int32
>( ceil(rRange
.getMaxY()) ) );
490 ::basegfx::B2DRange
b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange
& rRange
)
492 return ::basegfx::B2DRange( floor(rRange
.getMinX()),
493 floor(rRange
.getMinY()),
494 ceil(rRange
.getMaxX()),
495 ceil(rRange
.getMaxY()) );
498 } // namespace bgfxtools
500 } // namespace canvas
502 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */