1*89b56da7SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*89b56da7SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*89b56da7SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*89b56da7SAndrew Rist * distributed with this work for additional information 6*89b56da7SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*89b56da7SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*89b56da7SAndrew Rist * "License"); you may not use this file except in compliance 9*89b56da7SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*89b56da7SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*89b56da7SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*89b56da7SAndrew Rist * software distributed under the License is distributed on an 15*89b56da7SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*89b56da7SAndrew Rist * KIND, either express or implied. See the License for the 17*89b56da7SAndrew Rist * specific language governing permissions and limitations 18*89b56da7SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*89b56da7SAndrew Rist *************************************************************/ 21*89b56da7SAndrew Rist 22*89b56da7SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_tools.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #define _SV_POLY_CXX 28cdf0e10cSrcweir #include <osl/endian.h> 29cdf0e10cSrcweir #include <tools/bigint.hxx> 30cdf0e10cSrcweir #include <tools/debug.hxx> 31cdf0e10cSrcweir #include <tools/stream.hxx> 32cdf0e10cSrcweir #include <tools/vcompat.hxx> 33cdf0e10cSrcweir #include <poly.h> 34cdf0e10cSrcweir #include <tools/line.hxx> 35cdf0e10cSrcweir #ifndef _VECTOR2D_H 36cdf0e10cSrcweir #include <tools/vector2d.hxx> 37cdf0e10cSrcweir #endif 38cdf0e10cSrcweir #ifndef _POLY_HXX 39cdf0e10cSrcweir #include <tools/poly.hxx> 40cdf0e10cSrcweir #endif 41cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 42cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 43cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx> 44cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 45cdf0e10cSrcweir #include <basegfx/curve/b2dcubicbezier.hxx> 46cdf0e10cSrcweir 47cdf0e10cSrcweir #include <vector> 48cdf0e10cSrcweir #include <iterator> 49cdf0e10cSrcweir #include <algorithm> 50cdf0e10cSrcweir #include <cstring> 51cdf0e10cSrcweir #include <limits.h> 52cdf0e10cSrcweir #include <cmath> 53cdf0e10cSrcweir 54cdf0e10cSrcweir 55cdf0e10cSrcweir // ======================================================================= 56cdf0e10cSrcweir 57cdf0e10cSrcweir DBG_NAME( Polygon ) 58cdf0e10cSrcweir 59cdf0e10cSrcweir // ----------------------------------------------------------------------- 60cdf0e10cSrcweir 61cdf0e10cSrcweir #define EDGE_LEFT 1 62cdf0e10cSrcweir #define EDGE_TOP 2 63cdf0e10cSrcweir #define EDGE_RIGHT 4 64cdf0e10cSrcweir #define EDGE_BOTTOM 8 65cdf0e10cSrcweir #define EDGE_HORZ (EDGE_RIGHT | EDGE_LEFT) 66cdf0e10cSrcweir #define EDGE_VERT (EDGE_TOP | EDGE_BOTTOM) 67cdf0e10cSrcweir #define SMALL_DVALUE 0.0000001 68cdf0e10cSrcweir #define FSQRT2 1.4142135623730950488016887242097 69cdf0e10cSrcweir 70cdf0e10cSrcweir // ----------------------------------------------------------------------- 71cdf0e10cSrcweir 72cdf0e10cSrcweir static ImplPolygonData aStaticImplPolygon = 73cdf0e10cSrcweir { 74cdf0e10cSrcweir NULL, NULL, 0, 0 75cdf0e10cSrcweir }; 76cdf0e10cSrcweir 77cdf0e10cSrcweir // ======================================================================= 78cdf0e10cSrcweir 79cdf0e10cSrcweir ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, sal_Bool bFlags ) 80cdf0e10cSrcweir { 81cdf0e10cSrcweir if ( nInitSize ) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)]; 84cdf0e10cSrcweir memset( mpPointAry, 0, (sal_uIntPtr)nInitSize*sizeof(Point) ); 85cdf0e10cSrcweir } 86cdf0e10cSrcweir else 87cdf0e10cSrcweir mpPointAry = NULL; 88cdf0e10cSrcweir 89cdf0e10cSrcweir if( bFlags ) 90cdf0e10cSrcweir { 91cdf0e10cSrcweir mpFlagAry = new sal_uInt8[ nInitSize ]; 92cdf0e10cSrcweir memset( mpPointAry, 0, nInitSize ); 93cdf0e10cSrcweir } 94cdf0e10cSrcweir else 95cdf0e10cSrcweir mpFlagAry = NULL; 96cdf0e10cSrcweir 97cdf0e10cSrcweir mnRefCount = 1; 98cdf0e10cSrcweir mnPoints = nInitSize; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir // ----------------------------------------------------------------------- 102cdf0e10cSrcweir 103cdf0e10cSrcweir ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly ) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir if ( rImpPoly.mnPoints ) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir mpPointAry = (Point*)new char[(sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point)]; 108cdf0e10cSrcweir memcpy( mpPointAry, rImpPoly.mpPointAry, (sal_uIntPtr)rImpPoly.mnPoints*sizeof(Point) ); 109cdf0e10cSrcweir 110cdf0e10cSrcweir if( rImpPoly.mpFlagAry ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir mpFlagAry = new sal_uInt8[ rImpPoly.mnPoints ]; 113cdf0e10cSrcweir memcpy( mpFlagAry, rImpPoly.mpFlagAry, rImpPoly.mnPoints ); 114cdf0e10cSrcweir } 115cdf0e10cSrcweir else 116cdf0e10cSrcweir mpFlagAry = NULL; 117cdf0e10cSrcweir } 118cdf0e10cSrcweir else 119cdf0e10cSrcweir { 120cdf0e10cSrcweir mpPointAry = NULL; 121cdf0e10cSrcweir mpFlagAry = NULL; 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir mnRefCount = 1; 125cdf0e10cSrcweir mnPoints = rImpPoly.mnPoints; 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 128cdf0e10cSrcweir // ----------------------------------------------------------------------- 129cdf0e10cSrcweir 130cdf0e10cSrcweir ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const sal_uInt8* pInitFlags ) 131cdf0e10cSrcweir { 132cdf0e10cSrcweir if ( nInitSize ) 133cdf0e10cSrcweir { 134cdf0e10cSrcweir mpPointAry = (Point*)new char[(sal_uIntPtr)nInitSize*sizeof(Point)]; 135cdf0e10cSrcweir memcpy( mpPointAry, pInitAry, (sal_uIntPtr)nInitSize*sizeof( Point ) ); 136cdf0e10cSrcweir 137cdf0e10cSrcweir if( pInitFlags ) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir mpFlagAry = new sal_uInt8[ nInitSize ]; 140cdf0e10cSrcweir memcpy( mpFlagAry, pInitFlags, nInitSize ); 141cdf0e10cSrcweir } 142cdf0e10cSrcweir else 143cdf0e10cSrcweir mpFlagAry = NULL; 144cdf0e10cSrcweir } 145cdf0e10cSrcweir else 146cdf0e10cSrcweir { 147cdf0e10cSrcweir mpPointAry = NULL; 148cdf0e10cSrcweir mpFlagAry = NULL; 149cdf0e10cSrcweir } 150cdf0e10cSrcweir 151cdf0e10cSrcweir mnRefCount = 1; 152cdf0e10cSrcweir mnPoints = nInitSize; 153cdf0e10cSrcweir } 154cdf0e10cSrcweir 155cdf0e10cSrcweir // ----------------------------------------------------------------------- 156cdf0e10cSrcweir 157cdf0e10cSrcweir ImplPolygon::~ImplPolygon() 158cdf0e10cSrcweir { 159cdf0e10cSrcweir if ( mpPointAry ) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir delete[] (char*) mpPointAry; 162cdf0e10cSrcweir } 163cdf0e10cSrcweir 164cdf0e10cSrcweir if( mpFlagAry ) 165cdf0e10cSrcweir delete[] mpFlagAry; 166cdf0e10cSrcweir } 167cdf0e10cSrcweir 168cdf0e10cSrcweir // ----------------------------------------------------------------------- 169cdf0e10cSrcweir 170cdf0e10cSrcweir void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, sal_Bool bResize ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir if( mnPoints == nNewSize ) 173cdf0e10cSrcweir return; 174cdf0e10cSrcweir 175cdf0e10cSrcweir Point* pNewAry; 176cdf0e10cSrcweir 177cdf0e10cSrcweir if ( nNewSize ) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir pNewAry = (Point*)new char[(sal_uIntPtr)nNewSize*sizeof(Point)]; 180cdf0e10cSrcweir 181cdf0e10cSrcweir if ( bResize ) 182cdf0e10cSrcweir { 183cdf0e10cSrcweir // Alte Punkte kopieren 184cdf0e10cSrcweir if ( mnPoints < nNewSize ) 185cdf0e10cSrcweir { 186cdf0e10cSrcweir // Neue Punkte mit 0 initialisieren 187cdf0e10cSrcweir memset( pNewAry+mnPoints, 0, (sal_uIntPtr)(nNewSize-mnPoints)*sizeof(Point) ); 188cdf0e10cSrcweir if ( mpPointAry ) 189cdf0e10cSrcweir memcpy( pNewAry, mpPointAry, mnPoints*sizeof(Point) ); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir else 192cdf0e10cSrcweir { 193cdf0e10cSrcweir if ( mpPointAry ) 194cdf0e10cSrcweir memcpy( pNewAry, mpPointAry, (sal_uIntPtr)nNewSize*sizeof(Point) ); 195cdf0e10cSrcweir } 196cdf0e10cSrcweir } 197cdf0e10cSrcweir } 198cdf0e10cSrcweir else 199cdf0e10cSrcweir pNewAry = NULL; 200cdf0e10cSrcweir 201cdf0e10cSrcweir if ( mpPointAry ) 202cdf0e10cSrcweir delete[] (char*) mpPointAry; 203cdf0e10cSrcweir 204cdf0e10cSrcweir // ggf. FlagArray beruecksichtigen 205cdf0e10cSrcweir if( mpFlagAry ) 206cdf0e10cSrcweir { 207cdf0e10cSrcweir sal_uInt8* pNewFlagAry; 208cdf0e10cSrcweir 209cdf0e10cSrcweir if( nNewSize ) 210cdf0e10cSrcweir { 211cdf0e10cSrcweir pNewFlagAry = new sal_uInt8[ nNewSize ]; 212cdf0e10cSrcweir 213cdf0e10cSrcweir if( bResize ) 214cdf0e10cSrcweir { 215cdf0e10cSrcweir // Alte Flags kopieren 216cdf0e10cSrcweir if ( mnPoints < nNewSize ) 217cdf0e10cSrcweir { 218cdf0e10cSrcweir // Neue Punkte mit 0 initialisieren 219cdf0e10cSrcweir memset( pNewFlagAry+mnPoints, 0, nNewSize-mnPoints ); 220cdf0e10cSrcweir memcpy( pNewFlagAry, mpFlagAry, mnPoints ); 221cdf0e10cSrcweir } 222cdf0e10cSrcweir else 223cdf0e10cSrcweir memcpy( pNewFlagAry, mpFlagAry, nNewSize ); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir } 226cdf0e10cSrcweir else 227cdf0e10cSrcweir pNewFlagAry = NULL; 228cdf0e10cSrcweir 229cdf0e10cSrcweir delete[] mpFlagAry; 230cdf0e10cSrcweir mpFlagAry = pNewFlagAry; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir mpPointAry = pNewAry; 234cdf0e10cSrcweir mnPoints = nNewSize; 235cdf0e10cSrcweir } 236cdf0e10cSrcweir 237cdf0e10cSrcweir // ----------------------------------------------------------------------- 238cdf0e10cSrcweir 239cdf0e10cSrcweir void ImplPolygon::ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon* pInitPoly ) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir const sal_uIntPtr nSpaceSize = nSpace * sizeof( Point ); 242cdf0e10cSrcweir 243cdf0e10cSrcweir //Can't fit this in :-(, throw ? 244cdf0e10cSrcweir if (mnPoints + nSpace > USHRT_MAX) 245cdf0e10cSrcweir return; 246cdf0e10cSrcweir 247cdf0e10cSrcweir const sal_uInt16 nNewSize = mnPoints + nSpace; 248cdf0e10cSrcweir 249cdf0e10cSrcweir if( nPos >= mnPoints ) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir // Hinten anhaengen 252cdf0e10cSrcweir nPos = mnPoints; 253cdf0e10cSrcweir ImplSetSize( nNewSize, sal_True ); 254cdf0e10cSrcweir 255cdf0e10cSrcweir if( pInitPoly ) 256cdf0e10cSrcweir { 257cdf0e10cSrcweir memcpy( mpPointAry + nPos, pInitPoly->mpPointAry, nSpaceSize ); 258cdf0e10cSrcweir 259cdf0e10cSrcweir if( pInitPoly->mpFlagAry ) 260cdf0e10cSrcweir memcpy( mpFlagAry + nPos, pInitPoly->mpFlagAry, nSpace ); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir } 263cdf0e10cSrcweir else 264cdf0e10cSrcweir { 265cdf0e10cSrcweir // PointArray ist in diesem Zweig immer vorhanden 266cdf0e10cSrcweir const sal_uInt16 nSecPos = nPos + nSpace; 267cdf0e10cSrcweir const sal_uInt16 nRest = mnPoints - nPos; 268cdf0e10cSrcweir 269cdf0e10cSrcweir Point* pNewAry = (Point*) new char[ (sal_uIntPtr) nNewSize * sizeof( Point ) ]; 270cdf0e10cSrcweir 271cdf0e10cSrcweir memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) ); 272cdf0e10cSrcweir 273cdf0e10cSrcweir if( pInitPoly ) 274cdf0e10cSrcweir memcpy( pNewAry + nPos, pInitPoly->mpPointAry, nSpaceSize ); 275cdf0e10cSrcweir else 276cdf0e10cSrcweir memset( pNewAry + nPos, 0, nSpaceSize ); 277cdf0e10cSrcweir 278cdf0e10cSrcweir memcpy( pNewAry + nSecPos, mpPointAry + nPos, nRest * sizeof( Point ) ); 279cdf0e10cSrcweir delete[] (char*) mpPointAry; 280cdf0e10cSrcweir 281cdf0e10cSrcweir // ggf. FlagArray beruecksichtigen 282cdf0e10cSrcweir if( mpFlagAry ) 283cdf0e10cSrcweir { 284cdf0e10cSrcweir sal_uInt8* pNewFlagAry = new sal_uInt8[ nNewSize ]; 285cdf0e10cSrcweir 286cdf0e10cSrcweir memcpy( pNewFlagAry, mpFlagAry, nPos ); 287cdf0e10cSrcweir 288cdf0e10cSrcweir if( pInitPoly && pInitPoly->mpFlagAry ) 289cdf0e10cSrcweir memcpy( pNewFlagAry + nPos, pInitPoly->mpFlagAry, nSpace ); 290cdf0e10cSrcweir else 291cdf0e10cSrcweir memset( pNewFlagAry + nPos, 0, nSpace ); 292cdf0e10cSrcweir 293cdf0e10cSrcweir memcpy( pNewFlagAry + nSecPos, mpFlagAry + nPos, nRest ); 294cdf0e10cSrcweir delete[] mpFlagAry; 295cdf0e10cSrcweir mpFlagAry = pNewFlagAry; 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298cdf0e10cSrcweir mpPointAry = pNewAry; 299cdf0e10cSrcweir mnPoints = nNewSize; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir } 302cdf0e10cSrcweir 303cdf0e10cSrcweir // ----------------------------------------------------------------------- 304cdf0e10cSrcweir 305cdf0e10cSrcweir void ImplPolygon::ImplRemove( sal_uInt16 nPos, sal_uInt16 nCount ) 306cdf0e10cSrcweir { 307cdf0e10cSrcweir const sal_uInt16 nRemoveCount = Min( (sal_uInt16) ( mnPoints - nPos ), (sal_uInt16) nCount ); 308cdf0e10cSrcweir 309cdf0e10cSrcweir if( nRemoveCount ) 310cdf0e10cSrcweir { 311cdf0e10cSrcweir const sal_uInt16 nNewSize = mnPoints - nRemoveCount; 312cdf0e10cSrcweir const sal_uInt16 nSecPos = nPos + nRemoveCount; 313cdf0e10cSrcweir const sal_uInt16 nRest = mnPoints - nSecPos; 314cdf0e10cSrcweir 315cdf0e10cSrcweir Point* pNewAry = (Point*) new char[ (sal_uIntPtr) nNewSize * sizeof( Point ) ]; 316cdf0e10cSrcweir 317cdf0e10cSrcweir memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) ); 318cdf0e10cSrcweir memcpy( pNewAry + nPos, mpPointAry + nSecPos, nRest * sizeof( Point ) ); 319cdf0e10cSrcweir 320cdf0e10cSrcweir delete[] (char*) mpPointAry; 321cdf0e10cSrcweir 322cdf0e10cSrcweir // ggf. FlagArray beruecksichtigen 323cdf0e10cSrcweir if( mpFlagAry ) 324cdf0e10cSrcweir { 325cdf0e10cSrcweir sal_uInt8* pNewFlagAry = new sal_uInt8[ nNewSize ]; 326cdf0e10cSrcweir 327cdf0e10cSrcweir memcpy( pNewFlagAry, mpFlagAry, nPos ); 328cdf0e10cSrcweir memcpy( pNewFlagAry + nPos, mpFlagAry + nSecPos, nRest ); 329cdf0e10cSrcweir delete[] mpFlagAry; 330cdf0e10cSrcweir mpFlagAry = pNewFlagAry; 331cdf0e10cSrcweir } 332cdf0e10cSrcweir 333cdf0e10cSrcweir mpPointAry = pNewAry; 334cdf0e10cSrcweir mnPoints = nNewSize; 335cdf0e10cSrcweir } 336cdf0e10cSrcweir } 337cdf0e10cSrcweir 338cdf0e10cSrcweir // ----------------------------------------------------------------------- 339cdf0e10cSrcweir 340cdf0e10cSrcweir void ImplPolygon::ImplCreateFlagArray() 341cdf0e10cSrcweir { 342cdf0e10cSrcweir if( !mpFlagAry ) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir mpFlagAry = new sal_uInt8[ mnPoints ]; 345cdf0e10cSrcweir memset( mpFlagAry, 0, mnPoints ); 346cdf0e10cSrcweir } 347cdf0e10cSrcweir } 348cdf0e10cSrcweir 349cdf0e10cSrcweir // ======================================================================= 350cdf0e10cSrcweir 351cdf0e10cSrcweir inline void Polygon::ImplMakeUnique() 352cdf0e10cSrcweir { 353cdf0e10cSrcweir // Falls noch andere Referenzen bestehen, dann kopieren 354cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount != 1 ) 355cdf0e10cSrcweir { 356cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 357cdf0e10cSrcweir mpImplPolygon->mnRefCount--; 358cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( *mpImplPolygon ); 359cdf0e10cSrcweir } 360cdf0e10cSrcweir } 361cdf0e10cSrcweir 362cdf0e10cSrcweir // ----------------------------------------------------------------------- 363cdf0e10cSrcweir 364cdf0e10cSrcweir inline double ImplGetAngle( const Point& rCenter, const Point& rPt ) 365cdf0e10cSrcweir { 366cdf0e10cSrcweir const long nDX = rPt.X() - rCenter.X(); 367cdf0e10cSrcweir return( atan2( -rPt.Y() + rCenter.Y(), ( ( nDX == 0L ) ? 0.000000001 : nDX ) ) ); 368cdf0e10cSrcweir } 369cdf0e10cSrcweir 370cdf0e10cSrcweir // ----------------------------------------------------------------------- 371cdf0e10cSrcweir 372cdf0e10cSrcweir Polygon::Polygon() 373cdf0e10cSrcweir { 374cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 375cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 376cdf0e10cSrcweir } 377cdf0e10cSrcweir 378cdf0e10cSrcweir // ----------------------------------------------------------------------- 379cdf0e10cSrcweir 380cdf0e10cSrcweir Polygon::Polygon( sal_uInt16 nSize ) 381cdf0e10cSrcweir { 382cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 383cdf0e10cSrcweir 384cdf0e10cSrcweir if ( nSize ) 385cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( nSize ); 386cdf0e10cSrcweir else 387cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 388cdf0e10cSrcweir } 389cdf0e10cSrcweir 390cdf0e10cSrcweir // ----------------------------------------------------------------------- 391cdf0e10cSrcweir 392cdf0e10cSrcweir Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const sal_uInt8* pFlagAry ) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 395cdf0e10cSrcweir 396cdf0e10cSrcweir if( nPoints ) 397cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( nPoints, pPtAry, pFlagAry ); 398cdf0e10cSrcweir else 399cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 400cdf0e10cSrcweir } 401cdf0e10cSrcweir 402cdf0e10cSrcweir // ----------------------------------------------------------------------- 403cdf0e10cSrcweir 404cdf0e10cSrcweir Polygon::Polygon( const Polygon& rPoly ) 405cdf0e10cSrcweir { 406cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 407cdf0e10cSrcweir DBG_CHKOBJ( &rPoly, Polygon, NULL ); 408cdf0e10cSrcweir DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" ); 409cdf0e10cSrcweir 410cdf0e10cSrcweir mpImplPolygon = rPoly.mpImplPolygon; 411cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 412cdf0e10cSrcweir mpImplPolygon->mnRefCount++; 413cdf0e10cSrcweir } 414cdf0e10cSrcweir 415cdf0e10cSrcweir // ----------------------------------------------------------------------- 416cdf0e10cSrcweir 417cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rRect ) 418cdf0e10cSrcweir { 419cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 420cdf0e10cSrcweir 421cdf0e10cSrcweir if ( rRect.IsEmpty() ) 422cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 423cdf0e10cSrcweir else 424cdf0e10cSrcweir { 425cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( 5 ); 426cdf0e10cSrcweir mpImplPolygon->mpPointAry[0] = rRect.TopLeft(); 427cdf0e10cSrcweir mpImplPolygon->mpPointAry[1] = rRect.TopRight(); 428cdf0e10cSrcweir mpImplPolygon->mpPointAry[2] = rRect.BottomRight(); 429cdf0e10cSrcweir mpImplPolygon->mpPointAry[3] = rRect.BottomLeft(); 430cdf0e10cSrcweir mpImplPolygon->mpPointAry[4] = rRect.TopLeft(); 431cdf0e10cSrcweir } 432cdf0e10cSrcweir } 433cdf0e10cSrcweir 434cdf0e10cSrcweir // ----------------------------------------------------------------------- 435cdf0e10cSrcweir 436cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rRect, sal_uIntPtr nHorzRound, sal_uIntPtr nVertRound ) 437cdf0e10cSrcweir { 438cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 439cdf0e10cSrcweir 440cdf0e10cSrcweir if ( rRect.IsEmpty() ) 441cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 442cdf0e10cSrcweir else 443cdf0e10cSrcweir { 444cdf0e10cSrcweir Rectangle aRect( rRect ); 445cdf0e10cSrcweir aRect.Justify(); // SJ: i9140 446cdf0e10cSrcweir 447cdf0e10cSrcweir nHorzRound = Min( nHorzRound, (sal_uIntPtr) labs( aRect.GetWidth() >> 1 ) ); 448cdf0e10cSrcweir nVertRound = Min( nVertRound, (sal_uIntPtr) labs( aRect.GetHeight() >> 1 ) ); 449cdf0e10cSrcweir 450cdf0e10cSrcweir if( !nHorzRound && !nVertRound ) 451cdf0e10cSrcweir { 452cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( 5 ); 453cdf0e10cSrcweir mpImplPolygon->mpPointAry[0] = aRect.TopLeft(); 454cdf0e10cSrcweir mpImplPolygon->mpPointAry[1] = aRect.TopRight(); 455cdf0e10cSrcweir mpImplPolygon->mpPointAry[2] = aRect.BottomRight(); 456cdf0e10cSrcweir mpImplPolygon->mpPointAry[3] = aRect.BottomLeft(); 457cdf0e10cSrcweir mpImplPolygon->mpPointAry[4] = aRect.TopLeft(); 458cdf0e10cSrcweir } 459cdf0e10cSrcweir else 460cdf0e10cSrcweir { 461cdf0e10cSrcweir const Point aTL( aRect.Left() + nHorzRound, aRect.Top() + nVertRound ); 462cdf0e10cSrcweir const Point aTR( aRect.Right() - nHorzRound, aRect.Top() + nVertRound ); 463cdf0e10cSrcweir const Point aBR( aRect.Right() - nHorzRound, aRect.Bottom() - nVertRound ); 464cdf0e10cSrcweir const Point aBL( aRect.Left() + nHorzRound, aRect.Bottom() - nVertRound ); 465cdf0e10cSrcweir Polygon* pEllipsePoly = new Polygon( Point(), nHorzRound, nVertRound ); 466cdf0e10cSrcweir sal_uInt16 i, nEnd, nSize4 = pEllipsePoly->GetSize() >> 2; 467cdf0e10cSrcweir 468cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( pEllipsePoly->GetSize() + 1 ); 469cdf0e10cSrcweir 470cdf0e10cSrcweir const Point* pSrcAry = pEllipsePoly->GetConstPointAry(); 471cdf0e10cSrcweir Point* pDstAry = mpImplPolygon->mpPointAry; 472cdf0e10cSrcweir 473cdf0e10cSrcweir for( i = 0, nEnd = nSize4; i < nEnd; i++ ) 474cdf0e10cSrcweir ( pDstAry[ i ] = pSrcAry[ i ] ) += aTR; 475cdf0e10cSrcweir 476cdf0e10cSrcweir for( nEnd = nEnd + nSize4; i < nEnd; i++ ) 477cdf0e10cSrcweir ( pDstAry[ i ] = pSrcAry[ i ] ) += aTL; 478cdf0e10cSrcweir 479cdf0e10cSrcweir for( nEnd = nEnd + nSize4; i < nEnd; i++ ) 480cdf0e10cSrcweir ( pDstAry[ i ] = pSrcAry[ i ] ) += aBL; 481cdf0e10cSrcweir 482cdf0e10cSrcweir for( nEnd = nEnd + nSize4; i < nEnd; i++ ) 483cdf0e10cSrcweir ( pDstAry[ i ] = pSrcAry[ i ] ) += aBR; 484cdf0e10cSrcweir 485cdf0e10cSrcweir pDstAry[ nEnd ] = pDstAry[ 0 ]; 486cdf0e10cSrcweir delete pEllipsePoly; 487cdf0e10cSrcweir } 488cdf0e10cSrcweir } 489cdf0e10cSrcweir } 490cdf0e10cSrcweir 491cdf0e10cSrcweir // ----------------------------------------------------------------------- 492cdf0e10cSrcweir 493cdf0e10cSrcweir Polygon::Polygon( const Point& rCenter, long nRadX, long nRadY, sal_uInt16 nPoints ) 494cdf0e10cSrcweir { 495cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 496cdf0e10cSrcweir 497cdf0e10cSrcweir if( nRadX && nRadY ) 498cdf0e10cSrcweir { 499cdf0e10cSrcweir // Default berechnen (abhaengig von Groesse) 500cdf0e10cSrcweir if( !nPoints ) 501cdf0e10cSrcweir { 502cdf0e10cSrcweir nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) - 503cdf0e10cSrcweir sqrt( (double) labs( nRadX * nRadY ) ) ) ); 504cdf0e10cSrcweir 505cdf0e10cSrcweir nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 ); 506cdf0e10cSrcweir 507cdf0e10cSrcweir if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 ) 508cdf0e10cSrcweir nPoints >>= 1; 509cdf0e10cSrcweir } 510cdf0e10cSrcweir 511cdf0e10cSrcweir // Anzahl der Punkte auf durch 4 teilbare Zahl aufrunden 512cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( nPoints = (nPoints + 3) & ~3 ); 513cdf0e10cSrcweir 514cdf0e10cSrcweir Point* pPt; 515cdf0e10cSrcweir sal_uInt16 i; 516cdf0e10cSrcweir sal_uInt16 nPoints2 = nPoints >> 1; 517cdf0e10cSrcweir sal_uInt16 nPoints4 = nPoints >> 2; 518cdf0e10cSrcweir double nAngle; 519cdf0e10cSrcweir double nAngleStep = F_PI2 / ( nPoints4 - 1 ); 520cdf0e10cSrcweir 521cdf0e10cSrcweir for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep ) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir long nX = FRound( nRadX * cos( nAngle ) ); 524cdf0e10cSrcweir long nY = FRound( -nRadY * sin( nAngle ) ); 525cdf0e10cSrcweir 526cdf0e10cSrcweir pPt = &(mpImplPolygon->mpPointAry[i]); 527cdf0e10cSrcweir pPt->X() = nX + rCenter.X(); 528cdf0e10cSrcweir pPt->Y() = nY + rCenter.Y(); 529cdf0e10cSrcweir pPt = &(mpImplPolygon->mpPointAry[nPoints2-i-1]); 530cdf0e10cSrcweir pPt->X() = -nX + rCenter.X(); 531cdf0e10cSrcweir pPt->Y() = nY + rCenter.Y(); 532cdf0e10cSrcweir pPt = &(mpImplPolygon->mpPointAry[i+nPoints2]); 533cdf0e10cSrcweir pPt->X() = -nX + rCenter.X(); 534cdf0e10cSrcweir pPt->Y() = -nY + rCenter.Y(); 535cdf0e10cSrcweir pPt = &(mpImplPolygon->mpPointAry[nPoints-i-1]); 536cdf0e10cSrcweir pPt->X() = nX + rCenter.X(); 537cdf0e10cSrcweir pPt->Y() = -nY + rCenter.Y(); 538cdf0e10cSrcweir } 539cdf0e10cSrcweir } 540cdf0e10cSrcweir else 541cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 542cdf0e10cSrcweir } 543cdf0e10cSrcweir 544cdf0e10cSrcweir // ----------------------------------------------------------------------- 545cdf0e10cSrcweir 546cdf0e10cSrcweir Polygon::Polygon( const Rectangle& rBound, 547cdf0e10cSrcweir const Point& rStart, const Point& rEnd, PolyStyle eStyle ) 548cdf0e10cSrcweir { 549cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 550cdf0e10cSrcweir 551cdf0e10cSrcweir const long nWidth = rBound.GetWidth(); 552cdf0e10cSrcweir const long nHeight = rBound.GetHeight(); 553cdf0e10cSrcweir 554cdf0e10cSrcweir if( ( nWidth > 1 ) && ( nHeight > 1 ) ) 555cdf0e10cSrcweir { 556cdf0e10cSrcweir const Point aCenter( rBound.Center() ); 557cdf0e10cSrcweir const long nRadX = aCenter.X() - rBound.Left(); 558cdf0e10cSrcweir const long nRadY = aCenter.Y() - rBound.Top(); 559cdf0e10cSrcweir sal_uInt16 nPoints; 560cdf0e10cSrcweir 561cdf0e10cSrcweir nPoints = (sal_uInt16) ( F_PI * ( 1.5 * ( nRadX + nRadY ) - 562cdf0e10cSrcweir sqrt( (double) labs( nRadX * nRadY ) ) ) ); 563cdf0e10cSrcweir 564cdf0e10cSrcweir nPoints = (sal_uInt16) MinMax( nPoints, 32, 256 ); 565cdf0e10cSrcweir 566cdf0e10cSrcweir if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 ) 567cdf0e10cSrcweir nPoints >>= 1; 568cdf0e10cSrcweir 569cdf0e10cSrcweir // Winkel berechnen 570cdf0e10cSrcweir const double fRadX = nRadX; 571cdf0e10cSrcweir const double fRadY = nRadY; 572cdf0e10cSrcweir const double fCenterX = aCenter.X(); 573cdf0e10cSrcweir const double fCenterY = aCenter.Y(); 574cdf0e10cSrcweir double fStart = ImplGetAngle( aCenter, rStart ); 575cdf0e10cSrcweir double fEnd = ImplGetAngle( aCenter, rEnd ); 576cdf0e10cSrcweir double fDiff = fEnd - fStart; 577cdf0e10cSrcweir double fStep; 578cdf0e10cSrcweir sal_uInt16 nStart; 579cdf0e10cSrcweir sal_uInt16 nEnd; 580cdf0e10cSrcweir 581cdf0e10cSrcweir if( fDiff < 0. ) 582cdf0e10cSrcweir fDiff += F_2PI; 583cdf0e10cSrcweir 584cdf0e10cSrcweir // Punktanzahl proportional verkleinern ( fDiff / (2PI) ); 585cdf0e10cSrcweir // ist eingentlich nur fuer einen Kreis richtig; wir 586cdf0e10cSrcweir // machen es hier aber trotzdem 587cdf0e10cSrcweir nPoints = Max( (sal_uInt16) ( ( fDiff * 0.1591549 ) * nPoints ), (sal_uInt16) 16 ); 588cdf0e10cSrcweir fStep = fDiff / ( nPoints - 1 ); 589cdf0e10cSrcweir 590cdf0e10cSrcweir if( POLY_PIE == eStyle ) 591cdf0e10cSrcweir { 592cdf0e10cSrcweir const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) ); 593cdf0e10cSrcweir 594cdf0e10cSrcweir nStart = 1; 595cdf0e10cSrcweir nEnd = nPoints + 1; 596cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( nPoints + 2 ); 597cdf0e10cSrcweir mpImplPolygon->mpPointAry[ 0 ] = aCenter2; 598cdf0e10cSrcweir mpImplPolygon->mpPointAry[ nEnd ] = aCenter2; 599cdf0e10cSrcweir } 600cdf0e10cSrcweir else 601cdf0e10cSrcweir { 602cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( ( POLY_CHORD == eStyle ) ? ( nPoints + 1 ) : nPoints ); 603cdf0e10cSrcweir nStart = 0; 604cdf0e10cSrcweir nEnd = nPoints; 605cdf0e10cSrcweir } 606cdf0e10cSrcweir 607cdf0e10cSrcweir for(; nStart < nEnd; nStart++, fStart += fStep ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir Point& rPt = mpImplPolygon->mpPointAry[ nStart ]; 610cdf0e10cSrcweir 611cdf0e10cSrcweir rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) ); 612cdf0e10cSrcweir rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) ); 613cdf0e10cSrcweir } 614cdf0e10cSrcweir 615cdf0e10cSrcweir if( POLY_CHORD == eStyle ) 616cdf0e10cSrcweir mpImplPolygon->mpPointAry[ nPoints ] = mpImplPolygon->mpPointAry[ 0 ]; 617cdf0e10cSrcweir } 618cdf0e10cSrcweir else 619cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*) &aStaticImplPolygon; 620cdf0e10cSrcweir } 621cdf0e10cSrcweir 622cdf0e10cSrcweir // ----------------------------------------------------------------------- 623cdf0e10cSrcweir 624cdf0e10cSrcweir Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1, 625cdf0e10cSrcweir const Point& rBezPt2, const Point& rCtrlPt2, 626cdf0e10cSrcweir sal_uInt16 nPoints ) 627cdf0e10cSrcweir { 628cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 629cdf0e10cSrcweir 630cdf0e10cSrcweir nPoints = ( 0 == nPoints ) ? 25 : ( ( nPoints < 2 ) ? 2 : nPoints ); 631cdf0e10cSrcweir 632cdf0e10cSrcweir const double fInc = 1.0 / ( nPoints - 1 ); 633cdf0e10cSrcweir double fK_1 = 0.0, fK1_1 = 1.0; 634cdf0e10cSrcweir double fK_2, fK_3, fK1_2, fK1_3, fK12, fK21; 635cdf0e10cSrcweir const double fX0 = rBezPt1.X(); 636cdf0e10cSrcweir const double fY0 = rBezPt1.Y(); 637cdf0e10cSrcweir const double fX1 = 3.0 * rCtrlPt1.X(); 638cdf0e10cSrcweir const double fY1 = 3.0 * rCtrlPt1.Y(); 639cdf0e10cSrcweir const double fX2 = 3.0 * rCtrlPt2.X();; 640cdf0e10cSrcweir const double fY2 = 3.0 * rCtrlPt2.Y();; 641cdf0e10cSrcweir const double fX3 = rBezPt2.X(); 642cdf0e10cSrcweir const double fY3 = rBezPt2.Y(); 643cdf0e10cSrcweir 644cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( nPoints ); 645cdf0e10cSrcweir 646cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc ) 647cdf0e10cSrcweir { 648cdf0e10cSrcweir Point& rPt = mpImplPolygon->mpPointAry[ i ]; 649cdf0e10cSrcweir 650cdf0e10cSrcweir fK_2 = fK_1, fK_3 = ( fK_2 *= fK_1 ), fK_3 *= fK_1; 651cdf0e10cSrcweir fK1_2 = fK1_1, fK1_3 = ( fK1_2 *= fK1_1 ), fK1_3 *= fK1_1; 652cdf0e10cSrcweir fK12 = fK_1 * fK1_2, fK21 = fK_2 * fK1_1; 653cdf0e10cSrcweir 654cdf0e10cSrcweir rPt.X() = FRound( fK1_3 * fX0 + fK12 * fX1 + fK21 * fX2 + fK_3 * fX3 ); 655cdf0e10cSrcweir rPt.Y() = FRound( fK1_3 * fY0 + fK12 * fY1 + fK21 * fY2 + fK_3 * fY3 ); 656cdf0e10cSrcweir } 657cdf0e10cSrcweir } 658cdf0e10cSrcweir 659cdf0e10cSrcweir // ----------------------------------------------------------------------- 660cdf0e10cSrcweir 661cdf0e10cSrcweir Polygon::~Polygon() 662cdf0e10cSrcweir { 663cdf0e10cSrcweir DBG_DTOR( Polygon, NULL ); 664cdf0e10cSrcweir 665cdf0e10cSrcweir // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es 666cdf0e10cSrcweir // die letzte Referenz ist, sonst Referenzcounter decrementieren 667cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 668cdf0e10cSrcweir { 669cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount > 1 ) 670cdf0e10cSrcweir mpImplPolygon->mnRefCount--; 671cdf0e10cSrcweir else 672cdf0e10cSrcweir delete mpImplPolygon; 673cdf0e10cSrcweir } 674cdf0e10cSrcweir } 675cdf0e10cSrcweir 676cdf0e10cSrcweir // ----------------------------------------------------------------------- 677cdf0e10cSrcweir 678cdf0e10cSrcweir Point* Polygon::ImplGetPointAry() 679cdf0e10cSrcweir { 680cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 681cdf0e10cSrcweir 682cdf0e10cSrcweir ImplMakeUnique(); 683cdf0e10cSrcweir return (Point*)mpImplPolygon->mpPointAry; 684cdf0e10cSrcweir } 685cdf0e10cSrcweir 686cdf0e10cSrcweir // ----------------------------------------------------------------------- 687cdf0e10cSrcweir 688cdf0e10cSrcweir sal_uInt8* Polygon::ImplGetFlagAry() 689cdf0e10cSrcweir { 690cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 691cdf0e10cSrcweir 692cdf0e10cSrcweir ImplMakeUnique(); 693cdf0e10cSrcweir mpImplPolygon->ImplCreateFlagArray(); 694cdf0e10cSrcweir return mpImplPolygon->mpFlagAry; 695cdf0e10cSrcweir } 696cdf0e10cSrcweir 697cdf0e10cSrcweir // ----------------------------------------------------------------------- 698cdf0e10cSrcweir 699cdf0e10cSrcweir const Point* Polygon::GetConstPointAry() const 700cdf0e10cSrcweir { 701cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 702cdf0e10cSrcweir return (Point*)mpImplPolygon->mpPointAry; 703cdf0e10cSrcweir } 704cdf0e10cSrcweir 705cdf0e10cSrcweir // ----------------------------------------------------------------------- 706cdf0e10cSrcweir 707cdf0e10cSrcweir const sal_uInt8* Polygon::GetConstFlagAry() const 708cdf0e10cSrcweir { 709cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 710cdf0e10cSrcweir return mpImplPolygon->mpFlagAry; 711cdf0e10cSrcweir } 712cdf0e10cSrcweir 713cdf0e10cSrcweir // ----------------------------------------------------------------------- 714cdf0e10cSrcweir 715cdf0e10cSrcweir void Polygon::SetPoint( const Point& rPt, sal_uInt16 nPos ) 716cdf0e10cSrcweir { 717cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 718cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 719cdf0e10cSrcweir "Polygon::SetPoint(): nPos >= nPoints" ); 720cdf0e10cSrcweir 721cdf0e10cSrcweir ImplMakeUnique(); 722cdf0e10cSrcweir mpImplPolygon->mpPointAry[nPos] = rPt; 723cdf0e10cSrcweir } 724cdf0e10cSrcweir 725cdf0e10cSrcweir // ----------------------------------------------------------------------- 726cdf0e10cSrcweir 727cdf0e10cSrcweir void Polygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags ) 728cdf0e10cSrcweir { 729cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 730cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 731cdf0e10cSrcweir "Polygon::SetFlags(): nPos >= nPoints" ); 732cdf0e10cSrcweir 733cdf0e10cSrcweir // we do only want to create the flag array if there 734cdf0e10cSrcweir // is at least one flag different to POLY_NORMAL 735cdf0e10cSrcweir if ( mpImplPolygon || ( eFlags != POLY_NORMAL ) ) 736cdf0e10cSrcweir { 737cdf0e10cSrcweir ImplMakeUnique(); 738cdf0e10cSrcweir mpImplPolygon->ImplCreateFlagArray(); 739cdf0e10cSrcweir mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags; 740cdf0e10cSrcweir } 741cdf0e10cSrcweir } 742cdf0e10cSrcweir 743cdf0e10cSrcweir // ----------------------------------------------------------------------- 744cdf0e10cSrcweir 745cdf0e10cSrcweir const Point& Polygon::GetPoint( sal_uInt16 nPos ) const 746cdf0e10cSrcweir { 747cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 748cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 749cdf0e10cSrcweir "Polygon::GetPoint(): nPos >= nPoints" ); 750cdf0e10cSrcweir 751cdf0e10cSrcweir return mpImplPolygon->mpPointAry[nPos]; 752cdf0e10cSrcweir } 753cdf0e10cSrcweir 754cdf0e10cSrcweir // ----------------------------------------------------------------------- 755cdf0e10cSrcweir 756cdf0e10cSrcweir PolyFlags Polygon::GetFlags( sal_uInt16 nPos ) const 757cdf0e10cSrcweir { 758cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 759cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 760cdf0e10cSrcweir "Polygon::GetFlags(): nPos >= nPoints" ); 761cdf0e10cSrcweir return( mpImplPolygon->mpFlagAry ? 762cdf0e10cSrcweir (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] : 763cdf0e10cSrcweir POLY_NORMAL ); 764cdf0e10cSrcweir } 765cdf0e10cSrcweir 766cdf0e10cSrcweir // ----------------------------------------------------------------------- 767cdf0e10cSrcweir 768cdf0e10cSrcweir sal_Bool Polygon::HasFlags() const 769cdf0e10cSrcweir { 770cdf0e10cSrcweir return mpImplPolygon->mpFlagAry != NULL; 771cdf0e10cSrcweir } 772cdf0e10cSrcweir 773cdf0e10cSrcweir // ----------------------------------------------------------------------- 774cdf0e10cSrcweir 775cdf0e10cSrcweir sal_Bool Polygon::IsControl(sal_uInt16 nPos) const 776cdf0e10cSrcweir { 777cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 778cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 779cdf0e10cSrcweir "Polygon::GetFlags(): nPos >= nPoints" ); 780cdf0e10cSrcweir PolyFlags eFlags = mpImplPolygon->mpFlagAry ? 781cdf0e10cSrcweir (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] : POLY_NORMAL; 782cdf0e10cSrcweir 783cdf0e10cSrcweir return( POLY_CONTROL == eFlags ); 784cdf0e10cSrcweir } 785cdf0e10cSrcweir 786cdf0e10cSrcweir // ----------------------------------------------------------------------- 787cdf0e10cSrcweir 788cdf0e10cSrcweir sal_Bool Polygon::IsSmooth(sal_uInt16 nPos) const 789cdf0e10cSrcweir { 790cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 791cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, 792cdf0e10cSrcweir "Polygon::GetFlags(): nPos >= nPoints" ); 793cdf0e10cSrcweir PolyFlags eFlags = mpImplPolygon->mpFlagAry ? 794cdf0e10cSrcweir (PolyFlags) mpImplPolygon->mpFlagAry[ nPos ] : POLY_NORMAL; 795cdf0e10cSrcweir 796cdf0e10cSrcweir return( ( POLY_SMOOTH == eFlags ) || ( POLY_SYMMTR == eFlags ) ); 797cdf0e10cSrcweir } 798cdf0e10cSrcweir 799cdf0e10cSrcweir // ----------------------------------------------------------------------- 800cdf0e10cSrcweir 801cdf0e10cSrcweir sal_Bool Polygon::IsRect() const 802cdf0e10cSrcweir { 803cdf0e10cSrcweir sal_Bool bIsRect = sal_False; 804cdf0e10cSrcweir if ( mpImplPolygon->mpFlagAry == NULL ) 805cdf0e10cSrcweir { 806cdf0e10cSrcweir if ( ( ( mpImplPolygon->mnPoints == 5 ) && ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ 4 ] ) ) || 807cdf0e10cSrcweir ( mpImplPolygon->mnPoints == 4 ) ) 808cdf0e10cSrcweir { 809cdf0e10cSrcweir if ( ( mpImplPolygon->mpPointAry[ 0 ].X() == mpImplPolygon->mpPointAry[ 3 ].X() ) && 810cdf0e10cSrcweir ( mpImplPolygon->mpPointAry[ 0 ].Y() == mpImplPolygon->mpPointAry[ 1 ].Y() ) && 811cdf0e10cSrcweir ( mpImplPolygon->mpPointAry[ 1 ].X() == mpImplPolygon->mpPointAry[ 2 ].X() ) && 812cdf0e10cSrcweir ( mpImplPolygon->mpPointAry[ 2 ].Y() == mpImplPolygon->mpPointAry[ 3 ].Y() ) ) 813cdf0e10cSrcweir bIsRect = sal_True; 814cdf0e10cSrcweir } 815cdf0e10cSrcweir } 816cdf0e10cSrcweir return bIsRect; 817cdf0e10cSrcweir } 818cdf0e10cSrcweir 819cdf0e10cSrcweir // ----------------------------------------------------------------------- 820cdf0e10cSrcweir 821cdf0e10cSrcweir void Polygon::SetSize( sal_uInt16 nNewSize ) 822cdf0e10cSrcweir { 823cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 824cdf0e10cSrcweir 825cdf0e10cSrcweir if( nNewSize != mpImplPolygon->mnPoints ) 826cdf0e10cSrcweir { 827cdf0e10cSrcweir ImplMakeUnique(); 828cdf0e10cSrcweir mpImplPolygon->ImplSetSize( nNewSize ); 829cdf0e10cSrcweir } 830cdf0e10cSrcweir } 831cdf0e10cSrcweir 832cdf0e10cSrcweir // ----------------------------------------------------------------------- 833cdf0e10cSrcweir 834cdf0e10cSrcweir sal_uInt16 Polygon::GetSize() const 835cdf0e10cSrcweir { 836cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 837cdf0e10cSrcweir 838cdf0e10cSrcweir return mpImplPolygon->mnPoints; 839cdf0e10cSrcweir } 840cdf0e10cSrcweir 841cdf0e10cSrcweir // ----------------------------------------------------------------------- 842cdf0e10cSrcweir 843cdf0e10cSrcweir void Polygon::Clear() 844cdf0e10cSrcweir { 845cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 846cdf0e10cSrcweir 847cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 848cdf0e10cSrcweir { 849cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount > 1 ) 850cdf0e10cSrcweir mpImplPolygon->mnRefCount--; 851cdf0e10cSrcweir else 852cdf0e10cSrcweir delete mpImplPolygon; 853cdf0e10cSrcweir } 854cdf0e10cSrcweir 855cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 856cdf0e10cSrcweir } 857cdf0e10cSrcweir 858cdf0e10cSrcweir // ----------------------------------------------------------------------- 859cdf0e10cSrcweir 860cdf0e10cSrcweir double Polygon::CalcDistance( sal_uInt16 nP1, sal_uInt16 nP2 ) 861cdf0e10cSrcweir { 862cdf0e10cSrcweir DBG_ASSERT( nP1 < mpImplPolygon->mnPoints, 863cdf0e10cSrcweir "Polygon::CalcDistance(): nPos1 >= nPoints" ); 864cdf0e10cSrcweir DBG_ASSERT( nP2 < mpImplPolygon->mnPoints, 865cdf0e10cSrcweir "Polygon::CalcDistance(): nPos2 >= nPoints" ); 866cdf0e10cSrcweir 867cdf0e10cSrcweir const Point& rP1 = mpImplPolygon->mpPointAry[ nP1 ]; 868cdf0e10cSrcweir const Point& rP2 = mpImplPolygon->mpPointAry[ nP2 ]; 869cdf0e10cSrcweir const double fDx = rP2.X() - rP1.X(); 870cdf0e10cSrcweir const double fDy = rP2.Y() - rP1.Y(); 871cdf0e10cSrcweir 872cdf0e10cSrcweir return sqrt( fDx * fDx + fDy * fDy ); 873cdf0e10cSrcweir } 874cdf0e10cSrcweir 875cdf0e10cSrcweir // ----------------------------------------------------------------------- 876cdf0e10cSrcweir 877cdf0e10cSrcweir void Polygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData ) 878cdf0e10cSrcweir { 879cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 880cdf0e10cSrcweir DBG_ASSERT( !mpImplPolygon->mpFlagAry, "Optimizing could fail with beziers!" ); 881cdf0e10cSrcweir 882cdf0e10cSrcweir sal_uInt16 nSize = mpImplPolygon->mnPoints; 883cdf0e10cSrcweir 884cdf0e10cSrcweir if( nOptimizeFlags && nSize ) 885cdf0e10cSrcweir { 886cdf0e10cSrcweir if( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) 887cdf0e10cSrcweir { 888cdf0e10cSrcweir const Rectangle aBound( GetBoundRect() ); 889cdf0e10cSrcweir const double fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5; 890cdf0e10cSrcweir const sal_uInt16 nPercent = pData ? pData->GetPercentValue() : 50; 891cdf0e10cSrcweir 892cdf0e10cSrcweir Optimize( POLY_OPTIMIZE_NO_SAME ); 893cdf0e10cSrcweir ImplReduceEdges( *this, fArea, nPercent ); 894cdf0e10cSrcweir } 895cdf0e10cSrcweir else if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE | POLY_OPTIMIZE_NO_SAME ) ) 896cdf0e10cSrcweir { 897cdf0e10cSrcweir Polygon aNewPoly; 898cdf0e10cSrcweir const Point& rFirst = mpImplPolygon->mpPointAry[ 0 ]; 899cdf0e10cSrcweir sal_uIntPtr nReduce; 900cdf0e10cSrcweir 901cdf0e10cSrcweir if( nOptimizeFlags & ( POLY_OPTIMIZE_REDUCE ) ) 902cdf0e10cSrcweir nReduce = pData ? pData->GetAbsValue() : 4UL; 903cdf0e10cSrcweir else 904cdf0e10cSrcweir nReduce = 0UL; 905cdf0e10cSrcweir 906cdf0e10cSrcweir while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) ) 907cdf0e10cSrcweir nSize--; 908cdf0e10cSrcweir 909cdf0e10cSrcweir if( nSize > 1 ) 910cdf0e10cSrcweir { 911cdf0e10cSrcweir sal_uInt16 nLast = 0, nNewCount = 1; 912cdf0e10cSrcweir 913cdf0e10cSrcweir aNewPoly.SetSize( nSize ); 914cdf0e10cSrcweir aNewPoly[ 0 ] = rFirst; 915cdf0e10cSrcweir 916cdf0e10cSrcweir for( sal_uInt16 i = 1; i < nSize; i++ ) 917cdf0e10cSrcweir { 918cdf0e10cSrcweir if( ( mpImplPolygon->mpPointAry[ i ] != mpImplPolygon->mpPointAry[ nLast ] ) && 919cdf0e10cSrcweir ( !nReduce || ( nReduce < (sal_uIntPtr) FRound( CalcDistance( nLast, i ) ) ) ) ) 920cdf0e10cSrcweir { 921cdf0e10cSrcweir aNewPoly[ nNewCount++ ] = mpImplPolygon->mpPointAry[ nLast = i ]; 922cdf0e10cSrcweir } 923cdf0e10cSrcweir } 924cdf0e10cSrcweir 925cdf0e10cSrcweir if( nNewCount == 1 ) 926cdf0e10cSrcweir aNewPoly.Clear(); 927cdf0e10cSrcweir else 928cdf0e10cSrcweir aNewPoly.SetSize( nNewCount ); 929cdf0e10cSrcweir } 930cdf0e10cSrcweir 931cdf0e10cSrcweir *this = aNewPoly; 932cdf0e10cSrcweir } 933cdf0e10cSrcweir 934cdf0e10cSrcweir nSize = mpImplPolygon->mnPoints; 935cdf0e10cSrcweir 936cdf0e10cSrcweir if( nSize > 1 ) 937cdf0e10cSrcweir { 938cdf0e10cSrcweir if( ( nOptimizeFlags & POLY_OPTIMIZE_CLOSE ) && 939cdf0e10cSrcweir ( mpImplPolygon->mpPointAry[ 0 ] != mpImplPolygon->mpPointAry[ nSize - 1 ] ) ) 940cdf0e10cSrcweir { 941cdf0e10cSrcweir SetSize( mpImplPolygon->mnPoints + 1 ); 942cdf0e10cSrcweir mpImplPolygon->mpPointAry[ mpImplPolygon->mnPoints - 1 ] = mpImplPolygon->mpPointAry[ 0 ]; 943cdf0e10cSrcweir } 944cdf0e10cSrcweir else if( ( nOptimizeFlags & POLY_OPTIMIZE_OPEN ) && 945cdf0e10cSrcweir ( mpImplPolygon->mpPointAry[ 0 ] == mpImplPolygon->mpPointAry[ nSize - 1 ] ) ) 946cdf0e10cSrcweir { 947cdf0e10cSrcweir const Point& rFirst = mpImplPolygon->mpPointAry[ 0 ]; 948cdf0e10cSrcweir 949cdf0e10cSrcweir while( nSize && ( mpImplPolygon->mpPointAry[ nSize - 1 ] == rFirst ) ) 950cdf0e10cSrcweir nSize--; 951cdf0e10cSrcweir 952cdf0e10cSrcweir SetSize( nSize ); 953cdf0e10cSrcweir } 954cdf0e10cSrcweir } 955cdf0e10cSrcweir } 956cdf0e10cSrcweir } 957cdf0e10cSrcweir 958cdf0e10cSrcweir // ======================================================================= 959cdf0e10cSrcweir 960cdf0e10cSrcweir /* Recursively subdivide cubic bezier curve via deCasteljau. 961cdf0e10cSrcweir 962cdf0e10cSrcweir @param rPointIter 963cdf0e10cSrcweir Output iterator, where the subdivided polylines are written to. 964cdf0e10cSrcweir 965cdf0e10cSrcweir @param d 966cdf0e10cSrcweir Squared difference of curve to a straight line 967cdf0e10cSrcweir 968cdf0e10cSrcweir @param P* 969cdf0e10cSrcweir Exactly four points, interpreted as support and control points of 970cdf0e10cSrcweir a cubic bezier curve. Must be in device coordinates, since stop 971cdf0e10cSrcweir criterion is based on the following assumption: the device has a 972cdf0e10cSrcweir finite resolution, it is thus sufficient to stop subdivision if the 973cdf0e10cSrcweir curve does not deviate more than one pixel from a straight line. 974cdf0e10cSrcweir 975cdf0e10cSrcweir */ 976cdf0e10cSrcweir static void ImplAdaptiveSubdivide( ::std::back_insert_iterator< ::std::vector< Point > >& rPointIter, 977cdf0e10cSrcweir const double old_d2, 978cdf0e10cSrcweir int recursionDepth, 979cdf0e10cSrcweir const double d2, 980cdf0e10cSrcweir const double P1x, const double P1y, 981cdf0e10cSrcweir const double P2x, const double P2y, 982cdf0e10cSrcweir const double P3x, const double P3y, 983cdf0e10cSrcweir const double P4x, const double P4y ) 984cdf0e10cSrcweir { 985cdf0e10cSrcweir // Hard limit on recursion depth, empiric number. 986cdf0e10cSrcweir enum {maxRecursionDepth=128}; 987cdf0e10cSrcweir 988cdf0e10cSrcweir // Perform bezier flatness test (lecture notes from R. Schaback, 989cdf0e10cSrcweir // Mathematics of Computer-Aided Design, Uni Goettingen, 2000) 990cdf0e10cSrcweir // 991cdf0e10cSrcweir // ||P(t) - L(t)|| <= max ||b_j - b_0 - j/n(b_n - b_0)|| 992cdf0e10cSrcweir // 0<=j<=n 993cdf0e10cSrcweir // 994cdf0e10cSrcweir // What is calculated here is an upper bound to the distance from 995cdf0e10cSrcweir // a line through b_0 and b_3 (P1 and P4 in our notation) and the 996cdf0e10cSrcweir // curve. We can drop 0 and n from the running indices, since the 997cdf0e10cSrcweir // argument of max becomes zero for those cases. 998cdf0e10cSrcweir const double fJ1x( P2x - P1x - 1.0/3.0*(P4x - P1x) ); 999cdf0e10cSrcweir const double fJ1y( P2y - P1y - 1.0/3.0*(P4y - P1y) ); 1000cdf0e10cSrcweir const double fJ2x( P3x - P1x - 2.0/3.0*(P4x - P1x) ); 1001cdf0e10cSrcweir const double fJ2y( P3y - P1y - 2.0/3.0*(P4y - P1y) ); 1002cdf0e10cSrcweir const double distance2( ::std::max( fJ1x*fJ1x + fJ1y*fJ1y, 1003cdf0e10cSrcweir fJ2x*fJ2x + fJ2y*fJ2y) ); 1004cdf0e10cSrcweir 1005cdf0e10cSrcweir // stop if error measure does not improve anymore. This is a 1006cdf0e10cSrcweir // safety guard against floating point inaccuracies. 1007cdf0e10cSrcweir // stop at recursion level 128. This is a safety guard against 1008cdf0e10cSrcweir // floating point inaccuracies. 1009cdf0e10cSrcweir // stop if distance from line is guaranteed to be bounded by d 1010cdf0e10cSrcweir if( old_d2 > d2 && 1011cdf0e10cSrcweir recursionDepth < maxRecursionDepth && 1012cdf0e10cSrcweir distance2 >= d2 ) 1013cdf0e10cSrcweir { 1014cdf0e10cSrcweir // deCasteljau bezier arc, split at t=0.5 1015cdf0e10cSrcweir // Foley/vanDam, p. 508 1016cdf0e10cSrcweir const double L1x( P1x ), L1y( P1y ); 1017cdf0e10cSrcweir const double L2x( (P1x + P2x)*0.5 ), L2y( (P1y + P2y)*0.5 ); 1018cdf0e10cSrcweir const double Hx ( (P2x + P3x)*0.5 ), Hy ( (P2y + P3y)*0.5 ); 1019cdf0e10cSrcweir const double L3x( (L2x + Hx)*0.5 ), L3y( (L2y + Hy)*0.5 ); 1020cdf0e10cSrcweir const double R4x( P4x ), R4y( P4y ); 1021cdf0e10cSrcweir const double R3x( (P3x + P4x)*0.5 ), R3y( (P3y + P4y)*0.5 ); 1022cdf0e10cSrcweir const double R2x( (Hx + R3x)*0.5 ), R2y( (Hy + R3y)*0.5 ); 1023cdf0e10cSrcweir const double R1x( (L3x + R2x)*0.5 ), R1y( (L3y + R2y)*0.5 ); 1024cdf0e10cSrcweir const double L4x( R1x ), L4y( R1y ); 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir // subdivide further 1027cdf0e10cSrcweir ++recursionDepth; 1028cdf0e10cSrcweir ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y); 1029cdf0e10cSrcweir ImplAdaptiveSubdivide(rPointIter, distance2, recursionDepth, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y); 1030cdf0e10cSrcweir } 1031cdf0e10cSrcweir else 1032cdf0e10cSrcweir { 1033cdf0e10cSrcweir // requested resolution reached. 1034cdf0e10cSrcweir // Add end points to output iterator. 1035cdf0e10cSrcweir // order is preserved, since this is so to say depth first traversal. 1036cdf0e10cSrcweir *rPointIter++ = Point( FRound(P1x), FRound(P1y) ); 1037cdf0e10cSrcweir } 1038cdf0e10cSrcweir } 1039cdf0e10cSrcweir 1040cdf0e10cSrcweir // ======================================================================= 1041cdf0e10cSrcweir 1042cdf0e10cSrcweir void Polygon::AdaptiveSubdivide( Polygon& rResult, const double d ) const 1043cdf0e10cSrcweir { 1044cdf0e10cSrcweir if( !mpImplPolygon->mpFlagAry ) 1045cdf0e10cSrcweir { 1046cdf0e10cSrcweir rResult = *this; 1047cdf0e10cSrcweir } 1048cdf0e10cSrcweir else 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir sal_uInt16 i; 1051cdf0e10cSrcweir sal_uInt16 nPts( GetSize() ); 1052cdf0e10cSrcweir ::std::vector< Point > aPoints; 1053cdf0e10cSrcweir aPoints.reserve( nPts ); 1054cdf0e10cSrcweir ::std::back_insert_iterator< ::std::vector< Point > > aPointIter( aPoints ); 1055cdf0e10cSrcweir 1056cdf0e10cSrcweir for(i=0; i<nPts;) 1057cdf0e10cSrcweir { 1058cdf0e10cSrcweir if( ( i + 3 ) < nPts ) 1059cdf0e10cSrcweir { 1060cdf0e10cSrcweir sal_uInt8 P1( mpImplPolygon->mpFlagAry[ i ] ); 1061cdf0e10cSrcweir sal_uInt8 P4( mpImplPolygon->mpFlagAry[ i + 3 ] ); 1062cdf0e10cSrcweir 1063cdf0e10cSrcweir if( ( POLY_NORMAL == P1 || POLY_SMOOTH == P1 || POLY_SYMMTR == P1 ) && 1064cdf0e10cSrcweir ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 1 ] ) && 1065cdf0e10cSrcweir ( POLY_CONTROL == mpImplPolygon->mpFlagAry[ i + 2 ] ) && 1066cdf0e10cSrcweir ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) ) 1067cdf0e10cSrcweir { 1068cdf0e10cSrcweir ImplAdaptiveSubdivide( aPointIter, d*d+1.0, 0, d*d, 1069cdf0e10cSrcweir mpImplPolygon->mpPointAry[ i ].X(), mpImplPolygon->mpPointAry[ i ].Y(), 1070cdf0e10cSrcweir mpImplPolygon->mpPointAry[ i+1 ].X(), mpImplPolygon->mpPointAry[ i+1 ].Y(), 1071cdf0e10cSrcweir mpImplPolygon->mpPointAry[ i+2 ].X(), mpImplPolygon->mpPointAry[ i+2 ].Y(), 1072cdf0e10cSrcweir mpImplPolygon->mpPointAry[ i+3 ].X(), mpImplPolygon->mpPointAry[ i+3 ].Y() ); 1073cdf0e10cSrcweir i += 3; 1074cdf0e10cSrcweir continue; 1075cdf0e10cSrcweir } 1076cdf0e10cSrcweir } 1077cdf0e10cSrcweir 1078cdf0e10cSrcweir *aPointIter++ = mpImplPolygon->mpPointAry[ i++ ]; 1079cdf0e10cSrcweir } 1080cdf0e10cSrcweir 1081cdf0e10cSrcweir // fill result polygon 1082cdf0e10cSrcweir rResult = Polygon( (sal_uInt16)aPoints.size() ); // ensure sufficient size for copy 1083cdf0e10cSrcweir ::std::copy(aPoints.begin(), aPoints.end(), rResult.mpImplPolygon->mpPointAry); 1084cdf0e10cSrcweir } 1085cdf0e10cSrcweir } 1086cdf0e10cSrcweir 1087cdf0e10cSrcweir // ----------------------------------------------------------------------- 1088cdf0e10cSrcweir 1089cdf0e10cSrcweir void Polygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const 1090cdf0e10cSrcweir { 1091cdf0e10cSrcweir const PolyPolygon aTmp( *this ); 1092cdf0e10cSrcweir aTmp.GetIntersection( rPolyPoly, rResult ); 1093cdf0e10cSrcweir } 1094cdf0e10cSrcweir 1095cdf0e10cSrcweir // ----------------------------------------------------------------------- 1096cdf0e10cSrcweir 1097cdf0e10cSrcweir void Polygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const 1098cdf0e10cSrcweir { 1099cdf0e10cSrcweir const PolyPolygon aTmp( *this ); 1100cdf0e10cSrcweir aTmp.GetUnion( rPolyPoly, rResult ); 1101cdf0e10cSrcweir } 1102cdf0e10cSrcweir 1103cdf0e10cSrcweir // ----------------------------------------------------------------------- 1104cdf0e10cSrcweir 1105cdf0e10cSrcweir void Polygon::GetDifference( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const 1106cdf0e10cSrcweir { 1107cdf0e10cSrcweir const PolyPolygon aTmp( *this ); 1108cdf0e10cSrcweir aTmp.GetDifference( rPolyPoly, rResult ); 1109cdf0e10cSrcweir } 1110cdf0e10cSrcweir 1111cdf0e10cSrcweir // ----------------------------------------------------------------------- 1112cdf0e10cSrcweir 1113cdf0e10cSrcweir void Polygon::GetXOR( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const 1114cdf0e10cSrcweir { 1115cdf0e10cSrcweir const PolyPolygon aTmp( *this ); 1116cdf0e10cSrcweir aTmp.GetXOR( rPolyPoly, rResult ); 1117cdf0e10cSrcweir } 1118cdf0e10cSrcweir 1119cdf0e10cSrcweir // ----------------------------------------------------------------------- 1120cdf0e10cSrcweir 1121cdf0e10cSrcweir void Polygon::ImplReduceEdges( Polygon& rPoly, const double& rArea, sal_uInt16 nPercent ) 1122cdf0e10cSrcweir { 1123cdf0e10cSrcweir const double fBound = 2000.0 * ( 100 - nPercent ) * 0.01; 1124cdf0e10cSrcweir sal_uInt16 nNumNoChange = 0, nNumRuns = 0; 1125cdf0e10cSrcweir 1126cdf0e10cSrcweir while( nNumNoChange < 2 ) 1127cdf0e10cSrcweir { 1128cdf0e10cSrcweir sal_uInt16 nPntCnt = rPoly.GetSize(), nNewPos = 0; 1129cdf0e10cSrcweir Polygon aNewPoly( nPntCnt ); 1130cdf0e10cSrcweir sal_Bool bChangeInThisRun = sal_False; 1131cdf0e10cSrcweir 1132cdf0e10cSrcweir for( sal_uInt16 n = 0; n < nPntCnt; n++ ) 1133cdf0e10cSrcweir { 1134cdf0e10cSrcweir sal_Bool bDeletePoint = sal_False; 1135cdf0e10cSrcweir 1136cdf0e10cSrcweir if( ( n + nNumRuns ) % 2 ) 1137cdf0e10cSrcweir { 1138cdf0e10cSrcweir sal_uInt16 nIndPrev = !n ? nPntCnt - 1 : n - 1; 1139cdf0e10cSrcweir sal_uInt16 nIndPrevPrev = !nIndPrev ? nPntCnt - 1 : nIndPrev - 1; 1140cdf0e10cSrcweir sal_uInt16 nIndNext = ( n == nPntCnt-1 ) ? 0 : n + 1; 1141cdf0e10cSrcweir sal_uInt16 nIndNextNext = ( nIndNext == nPntCnt - 1 ) ? 0 : nIndNext + 1; 1142cdf0e10cSrcweir Vector2D aVec1( rPoly[ nIndPrev ] ); aVec1 -= rPoly[ nIndPrevPrev ]; 1143cdf0e10cSrcweir Vector2D aVec2( rPoly[ n ] ); aVec2 -= rPoly[ nIndPrev ]; 1144cdf0e10cSrcweir Vector2D aVec3( rPoly[ nIndNext ] ); aVec3 -= rPoly[ n ]; 1145cdf0e10cSrcweir Vector2D aVec4( rPoly[ nIndNextNext ] ); aVec4 -= rPoly[ nIndNext ]; 1146cdf0e10cSrcweir double fDist1 = aVec1.GetLength(), fDist2 = aVec2.GetLength(); 1147cdf0e10cSrcweir double fDist3 = aVec3.GetLength(), fDist4 = aVec4.GetLength(); 1148cdf0e10cSrcweir double fTurnB = aVec2.Normalize().Scalar( aVec3.Normalize() ); 1149cdf0e10cSrcweir 1150cdf0e10cSrcweir if( fabs( fTurnB ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnB ) > ( 1.0 - SMALL_DVALUE ) ) 1151cdf0e10cSrcweir bDeletePoint = sal_True; 1152cdf0e10cSrcweir else 1153cdf0e10cSrcweir { 1154cdf0e10cSrcweir Vector2D aVecB( rPoly[ nIndNext ] ); 1155cdf0e10cSrcweir double fDistB = ( aVecB -= rPoly[ nIndPrev ] ).GetLength(); 1156cdf0e10cSrcweir double fLenWithB = fDist2 + fDist3; 1157cdf0e10cSrcweir double fLenFact = ( fDistB != 0.0 ) ? fLenWithB / fDistB : 1.0; 1158cdf0e10cSrcweir double fTurnPrev = aVec1.Normalize().Scalar( aVec2 ); 1159cdf0e10cSrcweir double fTurnNext = aVec3.Scalar( aVec4.Normalize() ); 1160cdf0e10cSrcweir double fGradPrev, fGradB, fGradNext; 1161cdf0e10cSrcweir 1162cdf0e10cSrcweir if( fabs( fTurnPrev ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnPrev ) > ( 1.0 - SMALL_DVALUE ) ) 1163cdf0e10cSrcweir fGradPrev = 0.0; 1164cdf0e10cSrcweir else 1165cdf0e10cSrcweir fGradPrev = acos( fTurnPrev ) / ( aVec1.IsNegative( aVec2 ) ? -F_PI180 : F_PI180 ); 1166cdf0e10cSrcweir 1167cdf0e10cSrcweir fGradB = acos( fTurnB ) / ( aVec2.IsNegative( aVec3 ) ? -F_PI180 : F_PI180 ); 1168cdf0e10cSrcweir 1169cdf0e10cSrcweir if( fabs( fTurnNext ) < ( 1.0 + SMALL_DVALUE ) && fabs( fTurnNext ) > ( 1.0 - SMALL_DVALUE ) ) 1170cdf0e10cSrcweir fGradNext = 0.0; 1171cdf0e10cSrcweir else 1172cdf0e10cSrcweir fGradNext = acos( fTurnNext ) / ( aVec3.IsNegative( aVec4 ) ? -F_PI180 : F_PI180 ); 1173cdf0e10cSrcweir 1174cdf0e10cSrcweir if( ( fGradPrev > 0.0 && fGradB < 0.0 && fGradNext > 0.0 ) || 1175cdf0e10cSrcweir ( fGradPrev < 0.0 && fGradB > 0.0 && fGradNext < 0.0 ) ) 1176cdf0e10cSrcweir { 1177cdf0e10cSrcweir if( ( fLenFact < ( FSQRT2 + SMALL_DVALUE ) ) && 1178cdf0e10cSrcweir ( ( ( fDist1 + fDist4 ) / ( fDist2 + fDist3 ) ) * 2000.0 ) > fBound ) 1179cdf0e10cSrcweir { 1180cdf0e10cSrcweir bDeletePoint = sal_True; 1181cdf0e10cSrcweir } 1182cdf0e10cSrcweir } 1183cdf0e10cSrcweir else 1184cdf0e10cSrcweir { 1185cdf0e10cSrcweir double fRelLen = 1.0 - sqrt( fDistB / rArea ); 1186cdf0e10cSrcweir 1187cdf0e10cSrcweir if( fRelLen < 0.0 ) 1188cdf0e10cSrcweir fRelLen = 0.0; 1189cdf0e10cSrcweir else if( fRelLen > 1.0 ) 1190cdf0e10cSrcweir fRelLen = 1.0; 1191cdf0e10cSrcweir 1192cdf0e10cSrcweir if( ( (sal_uInt32) ( ( ( fLenFact - 1.0 ) * 1000000.0 ) + 0.5 ) < fBound ) && 1193cdf0e10cSrcweir ( fabs( fGradB ) <= ( fRelLen * fBound * 0.01 ) ) ) 1194cdf0e10cSrcweir { 1195cdf0e10cSrcweir bDeletePoint = sal_True; 1196cdf0e10cSrcweir } 1197cdf0e10cSrcweir } 1198cdf0e10cSrcweir } 1199cdf0e10cSrcweir } 1200cdf0e10cSrcweir 1201cdf0e10cSrcweir if( !bDeletePoint ) 1202cdf0e10cSrcweir aNewPoly[ nNewPos++ ] = rPoly[ n ]; 1203cdf0e10cSrcweir else 1204cdf0e10cSrcweir bChangeInThisRun = sal_True; 1205cdf0e10cSrcweir } 1206cdf0e10cSrcweir 1207cdf0e10cSrcweir if( bChangeInThisRun && nNewPos ) 1208cdf0e10cSrcweir { 1209cdf0e10cSrcweir aNewPoly.SetSize( nNewPos ); 1210cdf0e10cSrcweir rPoly = aNewPoly; 1211cdf0e10cSrcweir nNumNoChange = 0; 1212cdf0e10cSrcweir } 1213cdf0e10cSrcweir else 1214cdf0e10cSrcweir nNumNoChange++; 1215cdf0e10cSrcweir 1216cdf0e10cSrcweir nNumRuns++; 1217cdf0e10cSrcweir } 1218cdf0e10cSrcweir } 1219cdf0e10cSrcweir 1220cdf0e10cSrcweir // ----------------------------------------------------------------------- 1221cdf0e10cSrcweir 1222cdf0e10cSrcweir void Polygon::Move( long nHorzMove, long nVertMove ) 1223cdf0e10cSrcweir { 1224cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1225cdf0e10cSrcweir 1226cdf0e10cSrcweir // Diese Abfrage sollte man fuer die DrawEngine durchfuehren 1227cdf0e10cSrcweir if ( !nHorzMove && !nVertMove ) 1228cdf0e10cSrcweir return; 1229cdf0e10cSrcweir 1230cdf0e10cSrcweir ImplMakeUnique(); 1231cdf0e10cSrcweir 1232cdf0e10cSrcweir // Punkte verschieben 1233cdf0e10cSrcweir sal_uInt16 nCount = mpImplPolygon->mnPoints; 1234cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nCount; i++ ) 1235cdf0e10cSrcweir { 1236cdf0e10cSrcweir Point* pPt = &(mpImplPolygon->mpPointAry[i]); 1237cdf0e10cSrcweir pPt->X() += nHorzMove; 1238cdf0e10cSrcweir pPt->Y() += nVertMove; 1239cdf0e10cSrcweir } 1240cdf0e10cSrcweir } 1241cdf0e10cSrcweir 1242cdf0e10cSrcweir // ----------------------------------------------------------------------- 1243cdf0e10cSrcweir 1244cdf0e10cSrcweir void Polygon::Translate(const Point& rTrans) 1245cdf0e10cSrcweir { 1246cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1247cdf0e10cSrcweir ImplMakeUnique(); 1248cdf0e10cSrcweir 1249cdf0e10cSrcweir for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1250cdf0e10cSrcweir mpImplPolygon->mpPointAry[ i ] += rTrans; 1251cdf0e10cSrcweir } 1252cdf0e10cSrcweir 1253cdf0e10cSrcweir // ----------------------------------------------------------------------- 1254cdf0e10cSrcweir 1255cdf0e10cSrcweir void Polygon::Scale( double fScaleX, double fScaleY ) 1256cdf0e10cSrcweir { 1257cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1258cdf0e10cSrcweir ImplMakeUnique(); 1259cdf0e10cSrcweir 1260cdf0e10cSrcweir for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1261cdf0e10cSrcweir { 1262cdf0e10cSrcweir Point& rPnt = mpImplPolygon->mpPointAry[i]; 1263cdf0e10cSrcweir rPnt.X() = (long) ( fScaleX * rPnt.X() ); 1264cdf0e10cSrcweir rPnt.Y() = (long) ( fScaleY * rPnt.Y() ); 1265cdf0e10cSrcweir } 1266cdf0e10cSrcweir } 1267cdf0e10cSrcweir 1268cdf0e10cSrcweir // ----------------------------------------------------------------------- 1269cdf0e10cSrcweir 1270cdf0e10cSrcweir void Polygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 ) 1271cdf0e10cSrcweir { 1272cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1273cdf0e10cSrcweir nAngle10 %= 3600; 1274cdf0e10cSrcweir 1275cdf0e10cSrcweir if( nAngle10 ) 1276cdf0e10cSrcweir { 1277cdf0e10cSrcweir const double fAngle = F_PI1800 * nAngle10; 1278cdf0e10cSrcweir Rotate( rCenter, sin( fAngle ), cos( fAngle ) ); 1279cdf0e10cSrcweir } 1280cdf0e10cSrcweir } 1281cdf0e10cSrcweir 1282cdf0e10cSrcweir // ----------------------------------------------------------------------- 1283cdf0e10cSrcweir 1284cdf0e10cSrcweir void Polygon::Rotate( const Point& rCenter, double fSin, double fCos ) 1285cdf0e10cSrcweir { 1286cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1287cdf0e10cSrcweir ImplMakeUnique(); 1288cdf0e10cSrcweir 1289cdf0e10cSrcweir long nX, nY; 1290cdf0e10cSrcweir long nCenterX = rCenter.X(); 1291cdf0e10cSrcweir long nCenterY = rCenter.Y(); 1292cdf0e10cSrcweir 1293cdf0e10cSrcweir for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1294cdf0e10cSrcweir { 1295cdf0e10cSrcweir Point& rPt = mpImplPolygon->mpPointAry[ i ]; 1296cdf0e10cSrcweir 1297cdf0e10cSrcweir nX = rPt.X() - nCenterX; 1298cdf0e10cSrcweir nY = rPt.Y() - nCenterY; 1299cdf0e10cSrcweir rPt.X() = (long) FRound( fCos * nX + fSin * nY ) + nCenterX; 1300cdf0e10cSrcweir rPt.Y() = -(long) FRound( fSin * nX - fCos * nY ) + nCenterY; 1301cdf0e10cSrcweir } 1302cdf0e10cSrcweir } 1303cdf0e10cSrcweir 1304cdf0e10cSrcweir // ----------------------------------------------------------------------- 1305cdf0e10cSrcweir 1306cdf0e10cSrcweir void Polygon::SlantX( long nYRef, double fSin, double fCos ) 1307cdf0e10cSrcweir { 1308cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1309cdf0e10cSrcweir ImplMakeUnique(); 1310cdf0e10cSrcweir 1311cdf0e10cSrcweir for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1312cdf0e10cSrcweir { 1313cdf0e10cSrcweir Point& rPnt = mpImplPolygon->mpPointAry[ i ]; 1314cdf0e10cSrcweir const long nDy = rPnt.Y() - nYRef; 1315cdf0e10cSrcweir 1316cdf0e10cSrcweir rPnt.X() += (long)( fSin * nDy ); 1317cdf0e10cSrcweir rPnt.Y() = nYRef + (long)( fCos * nDy ); 1318cdf0e10cSrcweir } 1319cdf0e10cSrcweir } 1320cdf0e10cSrcweir 1321cdf0e10cSrcweir // ----------------------------------------------------------------------- 1322cdf0e10cSrcweir 1323cdf0e10cSrcweir void Polygon::SlantY( long nXRef, double fSin, double fCos ) 1324cdf0e10cSrcweir { 1325cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1326cdf0e10cSrcweir ImplMakeUnique(); 1327cdf0e10cSrcweir 1328cdf0e10cSrcweir for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1329cdf0e10cSrcweir { 1330cdf0e10cSrcweir Point& rPnt = mpImplPolygon->mpPointAry[ i ]; 1331cdf0e10cSrcweir const long nDx = rPnt.X() - nXRef; 1332cdf0e10cSrcweir 1333cdf0e10cSrcweir rPnt.X() = nXRef + (long)( fCos * nDx ); 1334cdf0e10cSrcweir rPnt.Y() -= (long)( fSin * nDx ); 1335cdf0e10cSrcweir } 1336cdf0e10cSrcweir } 1337cdf0e10cSrcweir 1338cdf0e10cSrcweir // ----------------------------------------------------------------------- 1339cdf0e10cSrcweir 1340cdf0e10cSrcweir void Polygon::Distort( const Rectangle& rRefRect, const Polygon& rDistortedRect ) 1341cdf0e10cSrcweir { 1342cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1343cdf0e10cSrcweir ImplMakeUnique(); 1344cdf0e10cSrcweir 1345cdf0e10cSrcweir long Xr, Wr, X1, X2, X3, X4; 1346cdf0e10cSrcweir long Yr, Hr, Y1, Y2, Y3, Y4; 1347cdf0e10cSrcweir double fTx, fTy, fUx, fUy; 1348cdf0e10cSrcweir 1349cdf0e10cSrcweir Xr = rRefRect.Left(); 1350cdf0e10cSrcweir Yr = rRefRect.Top(); 1351cdf0e10cSrcweir Wr = rRefRect.GetWidth(); 1352cdf0e10cSrcweir Hr = rRefRect.GetHeight(); 1353cdf0e10cSrcweir 1354cdf0e10cSrcweir if( Wr && Hr ) 1355cdf0e10cSrcweir { 1356cdf0e10cSrcweir DBG_ASSERT( rDistortedRect.mpImplPolygon->mnPoints >= 4, "Distort rect too small!" ); 1357cdf0e10cSrcweir 1358cdf0e10cSrcweir X1 = rDistortedRect[0].X(); 1359cdf0e10cSrcweir Y1 = rDistortedRect[0].Y(); 1360cdf0e10cSrcweir X2 = rDistortedRect[1].X(); 1361cdf0e10cSrcweir Y2 = rDistortedRect[1].Y(); 1362cdf0e10cSrcweir X3 = rDistortedRect[3].X(); 1363cdf0e10cSrcweir Y3 = rDistortedRect[3].Y(); 1364cdf0e10cSrcweir X4 = rDistortedRect[2].X(); 1365cdf0e10cSrcweir Y4 = rDistortedRect[2].Y(); 1366cdf0e10cSrcweir 1367cdf0e10cSrcweir for( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ ) 1368cdf0e10cSrcweir { 1369cdf0e10cSrcweir Point& rPnt = mpImplPolygon->mpPointAry[ i ]; 1370cdf0e10cSrcweir 1371cdf0e10cSrcweir fTx = (double)( rPnt.X() - Xr) / Wr; 1372cdf0e10cSrcweir fTy = (double)( rPnt.Y() - Yr) / Hr; 1373cdf0e10cSrcweir fUx = 1.0 - fTx; 1374cdf0e10cSrcweir fUy = 1.0 - fTy; 1375cdf0e10cSrcweir 1376cdf0e10cSrcweir rPnt.X() = (long) ( fUy * (fUx * X1 + fTx * X2) + fTy * (fUx * X3 + fTx * X4) ); 1377cdf0e10cSrcweir rPnt.Y() = (long) ( fUx * (fUy * Y1 + fTy * Y3) + fTx * (fUy * Y2 + fTy * Y4) ); 1378cdf0e10cSrcweir } 1379cdf0e10cSrcweir } 1380cdf0e10cSrcweir } 1381cdf0e10cSrcweir 1382cdf0e10cSrcweir // ----------------------------------------------------------------------- 1383cdf0e10cSrcweir 1384cdf0e10cSrcweir class ImplPointFilter 1385cdf0e10cSrcweir { 1386cdf0e10cSrcweir public: 1387cdf0e10cSrcweir virtual void LastPoint() = 0; 1388cdf0e10cSrcweir virtual void Input( const Point& rPoint ) = 0; 1389cdf0e10cSrcweir }; 1390cdf0e10cSrcweir 1391cdf0e10cSrcweir class ImplPolygonPointFilter : public ImplPointFilter 1392cdf0e10cSrcweir { 1393cdf0e10cSrcweir public: 1394cdf0e10cSrcweir ImplPolygon* mpPoly; // Nicht loeschen, wird dem Polygon zugewiesen 1395cdf0e10cSrcweir sal_uInt16 mnSize; 1396cdf0e10cSrcweir 1397cdf0e10cSrcweir ImplPolygonPointFilter( sal_uInt16 nDestSize ) : 1398cdf0e10cSrcweir mnSize( 0 ) 1399cdf0e10cSrcweir { 1400cdf0e10cSrcweir mpPoly = new ImplPolygon( nDestSize ); 1401cdf0e10cSrcweir } 1402cdf0e10cSrcweir 1403cdf0e10cSrcweir virtual void LastPoint(); 1404cdf0e10cSrcweir virtual void Input( const Point& rPoint ); 1405cdf0e10cSrcweir }; 1406cdf0e10cSrcweir 1407cdf0e10cSrcweir void ImplPolygonPointFilter::Input( const Point& rPoint ) 1408cdf0e10cSrcweir { 1409cdf0e10cSrcweir if ( !mnSize || (rPoint != mpPoly->mpPointAry[mnSize-1]) ) 1410cdf0e10cSrcweir { 1411cdf0e10cSrcweir mnSize++; 1412cdf0e10cSrcweir if ( mnSize > mpPoly->mnPoints ) 1413cdf0e10cSrcweir mpPoly->ImplSetSize( mnSize ); 1414cdf0e10cSrcweir mpPoly->mpPointAry[mnSize-1] = rPoint; 1415cdf0e10cSrcweir } 1416cdf0e10cSrcweir } 1417cdf0e10cSrcweir 1418cdf0e10cSrcweir void ImplPolygonPointFilter::LastPoint() 1419cdf0e10cSrcweir { 1420cdf0e10cSrcweir if ( mnSize < mpPoly->mnPoints ) 1421cdf0e10cSrcweir mpPoly->ImplSetSize( mnSize ); 1422cdf0e10cSrcweir }; 1423cdf0e10cSrcweir 1424cdf0e10cSrcweir class ImplEdgePointFilter : public ImplPointFilter 1425cdf0e10cSrcweir { 1426cdf0e10cSrcweir Point maFirstPoint; 1427cdf0e10cSrcweir Point maLastPoint; 1428cdf0e10cSrcweir ImplPointFilter& mrNextFilter; 1429cdf0e10cSrcweir const long mnLow; 1430cdf0e10cSrcweir const long mnHigh; 1431cdf0e10cSrcweir const int mnEdge; 1432cdf0e10cSrcweir int mnLastOutside; 1433cdf0e10cSrcweir sal_Bool mbFirst; 1434cdf0e10cSrcweir 1435cdf0e10cSrcweir public: 1436cdf0e10cSrcweir ImplEdgePointFilter( int nEdge, long nLow, long nHigh, 1437cdf0e10cSrcweir ImplPointFilter& rNextFilter ) : 1438cdf0e10cSrcweir mrNextFilter( rNextFilter ), 1439cdf0e10cSrcweir mnLow( nLow ), 1440cdf0e10cSrcweir mnHigh( nHigh ), 1441cdf0e10cSrcweir mnEdge( nEdge ), 1442cdf0e10cSrcweir mbFirst( sal_True ) 1443cdf0e10cSrcweir { 1444cdf0e10cSrcweir } 1445cdf0e10cSrcweir 1446cdf0e10cSrcweir Point EdgeSection( const Point& rPoint, int nEdge ) const; 1447cdf0e10cSrcweir int VisibleSide( const Point& rPoint ) const; 1448cdf0e10cSrcweir int IsPolygon() const 1449cdf0e10cSrcweir { return maFirstPoint == maLastPoint; } 1450cdf0e10cSrcweir 1451cdf0e10cSrcweir virtual void Input( const Point& rPoint ); 1452cdf0e10cSrcweir virtual void LastPoint(); 1453cdf0e10cSrcweir }; 1454cdf0e10cSrcweir 1455cdf0e10cSrcweir inline int ImplEdgePointFilter::VisibleSide( const Point& rPoint ) const 1456cdf0e10cSrcweir { 1457cdf0e10cSrcweir if ( mnEdge & EDGE_HORZ ) 1458cdf0e10cSrcweir { 1459cdf0e10cSrcweir return rPoint.X() < mnLow ? EDGE_LEFT : 1460cdf0e10cSrcweir rPoint.X() > mnHigh ? EDGE_RIGHT : 0; 1461cdf0e10cSrcweir } 1462cdf0e10cSrcweir else 1463cdf0e10cSrcweir { 1464cdf0e10cSrcweir return rPoint.Y() < mnLow ? EDGE_TOP : 1465cdf0e10cSrcweir rPoint.Y() > mnHigh ? EDGE_BOTTOM : 0; 1466cdf0e10cSrcweir } 1467cdf0e10cSrcweir } 1468cdf0e10cSrcweir 1469cdf0e10cSrcweir Point ImplEdgePointFilter::EdgeSection( const Point& rPoint, int nEdge ) const 1470cdf0e10cSrcweir { 1471cdf0e10cSrcweir long lx = maLastPoint.X(); 1472cdf0e10cSrcweir long ly = maLastPoint.Y(); 1473cdf0e10cSrcweir long md = rPoint.X() - lx; 1474cdf0e10cSrcweir long mn = rPoint.Y() - ly; 1475cdf0e10cSrcweir long nNewX; 1476cdf0e10cSrcweir long nNewY; 1477cdf0e10cSrcweir 1478cdf0e10cSrcweir if ( nEdge & EDGE_VERT ) 1479cdf0e10cSrcweir { 1480cdf0e10cSrcweir nNewY = (nEdge == EDGE_TOP) ? mnLow : mnHigh; 1481cdf0e10cSrcweir long dy = nNewY - ly; 1482cdf0e10cSrcweir if ( !md ) 1483cdf0e10cSrcweir nNewX = lx; 1484cdf0e10cSrcweir else if ( (LONG_MAX / Abs(md)) >= Abs(dy) ) 1485cdf0e10cSrcweir nNewX = (dy * md) / mn + lx; 1486cdf0e10cSrcweir else 1487cdf0e10cSrcweir { 1488cdf0e10cSrcweir BigInt ady = dy; 1489cdf0e10cSrcweir ady *= md; 1490cdf0e10cSrcweir if( ady.IsNeg() ) 1491cdf0e10cSrcweir if( mn < 0 ) 1492cdf0e10cSrcweir ady += mn/2; 1493cdf0e10cSrcweir else 1494cdf0e10cSrcweir ady -= (mn-1)/2; 1495cdf0e10cSrcweir else 1496cdf0e10cSrcweir if( mn < 0 ) 1497cdf0e10cSrcweir ady -= (mn+1)/2; 1498cdf0e10cSrcweir else 1499cdf0e10cSrcweir ady += mn/2; 1500cdf0e10cSrcweir ady /= mn; 1501cdf0e10cSrcweir nNewX = (long)ady + lx; 1502cdf0e10cSrcweir } 1503cdf0e10cSrcweir } 1504cdf0e10cSrcweir else 1505cdf0e10cSrcweir { 1506cdf0e10cSrcweir nNewX = (nEdge == EDGE_LEFT) ? mnLow : mnHigh; 1507cdf0e10cSrcweir long dx = nNewX - lx; 1508cdf0e10cSrcweir if ( !mn ) 1509cdf0e10cSrcweir nNewY = ly; 1510cdf0e10cSrcweir else if ( (LONG_MAX / Abs(mn)) >= Abs(dx) ) 1511cdf0e10cSrcweir nNewY = (dx * mn) / md + ly; 1512cdf0e10cSrcweir else 1513cdf0e10cSrcweir { 1514cdf0e10cSrcweir BigInt adx = dx; 1515cdf0e10cSrcweir adx *= mn; 1516cdf0e10cSrcweir if( adx.IsNeg() ) 1517cdf0e10cSrcweir if( md < 0 ) 1518cdf0e10cSrcweir adx += md/2; 1519cdf0e10cSrcweir else 1520cdf0e10cSrcweir adx -= (md-1)/2; 1521cdf0e10cSrcweir else 1522cdf0e10cSrcweir if( md < 0 ) 1523cdf0e10cSrcweir adx -= (md+1)/2; 1524cdf0e10cSrcweir else 1525cdf0e10cSrcweir adx += md/2; 1526cdf0e10cSrcweir adx /= md; 1527cdf0e10cSrcweir nNewY = (long)adx + ly; 1528cdf0e10cSrcweir } 1529cdf0e10cSrcweir } 1530cdf0e10cSrcweir 1531cdf0e10cSrcweir return Point( nNewX, nNewY ); 1532cdf0e10cSrcweir } 1533cdf0e10cSrcweir 1534cdf0e10cSrcweir void ImplEdgePointFilter::Input( const Point& rPoint ) 1535cdf0e10cSrcweir { 1536cdf0e10cSrcweir int nOutside = VisibleSide( rPoint ); 1537cdf0e10cSrcweir 1538cdf0e10cSrcweir if ( mbFirst ) 1539cdf0e10cSrcweir { 1540cdf0e10cSrcweir maFirstPoint = rPoint; 1541cdf0e10cSrcweir mbFirst = sal_False; 1542cdf0e10cSrcweir if ( !nOutside ) 1543cdf0e10cSrcweir mrNextFilter.Input( rPoint ); 1544cdf0e10cSrcweir } 1545cdf0e10cSrcweir else if ( rPoint == maLastPoint ) 1546cdf0e10cSrcweir return; 1547cdf0e10cSrcweir else if ( !nOutside ) 1548cdf0e10cSrcweir { 1549cdf0e10cSrcweir if ( mnLastOutside ) 1550cdf0e10cSrcweir mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) ); 1551cdf0e10cSrcweir mrNextFilter.Input( rPoint ); 1552cdf0e10cSrcweir } 1553cdf0e10cSrcweir else if ( !mnLastOutside ) 1554cdf0e10cSrcweir mrNextFilter.Input( EdgeSection( rPoint, nOutside ) ); 1555cdf0e10cSrcweir else if ( nOutside != mnLastOutside ) 1556cdf0e10cSrcweir { 1557cdf0e10cSrcweir mrNextFilter.Input( EdgeSection( rPoint, mnLastOutside ) ); 1558cdf0e10cSrcweir mrNextFilter.Input( EdgeSection( rPoint, nOutside ) ); 1559cdf0e10cSrcweir } 1560cdf0e10cSrcweir 1561cdf0e10cSrcweir maLastPoint = rPoint; 1562cdf0e10cSrcweir mnLastOutside = nOutside; 1563cdf0e10cSrcweir } 1564cdf0e10cSrcweir 1565cdf0e10cSrcweir void ImplEdgePointFilter::LastPoint() 1566cdf0e10cSrcweir { 1567cdf0e10cSrcweir if ( !mbFirst ) 1568cdf0e10cSrcweir { 1569cdf0e10cSrcweir int nOutside = VisibleSide( maFirstPoint ); 1570cdf0e10cSrcweir 1571cdf0e10cSrcweir if ( nOutside != mnLastOutside ) 1572cdf0e10cSrcweir Input( maFirstPoint ); 1573cdf0e10cSrcweir mrNextFilter.LastPoint(); 1574cdf0e10cSrcweir } 1575cdf0e10cSrcweir } 1576cdf0e10cSrcweir 1577cdf0e10cSrcweir // ----------------------------------------------------------------------- 1578cdf0e10cSrcweir 1579cdf0e10cSrcweir void Polygon::Clip( const Rectangle& rRect, sal_Bool bPolygon ) 1580cdf0e10cSrcweir { 1581cdf0e10cSrcweir // #105251# Justify rect befor edge filtering 1582cdf0e10cSrcweir Rectangle aJustifiedRect( rRect ); 1583cdf0e10cSrcweir aJustifiedRect.Justify(); 1584cdf0e10cSrcweir 1585cdf0e10cSrcweir sal_uInt16 nSourceSize = mpImplPolygon->mnPoints; 1586cdf0e10cSrcweir ImplPolygonPointFilter aPolygon( nSourceSize ); 1587cdf0e10cSrcweir ImplEdgePointFilter aHorzFilter( EDGE_HORZ, aJustifiedRect.Left(), aJustifiedRect.Right(), 1588cdf0e10cSrcweir aPolygon ); 1589cdf0e10cSrcweir ImplEdgePointFilter aVertFilter( EDGE_VERT, aJustifiedRect.Top(), aJustifiedRect.Bottom(), 1590cdf0e10cSrcweir aHorzFilter ); 1591cdf0e10cSrcweir 1592cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSourceSize; i++ ) 1593cdf0e10cSrcweir aVertFilter.Input( mpImplPolygon->mpPointAry[i] ); 1594cdf0e10cSrcweir if ( bPolygon || aVertFilter.IsPolygon() ) 1595cdf0e10cSrcweir aVertFilter.LastPoint(); 1596cdf0e10cSrcweir else 1597cdf0e10cSrcweir aPolygon.LastPoint(); 1598cdf0e10cSrcweir 1599cdf0e10cSrcweir // Alte ImpPolygon-Daten loeschen und die vom ImpPolygonPointFilter 1600cdf0e10cSrcweir // zuweisen 1601cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 1602cdf0e10cSrcweir { 1603cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount > 1 ) 1604cdf0e10cSrcweir mpImplPolygon->mnRefCount--; 1605cdf0e10cSrcweir else 1606cdf0e10cSrcweir delete mpImplPolygon; 1607cdf0e10cSrcweir } 1608cdf0e10cSrcweir mpImplPolygon = aPolygon.mpPoly; 1609cdf0e10cSrcweir } 1610cdf0e10cSrcweir 1611cdf0e10cSrcweir // ----------------------------------------------------------------------- 1612cdf0e10cSrcweir 1613cdf0e10cSrcweir Rectangle Polygon::GetBoundRect() const 1614cdf0e10cSrcweir { 1615cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1616cdf0e10cSrcweir // Removing the assert. Bezier curves have the attribute that each single 1617cdf0e10cSrcweir // curve segment defined by four points can not exit the four-point polygon 1618cdf0e10cSrcweir // defined by that points. This allows to say that the curve segment can also 1619cdf0e10cSrcweir // never leave the Range of it's defining points. 1620cdf0e10cSrcweir // The result is that Polygon::GetBoundRect() may not create the minimal 1621cdf0e10cSrcweir // BoundRect of the Polygon (to get that, use basegfx::B2DPolygon classes), 1622cdf0e10cSrcweir // but will always create a valid BoundRect, at least as long as this method 1623cdf0e10cSrcweir // 'blindly' travels over all points, including control points. 1624cdf0e10cSrcweir // 1625cdf0e10cSrcweir // DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetBoundRect could fail with beziers!" ); 1626cdf0e10cSrcweir 1627cdf0e10cSrcweir sal_uInt16 nCount = mpImplPolygon->mnPoints; 1628cdf0e10cSrcweir if( ! nCount ) 1629cdf0e10cSrcweir return Rectangle(); 1630cdf0e10cSrcweir 1631cdf0e10cSrcweir long nXMin, nXMax, nYMin, nYMax; 1632cdf0e10cSrcweir 1633cdf0e10cSrcweir const Point* pPt = &(mpImplPolygon->mpPointAry[0]); 1634cdf0e10cSrcweir nXMin = nXMax = pPt->X(); 1635cdf0e10cSrcweir nYMin = nYMax = pPt->Y(); 1636cdf0e10cSrcweir 1637cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nCount; i++ ) 1638cdf0e10cSrcweir { 1639cdf0e10cSrcweir pPt = &(mpImplPolygon->mpPointAry[i]); 1640cdf0e10cSrcweir 1641cdf0e10cSrcweir if ( pPt->X() < nXMin ) 1642cdf0e10cSrcweir nXMin = pPt->X(); 1643cdf0e10cSrcweir if ( pPt->X() > nXMax ) 1644cdf0e10cSrcweir nXMax = pPt->X(); 1645cdf0e10cSrcweir if ( pPt->Y() < nYMin ) 1646cdf0e10cSrcweir nYMin = pPt->Y(); 1647cdf0e10cSrcweir if ( pPt->Y() > nYMax ) 1648cdf0e10cSrcweir nYMax = pPt->Y(); 1649cdf0e10cSrcweir } 1650cdf0e10cSrcweir 1651cdf0e10cSrcweir return Rectangle( nXMin, nYMin, nXMax, nYMax ); 1652cdf0e10cSrcweir } 1653cdf0e10cSrcweir 1654cdf0e10cSrcweir // ----------------------------------------------------------------------- 1655cdf0e10cSrcweir 1656cdf0e10cSrcweir double Polygon::GetArea() const 1657cdf0e10cSrcweir { 1658cdf0e10cSrcweir const double fArea = GetSignedArea(); 1659cdf0e10cSrcweir return( ( fArea < 0.0 ) ? -fArea : fArea ); 1660cdf0e10cSrcweir } 1661cdf0e10cSrcweir 1662cdf0e10cSrcweir // ----------------------------------------------------------------------- 1663cdf0e10cSrcweir 1664cdf0e10cSrcweir double Polygon::GetSignedArea() const 1665cdf0e10cSrcweir { 1666cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1667cdf0e10cSrcweir DBG_ASSERT( !mpImplPolygon->mpFlagAry, "GetArea could fail with beziers!" ); 1668cdf0e10cSrcweir 1669cdf0e10cSrcweir double fArea = 0.0; 1670cdf0e10cSrcweir 1671cdf0e10cSrcweir if( mpImplPolygon->mnPoints > 2 ) 1672cdf0e10cSrcweir { 1673cdf0e10cSrcweir const sal_uInt16 nCount1 = mpImplPolygon->mnPoints - 1; 1674cdf0e10cSrcweir 1675cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nCount1; ) 1676cdf0e10cSrcweir { 1677cdf0e10cSrcweir const Point& rPt = mpImplPolygon->mpPointAry[ i ]; 1678cdf0e10cSrcweir const Point& rPt1 = mpImplPolygon->mpPointAry[ ++i ]; 1679cdf0e10cSrcweir fArea += ( rPt.X() - rPt1.X() ) * ( rPt.Y() + rPt1.Y() ); 1680cdf0e10cSrcweir } 1681cdf0e10cSrcweir 1682cdf0e10cSrcweir const Point& rPt = mpImplPolygon->mpPointAry[ nCount1 ]; 1683cdf0e10cSrcweir const Point& rPt0 = mpImplPolygon->mpPointAry[ 0 ]; 1684cdf0e10cSrcweir fArea += ( rPt.X() - rPt0.X() ) * ( rPt.Y() + rPt0.Y() ); 1685cdf0e10cSrcweir } 1686cdf0e10cSrcweir 1687cdf0e10cSrcweir return fArea; 1688cdf0e10cSrcweir } 1689cdf0e10cSrcweir 1690cdf0e10cSrcweir // ----------------------------------------------------------------------- 1691cdf0e10cSrcweir 1692cdf0e10cSrcweir sal_Bool Polygon::IsInside( const Point& rPoint ) const 1693cdf0e10cSrcweir { 1694cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1695cdf0e10cSrcweir DBG_ASSERT( !mpImplPolygon->mpFlagAry, "IsInside could fail with beziers!" ); 1696cdf0e10cSrcweir 1697cdf0e10cSrcweir const Rectangle aBound( GetBoundRect() ); 1698cdf0e10cSrcweir const Line aLine( rPoint, Point( aBound.Right() + 100L, rPoint.Y() ) ); 1699cdf0e10cSrcweir sal_uInt16 nCount = mpImplPolygon->mnPoints; 1700cdf0e10cSrcweir sal_uInt16 nPCounter = 0; 1701cdf0e10cSrcweir 1702cdf0e10cSrcweir if ( ( nCount > 2 ) && aBound.IsInside( rPoint ) ) 1703cdf0e10cSrcweir { 1704cdf0e10cSrcweir Point aPt1( mpImplPolygon->mpPointAry[ 0 ] ); 1705cdf0e10cSrcweir Point aIntersection; 1706cdf0e10cSrcweir Point aLastIntersection; 1707cdf0e10cSrcweir 1708cdf0e10cSrcweir while ( ( aPt1 == mpImplPolygon->mpPointAry[ nCount - 1 ] ) && ( nCount > 3 ) ) 1709cdf0e10cSrcweir nCount--; 1710cdf0e10cSrcweir 1711cdf0e10cSrcweir for ( sal_uInt16 i = 1; i <= nCount; i++ ) 1712cdf0e10cSrcweir { 1713cdf0e10cSrcweir const Point& rPt2 = mpImplPolygon->mpPointAry[ ( i < nCount ) ? i : 0 ]; 1714cdf0e10cSrcweir 1715cdf0e10cSrcweir if ( aLine.Intersection( Line( aPt1, rPt2 ), aIntersection ) ) 1716cdf0e10cSrcweir { 1717cdf0e10cSrcweir // Hiermit verhindern wir das Einfuegen von 1718cdf0e10cSrcweir // doppelten Intersections, die gleich hintereinander folgen 1719cdf0e10cSrcweir if ( nPCounter ) 1720cdf0e10cSrcweir { 1721cdf0e10cSrcweir if ( aIntersection != aLastIntersection ) 1722cdf0e10cSrcweir { 1723cdf0e10cSrcweir aLastIntersection = aIntersection; 1724cdf0e10cSrcweir nPCounter++; 1725cdf0e10cSrcweir } 1726cdf0e10cSrcweir } 1727cdf0e10cSrcweir else 1728cdf0e10cSrcweir { 1729cdf0e10cSrcweir aLastIntersection = aIntersection; 1730cdf0e10cSrcweir nPCounter++; 1731cdf0e10cSrcweir } 1732cdf0e10cSrcweir } 1733cdf0e10cSrcweir 1734cdf0e10cSrcweir aPt1 = rPt2; 1735cdf0e10cSrcweir } 1736cdf0e10cSrcweir } 1737cdf0e10cSrcweir 1738cdf0e10cSrcweir // innerhalb, wenn die Anzahl der Schnittpunkte ungerade ist 1739cdf0e10cSrcweir return ( ( nPCounter & 1 ) == 1 ); 1740cdf0e10cSrcweir } 1741cdf0e10cSrcweir 1742cdf0e10cSrcweir // ----------------------------------------------------------------------- 1743cdf0e10cSrcweir 1744cdf0e10cSrcweir sal_Bool Polygon::IsRightOrientated() const 1745cdf0e10cSrcweir { 1746cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1747cdf0e10cSrcweir return GetSignedArea() >= 0.0; 1748cdf0e10cSrcweir } 1749cdf0e10cSrcweir 1750cdf0e10cSrcweir // ----------------------------------------------------------------------- 1751cdf0e10cSrcweir 1752cdf0e10cSrcweir void Polygon::Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags ) 1753cdf0e10cSrcweir { 1754cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1755cdf0e10cSrcweir ImplMakeUnique(); 1756cdf0e10cSrcweir 1757cdf0e10cSrcweir if( nPos >= mpImplPolygon->mnPoints ) 1758cdf0e10cSrcweir nPos = mpImplPolygon->mnPoints; 1759cdf0e10cSrcweir 1760cdf0e10cSrcweir mpImplPolygon->ImplSplit( nPos, 1 ); 1761cdf0e10cSrcweir mpImplPolygon->mpPointAry[ nPos ] = rPt; 1762cdf0e10cSrcweir 1763cdf0e10cSrcweir if( POLY_NORMAL != eFlags ) 1764cdf0e10cSrcweir { 1765cdf0e10cSrcweir mpImplPolygon->ImplCreateFlagArray(); 1766cdf0e10cSrcweir mpImplPolygon->mpFlagAry[ nPos ] = (sal_uInt8) eFlags; 1767cdf0e10cSrcweir } 1768cdf0e10cSrcweir } 1769cdf0e10cSrcweir 1770cdf0e10cSrcweir // ----------------------------------------------------------------------- 1771cdf0e10cSrcweir 1772cdf0e10cSrcweir void Polygon::Insert( sal_uInt16 nPos, const Polygon& rPoly ) 1773cdf0e10cSrcweir { 1774cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1775cdf0e10cSrcweir const sal_uInt16 nInsertCount = rPoly.mpImplPolygon->mnPoints; 1776cdf0e10cSrcweir 1777cdf0e10cSrcweir if( nInsertCount ) 1778cdf0e10cSrcweir { 1779cdf0e10cSrcweir ImplMakeUnique(); 1780cdf0e10cSrcweir 1781cdf0e10cSrcweir if( nPos >= mpImplPolygon->mnPoints ) 1782cdf0e10cSrcweir nPos = mpImplPolygon->mnPoints; 1783cdf0e10cSrcweir 1784cdf0e10cSrcweir if( rPoly.mpImplPolygon->mpFlagAry ) 1785cdf0e10cSrcweir mpImplPolygon->ImplCreateFlagArray(); 1786cdf0e10cSrcweir 1787cdf0e10cSrcweir mpImplPolygon->ImplSplit( nPos, nInsertCount, rPoly.mpImplPolygon ); 1788cdf0e10cSrcweir } 1789cdf0e10cSrcweir } 1790cdf0e10cSrcweir 1791cdf0e10cSrcweir // ----------------------------------------------------------------------- 1792cdf0e10cSrcweir 1793cdf0e10cSrcweir void Polygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount ) 1794cdf0e10cSrcweir { 1795cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1796cdf0e10cSrcweir if( nCount && ( nPos < mpImplPolygon->mnPoints ) ) 1797cdf0e10cSrcweir { 1798cdf0e10cSrcweir ImplMakeUnique(); 1799cdf0e10cSrcweir mpImplPolygon->ImplRemove( nPos, nCount ); 1800cdf0e10cSrcweir } 1801cdf0e10cSrcweir } 1802cdf0e10cSrcweir 1803cdf0e10cSrcweir // ----------------------------------------------------------------------- 1804cdf0e10cSrcweir 1805cdf0e10cSrcweir Point& Polygon::operator[]( sal_uInt16 nPos ) 1806cdf0e10cSrcweir { 1807cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1808cdf0e10cSrcweir DBG_ASSERT( nPos < mpImplPolygon->mnPoints, "Polygon::[]: nPos >= nPoints" ); 1809cdf0e10cSrcweir 1810cdf0e10cSrcweir ImplMakeUnique(); 1811cdf0e10cSrcweir return mpImplPolygon->mpPointAry[nPos]; 1812cdf0e10cSrcweir } 1813cdf0e10cSrcweir 1814cdf0e10cSrcweir // ----------------------------------------------------------------------- 1815cdf0e10cSrcweir 1816cdf0e10cSrcweir Polygon& Polygon::operator=( const Polygon& rPoly ) 1817cdf0e10cSrcweir { 1818cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1819cdf0e10cSrcweir DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1820cdf0e10cSrcweir DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" ); 1821cdf0e10cSrcweir 1822cdf0e10cSrcweir // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann 1823cdf0e10cSrcweir // RefCount == 0 fuer statische Objekte 1824cdf0e10cSrcweir if ( rPoly.mpImplPolygon->mnRefCount ) 1825cdf0e10cSrcweir rPoly.mpImplPolygon->mnRefCount++; 1826cdf0e10cSrcweir 1827cdf0e10cSrcweir // Wenn es keine statischen ImpDaten sind, dann loeschen, wenn es 1828cdf0e10cSrcweir // die letzte Referenz ist, sonst Referenzcounter decrementieren 1829cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount ) 1830cdf0e10cSrcweir { 1831cdf0e10cSrcweir if ( mpImplPolygon->mnRefCount > 1 ) 1832cdf0e10cSrcweir mpImplPolygon->mnRefCount--; 1833cdf0e10cSrcweir else 1834cdf0e10cSrcweir delete mpImplPolygon; 1835cdf0e10cSrcweir } 1836cdf0e10cSrcweir 1837cdf0e10cSrcweir mpImplPolygon = rPoly.mpImplPolygon; 1838cdf0e10cSrcweir return *this; 1839cdf0e10cSrcweir } 1840cdf0e10cSrcweir 1841cdf0e10cSrcweir // ----------------------------------------------------------------------- 1842cdf0e10cSrcweir 1843cdf0e10cSrcweir sal_Bool Polygon::operator==( const Polygon& rPoly ) const 1844cdf0e10cSrcweir { 1845cdf0e10cSrcweir DBG_CHKTHIS( Polygon, NULL ); 1846cdf0e10cSrcweir DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1847cdf0e10cSrcweir 1848cdf0e10cSrcweir if ( (rPoly.mpImplPolygon == mpImplPolygon) ) 1849cdf0e10cSrcweir return sal_True; 1850cdf0e10cSrcweir else 1851cdf0e10cSrcweir return sal_False; 1852cdf0e10cSrcweir } 1853cdf0e10cSrcweir 1854cdf0e10cSrcweir // ----------------------------------------------------------------------- 1855cdf0e10cSrcweir 1856cdf0e10cSrcweir sal_Bool Polygon::IsEqual( const Polygon& rPoly ) const 1857cdf0e10cSrcweir { 1858cdf0e10cSrcweir sal_Bool bIsEqual = sal_True;; 1859cdf0e10cSrcweir sal_uInt16 i; 1860cdf0e10cSrcweir if ( GetSize() != rPoly.GetSize() ) 1861cdf0e10cSrcweir bIsEqual = sal_False; 1862cdf0e10cSrcweir else 1863cdf0e10cSrcweir { 1864cdf0e10cSrcweir for ( i = 0; i < GetSize(); i++ ) 1865cdf0e10cSrcweir { 1866cdf0e10cSrcweir if ( ( GetPoint( i ) != rPoly.GetPoint( i ) ) || 1867cdf0e10cSrcweir ( GetFlags( i ) != rPoly.GetFlags( i ) ) ) 1868cdf0e10cSrcweir { 1869cdf0e10cSrcweir bIsEqual = sal_False; 1870cdf0e10cSrcweir break; 1871cdf0e10cSrcweir } 1872cdf0e10cSrcweir } 1873cdf0e10cSrcweir } 1874cdf0e10cSrcweir return bIsEqual; 1875cdf0e10cSrcweir } 1876cdf0e10cSrcweir 1877cdf0e10cSrcweir // ----------------------------------------------------------------------- 1878cdf0e10cSrcweir 1879cdf0e10cSrcweir SvStream& operator>>( SvStream& rIStream, Polygon& rPoly ) 1880cdf0e10cSrcweir { 1881cdf0e10cSrcweir DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1882cdf0e10cSrcweir DBG_ASSERTWARNING( rIStream.GetVersion(), "Polygon::>> - Solar-Version not set on rIStream" ); 1883cdf0e10cSrcweir 1884cdf0e10cSrcweir sal_uInt16 i; 1885cdf0e10cSrcweir sal_uInt16 nStart; 1886cdf0e10cSrcweir sal_uInt16 nCurPoints; 1887cdf0e10cSrcweir sal_uInt16 nPoints; 1888cdf0e10cSrcweir unsigned char bShort; 1889cdf0e10cSrcweir short nShortX; 1890cdf0e10cSrcweir short nShortY; 1891cdf0e10cSrcweir long nLongX; 1892cdf0e10cSrcweir long nLongY; 1893cdf0e10cSrcweir 1894cdf0e10cSrcweir // Anzahl der Punkte einlesen und Array erzeugen 1895cdf0e10cSrcweir rIStream >> nPoints; 1896cdf0e10cSrcweir if ( rPoly.mpImplPolygon->mnRefCount != 1 ) 1897cdf0e10cSrcweir { 1898cdf0e10cSrcweir if ( rPoly.mpImplPolygon->mnRefCount ) 1899cdf0e10cSrcweir rPoly.mpImplPolygon->mnRefCount--; 1900cdf0e10cSrcweir rPoly.mpImplPolygon = new ImplPolygon( nPoints ); 1901cdf0e10cSrcweir } 1902cdf0e10cSrcweir else 1903cdf0e10cSrcweir rPoly.mpImplPolygon->ImplSetSize( nPoints, sal_False ); 1904cdf0e10cSrcweir 1905cdf0e10cSrcweir // Je nach CompressMode das Polygon einlesen 1906cdf0e10cSrcweir if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL ) 1907cdf0e10cSrcweir { 1908cdf0e10cSrcweir i = 0; 1909cdf0e10cSrcweir while ( i < nPoints ) 1910cdf0e10cSrcweir { 1911cdf0e10cSrcweir rIStream >> bShort >> nCurPoints; 1912cdf0e10cSrcweir 1913cdf0e10cSrcweir if ( bShort ) 1914cdf0e10cSrcweir { 1915cdf0e10cSrcweir for ( nStart = i; i < nStart+nCurPoints; i++ ) 1916cdf0e10cSrcweir { 1917cdf0e10cSrcweir rIStream >> nShortX >> nShortY; 1918cdf0e10cSrcweir rPoly.mpImplPolygon->mpPointAry[i].X() = nShortX; 1919cdf0e10cSrcweir rPoly.mpImplPolygon->mpPointAry[i].Y() = nShortY; 1920cdf0e10cSrcweir } 1921cdf0e10cSrcweir } 1922cdf0e10cSrcweir else 1923cdf0e10cSrcweir { 1924cdf0e10cSrcweir for ( nStart = i; i < nStart+nCurPoints; i++ ) 1925cdf0e10cSrcweir { 1926cdf0e10cSrcweir rIStream >> nLongX >> nLongY; 1927cdf0e10cSrcweir rPoly.mpImplPolygon->mpPointAry[i].X() = nLongX; 1928cdf0e10cSrcweir rPoly.mpImplPolygon->mpPointAry[i].Y() = nLongY; 1929cdf0e10cSrcweir } 1930cdf0e10cSrcweir } 1931cdf0e10cSrcweir } 1932cdf0e10cSrcweir } 1933cdf0e10cSrcweir else 1934cdf0e10cSrcweir { 1935cdf0e10cSrcweir // Feststellen, ob ueber die Operatoren geschrieben werden muss 1936cdf0e10cSrcweir #if (SAL_TYPES_SIZEOFLONG) != 4 1937cdf0e10cSrcweir if ( 1 ) 1938cdf0e10cSrcweir #else 1939cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 1940cdf0e10cSrcweir if ( rIStream.GetNumberFormatInt() != NUMBERFORMAT_INT_BIGENDIAN ) 1941cdf0e10cSrcweir #else 1942cdf0e10cSrcweir if ( rIStream.GetNumberFormatInt() != NUMBERFORMAT_INT_LITTLEENDIAN ) 1943cdf0e10cSrcweir #endif 1944cdf0e10cSrcweir #endif 1945cdf0e10cSrcweir { 1946cdf0e10cSrcweir for( i = 0; i < nPoints; i++ ) 1947cdf0e10cSrcweir { 1948cdf0e10cSrcweir rIStream >> rPoly.mpImplPolygon->mpPointAry[i].X() 1949cdf0e10cSrcweir >> rPoly.mpImplPolygon->mpPointAry[i].Y(); 1950cdf0e10cSrcweir } 1951cdf0e10cSrcweir } 1952cdf0e10cSrcweir else 1953cdf0e10cSrcweir rIStream.Read( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) ); 1954cdf0e10cSrcweir } 1955cdf0e10cSrcweir 1956cdf0e10cSrcweir return rIStream; 1957cdf0e10cSrcweir } 1958cdf0e10cSrcweir 1959cdf0e10cSrcweir // ----------------------------------------------------------------------- 1960cdf0e10cSrcweir 1961cdf0e10cSrcweir SvStream& operator<<( SvStream& rOStream, const Polygon& rPoly ) 1962cdf0e10cSrcweir { 1963cdf0e10cSrcweir DBG_CHKOBJ( &rPoly, Polygon, NULL ); 1964cdf0e10cSrcweir DBG_ASSERTWARNING( rOStream.GetVersion(), "Polygon::<< - Solar-Version not set on rOStream" ); 1965cdf0e10cSrcweir 1966cdf0e10cSrcweir unsigned char bShort; 1967cdf0e10cSrcweir unsigned char bCurShort; 1968cdf0e10cSrcweir sal_uInt16 nStart; 1969cdf0e10cSrcweir sal_uInt16 i; 1970cdf0e10cSrcweir sal_uInt16 nPoints = rPoly.GetSize(); 1971cdf0e10cSrcweir 1972cdf0e10cSrcweir // Anzahl der Punkte rausschreiben 1973cdf0e10cSrcweir rOStream << nPoints; 1974cdf0e10cSrcweir 1975cdf0e10cSrcweir // Je nach CompressMode das Polygon rausschreiben 1976cdf0e10cSrcweir if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL ) 1977cdf0e10cSrcweir { 1978cdf0e10cSrcweir i = 0; 1979cdf0e10cSrcweir while ( i < nPoints ) 1980cdf0e10cSrcweir { 1981cdf0e10cSrcweir nStart = i; 1982cdf0e10cSrcweir 1983cdf0e10cSrcweir // Feststellen, welcher Typ geschrieben werden soll 1984cdf0e10cSrcweir if ( ((rPoly.mpImplPolygon->mpPointAry[nStart].X() >= SHRT_MIN) && 1985cdf0e10cSrcweir (rPoly.mpImplPolygon->mpPointAry[nStart].X() <= SHRT_MAX)) && 1986cdf0e10cSrcweir ((rPoly.mpImplPolygon->mpPointAry[nStart].Y() >= SHRT_MIN) && 1987cdf0e10cSrcweir (rPoly.mpImplPolygon->mpPointAry[nStart].Y() <= SHRT_MAX)) ) 1988cdf0e10cSrcweir bShort = sal_True; 1989cdf0e10cSrcweir else 1990cdf0e10cSrcweir bShort = sal_False; 1991cdf0e10cSrcweir while ( i < nPoints ) 1992cdf0e10cSrcweir { 1993cdf0e10cSrcweir // Feststellen, welcher Typ geschrieben werden soll 1994cdf0e10cSrcweir if ( ((rPoly.mpImplPolygon->mpPointAry[nStart].X() >= SHRT_MIN) && 1995cdf0e10cSrcweir (rPoly.mpImplPolygon->mpPointAry[nStart].X() <= SHRT_MAX)) && 1996cdf0e10cSrcweir ((rPoly.mpImplPolygon->mpPointAry[nStart].Y() >= SHRT_MIN) && 1997cdf0e10cSrcweir (rPoly.mpImplPolygon->mpPointAry[nStart].Y() <= SHRT_MAX)) ) 1998cdf0e10cSrcweir bCurShort = sal_True; 1999cdf0e10cSrcweir else 2000cdf0e10cSrcweir bCurShort = sal_False; 2001cdf0e10cSrcweir 2002cdf0e10cSrcweir // Wenn sich die Werte in einen anderen Bereich begeben, 2003cdf0e10cSrcweir // muessen wir neu rausschreiben 2004cdf0e10cSrcweir if ( bCurShort != bShort ) 2005cdf0e10cSrcweir { 2006cdf0e10cSrcweir bShort = bCurShort; 2007cdf0e10cSrcweir break; 2008cdf0e10cSrcweir } 2009cdf0e10cSrcweir 2010cdf0e10cSrcweir i++; 2011cdf0e10cSrcweir } 2012cdf0e10cSrcweir 2013cdf0e10cSrcweir rOStream << bShort << (sal_uInt16)(i-nStart); 2014cdf0e10cSrcweir 2015cdf0e10cSrcweir if ( bShort ) 2016cdf0e10cSrcweir { 2017cdf0e10cSrcweir for( ; nStart < i; nStart++ ) 2018cdf0e10cSrcweir { 2019cdf0e10cSrcweir rOStream << (short)rPoly.mpImplPolygon->mpPointAry[nStart].X() 2020cdf0e10cSrcweir << (short)rPoly.mpImplPolygon->mpPointAry[nStart].Y(); 2021cdf0e10cSrcweir } 2022cdf0e10cSrcweir } 2023cdf0e10cSrcweir else 2024cdf0e10cSrcweir { 2025cdf0e10cSrcweir for( ; nStart < i; nStart++ ) 2026cdf0e10cSrcweir { 2027cdf0e10cSrcweir rOStream << rPoly.mpImplPolygon->mpPointAry[nStart].X() 2028cdf0e10cSrcweir << rPoly.mpImplPolygon->mpPointAry[nStart].Y(); 2029cdf0e10cSrcweir } 2030cdf0e10cSrcweir } 2031cdf0e10cSrcweir } 2032cdf0e10cSrcweir } 2033cdf0e10cSrcweir else 2034cdf0e10cSrcweir { 2035cdf0e10cSrcweir // Feststellen, ob ueber die Operatoren geschrieben werden muss 2036cdf0e10cSrcweir #if (SAL_TYPES_SIZEOFLONG) != 4 2037cdf0e10cSrcweir if ( 1 ) 2038cdf0e10cSrcweir #else 2039cdf0e10cSrcweir #ifdef OSL_BIGENDIAN 2040cdf0e10cSrcweir if ( rOStream.GetNumberFormatInt() != NUMBERFORMAT_INT_BIGENDIAN ) 2041cdf0e10cSrcweir #else 2042cdf0e10cSrcweir if ( rOStream.GetNumberFormatInt() != NUMBERFORMAT_INT_LITTLEENDIAN ) 2043cdf0e10cSrcweir #endif 2044cdf0e10cSrcweir #endif 2045cdf0e10cSrcweir { 2046cdf0e10cSrcweir for( i = 0; i < nPoints; i++ ) 2047cdf0e10cSrcweir { 2048cdf0e10cSrcweir rOStream << rPoly.mpImplPolygon->mpPointAry[i].X() 2049cdf0e10cSrcweir << rPoly.mpImplPolygon->mpPointAry[i].Y(); 2050cdf0e10cSrcweir } 2051cdf0e10cSrcweir } 2052cdf0e10cSrcweir else 2053cdf0e10cSrcweir { 2054cdf0e10cSrcweir if ( nPoints ) 2055cdf0e10cSrcweir rOStream.Write( rPoly.mpImplPolygon->mpPointAry, nPoints*sizeof(Point) ); 2056cdf0e10cSrcweir } 2057cdf0e10cSrcweir } 2058cdf0e10cSrcweir 2059cdf0e10cSrcweir return rOStream; 2060cdf0e10cSrcweir } 2061cdf0e10cSrcweir 2062cdf0e10cSrcweir // ----------------------------------------------------------------------- 2063cdf0e10cSrcweir 2064cdf0e10cSrcweir void Polygon::ImplRead( SvStream& rIStream ) 2065cdf0e10cSrcweir { 2066cdf0e10cSrcweir sal_uInt8 bHasPolyFlags; 2067cdf0e10cSrcweir 2068cdf0e10cSrcweir rIStream >> *this 2069cdf0e10cSrcweir >> bHasPolyFlags; 2070cdf0e10cSrcweir 2071cdf0e10cSrcweir if ( bHasPolyFlags ) 2072cdf0e10cSrcweir { 2073cdf0e10cSrcweir mpImplPolygon->mpFlagAry = new sal_uInt8[ mpImplPolygon->mnPoints ]; 2074cdf0e10cSrcweir rIStream.Read( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints ); 2075cdf0e10cSrcweir } 2076cdf0e10cSrcweir } 2077cdf0e10cSrcweir 2078cdf0e10cSrcweir // ----------------------------------------------------------------------- 2079cdf0e10cSrcweir 2080cdf0e10cSrcweir void Polygon::Read( SvStream& rIStream ) 2081cdf0e10cSrcweir { 2082cdf0e10cSrcweir VersionCompat aCompat( rIStream, STREAM_READ ); 2083cdf0e10cSrcweir 2084cdf0e10cSrcweir ImplRead( rIStream ); 2085cdf0e10cSrcweir } 2086cdf0e10cSrcweir 2087cdf0e10cSrcweir // ----------------------------------------------------------------------- 2088cdf0e10cSrcweir 2089cdf0e10cSrcweir void Polygon::ImplWrite( SvStream& rOStream ) const 2090cdf0e10cSrcweir { 2091cdf0e10cSrcweir sal_uInt8 bHasPolyFlags = mpImplPolygon->mpFlagAry != NULL; 2092cdf0e10cSrcweir rOStream << *this 2093cdf0e10cSrcweir << bHasPolyFlags; 2094cdf0e10cSrcweir 2095cdf0e10cSrcweir if ( bHasPolyFlags ) 2096cdf0e10cSrcweir rOStream.Write( mpImplPolygon->mpFlagAry, mpImplPolygon->mnPoints ); 2097cdf0e10cSrcweir } 2098cdf0e10cSrcweir 2099cdf0e10cSrcweir // ----------------------------------------------------------------------- 2100cdf0e10cSrcweir 2101cdf0e10cSrcweir void Polygon::Write( SvStream& rOStream ) const 2102cdf0e10cSrcweir { 2103cdf0e10cSrcweir VersionCompat aCompat( rOStream, STREAM_WRITE, 1 ); 2104cdf0e10cSrcweir 2105cdf0e10cSrcweir ImplWrite( rOStream ); 2106cdf0e10cSrcweir } 2107cdf0e10cSrcweir 2108cdf0e10cSrcweir // ----------------------------------------------------------------------- 2109cdf0e10cSrcweir // #i74631# numerical correction method for B2DPolygon 2110cdf0e10cSrcweir void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8 nCFlag) 2111cdf0e10cSrcweir { 2112cdf0e10cSrcweir const sal_uInt32 nPointCount(roPolygon.count()); 2113cdf0e10cSrcweir OSL_ENSURE(nIndex < nPointCount, "impCorrectContinuity: index access out of range (!)"); 2114cdf0e10cSrcweir 2115cdf0e10cSrcweir if(nIndex < nPointCount && (POLY_SMOOTH == nCFlag || POLY_SYMMTR == nCFlag)) 2116cdf0e10cSrcweir { 2117cdf0e10cSrcweir if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex)) 2118cdf0e10cSrcweir { 2119cdf0e10cSrcweir const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex)); 2120cdf0e10cSrcweir 2121cdf0e10cSrcweir if(POLY_SMOOTH == nCFlag) 2122cdf0e10cSrcweir { 2123cdf0e10cSrcweir // C1: apply inverse direction of prev to next, keep length of next 2124cdf0e10cSrcweir const basegfx::B2DVector aOriginalNext(roPolygon.getNextControlPoint(nIndex) - aPoint); 2125cdf0e10cSrcweir basegfx::B2DVector aNewNext(aPoint - roPolygon.getPrevControlPoint(nIndex)); 2126cdf0e10cSrcweir 2127cdf0e10cSrcweir aNewNext.setLength(aOriginalNext.getLength()); 2128cdf0e10cSrcweir roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aNewNext)); 2129cdf0e10cSrcweir } 2130cdf0e10cSrcweir else // POLY_SYMMTR 2131cdf0e10cSrcweir { 2132cdf0e10cSrcweir // C2: apply inverse control point to next 2133cdf0e10cSrcweir roPolygon.setNextControlPoint(nIndex, (2.0 * aPoint) - roPolygon.getPrevControlPoint(nIndex)); 2134cdf0e10cSrcweir } 2135cdf0e10cSrcweir } 2136cdf0e10cSrcweir } 2137cdf0e10cSrcweir } 2138cdf0e10cSrcweir 2139cdf0e10cSrcweir // ----------------------------------------------------------------------- 2140cdf0e10cSrcweir // convert to basegfx::B2DPolygon and return 2141cdf0e10cSrcweir basegfx::B2DPolygon Polygon::getB2DPolygon() const 2142cdf0e10cSrcweir { 2143cdf0e10cSrcweir basegfx::B2DPolygon aRetval; 2144cdf0e10cSrcweir const sal_uInt16 nCount(mpImplPolygon->mnPoints); 2145cdf0e10cSrcweir 2146cdf0e10cSrcweir if(nCount) 2147cdf0e10cSrcweir { 2148cdf0e10cSrcweir if(mpImplPolygon->mpFlagAry) 2149cdf0e10cSrcweir { 2150cdf0e10cSrcweir // handling for curves. Add start point 2151cdf0e10cSrcweir const Point aStartPoint(mpImplPolygon->mpPointAry[0]); 2152cdf0e10cSrcweir sal_uInt8 nPointFlag(mpImplPolygon->mpFlagAry[0]); 2153cdf0e10cSrcweir aRetval.append(basegfx::B2DPoint(aStartPoint.X(), aStartPoint.Y())); 2154cdf0e10cSrcweir Point aControlA, aControlB; 2155cdf0e10cSrcweir 2156cdf0e10cSrcweir for(sal_uInt16 a(1); a < nCount;) 2157cdf0e10cSrcweir { 2158cdf0e10cSrcweir bool bControlA(false); 2159cdf0e10cSrcweir bool bControlB(false); 2160cdf0e10cSrcweir 2161cdf0e10cSrcweir if(POLY_CONTROL == mpImplPolygon->mpFlagAry[a]) 2162cdf0e10cSrcweir { 2163cdf0e10cSrcweir aControlA = mpImplPolygon->mpPointAry[a++]; 2164cdf0e10cSrcweir bControlA = true; 2165cdf0e10cSrcweir } 2166cdf0e10cSrcweir 2167cdf0e10cSrcweir if(a < nCount && POLY_CONTROL == mpImplPolygon->mpFlagAry[a]) 2168cdf0e10cSrcweir { 2169cdf0e10cSrcweir aControlB = mpImplPolygon->mpPointAry[a++]; 2170cdf0e10cSrcweir bControlB = true; 2171cdf0e10cSrcweir } 2172cdf0e10cSrcweir 2173cdf0e10cSrcweir // assert invalid polygons 2174cdf0e10cSrcweir OSL_ENSURE(bControlA == bControlB, "Polygon::getB2DPolygon: Invalid source polygon (!)"); 2175cdf0e10cSrcweir 2176cdf0e10cSrcweir if(a < nCount) 2177cdf0e10cSrcweir { 2178cdf0e10cSrcweir const Point aEndPoint(mpImplPolygon->mpPointAry[a]); 2179cdf0e10cSrcweir 2180cdf0e10cSrcweir if(bControlA) 2181cdf0e10cSrcweir { 2182cdf0e10cSrcweir // bezier edge, add 2183cdf0e10cSrcweir aRetval.appendBezierSegment( 2184cdf0e10cSrcweir basegfx::B2DPoint(aControlA.X(), aControlA.Y()), 2185cdf0e10cSrcweir basegfx::B2DPoint(aControlB.X(), aControlB.Y()), 2186cdf0e10cSrcweir basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y())); 2187cdf0e10cSrcweir 2188cdf0e10cSrcweir impCorrectContinuity(aRetval, aRetval.count() - 2, nPointFlag); 2189cdf0e10cSrcweir } 2190cdf0e10cSrcweir else 2191cdf0e10cSrcweir { 2192cdf0e10cSrcweir // no bezier edge, add end point 2193cdf0e10cSrcweir aRetval.append(basegfx::B2DPoint(aEndPoint.X(), aEndPoint.Y())); 2194cdf0e10cSrcweir } 2195cdf0e10cSrcweir 2196cdf0e10cSrcweir nPointFlag = mpImplPolygon->mpFlagAry[a++]; 2197cdf0e10cSrcweir } 2198cdf0e10cSrcweir } 2199cdf0e10cSrcweir 2200cdf0e10cSrcweir // if exist, remove double first/last points, set closed and correct control points 2201cdf0e10cSrcweir basegfx::tools::checkClosed(aRetval); 2202cdf0e10cSrcweir 2203cdf0e10cSrcweir if(aRetval.isClosed()) 2204cdf0e10cSrcweir { 2205cdf0e10cSrcweir // closeWithGeometryChange did really close, so last point(s) were removed. 2206cdf0e10cSrcweir // Correct the continuity in the changed point 2207cdf0e10cSrcweir impCorrectContinuity(aRetval, 0, mpImplPolygon->mpFlagAry[0]); 2208cdf0e10cSrcweir } 2209cdf0e10cSrcweir } 2210cdf0e10cSrcweir else 2211cdf0e10cSrcweir { 2212cdf0e10cSrcweir // extra handling for non-curves (most-used case) for speedup 2213cdf0e10cSrcweir for(sal_uInt16 a(0); a < nCount; a++) 2214cdf0e10cSrcweir { 2215cdf0e10cSrcweir // get point and add 2216cdf0e10cSrcweir const Point aPoint(mpImplPolygon->mpPointAry[a]); 2217cdf0e10cSrcweir aRetval.append(basegfx::B2DPoint(aPoint.X(), aPoint.Y())); 2218cdf0e10cSrcweir } 2219cdf0e10cSrcweir 2220cdf0e10cSrcweir // set closed flag 2221cdf0e10cSrcweir basegfx::tools::checkClosed(aRetval); 2222cdf0e10cSrcweir } 2223cdf0e10cSrcweir } 2224cdf0e10cSrcweir 2225cdf0e10cSrcweir return aRetval; 2226cdf0e10cSrcweir } 2227cdf0e10cSrcweir 2228cdf0e10cSrcweir // ----------------------------------------------------------------------- 2229cdf0e10cSrcweir // constructor to convert from basegfx::B2DPolygon 2230cdf0e10cSrcweir // #i76891# Needed to change from adding all control points (even for unused 2231cdf0e10cSrcweir // edges) and creating a fixed-size Polygon in the first run to creating the 2232cdf0e10cSrcweir // minimal Polygon. This requires a temporary Point- and Flag-Array for curves 2233cdf0e10cSrcweir // and a memcopy at ImplPolygon creation, but contains no zero-controlpoints 2234cdf0e10cSrcweir // for straight edges. 2235cdf0e10cSrcweir Polygon::Polygon(const basegfx::B2DPolygon& rPolygon) 2236cdf0e10cSrcweir : mpImplPolygon(0) 2237cdf0e10cSrcweir { 2238cdf0e10cSrcweir DBG_CTOR( Polygon, NULL ); 2239cdf0e10cSrcweir 2240cdf0e10cSrcweir const bool bCurve(rPolygon.areControlPointsUsed()); 2241cdf0e10cSrcweir const bool bClosed(rPolygon.isClosed()); 2242cdf0e10cSrcweir sal_uInt32 nB2DLocalCount(rPolygon.count()); 2243cdf0e10cSrcweir 2244cdf0e10cSrcweir if(bCurve) 2245cdf0e10cSrcweir { 2246cdf0e10cSrcweir // #127979# Reduce source point count hard to the limit of the tools Polygon 2247cdf0e10cSrcweir if(nB2DLocalCount > ((0x0000ffff / 3L) - 1L)) 2248cdf0e10cSrcweir { 2249cdf0e10cSrcweir DBG_ERROR("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)"); 2250cdf0e10cSrcweir nB2DLocalCount = ((0x0000ffff / 3L) - 1L); 2251cdf0e10cSrcweir } 2252cdf0e10cSrcweir 2253cdf0e10cSrcweir // calculate target point count 2254cdf0e10cSrcweir const sal_uInt32 nLoopCount(bClosed ? nB2DLocalCount : (nB2DLocalCount ? nB2DLocalCount - 1L : 0L )); 2255cdf0e10cSrcweir 2256cdf0e10cSrcweir if(nLoopCount) 2257cdf0e10cSrcweir { 2258cdf0e10cSrcweir // calculate maximum array size and allocate; prepare insert index 2259cdf0e10cSrcweir const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1); 2260cdf0e10cSrcweir mpImplPolygon = new ImplPolygon(static_cast< sal_uInt16 >(nMaxTargetCount), true); 2261cdf0e10cSrcweir 2262cdf0e10cSrcweir // prepare insert index and current point 2263cdf0e10cSrcweir sal_uInt32 nArrayInsert(0); 2264cdf0e10cSrcweir basegfx::B2DCubicBezier aBezier; 2265cdf0e10cSrcweir aBezier.setStartPoint(rPolygon.getB2DPoint(0)); 2266cdf0e10cSrcweir 2267cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nLoopCount; a++) 2268cdf0e10cSrcweir { 2269cdf0e10cSrcweir // add current point (always) and remember StartPointIndex for evtl. later corrections 2270cdf0e10cSrcweir const Point aStartPoint(FRound(aBezier.getStartPoint().getX()), FRound(aBezier.getStartPoint().getY())); 2271cdf0e10cSrcweir const sal_uInt32 nStartPointIndex(nArrayInsert); 2272cdf0e10cSrcweir mpImplPolygon->mpPointAry[nStartPointIndex] = aStartPoint; 2273cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_NORMAL; 2274cdf0e10cSrcweir nArrayInsert++; 2275cdf0e10cSrcweir 2276cdf0e10cSrcweir // prepare next segment 2277cdf0e10cSrcweir const sal_uInt32 nNextIndex((a + 1) % nB2DLocalCount); 2278cdf0e10cSrcweir aBezier.setEndPoint(rPolygon.getB2DPoint(nNextIndex)); 2279cdf0e10cSrcweir aBezier.setControlPointA(rPolygon.getNextControlPoint(a)); 2280cdf0e10cSrcweir aBezier.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex)); 2281cdf0e10cSrcweir 2282cdf0e10cSrcweir if(aBezier.isBezier()) 2283cdf0e10cSrcweir { 2284cdf0e10cSrcweir // if one is used, add always two control points due to the old schema 2285cdf0e10cSrcweir mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointA().getX()), FRound(aBezier.getControlPointA().getY())); 2286cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL; 2287cdf0e10cSrcweir nArrayInsert++; 2288cdf0e10cSrcweir 2289cdf0e10cSrcweir mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointB().getX()), FRound(aBezier.getControlPointB().getY())); 2290cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_CONTROL; 2291cdf0e10cSrcweir nArrayInsert++; 2292cdf0e10cSrcweir } 2293cdf0e10cSrcweir 2294cdf0e10cSrcweir // test continuity with previous control point to set flag value 2295cdf0e10cSrcweir if(aBezier.getControlPointA() != aBezier.getStartPoint() && (bClosed || a)) 2296cdf0e10cSrcweir { 2297cdf0e10cSrcweir const basegfx::B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a)); 2298cdf0e10cSrcweir 2299cdf0e10cSrcweir if(basegfx::CONTINUITY_C1 == eCont) 2300cdf0e10cSrcweir { 2301cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SMOOTH; 2302cdf0e10cSrcweir } 2303cdf0e10cSrcweir else if(basegfx::CONTINUITY_C2 == eCont) 2304cdf0e10cSrcweir { 2305cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nStartPointIndex] = (sal_uInt8)POLY_SYMMTR; 2306cdf0e10cSrcweir } 2307cdf0e10cSrcweir } 2308cdf0e10cSrcweir 2309cdf0e10cSrcweir // prepare next polygon step 2310cdf0e10cSrcweir aBezier.setStartPoint(aBezier.getEndPoint()); 2311cdf0e10cSrcweir } 2312cdf0e10cSrcweir 2313cdf0e10cSrcweir if(bClosed) 2314cdf0e10cSrcweir { 2315cdf0e10cSrcweir // add first point again as closing point due to old definition 2316cdf0e10cSrcweir mpImplPolygon->mpPointAry[nArrayInsert] = mpImplPolygon->mpPointAry[0]; 2317cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL; 2318cdf0e10cSrcweir nArrayInsert++; 2319cdf0e10cSrcweir } 2320cdf0e10cSrcweir else 2321cdf0e10cSrcweir { 2322cdf0e10cSrcweir // add last point as closing point 2323cdf0e10cSrcweir const basegfx::B2DPoint aClosingPoint(rPolygon.getB2DPoint(nB2DLocalCount - 1L)); 2324cdf0e10cSrcweir const Point aEnd(FRound(aClosingPoint.getX()), FRound(aClosingPoint.getY())); 2325cdf0e10cSrcweir mpImplPolygon->mpPointAry[nArrayInsert] = aEnd; 2326cdf0e10cSrcweir mpImplPolygon->mpFlagAry[nArrayInsert] = (sal_uInt8)POLY_NORMAL; 2327cdf0e10cSrcweir nArrayInsert++; 2328cdf0e10cSrcweir } 2329cdf0e10cSrcweir 2330cdf0e10cSrcweir DBG_ASSERT(nArrayInsert <= nMaxTargetCount, "Polygon::Polygon from basegfx::B2DPolygon: wrong max point count estimation (!)"); 2331cdf0e10cSrcweir 2332cdf0e10cSrcweir if(nArrayInsert != nMaxTargetCount) 2333cdf0e10cSrcweir { 2334cdf0e10cSrcweir mpImplPolygon->ImplSetSize(static_cast< sal_uInt16 >(nArrayInsert), true); 2335cdf0e10cSrcweir } 2336cdf0e10cSrcweir } 2337cdf0e10cSrcweir } 2338cdf0e10cSrcweir else 2339cdf0e10cSrcweir { 2340cdf0e10cSrcweir // #127979# Reduce source point count hard to the limit of the tools Polygon 2341cdf0e10cSrcweir if(nB2DLocalCount > (0x0000ffff - 1L)) 2342cdf0e10cSrcweir { 2343cdf0e10cSrcweir DBG_ERROR("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)"); 2344cdf0e10cSrcweir nB2DLocalCount = (0x0000ffff - 1L); 2345cdf0e10cSrcweir } 2346cdf0e10cSrcweir 2347cdf0e10cSrcweir if(nB2DLocalCount) 2348cdf0e10cSrcweir { 2349cdf0e10cSrcweir // point list creation 2350cdf0e10cSrcweir const sal_uInt32 nTargetCount(nB2DLocalCount + (bClosed ? 1L : 0L)); 2351cdf0e10cSrcweir mpImplPolygon = new ImplPolygon( static_cast< sal_uInt16 >(nTargetCount) ); 2352cdf0e10cSrcweir sal_uInt16 nIndex(0); 2353cdf0e10cSrcweir 2354cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nB2DLocalCount; a++) 2355cdf0e10cSrcweir { 2356cdf0e10cSrcweir basegfx::B2DPoint aB2DPoint(rPolygon.getB2DPoint(a)); 2357cdf0e10cSrcweir Point aPoint(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY())); 2358cdf0e10cSrcweir mpImplPolygon->mpPointAry[nIndex++] = aPoint; 2359cdf0e10cSrcweir } 2360cdf0e10cSrcweir 2361cdf0e10cSrcweir if(bClosed) 2362cdf0e10cSrcweir { 2363cdf0e10cSrcweir // add first point as closing point 2364cdf0e10cSrcweir mpImplPolygon->mpPointAry[nIndex] = mpImplPolygon->mpPointAry[0]; 2365cdf0e10cSrcweir } 2366cdf0e10cSrcweir } 2367cdf0e10cSrcweir } 2368cdf0e10cSrcweir 2369cdf0e10cSrcweir if(!mpImplPolygon) 2370cdf0e10cSrcweir { 2371cdf0e10cSrcweir // no content yet, create empty polygon 2372cdf0e10cSrcweir mpImplPolygon = (ImplPolygon*)(&aStaticImplPolygon); 2373cdf0e10cSrcweir } 2374cdf0e10cSrcweir } 2375cdf0e10cSrcweir 2376cdf0e10cSrcweir // eof 2377