1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tools.hxx"
26
27 #include <stdlib.h>
28 #include <vos/macros.hxx>
29 #include <tools/color.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/stream.hxx>
32 #include <tools/rc.hxx>
33 #include <tools/rcid.h>
34 #include <tools/resid.hxx>
35 #ifndef _SV_RC_H
36 #include <tools/rc.h>
37 #endif
38
39 // -----------
40 // - Inlines -
41 // -----------
42
_FRound(double fVal)43 static inline long _FRound( double fVal )
44 {
45 return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
46 }
47
48 // ---------
49 // - Color -
50 // ---------
51
Color(const ResId & rResId)52 Color::Color( const ResId& rResId )
53 {
54 rResId.SetRT( RSC_COLOR );
55 ResMgr* pResMgr = rResId.GetResMgr();
56 if ( pResMgr && pResMgr->GetResource( rResId ) )
57 {
58 // Header ueberspringen
59 pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
60
61 // Daten laden
62 sal_uInt16 nRed = pResMgr->ReadShort();
63 sal_uInt16 nGreen = pResMgr->ReadShort();
64 sal_uInt16 nBlue = pResMgr->ReadShort();
65 // one more historical sal_uIntPtr
66 pResMgr->ReadLong();
67
68 // RGB-Farbe
69 mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
70 }
71 else
72 {
73 mnColor = RGB_COLORDATA( 0, 0, 0 );
74 }
75 }
GetColorError(const Color & rCompareColor) const76 sal_uInt8 Color::GetColorError( const Color& rCompareColor ) const
77 {
78 const long nErrAbs = labs( (long) rCompareColor.GetRed() - GetRed() ) +
79 labs( (long) rCompareColor.GetGreen() - GetGreen() ) +
80 labs( (long) rCompareColor.GetBlue() - GetBlue() );
81
82 return (sal_uInt8) _FRound( nErrAbs * 0.3333333333 );
83 }
84
85 // -----------------------------------------------------------------------
86
IncreaseLuminance(sal_uInt8 cLumInc)87 void Color::IncreaseLuminance( sal_uInt8 cLumInc )
88 {
89 SetRed( (sal_uInt8) VOS_BOUND( (long) COLORDATA_RED( mnColor ) + cLumInc, 0L, 255L ) );
90 SetGreen( (sal_uInt8) VOS_BOUND( (long) COLORDATA_GREEN( mnColor ) + cLumInc, 0L, 255L ) );
91 SetBlue( (sal_uInt8) VOS_BOUND( (long) COLORDATA_BLUE( mnColor ) + cLumInc, 0L, 255L ) );
92 }
93
94 // -----------------------------------------------------------------------
95
DecreaseLuminance(sal_uInt8 cLumDec)96 void Color::DecreaseLuminance( sal_uInt8 cLumDec )
97 {
98 SetRed( (sal_uInt8) VOS_BOUND( (long) COLORDATA_RED( mnColor ) - cLumDec, 0L, 255L ) );
99 SetGreen( (sal_uInt8) VOS_BOUND( (long) COLORDATA_GREEN( mnColor ) - cLumDec, 0L, 255L ) );
100 SetBlue( (sal_uInt8) VOS_BOUND( (long) COLORDATA_BLUE( mnColor ) - cLumDec, 0L, 255L ) );
101 }
102
103 // -----------------------------------------------------------------------
104
IncreaseContrast(sal_uInt8 cContInc)105 void Color::IncreaseContrast( sal_uInt8 cContInc )
106 {
107 if( cContInc)
108 {
109 const double fM = 128.0 / ( 128.0 - 0.4985 * cContInc );
110 const double fOff = 128.0 - fM * 128.0;
111
112 SetRed( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_RED( mnColor ) * fM + fOff ), 0L, 255L ) );
113 SetGreen( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_GREEN( mnColor ) * fM + fOff ), 0L, 255L ) );
114 SetBlue( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_BLUE( mnColor ) * fM + fOff ), 0L, 255L ) );
115 }
116 }
117
118 // -----------------------------------------------------------------------
119
DecreaseContrast(sal_uInt8 cContDec)120 void Color::DecreaseContrast( sal_uInt8 cContDec )
121 {
122 if( cContDec )
123 {
124 const double fM = ( 128.0 - 0.4985 * cContDec ) / 128.0;
125 const double fOff = 128.0 - fM * 128.0;
126
127 SetRed( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_RED( mnColor ) * fM + fOff ), 0L, 255L ) );
128 SetGreen( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_GREEN( mnColor ) * fM + fOff ), 0L, 255L ) );
129 SetBlue( (sal_uInt8) VOS_BOUND( _FRound( COLORDATA_BLUE( mnColor ) * fM + fOff ), 0L, 255L ) );
130 }
131 }
132
133 // -----------------------------------------------------------------------
134
Invert()135 void Color::Invert()
136 {
137 SetRed( ~COLORDATA_RED( mnColor ) );
138 SetGreen( ~COLORDATA_GREEN( mnColor ) );
139 SetBlue( ~COLORDATA_BLUE( mnColor ) );
140 }
141
142 // -----------------------------------------------------------------------
143
IsDark() const144 sal_Bool Color::IsDark() const
145 {
146 return GetLuminance() <= 55;
147 }
148
149 // -----------------------------------------------------------------------
150
IsBright() const151 sal_Bool Color::IsBright() const
152 {
153 return GetLuminance() >= 245;
154 }
155
156 // -----------------------------------------------------------------------
157 // color space conversion
158 // -----------------------------------------------------------------------
159
RGBtoHSB(sal_uInt16 & nHue,sal_uInt16 & nSat,sal_uInt16 & nBri) const160 void Color::RGBtoHSB( sal_uInt16& nHue, sal_uInt16& nSat, sal_uInt16& nBri ) const
161 {
162 sal_uInt8 c[3];
163 sal_uInt8 cMax, cMin;
164
165 c[0] = GetRed();
166 c[1] = GetGreen();
167 c[2] = GetBlue();
168
169 cMax = c[0];
170 if( c[1] > cMax )
171 cMax = c[1];
172 if( c[2] > cMax )
173 cMax = c[2];
174
175 // Brightness = max(R, G, B);
176 nBri = cMax * 100 / 255;
177
178 cMin = c[0];
179 if( c[1] < cMin )
180 cMin = c[1];
181 if( c[2] < cMin )
182 cMin = c[2];
183
184 sal_uInt8 cDelta = cMax - cMin;
185
186 // Saturation = max - min / max
187 if( nBri > 0 )
188 nSat = cDelta * 100 / cMax;
189 else
190 nSat = 0;
191
192 if( nSat == 0 )
193 nHue = 0; // Default = undefined
194 else
195 {
196 double dHue = 0.0;
197
198 if( c[0] == cMax )
199 {
200 dHue = (double)( c[1] - c[2] ) / (double)cDelta;
201 }
202 else if( c[1] == cMax )
203 {
204 dHue = 2.0 + (double)( c[2] - c[0] ) / (double)cDelta;
205 }
206 else if ( c[2] == cMax )
207 {
208 dHue = 4.0 + (double)( c[0] - c[1] ) / (double)cDelta;
209 }
210 dHue *= 60.0;
211
212 if( dHue < 0.0 )
213 dHue += 360.0;
214
215 nHue = (sal_uInt16) dHue;
216 }
217 }
218
HSBtoRGB(sal_uInt16 nHue,sal_uInt16 nSat,sal_uInt16 nBri)219 ColorData Color::HSBtoRGB( sal_uInt16 nHue, sal_uInt16 nSat, sal_uInt16 nBri )
220 {
221 sal_uInt8 cR=0,cG=0,cB=0;
222 sal_uInt8 nB = (sal_uInt8) ( nBri * 255 / 100 );
223
224 if( nSat == 0 )
225 {
226 cR = nB;
227 cG = nB;
228 cB = nB;
229 }
230 else
231 {
232 double dH = nHue;
233 double f;
234 sal_uInt16 n;
235 if( dH == 360.0 )
236 dH = 0.0;
237
238 dH /= 60.0;
239 n = (sal_uInt16) dH;
240 f = dH - n;
241
242 sal_uInt8 a = (sal_uInt8) ( nB * ( 100 - nSat ) / 100 );
243 sal_uInt8 b = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * f ) ) / 100 );
244 sal_uInt8 c = (sal_uInt8) ( nB * ( 100 - ( (double)nSat * ( 1.0 - f ) ) ) / 100 );
245
246 switch( n )
247 {
248 case 0: cR = nB; cG = c; cB = a; break;
249 case 1: cR = b; cG = nB; cB = a; break;
250 case 2: cR = a; cG = nB; cB = c; break;
251 case 3: cR = a; cG = b; cB = nB; break;
252 case 4: cR = c; cG = a; cB = nB; break;
253 case 5: cR = nB; cG = a; cB = b; break;
254 }
255 }
256
257 return RGB_COLORDATA( cR, cG, cB );
258 }
259
260 // -----------------------------------------------------------------------
261
262 // CMYK values from 0 to 1
CMYKtoRGB(double fCyan,double fMagenta,double fYellow,double fKey)263 ColorData Color::CMYKtoRGB( double fCyan, double fMagenta, double fYellow, double fKey )
264 {
265 fCyan = (fCyan * ( 1.0 - fKey )) + fKey;
266 fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey;
267 fYellow = (fYellow * ( 1.0 - fKey )) + fKey;
268
269 sal_uInt8 nRed = static_cast< sal_uInt8 >( std::max( std::min( ( 1.0 - fCyan ) * 255.0, 255.0), 0.0 ) );
270 sal_uInt8 nGreen = static_cast< sal_uInt8 >( std::max( std::min( ( 1.0 - fMagenta ) * 255.0, 255.0), 0.0 ) );
271 sal_uInt8 nBlue = static_cast< sal_uInt8 >( std::max( std::min( ( 1.0 - fYellow ) * 255.0, 255.0), 0.0 ) );
272
273 return RGB_COLORDATA( nRed, nGreen, nBlue );
274 }
275
276 // -----------------------------------------------------------------------
277
278 // RGB values from 0 to 255
279 // CMY results from 0 to 1
RGBtoCMYK(double & fCyan,double & fMagenta,double & fYellow,double & fKey)280 void Color::RGBtoCMYK( double& fCyan, double& fMagenta, double& fYellow, double& fKey )
281 {
282 fCyan = 1 - ( GetRed() / 255.0 );
283 fMagenta = 1 - ( GetGreen() / 255.0 );
284 fYellow = 1 - ( GetBlue() / 255.0 );
285
286 //CMYK and CMY values from 0 to 1
287 fKey = 1.0;
288 if( fCyan < fKey ) fKey = fCyan;
289 if( fMagenta < fKey ) fKey = fMagenta;
290 if( fYellow < fKey ) fKey = fYellow;
291
292 if ( fKey == 1.0 )
293 {
294 //Black
295 fCyan = 0.0;
296 fMagenta = 0.0;
297 fYellow = 0.0;
298 }
299 else
300 {
301 fCyan = ( fCyan - fKey ) / ( 1.0 - fKey );
302 fMagenta = ( fMagenta - fKey ) / ( 1.0 - fKey );
303 fYellow = ( fYellow - fKey ) / ( 1.0 - fKey );
304 }
305 }
306
307 // -----------------------------------------------------------------------
308
Read(SvStream & rIStm,sal_Bool bNewFormat)309 SvStream& Color::Read( SvStream& rIStm, sal_Bool bNewFormat )
310 {
311 if ( bNewFormat )
312 rIStm >> mnColor;
313 else
314 rIStm >> *this;
315
316 return rIStm;
317 }
318
319 // -----------------------------------------------------------------------
320
Write(SvStream & rOStm,sal_Bool bNewFormat)321 SvStream& Color::Write( SvStream& rOStm, sal_Bool bNewFormat )
322 {
323 if ( bNewFormat )
324 rOStm << mnColor;
325 else
326 rOStm << *this;
327
328 return rOStm;
329 }
330
331 // -----------------------------------------------------------------------
332
333 #define COL_NAME_USER ((sal_uInt16)0x8000)
334 #define COL_RED_1B ((sal_uInt16)0x0001)
335 #define COL_RED_2B ((sal_uInt16)0x0002)
336 #define COL_GREEN_1B ((sal_uInt16)0x0010)
337 #define COL_GREEN_2B ((sal_uInt16)0x0020)
338 #define COL_BLUE_1B ((sal_uInt16)0x0100)
339 #define COL_BLUE_2B ((sal_uInt16)0x0200)
340
341 // -----------------------------------------------------------------------
342
operator >>(SvStream & rIStream,Color & rColor)343 SvStream& operator>>( SvStream& rIStream, Color& rColor )
344 {
345 DBG_ASSERTWARNING( rIStream.GetVersion(), "Color::>> - Solar-Version not set on rIStream" );
346
347 sal_uInt16 nColorName;
348 sal_uInt16 nRed;
349 sal_uInt16 nGreen;
350 sal_uInt16 nBlue;
351
352 rIStream >> nColorName;
353
354 if ( nColorName & COL_NAME_USER )
355 {
356 if ( rIStream.GetCompressMode() == COMPRESSMODE_FULL )
357 {
358 unsigned char cAry[6];
359 sal_uInt16 i = 0;
360
361 nRed = 0;
362 nGreen = 0;
363 nBlue = 0;
364
365 if ( nColorName & COL_RED_2B )
366 i += 2;
367 else if ( nColorName & COL_RED_1B )
368 i++;
369 if ( nColorName & COL_GREEN_2B )
370 i += 2;
371 else if ( nColorName & COL_GREEN_1B )
372 i++;
373 if ( nColorName & COL_BLUE_2B )
374 i += 2;
375 else if ( nColorName & COL_BLUE_1B )
376 i++;
377
378 rIStream.Read( cAry, i );
379 i = 0;
380
381 if ( nColorName & COL_RED_2B )
382 {
383 nRed = cAry[i];
384 nRed <<= 8;
385 i++;
386 nRed |= cAry[i];
387 i++;
388 }
389 else if ( nColorName & COL_RED_1B )
390 {
391 nRed = cAry[i];
392 nRed <<= 8;
393 i++;
394 }
395 if ( nColorName & COL_GREEN_2B )
396 {
397 nGreen = cAry[i];
398 nGreen <<= 8;
399 i++;
400 nGreen |= cAry[i];
401 i++;
402 }
403 else if ( nColorName & COL_GREEN_1B )
404 {
405 nGreen = cAry[i];
406 nGreen <<= 8;
407 i++;
408 }
409 if ( nColorName & COL_BLUE_2B )
410 {
411 nBlue = cAry[i];
412 nBlue <<= 8;
413 i++;
414 nBlue |= cAry[i];
415 i++;
416 }
417 else if ( nColorName & COL_BLUE_1B )
418 {
419 nBlue = cAry[i];
420 nBlue <<= 8;
421 i++;
422 }
423 }
424 else
425 {
426 rIStream >> nRed;
427 rIStream >> nGreen;
428 rIStream >> nBlue;
429 }
430
431 rColor.mnColor = RGB_COLORDATA( nRed>>8, nGreen>>8, nBlue>>8 );
432 }
433 else
434 {
435 static ColorData aColAry[] =
436 {
437 COL_BLACK, // COL_BLACK
438 COL_BLUE, // COL_BLUE
439 COL_GREEN, // COL_GREEN
440 COL_CYAN, // COL_CYAN
441 COL_RED, // COL_RED
442 COL_MAGENTA, // COL_MAGENTA
443 COL_BROWN, // COL_BROWN
444 COL_GRAY, // COL_GRAY
445 COL_LIGHTGRAY, // COL_LIGHTGRAY
446 COL_LIGHTBLUE, // COL_LIGHTBLUE
447 COL_LIGHTGREEN, // COL_LIGHTGREEN
448 COL_LIGHTCYAN, // COL_LIGHTCYAN
449 COL_LIGHTRED, // COL_LIGHTRED
450 COL_LIGHTMAGENTA, // COL_LIGHTMAGENTA
451 COL_YELLOW, // COL_YELLOW
452 COL_WHITE, // COL_WHITE
453 COL_WHITE, // COL_MENUBAR
454 COL_BLACK, // COL_MENUBARTEXT
455 COL_WHITE, // COL_POPUPMENU
456 COL_BLACK, // COL_POPUPMENUTEXT
457 COL_BLACK, // COL_WINDOWTEXT
458 COL_WHITE, // COL_WINDOWWORKSPACE
459 COL_BLACK, // COL_HIGHLIGHT
460 COL_WHITE, // COL_HIGHLIGHTTEXT
461 COL_BLACK, // COL_3DTEXT
462 COL_LIGHTGRAY, // COL_3DFACE
463 COL_WHITE, // COL_3DLIGHT
464 COL_GRAY, // COL_3DSHADOW
465 COL_LIGHTGRAY, // COL_SCROLLBAR
466 COL_WHITE, // COL_FIELD
467 COL_BLACK // COL_FIELDTEXT
468 };
469
470 if ( nColorName < (sizeof( aColAry )/sizeof(ColorData)) )
471 rColor.mnColor = aColAry[nColorName];
472 else
473 rColor.mnColor = COL_BLACK;
474 }
475
476 return rIStream;
477 }
478
479 // -----------------------------------------------------------------------
480
operator <<(SvStream & rOStream,const Color & rColor)481 SvStream& operator<<( SvStream& rOStream, const Color& rColor )
482 {
483 DBG_ASSERTWARNING( rOStream.GetVersion(), "Color::<< - Solar-Version not set on rOStream" );
484
485 sal_uInt16 nColorName = COL_NAME_USER;
486 sal_uInt16 nRed = rColor.GetRed();
487 sal_uInt16 nGreen = rColor.GetGreen();
488 sal_uInt16 nBlue = rColor.GetBlue();
489 nRed = (nRed<<8) + nRed;
490 nGreen = (nGreen<<8) + nGreen;
491 nBlue = (nBlue<<8) + nBlue;
492
493 if ( rOStream.GetCompressMode() == COMPRESSMODE_FULL )
494 {
495 unsigned char cAry[6];
496 sal_uInt16 i = 0;
497
498 if ( nRed & 0x00FF )
499 {
500 nColorName |= COL_RED_2B;
501 cAry[i] = (unsigned char)(nRed & 0xFF);
502 i++;
503 cAry[i] = (unsigned char)((nRed >> 8) & 0xFF);
504 i++;
505 }
506 else if ( nRed & 0xFF00 )
507 {
508 nColorName |= COL_RED_1B;
509 cAry[i] = (unsigned char)((nRed >> 8) & 0xFF);
510 i++;
511 }
512 if ( nGreen & 0x00FF )
513 {
514 nColorName |= COL_GREEN_2B;
515 cAry[i] = (unsigned char)(nGreen & 0xFF);
516 i++;
517 cAry[i] = (unsigned char)((nGreen >> 8) & 0xFF);
518 i++;
519 }
520 else if ( nGreen & 0xFF00 )
521 {
522 nColorName |= COL_GREEN_1B;
523 cAry[i] = (unsigned char)((nGreen >> 8) & 0xFF);
524 i++;
525 }
526 if ( nBlue & 0x00FF )
527 {
528 nColorName |= COL_BLUE_2B;
529 cAry[i] = (unsigned char)(nBlue & 0xFF);
530 i++;
531 cAry[i] = (unsigned char)((nBlue >> 8) & 0xFF);
532 i++;
533 }
534 else if ( nBlue & 0xFF00 )
535 {
536 nColorName |= COL_BLUE_1B;
537 cAry[i] = (unsigned char)((nBlue >> 8) & 0xFF);
538 i++;
539 }
540
541 rOStream << nColorName;
542 rOStream.Write( cAry, i );
543 }
544 else
545 {
546 rOStream << nColorName;
547 rOStream << nRed;
548 rOStream << nGreen;
549 rOStream << nBlue;
550 }
551
552 return rOStream;
553 }
554