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/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
;
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
);
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.
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.
80 aSrcPoly
= pSrc
->getPolyPolygon();
84 // not a known implementation object - try data source
86 uno::Reference
< rendering::XBezierPolyPolygon2D
> xBezierPoly(
90 if( xBezierPoly
.is() )
92 aSrcPoly
= unotools::polyPolygonFromBezier2DSequenceSequence(
93 xBezierPoly
->getBezierSegments( 0,
100 uno::Reference
< rendering::XLinePolyPolygon2D
> xLinePoly(
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,
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(
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
);
154 void SAL_CALL
UnoPolyPolygon::setFillRule(
155 rendering::FillRule fillRule
)
157 osl::MutexGuard
const guard( m_aMutex
);
160 meFillRule
= fillRule
;
163 sal_Bool SAL_CALL
UnoPolyPolygon::isClosed(
166 osl::MutexGuard
const guard( m_aMutex
);
169 return maPolyPoly
.getB2DPolygon(index
).isClosed();
172 void SAL_CALL
UnoPolyPolygon::setClosed(
174 sal_Bool closedState
)
176 osl::MutexGuard
const guard( m_aMutex
);
182 maPolyPoly
.setClosed( closedState
);
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
,
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
);
219 const B2DPolyPolygon
& rNewPolyPoly(
220 unotools::polyPolygonFromPoint2DSequenceSequence( points
) );
222 if( nPolygonIndex
== -1 )
224 maPolyPoly
= rNewPolyPoly
;
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
);
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
,
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
);
288 const B2DPolyPolygon
& rNewPolyPoly(
289 unotools::polyPolygonFromBezier2DSequenceSequence( points
) );
291 if( nPolygonIndex
== -1 )
293 maPolyPoly
= rNewPolyPoly
;
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(),
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
);
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
,
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
&&
366 nNumberOfPolygons
== nPolyCount
&&
367 nNumberOfPoints
== -1 )
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
)
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
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!
405 throw lang::IndexOutOfBoundsException();
407 nLastPoint
= nFirstPoint
+nNumberOfPoints
;
412 // empty polygon - index checks already performed
413 // above, now simply append empty polygon
414 aSubsetPoly
.append( rCurrPoly
);
418 if( nFirstPoint
< 0 || nFirstPoint
>= nPolyCount
)
419 throw lang::IndexOutOfBoundsException();
421 if( nLastPoint
< 0 || nLastPoint
>= nPolyCount
)
422 throw lang::IndexOutOfBoundsException();
425 for( sal_Int32 j
=nFirstPoint
; j
<nLastPoint
; ++j
)
426 aTmp
.append( rCurrPoly
.getB2DPoint(j
) );
428 aSubsetPoly
.append( aTmp
);
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
);
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */