office-gobmx/include/tools/color.hxx
Rafał Dobrakowski 3d2134c011 tdf#157664 Drop operator !=, where respective operator == is defined
Found when working on 'tdf#141908'

Change-Id: I33aae153b448c4c6bf0a17810a16c34f8e400774
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163104
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-02-09 04:11:01 +01:00

517 lines
16 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 .
*/
#ifndef INCLUDED_TOOLS_COLOR_HXX
#define INCLUDED_TOOLS_COLOR_HXX
#include <sal/types.h>
#include <tools/toolsdllapi.h>
#include <com/sun/star/uno/Any.hxx>
#include <config_global.h>
#include <basegfx/color/bcolor.hxx>
#include <osl/endian.h>
namespace color
{
constexpr sal_uInt32 extractRGB(sal_uInt32 nColorNumber)
{
return nColorNumber & 0x00FFFFFF;
}
constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans)
{
return sal_uInt8(((sal_Int32(nDst) - nSrc) * nSrcTrans + ((nSrc << 8) | nDst)) >> 8);
}
}
/** used to deliberately select the right constructor */
enum ColorTransparencyTag { ColorTransparency = 0 };
enum ColorAlphaTag { ColorAlpha = 0 };
// Color
class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Color
{
union
{
sal_uInt32 mValue;
struct
{
#ifdef OSL_BIGENDIAN
sal_uInt8 T;
sal_uInt8 R;
sal_uInt8 G;
sal_uInt8 B;
#else
sal_uInt8 B;
sal_uInt8 G;
sal_uInt8 R;
sal_uInt8 T;
#endif
};
};
public:
constexpr Color()
: mValue(0) // black
{}
#if HAVE_CPP_CONSTEVAL
consteval
#else
constexpr
#endif
Color(const sal_uInt32 nColor)
: mValue(nColor)
{
assert(nColor <= 0xffffff && "don't pass transparency to this constructor, use the Color(ColorTransparencyTag,...) or Color(ColorAlphaTag,...) constructor to make it explicit");
}
constexpr Color(enum ColorTransparencyTag, sal_uInt32 nColor)
: mValue(nColor)
{
}
constexpr Color(enum ColorAlphaTag, sal_uInt32 nColor)
: mValue((nColor & 0xffffff) | ((255 - (nColor >> 24)) << 24))
{
}
constexpr Color(enum ColorTransparencyTag, sal_uInt8 nTransparency, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
: mValue(sal_uInt32(nBlue) | (sal_uInt32(nGreen) << 8) | (sal_uInt32(nRed) << 16) | (sal_uInt32(nTransparency) << 24))
{}
constexpr Color(enum ColorAlphaTag, sal_uInt8 nAlpha, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
: Color(ColorTransparency, 255 - nAlpha, nRed, nGreen, nBlue)
{}
constexpr Color(sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
: Color(ColorTransparency, 0, nRed, nGreen, nBlue)
{}
// constructor to create a tools-Color from ::basegfx::BColor
explicit Color(const basegfx::BColor& rBColor)
: Color(ColorTransparency, 0,
sal_uInt8(std::lround(rBColor.getRed() * 255.0)),
sal_uInt8(std::lround(rBColor.getGreen() * 255.0)),
sal_uInt8(std::lround(rBColor.getBlue() * 255.0)))
{}
/** Casts the color to corresponding uInt32.
* Primarily used when passing Color objects to UNO API
* @return corresponding sal_uInt32
*/
constexpr explicit operator sal_uInt32() const
{
return mValue;
}
/** Casts the color to corresponding iInt32.
* If there is no transparency, will be positive.
* @return corresponding sal_Int32
*/
constexpr explicit operator sal_Int32() const
{
return sal_Int32(mValue);
}
/* Basic RGBA operations */
/** Gets the red value.
* @return R
*/
sal_uInt8 GetRed() const
{
return R;
}
/** Gets the green value.
* @return G
*/
sal_uInt8 GetGreen() const
{
return G;
}
/** Gets the blue value.
* @return B
*/
sal_uInt8 GetBlue() const
{
return B;
}
/** Gets the alpha value.
* @return A
*/
sal_uInt8 GetAlpha() const
{
return 255 - T;
}
/** Is the color transparent?
*/
bool IsTransparent() const
{
return GetAlpha() != 255;
}
/** Is the color fully transparent i.e. 100% transparency ?
*/
bool IsFullyTransparent() const
{
return T == 255;
}
/** Sets the red value.
* @param nRed
*/
void SetRed(sal_uInt8 nRed)
{
R = nRed;
}
/** Sets the green value.
* @param nGreen
*/
void SetGreen(sal_uInt8 nGreen)
{
G = nGreen;
}
/** Sets the blue value.
* @param nBlue
*/
void SetBlue(sal_uInt8 nBlue)
{
B = nBlue;
}
/** Sets the alpha value.
* @param nAlpha
*/
void SetAlpha(sal_uInt8 nAlpha)
{
T = 255 - nAlpha;
}
/** Returns the same color but ignoring the transparency value.
* @return RGB version
*/
Color GetRGBColor() const
{
return {R, G, B};
}
/* Comparison and operators */
/** Check if the color RGB value is equal than rColor.
* @param rColor
* @return is equal
*/
bool IsRGBEqual( const Color& rColor ) const
{
return ( mValue & 0x00FFFFFF ) == ( rColor.mValue & 0x00FFFFFF );
}
/** Check if the color value is lower than aCompareColor.
* @param aCompareColor
* @return is lower
*/
bool operator<(const Color& aCompareColor) const
{
return mValue < aCompareColor.mValue;
}
/** Check if the color value is greater than aCompareColor.
* @param aCompareColor
* @return is greater
*/
bool operator>(const Color& aCompareColor) const
{
return mValue > aCompareColor.mValue;
}
/** Check if the color value is equal than rColor.
* @param rColor
* @return is equal
*/
bool operator==(const Color& rColor) const
{
return mValue == rColor.mValue;
}
/** Gets the color error compared to another.
* It describes how different they are.
* It takes the abs of differences in parameters.
* @param rCompareColor
* @return error
*/
sal_uInt16 GetColorError(const Color& rCompareColor) const
{
return static_cast<sal_uInt16>(
abs(static_cast<int>(GetBlue()) - rCompareColor.GetBlue()) +
abs(static_cast<int>(GetGreen()) - rCompareColor.GetGreen()) +
abs(static_cast<int>(GetRed()) - rCompareColor.GetRed()));
}
/* Light and contrast */
/** Gets the color luminance. It means perceived brightness.
* @return luminance
*/
sal_uInt8 GetLuminance() const
{
return sal_uInt8((B * 29UL + G * 151UL + R * 76UL) >> 8);
}
/** Increases the color luminance by cLumInc.
* @param cLumInc
*/
void IncreaseLuminance(sal_uInt8 cLumInc);
/** Decreases the color luminance by cLumDec.
* @param cLumDec
*/
void DecreaseLuminance(sal_uInt8 cLumDec);
/** Decreases color contrast with white by cContDec.
* @param cContDec
*/
void DecreaseContrast(sal_uInt8 cContDec);
/** Comparison with luminance thresholds.
* @return is dark
*/
bool IsDark() const
{
// tdf#156182, and band aid for follow-up issues
if (mValue == 0x729fcf) // COL_DEFAULT_SHAPE_FILLING
return GetLuminance() <= 62;
else
return GetLuminance() <= 156;
}
/** Comparison with luminance thresholds.
* @return is dark
*/
bool IsBright() const
{
return GetLuminance() >= 245;
}
/* Color filters */
/**
* Apply tint or shade to a color.
*
* The input value is the percentage (in 100th of percent) of how much the
* color changes towards the black (shade) or white (tint). If the value
* is positive, the color is tinted, if the value is negative, the color is
* shaded.
**/
void ApplyTintOrShade(sal_Int16 n100thPercent);
/**
* Apply luminance offset and/or modulation.
*
* The input values are in percentages (in 100th percents). 100% modulation and 0% offset
* results in no change.
*/
void ApplyLumModOff(sal_Int16 nMod, sal_Int16 nOff);
/** Inverts color. 1 and 0 are switched.
* Note that the result will be the complementary color.
* For example, if you have red, you will get cyan: FF0000 -> 00FFFF.
*/
void Invert()
{
R = ~R;
G = ~G;
B = ~B;
}
/** Merges color with rMergeColor.
* Allows to get resulting color when superposing another.
* @param rMergeColor
* @param cTransparency
*/
void Merge(const Color& rMergeColor, sal_uInt8 cTransparency)
{
R = color::ColorChannelMerge(R, rMergeColor.R, cTransparency);
G = color::ColorChannelMerge(G, rMergeColor.G, cTransparency);
B = color::ColorChannelMerge(B, rMergeColor.B, cTransparency);
}
/* Change of format */
/** Color space conversion tools
* The range for h/s/b is:
* - Hue: 0-360 degree
* - Saturation: 0-100%
* - Brightness: 0-100%
* @param nHue
* @param nSaturation
* @param nBrightness
* @return rgb color
*/
static Color HSBtoRGB(sal_uInt16 nHue, sal_uInt16 nSaturation, sal_uInt16 nBrightness);
/** Converts a string into a color. Supports:
* #RRGGBB
* #rrggbb
* #RGB
* #rgb
* RRGGBB
* rrggbb
* RGB
* rgb
* If fails returns Color().
*/
static Color STRtoRGB(std::u16string_view colorname);
/** Color space conversion tools
* @param nHue
* @param nSaturation
* @param nBrightness
*/
void RGBtoHSB(sal_uInt16& nHue, sal_uInt16& nSaturation, sal_uInt16& nBrightness) const;
/* Return color as RGB hex string: rrggbb
* for example "00ff00" for green color
* @return hex string
*/
OUString AsRGBHexString() const;
/* Return color as RGB hex string: RRGGBB
* for example "00FF00" for green color
* @return hex string
*/
OUString AsRGBHEXString() const;
/* get ::basegfx::BColor from this color
* @return basegfx color
*/
basegfx::BColor getBColor() const
{
basegfx::BColor aColor(R / 255.0, G / 255.0, B / 255.0);
if (mValue == Color(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF).mValue)
aColor.setAutomatic(true);
return aColor;
}
};
// to reduce the noise when moving these into and out of Any
inline bool operator >>=( const css::uno::Any & rAny, Color & value )
{
sal_Int32 nTmp = {}; // spurious -Werror=maybe-uninitialized
if (!(rAny >>= nTmp))
return false;
value = Color(ColorTransparency, nTmp);
return true;
}
inline void operator <<=( css::uno::Any & rAny, Color value )
{
rAny <<= sal_Int32(value);
}
namespace com::sun::star::uno {
template<> inline Any::Any(Color const & value): Any(sal_Int32(value)) {}
}
// Test compile time conversion of Color to sal_uInt32
static_assert (sal_uInt32(Color(ColorTransparency, 0x00, 0x12, 0x34, 0x56)) == 0x00123456);
static_assert (sal_uInt32(Color(0x12, 0x34, 0x56)) == 0x00123456);
// Color types
inline constexpr ::Color COL_TRANSPARENT ( ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF );
inline constexpr ::Color COL_AUTO ( ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF );
// These are used when drawing to the separate alpha channel we use in vcl
inline constexpr ::Color COL_ALPHA_TRANSPARENT ( 0x00, 0x00, 0x00 );
inline constexpr ::Color COL_ALPHA_OPAQUE ( 0xff, 0xff, 0xff );
inline constexpr ::Color COL_BLACK ( 0x00, 0x00, 0x00 );
inline constexpr ::Color COL_BLUE ( 0x00, 0x00, 0x80 );
inline constexpr ::Color COL_GREEN ( 0x00, 0x80, 0x00 );
inline constexpr ::Color COL_CYAN ( 0x00, 0x80, 0x80 );
inline constexpr ::Color COL_RED ( 0x80, 0x00, 0x00 );
inline constexpr ::Color COL_MAGENTA ( 0x80, 0x00, 0x80 );
inline constexpr ::Color COL_BROWN ( 0x80, 0x80, 0x00 );
inline constexpr ::Color COL_GRAY ( 0x80, 0x80, 0x80 );
inline constexpr ::Color COL_GRAY3 ( 0xCC, 0xCC, 0xCC );
inline constexpr ::Color COL_GRAY7 ( 0x66, 0x66, 0x66 );
inline constexpr ::Color COL_LIGHTGRAY ( 0xC0, 0xC0, 0xC0 );
inline constexpr ::Color COL_LIGHTBLUE ( 0x00, 0x00, 0xFF );
inline constexpr ::Color COL_LIGHTGREEN ( 0x00, 0xFF, 0x00 );
inline constexpr ::Color COL_LIGHTCYAN ( 0x00, 0xFF, 0xFF );
inline constexpr ::Color COL_LIGHTRED ( 0xFF, 0x00, 0x00 );
inline constexpr ::Color COL_LIGHTMAGENTA ( 0xFF, 0x00, 0xFF );
inline constexpr ::Color COL_LIGHTGRAYBLUE ( 0xE0, 0xE0, 0xFF );
inline constexpr ::Color COL_YELLOW ( 0xFF, 0xFF, 0x00 );
inline constexpr ::Color COL_WHITE ( 0xFF, 0xFF, 0xFF );
inline constexpr ::Color COL_AUTHOR1_DARK ( 0xC6, 0x92, 0x00 );
inline constexpr ::Color COL_AUTHOR1_NORMAL ( 0xFF, 0xFF, 0x9E );
inline constexpr ::Color COL_AUTHOR1_LIGHT ( 0xFF, 0xFF, 0xC3 );
inline constexpr ::Color COL_AUTHOR2_DARK ( 0x06, 0x46, 0xA2 );
inline constexpr ::Color COL_AUTHOR2_NORMAL ( 0xD8, 0xE8, 0xFF );
inline constexpr ::Color COL_AUTHOR2_LIGHT ( 0xE9, 0xF2, 0xFF );
inline constexpr ::Color COL_AUTHOR3_DARK ( 0x57, 0x9D, 0x1C );
inline constexpr ::Color COL_AUTHOR3_NORMAL ( 0xDA, 0xF8, 0xC1 );
inline constexpr ::Color COL_AUTHOR3_LIGHT ( 0xE2, 0xFA, 0xCF );
inline constexpr ::Color COL_AUTHOR4_DARK ( 0x69, 0x2B, 0x9D );
inline constexpr ::Color COL_AUTHOR4_NORMAL ( 0xE4, 0xD2, 0xF5 );
inline constexpr ::Color COL_AUTHOR4_LIGHT ( 0xEF, 0xE4, 0xF8 );
inline constexpr ::Color COL_AUTHOR5_DARK ( 0xC5, 0x00, 0x0B );
inline constexpr ::Color COL_AUTHOR5_NORMAL ( 0xFE, 0xCD, 0xD0 );
inline constexpr ::Color COL_AUTHOR5_LIGHT ( 0xFF, 0xE3, 0xE5 );
inline constexpr ::Color COL_AUTHOR6_DARK ( 0x00, 0x80, 0x80 );
inline constexpr ::Color COL_AUTHOR6_NORMAL ( 0xD2, 0xF6, 0xF6 );
inline constexpr ::Color COL_AUTHOR6_LIGHT ( 0xE6, 0xFA, 0xFA );
inline constexpr ::Color COL_AUTHOR7_DARK ( 0x8C, 0x84, 0x00 );
inline constexpr ::Color COL_AUTHOR7_NORMAL ( 0xED, 0xFC, 0xA3 );
inline constexpr ::Color COL_AUTHOR7_LIGHT ( 0xF2, 0xFE, 0xB5 );
inline constexpr ::Color COL_AUTHOR8_DARK ( 0x35, 0x55, 0x6B );
inline constexpr ::Color COL_AUTHOR8_NORMAL ( 0xD3, 0xDE, 0xE8 );
inline constexpr ::Color COL_AUTHOR8_LIGHT ( 0xE2, 0xEA, 0xF1 );
inline constexpr ::Color COL_AUTHOR9_DARK ( 0xD1, 0x76, 0x00 );
inline constexpr ::Color COL_AUTHOR9_NORMAL ( 0xFF, 0xE2, 0xB9 );
inline constexpr ::Color COL_AUTHOR9_LIGHT ( 0xFF, 0xE7, 0xC7 );
inline constexpr ::Color COL_AUTHOR_TABLE_INS ( 0xE1, 0xF2, 0xFA );
inline constexpr ::Color COL_AUTHOR_TABLE_DEL ( 0xFC, 0xE6, 0xF4 );
template<typename charT, typename traits>
inline std::basic_ostream<charT, traits>& operator <<(std::basic_ostream<charT, traits>& rStream, const Color& rColor)
{
std::ios_base::fmtflags nOrigFlags = rStream.flags();
rStream << "rgba[" << std::hex << std::setfill ('0')
<< std::setw(2) << static_cast<int>(rColor.GetRed())
<< std::setw(2) << static_cast<int>(rColor.GetGreen())
<< std::setw(2) << static_cast<int>(rColor.GetBlue())
<< std::setw(2) << static_cast<int>(rColor.GetAlpha()) << "]";
rStream.setf(nOrigFlags);
return rStream;
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */