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 <osl/endian.h>
21 : #include <tools/stream.hxx>
22 : #include <tools/debug.hxx>
23 : #include <tools/poly.hxx>
24 : #include <tools/helpers.hxx>
25 :
26 : #include <svx/xpoly.hxx>
27 : #include "xpolyimp.hxx"
28 : #include <basegfx/polygon/b2dpolygon.hxx>
29 : #include <basegfx/point/b2dpoint.hxx>
30 : #include <basegfx/vector/b2dvector.hxx>
31 : #include <basegfx/polygon/b2dpolygontools.hxx>
32 : #include <basegfx/range/b2drange.hxx>
33 : #include <basegfx/numeric/ftools.hxx>
34 :
35 : DBG_NAME(XPolygon);
36 : DBG_NAME(XPolyPolygon);
37 :
38 : /*************************************************************************
39 : |*
40 : |* ImpXPolygon::ImpXPolygon()
41 : |*
42 : *************************************************************************/
43 :
44 104 : ImpXPolygon::ImpXPolygon( sal_uInt16 nInitSize, sal_uInt16 _nResize )
45 : {
46 104 : pPointAry = NULL;
47 104 : pFlagAry = NULL;
48 104 : bDeleteOldPoints = sal_False;
49 104 : nSize = 0;
50 104 : nResize = _nResize;
51 104 : nPoints = 0;
52 104 : nRefCount = 1;
53 :
54 104 : Resize( nInitSize );
55 104 : }
56 :
57 : /*************************************************************************
58 : |*
59 : |* ImpXPolygon::ImpXPolygon()
60 : |*
61 : *************************************************************************/
62 :
63 0 : ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
64 : {
65 0 : ( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
66 :
67 0 : pPointAry = NULL;
68 0 : pFlagAry = NULL;
69 0 : bDeleteOldPoints = sal_False;
70 0 : nSize = 0;
71 0 : ImpXPolygon::nResize = rImpXPoly.nResize;
72 0 : nPoints = 0;
73 0 : nRefCount = 1;
74 :
75 0 : Resize( rImpXPoly.nSize );
76 :
77 : // Kopieren
78 0 : nPoints = rImpXPoly.nPoints;
79 0 : memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
80 0 : memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
81 0 : }
82 :
83 : /*************************************************************************
84 : |*
85 : |* ImpXPolygon::~ImpXPolygon()
86 : |*
87 : *************************************************************************/
88 :
89 104 : ImpXPolygon::~ImpXPolygon()
90 : {
91 104 : delete[] (char*) pPointAry;
92 104 : delete[] pFlagAry;
93 104 : if ( bDeleteOldPoints )
94 0 : delete[] (char*) pOldPointAry;
95 104 : }
96 :
97 : /*************************************************************************
98 : |*
99 : |* ImpXPolygon::operator==()
100 : |*
101 : *************************************************************************/
102 :
103 :
104 0 : bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
105 : {
106 : return nPoints==rImpXPoly.nPoints &&
107 : (nPoints==0 ||
108 0 : (memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
109 0 : memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
110 : }
111 :
112 : /*************************************************************************
113 : |*
114 : |* ImpXPolygon::Resize()
115 : |*
116 : |* !!! Polygongroesse aendern - wenn bDeletePoints sal_False, dann den
117 : |* Point-Array nicht loeschen, sondern in pOldPointAry sichern und
118 : |* das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
119 : |* das Array dann geloescht.
120 : |* Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
121 : |* Resize der fuer den rechten Ausdruck verwendete Point-Array
122 : |* vorzeitig geloescht wird.
123 : |*
124 : *************************************************************************/
125 :
126 104 : void ImpXPolygon::Resize( sal_uInt16 nNewSize, sal_Bool bDeletePoints )
127 : {
128 104 : if( nNewSize == nSize )
129 104 : return;
130 :
131 104 : sal_uInt8* pOldFlagAry = pFlagAry;
132 104 : sal_uInt16 nOldSize = nSize;
133 :
134 104 : CheckPointDelete();
135 104 : pOldPointAry = pPointAry;
136 :
137 : // Neue Groesse auf vielfaches von nResize runden, sofern Objekt
138 : // nicht neu angelegt wurde (nSize != 0)
139 104 : if ( nSize != 0 && nNewSize > nSize )
140 : {
141 : DBG_ASSERT(nResize, "Resize-Versuch trotz nResize = 0 !");
142 0 : nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
143 : }
144 : // Punkt Array erzeugen
145 104 : nSize = nNewSize;
146 104 : pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
147 104 : memset( pPointAry, 0, nSize*sizeof( Point ) );
148 :
149 : // Flag Array erzeugen
150 104 : pFlagAry = new sal_uInt8[ nSize ];
151 104 : memset( pFlagAry, 0, nSize );
152 :
153 : // Eventuell umkopieren
154 104 : if( nOldSize )
155 : {
156 0 : if( nOldSize < nSize )
157 : {
158 0 : memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
159 0 : memcpy( pFlagAry, pOldFlagAry, nOldSize );
160 : }
161 : else
162 : {
163 0 : memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
164 0 : memcpy( pFlagAry, pOldFlagAry, nSize );
165 :
166 : // Anzahl der gueltigen Punkte anpassen
167 0 : if( nPoints > nSize )
168 0 : nPoints = nSize;
169 : }
170 0 : if ( bDeletePoints ) delete[] (char*) pOldPointAry;
171 0 : else bDeleteOldPoints = sal_True;
172 0 : delete[] pOldFlagAry;
173 : }
174 : }
175 :
176 :
177 : /*************************************************************************
178 : |*
179 : |* ImpXPolygon::InsertSpace()
180 : |*
181 : *************************************************************************/
182 :
183 240 : void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
184 : {
185 240 : CheckPointDelete();
186 :
187 240 : if ( nPos > nPoints )
188 0 : nPos = nPoints;
189 :
190 : // Wenn Polygon zu klein dann groesser machen
191 240 : if( (nPoints + nCount) > nSize )
192 0 : Resize( nPoints + nCount );
193 :
194 : // Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
195 : // den Rest nach hinten schieben
196 240 : if( nPos < nPoints )
197 : {
198 0 : sal_uInt16 nMove = nPoints - nPos;
199 0 : memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
200 0 : nMove * sizeof(Point) );
201 0 : memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
202 : }
203 240 : memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
204 240 : memset( &pFlagAry [nPos], 0, nCount );
205 :
206 240 : nPoints = nPoints + nCount;
207 240 : }
208 :
209 :
210 : /*************************************************************************
211 : |*
212 : |* ImpXPolygon::Remove()
213 : |*
214 : *************************************************************************/
215 :
216 96 : void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
217 : {
218 96 : CheckPointDelete();
219 :
220 96 : if( (nPos + nCount) <= nPoints )
221 : {
222 96 : sal_uInt16 nMove = nPoints - nPos - nCount;
223 :
224 96 : if( nMove )
225 : {
226 0 : memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
227 0 : nMove * sizeof(Point) );
228 0 : memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
229 : }
230 96 : memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
231 96 : memset( &pFlagAry [nPoints - nCount], 0, nCount );
232 96 : nPoints = nPoints - nCount;
233 : }
234 96 : }
235 :
236 :
237 : /*************************************************************************
238 : |*
239 : |* XPolygon::XPolygon()
240 : |*
241 : *************************************************************************/
242 :
243 104 : XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
244 : {
245 : DBG_CTOR(XPolygon,NULL);
246 104 : pImpXPolygon = new ImpXPolygon( nSize, nResize );
247 104 : }
248 :
249 : /*************************************************************************
250 : |*
251 : |* XPolygon::XPolygon()
252 : |*
253 : *************************************************************************/
254 :
255 48 : XPolygon::XPolygon( const XPolygon& rXPoly )
256 : {
257 : DBG_CTOR(XPolygon,NULL);
258 48 : pImpXPolygon = rXPoly.pImpXPolygon;
259 48 : pImpXPolygon->nRefCount++;
260 48 : }
261 :
262 : /*************************************************************************
263 : |*
264 : |* XPolygon::XPolygon()
265 : |*
266 : |* Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
267 : |*
268 : *************************************************************************/
269 :
270 0 : XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
271 : {
272 : DBG_CTOR(XPolygon,NULL);
273 0 : pImpXPolygon = new ImpXPolygon(17);
274 0 : long nWh = (rRect.GetWidth() - 1) / 2;
275 0 : long nHh = (rRect.GetHeight() - 1) / 2;
276 :
277 0 : if ( nRx > nWh ) nRx = nWh;
278 0 : if ( nRy > nHh ) nRy = nHh;
279 :
280 : // Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
281 0 : nRx = -nRx;
282 :
283 : // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
284 0 : long nXHdl = (long)(0.552284749 * nRx);
285 0 : long nYHdl = (long)(0.552284749 * nRy);
286 0 : sal_uInt16 nPos = 0;
287 :
288 0 : if ( nRx && nRy )
289 : {
290 0 : Point aCenter;
291 :
292 0 : for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
293 : {
294 0 : switch ( nQuad )
295 : {
296 0 : case 0: aCenter = rRect.TopLeft();
297 0 : aCenter.X() -= nRx;
298 0 : aCenter.Y() += nRy;
299 0 : break;
300 0 : case 1: aCenter = rRect.TopRight();
301 0 : aCenter.X() += nRx;
302 0 : aCenter.Y() += nRy;
303 0 : break;
304 0 : case 2: aCenter = rRect.BottomRight();
305 0 : aCenter.X() += nRx;
306 0 : aCenter.Y() -= nRy;
307 0 : break;
308 0 : case 3: aCenter = rRect.BottomLeft();
309 0 : aCenter.X() -= nRx;
310 0 : aCenter.Y() -= nRy;
311 0 : break;
312 : }
313 0 : GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
314 0 : pImpXPolygon->pFlagAry[nPos ] = (sal_uInt8) XPOLY_SMOOTH;
315 0 : pImpXPolygon->pFlagAry[nPos+3] = (sal_uInt8) XPOLY_SMOOTH;
316 0 : nPos += 4;
317 0 : }
318 : }
319 : else
320 : {
321 0 : pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
322 0 : pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
323 0 : pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
324 0 : pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
325 : }
326 0 : pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
327 0 : pImpXPolygon->nPoints = nPos + 1;
328 0 : }
329 :
330 : /*************************************************************************
331 : |*
332 : |* XPolygon::XPolygon()
333 : |*
334 : |* Ellipsen(bogen) als Bezierpolygon erzeugen
335 : |*
336 : *************************************************************************/
337 :
338 0 : XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
339 : sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, sal_Bool bClose)
340 : {
341 : DBG_CTOR(XPolygon,NULL);
342 0 : pImpXPolygon = new ImpXPolygon(17);
343 :
344 0 : nStartAngle %= 3600;
345 0 : if ( nEndAngle > 3600 ) nEndAngle %= 3600;
346 0 : sal_Bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
347 :
348 : // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
349 0 : long nXHdl = (long)(0.552284749 * nRx);
350 0 : long nYHdl = (long)(0.552284749 * nRy);
351 0 : sal_uInt16 nPos = 0;
352 0 : sal_Bool bLoopEnd = sal_False;
353 :
354 0 : do
355 : {
356 : sal_uInt16 nA1, nA2;
357 0 : sal_uInt16 nQuad = nStartAngle / 900;
358 0 : if ( nQuad == 4 ) nQuad = 0;
359 0 : bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
360 0 : GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
361 0 : nPos += 3;
362 0 : if ( !bLoopEnd )
363 0 : pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
364 :
365 0 : } while ( !bLoopEnd );
366 :
367 : // Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
368 0 : if ( !bFull && bClose )
369 0 : pImpXPolygon->pPointAry[++nPos] = rCenter;
370 :
371 0 : if ( bFull )
372 : {
373 0 : pImpXPolygon->pFlagAry[0 ] = (sal_uInt8) XPOLY_SMOOTH;
374 0 : pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
375 : }
376 0 : pImpXPolygon->nPoints = nPos + 1;
377 0 : }
378 :
379 : /*************************************************************************
380 : |*
381 : |* XPolygon::~XPolygon()
382 : |*
383 : *************************************************************************/
384 :
385 152 : XPolygon::~XPolygon()
386 : {
387 : DBG_DTOR(XPolygon,NULL);
388 152 : if( pImpXPolygon->nRefCount > 1 )
389 54 : pImpXPolygon->nRefCount--;
390 : else
391 98 : delete pImpXPolygon;
392 152 : }
393 :
394 : /*************************************************************************
395 : |*
396 : |* XPolygon::CheckReference()
397 : |*
398 : |* Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
399 : |*
400 : *************************************************************************/
401 :
402 1066 : void XPolygon::CheckReference()
403 : {
404 1066 : if( pImpXPolygon->nRefCount > 1 )
405 : {
406 0 : pImpXPolygon->nRefCount--;
407 0 : pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
408 : }
409 1066 : }
410 :
411 : /*************************************************************************
412 : |*
413 : |* XPolygon::SetPointCount()
414 : |*
415 : *************************************************************************/
416 :
417 0 : void XPolygon::SetPointCount( sal_uInt16 nPoints )
418 : {
419 0 : pImpXPolygon->CheckPointDelete();
420 0 : CheckReference();
421 :
422 0 : if( pImpXPolygon->nSize < nPoints )
423 0 : pImpXPolygon->Resize( nPoints );
424 :
425 0 : if ( nPoints < pImpXPolygon->nPoints )
426 : {
427 0 : sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
428 0 : memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
429 0 : memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
430 : }
431 0 : pImpXPolygon->nPoints = nPoints;
432 0 : }
433 :
434 : /*************************************************************************
435 : |*
436 : |* XPolygon::GetPointCount()
437 : |*
438 : *************************************************************************/
439 :
440 214 : sal_uInt16 XPolygon::GetPointCount() const
441 : {
442 214 : pImpXPolygon->CheckPointDelete();
443 214 : return pImpXPolygon->nPoints;
444 : }
445 :
446 : /*************************************************************************
447 : |*
448 : |* XPolygon::Insert()
449 : |*
450 : *************************************************************************/
451 :
452 240 : void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, XPolyFlags eFlags )
453 : {
454 240 : CheckReference();
455 240 : if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
456 240 : pImpXPolygon->InsertSpace( nPos, 1 );
457 240 : pImpXPolygon->pPointAry[nPos] = rPt;
458 240 : pImpXPolygon->pFlagAry[nPos] = (sal_uInt8)eFlags;
459 240 : }
460 :
461 : /*************************************************************************
462 : |*
463 : |* XPolygon::Insert()
464 : |*
465 : *************************************************************************/
466 :
467 0 : void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
468 : {
469 0 : CheckReference();
470 0 : if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
471 :
472 0 : sal_uInt16 nPoints = rXPoly.GetPointCount();
473 :
474 0 : pImpXPolygon->InsertSpace( nPos, nPoints );
475 :
476 0 : memcpy( &(pImpXPolygon->pPointAry[nPos]),
477 : rXPoly.pImpXPolygon->pPointAry,
478 0 : nPoints*sizeof( Point ) );
479 0 : memcpy( &(pImpXPolygon->pFlagAry[nPos]),
480 : rXPoly.pImpXPolygon->pFlagAry,
481 0 : nPoints );
482 0 : }
483 :
484 : /*************************************************************************
485 : |*
486 : |* XPolygon::Remove()
487 : |*
488 : *************************************************************************/
489 :
490 96 : void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
491 : {
492 96 : CheckReference();
493 96 : pImpXPolygon->Remove( nPos, nCount );
494 96 : }
495 :
496 : /*************************************************************************
497 : |*
498 : |* XPolygon::Move()
499 : |*
500 : *************************************************************************/
501 :
502 0 : void XPolygon::Move( long nHorzMove, long nVertMove )
503 : {
504 0 : if ( !nHorzMove && !nVertMove )
505 0 : return;
506 :
507 0 : CheckReference();
508 :
509 : // Punkte verschieben
510 0 : sal_uInt16 nCount = pImpXPolygon->nPoints;
511 0 : for ( sal_uInt16 i = 0; i < nCount; i++ )
512 : {
513 0 : Point* pPt = &(pImpXPolygon->pPointAry[i]);
514 0 : pPt->X() += nHorzMove;
515 0 : pPt->Y() += nVertMove;
516 : }
517 : }
518 :
519 : /*************************************************************************
520 : |*
521 : |* XPolygon::GetBoundRect()
522 : |*
523 : *************************************************************************/
524 :
525 3 : Rectangle XPolygon::GetBoundRect() const
526 : {
527 3 : pImpXPolygon->CheckPointDelete();
528 3 : Rectangle aRetval;
529 :
530 3 : if(pImpXPolygon->nPoints)
531 : {
532 : // #i37709#
533 : // For historical reasons the control points are not part of the
534 : // BoundRect. This makes it necessary to subdivide the polygon to
535 : // get a relatively correct BoundRect. Numerically, this is not
536 : // correct and never was.
537 :
538 3 : const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
539 : aRetval = Rectangle(
540 : FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
541 3 : FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
542 : }
543 :
544 3 : return aRetval;
545 : }
546 :
547 : /*************************************************************************
548 : |*
549 : |* XPolygon::operator[]()
550 : |*
551 : *************************************************************************/
552 :
553 6 : const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
554 : {
555 : DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
556 :
557 6 : pImpXPolygon->CheckPointDelete();
558 6 : return pImpXPolygon->pPointAry[nPos];
559 : }
560 :
561 : /*************************************************************************
562 : |*
563 : |* XPolygon::operator[]()
564 : |*
565 : *************************************************************************/
566 :
567 730 : Point& XPolygon::operator[]( sal_uInt16 nPos )
568 : {
569 730 : pImpXPolygon->CheckPointDelete();
570 730 : CheckReference();
571 :
572 730 : if( nPos >= pImpXPolygon->nSize )
573 : {
574 : DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
575 0 : pImpXPolygon->Resize(nPos + 1, sal_False);
576 : }
577 730 : if( nPos >= pImpXPolygon->nPoints )
578 5 : pImpXPolygon->nPoints = nPos + 1;
579 :
580 730 : return pImpXPolygon->pPointAry[nPos];
581 : }
582 :
583 : /*************************************************************************
584 : |*
585 : |* XPolygon::operator=()
586 : |*
587 : |* Beschreibung Zuweisungsoperator
588 : |*
589 : *************************************************************************/
590 :
591 6 : XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
592 : {
593 6 : pImpXPolygon->CheckPointDelete();
594 :
595 6 : rXPoly.pImpXPolygon->nRefCount++;
596 :
597 6 : if( pImpXPolygon->nRefCount > 1 )
598 0 : pImpXPolygon->nRefCount--;
599 : else
600 6 : delete pImpXPolygon;
601 :
602 6 : pImpXPolygon = rXPoly.pImpXPolygon;
603 6 : return *this;
604 : }
605 :
606 : /*************************************************************************
607 : |*
608 : |* XPolygon::operator==()
609 : |*
610 : |* Beschreibung Gleichheitsoperator
611 : |*
612 : *************************************************************************/
613 :
614 0 : sal_Bool XPolygon::operator==( const XPolygon& rXPoly ) const
615 : {
616 0 : pImpXPolygon->CheckPointDelete();
617 0 : if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_True;
618 0 : return *rXPoly.pImpXPolygon == *pImpXPolygon;
619 : }
620 :
621 : /*************************************************************************
622 : |*
623 : |* XPolygon::operator!=()
624 : |*
625 : |* Beschreibung Ungleichheitsoperator
626 : |*
627 : *************************************************************************/
628 :
629 0 : sal_Bool XPolygon::operator!=( const XPolygon& rXPoly ) const
630 : {
631 0 : pImpXPolygon->CheckPointDelete();
632 0 : if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_False;
633 0 : return *rXPoly.pImpXPolygon != *pImpXPolygon;
634 : }
635 :
636 : /*************************************************************************
637 : |*
638 : |* XPolygon::GetFlags()
639 : |*
640 : |* Flags fuer den Punkt an der Position nPos zurueckgeben
641 : |*
642 : *************************************************************************/
643 :
644 0 : XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
645 : {
646 0 : pImpXPolygon->CheckPointDelete();
647 0 : return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
648 : }
649 :
650 : /*************************************************************************
651 : |*
652 : |* XPolygon::SetFlags()
653 : |*
654 : |* Flags fuer den Punkt an der Position nPos setzen
655 : |*
656 : *************************************************************************/
657 :
658 0 : void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
659 : {
660 0 : pImpXPolygon->CheckPointDelete();
661 0 : CheckReference();
662 0 : pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
663 0 : }
664 :
665 : /*************************************************************************
666 : |*
667 : |* XPolygon::IsControl()
668 : |*
669 : |* Kurzform zur Abfrage des CONTROL-Flags
670 : |*
671 : *************************************************************************/
672 :
673 0 : sal_Bool XPolygon::IsControl(sal_uInt16 nPos) const
674 : {
675 0 : return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
676 : }
677 :
678 : /*************************************************************************
679 : |*
680 : |* XPolygon::IsSmooth()
681 : |*
682 : |* Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
683 : |*
684 : *************************************************************************/
685 :
686 0 : sal_Bool XPolygon::IsSmooth(sal_uInt16 nPos) const
687 : {
688 0 : XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
689 0 : return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
690 : }
691 :
692 : /*************************************************************************
693 : |*
694 : |* XPolygon::CalcDistance()
695 : |*
696 : |* Abstand zwischen zwei Punkten berechnen
697 : |*
698 : *************************************************************************/
699 :
700 0 : double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
701 : {
702 0 : const Point& rP1 = pImpXPolygon->pPointAry[nP1];
703 0 : const Point& rP2 = pImpXPolygon->pPointAry[nP2];
704 0 : double fDx = rP2.X() - rP1.X();
705 0 : double fDy = rP2.Y() - rP1.Y();
706 0 : return sqrt(fDx * fDx + fDy * fDy);
707 : }
708 :
709 : /*************************************************************************
710 : |*
711 : |* XPolygon::SubdivideBezier()
712 : |*
713 : |* Bezierkurve unterteilen
714 : |*
715 : *************************************************************************/
716 :
717 0 : void XPolygon::SubdivideBezier(sal_uInt16 nPos, sal_Bool bCalcFirst, double fT)
718 : {
719 0 : Point* pPoints = pImpXPolygon->pPointAry;
720 0 : double fT2 = fT * fT;
721 0 : double fT3 = fT * fT2;
722 0 : double fU = 1.0 - fT;
723 0 : double fU2 = fU * fU;
724 0 : double fU3 = fU * fU2;
725 0 : sal_uInt16 nIdx = nPos;
726 : short nPosInc, nIdxInc;
727 :
728 0 : if ( bCalcFirst )
729 : {
730 0 : nPos += 3;
731 0 : nPosInc = -1;
732 0 : nIdxInc = 0;
733 : }
734 : else
735 : {
736 0 : nPosInc = 1;
737 0 : nIdxInc = 1;
738 : }
739 0 : pPoints[nPos].X() = (long) (fU3 * pPoints[nIdx ].X() +
740 0 : fT * fU2 * pPoints[nIdx+1].X() * 3 +
741 0 : fT2 * fU * pPoints[nIdx+2].X() * 3 +
742 0 : fT3 * pPoints[nIdx+3].X());
743 0 : pPoints[nPos].Y() = (long) (fU3 * pPoints[nIdx ].Y() +
744 0 : fT * fU2 * pPoints[nIdx+1].Y() * 3 +
745 0 : fT2 * fU * pPoints[nIdx+2].Y() * 3 +
746 0 : fT3 * pPoints[nIdx+3].Y());
747 0 : nPos = nPos + nPosInc;
748 0 : nIdx = nIdx + nIdxInc;
749 0 : pPoints[nPos].X() = (long) (fU2 * pPoints[nIdx ].X() +
750 0 : fT * fU * pPoints[nIdx+1].X() * 2 +
751 0 : fT2 * pPoints[nIdx+2].X());
752 0 : pPoints[nPos].Y() = (long) (fU2 * pPoints[nIdx ].Y() +
753 0 : fT * fU * pPoints[nIdx+1].Y() * 2 +
754 0 : fT2 * pPoints[nIdx+2].Y());
755 0 : nPos = nPos + nPosInc;
756 0 : nIdx = nIdx + nIdxInc;
757 0 : pPoints[nPos].X() = (long) (fU * pPoints[nIdx ].X() +
758 0 : fT * pPoints[nIdx+1].X());
759 0 : pPoints[nPos].Y() = (long) (fU * pPoints[nIdx ].Y() +
760 0 : fT * pPoints[nIdx+1].Y());
761 0 : }
762 :
763 : /************************************************************************/
764 :
765 0 : void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
766 : long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
767 : sal_uInt16 nQuad, sal_uInt16 nFirst)
768 : {
769 0 : Point* pPoints = pImpXPolygon->pPointAry;
770 0 : pPoints[nFirst ] = rCenter;
771 0 : pPoints[nFirst+3] = rCenter;
772 :
773 0 : if ( nQuad == 1 || nQuad == 2 )
774 : {
775 0 : nRx = -nRx; nXHdl = -nXHdl;
776 : }
777 0 : if ( nQuad == 0 || nQuad == 1 )
778 : {
779 0 : nRy = -nRy; nYHdl = -nYHdl;
780 : }
781 :
782 0 : if ( nQuad == 0 || nQuad == 2 )
783 : {
784 0 : pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
785 : }
786 : else
787 : {
788 0 : pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
789 : }
790 0 : pPoints[nFirst+1] = pPoints[nFirst];
791 0 : pPoints[nFirst+2] = pPoints[nFirst+3];
792 :
793 0 : if ( nQuad == 0 || nQuad == 2 )
794 : {
795 0 : pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
796 : }
797 : else
798 : {
799 0 : pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
800 : }
801 0 : if ( nStart > 0 )
802 0 : SubdivideBezier(nFirst, sal_False, (double)nStart / 900);
803 0 : if ( nEnd < 900 )
804 0 : SubdivideBezier(nFirst, sal_True, (double)(nEnd-nStart) / (900-nStart));
805 0 : SetFlags(nFirst+1, XPOLY_CONTROL);
806 0 : SetFlags(nFirst+2, XPOLY_CONTROL);
807 0 : }
808 :
809 : /************************************************************************/
810 :
811 0 : sal_Bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
812 : {
813 0 : if ( nStart == 3600 ) nStart = 0;
814 0 : if ( nEnd == 0 ) nEnd = 3600;
815 0 : sal_uInt16 nStPrev = nStart;
816 0 : sal_uInt16 nMax = (nStart / 900 + 1) * 900;
817 0 : sal_uInt16 nMin = nMax - 900;
818 :
819 0 : if ( nEnd >= nMax || nEnd <= nStart ) nA2 = 900;
820 0 : else nA2 = nEnd - nMin;
821 0 : nA1 = nStart - nMin;
822 0 : nStart = nMax;
823 :
824 : // sal_True zurueck, falls letztes Segment berechnet wurde
825 0 : return (nStPrev < nEnd && nStart >= nEnd);
826 : }
827 :
828 : /*************************************************************************
829 : |*
830 : |* XPolygon::CalcSmoothJoin()
831 : |*
832 : |* glatten Uebergang zu einer Bezierkurve berechnen, indem der
833 : |* entsprechende Punkt auf die Verbindungslinie von zwei anderen
834 : |* Punkten projiziert wird
835 : |* Center = End- bzw. Anfangspunkt der Bezierkurve
836 : |* Drag = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
837 : |* Pnt = der zu modifizierende Punkt
838 : |* Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
839 : |* auf die entgegengesetzte Seite verlegt
840 : |*
841 : \************************************************************************/
842 :
843 0 : void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
844 : {
845 0 : CheckReference();
846 :
847 : // sal_uInt16 nMaxPnt = pImpXPolygon->nPoints - 1;
848 :
849 : // if ( nCenter == nMaxPnt ) nPnt = 1;
850 : // else if ( nCenter == 0 ) nPnt = nMaxPnt - 1;
851 :
852 : // Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
853 : // statt dessen nDrag auf der Achse nCenter-nPnt verschieben
854 0 : if ( !IsControl(nPnt) )
855 : {
856 0 : sal_uInt16 nTmp = nDrag;
857 0 : nDrag = nPnt;
858 0 : nPnt = nTmp;
859 : }
860 0 : Point* pPoints = pImpXPolygon->pPointAry;
861 0 : Point aDiff = pPoints[nDrag] - pPoints[nCenter];
862 0 : double fDiv = CalcDistance(nCenter, nDrag);
863 :
864 0 : if ( fDiv )
865 : {
866 0 : double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
867 : // bei SMOOTH bisherige Laenge beibehalten
868 0 : if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
869 : {
870 0 : aDiff.X() = (long) (fRatio * aDiff.X());
871 0 : aDiff.Y() = (long) (fRatio * aDiff.Y());
872 : }
873 0 : pPoints[nPnt] = pPoints[nCenter] - aDiff;
874 : }
875 0 : }
876 :
877 : /*************************************************************************
878 : |*
879 : |* XPolygon::CalcTangent()
880 : |*
881 : |* Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
882 : |* Center = End- bzw. Anfangspunkt der Bezierkurven
883 : |* Prev = vorheriger Zugpunkt
884 : |* Next = naechster Zugpunkt
885 : |*
886 : \************************************************************************/
887 :
888 0 : void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
889 : {
890 0 : CheckReference();
891 :
892 0 : double fAbsLen = CalcDistance(nNext, nPrev);
893 :
894 0 : if ( fAbsLen )
895 : {
896 0 : const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
897 0 : Point& rNext = pImpXPolygon->pPointAry[nNext];
898 0 : Point& rPrev = pImpXPolygon->pPointAry[nPrev];
899 0 : Point aDiff = rNext - rPrev;
900 0 : double fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
901 0 : double fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
902 :
903 : // bei SYMMTR gleiche Laenge fuer beide Seiten
904 0 : if ( GetFlags(nCenter) == XPOLY_SYMMTR )
905 : {
906 0 : fPrevLen = (fNextLen + fPrevLen) / 2;
907 0 : fNextLen = fPrevLen;
908 : }
909 0 : rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
910 0 : rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
911 0 : rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
912 0 : rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
913 : }
914 0 : }
915 :
916 : /*************************************************************************
917 : |*
918 : |* XPolygon::PointsToBezier()
919 : |*
920 : |* wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
921 : |*
922 : \************************************************************************/
923 :
924 0 : void XPolygon::PointsToBezier(sal_uInt16 nFirst)
925 : {
926 : double nFullLength, nPart1Length, nPart2Length;
927 : double fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
928 : double fTx1, fTx2, fTy1, fTy2;
929 : double fT1, fU1, fT2, fU2, fV;
930 0 : Point* pPoints = pImpXPolygon->pPointAry;
931 :
932 0 : if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
933 0 : IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
934 0 : return;
935 :
936 0 : CheckReference();
937 :
938 0 : fTx1 = pPoints[nFirst+1].X();
939 0 : fTy1 = pPoints[nFirst+1].Y();
940 0 : fTx2 = pPoints[nFirst+2].X();
941 0 : fTy2 = pPoints[nFirst+2].Y();
942 0 : fX0 = pPoints[nFirst ].X();
943 0 : fY0 = pPoints[nFirst ].Y();
944 0 : fX3 = pPoints[nFirst+3].X();
945 0 : fY3 = pPoints[nFirst+3].Y();
946 :
947 0 : nPart1Length = CalcDistance(nFirst, nFirst+1);
948 0 : nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
949 0 : nFullLength = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
950 0 : if ( nFullLength < 20 )
951 0 : return;
952 :
953 0 : if ( nPart2Length == nFullLength )
954 0 : nPart2Length -= 1;
955 0 : if ( nPart1Length == nFullLength )
956 0 : nPart1Length = nPart2Length - 1;
957 0 : if ( nPart1Length <= 0 )
958 0 : nPart1Length = 1;
959 0 : if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
960 0 : nPart2Length = nPart1Length + 1;
961 :
962 0 : fT1 = nPart1Length / nFullLength;
963 0 : fU1 = 1.0 - fT1;
964 0 : fT2 = nPart2Length / nFullLength;
965 0 : fU2 = 1.0 - fT2;
966 0 : fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
967 :
968 0 : fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
969 0 : fX1 /= fV;
970 0 : fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
971 0 : fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
972 :
973 0 : fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
974 0 : fY1 /= fV;
975 0 : fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
976 0 : fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
977 :
978 0 : fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
979 0 : fX2 -= fX1 * fU2 / fT2;
980 0 : fX2 -= fX3 * fT2 / (fU2 * 3);
981 :
982 0 : fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
983 0 : fY2 -= fY1 * fU2 / fT2;
984 0 : fY2 -= fY3 * fT2 / (fU2 * 3);
985 :
986 0 : pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
987 0 : pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
988 0 : SetFlags(nFirst+1, XPOLY_CONTROL);
989 0 : SetFlags(nFirst+2, XPOLY_CONTROL);
990 : }
991 :
992 : /*************************************************************************
993 : |*
994 : |* XPolygon::Scale()
995 : |*
996 : |* XPolygon in X- und/oder Y-Richtung skalieren
997 : |*
998 : *************************************************************************/
999 :
1000 0 : void XPolygon::Scale(double fSx, double fSy)
1001 : {
1002 0 : pImpXPolygon->CheckPointDelete();
1003 0 : CheckReference();
1004 :
1005 0 : sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1006 :
1007 0 : for (sal_uInt16 i = 0; i < nPntCnt; i++)
1008 : {
1009 0 : Point& rPnt = pImpXPolygon->pPointAry[i];
1010 0 : rPnt.X() = (long)(fSx * rPnt.X());
1011 0 : rPnt.Y() = (long)(fSy * rPnt.Y());
1012 : }
1013 0 : }
1014 :
1015 : /*************************************************************************
1016 : |*
1017 : |* XPolygon::Distort()
1018 : |*
1019 : |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1020 : |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1021 : |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1022 : |* 0: links oben 0----1
1023 : |* 1: rechts oben | |
1024 : |* 2: rechts unten 3----2
1025 : |* 3: links unten
1026 : |*
1027 : *************************************************************************/
1028 :
1029 0 : void XPolygon::Distort(const Rectangle& rRefRect,
1030 : const XPolygon& rDistortedRect)
1031 : {
1032 0 : pImpXPolygon->CheckPointDelete();
1033 0 : CheckReference();
1034 :
1035 : long Xr, Wr;
1036 : long Yr, Hr;
1037 :
1038 0 : Xr = rRefRect.Left();
1039 0 : Yr = rRefRect.Top();
1040 0 : Wr = rRefRect.GetWidth();
1041 0 : Hr = rRefRect.GetHeight();
1042 :
1043 0 : if ( Wr && Hr )
1044 : {
1045 : long X1, X2, X3, X4;
1046 : long Y1, Y2, Y3, Y4;
1047 : DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
1048 : "Distort-Rechteck zu klein");
1049 :
1050 0 : X1 = rDistortedRect[0].X();
1051 0 : Y1 = rDistortedRect[0].Y();
1052 0 : X2 = rDistortedRect[1].X();
1053 0 : Y2 = rDistortedRect[1].Y();
1054 0 : X3 = rDistortedRect[3].X();
1055 0 : Y3 = rDistortedRect[3].Y();
1056 0 : X4 = rDistortedRect[2].X();
1057 0 : Y4 = rDistortedRect[2].Y();
1058 :
1059 0 : sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1060 :
1061 0 : for (sal_uInt16 i = 0; i < nPntCnt; i++)
1062 : {
1063 : double fTx, fTy, fUx, fUy;
1064 0 : Point& rPnt = pImpXPolygon->pPointAry[i];
1065 :
1066 0 : fTx = (double)(rPnt.X() - Xr) / Wr;
1067 0 : fTy = (double)(rPnt.Y() - Yr) / Hr;
1068 0 : fUx = 1.0 - fTx;
1069 0 : fUy = 1.0 - fTy;
1070 :
1071 0 : rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
1072 0 : fTy * (fUx * X3 + fTx * X4) );
1073 0 : rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
1074 0 : fTx * (fUy * Y2 + fTy * Y4) );
1075 : }
1076 : }
1077 0 : }
1078 :
1079 6 : basegfx::B2DPolygon XPolygon::getB2DPolygon() const
1080 : {
1081 : // #i74631# use tools Polygon class for conversion to not have the code doubled
1082 : // here. This needs one more conversion but avoids different convertors in
1083 : // the long run
1084 : DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1085 6 : const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
1086 :
1087 6 : return aSource.getB2DPolygon();
1088 : }
1089 :
1090 0 : XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
1091 : {
1092 : // #i74631# use tools Polygon class for conversion to not have the code doubled
1093 : // here. This needs one more conversion but avoids different convertors in
1094 : // the long run
1095 : DBG_CTOR(XPolygon,NULL);
1096 :
1097 0 : const Polygon aSource(rPolygon);
1098 0 : sal_uInt16 nSize = aSource.GetSize();
1099 0 : pImpXPolygon = new ImpXPolygon( nSize );
1100 0 : pImpXPolygon->nPoints = nSize;
1101 :
1102 0 : for( sal_uInt16 i = 0; i < nSize; i++ )
1103 : {
1104 0 : pImpXPolygon->pPointAry[i] = aSource[i];
1105 0 : pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
1106 0 : }
1107 0 : }
1108 :
1109 : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1110 : //+--------------- XPolyPolygon -----------------------------------------+
1111 : //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1112 :
1113 : /*************************************************************************
1114 : |*
1115 : |* ImpXPolyPolygon::ImpXPolyPolygon()
1116 : |*
1117 : |* Beschreibung Erzeugt das XPolygon-Array
1118 : |*
1119 : *************************************************************************/
1120 :
1121 0 : ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
1122 0 : aXPolyList( rImpXPolyPoly.aXPolyList )
1123 : {
1124 0 : nRefCount = 1;
1125 :
1126 : // Einzelne Elemente duplizieren
1127 0 : for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
1128 0 : aXPolyList[ i ] = new XPolygon( *aXPolyList[ i ] );
1129 0 : }
1130 :
1131 :
1132 : /*************************************************************************
1133 : |*
1134 : |* ImpXPolyPolygon::~ImpXPolyPolygon()
1135 : |*
1136 : |* Beschreibung Loescht das Polygon-Array
1137 : |*
1138 : *************************************************************************/
1139 :
1140 0 : ImpXPolyPolygon::~ImpXPolyPolygon()
1141 : {
1142 0 : for ( size_t i = 0, n = aXPolyList.size(); i < n; ++i )
1143 0 : delete aXPolyList[ i ];
1144 0 : aXPolyList.clear();
1145 0 : }
1146 :
1147 : /*************************************************************************
1148 : |*
1149 : |* ImpXPolyPolygon::operator==()
1150 : |*
1151 : *************************************************************************/
1152 :
1153 0 : bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
1154 : {
1155 0 : size_t nAnz = aXPolyList.size();
1156 0 : const XPolygonList& rCmpList = rImpXPolyPoly.aXPolyList;
1157 0 : if ( nAnz != rCmpList.size() ) return false;
1158 0 : bool bEq=true;
1159 0 : for ( size_t i = nAnz; i > 0 && bEq; )
1160 : {
1161 0 : i--;
1162 0 : bEq = ( *aXPolyList[ i ] == *rCmpList[ i ] );
1163 : }
1164 0 : return bEq;
1165 : }
1166 :
1167 : /*************************************************************************
1168 : |*
1169 : |* XPolyPolygon::XPolyPolygon()
1170 : |*
1171 : *************************************************************************/
1172 :
1173 0 : XPolyPolygon::XPolyPolygon( sal_uInt16 /*nInitSize*/, sal_uInt16 /*nResize*/ )
1174 : {
1175 : DBG_CTOR(XPolyPolygon,NULL);
1176 0 : pImpXPolyPolygon = new ImpXPolyPolygon();
1177 0 : }
1178 :
1179 : /*************************************************************************
1180 : |*
1181 : |* XPolyPolygon::XPolyPolygon()
1182 : |*
1183 : *************************************************************************/
1184 :
1185 0 : XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
1186 : {
1187 : DBG_CTOR(XPolyPolygon,NULL);
1188 0 : pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1189 0 : pImpXPolyPolygon->nRefCount++;
1190 0 : }
1191 :
1192 : /*************************************************************************
1193 : |*
1194 : |* XPolyPolygon::~XPolyPolygon()
1195 : |*
1196 : *************************************************************************/
1197 :
1198 0 : XPolyPolygon::~XPolyPolygon()
1199 : {
1200 : DBG_DTOR(XPolyPolygon,NULL);
1201 0 : if( pImpXPolyPolygon->nRefCount > 1 )
1202 0 : pImpXPolyPolygon->nRefCount--;
1203 : else
1204 0 : delete pImpXPolyPolygon;
1205 0 : }
1206 :
1207 : /*************************************************************************
1208 : |*
1209 : |* XPolygon::CheckReference()
1210 : |*
1211 : |* Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1212 : |*
1213 : *************************************************************************/
1214 :
1215 0 : void XPolyPolygon::CheckReference()
1216 : {
1217 0 : if( pImpXPolyPolygon->nRefCount > 1 )
1218 : {
1219 0 : pImpXPolyPolygon->nRefCount--;
1220 0 : pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
1221 : }
1222 0 : }
1223 :
1224 : /*************************************************************************
1225 : |*
1226 : |* XPolyPolygon::Insert()
1227 : |*
1228 : *************************************************************************/
1229 :
1230 0 : void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
1231 : {
1232 0 : CheckReference();
1233 0 : XPolygon* pXPoly = new XPolygon( rXPoly );
1234 0 : if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
1235 : {
1236 0 : XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
1237 0 : ::std::advance( it, nPos );
1238 0 : pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
1239 : }
1240 : else
1241 0 : pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
1242 0 : }
1243 :
1244 : /*************************************************************************
1245 : |*
1246 : |* XPolyPolygon::Insert()
1247 : |*
1248 : |* saemtliche XPolygone aus einem XPolyPolygon einfuegen
1249 : |*
1250 : *************************************************************************/
1251 :
1252 0 : void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
1253 : {
1254 0 : CheckReference();
1255 :
1256 0 : for ( size_t i = 0; i < rXPolyPoly.Count(); i++)
1257 : {
1258 0 : XPolygon* pXPoly = new XPolygon( rXPolyPoly[i] );
1259 :
1260 0 : if ( nPos < pImpXPolyPolygon->aXPolyList.size() )
1261 : {
1262 0 : XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
1263 0 : ::std::advance( it, nPos );
1264 0 : pImpXPolyPolygon->aXPolyList.insert( it, pXPoly );
1265 0 : nPos++;
1266 : }
1267 : else
1268 0 : pImpXPolyPolygon->aXPolyList.push_back( pXPoly );
1269 : }
1270 0 : }
1271 :
1272 : /*************************************************************************
1273 : |*
1274 : |* XPolyPolygon::Remove()
1275 : |*
1276 : *************************************************************************/
1277 :
1278 0 : XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
1279 : {
1280 0 : CheckReference();
1281 0 : XPolygonList::iterator it = pImpXPolyPolygon->aXPolyList.begin();
1282 0 : ::std::advance( it, nPos );
1283 0 : XPolygon* pTmpXPoly = *it;
1284 0 : pImpXPolyPolygon->aXPolyList.erase( it );
1285 0 : XPolygon aXPoly( *pTmpXPoly );
1286 0 : delete pTmpXPoly;
1287 0 : return aXPoly;
1288 : }
1289 :
1290 :
1291 : /*************************************************************************
1292 : |*
1293 : |* XPolyPolygon::GetObject()
1294 : |*
1295 : *************************************************************************/
1296 :
1297 0 : const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
1298 : {
1299 0 : return *(pImpXPolyPolygon->aXPolyList[ nPos ]);
1300 : }
1301 :
1302 :
1303 : /*************************************************************************
1304 : |*
1305 : |* XPolyPolygon::Clear()
1306 : |*
1307 : *************************************************************************/
1308 :
1309 0 : void XPolyPolygon::Clear()
1310 : {
1311 0 : if ( pImpXPolyPolygon->nRefCount > 1 )
1312 : {
1313 0 : pImpXPolyPolygon->nRefCount--;
1314 0 : pImpXPolyPolygon = new ImpXPolyPolygon();
1315 : }
1316 : else
1317 : {
1318 0 : for( size_t i = 0, n = pImpXPolyPolygon->aXPolyList.size(); i < n; ++i )
1319 0 : delete pImpXPolyPolygon->aXPolyList[ i ];
1320 0 : pImpXPolyPolygon->aXPolyList.clear();
1321 : }
1322 0 : }
1323 :
1324 :
1325 : /*************************************************************************
1326 : |*
1327 : |* XPolyPolygon::Count()
1328 : |*
1329 : *************************************************************************/
1330 :
1331 0 : sal_uInt16 XPolyPolygon::Count() const
1332 : {
1333 0 : return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.size());
1334 : }
1335 :
1336 : /*************************************************************************
1337 : |*
1338 : |* XPolyPolygon::GetBoundRect()
1339 : |*
1340 : *************************************************************************/
1341 :
1342 0 : Rectangle XPolyPolygon::GetBoundRect() const
1343 : {
1344 0 : size_t nXPoly = pImpXPolyPolygon->aXPolyList.size();
1345 0 : Rectangle aRect;
1346 :
1347 0 : for ( size_t n = 0; n < nXPoly; n++ )
1348 : {
1349 0 : const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList[ n ];
1350 0 : aRect.Union( pXPoly->GetBoundRect() );
1351 : }
1352 :
1353 0 : return aRect;
1354 : }
1355 :
1356 :
1357 : /*************************************************************************
1358 : |*
1359 : |* XPolyPolygon::operator[]()
1360 : |*
1361 : *************************************************************************/
1362 :
1363 0 : XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
1364 : {
1365 0 : CheckReference();
1366 0 : return *( pImpXPolyPolygon->aXPolyList[ nPos ] );
1367 : }
1368 :
1369 : /*************************************************************************
1370 : |*
1371 : |* XPolyPolygon::operator=()
1372 : |*
1373 : *************************************************************************/
1374 :
1375 0 : XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
1376 : {
1377 0 : rXPolyPoly.pImpXPolyPolygon->nRefCount++;
1378 :
1379 0 : if( pImpXPolyPolygon->nRefCount > 1 )
1380 0 : pImpXPolyPolygon->nRefCount--;
1381 : else
1382 0 : delete pImpXPolyPolygon;
1383 :
1384 0 : pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1385 0 : return *this;
1386 : }
1387 :
1388 :
1389 : /*************************************************************************
1390 : |*
1391 : |* XPolyPolygon::operator==()
1392 : |*
1393 : *************************************************************************/
1394 :
1395 0 : sal_Bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
1396 : {
1397 0 : if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_True;
1398 0 : return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
1399 : }
1400 :
1401 :
1402 : /*************************************************************************
1403 : |*
1404 : |* XPolyPolygon::operator!=()
1405 : |*
1406 : *************************************************************************/
1407 :
1408 0 : sal_Bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
1409 : {
1410 0 : if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_False;
1411 0 : return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
1412 : }
1413 :
1414 : /*************************************************************************
1415 : |*
1416 : |* XPolygon::Distort()
1417 : |*
1418 : |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1419 : |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1420 : |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1421 : |* 0: links oben 0----1
1422 : |* 1: rechts oben | |
1423 : |* 2: rechts unten 3----2
1424 : |* 3: links unten
1425 : |*
1426 : *************************************************************************/
1427 :
1428 0 : void XPolyPolygon::Distort(const Rectangle& rRefRect,
1429 : const XPolygon& rDistortedRect)
1430 : {
1431 0 : CheckReference();
1432 :
1433 0 : for (size_t i = 0; i < Count(); i++)
1434 0 : pImpXPolyPolygon->aXPolyList[ i ]->Distort(rRefRect, rDistortedRect);
1435 0 : }
1436 :
1437 0 : basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
1438 : {
1439 0 : basegfx::B2DPolyPolygon aRetval;
1440 :
1441 0 : for(sal_uInt16 a(0L); a < Count(); a++)
1442 : {
1443 0 : const XPolygon& rPoly = (*this)[a];
1444 0 : aRetval.append(rPoly.getB2DPolygon());
1445 : }
1446 :
1447 0 : return aRetval;
1448 : }
1449 :
1450 0 : XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
1451 : {
1452 : DBG_CTOR(XPolyPolygon,NULL);
1453 0 : pImpXPolyPolygon = new ImpXPolyPolygon();
1454 :
1455 0 : for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
1456 : {
1457 0 : basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
1458 0 : XPolygon aNewPoly(aCandidate);
1459 0 : Insert(aNewPoly);
1460 0 : }
1461 0 : }
1462 :
1463 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|