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