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 0 : static inline long _FRound( double fVal )
31 : {
32 0 : return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
33 : }
34 :
35 0 : Color::Color( const ResId& rResId )
36 : {
37 0 : rResId.SetRT( RSC_COLOR );
38 0 : ResMgr* pResMgr = rResId.GetResMgr();
39 0 : if ( pResMgr && pResMgr->GetResource( rResId ) )
40 : {
41 : // Header ueberspringen
42 0 : pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
43 :
44 : // Daten laden
45 0 : sal_uInt16 nRed = pResMgr->ReadShort();
46 0 : sal_uInt16 nGreen = pResMgr->ReadShort();
47 0 : sal_uInt16 nBlue = pResMgr->ReadShort();
48 : // one more historical sal_uIntPtr
49 0 : pResMgr->ReadLong();
50 :
51 : // RGB-Farbe
52 0 : mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
53 : }
54 : else
55 : {
56 0 : mnColor = RGB_COLORDATA( 0, 0, 0 );
57 : }
58 0 : }
59 :
60 0 : sal_uInt8 Color::GetColorError( const Color& rCompareColor ) const
61 : {
62 0 : const long nErrAbs = labs( (long) rCompareColor.GetRed() - GetRed() ) +
63 0 : labs( (long) rCompareColor.GetGreen() - GetGreen() ) +
64 0 : labs( (long) rCompareColor.GetBlue() - GetBlue() );
65 :
66 0 : return (sal_uInt8) _FRound( nErrAbs * 0.3333333333 );
67 : }
68 :
69 0 : void Color::IncreaseLuminance( sal_uInt8 cLumInc )
70 : {
71 0 : SetRed( (sal_uInt8) SAL_BOUND( (long) COLORDATA_RED( mnColor ) + cLumInc, 0L, 255L ) );
72 0 : SetGreen( (sal_uInt8) SAL_BOUND( (long) COLORDATA_GREEN( mnColor ) + cLumInc, 0L, 255L ) );
73 0 : SetBlue( (sal_uInt8) SAL_BOUND( (long) COLORDATA_BLUE( mnColor ) + cLumInc, 0L, 255L ) );
74 0 : }
75 :
76 0 : void Color::DecreaseLuminance( sal_uInt8 cLumDec )
77 : {
78 0 : SetRed( (sal_uInt8) SAL_BOUND( (long) COLORDATA_RED( mnColor ) - cLumDec, 0L, 255L ) );
79 0 : SetGreen( (sal_uInt8) SAL_BOUND( (long) COLORDATA_GREEN( mnColor ) - cLumDec, 0L, 255L ) );
80 0 : SetBlue( (sal_uInt8) SAL_BOUND( (long) COLORDATA_BLUE( mnColor ) - cLumDec, 0L, 255L ) );
81 0 : }
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 0 : bool Color::IsDark() const
104 : {
105 0 : return GetLuminance() <= 60;
106 : }
107 :
108 0 : bool Color::IsBright() const
109 : {
110 0 : return GetLuminance() >= 245;
111 : }
112 :
113 : // color space conversion
114 :
115 0 : 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 0 : c[0] = GetRed();
121 0 : c[1] = GetGreen();
122 0 : c[2] = GetBlue();
123 :
124 0 : cMax = c[0];
125 0 : if( c[1] > cMax )
126 0 : cMax = c[1];
127 0 : if( c[2] > cMax )
128 0 : cMax = c[2];
129 :
130 : // Brightness = max(R, G, B);
131 0 : nBri = cMax * 100 / 255;
132 :
133 0 : cMin = c[0];
134 0 : if( c[1] < cMin )
135 0 : cMin = c[1];
136 0 : if( c[2] < cMin )
137 0 : cMin = c[2];
138 :
139 0 : sal_uInt8 cDelta = cMax - cMin;
140 :
141 : // Saturation = max - min / max
142 0 : if( nBri > 0 )
143 0 : nSat = cDelta * 100 / cMax;
144 : else
145 0 : nSat = 0;
146 :
147 0 : if( nSat == 0 )
148 0 : nHue = 0; // Default = undefined
149 : else
150 : {
151 0 : double dHue = 0.0;
152 :
153 0 : if( c[0] == cMax )
154 : {
155 0 : dHue = (double)( c[1] - c[2] ) / (double)cDelta;
156 : }
157 0 : else if( c[1] == cMax )
158 : {
159 0 : dHue = 2.0 + (double)( c[2] - c[0] ) / (double)cDelta;
160 : }
161 0 : else if ( c[2] == cMax )
162 : {
163 0 : dHue = 4.0 + (double)( c[0] - c[1] ) / (double)cDelta;
164 : }
165 0 : dHue *= 60.0;
166 :
167 0 : if( dHue < 0.0 )
168 0 : dHue += 360.0;
169 :
170 0 : nHue = (sal_uInt16) dHue;
171 : }
172 0 : }
173 :
174 0 : ColorData Color::HSBtoRGB( sal_uInt16 nHue, sal_uInt16 nSat, sal_uInt16 nBri )
175 : {
176 0 : sal_uInt8 cR=0,cG=0,cB=0;
177 0 : sal_uInt8 nB = (sal_uInt8) ( nBri * 255 / 100 );
178 :
179 0 : if( nSat == 0 )
180 : {
181 0 : cR = nB;
182 0 : cG = nB;
183 0 : cB = nB;
184 : }
185 : else
186 : {
187 0 : double dH = nHue;
188 : double f;
189 : sal_uInt16 n;
190 0 : if( dH == 360.0 )
191 0 : dH = 0.0;
192 :
193 0 : dH /= 60.0;
194 0 : n = (sal_uInt16) dH;
195 0 : f = dH - n;
196 :
197 0 : sal_uInt8 a = (sal_uInt8) ( nB * ( 100 - nSat ) / 100 );
198 0 : sal_uInt8 b = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * f ) ) / 100 );
199 0 : sal_uInt8 c = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * ( 1.0 - f ) ) ) / 100 );
200 :
201 0 : 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 0 : case 4: cR = c; cG = a; cB = nB; break;
208 0 : case 5: cR = nB; cG = a; cB = b; break;
209 : }
210 : }
211 :
212 0 : return RGB_COLORDATA( cR, cG, cB );
213 : }
214 :
215 0 : SvStream& Color::Read( SvStream& rIStm, bool bNewFormat )
216 : {
217 0 : if ( bNewFormat )
218 0 : rIStm.ReadUInt32( mnColor );
219 : else
220 0 : ReadColor( rIStm, *this );
221 :
222 0 : return rIStm;
223 : }
224 :
225 0 : SvStream& Color::Write( SvStream& rOStm, bool bNewFormat )
226 : {
227 0 : if ( bNewFormat )
228 0 : rOStm.WriteUInt32( mnColor );
229 : else
230 0 : WriteColor( rOStm, *this );
231 :
232 0 : return rOStm;
233 : }
234 :
235 : #define COL_NAME_USER ((sal_uInt16)0x8000)
236 :
237 0 : SvStream& ReadColor( SvStream& rIStream, Color& rColor )
238 : {
239 : DBG_ASSERTWARNING( rIStream.GetVersion(), "Color::>> - Solar-Version not set on rIStream" );
240 :
241 : sal_uInt16 nColorName;
242 :
243 0 : rIStream.ReadUInt16( nColorName );
244 :
245 0 : if ( nColorName & COL_NAME_USER )
246 : {
247 : sal_uInt16 nRed;
248 : sal_uInt16 nGreen;
249 : sal_uInt16 nBlue;
250 :
251 0 : rIStream.ReadUInt16( nRed );
252 0 : rIStream.ReadUInt16( nGreen );
253 0 : rIStream.ReadUInt16( nBlue );
254 :
255 0 : rColor.mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
256 : }
257 : else
258 : {
259 : static const ColorData aColAry[] =
260 : {
261 : COL_BLACK, // COL_BLACK
262 : COL_BLUE, // COL_BLUE
263 : COL_GREEN, // COL_GREEN
264 : COL_CYAN, // COL_CYAN
265 : COL_RED, // COL_RED
266 : COL_MAGENTA, // COL_MAGENTA
267 : COL_BROWN, // COL_BROWN
268 : COL_GRAY, // COL_GRAY
269 : COL_LIGHTGRAY, // COL_LIGHTGRAY
270 : COL_LIGHTBLUE, // COL_LIGHTBLUE
271 : COL_LIGHTGREEN, // COL_LIGHTGREEN
272 : COL_LIGHTCYAN, // COL_LIGHTCYAN
273 : COL_LIGHTRED, // COL_LIGHTRED
274 : COL_LIGHTMAGENTA, // COL_LIGHTMAGENTA
275 : COL_YELLOW, // COL_YELLOW
276 : COL_WHITE, // COL_WHITE
277 : COL_WHITE, // COL_MENUBAR
278 : COL_BLACK, // COL_MENUBARTEXT
279 : COL_WHITE, // COL_POPUPMENU
280 : COL_BLACK, // COL_POPUPMENUTEXT
281 : COL_BLACK, // COL_WINDOWTEXT
282 : COL_WHITE, // COL_WINDOWWORKSPACE
283 : COL_BLACK, // COL_HIGHLIGHT
284 : COL_WHITE, // COL_HIGHLIGHTTEXT
285 : COL_BLACK, // COL_3DTEXT
286 : COL_LIGHTGRAY, // COL_3DFACE
287 : COL_WHITE, // COL_3DLIGHT
288 : COL_GRAY, // COL_3DSHADOW
289 : COL_LIGHTGRAY, // COL_SCROLLBAR
290 : COL_WHITE, // COL_FIELD
291 : COL_BLACK // COL_FIELDTEXT
292 : };
293 :
294 0 : if ( nColorName < (sizeof( aColAry )/sizeof(ColorData)) )
295 0 : rColor.mnColor = aColAry[nColorName];
296 : else
297 0 : rColor.mnColor = COL_BLACK;
298 : }
299 :
300 0 : return rIStream;
301 : }
302 :
303 0 : SvStream& WriteColor( SvStream& rOStream, const Color& rColor )
304 : {
305 : DBG_ASSERTWARNING( rOStream.GetVersion(), "Color::<< - Solar-Version not set on rOStream" );
306 :
307 0 : sal_uInt16 nColorName = COL_NAME_USER;
308 0 : sal_uInt16 nRed = rColor.GetRed();
309 0 : sal_uInt16 nGreen = rColor.GetGreen();
310 0 : sal_uInt16 nBlue = rColor.GetBlue();
311 0 : nRed = (nRed<<8) + nRed;
312 0 : nGreen = (nGreen<<8) + nGreen;
313 0 : nBlue = (nBlue<<8) + nBlue;
314 :
315 0 : rOStream.WriteUInt16( nColorName );
316 0 : rOStream.WriteUInt16( nRed );
317 0 : rOStream.WriteUInt16( nGreen );
318 0 : rOStream.WriteUInt16( nBlue );
319 :
320 0 : return rOStream;
321 : }
322 :
323 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|