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