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