Update ooo320-m1
[ooovba.git] / svx / source / svdraw / gradtrns.cxx
blob75da911e8cc5901355d71c7c260ea3c61537cced
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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)
44 // handle start color
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);
52 // handle end color
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())
68 case XGRAD_LINEAR :
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;
77 aFullVec.normalize();
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;
93 break;
95 case XGRAD_AXIAL :
97 aStartPos = aCenter;
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;
120 break;
122 case XGRAD_RADIAL :
123 case XGRAD_SQUARE :
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;
156 aEndPos += aOffset;
159 break;
161 case XGRAD_ELLIPTICAL :
162 case XGRAD_RECT :
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;
195 aEndPos += aOffset;
198 break;
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
213 rG = rGOld;
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())
236 case XGRAD_LINEAR :
238 if(!bMoveSingle || (bMoveSingle && !bMoveFirst))
240 basegfx::B2DVector aFullVec(aEndPos - aStartPos);
242 if(bMoveSingle)
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;
254 // clip
255 while(fNewFullAngle < 0.0)
257 fNewFullAngle += 3600.0;
260 while(fNewFullAngle >= 3600.0)
262 fNewFullAngle -= 3600.0;
265 // to int and set
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));
285 // clip
286 if(nNewBorder < 0L)
288 nNewBorder = 0L;
291 if(nNewBorder > 100L)
293 nNewBorder = 100L;
296 // set
297 if(nNewBorder != rG.aGradient.GetBorder())
299 rG.aGradient.SetBorder((sal_uInt16)nNewBorder);
303 break;
305 case XGRAD_AXIAL :
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);
316 // clip
317 if(nNewBorder < 0L)
319 nNewBorder = 0L;
322 if(nNewBorder > 100L)
324 nNewBorder = 100L;
327 // set
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;
339 // clip
340 while(fNewFullAngle < 0.0)
342 fNewFullAngle += 3600.0;
345 while(fNewFullAngle >= 3600.0)
347 fNewFullAngle -= 3600.0;
350 // to int and set
351 const sal_Int32 nNewAngle(FRound(fNewFullAngle));
353 if(nNewAngle != rGOld.aGradient.GetAngle())
355 rG.aGradient.SetAngle(nNewAngle);
359 break;
361 case XGRAD_RADIAL :
362 case XGRAD_SQUARE :
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()));
371 // clip
372 if(nNewXOffset < 0L)
374 nNewXOffset = 0L;
377 if(nNewXOffset > 100L)
379 nNewXOffset = 100L;
382 if(nNewYOffset < 0L)
384 nNewYOffset = 0L;
387 if(nNewYOffset > 100L)
389 nNewYOffset = 100L;
392 rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset);
393 rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset);
395 aStartPos -= aOffset;
396 aEndPos -= 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));
410 // clip
411 if(nNewBorder < 0L)
413 nNewBorder = 0L;
416 if(nNewBorder > 100L)
418 nNewBorder = 100L;
421 // set
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;
435 // clip
436 while(fNewFullAngle < 0.0)
438 fNewFullAngle += 3600.0;
441 while(fNewFullAngle >= 3600.0)
443 fNewFullAngle -= 3600.0;
446 // to int and set
447 const sal_Int32 nNewAngle(FRound(fNewFullAngle));
449 if(nNewAngle != rGOld.aGradient.GetAngle())
451 rG.aGradient.SetAngle(nNewAngle);
455 break;
457 case XGRAD_ELLIPTICAL :
458 case XGRAD_RECT :
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()));
467 // clip
468 if(nNewXOffset < 0L)
470 nNewXOffset = 0L;
473 if(nNewXOffset > 100L)
475 nNewXOffset = 100L;
478 if(nNewYOffset < 0L)
480 nNewYOffset = 0L;
483 if(nNewYOffset > 100L)
485 nNewYOffset = 100L;
488 rG.aGradient.SetXOffset((sal_uInt16)nNewXOffset);
489 rG.aGradient.SetYOffset((sal_uInt16)nNewYOffset);
491 aStartPos -= aOffset;
492 aEndPos -= 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));
506 // clip
507 if(nNewBorder < 0L)
509 nNewBorder = 0L;
512 if(nNewBorder > 100L)
514 nNewBorder = 100L;
517 // set
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;
531 // clip
532 while(fNewFullAngle < 0.0)
534 fNewFullAngle += 3600.0;
537 while(fNewFullAngle >= 3600.0)
539 fNewFullAngle -= 3600.0;
542 // to int and set
543 const sal_Int32 nNewAngle(FRound(fNewFullAngle));
545 if(nNewAngle != rGOld.aGradient.GetAngle())
547 rG.aGradient.SetAngle(nNewAngle);
551 break;
556 // eof