1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "gradtrns.hxx"
22 #include <svx/svdobj.hxx>
23 #include <basegfx/range/b2drange.hxx>
24 #include <basegfx/matrix/b2dhommatrix.hxx>
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <tools/helpers.hxx>
30 void GradTransformer::GradToVec(GradTransGradient
& rG
, GradTransVector
& rV
, const SdrObject
* pObj
)
33 rV
.aCol1
= rG
.aGradient
.GetStartColor();
34 if(100 != rG
.aGradient
.GetStartIntens())
36 const double fFact((double)rG
.aGradient
.GetStartIntens() / 100.0);
37 rV
.aCol1
= Color(rV
.aCol1
.getBColor() * fFact
);
41 rV
.aCol2
= rG
.aGradient
.GetEndColor();
42 if(100 != rG
.aGradient
.GetEndIntens())
44 const double fFact((double)rG
.aGradient
.GetEndIntens() / 100.0);
45 rV
.aCol2
= Color(rV
.aCol2
.getBColor() * fFact
);
48 // calc the basic positions
49 const Rectangle
aObjectSnapRectangle(pObj
->GetSnapRect());
50 const basegfx::B2DRange
aRange(aObjectSnapRectangle
.Left(), aObjectSnapRectangle
.Top(), aObjectSnapRectangle
.Right(), aObjectSnapRectangle
.Bottom());
51 const basegfx::B2DPoint
aCenter(aRange
.getCenter());
52 basegfx::B2DPoint aStartPos
, aEndPos
;
54 switch(rG
.aGradient
.GetGradientStyle())
58 aStartPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMinY());
59 aEndPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY());
61 if(rG
.aGradient
.GetBorder())
63 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
64 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
66 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
69 if(rG
.aGradient
.GetAngle())
71 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
72 const basegfx::B2DHomMatrix
aTransformation(basegfx::tools::createRotateAroundPoint(aCenter
, -fAngle
));
74 aStartPos
*= aTransformation
;
75 aEndPos
*= aTransformation
;
82 aEndPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY());
84 if(rG
.aGradient
.GetBorder())
86 basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
87 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
89 aEndPos
= aStartPos
+ (aFullVec
* fLen
);
92 if(rG
.aGradient
.GetAngle())
94 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
95 const basegfx::B2DHomMatrix
aTransformation(basegfx::tools::createRotateAroundPoint(aCenter
, -fAngle
));
97 aStartPos
*= aTransformation
;
98 aEndPos
*= aTransformation
;
105 aStartPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMaximum().getY());
106 aEndPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMinY());
108 if(rG
.aGradient
.GetBorder())
110 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
111 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
112 aFullVec
.normalize();
113 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
116 if(rG
.aGradient
.GetAngle())
118 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
119 const basegfx::B2DHomMatrix
aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos
, -fAngle
));
121 aStartPos
*= aTransformation
;
122 aEndPos
*= aTransformation
;
125 if(rG
.aGradient
.GetXOffset() || rG
.aGradient
.GetYOffset())
127 basegfx::B2DPoint
aOffset(
128 (aRange
.getWidth() * rG
.aGradient
.GetXOffset()) / 100.0,
129 (aRange
.getHeight() * rG
.aGradient
.GetYOffset()) / 100.0);
131 aStartPos
+= aOffset
;
137 case XGRAD_ELLIPTICAL
:
140 aStartPos
= basegfx::B2DPoint(aRange
.getMinX(), aCenter
.getY());
141 aEndPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMinY());
143 if(rG
.aGradient
.GetBorder())
145 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
146 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
147 aFullVec
.normalize();
148 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
151 if(rG
.aGradient
.GetAngle())
153 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
154 const basegfx::B2DHomMatrix
aTransformation(basegfx::tools::createRotateAroundPoint(aEndPos
, -fAngle
));
156 aStartPos
*= aTransformation
;
157 aEndPos
*= aTransformation
;
160 if(rG
.aGradient
.GetXOffset() || rG
.aGradient
.GetYOffset())
162 basegfx::B2DPoint
aOffset(
163 (aRange
.getWidth() * rG
.aGradient
.GetXOffset()) / 100.0,
164 (aRange
.getHeight() * rG
.aGradient
.GetYOffset()) / 100.0);
166 aStartPos
+= aOffset
;
174 // set values for vector positions now
175 rV
.maPositionA
= aStartPos
;
176 rV
.maPositionB
= aEndPos
;
181 void GradTransformer::VecToGrad(GradTransVector
& rV
, GradTransGradient
& rG
, GradTransGradient
& rGOld
, const SdrObject
* pObj
,
182 bool bMoveSingle
, bool bMoveFirst
)
184 // fill old gradient to new gradient to have a base
187 // handle color changes
188 if(rV
.aCol1
!= rGOld
.aGradient
.GetStartColor())
190 rG
.aGradient
.SetStartColor(rV
.aCol1
);
191 rG
.aGradient
.SetStartIntens(100);
193 if(rV
.aCol2
!= rGOld
.aGradient
.GetEndColor())
195 rG
.aGradient
.SetEndColor(rV
.aCol2
);
196 rG
.aGradient
.SetEndIntens(100);
199 // calc the basic positions
200 const Rectangle
aObjectSnapRectangle(pObj
->GetSnapRect());
201 const basegfx::B2DRange
aRange(aObjectSnapRectangle
.Left(), aObjectSnapRectangle
.Top(), aObjectSnapRectangle
.Right(), aObjectSnapRectangle
.Bottom());
202 const basegfx::B2DPoint
aCenter(aRange
.getCenter());
203 basegfx::B2DPoint
aStartPos(rV
.maPositionA
);
204 basegfx::B2DPoint
aEndPos(rV
.maPositionB
);
206 switch(rG
.aGradient
.GetGradientStyle())
210 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
212 basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
216 aFullVec
= aEndPos
- aCenter
;
219 aFullVec
.normalize();
221 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
222 fNewFullAngle
/= F_PI180
;
223 fNewFullAngle
*= -10.0;
224 fNewFullAngle
+= 900.0;
227 while(fNewFullAngle
< 0.0)
229 fNewFullAngle
+= 3600.0;
232 while(fNewFullAngle
>= 3600.0)
234 fNewFullAngle
-= 3600.0;
238 sal_Int32 nNewAngle
= FRound(fNewFullAngle
);
240 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
242 rG
.aGradient
.SetAngle(nNewAngle
);
246 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
248 const basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
249 const basegfx::B2DPoint
aBottomLeft(aRange
.getMinX(), aRange
.getMaximum().getY());
250 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
251 const basegfx::B2DVector
aOldVec(aBottomLeft
- aTopLeft
);
252 const double fFullLen(aFullVec
.getLength());
253 const double fOldLen(aOldVec
.getLength());
254 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
255 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
263 if(nNewBorder
> 100L)
269 if(nNewBorder
!= rG
.aGradient
.GetBorder())
271 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
279 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
281 basegfx::B2DVector
aFullVec(aEndPos
- aCenter
);
282 const basegfx::B2DVector
aOldVec(basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY()) - aCenter
);
283 const double fFullLen(aFullVec
.getLength());
284 const double fOldLen(aOldVec
.getLength());
285 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
286 sal_Int32 nNewBorder
= 100 - FRound(fNewBorder
);
294 if(nNewBorder
> 100L)
300 if(nNewBorder
!= rG
.aGradient
.GetBorder())
302 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
305 aFullVec
.normalize();
306 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
307 fNewFullAngle
/= F_PI180
;
308 fNewFullAngle
*= -10.0;
309 fNewFullAngle
+= 900.0;
312 while(fNewFullAngle
< 0.0)
314 fNewFullAngle
+= 3600.0;
317 while(fNewFullAngle
>= 3600.0)
319 fNewFullAngle
-= 3600.0;
323 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
325 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
327 rG
.aGradient
.SetAngle(nNewAngle
);
336 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
338 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
339 const basegfx::B2DPoint
aOffset(aEndPos
- aTopLeft
);
340 sal_Int32
nNewXOffset(FRound((aOffset
.getX() * 100.0) / aRange
.getWidth()));
341 sal_Int32
nNewYOffset(FRound((aOffset
.getY() * 100.0) / aRange
.getHeight()));
349 if(nNewXOffset
> 100L)
359 if(nNewYOffset
> 100L)
364 rG
.aGradient
.SetXOffset((sal_uInt16
)nNewXOffset
);
365 rG
.aGradient
.SetYOffset((sal_uInt16
)nNewYOffset
);
367 aStartPos
-= aOffset
;
371 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
373 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
374 const basegfx::B2DPoint
aBottomLeft(aRange
.getMinX(), aRange
.getMaximum().getY());
375 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
376 const basegfx::B2DVector
aOldVec(aBottomLeft
- aTopLeft
);
377 const double fFullLen(aFullVec
.getLength());
378 const double fOldLen(aOldVec
.getLength());
379 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
380 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
388 if(nNewBorder
> 100L)
394 if(nNewBorder
!= rG
.aGradient
.GetBorder())
396 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
399 // angle is not definitely necessary for these modes, but it makes
400 // controlling more fun for the user
401 aFullVec
.normalize();
402 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
403 fNewFullAngle
/= F_PI180
;
404 fNewFullAngle
*= -10.0;
405 fNewFullAngle
+= 900.0;
408 while(fNewFullAngle
< 0.0)
410 fNewFullAngle
+= 3600.0;
413 while(fNewFullAngle
>= 3600.0)
415 fNewFullAngle
-= 3600.0;
419 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
421 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
423 rG
.aGradient
.SetAngle(nNewAngle
);
429 case XGRAD_ELLIPTICAL
:
432 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
434 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
435 const basegfx::B2DPoint
aOffset(aEndPos
- aTopLeft
);
436 sal_Int32
nNewXOffset(FRound((aOffset
.getX() * 100.0) / aRange
.getWidth()));
437 sal_Int32
nNewYOffset(FRound((aOffset
.getY() * 100.0) / aRange
.getHeight()));
445 if(nNewXOffset
> 100L)
455 if(nNewYOffset
> 100L)
460 rG
.aGradient
.SetXOffset((sal_uInt16
)nNewXOffset
);
461 rG
.aGradient
.SetYOffset((sal_uInt16
)nNewYOffset
);
463 aStartPos
-= aOffset
;
467 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
469 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
470 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
471 const basegfx::B2DPoint
aCenterLeft(aRange
.getMinX(), aRange
.getHeight());
472 const basegfx::B2DVector
aOldVec(aCenterLeft
- aTopLeft
);
473 const double fFullLen(aFullVec
.getLength());
474 const double fOldLen(aOldVec
.getLength());
475 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
476 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
484 if(nNewBorder
> 100L)
490 if(nNewBorder
!= rG
.aGradient
.GetBorder())
492 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
495 // angle is not definitely necessary for these modes, but it makes
496 // controlling more fun for the user
497 aFullVec
.normalize();
498 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
499 fNewFullAngle
/= F_PI180
;
500 fNewFullAngle
*= -10.0;
501 fNewFullAngle
+= 900.0;
504 while(fNewFullAngle
< 0.0)
506 fNewFullAngle
+= 3600.0;
509 while(fNewFullAngle
>= 3600.0)
511 fNewFullAngle
-= 3600.0;
515 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
517 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
519 rG
.aGradient
.SetAngle(nNewAngle
);
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */