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