1*5b190011SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*5b190011SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*5b190011SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*5b190011SAndrew Rist * distributed with this work for additional information 6*5b190011SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*5b190011SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*5b190011SAndrew Rist * "License"); you may not use this file except in compliance 9*5b190011SAndrew Rist * with the License. You may obtain a copy of the License at 10*5b190011SAndrew Rist * 11*5b190011SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*5b190011SAndrew Rist * 13*5b190011SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*5b190011SAndrew Rist * software distributed under the License is distributed on an 15*5b190011SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*5b190011SAndrew Rist * KIND, either express or implied. See the License for the 17*5b190011SAndrew Rist * specific language governing permissions and limitations 18*5b190011SAndrew Rist * under the License. 19*5b190011SAndrew Rist * 20*5b190011SAndrew Rist *************************************************************/ 21*5b190011SAndrew Rist 22*5b190011SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sd.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir //#define _FUMORPH_PRIVATE 28cdf0e10cSrcweir #include "fumorph.hxx" 29cdf0e10cSrcweir #include <svx/xfillit.hxx> 30cdf0e10cSrcweir #include <svx/xlineit.hxx> 31cdf0e10cSrcweir #include <vcl/msgbox.hxx> 32cdf0e10cSrcweir #include <svx/svdpool.hxx> 33cdf0e10cSrcweir #include <tools/poly.hxx> 34cdf0e10cSrcweir #include <svx/svdopath.hxx> 35cdf0e10cSrcweir #include <svx/svdogrp.hxx> 36cdf0e10cSrcweir #include <editeng/eeitem.hxx> 37cdf0e10cSrcweir 38cdf0e10cSrcweir #include "View.hxx" 39cdf0e10cSrcweir #include "ViewShell.hxx" 40cdf0e10cSrcweir #include "Window.hxx" 41cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 42cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 43cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 44cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx> 45cdf0e10cSrcweir 46cdf0e10cSrcweir #include "strings.hrc" 47cdf0e10cSrcweir #include "sdresid.hxx" 48cdf0e10cSrcweir 49cdf0e10cSrcweir #include "sdabstdlg.hxx" 50cdf0e10cSrcweir 51cdf0e10cSrcweir // #i48168# 52cdf0e10cSrcweir #include <svx/svditer.hxx> 53cdf0e10cSrcweir 54cdf0e10cSrcweir #include <basegfx/color/bcolor.hxx> 55cdf0e10cSrcweir 56cdf0e10cSrcweir namespace sd { 57cdf0e10cSrcweir 58cdf0e10cSrcweir #define ITEMVALUE( ItemSet, Id, Cast ) ( ( (const Cast&) (ItemSet).Get( (Id) ) ).GetValue() ) 59cdf0e10cSrcweir TYPEINIT1( FuMorph, FuPoor ); 60cdf0e10cSrcweir 61cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 62cdf0e10cSrcweir // constructor 63cdf0e10cSrcweir // 64cdf0e10cSrcweir FuMorph::FuMorph ( 65cdf0e10cSrcweir ViewShell* pViewSh, 66cdf0e10cSrcweir ::sd::Window* pWin, 67cdf0e10cSrcweir ::sd::View* pView, 68cdf0e10cSrcweir SdDrawDocument* pDoc, 69cdf0e10cSrcweir SfxRequest& rReq ) 70cdf0e10cSrcweir : FuPoor(pViewSh, pWin, pView, pDoc, rReq) 71cdf0e10cSrcweir { 72cdf0e10cSrcweir } 73cdf0e10cSrcweir 74cdf0e10cSrcweir FunctionReference FuMorph::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) 75cdf0e10cSrcweir { 76cdf0e10cSrcweir FunctionReference xFunc( new FuMorph( pViewSh, pWin, pView, pDoc, rReq ) ); 77cdf0e10cSrcweir xFunc->DoExecute(rReq); 78cdf0e10cSrcweir return xFunc; 79cdf0e10cSrcweir } 80cdf0e10cSrcweir 81cdf0e10cSrcweir void FuMorph::DoExecute( SfxRequest& ) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 84cdf0e10cSrcweir 85cdf0e10cSrcweir if(rMarkList.GetMarkCount() == 2) 86cdf0e10cSrcweir { 87cdf0e10cSrcweir // Clones erzeugen 88cdf0e10cSrcweir SdrObject* pObj1 = rMarkList.GetMark(0)->GetMarkedSdrObj(); 89cdf0e10cSrcweir SdrObject* pObj2 = rMarkList.GetMark(1)->GetMarkedSdrObj(); 90cdf0e10cSrcweir SdrObject* pCloneObj1 = pObj1->Clone(); 91cdf0e10cSrcweir SdrObject* pCloneObj2 = pObj2->Clone(); 92cdf0e10cSrcweir 93cdf0e10cSrcweir // Text am Clone loeschen, da wir sonst kein richtiges PathObj bekommen 94cdf0e10cSrcweir pCloneObj1->SetOutlinerParaObject(NULL); 95cdf0e10cSrcweir pCloneObj2->SetOutlinerParaObject(NULL); 96cdf0e10cSrcweir 97cdf0e10cSrcweir // Path-Objekte erzeugen 98cdf0e10cSrcweir SdrObject* pPolyObj1 = pCloneObj1->ConvertToPolyObj(sal_False, sal_False); 99cdf0e10cSrcweir SdrObject* pPolyObj2 = pCloneObj2->ConvertToPolyObj(sal_False, sal_False); 100cdf0e10cSrcweir SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); 101cdf0e10cSrcweir AbstractMorphDlg* pDlg = pFact ? pFact->CreateMorphDlg( static_cast< ::Window*>(mpWindow), pObj1, pObj2 ) : 0; 102cdf0e10cSrcweir if(pPolyObj1 && pPolyObj2 && pDlg && (pDlg->Execute() == RET_OK)) 103cdf0e10cSrcweir { 104cdf0e10cSrcweir List aPolyPolyList; 105cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aPolyPoly1; 106cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aPolyPoly2; 107cdf0e10cSrcweir ::basegfx::B2DPolyPolygon* pPolyPoly; 108cdf0e10cSrcweir 109cdf0e10cSrcweir pDlg->SaveSettings(); 110cdf0e10cSrcweir 111cdf0e10cSrcweir // #i48168# Not always is the pPolyObj1/pPolyObj2 a SdrPathObj, it may also be a group object 112cdf0e10cSrcweir // containing SdrPathObjs. To get the polygons, i add two iters here 113cdf0e10cSrcweir SdrObjListIter aIter1(*pPolyObj1); 114cdf0e10cSrcweir SdrObjListIter aIter2(*pPolyObj2); 115cdf0e10cSrcweir 116cdf0e10cSrcweir while(aIter1.IsMore()) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir SdrObject* pObj = aIter1.Next(); 119cdf0e10cSrcweir if(pObj && pObj->ISA(SdrPathObj)) 120cdf0e10cSrcweir aPolyPoly1.append(((SdrPathObj*)pObj)->GetPathPoly()); 121cdf0e10cSrcweir } 122cdf0e10cSrcweir 123cdf0e10cSrcweir while(aIter2.IsMore()) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir SdrObject* pObj = aIter2.Next(); 126cdf0e10cSrcweir if(pObj && pObj->ISA(SdrPathObj)) 127cdf0e10cSrcweir aPolyPoly2.append(((SdrPathObj*)pObj)->GetPathPoly()); 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 130cdf0e10cSrcweir // Morphing durchfuehren 131cdf0e10cSrcweir if(aPolyPoly1.count() && aPolyPoly2.count()) 132cdf0e10cSrcweir { 133cdf0e10cSrcweir aPolyPoly1 = ::basegfx::tools::correctOrientations(aPolyPoly1); 134cdf0e10cSrcweir aPolyPoly1.removeDoublePoints(); 135cdf0e10cSrcweir ::basegfx::B2VectorOrientation eIsClockwise1(::basegfx::tools::getOrientation(aPolyPoly1.getB2DPolygon(0L))); 136cdf0e10cSrcweir 137cdf0e10cSrcweir aPolyPoly2 = ::basegfx::tools::correctOrientations(aPolyPoly2); 138cdf0e10cSrcweir aPolyPoly2.removeDoublePoints(); 139cdf0e10cSrcweir ::basegfx::B2VectorOrientation eIsClockwise2(::basegfx::tools::getOrientation(aPolyPoly2.getB2DPolygon(0L))); 140cdf0e10cSrcweir 141cdf0e10cSrcweir // set same orientation 142cdf0e10cSrcweir if(eIsClockwise1 != eIsClockwise2) 143cdf0e10cSrcweir aPolyPoly2.flip(); 144cdf0e10cSrcweir 145cdf0e10cSrcweir // force same poly count 146cdf0e10cSrcweir if(aPolyPoly1.count() < aPolyPoly2.count()) 147cdf0e10cSrcweir ImpAddPolys(aPolyPoly1, aPolyPoly2); 148cdf0e10cSrcweir else if(aPolyPoly2.count() < aPolyPoly1.count()) 149cdf0e10cSrcweir ImpAddPolys(aPolyPoly2, aPolyPoly1); 150cdf0e10cSrcweir 151cdf0e10cSrcweir // use orientation flag from dialog 152cdf0e10cSrcweir if(!pDlg->IsOrientationFade()) 153cdf0e10cSrcweir aPolyPoly2.flip(); 154cdf0e10cSrcweir 155cdf0e10cSrcweir // force same point counts 156cdf0e10cSrcweir for( sal_uInt32 a(0L); a < aPolyPoly1.count(); a++ ) 157cdf0e10cSrcweir { 158cdf0e10cSrcweir ::basegfx::B2DPolygon aSub1(aPolyPoly1.getB2DPolygon(a)); 159cdf0e10cSrcweir ::basegfx::B2DPolygon aSub2(aPolyPoly2.getB2DPolygon(a)); 160cdf0e10cSrcweir 161cdf0e10cSrcweir if(aSub1.count() < aSub2.count()) 162cdf0e10cSrcweir ImpEqualizePolyPointCount(aSub1, aSub2); 163cdf0e10cSrcweir else if(aSub2.count() < aSub1.count()) 164cdf0e10cSrcweir ImpEqualizePolyPointCount(aSub2, aSub1); 165cdf0e10cSrcweir 166cdf0e10cSrcweir aPolyPoly1.setB2DPolygon(a, aSub1); 167cdf0e10cSrcweir aPolyPoly2.setB2DPolygon(a, aSub2); 168cdf0e10cSrcweir } 169cdf0e10cSrcweir 170cdf0e10cSrcweir if(ImpMorphPolygons(aPolyPoly1, aPolyPoly2, pDlg->GetFadeSteps(), aPolyPolyList)) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir String aString(mpView->GetDescriptionOfMarkedObjects()); 173cdf0e10cSrcweir 174cdf0e10cSrcweir aString.Append(sal_Unicode(' ')); 175cdf0e10cSrcweir aString.Append(String(SdResId(STR_UNDO_MORPHING))); 176cdf0e10cSrcweir 177cdf0e10cSrcweir mpView->BegUndo(aString); 178cdf0e10cSrcweir ImpInsertPolygons(aPolyPolyList, pDlg->IsAttributeFade(), pObj1, pObj2); 179cdf0e10cSrcweir mpView->EndUndo(); 180cdf0e10cSrcweir } 181cdf0e10cSrcweir 182cdf0e10cSrcweir // erzeugte Polygone wieder loeschen 183cdf0e10cSrcweir for(pPolyPoly = (::basegfx::B2DPolyPolygon*)aPolyPolyList.First(); pPolyPoly; pPolyPoly = (::basegfx::B2DPolyPolygon *)aPolyPolyList.Next()) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir delete pPolyPoly; 186cdf0e10cSrcweir } 187cdf0e10cSrcweir } 188cdf0e10cSrcweir } 189cdf0e10cSrcweir delete pDlg; 190cdf0e10cSrcweir SdrObject::Free( pCloneObj1 ); 191cdf0e10cSrcweir SdrObject::Free( pCloneObj2 ); 192cdf0e10cSrcweir 193cdf0e10cSrcweir SdrObject::Free( pPolyObj1 ); 194cdf0e10cSrcweir SdrObject::Free( pPolyObj2 ); 195cdf0e10cSrcweir } 196cdf0e10cSrcweir } 197cdf0e10cSrcweir 198cdf0e10cSrcweir ::basegfx::B2DPolygon ImpGetExpandedPolygon(const ::basegfx::B2DPolygon& rCandidate, sal_uInt32 nNum) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir if(rCandidate.count() && nNum && rCandidate.count() != nNum) 201cdf0e10cSrcweir { 202cdf0e10cSrcweir // length of step in dest poly 203cdf0e10cSrcweir ::basegfx::B2DPolygon aRetval; 204cdf0e10cSrcweir const double fStep(::basegfx::tools::getLength(rCandidate) / (double)(rCandidate.isClosed() ? nNum : nNum - 1L)); 205cdf0e10cSrcweir double fDestPos(0.0); 206cdf0e10cSrcweir double fSrcPos(0.0); 207cdf0e10cSrcweir sal_uInt32 nSrcPos(0L); 208cdf0e10cSrcweir sal_uInt32 nSrcPosNext((nSrcPos + 1L == rCandidate.count()) ? 0L : nSrcPos + 1L); 209cdf0e10cSrcweir double fNextSrcLen(::basegfx::B2DVector(rCandidate.getB2DPoint(nSrcPos) - rCandidate.getB2DPoint(nSrcPosNext)).getLength()); 210cdf0e10cSrcweir 211cdf0e10cSrcweir for(sal_uInt32 b(0L); b < nNum; b++) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir // calc fDestPos in source 214cdf0e10cSrcweir while(fSrcPos + fNextSrcLen < fDestPos) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir fSrcPos += fNextSrcLen; 217cdf0e10cSrcweir nSrcPos++; 218cdf0e10cSrcweir nSrcPosNext = (nSrcPos + 1L == rCandidate.count()) ? 0L : nSrcPos + 1L; 219cdf0e10cSrcweir fNextSrcLen = ::basegfx::B2DVector(rCandidate.getB2DPoint(nSrcPos) - rCandidate.getB2DPoint(nSrcPosNext)).getLength(); 220cdf0e10cSrcweir } 221cdf0e10cSrcweir 222cdf0e10cSrcweir // fDestPos is between fSrcPos and (fSrcPos + fNextSrcLen) 223cdf0e10cSrcweir const double fLenA((fDestPos - fSrcPos) / fNextSrcLen); 224cdf0e10cSrcweir const ::basegfx::B2DPoint aOld1(rCandidate.getB2DPoint(nSrcPos)); 225cdf0e10cSrcweir const ::basegfx::B2DPoint aOld2(rCandidate.getB2DPoint(nSrcPosNext)); 226cdf0e10cSrcweir ::basegfx::B2DPoint aNewPoint(basegfx::interpolate(aOld1, aOld2, fLenA)); 227cdf0e10cSrcweir aRetval.append(aNewPoint); 228cdf0e10cSrcweir 229cdf0e10cSrcweir // next step 230cdf0e10cSrcweir fDestPos += fStep; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir if(aRetval.count() >= 3L) 234cdf0e10cSrcweir { 235cdf0e10cSrcweir aRetval.setClosed(rCandidate.isClosed()); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir return aRetval; 239cdf0e10cSrcweir } 240cdf0e10cSrcweir else 241cdf0e10cSrcweir { 242cdf0e10cSrcweir return rCandidate; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir } 245cdf0e10cSrcweir 246cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 247cdf0e10cSrcweir // make the point count of the polygons equal in adding points 248cdf0e10cSrcweir // 249cdf0e10cSrcweir void FuMorph::ImpEqualizePolyPointCount(::basegfx::B2DPolygon& rSmall, const ::basegfx::B2DPolygon& rBig) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir // create poly with equal point count 252cdf0e10cSrcweir const sal_uInt32 nCnt(rBig.count()); 253cdf0e10cSrcweir ::basegfx::B2DPolygon aPoly1(ImpGetExpandedPolygon(rSmall, nCnt)); 254cdf0e10cSrcweir 255cdf0e10cSrcweir // create transformation for rBig to do the compare 256cdf0e10cSrcweir const ::basegfx::B2DRange aSrcSize(::basegfx::tools::getRange(rBig)); 257cdf0e10cSrcweir const ::basegfx::B2DPoint aSrcPos(aSrcSize.getCenter()); 258cdf0e10cSrcweir const ::basegfx::B2DRange aDstSize(::basegfx::tools::getRange(rSmall)); 259cdf0e10cSrcweir const ::basegfx::B2DPoint aDstPos(aDstSize.getCenter()); 260cdf0e10cSrcweir 261cdf0e10cSrcweir basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-aSrcPos.getX(), -aSrcPos.getY())); 262cdf0e10cSrcweir aTrans.scale(aDstSize.getWidth() / aSrcSize.getWidth(), aDstSize.getHeight() / aSrcSize.getHeight()); 263cdf0e10cSrcweir aTrans.translate(aDstPos.getX(), aDstPos.getY()); 264cdf0e10cSrcweir 265cdf0e10cSrcweir // transpose points to have smooth linear blending 266cdf0e10cSrcweir ::basegfx::B2DPolygon aPoly2; 267cdf0e10cSrcweir aPoly2.append(::basegfx::B2DPoint(), nCnt); 268cdf0e10cSrcweir sal_uInt32 nInd(ImpGetNearestIndex(aPoly1, aTrans * rBig.getB2DPoint(0L))); 269cdf0e10cSrcweir 270cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nCnt; a++) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir aPoly2.setB2DPoint((a + nCnt - nInd) % nCnt, aPoly1.getB2DPoint(a)); 273cdf0e10cSrcweir } 274cdf0e10cSrcweir 275cdf0e10cSrcweir aPoly2.setClosed(rBig.isClosed()); 276cdf0e10cSrcweir rSmall = aPoly2; 277cdf0e10cSrcweir } 278cdf0e10cSrcweir 279cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 280cdf0e10cSrcweir // 281cdf0e10cSrcweir sal_uInt32 FuMorph::ImpGetNearestIndex(const ::basegfx::B2DPolygon& rPoly, const ::basegfx::B2DPoint& rPos) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir double fMinDist = 0.0; 284cdf0e10cSrcweir sal_uInt32 nActInd = 0; 285cdf0e10cSrcweir 286cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rPoly.count(); a++) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir double fNewDist(::basegfx::B2DVector(rPoly.getB2DPoint(a) - rPos).getLength()); 289cdf0e10cSrcweir 290cdf0e10cSrcweir if(!a || fNewDist < fMinDist) 291cdf0e10cSrcweir { 292cdf0e10cSrcweir fMinDist = fNewDist; 293cdf0e10cSrcweir nActInd = a; 294cdf0e10cSrcweir } 295cdf0e10cSrcweir } 296cdf0e10cSrcweir 297cdf0e10cSrcweir return nActInd; 298cdf0e10cSrcweir } 299cdf0e10cSrcweir 300cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 301cdf0e10cSrcweir // add to a point reduced polys until count is same 302cdf0e10cSrcweir // 303cdf0e10cSrcweir void FuMorph::ImpAddPolys(::basegfx::B2DPolyPolygon& rSmaller, const ::basegfx::B2DPolyPolygon& rBigger) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir while(rSmaller.count() < rBigger.count()) 306cdf0e10cSrcweir { 307cdf0e10cSrcweir const ::basegfx::B2DPolygon aToBeCopied(rBigger.getB2DPolygon(rSmaller.count())); 308cdf0e10cSrcweir const ::basegfx::B2DRange aToBeCopiedPolySize(::basegfx::tools::getRange(aToBeCopied)); 309cdf0e10cSrcweir ::basegfx::B2DPoint aNewPoint(aToBeCopiedPolySize.getCenter()); 310cdf0e10cSrcweir ::basegfx::B2DPolygon aNewPoly; 311cdf0e10cSrcweir 312cdf0e10cSrcweir const ::basegfx::B2DRange aSrcSize(::basegfx::tools::getRange(rBigger.getB2DPolygon(0L))); 313cdf0e10cSrcweir const ::basegfx::B2DPoint aSrcPos(aSrcSize.getCenter()); 314cdf0e10cSrcweir const ::basegfx::B2DRange aDstSize(::basegfx::tools::getRange(rSmaller.getB2DPolygon(0L))); 315cdf0e10cSrcweir const ::basegfx::B2DPoint aDstPos(aDstSize.getCenter()); 316cdf0e10cSrcweir aNewPoint = aNewPoint - aSrcPos + aDstPos; 317cdf0e10cSrcweir 318cdf0e10cSrcweir for(sal_uInt32 a(0L); a < aToBeCopied.count(); a++) 319cdf0e10cSrcweir { 320cdf0e10cSrcweir aNewPoly.append(aNewPoint); 321cdf0e10cSrcweir } 322cdf0e10cSrcweir 323cdf0e10cSrcweir rSmaller.append(aNewPoly); 324cdf0e10cSrcweir } 325cdf0e10cSrcweir } 326cdf0e10cSrcweir 327cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 328cdf0e10cSrcweir // create group object with morphed polygons 329cdf0e10cSrcweir // 330cdf0e10cSrcweir void FuMorph::ImpInsertPolygons(List& rPolyPolyList3D, sal_Bool bAttributeFade, 331cdf0e10cSrcweir const SdrObject* pObj1, const SdrObject* pObj2) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir Color aStartFillCol; 334cdf0e10cSrcweir Color aEndFillCol; 335cdf0e10cSrcweir Color aStartLineCol; 336cdf0e10cSrcweir Color aEndLineCol; 337cdf0e10cSrcweir long nStartLineWidth = 0; 338cdf0e10cSrcweir long nEndLineWidth = 0; 339cdf0e10cSrcweir SdrPageView* pPageView = mpView->GetSdrPageView(); 340cdf0e10cSrcweir SfxItemPool* pPool = pObj1->GetObjectItemPool(); 341cdf0e10cSrcweir SfxItemSet aSet1( *pPool,SDRATTR_START,SDRATTR_NOTPERSIST_FIRST-1,EE_ITEMS_START,EE_ITEMS_END,0 ); 342cdf0e10cSrcweir SfxItemSet aSet2( aSet1 ); 343cdf0e10cSrcweir sal_Bool bLineColor = sal_False; 344cdf0e10cSrcweir sal_Bool bFillColor = sal_False; 345cdf0e10cSrcweir sal_Bool bLineWidth = sal_False; 346cdf0e10cSrcweir sal_Bool bIgnoreLine = sal_False; 347cdf0e10cSrcweir sal_Bool bIgnoreFill = sal_False; 348cdf0e10cSrcweir 349cdf0e10cSrcweir aSet1.Put(pObj1->GetMergedItemSet()); 350cdf0e10cSrcweir aSet2.Put(pObj2->GetMergedItemSet()); 351cdf0e10cSrcweir 352cdf0e10cSrcweir const XLineStyle eLineStyle1 = ITEMVALUE( aSet1, XATTR_LINESTYLE, XLineStyleItem ); 353cdf0e10cSrcweir const XLineStyle eLineStyle2 = ITEMVALUE( aSet2, XATTR_LINESTYLE, XLineStyleItem ); 354cdf0e10cSrcweir const XFillStyle eFillStyle1 = ITEMVALUE( aSet1, XATTR_FILLSTYLE, XFillStyleItem ); 355cdf0e10cSrcweir const XFillStyle eFillStyle2 = ITEMVALUE( aSet2, XATTR_FILLSTYLE, XFillStyleItem ); 356cdf0e10cSrcweir 357cdf0e10cSrcweir if ( bAttributeFade ) 358cdf0e10cSrcweir { 359cdf0e10cSrcweir if ( ( eLineStyle1 != XLINE_NONE ) && ( eLineStyle2 != XLINE_NONE ) ) 360cdf0e10cSrcweir { 361cdf0e10cSrcweir bLineWidth = bLineColor = sal_True; 362cdf0e10cSrcweir 363cdf0e10cSrcweir aStartLineCol = static_cast< XLineColorItem const & >( 364cdf0e10cSrcweir aSet1.Get(XATTR_LINECOLOR)).GetColorValue(); 365cdf0e10cSrcweir aEndLineCol = static_cast< XLineColorItem const & >( 366cdf0e10cSrcweir aSet2.Get(XATTR_LINECOLOR)).GetColorValue(); 367cdf0e10cSrcweir 368cdf0e10cSrcweir nStartLineWidth = ITEMVALUE( aSet1, XATTR_LINEWIDTH, XLineWidthItem ); 369cdf0e10cSrcweir nEndLineWidth = ITEMVALUE( aSet2, XATTR_LINEWIDTH, XLineWidthItem ); 370cdf0e10cSrcweir } 371cdf0e10cSrcweir else if ( ( eLineStyle1 == XLINE_NONE ) && ( eLineStyle2 == XLINE_NONE ) ) 372cdf0e10cSrcweir bIgnoreLine = sal_True; 373cdf0e10cSrcweir 374cdf0e10cSrcweir if ( ( eFillStyle1 == XFILL_SOLID ) && ( eFillStyle2 == XFILL_SOLID ) ) 375cdf0e10cSrcweir { 376cdf0e10cSrcweir bFillColor = sal_True; 377cdf0e10cSrcweir aStartFillCol = static_cast< XFillColorItem const & >( 378cdf0e10cSrcweir aSet1.Get(XATTR_FILLCOLOR)).GetColorValue(); 379cdf0e10cSrcweir aEndFillCol = static_cast< XFillColorItem const & >( 380cdf0e10cSrcweir aSet2.Get(XATTR_FILLCOLOR)).GetColorValue(); 381cdf0e10cSrcweir } 382cdf0e10cSrcweir else if ( ( eFillStyle1 == XFILL_NONE ) && ( eFillStyle2 == XFILL_NONE ) ) 383cdf0e10cSrcweir bIgnoreFill = sal_True; 384cdf0e10cSrcweir } 385cdf0e10cSrcweir 386cdf0e10cSrcweir if ( pPageView ) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir SfxItemSet aSet( aSet1 ); 389cdf0e10cSrcweir SdrObjGroup* pObjGroup = new SdrObjGroup; 390cdf0e10cSrcweir SdrObjList* pObjList = pObjGroup->GetSubList(); 391cdf0e10cSrcweir const sal_uLong nCount = rPolyPolyList3D.Count(); 392cdf0e10cSrcweir const double fStep = 1. / ( nCount + 1 ); 393cdf0e10cSrcweir const double fDelta = nEndLineWidth - nStartLineWidth; 394cdf0e10cSrcweir double fFactor = fStep; 395cdf0e10cSrcweir 396cdf0e10cSrcweir aSet.Put( XLineStyleItem( XLINE_SOLID ) ); 397cdf0e10cSrcweir aSet.Put( XFillStyleItem( XFILL_SOLID ) ); 398cdf0e10cSrcweir 399cdf0e10cSrcweir for ( sal_uLong i = 0; i < nCount; i++, fFactor += fStep ) 400cdf0e10cSrcweir { 401cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPoly3D = *(::basegfx::B2DPolyPolygon*)rPolyPolyList3D.GetObject(i); 402cdf0e10cSrcweir SdrPathObj* pNewObj = new SdrPathObj(OBJ_POLY, rPolyPoly3D); 403cdf0e10cSrcweir 404cdf0e10cSrcweir // Linienfarbe 405cdf0e10cSrcweir if ( bLineColor ) 406cdf0e10cSrcweir { 407cdf0e10cSrcweir const basegfx::BColor aLineColor(basegfx::interpolate(aStartLineCol.getBColor(), aEndLineCol.getBColor(), fFactor)); 408cdf0e10cSrcweir aSet.Put( XLineColorItem( aEmptyStr, Color(aLineColor))); 409cdf0e10cSrcweir } 410cdf0e10cSrcweir else if ( bIgnoreLine ) 411cdf0e10cSrcweir aSet.Put( XLineStyleItem( XLINE_NONE ) ); 412cdf0e10cSrcweir 413cdf0e10cSrcweir // Fuellfarbe 414cdf0e10cSrcweir if ( bFillColor ) 415cdf0e10cSrcweir { 416cdf0e10cSrcweir const basegfx::BColor aFillColor(basegfx::interpolate(aStartFillCol.getBColor(), aEndFillCol.getBColor(), fFactor)); 417cdf0e10cSrcweir aSet.Put( XFillColorItem( aEmptyStr, Color(aFillColor))); 418cdf0e10cSrcweir } 419cdf0e10cSrcweir else if ( bIgnoreFill ) 420cdf0e10cSrcweir aSet.Put( XFillStyleItem( XFILL_NONE ) ); 421cdf0e10cSrcweir 422cdf0e10cSrcweir // Linienstaerke 423cdf0e10cSrcweir if ( bLineWidth ) 424cdf0e10cSrcweir aSet.Put( XLineWidthItem( nStartLineWidth + (long) ( fFactor * fDelta + 0.5 ) ) ); 425cdf0e10cSrcweir 426cdf0e10cSrcweir pNewObj->SetMergedItemSetAndBroadcast(aSet); 427cdf0e10cSrcweir 428cdf0e10cSrcweir pObjList->InsertObject( pNewObj, LIST_APPEND ); 429cdf0e10cSrcweir } 430cdf0e10cSrcweir 431cdf0e10cSrcweir if ( nCount ) 432cdf0e10cSrcweir { 433cdf0e10cSrcweir pObjList->InsertObject( pObj1->Clone(), 0 ); 434cdf0e10cSrcweir pObjList->InsertObject( pObj2->Clone(), LIST_APPEND ); 435cdf0e10cSrcweir mpView->DeleteMarked(); 436cdf0e10cSrcweir mpView->InsertObjectAtView( pObjGroup, *pPageView, SDRINSERT_SETDEFLAYER ); 437cdf0e10cSrcweir } 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir 441cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 442cdf0e10cSrcweir // create single morphed PolyPolygon 443cdf0e10cSrcweir // 444cdf0e10cSrcweir ::basegfx::B2DPolyPolygon* FuMorph::ImpCreateMorphedPolygon( 445cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPolyStart, 446cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPolyEnd, 447cdf0e10cSrcweir double fMorphingFactor) 448cdf0e10cSrcweir { 449cdf0e10cSrcweir ::basegfx::B2DPolyPolygon* pNewPolyPolygon = new ::basegfx::B2DPolyPolygon(); 450cdf0e10cSrcweir const double fFactor = 1.0 - fMorphingFactor; 451cdf0e10cSrcweir 452cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rPolyPolyStart.count(); a++) 453cdf0e10cSrcweir { 454cdf0e10cSrcweir const ::basegfx::B2DPolygon aPolyStart(rPolyPolyStart.getB2DPolygon(a)); 455cdf0e10cSrcweir const ::basegfx::B2DPolygon aPolyEnd(rPolyPolyEnd.getB2DPolygon(a)); 456cdf0e10cSrcweir const sal_uInt32 nCount(aPolyStart.count()); 457cdf0e10cSrcweir ::basegfx::B2DPolygon aNewPolygon; 458cdf0e10cSrcweir 459cdf0e10cSrcweir for(sal_uInt32 b(0L); b < nCount; b++) 460cdf0e10cSrcweir { 461cdf0e10cSrcweir const ::basegfx::B2DPoint& aPtStart(aPolyStart.getB2DPoint(b)); 462cdf0e10cSrcweir const ::basegfx::B2DPoint& aPtEnd(aPolyEnd.getB2DPoint(b)); 463cdf0e10cSrcweir aNewPolygon.append(aPtEnd + ((aPtStart - aPtEnd) * fFactor)); 464cdf0e10cSrcweir } 465cdf0e10cSrcweir 466cdf0e10cSrcweir aNewPolygon.setClosed(aPolyStart.isClosed() && aPolyEnd.isClosed()); 467cdf0e10cSrcweir pNewPolyPolygon->append(aNewPolygon); 468cdf0e10cSrcweir } 469cdf0e10cSrcweir 470cdf0e10cSrcweir return pNewPolyPolygon; 471cdf0e10cSrcweir } 472cdf0e10cSrcweir 473cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 474cdf0e10cSrcweir // create morphed PolyPolygons 475cdf0e10cSrcweir // 476cdf0e10cSrcweir sal_Bool FuMorph::ImpMorphPolygons( 477cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPoly1, 478cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPoly2, 479cdf0e10cSrcweir const sal_uInt16 nSteps, List& rPolyPolyList3D) 480cdf0e10cSrcweir { 481cdf0e10cSrcweir if(nSteps) 482cdf0e10cSrcweir { 483cdf0e10cSrcweir const ::basegfx::B2DRange aStartPolySize(::basegfx::tools::getRange(rPolyPoly1)); 484cdf0e10cSrcweir const ::basegfx::B2DPoint aStartCenter(aStartPolySize.getCenter()); 485cdf0e10cSrcweir const ::basegfx::B2DRange aEndPolySize(::basegfx::tools::getRange(rPolyPoly2)); 486cdf0e10cSrcweir const ::basegfx::B2DPoint aEndCenter(aEndPolySize.getCenter()); 487cdf0e10cSrcweir const ::basegfx::B2DPoint aDelta(aEndCenter - aStartCenter); 488cdf0e10cSrcweir const double fFactor(1.0 / (nSteps + 1)); 489cdf0e10cSrcweir double fValue(0.0); 490cdf0e10cSrcweir 491cdf0e10cSrcweir for(sal_uInt16 i(0); i < nSteps; i++) 492cdf0e10cSrcweir { 493cdf0e10cSrcweir fValue += fFactor; 494cdf0e10cSrcweir ::basegfx::B2DPolyPolygon* pNewPolyPoly2D = ImpCreateMorphedPolygon(rPolyPoly1, rPolyPoly2, fValue); 495cdf0e10cSrcweir 496cdf0e10cSrcweir const ::basegfx::B2DRange aNewPolySize(::basegfx::tools::getRange(*pNewPolyPoly2D)); 497cdf0e10cSrcweir const ::basegfx::B2DPoint aNewS(aNewPolySize.getCenter()); 498cdf0e10cSrcweir const ::basegfx::B2DPoint aRealS(aStartCenter + (aDelta * fValue)); 499cdf0e10cSrcweir const ::basegfx::B2DPoint aDiff(aRealS - aNewS); 500cdf0e10cSrcweir 501cdf0e10cSrcweir pNewPolyPoly2D->transform(basegfx::tools::createTranslateB2DHomMatrix(aDiff)); 502cdf0e10cSrcweir rPolyPolyList3D.Insert(pNewPolyPoly2D, LIST_APPEND); 503cdf0e10cSrcweir } 504cdf0e10cSrcweir } 505cdf0e10cSrcweir return sal_True; 506cdf0e10cSrcweir } 507cdf0e10cSrcweir 508cdf0e10cSrcweir 509cdf0e10cSrcweir } // end of namespace sd 510