LibreOffice Module vcl (master)  1
gdi/gradient.cxx
Go to the documentation of this file.
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/gen.hxx>
24 #include <vcl/gradient.hxx>
25 
27  maStartColor( COL_BLACK ),
28  maEndColor( COL_WHITE )
29 {
30  meStyle = GradientStyle::Linear;
31  mnAngle = 0;
32  mnBorder = 0;
33  mnOfsX = 50;
34  mnOfsY = 50;
35  mnIntensityStart = 100;
36  mnIntensityEnd = 100;
37  mnStepCount = 0;
38 }
39 
41  maStartColor( rImplGradient.maStartColor ),
42  maEndColor( rImplGradient.maEndColor )
43 {
44  meStyle = rImplGradient.meStyle;
45  mnAngle = rImplGradient.mnAngle;
46  mnBorder = rImplGradient.mnBorder;
47  mnOfsX = rImplGradient.mnOfsX;
48  mnOfsY = rImplGradient.mnOfsY;
49  mnIntensityStart = rImplGradient.mnIntensityStart;
50  mnIntensityEnd = rImplGradient.mnIntensityEnd;
51  mnStepCount = rImplGradient.mnStepCount;
52 }
53 
54 bool Impl_Gradient::operator==( const Impl_Gradient& rImpl_Gradient ) const
55 {
56  return (meStyle == rImpl_Gradient.meStyle) &&
57  (mnAngle == rImpl_Gradient.mnAngle) &&
58  (mnBorder == rImpl_Gradient.mnBorder) &&
59  (mnOfsX == rImpl_Gradient.mnOfsX) &&
60  (mnOfsY == rImpl_Gradient.mnOfsY) &&
61  (mnStepCount == rImpl_Gradient.mnStepCount) &&
62  (mnIntensityStart == rImpl_Gradient.mnIntensityStart) &&
63  (mnIntensityEnd == rImpl_Gradient.mnIntensityEnd) &&
64  (maStartColor == rImpl_Gradient.maStartColor) &&
65  (maEndColor == rImpl_Gradient.maEndColor);
66 }
67 
68 Gradient::Gradient() = default;
69 
70 Gradient::Gradient( const Gradient& ) = default;
71 
72 Gradient::Gradient( Gradient&& ) = default;
73 
75  const Color& rStartColor, const Color& rEndColor ) :
76  mpImplGradient()
77 {
78  mpImplGradient->meStyle = eStyle;
79  mpImplGradient->maStartColor = rStartColor;
80  mpImplGradient->maEndColor = rEndColor;
81 }
82 
83 Gradient::~Gradient() = default;
84 
86 {
87  mpImplGradient->meStyle = eStyle;
88 }
89 
90 void Gradient::SetStartColor( const Color& rColor )
91 {
92  mpImplGradient->maStartColor = rColor;
93 }
94 
95 void Gradient::SetEndColor( const Color& rColor )
96 {
97  mpImplGradient->maEndColor = rColor;
98 }
99 
100 void Gradient::SetAngle( sal_uInt16 nAngle )
101 {
102  mpImplGradient->mnAngle = nAngle;
103 }
104 
105 void Gradient::SetBorder( sal_uInt16 nBorder )
106 {
107  mpImplGradient->mnBorder = nBorder;
108 }
109 
110 void Gradient::SetOfsX( sal_uInt16 nOfsX )
111 {
112  mpImplGradient->mnOfsX = nOfsX;
113 }
114 
115 void Gradient::SetOfsY( sal_uInt16 nOfsY )
116 {
117  mpImplGradient->mnOfsY = nOfsY;
118 }
119 
120 void Gradient::SetStartIntensity( sal_uInt16 nIntens )
121 {
122  mpImplGradient->mnIntensityStart = nIntens;
123 }
124 
125 void Gradient::SetEndIntensity( sal_uInt16 nIntens )
126 {
127  mpImplGradient->mnIntensityEnd = nIntens;
128 }
129 
130 void Gradient::SetSteps( sal_uInt16 nSteps )
131 {
132  mpImplGradient->mnStepCount = nSteps;
133 }
134 
135 void Gradient::GetBoundRect( const tools::Rectangle& rRect, tools::Rectangle& rBoundRect, Point& rCenter ) const
136 {
137  tools::Rectangle aRect( rRect );
138  sal_uInt16 nAngle = GetAngle() % 3600;
139 
140  if( GetStyle() == GradientStyle::Linear || GetStyle() == GradientStyle::Axial )
141  {
142  const double fAngle = nAngle * F_PI1800;
143  const double fWidth = aRect.GetWidth();
144  const double fHeight = aRect.GetHeight();
145  double fDX = fWidth * fabs( cos( fAngle ) ) +
146  fHeight * fabs( sin( fAngle ) );
147  double fDY = fHeight * fabs( cos( fAngle ) ) +
148  fWidth * fabs( sin( fAngle ) );
149  fDX = (fDX - fWidth) * 0.5 + 0.5;
150  fDY = (fDY - fHeight) * 0.5 + 0.5;
151  aRect.AdjustLeft( -static_cast<long>(fDX) );
152  aRect.AdjustRight(static_cast<long>(fDX) );
153  aRect.AdjustTop( -static_cast<long>(fDY) );
154  aRect.AdjustBottom(static_cast<long>(fDY) );
155 
156  rBoundRect = aRect;
157  rCenter = rRect.Center();
158  }
159  else
160  {
161  if( GetStyle() == GradientStyle::Square || GetStyle() == GradientStyle::Rect )
162  {
163  const double fAngle = nAngle * F_PI1800;
164  const double fWidth = aRect.GetWidth();
165  const double fHeight = aRect.GetHeight();
166  double fDX = fWidth * fabs( cos( fAngle ) ) + fHeight * fabs( sin( fAngle ) );
167  double fDY = fHeight * fabs( cos( fAngle ) ) + fWidth * fabs( sin( fAngle ) );
168 
169  fDX = ( fDX - fWidth ) * 0.5 + 0.5;
170  fDY = ( fDY - fHeight ) * 0.5 + 0.5;
171 
172  aRect.AdjustLeft( -static_cast<long>(fDX) );
173  aRect.AdjustRight(static_cast<long>(fDX) );
174  aRect.AdjustTop( -static_cast<long>(fDY) );
175  aRect.AdjustBottom(static_cast<long>(fDY) );
176  }
177 
178  Size aSize( aRect.GetSize() );
179 
180  if( GetStyle() == GradientStyle::Radial )
181  {
182  // Calculation of radii for circle
183  aSize.setWidth( static_cast<long>(0.5 + sqrt(static_cast<double>(aSize.Width())*static_cast<double>(aSize.Width()) + static_cast<double>(aSize.Height())*static_cast<double>(aSize.Height()))) );
184  aSize.setHeight( aSize.Width() );
185  }
186  else if( GetStyle() == GradientStyle::Elliptical )
187  {
188  // Calculation of radii for ellipse
189  aSize.setWidth( static_cast<long>( 0.5 + static_cast<double>(aSize.Width()) * 1.4142 ) );
190  aSize.setHeight( static_cast<long>( 0.5 + static_cast<double>(aSize.Height()) * 1.4142 ) );
191  }
192 
193  // Calculate new centers
194  long nZWidth = aRect.GetWidth() * static_cast<long>(GetOfsX()) / 100;
195  long nZHeight = aRect.GetHeight() * static_cast<long>(GetOfsY()) / 100;
196  long nBorderX = static_cast<long>(GetBorder()) * aSize.Width() / 100;
197  long nBorderY = static_cast<long>(GetBorder()) * aSize.Height() / 100;
198  rCenter = Point( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
199 
200  // Respect borders
201  aSize.AdjustWidth( -nBorderX );
202  aSize.AdjustHeight( -nBorderY );
203 
204  // Recalculate output rectangle
205  aRect.SetLeft( rCenter.X() - ( aSize.Width() >> 1 ) );
206  aRect.SetTop( rCenter.Y() - ( aSize.Height() >> 1 ) );
207 
208  aRect.SetSize( aSize );
209  rBoundRect = aRect;
210  }
211 }
212 
213 Gradient& Gradient::operator=( const Gradient& ) = default;
214 
215 Gradient& Gradient::operator=( Gradient&& ) = default;
216 
217 bool Gradient::operator==( const Gradient& rGradient ) const
218 {
219  return mpImplGradient == rGradient.mpImplGradient;
220 }
221 
222 SvStream& ReadGradient( SvStream& rIStm, Gradient& rGradient )
223 {
224  VersionCompat aCompat( rIStm, StreamMode::READ );
225  sal_uInt16 nTmp16;
226 
227  rIStm.ReadUInt16( nTmp16 ); rGradient.mpImplGradient->meStyle = static_cast<GradientStyle>(nTmp16);
228 
229  tools::GenericTypeSerializer aSerializer(rIStm);
230  aSerializer.readColor(rGradient.mpImplGradient->maStartColor);
231  aSerializer.readColor(rGradient.mpImplGradient->maEndColor);
232  rIStm.ReadUInt16( rGradient.mpImplGradient->mnAngle )
233  .ReadUInt16( rGradient.mpImplGradient->mnBorder )
234  .ReadUInt16( rGradient.mpImplGradient->mnOfsX )
235  .ReadUInt16( rGradient.mpImplGradient->mnOfsY )
238  .ReadUInt16( rGradient.mpImplGradient->mnStepCount );
239 
240  return rIStm;
241 }
242 
243 SvStream& WriteGradient( SvStream& rOStm, const Gradient& rGradient )
244 {
245  VersionCompat aCompat( rOStm, StreamMode::WRITE, 1 );
246 
247  rOStm.WriteUInt16( static_cast<sal_uInt16>(rGradient.mpImplGradient->meStyle) );
248  tools::GenericTypeSerializer aSerializer(rOStm);
249  aSerializer.writeColor(rGradient.mpImplGradient->maStartColor);
250  aSerializer.writeColor(rGradient.mpImplGradient->maEndColor);
251  rOStm.WriteUInt16( rGradient.mpImplGradient->mnAngle )
252  .WriteUInt16( rGradient.mpImplGradient->mnBorder )
253  .WriteUInt16( rGradient.mpImplGradient->mnOfsX )
254  .WriteUInt16( rGradient.mpImplGradient->mnOfsY )
257  .WriteUInt16( rGradient.mpImplGradient->mnStepCount );
258 
259  return rOStm;
260 }
261 
262 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetEndColor(const Color &rColor)
SvStream & ReadGradient(SvStream &rIStm, Gradient &rGradient)
long GetWidth() const
GradientStyle GetStyle() const
Definition: gradient.hxx:74
long GetHeight() const
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
sal_uInt16 GetOfsY() const
Definition: gradient.hxx:89
long AdjustLeft(long nHorzMoveDelta)
#define F_PI1800
sal_uInt16 GetBorder() const
Definition: gradient.hxx:85
void SetBorder(sal_uInt16 nBorder)
void SetEndIntensity(sal_uInt16 nIntens)
long AdjustBottom(long nVertMoveDelta)
sal_uInt16 mnOfsY
Definition: gradient.hxx:47
SvStream & WriteGradient(SvStream &rOStm, const Gradient &rGradient)
Gradient & operator=(const Gradient &rGradient)
void SetSteps(sal_uInt16 nSteps)
bool operator==(const Impl_Gradient &rImpl_Gradient) const
void SetOfsY(sal_uInt16 nOfsY)
void SetStartColor(const Color &rColor)
Color maStartColor
Definition: gradient.hxx:42
GradientStyle
long Top() const
GradientStyle meStyle
Definition: gradient.hxx:41
void GetBoundRect(const tools::Rectangle &rRect, tools::Rectangle &rBoundRect, Point &rCenter) const
void SetTop(long v)
sal_uInt16 GetAngle() const
Definition: gradient.hxx:82
Color maEndColor
Definition: gradient.hxx:43
void SetSize(const Size &rSize)
sal_uInt16 GetOfsX() const
Definition: gradient.hxx:87
sal_uInt16 mnBorder
Definition: gradient.hxx:45
sal_uInt16 mnStepCount
Definition: gradient.hxx:50
bool operator==(const Gradient &rGradient) const
void SetOfsX(sal_uInt16 nOfsX)
long X() const
Size GetSize() const
sal_uInt16 mnIntensityStart
Definition: gradient.hxx:48
::o3tl::cow_wrapper< Impl_Gradient > mpImplGradient
Definition: gradient.hxx:62
long AdjustRight(long nHorzMoveDelta)
void SetAngle(sal_uInt16 nAngle)
long AdjustTop(long nVertMoveDelta)
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
long Left() const
sal_uInt16 mnAngle
Definition: gradient.hxx:44
void SetLeft(long v)
void writeColor(const Color &rColor)
void SetStyle(GradientStyle eStyle)
void setWidth(long nWidth)
sal_uInt16 mnOfsX
Definition: gradient.hxx:46
sal_uInt16 mnIntensityEnd
Definition: gradient.hxx:49
void SetStartIntensity(sal_uInt16 nIntens)
Point Center() const
long Y() const
void readColor(Color &rColor)