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 //
FuMorph(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)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
Create(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)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
DoExecute(SfxRequest &)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
ImpGetExpandedPolygon(const::basegfx::B2DPolygon & rCandidate,sal_uInt32 nNum)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 //
ImpEqualizePolyPointCount(::basegfx::B2DPolygon & rSmall,const::basegfx::B2DPolygon & rBig)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 //
ImpGetNearestIndex(const::basegfx::B2DPolygon & rPoly,const::basegfx::B2DPoint & rPos)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 //
ImpAddPolys(::basegfx::B2DPolyPolygon & rSmaller,const::basegfx::B2DPolyPolygon & rBigger)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 //
ImpInsertPolygons(List & rPolyPolyList3D,sal_Bool bAttributeFade,const SdrObject * pObj1,const SdrObject * pObj2)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 //
ImpCreateMorphedPolygon(const::basegfx::B2DPolyPolygon & rPolyPolyStart,const::basegfx::B2DPolyPolygon & rPolyPolyEnd,double fMorphingFactor)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 //
ImpMorphPolygons(const::basegfx::B2DPolyPolygon & rPolyPoly1,const::basegfx::B2DPolyPolygon & rPolyPoly2,const sal_uInt16 nSteps,List & rPolyPolyList3D)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