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 <basegfx/polygon/b2dpolypolygontools.hxx>
21 : #include <osl/diagnose.h>
22 : #include <basegfx/polygon/b2dpolypolygon.hxx>
23 : #include <basegfx/polygon/b2dpolygon.hxx>
24 : #include <basegfx/polygon/b2dpolygontools.hxx>
25 : #include <basegfx/numeric/ftools.hxx>
26 : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
27 : #include <numeric>
28 :
29 : namespace basegfx
30 : {
31 : namespace tools
32 : {
33 4626 : B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate)
34 : {
35 4626 : B2DPolyPolygon aRetval(rCandidate);
36 4626 : const sal_uInt32 nCount(aRetval.count());
37 :
38 9441 : for(sal_uInt32 a(0L); a < nCount; a++)
39 : {
40 4815 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
41 4815 : const B2VectorOrientation aOrientation(tools::getOrientation(aCandidate));
42 4815 : sal_uInt32 nDepth(0L);
43 :
44 10136 : for(sal_uInt32 b(0L); b < nCount; b++)
45 : {
46 5321 : if(b != a)
47 : {
48 506 : const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
49 :
50 506 : if(tools::isInside(aCompare, aCandidate, true))
51 : {
52 12 : nDepth++;
53 506 : }
54 : }
55 : }
56 :
57 4815 : const bool bShallBeHole(1L == (nDepth & 0x00000001));
58 4815 : const bool bIsHole(B2VectorOrientation::Negative == aOrientation);
59 :
60 4815 : if(bShallBeHole != bIsHole && B2VectorOrientation::Neutral != aOrientation)
61 : {
62 197 : B2DPolygon aFlipped(aCandidate);
63 197 : aFlipped.flip();
64 197 : aRetval.setB2DPolygon(a, aFlipped);
65 : }
66 4815 : }
67 :
68 4626 : return aRetval;
69 : }
70 :
71 4328 : B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate)
72 : {
73 4328 : const sal_uInt32 nCount(rCandidate.count());
74 :
75 4328 : if(nCount > 1L)
76 : {
77 120 : for(sal_uInt32 a(0L); a < nCount; a++)
78 : {
79 120 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
80 120 : sal_uInt32 nDepth(0L);
81 :
82 416 : for(sal_uInt32 b(0L); b < nCount; b++)
83 : {
84 296 : if(b != a)
85 : {
86 176 : const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
87 :
88 176 : if(tools::isInside(aCompare, aCandidate, true))
89 : {
90 0 : nDepth++;
91 176 : }
92 : }
93 : }
94 :
95 120 : if(!nDepth)
96 : {
97 120 : B2DPolyPolygon aRetval(rCandidate);
98 :
99 120 : if(a != 0L)
100 : {
101 : // exchange polygon a and polygon 0L
102 0 : aRetval.setB2DPolygon(0L, aCandidate);
103 0 : aRetval.setB2DPolygon(a, rCandidate.getB2DPolygon(0L));
104 : }
105 :
106 : // exit
107 120 : return aRetval;
108 : }
109 0 : }
110 : }
111 :
112 4208 : return rCandidate;
113 : }
114 :
115 0 : B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound)
116 : {
117 0 : if(rCandidate.areControlPointsUsed())
118 : {
119 0 : const sal_uInt32 nPolygonCount(rCandidate.count());
120 0 : B2DPolyPolygon aRetval;
121 :
122 0 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
123 : {
124 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
125 :
126 0 : if(aCandidate.areControlPointsUsed())
127 : {
128 0 : aRetval.append(tools::adaptiveSubdivideByDistance(aCandidate, fDistanceBound));
129 : }
130 : else
131 : {
132 0 : aRetval.append(aCandidate);
133 : }
134 0 : }
135 :
136 0 : return aRetval;
137 : }
138 : else
139 : {
140 0 : return rCandidate;
141 : }
142 : }
143 :
144 4372 : B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound)
145 : {
146 4372 : if(rCandidate.areControlPointsUsed())
147 : {
148 33 : const sal_uInt32 nPolygonCount(rCandidate.count());
149 33 : B2DPolyPolygon aRetval;
150 :
151 66 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
152 : {
153 33 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
154 :
155 33 : if(aCandidate.areControlPointsUsed())
156 : {
157 33 : aRetval.append(tools::adaptiveSubdivideByAngle(aCandidate, fAngleBound));
158 : }
159 : else
160 : {
161 0 : aRetval.append(aCandidate);
162 : }
163 33 : }
164 :
165 33 : return aRetval;
166 : }
167 : else
168 : {
169 4339 : return rCandidate;
170 : }
171 : }
172 :
173 0 : B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount)
174 : {
175 0 : if(rCandidate.areControlPointsUsed())
176 : {
177 0 : const sal_uInt32 nPolygonCount(rCandidate.count());
178 0 : B2DPolyPolygon aRetval;
179 :
180 0 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
181 : {
182 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
183 :
184 0 : if(aCandidate.areControlPointsUsed())
185 : {
186 0 : aRetval.append(tools::adaptiveSubdivideByCount(aCandidate, nCount));
187 : }
188 : else
189 : {
190 0 : aRetval.append(aCandidate);
191 : }
192 0 : }
193 :
194 0 : return aRetval;
195 : }
196 : else
197 : {
198 0 : return rCandidate;
199 : }
200 : }
201 :
202 5532 : bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder)
203 : {
204 5532 : const sal_uInt32 nPolygonCount(rCandidate.count());
205 :
206 5532 : if(1L == nPolygonCount)
207 : {
208 5531 : return isInside(rCandidate.getB2DPolygon(0L), rPoint, bWithBorder);
209 : }
210 : else
211 : {
212 1 : sal_Int32 nInsideCount(0L);
213 :
214 4 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
215 : {
216 3 : const B2DPolygon aPolygon(rCandidate.getB2DPolygon(a));
217 3 : const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
218 :
219 3 : if(bInside)
220 : {
221 1 : nInsideCount++;
222 : }
223 3 : }
224 :
225 1 : return (nInsideCount % 2L);
226 : }
227 : }
228 :
229 4108048 : B2DRange getRange(const B2DPolyPolygon& rCandidate)
230 : {
231 4108048 : B2DRange aRetval;
232 4108048 : const sal_uInt32 nPolygonCount(rCandidate.count());
233 :
234 8396440 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
235 : {
236 4288392 : B2DPolygon aCandidate = rCandidate.getB2DPolygon(a);
237 4288392 : aRetval.expand(tools::getRange(aCandidate));
238 4288392 : }
239 :
240 4108048 : return aRetval;
241 : }
242 :
243 0 : double getSignedArea(const B2DPolyPolygon& rCandidate)
244 : {
245 0 : double fRetval(0.0);
246 0 : const sal_uInt32 nPolygonCount(rCandidate.count());
247 :
248 0 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
249 : {
250 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
251 :
252 0 : fRetval += tools::getSignedArea(aCandidate);
253 0 : }
254 :
255 0 : return fRetval;
256 : }
257 :
258 0 : double getArea(const B2DPolyPolygon& rCandidate)
259 : {
260 0 : return fabs(getSignedArea(rCandidate));
261 : }
262 :
263 0 : void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen)
264 : {
265 0 : if(0.0 == fFullDashDotLen && rDotDashArray.size())
266 : {
267 : // calculate fFullDashDotLen from rDotDashArray
268 0 : fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
269 : }
270 :
271 0 : if(rCandidate.count() && fFullDashDotLen > 0.0)
272 : {
273 0 : B2DPolyPolygon aLineTarget, aGapTarget;
274 :
275 0 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
276 : {
277 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
278 :
279 : applyLineDashing(
280 : aCandidate,
281 : rDotDashArray,
282 : pLineTarget ? &aLineTarget : 0,
283 : pGapTarget ? &aGapTarget : 0,
284 0 : fFullDashDotLen);
285 :
286 0 : if(pLineTarget)
287 : {
288 0 : pLineTarget->append(aLineTarget);
289 : }
290 :
291 0 : if(pGapTarget)
292 : {
293 0 : pGapTarget->append(aGapTarget);
294 : }
295 0 : }
296 : }
297 0 : }
298 :
299 50 : bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance)
300 : {
301 50 : const sal_uInt32 nPolygonCount(rCandidate.count());
302 :
303 58 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
304 : {
305 52 : B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
306 :
307 52 : if(isInEpsilonRange(aCandidate, rTestPosition, fDistance))
308 : {
309 44 : return true;
310 : }
311 8 : }
312 :
313 6 : return false;
314 : }
315 :
316 21972 : B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate)
317 : {
318 21972 : const sal_uInt32 nPolygonCount(rCandidate.count());
319 21972 : B3DPolyPolygon aRetval;
320 :
321 51376 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
322 : {
323 29404 : B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
324 :
325 29404 : aRetval.append(createB3DPolygonFromB2DPolygon(aCandidate, fZCoordinate));
326 29404 : }
327 :
328 21972 : return aRetval;
329 : }
330 :
331 4837 : B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat)
332 : {
333 4837 : const sal_uInt32 nPolygonCount(rCandidate.count());
334 4837 : B2DPolyPolygon aRetval;
335 :
336 10034 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
337 : {
338 5197 : B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
339 :
340 5197 : aRetval.append(createB2DPolygonFromB3DPolygon(aCandidate, rMat));
341 5197 : }
342 :
343 4837 : return aRetval;
344 : }
345 :
346 0 : double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut)
347 : {
348 0 : double fRetval(DBL_MAX);
349 0 : const double fZero(0.0);
350 0 : const sal_uInt32 nPolygonCount(rCandidate.count());
351 :
352 0 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
353 : {
354 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
355 : sal_uInt32 nNewEdgeIndex;
356 0 : double fNewCut(0.0);
357 0 : const double fNewDistance(getSmallestDistancePointToPolygon(aCandidate, rTestPoint, nNewEdgeIndex, fNewCut));
358 :
359 0 : if(DBL_MAX == fRetval || fNewDistance < fRetval)
360 : {
361 0 : fRetval = fNewDistance;
362 0 : rPolygonIndex = a;
363 0 : rEdgeIndex = nNewEdgeIndex;
364 0 : rCut = fNewCut;
365 :
366 0 : if(fTools::equal(fRetval, fZero))
367 : {
368 : // already found zero distance, cannot get better. Ensure numerical zero value and end loop.
369 0 : fRetval = 0.0;
370 0 : break;
371 : }
372 : }
373 0 : }
374 :
375 0 : return fRetval;
376 : }
377 :
378 0 : B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight)
379 : {
380 0 : const sal_uInt32 nPolygonCount(rCandidate.count());
381 0 : B2DPolyPolygon aRetval;
382 :
383 0 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
384 : {
385 0 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
386 :
387 0 : aRetval.append(distort(aCandidate, rOriginal, rTopLeft, rTopRight, rBottomLeft, rBottomRight));
388 0 : }
389 :
390 0 : return aRetval;
391 : }
392 :
393 20 : B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate)
394 : {
395 20 : const sal_uInt32 nPolygonCount(rCandidate.count());
396 20 : B2DPolyPolygon aRetval;
397 :
398 40 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
399 : {
400 20 : const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
401 :
402 20 : aRetval.append(expandToCurve(aCandidate));
403 20 : }
404 :
405 20 : return aRetval;
406 : }
407 :
408 234 : B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue)
409 : {
410 234 : if(0.0 != fValue)
411 : {
412 234 : B2DPolyPolygon aRetval;
413 :
414 468 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
415 : {
416 234 : aRetval.append(growInNormalDirection(rCandidate.getB2DPolygon(a), fValue));
417 : }
418 :
419 234 : return aRetval;
420 : }
421 : else
422 : {
423 0 : return rCandidate;
424 : }
425 : }
426 :
427 0 : void correctGrowShrinkPolygonPair(SAL_UNUSED_PARAMETER B2DPolyPolygon& /*rOriginal*/, SAL_UNUSED_PARAMETER B2DPolyPolygon& /*rGrown*/)
428 : {
429 : //TODO!
430 0 : }
431 :
432 0 : B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments)
433 : {
434 0 : B2DPolyPolygon aRetval;
435 :
436 0 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
437 : {
438 0 : aRetval.append(reSegmentPolygon(rCandidate.getB2DPolygon(a), nSegments));
439 : }
440 :
441 0 : return aRetval;
442 : }
443 :
444 0 : B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t)
445 : {
446 : OSL_ENSURE(rOld1.count() == rOld2.count(), "B2DPolyPolygon interpolate: Different geometry (!)");
447 0 : B2DPolyPolygon aRetval;
448 :
449 0 : for(sal_uInt32 a(0L); a < rOld1.count(); a++)
450 : {
451 0 : aRetval.append(interpolate(rOld1.getB2DPolygon(a), rOld2.getB2DPolygon(a), t));
452 : }
453 :
454 0 : return aRetval;
455 : }
456 :
457 18345 : bool isRectangle( const B2DPolyPolygon& rPoly )
458 : {
459 : // exclude some cheap cases first
460 18345 : if( rPoly.count() != 1 )
461 4 : return false;
462 :
463 18341 : return isRectangle( rPoly.getB2DPolygon(0) );
464 : }
465 :
466 : // #i76891#
467 977 : B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate)
468 : {
469 977 : if(rCandidate.areControlPointsUsed())
470 : {
471 487 : B2DPolyPolygon aRetval;
472 :
473 2321 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
474 : {
475 1834 : aRetval.append(simplifyCurveSegments(rCandidate.getB2DPolygon(a)));
476 : }
477 :
478 487 : return aRetval;
479 : }
480 : else
481 : {
482 490 : return rCandidate;
483 : }
484 : }
485 :
486 0 : B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate)
487 : {
488 0 : B2DPolyPolygon aRetval;
489 :
490 0 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
491 : {
492 0 : aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rCandidate.getB2DPolygon(a)));
493 : }
494 :
495 0 : return aRetval;
496 : }
497 :
498 0 : bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate)
499 : {
500 0 : if(rCandidate.areControlPointsUsed())
501 : {
502 0 : return false;
503 : }
504 :
505 0 : for(sal_uInt32 a(0); a < rCandidate.count(); a++)
506 : {
507 0 : if(!containsOnlyHorizontalAndVerticalEdges(rCandidate.getB2DPolygon(a)))
508 : {
509 0 : return false;
510 : }
511 : }
512 :
513 0 : return true;
514 : }
515 :
516 0 : B2DPolyPolygon createSevenSegmentPolyPolygon(sal_Char nNumber, bool bLitSegments)
517 : {
518 : // config here
519 : // {
520 0 : const double fTotalSize=1.0;
521 0 : const double fPosMiddleSegment=0.6;
522 0 : const double fSegmentEndChopHoriz=0.08;
523 0 : const double fSegmentEndChopVert =0.04;
524 : // }
525 : // config here
526 :
527 0 : const double fLeft=0.0;
528 0 : const double fRight=fTotalSize;
529 0 : const double fTop=0.0;
530 0 : const double fMiddle=fPosMiddleSegment;
531 0 : const double fBottom=fTotalSize;
532 :
533 : // from 0 to 5: pair of segment corner coordinates
534 :
535 : // segment corner indices are these:
536 :
537 : // 0 - 1
538 : // | |
539 : // 2 - 3
540 : // | |
541 : // 4 - 5
542 :
543 : static const double corners[] =
544 : {
545 : fLeft, fTop,
546 : fRight, fTop,
547 : fLeft, fMiddle,
548 : fRight, fMiddle,
549 : fLeft, fBottom,
550 : fRight, fBottom
551 : };
552 :
553 : // from 0 to 9: which segments are 'lit' for this number?
554 :
555 : // array denotes graph edges to traverse, with -1 means
556 : // stop (the vertices are the corner indices from above):
557 : // 0
558 : // -
559 : // 1 | | 2
560 : // - 3
561 : // 4 | | 5
562 : // -
563 : // 6
564 :
565 : static const int numbers[] =
566 : {
567 : 1, 1, 1, 0, 1, 1, 1, // 0
568 : 0, 0, 1, 0, 0, 1, 0, // 1
569 : 1, 0, 1, 1, 1, 0, 1, // 2
570 : 1, 0, 1, 1, 0, 1, 1, // 3
571 : 0, 1, 1, 1, 0, 1, 0, // 4
572 : 1, 1, 0, 1, 0, 1, 1, // 5
573 : 1, 1, 0, 1, 1, 1, 1, // 6
574 : 1, 0, 1, 0, 0, 1, 0, // 1
575 : 1, 1, 1, 1, 1, 1, 1, // 8
576 : 1, 1, 1, 1, 0, 1, 1, // 9
577 : 0, 0, 0, 1, 0, 0, 0, // '-'
578 : 1, 1, 0, 1, 1, 0, 1, // 'E'
579 : };
580 :
581 : // maps segment index to two corner ids:
582 : static const int index2corner[] =
583 : {
584 : 0, 2, // 0
585 : 0, 4, // 1
586 : 2, 6, // 2
587 : 4, 6, // 3
588 : 4, 8, // 4
589 : 6, 10, // 5
590 : 8, 10, // 6
591 : };
592 :
593 0 : B2DPolyPolygon aRes;
594 0 : if( nNumber == '-' )
595 : {
596 0 : nNumber = 10;
597 : }
598 0 : else if( nNumber == 'E' )
599 : {
600 0 : nNumber = 11;
601 : }
602 0 : else if( nNumber == '.' )
603 : {
604 0 : if( bLitSegments )
605 : aRes.append(createPolygonFromCircle(B2DPoint(fTotalSize/2, fTotalSize),
606 0 : fSegmentEndChopHoriz));
607 0 : return aRes;
608 : }
609 : else
610 : {
611 0 : nNumber=clamp<sal_uInt32>(nNumber,'0','9') - '0';
612 : }
613 :
614 0 : B2DPolygon aCurrSegment;
615 0 : const size_t sliceSize=SAL_N_ELEMENTS(numbers)/12;
616 0 : const int* pCurrSegment=numbers + nNumber*sliceSize;
617 0 : for( size_t i=0; i<sliceSize; i++, pCurrSegment++)
618 : {
619 0 : if( !(*pCurrSegment ^ int(bLitSegments)) )
620 : {
621 0 : const size_t j=2*i;
622 0 : aCurrSegment.clear();
623 0 : B2DPoint start(corners[index2corner[j]],
624 0 : corners[index2corner[j]+1] );
625 0 : B2DPoint end (corners[index2corner[j+1]],
626 0 : corners[index2corner[j+1]+1]);
627 :
628 0 : if( start.getX() == end.getX() )
629 : {
630 0 : start.setY(start.getY()+fSegmentEndChopVert);
631 0 : end.setY(end.getY()-fSegmentEndChopVert);
632 : }
633 : else
634 : {
635 0 : start.setX(start.getX()+fSegmentEndChopHoriz);
636 0 : end.setX(end.getX()-fSegmentEndChopHoriz);
637 : }
638 :
639 0 : aCurrSegment.append(start);
640 0 : aCurrSegment.append(end);
641 : }
642 0 : aRes.append(aCurrSegment);
643 : }
644 :
645 0 : return aRes;
646 : }
647 :
648 : // converters for com::sun::star::drawing::PointSequence
649 :
650 16 : B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
651 : const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
652 : bool bCheckClosed)
653 : {
654 16 : B2DPolyPolygon aRetval;
655 16 : const com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceSource.getConstArray();
656 16 : const com::sun::star::drawing::PointSequence* pPointSeqEnd = pPointSequence + rPointSequenceSequenceSource.getLength();
657 :
658 17 : for(;pPointSequence != pPointSeqEnd; pPointSequence++)
659 : {
660 1 : const B2DPolygon aNewPolygon = UnoPointSequenceToB2DPolygon(*pPointSequence, bCheckClosed);
661 1 : aRetval.append(aNewPolygon);
662 1 : }
663 :
664 16 : return aRetval;
665 : }
666 :
667 446 : void B2DPolyPolygonToUnoPointSequenceSequence(
668 : const B2DPolyPolygon& rPolyPolygon,
669 : com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval)
670 : {
671 446 : const sal_uInt32 nCount(rPolyPolygon.count());
672 :
673 446 : if(nCount)
674 : {
675 446 : rPointSequenceSequenceRetval.realloc(nCount);
676 446 : com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceRetval.getArray();
677 :
678 892 : for(sal_uInt32 a(0); a < nCount; a++)
679 : {
680 446 : const B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(a));
681 :
682 446 : B2DPolygonToUnoPointSequence(aPolygon, *pPointSequence);
683 446 : pPointSequence++;
684 446 : }
685 : }
686 : else
687 : {
688 0 : rPointSequenceSequenceRetval.realloc(0);
689 : }
690 446 : }
691 :
692 : // converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
693 :
694 20 : B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
695 : const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
696 : bool bCheckClosed)
697 : {
698 20 : B2DPolyPolygon aRetval;
699 20 : const sal_uInt32 nSequenceCount((sal_uInt32)rPolyPolygonBezierCoordsSource.Coordinates.getLength());
700 :
701 20 : if(nSequenceCount)
702 : {
703 : OSL_ENSURE(nSequenceCount == (sal_uInt32)rPolyPolygonBezierCoordsSource.Flags.getLength(),
704 : "UnoPolyPolygonBezierCoordsToB2DPolyPolygon: unequal number of Points and Flags (!)");
705 20 : const com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsSource.Coordinates.getConstArray();
706 20 : const com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsSource.Flags.getConstArray();
707 :
708 40 : for(sal_uInt32 a(0); a < nSequenceCount; a++)
709 : {
710 : const B2DPolygon aNewPolygon(UnoPolygonBezierCoordsToB2DPolygon(
711 : *pPointSequence,
712 : *pFlagSequence,
713 20 : bCheckClosed));
714 :
715 20 : pPointSequence++;
716 20 : pFlagSequence++;
717 20 : aRetval.append(aNewPolygon);
718 20 : }
719 : }
720 :
721 20 : return aRetval;
722 : }
723 :
724 412 : void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
725 : const B2DPolyPolygon& rPolyPolygon,
726 : com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval)
727 : {
728 412 : const sal_uInt32 nCount(rPolyPolygon.count());
729 :
730 412 : if(nCount)
731 : {
732 : // prepare return value memory
733 412 : rPolyPolygonBezierCoordsRetval.Coordinates.realloc((sal_Int32)nCount);
734 412 : rPolyPolygonBezierCoordsRetval.Flags.realloc((sal_Int32)nCount);
735 :
736 : // get pointers to arrays
737 412 : com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsRetval.Coordinates.getArray();
738 412 : com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsRetval.Flags.getArray();
739 :
740 939 : for(sal_uInt32 a(0); a < nCount; a++)
741 : {
742 527 : const B2DPolygon aSource(rPolyPolygon.getB2DPolygon(a));
743 :
744 : B2DPolygonToUnoPolygonBezierCoords(
745 : aSource,
746 : *pPointSequence,
747 527 : *pFlagSequence);
748 527 : pPointSequence++;
749 527 : pFlagSequence++;
750 527 : }
751 : }
752 : else
753 : {
754 0 : rPolyPolygonBezierCoordsRetval.Coordinates.realloc(0);
755 0 : rPolyPolygonBezierCoordsRetval.Flags.realloc(0);
756 : }
757 412 : }
758 :
759 : } // end of namespace tools
760 : } // end of namespace basegfx
761 :
762 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|