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 	{
38 		GeoTexSvx::GeoTexSvx()
39 		{
40 		}
41 
42 		GeoTexSvx::~GeoTexSvx()
43 		{
44 		}
45 
46 		bool GeoTexSvx::operator==(const GeoTexSvx& /*rGeoTexSvx*/) const
47 		{
48 			// default implementation says yes (no data -> no difference)
49 			return true;
50 		}
51 
52 		void GeoTexSvx::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& /*rMatrices*/)
53 		{
54 			// default implementation does nothing
55 		}
56 
57 		void GeoTexSvx::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
58 		{
59 			// base implementation creates random color (for testing only, may also be pure virtual)
60 			rBColor.setRed((rand() & 0x7fff) / 32767.0);
61 			rBColor.setGreen((rand() & 0x7fff) / 32767.0);
62 			rBColor.setBlue((rand() & 0x7fff) / 32767.0);
63 		}
64 
65 		void GeoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
66 		{
67 			// base implementation uses inverse of luminance of solved color (for testing only, may also be pure virtual)
68 			basegfx::BColor aBaseColor;
69 			modifyBColor(rUV, aBaseColor, rfOpacity);
70 			rfOpacity = 1.0 - aBaseColor.luminance();
71 		}
72 	} // end of namespace texture
73 } // end of namespace drawinglayer
74 
75 //////////////////////////////////////////////////////////////////////////////
76 
77 namespace drawinglayer
78 {
79 	namespace texture
80 	{
81 		void GeoTexSvxGradient::impAppendMatrix(::std::vector< basegfx::B2DHomMatrix >& rMatrices, const basegfx::B2DRange& rRange)
82 		{
83 			basegfx::B2DHomMatrix aNew;
84 			aNew.set(0, 0, rRange.getWidth());
85 			aNew.set(1, 1, rRange.getHeight());
86 			aNew.set(0, 2, rRange.getMinX());
87 			aNew.set(1, 2, rRange.getMinY());
88 			rMatrices.push_back(maGradientInfo.maTextureTransform * aNew);
89 		}
90 
91 		void GeoTexSvxGradient::impAppendColorsRadial(::std::vector< basegfx::BColor >& rColors)
92 		{
93 			if(maGradientInfo.mnSteps)
94 			{
95 				rColors.push_back(maStart);
96 
97 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps - 1L; a++)
98 				{
99 					rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)maGradientInfo.mnSteps));
100 				}
101 
102 				rColors.push_back(maEnd);
103 			}
104 		}
105 
106 		GeoTexSvxGradient::GeoTexSvxGradient(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder)
107 		:	maTargetRange(rTargetRange),
108 			maStart(rStart),
109 			maEnd(rEnd),
110 			mfBorder(fBorder)
111 		{
112 			maGradientInfo.mnSteps = nSteps;
113 			maGradientInfo.mfAspectRatio = 1.0;
114 		}
115 
116 		GeoTexSvxGradient::~GeoTexSvxGradient()
117 		{
118 		}
119 
120 		bool GeoTexSvxGradient::operator==(const GeoTexSvx& rGeoTexSvx) const
121 		{
122 			const GeoTexSvxGradient* pCompare = dynamic_cast< const GeoTexSvxGradient* >(&rGeoTexSvx);
123 			return (pCompare
124 				&& maGradientInfo.maTextureTransform == pCompare->maGradientInfo.maTextureTransform
125 				&& maTargetRange == pCompare->maTargetRange
126 				&& maGradientInfo.mnSteps == pCompare->maGradientInfo.mnSteps
127 				&& maGradientInfo.mfAspectRatio == pCompare->maGradientInfo.mfAspectRatio
128 				&& mfBorder == pCompare->mfBorder);
129 		}
130 	} // end of namespace texture
131 } // end of namespace drawinglayer
132 
133 //////////////////////////////////////////////////////////////////////////////
134 
135 namespace drawinglayer
136 {
137 	namespace texture
138 	{
139 		GeoTexSvxGradientLinear::GeoTexSvxGradientLinear(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle)
140 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
141 		{
142             basegfx::tools::createLinearODFGradientInfo(maGradientInfo,
143                                                         rTargetRange,
144                                                         nSteps,
145                                                         fBorder,
146                                                         fAngle);
147 		}
148 
149 		GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear()
150 		{
151 		}
152 
153 		void GeoTexSvxGradientLinear::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
154 		{
155 			if(maGradientInfo.mnSteps)
156 			{
157 				const double fStripeWidth(1.0 / maGradientInfo.mnSteps);
158 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
159 				{
160 					const basegfx::B2DRange aRect(0.0, fStripeWidth * a, 1.0, 1.0);
161 					impAppendMatrix(rMatrices, aRect);
162 				}
163 			}
164 		}
165 
166 		void GeoTexSvxGradientLinear::appendColors(::std::vector< basegfx::BColor >& rColors)
167 		{
168 			if(maGradientInfo.mnSteps)
169 			{
170 				rColors.push_back(maStart);
171 
172 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
173 				{
174 					rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)(maGradientInfo.mnSteps + 1L)));
175 				}
176 			}
177 		}
178 
179 		void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
180 		{
181             const double fScaler(basegfx::tools::getLinearGradientAlpha(rUV, maGradientInfo));
182 
183 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
184 		}
185 	} // end of namespace texture
186 } // end of namespace drawinglayer
187 
188 //////////////////////////////////////////////////////////////////////////////
189 
190 namespace drawinglayer
191 {
192 	namespace texture
193 	{
194 		GeoTexSvxGradientAxial::GeoTexSvxGradientAxial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle)
195 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
196 		{
197             basegfx::tools::createAxialODFGradientInfo(maGradientInfo,
198                                                        rTargetRange,
199                                                        nSteps,
200                                                        fBorder,
201                                                        fAngle);
202 		}
203 
204 		GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial()
205 		{
206 		}
207 
208 		void GeoTexSvxGradientAxial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
209 		{
210 			if(maGradientInfo.mnSteps)
211 			{
212 				const double fStripeWidth=1.0 / (maGradientInfo.mnSteps - 1L);
213 				for(sal_uInt32 a(maGradientInfo.mnSteps-1L); a != 0; a--)
214 				{
215 					const basegfx::B2DRange aRect(0, 0, 1.0, fStripeWidth * a);
216 					impAppendMatrix(rMatrices, aRect);
217 				}
218 			}
219 		}
220 
221 		void GeoTexSvxGradientAxial::appendColors(::std::vector< basegfx::BColor >& rColors)
222 		{
223 			if(maGradientInfo.mnSteps)
224 			{
225 				rColors.push_back(maEnd);
226 
227 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
228 				{
229 					rColors.push_back(interpolate(maEnd, maStart, (double)a / (double)maGradientInfo.mnSteps));
230 				}
231 			}
232 		}
233 
234 		void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
235 		{
236             const double fScaler(basegfx::tools::getAxialGradientAlpha(rUV, maGradientInfo));
237 
238 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
239 		}
240 	} // end of namespace texture
241 } // end of namespace drawinglayer
242 
243 //////////////////////////////////////////////////////////////////////////////
244 
245 namespace drawinglayer
246 {
247 	namespace texture
248 	{
249 		GeoTexSvxGradientRadial::GeoTexSvxGradientRadial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY)
250 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
251 		{
252             basegfx::tools::createRadialODFGradientInfo(maGradientInfo,
253                                                         rTargetRange,
254                                                         basegfx::B2DVector(fOffsetX,fOffsetY),
255                                                         nSteps,
256                                                         fBorder);
257 		}
258 
259 		GeoTexSvxGradientRadial::~GeoTexSvxGradientRadial()
260 		{
261 		}
262 
263 		void GeoTexSvxGradientRadial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
264 		{
265 			if(maGradientInfo.mnSteps)
266 			{
267 				const double fStepSize=1.0 / maGradientInfo.mnSteps;
268 				for(sal_uInt32 a(maGradientInfo.mnSteps-1L); a > 0; a--)
269 				{
270 					const basegfx::B2DRange aRect(0, 0, fStepSize*a, fStepSize*a);
271 					impAppendMatrix(rMatrices, aRect);
272 				}
273 			}
274 		}
275 
276 		void GeoTexSvxGradientRadial::appendColors(::std::vector< basegfx::BColor >& rColors)
277 		{
278 			impAppendColorsRadial(rColors);
279 		}
280 
281 		void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
282 		{
283             const double fScaler(basegfx::tools::getRadialGradientAlpha(rUV, maGradientInfo));
284 
285 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
286 		}
287 	} // end of namespace texture
288 } // end of namespace drawinglayer
289 
290 //////////////////////////////////////////////////////////////////////////////
291 
292 namespace drawinglayer
293 {
294 	namespace texture
295 	{
296 		GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
297 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
298 		{
299             basegfx::tools::createEllipticalODFGradientInfo(maGradientInfo,
300                                                             rTargetRange,
301                                                             basegfx::B2DVector(fOffsetX,fOffsetY),
302                                                             nSteps,
303                                                             fBorder,
304                                                             fAngle);
305 		}
306 
307 		GeoTexSvxGradientElliptical::~GeoTexSvxGradientElliptical()
308 		{
309 		}
310 
311 		void GeoTexSvxGradientElliptical::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
312 		{
313 			if(maGradientInfo.mnSteps)
314 			{
315 				double fWidth(1);
316 				double fHeight(1);
317 				double fIncrementX, fIncrementY;
318 
319 				if(maGradientInfo.mfAspectRatio > 1.0)
320 				{
321 					fIncrementY = fHeight / maGradientInfo.mnSteps;
322 					fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
323 				}
324 				else
325 				{
326 					fIncrementX = fWidth / maGradientInfo.mnSteps;
327 					fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
328 				}
329 
330 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
331 				{
332 					// next step
333 					fWidth  -= fIncrementX;
334 					fHeight -= fIncrementY;
335 
336 					// create matrix
337 					const basegfx::B2DRange aRect(0, 0, fWidth, fHeight);
338 					impAppendMatrix(rMatrices, aRect);
339 				}
340 			}
341 		}
342 
343 		void GeoTexSvxGradientElliptical::appendColors(::std::vector< basegfx::BColor >& rColors)
344 		{
345 			impAppendColorsRadial(rColors);
346 		}
347 
348 		void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
349 		{
350             const double fScaler(basegfx::tools::getEllipticalGradientAlpha(rUV, maGradientInfo));
351 
352 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
353 		}
354 	} // end of namespace texture
355 } // end of namespace drawinglayer
356 
357 //////////////////////////////////////////////////////////////////////////////
358 
359 namespace drawinglayer
360 {
361 	namespace texture
362 	{
363 		GeoTexSvxGradientSquare::GeoTexSvxGradientSquare(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
364 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
365 		{
366             basegfx::tools::createSquareODFGradientInfo(maGradientInfo,
367                                                         rTargetRange,
368                                                         basegfx::B2DVector(fOffsetX,fOffsetY),
369                                                         nSteps,
370                                                         fBorder,
371                                                         fAngle);
372 		}
373 
374 		GeoTexSvxGradientSquare::~GeoTexSvxGradientSquare()
375 		{
376 		}
377 
378 		void GeoTexSvxGradientSquare::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
379 		{
380 			if(maGradientInfo.mnSteps)
381 			{
382 				const double fStepSize=1.0 / maGradientInfo.mnSteps;
383 				for(sal_uInt32 a(maGradientInfo.mnSteps-1L); a > 0; a--)
384 				{
385 					const basegfx::B2DRange aRect(0, 0, fStepSize*a, fStepSize*a);
386 					impAppendMatrix(rMatrices, aRect);
387 				}
388 			}
389 		}
390 
391 		void GeoTexSvxGradientSquare::appendColors(::std::vector< basegfx::BColor >& rColors)
392 		{
393 			impAppendColorsRadial(rColors);
394 		}
395 
396 		void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
397 		{
398             const double fScaler(basegfx::tools::getSquareGradientAlpha(rUV, maGradientInfo));
399 
400 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
401 		}
402 	} // end of namespace texture
403 } // end of namespace drawinglayer
404 
405 //////////////////////////////////////////////////////////////////////////////
406 
407 namespace drawinglayer
408 {
409 	namespace texture
410 	{
411 		GeoTexSvxGradientRect::GeoTexSvxGradientRect(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle)
412 		:	GeoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder)
413 		{
414             basegfx::tools::createRectangularODFGradientInfo(maGradientInfo,
415                                                              rTargetRange,
416                                                              basegfx::B2DVector(fOffsetX,fOffsetY),
417                                                              nSteps,
418                                                              fBorder,
419                                                              fAngle);
420 		}
421 
422 		GeoTexSvxGradientRect::~GeoTexSvxGradientRect()
423 		{
424 		}
425 
426 		void GeoTexSvxGradientRect::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
427 		{
428 			if(maGradientInfo.mnSteps)
429 			{
430 				double fWidth(1);
431 				double fHeight(1);
432 				double fIncrementX, fIncrementY;
433 
434 				if(maGradientInfo.mfAspectRatio > 1.0)
435 				{
436 					fIncrementY = fHeight / maGradientInfo.mnSteps;
437 					fIncrementX = fIncrementY / maGradientInfo.mfAspectRatio;
438 				}
439 				else
440 				{
441 					fIncrementX = fWidth / maGradientInfo.mnSteps;
442 					fIncrementY = fIncrementX * maGradientInfo.mfAspectRatio;
443 				}
444 
445 				for(sal_uInt32 a(1L); a < maGradientInfo.mnSteps; a++)
446 				{
447 					// next step
448 					fWidth  -= fIncrementX;
449 					fHeight -= fIncrementY;
450 
451 					// create matrix
452 					const basegfx::B2DRange aRect(0, 0, fWidth, fHeight);
453 					impAppendMatrix(rMatrices, aRect);
454 				}
455 			}
456 		}
457 
458 		void GeoTexSvxGradientRect::appendColors(::std::vector< basegfx::BColor >& rColors)
459 		{
460 			impAppendColorsRadial(rColors);
461 		}
462 
463 		void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
464 		{
465             const double fScaler(basegfx::tools::getRectangularGradientAlpha(rUV, maGradientInfo));
466 
467 			rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler);
468 		}
469 	} // end of namespace texture
470 } // end of namespace drawinglayer
471 
472 //////////////////////////////////////////////////////////////////////////////
473 
474 namespace drawinglayer
475 {
476 	namespace texture
477 	{
478 		GeoTexSvxHatch::GeoTexSvxHatch(const basegfx::B2DRange& rTargetRange, double fDistance, double fAngle)
479 		:	mfDistance(0.1),
480 			mfAngle(fAngle),
481 			mnSteps(10L)
482 		{
483 			double fTargetSizeX(rTargetRange.getWidth());
484 			double fTargetSizeY(rTargetRange.getHeight());
485 			double fTargetOffsetX(rTargetRange.getMinX());
486 			double fTargetOffsetY(rTargetRange.getMinY());
487 
488             fAngle = -fAngle;
489 
490 			// add object expansion
491 			if(0.0 != fAngle)
492 			{
493 				const double fAbsCos(fabs(cos(fAngle)));
494 				const double fAbsSin(fabs(sin(fAngle)));
495 				const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
496 				const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
497 				fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
498 				fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
499 				fTargetSizeX = fNewX;
500 				fTargetSizeY = fNewY;
501 			}
502 
503 			// add object scale before rotate
504 			maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
505 
506 			// add texture rotate after scale to keep perpendicular angles
507 			if(0.0 != fAngle)
508 			{
509 				basegfx::B2DPoint aCenter(0.5, 0.5);
510 				aCenter *= maTextureTransform;
511 
512                 maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
513                     * maTextureTransform;
514 			}
515 
516 			// add object translate
517 			maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
518 
519 			// prepare height for texture
520 			const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0);
521 			mnSteps = basegfx::fround(fSteps + 0.5);
522 			mfDistance = 1.0 / fSteps;
523 
524 			// build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
525 			maBackTextureTransform = maTextureTransform;
526 			maBackTextureTransform.invert();
527 		}
528 
529 		GeoTexSvxHatch::~GeoTexSvxHatch()
530 		{
531 		}
532 
533 		bool GeoTexSvxHatch::operator==(const GeoTexSvx& rGeoTexSvx) const
534 		{
535 			const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx);
536 			return (pCompare
537 				&& maTextureTransform == pCompare->maTextureTransform
538 				&& mfDistance == pCompare->mfDistance
539 				&& mfAngle == pCompare->mfAngle
540 				&& mnSteps == pCompare->mnSteps);
541 		}
542 
543 		void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
544 		{
545 			for(sal_uInt32 a(1L); a < mnSteps; a++)
546 			{
547 				// create matrix
548 				const double fOffset(mfDistance * (double)a);
549 				basegfx::B2DHomMatrix aNew;
550 				aNew.set(1, 2, fOffset);
551 				rMatrices.push_back(maTextureTransform * aNew);
552 			}
553 		}
554 
555 		double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
556 		{
557 			const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV);
558 			return fmod(aCoor.getY(), mfDistance);
559 		}
560 	} // end of namespace texture
561 } // end of namespace drawinglayer
562 
563 //////////////////////////////////////////////////////////////////////////////
564 
565 namespace drawinglayer
566 {
567 	namespace texture
568 	{
569 		GeoTexSvxTiled::GeoTexSvxTiled(const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize)
570 		:	maTopLeft(rTopLeft),
571 			maSize(rSize)
572 		{
573 			if(basegfx::fTools::lessOrEqual(maSize.getX(), 0.0))
574 			{
575 				maSize.setX(1.0);
576 			}
577 
578 			if(basegfx::fTools::lessOrEqual(maSize.getY(), 0.0))
579 			{
580 				maSize.setY(1.0);
581 			}
582 		}
583 
584 		GeoTexSvxTiled::~GeoTexSvxTiled()
585 		{
586 		}
587 
588 		bool GeoTexSvxTiled::operator==(const GeoTexSvx& rGeoTexSvx) const
589 		{
590 			const GeoTexSvxTiled* pCompare = dynamic_cast< const GeoTexSvxTiled* >(&rGeoTexSvx);
591 			return (pCompare
592 				&& maTopLeft == pCompare->maTopLeft
593 				&& maSize == pCompare->maSize);
594 		}
595 
596 		void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
597 		{
598 			double fStartX(maTopLeft.getX());
599 			double fStartY(maTopLeft.getY());
600 
601 			if(basegfx::fTools::more(fStartX, 0.0))
602 			{
603 				fStartX -= (floor(fStartX / maSize.getX()) + 1.0) * maSize.getX();
604 			}
605 
606 			if(basegfx::fTools::less(fStartX + maSize.getX(), 0.0))
607 			{
608 				fStartX += floor(-fStartX / maSize.getX()) * maSize.getX();
609 			}
610 
611 			if(basegfx::fTools::more(fStartY, 0.0))
612 			{
613 				fStartY -= (floor(fStartY / maSize.getY()) + 1.0) * maSize.getY();
614 			}
615 
616 			if(basegfx::fTools::less(fStartY + maSize.getY(), 0.0))
617 			{
618 				fStartY += floor(-fStartY / maSize.getY()) * maSize.getY();
619 			}
620 
621 			for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += maSize.getY())
622 			{
623 				for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += maSize.getX())
624 				{
625 					basegfx::B2DHomMatrix aNew;
626 
627 					aNew.set(0, 0, maSize.getX());
628 					aNew.set(1, 1, maSize.getY());
629 					aNew.set(0, 2, fPosX);
630 					aNew.set(1, 2, fPosY);
631 
632 					rMatrices.push_back(aNew);
633 				}
634 			}
635 		}
636 	} // end of namespace texture
637 } // end of namespace drawinglayer
638 
639 //////////////////////////////////////////////////////////////////////////////
640 // eof
641