Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
50 : #include <limits>
51 :
52 : using namespace ::com::sun::star;
53 :
54 : namespace basegfx
55 : {
56 :
57 : namespace unotools
58 : {
59 : namespace
60 : {
61 0 : uno::Sequence< geometry::RealBezierSegment2D > bezierSequenceFromB2DPolygon(const ::basegfx::B2DPolygon& rPoly)
62 : {
63 0 : const sal_uInt32 nPointCount(rPoly.count());
64 0 : uno::Sequence< geometry::RealBezierSegment2D > outputSequence(nPointCount);
65 0 : geometry::RealBezierSegment2D* pOutput = outputSequence.getArray();
66 :
67 : // fill sequences and imply clodes polygon on this implementation layer
68 0 : for(sal_uInt32 a(0); a < nPointCount; a++)
69 : {
70 0 : const basegfx::B2DPoint aStart(rPoly.getB2DPoint(a));
71 0 : const basegfx::B2DPoint aControlA(rPoly.getNextControlPoint(a));
72 0 : const basegfx::B2DPoint aControlB(rPoly.getPrevControlPoint((a + 1) % nPointCount));
73 :
74 : pOutput[a] = geometry::RealBezierSegment2D(
75 0 : aStart.getX(), aStart.getY(),
76 0 : aControlA.getX(), aControlA.getY(),
77 0 : aControlB.getX(), aControlB.getY());
78 0 : }
79 :
80 0 : return outputSequence;
81 : }
82 :
83 0 : uno::Sequence< geometry::RealPoint2D > pointSequenceFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly )
84 : {
85 0 : const sal_uInt32 nNumPoints( rPoly.count() );
86 :
87 0 : uno::Sequence< geometry::RealPoint2D > outputSequence( nNumPoints );
88 0 : geometry::RealPoint2D* pOutput = outputSequence.getArray();
89 :
90 : // fill sequence from polygon
91 : sal_uInt32 i;
92 0 : for( i=0; i<nNumPoints; ++i )
93 : {
94 0 : const ::basegfx::B2DPoint aPoint( rPoly.getB2DPoint(i) );
95 :
96 0 : pOutput[i] = geometry::RealPoint2D( aPoint.getX(),
97 0 : aPoint.getY() );
98 0 : }
99 :
100 0 : return outputSequence;
101 : }
102 : }
103 :
104 0 : uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
105 : {
106 0 : const sal_uInt32 nNumPolies( rPolyPoly.count() );
107 : sal_uInt32 i;
108 :
109 0 : uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > outputSequence( nNumPolies );
110 0 : uno::Sequence< geometry::RealBezierSegment2D >* pOutput = outputSequence.getArray();
111 :
112 0 : for( i=0; i<nNumPolies; ++i )
113 : {
114 0 : pOutput[i] = bezierSequenceFromB2DPolygon( rPolyPoly.getB2DPolygon(i) );
115 : }
116 :
117 0 : return outputSequence;
118 : }
119 :
120 0 : uno::Sequence< uno::Sequence< geometry::RealPoint2D > > pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
121 : {
122 0 : const sal_uInt32 nNumPolies( rPolyPoly.count() );
123 : sal_uInt32 i;
124 :
125 0 : uno::Sequence< uno::Sequence< geometry::RealPoint2D > > outputSequence( nNumPolies );
126 0 : uno::Sequence< geometry::RealPoint2D >* pOutput = outputSequence.getArray();
127 :
128 0 : for( i=0; i<nNumPolies; ++i )
129 : {
130 0 : pOutput[i] = pointSequenceFromB2DPolygon( rPolyPoly.getB2DPolygon(i) );
131 : }
132 :
133 0 : return outputSequence;
134 : }
135 :
136 0 : uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromB2DPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
137 : const ::basegfx::B2DPolygon& rPoly )
138 : {
139 0 : uno::Reference< rendering::XPolyPolygon2D > xRes;
140 :
141 0 : if( !xGraphicDevice.is() )
142 0 : return xRes;
143 :
144 0 : if( rPoly.areControlPointsUsed() )
145 : {
146 0 : uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > outputSequence( 1 );
147 0 : outputSequence[0] = bezierSequenceFromB2DPolygon( rPoly );
148 :
149 0 : xRes.set( xGraphicDevice->createCompatibleBezierPolyPolygon( outputSequence ),
150 0 : uno::UNO_QUERY );
151 : }
152 : else
153 : {
154 0 : uno::Sequence< uno::Sequence< geometry::RealPoint2D > > outputSequence( 1 );
155 0 : outputSequence[0] = pointSequenceFromB2DPolygon( rPoly );
156 :
157 0 : xRes.set( xGraphicDevice->createCompatibleLinePolyPolygon( outputSequence ),
158 0 : uno::UNO_QUERY );
159 : }
160 :
161 0 : if( xRes.is() && rPoly.isClosed() )
162 0 : xRes->setClosed( 0, true );
163 :
164 0 : return xRes;
165 : }
166 :
167 0 : uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromB2DPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
168 : const ::basegfx::B2DPolyPolygon& rPolyPoly )
169 : {
170 0 : uno::Reference< rendering::XPolyPolygon2D > xRes;
171 :
172 0 : if( !xGraphicDevice.is() )
173 0 : return xRes;
174 :
175 0 : const sal_uInt32 nNumPolies( rPolyPoly.count() );
176 : sal_uInt32 i;
177 :
178 0 : if( rPolyPoly.areControlPointsUsed() )
179 : {
180 0 : xRes.set( xGraphicDevice->createCompatibleBezierPolyPolygon(
181 0 : bezierSequenceSequenceFromB2DPolyPolygon( rPolyPoly ) ),
182 0 : uno::UNO_QUERY );
183 : }
184 : else
185 : {
186 0 : xRes.set( xGraphicDevice->createCompatibleLinePolyPolygon(
187 0 : pointSequenceSequenceFromB2DPolyPolygon( rPolyPoly ) ),
188 0 : uno::UNO_QUERY );
189 : }
190 :
191 0 : for( i=0; i<nNumPolies; ++i )
192 : {
193 0 : xRes->setClosed( i, rPolyPoly.getB2DPolygon(i).isClosed() );
194 : }
195 :
196 0 : return xRes;
197 : }
198 :
199 0 : ::basegfx::B2DPolygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points )
200 : {
201 0 : const sal_Int32 nCurrSize( points.getLength() );
202 :
203 0 : ::basegfx::B2DPolygon aPoly;
204 :
205 0 : for( sal_Int32 nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint )
206 0 : aPoly.append( b2DPointFromRealPoint2D( points[nCurrPoint] ) );
207 :
208 0 : return aPoly;
209 : }
210 :
211 0 : ::basegfx::B2DPolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
212 : {
213 0 : ::basegfx::B2DPolyPolygon aRes;
214 :
215 0 : for( sal_Int32 nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
216 : {
217 0 : aRes.append( polygonFromPoint2DSequence( points[nCurrPoly] ) );
218 : }
219 :
220 0 : return aRes;
221 : }
222 :
223 0 : ::basegfx::B2DPolygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves )
224 : {
225 0 : const sal_Int32 nSize(curves.getLength());
226 0 : basegfx::B2DPolygon aRetval;
227 :
228 0 : if(nSize)
229 : {
230 : // prepare start with providing a start point. Use the first point from
231 : // the sequence for this
232 0 : const geometry::RealBezierSegment2D& rFirstSegment(curves[0]); // #i79917# first segment, not last
233 0 : aRetval.append(basegfx::B2DPoint(rFirstSegment.Px, rFirstSegment.Py));
234 :
235 0 : for(sal_Int32 a(0); a < nSize; a++)
236 : {
237 0 : const geometry::RealBezierSegment2D& rCurrSegment(curves[a]);
238 0 : const geometry::RealBezierSegment2D& rNextSegment(curves[(a + 1) % nSize]);
239 :
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 0 : basegfx::B2DPoint(rNextSegment.Px, rNextSegment.Py));
245 : }
246 :
247 : // rescue the control point and remove the now double-added point
248 0 : aRetval.setPrevControlPoint(0, aRetval.getPrevControlPoint(aRetval.count() - 1));
249 0 : aRetval.remove(aRetval.count() - 1);
250 : }
251 :
252 0 : return aRetval;
253 : }
254 :
255 0 : ::basegfx::B2DPolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves )
256 : {
257 0 : ::basegfx::B2DPolyPolygon aRes;
258 :
259 0 : for( sal_Int32 nCurrPoly=0; nCurrPoly<curves.getLength(); ++nCurrPoly )
260 : {
261 0 : aRes.append( polygonFromBezier2DSequence( curves[nCurrPoly] ) );
262 : }
263 :
264 0 : return aRes;
265 : }
266 :
267 30 : ::basegfx::B2DPolyPolygon b2DPolyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
268 : {
269 : ::basegfx::unotools::UnoPolyPolygon* pPolyImpl =
270 30 : dynamic_cast< ::basegfx::unotools::UnoPolyPolygon* >( xPoly.get() );
271 :
272 30 : if( pPolyImpl )
273 : {
274 30 : return pPolyImpl->getPolyPolygon();
275 : }
276 : else
277 : {
278 : // not a known implementation object - try data source
279 : // interfaces
280 0 : const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );
281 :
282 : uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
283 : xPoly,
284 0 : uno::UNO_QUERY );
285 :
286 0 : if( xBezierPoly.is() )
287 : {
288 : return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
289 0 : xBezierPoly->getBezierSegments( 0,
290 : nPolys,
291 : 0,
292 0 : -1 ) );
293 : }
294 : else
295 : {
296 : uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
297 : xPoly,
298 0 : uno::UNO_QUERY );
299 :
300 : // no implementation class and no data provider
301 : // found - contract violation.
302 0 : if( !xLinePoly.is() )
303 : {
304 : throw lang::IllegalArgumentException(
305 : OUString(
306 : "basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(): Invalid input"
307 : "poly-polygon, cannot retrieve vertex data"),
308 : uno::Reference< uno::XInterface >(),
309 0 : 0 );
310 : }
311 :
312 : return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
313 0 : xLinePoly->getPoints( 0,
314 : nPolys,
315 : 0,
316 0 : -1 ));
317 0 : }
318 : }
319 : }
320 :
321 12 : ::basegfx::B2DHomMatrix& homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix& output,
322 : const geometry::AffineMatrix2D& input )
323 : {
324 : // ensure last row is [0,0,1] (and optimized away)
325 12 : output.identity();
326 :
327 12 : output.set(0,0, input.m00);
328 12 : output.set(0,1, input.m01);
329 12 : output.set(0,2, input.m02);
330 12 : output.set(1,0, input.m10);
331 12 : output.set(1,1, input.m11);
332 12 : output.set(1,2, input.m12);
333 :
334 12 : return output;
335 : }
336 :
337 0 : ::basegfx::B3DHomMatrix homMatrixFromAffineMatrix3D( const ::com::sun::star::geometry::AffineMatrix3D& input )
338 : {
339 0 : ::basegfx::B3DHomMatrix output;
340 :
341 0 : output.set(0,0, input.m00);
342 0 : output.set(0,1, input.m01);
343 0 : output.set(0,2, input.m02);
344 0 : output.set(0,3, input.m03);
345 :
346 0 : output.set(1,0, input.m10);
347 0 : output.set(1,1, input.m11);
348 0 : output.set(1,2, input.m12);
349 0 : output.set(1,3, input.m13);
350 :
351 0 : output.set(2,0, input.m20);
352 0 : output.set(2,1, input.m21);
353 0 : output.set(2,2, input.m22);
354 0 : output.set(2,3, input.m23);
355 :
356 0 : return output;
357 : }
358 :
359 0 : geometry::AffineMatrix2D& affineMatrixFromHomMatrix( geometry::AffineMatrix2D& output,
360 : const ::basegfx::B2DHomMatrix& input)
361 : {
362 0 : output.m00 = input.get(0,0);
363 0 : output.m01 = input.get(0,1);
364 0 : output.m02 = input.get(0,2);
365 0 : output.m10 = input.get(1,0);
366 0 : output.m11 = input.get(1,1);
367 0 : output.m12 = input.get(1,2);
368 :
369 0 : return output;
370 : }
371 :
372 0 : geometry::AffineMatrix3D& affineMatrixFromHomMatrix3D(
373 : geometry::AffineMatrix3D& output,
374 : const ::basegfx::B3DHomMatrix& input)
375 : {
376 0 : output.m00 = input.get(0,0);
377 0 : output.m01 = input.get(0,1);
378 0 : output.m02 = input.get(0,2);
379 0 : output.m03 = input.get(0,3);
380 :
381 0 : output.m10 = input.get(1,0);
382 0 : output.m11 = input.get(1,1);
383 0 : output.m12 = input.get(1,2);
384 0 : output.m13 = input.get(1,3);
385 :
386 0 : output.m20 = input.get(2,0);
387 0 : output.m21 = input.get(2,1);
388 0 : output.m22 = input.get(2,2);
389 0 : output.m23 = input.get(2,3);
390 :
391 0 : return output;
392 : }
393 :
394 0 : geometry::RealSize2D size2DFromB2DSize( const ::basegfx::B2DVector& rVec )
395 : {
396 0 : return geometry::RealSize2D( rVec.getX(),
397 0 : rVec.getY() );
398 : }
399 :
400 0 : geometry::RealPoint2D point2DFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
401 : {
402 0 : return geometry::RealPoint2D( rPoint.getX(),
403 0 : rPoint.getY() );
404 : }
405 :
406 292 : geometry::RealRectangle2D rectangle2DFromB2DRectangle( const ::basegfx::B2DRange& rRect )
407 : {
408 292 : return geometry::RealRectangle2D( rRect.getMinX(),
409 292 : rRect.getMinY(),
410 292 : rRect.getMaxX(),
411 1168 : rRect.getMaxY() );
412 : }
413 :
414 0 : geometry::RealRectangle3D rectangle3DFromB3DRectangle( const ::basegfx::B3DRange& rRect )
415 : {
416 0 : return geometry::RealRectangle3D( rRect.getMinX(),
417 0 : rRect.getMinY(),
418 0 : rRect.getMinZ(),
419 0 : rRect.getMaxX(),
420 0 : rRect.getMaxY(),
421 0 : rRect.getMaxZ());
422 : }
423 :
424 0 : ::basegfx::B2DPoint b2DPointFromRealPoint2D( const geometry::RealPoint2D& rPoint )
425 : {
426 : return ::basegfx::B2DPoint( rPoint.X,
427 0 : rPoint.Y );
428 : }
429 :
430 0 : ::basegfx::B2DRange b2DRectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect )
431 : {
432 : return ::basegfx::B2DRange( rRect.X1,
433 : rRect.Y1,
434 : rRect.X2,
435 0 : rRect.Y2 );
436 : }
437 :
438 0 : ::basegfx::B3DRange b3DRectangleFromRealRectangle3D( const geometry::RealRectangle3D& rRect )
439 : {
440 : return ::basegfx::B3DRange( rRect.X1,
441 : rRect.Y1,
442 : rRect.Z1,
443 : rRect.X2,
444 : rRect.Y2,
445 0 : rRect.Z2);
446 : }
447 :
448 0 : geometry::IntegerSize2D integerSize2DFromB2ISize( const ::basegfx::B2IVector& rSize )
449 : {
450 0 : return geometry::IntegerSize2D( rSize.getX(),
451 0 : rSize.getY() );
452 : }
453 :
454 0 : ::basegfx::B2IVector b2ISizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
455 : {
456 : return ::basegfx::B2IVector( rSize.Width,
457 0 : rSize.Height );
458 : }
459 :
460 0 : ::basegfx::B2IRange b2IRectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
461 : {
462 : return ::basegfx::B2IRange( rRectangle.X1, rRectangle.Y1,
463 0 : rRectangle.X2, rRectangle.Y2 );
464 : }
465 :
466 0 : ::basegfx::B2IRange b2IRectangleFromAwtRectangle( const awt::Rectangle& rRect )
467 : {
468 : return ::basegfx::B2IRange( rRect.X,
469 : rRect.Y,
470 : rRect.X + rRect.Width,
471 0 : rRect.Y + rRect.Height );
472 : }
473 :
474 0 : ::basegfx::B2IBox b2ISurroundingBoxFromB2DRange( const ::basegfx::B2DRange& rRange )
475 : {
476 0 : return ::basegfx::B2IBox( static_cast<sal_Int32>( floor(rRange.getMinX()) ),
477 0 : static_cast<sal_Int32>( floor(rRange.getMinY()) ),
478 0 : static_cast<sal_Int32>( ceil(rRange.getMaxX()) ),
479 0 : static_cast<sal_Int32>( ceil(rRange.getMaxY()) ) );
480 : }
481 :
482 0 : ::basegfx::B2IRange b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange& rRange )
483 : {
484 0 : return ::basegfx::B2IRange( static_cast<sal_Int32>( floor(rRange.getMinX()) ),
485 0 : static_cast<sal_Int32>( floor(rRange.getMinY()) ),
486 0 : static_cast<sal_Int32>( ceil(rRange.getMaxX()) ),
487 0 : static_cast<sal_Int32>( ceil(rRange.getMaxY()) ) );
488 : }
489 :
490 0 : ::basegfx::B2DRange b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange& rRange )
491 : {
492 : return ::basegfx::B2DRange( floor(rRange.getMinX()),
493 : floor(rRange.getMinY()),
494 : ceil(rRange.getMaxX()),
495 0 : ceil(rRange.getMaxY()) );
496 : }
497 :
498 : } // namespace bgfxtools
499 :
500 : } // namespace canvas
501 :
502 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|