Files
libreoffice/slideshow/source/engine/color.cxx
Noel Grandin f775249547 remove cppcanvas Color class
which actually does nothing useful. Looks like it was originally
intended to be used to implement color profiles, but since nothing
has happened on that front since it was created, safe to say it never
will. Probably not the right place in the graphics stack to do it
anyhow.

Change-Id: I36990db4036e3b4b2b75261fc430028562a6dbd9
Reviewed-on: https://gerrit.libreoffice.org/43240
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2017-10-09 21:05:09 +02:00

351 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <hslcolor.hxx>
#include <rgbcolor.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <cmath>
#include <algorithm>
namespace slideshow
{
namespace internal
{
namespace
{
// helper functions
// ================
double getMagic( double nLuminance, double nSaturation )
{
if( nLuminance <= 0.5 )
return nLuminance*(1.0 + nSaturation);
else
return nLuminance + nSaturation - nLuminance*nSaturation;
}
HSLColor::HSLTriple rgb2hsl( double nRed, double nGreen, double nBlue )
{
// r,g,b in [0,1], h in [0,360] and s,l in [0,1]
HSLColor::HSLTriple aRes;
const double nMax( ::std::max(nRed,::std::max(nGreen, nBlue)) );
const double nMin( ::std::min(nRed,::std::min(nGreen, nBlue)) );
const double nDelta( nMax - nMin );
aRes.mnLuminance = (nMax + nMin) / 2.0;
if( ::basegfx::fTools::equalZero( nDelta ) )
{
aRes.mnSaturation = 0.0;
// hue undefined (achromatic case)
aRes.mnHue = 0.0;
}
else
{
aRes.mnSaturation = aRes.mnLuminance > 0.5 ?
nDelta/(2.0-nMax-nMin) :
nDelta/(nMax + nMin);
if( rtl::math::approxEqual(nRed, nMax) )
aRes.mnHue = (nGreen - nBlue)/nDelta;
else if( rtl::math::approxEqual(nGreen, nMax) )
aRes.mnHue = 2.0 + (nBlue - nRed)/nDelta;
else if( rtl::math::approxEqual(nBlue, nMax) )
aRes.mnHue = 4.0 + (nRed - nGreen)/nDelta;
aRes.mnHue *= 60.0;
if( aRes.mnHue < 0.0 )
aRes.mnHue += 360.0;
}
return aRes;
}
double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
{
// clamp hue to [0,360]
nHue = fmod( nHue, 360.0 );
// cope with wrap-arounds
if( nHue < 0.0 )
nHue += 360.0;
if( nHue < 60.0 )
return nValue1 + (nValue2 - nValue1)*nHue/60.0;
else if( nHue < 180.0 )
return nValue2;
else if( nHue < 240.0 )
return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
else
return nValue1;
}
RGBColor::RGBTriple hsl2rgb( double nHue, double nSaturation, double nLuminance )
{
if( ::basegfx::fTools::equalZero( nSaturation ) )
return RGBColor::RGBTriple(0.0, 0.0, nLuminance );
const double nVal1( getMagic(nLuminance, nSaturation) );
const double nVal2( 2.0*nLuminance - nVal1 );
RGBColor::RGBTriple aRes;
aRes.mnRed = hsl2rgbHelper( nVal2,
nVal1,
nHue + 120.0 );
aRes.mnGreen = hsl2rgbHelper( nVal2,
nVal1,
nHue );
aRes.mnBlue = hsl2rgbHelper( nVal2,
nVal1,
nHue - 120.0 );
return aRes;
}
/// Truncate range of value to [0,1]
double truncateRangeStd( double nVal )
{
return ::std::max( 0.0,
::std::min( 1.0,
nVal ) );
}
/// Truncate range of value to [0,360]
double truncateRangeHue( double nVal )
{
return ::std::max( 0.0,
::std::min( 360.0,
nVal ) );
}
/// convert RGB color to sal_uInt8, truncate range appropriately before
sal_uInt8 colorToInt( double nCol )
{
return static_cast< sal_uInt8 >(
::basegfx::fround( truncateRangeStd( nCol ) * 255.0 ) );
}
}
// HSLColor
HSLColor::HSLTriple::HSLTriple() :
mnHue(),
mnSaturation(),
mnLuminance()
{
}
HSLColor::HSLTriple::HSLTriple( double nHue, double nSaturation, double nLuminance ) :
mnHue( nHue ),
mnSaturation( nSaturation ),
mnLuminance( nLuminance )
{
}
HSLColor::HSLColor() :
maHSLTriple( 0.0, 0.0, 0.0 )
{
}
HSLColor::HSLColor( double nHue, double nSaturation, double nLuminance ) :
maHSLTriple( nHue, nSaturation, nLuminance )
{
}
HSLColor::HSLColor( const RGBColor& rColor ) :
maHSLTriple( rgb2hsl( truncateRangeStd( rColor.getRed() ),
truncateRangeStd( rColor.getGreen() ),
truncateRangeStd( rColor.getBlue() ) ) )
{
}
bool operator==( const HSLColor& rLHS, const HSLColor& rRHS )
{
return ( rLHS.getHue() == rRHS.getHue() &&
rLHS.getSaturation() == rRHS.getSaturation() &&
rLHS.getLuminance() == rRHS.getLuminance() );
}
bool operator!=( const HSLColor& rLHS, const HSLColor& rRHS )
{
return !( rLHS == rRHS );
}
HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS )
{
return HSLColor( rLHS.getHue() + rRHS.getHue(),
rLHS.getSaturation() + rRHS.getSaturation(),
rLHS.getLuminance() + rRHS.getLuminance() );
}
HSLColor operator*( double nFactor, const HSLColor& rRHS )
{
return HSLColor( nFactor * rRHS.getHue(),
nFactor * rRHS.getSaturation(),
nFactor * rRHS.getLuminance() );
}
HSLColor interpolate( const HSLColor& rFrom, const HSLColor& rTo, double t, bool bCCW )
{
const double nFromHue( rFrom.getHue() );
const double nToHue ( rTo.getHue() );
double nHue=0.0;
if( nFromHue <= nToHue && !bCCW )
{
// interpolate hue clockwise. That is, hue starts at
// high values and ends at low ones. Therefore, we
// must 'cross' the 360 degrees and start at low
// values again (imagine the hues to lie on the
// circle, where values above 360 degrees are mapped
// back to [0,360)).
nHue = (1.0-t)*(nFromHue + 360.0) + t*nToHue;
}
else if( nFromHue > nToHue && bCCW )
{
// interpolate hue counter-clockwise. That is, hue
// starts at high values and ends at low
// ones. Therefore, we must 'cross' the 360 degrees
// and start at low values again (imagine the hues to
// lie on the circle, where values above 360 degrees
// are mapped back to [0,360)).
nHue = (1.0-t)*nFromHue + t*(nToHue + 360.0);
}
else
{
// interpolate hue counter-clockwise. That is, hue
// starts at low values and ends at high ones (imagine
// the hue value as degrees on a circle, with
// increasing values going counter-clockwise)
nHue = (1.0-t)*nFromHue + t*nToHue;
}
return HSLColor( nHue,
(1.0-t)*rFrom.getSaturation() + t*rTo.getSaturation(),
(1.0-t)*rFrom.getLuminance() + t*rTo.getLuminance() );
}
// RGBColor
RGBColor::RGBTriple::RGBTriple() :
mnRed(),
mnGreen(),
mnBlue()
{
}
RGBColor::RGBTriple::RGBTriple( double nRed, double nGreen, double nBlue ) :
mnRed( nRed ),
mnGreen( nGreen ),
mnBlue( nBlue )
{
}
RGBColor::RGBColor() :
maRGBTriple( 0.0, 0.0, 0.0 )
{
}
RGBColor::RGBColor( ::cppcanvas::IntSRGBA nRGBColor ) :
maRGBTriple( ::cppcanvas::getRed( nRGBColor ) / 255.0,
::cppcanvas::getGreen( nRGBColor ) / 255.0,
::cppcanvas::getBlue( nRGBColor ) / 255.0 )
{
}
RGBColor::RGBColor( double nRed, double nGreen, double nBlue ) :
maRGBTriple( nRed, nGreen, nBlue )
{
}
RGBColor::RGBColor( const HSLColor& rColor ) :
maRGBTriple( hsl2rgb( truncateRangeHue( rColor.getHue() ),
truncateRangeStd( rColor.getSaturation() ),
truncateRangeStd( rColor.getLuminance() ) ) )
{
}
::cppcanvas::IntSRGBA RGBColor::getIntegerColor() const
{
return ::cppcanvas::makeColor( colorToInt( getRed() ),
colorToInt( getGreen() ),
colorToInt( getBlue() ),
255 );
}
bool operator==( const RGBColor& rLHS, const RGBColor& rRHS )
{
return ( rLHS.getRed() == rRHS.getRed() &&
rLHS.getGreen() == rRHS.getGreen() &&
rLHS.getBlue() == rRHS.getBlue() );
}
bool operator!=( const RGBColor& rLHS, const RGBColor& rRHS )
{
return !( rLHS == rRHS );
}
RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS )
{
return RGBColor( rLHS.getRed() + rRHS.getRed(),
rLHS.getGreen() + rRHS.getGreen(),
rLHS.getBlue() + rRHS.getBlue() );
}
RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS )
{
return RGBColor( rLHS.getRed() * rRHS.getRed(),
rLHS.getGreen() * rRHS.getGreen(),
rLHS.getBlue() * rRHS.getBlue() );
}
RGBColor operator*( double nFactor, const RGBColor& rRHS )
{
return RGBColor( nFactor * rRHS.getRed(),
nFactor * rRHS.getGreen(),
nFactor * rRHS.getBlue() );
}
RGBColor interpolate( const RGBColor& rFrom, const RGBColor& rTo, double t )
{
return RGBColor( (1.0-t)*rFrom.getRed() + t*rTo.getRed(),
(1.0-t)*rFrom.getGreen() + t*rTo.getGreen(),
(1.0-t)*rFrom.getBlue() + t*rTo.getBlue() );
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */