merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / color.cxx
blob83d030eb97a3857c36d3dbe501e5886dc4d90eea
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: color.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <hslcolor.hxx>
35 #include <rgbcolor.hxx>
37 #include <basegfx/numeric/ftools.hxx>
39 #include <cmath> // for fmod
40 #include <algorithm>
43 namespace slideshow
45 namespace internal
47 namespace
49 // helper functions
50 // ================
52 double getMagic( double nLuminance, double nSaturation )
54 if( nLuminance <= 0.5 )
55 return nLuminance*(1.0 + nSaturation);
56 else
57 return nLuminance + nSaturation - nLuminance*nSaturation;
60 HSLColor::HSLTriple rgb2hsl( double nRed, double nGreen, double nBlue )
62 // r,g,b in [0,1], h in [0,360] and s,l in [0,1]
63 HSLColor::HSLTriple aRes;
65 const double nMax( ::std::max(nRed,::std::max(nGreen, nBlue)) );
66 const double nMin( ::std::min(nRed,::std::min(nGreen, nBlue)) );
68 const double nDelta( nMax - nMin );
70 aRes.mnLuminance = (nMax + nMin) / 2.0;
72 if( ::basegfx::fTools::equalZero( nDelta ) )
74 aRes.mnSaturation = 0.0;
76 // hue undefined (achromatic case)
77 aRes.mnHue = 0.0;
79 else
81 aRes.mnSaturation = aRes.mnLuminance > 0.5 ?
82 nDelta/(2.0-nMax-nMin) :
83 nDelta/(nMax + nMin);
85 if( nRed == nMax )
86 aRes.mnHue = (nGreen - nBlue)/nDelta;
87 else if( nGreen == nMax )
88 aRes.mnHue = 2.0 + (nBlue - nRed)/nDelta;
89 else if( nBlue == nMax )
90 aRes.mnHue = 4.0 + (nRed - nGreen)/nDelta;
92 aRes.mnHue *= 60.0;
94 if( aRes.mnHue < 0.0 )
95 aRes.mnHue += 360.0;
98 return aRes;
101 double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
103 // clamp hue to [0,360]
104 nHue = fmod( nHue, 360.0 );
106 // cope with wrap-arounds
107 if( nHue < 0.0 )
108 nHue += 360.0;
110 if( nHue < 60.0 )
111 return nValue1 + (nValue2 - nValue1)*nHue/60.0;
112 else if( nHue < 180.0 )
113 return nValue2;
114 else if( nHue < 240.0 )
115 return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
116 else
117 return nValue1;
120 RGBColor::RGBTriple hsl2rgb( double nHue, double nSaturation, double nLuminance )
122 if( ::basegfx::fTools::equalZero( nSaturation ) )
123 return RGBColor::RGBTriple(0.0, 0.0, nLuminance );
125 const double nVal1( getMagic(nLuminance, nSaturation) );
126 const double nVal2( 2.0*nLuminance - nVal1 );
128 RGBColor::RGBTriple aRes;
130 aRes.mnRed = hsl2rgbHelper( nVal2,
131 nVal1,
132 nHue + 120.0 );
133 aRes.mnGreen = hsl2rgbHelper( nVal2,
134 nVal1,
135 nHue );
136 aRes.mnBlue = hsl2rgbHelper( nVal2,
137 nVal1,
138 nHue - 120.0 );
140 return aRes;
143 /// Truncate range of value to [0,1]
144 double truncateRangeStd( double nVal )
146 return ::std::max( 0.0,
147 ::std::min( 1.0,
148 nVal ) );
151 /// Truncate range of value to [0,360]
152 double truncateRangeHue( double nVal )
154 return ::std::max( 0.0,
155 ::std::min( 360.0,
156 nVal ) );
159 /// convert RGB color to sal_uInt8, truncate range appropriately before
160 sal_uInt8 colorToInt( double nCol )
162 return static_cast< sal_uInt8 >(
163 ::basegfx::fround( truncateRangeStd( nCol ) * 255.0 ) );
169 // HSLColor
170 // ===============================================
172 HSLColor::HSLTriple::HSLTriple() :
173 mnHue(),
174 mnSaturation(),
175 mnLuminance()
179 HSLColor::HSLTriple::HSLTriple( double nHue, double nSaturation, double nLuminance ) :
180 mnHue( nHue ),
181 mnSaturation( nSaturation ),
182 mnLuminance( nLuminance )
186 HSLColor::HSLColor() :
187 maHSLTriple( 0.0, 0.0, 0.0 ),
188 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
189 maHSLTriple.mnSaturation ) )
193 HSLColor::HSLColor( ::cppcanvas::Color::IntSRGBA nRGBColor ) :
194 maHSLTriple( rgb2hsl( ::cppcanvas::getRed( nRGBColor ) / 255.0,
195 ::cppcanvas::getGreen( nRGBColor ) / 255.0,
196 ::cppcanvas::getBlue( nRGBColor ) / 255.0 ) ),
197 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
198 maHSLTriple.mnSaturation ) )
202 HSLColor::HSLColor( double nHue, double nSaturation, double nLuminance ) :
203 maHSLTriple( nHue, nSaturation, nLuminance ),
204 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
205 maHSLTriple.mnSaturation ) )
209 HSLColor::HSLColor( const RGBColor& rColor ) :
210 maHSLTriple( rgb2hsl( truncateRangeStd( rColor.getRed() ),
211 truncateRangeStd( rColor.getGreen() ),
212 truncateRangeStd( rColor.getBlue() ) ) ),
213 mnMagicValue( getMagic( maHSLTriple.mnLuminance,
214 maHSLTriple.mnSaturation ) )
218 double HSLColor::getHue() const
220 return maHSLTriple.mnHue;
223 double HSLColor::getSaturation() const
225 return maHSLTriple.mnSaturation;
228 double HSLColor::getLuminance() const
230 return maHSLTriple.mnLuminance;
233 double HSLColor::getRed() const
235 if( ::basegfx::fTools::equalZero( getSaturation() ) )
236 return getLuminance();
238 return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
239 mnMagicValue,
240 getHue() + 120.0 );
243 double HSLColor::getGreen() const
245 if( ::basegfx::fTools::equalZero( getSaturation() ) )
246 return getLuminance();
248 return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
249 mnMagicValue,
250 getHue() );
253 double HSLColor::getBlue() const
255 if( ::basegfx::fTools::equalZero( getSaturation() ) )
256 return getLuminance();
258 return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
259 mnMagicValue,
260 getHue() - 120.0 );
263 RGBColor HSLColor::getRGBColor() const
265 RGBColor::RGBTriple aColor( hsl2rgb( getHue(),
266 getSaturation(),
267 getLuminance() ) );
268 return RGBColor( aColor.mnRed, aColor.mnGreen, aColor.mnBlue );
271 HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS )
273 return HSLColor( rLHS.getHue() + rRHS.getHue(),
274 rLHS.getSaturation() + rRHS.getSaturation(),
275 rLHS.getLuminance() + rRHS.getLuminance() );
278 HSLColor operator*( const HSLColor& rLHS, const HSLColor& rRHS )
280 return HSLColor( rLHS.getHue() * rRHS.getHue(),
281 rLHS.getSaturation() * rRHS.getSaturation(),
282 rLHS.getLuminance() * rRHS.getLuminance() );
285 HSLColor operator*( double nFactor, const HSLColor& rRHS )
287 return HSLColor( nFactor * rRHS.getHue(),
288 nFactor * rRHS.getSaturation(),
289 nFactor * rRHS.getLuminance() );
292 HSLColor interpolate( const HSLColor& rFrom, const HSLColor& rTo, double t, bool bCCW )
294 const double nFromHue( rFrom.getHue() );
295 const double nToHue ( rTo.getHue() );
297 double nHue=0.0;
299 if( nFromHue <= nToHue && !bCCW )
301 // interpolate hue clockwise. That is, hue starts at
302 // high values and ends at low ones. Therefore, we
303 // must 'cross' the 360 degrees and start at low
304 // values again (imagine the hues to lie on the
305 // circle, where values above 360 degrees are mapped
306 // back to [0,360)).
307 nHue = (1.0-t)*(nFromHue + 360.0) + t*nToHue;
309 else if( nFromHue > nToHue && bCCW )
311 // interpolate hue counter-clockwise. That is, hue
312 // starts at high values and ends at low
313 // ones. Therefore, we must 'cross' the 360 degrees
314 // and start at low values again (imagine the hues to
315 // lie on the circle, where values above 360 degrees
316 // are mapped back to [0,360)).
317 nHue = (1.0-t)*nFromHue + t*(nToHue + 360.0);
319 else
321 // interpolate hue counter-clockwise. That is, hue
322 // starts at low values and ends at high ones (imagine
323 // the hue value as degrees on a circle, with
324 // increasing values going counter-clockwise)
325 nHue = (1.0-t)*nFromHue + t*nToHue;
328 return HSLColor( nHue,
329 (1.0-t)*rFrom.getSaturation() + t*rTo.getSaturation(),
330 (1.0-t)*rFrom.getLuminance() + t*rTo.getLuminance() );
335 // RGBColor
336 // ===============================================
339 RGBColor::RGBTriple::RGBTriple() :
340 mnRed(),
341 mnGreen(),
342 mnBlue()
346 RGBColor::RGBTriple::RGBTriple( double nRed, double nGreen, double nBlue ) :
347 mnRed( nRed ),
348 mnGreen( nGreen ),
349 mnBlue( nBlue )
353 RGBColor::RGBColor() :
354 maRGBTriple( 0.0, 0.0, 0.0 )
358 RGBColor::RGBColor( ::cppcanvas::Color::IntSRGBA nRGBColor ) :
359 maRGBTriple( ::cppcanvas::getRed( nRGBColor ) / 255.0,
360 ::cppcanvas::getGreen( nRGBColor ) / 255.0,
361 ::cppcanvas::getBlue( nRGBColor ) / 255.0 )
365 RGBColor::RGBColor( double nRed, double nGreen, double nBlue ) :
366 maRGBTriple( nRed, nGreen, nBlue )
370 RGBColor::RGBColor( const HSLColor& rColor ) :
371 maRGBTriple( hsl2rgb( truncateRangeHue( rColor.getHue() ),
372 truncateRangeStd( rColor.getSaturation() ),
373 truncateRangeStd( rColor.getLuminance() ) ) )
377 double RGBColor::getHue() const
379 return rgb2hsl( getRed(),
380 getGreen(),
381 getBlue() ).mnHue;
384 double RGBColor::getSaturation() const
386 return rgb2hsl( getRed(),
387 getGreen(),
388 getBlue() ).mnSaturation;
391 double RGBColor::getLuminance() const
393 return rgb2hsl( getRed(),
394 getGreen(),
395 getBlue() ).mnLuminance;
398 double RGBColor::getRed() const
400 return maRGBTriple.mnRed;
403 double RGBColor::getGreen() const
405 return maRGBTriple.mnGreen;
408 double RGBColor::getBlue() const
410 return maRGBTriple.mnBlue;
413 HSLColor RGBColor::getHSLColor() const
415 HSLColor::HSLTriple aColor( rgb2hsl( getRed(),
416 getGreen(),
417 getBlue() ) );
418 return HSLColor( aColor.mnHue, aColor.mnSaturation, aColor.mnLuminance );
421 ::cppcanvas::Color::IntSRGBA RGBColor::getIntegerColor() const
423 return ::cppcanvas::makeColor( colorToInt( getRed() ),
424 colorToInt( getGreen() ),
425 colorToInt( getBlue() ),
426 255 );
429 RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS )
431 return RGBColor( rLHS.getRed() + rRHS.getRed(),
432 rLHS.getGreen() + rRHS.getGreen(),
433 rLHS.getBlue() + rRHS.getBlue() );
436 RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS )
438 return RGBColor( rLHS.getRed() * rRHS.getRed(),
439 rLHS.getGreen() * rRHS.getGreen(),
440 rLHS.getBlue() * rRHS.getBlue() );
443 RGBColor operator*( double nFactor, const RGBColor& rRHS )
445 return RGBColor( nFactor * rRHS.getRed(),
446 nFactor * rRHS.getGreen(),
447 nFactor * rRHS.getBlue() );
450 RGBColor interpolate( const RGBColor& rFrom, const RGBColor& rTo, double t )
452 return RGBColor( (1.0-t)*rFrom.getRed() + t*rTo.getRed(),
453 (1.0-t)*rFrom.getGreen() + t*rTo.getGreen(),
454 (1.0-t)*rFrom.getBlue() + t*rTo.getBlue() );