1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gradtrns.cxx,v $
10 * $Revision: 1.7.226.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include "gradtrns.hxx"
35 #include <svx/svdobj.hxx>
36 #include <basegfx/range/b2drange.hxx>
37 #include <basegfx/matrix/b2dhommatrix.hxx>
38 #include <vcl/salbtype.hxx> // FRound
40 //////////////////////////////////////////////////////////////////////////////
42 void GradTransformer::GradToVec(GradTransGradient
& rG
, GradTransVector
& rV
, const SdrObject
* pObj
)
45 rV
.aCol1
= rG
.aGradient
.GetStartColor();
46 if(100 != rG
.aGradient
.GetStartIntens())
48 const double fFact((double)rG
.aGradient
.GetStartIntens() / 100.0);
49 rV
.aCol1
= Color(rV
.aCol1
.getBColor() * fFact
);
53 rV
.aCol2
= rG
.aGradient
.GetEndColor();
54 if(100 != rG
.aGradient
.GetEndIntens())
56 const double fFact((double)rG
.aGradient
.GetEndIntens() / 100.0);
57 rV
.aCol2
= Color(rV
.aCol2
.getBColor() * fFact
);
60 // calc the basic positions
61 const Rectangle
aObjectSnapRectangle(pObj
->GetSnapRect());
62 const basegfx::B2DRange
aRange(aObjectSnapRectangle
.Left(), aObjectSnapRectangle
.Top(), aObjectSnapRectangle
.Right(), aObjectSnapRectangle
.Bottom());
63 const basegfx::B2DPoint
aCenter(aRange
.getCenter());
64 basegfx::B2DPoint aStartPos
, aEndPos
;
66 switch(rG
.aGradient
.GetGradientStyle())
70 aStartPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMinY());
71 aEndPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY());
73 if(rG
.aGradient
.GetBorder())
75 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
76 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
78 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
81 if(rG
.aGradient
.GetAngle())
83 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
84 basegfx::B2DHomMatrix aTransformation
;
86 aTransformation
.translate(-aCenter
.getX(), -aCenter
.getY());
87 aTransformation
.rotate(-fAngle
);
88 aTransformation
.translate(aCenter
.getX(), aCenter
.getY());
90 aStartPos
*= aTransformation
;
91 aEndPos
*= aTransformation
;
98 aEndPos
= basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY());
100 if(rG
.aGradient
.GetBorder())
102 basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
103 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
104 aFullVec
.normalize();
105 aEndPos
= aStartPos
+ (aFullVec
* fLen
);
108 if(rG
.aGradient
.GetAngle())
110 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
111 basegfx::B2DHomMatrix aTransformation
;
113 aTransformation
.translate(-aCenter
.getX(), -aCenter
.getY());
114 aTransformation
.rotate(-fAngle
);
115 aTransformation
.translate(aCenter
.getX(), aCenter
.getY());
117 aStartPos
*= aTransformation
;
118 aEndPos
*= aTransformation
;
125 aStartPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMaximum().getY());
126 aEndPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMinY());
128 if(rG
.aGradient
.GetBorder())
130 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
131 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
132 aFullVec
.normalize();
133 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
136 if(rG
.aGradient
.GetAngle())
138 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
139 basegfx::B2DHomMatrix aTransformation
;
141 aTransformation
.translate(-aEndPos
.getX(), -aEndPos
.getY());
142 aTransformation
.rotate(-fAngle
);
143 aTransformation
.translate(aEndPos
.getX(), aEndPos
.getY());
145 aStartPos
*= aTransformation
;
146 aEndPos
*= aTransformation
;
149 if(rG
.aGradient
.GetXOffset() || rG
.aGradient
.GetYOffset())
151 basegfx::B2DPoint
aOffset(
152 (aRange
.getWidth() * rG
.aGradient
.GetXOffset()) / 100.0,
153 (aRange
.getHeight() * rG
.aGradient
.GetYOffset()) / 100.0);
155 aStartPos
+= aOffset
;
161 case XGRAD_ELLIPTICAL
:
164 aStartPos
= basegfx::B2DPoint(aRange
.getMinX(), aCenter
.getY());
165 aEndPos
= basegfx::B2DPoint(aRange
.getMinX(), aRange
.getMinY());
167 if(rG
.aGradient
.GetBorder())
169 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
170 const double fLen
= (aFullVec
.getLength() * (100.0 - (double)rG
.aGradient
.GetBorder())) / 100.0;
171 aFullVec
.normalize();
172 aStartPos
= aEndPos
+ (aFullVec
* fLen
);
175 if(rG
.aGradient
.GetAngle())
177 const double fAngle
= (double)rG
.aGradient
.GetAngle() * (F_PI180
/ 10.0);
178 basegfx::B2DHomMatrix aTransformation
;
180 aTransformation
.translate(-aEndPos
.getX(), -aEndPos
.getY());
181 aTransformation
.rotate(-fAngle
);
182 aTransformation
.translate(aEndPos
.getX(), aEndPos
.getY());
184 aStartPos
*= aTransformation
;
185 aEndPos
*= aTransformation
;
188 if(rG
.aGradient
.GetXOffset() || rG
.aGradient
.GetYOffset())
190 basegfx::B2DPoint
aOffset(
191 (aRange
.getWidth() * rG
.aGradient
.GetXOffset()) / 100.0,
192 (aRange
.getHeight() * rG
.aGradient
.GetYOffset()) / 100.0);
194 aStartPos
+= aOffset
;
202 // set values for vector positions now
203 rV
.maPositionA
= aStartPos
;
204 rV
.maPositionB
= aEndPos
;
207 //////////////////////////////////////////////////////////////////////////////
209 void GradTransformer::VecToGrad(GradTransVector
& rV
, GradTransGradient
& rG
, GradTransGradient
& rGOld
, const SdrObject
* pObj
,
210 sal_Bool bMoveSingle
, sal_Bool bMoveFirst
)
212 // fill old gradient to new gradient to have a base
215 // handle color changes
216 if(rV
.aCol1
!= rGOld
.aGradient
.GetStartColor())
218 rG
.aGradient
.SetStartColor(rV
.aCol1
);
219 rG
.aGradient
.SetStartIntens(100);
221 if(rV
.aCol2
!= rGOld
.aGradient
.GetEndColor())
223 rG
.aGradient
.SetEndColor(rV
.aCol2
);
224 rG
.aGradient
.SetEndIntens(100);
227 // calc the basic positions
228 const Rectangle
aObjectSnapRectangle(pObj
->GetSnapRect());
229 const basegfx::B2DRange
aRange(aObjectSnapRectangle
.Left(), aObjectSnapRectangle
.Top(), aObjectSnapRectangle
.Right(), aObjectSnapRectangle
.Bottom());
230 const basegfx::B2DPoint
aCenter(aRange
.getCenter());
231 basegfx::B2DPoint
aStartPos(rV
.maPositionA
);
232 basegfx::B2DPoint
aEndPos(rV
.maPositionB
);
234 switch(rG
.aGradient
.GetGradientStyle())
238 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
240 basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
244 aFullVec
= aEndPos
- aCenter
;
247 aFullVec
.normalize();
249 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
250 fNewFullAngle
/= F_PI180
;
251 fNewFullAngle
*= -10.0;
252 fNewFullAngle
+= 900.0;
255 while(fNewFullAngle
< 0.0)
257 fNewFullAngle
+= 3600.0;
260 while(fNewFullAngle
>= 3600.0)
262 fNewFullAngle
-= 3600.0;
266 sal_Int32 nNewAngle
= FRound(fNewFullAngle
);
268 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
270 rG
.aGradient
.SetAngle(nNewAngle
);
274 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
276 const basegfx::B2DVector
aFullVec(aEndPos
- aStartPos
);
277 const basegfx::B2DPoint
aBottomLeft(aRange
.getMinX(), aRange
.getMaximum().getY());
278 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
279 const basegfx::B2DVector
aOldVec(aBottomLeft
- aTopLeft
);
280 const double fFullLen(aFullVec
.getLength());
281 const double fOldLen(aOldVec
.getLength());
282 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
283 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
291 if(nNewBorder
> 100L)
297 if(nNewBorder
!= rG
.aGradient
.GetBorder())
299 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
307 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
309 basegfx::B2DVector
aFullVec(aEndPos
- aCenter
);
310 const basegfx::B2DVector
aOldVec(basegfx::B2DPoint(aCenter
.getX(), aRange
.getMaximum().getY()) - aCenter
);
311 const double fFullLen(aFullVec
.getLength());
312 const double fOldLen(aOldVec
.getLength());
313 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
314 sal_Int32 nNewBorder
= 100 - FRound(fNewBorder
);
322 if(nNewBorder
> 100L)
328 if(nNewBorder
!= rG
.aGradient
.GetBorder())
330 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
333 aFullVec
.normalize();
334 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
335 fNewFullAngle
/= F_PI180
;
336 fNewFullAngle
*= -10.0;
337 fNewFullAngle
+= 900.0;
340 while(fNewFullAngle
< 0.0)
342 fNewFullAngle
+= 3600.0;
345 while(fNewFullAngle
>= 3600.0)
347 fNewFullAngle
-= 3600.0;
351 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
353 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
355 rG
.aGradient
.SetAngle(nNewAngle
);
364 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
366 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
367 const basegfx::B2DPoint
aOffset(aEndPos
- aTopLeft
);
368 sal_Int32
nNewXOffset(FRound((aOffset
.getX() * 100.0) / aRange
.getWidth()));
369 sal_Int32
nNewYOffset(FRound((aOffset
.getY() * 100.0) / aRange
.getHeight()));
377 if(nNewXOffset
> 100L)
387 if(nNewYOffset
> 100L)
392 rG
.aGradient
.SetXOffset((sal_uInt16
)nNewXOffset
);
393 rG
.aGradient
.SetYOffset((sal_uInt16
)nNewYOffset
);
395 aStartPos
-= aOffset
;
399 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
401 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
402 const basegfx::B2DPoint
aBottomLeft(aRange
.getMinX(), aRange
.getMaximum().getY());
403 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
404 const basegfx::B2DVector
aOldVec(aBottomLeft
- aTopLeft
);
405 const double fFullLen(aFullVec
.getLength());
406 const double fOldLen(aOldVec
.getLength());
407 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
408 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
416 if(nNewBorder
> 100L)
422 if(nNewBorder
!= rG
.aGradient
.GetBorder())
424 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
427 // angle is not definitely necessary for these modes, but it makes
428 // controlling more fun for the user
429 aFullVec
.normalize();
430 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
431 fNewFullAngle
/= F_PI180
;
432 fNewFullAngle
*= -10.0;
433 fNewFullAngle
+= 900.0;
436 while(fNewFullAngle
< 0.0)
438 fNewFullAngle
+= 3600.0;
441 while(fNewFullAngle
>= 3600.0)
443 fNewFullAngle
-= 3600.0;
447 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
449 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
451 rG
.aGradient
.SetAngle(nNewAngle
);
457 case XGRAD_ELLIPTICAL
:
460 if(!bMoveSingle
|| (bMoveSingle
&& !bMoveFirst
))
462 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
463 const basegfx::B2DPoint
aOffset(aEndPos
- aTopLeft
);
464 sal_Int32
nNewXOffset(FRound((aOffset
.getX() * 100.0) / aRange
.getWidth()));
465 sal_Int32
nNewYOffset(FRound((aOffset
.getY() * 100.0) / aRange
.getHeight()));
473 if(nNewXOffset
> 100L)
483 if(nNewYOffset
> 100L)
488 rG
.aGradient
.SetXOffset((sal_uInt16
)nNewXOffset
);
489 rG
.aGradient
.SetYOffset((sal_uInt16
)nNewYOffset
);
491 aStartPos
-= aOffset
;
495 if(!bMoveSingle
|| (bMoveSingle
&& bMoveFirst
))
497 basegfx::B2DVector
aFullVec(aStartPos
- aEndPos
);
498 const basegfx::B2DPoint
aTopLeft(aRange
.getMinX(), aRange
.getMinY());
499 const basegfx::B2DPoint
aCenterLeft(aRange
.getMinX(), aRange
.getHeight());
500 const basegfx::B2DVector
aOldVec(aCenterLeft
- aTopLeft
);
501 const double fFullLen(aFullVec
.getLength());
502 const double fOldLen(aOldVec
.getLength());
503 const double fNewBorder((fFullLen
* 100.0) / fOldLen
);
504 sal_Int32
nNewBorder(100L - FRound(fNewBorder
));
512 if(nNewBorder
> 100L)
518 if(nNewBorder
!= rG
.aGradient
.GetBorder())
520 rG
.aGradient
.SetBorder((sal_uInt16
)nNewBorder
);
523 // angle is not definitely necessary for these modes, but it makes
524 // controlling more fun for the user
525 aFullVec
.normalize();
526 double fNewFullAngle(atan2(aFullVec
.getY(), aFullVec
.getX()));
527 fNewFullAngle
/= F_PI180
;
528 fNewFullAngle
*= -10.0;
529 fNewFullAngle
+= 900.0;
532 while(fNewFullAngle
< 0.0)
534 fNewFullAngle
+= 3600.0;
537 while(fNewFullAngle
>= 3600.0)
539 fNewFullAngle
-= 3600.0;
543 const sal_Int32
nNewAngle(FRound(fNewFullAngle
));
545 if(nNewAngle
!= rGOld
.aGradient
.GetAngle())
547 rG
.aGradient
.SetAngle(nNewAngle
);