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