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 & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32,double fBorder)76 		GeoTexSvxGradient::GeoTexSvxGradient(
77             const basegfx::B2DRange& rTargetRange,
78             const basegfx::BColor& rStart,
79             const basegfx::BColor& rEnd,
80             sal_uInt32 /* nSteps */,
81             double fBorder)
82 		:	GeoTexSvx(),
83             maGradientInfo(),
84             maTargetRange(rTargetRange),
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 				&& maTargetRange == pCompare->maTargetRange
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 & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fAngle)113 		GeoTexSvxGradientLinear::GeoTexSvxGradientLinear(
114             const basegfx::B2DRange& rTargetRange,
115             const basegfx::BColor& rStart,
116             const basegfx::BColor& rEnd,
117             sal_uInt32 nSteps,
118             double fBorder,
119             double fAngle)
120 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
121 		{
122             maGradientInfo = basegfx::tools::createLinearODFGradientInfo(
123                 rTargetRange,
124                 nSteps,
125                 fBorder,
126                 fAngle);
127 		}
128 
~GeoTexSvxGradientLinear()129 		GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear()
130 		{
131 		}
132 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)133         void GeoTexSvxGradientLinear::appendTransformationsAndColors(
134             std::vector< B2DHomMatrixAndBColor >& rEntries,
135             basegfx::BColor& rOutmostColor)
136         {
137             rOutmostColor = maStart;
138 
139             if(maGradientInfo.getSteps())
140             {
141                 const double fStripeWidth(1.0 / maGradientInfo.getSteps());
142                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
143 
144                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
145                 {
146                     const double fPos(fStripeWidth * a);
147                     // optimized below...
148                     //
149                     // basegfx::B2DHomMatrix aNew;
150                     // aNew.scale(0.5, 0.5);
151                     // aNew.translate(0.5, 0.5);
152                     // aNew.scale(1.0, (1.0 - fPos));
153                     // aNew.translate(0.0, fPos);
154                     // aNew = maGradientInfo.getTextureTransform() * aNew;
155                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() *
156                         basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5 * (1.0 - fPos), 0.5, 0.5 * (1.0 + fPos));
157                     aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
158                     rEntries.push_back(aB2DHomMatrixAndBColor);
159                 }
160             }
161         }
162 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const163 		void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
164 		{
165             const double fScaler(basegfx::tools::getLinearGradientAlpha(rUV, maGradientInfo));
166 
167             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
168 		}
169 	} // end of namespace texture
170 } // end of namespace drawinglayer
171 
172 //////////////////////////////////////////////////////////////////////////////
173 
174 namespace drawinglayer
175 {
176 	namespace texture
177 	{
GeoTexSvxGradientAxial(const basegfx::B2DRange & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fAngle)178 		GeoTexSvxGradientAxial::GeoTexSvxGradientAxial(
179             const basegfx::B2DRange& rTargetRange,
180             const basegfx::BColor& rStart,
181             const basegfx::BColor& rEnd,
182             sal_uInt32 nSteps,
183             double fBorder,
184             double fAngle)
185 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
186 		{
187             maGradientInfo = basegfx::tools::createAxialODFGradientInfo(
188                 rTargetRange,
189                 nSteps,
190                 fBorder,
191                 fAngle);
192 		}
193 
~GeoTexSvxGradientAxial()194 		GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial()
195 		{
196 		}
197 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)198         void GeoTexSvxGradientAxial::appendTransformationsAndColors(
199             std::vector< B2DHomMatrixAndBColor >& rEntries,
200             basegfx::BColor& rOutmostColor)
201         {
202             rOutmostColor = maEnd;
203 
204             if(maGradientInfo.getSteps())
205             {
206                 const double fStripeWidth(1.0 / maGradientInfo.getSteps());
207                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
208 
209                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
210                 {
211                     // const double fPos(fStripeWidth * a);
212                     // optimized below...
213                     //
214                     // basegfx::B2DHomMatrix aNew;
215                     // aNew.scale(0.50, (1.0 - fPos));
216                     // aNew.translate(0.5, 0.0);
217                     // aNew = maGradientInfo.getTextureTransform() * aNew;
218                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() *
219                         basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 1.0 - (fStripeWidth * a), 0.5, 0.0);
220                     aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1));
221                     rEntries.push_back(aB2DHomMatrixAndBColor);
222                 }
223             }
224 		}
225 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const226 		void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
227 		{
228             const double fScaler(basegfx::tools::getAxialGradientAlpha(rUV, maGradientInfo));
229 
230             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
231 		}
232 	} // end of namespace texture
233 } // end of namespace drawinglayer
234 
235 //////////////////////////////////////////////////////////////////////////////
236 
237 namespace drawinglayer
238 {
239 	namespace texture
240 	{
GeoTexSvxGradientRadial(const basegfx::B2DRange & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY)241 		GeoTexSvxGradientRadial::GeoTexSvxGradientRadial(
242             const basegfx::B2DRange& rTargetRange,
243             const basegfx::BColor& rStart,
244             const basegfx::BColor& rEnd,
245             sal_uInt32 nSteps,
246             double fBorder,
247             double fOffsetX,
248             double fOffsetY)
249 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
250 		{
251             maGradientInfo = basegfx::tools::createRadialODFGradientInfo(
252                 rTargetRange,
253                 basegfx::B2DVector(fOffsetX,fOffsetY),
254                 nSteps,
255                 fBorder);
256 		}
257 
~GeoTexSvxGradientRadial()258 		GeoTexSvxGradientRadial::~GeoTexSvxGradientRadial()
259 		{
260 		}
261 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)262 		void GeoTexSvxGradientRadial::appendTransformationsAndColors(
263             std::vector< B2DHomMatrixAndBColor >& rEntries,
264             basegfx::BColor& rOutmostColor)
265 		{
266             rOutmostColor = maStart;
267 
268             if(maGradientInfo.getSteps())
269             {
270                 const double fStepSize(1.0 / maGradientInfo.getSteps());
271                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
272 
273                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
274                 {
275                     const double fSize(1.0 - (fStepSize * a));
276                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize);
277                     aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
278                     rEntries.push_back(aB2DHomMatrixAndBColor);
279                 }
280             }
281         }
282 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const283 		void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
284 		{
285             const double fScaler(basegfx::tools::getRadialGradientAlpha(rUV, maGradientInfo));
286 
287             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
288 		}
289 	} // end of namespace texture
290 } // end of namespace drawinglayer
291 
292 //////////////////////////////////////////////////////////////////////////////
293 
294 namespace drawinglayer
295 {
296 	namespace texture
297 	{
GeoTexSvxGradientElliptical(const basegfx::B2DRange & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)298 		GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical(
299             const basegfx::B2DRange& rTargetRange,
300             const basegfx::BColor& rStart,
301             const basegfx::BColor& rEnd,
302             sal_uInt32 nSteps,
303             double fBorder,
304             double fOffsetX,
305             double fOffsetY,
306             double fAngle)
307 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
308 		{
309             maGradientInfo = basegfx::tools::createEllipticalODFGradientInfo(
310                 rTargetRange,
311                 basegfx::B2DVector(fOffsetX,fOffsetY),
312                 nSteps,
313                 fBorder,
314                 fAngle);
315 		}
316 
~GeoTexSvxGradientElliptical()317 		GeoTexSvxGradientElliptical::~GeoTexSvxGradientElliptical()
318 		{
319 		}
320 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)321 		void GeoTexSvxGradientElliptical::appendTransformationsAndColors(
322             std::vector< B2DHomMatrixAndBColor >& rEntries,
323             basegfx::BColor& rOutmostColor)
324 		{
325             rOutmostColor = maStart;
326 
327             if(maGradientInfo.getSteps())
328             {
329                 double fWidth(1.0);
330                 double fHeight(1.0);
331                 double fIncrementX(0.0);
332                 double fIncrementY(0.0);
333 
334                 if(maGradientInfo.getAspectRatio() > 1.0)
335                 {
336                     fIncrementY = fHeight / maGradientInfo.getSteps();
337                     fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
338                 }
339                 else
340                 {
341                     fIncrementX = fWidth / maGradientInfo.getSteps();
342                     fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
343                 }
344 
345                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
346 
347                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
348                 {
349                     // next step
350                     fWidth -= fIncrementX;
351                     fHeight -= fIncrementY;
352 
353                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight);
354                     aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
355                     rEntries.push_back(aB2DHomMatrixAndBColor);
356                 }
357             }
358 		}
359 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const360 		void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
361 		{
362             const double fScaler(basegfx::tools::getEllipticalGradientAlpha(rUV, maGradientInfo));
363 
364             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
365 		}
366 	} // end of namespace texture
367 } // end of namespace drawinglayer
368 
369 //////////////////////////////////////////////////////////////////////////////
370 
371 namespace drawinglayer
372 {
373 	namespace texture
374 	{
GeoTexSvxGradientSquare(const basegfx::B2DRange & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)375 		GeoTexSvxGradientSquare::GeoTexSvxGradientSquare(
376             const basegfx::B2DRange& rTargetRange,
377             const basegfx::BColor& rStart,
378             const basegfx::BColor& rEnd,
379             sal_uInt32 nSteps,
380             double fBorder,
381             double fOffsetX,
382             double fOffsetY,
383             double fAngle)
384 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
385 		{
386             maGradientInfo = basegfx::tools::createSquareODFGradientInfo(
387                 rTargetRange,
388                 basegfx::B2DVector(fOffsetX,fOffsetY),
389                 nSteps,
390                 fBorder,
391                 fAngle);
392 		}
393 
~GeoTexSvxGradientSquare()394 		GeoTexSvxGradientSquare::~GeoTexSvxGradientSquare()
395 		{
396 		}
397 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)398 		void GeoTexSvxGradientSquare::appendTransformationsAndColors(
399             std::vector< B2DHomMatrixAndBColor >& rEntries,
400             basegfx::BColor& rOutmostColor)
401 		{
402             rOutmostColor = maStart;
403 
404             if(maGradientInfo.getSteps())
405             {
406                 const double fStepSize(1.0 / maGradientInfo.getSteps());
407                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
408 
409                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
410                 {
411                     const double fSize(1.0 - (fStepSize * a));
412                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize);
413                     aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
414                     rEntries.push_back(aB2DHomMatrixAndBColor);
415                 }
416             }
417 		}
418 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const419 		void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
420 		{
421             const double fScaler(basegfx::tools::getSquareGradientAlpha(rUV, maGradientInfo));
422 
423             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
424 		}
425 	} // end of namespace texture
426 } // end of namespace drawinglayer
427 
428 //////////////////////////////////////////////////////////////////////////////
429 
430 namespace drawinglayer
431 {
432 	namespace texture
433 	{
GeoTexSvxGradientRect(const basegfx::B2DRange & rTargetRange,const basegfx::BColor & rStart,const basegfx::BColor & rEnd,sal_uInt32 nSteps,double fBorder,double fOffsetX,double fOffsetY,double fAngle)434 		GeoTexSvxGradientRect::GeoTexSvxGradientRect(
435             const basegfx::B2DRange& rTargetRange,
436             const basegfx::BColor& rStart,
437             const basegfx::BColor& rEnd,
438             sal_uInt32 nSteps,
439             double fBorder,
440             double fOffsetX,
441             double fOffsetY,
442             double fAngle)
443 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
444 		{
445             maGradientInfo = basegfx::tools::createRectangularODFGradientInfo(
446                 rTargetRange,
447                 basegfx::B2DVector(fOffsetX,fOffsetY),
448                 nSteps,
449                 fBorder,
450                 fAngle);
451 		}
452 
~GeoTexSvxGradientRect()453 		GeoTexSvxGradientRect::~GeoTexSvxGradientRect()
454 		{
455 		}
456 
appendTransformationsAndColors(std::vector<B2DHomMatrixAndBColor> & rEntries,basegfx::BColor & rOutmostColor)457 		void GeoTexSvxGradientRect::appendTransformationsAndColors(
458             std::vector< B2DHomMatrixAndBColor >& rEntries,
459             basegfx::BColor& rOutmostColor)
460 		{
461             rOutmostColor = maStart;
462 
463             if(maGradientInfo.getSteps())
464             {
465                 double fWidth(1.0);
466                 double fHeight(1.0);
467                 double fIncrementX(0.0);
468                 double fIncrementY(0.0);
469 
470                 if(maGradientInfo.getAspectRatio() > 1.0)
471                 {
472                     fIncrementY = fHeight / maGradientInfo.getSteps();
473                     fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
474                 }
475                 else
476                 {
477                     fIncrementX = fWidth / maGradientInfo.getSteps();
478                     fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
479                 }
480 
481                 B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
482 
483                 for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
484                 {
485                     // next step
486                     fWidth -= fIncrementX;
487                     fHeight -= fIncrementY;
488 
489                     aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight);
490                     aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
491                     rEntries.push_back(aB2DHomMatrixAndBColor);
492                 }
493             }
494 		}
495 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double &) const496 		void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
497 		{
498             const double fScaler(basegfx::tools::getRectangularGradientAlpha(rUV, maGradientInfo));
499 
500             rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
501 		}
502 	} // end of namespace texture
503 } // end of namespace drawinglayer
504 
505 //////////////////////////////////////////////////////////////////////////////
506 
507 namespace drawinglayer
508 {
509 	namespace texture
510 	{
GeoTexSvxHatch(const basegfx::B2DRange & rTargetRange,double fDistance,double fAngle)511 		GeoTexSvxHatch::GeoTexSvxHatch(
512             const basegfx::B2DRange& rTargetRange,
513             double fDistance,
514             double fAngle)
515 		:	mfDistance(0.1),
516 			mfAngle(fAngle),
517 			mnSteps(10L)
518 		{
519 			double fTargetSizeX(rTargetRange.getWidth());
520 			double fTargetSizeY(rTargetRange.getHeight());
521 			double fTargetOffsetX(rTargetRange.getMinX());
522 			double fTargetOffsetY(rTargetRange.getMinY());
523 
524             fAngle = -fAngle;
525 
526 			// add object expansion
527 			if(0.0 != fAngle)
528 			{
529 				const double fAbsCos(fabs(cos(fAngle)));
530 				const double fAbsSin(fabs(sin(fAngle)));
531 				const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
532 				const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
533 				fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
534 				fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
535 				fTargetSizeX = fNewX;
536 				fTargetSizeY = fNewY;
537 			}
538 
539 			// add object scale before rotate
540 			maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
541 
542 			// add texture rotate after scale to keep perpendicular angles
543 			if(0.0 != fAngle)
544 			{
545 				basegfx::B2DPoint aCenter(0.5, 0.5);
546 				aCenter *= maTextureTransform;
547 
548                 maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
549                     * maTextureTransform;
550 			}
551 
552 			// add object translate
553 			maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
554 
555 			// prepare height for texture
556 			const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0);
557 			mnSteps = basegfx::fround(fSteps + 0.5);
558 			mfDistance = 1.0 / fSteps;
559 		}
560 
~GeoTexSvxHatch()561 		GeoTexSvxHatch::~GeoTexSvxHatch()
562 		{
563 		}
564 
operator ==(const GeoTexSvx & rGeoTexSvx) const565 		bool GeoTexSvxHatch::operator==(const GeoTexSvx& rGeoTexSvx) const
566 		{
567 			const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx);
568 			return (pCompare
569 				&& maTextureTransform == pCompare->maTextureTransform
570 				&& mfDistance == pCompare->mfDistance
571 				&& mfAngle == pCompare->mfAngle
572 				&& mnSteps == pCompare->mnSteps);
573 		}
574 
appendTransformations(::std::vector<basegfx::B2DHomMatrix> & rMatrices)575 		void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
576 		{
577 			for(sal_uInt32 a(1L); a < mnSteps; a++)
578 			{
579 				// create matrix
580 				const double fOffset(mfDistance * (double)a);
581 				basegfx::B2DHomMatrix aNew;
582 				aNew.set(1, 2, fOffset);
583 				rMatrices.push_back(maTextureTransform * aNew);
584 			}
585 		}
586 
getDistanceToHatch(const basegfx::B2DPoint & rUV) const587 		double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
588 		{
589 			const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV);
590 			return fmod(aCoor.getY(), mfDistance);
591 		}
592 
getBackTextureTransform() const593         const basegfx::B2DHomMatrix& GeoTexSvxHatch::getBackTextureTransform() const
594         {
595             if(maBackTextureTransform.isIdentity())
596             {
597                 const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform = maTextureTransform;
598                 const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform.invert();
599             }
600 
601             return maBackTextureTransform;
602         }
603 	} // end of namespace texture
604 } // end of namespace drawinglayer
605 
606 //////////////////////////////////////////////////////////////////////////////
607 
608 namespace drawinglayer
609 {
610 	namespace texture
611 	{
GeoTexSvxTiled(const basegfx::B2DRange & rRange,double fOffsetX,double fOffsetY)612 		GeoTexSvxTiled::GeoTexSvxTiled(
613             const basegfx::B2DRange& rRange,
614             double fOffsetX,
615             double fOffsetY)
616 		:	maRange(rRange),
617             mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)),
618             mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0))
619 		{
620             if(!basegfx::fTools::equalZero(mfOffsetX))
621             {
622                 mfOffsetY = 0.0;
623             }
624 		}
625 
~GeoTexSvxTiled()626 		GeoTexSvxTiled::~GeoTexSvxTiled()
627 		{
628 		}
629 
operator ==(const GeoTexSvx & rGeoTexSvx) const630 		bool GeoTexSvxTiled::operator==(const GeoTexSvx& rGeoTexSvx) const
631 		{
632 			const GeoTexSvxTiled* pCompare = dynamic_cast< const GeoTexSvxTiled* >(&rGeoTexSvx);
633 
634             return (pCompare
635 				&& maRange == pCompare->maRange
636 				&& mfOffsetX == pCompare->mfOffsetX
637                 && mfOffsetY == pCompare->mfOffsetY);
638 		}
639 
appendTransformations(::std::vector<basegfx::B2DHomMatrix> & rMatrices)640 		void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
641 		{
642             const double fWidth(maRange.getWidth());
643 
644             if(!basegfx::fTools::equalZero(fWidth))
645             {
646                 const double fHeight(maRange.getHeight());
647 
648                 if(!basegfx::fTools::equalZero(fHeight))
649                 {
650 			        double fStartX(maRange.getMinX());
651 			        double fStartY(maRange.getMinY());
652                     sal_Int32 nPosX(0);
653                     sal_Int32 nPosY(0);
654 
655 			        if(basegfx::fTools::more(fStartX, 0.0))
656 			        {
657                         const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1);
658 
659                         nPosX -= nDiff;
660 				        fStartX -= nDiff * fWidth;
661 			        }
662 
663 			        if(basegfx::fTools::less(fStartX + fWidth, 0.0))
664 			        {
665                         const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth)));
666 
667                         nPosX += nDiff;
668 				        fStartX += nDiff * fWidth;
669 			        }
670 
671 			        if(basegfx::fTools::more(fStartY, 0.0))
672 			        {
673                         const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1);
674 
675                         nPosY -= nDiff;
676 				        fStartY -= nDiff * fHeight;
677 			        }
678 
679 			        if(basegfx::fTools::less(fStartY + fHeight, 0.0))
680 			        {
681                         const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight)));
682 
683                         nPosY += nDiff;
684 				        fStartY += nDiff * fHeight;
685 			        }
686 
687                     if(!basegfx::fTools::equalZero(mfOffsetY))
688                     {
689                         for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth, nPosX++)
690                         {
691                             for(double fPosY(nPosX % 2 ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY);
692                                 basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight)
693                             {
694                                 rMatrices.push_back(
695                                     basegfx::tools::createScaleTranslateB2DHomMatrix(
696                                         fWidth,
697                                         fHeight,
698                                         fPosX,
699                                         fPosY));
700                             }
701                         }
702                     }
703                     else
704                     {
705                         for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight, nPosY++)
706                         {
707                             for(double fPosX(nPosY % 2 ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX);
708                                 basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth)
709                             {
710                                 rMatrices.push_back(
711                                     basegfx::tools::createScaleTranslateB2DHomMatrix(
712                                         fWidth,
713                                         fHeight,
714                                         fPosX,
715                                         fPosY));
716                             }
717                         }
718                     }
719                 }
720             }
721 		}
722 	} // end of namespace texture
723 } // end of namespace drawinglayer
724 
725 //////////////////////////////////////////////////////////////////////////////
726 // eof
727