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
1009dbbe93SAndrew Rist  *
1109dbbe93SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1209dbbe93SAndrew Rist  *
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.
1909dbbe93SAndrew Rist  *
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 {
operator ==(const ODFGradientInfo & rODFGradientInfo) const3496fc4b33SArmin Le Grand     bool ODFGradientInfo::operator==(const ODFGradientInfo& rODFGradientInfo) const
3596fc4b33SArmin Le Grand     {
3696fc4b33SArmin Le Grand         return getTextureTransform() == rODFGradientInfo.getTextureTransform()
3796fc4b33SArmin Le Grand             && getAspectRatio() == rODFGradientInfo.getAspectRatio()
3896fc4b33SArmin Le Grand             && getSteps() == rODFGradientInfo.getSteps();
3996fc4b33SArmin Le Grand     }
4096fc4b33SArmin Le Grand 
getBackTextureTransform() const4196fc4b33SArmin Le Grand     const B2DHomMatrix& ODFGradientInfo::getBackTextureTransform() const
4296fc4b33SArmin Le Grand     {
4396fc4b33SArmin Le Grand         if(maBackTextureTransform.isIdentity())
4496fc4b33SArmin Le Grand         {
4596fc4b33SArmin Le Grand             const_cast< ODFGradientInfo* >(this)->maBackTextureTransform = getTextureTransform();
4696fc4b33SArmin Le Grand             const_cast< ODFGradientInfo* >(this)->maBackTextureTransform.invert();
4796fc4b33SArmin Le Grand         }
4896fc4b33SArmin Le Grand 
4996fc4b33SArmin Le Grand         return maBackTextureTransform;
5096fc4b33SArmin Le Grand     }
5196fc4b33SArmin Le Grand 
52cdf0e10cSrcweir     /** Most of the setup for linear & axial gradient is the same, except
53cdf0e10cSrcweir         for the border treatment. Factored out here.
54cdf0e10cSrcweir     */
init1DGradientInfo(const B2DRange & rTargetRange,sal_uInt32 nSteps,double fBorder,double fAngle,bool bAxial)5596fc4b33SArmin Le Grand     ODFGradientInfo init1DGradientInfo(
5696fc4b33SArmin Le Grand         const B2DRange& rTargetRange,
5796fc4b33SArmin Le Grand         sal_uInt32 nSteps,
5896fc4b33SArmin Le Grand         double fBorder,
5996fc4b33SArmin Le Grand         double fAngle,
6096fc4b33SArmin Le Grand         bool bAxial)
61cdf0e10cSrcweir     {
6296fc4b33SArmin 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
7296fc4b33SArmin Le Grand         const bool bAngleUsed(!fTools::equalZero(fAngle));
7396fc4b33SArmin Le Grand 
7496fc4b33SArmin 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);
8096fc4b33SArmin Le Grand 
81cdf0e10cSrcweir             fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
82cdf0e10cSrcweir             fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
83cdf0e10cSrcweir             fTargetSizeX = fNewX;
84cdf0e10cSrcweir             fTargetSizeY = fNewY;
85cdf0e10cSrcweir         }
86cdf0e10cSrcweir 
8796fc4b33SArmin Le Grand         const double fSizeWithoutBorder(1.0 - fBorder);
8896fc4b33SArmin Le Grand 
8996fc4b33SArmin Le Grand         if(bAxial)
90cdf0e10cSrcweir         {
9196fc4b33SArmin Le Grand             aTextureTransform.scale(1.0, fSizeWithoutBorder * 0.5);
9296fc4b33SArmin Le Grand             aTextureTransform.translate(0.0, 0.5);
93cdf0e10cSrcweir         }
94cdf0e10cSrcweir         else
95cdf0e10cSrcweir         {
96cdf0e10cSrcweir             if(!fTools::equal(fSizeWithoutBorder, 1.0))
97cdf0e10cSrcweir             {
9896fc4b33SArmin Le Grand                 aTextureTransform.scale(1.0, fSizeWithoutBorder);
9996fc4b33SArmin Le Grand                 aTextureTransform.translate(0.0, fBorder);
100cdf0e10cSrcweir             }
101cdf0e10cSrcweir         }
102cdf0e10cSrcweir 
10396fc4b33SArmin Le Grand         aTextureTransform.scale(fTargetSizeX, fTargetSizeY);
104cdf0e10cSrcweir 
105cdf0e10cSrcweir         // add texture rotate after scale to keep perpendicular angles
10696fc4b33SArmin Le Grand         if(bAngleUsed)
107cdf0e10cSrcweir         {
10896fc4b33SArmin Le Grand             const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY);
10996fc4b33SArmin Le Grand 
11096fc4b33SArmin Le Grand             aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
111cdf0e10cSrcweir         }
112cdf0e10cSrcweir 
113cdf0e10cSrcweir         // add object translate
11496fc4b33SArmin Le Grand         aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
115cdf0e10cSrcweir 
116cdf0e10cSrcweir         // prepare aspect for texture
11796fc4b33SArmin Le Grand         const double fAspectRatio(fTools::equalZero(fTargetSizeY) ?  1.0 : fTargetSizeX / fTargetSizeY);
118cdf0e10cSrcweir 
11996fc4b33SArmin 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     */
initEllipticalGradientInfo(const B2DRange & rTargetRange,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder,double fAngle,bool bCircular)12596fc4b33SArmin Le Grand     ODFGradientInfo initEllipticalGradientInfo(
12696fc4b33SArmin Le Grand         const B2DRange& rTargetRange,
12796fc4b33SArmin Le Grand         const B2DVector& rOffset,
12896fc4b33SArmin Le Grand         sal_uInt32 nSteps,
12996fc4b33SArmin Le Grand         double fBorder,
13096fc4b33SArmin Le Grand         double fAngle,
13196fc4b33SArmin Le Grand         bool bCircular)
132cdf0e10cSrcweir     {
13396fc4b33SArmin Le Grand         B2DHomMatrix aTextureTransform;
13496fc4b33SArmin Le Grand 
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
14396fc4b33SArmin Le Grand         if(bCircular)
144cdf0e10cSrcweir         {
145cdf0e10cSrcweir             const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY)));
14696fc4b33SArmin 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 
16296fc4b33SArmin Le Grand         aTextureTransform.scale(fHalfBorder, fHalfBorder);
16396fc4b33SArmin Le Grand         aTextureTransform.translate(0.5, 0.5);
16496fc4b33SArmin Le Grand         aTextureTransform.scale(fTargetSizeX, fTargetSizeY);
165cdf0e10cSrcweir 
166cdf0e10cSrcweir         // add texture rotate after scale to keep perpendicular angles
16796fc4b33SArmin Le Grand         if(!bCircular && !fTools::equalZero(fAngle))
168cdf0e10cSrcweir         {
16996fc4b33SArmin Le Grand             const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY);
17096fc4b33SArmin Le Grand 
17196fc4b33SArmin Le Grand             aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
172cdf0e10cSrcweir         }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         // add defined offsets after rotation
17596fc4b33SArmin 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
18396fc4b33SArmin Le Grand         aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
184cdf0e10cSrcweir 
185cdf0e10cSrcweir         // prepare aspect for texture
18696fc4b33SArmin Le Grand         const double fAspectRatio((0.0 != fTargetSizeY) ?  fTargetSizeX / fTargetSizeY : 1.0);
187cdf0e10cSrcweir 
18896fc4b33SArmin Le Grand         return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps);
189cdf0e10cSrcweir     }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     /** Setup for rect & square gradient is exactly the same. Factored out
192cdf0e10cSrcweir         here.
193cdf0e10cSrcweir     */
initRectGradientInfo(const B2DRange & rTargetRange,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder,double fAngle,bool bSquare)19496fc4b33SArmin Le Grand     ODFGradientInfo initRectGradientInfo(
19596fc4b33SArmin Le Grand         const B2DRange& rTargetRange,
19696fc4b33SArmin Le Grand         const B2DVector& rOffset,
19796fc4b33SArmin Le Grand         sal_uInt32 nSteps,
19896fc4b33SArmin Le Grand         double fBorder,
19996fc4b33SArmin Le Grand         double fAngle,
20096fc4b33SArmin Le Grand         bool bSquare)
201cdf0e10cSrcweir     {
20296fc4b33SArmin 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 
211d939e20fSArmin Le Grand         // add object expansion
212d939e20fSArmin Le Grand         if(bSquare)
213d939e20fSArmin Le Grand         {
214849a1ce7SArmin Le Grand             const double fSquareWidth(std::max(fTargetSizeX, fTargetSizeY));
21596fc4b33SArmin 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 
221cdf0e10cSrcweir         // add object expansion
22296fc4b33SArmin Le Grand         const bool bAngleUsed(!fTools::equalZero(fAngle));
22396fc4b33SArmin Le Grand 
22496fc4b33SArmin 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);
23096fc4b33SArmin 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);
23896fc4b33SArmin Le Grand 
23996fc4b33SArmin Le Grand         aTextureTransform.scale(fHalfBorder, fHalfBorder);
24096fc4b33SArmin Le Grand         aTextureTransform.translate(0.5, 0.5);
24196fc4b33SArmin Le Grand         aTextureTransform.scale(fTargetSizeX, fTargetSizeY);
242cdf0e10cSrcweir 
243cdf0e10cSrcweir         // add texture rotate after scale to keep perpendicular angles
24496fc4b33SArmin Le Grand         if(bAngleUsed)
245cdf0e10cSrcweir         {
24696fc4b33SArmin Le Grand             const B2DPoint aCenter(0.5 * fTargetSizeX, 0.5 * fTargetSizeY);
24796fc4b33SArmin Le Grand 
24896fc4b33SArmin Le Grand             aTextureTransform *= basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
249cdf0e10cSrcweir         }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir         // add defined offsets after rotation
25296fc4b33SArmin 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
26096fc4b33SArmin Le Grand         aTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
261cdf0e10cSrcweir 
262cdf0e10cSrcweir         // prepare aspect for texture
26396fc4b33SArmin Le Grand         const double fAspectRatio((0.0 != fTargetSizeY) ?  fTargetSizeX / fTargetSizeY : 1.0);
264cdf0e10cSrcweir 
26596fc4b33SArmin Le Grand         return ODFGradientInfo(aTextureTransform, fAspectRatio, nSteps);
266cdf0e10cSrcweir     }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir     namespace tools
269cdf0e10cSrcweir     {
createLinearODFGradientInfo(const B2DRange & rTargetArea,sal_uInt32 nSteps,double fBorder,double fAngle)27096fc4b33SArmin Le Grand         ODFGradientInfo createLinearODFGradientInfo(
27196fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
27296fc4b33SArmin Le Grand             sal_uInt32 nSteps,
27396fc4b33SArmin Le Grand             double fBorder,
27496fc4b33SArmin Le Grand             double fAngle)
275cdf0e10cSrcweir         {
27696fc4b33SArmin Le Grand             return init1DGradientInfo(
27796fc4b33SArmin Le Grand                 rTargetArea,
27896fc4b33SArmin Le Grand                 nSteps,
27996fc4b33SArmin Le Grand                 fBorder,
28096fc4b33SArmin Le Grand                 fAngle,
28196fc4b33SArmin Le Grand                 false);
282cdf0e10cSrcweir         }
283cdf0e10cSrcweir 
createAxialODFGradientInfo(const B2DRange & rTargetArea,sal_uInt32 nSteps,double fBorder,double fAngle)28496fc4b33SArmin Le Grand         ODFGradientInfo createAxialODFGradientInfo(
28596fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
28696fc4b33SArmin Le Grand             sal_uInt32 nSteps,
28796fc4b33SArmin Le Grand             double fBorder,
28896fc4b33SArmin Le Grand             double fAngle)
289cdf0e10cSrcweir         {
29096fc4b33SArmin Le Grand             return init1DGradientInfo(
29196fc4b33SArmin Le Grand                 rTargetArea,
29296fc4b33SArmin Le Grand                 nSteps,
29396fc4b33SArmin Le Grand                 fBorder,
29496fc4b33SArmin Le Grand                 fAngle,
29596fc4b33SArmin Le Grand                 true);
296cdf0e10cSrcweir         }
297cdf0e10cSrcweir 
createRadialODFGradientInfo(const B2DRange & rTargetArea,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder)29896fc4b33SArmin Le Grand         ODFGradientInfo createRadialODFGradientInfo(
29996fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
30096fc4b33SArmin Le Grand             const B2DVector& rOffset,
30196fc4b33SArmin Le Grand             sal_uInt32 nSteps,
30296fc4b33SArmin Le Grand             double fBorder)
303cdf0e10cSrcweir         {
30496fc4b33SArmin Le Grand             return initEllipticalGradientInfo(
30596fc4b33SArmin Le Grand                 rTargetArea,
30696fc4b33SArmin Le Grand                 rOffset,
30796fc4b33SArmin Le Grand                 nSteps,
30896fc4b33SArmin Le Grand                 fBorder,
30996fc4b33SArmin Le Grand                 0.0,
31096fc4b33SArmin Le Grand                 true);
311cdf0e10cSrcweir         }
312cdf0e10cSrcweir 
createEllipticalODFGradientInfo(const B2DRange & rTargetArea,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder,double fAngle)31396fc4b33SArmin Le Grand         ODFGradientInfo createEllipticalODFGradientInfo(
31496fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
31596fc4b33SArmin Le Grand             const B2DVector& rOffset,
31696fc4b33SArmin Le Grand             sal_uInt32 nSteps,
31796fc4b33SArmin Le Grand             double fBorder,
31896fc4b33SArmin Le Grand             double fAngle)
319cdf0e10cSrcweir         {
32096fc4b33SArmin Le Grand             return initEllipticalGradientInfo(
32196fc4b33SArmin Le Grand                 rTargetArea,
32296fc4b33SArmin Le Grand                 rOffset,
32396fc4b33SArmin Le Grand                 nSteps,
32496fc4b33SArmin Le Grand                 fBorder,
32596fc4b33SArmin Le Grand                 fAngle,
32696fc4b33SArmin Le Grand                 false);
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir 
createSquareODFGradientInfo(const B2DRange & rTargetArea,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder,double fAngle)32996fc4b33SArmin Le Grand         ODFGradientInfo createSquareODFGradientInfo(
33096fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
33196fc4b33SArmin Le Grand             const B2DVector& rOffset,
33296fc4b33SArmin Le Grand             sal_uInt32 nSteps,
33396fc4b33SArmin Le Grand             double fBorder,
33496fc4b33SArmin Le Grand             double fAngle)
335cdf0e10cSrcweir         {
33696fc4b33SArmin Le Grand             return initRectGradientInfo(
33796fc4b33SArmin Le Grand                 rTargetArea,
33896fc4b33SArmin Le Grand                 rOffset,
33996fc4b33SArmin Le Grand                 nSteps,
34096fc4b33SArmin Le Grand                 fBorder,
34196fc4b33SArmin Le Grand                 fAngle,
34296fc4b33SArmin Le Grand                 true);
343cdf0e10cSrcweir         }
344cdf0e10cSrcweir 
createRectangularODFGradientInfo(const B2DRange & rTargetArea,const B2DVector & rOffset,sal_uInt32 nSteps,double fBorder,double fAngle)34596fc4b33SArmin Le Grand         ODFGradientInfo createRectangularODFGradientInfo(
34696fc4b33SArmin Le Grand             const B2DRange& rTargetArea,
34796fc4b33SArmin Le Grand             const B2DVector& rOffset,
34896fc4b33SArmin Le Grand             sal_uInt32 nSteps,
34996fc4b33SArmin Le Grand             double fBorder,
35096fc4b33SArmin Le Grand             double fAngle)
351cdf0e10cSrcweir         {
35296fc4b33SArmin Le Grand             return initRectGradientInfo(
35396fc4b33SArmin Le Grand                 rTargetArea,
35496fc4b33SArmin Le Grand                 rOffset,
35596fc4b33SArmin Le Grand                 nSteps,
35696fc4b33SArmin Le Grand                 fBorder,
35796fc4b33SArmin Le Grand                 fAngle,
35896fc4b33SArmin Le Grand                 false);
359cdf0e10cSrcweir         }
360cdf0e10cSrcweir 
getLinearGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)36196fc4b33SArmin Le Grand         double getLinearGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
36296fc4b33SArmin Le Grand         {
36396fc4b33SArmin Le Grand             const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV);
36407540651SArmin Le Grand 
365*7024eca9SArmin Le Grand             // Ignore Y, this is not needed at all for Y-Oriented gradients
366*7024eca9SArmin Le Grand             // if(aCoor.getX() < 0.0 || aCoor.getX() > 1.0)
367*7024eca9SArmin Le Grand             // {
368*7024eca9SArmin Le Grand             //     return 0.0;
369*7024eca9SArmin Le Grand             // }
37007540651SArmin Le Grand 
37107540651SArmin Le Grand             if(aCoor.getY() <= 0.0)
37207540651SArmin Le Grand             {
373*7024eca9SArmin Le Grand                 return 0.0; // start value for inside
37407540651SArmin Le Grand             }
37507540651SArmin Le Grand 
37607540651SArmin Le Grand             if(aCoor.getY() >= 1.0)
37707540651SArmin Le Grand             {
378*7024eca9SArmin Le Grand                 return 1.0; // end value for outside
37907540651SArmin Le Grand             }
38007540651SArmin Le Grand 
38196fc4b33SArmin Le Grand             const sal_uInt32 nSteps(rGradInfo.getSteps());
38296fc4b33SArmin Le Grand 
38396fc4b33SArmin Le Grand             if(nSteps)
38496fc4b33SArmin Le Grand             {
38507540651SArmin Le Grand                 return floor(aCoor.getY() * nSteps) / double(nSteps - 1);
38696fc4b33SArmin Le Grand             }
38796fc4b33SArmin Le Grand 
38807540651SArmin Le Grand             return aCoor.getY();
38996fc4b33SArmin Le Grand         }
39096fc4b33SArmin Le Grand 
getAxialGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)39196fc4b33SArmin Le Grand         double getAxialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
39296fc4b33SArmin Le Grand         {
39396fc4b33SArmin Le Grand             const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV);
39407540651SArmin Le Grand 
395*7024eca9SArmin Le Grand             // Ignore Y, this is not needed at all for Y-Oriented gradients
396*7024eca9SArmin Le Grand             //if(aCoor.getX() < 0.0 || aCoor.getX() > 1.0)
397*7024eca9SArmin Le Grand             //{
398*7024eca9SArmin Le Grand             //    return 0.0;
399*7024eca9SArmin Le Grand             //}
40007540651SArmin Le Grand 
40107540651SArmin Le Grand             const double fAbsY(fabs(aCoor.getY()));
40207540651SArmin Le Grand 
40307540651SArmin Le Grand             if(fAbsY >= 1.0)
40407540651SArmin Le Grand             {
405*7024eca9SArmin Le Grand                 return 1.0; // use end value when outside in Y
40607540651SArmin Le Grand             }
40707540651SArmin Le Grand 
40896fc4b33SArmin Le Grand             const sal_uInt32 nSteps(rGradInfo.getSteps());
40996fc4b33SArmin Le Grand 
41096fc4b33SArmin Le Grand             if(nSteps)
41196fc4b33SArmin Le Grand             {
41207540651SArmin Le Grand                 return floor(fAbsY * nSteps) / double(nSteps - 1);
41396fc4b33SArmin Le Grand             }
41496fc4b33SArmin Le Grand 
41507540651SArmin Le Grand             return fAbsY;
41696fc4b33SArmin Le Grand         }
41796fc4b33SArmin Le Grand 
getRadialGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)41896fc4b33SArmin Le Grand         double getRadialGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
41996fc4b33SArmin Le Grand         {
42096fc4b33SArmin Le Grand             const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV);
42107540651SArmin Le Grand 
42207540651SArmin Le Grand             if(aCoor.getX() < -1.0 || aCoor.getX() > 1.0 || aCoor.getY() < -1.0 || aCoor.getY() > 1.0)
42307540651SArmin Le Grand             {
42407540651SArmin Le Grand                 return 0.0;
42507540651SArmin Le Grand             }
42607540651SArmin Le Grand 
42707540651SArmin Le Grand             const double t(1.0 - sqrt(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY()));
42896fc4b33SArmin Le Grand             const sal_uInt32 nSteps(rGradInfo.getSteps());
42996fc4b33SArmin Le Grand 
43007540651SArmin Le Grand             if(nSteps && t < 1.0)
43196fc4b33SArmin Le Grand             {
43207540651SArmin Le Grand                 return floor(t * nSteps) / double(nSteps - 1);
43396fc4b33SArmin Le Grand             }
43496fc4b33SArmin Le Grand 
43596fc4b33SArmin Le Grand             return t;
43696fc4b33SArmin Le Grand         }
43796fc4b33SArmin Le Grand 
getEllipticalGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)43896fc4b33SArmin Le Grand         double getEllipticalGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
43996fc4b33SArmin Le Grand         {
44096fc4b33SArmin Le Grand             return getRadialGradientAlpha(rUV, rGradInfo); // only matrix setup differs
44196fc4b33SArmin Le Grand         }
44296fc4b33SArmin Le Grand 
getSquareGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)44396fc4b33SArmin Le Grand         double getSquareGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
44496fc4b33SArmin Le Grand         {
44596fc4b33SArmin Le Grand             const B2DPoint aCoor(rGradInfo.getBackTextureTransform() * rUV);
44696fc4b33SArmin Le Grand             const double fAbsX(fabs(aCoor.getX()));
44707540651SArmin Le Grand 
44807540651SArmin Le Grand             if(fAbsX >= 1.0)
44907540651SArmin Le Grand             {
45007540651SArmin Le Grand                 return 0.0;
45107540651SArmin Le Grand             }
45207540651SArmin Le Grand 
45396fc4b33SArmin Le Grand             const double fAbsY(fabs(aCoor.getY()));
45496fc4b33SArmin Le Grand 
45507540651SArmin Le Grand             if(fAbsY >= 1.0)
45696fc4b33SArmin Le Grand             {
45796fc4b33SArmin Le Grand                 return 0.0;
45896fc4b33SArmin Le Grand             }
45996fc4b33SArmin Le Grand 
46096fc4b33SArmin Le Grand             const double t(1.0 - std::max(fAbsX, fAbsY));
46196fc4b33SArmin Le Grand             const sal_uInt32 nSteps(rGradInfo.getSteps());
46296fc4b33SArmin Le Grand 
46307540651SArmin Le Grand             if(nSteps && t < 1.0)
46496fc4b33SArmin Le Grand             {
46507540651SArmin Le Grand                 return floor(t * nSteps) / double(nSteps - 1);
46696fc4b33SArmin Le Grand             }
46796fc4b33SArmin Le Grand 
46896fc4b33SArmin Le Grand             return t;
46996fc4b33SArmin Le Grand         }
47096fc4b33SArmin Le Grand 
getRectangularGradientAlpha(const B2DPoint & rUV,const ODFGradientInfo & rGradInfo)47196fc4b33SArmin Le Grand         double getRectangularGradientAlpha(const B2DPoint& rUV, const ODFGradientInfo& rGradInfo)
47296fc4b33SArmin Le Grand         {
47396fc4b33SArmin Le Grand             return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs
47496fc4b33SArmin Le Grand         }
47596fc4b33SArmin Le Grand     } // namespace tools
476cdf0e10cSrcweir } // namespace basegfx
47796fc4b33SArmin Le Grand 
47896fc4b33SArmin Le Grand // eof
479