xref: /aoo41x/main/svx/source/xoutdev/_xpoly.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <osl/endian.h>
27 #include <tools/stream.hxx>
28 #include <tools/debug.hxx>
29 #include <tools/poly.hxx>
30 
31 #include <svx/xpoly.hxx>
32 #include "xpolyimp.hxx"
33 #include <basegfx/polygon/b2dpolygon.hxx>
34 #include <basegfx/point/b2dpoint.hxx>
35 #include <basegfx/vector/b2dvector.hxx>
36 #include <basegfx/polygon/b2dpolygontools.hxx>
37 #include <vcl/salbtype.hxx>		// FRound
38 #include <basegfx/range/b2drange.hxx>
39 #include <basegfx/numeric/ftools.hxx>
40 
41 #define GLOBALOVERFLOW
42 
43 DBG_NAME(XPolygon);
44 DBG_NAME(XPolyPolygon);
45 
46 /*************************************************************************
47 |*
48 |*    ImpXPolygon::ImpXPolygon()
49 |*
50 |*    Beschreibung
51 |*    Ersterstellung    08.11.94
52 |*    Letzte Aenderung  12.01.95 ESO
53 |*
54 *************************************************************************/
55 
ImpXPolygon(sal_uInt16 nInitSize,sal_uInt16 _nResize)56 ImpXPolygon::ImpXPolygon( sal_uInt16 nInitSize, sal_uInt16 _nResize )
57 {
58 	pPointAry               = NULL;
59 	pFlagAry                = NULL;
60 	bDeleteOldPoints        = sal_False;
61 	nSize                   = 0;
62 	nResize					= _nResize;
63 	nPoints                 = 0;
64 	nRefCount               = 1;
65 
66 	Resize( nInitSize );
67 }
68 
69 /*************************************************************************
70 |*
71 |*    ImpXPolygon::ImpXPolygon()
72 |*
73 |*    Beschreibung
74 |*    Ersterstellung    08.11.94
75 |*    Letzte Aenderung  12.01.95 ESO
76 |*
77 *************************************************************************/
78 
ImpXPolygon(const ImpXPolygon & rImpXPoly)79 ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
80 {
81 	( (ImpXPolygon&) rImpXPoly ).CheckPointDelete();
82 
83 	pPointAry               = NULL;
84 	pFlagAry                = NULL;
85 	bDeleteOldPoints        = sal_False;
86 	nSize                   = 0;
87 	ImpXPolygon::nResize    = rImpXPoly.nResize;
88 	nPoints                 = 0;
89 	nRefCount               = 1;
90 
91 	Resize( rImpXPoly.nSize );
92 
93 	// Kopieren
94 	nPoints = rImpXPoly.nPoints;
95 	memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
96 	memcpy( pFlagAry, rImpXPoly.pFlagAry, nSize );
97 }
98 
99 /*************************************************************************
100 |*
101 |*    ImpXPolygon::~ImpXPolygon()
102 |*
103 |*    Beschreibung
104 |*    Ersterstellung    08.11.94
105 |*    Letzte Aenderung  12.01.95 ESO
106 |*
107 *************************************************************************/
108 
~ImpXPolygon()109 ImpXPolygon::~ImpXPolygon()
110 {
111 	delete[] (char*) pPointAry;
112 	delete[] pFlagAry;
113 	if ( bDeleteOldPoints )
114 		delete[] (char*) pOldPointAry;
115 }
116 
117 /*************************************************************************
118 |*
119 |*    ImpXPolygon::operator==()
120 |*
121 |*    Ersterstellung    Joe 26-09-95
122 |*    Letzte Aenderung
123 |*
124 *************************************************************************/
125 
126 
operator ==(const ImpXPolygon & rImpXPoly) const127 bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
128 {
129 	return nPoints==rImpXPoly.nPoints &&
130 		   (nPoints==0 ||
131 			(memcmp(pPointAry,rImpXPoly.pPointAry,nPoints*sizeof(Point))==0 &&
132 			 memcmp(pFlagAry,rImpXPoly.pFlagAry,nPoints)==0));
133 }
134 
135 /*************************************************************************
136 |*
137 |*    ImpXPolygon::Resize()
138 |*
139 |*    !!! Polygongroesse aendern - wenn bDeletePoints sal_False, dann den
140 |*    Point-Array nicht loeschen, sondern in pOldPointAry sichern und
141 |*    das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
142 |*    das Array dann geloescht.
143 |*    Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
144 |*    Resize der fuer den rechten Ausdruck verwendete Point-Array
145 |*    vorzeitig geloescht wird.
146 |*    Ersterstellung    08.11.94
147 |*    Letzte Aenderung  12.01.95 ESO
148 |*
149 *************************************************************************/
150 
Resize(sal_uInt16 nNewSize,sal_Bool bDeletePoints)151 void ImpXPolygon::Resize( sal_uInt16 nNewSize, sal_Bool bDeletePoints )
152 {
153 	if( nNewSize == nSize )
154 		return;
155 
156 	sal_uInt8*   pOldFlagAry  = pFlagAry;
157 	sal_uInt16  nOldSize     = nSize;
158 
159 	CheckPointDelete();
160 	pOldPointAry = pPointAry;
161 
162 	// Neue Groesse auf vielfaches von nResize runden, sofern Objekt
163 	// nicht neu angelegt wurde (nSize != 0)
164 	if ( nSize != 0 && nNewSize > nSize )
165 	{
166 		DBG_ASSERT(nResize, "Resize-Versuch trotz nResize = 0 !");
167 		nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
168 	}
169 	// Punkt Array erzeugen
170 	nSize     = nNewSize;
171 	pPointAry = (Point*)new char[ nSize*sizeof( Point ) ];
172 	memset( pPointAry, 0, nSize*sizeof( Point ) );
173 
174 	// Flag Array erzeugen
175 	pFlagAry = new sal_uInt8[ nSize ];
176 	memset( pFlagAry, 0, nSize );
177 
178 	// Eventuell umkopieren
179 	if( nOldSize )
180 	{
181 		if( nOldSize < nSize )
182 		{
183 			memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
184 			memcpy( pFlagAry,  pOldFlagAry, nOldSize );
185 		}
186 		else
187 		{
188 			memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
189 			memcpy( pFlagAry, pOldFlagAry, nSize );
190 
191 			// Anzahl der gueltigen Punkte anpassen
192 			if( nPoints > nSize )
193 				nPoints = nSize;
194 		}
195 		if ( bDeletePoints )    delete[] (char*) pOldPointAry;
196 		else                    bDeleteOldPoints = sal_True;
197 		delete[] pOldFlagAry;
198 	}
199 }
200 
201 
202 /*************************************************************************
203 |*
204 |*    ImpXPolygon::InsertSpace()
205 |*
206 |*    Beschreibung
207 |*    Ersterstellung    08.11.94
208 |*    Letzte Aenderung  29.03.95 ESO
209 |*
210 *************************************************************************/
211 
InsertSpace(sal_uInt16 nPos,sal_uInt16 nCount)212 void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
213 {
214 	CheckPointDelete();
215 
216 	if ( nPos > nPoints )
217 		nPos = nPoints;
218 
219 	// Wenn Polygon zu klein dann groesser machen
220 	if( (nPoints + nCount) > nSize )
221 		Resize( nPoints + nCount );
222 
223 	// Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
224 	// den Rest nach hinten schieben
225 	if( nPos < nPoints )
226 	{
227 		sal_uInt16 nMove = nPoints - nPos;
228 		memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
229 				 nMove * sizeof(Point) );
230 		memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
231 	}
232 	memset( &pPointAry[nPos], 0, nCount * sizeof( Point ) );
233 	memset( &pFlagAry [nPos], 0, nCount );
234 
235 	nPoints = nPoints + nCount;
236 }
237 
238 
239 /*************************************************************************
240 |*
241 |*    ImpXPolygon::Remove()
242 |*
243 |*    Beschreibung
244 |*    Ersterstellung    08.11.94
245 |*    Letzte Aenderung  12.01.94 ESO
246 |*
247 *************************************************************************/
248 
Remove(sal_uInt16 nPos,sal_uInt16 nCount)249 void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
250 {
251 	CheckPointDelete();
252 
253 	if( (nPos + nCount) <= nPoints )
254 	{
255 		sal_uInt16 nMove = nPoints - nPos - nCount;
256 
257 		if( nMove )
258 		{
259 			memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
260 					 nMove * sizeof(Point) );
261 			memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
262 		}
263 		memset( &pPointAry[nPoints - nCount], 0, nCount * sizeof( Point ) );
264 		memset( &pFlagAry [nPoints - nCount], 0, nCount );
265 		nPoints = nPoints - nCount;
266 	}
267 }
268 
269 
270 /*************************************************************************
271 |*
272 |*    XPolygon::XPolygon()
273 |*
274 |*    Beschreibung
275 |*    Ersterstellung    08.11.94
276 |*    Letzte Aenderung  08.11.94
277 |*
278 *************************************************************************/
279 
XPolygon(sal_uInt16 nSize,sal_uInt16 nResize)280 XPolygon::XPolygon( sal_uInt16 nSize, sal_uInt16 nResize )
281 {
282 	DBG_CTOR(XPolygon,NULL);
283 	pImpXPolygon = new ImpXPolygon( nSize, nResize );
284 }
285 
286 /*************************************************************************
287 |*
288 |*    XPolygon::XPolygon()
289 |*
290 |*    Beschreibung
291 |*    Ersterstellung    08.11.94
292 |*    Letzte Aenderung  08.11.94
293 |*
294 *************************************************************************/
295 
XPolygon(const XPolygon & rXPoly)296 XPolygon::XPolygon( const XPolygon& rXPoly )
297 {
298 	DBG_CTOR(XPolygon,NULL);
299 	pImpXPolygon = rXPoly.pImpXPolygon;
300 	pImpXPolygon->nRefCount++;
301 }
302 
303 /*************************************************************************
304 |*
305 |*    XPolygon::XPolygon()
306 |*
307 |*    XPolygon aus einem Standardpolygon erstellen
308 |*    Ersterstellung    18.01.95 ESO
309 |*    Letzte Aenderung  18.01.95 ESO
310 |*
311 *************************************************************************/
312 
XPolygon(const Polygon & rPoly)313 XPolygon::XPolygon( const Polygon& rPoly )
314 {
315 	DBG_CTOR(XPolygon,NULL);
316 
317 	sal_uInt16 nSize = rPoly.GetSize();
318 	pImpXPolygon = new ImpXPolygon( nSize );
319 	pImpXPolygon->nPoints = nSize;
320 
321 	for( sal_uInt16 i = 0; i < nSize;  i++ )
322 	{
323 		pImpXPolygon->pPointAry[i] = rPoly[i];
324 		pImpXPolygon->pFlagAry[i] = (sal_uInt8) rPoly.GetFlags( i );
325 	}
326 }
327 
328 /*************************************************************************
329 |*
330 |*    XPolygon::XPolygon()
331 |*
332 |*    Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
333 |*    Ersterstellung    09.01.95 ESO
334 |*    Letzte Aenderung  09.01.95 ESO
335 |*
336 *************************************************************************/
337 
XPolygon(const Rectangle & rRect,long nRx,long nRy)338 XPolygon::XPolygon(const Rectangle& rRect, long nRx, long nRy)
339 {
340 	DBG_CTOR(XPolygon,NULL);
341 	pImpXPolygon = new ImpXPolygon(17);
342 	long nWh = (rRect.GetWidth()  - 1) / 2;
343 	long nHh = (rRect.GetHeight() - 1) / 2;
344 
345 	if ( nRx > nWh )    nRx = nWh;
346 	if ( nRy > nHh )    nRy = nHh;
347 
348 	// Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
349 	nRx = -nRx;
350 
351 	// Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
352 	long    nXHdl = (long)(0.552284749 * nRx);
353 	long    nYHdl = (long)(0.552284749 * nRy);
354 	sal_uInt16  nPos = 0;
355 
356 	if ( nRx && nRy )
357 	{
358 		Point aCenter;
359 
360 		for (sal_uInt16 nQuad = 0; nQuad < 4; nQuad++)
361 		{
362 			switch ( nQuad )
363 			{
364 				case 0:	aCenter = rRect.TopLeft();
365 						aCenter.X() -= nRx;
366 						aCenter.Y() += nRy;
367 						break;
368 				case 1:	aCenter = rRect.TopRight();
369 						aCenter.X() += nRx;
370 						aCenter.Y() += nRy;
371 						break;
372 				case 2:	aCenter = rRect.BottomRight();
373 						aCenter.X() += nRx;
374 						aCenter.Y() -= nRy;
375 						break;
376 				case 3:	aCenter = rRect.BottomLeft();
377 						aCenter.X() -= nRx;
378 						aCenter.Y() -= nRy;
379 						break;
380 			}
381 			GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
382 			pImpXPolygon->pFlagAry[nPos  ] = (sal_uInt8) XPOLY_SMOOTH;
383 			pImpXPolygon->pFlagAry[nPos+3] = (sal_uInt8) XPOLY_SMOOTH;
384 			nPos += 4;
385 		}
386 	}
387 	else
388 	{
389 		pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
390 		pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
391 		pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
392 		pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
393 	}
394 	pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
395 	pImpXPolygon->nPoints = nPos + 1;
396 }
397 
398 /*************************************************************************
399 |*
400 |*    XPolygon::XPolygon()
401 |*
402 |*    Ellipsen(bogen) als Bezierpolygon erzeugen
403 |*    Ersterstellung    09.01.95
404 |*    Letzte Aenderung  09.01.95
405 |*
406 *************************************************************************/
407 
XPolygon(const Point & rCenter,long nRx,long nRy,sal_uInt16 nStartAngle,sal_uInt16 nEndAngle,sal_Bool bClose)408 XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
409 				   sal_uInt16 nStartAngle, sal_uInt16 nEndAngle, sal_Bool bClose)
410 {
411 	DBG_CTOR(XPolygon,NULL);
412 	pImpXPolygon = new ImpXPolygon(17);
413 
414 	nStartAngle %= 3600;
415 	if ( nEndAngle > 3600 ) nEndAngle %= 3600;
416 	sal_Bool bFull = (nStartAngle == 0 && nEndAngle == 3600);
417 
418 	// Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
419 	long    nXHdl = (long)(0.552284749 * nRx);
420 	long    nYHdl = (long)(0.552284749 * nRy);
421 	sal_uInt16  nPos = 0;
422 	sal_Bool    bLoopEnd = sal_False;
423 
424 	do
425 	{
426 		sal_uInt16 nA1, nA2;
427 		sal_uInt16 nQuad = nStartAngle / 900;
428 		if ( nQuad == 4 ) nQuad = 0;
429 		bLoopEnd = CheckAngles(nStartAngle, nEndAngle, nA1, nA2);
430 		GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
431 		nPos += 3;
432 		if ( !bLoopEnd )
433 			pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
434 
435 	} while ( !bLoopEnd );
436 
437 	// Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
438 	if ( !bFull && bClose )
439 		pImpXPolygon->pPointAry[++nPos] = rCenter;
440 
441 	if ( bFull )
442 	{
443 		pImpXPolygon->pFlagAry[0   ] = (sal_uInt8) XPOLY_SMOOTH;
444 		pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) XPOLY_SMOOTH;
445 	}
446 	pImpXPolygon->nPoints = nPos + 1;
447 }
448 
449 /*************************************************************************
450 |*
451 |*    XPolygon::~XPolygon()
452 |*
453 |*    Beschreibung
454 |*    Ersterstellung    08.11.94
455 |*    Letzte Aenderung  08.11.94
456 |*
457 *************************************************************************/
458 
~XPolygon()459 XPolygon::~XPolygon()
460 {
461 	DBG_DTOR(XPolygon,NULL);
462 	if( pImpXPolygon->nRefCount > 1 )
463 		pImpXPolygon->nRefCount--;
464 	else
465 		delete pImpXPolygon;
466 }
467 
468 /*************************************************************************
469 |*
470 |*    XPolygon::CheckReference()
471 |*
472 |*    Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
473 |*    Ersterstellung    17.01.95 ESO
474 |*    Letzte Aenderung  17.01.95 ESO
475 |*
476 *************************************************************************/
477 
CheckReference()478 void XPolygon::CheckReference()
479 {
480 	if( pImpXPolygon->nRefCount > 1 )
481 	{
482 		pImpXPolygon->nRefCount--;
483 		pImpXPolygon = new ImpXPolygon( *pImpXPolygon );
484 	}
485 }
486 
487 /*************************************************************************
488 |*
489 |*    XPolygon::SetSize()
490 |*
491 |*    Beschreibung
492 |*    Ersterstellung    08.11.94
493 |*    Letzte Aenderung  08.11.94
494 |*
495 *************************************************************************/
496 
SetSize(sal_uInt16 nNewSize)497 void XPolygon::SetSize( sal_uInt16 nNewSize )
498 {
499 	CheckReference();
500 	pImpXPolygon->Resize( nNewSize );
501 }
502 
503 /*************************************************************************
504 |*
505 |*    XPolygon::GetSize()
506 |*
507 |*    Beschreibung
508 |*    Ersterstellung    08.11.94
509 |*    Letzte Aenderung  12.01.95 ESO
510 |*
511 *************************************************************************/
512 
GetSize() const513 sal_uInt16 XPolygon::GetSize() const
514 {
515 	pImpXPolygon->CheckPointDelete();
516 	return pImpXPolygon->nSize;
517 }
518 
519 /*************************************************************************
520 |*
521 |*    XPolygon::SetPointCount()
522 |*
523 |*    Beschreibung
524 |*    Ersterstellung    08.11.94
525 |*    Letzte Aenderung  12.01.95 ESO
526 |*
527 *************************************************************************/
528 
SetPointCount(sal_uInt16 nPoints)529 void XPolygon::SetPointCount( sal_uInt16 nPoints )
530 {
531 	pImpXPolygon->CheckPointDelete();
532 	CheckReference();
533 
534 	if( pImpXPolygon->nSize < nPoints )
535 		pImpXPolygon->Resize( nPoints );
536 
537 	if ( nPoints < pImpXPolygon->nPoints )
538 	{
539 		sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
540 		memset( &pImpXPolygon->pPointAry[nPoints], 0, nSize * sizeof( Point ) );
541 		memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
542 	}
543 	pImpXPolygon->nPoints = nPoints;
544 }
545 
546 /*************************************************************************
547 |*
548 |*    XPolygon::GetPointCount()
549 |*
550 |*    Beschreibung
551 |*    Ersterstellung    08.11.94
552 |*    Letzte Aenderung  12.01.95 ESO
553 |*
554 *************************************************************************/
555 
GetPointCount() const556 sal_uInt16 XPolygon::GetPointCount() const
557 {
558 	pImpXPolygon->CheckPointDelete();
559 	return pImpXPolygon->nPoints;
560 }
561 
562 /*************************************************************************
563 |*
564 |*    XPolygon::Insert()
565 |*
566 |*    Beschreibung
567 |*    Ersterstellung    08.11.94
568 |*    Letzte Aenderung  08.11.94
569 |*
570 *************************************************************************/
571 
Insert(sal_uInt16 nPos,const Point & rPt,XPolyFlags eFlags)572 void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, XPolyFlags eFlags )
573 {
574 	CheckReference();
575 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
576 	pImpXPolygon->InsertSpace( nPos, 1 );
577 	pImpXPolygon->pPointAry[nPos] = rPt;
578 	pImpXPolygon->pFlagAry[nPos]  = (sal_uInt8)eFlags;
579 }
580 
581 /*************************************************************************
582 |*
583 |*    XPolygon::Insert()
584 |*
585 |*    Beschreibung
586 |*    Ersterstellung    08.11.94
587 |*    Letzte Aenderung  08.11.94
588 |*
589 *************************************************************************/
590 
Insert(sal_uInt16 nPos,const XPolygon & rXPoly)591 void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
592 {
593 	CheckReference();
594 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
595 
596 	sal_uInt16 nPoints = rXPoly.GetPointCount();
597 
598 	pImpXPolygon->InsertSpace( nPos, nPoints );
599 
600 	memcpy( &(pImpXPolygon->pPointAry[nPos]),
601 			rXPoly.pImpXPolygon->pPointAry,
602 			nPoints*sizeof( Point ) );
603 	memcpy( &(pImpXPolygon->pFlagAry[nPos]),
604 			rXPoly.pImpXPolygon->pFlagAry,
605 			nPoints );
606 }
607 
608 /*************************************************************************
609 |*
610 |*    XPolygon::Insert()
611 |*
612 |*    Beschreibung
613 |*    Ersterstellung    08.11.94
614 |*    Letzte Aenderung  08.11.94
615 |*
616 *************************************************************************/
617 
Insert(sal_uInt16 nPos,const Polygon & rPoly)618 void XPolygon::Insert( sal_uInt16 nPos, const Polygon& rPoly )
619 {
620 	CheckReference();
621 	if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
622 
623 	sal_uInt16 nPoints = rPoly.GetSize();
624 
625 	pImpXPolygon->InsertSpace( nPos, nPoints );
626 
627 	sal_uInt16 i;
628 	for( i=0; i < nPoints; i++ )
629 		pImpXPolygon->pPointAry[i] = rPoly[i];
630 
631 	// Die Flags sind durch das InsertSpace bereits auf 0 gesetzt
632 }
633 
634 /*************************************************************************
635 |*
636 |*    XPolygon::Remove()
637 |*
638 |*    Beschreibung
639 |*    Ersterstellung    08.11.94
640 |*    Letzte Aenderung  08.11.94
641 |*
642 *************************************************************************/
643 
Remove(sal_uInt16 nPos,sal_uInt16 nCount)644 void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
645 {
646 	CheckReference();
647 	pImpXPolygon->Remove( nPos, nCount );
648 }
649 
650 /*************************************************************************
651 |*
652 |*    XPolygon::Move()
653 |*
654 |*    Beschreibung
655 |*    Ersterstellung    09.11.94
656 |*    Letzte Aenderung  09.11.94
657 |*
658 *************************************************************************/
659 
Move(long nHorzMove,long nVertMove)660 void XPolygon::Move( long nHorzMove, long nVertMove )
661 {
662 	if ( !nHorzMove && !nVertMove )
663 		return;
664 
665 	CheckReference();
666 
667 	// Punkte verschieben
668 	sal_uInt16 nCount = pImpXPolygon->nPoints;
669 	for ( sal_uInt16 i = 0; i < nCount; i++ )
670 	{
671 		Point* pPt = &(pImpXPolygon->pPointAry[i]);
672 		pPt->X() += nHorzMove;
673 		pPt->Y() += nVertMove;
674 	}
675 }
676 
677 /*************************************************************************
678 |*
679 |*    XPolygon::GetBoundRect()
680 |*
681 |*    Beschreibung
682 |*    Ersterstellung    09.11.94
683 |*    Letzte Aenderung  12.01.95 ESO
684 |*
685 *************************************************************************/
686 
GetBoundRect() const687 Rectangle XPolygon::GetBoundRect() const
688 {
689 	pImpXPolygon->CheckPointDelete();
690 	Rectangle aRetval;
691 
692 	if(pImpXPolygon->nPoints)
693 	{
694 		// #i37709#
695 		// For historical reasons the control points are not part of the
696 		// BoundRect. This makes it necessary to subdivide the polygon to
697 		// get a relatively correct BoundRect. Numerically, this is not
698 		// correct and never was.
699 
700 		const basegfx::B2DRange aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
701 		aRetval = Rectangle(
702 			FRound(aPolygonRange.getMinX()), FRound(aPolygonRange.getMinY()),
703 			FRound(aPolygonRange.getMaxX()), FRound(aPolygonRange.getMaxY()));
704 	}
705 
706 	return aRetval;
707 }
708 
709 /*************************************************************************
710 |*
711 |*    XPolygon::operator[]()
712 |*
713 |*    Beschreibung
714 |*    Ersterstellung    08.11.94
715 |*    Letzte Aenderung  12.01.95
716 |*
717 *************************************************************************/
718 
operator [](sal_uInt16 nPos) const719 const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
720 {
721 	DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
722 
723 	pImpXPolygon->CheckPointDelete();
724 	return pImpXPolygon->pPointAry[nPos];
725 }
726 
727 /*************************************************************************
728 |*
729 |*    XPolygon::operator[]()
730 |*
731 |*    Beschreibung
732 |*    Ersterstellung    08.11.94
733 |*    Letzte Aenderung  12.01.95 ESO
734 |*
735 *************************************************************************/
736 
operator [](sal_uInt16 nPos)737 Point& XPolygon::operator[]( sal_uInt16 nPos )
738 {
739 	pImpXPolygon->CheckPointDelete();
740 	CheckReference();
741 
742 	if( nPos >= pImpXPolygon->nSize )
743 	{
744 		DBG_ASSERT(pImpXPolygon->nResize, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
745 		pImpXPolygon->Resize(nPos + 1, sal_False);
746 	}
747 	if( nPos >= pImpXPolygon->nPoints )
748 		pImpXPolygon->nPoints = nPos + 1;
749 
750 	return pImpXPolygon->pPointAry[nPos];
751 }
752 
753 /*************************************************************************
754 |*
755 |*    XPolygon::operator=()
756 |*
757 |*    Beschreibung      Zuweisungsoperator
758 |*    Ersterstellung    ESO 22.11.94
759 |*    Letzte Aenderung  ESO 12.01.95
760 |*
761 *************************************************************************/
762 
operator =(const XPolygon & rXPoly)763 XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
764 {
765 	pImpXPolygon->CheckPointDelete();
766 
767 	rXPoly.pImpXPolygon->nRefCount++;
768 
769 	if( pImpXPolygon->nRefCount > 1 )
770 		pImpXPolygon->nRefCount--;
771 	else
772 		delete pImpXPolygon;
773 
774 	pImpXPolygon = rXPoly.pImpXPolygon;
775 	return *this;
776 }
777 
778 /*************************************************************************
779 |*
780 |*    XPolygon::operator==()
781 |*
782 |*    Beschreibung      Gleichheitsoperator
783 |*    Ersterstellung    ESO 22.11.94
784 |*    Letzte Aenderung  Joe 26.09.95
785 |*
786 *************************************************************************/
787 
operator ==(const XPolygon & rXPoly) const788 sal_Bool XPolygon::operator==( const XPolygon& rXPoly ) const
789 {
790 	pImpXPolygon->CheckPointDelete();
791 	if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_True;
792 	return *rXPoly.pImpXPolygon == *pImpXPolygon;
793 }
794 
795 /*************************************************************************
796 |*
797 |*    XPolygon::operator!=()
798 |*
799 |*    Beschreibung      Ungleichheitsoperator
800 |*    Ersterstellung    ESO 22.11.94
801 |*    Letzte Aenderung  Joe 26.09.95
802 |*
803 *************************************************************************/
804 
operator !=(const XPolygon & rXPoly) const805 sal_Bool XPolygon::operator!=( const XPolygon& rXPoly ) const
806 {
807 	pImpXPolygon->CheckPointDelete();
808 	if (rXPoly.pImpXPolygon==pImpXPolygon) return sal_False;
809 	return *rXPoly.pImpXPolygon != *pImpXPolygon;
810 }
811 
812 /*************************************************************************
813 |*
814 |*    XPolygon::GetFlags()
815 |*
816 |*    Flags fuer den Punkt an der Position nPos zurueckgeben
817 |*    Ersterstellung    ESO 11.11.94
818 |*    Letzte Aenderung  ESO 12.01.95
819 |*
820 *************************************************************************/
821 
GetFlags(sal_uInt16 nPos) const822 XPolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
823 {
824 	pImpXPolygon->CheckPointDelete();
825 	return (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
826 }
827 
828 /*************************************************************************
829 |*
830 |*    XPolygon::SetFlags()
831 |*
832 |*    Flags fuer den Punkt an der Position nPos setzen
833 |*    Ersterstellung    ESO 11.11.94
834 |*    Letzte Aenderung  ESO 12.01.95
835 |*
836 *************************************************************************/
837 
SetFlags(sal_uInt16 nPos,XPolyFlags eFlags)838 void XPolygon::SetFlags( sal_uInt16 nPos, XPolyFlags eFlags )
839 {
840 	pImpXPolygon->CheckPointDelete();
841 	CheckReference();
842 	pImpXPolygon->pFlagAry[nPos] = (sal_uInt8) eFlags;
843 }
844 
845 /*************************************************************************
846 |*
847 |*    XPolygon::IsControl()
848 |*
849 |*    Kurzform zur Abfrage des CONTROL-Flags
850 |*    Ersterstellung    ESO 09.01.95
851 |*    Letzte Aenderung  ESO 12.01.95
852 |*
853 *************************************************************************/
854 
IsControl(sal_uInt16 nPos) const855 sal_Bool XPolygon::IsControl(sal_uInt16 nPos) const
856 {
857 	return ( (XPolyFlags) pImpXPolygon->pFlagAry[nPos] == XPOLY_CONTROL );
858 }
859 
860 /*************************************************************************
861 |*
862 |*    XPolygon::IsSmooth()
863 |*
864 |*    Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
865 |*    Ersterstellung    ESO 18.04.95
866 |*    Letzte Aenderung  ESO 18.04.95
867 |*
868 *************************************************************************/
869 
IsSmooth(sal_uInt16 nPos) const870 sal_Bool XPolygon::IsSmooth(sal_uInt16 nPos) const
871 {
872 	XPolyFlags eFlag = (XPolyFlags) pImpXPolygon->pFlagAry[nPos];
873 	return ( eFlag == XPOLY_SMOOTH || eFlag == XPOLY_SYMMTR );
874 }
875 
876 /*************************************************************************
877 |*
878 |*    XPolygon::CalcDistance()
879 |*
880 |*    Abstand zwischen zwei Punkten berechnen
881 |*    Ersterstellung    ESO 09.01.95
882 |*    Letzte Aenderung  ESO 09.01.95
883 |*
884 *************************************************************************/
885 
CalcDistance(sal_uInt16 nP1,sal_uInt16 nP2)886 double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
887 {
888 	const Point& rP1 = pImpXPolygon->pPointAry[nP1];
889 	const Point& rP2 = pImpXPolygon->pPointAry[nP2];
890 	double fDx = rP2.X() - rP1.X();
891 	double fDy = rP2.Y() - rP1.Y();
892 	return sqrt(fDx * fDx + fDy * fDy);
893 }
894 
895 /*************************************************************************
896 |*
897 |*    XPolygon::SubdivideBezier()
898 |*
899 |*    Bezierkurve unterteilen
900 |*    Ersterstellung    ESO 09.01.95
901 |*    Letzte Aenderung  ESO 09.01.95
902 |*
903 *************************************************************************/
904 
SubdivideBezier(sal_uInt16 nPos,sal_Bool bCalcFirst,double fT)905 void XPolygon::SubdivideBezier(sal_uInt16 nPos, sal_Bool bCalcFirst, double fT)
906 {
907 	Point*  pPoints = pImpXPolygon->pPointAry;
908 	double  fT2 = fT * fT;
909 	double  fT3 = fT * fT2;
910 	double  fU = 1.0 - fT;
911 	double  fU2 = fU * fU;
912 	double  fU3 = fU * fU2;
913 	sal_uInt16  nIdx = nPos;
914 	short   nPosInc, nIdxInc;
915 
916 	if ( bCalcFirst )
917 	{
918 		nPos += 3;
919 		nPosInc = -1;
920 		nIdxInc = 0;
921 	}
922 	else
923 	{
924 		nPosInc = 1;
925 		nIdxInc = 1;
926 	}
927 	pPoints[nPos].X() = (long) (fU3 *       pPoints[nIdx  ].X() +
928 								fT  * fU2 * pPoints[nIdx+1].X() * 3 +
929 								fT2 * fU  * pPoints[nIdx+2].X() * 3 +
930 								fT3 *       pPoints[nIdx+3].X());
931 	pPoints[nPos].Y() = (long) (fU3 *       pPoints[nIdx  ].Y() +
932 								fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
933 								fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
934 								fT3 *       pPoints[nIdx+3].Y());
935 	nPos = nPos + nPosInc;
936 	nIdx = nIdx + nIdxInc;
937 	pPoints[nPos].X() = (long) (fU2 *       pPoints[nIdx  ].X() +
938 								fT  * fU *  pPoints[nIdx+1].X() * 2 +
939 								fT2 *       pPoints[nIdx+2].X());
940 	pPoints[nPos].Y() = (long) (fU2 *       pPoints[nIdx  ].Y() +
941 								fT  * fU *  pPoints[nIdx+1].Y() * 2 +
942 								fT2 *       pPoints[nIdx+2].Y());
943 	nPos = nPos + nPosInc;
944 	nIdx = nIdx + nIdxInc;
945 	pPoints[nPos].X() = (long) (fU * pPoints[nIdx  ].X() +
946 								fT * pPoints[nIdx+1].X());
947 	pPoints[nPos].Y() = (long) (fU * pPoints[nIdx  ].Y() +
948 								fT * pPoints[nIdx+1].Y());
949 }
950 
951 /************************************************************************/
952 
GenBezArc(const Point & rCenter,long nRx,long nRy,long nXHdl,long nYHdl,sal_uInt16 nStart,sal_uInt16 nEnd,sal_uInt16 nQuad,sal_uInt16 nFirst)953 void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
954 						 long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
955 						 sal_uInt16 nQuad, sal_uInt16 nFirst)
956 {
957 	Point* pPoints = pImpXPolygon->pPointAry;
958 	pPoints[nFirst  ] = rCenter;
959 	pPoints[nFirst+3] = rCenter;
960 
961 	if ( nQuad == 1 || nQuad == 2 )
962 	{
963 		nRx   = -nRx; nXHdl = -nXHdl;
964 	}
965 	if ( nQuad == 0 || nQuad == 1 )
966 	{
967 		nRy   = -nRy; nYHdl = -nYHdl;
968 	}
969 
970 	if ( nQuad == 0 || nQuad == 2 )
971 	{
972 		pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
973 	}
974 	else
975 	{
976 		pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
977 	}
978 	pPoints[nFirst+1] = pPoints[nFirst];
979 	pPoints[nFirst+2] = pPoints[nFirst+3];
980 
981 	if ( nQuad == 0 || nQuad == 2 )
982 	{
983 		pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
984 	}
985 	else
986 	{
987 		pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
988 	}
989 	if ( nStart > 0 )
990 		SubdivideBezier(nFirst, sal_False, (double)nStart / 900);
991 	if ( nEnd < 900 )
992 		SubdivideBezier(nFirst, sal_True, (double)(nEnd-nStart) / (900-nStart));
993 	SetFlags(nFirst+1, XPOLY_CONTROL);
994 	SetFlags(nFirst+2, XPOLY_CONTROL);
995 }
996 
997 /************************************************************************/
998 
CheckAngles(sal_uInt16 & nStart,sal_uInt16 nEnd,sal_uInt16 & nA1,sal_uInt16 & nA2)999 sal_Bool XPolygon::CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2)
1000 {
1001 	if ( nStart == 3600 ) nStart = 0;
1002 	if ( nEnd == 0 ) nEnd = 3600;
1003 	sal_uInt16 nStPrev = nStart;
1004 	sal_uInt16 nMax = (nStart / 900 + 1) * 900;
1005 	sal_uInt16 nMin = nMax - 900;
1006 
1007 	if ( nEnd >= nMax || nEnd <= nStart )   nA2 = 900;
1008 	else                                    nA2 = nEnd - nMin;
1009 	nA1 = nStart - nMin;
1010 	nStart = nMax;
1011 
1012 	// sal_True zurueck, falls letztes Segment berechnet wurde
1013 	return (nStPrev < nEnd && nStart >= nEnd);
1014 }
1015 
1016 /*************************************************************************
1017 |*
1018 |*    XPolygon::CalcSmoothJoin()
1019 |*
1020 |*    glatten Uebergang zu einer Bezierkurve berechnen, indem der
1021 |*    entsprechende Punkt auf die Verbindungslinie von zwei anderen
1022 |*    Punkten projiziert wird
1023 |*     Center = End- bzw. Anfangspunkt der Bezierkurve
1024 |*     Drag   = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
1025 |*     Pnt    = der zu modifizierende Punkt
1026 |*    Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
1027 |*    auf die entgegengesetzte Seite verlegt
1028 |*    Ersterstellung    ESO 09.01.95
1029 |*    Letzte Aenderung  ESO 18.04.95
1030 |*
1031 \************************************************************************/
1032 
CalcSmoothJoin(sal_uInt16 nCenter,sal_uInt16 nDrag,sal_uInt16 nPnt)1033 void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 nPnt)
1034 {
1035 	CheckReference();
1036 
1037 //	sal_uInt16  nMaxPnt = pImpXPolygon->nPoints - 1;
1038 
1039 //  if ( nCenter == nMaxPnt )   nPnt = 1;
1040 //  else if ( nCenter == 0 )    nPnt = nMaxPnt - 1;
1041 
1042 	// Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
1043 	// statt dessen nDrag auf der Achse nCenter-nPnt verschieben
1044 	if ( !IsControl(nPnt) )
1045 	{
1046 		sal_uInt16 nTmp = nDrag;
1047 		nDrag = nPnt;
1048 		nPnt = nTmp;
1049 	}
1050 	Point*  pPoints = pImpXPolygon->pPointAry;
1051 	Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
1052 	double  fDiv    = CalcDistance(nCenter, nDrag);
1053 
1054 	if ( fDiv )
1055 	{
1056 		double fRatio = CalcDistance(nCenter, nPnt) / fDiv;
1057 		// bei SMOOTH bisherige Laenge beibehalten
1058 		if ( GetFlags(nCenter) == XPOLY_SMOOTH || !IsControl(nDrag) )
1059 		{
1060 			aDiff.X() = (long) (fRatio * aDiff.X());
1061 			aDiff.Y() = (long) (fRatio * aDiff.Y());
1062 		}
1063 		pPoints[nPnt] = pPoints[nCenter] - aDiff;
1064 	}
1065 }
1066 
1067 /*************************************************************************
1068 |*
1069 |*    XPolygon::CalcTangent()
1070 |*
1071 |*    Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
1072 |*     Center = End- bzw. Anfangspunkt der Bezierkurven
1073 |*     Prev   = vorheriger Zugpunkt
1074 |*     Next   = naechster Zugpunkt
1075 |*    Ersterstellung    ESO 09.01.95
1076 |*    Letzte Aenderung  ESO 18.04.95
1077 |*
1078 \************************************************************************/
1079 
CalcTangent(sal_uInt16 nCenter,sal_uInt16 nPrev,sal_uInt16 nNext)1080 void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNext)
1081 {
1082 	CheckReference();
1083 
1084 	double fAbsLen = CalcDistance(nNext, nPrev);
1085 
1086 	if ( fAbsLen )
1087 	{
1088 		const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
1089 		Point&  rNext = pImpXPolygon->pPointAry[nNext];
1090 		Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
1091 		Point   aDiff = rNext - rPrev;
1092 		double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
1093 		double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
1094 
1095 		// bei SYMMTR gleiche Laenge fuer beide Seiten
1096 		if ( GetFlags(nCenter) == XPOLY_SYMMTR )
1097 		{
1098 			fPrevLen = (fNextLen + fPrevLen) / 2;
1099 			fNextLen = fPrevLen;
1100 		}
1101 		rNext.X() = rCenter.X() + (long) (fNextLen * aDiff.X());
1102 		rNext.Y() = rCenter.Y() + (long) (fNextLen * aDiff.Y());
1103 		rPrev.X() = rCenter.X() - (long) (fPrevLen * aDiff.X());
1104 		rPrev.Y() = rCenter.Y() - (long) (fPrevLen * aDiff.Y());
1105 	}
1106 }
1107 
1108 /*************************************************************************
1109 |*
1110 |*    XPolygon::PointsToBezier()
1111 |*
1112 |*    wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
1113 |*    Ersterstellung    ESO 09.01.95
1114 |*    Letzte Aenderung  ESO 09.01.95
1115 |*
1116 \************************************************************************/
1117 
PointsToBezier(sal_uInt16 nFirst)1118 void XPolygon::PointsToBezier(sal_uInt16 nFirst)
1119 {
1120 	double  nFullLength, nPart1Length, nPart2Length;
1121 	double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
1122 	double  fTx1, fTx2, fTy1, fTy2;
1123 	double  fT1, fU1, fT2, fU2, fV;
1124 	Point*  pPoints = pImpXPolygon->pPointAry;
1125 
1126 	if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
1127 		 IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
1128 		return;
1129 
1130 	CheckReference();
1131 
1132 	fTx1 = pPoints[nFirst+1].X();
1133 	fTy1 = pPoints[nFirst+1].Y();
1134 	fTx2 = pPoints[nFirst+2].X();
1135 	fTy2 = pPoints[nFirst+2].Y();
1136 	fX0  = pPoints[nFirst  ].X();
1137 	fY0  = pPoints[nFirst  ].Y();
1138 	fX3  = pPoints[nFirst+3].X();
1139 	fY3  = pPoints[nFirst+3].Y();
1140 
1141 	nPart1Length = CalcDistance(nFirst, nFirst+1);
1142 	nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
1143 	nFullLength  = nPart2Length + CalcDistance(nFirst+2, nFirst+3);
1144 	if ( nFullLength < 20 )
1145 		return;
1146 
1147 	if ( nPart2Length == nFullLength )
1148 		nPart2Length -= 1;
1149 	if ( nPart1Length == nFullLength )
1150 		nPart1Length = nPart2Length - 1;
1151 	if ( nPart1Length <= 0 )
1152 		nPart1Length = 1;
1153 	if ( nPart2Length <= 0 || nPart2Length == nPart1Length )
1154 		nPart2Length = nPart1Length + 1;
1155 
1156 	fT1 = nPart1Length / nFullLength;
1157 	fU1 = 1.0 - fT1;
1158 	fT2 = nPart2Length / nFullLength;
1159 	fU2 = 1.0 - fT2;
1160 	fV = 3 * (1.0 - (fT1 * fU2) / (fT2 * fU1));
1161 
1162 	fX1 = fTx1 / (fT1 * fU1 * fU1) - fTx2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1163 	fX1 /= fV;
1164 	fX1 -= fX0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1165 	fX1 += fX3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1166 
1167 	fY1 = fTy1 / (fT1 * fU1 * fU1) - fTy2 * fT1 / (fT2 * fT2 * fU1 * fU2);
1168 	fY1 /= fV;
1169 	fY1 -= fY0 * ( fU1 / fT1 + fU2 / fT2) / 3;
1170 	fY1 += fY3 * ( fT1 * fT2 / (fU1 * fU2)) / 3;
1171 
1172 	fX2 = fTx2 / (fT2 * fT2 * fU2 * 3) - fX0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1173 	fX2 -= fX1 * fU2 / fT2;
1174 	fX2 -= fX3 * fT2 / (fU2 * 3);
1175 
1176 	fY2 = fTy2 / (fT2 * fT2 * fU2 * 3) - fY0 * fU2 * fU2 / ( fT2 * fT2 * 3);
1177 	fY2 -= fY1 * fU2 / fT2;
1178 	fY2 -= fY3 * fT2 / (fU2 * 3);
1179 
1180 	pPoints[nFirst+1] = Point((long) fX1, (long) fY1);
1181 	pPoints[nFirst+2] = Point((long) fX2, (long) fY2);
1182 	SetFlags(nFirst+1, XPOLY_CONTROL);
1183 	SetFlags(nFirst+2, XPOLY_CONTROL);
1184 }
1185 
1186 /*************************************************************************
1187 |*
1188 |*    XPolygon::Translate()
1189 |*
1190 |*    Polygon auf den uebergebenen Punkt verschieben
1191 |*    Ersterstellung    ESO 17.01.95
1192 |*    Letzte Aenderung  ESO 17.01.95
1193 |*
1194 *************************************************************************/
1195 
Translate(const Point & rTrans)1196 void XPolygon::Translate(const Point& rTrans)
1197 {
1198 	pImpXPolygon->CheckPointDelete();
1199 	CheckReference();
1200 
1201 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1202 
1203 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1204 		pImpXPolygon->pPointAry[i] += rTrans;
1205 }
1206 
1207 /*************************************************************************
1208 |*
1209 |*    XPolygon::Rotate()
1210 |*
1211 |*    Alle Punkte um den Punkt rCenter drehen, Sinus und Cosinus
1212 |*    muessen uebergeben werden
1213 |*    Ersterstellung    ESO 09.01.95
1214 |*    Letzte Aenderung  ESO 17.01.95
1215 |*
1216 *************************************************************************/
1217 
Rotate(const Point & rCenter,double fSin,double fCos)1218 void XPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1219 {
1220 	pImpXPolygon->CheckPointDelete();
1221 	CheckReference();
1222 
1223 	long nX;
1224 	long nY;
1225 	long nNewX;
1226 	long nNewY;
1227 	long nCenterX = rCenter.X();
1228 	long nCenterY = rCenter.Y();
1229 
1230 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1231 
1232 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1233 	{
1234 		Point *pPt = &(pImpXPolygon->pPointAry[i]);
1235 		nX = pPt->X()-nCenterX;
1236 		nY = pPt->Y()-nCenterY;
1237 		nNewX =  (long)floor(fCos * nX + fSin * nY + 0.5);
1238 		nNewY = -(long)floor(fSin * nX - fCos * nY + 0.5);
1239 		pPt->X() = nNewX + nCenterX;
1240 		pPt->Y() = nNewY + nCenterY;
1241 
1242 	/* und so stand das in einem anderen File auf T:
1243 	   dass ich am 29-11-1995 gegettet habe. Joe M.
1244 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1245 
1246 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1247 	{
1248 		Point P = pImpXPolygon->pPointAry[i] - rCenter;
1249 		long X = P.X();
1250 		long Y = P.Y();
1251 		P.X() =  (long)floor(fCos * X + fSin * Y + 0.5);
1252 		P.Y() = -(long)floor(fSin * X - fCos * Y + 0.5);
1253 		pImpXPolygon->pPointAry[i] = P + rCenter;
1254 	*/
1255 	}
1256 }
1257 
1258 /*************************************************************************
1259 |*
1260 |*    XPolygon::Rotate()
1261 |*
1262 |*    Alle Punkte um den Punkt rCenter mit dem Winkel nAngle drehen
1263 |*    Winkel in 10tel Grad, Wertebereich 0 - 3600
1264 |*    Ersterstellung    ESO 17.01.95
1265 |*    Letzte Aenderung  ESO 17.01.95
1266 |*
1267 *************************************************************************/
1268 
Rotate(const Point & rCenter,sal_uInt16 nAngle)1269 void XPolygon::Rotate(const Point& rCenter, sal_uInt16 nAngle)
1270 {
1271 	nAngle %= 3600;
1272 
1273 	if ( nAngle != 0 )
1274 	{
1275 		double fAngle = F_PI * nAngle / 1800;
1276 		double fSin = sin(fAngle);
1277 		double fCos = cos(fAngle);
1278 		Rotate(rCenter, fSin, fCos);
1279 	}
1280 }
1281 
1282 /*************************************************************************
1283 |*
1284 |*    XPolygon::Scale()
1285 |*
1286 |*    XPolygon in X- und/oder Y-Richtung skalieren
1287 |*    Ersterstellung    ESO 01.02.95
1288 |*    Letzte Aenderung  ESO 01.02.95
1289 |*
1290 *************************************************************************/
1291 
Scale(double fSx,double fSy)1292 void XPolygon::Scale(double fSx, double fSy)
1293 {
1294 	pImpXPolygon->CheckPointDelete();
1295 	CheckReference();
1296 
1297 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1298 
1299 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1300 	{
1301 		Point& rPnt = pImpXPolygon->pPointAry[i];
1302 		rPnt.X() = (long)(fSx * rPnt.X());
1303 		rPnt.Y() = (long)(fSy * rPnt.Y());
1304 	}
1305 }
1306 
1307 /*************************************************************************
1308 |*
1309 |*    XPolygon::SlantX()
1310 |*
1311 |*    XPolygon in X-Richtung um einen beliebigen Winkel kippen,
1312 |*    bezogen auf eine Referenz-Y-Koordinate
1313 |*    Ersterstellung    ESO 01.02.95
1314 |*    Letzte Aenderung  ESO 01.02.95
1315 |*
1316 *************************************************************************/
1317 
SlantX(long nYRef,double fSin,double fCos)1318 void XPolygon::SlantX(long nYRef, double fSin, double fCos)
1319 {
1320 	pImpXPolygon->CheckPointDelete();
1321 	CheckReference();
1322 
1323 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1324 
1325 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1326 	{
1327 		Point& rPnt = pImpXPolygon->pPointAry[i];
1328 		long nDy = rPnt.Y() - nYRef;
1329 		rPnt.X() += (long)(fSin * nDy);
1330 		rPnt.Y() = nYRef + (long)(fCos * nDy);
1331 	}
1332 }
1333 
1334 /*************************************************************************
1335 |*
1336 |*    XPolygon::SlantY()
1337 |*
1338 |*    XPolygon in Y-Richtung um einen beliebigen Winkel kippen,
1339 |*    bezogen auf eine Referenz-X-Koordinate
1340 |*    Ersterstellung    ESO 01.02.95
1341 |*    Letzte Aenderung  ESO 01.02.95
1342 |*
1343 *************************************************************************/
1344 
SlantY(long nXRef,double fSin,double fCos)1345 void XPolygon::SlantY(long nXRef, double fSin, double fCos)
1346 {
1347 	pImpXPolygon->CheckPointDelete();
1348 	CheckReference();
1349 
1350 	sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1351 
1352 	for (sal_uInt16 i = 0; i < nPntCnt; i++)
1353 	{
1354 		Point& rPnt = pImpXPolygon->pPointAry[i];
1355 		long nDx = rPnt.X() - nXRef;
1356 		rPnt.X() = nXRef + (long)(fCos * nDx);
1357 		rPnt.Y() -= (long)(fSin * nDx);
1358 	}
1359 }
1360 
1361 /*************************************************************************
1362 |*
1363 |*    XPolygon::Distort()
1364 |*
1365 |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
1366 |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
1367 |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1368 |*    0: links oben      0----1
1369 |*    1: rechts oben     |    |
1370 |*    2: rechts unten    3----2
1371 |*    3: links unten
1372 |*    Ersterstellung    ESO 07.07.95
1373 |*    Letzte Aenderung  ESO 07.07.95
1374 |*
1375 *************************************************************************/
1376 
Distort(const Rectangle & rRefRect,const XPolygon & rDistortedRect)1377 void XPolygon::Distort(const Rectangle& rRefRect,
1378 					   const XPolygon& rDistortedRect)
1379 {
1380 	pImpXPolygon->CheckPointDelete();
1381 	CheckReference();
1382 
1383 	long    Xr, Wr, X1, X2, X3, X4;
1384 	long    Yr, Hr, Y1, Y2, Y3, Y4;
1385 	double  fTx, fTy, fUx, fUy;
1386 
1387 	Xr = rRefRect.Left();
1388 	Yr = rRefRect.Top();
1389 	Wr = rRefRect.GetWidth();
1390 	Hr = rRefRect.GetHeight();
1391 
1392 	if ( Wr && Hr )
1393 	{
1394 		DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
1395 				   "Distort-Rechteck zu klein");
1396 
1397 		X1 = rDistortedRect[0].X();
1398 		Y1 = rDistortedRect[0].Y();
1399 		X2 = rDistortedRect[1].X();
1400 		Y2 = rDistortedRect[1].Y();
1401 		X3 = rDistortedRect[3].X();
1402 		Y3 = rDistortedRect[3].Y();
1403 		X4 = rDistortedRect[2].X();
1404 		Y4 = rDistortedRect[2].Y();
1405 
1406 		sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
1407 
1408 		for (sal_uInt16 i = 0; i < nPntCnt; i++)
1409 		{
1410 			Point& rPnt = pImpXPolygon->pPointAry[i];
1411 
1412 			fTx = (double)(rPnt.X() - Xr) / Wr;
1413 			fTy = (double)(rPnt.Y() - Yr) / Hr;
1414 			fUx = 1.0 - fTx;
1415 			fUy = 1.0 - fTy;
1416 
1417 			rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) +
1418 								fTy * (fUx * X3 + fTx * X4) );
1419 			rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) +
1420 								fTx * (fUy * Y2 + fTy * Y4) );
1421 		}
1422 	}
1423 }
1424 
1425 /*************************************************************************
1426 |*
1427 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1428 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1429 |*
1430 \************************************************************************/
1431 
Rotate20()1432 void XPolygon::Rotate20()
1433 {
1434 	pImpXPolygon->CheckPointDelete();
1435 	CheckReference();
1436 
1437 	double   fMinY   = pImpXPolygon->pPointAry->Y();
1438 	double   fMinX   = pImpXPolygon->pPointAry->X();
1439 	long     nPntCnt = pImpXPolygon->nPoints;
1440 	long     nIndex0 = 0;
1441 
1442 	for (long nPoints = 1;
1443 			  nPoints < nPntCnt;
1444 			  nPoints ++)
1445 	{
1446 		Point &rPnt = pImpXPolygon->pPointAry[nPoints];
1447 
1448 		if ((rPnt.X () < fMinX) || (fMinX == rPnt.X ()) &&
1449 								   (fMinY >= rPnt.Y ()))
1450 		{
1451 			fMinX   = rPnt.X ();
1452 			fMinY   = rPnt.Y ();
1453 			nIndex0 = nPoints;
1454 		}
1455 	}
1456 
1457 	if (nIndex0 < nPntCnt)
1458 	{
1459 		Point *pTemp = new Point [nIndex0];
1460 		memcpy (pTemp, pImpXPolygon->pPointAry, nIndex0 * sizeof (Point));
1461 		memcpy (pImpXPolygon->pPointAry, &pImpXPolygon->pPointAry [nIndex0], (nPntCnt - nIndex0) * sizeof (Point));
1462 		memcpy (&pImpXPolygon->pPointAry [nIndex0], pTemp, nIndex0 * sizeof (Point));
1463 		delete[] pTemp;
1464 	}
1465 }
1466 
getB2DPolygon() const1467 basegfx::B2DPolygon XPolygon::getB2DPolygon() const
1468 {
1469 	// #i74631# use tools Polygon class for conversion to not have the code doubled
1470 	// here. This needs one more conversion but avoids different convertors in
1471 	// the long run
1472 	DBG_ASSERT(pImpXPolygon != 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1473 	const Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry);
1474 
1475 	return aSource.getB2DPolygon();
1476 }
1477 
XPolygon(const basegfx::B2DPolygon & rPolygon)1478 XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
1479 {
1480 	// #i74631# use tools Polygon class for conversion to not have the code doubled
1481 	// here. This needs one more conversion but avoids different convertors in
1482 	// the long run
1483 	DBG_CTOR(XPolygon,NULL);
1484 
1485 	const Polygon aSource(rPolygon);
1486 	sal_uInt16 nSize = aSource.GetSize();
1487 	pImpXPolygon = new ImpXPolygon( nSize );
1488 	pImpXPolygon->nPoints = nSize;
1489 
1490 	for( sal_uInt16 i = 0; i < nSize;  i++ )
1491 	{
1492 		pImpXPolygon->pPointAry[i] = aSource[i];
1493 		pImpXPolygon->pFlagAry[i] = (sal_uInt8) aSource.GetFlags( i );
1494 	}
1495 }
1496 
1497 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1498 //+--------------- XPolyPolygon -----------------------------------------+
1499 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1500 
1501 /*************************************************************************
1502 |*
1503 |*    ImpXPolyPolygon::ImpXPolyPolygon()
1504 |*
1505 |*    Beschreibung      Erzeugt das XPolygon-Array
1506 |*    Ersterstellung    CL 09.11.94
1507 |*    Letzte Aenderung  MM 09.11.94
1508 |*
1509 *************************************************************************/
1510 
ImpXPolyPolygon(const ImpXPolyPolygon & rImpXPolyPoly)1511 ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon& rImpXPolyPoly ) :
1512 					 aXPolyList( rImpXPolyPoly.aXPolyList )
1513 {
1514 	nRefCount = 1;
1515 
1516 	// Einzelne Elemente duplizieren
1517 	XPolygon* pXPoly = aXPolyList.First();
1518 	while ( pXPoly )
1519 	{
1520 		aXPolyList.Replace( new XPolygon( *(aXPolyList.GetCurObject()) ) );
1521 		pXPoly = aXPolyList.Next();
1522 	}
1523 }
1524 
1525 
1526 /*************************************************************************
1527 |*
1528 |*    ImpXPolyPolygon::~ImpXPolyPolygon()
1529 |*
1530 |*    Beschreibung      Loescht das Polygon-Array
1531 |*    Ersterstellung    CL 09.06.93
1532 |*    Letzte Aenderung  CL 09.06.93
1533 |*
1534 *************************************************************************/
1535 
~ImpXPolyPolygon()1536 ImpXPolyPolygon::~ImpXPolyPolygon()
1537 {
1538 	XPolygon* pXPoly = aXPolyList.First();
1539 	while( pXPoly )
1540 	{
1541 		delete pXPoly;
1542 		pXPoly = aXPolyList.Next();
1543 	}
1544 }
1545 
1546 /*************************************************************************
1547 |*
1548 |*    ImpXPolyPolygon::operator==()
1549 |*
1550 |*    Ersterstellung    Joe 26-09-95
1551 |*    Letzte Aenderung
1552 |*
1553 *************************************************************************/
1554 
1555 
operator ==(const ImpXPolyPolygon & rImpXPolyPoly) const1556 bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon& rImpXPolyPoly) const
1557 {
1558 	sal_uInt16 nAnz=(sal_uInt16)aXPolyList.Count();
1559 	const XPolygonList& rCmpList=rImpXPolyPoly.aXPolyList;
1560 	if (nAnz!=(sal_uInt16)rCmpList.Count()) return sal_False;
1561 	bool bEq=true;
1562 	for (sal_uInt16 i=nAnz; i>0 && bEq;) {
1563 		i--;
1564 		bEq= *aXPolyList.GetObject(i) == *rCmpList.GetObject(i);
1565 	}
1566 	return bEq;
1567 }
1568 
1569 /*************************************************************************
1570 |*
1571 |*    XPolyPolygon::XPolyPolygon()
1572 |*
1573 |*    Beschreibung      POLY.SDW
1574 |*    Ersterstellung    CL 27.01.93
1575 |*    Letzte Aenderung  CL 27.01.93
1576 |*
1577 *************************************************************************/
1578 
XPolyPolygon(sal_uInt16 nInitSize,sal_uInt16 nResize)1579 XPolyPolygon::XPolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
1580 {
1581 	DBG_CTOR(XPolyPolygon,NULL);
1582 	pImpXPolyPolygon = new ImpXPolyPolygon( nInitSize, nResize );
1583 }
1584 
1585 
1586 /*************************************************************************
1587 |*
1588 |*    XPolyPolygon::XPolyPolygon()
1589 |*
1590 |*    Beschreibung      POLY.SDW
1591 |*    Ersterstellung    CL 27.01.93
1592 |*    Letzte Aenderung  CL 27.01.93
1593 |*
1594 *************************************************************************/
1595 
XPolyPolygon(const XPolygon & rXPoly)1596 XPolyPolygon::XPolyPolygon( const XPolygon& rXPoly )
1597 {
1598 	DBG_CTOR(XPolyPolygon,NULL);
1599 	pImpXPolyPolygon = new ImpXPolyPolygon;
1600 	pImpXPolyPolygon->aXPolyList.Insert( new XPolygon( rXPoly ) );
1601 }
1602 
1603 /*************************************************************************
1604 |*
1605 |*    XPolyPolygon::XPolyPolygon()
1606 |*
1607 |*    Beschreibung      POLY.SDW
1608 |*    Ersterstellung    CL 27.01.93
1609 |*    Letzte Aenderung  CL 27.01.93
1610 |*
1611 *************************************************************************/
1612 
XPolyPolygon(const XPolyPolygon & rXPolyPoly)1613 XPolyPolygon::XPolyPolygon( const XPolyPolygon& rXPolyPoly )
1614 {
1615 	DBG_CTOR(XPolyPolygon,NULL);
1616 	pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1617 	pImpXPolyPolygon->nRefCount++;
1618 }
1619 
1620 /*************************************************************************
1621 |*
1622 |*    XPolyPolygon::XPolyPolygon()
1623 |*
1624 |*    XPolyPolygon aus einen Standard-PolyPolygon erzeugen
1625 |*    Ersterstellung    18.01.95 ESO
1626 |*    Letzte Aenderung  18.01.95 ESO
1627 |*
1628 *************************************************************************/
1629 
XPolyPolygon(const PolyPolygon & rPolyPoly)1630 XPolyPolygon::XPolyPolygon( const PolyPolygon& rPolyPoly )
1631 {
1632 	DBG_CTOR(XPolyPolygon,NULL);
1633 	pImpXPolyPolygon = new ImpXPolyPolygon;
1634 
1635 	for (sal_uInt16 i = 0; i < rPolyPoly.Count(); i++)
1636 		pImpXPolyPolygon->aXPolyList.Insert(
1637 									new XPolygon(rPolyPoly.GetObject(i)) );
1638 }
1639 
1640 /*************************************************************************
1641 |*
1642 |*    XPolyPolygon::~XPolyPolygon()
1643 |*
1644 |*    Beschreibung      POLY.SDW
1645 |*    Ersterstellung    CL 27.01.93
1646 |*    Letzte Aenderung  CL 27.01.93
1647 |*
1648 *************************************************************************/
1649 
~XPolyPolygon()1650 XPolyPolygon::~XPolyPolygon()
1651 {
1652 	DBG_DTOR(XPolyPolygon,NULL);
1653 	if( pImpXPolyPolygon->nRefCount > 1 )
1654 		pImpXPolyPolygon->nRefCount--;
1655 	else
1656 		delete pImpXPolyPolygon;
1657 }
1658 
1659 /*************************************************************************
1660 |*
1661 |*    XPolygon::CheckReference()
1662 |*
1663 |*    Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1664 |*    Ersterstellung    18.01.95 ESO
1665 |*    Letzte Aenderung  18.01.95 ESO
1666 |*
1667 *************************************************************************/
1668 
CheckReference()1669 void XPolyPolygon::CheckReference()
1670 {
1671 	if( pImpXPolyPolygon->nRefCount > 1 )
1672 	{
1673 		pImpXPolyPolygon->nRefCount--;
1674 		pImpXPolyPolygon = new ImpXPolyPolygon( *pImpXPolyPolygon );
1675 	}
1676 }
1677 
1678 /*************************************************************************
1679 |*
1680 |*    XPolyPolygon::Insert()
1681 |*
1682 |*    Beschreibung      POLY.SDW
1683 |*    Ersterstellung    CL 27.01.93
1684 |*    Letzte Aenderung  CL 27.01.93
1685 |*
1686 *************************************************************************/
1687 
Insert(const XPolygon & rXPoly,sal_uInt16 nPos)1688 void XPolyPolygon::Insert( const XPolygon& rXPoly, sal_uInt16 nPos )
1689 {
1690 	CheckReference();
1691 	XPolygon* pXPoly = new XPolygon( rXPoly );
1692 	pImpXPolyPolygon->aXPolyList.Insert( pXPoly, nPos );
1693 }
1694 
1695 /*************************************************************************
1696 |*
1697 |*    XPolyPolygon::Insert()
1698 |*
1699 |*    saemtliche XPolygone aus einem XPolyPolygon einfuegen
1700 |*    Ersterstellung    18.01.95 ESO
1701 |*    Letzte Aenderung  18.01.95 ESO
1702 |*
1703 *************************************************************************/
1704 
Insert(const XPolyPolygon & rXPolyPoly,sal_uInt16 nPos)1705 void XPolyPolygon::Insert( const XPolyPolygon& rXPolyPoly, sal_uInt16 nPos )
1706 {
1707 	CheckReference();
1708 
1709 	for (sal_uInt16 i = 0; i < rXPolyPoly.Count(); i++)
1710 	{
1711 		XPolygon* pXPoly = new XPolygon(rXPolyPoly[i]);
1712 		pImpXPolyPolygon->aXPolyList.Insert(pXPoly, nPos);
1713 		if ( nPos != XPOLYPOLY_APPEND )
1714 			nPos++;
1715 	}
1716 }
1717 
1718 /*************************************************************************
1719 |*
1720 |*    XPolyPolygon::Remove()
1721 |*
1722 |*    Beschreibung      POLY.SDW
1723 |*    Ersterstellung    CL 27.01.93
1724 |*    Letzte Aenderung  CL 27.01.93
1725 |*
1726 *************************************************************************/
1727 
Remove(sal_uInt16 nPos)1728 XPolygon XPolyPolygon::Remove( sal_uInt16 nPos )
1729 {
1730 	CheckReference();
1731 	XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Remove( nPos );
1732 	XPolygon  aXPoly( *pTmpXPoly );
1733 	delete pTmpXPoly;
1734 	return aXPoly;
1735 }
1736 
1737 
1738 /*************************************************************************
1739 |*
1740 |*    XPolyPolygon::Replace()
1741 |*
1742 |*    Beschreibung      POLY.SDW
1743 |*    Ersterstellung    CL 27.01.93
1744 |*    Letzte Aenderung  CL 27.01.93
1745 |*
1746 *************************************************************************/
1747 
Replace(const XPolygon & rXPoly,sal_uInt16 nPos)1748 XPolygon XPolyPolygon::Replace( const XPolygon& rXPoly, sal_uInt16 nPos )
1749 {
1750 	CheckReference();
1751 	XPolygon* pXPoly = new XPolygon( rXPoly );
1752 	XPolygon* pTmpXPoly = pImpXPolyPolygon->aXPolyList.Replace( pXPoly, nPos );
1753 	XPolygon  aXPoly( *pTmpXPoly );
1754 	delete pTmpXPoly;
1755 	return aXPoly;
1756 }
1757 
1758 
1759 /*************************************************************************
1760 |*
1761 |*    XPolyPolygon::GetObject()
1762 |*
1763 |*    Beschreibung      POLY.SDW
1764 |*    Ersterstellung    CL 27.01.93
1765 |*    Letzte Aenderung  CL 27.01.93
1766 |*
1767 *************************************************************************/
1768 
GetObject(sal_uInt16 nPos) const1769 const XPolygon& XPolyPolygon::GetObject( sal_uInt16 nPos ) const
1770 {
1771 	return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1772 }
1773 
1774 
1775 /*************************************************************************
1776 |*
1777 |*    XPolyPolygon::Clear()
1778 |*
1779 |*    Beschreibung      POLY.SDW
1780 |*    Ersterstellung    CL 27.01.93
1781 |*    Letzte Aenderung  TH 17.10.94
1782 |*
1783 *************************************************************************/
1784 
Clear()1785 void XPolyPolygon::Clear()
1786 {
1787 	if ( pImpXPolyPolygon->nRefCount > 1 )
1788 	{
1789 		pImpXPolyPolygon->nRefCount--;
1790 		pImpXPolyPolygon = new ImpXPolyPolygon();
1791 	}
1792 	else
1793 	{
1794 		XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1795 		while( pXPoly )
1796 		{
1797 			delete pXPoly;
1798 			pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1799 		}
1800 		pImpXPolyPolygon->aXPolyList.Clear();
1801 	}
1802 }
1803 
1804 
1805 /*************************************************************************
1806 |*
1807 |*    XPolyPolygon::Count()
1808 |*
1809 |*    Beschreibung
1810 |*    Ersterstellung    CL 27.01.93
1811 |*    Letzte Aenderung  CL 27.01.93
1812 |*
1813 *************************************************************************/
1814 
Count() const1815 sal_uInt16 XPolyPolygon::Count() const
1816 {
1817 	return (sal_uInt16)(pImpXPolyPolygon->aXPolyList.Count());
1818 }
1819 
1820 
1821 /*************************************************************************
1822 |*
1823 |*    XPolyPolygon::Move()
1824 |*
1825 |*    Beschreibung      POLY.SDW
1826 |*    Ersterstellung    TH 04.10.94
1827 |*    Letzte Aenderung  TH 04.10.94
1828 |*
1829 *************************************************************************/
1830 
Move(long nHorzMove,long nVertMove)1831 void XPolyPolygon::Move( long nHorzMove, long nVertMove )
1832 {
1833 	// Diese Abfrage sollte man fuer die DrawEngine durchfuehren
1834 	if ( !nHorzMove && !nVertMove )
1835 		return;
1836 
1837 	// Referenzcounter beruecksichtigen
1838 	CheckReference();
1839 
1840 	// Punkte verschieben
1841 	XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.First();
1842 	while( pXPoly )
1843 	{
1844 		pXPoly->Move( nHorzMove, nVertMove );
1845 		pXPoly = pImpXPolyPolygon->aXPolyList.Next();
1846 	}
1847 }
1848 
1849 /*************************************************************************
1850 |*
1851 |*    XPolyPolygon::GetBoundRect()
1852 |*
1853 |*    Beschreibung      POLY.SDW
1854 |*    Ersterstellung    TH 04.10.94
1855 |*    Letzte Aenderung  TH 04.10.94
1856 |*
1857 *************************************************************************/
1858 
GetBoundRect() const1859 Rectangle XPolyPolygon::GetBoundRect() const
1860 {
1861 	sal_uInt16    nXPoly = (sal_uInt16)pImpXPolyPolygon->aXPolyList.Count();
1862 	Rectangle aRect;
1863 
1864 	for ( sal_uInt16 n = 0; n < nXPoly; n++ )
1865 	{
1866 		const XPolygon* pXPoly = pImpXPolyPolygon->aXPolyList.GetObject( n );
1867 		aRect.Union( pXPoly->GetBoundRect() );
1868 	}
1869 
1870 	return aRect;
1871 }
1872 
1873 
1874 /*************************************************************************
1875 |*
1876 |*    XPolyPolygon::operator[]()
1877 |*
1878 |*    Beschreibung      POLY.SDW
1879 |*    Ersterstellung    TH 28.10.94
1880 |*    Letzte Aenderung  TH 28.10.94
1881 |*
1882 *************************************************************************/
1883 
operator [](sal_uInt16 nPos)1884 XPolygon& XPolyPolygon::operator[]( sal_uInt16 nPos )
1885 {
1886 	CheckReference();
1887 	return *(pImpXPolyPolygon->aXPolyList.GetObject( nPos ));
1888 }
1889 
1890 /*************************************************************************
1891 |*
1892 |*    XPolyPolygon::operator=()
1893 |*
1894 |*    Beschreibung      POLY.SDW
1895 |*    Ersterstellung    CL 27.01.93
1896 |*    Letzte Aenderung  CL 27.01.93
1897 |*
1898 *************************************************************************/
1899 
operator =(const XPolyPolygon & rXPolyPoly)1900 XPolyPolygon& XPolyPolygon::operator=( const XPolyPolygon& rXPolyPoly )
1901 {
1902 	rXPolyPoly.pImpXPolyPolygon->nRefCount++;
1903 
1904 	if( pImpXPolyPolygon->nRefCount > 1 )
1905 		pImpXPolyPolygon->nRefCount--;
1906 	else
1907 		delete pImpXPolyPolygon;
1908 
1909 	pImpXPolyPolygon = rXPolyPoly.pImpXPolyPolygon;
1910 	return *this;
1911 }
1912 
1913 
1914 /*************************************************************************
1915 |*
1916 |*    XPolyPolygon::operator==()
1917 |*
1918 |*    Beschreibung      POLY.SDW
1919 |*    Ersterstellung    CL  27.01.93
1920 |*    Letzte Aenderung  Joe 27.01.93
1921 |*
1922 *************************************************************************/
1923 
operator ==(const XPolyPolygon & rXPolyPoly) const1924 sal_Bool XPolyPolygon::operator==( const XPolyPolygon& rXPolyPoly ) const
1925 {
1926 	if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_True;
1927 	return *pImpXPolyPolygon == *rXPolyPoly.pImpXPolyPolygon;
1928 }
1929 
1930 
1931 /*************************************************************************
1932 |*
1933 |*    XPolyPolygon::operator!=()
1934 |*
1935 |*    Beschreibung      POLY.SDW
1936 |*    Ersterstellung    CL  27.01.93
1937 |*    Letzte Aenderung  Joe 27.01.93
1938 |*
1939 *************************************************************************/
1940 
operator !=(const XPolyPolygon & rXPolyPoly) const1941 sal_Bool XPolyPolygon::operator!=( const XPolyPolygon& rXPolyPoly ) const
1942 {
1943 	if (pImpXPolyPolygon==rXPolyPoly.pImpXPolyPolygon) return sal_False;
1944 	return *pImpXPolyPolygon != *rXPolyPoly.pImpXPolyPolygon;
1945 }
1946 
1947 /*************************************************************************
1948 |*
1949 |*    XPolyPolygon::Translate()
1950 |*
1951 |*    Alle Polygone auf den uebergebenen Punkt verschieben
1952 |*    Ersterstellung    ESO 25.01.95
1953 |*    Letzte Aenderung  ESO 25.01.95
1954 |*
1955 *************************************************************************/
1956 
Translate(const Point & rTrans)1957 void XPolyPolygon::Translate(const Point& rTrans)
1958 {
1959 	CheckReference();
1960 
1961 	for (sal_uInt16 i = 0; i < Count(); i++)
1962 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Translate(rTrans);
1963 }
1964 
1965 /*************************************************************************
1966 |*
1967 |*    XPolyPolygon::Rotate()
1968 |*
1969 |*    Alle Polygone um den Punkt rCenter drehen, Sinus und Cosinus
1970 |*    muessen uebergeben werden
1971 |*    Ersterstellung    ESO 25.01.95
1972 |*    Letzte Aenderung  ESO 25.01.95
1973 |*
1974 *************************************************************************/
1975 
Rotate(const Point & rCenter,double fSin,double fCos)1976 void XPolyPolygon::Rotate(const Point& rCenter, double fSin, double fCos)
1977 {
1978 	CheckReference();
1979 
1980 	for (sal_uInt16 i = 0; i < Count(); i++)
1981 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate(rCenter, fSin, fCos);
1982 }
1983 
1984 /*************************************************************************
1985 |*
1986 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1987 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1988 |*
1989 \************************************************************************/
1990 
Rotate20()1991 void XPolyPolygon::Rotate20()
1992 {
1993 	CheckReference();
1994 
1995 	for (sal_uInt16 i = 0; i < Count(); i++)
1996 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Rotate20();
1997 }
1998 
1999 /*************************************************************************
2000 |*
2001 |*    XPolyPolygon::Rotate()
2002 |*
2003 |*    Alle Poylgone um den Punkt rCenter mit dem Winkel nAngle drehen
2004 |*    Winkel in 10tel Grad, Wertebereich 0 - 3600
2005 |*    Ersterstellung    ESO 25.01.95
2006 |*    Letzte Aenderung  ESO 25.01.95
2007 |*
2008 *************************************************************************/
2009 
Rotate(const Point & rCenter,sal_uInt16 nAngle)2010 void XPolyPolygon::Rotate(const Point& rCenter, sal_uInt16 nAngle)
2011 {
2012 	nAngle %= 3600;
2013 
2014 	if ( nAngle != 0 )
2015 	{
2016 		double fAngle = F_PI * nAngle / 1800;
2017 		double fSin = sin(fAngle);
2018 		double fCos = cos(fAngle);
2019 		Rotate(rCenter, fSin, fCos);
2020 	}
2021 }
2022 
2023 /*************************************************************************
2024 |*
2025 |*    XPolyPolygon::Scale()
2026 |*
2027 |*    Alle Polygone in X- und/oder Y-Richtung skalieren
2028 |*    Ersterstellung    ESO 01.02.95
2029 |*    Letzte Aenderung  ESO 01.02.95
2030 |*
2031 *************************************************************************/
2032 
Scale(double fSx,double fSy)2033 void XPolyPolygon::Scale(double fSx, double fSy)
2034 {
2035 	CheckReference();
2036 
2037 	for (sal_uInt16 i = 0; i < Count(); i++)
2038 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Scale(fSx, fSy);
2039 }
2040 
2041 /*************************************************************************
2042 |*
2043 |*    XPolyPolygon::SlantX()
2044 |*
2045 |*    Alle Polygone in X-Richtung um einen beliebigen Winkel kippen,
2046 |*    bezogen auf eine Referenz-Y-Koordinate
2047 |*    Ersterstellung    ESO 01.02.95
2048 |*    Letzte Aenderung  ESO 01.02.95
2049 |*
2050 *************************************************************************/
2051 
SlantX(long nYRef,double fSin,double fCos)2052 void XPolyPolygon::SlantX(long nYRef, double fSin, double fCos)
2053 {
2054 	CheckReference();
2055 
2056 	for (sal_uInt16 i = 0; i < Count(); i++)
2057 		pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantX(nYRef, fSin, fCos);
2058 }
2059 
2060 /*************************************************************************
2061 |*
2062 |*    XPolyPolygon::SlantY()
2063 |*
2064 |*    Alle Polygone in Y-Richtung um einen beliebigen Winkel kippen,
2065 |*    bezogen auf eine Referenz-X-Koordinate
2066 |*    Ersterstellung    ESO 01.02.95
2067 |*    Letzte Aenderung  ESO 01.02.95
2068 |*
2069 *************************************************************************/
2070 
SlantY(long nXRef,double fSin,double fCos)2071 void XPolyPolygon::SlantY(long nXRef, double fSin, double fCos)
2072 {
2073 	CheckReference();
2074 
2075 	for (sal_uInt16 i = 0; i < Count(); i++)
2076 		pImpXPolyPolygon->aXPolyList.GetObject(i)->SlantY(nXRef, fSin, fCos);
2077 }
2078 
2079 /*************************************************************************
2080 |*
2081 |*    XPolygon::Distort()
2082 |*
2083 |*    XPolygon verzerren, indem die Koordinaten relativ zu einem
2084 |*    Referenzrechteck in ein beliebiges Viereck skaliert werden
2085 |*    Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
2086 |*    0: links oben      0----1
2087 |*    1: rechts oben     |    |
2088 |*    2: rechts unten    3----2
2089 |*    3: links unten
2090 |*    Ersterstellung    ESO 07.07.95
2091 |*    Letzte Aenderung  ESO 07.07.95
2092 |*
2093 *************************************************************************/
2094 
Distort(const Rectangle & rRefRect,const XPolygon & rDistortedRect)2095 void XPolyPolygon::Distort(const Rectangle& rRefRect,
2096 						   const XPolygon& rDistortedRect)
2097 {
2098 	CheckReference();
2099 
2100 	for (sal_uInt16 i = 0; i < Count(); i++)
2101 		pImpXPolyPolygon->aXPolyList.GetObject(i)->Distort(rRefRect,
2102 														   rDistortedRect);
2103 }
2104 
getB2DPolyPolygon() const2105 basegfx::B2DPolyPolygon XPolyPolygon::getB2DPolyPolygon() const
2106 {
2107 	basegfx::B2DPolyPolygon aRetval;
2108 
2109 	for(sal_uInt16 a(0L); a < Count(); a++)
2110 	{
2111 		const XPolygon& rPoly = (*this)[a];
2112 		aRetval.append(rPoly.getB2DPolygon());
2113 	}
2114 
2115 	return aRetval;
2116 }
2117 
XPolyPolygon(const basegfx::B2DPolyPolygon & rPolyPolygon)2118 XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
2119 {
2120 	DBG_CTOR(XPolyPolygon,NULL);
2121 	pImpXPolyPolygon = new ImpXPolyPolygon( 16, 16 );
2122 
2123 	for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
2124 	{
2125 		basegfx::B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
2126 		XPolygon aNewPoly(aCandidate);
2127 		Insert(aNewPoly);
2128 	}
2129 }
2130 
2131 // eof
2132