1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <sal/config.h>
26 #include <tools/color.hxx>
27 #include <tools/stream.hxx>
28 #include <tools/helpers.hxx>
29 #include <basegfx/color/bcolortools.hxx>
31 sal_uInt8
Color::GetColorError( const Color
& rCompareColor
) const
33 const long nErrAbs
= labs( static_cast<long>(rCompareColor
.GetRed()) - GetRed() ) +
34 labs( static_cast<long>(rCompareColor
.GetGreen()) - GetGreen() ) +
35 labs( static_cast<long>(rCompareColor
.GetBlue()) - GetBlue() );
37 return static_cast<sal_uInt8
>(FRound( nErrAbs
* 0.3333333333 ));
40 void Color::IncreaseLuminance( sal_uInt8 cLumInc
)
42 SetRed( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_RED( mnColor
)) + cLumInc
, 0L, 255L )) );
43 SetGreen( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_GREEN( mnColor
)) + cLumInc
, 0L, 255L )) );
44 SetBlue( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_BLUE( mnColor
)) + cLumInc
, 0L, 255L )) );
47 void Color::DecreaseLuminance( sal_uInt8 cLumDec
)
49 SetRed( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_RED( mnColor
)) - cLumDec
, 0L, 255L )) );
50 SetGreen( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_GREEN( mnColor
)) - cLumDec
, 0L, 255L )) );
51 SetBlue( static_cast<sal_uInt8
>(SAL_BOUND( static_cast<long>(COLORDATA_BLUE( mnColor
)) - cLumDec
, 0L, 255L )) );
54 void Color::DecreaseContrast( sal_uInt8 cContDec
)
58 const double fM
= ( 128.0 - 0.4985 * cContDec
) / 128.0;
59 const double fOff
= 128.0 - fM
* 128.0;
61 SetRed( static_cast<sal_uInt8
>(SAL_BOUND( FRound( COLORDATA_RED( mnColor
) * fM
+ fOff
), 0L, 255L )) );
62 SetGreen( static_cast<sal_uInt8
>(SAL_BOUND( FRound( COLORDATA_GREEN( mnColor
) * fM
+ fOff
), 0L, 255L )) );
63 SetBlue( static_cast<sal_uInt8
>(SAL_BOUND( FRound( COLORDATA_BLUE( mnColor
) * fM
+ fOff
), 0L, 255L )) );
69 SetRed( ~COLORDATA_RED( mnColor
) );
70 SetGreen( ~COLORDATA_GREEN( mnColor
) );
71 SetBlue( ~COLORDATA_BLUE( mnColor
) );
74 bool Color::IsDark() const
76 return GetLuminance() <= 60;
79 bool Color::IsBright() const
81 return GetLuminance() >= 245;
84 // color space conversion
86 void Color::RGBtoHSB( sal_uInt16
& nHue
, sal_uInt16
& nSat
, sal_uInt16
& nBri
) const
101 // Brightness = max(R, G, B);
102 nBri
= cMax
* 100 / 255;
110 sal_uInt8 cDelta
= cMax
- cMin
;
112 // Saturation = max - min / max
114 nSat
= cDelta
* 100 / cMax
;
119 nHue
= 0; // Default = undefined
126 dHue
= static_cast<double>( c
[1] - c
[2] ) / static_cast<double>(cDelta
);
128 else if( c
[1] == cMax
)
130 dHue
= 2.0 + static_cast<double>( c
[2] - c
[0] ) / static_cast<double>(cDelta
);
132 else if ( c
[2] == cMax
)
134 dHue
= 4.0 + static_cast<double>( c
[0] - c
[1] ) / static_cast<double>(cDelta
);
141 nHue
= static_cast<sal_uInt16
>(dHue
);
145 Color
Color::HSBtoRGB( sal_uInt16 nHue
, sal_uInt16 nSat
, sal_uInt16 nBri
)
147 sal_uInt8 cR
=0,cG
=0,cB
=0;
148 sal_uInt8 nB
= static_cast<sal_uInt8
>( nBri
* 255 / 100 );
165 n
= static_cast<sal_uInt16
>(dH
);
168 sal_uInt8 a
= static_cast<sal_uInt8
>( nB
* ( 100 - nSat
) / 100 );
169 sal_uInt8 b
= static_cast<sal_uInt8
>( nB
* ( 100 - ( static_cast<double>(nSat
) * f
) ) / 100 );
170 sal_uInt8 c
= static_cast<sal_uInt8
>( nB
* ( 100 - ( static_cast<double>(nSat
) * ( 1.0 - f
) ) ) / 100 );
174 case 0: cR
= nB
; cG
= c
; cB
= a
; break;
175 case 1: cR
= b
; cG
= nB
; cB
= a
; break;
176 case 2: cR
= a
; cG
= nB
; cB
= c
; break;
177 case 3: cR
= a
; cG
= b
; cB
= nB
; break;
178 case 4: cR
= c
; cG
= a
; cB
= nB
; break;
179 case 5: cR
= nB
; cG
= a
; cB
= b
; break;
183 return Color( cR
, cG
, cB
);
186 SvStream
& Color::Read( SvStream
& rIStm
)
188 rIStm
.ReadUInt32( mnColor
);
192 SvStream
& Color::Write( SvStream
& rOStm
) const
194 rOStm
.WriteUInt32( mnColor
);
198 OUString
Color::AsRGBHexString() const
200 std::stringstream ss
;
201 ss
<< std::hex
<< std::setfill ('0') << std::setw(6) << sal_uInt32(GetRGBColor());
202 return OUString::createFromAscii(ss
.str().c_str());
205 #define COL_NAME_USER (sal_uInt16(0x8000))
207 SvStream
& ReadColor( SvStream
& rIStream
, Color
& rColor
)
209 sal_uInt16 nColorName
;
211 rIStream
.ReadUInt16( nColorName
);
213 if ( nColorName
& COL_NAME_USER
)
219 rIStream
.ReadUInt16( nRed
);
220 rIStream
.ReadUInt16( nGreen
);
221 rIStream
.ReadUInt16( nBlue
);
223 rColor
= Color( nRed
>>8, nGreen
>>8, nBlue
>>8 );
227 static const Color aColAry
[] =
229 COL_BLACK
, // COL_BLACK
230 COL_BLUE
, // COL_BLUE
231 COL_GREEN
, // COL_GREEN
232 COL_CYAN
, // COL_CYAN
234 COL_MAGENTA
, // COL_MAGENTA
235 COL_BROWN
, // COL_BROWN
236 COL_GRAY
, // COL_GRAY
237 COL_LIGHTGRAY
, // COL_LIGHTGRAY
238 COL_LIGHTBLUE
, // COL_LIGHTBLUE
239 COL_LIGHTGREEN
, // COL_LIGHTGREEN
240 COL_LIGHTCYAN
, // COL_LIGHTCYAN
241 COL_LIGHTRED
, // COL_LIGHTRED
242 COL_LIGHTMAGENTA
, // COL_LIGHTMAGENTA
243 COL_YELLOW
, // COL_YELLOW
244 COL_WHITE
, // COL_WHITE
245 COL_WHITE
, // COL_MENUBAR
246 COL_BLACK
, // COL_MENUBARTEXT
247 COL_WHITE
, // COL_POPUPMENU
248 COL_BLACK
, // COL_POPUPMENUTEXT
249 COL_BLACK
, // COL_WINDOWTEXT
250 COL_WHITE
, // COL_WINDOWWORKSPACE
251 COL_BLACK
, // COL_HIGHLIGHT
252 COL_WHITE
, // COL_HIGHLIGHTTEXT
253 COL_BLACK
, // COL_3DTEXT
254 COL_LIGHTGRAY
, // COL_3DFACE
255 COL_WHITE
, // COL_3DLIGHT
256 COL_GRAY
, // COL_3DSHADOW
257 COL_LIGHTGRAY
, // COL_SCROLLBAR
258 COL_WHITE
, // COL_FIELD
259 COL_BLACK
// COL_FIELDTEXT
262 if ( nColorName
< SAL_N_ELEMENTS( aColAry
) )
263 rColor
= aColAry
[nColorName
];
271 void Color::ApplyTintOrShade(sal_Int16 n100thPercent
)
273 if (n100thPercent
== 0)
276 basegfx::BColor aBColor
= basegfx::utils::rgb2hsl(getBColor());
277 double fFactor
= 1.0 - (std::abs(double(n100thPercent
)) / 10000.0);
280 if (n100thPercent
> 0) // tint
282 fResult
= aBColor
.getBlue() * fFactor
+ (1.0 - fFactor
);
286 fResult
= aBColor
.getBlue() * fFactor
;
289 aBColor
.setBlue(fResult
);
290 aBColor
= basegfx::utils::hsl2rgb(aBColor
);
292 SetRed(sal_uInt8(( aBColor
.getRed() * 255.0) + 0.5));
293 SetGreen(sal_uInt8((aBColor
.getGreen() * 255.0) + 0.5));
294 SetBlue(sal_uInt8(( aBColor
.getBlue() * 255.0) + 0.5));
297 SvStream
& WriteColor( SvStream
& rOStream
, const Color
& rColor
)
299 sal_uInt16 nRed
= rColor
.GetRed();
300 sal_uInt16 nGreen
= rColor
.GetGreen();
301 sal_uInt16 nBlue
= rColor
.GetBlue();
302 nRed
= (nRed
<<8) + nRed
;
303 nGreen
= (nGreen
<<8) + nGreen
;
304 nBlue
= (nBlue
<<8) + nBlue
;
306 rOStream
.WriteUInt16( COL_NAME_USER
);
307 rOStream
.WriteUInt16( nRed
);
308 rOStream
.WriteUInt16( nGreen
);
309 rOStream
.WriteUInt16( nBlue
);
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */