fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / basegfx / source / tools / gradienttools.cxx
blob7bdc07d1441ccb564b2aab10e54ff7d9aa0e8421
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basegfx/tools/gradienttools.hxx>
21 #include <basegfx/point/b2dpoint.hxx>
22 #include <basegfx/range/b2drange.hxx>
23 #include <basegfx/matrix/b2dhommatrixtools.hxx>
25 namespace basegfx
27 /** Most of the setup for linear & axial gradient is the same, except
28 for the border treatment. Factored out here.
30 static void init1DGradientInfo(ODFGradientInfo& o_rGradientInfo,
31 const B2DRange& rTargetRange,
32 sal_uInt32 nSteps,
33 double fBorder,
34 double fAngle,
35 bool bAxial)
37 o_rGradientInfo.maTextureTransform.identity();
38 o_rGradientInfo.maBackTextureTransform.identity();
39 o_rGradientInfo.mnSteps = nSteps;
41 fAngle = -fAngle;
43 double fTargetSizeX(rTargetRange.getWidth());
44 double fTargetSizeY(rTargetRange.getHeight());
45 double fTargetOffsetX(rTargetRange.getMinX());
46 double fTargetOffsetY(rTargetRange.getMinY());
48 // add object expansion
49 if(0.0 != fAngle)
51 const double fAbsCos(fabs(cos(fAngle)));
52 const double fAbsSin(fabs(sin(fAngle)));
53 const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
54 const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
55 fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
56 fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
57 fTargetSizeX = fNewX;
58 fTargetSizeY = fNewY;
61 const double fSizeWithoutBorder=1.0 - fBorder;
62 if( bAxial )
64 o_rGradientInfo.maTextureTransform.scale(1.0, fSizeWithoutBorder * .5);
65 o_rGradientInfo.maTextureTransform.translate(0.0, 0.5);
67 else
69 if(!fTools::equal(fSizeWithoutBorder, 1.0))
71 o_rGradientInfo.maTextureTransform.scale(1.0, fSizeWithoutBorder);
72 o_rGradientInfo.maTextureTransform.translate(0.0, fBorder);
76 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
78 // add texture rotate after scale to keep perpendicular angles
79 if(0.0 != fAngle)
81 const B2DPoint aCenter(0.5*fTargetSizeX,
82 0.5*fTargetSizeY);
83 o_rGradientInfo.maTextureTransform *=
84 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
87 // add object translate
88 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
90 // prepare aspect for texture
91 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
93 // build transform from u,v to [0.0 .. 1.0].
94 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
95 o_rGradientInfo.maBackTextureTransform.invert();
98 /** Most of the setup for radial & ellipsoidal gradient is the same,
99 except for the border treatment. Factored out here.
101 static void initEllipticalGradientInfo(ODFGradientInfo& o_rGradientInfo,
102 const B2DRange& rTargetRange,
103 const B2DVector& rOffset,
104 sal_uInt32 nSteps,
105 double fBorder,
106 double fAngle,
107 bool bCircular)
109 o_rGradientInfo.maTextureTransform.identity();
110 o_rGradientInfo.maBackTextureTransform.identity();
111 o_rGradientInfo.mnSteps = nSteps;
113 fAngle = -fAngle;
115 double fTargetSizeX(rTargetRange.getWidth());
116 double fTargetSizeY(rTargetRange.getHeight());
117 double fTargetOffsetX(rTargetRange.getMinX());
118 double fTargetOffsetY(rTargetRange.getMinY());
120 // add object expansion
121 if( bCircular )
123 const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY)));
124 fTargetOffsetX -= (fOriginalDiag - fTargetSizeX) / 2.0;
125 fTargetOffsetY -= (fOriginalDiag - fTargetSizeY) / 2.0;
126 fTargetSizeX = fOriginalDiag;
127 fTargetSizeY = fOriginalDiag;
129 else
131 fTargetOffsetX -= (0.4142 / 2.0 ) * fTargetSizeX;
132 fTargetOffsetY -= (0.4142 / 2.0 ) * fTargetSizeY;
133 fTargetSizeX = 1.4142 * fTargetSizeX;
134 fTargetSizeY = 1.4142 * fTargetSizeY;
137 const double fHalfBorder((1.0 - fBorder) * 0.5);
138 o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
140 o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
141 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
143 // add texture rotate after scale to keep perpendicular angles
144 if( !bCircular && 0.0 != fAngle)
146 const B2DPoint aCenter(0.5*fTargetSizeX,
147 0.5*fTargetSizeY);
148 o_rGradientInfo.maTextureTransform *=
149 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
152 // add defined offsets after rotation
153 if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
155 // use original target size
156 fTargetOffsetX += (rOffset.getX() - 0.5) * rTargetRange.getWidth();
157 fTargetOffsetY += (rOffset.getY() - 0.5) * rTargetRange.getHeight();
160 // add object translate
161 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
163 // prepare aspect for texture
164 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
166 // build transform from u,v to [0.0 .. 1.0].
167 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
168 o_rGradientInfo.maBackTextureTransform.invert();
171 /** Setup for rect & square gradient is exactly the same. Factored out
172 here.
174 static void initRectGradientInfo(ODFGradientInfo& o_rGradientInfo,
175 const B2DRange& rTargetRange,
176 const B2DVector& rOffset,
177 sal_uInt32 nSteps,
178 double fBorder,
179 double fAngle,
180 bool bSquare)
182 o_rGradientInfo.maTextureTransform.identity();
183 o_rGradientInfo.maBackTextureTransform.identity();
184 o_rGradientInfo.mnSteps = nSteps;
186 fAngle = -fAngle;
188 double fTargetSizeX(rTargetRange.getWidth());
189 double fTargetSizeY(rTargetRange.getHeight());
190 double fTargetOffsetX(rTargetRange.getMinX());
191 double fTargetOffsetY(rTargetRange.getMinY());
193 // add object expansion
194 if(bSquare)
196 const double fSquareWidth(std::max(fTargetSizeX, fTargetSizeY));
197 fTargetOffsetX -= (fSquareWidth - fTargetSizeX) / 2.0;
198 fTargetOffsetY -= (fSquareWidth - fTargetSizeY) / 2.0;
199 fTargetSizeX = fTargetSizeY = fSquareWidth;
202 // add object expansion
203 if(0.0 != fAngle)
205 const double fAbsCos(fabs(cos(fAngle)));
206 const double fAbsSin(fabs(sin(fAngle)));
207 const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
208 const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
209 fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
210 fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
211 fTargetSizeX = fNewX;
212 fTargetSizeY = fNewY;
215 const double fHalfBorder((1.0 - fBorder) * 0.5);
216 o_rGradientInfo.maTextureTransform.scale(fHalfBorder, fHalfBorder);
218 o_rGradientInfo.maTextureTransform.translate(0.5, 0.5);
219 o_rGradientInfo.maTextureTransform.scale(fTargetSizeX, fTargetSizeY);
221 // add texture rotate after scale to keep perpendicular angles
222 if(0.0 != fAngle)
224 const B2DPoint aCenter(0.5*fTargetSizeX,
225 0.5*fTargetSizeY);
226 o_rGradientInfo.maTextureTransform *=
227 basegfx::tools::createRotateAroundPoint(aCenter, fAngle);
230 // add defined offsets after rotation
231 if(0.5 != rOffset.getX() || 0.5 != rOffset.getY())
233 // use scaled target size
234 fTargetOffsetX += (rOffset.getX() - 0.5) * fTargetSizeX;
235 fTargetOffsetY += (rOffset.getY() - 0.5) * fTargetSizeY;
238 // add object translate
239 o_rGradientInfo.maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);
241 // prepare aspect for texture
242 o_rGradientInfo.mfAspectRatio = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0;
244 // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform
245 o_rGradientInfo.maBackTextureTransform = o_rGradientInfo.maTextureTransform;
246 o_rGradientInfo.maBackTextureTransform.invert();
249 namespace tools
251 ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
252 const B2DRange& rTargetArea,
253 sal_uInt32 nSteps,
254 double fBorder,
255 double fAngle)
257 init1DGradientInfo(o_rGradientInfo,
258 rTargetArea,
259 nSteps,
260 fBorder,
261 fAngle,
262 false);
263 return o_rGradientInfo;
266 ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
267 const B2DRange& rTargetArea,
268 sal_uInt32 nSteps,
269 double fBorder,
270 double fAngle)
272 init1DGradientInfo(o_rGradientInfo,
273 rTargetArea,
274 nSteps,
275 fBorder,
276 fAngle,
277 true);
278 return o_rGradientInfo;
281 ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
282 const B2DRange& rTargetArea,
283 const B2DVector& rOffset,
284 sal_uInt32 nSteps,
285 double fBorder)
287 initEllipticalGradientInfo(o_rGradientInfo,
288 rTargetArea,
289 rOffset,
290 nSteps,
291 fBorder,
292 0.0,
293 true);
294 return o_rGradientInfo;
297 ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
298 const B2DRange& rTargetArea,
299 const B2DVector& rOffset,
300 sal_uInt32 nSteps,
301 double fBorder,
302 double fAngle)
304 initEllipticalGradientInfo(o_rGradientInfo,
305 rTargetArea,
306 rOffset,
307 nSteps,
308 fBorder,
309 fAngle,
310 false);
311 return o_rGradientInfo;
314 ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
315 const B2DRange& rTargetArea,
316 const B2DVector& rOffset,
317 sal_uInt32 nSteps,
318 double fBorder,
319 double fAngle)
321 initRectGradientInfo(o_rGradientInfo,
322 rTargetArea,
323 rOffset,
324 nSteps,
325 fBorder,
326 fAngle,
327 true);
328 return o_rGradientInfo;
331 ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo,
332 const B2DRange& rTargetArea,
333 const B2DVector& rOffset,
334 sal_uInt32 nSteps,
335 double fBorder,
336 double fAngle)
338 initRectGradientInfo(o_rGradientInfo,
339 rTargetArea,
340 rOffset,
341 nSteps,
342 fBorder,
343 fAngle,
344 false);
345 return o_rGradientInfo;
348 } // namespace tools
350 } // namespace basegfx
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */