Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / basegfx / source / tools / unopolypolygon.cxx
blobe0b5b85f079b0f493f79b77f4206dfd88b5d6d48
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/AffineMatrix2D.hpp>
21 #include <com/sun/star/lang/IllegalArgumentException.hpp>
22 #include <com/sun/star/rendering/RenderState.hpp>
23 #include <com/sun/star/rendering/ViewState.hpp>
24 #include <com/sun/star/rendering/XCanvas.hpp>
25 #include <com/sun/star/rendering/CompositeOperation.hpp>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <basegfx/range/b2drange.hxx>
29 #include <basegfx/range/b2drectangle.hxx>
30 #include <basegfx/point/b2dpoint.hxx>
31 #include <basegfx/utils/canvastools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <basegfx/polygon/b2dpolypolygontools.hxx>
34 #include <basegfx/utils/unopolypolygon.hxx>
35 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 #include <cppuhelper/supportsservice.hxx>
38 using namespace ::com::sun::star;
40 namespace basegfx
42 namespace unotools
44 UnoPolyPolygon::UnoPolyPolygon( const B2DPolyPolygon& rPolyPoly ) :
45 UnoPolyPolygonBase( m_aMutex ),
46 maPolyPoly( rPolyPoly ),
47 meFillRule( rendering::FillRule_EVEN_ODD )
49 // or else races will haunt us.
50 maPolyPoly.makeUnique();
53 void SAL_CALL UnoPolyPolygon::addPolyPolygon(
54 const geometry::RealPoint2D& position,
55 const uno::Reference< rendering::XPolyPolygon2D >& polyPolygon )
57 osl::MutexGuard const guard( m_aMutex );
58 modifying();
60 // TODO(F1): Correctly fulfill the UNO API
61 // specification. This will probably result in a vector of
62 // poly-polygons to be stored in this object.
64 const sal_Int32 nPolys( polyPolygon->getNumberOfPolygons() );
66 if( !polyPolygon.is() || !nPolys )
68 // invalid or empty polygon - nothing to do.
69 return;
72 B2DPolyPolygon aSrcPoly;
73 const UnoPolyPolygon* pSrc( dynamic_cast< UnoPolyPolygon* >(polyPolygon.get()) );
75 // try to extract polygon data from interface. First,
76 // check whether it's the same implementation object,
77 // which we can tunnel then.
78 if( pSrc )
80 aSrcPoly = pSrc->getPolyPolygon();
82 else
84 // not a known implementation object - try data source
85 // interfaces
86 uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
87 polyPolygon,
88 uno::UNO_QUERY );
90 if( xBezierPoly.is() )
92 aSrcPoly = unotools::polyPolygonFromBezier2DSequenceSequence(
93 xBezierPoly->getBezierSegments( 0,
94 nPolys,
96 -1 ) );
98 else
100 uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
101 polyPolygon,
102 uno::UNO_QUERY );
104 // no implementation class and no data provider
105 // found - contract violation.
106 if( !xLinePoly.is() )
107 throw lang::IllegalArgumentException(
108 "UnoPolyPolygon::addPolyPolygon(): Invalid input "
109 "poly-polygon, cannot retrieve vertex data",
110 static_cast<cppu::OWeakObject*>(this), 1);
112 aSrcPoly = unotools::polyPolygonFromPoint2DSequenceSequence(
113 xLinePoly->getPoints( 0,
114 nPolys,
116 -1 ) );
120 const B2DRange aBounds( utils::getRange( aSrcPoly ) );
121 const B2DVector aOffset( unotools::b2DPointFromRealPoint2D( position ) -
122 aBounds.getMinimum() );
124 if( !aOffset.equalZero() )
126 const B2DHomMatrix aTranslate(utils::createTranslateB2DHomMatrix(aOffset));
127 aSrcPoly.transform( aTranslate );
130 maPolyPoly.append( aSrcPoly );
133 sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygons()
135 osl::MutexGuard const guard( m_aMutex );
136 return maPolyPoly.count();
139 sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygonPoints(
140 sal_Int32 polygon )
142 osl::MutexGuard const guard( m_aMutex );
143 checkIndex( polygon );
145 return maPolyPoly.getB2DPolygon(polygon).count();
148 rendering::FillRule SAL_CALL UnoPolyPolygon::getFillRule()
150 osl::MutexGuard const guard( m_aMutex );
151 return meFillRule;
154 void SAL_CALL UnoPolyPolygon::setFillRule(
155 rendering::FillRule fillRule )
157 osl::MutexGuard const guard( m_aMutex );
158 modifying();
160 meFillRule = fillRule;
163 sal_Bool SAL_CALL UnoPolyPolygon::isClosed(
164 sal_Int32 index )
166 osl::MutexGuard const guard( m_aMutex );
167 checkIndex( index );
169 return maPolyPoly.getB2DPolygon(index).isClosed();
172 void SAL_CALL UnoPolyPolygon::setClosed(
173 sal_Int32 index,
174 sal_Bool closedState )
176 osl::MutexGuard const guard( m_aMutex );
177 modifying();
179 if( index == -1 )
181 // set all
182 maPolyPoly.setClosed( closedState );
184 else
186 checkIndex( index );
188 // fetch referenced polygon, change state
189 B2DPolygon aTmp( maPolyPoly.getB2DPolygon(index) );
190 aTmp.setClosed( closedState );
192 // set back to container
193 maPolyPoly.setB2DPolygon( index, aTmp );
197 uno::Sequence< uno::Sequence< geometry::RealPoint2D > > SAL_CALL UnoPolyPolygon::getPoints(
198 sal_Int32 nPolygonIndex,
199 sal_Int32 nNumberOfPolygons,
200 sal_Int32 nPointIndex,
201 sal_Int32 nNumberOfPoints )
203 osl::MutexGuard const guard( m_aMutex );
205 return unotools::pointSequenceSequenceFromB2DPolyPolygon(
206 getSubsetPolyPolygon( nPolygonIndex,
207 nNumberOfPolygons,
208 nPointIndex,
209 nNumberOfPoints ) );
212 void SAL_CALL UnoPolyPolygon::setPoints(
213 const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points,
214 sal_Int32 nPolygonIndex )
216 osl::MutexGuard const guard( m_aMutex );
217 modifying();
219 const B2DPolyPolygon& rNewPolyPoly(
220 unotools::polyPolygonFromPoint2DSequenceSequence( points ) );
222 if( nPolygonIndex == -1 )
224 maPolyPoly = rNewPolyPoly;
226 else
228 checkIndex( nPolygonIndex );
230 maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
234 geometry::RealPoint2D SAL_CALL UnoPolyPolygon::getPoint(
235 sal_Int32 nPolygonIndex,
236 sal_Int32 nPointIndex )
238 osl::MutexGuard const guard( m_aMutex );
239 checkIndex( nPolygonIndex );
241 const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
243 if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(rPoly.count()) )
244 throw lang::IndexOutOfBoundsException();
246 return unotools::point2DFromB2DPoint( rPoly.getB2DPoint( nPointIndex ) );
249 void SAL_CALL UnoPolyPolygon::setPoint(
250 const geometry::RealPoint2D& point,
251 sal_Int32 nPolygonIndex,
252 sal_Int32 nPointIndex )
254 osl::MutexGuard const guard( m_aMutex );
255 checkIndex( nPolygonIndex );
256 modifying();
258 B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
260 if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(aPoly.count()) )
261 throw lang::IndexOutOfBoundsException();
263 aPoly.setB2DPoint( nPointIndex,
264 unotools::b2DPointFromRealPoint2D( point ) );
265 maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
268 uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > SAL_CALL UnoPolyPolygon::getBezierSegments(
269 sal_Int32 nPolygonIndex,
270 sal_Int32 nNumberOfPolygons,
271 sal_Int32 nPointIndex,
272 sal_Int32 nNumberOfPoints )
274 osl::MutexGuard const guard( m_aMutex );
275 return unotools::bezierSequenceSequenceFromB2DPolyPolygon(
276 getSubsetPolyPolygon( nPolygonIndex,
277 nNumberOfPolygons,
278 nPointIndex,
279 nNumberOfPoints ) );
282 void SAL_CALL UnoPolyPolygon::setBezierSegments(
283 const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points,
284 sal_Int32 nPolygonIndex )
286 osl::MutexGuard const guard( m_aMutex );
287 modifying();
288 const B2DPolyPolygon& rNewPolyPoly(
289 unotools::polyPolygonFromBezier2DSequenceSequence( points ) );
291 if( nPolygonIndex == -1 )
293 maPolyPoly = rNewPolyPoly;
295 else
297 checkIndex( nPolygonIndex );
299 maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
303 geometry::RealBezierSegment2D SAL_CALL UnoPolyPolygon::getBezierSegment( sal_Int32 nPolygonIndex,
304 sal_Int32 nPointIndex )
306 osl::MutexGuard const guard( m_aMutex );
307 checkIndex( nPolygonIndex );
309 const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
310 const sal_uInt32 nPointCount(rPoly.count());
312 if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
313 throw lang::IndexOutOfBoundsException();
315 const B2DPoint& rPt( rPoly.getB2DPoint( nPointIndex ) );
316 const B2DPoint& rCtrl0( rPoly.getNextControlPoint(nPointIndex) );
317 const B2DPoint& rCtrl1( rPoly.getPrevControlPoint((nPointIndex + 1) % nPointCount) );
319 return geometry::RealBezierSegment2D( rPt.getX(),
320 rPt.getY(),
321 rCtrl0.getX(),
322 rCtrl0.getY(),
323 rCtrl1.getX(),
324 rCtrl1.getY() );
327 void SAL_CALL UnoPolyPolygon::setBezierSegment( const geometry::RealBezierSegment2D& segment,
328 sal_Int32 nPolygonIndex,
329 sal_Int32 nPointIndex )
331 osl::MutexGuard const guard( m_aMutex );
332 checkIndex( nPolygonIndex );
333 modifying();
335 B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
336 const sal_uInt32 nPointCount(aPoly.count());
338 if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
339 throw lang::IndexOutOfBoundsException();
341 aPoly.setB2DPoint( nPointIndex,
342 B2DPoint( segment.Px,
343 segment.Py ) );
344 aPoly.setNextControlPoint(nPointIndex,
345 B2DPoint(segment.C1x, segment.C1y));
346 aPoly.setPrevControlPoint((nPointIndex + 1) % nPointCount,
347 B2DPoint(segment.C2x, segment.C2y));
349 maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
352 B2DPolyPolygon UnoPolyPolygon::getSubsetPolyPolygon(
353 sal_Int32 nPolygonIndex,
354 sal_Int32 nNumberOfPolygons,
355 sal_Int32 nPointIndex,
356 sal_Int32 nNumberOfPoints ) const
358 osl::MutexGuard const guard( m_aMutex );
359 checkIndex( nPolygonIndex );
361 const sal_Int32 nPolyCount( maPolyPoly.count() );
363 // check for "full polygon" case
364 if( !nPolygonIndex &&
365 !nPointIndex &&
366 nNumberOfPolygons == nPolyCount &&
367 nNumberOfPoints == -1 )
369 return maPolyPoly;
372 B2DPolyPolygon aSubsetPoly;
374 // create temporary polygon (as an extract from maPoly,
375 // which contains the requested subset)
376 for( sal_Int32 i=nPolygonIndex; i<nNumberOfPolygons; ++i )
378 checkIndex(i);
380 const B2DPolygon& rCurrPoly( maPolyPoly.getB2DPolygon(i) );
382 sal_Int32 nFirstPoint(0);
383 sal_Int32 nLastPoint(nPolyCount-1);
385 if( nPointIndex && i==nPolygonIndex )
387 // very first polygon - respect nPointIndex, if
388 // not zero
390 // empty polygon - impossible to specify _any_
391 // legal value except 0 here!
392 if( !nPolyCount && nPointIndex )
393 throw lang::IndexOutOfBoundsException();
395 nFirstPoint = nPointIndex;
398 if( i==nNumberOfPolygons-1 && nNumberOfPoints != -1 )
400 // very last polygon - respect nNumberOfPoints
402 // empty polygon - impossible to specify _any_
403 // legal value except -1 here!
404 if( !nPolyCount )
405 throw lang::IndexOutOfBoundsException();
407 nLastPoint = nFirstPoint+nNumberOfPoints;
410 if( !nPolyCount )
412 // empty polygon - index checks already performed
413 // above, now simply append empty polygon
414 aSubsetPoly.append( rCurrPoly );
416 else
418 if( nFirstPoint < 0 || nFirstPoint >= nPolyCount )
419 throw lang::IndexOutOfBoundsException();
421 if( nLastPoint < 0 || nLastPoint >= nPolyCount )
422 throw lang::IndexOutOfBoundsException();
424 B2DPolygon aTmp;
425 for( sal_Int32 j=nFirstPoint; j<nLastPoint; ++j )
426 aTmp.append( rCurrPoly.getB2DPoint(j) );
428 aSubsetPoly.append( aTmp );
432 return aSubsetPoly;
435 #define IMPLEMENTATION_NAME "gfx::internal::UnoPolyPolygon"
436 #define SERVICE_NAME "com.sun.star.rendering.PolyPolygon2D"
437 OUString SAL_CALL UnoPolyPolygon::getImplementationName()
439 return OUString( IMPLEMENTATION_NAME );
442 sal_Bool SAL_CALL UnoPolyPolygon::supportsService( const OUString& ServiceName )
444 return cppu::supportsService(this, ServiceName);
447 uno::Sequence< OUString > SAL_CALL UnoPolyPolygon::getSupportedServiceNames()
449 return { SERVICE_NAME };
452 B2DPolyPolygon UnoPolyPolygon::getPolyPolygon() const
454 osl::MutexGuard const guard( m_aMutex );
456 // detach result from us
457 B2DPolyPolygon aRet( maPolyPoly );
458 aRet.makeUnique();
459 return aRet;
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */