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