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