109dbbe93SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 309dbbe93SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 409dbbe93SAndrew Rist * or more contributor license agreements. See the NOTICE file 509dbbe93SAndrew Rist * distributed with this work for additional information 609dbbe93SAndrew Rist * regarding copyright ownership. The ASF licenses this file 709dbbe93SAndrew Rist * to you under the Apache License, Version 2.0 (the 809dbbe93SAndrew Rist * "License"); you may not use this file except in compliance 909dbbe93SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1109dbbe93SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1309dbbe93SAndrew Rist * Unless required by applicable law or agreed to in writing, 1409dbbe93SAndrew Rist * software distributed under the License is distributed on an 1509dbbe93SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1609dbbe93SAndrew Rist * KIND, either express or implied. See the License for the 1709dbbe93SAndrew Rist * specific language governing permissions and limitations 1809dbbe93SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2009dbbe93SAndrew Rist *************************************************************/ 2109dbbe93SAndrew Rist 2209dbbe93SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_basegfx.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <basegfx/tools/gradienttools.hxx> 28cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 29cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx> 30cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir namespace basegfx 33cdf0e10cSrcweir { 34*96fc4b33SArmin Le Grand bool ODFGradientInfo::operator==(const ODFGradientInfo& rODFGradientInfo) const 35*96fc4b33SArmin Le Grand { 36*96fc4b33SArmin Le Grand return getTextureTransform() == rODFGradientInfo.getTextureTransform() 37*96fc4b33SArmin Le Grand && getAspectRatio() == rODFGradientInfo.getAspectRatio() 38*96fc4b33SArmin Le Grand && getSteps() == rODFGradientInfo.getSteps(); 39*96fc4b33SArmin Le Grand } 40*96fc4b33SArmin Le Grand 41*96fc4b33SArmin Le Grand const B2DHomMatrix& ODFGradientInfo::getBackTextureTransform() const 42*96fc4b33SArmin Le Grand { 43*96fc4b33SArmin Le Grand if(maBackTextureTransform.isIdentity()) 44*96fc4b33SArmin Le Grand { 45*96fc4b33SArmin Le Grand const_cast< ODFGradientInfo* >(this)->maBackTextureTransform = getTextureTransform(); 46*96fc4b33SArmin Le Grand const_cast< ODFGradientInfo* >(this)->maBackTextureTransform.invert(); 47*96fc4b33SArmin Le Grand } 48*96fc4b33SArmin Le Grand 49*96fc4b33SArmin Le Grand return maBackTextureTransform; 50*96fc4b33SArmin Le Grand } 51*96fc4b33SArmin Le Grand 52cdf0e10cSrcweir /** Most of the setup for linear & axial gradient is the same, except 53cdf0e10cSrcweir for the border treatment. Factored out here. 54cdf0e10cSrcweir */ 55*96fc4b33SArmin Le Grand ODFGradientInfo init1DGradientInfo( 56cdf0e10cSrcweir const B2DRange& rTargetRange, 57cdf0e10cSrcweir sal_uInt32 nSteps, 58cdf0e10cSrcweir double fBorder, 59cdf0e10cSrcweir double fAngle, 60cdf0e10cSrcweir bool bAxial) 61cdf0e10cSrcweir { 62*96fc4b33SArmin Le Grand B2DHomMatrix aTextureTransform; 63cdf0e10cSrcweir 64cdf0e10cSrcweir fAngle = -fAngle; 65cdf0e10cSrcweir 66cdf0e10cSrcweir double fTargetSizeX(rTargetRange.getWidth()); 67cdf0e10cSrcweir double fTargetSizeY(rTargetRange.getHeight()); 68cdf0e10cSrcweir double fTargetOffsetX(rTargetRange.getMinX()); 69cdf0e10cSrcweir double fTargetOffsetY(rTargetRange.getMinY()); 70cdf0e10cSrcweir 71cdf0e10cSrcweir // add object expansion 72*96fc4b33SArmin Le Grand const bool bAngleUsed(!fTools::equalZero(fAngle)); 73*96fc4b33SArmin Le Grand 74*96fc4b33SArmin Le Grand if(bAngleUsed) 75cdf0e10cSrcweir { 76cdf0e10cSrcweir const double fAbsCos(fabs(cos(fAngle))); 77cdf0e10cSrcweir const double fAbsSin(fabs(sin(fAngle))); 78cdf0e10cSrcweir const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); 79cdf0e10cSrcweir const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); 80*96fc4b33SArmin Le Grand 81cdf0e10cSrcweir fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; 82cdf0e10cSrcweir fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; 83cdf0e10cSrcweir fTargetSizeX = fNewX; 84cdf0e10cSrcweir fTargetSizeY = fNewY; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87*96fc4b33SArmin Le Grand const double fSizeWithoutBorder(1.0 - fBorder); 88*96fc4b33SArmin Le Grand 89cdf0e10cSrcweir if(bAxial) 90cdf0e10cSrcweir { 91*96fc4b33SArmin Le Grand aTextureTransform.scale(1.0, fSizeWithoutBorder * 0.5); 92*96fc4b33SArmin Le Grand aTextureTransform.translate(0.0, 0.5); 93cdf0e10cSrcweir } 94cdf0e10cSrcweir else 95cdf0e10cSrcweir { 96cdf0e10cSrcweir if(!fTools::equal(fSizeWithoutBorder, 1.0)) 97cdf0e10cSrcweir { 98*96fc4b33SArmin Le Grand aTextureTransform.scale(1.0, fSizeWithoutBorder); 99*96fc4b33SArmin Le Grand aTextureTransform.translate(0.0, fBorder); 100cdf0e10cSrcweir } 101cdf0e10cSrcweir } 102cdf0e10cSrcweir 103*96fc4b33SArmin Le Grand aTextureTransform.scale(fTargetSizeX, fTargetSizeY); 104cdf0e10cSrcweir 105cdf0e10cSrcweir // add texture rotate after scale to keep perpendicular angles 106*96fc4b33SArmin Le Grand if(bAngleUsed) 107cdf0e10cSrcweir { 108*96fc4b33SArmin Le Grand const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY); 109*96fc4b33SArmin Le Grand 110*96fc4b33SArmin Le Grand aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle); 111cdf0e10cSrcweir } 112cdf0e10cSrcweir 113cdf0e10cSrcweir // add object translate 114*96fc4b33SArmin Le Grand aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); 115cdf0e10cSrcweir 116cdf0e10cSrcweir // prepare aspect for texture 117*96fc4b33SArmin Le Grand const double fAspectRatio(fTools::equalZero(fTargetSizeY) ? 1.0 : fTargetSizeX / fTargetSizeY); 118cdf0e10cSrcweir 119*96fc4b33SArmin Le Grand return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps); 120cdf0e10cSrcweir } 121cdf0e10cSrcweir 122cdf0e10cSrcweir /** Most of the setup for radial & ellipsoidal gradient is the same, 123cdf0e10cSrcweir except for the border treatment. Factored out here. 124cdf0e10cSrcweir */ 125*96fc4b33SArmin Le Grand ODFGradientInfo initEllipticalGradientInfo( 126cdf0e10cSrcweir const B2DRange& rTargetRange, 127cdf0e10cSrcweir const B2DVector& rOffset, 128cdf0e10cSrcweir sal_uInt32 nSteps, 129cdf0e10cSrcweir double fBorder, 130cdf0e10cSrcweir double fAngle, 131cdf0e10cSrcweir bool bCircular) 132cdf0e10cSrcweir { 133*96fc4b33SArmin Le Grand B2DHomMatrix aTextureTransform; 134cdf0e10cSrcweir 135cdf0e10cSrcweir fAngle = -fAngle; 136cdf0e10cSrcweir 137cdf0e10cSrcweir double fTargetSizeX(rTargetRange.getWidth()); 138cdf0e10cSrcweir double fTargetSizeY(rTargetRange.getHeight()); 139cdf0e10cSrcweir double fTargetOffsetX(rTargetRange.getMinX()); 140cdf0e10cSrcweir double fTargetOffsetY(rTargetRange.getMinY()); 141cdf0e10cSrcweir 142cdf0e10cSrcweir // add object expansion 143cdf0e10cSrcweir if(bCircular) 144cdf0e10cSrcweir { 145cdf0e10cSrcweir const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY))); 146*96fc4b33SArmin Le Grand 147cdf0e10cSrcweir fTargetOffsetX -= (fOriginalDiag - fTargetSizeX) / 2.0; 148cdf0e10cSrcweir fTargetOffsetY -= (fOriginalDiag - fTargetSizeY) / 2.0; 149cdf0e10cSrcweir fTargetSizeX = fOriginalDiag; 150cdf0e10cSrcweir fTargetSizeY = fOriginalDiag; 151cdf0e10cSrcweir } 152cdf0e10cSrcweir else 153cdf0e10cSrcweir { 154cdf0e10cSrcweir fTargetOffsetX -= (0.4142 / 2.0 ) * fTargetSizeX; 155cdf0e10cSrcweir fTargetOffsetY -= (0.4142 / 2.0 ) * fTargetSizeY; 156cdf0e10cSrcweir fTargetSizeX = 1.4142 * fTargetSizeX; 157cdf0e10cSrcweir fTargetSizeY = 1.4142 * fTargetSizeY; 158cdf0e10cSrcweir } 159cdf0e10cSrcweir 160cdf0e10cSrcweir const double fHalfBorder((1.0 - fBorder) * 0.5); 161cdf0e10cSrcweir 162*96fc4b33SArmin Le Grand aTextureTransform.scale(fHalfBorder, fHalfBorder); 163*96fc4b33SArmin Le Grand aTextureTransform.translate(0.5, 0.5); 164*96fc4b33SArmin Le Grand aTextureTransform.scale(fTargetSizeX, fTargetSizeY); 165cdf0e10cSrcweir 166cdf0e10cSrcweir // add texture rotate after scale to keep perpendicular angles 167*96fc4b33SArmin Le Grand if(!bCircular && !fTools::equalZero(fAngle)) 168cdf0e10cSrcweir { 169*96fc4b33SArmin Le Grand const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY); 170*96fc4b33SArmin Le Grand 171*96fc4b33SArmin Le Grand aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle); 172cdf0e10cSrcweir } 173cdf0e10cSrcweir 174cdf0e10cSrcweir // add defined offsets after rotation 175*96fc4b33SArmin Le Grand if(!fTools::equal(0.5, rOffset.getX()) || !fTools::equal(0.5, rOffset.getY())) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir // use original target size 178cdf0e10cSrcweir fTargetOffsetX += (rOffset.getX() - 0.5) * rTargetRange.getWidth(); 179cdf0e10cSrcweir fTargetOffsetY += (rOffset.getY() - 0.5) * rTargetRange.getHeight(); 180cdf0e10cSrcweir } 181cdf0e10cSrcweir 182cdf0e10cSrcweir // add object translate 183*96fc4b33SArmin Le Grand aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); 184cdf0e10cSrcweir 185cdf0e10cSrcweir // prepare aspect for texture 186*96fc4b33SArmin Le Grand const double fAspectRatio((0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0); 187cdf0e10cSrcweir 188*96fc4b33SArmin Le Grand return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir /** Setup for rect & square gradient is exactly the same. Factored out 192cdf0e10cSrcweir here. 193cdf0e10cSrcweir */ 194*96fc4b33SArmin Le Grand ODFGradientInfo initRectGradientInfo( 195cdf0e10cSrcweir const B2DRange& rTargetRange, 196cdf0e10cSrcweir const B2DVector& rOffset, 197cdf0e10cSrcweir sal_uInt32 nSteps, 198cdf0e10cSrcweir double fBorder, 199d939e20fSArmin Le Grand double fAngle, 200d939e20fSArmin Le Grand bool bSquare) 201cdf0e10cSrcweir { 202*96fc4b33SArmin Le Grand B2DHomMatrix aTextureTransform; 203cdf0e10cSrcweir 204cdf0e10cSrcweir fAngle = -fAngle; 205cdf0e10cSrcweir 206cdf0e10cSrcweir double fTargetSizeX(rTargetRange.getWidth()); 207cdf0e10cSrcweir double fTargetSizeY(rTargetRange.getHeight()); 208cdf0e10cSrcweir double fTargetOffsetX(rTargetRange.getMinX()); 209cdf0e10cSrcweir double fTargetOffsetY(rTargetRange.getMinY()); 210cdf0e10cSrcweir 211cdf0e10cSrcweir // add object expansion 212d939e20fSArmin Le Grand if(bSquare) 213d939e20fSArmin Le Grand { 214849a1ce7SArmin Le Grand const double fSquareWidth(std::max(fTargetSizeX, fTargetSizeY)); 215*96fc4b33SArmin Le Grand 216849a1ce7SArmin Le Grand fTargetOffsetX -= (fSquareWidth - fTargetSizeX) / 2.0; 217849a1ce7SArmin Le Grand fTargetOffsetY -= (fSquareWidth - fTargetSizeY) / 2.0; 218849a1ce7SArmin Le Grand fTargetSizeX = fTargetSizeY = fSquareWidth; 219d939e20fSArmin Le Grand } 220d939e20fSArmin Le Grand 221d939e20fSArmin Le Grand // add object expansion 222*96fc4b33SArmin Le Grand const bool bAngleUsed(!fTools::equalZero(fAngle)); 223*96fc4b33SArmin Le Grand 224*96fc4b33SArmin Le Grand if(bAngleUsed) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir const double fAbsCos(fabs(cos(fAngle))); 227cdf0e10cSrcweir const double fAbsSin(fabs(sin(fAngle))); 228cdf0e10cSrcweir const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); 229cdf0e10cSrcweir const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); 230*96fc4b33SArmin Le Grand 231cdf0e10cSrcweir fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; 232cdf0e10cSrcweir fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; 233cdf0e10cSrcweir fTargetSizeX = fNewX; 234cdf0e10cSrcweir fTargetSizeY = fNewY; 235cdf0e10cSrcweir } 236cdf0e10cSrcweir 237cdf0e10cSrcweir const double fHalfBorder((1.0 - fBorder) * 0.5); 238cdf0e10cSrcweir 239*96fc4b33SArmin Le Grand aTextureTransform.scale(fHalfBorder, fHalfBorder); 240*96fc4b33SArmin Le Grand aTextureTransform.translate(0.5, 0.5); 241*96fc4b33SArmin Le Grand aTextureTransform.scale(fTargetSizeX, fTargetSizeY); 242cdf0e10cSrcweir 243cdf0e10cSrcweir // add texture rotate after scale to keep perpendicular angles 244*96fc4b33SArmin Le Grand if(bAngleUsed) 245cdf0e10cSrcweir { 246*96fc4b33SArmin Le Grand const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY); 247*96fc4b33SArmin Le Grand 248*96fc4b33SArmin Le Grand aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle); 249cdf0e10cSrcweir } 250cdf0e10cSrcweir 251cdf0e10cSrcweir // add defined offsets after rotation 252*96fc4b33SArmin Le Grand if(!fTools::equal(0.5, rOffset.getX()) || !fTools::equal(0.5, rOffset.getY())) 253cdf0e10cSrcweir { 254cdf0e10cSrcweir // use scaled target size 255cdf0e10cSrcweir fTargetOffsetX += (rOffset.getX() - 0.5) * fTargetSizeX; 256cdf0e10cSrcweir fTargetOffsetY += (rOffset.getY() - 0.5) * fTargetSizeY; 257cdf0e10cSrcweir } 258cdf0e10cSrcweir 259cdf0e10cSrcweir // add object translate 260*96fc4b33SArmin Le Grand aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); 261cdf0e10cSrcweir 262cdf0e10cSrcweir // prepare aspect for texture 263*96fc4b33SArmin Le Grand const double fAspectRatio((0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0); 264cdf0e10cSrcweir 265*96fc4b33SArmin Le Grand return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps); 266cdf0e10cSrcweir } 267cdf0e10cSrcweir 268cdf0e10cSrcweir namespace tools 269cdf0e10cSrcweir { 270*96fc4b33SArmin Le Grand ODFGradientInfo createLinearODFGradientInfo( 271cdf0e10cSrcweir const B2DRange& rTargetArea, 272cdf0e10cSrcweir sal_uInt32 nSteps, 273cdf0e10cSrcweir double fBorder, 274cdf0e10cSrcweir double fAngle) 275cdf0e10cSrcweir { 276*96fc4b33SArmin Le Grand return init1DGradientInfo( 277cdf0e10cSrcweir rTargetArea, 278cdf0e10cSrcweir nSteps, 279cdf0e10cSrcweir fBorder, 280cdf0e10cSrcweir fAngle, 281cdf0e10cSrcweir false); 282cdf0e10cSrcweir } 283cdf0e10cSrcweir 284*96fc4b33SArmin Le Grand ODFGradientInfo createAxialODFGradientInfo( 285cdf0e10cSrcweir const B2DRange& rTargetArea, 286cdf0e10cSrcweir sal_uInt32 nSteps, 287cdf0e10cSrcweir double fBorder, 288cdf0e10cSrcweir double fAngle) 289cdf0e10cSrcweir { 290*96fc4b33SArmin Le Grand return init1DGradientInfo( 291cdf0e10cSrcweir rTargetArea, 292cdf0e10cSrcweir nSteps, 293cdf0e10cSrcweir fBorder, 294cdf0e10cSrcweir fAngle, 295cdf0e10cSrcweir true); 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298*96fc4b33SArmin Le Grand ODFGradientInfo createRadialODFGradientInfo( 299cdf0e10cSrcweir const B2DRange& rTargetArea, 300cdf0e10cSrcweir const B2DVector& rOffset, 301cdf0e10cSrcweir sal_uInt32 nSteps, 302cdf0e10cSrcweir double fBorder) 303cdf0e10cSrcweir { 304*96fc4b33SArmin Le Grand return initEllipticalGradientInfo( 305cdf0e10cSrcweir rTargetArea, 306cdf0e10cSrcweir rOffset, 307cdf0e10cSrcweir nSteps, 308cdf0e10cSrcweir fBorder, 309cdf0e10cSrcweir 0.0, 310cdf0e10cSrcweir true); 311cdf0e10cSrcweir } 312cdf0e10cSrcweir 313*96fc4b33SArmin Le Grand ODFGradientInfo createEllipticalODFGradientInfo( 314cdf0e10cSrcweir const B2DRange& rTargetArea, 315cdf0e10cSrcweir const B2DVector& rOffset, 316cdf0e10cSrcweir sal_uInt32 nSteps, 317cdf0e10cSrcweir double fBorder, 318cdf0e10cSrcweir double fAngle) 319cdf0e10cSrcweir { 320*96fc4b33SArmin Le Grand return initEllipticalGradientInfo( 321cdf0e10cSrcweir rTargetArea, 322cdf0e10cSrcweir rOffset, 323cdf0e10cSrcweir nSteps, 324cdf0e10cSrcweir fBorder, 325cdf0e10cSrcweir fAngle, 326cdf0e10cSrcweir false); 327cdf0e10cSrcweir } 328cdf0e10cSrcweir 329*96fc4b33SArmin Le Grand ODFGradientInfo createSquareODFGradientInfo( 330cdf0e10cSrcweir const B2DRange& rTargetArea, 331cdf0e10cSrcweir const B2DVector& rOffset, 332cdf0e10cSrcweir sal_uInt32 nSteps, 333cdf0e10cSrcweir double fBorder, 334cdf0e10cSrcweir double fAngle) 335cdf0e10cSrcweir { 336*96fc4b33SArmin Le Grand return initRectGradientInfo( 337cdf0e10cSrcweir rTargetArea, 338cdf0e10cSrcweir rOffset, 339cdf0e10cSrcweir nSteps, 340cdf0e10cSrcweir fBorder, 341d939e20fSArmin Le Grand fAngle, 342d939e20fSArmin Le Grand true); 343cdf0e10cSrcweir } 344cdf0e10cSrcweir 345*96fc4b33SArmin Le Grand ODFGradientInfo createRectangularODFGradientInfo( 346cdf0e10cSrcweir const B2DRange& rTargetArea, 347cdf0e10cSrcweir const B2DVector& rOffset, 348cdf0e10cSrcweir sal_uInt32 nSteps, 349cdf0e10cSrcweir double fBorder, 350cdf0e10cSrcweir double fAngle) 351cdf0e10cSrcweir { 352*96fc4b33SArmin Le Grand return initRectGradientInfo( 353cdf0e10cSrcweir rTargetArea, 354cdf0e10cSrcweir rOffset, 355cdf0e10cSrcweir nSteps, 356cdf0e10cSrcweir fBorder, 357d939e20fSArmin Le Grand fAngle, 358d939e20fSArmin Le Grand false); 359cdf0e10cSrcweir } 360cdf0e10cSrcweir 361*96fc4b33SArmin Le Grand double getLinearGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 362*96fc4b33SArmin Le Grand { 363*96fc4b33SArmin Le Grand const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV); 364*96fc4b33SArmin Le Grand const double t(clamp(aCoor.getY(), 0.0, 1.0)); 365*96fc4b33SArmin Le Grand const sal_uInt32 nSteps(rGradInfo.getSteps()); 366cdf0e10cSrcweir 367*96fc4b33SArmin Le Grand if(nSteps) 368*96fc4b33SArmin Le Grand { 369*96fc4b33SArmin Le Grand return floor(t * nSteps) / double(nSteps + 1L); 370*96fc4b33SArmin Le Grand } 371*96fc4b33SArmin Le Grand 372*96fc4b33SArmin Le Grand return t; 373*96fc4b33SArmin Le Grand } 374*96fc4b33SArmin Le Grand 375*96fc4b33SArmin Le Grand double getAxialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 376*96fc4b33SArmin Le Grand { 377*96fc4b33SArmin Le Grand const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV); 378*96fc4b33SArmin Le Grand const double t(clamp(fabs(aCoor.getY()), 0.0, 1.0)); 379*96fc4b33SArmin Le Grand const sal_uInt32 nSteps(rGradInfo.getSteps()); 380*96fc4b33SArmin Le Grand const double fInternalSteps((nSteps * 2) - 1); 381*96fc4b33SArmin Le Grand 382*96fc4b33SArmin Le Grand if(nSteps) 383*96fc4b33SArmin Le Grand { 384*96fc4b33SArmin Le Grand return floor(((t * fInternalSteps) + 1.0) / 2.0) / double(nSteps - 1L); 385*96fc4b33SArmin Le Grand } 386*96fc4b33SArmin Le Grand 387*96fc4b33SArmin Le Grand return t; 388*96fc4b33SArmin Le Grand } 389*96fc4b33SArmin Le Grand 390*96fc4b33SArmin Le Grand double getRadialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 391*96fc4b33SArmin Le Grand { 392*96fc4b33SArmin Le Grand const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV); 393*96fc4b33SArmin Le Grand const double fDist(clamp(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY(), 0.0, 1.0)); 394*96fc4b33SArmin Le Grand const double t(1.0 - sqrt(fDist)); 395*96fc4b33SArmin Le Grand const sal_uInt32 nSteps(rGradInfo.getSteps()); 396*96fc4b33SArmin Le Grand 397*96fc4b33SArmin Le Grand if(nSteps) 398*96fc4b33SArmin Le Grand { 399*96fc4b33SArmin Le Grand return floor(t * nSteps) / double(nSteps - 1L); 400*96fc4b33SArmin Le Grand } 401*96fc4b33SArmin Le Grand 402*96fc4b33SArmin Le Grand return t; 403*96fc4b33SArmin Le Grand } 404*96fc4b33SArmin Le Grand 405*96fc4b33SArmin Le Grand double getEllipticalGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 406*96fc4b33SArmin Le Grand { 407*96fc4b33SArmin Le Grand return getRadialGradientAlpha(rUV, rGradInfo); // only matrix setup differs 408*96fc4b33SArmin Le Grand } 409*96fc4b33SArmin Le Grand 410*96fc4b33SArmin Le Grand double getSquareGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 411*96fc4b33SArmin Le Grand { 412*96fc4b33SArmin Le Grand const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV); 413*96fc4b33SArmin Le Grand const double fAbsX(fabs(aCoor.getX())); 414*96fc4b33SArmin Le Grand const double fAbsY(fabs(aCoor.getY())); 415*96fc4b33SArmin Le Grand 416*96fc4b33SArmin Le Grand if(fTools::moreOrEqual(fAbsX, 1.0) || fTools::moreOrEqual(fAbsY, 1.0)) 417*96fc4b33SArmin Le Grand { 418*96fc4b33SArmin Le Grand return 0.0; 419*96fc4b33SArmin Le Grand } 420*96fc4b33SArmin Le Grand 421*96fc4b33SArmin Le Grand const double t(1.0 - std::max(fAbsX, fAbsY)); 422*96fc4b33SArmin Le Grand const sal_uInt32 nSteps(rGradInfo.getSteps()); 423*96fc4b33SArmin Le Grand 424*96fc4b33SArmin Le Grand if(nSteps) 425*96fc4b33SArmin Le Grand { 426*96fc4b33SArmin Le Grand return floor(t * nSteps) / double(nSteps - 1L); 427*96fc4b33SArmin Le Grand } 428*96fc4b33SArmin Le Grand 429*96fc4b33SArmin Le Grand return t; 430*96fc4b33SArmin Le Grand } 431*96fc4b33SArmin Le Grand 432*96fc4b33SArmin Le Grand double getRectangularGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo) 433*96fc4b33SArmin Le Grand { 434*96fc4b33SArmin Le Grand return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs 435*96fc4b33SArmin Le Grand } 436*96fc4b33SArmin Le Grand } // namespace tools 437cdf0e10cSrcweir } // namespace basegfx 438*96fc4b33SArmin Le Grand 439*96fc4b33SArmin Le Grand // eof 440