xref: /aoo41x/main/svx/source/svdraw/gradtrns.cxx (revision f6e50924)
1*f6e50924SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*f6e50924SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*f6e50924SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*f6e50924SAndrew Rist  * distributed with this work for additional information
6*f6e50924SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*f6e50924SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*f6e50924SAndrew Rist  * "License"); you may not use this file except in compliance
9*f6e50924SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*f6e50924SAndrew Rist  *
11*f6e50924SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*f6e50924SAndrew Rist  *
13*f6e50924SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*f6e50924SAndrew Rist  * software distributed under the License is distributed on an
15*f6e50924SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*f6e50924SAndrew Rist  * KIND, either express or implied.  See the License for the
17*f6e50924SAndrew Rist  * specific language governing permissions and limitations
18*f6e50924SAndrew Rist  * under the License.
19*f6e50924SAndrew Rist  *
20*f6e50924SAndrew Rist  *************************************************************/
21*f6e50924SAndrew Rist 
22*f6e50924SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "gradtrns.hxx"
28cdf0e10cSrcweir #include <svx/svdobj.hxx>
29cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
30cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
31cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
32cdf0e10cSrcweir #include <vcl/salbtype.hxx>		// FRound
33cdf0e10cSrcweir 
34cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
35cdf0e10cSrcweir 
GradToVec(GradTransGradient & rG,GradTransVector & rV,const SdrObject * pObj)36cdf0e10cSrcweir void GradTransformer::GradToVec(GradTransGradient& rG, GradTransVector& rV, const SdrObject* pObj)
37cdf0e10cSrcweir {
38cdf0e10cSrcweir 	// handle start color
39cdf0e10cSrcweir 	rV.aCol1 = rG.aGradient.GetStartColor();
40cdf0e10cSrcweir 	if(100 != rG.aGradient.GetStartIntens())
41cdf0e10cSrcweir 	{
42cdf0e10cSrcweir 		const double fFact((double)rG.aGradient.GetStartIntens() / 100.0);
43cdf0e10cSrcweir         rV.aCol1 = Color(rV.aCol1.getBColor() * fFact);
44cdf0e10cSrcweir 	}
45cdf0e10cSrcweir 
46cdf0e10cSrcweir 	// handle end color
47cdf0e10cSrcweir 	rV.aCol2 = rG.aGradient.GetEndColor();
48cdf0e10cSrcweir 	if(100 != rG.aGradient.GetEndIntens())
49cdf0e10cSrcweir 	{
50cdf0e10cSrcweir 		const double fFact((double)rG.aGradient.GetEndIntens() / 100.0);
51cdf0e10cSrcweir         rV.aCol2 = Color(rV.aCol2.getBColor() * fFact);
52cdf0e10cSrcweir 	}
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 	// calc the basic positions
55cdf0e10cSrcweir 	const Rectangle aObjectSnapRectangle(pObj->GetSnapRect());
56cdf0e10cSrcweir 	const basegfx::B2DRange aRange(aObjectSnapRectangle.Left(), aObjectSnapRectangle.Top(), aObjectSnapRectangle.Right(), aObjectSnapRectangle.Bottom());
57cdf0e10cSrcweir 	const basegfx::B2DPoint aCenter(aRange.getCenter());
58cdf0e10cSrcweir 	basegfx::B2DPoint aStartPos, aEndPos;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir 	switch(rG.aGradient.GetGradientStyle())
61cdf0e10cSrcweir 	{
62cdf0e10cSrcweir 		case XGRAD_LINEAR :
63cdf0e10cSrcweir 		{
64cdf0e10cSrcweir 			aStartPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMinY());
65cdf0e10cSrcweir 			aEndPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY());
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 			if(rG.aGradient.GetBorder())
68cdf0e10cSrcweir 			{
69cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aStartPos - aEndPos);
70cdf0e10cSrcweir 				const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0;
71cdf0e10cSrcweir 				aFullVec.normalize();
72cdf0e10cSrcweir 				aStartPos = aEndPos + (aFullVec * fLen);
73cdf0e10cSrcweir 			}
74cdf0e10cSrcweir 
75cdf0e10cSrcweir 			if(rG.aGradient.GetAngle())
76cdf0e10cSrcweir 			{
77cdf0e10cSrcweir 				const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0);
78cdf0e10cSrcweir                 const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aCenter, -fAngle));
79cdf0e10cSrcweir 
80cdf0e10cSrcweir 				aStartPos *= aTransformation;
81cdf0e10cSrcweir 				aEndPos *= aTransformation;
82cdf0e10cSrcweir 			}
83cdf0e10cSrcweir 			break;
84cdf0e10cSrcweir 		}
85cdf0e10cSrcweir 		case XGRAD_AXIAL :
86cdf0e10cSrcweir 		{
87cdf0e10cSrcweir 			aStartPos = aCenter;
88cdf0e10cSrcweir 			aEndPos = basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY());
89cdf0e10cSrcweir 
90cdf0e10cSrcweir 			if(rG.aGradient.GetBorder())
91cdf0e10cSrcweir 			{
92cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aEndPos - aStartPos);
93cdf0e10cSrcweir 				const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0;
94cdf0e10cSrcweir 				aFullVec.normalize();
95cdf0e10cSrcweir 				aEndPos = aStartPos + (aFullVec * fLen);
96cdf0e10cSrcweir 			}
97cdf0e10cSrcweir 
98cdf0e10cSrcweir 			if(rG.aGradient.GetAngle())
99cdf0e10cSrcweir 			{
100cdf0e10cSrcweir 				const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0);
101cdf0e10cSrcweir                 const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aCenter, -fAngle));
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 				aStartPos *= aTransformation;
104cdf0e10cSrcweir 				aEndPos *= aTransformation;
105cdf0e10cSrcweir 			}
106cdf0e10cSrcweir 			break;
107cdf0e10cSrcweir 		}
108cdf0e10cSrcweir 		case XGRAD_RADIAL :
109cdf0e10cSrcweir 		case XGRAD_SQUARE :
110cdf0e10cSrcweir 		{
111cdf0e10cSrcweir 			aStartPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMaximum().getY());
112cdf0e10cSrcweir 			aEndPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY());
113cdf0e10cSrcweir 
114cdf0e10cSrcweir 			if(rG.aGradient.GetBorder())
115cdf0e10cSrcweir 			{
116cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aStartPos - aEndPos);
117cdf0e10cSrcweir 				const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0;
118cdf0e10cSrcweir 				aFullVec.normalize();
119cdf0e10cSrcweir 				aStartPos = aEndPos + (aFullVec * fLen);
120cdf0e10cSrcweir 			}
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 			if(rG.aGradient.GetAngle())
123cdf0e10cSrcweir 			{
124cdf0e10cSrcweir 				const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0);
125cdf0e10cSrcweir                 const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos, -fAngle));
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 				aStartPos *= aTransformation;
128cdf0e10cSrcweir 				aEndPos *= aTransformation;
129cdf0e10cSrcweir 			}
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 			if(rG.aGradient.GetXOffset() || rG.aGradient.GetYOffset())
132cdf0e10cSrcweir 			{
133cdf0e10cSrcweir 				basegfx::B2DPoint aOffset(
134cdf0e10cSrcweir 					(aRange.getWidth() * rG.aGradient.GetXOffset()) / 100.0,
135cdf0e10cSrcweir 					(aRange.getHeight() * rG.aGradient.GetYOffset()) / 100.0);
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 				aStartPos += aOffset;
138cdf0e10cSrcweir 				aEndPos += aOffset;
139cdf0e10cSrcweir 			}
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 			break;
142cdf0e10cSrcweir 		}
143cdf0e10cSrcweir 		case XGRAD_ELLIPTICAL :
144cdf0e10cSrcweir 		case XGRAD_RECT :
145cdf0e10cSrcweir 		{
146cdf0e10cSrcweir 			aStartPos = basegfx::B2DPoint(aRange.getMinX(), aCenter.getY());
147cdf0e10cSrcweir 			aEndPos = basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY());
148cdf0e10cSrcweir 
149cdf0e10cSrcweir 			if(rG.aGradient.GetBorder())
150cdf0e10cSrcweir 			{
151cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aStartPos - aEndPos);
152cdf0e10cSrcweir 				const double fLen = (aFullVec.getLength() * (100.0 - (double)rG.aGradient.GetBorder())) / 100.0;
153cdf0e10cSrcweir 				aFullVec.normalize();
154cdf0e10cSrcweir 				aStartPos = aEndPos + (aFullVec * fLen);
155cdf0e10cSrcweir 			}
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 			if(rG.aGradient.GetAngle())
158cdf0e10cSrcweir 			{
159cdf0e10cSrcweir 				const double fAngle = (double)rG.aGradient.GetAngle() * (F_PI180 / 10.0);
160cdf0e10cSrcweir                 const basegfx::B2DHomMatrix aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos, -fAngle));
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 				aStartPos *= aTransformation;
163cdf0e10cSrcweir 				aEndPos *= aTransformation;
164cdf0e10cSrcweir 			}
165cdf0e10cSrcweir 
166cdf0e10cSrcweir 			if(rG.aGradient.GetXOffset() || rG.aGradient.GetYOffset())
167cdf0e10cSrcweir 			{
168cdf0e10cSrcweir 				basegfx::B2DPoint aOffset(
169cdf0e10cSrcweir 					(aRange.getWidth() * rG.aGradient.GetXOffset()) / 100.0,
170cdf0e10cSrcweir 					(aRange.getHeight() * rG.aGradient.GetYOffset()) / 100.0);
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 				aStartPos += aOffset;
173cdf0e10cSrcweir 				aEndPos += aOffset;
174cdf0e10cSrcweir 			}
175cdf0e10cSrcweir 
176cdf0e10cSrcweir 			break;
177cdf0e10cSrcweir 		}
178cdf0e10cSrcweir 	}
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 	// set values for vector positions now
181cdf0e10cSrcweir 	rV.maPositionA = aStartPos;
182cdf0e10cSrcweir 	rV.maPositionB = aEndPos;
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
186cdf0e10cSrcweir 
VecToGrad(GradTransVector & rV,GradTransGradient & rG,GradTransGradient & rGOld,const SdrObject * pObj,sal_Bool bMoveSingle,sal_Bool bMoveFirst)187cdf0e10cSrcweir void GradTransformer::VecToGrad(GradTransVector& rV, GradTransGradient& rG, GradTransGradient& rGOld, const SdrObject* pObj,
188cdf0e10cSrcweir 	sal_Bool bMoveSingle, sal_Bool bMoveFirst)
189cdf0e10cSrcweir {
190cdf0e10cSrcweir 	// fill old gradient to new gradient to have a base
191cdf0e10cSrcweir 	rG = rGOld;
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	// handle color changes
194cdf0e10cSrcweir 	if(rV.aCol1 != rGOld.aGradient.GetStartColor())
195cdf0e10cSrcweir 	{
196cdf0e10cSrcweir 		rG.aGradient.SetStartColor(rV.aCol1);
197cdf0e10cSrcweir 		rG.aGradient.SetStartIntens(100);
198cdf0e10cSrcweir 	}
199cdf0e10cSrcweir 	if(rV.aCol2 != rGOld.aGradient.GetEndColor())
200cdf0e10cSrcweir 	{
201cdf0e10cSrcweir 		rG.aGradient.SetEndColor(rV.aCol2);
202cdf0e10cSrcweir 		rG.aGradient.SetEndIntens(100);
203cdf0e10cSrcweir 	}
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	// calc the basic positions
206cdf0e10cSrcweir 	const Rectangle aObjectSnapRectangle(pObj->GetSnapRect());
207cdf0e10cSrcweir 	const basegfx::B2DRange aRange(aObjectSnapRectangle.Left(), aObjectSnapRectangle.Top(), aObjectSnapRectangle.Right(), aObjectSnapRectangle.Bottom());
208cdf0e10cSrcweir 	const basegfx::B2DPoint aCenter(aRange.getCenter());
209cdf0e10cSrcweir 	basegfx::B2DPoint aStartPos(rV.maPositionA);
210cdf0e10cSrcweir 	basegfx::B2DPoint aEndPos(rV.maPositionB);
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 	switch(rG.aGradient.GetGradientStyle())
213cdf0e10cSrcweir 	{
214cdf0e10cSrcweir 		case XGRAD_LINEAR :
215cdf0e10cSrcweir 		{
216cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && !bMoveFirst))
217cdf0e10cSrcweir 			{
218cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aEndPos - aStartPos);
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 				if(bMoveSingle)
221cdf0e10cSrcweir 				{
222cdf0e10cSrcweir 					aFullVec = aEndPos - aCenter;
223cdf0e10cSrcweir 				}
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 				aFullVec.normalize();
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 				double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX()));
228cdf0e10cSrcweir 				fNewFullAngle /= F_PI180;
229cdf0e10cSrcweir 				fNewFullAngle *= -10.0;
230cdf0e10cSrcweir 				fNewFullAngle += 900.0;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 				// clip
233cdf0e10cSrcweir 				while(fNewFullAngle < 0.0)
234cdf0e10cSrcweir 				{
235cdf0e10cSrcweir 					fNewFullAngle += 3600.0;
236cdf0e10cSrcweir 				}
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 				while(fNewFullAngle >= 3600.0)
239cdf0e10cSrcweir 				{
240cdf0e10cSrcweir 					fNewFullAngle -= 3600.0;
241cdf0e10cSrcweir 				}
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 				// to int and set
244cdf0e10cSrcweir 				sal_Int32 nNewAngle = FRound(fNewFullAngle);
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 				if(nNewAngle != rGOld.aGradient.GetAngle())
247cdf0e10cSrcweir 				{
248cdf0e10cSrcweir 					rG.aGradient.SetAngle(nNewAngle);
249cdf0e10cSrcweir 				}
250cdf0e10cSrcweir 			}
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && bMoveFirst))
253cdf0e10cSrcweir 			{
254cdf0e10cSrcweir 				const basegfx::B2DVector aFullVec(aEndPos - aStartPos);
255cdf0e10cSrcweir 				const basegfx::B2DPoint aBottomLeft(aRange.getMinX(), aRange.getMaximum().getY());
256cdf0e10cSrcweir 				const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY());
257cdf0e10cSrcweir 				const basegfx::B2DVector aOldVec(aBottomLeft - aTopLeft);
258cdf0e10cSrcweir 				const double fFullLen(aFullVec.getLength());
259cdf0e10cSrcweir 				const double fOldLen(aOldVec.getLength());
260cdf0e10cSrcweir 				const double fNewBorder((fFullLen * 100.0) / fOldLen);
261cdf0e10cSrcweir 				sal_Int32 nNewBorder(100L - FRound(fNewBorder));
262cdf0e10cSrcweir 
263cdf0e10cSrcweir 				// clip
264cdf0e10cSrcweir 				if(nNewBorder < 0L)
265cdf0e10cSrcweir 				{
266cdf0e10cSrcweir 					nNewBorder = 0L;
267cdf0e10cSrcweir 				}
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 				if(nNewBorder > 100L)
270cdf0e10cSrcweir 				{
271cdf0e10cSrcweir 					nNewBorder = 100L;
272cdf0e10cSrcweir 				}
273cdf0e10cSrcweir 
274cdf0e10cSrcweir 				// set
275cdf0e10cSrcweir 				if(nNewBorder != rG.aGradient.GetBorder())
276cdf0e10cSrcweir 				{
277cdf0e10cSrcweir 					rG.aGradient.SetBorder((sal_uInt16)nNewBorder);
278cdf0e10cSrcweir 				}
279cdf0e10cSrcweir 			}
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 			break;
282cdf0e10cSrcweir 		}
283cdf0e10cSrcweir 		case XGRAD_AXIAL :
284cdf0e10cSrcweir 		{
285cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && !bMoveFirst))
286cdf0e10cSrcweir 			{
287cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aEndPos - aCenter);
288cdf0e10cSrcweir 				const basegfx::B2DVector aOldVec(basegfx::B2DPoint(aCenter.getX(), aRange.getMaximum().getY()) - aCenter);
289cdf0e10cSrcweir 				const double fFullLen(aFullVec.getLength());
290cdf0e10cSrcweir 				const double fOldLen(aOldVec.getLength());
291cdf0e10cSrcweir 				const double fNewBorder((fFullLen * 100.0) / fOldLen);
292cdf0e10cSrcweir 				sal_Int32 nNewBorder = 100 - FRound(fNewBorder);
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 				// clip
295cdf0e10cSrcweir 				if(nNewBorder < 0L)
296cdf0e10cSrcweir 				{
297cdf0e10cSrcweir 					nNewBorder = 0L;
298cdf0e10cSrcweir 				}
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 				if(nNewBorder > 100L)
301cdf0e10cSrcweir 				{
302cdf0e10cSrcweir 					nNewBorder = 100L;
303cdf0e10cSrcweir 				}
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 				// set
306cdf0e10cSrcweir 				if(nNewBorder != rG.aGradient.GetBorder())
307cdf0e10cSrcweir 				{
308cdf0e10cSrcweir 					rG.aGradient.SetBorder((sal_uInt16)nNewBorder);
309cdf0e10cSrcweir 				}
310cdf0e10cSrcweir 
311cdf0e10cSrcweir 				aFullVec.normalize();
312cdf0e10cSrcweir 				double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX()));
313cdf0e10cSrcweir 				fNewFullAngle /= F_PI180;
314cdf0e10cSrcweir 				fNewFullAngle *= -10.0;
315cdf0e10cSrcweir 				fNewFullAngle += 900.0;
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 				// clip
318cdf0e10cSrcweir 				while(fNewFullAngle < 0.0)
319cdf0e10cSrcweir 				{
320cdf0e10cSrcweir 					fNewFullAngle += 3600.0;
321cdf0e10cSrcweir 				}
322cdf0e10cSrcweir 
323cdf0e10cSrcweir 				while(fNewFullAngle >= 3600.0)
324cdf0e10cSrcweir 				{
325cdf0e10cSrcweir 					fNewFullAngle -= 3600.0;
326cdf0e10cSrcweir 				}
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 				// to int and set
329cdf0e10cSrcweir 				const sal_Int32 nNewAngle(FRound(fNewFullAngle));
330cdf0e10cSrcweir 
331cdf0e10cSrcweir 				if(nNewAngle != rGOld.aGradient.GetAngle())
332cdf0e10cSrcweir 				{
333cdf0e10cSrcweir 					rG.aGradient.SetAngle(nNewAngle);
334cdf0e10cSrcweir 				}
335cdf0e10cSrcweir 			}
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 			break;
338cdf0e10cSrcweir 		}
339cdf0e10cSrcweir 		case XGRAD_RADIAL :
340cdf0e10cSrcweir 		case XGRAD_SQUARE :
341cdf0e10cSrcweir 		{
342cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && !bMoveFirst))
343cdf0e10cSrcweir 			{
344cdf0e10cSrcweir 				const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY());
345cdf0e10cSrcweir 				const basegfx::B2DPoint aOffset(aEndPos - aTopLeft);
346cdf0e10cSrcweir 				sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth()));
347cdf0e10cSrcweir 				sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight()));
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 				// clip
350cdf0e10cSrcweir 				if(nNewXOffset < 0L)
351cdf0e10cSrcweir 				{
352cdf0e10cSrcweir 					nNewXOffset = 0L;
353cdf0e10cSrcweir 				}
354cdf0e10cSrcweir 
355cdf0e10cSrcweir 				if(nNewXOffset > 100L)
356cdf0e10cSrcweir 				{
357cdf0e10cSrcweir 					nNewXOffset = 100L;
358cdf0e10cSrcweir 				}
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 				if(nNewYOffset < 0L)
361cdf0e10cSrcweir 				{
362cdf0e10cSrcweir 					nNewYOffset = 0L;
363cdf0e10cSrcweir 				}
364cdf0e10cSrcweir 
365cdf0e10cSrcweir 				if(nNewYOffset > 100L)
366cdf0e10cSrcweir 				{
367cdf0e10cSrcweir 					nNewYOffset = 100L;
368cdf0e10cSrcweir 				}
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 				rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset);
371cdf0e10cSrcweir 				rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset);
372cdf0e10cSrcweir 
373cdf0e10cSrcweir 				aStartPos -= aOffset;
374cdf0e10cSrcweir 				aEndPos -= aOffset;
375cdf0e10cSrcweir 			}
376cdf0e10cSrcweir 
377cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && bMoveFirst))
378cdf0e10cSrcweir 			{
379cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aStartPos - aEndPos);
380cdf0e10cSrcweir 				const basegfx::B2DPoint aBottomLeft(aRange.getMinX(), aRange.getMaximum().getY());
381cdf0e10cSrcweir 				const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY());
382cdf0e10cSrcweir 				const basegfx::B2DVector aOldVec(aBottomLeft - aTopLeft);
383cdf0e10cSrcweir 				const double fFullLen(aFullVec.getLength());
384cdf0e10cSrcweir 				const double fOldLen(aOldVec.getLength());
385cdf0e10cSrcweir 				const double fNewBorder((fFullLen * 100.0) / fOldLen);
386cdf0e10cSrcweir 				sal_Int32 nNewBorder(100L - FRound(fNewBorder));
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 				// clip
389cdf0e10cSrcweir 				if(nNewBorder < 0L)
390cdf0e10cSrcweir 				{
391cdf0e10cSrcweir 					nNewBorder = 0L;
392cdf0e10cSrcweir 				}
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 				if(nNewBorder > 100L)
395cdf0e10cSrcweir 				{
396cdf0e10cSrcweir 					nNewBorder = 100L;
397cdf0e10cSrcweir 				}
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 				// set
400cdf0e10cSrcweir 				if(nNewBorder != rG.aGradient.GetBorder())
401cdf0e10cSrcweir 				{
402cdf0e10cSrcweir 					rG.aGradient.SetBorder((sal_uInt16)nNewBorder);
403cdf0e10cSrcweir 				}
404cdf0e10cSrcweir 
405cdf0e10cSrcweir 				// angle is not definitely necessary for these modes, but it makes
406cdf0e10cSrcweir 				// controlling more fun for the user
407cdf0e10cSrcweir 				aFullVec.normalize();
408cdf0e10cSrcweir 				double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX()));
409cdf0e10cSrcweir 				fNewFullAngle /= F_PI180;
410cdf0e10cSrcweir 				fNewFullAngle *= -10.0;
411cdf0e10cSrcweir 				fNewFullAngle += 900.0;
412cdf0e10cSrcweir 
413cdf0e10cSrcweir 				// clip
414cdf0e10cSrcweir 				while(fNewFullAngle < 0.0)
415cdf0e10cSrcweir 				{
416cdf0e10cSrcweir 					fNewFullAngle += 3600.0;
417cdf0e10cSrcweir 				}
418cdf0e10cSrcweir 
419cdf0e10cSrcweir 				while(fNewFullAngle >= 3600.0)
420cdf0e10cSrcweir 				{
421cdf0e10cSrcweir 					fNewFullAngle -= 3600.0;
422cdf0e10cSrcweir 				}
423cdf0e10cSrcweir 
424cdf0e10cSrcweir 				// to int and set
425cdf0e10cSrcweir 				const sal_Int32 nNewAngle(FRound(fNewFullAngle));
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 				if(nNewAngle != rGOld.aGradient.GetAngle())
428cdf0e10cSrcweir 				{
429cdf0e10cSrcweir 					rG.aGradient.SetAngle(nNewAngle);
430cdf0e10cSrcweir 				}
431cdf0e10cSrcweir 			}
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 			break;
434cdf0e10cSrcweir 		}
435cdf0e10cSrcweir 		case XGRAD_ELLIPTICAL :
436cdf0e10cSrcweir 		case XGRAD_RECT :
437cdf0e10cSrcweir 		{
438cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && !bMoveFirst))
439cdf0e10cSrcweir 			{
440cdf0e10cSrcweir 				const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY());
441cdf0e10cSrcweir 				const basegfx::B2DPoint aOffset(aEndPos - aTopLeft);
442cdf0e10cSrcweir 				sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth()));
443cdf0e10cSrcweir 				sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight()));
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 				// clip
446cdf0e10cSrcweir 				if(nNewXOffset < 0L)
447cdf0e10cSrcweir 				{
448cdf0e10cSrcweir 					nNewXOffset = 0L;
449cdf0e10cSrcweir 				}
450cdf0e10cSrcweir 
451cdf0e10cSrcweir 				if(nNewXOffset > 100L)
452cdf0e10cSrcweir 				{
453cdf0e10cSrcweir 					nNewXOffset = 100L;
454cdf0e10cSrcweir 				}
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 				if(nNewYOffset < 0L)
457cdf0e10cSrcweir 				{
458cdf0e10cSrcweir 					nNewYOffset = 0L;
459cdf0e10cSrcweir 				}
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 				if(nNewYOffset > 100L)
462cdf0e10cSrcweir 				{
463cdf0e10cSrcweir 					nNewYOffset = 100L;
464cdf0e10cSrcweir 				}
465cdf0e10cSrcweir 
466cdf0e10cSrcweir 				rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset);
467cdf0e10cSrcweir 				rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset);
468cdf0e10cSrcweir 
469cdf0e10cSrcweir 				aStartPos -= aOffset;
470cdf0e10cSrcweir 				aEndPos -= aOffset;
471cdf0e10cSrcweir 			}
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 			if(!bMoveSingle || (bMoveSingle && bMoveFirst))
474cdf0e10cSrcweir 			{
475cdf0e10cSrcweir 				basegfx::B2DVector aFullVec(aStartPos - aEndPos);
476cdf0e10cSrcweir 				const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY());
477cdf0e10cSrcweir 				const basegfx::B2DPoint aCenterLeft(aRange.getMinX(), aRange.getHeight());
478cdf0e10cSrcweir 				const basegfx::B2DVector aOldVec(aCenterLeft - aTopLeft);
479cdf0e10cSrcweir 				const double fFullLen(aFullVec.getLength());
480cdf0e10cSrcweir 				const double fOldLen(aOldVec.getLength());
481cdf0e10cSrcweir 				const double fNewBorder((fFullLen * 100.0) / fOldLen);
482cdf0e10cSrcweir 				sal_Int32 nNewBorder(100L - FRound(fNewBorder));
483cdf0e10cSrcweir 
484cdf0e10cSrcweir 				// clip
485cdf0e10cSrcweir 				if(nNewBorder < 0L)
486cdf0e10cSrcweir 				{
487cdf0e10cSrcweir 					nNewBorder = 0L;
488cdf0e10cSrcweir 				}
489cdf0e10cSrcweir 
490cdf0e10cSrcweir 				if(nNewBorder > 100L)
491cdf0e10cSrcweir 				{
492cdf0e10cSrcweir 					nNewBorder = 100L;
493cdf0e10cSrcweir 				}
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 				// set
496cdf0e10cSrcweir 				if(nNewBorder != rG.aGradient.GetBorder())
497cdf0e10cSrcweir 				{
498cdf0e10cSrcweir 					rG.aGradient.SetBorder((sal_uInt16)nNewBorder);
499cdf0e10cSrcweir 				}
500cdf0e10cSrcweir 
501cdf0e10cSrcweir 				// angle is not definitely necessary for these modes, but it makes
502cdf0e10cSrcweir 				// controlling more fun for the user
503cdf0e10cSrcweir 				aFullVec.normalize();
504cdf0e10cSrcweir 				double fNewFullAngle(atan2(aFullVec.getY(), aFullVec.getX()));
505cdf0e10cSrcweir 				fNewFullAngle /= F_PI180;
506cdf0e10cSrcweir 				fNewFullAngle *= -10.0;
507cdf0e10cSrcweir 				fNewFullAngle += 900.0;
508cdf0e10cSrcweir 
509cdf0e10cSrcweir 				// clip
510cdf0e10cSrcweir 				while(fNewFullAngle < 0.0)
511cdf0e10cSrcweir 				{
512cdf0e10cSrcweir 					fNewFullAngle += 3600.0;
513cdf0e10cSrcweir 				}
514cdf0e10cSrcweir 
515cdf0e10cSrcweir 				while(fNewFullAngle >= 3600.0)
516cdf0e10cSrcweir 				{
517cdf0e10cSrcweir 					fNewFullAngle -= 3600.0;
518cdf0e10cSrcweir 				}
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 				// to int and set
521cdf0e10cSrcweir 				const sal_Int32 nNewAngle(FRound(fNewFullAngle));
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 				if(nNewAngle != rGOld.aGradient.GetAngle())
524cdf0e10cSrcweir 				{
525cdf0e10cSrcweir 					rG.aGradient.SetAngle(nNewAngle);
526cdf0e10cSrcweir 				}
527cdf0e10cSrcweir 			}
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 			break;
530cdf0e10cSrcweir 		}
531cdf0e10cSrcweir 	}
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir // eof
535