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, sal_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 0 : ::basegfx::B2DPolyPolygon b2DPolyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
268 : {
269 : ::basegfx::unotools::UnoPolyPolygon* pPolyImpl =
270 0 : dynamic_cast< ::basegfx::unotools::UnoPolyPolygon* >( xPoly.get() );
271 :
272 0 : if( pPolyImpl )
273 : {
274 0 : 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 0 : ::basegfx::B2DHomMatrix& homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix& output,
322 : const geometry::AffineMatrix2D& input )
323 : {
324 : // ensure last row is [0,0,1] (and optimized away)
325 0 : output.identity();
326 :
327 0 : output.set(0,0, input.m00);
328 0 : output.set(0,1, input.m01);
329 0 : output.set(0,2, input.m02);
330 0 : output.set(1,0, input.m10);
331 0 : output.set(1,1, input.m11);
332 0 : output.set(1,2, input.m12);
333 :
334 0 : 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 : ::basegfx::B2DHomMatrix& homMatrixFromMatrix( ::basegfx::B2DHomMatrix& output,
395 : const geometry::Matrix2D& input )
396 : {
397 : // ensure last row is [0,0,1] (and optimized away)
398 0 : output.identity();
399 :
400 0 : output.set(0,0, input.m00);
401 0 : output.set(0,1, input.m01);
402 0 : output.set(1,0, input.m10);
403 0 : output.set(1,1, input.m11);
404 :
405 0 : return output;
406 : }
407 :
408 0 : geometry::RealSize2D size2DFromB2DSize( const ::basegfx::B2DVector& rVec )
409 : {
410 0 : return geometry::RealSize2D( rVec.getX(),
411 0 : rVec.getY() );
412 : }
413 :
414 0 : geometry::RealPoint2D point2DFromB2DPoint( const ::basegfx::B2DPoint& rPoint )
415 : {
416 0 : return geometry::RealPoint2D( rPoint.getX(),
417 0 : rPoint.getY() );
418 : }
419 :
420 0 : geometry::RealRectangle2D rectangle2DFromB2DRectangle( const ::basegfx::B2DRange& rRect )
421 : {
422 0 : return geometry::RealRectangle2D( rRect.getMinX(),
423 0 : rRect.getMinY(),
424 0 : rRect.getMaxX(),
425 0 : rRect.getMaxY() );
426 : }
427 :
428 0 : geometry::RealRectangle3D rectangle3DFromB3DRectangle( const ::basegfx::B3DRange& rRect )
429 : {
430 0 : return geometry::RealRectangle3D( rRect.getMinX(),
431 0 : rRect.getMinY(),
432 0 : rRect.getMinZ(),
433 0 : rRect.getMaxX(),
434 0 : rRect.getMaxY(),
435 0 : rRect.getMaxZ());
436 : }
437 :
438 0 : ::basegfx::B2DPoint b2DPointFromRealPoint2D( const geometry::RealPoint2D& rPoint )
439 : {
440 : return ::basegfx::B2DPoint( rPoint.X,
441 0 : rPoint.Y );
442 : }
443 :
444 0 : ::basegfx::B2DRange b2DRectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect )
445 : {
446 : return ::basegfx::B2DRange( rRect.X1,
447 : rRect.Y1,
448 : rRect.X2,
449 0 : rRect.Y2 );
450 : }
451 :
452 0 : ::basegfx::B3DRange b3DRectangleFromRealRectangle3D( const geometry::RealRectangle3D& rRect )
453 : {
454 : return ::basegfx::B3DRange( rRect.X1,
455 : rRect.Y1,
456 : rRect.Z1,
457 : rRect.X2,
458 : rRect.Y2,
459 0 : rRect.Z2);
460 : }
461 :
462 0 : geometry::IntegerSize2D integerSize2DFromB2ISize( const ::basegfx::B2IVector& rSize )
463 : {
464 0 : return geometry::IntegerSize2D( rSize.getX(),
465 0 : rSize.getY() );
466 : }
467 :
468 0 : ::basegfx::B2IVector b2ISizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize )
469 : {
470 : return ::basegfx::B2IVector( rSize.Width,
471 0 : rSize.Height );
472 : }
473 :
474 0 : ::basegfx::B2IRange b2IRectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle )
475 : {
476 : return ::basegfx::B2IRange( rRectangle.X1, rRectangle.Y1,
477 0 : rRectangle.X2, rRectangle.Y2 );
478 : }
479 :
480 0 : ::basegfx::B2IRange b2IRectangleFromAwtRectangle( const awt::Rectangle& rRect )
481 : {
482 : return ::basegfx::B2IRange( rRect.X,
483 : rRect.Y,
484 : rRect.X + rRect.Width,
485 0 : rRect.Y + rRect.Height );
486 : }
487 :
488 0 : ::basegfx::B2IBox b2ISurroundingBoxFromB2DRange( const ::basegfx::B2DRange& rRange )
489 : {
490 0 : return ::basegfx::B2IBox( static_cast<sal_Int32>( floor(rRange.getMinX()) ),
491 0 : static_cast<sal_Int32>( floor(rRange.getMinY()) ),
492 0 : static_cast<sal_Int32>( ceil(rRange.getMaxX()) ),
493 0 : static_cast<sal_Int32>( ceil(rRange.getMaxY()) ) );
494 : }
495 :
496 0 : ::basegfx::B2IRange b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange& rRange )
497 : {
498 0 : return ::basegfx::B2IRange( static_cast<sal_Int32>( floor(rRange.getMinX()) ),
499 0 : static_cast<sal_Int32>( floor(rRange.getMinY()) ),
500 0 : static_cast<sal_Int32>( ceil(rRange.getMaxX()) ),
501 0 : static_cast<sal_Int32>( ceil(rRange.getMaxY()) ) );
502 : }
503 :
504 0 : ::basegfx::B2DRange b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange& rRange )
505 : {
506 : return ::basegfx::B2DRange( floor(rRange.getMinX()),
507 : floor(rRange.getMinY()),
508 : ceil(rRange.getMaxX()),
509 0 : ceil(rRange.getMaxY()) );
510 : }
511 :
512 : } // namespace bgfxtools
513 :
514 : } // namespace canvas
515 :
516 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|