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>
25 #include <tools/color.hxx>
26 #include <tools/debug.hxx>
27 #include <tools/stream.hxx>
28 #include <tools/rc.hxx>
29 #include <tools/rcid.h>
30 #include <tools/resid.hxx>
32 #include <tools/helpers.hxx>
33 #include <basegfx/color/bcolortools.hxx>
35 static inline long _FRound( double fVal
)
37 return( fVal
> 0.0 ? (long) ( fVal
+ 0.5 ) : -(long) ( -fVal
+ 0.5 ) );
40 Color::Color( const ResId
& rResId
)
42 rResId
.SetRT( RSC_COLOR
);
43 ResMgr
* pResMgr
= rResId
.GetResMgr();
44 if ( pResMgr
&& pResMgr
->GetResource( rResId
) )
46 // Header ueberspringen
47 pResMgr
->Increment( sizeof( RSHEADER_TYPE
) );
50 sal_uInt16 nRed
= pResMgr
->ReadShort();
51 sal_uInt16 nGreen
= pResMgr
->ReadShort();
52 sal_uInt16 nBlue
= pResMgr
->ReadShort();
53 // one more historical sal_uIntPtr
57 mnColor
= RGB_COLORDATA( nRed
>>8, nGreen
>>8, nBlue
>>8 );
61 mnColor
= RGB_COLORDATA( 0, 0, 0 );
65 sal_uInt8
Color::GetColorError( const Color
& rCompareColor
) const
67 const long nErrAbs
= labs( (long) rCompareColor
.GetRed() - GetRed() ) +
68 labs( (long) rCompareColor
.GetGreen() - GetGreen() ) +
69 labs( (long) rCompareColor
.GetBlue() - GetBlue() );
71 return (sal_uInt8
) _FRound( nErrAbs
* 0.3333333333 );
74 void Color::IncreaseLuminance( sal_uInt8 cLumInc
)
76 SetRed( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_RED( mnColor
) + cLumInc
, 0L, 255L ) );
77 SetGreen( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_GREEN( mnColor
) + cLumInc
, 0L, 255L ) );
78 SetBlue( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_BLUE( mnColor
) + cLumInc
, 0L, 255L ) );
81 void Color::DecreaseLuminance( sal_uInt8 cLumDec
)
83 SetRed( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_RED( mnColor
) - cLumDec
, 0L, 255L ) );
84 SetGreen( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_GREEN( mnColor
) - cLumDec
, 0L, 255L ) );
85 SetBlue( (sal_uInt8
) SAL_BOUND( (long) COLORDATA_BLUE( mnColor
) - cLumDec
, 0L, 255L ) );
88 void Color::DecreaseContrast( sal_uInt8 cContDec
)
92 const double fM
= ( 128.0 - 0.4985 * cContDec
) / 128.0;
93 const double fOff
= 128.0 - fM
* 128.0;
95 SetRed( (sal_uInt8
) SAL_BOUND( _FRound( COLORDATA_RED( mnColor
) * fM
+ fOff
), 0L, 255L ) );
96 SetGreen( (sal_uInt8
) SAL_BOUND( _FRound( COLORDATA_GREEN( mnColor
) * fM
+ fOff
), 0L, 255L ) );
97 SetBlue( (sal_uInt8
) SAL_BOUND( _FRound( COLORDATA_BLUE( mnColor
) * fM
+ fOff
), 0L, 255L ) );
103 SetRed( ~COLORDATA_RED( mnColor
) );
104 SetGreen( ~COLORDATA_GREEN( mnColor
) );
105 SetBlue( ~COLORDATA_BLUE( mnColor
) );
108 bool Color::IsDark() const
110 return GetLuminance() <= 60;
113 bool Color::IsBright() const
115 return GetLuminance() >= 245;
118 void Color::ApplyTintOrShade(sal_Int16 n100thPercent
)
120 if (n100thPercent
> 0)
122 basegfx::BColor aBColor
= basegfx::tools::rgb2hsl(getBColor());
124 double fFactor
= std::abs(n100thPercent
) / 10000.0;
125 aBColor
.setBlue(aBColor
.getBlue() * fFactor
+ (100.0 - aBColor
.getBlue()));
126 aBColor
= basegfx::tools::hsl2rgb(aBColor
);
128 SetRed(sal_uInt8((aBColor
.getRed() * 255.0) + 0.5));
129 SetGreen(sal_uInt8((aBColor
.getGreen() * 255.0) + 0.5));
130 SetBlue(sal_uInt8((aBColor
.getBlue() * 255.0) + 0.5));
132 else if (n100thPercent
< 0)
134 basegfx::BColor aBColor
= basegfx::tools::rgb2hsl(getBColor());
136 double fFactor
= std::abs(n100thPercent
) / 10000.0;
137 aBColor
.setBlue(aBColor
.getBlue() * fFactor
);
138 aBColor
= basegfx::tools::hsl2rgb(aBColor
);
140 SetRed(sal_uInt8((aBColor
.getRed() * 255.0) + 0.5));
141 SetGreen(sal_uInt8((aBColor
.getGreen() * 255.0) + 0.5));
142 SetBlue(sal_uInt8((aBColor
.getBlue() * 255.0) + 0.5));
146 // color space conversion
148 void Color::RGBtoHSB( sal_uInt16
& nHue
, sal_uInt16
& nSat
, sal_uInt16
& nBri
) const
151 sal_uInt8 cMax
, cMin
;
163 // Brightness = max(R, G, B);
164 nBri
= cMax
* 100 / 255;
172 sal_uInt8 cDelta
= cMax
- cMin
;
174 // Saturation = max - min / max
176 nSat
= cDelta
* 100 / cMax
;
181 nHue
= 0; // Default = undefined
188 dHue
= (double)( c
[1] - c
[2] ) / (double)cDelta
;
190 else if( c
[1] == cMax
)
192 dHue
= 2.0 + (double)( c
[2] - c
[0] ) / (double)cDelta
;
194 else if ( c
[2] == cMax
)
196 dHue
= 4.0 + (double)( c
[0] - c
[1] ) / (double)cDelta
;
203 nHue
= (sal_uInt16
) dHue
;
207 ColorData
Color::HSBtoRGB( sal_uInt16 nHue
, sal_uInt16 nSat
, sal_uInt16 nBri
)
209 sal_uInt8 cR
=0,cG
=0,cB
=0;
210 sal_uInt8 nB
= (sal_uInt8
) ( nBri
* 255 / 100 );
230 sal_uInt8 a
= (sal_uInt8
) ( nB
* ( 100 - nSat
) / 100 );
231 sal_uInt8 b
= (sal_uInt8
) ( nB
* ( 100 - ( (double)nSat
* f
) ) / 100 );
232 sal_uInt8 c
= (sal_uInt8
) ( nB
* ( 100 - ( (double)nSat
* ( 1.0 - f
) ) ) / 100 );
236 case 0: cR
= nB
; cG
= c
; cB
= a
; break;
237 case 1: cR
= b
; cG
= nB
; cB
= a
; break;
238 case 2: cR
= a
; cG
= nB
; cB
= c
; break;
239 case 3: cR
= a
; cG
= b
; cB
= nB
; break;
240 case 4: cR
= c
; cG
= a
; cB
= nB
; break;
241 case 5: cR
= nB
; cG
= a
; cB
= b
; break;
245 return RGB_COLORDATA( cR
, cG
, cB
);
248 SvStream
& Color::Read( SvStream
& rIStm
, bool bNewFormat
)
251 rIStm
.ReadUInt32( mnColor
);
253 ReadColor( rIStm
, *this );
258 SvStream
& Color::Write( SvStream
& rOStm
, bool bNewFormat
) const
261 rOStm
.WriteUInt32( mnColor
);
263 WriteColor( rOStm
, *this );
268 OUString
Color::AsRGBHexString() const
270 std::stringstream ss
;
271 ss
<< std::hex
<< std::setfill ('0') << std::setw(6) << GetRGBColor();
272 return OUString::createFromAscii(ss
.str().c_str());
275 #define COL_NAME_USER ((sal_uInt16)0x8000)
277 SvStream
& ReadColor( SvStream
& rIStream
, Color
& rColor
)
279 DBG_ASSERTWARNING( rIStream
.GetVersion(), "Color::>> - Solar-Version not set on rIStream" );
281 sal_uInt16 nColorName
;
283 rIStream
.ReadUInt16( nColorName
);
285 if ( nColorName
& COL_NAME_USER
)
291 rIStream
.ReadUInt16( nRed
);
292 rIStream
.ReadUInt16( nGreen
);
293 rIStream
.ReadUInt16( nBlue
);
295 rColor
.mnColor
= RGB_COLORDATA( nRed
>>8, nGreen
>>8, nBlue
>>8 );
299 static const ColorData aColAry
[] =
301 COL_BLACK
, // COL_BLACK
302 COL_BLUE
, // COL_BLUE
303 COL_GREEN
, // COL_GREEN
304 COL_CYAN
, // COL_CYAN
306 COL_MAGENTA
, // COL_MAGENTA
307 COL_BROWN
, // COL_BROWN
308 COL_GRAY
, // COL_GRAY
309 COL_LIGHTGRAY
, // COL_LIGHTGRAY
310 COL_LIGHTBLUE
, // COL_LIGHTBLUE
311 COL_LIGHTGREEN
, // COL_LIGHTGREEN
312 COL_LIGHTCYAN
, // COL_LIGHTCYAN
313 COL_LIGHTRED
, // COL_LIGHTRED
314 COL_LIGHTMAGENTA
, // COL_LIGHTMAGENTA
315 COL_YELLOW
, // COL_YELLOW
316 COL_WHITE
, // COL_WHITE
317 COL_WHITE
, // COL_MENUBAR
318 COL_BLACK
, // COL_MENUBARTEXT
319 COL_WHITE
, // COL_POPUPMENU
320 COL_BLACK
, // COL_POPUPMENUTEXT
321 COL_BLACK
, // COL_WINDOWTEXT
322 COL_WHITE
, // COL_WINDOWWORKSPACE
323 COL_BLACK
, // COL_HIGHLIGHT
324 COL_WHITE
, // COL_HIGHLIGHTTEXT
325 COL_BLACK
, // COL_3DTEXT
326 COL_LIGHTGRAY
, // COL_3DFACE
327 COL_WHITE
, // COL_3DLIGHT
328 COL_GRAY
, // COL_3DSHADOW
329 COL_LIGHTGRAY
, // COL_SCROLLBAR
330 COL_WHITE
, // COL_FIELD
331 COL_BLACK
// COL_FIELDTEXT
334 if ( nColorName
< (sizeof( aColAry
)/sizeof(ColorData
)) )
335 rColor
.mnColor
= aColAry
[nColorName
];
337 rColor
.mnColor
= COL_BLACK
;
343 SvStream
& WriteColor( SvStream
& rOStream
, const Color
& rColor
)
345 DBG_ASSERTWARNING( rOStream
.GetVersion(), "Color::<< - Solar-Version not set on rOStream" );
347 sal_uInt16 nColorName
= COL_NAME_USER
;
348 sal_uInt16 nRed
= rColor
.GetRed();
349 sal_uInt16 nGreen
= rColor
.GetGreen();
350 sal_uInt16 nBlue
= rColor
.GetBlue();
351 nRed
= (nRed
<<8) + nRed
;
352 nGreen
= (nGreen
<<8) + nGreen
;
353 nBlue
= (nBlue
<<8) + nBlue
;
355 rOStream
.WriteUInt16( nColorName
);
356 rOStream
.WriteUInt16( nRed
);
357 rOStream
.WriteUInt16( nGreen
);
358 rOStream
.WriteUInt16( nBlue
);
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */