fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / color.cxx
blob9bb40d6fd4ba2157c14bd291106bbfe1b5448a40
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 .
21 #include <hslcolor.hxx>
22 #include <rgbcolor.hxx>
24 #include <basegfx/numeric/ftools.hxx>
26 #include <cmath>
27 #include <algorithm>
30 namespace slideshow
32 namespace internal
34 namespace
36 // helper functions
37 // ================
39 double getMagic( double nLuminance, double nSaturation )
41 if( nLuminance <= 0.5 )
42 return nLuminance*(1.0 + nSaturation);
43 else
44 return nLuminance + nSaturation - nLuminance*nSaturation;
47 HSLColor::HSLTriple rgb2hsl( double nRed, double nGreen, double nBlue )
49 // r,g,b in [0,1], h in [0,360] and s,l in [0,1]
50 HSLColor::HSLTriple aRes;
52 const double nMax( ::std::max(nRed,::std::max(nGreen, nBlue)) );
53 const double nMin( ::std::min(nRed,::std::min(nGreen, nBlue)) );
55 const double nDelta( nMax - nMin );
57 aRes.mnLuminance = (nMax + nMin) / 2.0;
59 if( ::basegfx::fTools::equalZero( nDelta ) )
61 aRes.mnSaturation = 0.0;
63 // hue undefined (achromatic case)
64 aRes.mnHue = 0.0;
66 else
68 aRes.mnSaturation = aRes.mnLuminance > 0.5 ?
69 nDelta/(2.0-nMax-nMin) :
70 nDelta/(nMax + nMin);
72 if( nRed == nMax )
73 aRes.mnHue = (nGreen - nBlue)/nDelta;
74 else if( nGreen == nMax )
75 aRes.mnHue = 2.0 + (nBlue - nRed)/nDelta;
76 else if( nBlue == nMax )
77 aRes.mnHue = 4.0 + (nRed - nGreen)/nDelta;
79 aRes.mnHue *= 60.0;
81 if( aRes.mnHue < 0.0 )
82 aRes.mnHue += 360.0;
85 return aRes;
88 double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
90 // clamp hue to [0,360]
91 nHue = fmod( nHue, 360.0 );
93 // cope with wrap-arounds
94 if( nHue < 0.0 )
95 nHue += 360.0;
97 if( nHue < 60.0 )
98 return nValue1 + (nValue2 - nValue1)*nHue/60.0;
99 else if( nHue < 180.0 )
100 return nValue2;
101 else if( nHue < 240.0 )
102 return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
103 else
104 return nValue1;
107 RGBColor::RGBTriple hsl2rgb( double nHue, double nSaturation, double nLuminance )
109 if( ::basegfx::fTools::equalZero( nSaturation ) )
110 return RGBColor::RGBTriple(0.0, 0.0, nLuminance );
112 const double nVal1( getMagic(nLuminance, nSaturation) );
113 const double nVal2( 2.0*nLuminance - nVal1 );
115 RGBColor::RGBTriple aRes;
117 aRes.mnRed = hsl2rgbHelper( nVal2,
118 nVal1,
119 nHue + 120.0 );
120 aRes.mnGreen = hsl2rgbHelper( nVal2,
121 nVal1,
122 nHue );
123 aRes.mnBlue = hsl2rgbHelper( nVal2,
124 nVal1,
125 nHue - 120.0 );
127 return aRes;
130 /// Truncate range of value to [0,1]
131 double truncateRangeStd( double nVal )
133 return ::std::max( 0.0,
134 ::std::min( 1.0,
135 nVal ) );
138 /// Truncate range of value to [0,360]
139 double truncateRangeHue( double nVal )
141 return ::std::max( 0.0,
142 ::std::min( 360.0,
143 nVal ) );
146 /// convert RGB color to sal_uInt8, truncate range appropriately before
147 sal_uInt8 colorToInt( double nCol )
149 return static_cast< sal_uInt8 >(
150 ::basegfx::fround( truncateRangeStd( nCol ) * 255.0 ) );
156 // HSLColor
159 HSLColor::HSLTriple::HSLTriple() :
160 mnHue(),
161 mnSaturation(),
162 mnLuminance()
166 HSLColor::HSLTriple::HSLTriple( double nHue, double nSaturation, double nLuminance ) :
167 mnHue( nHue ),
168 mnSaturation( nSaturation ),
169 mnLuminance( nLuminance )
173 HSLColor::HSLColor() :
174 maHSLTriple( 0.0, 0.0, 0.0 ),
175 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
176 maHSLTriple.mnSaturation ) )
180 HSLColor::HSLColor( double nHue, double nSaturation, double nLuminance ) :
181 maHSLTriple( nHue, nSaturation, nLuminance ),
182 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
183 maHSLTriple.mnSaturation ) )
187 HSLColor::HSLColor( const RGBColor& rColor ) :
188 maHSLTriple( rgb2hsl( truncateRangeStd( rColor.getRed() ),
189 truncateRangeStd( rColor.getGreen() ),
190 truncateRangeStd( rColor.getBlue() ) ) ),
191 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
192 maHSLTriple.mnSaturation ) )
200 bool operator==( const HSLColor& rLHS, const HSLColor& rRHS )
202 return ( rLHS.getHue() == rRHS.getHue() &&
203 rLHS.getSaturation() == rRHS.getSaturation() &&
204 rLHS.getLuminance() == rRHS.getLuminance() );
207 bool operator!=( const HSLColor& rLHS, const HSLColor& rRHS )
209 return !( rLHS == rRHS );
212 HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS )
214 return HSLColor( rLHS.getHue() + rRHS.getHue(),
215 rLHS.getSaturation() + rRHS.getSaturation(),
216 rLHS.getLuminance() + rRHS.getLuminance() );
219 HSLColor operator*( const HSLColor& rLHS, const HSLColor& rRHS )
221 return HSLColor( rLHS.getHue() * rRHS.getHue(),
222 rLHS.getSaturation() * rRHS.getSaturation(),
223 rLHS.getLuminance() * rRHS.getLuminance() );
226 HSLColor operator*( double nFactor, const HSLColor& rRHS )
228 return HSLColor( nFactor * rRHS.getHue(),
229 nFactor * rRHS.getSaturation(),
230 nFactor * rRHS.getLuminance() );
233 HSLColor interpolate( const HSLColor& rFrom, const HSLColor& rTo, double t, bool bCCW )
235 const double nFromHue( rFrom.getHue() );
236 const double nToHue ( rTo.getHue() );
238 double nHue=0.0;
240 if( nFromHue <= nToHue && !bCCW )
242 // interpolate hue clockwise. That is, hue starts at
243 // high values and ends at low ones. Therefore, we
244 // must 'cross' the 360 degrees and start at low
245 // values again (imagine the hues to lie on the
246 // circle, where values above 360 degrees are mapped
247 // back to [0,360)).
248 nHue = (1.0-t)*(nFromHue + 360.0) + t*nToHue;
250 else if( nFromHue > nToHue && bCCW )
252 // interpolate hue counter-clockwise. That is, hue
253 // starts at high values and ends at low
254 // ones. Therefore, we must 'cross' the 360 degrees
255 // and start at low values again (imagine the hues to
256 // lie on the circle, where values above 360 degrees
257 // are mapped back to [0,360)).
258 nHue = (1.0-t)*nFromHue + t*(nToHue + 360.0);
260 else
262 // interpolate hue counter-clockwise. That is, hue
263 // starts at low values and ends at high ones (imagine
264 // the hue value as degrees on a circle, with
265 // increasing values going counter-clockwise)
266 nHue = (1.0-t)*nFromHue + t*nToHue;
269 return HSLColor( nHue,
270 (1.0-t)*rFrom.getSaturation() + t*rTo.getSaturation(),
271 (1.0-t)*rFrom.getLuminance() + t*rTo.getLuminance() );
276 // RGBColor
280 RGBColor::RGBTriple::RGBTriple() :
281 mnRed(),
282 mnGreen(),
283 mnBlue()
287 RGBColor::RGBTriple::RGBTriple( double nRed, double nGreen, double nBlue ) :
288 mnRed( nRed ),
289 mnGreen( nGreen ),
290 mnBlue( nBlue )
294 RGBColor::RGBColor() :
295 maRGBTriple( 0.0, 0.0, 0.0 )
299 RGBColor::RGBColor( ::cppcanvas::Color::IntSRGBA nRGBColor ) :
300 maRGBTriple( ::cppcanvas::getRed( nRGBColor ) / 255.0,
301 ::cppcanvas::getGreen( nRGBColor ) / 255.0,
302 ::cppcanvas::getBlue( nRGBColor ) / 255.0 )
306 RGBColor::RGBColor( double nRed, double nGreen, double nBlue ) :
307 maRGBTriple( nRed, nGreen, nBlue )
311 RGBColor::RGBColor( const HSLColor& rColor ) :
312 maRGBTriple( hsl2rgb( truncateRangeHue( rColor.getHue() ),
313 truncateRangeStd( rColor.getSaturation() ),
314 truncateRangeStd( rColor.getLuminance() ) ) )
321 ::cppcanvas::Color::IntSRGBA RGBColor::getIntegerColor() const
323 return ::cppcanvas::makeColor( colorToInt( getRed() ),
324 colorToInt( getGreen() ),
325 colorToInt( getBlue() ),
326 255 );
329 bool operator==( const RGBColor& rLHS, const RGBColor& rRHS )
331 return ( rLHS.getRed() == rRHS.getRed() &&
332 rLHS.getGreen() == rRHS.getGreen() &&
333 rLHS.getBlue() == rRHS.getBlue() );
336 bool operator!=( const RGBColor& rLHS, const RGBColor& rRHS )
338 return !( rLHS == rRHS );
341 RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS )
343 return RGBColor( rLHS.getRed() + rRHS.getRed(),
344 rLHS.getGreen() + rRHS.getGreen(),
345 rLHS.getBlue() + rRHS.getBlue() );
348 RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS )
350 return RGBColor( rLHS.getRed() * rRHS.getRed(),
351 rLHS.getGreen() * rRHS.getGreen(),
352 rLHS.getBlue() * rRHS.getBlue() );
355 RGBColor operator*( double nFactor, const RGBColor& rRHS )
357 return RGBColor( nFactor * rRHS.getRed(),
358 nFactor * rRHS.getGreen(),
359 nFactor * rRHS.getBlue() );
362 RGBColor interpolate( const RGBColor& rFrom, const RGBColor& rTo, double t )
364 return RGBColor( (1.0-t)*rFrom.getRed() + t*rTo.getRed(),
365 (1.0-t)*rFrom.getGreen() + t*rTo.getGreen(),
366 (1.0-t)*rFrom.getBlue() + t*rTo.getBlue() );
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */