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