LibreOffice Module basegfx (master) 1
unopolypolygon.cxx
Go to the documentation of this file.
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/lang/IllegalArgumentException.hpp>
21
31#include <utility>
32
33using namespace ::com::sun::star;
34
35namespace basegfx::unotools
36{
38 maPolyPoly(std::move( aPolyPoly )),
39 meFillRule( rendering::FillRule_EVEN_ODD )
40 {
41 }
42
44 const geometry::RealPoint2D& position,
45 const uno::Reference< rendering::XPolyPolygon2D >& polyPolygon )
46 {
47 std::unique_lock const guard( m_aMutex );
48 modifying();
49
50 // TODO(F1): Correctly fulfill the UNO API
51 // specification. This will probably result in a vector of
52 // poly-polygons to be stored in this object.
53
54 const sal_Int32 nPolys( polyPolygon->getNumberOfPolygons() );
55
56 if( !polyPolygon.is() || !nPolys )
57 {
58 // invalid or empty polygon - nothing to do.
59 return;
60 }
61
62 B2DPolyPolygon aSrcPoly;
63 const UnoPolyPolygon* pSrc( dynamic_cast< UnoPolyPolygon* >(polyPolygon.get()) );
64
65 // try to extract polygon data from interface. First,
66 // check whether it's the same implementation object,
67 // which we can tunnel then.
68 if( pSrc )
69 {
70 aSrcPoly = pSrc->getPolyPolygon();
71 }
72 else
73 {
74 // not a known implementation object - try data source
75 // interfaces
76 uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
77 polyPolygon,
78 uno::UNO_QUERY );
79
80 if( xBezierPoly.is() )
81 {
83 xBezierPoly->getBezierSegments( 0,
84 nPolys,
85 0,
86 -1 ) );
87 }
88 else
89 {
90 uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
91 polyPolygon,
92 uno::UNO_QUERY );
93
94 // no implementation class and no data provider
95 // found - contract violation.
96 if( !xLinePoly.is() )
97 throw lang::IllegalArgumentException(
98 "UnoPolyPolygon::addPolyPolygon(): Invalid input "
99 "poly-polygon, cannot retrieve vertex data",
100 getXWeak(), 1);
101
103 xLinePoly->getPoints( 0,
104 nPolys,
105 0,
106 -1 ) );
107 }
108 }
109
110 const B2DRange aBounds( utils::getRange( aSrcPoly ) );
112 aBounds.getMinimum() );
113
114 if( !aOffset.equalZero() )
115 {
116 const B2DHomMatrix aTranslate(utils::createTranslateB2DHomMatrix(aOffset));
117 aSrcPoly.transform( aTranslate );
118 }
119
120 maPolyPoly.append( aSrcPoly );
121 }
122
124 {
125 std::unique_lock const guard( m_aMutex );
126 return maPolyPoly.count();
127 }
128
130 sal_Int32 polygon )
131 {
132 std::unique_lock const guard( m_aMutex );
133 checkIndex( polygon );
134
135 return maPolyPoly.getB2DPolygon(polygon).count();
136 }
137
138 rendering::FillRule SAL_CALL UnoPolyPolygon::getFillRule()
139 {
140 std::unique_lock const guard( m_aMutex );
141 return meFillRule;
142 }
143
145 rendering::FillRule fillRule )
146 {
147 std::unique_lock const guard( m_aMutex );
148 modifying();
149
150 meFillRule = fillRule;
151 }
152
154 sal_Int32 index )
155 {
156 std::unique_lock const guard( m_aMutex );
157 checkIndex( index );
158
160 }
161
163 sal_Int32 index,
164 sal_Bool closedState )
165 {
166 std::unique_lock const guard( m_aMutex );
167 modifying();
168
169 if( index == -1 )
170 {
171 // set all
172 maPolyPoly.setClosed( closedState );
173 }
174 else
175 {
176 checkIndex( index );
177
178 // fetch referenced polygon, change state
180 aTmp.setClosed( closedState );
181
182 // set back to container
184 }
185 }
186
187 uno::Sequence< uno::Sequence< geometry::RealPoint2D > > SAL_CALL UnoPolyPolygon::getPoints(
188 sal_Int32 nPolygonIndex,
189 sal_Int32 nNumberOfPolygons,
190 sal_Int32 nPointIndex,
191 sal_Int32 nNumberOfPoints )
192 {
194 getSubsetPolyPolygon( nPolygonIndex,
195 nNumberOfPolygons,
196 nPointIndex,
197 nNumberOfPoints ) );
198 }
199
201 const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points,
202 sal_Int32 nPolygonIndex )
203 {
204 std::unique_lock const guard( m_aMutex );
205 modifying();
206
207 const B2DPolyPolygon& rNewPolyPoly(
209
210 if( nPolygonIndex == -1 )
211 {
212 maPolyPoly = rNewPolyPoly;
213 }
214 else
215 {
216 checkIndex( nPolygonIndex );
217
218 maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
219 }
220 }
221
222 geometry::RealPoint2D SAL_CALL UnoPolyPolygon::getPoint(
223 sal_Int32 nPolygonIndex,
224 sal_Int32 nPointIndex )
225 {
226 std::unique_lock const guard( m_aMutex );
227 checkIndex( nPolygonIndex );
228
229 const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
230
231 if( nPointIndex < 0 || o3tl::make_unsigned(nPointIndex) >= rPoly.count() )
232 throw lang::IndexOutOfBoundsException();
233
234 return unotools::point2DFromB2DPoint( rPoly.getB2DPoint( nPointIndex ) );
235 }
236
238 const geometry::RealPoint2D& point,
239 sal_Int32 nPolygonIndex,
240 sal_Int32 nPointIndex )
241 {
242 std::unique_lock const guard( m_aMutex );
243 checkIndex( nPolygonIndex );
244 modifying();
245
246 B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
247
248 if( nPointIndex < 0 || o3tl::make_unsigned(nPointIndex) >= aPoly.count() )
249 throw lang::IndexOutOfBoundsException();
250
251 aPoly.setB2DPoint( nPointIndex,
253 maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
254 }
255
256 uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > SAL_CALL UnoPolyPolygon::getBezierSegments(
257 sal_Int32 nPolygonIndex,
258 sal_Int32 nNumberOfPolygons,
259 sal_Int32 nPointIndex,
260 sal_Int32 nNumberOfPoints )
261 {
263 getSubsetPolyPolygon( nPolygonIndex,
264 nNumberOfPolygons,
265 nPointIndex,
266 nNumberOfPoints ) );
267 }
268
270 const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points,
271 sal_Int32 nPolygonIndex )
272 {
273 std::unique_lock const guard( m_aMutex );
274 modifying();
275 const B2DPolyPolygon& rNewPolyPoly(
277
278 if( nPolygonIndex == -1 )
279 {
280 maPolyPoly = rNewPolyPoly;
281 }
282 else
283 {
284 checkIndex( nPolygonIndex );
285
286 maPolyPoly.insert( nPolygonIndex, rNewPolyPoly );
287 }
288 }
289
290 geometry::RealBezierSegment2D SAL_CALL UnoPolyPolygon::getBezierSegment( sal_Int32 nPolygonIndex,
291 sal_Int32 nPointIndex )
292 {
293 std::unique_lock const guard( m_aMutex );
294 checkIndex( nPolygonIndex );
295
296 const B2DPolygon& rPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
297 const sal_uInt32 nPointCount(rPoly.count());
298
299 if( nPointIndex < 0 || o3tl::make_unsigned(nPointIndex) >= nPointCount )
300 throw lang::IndexOutOfBoundsException();
301
302 const B2DPoint& rPt( rPoly.getB2DPoint( nPointIndex ) );
303 const B2DPoint& rCtrl0( rPoly.getNextControlPoint(nPointIndex) );
304 const B2DPoint& rCtrl1( rPoly.getPrevControlPoint((nPointIndex + 1) % nPointCount) );
305
306 return geometry::RealBezierSegment2D( rPt.getX(),
307 rPt.getY(),
308 rCtrl0.getX(),
309 rCtrl0.getY(),
310 rCtrl1.getX(),
311 rCtrl1.getY() );
312 }
313
314 void SAL_CALL UnoPolyPolygon::setBezierSegment( const geometry::RealBezierSegment2D& segment,
315 sal_Int32 nPolygonIndex,
316 sal_Int32 nPointIndex )
317 {
318 std::unique_lock const guard( m_aMutex );
319 checkIndex( nPolygonIndex );
320 modifying();
321
322 B2DPolygon aPoly( maPolyPoly.getB2DPolygon( nPolygonIndex ) );
323 const sal_uInt32 nPointCount(aPoly.count());
324
325 if( nPointIndex < 0 || o3tl::make_unsigned(nPointIndex) >= nPointCount )
326 throw lang::IndexOutOfBoundsException();
327
328 aPoly.setB2DPoint( nPointIndex,
329 B2DPoint( segment.Px,
330 segment.Py ) );
331 aPoly.setNextControlPoint(nPointIndex,
332 B2DPoint(segment.C1x, segment.C1y));
333 aPoly.setPrevControlPoint((nPointIndex + 1) % nPointCount,
334 B2DPoint(segment.C2x, segment.C2y));
335
336 maPolyPoly.setB2DPolygon( nPolygonIndex, aPoly );
337 }
338
340 sal_Int32 nPolygonIndex,
341 sal_Int32 nNumberOfPolygons,
342 sal_Int32 nPointIndex,
343 sal_Int32 nNumberOfPoints ) const
344 {
345 std::unique_lock const guard( m_aMutex );
346 checkIndex( nPolygonIndex );
347
348 const sal_Int32 nPolyCount( maPolyPoly.count() );
349
350 // check for "full polygon" case
351 if( !nPolygonIndex &&
352 !nPointIndex &&
353 nNumberOfPolygons == nPolyCount &&
354 nNumberOfPoints == -1 )
355 {
356 return maPolyPoly;
357 }
358
359 B2DPolyPolygon aSubsetPoly;
360
361 // create temporary polygon (as an extract from maPoly,
362 // which contains the requested subset)
363 for( sal_Int32 i=nPolygonIndex; i<nNumberOfPolygons; ++i )
364 {
365 checkIndex(i);
366
367 const B2DPolygon& rCurrPoly( maPolyPoly.getB2DPolygon(i) );
368
369 sal_Int32 nFirstPoint(0);
370 sal_Int32 nLastPoint(nPolyCount-1);
371
372 if( nPointIndex && i==nPolygonIndex )
373 {
374 // very first polygon - respect nPointIndex, if
375 // not zero
376
377 // empty polygon - impossible to specify _any_
378 // legal value except 0 here!
379 if( !nPolyCount)
380 throw lang::IndexOutOfBoundsException();
381
382 nFirstPoint = nPointIndex;
383 }
384
385 if( i==nNumberOfPolygons-1 && nNumberOfPoints != -1 )
386 {
387 // very last polygon - respect nNumberOfPoints
388
389 // empty polygon - impossible to specify _any_
390 // legal value except -1 here!
391 if( !nPolyCount )
392 throw lang::IndexOutOfBoundsException();
393
394 nLastPoint = nFirstPoint+nNumberOfPoints;
395 }
396
397 if( !nPolyCount )
398 {
399 // empty polygon - index checks already performed
400 // above, now simply append empty polygon
401 aSubsetPoly.append( rCurrPoly );
402 }
403 else
404 {
405 if( nFirstPoint < 0 || nFirstPoint >= nPolyCount )
406 throw lang::IndexOutOfBoundsException();
407
408 if( nLastPoint < 0 || nLastPoint >= nPolyCount )
409 throw lang::IndexOutOfBoundsException();
410
411 B2DPolygon aTmp;
412 for( sal_Int32 j=nFirstPoint; j<nLastPoint; ++j )
413 aTmp.append( rCurrPoly.getB2DPoint(j) );
414
415 aSubsetPoly.append( aTmp );
416 }
417 }
418
419 return aSubsetPoly;
420 }
421
423 {
424 return "gfx::internal::UnoPolyPolygon";
425 }
426
427 sal_Bool SAL_CALL UnoPolyPolygon::supportsService( const OUString& ServiceName )
428 {
430 }
431
432 uno::Sequence< OUString > SAL_CALL UnoPolyPolygon::getSupportedServiceNames()
433 {
434 return { "com.sun.star.rendering.PolyPolygon2D" };
435 }
436
438 {
439 std::unique_lock const guard( m_aMutex );
440
441 return maPolyPoly;
442 }
443
444}
445
446/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Base Point class with two double values.
Definition: b2dpoint.hxx:42
void insert(sal_uInt32 nIndex, const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
void setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon &rPolygon)
void transform(const basegfx::B2DHomMatrix &rMatrix)
sal_uInt32 count() const
void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
bool isClosed() const
closed state interface
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const
Coordinate interface.
void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const
Basic ControlPoint interface.
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
sal_uInt32 count() const
member count
void setClosed(bool bNew)
basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const
A two-dimensional interval over doubles.
Definition: b2drange.hxx:54
B2DPoint getMinimum() const
get lower bound of the set. returns arbitrary values for empty sets.
Definition: b2drange.hxx:80
Base Point class with two double values.
Definition: b2dvector.hxx:40
bool equalZero() const
Definition: Tuple2D.hxx:95
TYPE getX() const
Get X-Coordinate of 2D Tuple.
Definition: Tuple2D.hxx:63
TYPE getY() const
Get Y-Coordinate of 2D Tuple.
Definition: Tuple2D.hxx:66
virtual SAL_DLLPRIVATE void SAL_CALL setBezierSegments(const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > > &points, ::sal_Int32 nPolygonIndex) override
virtual SAL_DLLPRIVATE css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > > SAL_CALL getPoints(::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints) override
virtual void modifying() const
Called whenever internal polypolygon gets modified.
virtual SAL_DLLPRIVATE void SAL_CALL setPoints(const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > > &points, ::sal_Int32 nPolygonIndex) override
virtual SAL_DLLPRIVATE css::geometry::RealBezierSegment2D SAL_CALL getBezierSegment(::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex) override
void checkIndex(sal_Int32 nIndex) const
Check whether index is a valid polygon index.
virtual SAL_DLLPRIVATE ::sal_Int32 SAL_CALL getNumberOfPolygonPoints(::sal_Int32 polygon) override
virtual SAL_DLLPRIVATE css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > > SAL_CALL getBezierSegments(::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints) override
virtual SAL_DLLPRIVATE void SAL_CALL setClosed(::sal_Int32 index, sal_Bool closedState) override
virtual SAL_DLLPRIVATE void SAL_CALL setFillRule(css::rendering::FillRule fillRule) override
virtual SAL_DLLPRIVATE sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual SAL_DLLPRIVATE void SAL_CALL setPoint(const css::geometry::RealPoint2D &point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex) override
virtual SAL_DLLPRIVATE OUString SAL_CALL getImplementationName() override
SAL_DLLPRIVATE B2DPolyPolygon getSubsetPolyPolygon(sal_Int32 nPolygonIndex, sal_Int32 nNumberOfPolygons, sal_Int32 nPointIndex, sal_Int32 nNumberOfPoints) const
SAL_DLLPRIVATE B2DPolyPolygon getPolyPolygon() const
css::rendering::FillRule meFillRule
virtual SAL_DLLPRIVATE css::rendering::FillRule SAL_CALL getFillRule() override
virtual SAL_DLLPRIVATE sal_Bool SAL_CALL isClosed(::sal_Int32 index) override
virtual SAL_DLLPRIVATE ::sal_Int32 SAL_CALL getNumberOfPolygons() override
virtual SAL_DLLPRIVATE void SAL_CALL addPolyPolygon(const css::geometry::RealPoint2D &position, const css::uno::Reference< css::rendering::XPolyPolygon2D > &polyPolygon) override
virtual SAL_DLLPRIVATE void SAL_CALL setBezierSegment(const css::geometry::RealBezierSegment2D &point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex) override
virtual SAL_DLLPRIVATE css::geometry::RealPoint2D SAL_CALL getPoint(::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex) override
virtual SAL_DLLPRIVATE css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
def position(n=-1)
def point()
::basegfx::B2DPolyPolygon polyPolygonFromPoint2DSequenceSequence(const uno::Sequence< uno::Sequence< geometry::RealPoint2D > > &points)
::basegfx::B2DPolyPolygon polyPolygonFromBezier2DSequenceSequence(const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > &curves)
::basegfx::B2DPoint b2DPointFromRealPoint2D(const geometry::RealPoint2D &rPoint)
geometry::RealPoint2D point2DFromB2DPoint(const ::basegfx::B2DPoint &rPoint)
uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > > bezierSequenceSequenceFromB2DPolyPolygon(const ::basegfx::B2DPolyPolygon &rPolyPoly)
Definition: canvastools.cxx:94
uno::Sequence< uno::Sequence< geometry::RealPoint2D > > pointSequenceSequenceFromB2DPolyPolygon(const ::basegfx::B2DPolyPolygon &rPolyPoly)
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
B2DRange getRange(const B2DPolygon &rCandidate)
Get the range of a polygon.
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
index
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
unsigned char sal_Bool