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