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