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