1*09dbbe93SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*09dbbe93SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*09dbbe93SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*09dbbe93SAndrew Rist  * distributed with this work for additional information
6*09dbbe93SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*09dbbe93SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*09dbbe93SAndrew Rist  * "License"); you may not use this file except in compliance
9*09dbbe93SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*09dbbe93SAndrew Rist  *
11*09dbbe93SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*09dbbe93SAndrew Rist  *
13*09dbbe93SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*09dbbe93SAndrew Rist  * software distributed under the License is distributed on an
15*09dbbe93SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*09dbbe93SAndrew Rist  * KIND, either express or implied.  See the License for the
17*09dbbe93SAndrew Rist  * specific language governing permissions and limitations
18*09dbbe93SAndrew Rist  * under the License.
19*09dbbe93SAndrew Rist  *
20*09dbbe93SAndrew Rist  *************************************************************/
21*09dbbe93SAndrew Rist 
22*09dbbe93SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basegfx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <com/sun/star/geometry/AffineMatrix2D.hpp>
28cdf0e10cSrcweir #include <com/sun/star/rendering/RenderState.hpp>
29cdf0e10cSrcweir #include <com/sun/star/rendering/ViewState.hpp>
30cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvas.hpp>
31cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
34cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
35cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
36cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
37cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
38cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
39cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
40cdf0e10cSrcweir #include <basegfx/tools/unopolypolygon.hxx>
41cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir 
44cdf0e10cSrcweir using namespace ::com::sun::star;
45cdf0e10cSrcweir 
46cdf0e10cSrcweir namespace basegfx
47cdf0e10cSrcweir {
48cdf0e10cSrcweir namespace unotools
49cdf0e10cSrcweir {
50cdf0e10cSrcweir     UnoPolyPolygon::UnoPolyPolygon( const B2DPolyPolygon& rPolyPoly ) :
51cdf0e10cSrcweir         UnoPolyPolygonBase( m_aMutex ),
52cdf0e10cSrcweir         maPolyPoly( rPolyPoly ),
53cdf0e10cSrcweir         meFillRule( rendering::FillRule_EVEN_ODD )
54cdf0e10cSrcweir     {
55cdf0e10cSrcweir         // or else races will haunt us.
56cdf0e10cSrcweir         maPolyPoly.makeUnique();
57cdf0e10cSrcweir     }
58cdf0e10cSrcweir 
59cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::addPolyPolygon(
60cdf0e10cSrcweir         const geometry::RealPoint2D& 						position,
61cdf0e10cSrcweir         const uno::Reference< rendering::XPolyPolygon2D >&	polyPolygon ) throw (lang::IllegalArgumentException,uno::RuntimeException)
62cdf0e10cSrcweir     {
63cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
64cdf0e10cSrcweir         modifying();
65cdf0e10cSrcweir 
66cdf0e10cSrcweir         // TODO(F1): Correctly fulfill the UNO API
67cdf0e10cSrcweir         // specification. This will probably result in a vector of
68cdf0e10cSrcweir         // poly-polygons to be stored in this object.
69cdf0e10cSrcweir 
70cdf0e10cSrcweir         const sal_Int32 nPolys( polyPolygon->getNumberOfPolygons() );
71cdf0e10cSrcweir 
72cdf0e10cSrcweir         if( !polyPolygon.is() || !nPolys )
73cdf0e10cSrcweir         {
74cdf0e10cSrcweir             // invalid or empty polygon - nothing to do.
75cdf0e10cSrcweir             return;
76cdf0e10cSrcweir         }
77cdf0e10cSrcweir 
78cdf0e10cSrcweir         B2DPolyPolygon        aSrcPoly;
79cdf0e10cSrcweir         const UnoPolyPolygon* pSrc( dynamic_cast< UnoPolyPolygon* >(polyPolygon.get()) );
80cdf0e10cSrcweir 
81cdf0e10cSrcweir         // try to extract polygon data from interface. First,
82cdf0e10cSrcweir         // check whether it's the same implementation object,
83cdf0e10cSrcweir         // which we can tunnel then.
84cdf0e10cSrcweir         if( pSrc )
85cdf0e10cSrcweir         {
86cdf0e10cSrcweir             aSrcPoly = pSrc->getPolyPolygon();
87cdf0e10cSrcweir         }
88cdf0e10cSrcweir         else
89cdf0e10cSrcweir         {
90cdf0e10cSrcweir             // not a known implementation object - try data source
91cdf0e10cSrcweir             // interfaces
92cdf0e10cSrcweir             uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
93cdf0e10cSrcweir                 polyPolygon,
94cdf0e10cSrcweir                 uno::UNO_QUERY );
95cdf0e10cSrcweir 
96cdf0e10cSrcweir             if( xBezierPoly.is() )
97cdf0e10cSrcweir             {
98cdf0e10cSrcweir                 aSrcPoly = unotools::polyPolygonFromBezier2DSequenceSequence(
99cdf0e10cSrcweir                     xBezierPoly->getBezierSegments( 0,
100cdf0e10cSrcweir                                                     nPolys,
101cdf0e10cSrcweir                                                     0,
102cdf0e10cSrcweir                                                     -1 ) );
103cdf0e10cSrcweir             }
104cdf0e10cSrcweir             else
105cdf0e10cSrcweir             {
106cdf0e10cSrcweir                 uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
107cdf0e10cSrcweir                     polyPolygon,
108cdf0e10cSrcweir                     uno::UNO_QUERY );
109cdf0e10cSrcweir 
110cdf0e10cSrcweir                 // no implementation class and no data provider
111cdf0e10cSrcweir                 // found - contract violation.
112cdf0e10cSrcweir                 if( !xLinePoly.is() )
113cdf0e10cSrcweir                     throw lang::IllegalArgumentException(
114cdf0e10cSrcweir                         ::rtl::OUString(
115cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
116cdf0e10cSrcweir                                 "UnoPolyPolygon::addPolyPolygon(): Invalid input "
117cdf0e10cSrcweir                                 "poly-polygon, cannot retrieve vertex data")),
118cdf0e10cSrcweir                         static_cast<cppu::OWeakObject*>(this), 1);
119cdf0e10cSrcweir 
120cdf0e10cSrcweir                 aSrcPoly = unotools::polyPolygonFromPoint2DSequenceSequence(
121cdf0e10cSrcweir                     xLinePoly->getPoints( 0,
122cdf0e10cSrcweir                                           nPolys,
123cdf0e10cSrcweir                                           0,
124cdf0e10cSrcweir                                           -1 ) );
125cdf0e10cSrcweir             }
126cdf0e10cSrcweir         }
127cdf0e10cSrcweir 
128cdf0e10cSrcweir         const B2DRange	aBounds( tools::getRange( aSrcPoly ) );
129cdf0e10cSrcweir         const B2DVector 	aOffset( unotools::b2DPointFromRealPoint2D( position ) -
130cdf0e10cSrcweir                                              aBounds.getMinimum() );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir         if( !aOffset.equalZero() )
133cdf0e10cSrcweir         {
134cdf0e10cSrcweir             const B2DHomMatrix aTranslate(tools::createTranslateB2DHomMatrix(aOffset));
135cdf0e10cSrcweir             aSrcPoly.transform( aTranslate );
136cdf0e10cSrcweir         }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         maPolyPoly.append( aSrcPoly );
139cdf0e10cSrcweir     }
140cdf0e10cSrcweir 
141cdf0e10cSrcweir     sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygons() throw (uno::RuntimeException)
142cdf0e10cSrcweir     {
143cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
144cdf0e10cSrcweir         return maPolyPoly.count();
145cdf0e10cSrcweir     }
146cdf0e10cSrcweir 
147cdf0e10cSrcweir     sal_Int32 SAL_CALL UnoPolyPolygon::getNumberOfPolygonPoints(
148cdf0e10cSrcweir         sal_Int32 polygon ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
149cdf0e10cSrcweir     {
150cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
151cdf0e10cSrcweir         checkIndex( polygon );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir         return maPolyPoly.getB2DPolygon(polygon).count();
154cdf0e10cSrcweir     }
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     rendering::FillRule SAL_CALL UnoPolyPolygon::getFillRule() throw (uno::RuntimeException)
157cdf0e10cSrcweir     {
158cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
159cdf0e10cSrcweir         return meFillRule;
160cdf0e10cSrcweir     }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setFillRule(
163cdf0e10cSrcweir         rendering::FillRule fillRule ) throw (uno::RuntimeException)
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
166cdf0e10cSrcweir         modifying();
167cdf0e10cSrcweir 
168cdf0e10cSrcweir         meFillRule = fillRule;
169cdf0e10cSrcweir     }
170cdf0e10cSrcweir 
171cdf0e10cSrcweir     sal_Bool SAL_CALL UnoPolyPolygon::isClosed(
172cdf0e10cSrcweir         sal_Int32 index ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
173cdf0e10cSrcweir     {
174cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
175cdf0e10cSrcweir         checkIndex( index );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         return maPolyPoly.getB2DPolygon(index).isClosed();
178cdf0e10cSrcweir     }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setClosed(
181cdf0e10cSrcweir         sal_Int32 index,
182cdf0e10cSrcweir         sal_Bool closedState ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
183cdf0e10cSrcweir     {
184cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
185cdf0e10cSrcweir         modifying();
186cdf0e10cSrcweir 
187cdf0e10cSrcweir         if( index == -1L )
188cdf0e10cSrcweir         {
189cdf0e10cSrcweir             // set all
190cdf0e10cSrcweir             maPolyPoly.setClosed( closedState );
191cdf0e10cSrcweir         }
192cdf0e10cSrcweir         else
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             checkIndex( index );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir             // fetch referenced polygon, change state
197cdf0e10cSrcweir             B2DPolygon aTmp( maPolyPoly.getB2DPolygon(index) );
198cdf0e10cSrcweir             aTmp.setClosed( closedState );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir             // set back to container
201cdf0e10cSrcweir             maPolyPoly.setB2DPolygon( index, aTmp );
202cdf0e10cSrcweir         }
203cdf0e10cSrcweir     }
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     uno::Sequence< uno::Sequence< geometry::RealPoint2D > > SAL_CALL UnoPolyPolygon::getPoints(
206cdf0e10cSrcweir         sal_Int32 nPolygonIndex,
207cdf0e10cSrcweir         sal_Int32 nNumberOfPolygons,
208cdf0e10cSrcweir         sal_Int32 nPointIndex,
209cdf0e10cSrcweir         sal_Int32 nNumberOfPoints ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
210cdf0e10cSrcweir     {
211cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir         return unotools::pointSequenceSequenceFromB2DPolyPolygon(
214cdf0e10cSrcweir             getSubsetPolyPolygon( nPolygonIndex,
215cdf0e10cSrcweir                                   nNumberOfPolygons,
216cdf0e10cSrcweir                                   nPointIndex,
217cdf0e10cSrcweir                                   nNumberOfPoints ) );
218cdf0e10cSrcweir     }
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setPoints(
221cdf0e10cSrcweir         const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points,
222cdf0e10cSrcweir         sal_Int32 nPolygonIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
223cdf0e10cSrcweir     {
224cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
225cdf0e10cSrcweir         modifying();
226cdf0e10cSrcweir 
227cdf0e10cSrcweir         const B2DPolyPolygon& rNewPolyPoly(
228cdf0e10cSrcweir             unotools::polyPolygonFromPoint2DSequenceSequence( points ) );
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         if( nPolygonIndex == -1 )
231cdf0e10cSrcweir         {
232cdf0e10cSrcweir             maPolyPoly = rNewPolyPoly;
233cdf0e10cSrcweir         }
234cdf0e10cSrcweir         else
235cdf0e10cSrcweir         {
236cdf0e10cSrcweir             checkIndex( nPolygonIndex );
237cdf0e10cSrcweir 
238cdf0e10cSrcweir             maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
239cdf0e10cSrcweir         }
240cdf0e10cSrcweir     }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir     geometry::RealPoint2D SAL_CALL UnoPolyPolygon::getPoint(
243cdf0e10cSrcweir         sal_Int32 nPolygonIndex,
244cdf0e10cSrcweir         sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
245cdf0e10cSrcweir     {
246cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
247cdf0e10cSrcweir         checkIndex( nPolygonIndex );
248cdf0e10cSrcweir 
249cdf0e10cSrcweir         const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
250cdf0e10cSrcweir 
251cdf0e10cSrcweir         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(rPoly.count()) )
252cdf0e10cSrcweir             throw lang::IndexOutOfBoundsException();
253cdf0e10cSrcweir 
254cdf0e10cSrcweir         return unotools::point2DFromB2DPoint( rPoly.getB2DPoint( nPointIndex ) );
255cdf0e10cSrcweir     }
256cdf0e10cSrcweir 
257cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setPoint(
258cdf0e10cSrcweir         const geometry::RealPoint2D& point,
259cdf0e10cSrcweir         sal_Int32 nPolygonIndex,
260cdf0e10cSrcweir         sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,uno::RuntimeException)
261cdf0e10cSrcweir     {
262cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
263cdf0e10cSrcweir         checkIndex( nPolygonIndex );
264cdf0e10cSrcweir         modifying();
265cdf0e10cSrcweir 
266cdf0e10cSrcweir         B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
267cdf0e10cSrcweir 
268cdf0e10cSrcweir         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(aPoly.count()) )
269cdf0e10cSrcweir             throw lang::IndexOutOfBoundsException();
270cdf0e10cSrcweir 
271cdf0e10cSrcweir         aPoly.setB2DPoint( nPointIndex,
272cdf0e10cSrcweir                            unotools::b2DPointFromRealPoint2D( point ) );
273cdf0e10cSrcweir         maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
274cdf0e10cSrcweir     }
275cdf0e10cSrcweir 
276cdf0e10cSrcweir     uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > SAL_CALL UnoPolyPolygon::getBezierSegments(
277cdf0e10cSrcweir         sal_Int32 nPolygonIndex,
278cdf0e10cSrcweir         sal_Int32 nNumberOfPolygons,
279cdf0e10cSrcweir         sal_Int32 nPointIndex,
280cdf0e10cSrcweir         sal_Int32 nNumberOfPoints ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
283cdf0e10cSrcweir         return unotools::bezierSequenceSequenceFromB2DPolyPolygon(
284cdf0e10cSrcweir             getSubsetPolyPolygon( nPolygonIndex,
285cdf0e10cSrcweir                                   nNumberOfPolygons,
286cdf0e10cSrcweir                                   nPointIndex,
287cdf0e10cSrcweir                                   nNumberOfPoints ) );
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setBezierSegments(
291cdf0e10cSrcweir         const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >&	points,
292cdf0e10cSrcweir         sal_Int32 																nPolygonIndex ) throw (lang::IndexOutOfBoundsException,
293cdf0e10cSrcweir                                                                                                        uno::RuntimeException)
294cdf0e10cSrcweir     {
295cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
296cdf0e10cSrcweir         modifying();
297cdf0e10cSrcweir         const B2DPolyPolygon& rNewPolyPoly(
298cdf0e10cSrcweir             unotools::polyPolygonFromBezier2DSequenceSequence( points ) );
299cdf0e10cSrcweir 
300cdf0e10cSrcweir         if( nPolygonIndex == -1 )
301cdf0e10cSrcweir         {
302cdf0e10cSrcweir             maPolyPoly = rNewPolyPoly;
303cdf0e10cSrcweir         }
304cdf0e10cSrcweir         else
305cdf0e10cSrcweir         {
306cdf0e10cSrcweir             checkIndex( nPolygonIndex );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir             maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
309cdf0e10cSrcweir         }
310cdf0e10cSrcweir     }
311cdf0e10cSrcweir 
312cdf0e10cSrcweir     geometry::RealBezierSegment2D SAL_CALL UnoPolyPolygon::getBezierSegment( sal_Int32 nPolygonIndex,
313cdf0e10cSrcweir                                                                              sal_Int32 nPointIndex ) throw (lang::IndexOutOfBoundsException,
314cdf0e10cSrcweir                                                                                                             uno::RuntimeException)
315cdf0e10cSrcweir     {
316cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
317cdf0e10cSrcweir         checkIndex( nPolygonIndex );
318cdf0e10cSrcweir 
319cdf0e10cSrcweir         const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
320cdf0e10cSrcweir 		const sal_uInt32  nPointCount(rPoly.count());
321cdf0e10cSrcweir 
322cdf0e10cSrcweir         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
323cdf0e10cSrcweir             throw lang::IndexOutOfBoundsException();
324cdf0e10cSrcweir 
325cdf0e10cSrcweir         const B2DPoint& rPt( rPoly.getB2DPoint( nPointIndex ) );
326cdf0e10cSrcweir         const B2DPoint& rCtrl0( rPoly.getNextControlPoint(nPointIndex) );
327cdf0e10cSrcweir         const B2DPoint& rCtrl1( rPoly.getPrevControlPoint((nPointIndex + 1) % nPointCount) );
328cdf0e10cSrcweir 
329cdf0e10cSrcweir         return geometry::RealBezierSegment2D( rPt.getX(),
330cdf0e10cSrcweir                                               rPt.getY(),
331cdf0e10cSrcweir                                               rCtrl0.getX(),
332cdf0e10cSrcweir                                               rCtrl0.getY(),
333cdf0e10cSrcweir                                               rCtrl1.getX(),
334cdf0e10cSrcweir                                               rCtrl1.getY() );
335cdf0e10cSrcweir     }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir     void SAL_CALL UnoPolyPolygon::setBezierSegment( const geometry::RealBezierSegment2D& segment,
338cdf0e10cSrcweir                                                          sal_Int32 						 nPolygonIndex,
339cdf0e10cSrcweir                                                          sal_Int32						 nPointIndex ) throw (lang::IndexOutOfBoundsException,
340cdf0e10cSrcweir                                                                                                               uno::RuntimeException)
341cdf0e10cSrcweir     {
342cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
343cdf0e10cSrcweir         checkIndex( nPolygonIndex );
344cdf0e10cSrcweir         modifying();
345cdf0e10cSrcweir 
346cdf0e10cSrcweir         B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
347cdf0e10cSrcweir 		const sal_uInt32 nPointCount(aPoly.count());
348cdf0e10cSrcweir 
349cdf0e10cSrcweir         if( nPointIndex < 0 || nPointIndex >= static_cast<sal_Int32>(nPointCount) )
350cdf0e10cSrcweir             throw lang::IndexOutOfBoundsException();
351cdf0e10cSrcweir 
352cdf0e10cSrcweir         aPoly.setB2DPoint( nPointIndex,
353cdf0e10cSrcweir                            B2DPoint( segment.Px,
354cdf0e10cSrcweir                                      segment.Py ) );
355cdf0e10cSrcweir         aPoly.setNextControlPoint(nPointIndex,
356cdf0e10cSrcweir                                   B2DPoint(segment.C1x, segment.C1y));
357cdf0e10cSrcweir         aPoly.setPrevControlPoint((nPointIndex + 1) % nPointCount,
358cdf0e10cSrcweir                                   B2DPoint(segment.C2x, segment.C2y));
359cdf0e10cSrcweir 
360cdf0e10cSrcweir         maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     B2DPolyPolygon UnoPolyPolygon::getSubsetPolyPolygon(
364cdf0e10cSrcweir         sal_Int32 nPolygonIndex,
365cdf0e10cSrcweir         sal_Int32 nNumberOfPolygons,
366cdf0e10cSrcweir         sal_Int32 nPointIndex,
367cdf0e10cSrcweir         sal_Int32 nNumberOfPoints ) const
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
370cdf0e10cSrcweir         checkIndex( nPolygonIndex );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir         const sal_Int32 nPolyCount( maPolyPoly.count() );
373cdf0e10cSrcweir 
374cdf0e10cSrcweir         // check for "full polygon" case
375cdf0e10cSrcweir         if( !nPolygonIndex &&
376cdf0e10cSrcweir             !nPointIndex &&
377cdf0e10cSrcweir             nNumberOfPolygons == nPolyCount &&
378cdf0e10cSrcweir             nNumberOfPoints == -1 )
379cdf0e10cSrcweir         {
380cdf0e10cSrcweir             return maPolyPoly;
381cdf0e10cSrcweir         }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir         B2DPolyPolygon aSubsetPoly;
384cdf0e10cSrcweir 
385cdf0e10cSrcweir         // create temporary polygon (as an extract from maPoly,
386cdf0e10cSrcweir         // which contains the requested subset)
387cdf0e10cSrcweir         for( sal_Int32 i=nPolygonIndex; i<nNumberOfPolygons; ++i )
388cdf0e10cSrcweir         {
389cdf0e10cSrcweir             checkIndex(i);
390cdf0e10cSrcweir 
391cdf0e10cSrcweir             const B2DPolygon& rCurrPoly( maPolyPoly.getB2DPolygon(i) );
392cdf0e10cSrcweir 
393cdf0e10cSrcweir             sal_Int32 nFirstPoint(0);
394cdf0e10cSrcweir             sal_Int32 nLastPoint(nPolyCount-1);
395cdf0e10cSrcweir 
396cdf0e10cSrcweir             if( nPointIndex && i==nPolygonIndex )
397cdf0e10cSrcweir             {
398cdf0e10cSrcweir                 // very first polygon - respect nPointIndex, if
399cdf0e10cSrcweir                 // not zero
400cdf0e10cSrcweir 
401cdf0e10cSrcweir                 // empty polygon - impossible to specify _any_
402cdf0e10cSrcweir                 // legal value except 0 here!
403cdf0e10cSrcweir                 if( !nPolyCount && nPointIndex )
404cdf0e10cSrcweir                     throw lang::IndexOutOfBoundsException();
405cdf0e10cSrcweir 
406cdf0e10cSrcweir                 nFirstPoint = nPointIndex;
407cdf0e10cSrcweir             }
408cdf0e10cSrcweir 
409cdf0e10cSrcweir             if( i==nNumberOfPolygons-1 && nNumberOfPoints != -1 )
410cdf0e10cSrcweir             {
411cdf0e10cSrcweir                 // very last polygon - respect nNumberOfPoints
412cdf0e10cSrcweir 
413cdf0e10cSrcweir                 // empty polygon - impossible to specify _any_
414cdf0e10cSrcweir                 // legal value except -1 here!
415cdf0e10cSrcweir                 if( !nPolyCount )
416cdf0e10cSrcweir                     throw lang::IndexOutOfBoundsException();
417cdf0e10cSrcweir 
418cdf0e10cSrcweir                 nLastPoint = nFirstPoint+nNumberOfPoints;
419cdf0e10cSrcweir             }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir             if( !nPolyCount )
422cdf0e10cSrcweir             {
423cdf0e10cSrcweir                 // empty polygon - index checks already performed
424cdf0e10cSrcweir                 // above, now simply append empty polygon
425cdf0e10cSrcweir                 aSubsetPoly.append( rCurrPoly );
426cdf0e10cSrcweir             }
427cdf0e10cSrcweir             else
428cdf0e10cSrcweir             {
429cdf0e10cSrcweir                 if( nFirstPoint < 0 || nFirstPoint >= nPolyCount )
430cdf0e10cSrcweir                     throw lang::IndexOutOfBoundsException();
431cdf0e10cSrcweir 
432cdf0e10cSrcweir                 if( nLastPoint < 0 || nLastPoint >= nPolyCount )
433cdf0e10cSrcweir                     throw lang::IndexOutOfBoundsException();
434cdf0e10cSrcweir 
435cdf0e10cSrcweir                 B2DPolygon aTmp;
436cdf0e10cSrcweir                 for( sal_Int32 j=nFirstPoint; j<nLastPoint; ++j )
437cdf0e10cSrcweir                     aTmp.append( rCurrPoly.getB2DPoint(j) );
438cdf0e10cSrcweir 
439cdf0e10cSrcweir                 aSubsetPoly.append( aTmp );
440cdf0e10cSrcweir             }
441cdf0e10cSrcweir         }
442cdf0e10cSrcweir 
443cdf0e10cSrcweir         return aSubsetPoly;
444cdf0e10cSrcweir     }
445cdf0e10cSrcweir 
446cdf0e10cSrcweir     B2DPolyPolygon UnoPolyPolygon::getPolyPolygonUnsafe() const
447cdf0e10cSrcweir     {
448cdf0e10cSrcweir         return maPolyPoly;
449cdf0e10cSrcweir     }
450cdf0e10cSrcweir 
451cdf0e10cSrcweir #define IMPLEMENTATION_NAME "gfx::internal::UnoPolyPolygon"
452cdf0e10cSrcweir #define SERVICE_NAME "com.sun.star.rendering.PolyPolygon2D"
453cdf0e10cSrcweir     ::rtl::OUString SAL_CALL UnoPolyPolygon::getImplementationName() throw( uno::RuntimeException )
454cdf0e10cSrcweir     {
455cdf0e10cSrcweir         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
456cdf0e10cSrcweir     }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir     sal_Bool SAL_CALL UnoPolyPolygon::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
459cdf0e10cSrcweir     {
460cdf0e10cSrcweir         return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
461cdf0e10cSrcweir     }
462cdf0e10cSrcweir 
463cdf0e10cSrcweir     uno::Sequence< ::rtl::OUString > SAL_CALL UnoPolyPolygon::getSupportedServiceNames()  throw( uno::RuntimeException )
464cdf0e10cSrcweir     {
465cdf0e10cSrcweir         uno::Sequence< ::rtl::OUString > aRet(1);
466cdf0e10cSrcweir         aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
467cdf0e10cSrcweir 
468cdf0e10cSrcweir         return aRet;
469cdf0e10cSrcweir     }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir     B2DPolyPolygon UnoPolyPolygon::getPolyPolygon() const
472cdf0e10cSrcweir     {
473cdf0e10cSrcweir         osl::MutexGuard const guard( m_aMutex );
474cdf0e10cSrcweir 
475cdf0e10cSrcweir         // detach result from us
476cdf0e10cSrcweir         B2DPolyPolygon aRet( maPolyPoly );
477cdf0e10cSrcweir         aRet.makeUnique();
478cdf0e10cSrcweir         return aRet;
479cdf0e10cSrcweir     }
480cdf0e10cSrcweir 
481cdf0e10cSrcweir }
482cdf0e10cSrcweir }
483