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_drawinglayer.hxx" 26 27 #include <drawinglayer/texture/texture.hxx> 28 #include <basegfx/numeric/ftools.hxx> 29 #include <basegfx/tools/gradienttools.hxx> 30 #include <basegfx/matrix/b2dhommatrixtools.hxx> 31 32 ////////////////////////////////////////////////////////////////////////////// 33 34 namespace drawinglayer 35 { 36 namespace texture 37 { GeoTexSvx()38 GeoTexSvx::GeoTexSvx() 39 { 40 } 41 ~GeoTexSvx()42 GeoTexSvx::~GeoTexSvx() 43 { 44 } 45 operator ==(const GeoTexSvx &) const46 bool GeoTexSvx::operator==(const GeoTexSvx& /*rGeoTexSvx*/) const 47 { 48 // default implementation says yes (no data -> no difference) 49 return true; 50 } 51 modifyBColor(const basegfx::B2DPoint &,basegfx::BColor & rBColor,double &) const52 void GeoTexSvx::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 53 { 54 // base implementation creates random color (for testing only, may also be pure virtual) 55 rBColor.setRed((rand() & 0x7fff) / 32767.0); 56 rBColor.setGreen((rand() & 0x7fff) / 32767.0); 57 rBColor.setBlue((rand() & 0x7fff) / 32767.0); 58 } 59 modifyOpacity(const basegfx::B2DPoint & rUV,double & rfOpacity) const60 void GeoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const 61 { 62 // base implementation uses inverse of luminance of solved color (for testing only, may also be pure virtual) 63 basegfx::BColor aBaseColor; 64 modifyBColor(rUV, aBaseColor, rfOpacity); 65 rfOpacity = 1.0 - aBaseColor.luminance(); 66 } 67 } // end of namespace texture 68 } // end of namespace drawinglayer 69 70 ////////////////////////////////////////////////////////////////////////////// 71 72 namespace drawinglayer 73 { 74 namespace texture 75 { GeoTexSvxGradient(const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32,double fBorder)76 GeoTexSvxGradient::GeoTexSvxGradient( 77 const basegfx::B2DRange& rDefinitionRange, 78 const basegfx::BColor& rStart, 79 const basegfx::BColor& rEnd, 80 sal_uInt32 /* nSteps */, 81 double fBorder) 82 : GeoTexSvx(), 83 maGradientInfo(), 84 maDefinitionRange(rDefinitionRange), 85 maStart(rStart), 86 maEnd(rEnd), 87 mfBorder(fBorder) 88 { 89 } 90 ~GeoTexSvxGradient()91 GeoTexSvxGradient::~GeoTexSvxGradient() 92 { 93 } 94 operator ==(const GeoTexSvx & rGeoTexSvx) const95 bool GeoTexSvxGradient::operator==(const GeoTexSvx& rGeoTexSvx) const 96 { 97 const GeoTexSvxGradient* pCompare = dynamic_cast< const GeoTexSvxGradient* >(&rGeoTexSvx); 98 99 return (pCompare 100 && maGradientInfo == pCompare->maGradientInfo 101 && maDefinitionRange == pCompare->maDefinitionRange 102 && mfBorder == pCompare->mfBorder); 103 } 104 } // end of namespace texture 105 } // end of namespace drawinglayer 106 107 ////////////////////////////////////////////////////////////////////////////// 108 109 namespace drawinglayer 110 { 111 namespace texture 112 { GeoTexSvxGradientLinear(const basegfx::B2DRange & rDefinitionRange,const basegfx::B2DRange & rOutputRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fAngle)113 GeoTexSvxGradientLinear::GeoTexSvxGradientLinear( 114 const basegfx::B2DRange& rDefinitionRange, 115 const basegfx::B2DRange& rOutputRange, 116 const basegfx::BColor& rStart, 117 const basegfx::BColor& rEnd, 118 sal_uInt32 nSteps, 119 double fBorder, 120 double fAngle) 121 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder), 122 mfUnitMinX(0.0), 123 mfUnitWidth(1.0), 124 mfUnitMaxY(1.0) 125 { 126 maGradientInfo = basegfx::tools::createLinearODFGradientInfo( 127 rDefinitionRange, 128 nSteps, 129 fBorder, 130 fAngle); 131 132 if(rDefinitionRange != rOutputRange) 133 { 134 basegfx::B2DRange aInvOutputRange(rOutputRange); 135 136 aInvOutputRange.transform(maGradientInfo.getBackTextureTransform()); 137 mfUnitMinX = aInvOutputRange.getMinX(); 138 mfUnitWidth = aInvOutputRange.getWidth(); 139 mfUnitMaxY = aInvOutputRange.getMaxY(); 140 } 141 } 142 ~GeoTexSvxGradientLinear()143 GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear() 144 { 145 } 146 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)147 void GeoTexSvxGradientLinear::appendTransformationsAndColors( 148 std::vector< B2DHomMatrixAndBColor >& rEntries, 149 basegfx::BColor& rOuterColor) 150 { 151 rOuterColor = maStart; 152 153 if(maGradientInfo.getSteps()) 154 { 155 const double fStripeWidth(1.0 / maGradientInfo.getSteps()); 156 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 157 basegfx::B2DHomMatrix aPattern; 158 159 // bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] 160 aPattern.scale(0.5, 0.5); 161 aPattern.translate(0.5, 0.5); 162 163 // scale and translate in X 164 aPattern.scale(mfUnitWidth, 1.0); 165 aPattern.translate(mfUnitMinX, 0.0); 166 167 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 168 { 169 const double fPos(fStripeWidth * a); 170 basegfx::B2DHomMatrix aNew(aPattern); 171 172 // scale and translate in Y 173 double fHeight(1.0 - fPos); 174 175 if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0) 176 { 177 fHeight += mfUnitMaxY - 1.0; 178 } 179 180 aNew.scale(1.0, fHeight); 181 aNew.translate(0.0, fPos); 182 183 // set at target 184 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; 185 186 // interpolate and set color 187 aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); 188 189 rEntries.push_back(aB2DHomMatrixAndBColor); 190 } 191 } 192 } 193 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const194 void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 195 { 196 const double fScaler(basegfx::tools::getLinearGradientAlpha(rUV, maGradientInfo)); 197 198 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 199 } 200 } // end of namespace texture 201 } // end of namespace drawinglayer 202 203 ////////////////////////////////////////////////////////////////////////////// 204 205 namespace drawinglayer 206 { 207 namespace texture 208 { GeoTexSvxGradientAxial(const basegfx::B2DRange & rDefinitionRange,const basegfx::B2DRange & rOutputRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fAngle)209 GeoTexSvxGradientAxial::GeoTexSvxGradientAxial( 210 const basegfx::B2DRange& rDefinitionRange, 211 const basegfx::B2DRange& rOutputRange, 212 const basegfx::BColor& rStart, 213 const basegfx::BColor& rEnd, 214 sal_uInt32 nSteps, 215 double fBorder, 216 double fAngle) 217 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder), 218 mfUnitMinX(0.0), 219 mfUnitWidth(1.0) 220 { 221 maGradientInfo = basegfx::tools::createAxialODFGradientInfo( 222 rDefinitionRange, 223 nSteps, 224 fBorder, 225 fAngle); 226 227 if(rDefinitionRange != rOutputRange) 228 { 229 basegfx::B2DRange aInvOutputRange(rOutputRange); 230 231 aInvOutputRange.transform(maGradientInfo.getBackTextureTransform()); 232 mfUnitMinX = aInvOutputRange.getMinX(); 233 mfUnitWidth = aInvOutputRange.getWidth(); 234 } 235 } 236 ~GeoTexSvxGradientAxial()237 GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial() 238 { 239 } 240 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)241 void GeoTexSvxGradientAxial::appendTransformationsAndColors( 242 std::vector< B2DHomMatrixAndBColor >& rEntries, 243 basegfx::BColor& rOuterColor) 244 { 245 rOuterColor = maEnd; 246 247 if(maGradientInfo.getSteps()) 248 { 249 const double fStripeWidth(1.0 / maGradientInfo.getSteps()); 250 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 251 252 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 253 { 254 const double fPos(fStripeWidth * a); 255 basegfx::B2DHomMatrix aNew; 256 257 // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] 258 aNew.scale(0.5, 1.0); 259 aNew.translate(0.5, 0.0); 260 261 // scale/translate in X 262 aNew.scale(mfUnitWidth, 1.0); 263 aNew.translate(mfUnitMinX, 0.0); 264 265 // already centerd in Y on X-Axis, just scale in Y 266 aNew.scale(1.0, 1.0 - fPos); 267 268 // set at target 269 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; 270 271 // interpolate and set color 272 aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1)); 273 274 rEntries.push_back(aB2DHomMatrixAndBColor); 275 } 276 } 277 } 278 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const279 void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 280 { 281 const double fScaler(basegfx::tools::getAxialGradientAlpha(rUV, maGradientInfo)); 282 283 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 284 } 285 } // end of namespace texture 286 } // end of namespace drawinglayer 287 288 ////////////////////////////////////////////////////////////////////////////// 289 290 namespace drawinglayer 291 { 292 namespace texture 293 { GeoTexSvxGradientRadial(const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY)294 GeoTexSvxGradientRadial::GeoTexSvxGradientRadial( 295 const basegfx::B2DRange& rDefinitionRange, 296 const basegfx::BColor& rStart, 297 const basegfx::BColor& rEnd, 298 sal_uInt32 nSteps, 299 double fBorder, 300 double fOffsetX, 301 double fOffsetY) 302 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) 303 { 304 maGradientInfo = basegfx::tools::createRadialODFGradientInfo( 305 rDefinitionRange, 306 basegfx::B2DVector(fOffsetX,fOffsetY), 307 nSteps, 308 fBorder); 309 } 310 ~GeoTexSvxGradientRadial()311 GeoTexSvxGradientRadial::~GeoTexSvxGradientRadial() 312 { 313 } 314 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)315 void GeoTexSvxGradientRadial::appendTransformationsAndColors( 316 std::vector< B2DHomMatrixAndBColor >& rEntries, 317 basegfx::BColor& rOuterColor) 318 { 319 rOuterColor = maStart; 320 321 if(maGradientInfo.getSteps()) 322 { 323 const double fStepSize(1.0 / maGradientInfo.getSteps()); 324 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 325 326 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 327 { 328 const double fSize(1.0 - (fStepSize * a)); 329 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize); 330 aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); 331 rEntries.push_back(aB2DHomMatrixAndBColor); 332 } 333 } 334 } 335 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const336 void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 337 { 338 const double fScaler(basegfx::tools::getRadialGradientAlpha(rUV, maGradientInfo)); 339 340 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 341 } 342 } // end of namespace texture 343 } // end of namespace drawinglayer 344 345 ////////////////////////////////////////////////////////////////////////////// 346 347 namespace drawinglayer 348 { 349 namespace texture 350 { GeoTexSvxGradientElliptical(const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)351 GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical( 352 const basegfx::B2DRange& rDefinitionRange, 353 const basegfx::BColor& rStart, 354 const basegfx::BColor& rEnd, 355 sal_uInt32 nSteps, 356 double fBorder, 357 double fOffsetX, 358 double fOffsetY, 359 double fAngle) 360 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) 361 { 362 maGradientInfo = basegfx::tools::createEllipticalODFGradientInfo( 363 rDefinitionRange, 364 basegfx::B2DVector(fOffsetX,fOffsetY), 365 nSteps, 366 fBorder, 367 fAngle); 368 } 369 ~GeoTexSvxGradientElliptical()370 GeoTexSvxGradientElliptical::~GeoTexSvxGradientElliptical() 371 { 372 } 373 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)374 void GeoTexSvxGradientElliptical::appendTransformationsAndColors( 375 std::vector< B2DHomMatrixAndBColor >& rEntries, 376 basegfx::BColor& rOuterColor) 377 { 378 rOuterColor = maStart; 379 380 if(maGradientInfo.getSteps()) 381 { 382 double fWidth(1.0); 383 double fHeight(1.0); 384 double fIncrementX(0.0); 385 double fIncrementY(0.0); 386 387 if(maGradientInfo.getAspectRatio() > 1.0) 388 { 389 fIncrementY = fHeight / maGradientInfo.getSteps(); 390 fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); 391 } 392 else 393 { 394 fIncrementX = fWidth / maGradientInfo.getSteps(); 395 fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); 396 } 397 398 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 399 400 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 401 { 402 // next step 403 fWidth -= fIncrementX; 404 fHeight -= fIncrementY; 405 406 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight); 407 aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); 408 rEntries.push_back(aB2DHomMatrixAndBColor); 409 } 410 } 411 } 412 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const413 void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 414 { 415 const double fScaler(basegfx::tools::getEllipticalGradientAlpha(rUV, maGradientInfo)); 416 417 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 418 } 419 } // end of namespace texture 420 } // end of namespace drawinglayer 421 422 ////////////////////////////////////////////////////////////////////////////// 423 424 namespace drawinglayer 425 { 426 namespace texture 427 { GeoTexSvxGradientSquare(const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)428 GeoTexSvxGradientSquare::GeoTexSvxGradientSquare( 429 const basegfx::B2DRange& rDefinitionRange, 430 const basegfx::BColor& rStart, 431 const basegfx::BColor& rEnd, 432 sal_uInt32 nSteps, 433 double fBorder, 434 double fOffsetX, 435 double fOffsetY, 436 double fAngle) 437 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) 438 { 439 maGradientInfo = basegfx::tools::createSquareODFGradientInfo( 440 rDefinitionRange, 441 basegfx::B2DVector(fOffsetX,fOffsetY), 442 nSteps, 443 fBorder, 444 fAngle); 445 } 446 ~GeoTexSvxGradientSquare()447 GeoTexSvxGradientSquare::~GeoTexSvxGradientSquare() 448 { 449 } 450 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)451 void GeoTexSvxGradientSquare::appendTransformationsAndColors( 452 std::vector< B2DHomMatrixAndBColor >& rEntries, 453 basegfx::BColor& rOuterColor) 454 { 455 rOuterColor = maStart; 456 457 if(maGradientInfo.getSteps()) 458 { 459 const double fStepSize(1.0 / maGradientInfo.getSteps()); 460 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 461 462 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 463 { 464 const double fSize(1.0 - (fStepSize * a)); 465 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize); 466 aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); 467 rEntries.push_back(aB2DHomMatrixAndBColor); 468 } 469 } 470 } 471 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const472 void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 473 { 474 const double fScaler(basegfx::tools::getSquareGradientAlpha(rUV, maGradientInfo)); 475 476 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 477 } 478 } // end of namespace texture 479 } // end of namespace drawinglayer 480 481 ////////////////////////////////////////////////////////////////////////////// 482 483 namespace drawinglayer 484 { 485 namespace texture 486 { GeoTexSvxGradientRect(const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)487 GeoTexSvxGradientRect::GeoTexSvxGradientRect( 488 const basegfx::B2DRange& rDefinitionRange, 489 const basegfx::BColor& rStart, 490 const basegfx::BColor& rEnd, 491 sal_uInt32 nSteps, 492 double fBorder, 493 double fOffsetX, 494 double fOffsetY, 495 double fAngle) 496 : GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder) 497 { 498 maGradientInfo = basegfx::tools::createRectangularODFGradientInfo( 499 rDefinitionRange, 500 basegfx::B2DVector(fOffsetX,fOffsetY), 501 nSteps, 502 fBorder, 503 fAngle); 504 } 505 ~GeoTexSvxGradientRect()506 GeoTexSvxGradientRect::~GeoTexSvxGradientRect() 507 { 508 } 509 appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOuterColor)510 void GeoTexSvxGradientRect::appendTransformationsAndColors( 511 std::vector< B2DHomMatrixAndBColor >& rEntries, 512 basegfx::BColor& rOuterColor) 513 { 514 rOuterColor = maStart; 515 516 if(maGradientInfo.getSteps()) 517 { 518 double fWidth(1.0); 519 double fHeight(1.0); 520 double fIncrementX(0.0); 521 double fIncrementY(0.0); 522 523 if(maGradientInfo.getAspectRatio() > 1.0) 524 { 525 fIncrementY = fHeight / maGradientInfo.getSteps(); 526 fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); 527 } 528 else 529 { 530 fIncrementX = fWidth / maGradientInfo.getSteps(); 531 fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); 532 } 533 534 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; 535 536 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) 537 { 538 // next step 539 fWidth -= fIncrementX; 540 fHeight -= fIncrementY; 541 542 aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight); 543 aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); 544 rEntries.push_back(aB2DHomMatrixAndBColor); 545 } 546 } 547 } 548 modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const549 void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const 550 { 551 const double fScaler(basegfx::tools::getRectangularGradientAlpha(rUV, maGradientInfo)); 552 553 rBColor = basegfx::interpolate(maStart, maEnd, fScaler); 554 } 555 } // end of namespace texture 556 } // end of namespace drawinglayer 557 558 ////////////////////////////////////////////////////////////////////////////// 559 560 namespace drawinglayer 561 { 562 namespace texture 563 { GeoTexSvxHatch(const basegfx::B2DRange & rDefinitionRange,const basegfx::B2DRange & rOutputRange,double fDistance,double fAngle)564 GeoTexSvxHatch::GeoTexSvxHatch( 565 const basegfx::B2DRange& rDefinitionRange, 566 const basegfx::B2DRange& rOutputRange, 567 double fDistance, 568 double fAngle) 569 : maOutputRange(rOutputRange), 570 maTextureTransform(), 571 maBackTextureTransform(), 572 mfDistance(0.1), 573 mfAngle(fAngle), 574 mnSteps(10), 575 mbDefinitionRangeEqualsOutputRange(rDefinitionRange == rOutputRange) 576 { 577 double fTargetSizeX(rDefinitionRange.getWidth()); 578 double fTargetSizeY(rDefinitionRange.getHeight()); 579 double fTargetOffsetX(rDefinitionRange.getMinX()); 580 double fTargetOffsetY(rDefinitionRange.getMinY()); 581 582 fAngle = -fAngle; 583 584 // add object expansion 585 if(0.0 != fAngle) 586 { 587 const double fAbsCos(fabs(cos(fAngle))); 588 const double fAbsSin(fabs(sin(fAngle))); 589 const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); 590 const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); 591 fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; 592 fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; 593 fTargetSizeX = fNewX; 594 fTargetSizeY = fNewY; 595 } 596 597 // add object scale before rotate 598 maTextureTransform.scale(fTargetSizeX, fTargetSizeY); 599 600 // add texture rotate after scale to keep perpendicular angles 601 if(0.0 != fAngle) 602 { 603 basegfx::B2DPoint aCenter(0.5, 0.5); 604 aCenter *= maTextureTransform; 605 606 maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle) 607 * maTextureTransform; 608 } 609 610 // add object translate 611 maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); 612 613 // prepare height for texture 614 const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0); 615 mnSteps = basegfx::fround(fSteps + 0.5); 616 mfDistance = 1.0 / fSteps; 617 } 618 ~GeoTexSvxHatch()619 GeoTexSvxHatch::~GeoTexSvxHatch() 620 { 621 } 622 operator ==(const GeoTexSvx & rGeoTexSvx) const623 bool GeoTexSvxHatch::operator==(const GeoTexSvx& rGeoTexSvx) const 624 { 625 const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx); 626 return (pCompare 627 && maOutputRange == pCompare->maOutputRange 628 && maTextureTransform == pCompare->maTextureTransform 629 && mfDistance == pCompare->mfDistance 630 && mfAngle == pCompare->mfAngle 631 && mnSteps == pCompare->mnSteps); 632 } 633 appendTransformations(::std::vector<basegfx::B2DHomMatrix> & rMatrices)634 void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) 635 { 636 if(mbDefinitionRangeEqualsOutputRange) 637 { 638 // simple hatch where the definition area equals the output area 639 for(sal_uInt32 a(1); a < mnSteps; a++) 640 { 641 // create matrix 642 const double fOffset(mfDistance * (double)a); 643 basegfx::B2DHomMatrix aNew; 644 aNew.set(1, 2, fOffset); 645 rMatrices.push_back(maTextureTransform * aNew); 646 } 647 } 648 else 649 { 650 // output area is different from definition area, back-transform to get 651 // the output area in unit coordinates and fill this with hatch lines 652 // using the settings derived from the definition area 653 basegfx::B2DRange aBackUnitRange(maOutputRange); 654 655 aBackUnitRange.transform(getBackTextureTransform()); 656 657 // calculate vertical start value and a security maximum integer value to avoid death loops 658 double fStart(basegfx::snapToNearestMultiple(aBackUnitRange.getMinY(), mfDistance)); 659 const sal_uInt32 nNeededIntegerSteps(basegfx::fround((aBackUnitRange.getHeight() / mfDistance) + 0.5)); 660 sal_uInt32 nMaxIntegerSteps(::std::min(nNeededIntegerSteps, sal_uInt32(10000))); 661 662 while(fStart < aBackUnitRange.getMaxY() && nMaxIntegerSteps) 663 { 664 // create new transform for 665 basegfx::B2DHomMatrix aNew; 666 667 // adapt x scale and position 668 //aNew.scale(aBackUnitRange.getWidth(), 1.0); 669 //aNew.translate(aBackUnitRange.getMinX(), 0.0); 670 aNew.set(0, 0, aBackUnitRange.getWidth()); 671 aNew.set(0, 2, aBackUnitRange.getMinX()); 672 673 // adapt y position to current step 674 aNew.set(1, 2, fStart); 675 //aNew.translate(0.0, fStart); 676 677 // add new transformation 678 rMatrices.push_back(maTextureTransform * aNew); 679 680 // next step 681 fStart += mfDistance; 682 nMaxIntegerSteps--; 683 } 684 } 685 } 686 getDistanceToHatch(const basegfx::B2DPoint & rUV) const687 double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const 688 { 689 const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV); 690 return fmod(aCoor.getY(), mfDistance); 691 } 692 getBackTextureTransform() const693 const basegfx::B2DHomMatrix& GeoTexSvxHatch::getBackTextureTransform() const 694 { 695 if(maBackTextureTransform.isIdentity()) 696 { 697 const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform = maTextureTransform; 698 const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform.invert(); 699 } 700 701 return maBackTextureTransform; 702 } 703 } // end of namespace texture 704 } // end of namespace drawinglayer 705 706 ////////////////////////////////////////////////////////////////////////////// 707 708 namespace drawinglayer 709 { 710 namespace texture 711 { GeoTexSvxTiled(const basegfx::B2DRange & rRange,double fOffsetX,double fOffsetY)712 GeoTexSvxTiled::GeoTexSvxTiled( 713 const basegfx::B2DRange& rRange, 714 double fOffsetX, 715 double fOffsetY) 716 : maRange(rRange), 717 mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)), 718 mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0)) 719 { 720 if(!basegfx::fTools::equalZero(mfOffsetX)) 721 { 722 mfOffsetY = 0.0; 723 } 724 } 725 ~GeoTexSvxTiled()726 GeoTexSvxTiled::~GeoTexSvxTiled() 727 { 728 } 729 operator ==(const GeoTexSvx & rGeoTexSvx) const730 bool GeoTexSvxTiled::operator==(const GeoTexSvx& rGeoTexSvx) const 731 { 732 const GeoTexSvxTiled* pCompare = dynamic_cast< const GeoTexSvxTiled* >(&rGeoTexSvx); 733 734 return (pCompare 735 && maRange == pCompare->maRange 736 && mfOffsetX == pCompare->mfOffsetX 737 && mfOffsetY == pCompare->mfOffsetY); 738 } 739 appendTransformations(::std::vector<basegfx::B2DHomMatrix> & rMatrices)740 void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) 741 { 742 const double fWidth(maRange.getWidth()); 743 744 if(!basegfx::fTools::equalZero(fWidth)) 745 { 746 const double fHeight(maRange.getHeight()); 747 748 if(!basegfx::fTools::equalZero(fHeight)) 749 { 750 double fStartX(maRange.getMinX()); 751 double fStartY(maRange.getMinY()); 752 sal_Int32 nPosX(0); 753 sal_Int32 nPosY(0); 754 755 if(basegfx::fTools::more(fStartX, 0.0)) 756 { 757 const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1); 758 759 nPosX -= nDiff; 760 fStartX -= nDiff * fWidth; 761 } 762 763 if(basegfx::fTools::less(fStartX + fWidth, 0.0)) 764 { 765 const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth))); 766 767 nPosX += nDiff; 768 fStartX += nDiff * fWidth; 769 } 770 771 if(basegfx::fTools::more(fStartY, 0.0)) 772 { 773 const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1); 774 775 nPosY -= nDiff; 776 fStartY -= nDiff * fHeight; 777 } 778 779 if(basegfx::fTools::less(fStartY + fHeight, 0.0)) 780 { 781 const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight))); 782 783 nPosY += nDiff; 784 fStartY += nDiff * fHeight; 785 } 786 787 if(!basegfx::fTools::equalZero(mfOffsetY)) 788 { 789 for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth, nPosX++) 790 { 791 for(double fPosY(nPosX % 2 ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY); 792 basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight) 793 { 794 rMatrices.push_back( 795 basegfx::tools::createScaleTranslateB2DHomMatrix( 796 fWidth, 797 fHeight, 798 fPosX, 799 fPosY)); 800 } 801 } 802 } 803 else 804 { 805 for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight, nPosY++) 806 { 807 for(double fPosX(nPosY % 2 ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX); 808 basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth) 809 { 810 rMatrices.push_back( 811 basegfx::tools::createScaleTranslateB2DHomMatrix( 812 fWidth, 813 fHeight, 814 fPosX, 815 fPosY)); 816 } 817 } 818 } 819 } 820 } 821 } 822 } // end of namespace texture 823 } // end of namespace drawinglayer 824 825 ////////////////////////////////////////////////////////////////////////////// 826 // eof 827