Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <stdlib.h>
21 :
22 : #include <tools/color.hxx>
23 : #include <tools/debug.hxx>
24 : #include <tools/stream.hxx>
25 : #include <tools/rc.hxx>
26 : #include <tools/rcid.h>
27 : #include <tools/resid.hxx>
28 : #include <tools/rc.h>
29 :
30 764 : static inline long _FRound( double fVal )
31 : {
32 764 : return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
33 : }
34 :
35 2183 : Color::Color( const ResId& rResId )
36 : {
37 2183 : rResId.SetRT( RSC_COLOR );
38 2183 : ResMgr* pResMgr = rResId.GetResMgr();
39 2183 : if ( pResMgr && pResMgr->GetResource( rResId ) )
40 : {
41 : // Header ueberspringen
42 2183 : pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
43 :
44 : // Daten laden
45 2183 : sal_uInt16 nRed = pResMgr->ReadShort();
46 2183 : sal_uInt16 nGreen = pResMgr->ReadShort();
47 2183 : sal_uInt16 nBlue = pResMgr->ReadShort();
48 : // one more historical sal_uIntPtr
49 2183 : pResMgr->ReadLong();
50 :
51 : // RGB-Farbe
52 2183 : mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
53 : }
54 : else
55 : {
56 0 : mnColor = RGB_COLORDATA( 0, 0, 0 );
57 : }
58 2183 : }
59 :
60 764 : sal_uInt8 Color::GetColorError( const Color& rCompareColor ) const
61 : {
62 1528 : const long nErrAbs = labs( (long) rCompareColor.GetRed() - GetRed() ) +
63 764 : labs( (long) rCompareColor.GetGreen() - GetGreen() ) +
64 764 : labs( (long) rCompareColor.GetBlue() - GetBlue() );
65 :
66 764 : return (sal_uInt8) _FRound( nErrAbs * 0.3333333333 );
67 : }
68 :
69 8654 : void Color::IncreaseLuminance( sal_uInt8 cLumInc )
70 : {
71 8654 : SetRed( (sal_uInt8) SAL_BOUND( (long) COLORDATA_RED( mnColor ) + cLumInc, 0L, 255L ) );
72 8654 : SetGreen( (sal_uInt8) SAL_BOUND( (long) COLORDATA_GREEN( mnColor ) + cLumInc, 0L, 255L ) );
73 8654 : SetBlue( (sal_uInt8) SAL_BOUND( (long) COLORDATA_BLUE( mnColor ) + cLumInc, 0L, 255L ) );
74 8654 : }
75 :
76 2232 : void Color::DecreaseLuminance( sal_uInt8 cLumDec )
77 : {
78 2232 : SetRed( (sal_uInt8) SAL_BOUND( (long) COLORDATA_RED( mnColor ) - cLumDec, 0L, 255L ) );
79 2232 : SetGreen( (sal_uInt8) SAL_BOUND( (long) COLORDATA_GREEN( mnColor ) - cLumDec, 0L, 255L ) );
80 2232 : SetBlue( (sal_uInt8) SAL_BOUND( (long) COLORDATA_BLUE( mnColor ) - cLumDec, 0L, 255L ) );
81 2232 : }
82 :
83 0 : void Color::DecreaseContrast( sal_uInt8 cContDec )
84 : {
85 0 : if( cContDec )
86 : {
87 0 : const double fM = ( 128.0 - 0.4985 * cContDec ) / 128.0;
88 0 : const double fOff = 128.0 - fM * 128.0;
89 :
90 0 : SetRed( (sal_uInt8) SAL_BOUND( _FRound( COLORDATA_RED( mnColor ) * fM + fOff ), 0L, 255L ) );
91 0 : SetGreen( (sal_uInt8) SAL_BOUND( _FRound( COLORDATA_GREEN( mnColor ) * fM + fOff ), 0L, 255L ) );
92 0 : SetBlue( (sal_uInt8) SAL_BOUND( _FRound( COLORDATA_BLUE( mnColor ) * fM + fOff ), 0L, 255L ) );
93 : }
94 0 : }
95 :
96 0 : void Color::Invert()
97 : {
98 0 : SetRed( ~COLORDATA_RED( mnColor ) );
99 0 : SetGreen( ~COLORDATA_GREEN( mnColor ) );
100 0 : SetBlue( ~COLORDATA_BLUE( mnColor ) );
101 0 : }
102 :
103 197997 : bool Color::IsDark() const
104 : {
105 197997 : return GetLuminance() <= 60;
106 : }
107 :
108 284168 : bool Color::IsBright() const
109 : {
110 284168 : return GetLuminance() >= 245;
111 : }
112 :
113 : // color space conversion
114 :
115 323371 : void Color::RGBtoHSB( sal_uInt16& nHue, sal_uInt16& nSat, sal_uInt16& nBri ) const
116 : {
117 : sal_uInt8 c[3];
118 : sal_uInt8 cMax, cMin;
119 :
120 323371 : c[0] = GetRed();
121 323371 : c[1] = GetGreen();
122 323371 : c[2] = GetBlue();
123 :
124 323371 : cMax = c[0];
125 323371 : if( c[1] > cMax )
126 0 : cMax = c[1];
127 323371 : if( c[2] > cMax )
128 739 : cMax = c[2];
129 :
130 : // Brightness = max(R, G, B);
131 323371 : nBri = cMax * 100 / 255;
132 :
133 323371 : cMin = c[0];
134 323371 : if( c[1] < cMin )
135 0 : cMin = c[1];
136 323371 : if( c[2] < cMin )
137 0 : cMin = c[2];
138 :
139 323371 : sal_uInt8 cDelta = cMax - cMin;
140 :
141 : // Saturation = max - min / max
142 323371 : if( nBri > 0 )
143 323371 : nSat = cDelta * 100 / cMax;
144 : else
145 0 : nSat = 0;
146 :
147 323371 : if( nSat == 0 )
148 322632 : nHue = 0; // Default = undefined
149 : else
150 : {
151 739 : double dHue = 0.0;
152 :
153 739 : if( c[0] == cMax )
154 : {
155 0 : dHue = (double)( c[1] - c[2] ) / (double)cDelta;
156 : }
157 739 : else if( c[1] == cMax )
158 : {
159 0 : dHue = 2.0 + (double)( c[2] - c[0] ) / (double)cDelta;
160 : }
161 739 : else if ( c[2] == cMax )
162 : {
163 739 : dHue = 4.0 + (double)( c[0] - c[1] ) / (double)cDelta;
164 : }
165 739 : dHue *= 60.0;
166 :
167 739 : if( dHue < 0.0 )
168 0 : dHue += 360.0;
169 :
170 739 : nHue = (sal_uInt16) dHue;
171 : }
172 323371 : }
173 :
174 323371 : ColorData Color::HSBtoRGB( sal_uInt16 nHue, sal_uInt16 nSat, sal_uInt16 nBri )
175 : {
176 323371 : sal_uInt8 cR=0,cG=0,cB=0;
177 323371 : sal_uInt8 nB = (sal_uInt8) ( nBri * 255 / 100 );
178 :
179 323371 : if( nSat == 0 )
180 : {
181 322758 : cR = nB;
182 322758 : cG = nB;
183 322758 : cB = nB;
184 : }
185 : else
186 : {
187 613 : double dH = nHue;
188 : double f;
189 : sal_uInt16 n;
190 613 : if( dH == 360.0 )
191 0 : dH = 0.0;
192 :
193 613 : dH /= 60.0;
194 613 : n = (sal_uInt16) dH;
195 613 : f = dH - n;
196 :
197 613 : sal_uInt8 a = (sal_uInt8) ( nB * ( 100 - nSat ) / 100 );
198 613 : sal_uInt8 b = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * f ) ) / 100 );
199 613 : sal_uInt8 c = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * ( 1.0 - f ) ) ) / 100 );
200 :
201 613 : switch( n )
202 : {
203 0 : case 0: cR = nB; cG = c; cB = a; break;
204 0 : case 1: cR = b; cG = nB; cB = a; break;
205 0 : case 2: cR = a; cG = nB; cB = c; break;
206 0 : case 3: cR = a; cG = b; cB = nB; break;
207 613 : case 4: cR = c; cG = a; cB = nB; break;
208 0 : case 5: cR = nB; cG = a; cB = b; break;
209 : }
210 : }
211 :
212 323371 : return RGB_COLORDATA( cR, cG, cB );
213 : }
214 :
215 167112 : SvStream& Color::Read( SvStream& rIStm, bool bNewFormat )
216 : {
217 167112 : if ( bNewFormat )
218 167112 : rIStm.ReadUInt32( mnColor );
219 : else
220 0 : ReadColor( rIStm, *this );
221 :
222 167112 : return rIStm;
223 : }
224 :
225 218764 : SvStream& Color::Write( SvStream& rOStm, bool bNewFormat )
226 : {
227 218764 : if ( bNewFormat )
228 218764 : rOStm.WriteUInt32( mnColor );
229 : else
230 0 : WriteColor( rOStm, *this );
231 :
232 218764 : return rOStm;
233 : }
234 :
235 70 : OUString Color::AsRGBHexString()
236 : {
237 70 : std::stringstream ss;
238 70 : ss << std::hex << std::setfill ('0') << std::setw(6) << GetRGBColor();
239 70 : return OUString::createFromAscii(ss.str().c_str());
240 : }
241 :
242 : #define COL_NAME_USER ((sal_uInt16)0x8000)
243 :
244 3546 : SvStream& ReadColor( SvStream& rIStream, Color& rColor )
245 : {
246 : DBG_ASSERTWARNING( rIStream.GetVersion(), "Color::>> - Solar-Version not set on rIStream" );
247 :
248 : sal_uInt16 nColorName;
249 :
250 3546 : rIStream.ReadUInt16( nColorName );
251 :
252 3546 : if ( nColorName & COL_NAME_USER )
253 : {
254 : sal_uInt16 nRed;
255 : sal_uInt16 nGreen;
256 : sal_uInt16 nBlue;
257 :
258 3546 : rIStream.ReadUInt16( nRed );
259 3546 : rIStream.ReadUInt16( nGreen );
260 3546 : rIStream.ReadUInt16( nBlue );
261 :
262 3546 : rColor.mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
263 : }
264 : else
265 : {
266 : static const ColorData aColAry[] =
267 : {
268 : COL_BLACK, // COL_BLACK
269 : COL_BLUE, // COL_BLUE
270 : COL_GREEN, // COL_GREEN
271 : COL_CYAN, // COL_CYAN
272 : COL_RED, // COL_RED
273 : COL_MAGENTA, // COL_MAGENTA
274 : COL_BROWN, // COL_BROWN
275 : COL_GRAY, // COL_GRAY
276 : COL_LIGHTGRAY, // COL_LIGHTGRAY
277 : COL_LIGHTBLUE, // COL_LIGHTBLUE
278 : COL_LIGHTGREEN, // COL_LIGHTGREEN
279 : COL_LIGHTCYAN, // COL_LIGHTCYAN
280 : COL_LIGHTRED, // COL_LIGHTRED
281 : COL_LIGHTMAGENTA, // COL_LIGHTMAGENTA
282 : COL_YELLOW, // COL_YELLOW
283 : COL_WHITE, // COL_WHITE
284 : COL_WHITE, // COL_MENUBAR
285 : COL_BLACK, // COL_MENUBARTEXT
286 : COL_WHITE, // COL_POPUPMENU
287 : COL_BLACK, // COL_POPUPMENUTEXT
288 : COL_BLACK, // COL_WINDOWTEXT
289 : COL_WHITE, // COL_WINDOWWORKSPACE
290 : COL_BLACK, // COL_HIGHLIGHT
291 : COL_WHITE, // COL_HIGHLIGHTTEXT
292 : COL_BLACK, // COL_3DTEXT
293 : COL_LIGHTGRAY, // COL_3DFACE
294 : COL_WHITE, // COL_3DLIGHT
295 : COL_GRAY, // COL_3DSHADOW
296 : COL_LIGHTGRAY, // COL_SCROLLBAR
297 : COL_WHITE, // COL_FIELD
298 : COL_BLACK // COL_FIELDTEXT
299 : };
300 :
301 0 : if ( nColorName < (sizeof( aColAry )/sizeof(ColorData)) )
302 0 : rColor.mnColor = aColAry[nColorName];
303 : else
304 0 : rColor.mnColor = COL_BLACK;
305 : }
306 :
307 3546 : return rIStream;
308 : }
309 :
310 9734 : SvStream& WriteColor( SvStream& rOStream, const Color& rColor )
311 : {
312 : DBG_ASSERTWARNING( rOStream.GetVersion(), "Color::<< - Solar-Version not set on rOStream" );
313 :
314 9734 : sal_uInt16 nColorName = COL_NAME_USER;
315 9734 : sal_uInt16 nRed = rColor.GetRed();
316 9734 : sal_uInt16 nGreen = rColor.GetGreen();
317 9734 : sal_uInt16 nBlue = rColor.GetBlue();
318 9734 : nRed = (nRed<<8) + nRed;
319 9734 : nGreen = (nGreen<<8) + nGreen;
320 9734 : nBlue = (nBlue<<8) + nBlue;
321 :
322 9734 : rOStream.WriteUInt16( nColorName );
323 9734 : rOStream.WriteUInt16( nRed );
324 9734 : rOStream.WriteUInt16( nGreen );
325 9734 : rOStream.WriteUInt16( nBlue );
326 :
327 9734 : return rOStream;
328 : }
329 :
330 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|