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 <tools/stream.hxx>
21 : #include <tools/vcompat.hxx>
22 : #include <tools/debug.hxx>
23 : #include <vcl/gradient.hxx>
24 :
25 : // =======================================================================
26 :
27 : DBG_NAME( Gradient )
28 :
29 : // -----------------------------------------------------------------------
30 :
31 3406 : Impl_Gradient::Impl_Gradient() :
32 : maStartColor( COL_BLACK ),
33 3406 : maEndColor( COL_WHITE )
34 : {
35 3406 : mnRefCount = 1;
36 3406 : meStyle = GradientStyle_LINEAR;
37 3406 : mnAngle = 0;
38 3406 : mnBorder = 0;
39 3406 : mnOfsX = 50;
40 3406 : mnOfsY = 50;
41 3406 : mnIntensityStart = 100;
42 3406 : mnIntensityEnd = 100;
43 3406 : mnStepCount = 0;
44 3406 : }
45 :
46 : // -----------------------------------------------------------------------
47 :
48 1215 : Impl_Gradient::Impl_Gradient( const Impl_Gradient& rImplGradient ) :
49 : maStartColor( rImplGradient.maStartColor ),
50 1215 : maEndColor( rImplGradient.maEndColor )
51 : {
52 1215 : mnRefCount = 1;
53 1215 : meStyle = rImplGradient.meStyle;
54 1215 : mnAngle = rImplGradient.mnAngle;
55 1215 : mnBorder = rImplGradient.mnBorder;
56 1215 : mnOfsX = rImplGradient.mnOfsX;
57 1215 : mnOfsY = rImplGradient.mnOfsY;
58 1215 : mnIntensityStart = rImplGradient.mnIntensityStart;
59 1215 : mnIntensityEnd = rImplGradient.mnIntensityEnd;
60 1215 : mnStepCount = rImplGradient.mnStepCount;
61 1215 : }
62 :
63 : // -----------------------------------------------------------------------
64 :
65 14699 : void Gradient::MakeUnique()
66 : {
67 : // Falls noch andere Referenzen bestehen, dann kopieren
68 14699 : if ( mpImplGradient->mnRefCount != 1 )
69 : {
70 1215 : if( mpImplGradient->mnRefCount )
71 1215 : mpImplGradient->mnRefCount--;
72 :
73 1215 : mpImplGradient = new Impl_Gradient( *mpImplGradient );
74 : }
75 14699 : }
76 :
77 : // -----------------------------------------------------------------------
78 :
79 3371 : Gradient::Gradient()
80 : {
81 : DBG_CTOR( Gradient, NULL );
82 :
83 3371 : mpImplGradient = new Impl_Gradient;
84 3371 : }
85 :
86 : // -----------------------------------------------------------------------
87 :
88 4009 : Gradient::Gradient( const Gradient& rGradient )
89 : {
90 : DBG_CTOR( Gradient, NULL );
91 : DBG_CHKOBJ( &rGradient, Gradient, NULL );
92 :
93 : // Instance Daten uebernehmen und Referenzcounter erhoehen
94 4009 : mpImplGradient = rGradient.mpImplGradient;
95 4009 : mpImplGradient->mnRefCount++;
96 4009 : }
97 :
98 : // -----------------------------------------------------------------------
99 :
100 35 : Gradient::Gradient( GradientStyle eStyle,
101 : const Color& rStartColor, const Color& rEndColor )
102 : {
103 : DBG_CTOR( Gradient, NULL );
104 :
105 35 : mpImplGradient = new Impl_Gradient;
106 35 : mpImplGradient->meStyle = eStyle;
107 35 : mpImplGradient->maStartColor = rStartColor;
108 35 : mpImplGradient->maEndColor = rEndColor;
109 35 : }
110 :
111 : // -----------------------------------------------------------------------
112 :
113 5798 : Gradient::~Gradient()
114 : {
115 : DBG_DTOR( Gradient, NULL );
116 :
117 : // Wenn es die letzte Referenz ist, loeschen,
118 : // sonst Referenzcounter decrementieren
119 5798 : if ( mpImplGradient->mnRefCount == 1 )
120 3004 : delete mpImplGradient;
121 : else
122 2794 : mpImplGradient->mnRefCount--;
123 5798 : }
124 :
125 : // -----------------------------------------------------------------------
126 :
127 3371 : void Gradient::SetStyle( GradientStyle eStyle )
128 : {
129 : DBG_CHKTHIS( Gradient, NULL );
130 :
131 3371 : MakeUnique();
132 3371 : mpImplGradient->meStyle = eStyle;
133 3371 : }
134 :
135 : // -----------------------------------------------------------------------
136 :
137 3371 : void Gradient::SetStartColor( const Color& rColor )
138 : {
139 : DBG_CHKTHIS( Gradient, NULL );
140 :
141 3371 : MakeUnique();
142 3371 : mpImplGradient->maStartColor = rColor;
143 3371 : }
144 :
145 : // -----------------------------------------------------------------------
146 :
147 3371 : void Gradient::SetEndColor( const Color& rColor )
148 : {
149 : DBG_CHKTHIS( Gradient, NULL );
150 :
151 3371 : MakeUnique();
152 3371 : mpImplGradient->maEndColor = rColor;
153 3371 : }
154 :
155 : // -----------------------------------------------------------------------
156 :
157 3371 : void Gradient::SetAngle( sal_uInt16 nAngle )
158 : {
159 : DBG_CHKTHIS( Gradient, NULL );
160 :
161 3371 : MakeUnique();
162 3371 : mpImplGradient->mnAngle = nAngle;
163 3371 : }
164 :
165 : // -----------------------------------------------------------------------
166 :
167 0 : void Gradient::SetBorder( sal_uInt16 nBorder )
168 : {
169 : DBG_CHKTHIS( Gradient, NULL );
170 :
171 0 : MakeUnique();
172 0 : mpImplGradient->mnBorder = nBorder;
173 0 : }
174 :
175 : // -----------------------------------------------------------------------
176 :
177 0 : void Gradient::SetOfsX( sal_uInt16 nOfsX )
178 : {
179 : DBG_CHKTHIS( Gradient, NULL );
180 :
181 0 : MakeUnique();
182 0 : mpImplGradient->mnOfsX = nOfsX;
183 0 : }
184 :
185 : // -----------------------------------------------------------------------
186 :
187 0 : void Gradient::SetOfsY( sal_uInt16 nOfsY )
188 : {
189 : DBG_CHKTHIS( Gradient, NULL );
190 :
191 0 : MakeUnique();
192 0 : mpImplGradient->mnOfsY = nOfsY;
193 0 : }
194 :
195 : // -----------------------------------------------------------------------
196 :
197 0 : void Gradient::SetStartIntensity( sal_uInt16 nIntens )
198 : {
199 : DBG_CHKTHIS( Gradient, NULL );
200 :
201 0 : MakeUnique();
202 0 : mpImplGradient->mnIntensityStart = nIntens;
203 0 : }
204 :
205 : // -----------------------------------------------------------------------
206 :
207 0 : void Gradient::SetEndIntensity( sal_uInt16 nIntens )
208 : {
209 : DBG_CHKTHIS( Gradient, NULL );
210 :
211 0 : MakeUnique();
212 0 : mpImplGradient->mnIntensityEnd = nIntens;
213 0 : }
214 :
215 : // -----------------------------------------------------------------------
216 :
217 1215 : void Gradient::SetSteps( sal_uInt16 nSteps )
218 : {
219 : DBG_CHKTHIS( Gradient, NULL );
220 :
221 1215 : MakeUnique();
222 1215 : mpImplGradient->mnStepCount = nSteps;
223 1215 : }
224 :
225 : // -----------------------------------------------------------------------
226 :
227 1215 : void Gradient::GetBoundRect( const Rectangle& rRect, Rectangle& rBoundRect, Point& rCenter ) const
228 : {
229 1215 : Rectangle aRect( rRect );
230 1215 : sal_uInt16 nAngle = GetAngle() % 3600;
231 :
232 1215 : if( GetStyle() == GradientStyle_LINEAR || GetStyle() == GradientStyle_AXIAL )
233 : {
234 1215 : aRect.Left()--;
235 1215 : aRect.Top()--;
236 1215 : aRect.Right()++;
237 1215 : aRect.Bottom()++;
238 :
239 1215 : const double fAngle = nAngle * F_PI1800;
240 1215 : const double fWidth = aRect.GetWidth();
241 1215 : const double fHeight = aRect.GetHeight();
242 1215 : double fDX = fWidth * fabs( cos( fAngle ) ) + fHeight * fabs( sin( fAngle ) );
243 1215 : double fDY = fHeight * fabs( cos( fAngle ) ) + fWidth * fabs( sin( fAngle ) );
244 :
245 1215 : fDX = ( fDX - fWidth ) * 0.5 + 0.5;
246 1215 : fDY = ( fDY - fHeight ) * 0.5 + 0.5;
247 :
248 1215 : aRect.Left() -= (long) fDX;
249 1215 : aRect.Right() += (long) fDX;
250 1215 : aRect.Top() -= (long) fDY;
251 1215 : aRect.Bottom() += (long) fDY;
252 :
253 1215 : rBoundRect = aRect;
254 1215 : rCenter = rRect.Center();
255 : }
256 : else
257 : {
258 0 : if( GetStyle() == GradientStyle_SQUARE || GetStyle() == GradientStyle_RECT )
259 : {
260 0 : const double fAngle = nAngle * F_PI1800;
261 0 : const double fWidth = aRect.GetWidth();
262 0 : const double fHeight = aRect.GetHeight();
263 0 : double fDX = fWidth * fabs( cos( fAngle ) ) + fHeight * fabs( sin( fAngle ) );
264 0 : double fDY = fHeight * fabs( cos( fAngle ) ) + fWidth * fabs( sin( fAngle ) );
265 :
266 0 : fDX = ( fDX - fWidth ) * 0.5 + 0.5;
267 0 : fDY = ( fDY - fHeight ) * 0.5 + 0.5;
268 :
269 0 : aRect.Left() -= (long) fDX;
270 0 : aRect.Right() += (long) fDX;
271 0 : aRect.Top() -= (long) fDY;
272 0 : aRect.Bottom() += (long) fDY;
273 : }
274 :
275 0 : Size aSize( aRect.GetSize() );
276 :
277 0 : if( GetStyle() == GradientStyle_RADIAL )
278 : {
279 : // Radien-Berechnung fuer Kreis
280 0 : aSize.Width() = (long)(0.5 + sqrt((double)aSize.Width()*(double)aSize.Width() + (double)aSize.Height()*(double)aSize.Height()));
281 0 : aSize.Height() = aSize.Width();
282 : }
283 0 : else if( GetStyle() == GradientStyle_ELLIPTICAL )
284 : {
285 : // Radien-Berechnung fuer Ellipse
286 0 : aSize.Width() = (long)( 0.5 + (double) aSize.Width() * 1.4142 );
287 0 : aSize.Height() = (long)( 0.5 + (double) aSize.Height() * 1.4142 );
288 : }
289 :
290 : // neue Mittelpunkte berechnen
291 0 : long nZWidth = aRect.GetWidth() * (long) GetOfsX() / 100;
292 0 : long nZHeight = aRect.GetHeight() * (long) GetOfsY() / 100;
293 0 : long nBorderX = (long) GetBorder() * aSize.Width() / 100;
294 0 : long nBorderY = (long) GetBorder() * aSize.Height() / 100;
295 0 : rCenter = Point( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
296 :
297 : // Rand beruecksichtigen
298 0 : aSize.Width() -= nBorderX;
299 0 : aSize.Height() -= nBorderY;
300 :
301 : // Ausgaberechteck neu setzen
302 0 : aRect.Left() = rCenter.X() - ( aSize.Width() >> 1 );
303 0 : aRect.Top() = rCenter.Y() - ( aSize.Height() >> 1 );
304 :
305 0 : aRect.SetSize( aSize );
306 0 : rBoundRect = aRect;
307 : }
308 1215 : }
309 :
310 : // -----------------------------------------------------------------------
311 :
312 0 : Gradient& Gradient::operator=( const Gradient& rGradient )
313 : {
314 : DBG_CHKTHIS( Gradient, NULL );
315 : DBG_CHKOBJ( &rGradient, Gradient, NULL );
316 :
317 : // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
318 0 : rGradient.mpImplGradient->mnRefCount++;
319 :
320 : // Wenn es die letzte Referenz ist, loeschen,
321 : // sonst Referenzcounter decrementieren
322 0 : if ( mpImplGradient->mnRefCount == 1 )
323 0 : delete mpImplGradient;
324 : else
325 0 : mpImplGradient->mnRefCount--;
326 0 : mpImplGradient = rGradient.mpImplGradient;
327 :
328 0 : return *this;
329 : }
330 :
331 : // -----------------------------------------------------------------------
332 :
333 0 : sal_Bool Gradient::operator==( const Gradient& rGradient ) const
334 : {
335 : DBG_CHKTHIS( Gradient, NULL );
336 : DBG_CHKOBJ( &rGradient, Gradient, NULL );
337 :
338 0 : if ( mpImplGradient == rGradient.mpImplGradient )
339 0 : return sal_True;
340 :
341 0 : if ( (mpImplGradient->meStyle == rGradient.mpImplGradient->meStyle) ||
342 : (mpImplGradient->mnAngle == rGradient.mpImplGradient->mnAngle) ||
343 : (mpImplGradient->mnBorder == rGradient.mpImplGradient->mnBorder) ||
344 : (mpImplGradient->mnOfsX == rGradient.mpImplGradient->mnOfsX) ||
345 : (mpImplGradient->mnOfsY == rGradient.mpImplGradient->mnOfsY) ||
346 : (mpImplGradient->mnStepCount == rGradient.mpImplGradient->mnStepCount) ||
347 : (mpImplGradient->mnIntensityStart == rGradient.mpImplGradient->mnIntensityStart) ||
348 : (mpImplGradient->mnIntensityEnd == rGradient.mpImplGradient->mnIntensityEnd) ||
349 0 : (mpImplGradient->maStartColor == rGradient.mpImplGradient->maStartColor) ||
350 0 : (mpImplGradient->maEndColor == rGradient.mpImplGradient->maEndColor) )
351 0 : return sal_True;
352 : else
353 0 : return sal_False;
354 : }
355 :
356 0 : SvStream& operator>>( SvStream& rIStm, Impl_Gradient& rImpl_Gradient )
357 : {
358 0 : VersionCompat aCompat( rIStm, STREAM_READ );
359 : sal_uInt16 nTmp16;
360 :
361 0 : rIStm >> nTmp16; rImpl_Gradient.meStyle = (GradientStyle) nTmp16;
362 :
363 0 : rIStm >> rImpl_Gradient.maStartColor >>
364 0 : rImpl_Gradient.maEndColor >>
365 0 : rImpl_Gradient.mnAngle >>
366 0 : rImpl_Gradient.mnBorder >>
367 0 : rImpl_Gradient.mnOfsX >>
368 0 : rImpl_Gradient.mnOfsY >>
369 0 : rImpl_Gradient.mnIntensityStart >>
370 0 : rImpl_Gradient.mnIntensityEnd >>
371 0 : rImpl_Gradient.mnStepCount;
372 :
373 0 : return rIStm;
374 : }
375 :
376 : // -----------------------------------------------------------------------
377 :
378 0 : SvStream& operator<<( SvStream& rOStm, const Impl_Gradient& rImpl_Gradient )
379 : {
380 0 : VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );
381 :
382 0 : rOStm << (sal_uInt16) rImpl_Gradient.meStyle <<
383 0 : rImpl_Gradient.maStartColor <<
384 0 : rImpl_Gradient.maEndColor <<
385 0 : rImpl_Gradient.mnAngle <<
386 0 : rImpl_Gradient.mnBorder <<
387 0 : rImpl_Gradient.mnOfsX <<
388 0 : rImpl_Gradient.mnOfsY <<
389 0 : rImpl_Gradient.mnIntensityStart <<
390 0 : rImpl_Gradient.mnIntensityEnd <<
391 0 : rImpl_Gradient.mnStepCount;
392 :
393 0 : return rOStm;
394 : }
395 :
396 : // -----------------------------------------------------------------------
397 :
398 0 : SvStream& operator>>( SvStream& rIStm, Gradient& rGradient )
399 : {
400 0 : rGradient.MakeUnique();
401 0 : return( rIStm >> *rGradient.mpImplGradient );
402 : }
403 :
404 : // -----------------------------------------------------------------------
405 :
406 0 : SvStream& operator<<( SvStream& rOStm, const Gradient& rGradient )
407 : {
408 0 : return( rOStm << *rGradient.mpImplGradient );
409 : }
410 :
411 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|