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/gen.hxx>
21 #include <vcl/gradient.hxx>
22 
24 {
25 public:
30  sal_uInt16 mnBorder;
31  sal_uInt16 mnOfsX;
32  sal_uInt16 mnOfsY;
33  sal_uInt16 mnIntensityStart;
34  sal_uInt16 mnIntensityEnd;
35  sal_uInt16 mnStepCount;
36 
37  Impl()
38  : meStyle (GradientStyle::Linear)
39  , maStartColor(COL_BLACK)
40  , maEndColor(COL_WHITE)
41  , mnAngle(0)
42  , mnBorder(0)
43  , mnOfsX(50)
44  , mnOfsY(50)
45  , mnIntensityStart(100)
46  , mnIntensityEnd(100)
47  , mnStepCount(0)
48  {
49  }
50 
51  Impl(const Impl& rImplGradient)
52  : meStyle (rImplGradient.meStyle)
53  , maStartColor(rImplGradient.maStartColor)
54  , maEndColor(rImplGradient.maEndColor)
55  , mnAngle(rImplGradient.mnAngle)
56  , mnBorder(rImplGradient.mnBorder)
57  , mnOfsX(rImplGradient.mnOfsX)
58  , mnOfsY(rImplGradient.mnOfsY)
59  , mnIntensityStart(rImplGradient.mnIntensityStart)
60  , mnIntensityEnd(rImplGradient.mnIntensityEnd)
61  , mnStepCount(rImplGradient.mnStepCount)
62  {
63  }
64 
65  bool operator==(const Impl& rImpl_Gradient) const
66  {
67  return (meStyle == rImpl_Gradient.meStyle)
68  && (mnAngle == rImpl_Gradient.mnAngle)
69  && (mnBorder == rImpl_Gradient.mnBorder)
70  && (mnOfsX == rImpl_Gradient.mnOfsX)
71  && (mnOfsY == rImpl_Gradient.mnOfsY)
72  && (mnStepCount == rImpl_Gradient.mnStepCount)
73  && (mnIntensityStart == rImpl_Gradient.mnIntensityStart)
74  && (mnIntensityEnd == rImpl_Gradient.mnIntensityEnd)
75  && (maStartColor == rImpl_Gradient.maStartColor)
76  && (maEndColor == rImpl_Gradient.maEndColor);
77  }
78 };
79 
80 Gradient::Gradient() = default;
81 
82 Gradient::Gradient( const Gradient& ) = default;
83 
84 Gradient::Gradient( Gradient&& ) = default;
85 
87  const Color& rStartColor, const Color& rEndColor )
88 {
89  mpImplGradient->meStyle = eStyle;
90  mpImplGradient->maStartColor = rStartColor;
91  mpImplGradient->maEndColor = rEndColor;
92 }
93 
94 Gradient::~Gradient() = default;
95 
96 
98 {
99  return mpImplGradient->meStyle;
100 }
101 
103 {
104  mpImplGradient->meStyle = eStyle;
105 }
106 
108 {
109  return mpImplGradient->maStartColor;
110 }
111 
112 void Gradient::SetStartColor( const Color& rColor )
113 {
114  mpImplGradient->maStartColor = rColor;
115 }
116 
118 {
119  return mpImplGradient->maEndColor;
120 }
121 
122 void Gradient::SetEndColor( const Color& rColor )
123 {
124  mpImplGradient->maEndColor = rColor;
125 }
126 
128 {
129  return mpImplGradient->mnAngle;
130 }
131 
133 {
134  mpImplGradient->mnAngle = nAngle;
135 }
136 
137 sal_uInt16 Gradient::GetBorder() const
138 {
139  return mpImplGradient->mnBorder;
140 }
141 
142 void Gradient::SetBorder( sal_uInt16 nBorder )
143 {
144  mpImplGradient->mnBorder = nBorder;
145 }
146 
147 sal_uInt16 Gradient::GetOfsX() const
148 {
149  return mpImplGradient->mnOfsX;
150 }
151 
152 void Gradient::SetOfsX( sal_uInt16 nOfsX )
153 {
154  mpImplGradient->mnOfsX = nOfsX;
155 }
156 
157 sal_uInt16 Gradient::GetOfsY() const
158 {
159  return mpImplGradient->mnOfsY;
160 }
161 
162 void Gradient::SetOfsY( sal_uInt16 nOfsY )
163 {
164  mpImplGradient->mnOfsY = nOfsY;
165 }
166 
167 sal_uInt16 Gradient::GetStartIntensity() const
168 {
169  return mpImplGradient->mnIntensityStart;
170 }
171 
172 void Gradient::SetStartIntensity( sal_uInt16 nIntens )
173 {
174  mpImplGradient->mnIntensityStart = nIntens;
175 }
176 
177 sal_uInt16 Gradient::GetEndIntensity() const
178 {
179  return mpImplGradient->mnIntensityEnd;
180 }
181 
182 void Gradient::SetEndIntensity( sal_uInt16 nIntens )
183 {
184  mpImplGradient->mnIntensityEnd = nIntens;
185 }
186 
187 sal_uInt16 Gradient::GetSteps() const
188 {
189  return mpImplGradient->mnStepCount;
190 }
191 
192 void Gradient::SetSteps( sal_uInt16 nSteps )
193 {
194  mpImplGradient->mnStepCount = nSteps;
195 }
196 
197 void Gradient::GetBoundRect( const tools::Rectangle& rRect, tools::Rectangle& rBoundRect, Point& rCenter ) const
198 {
199  tools::Rectangle aRect( rRect );
200  Degree10 nAngle = GetAngle() % 3600_deg10;
201 
202  if( GetStyle() == GradientStyle::Linear || GetStyle() == GradientStyle::Axial )
203  {
204  const double fAngle = nAngle.get() * F_PI1800;
205  const double fWidth = aRect.GetWidth();
206  const double fHeight = aRect.GetHeight();
207  double fDX = fWidth * fabs( cos( fAngle ) ) +
208  fHeight * fabs( sin( fAngle ) );
209  double fDY = fHeight * fabs( cos( fAngle ) ) +
210  fWidth * fabs( sin( fAngle ) );
211  fDX = (fDX - fWidth) * 0.5 + 0.5;
212  fDY = (fDY - fHeight) * 0.5 + 0.5;
213  aRect.AdjustLeft( -static_cast<tools::Long>(fDX) );
214  aRect.AdjustRight(static_cast<tools::Long>(fDX) );
215  aRect.AdjustTop( -static_cast<tools::Long>(fDY) );
216  aRect.AdjustBottom(static_cast<tools::Long>(fDY) );
217 
218  rBoundRect = aRect;
219  rCenter = rRect.Center();
220  }
221  else
222  {
223  if( GetStyle() == GradientStyle::Square || GetStyle() == GradientStyle::Rect )
224  {
225  const double fAngle = nAngle.get() * F_PI1800;
226  const double fWidth = aRect.GetWidth();
227  const double fHeight = aRect.GetHeight();
228  double fDX = fWidth * fabs( cos( fAngle ) ) + fHeight * fabs( sin( fAngle ) );
229  double fDY = fHeight * fabs( cos( fAngle ) ) + fWidth * fabs( sin( fAngle ) );
230 
231  fDX = ( fDX - fWidth ) * 0.5 + 0.5;
232  fDY = ( fDY - fHeight ) * 0.5 + 0.5;
233 
234  aRect.AdjustLeft( -static_cast<tools::Long>(fDX) );
235  aRect.AdjustRight(static_cast<tools::Long>(fDX) );
236  aRect.AdjustTop( -static_cast<tools::Long>(fDY) );
237  aRect.AdjustBottom(static_cast<tools::Long>(fDY) );
238  }
239 
240  Size aSize( aRect.GetSize() );
241 
242  if( GetStyle() == GradientStyle::Radial )
243  {
244  // Calculation of radii for circle
245  aSize.setWidth( static_cast<tools::Long>(0.5 + sqrt(static_cast<double>(aSize.Width())*static_cast<double>(aSize.Width()) + static_cast<double>(aSize.Height())*static_cast<double>(aSize.Height()))) );
246  aSize.setHeight( aSize.Width() );
247  }
248  else if( GetStyle() == GradientStyle::Elliptical )
249  {
250  // Calculation of radii for ellipse
251  aSize.setWidth( static_cast<tools::Long>( 0.5 + static_cast<double>(aSize.Width()) * 1.4142 ) );
252  aSize.setHeight( static_cast<tools::Long>( 0.5 + static_cast<double>(aSize.Height()) * 1.4142 ) );
253  }
254 
255  // Calculate new centers
256  tools::Long nZWidth = aRect.GetWidth() * static_cast<tools::Long>(GetOfsX()) / 100;
257  tools::Long nZHeight = aRect.GetHeight() * static_cast<tools::Long>(GetOfsY()) / 100;
258  tools::Long nBorderX = static_cast<tools::Long>(GetBorder()) * aSize.Width() / 100;
259  tools::Long nBorderY = static_cast<tools::Long>(GetBorder()) * aSize.Height() / 100;
260  rCenter = Point( aRect.Left() + nZWidth, aRect.Top() + nZHeight );
261 
262  // Respect borders
263  aSize.AdjustWidth( -nBorderX );
264  aSize.AdjustHeight( -nBorderY );
265 
266  // Recalculate output rectangle
267  aRect.SetLeft( rCenter.X() - ( aSize.Width() >> 1 ) );
268  aRect.SetTop( rCenter.Y() - ( aSize.Height() >> 1 ) );
269 
270  aRect.SetSize( aSize );
271  rBoundRect = aRect;
272  }
273 }
274 
276 {
277  Color aStartCol(GetStartColor());
278  Color aEndCol(GetEndColor());
279  sal_uInt8 cStartLum = aStartCol.GetLuminance();
280  sal_uInt8 cEndLum = aEndCol.GetLuminance();
281 
282  aStartCol = Color(cStartLum, cStartLum, cStartLum);
283  aEndCol = Color(cEndLum, cEndLum, cEndLum);
284 
285  SetStartColor(aStartCol);
286  SetEndColor(aEndCol);
287 }
288 
289 Gradient& Gradient::operator=( const Gradient& ) = default;
290 
291 Gradient& Gradient::operator=( Gradient&& ) = default;
292 
293 bool Gradient::operator==( const Gradient& rGradient ) const
294 {
295  return mpImplGradient == rGradient.mpImplGradient;
296 }
297 
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetEndColor(const Color &rColor)
GradientStyle GetStyle() const
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
void setWidth(tools::Long nWidth)
constexpr tools::Long Left() const
sal_uInt16 GetOfsY() const
Degree10 mnAngle
long Long
#define F_PI1800
sal_uInt8 GetLuminance() const
sal_uInt16 GetBorder() const
void SetBorder(sal_uInt16 nBorder)
sal_uInt16 mnIntensityEnd
void SetEndIntensity(sal_uInt16 nIntens)
Gradient & operator=(const Gradient &rGradient)
void SetSteps(sal_uInt16 nSteps)
void SetOfsY(sal_uInt16 nOfsY)
void SetStartColor(const Color &rColor)
constexpr tools::Long GetWidth() const
GradientStyle
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
constexpr void SetLeft(tools::Long v)
UNDERLYING_TYPE get() const
void GetBoundRect(const tools::Rectangle &rRect, tools::Rectangle &rBoundRect, Point &rCenter) const
void SetSize(const Size &rSize)
sal_uInt16 GetOfsX() const
Impl(const Impl &rImplGradient)
constexpr tools::Long Top() const
sal_uInt16 GetEndIntensity() const
sal_uInt16 mnOfsX
sal_uInt16 mnStepCount
bool operator==(const Gradient &rGradient) const
void SetOfsX(sal_uInt16 nOfsX)
constexpr void SetTop(tools::Long v)
constexpr Point Center() const
sal_uInt16 GetSteps() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
const Color & GetStartColor() const
void SetAngle(Degree10 nAngle)
constexpr Size GetSize() const
Degree10 GetAngle() const
void MakeGrayscale()
unsigned char sal_uInt8
::o3tl::cow_wrapper< Impl > mpImplGradient
Definition: gradient.hxx:40
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
const Color & GetEndColor() const
GradientStyle meStyle
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
sal_uInt16 mnIntensityStart
sal_uInt16 mnOfsY
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void SetStyle(GradientStyle eStyle)
sal_uInt16 GetStartIntensity() const
bool operator==(const Impl &rImpl_Gradient) const
sal_uInt16 mnBorder
void SetStartIntensity(sal_uInt16 nIntens)
constexpr tools::Long GetHeight() const