1/** <title>NSColor</title> 2 3 <abstract>The colorful color class</abstract> 4 5 Copyright (C) 1996, 1998, 2001, 2002 Free Software Foundation, Inc. 6 7 Author: Scott Christley <scottc@net-community.com> 8 Date: 1996 9 Author: Fred Kiefer <fredkiefer@gmx.de> 10 Date: 2001, 2002 11 12 This file is part of the GNUstep GUI Library. 13 14 This library is free software; you can redistribute it and/or 15 modify it under the terms of the GNU Lesser General Public 16 License as published by the Free Software Foundation; either 17 version 2 of the License, or (at your option) any later version. 18 19 This library is distributed in the hope that it will be useful, 20 but WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 Lesser General Public License for more details. 23 24 You should have received a copy of the GNU Lesser General Public 25 License along with this library; see the file COPYING.LIB. 26 If not, see <http://www.gnu.org/licenses/> or write to the 27 Free Software Foundation, 51 Franklin Street, Fifth Floor, 28 Boston, MA 02110-1301, USA. 29*/ 30 31#import "config.h" 32#import <Foundation/NSString.h> 33#import <Foundation/NSArchiver.h> 34#import <Foundation/NSDictionary.h> 35#import <Foundation/NSException.h> 36#import <Foundation/NSLock.h> 37#import <Foundation/NSNotification.h> 38#import <Foundation/NSUserDefaults.h> 39#import <Foundation/NSBundle.h> 40#import <Foundation/NSDebug.h> 41#import <Foundation/NSScanner.h> 42 43#import "AppKit/NSBezierPath.h" 44#import "AppKit/NSColor.h" 45#import "AppKit/NSColorList.h" 46#import "AppKit/NSColorSpace.h" 47#import "AppKit/NSPasteboard.h" 48#import "AppKit/NSView.h" 49#import "AppKit/NSImage.h" 50#import "AppKit/NSGraphics.h" 51#import "AppKit/PSOperators.h" 52#import "GNUstepGUI/GSTheme.h" 53#import "GSGuiPrivate.h" 54 55static Class NSColorClass; 56 57/* This interface must be provided in NSColorList to let us manage 58 * system colors. 59 */ 60@interface NSColorList (GNUstepPrivate) 61+ (void) _setDefaultSystemColorList: (NSColorList*)aList; 62+ (void) _setThemeSystemColorList: (NSColorList*)aList; 63@end 64 65 66@interface GSNamedColor : NSColor 67{ 68 NSString *_catalog_name; 69 NSString *_color_name; 70 NSString *_cached_name_space; 71 NSColor *_cached_color; 72} 73 74- (NSColor*) initWithCatalogName: (NSString *)listName 75 colorName: (NSString *)colorName; 76- (void) recache; 77 78@end 79 80@interface GSWhiteColor : NSColor 81{ 82 CGFloat _white_component; 83 CGFloat _alpha_component; 84} 85 86@end 87 88@interface GSDeviceWhiteColor : GSWhiteColor 89 90- (NSColor*) initWithDeviceWhite: (CGFloat)white 91 alpha: (CGFloat)alpha; 92 93@end 94 95@interface GSCalibratedWhiteColor : GSWhiteColor 96 97- (NSColor*) initWithCalibratedWhite: (CGFloat)white 98 alpha: (CGFloat)alpha; 99 100@end 101 102@interface GSDeviceCMYKColor : NSColor 103{ 104 CGFloat _cyan_component; 105 CGFloat _magenta_component; 106 CGFloat _yellow_component; 107 CGFloat _black_component; 108 CGFloat _alpha_component; 109} 110 111- (NSColor*) initWithDeviceCyan: (CGFloat)cyan 112 magenta: (CGFloat)magenta 113 yellow: (CGFloat)yellow 114 black: (CGFloat)black 115 alpha: (CGFloat)alpha; 116 117@end 118 119@interface GSRGBColor : NSColor 120{ 121 CGFloat _red_component; 122 CGFloat _green_component; 123 CGFloat _blue_component; 124 CGFloat _hue_component; 125 CGFloat _saturation_component; 126 CGFloat _brightness_component; 127 CGFloat _alpha_component; 128} 129 130@end 131 132@interface GSDeviceRGBColor : GSRGBColor 133 134- (NSColor*) initWithDeviceRed: (CGFloat)red 135 green: (CGFloat)green 136 blue: (CGFloat)blue 137 alpha: (CGFloat)alpha; 138- (NSColor*) initWithDeviceHue: (CGFloat)hue 139 saturation: (CGFloat)saturation 140 brightness: (CGFloat)brightness 141 alpha: (CGFloat)alpha; 142 143@end 144 145@interface GSCalibratedRGBColor : GSRGBColor 146 147- (NSColor*) initWithCalibratedRed: (CGFloat)red 148 green: (CGFloat)green 149 blue: (CGFloat)blue 150 alpha: (CGFloat)alpha; 151- (NSColor*) initWithCalibratedHue: (CGFloat)hue 152 saturation: (CGFloat)saturation 153 brightness: (CGFloat)brightness 154 alpha: (CGFloat)alpha; 155@end 156 157// FIXME: This is not described in the specification 158@interface GSPatternColor : NSColor 159{ 160 NSImage *_pattern; 161} 162 163- (NSColor*) initWithPatternImage: (NSImage*) pattern; 164 165@end 166 167@interface NSColor (GNUstepPrivate) 168 169+ (NSColor*) colorFromString: (NSString*)string; 170+ (void) defaultsDidChange: (NSNotification*)notification; 171+ (void) themeDidActivate: (NSNotification*)notification; 172 173@end 174 175// Class variables 176static BOOL gnustep_gui_ignores_alpha = YES; 177static NSColorList *systemColors = nil; 178static NSColorList *defaultSystemColors = nil; 179static NSMutableDictionary *colorStrings = nil; 180static NSMutableDictionary *systemDict = nil; 181 182static 183void initSystemColors(void) 184{ 185 NSString *white; 186 NSString *lightGray; 187 NSString *gray; 188 NSString *darkGray; 189 NSString *black; 190 NSString *lightYellow; 191 192 // Set up a dictionary containing the names of all the system colors 193 // as keys and with colors in string format as values. 194 white = [NSString stringWithFormat: @"%g %g %g", 195 (double)NSWhite, (double)NSWhite, (double)NSWhite]; 196 lightGray = [NSString stringWithFormat: @"%g %g %g", 197 (double)NSLightGray, (double)NSLightGray, (double)NSLightGray]; 198 gray = [NSString stringWithFormat: @"%g %g %g", 199 (double)NSGray, (double)NSGray, (double)NSGray]; 200 darkGray = [NSString stringWithFormat: @"%g %g %g", 201 (double)NSDarkGray, (double)NSDarkGray, (double)NSDarkGray]; 202 black = [NSString stringWithFormat: @"%g %g %g", 203 (double)NSBlack, (double)NSBlack, (double)NSBlack]; 204 lightYellow = @"1.0 1.0 0.9"; 205 206 colorStrings = [[NSMutableDictionary alloc] 207 initWithObjectsAndKeys: 208 black, @"alternateSelectedControlColor", 209 white, @"alternateSelectedControlTextColor", 210 lightGray, @"controlBackgroundColor", 211 lightGray, @"controlColor", 212 black, @"controlDarkShadowColor", 213 lightGray, @"controlHighlightColor", 214 white, @"controlLightHighlightColor", 215 darkGray, @"controlShadowColor", 216 black, @"controlTextColor", 217 darkGray, @"disabledControlTextColor", 218 gray, @"gridColor", 219 lightGray, @"headerColor", 220 black, @"headerTextColor", 221 white, @"highlightColor", 222 black, @"keyboardFocusIndicatorColor", 223 lightGray, @"knobColor", 224 black, @"labelColor", 225 black, @"quaternaryLabelColor", 226 gray, @"scrollBarColor", 227 black, @"secondaryLabelColor", 228 lightGray, @"secondarySelectedControlColor", 229 white, @"selectedControlColor", 230 black, @"selectedControlTextColor", 231 lightGray, @"selectedKnobColor", 232 white, @"selectedMenuItemColor", 233 black, @"selectedMenuItemTextColor", 234 lightGray, @"selectedTextBackgroundColor", 235 black, @"selectedTextColor", 236 black, @"shadowColor", 237 black, @"tertiaryLabelColor", 238 white, @"textBackgroundColor", 239 black, @"textColor", 240 lightGray, @"windowBackgroundColor", 241 black, @"windowFrameColor", 242 white, @"windowFrameTextColor", 243 244 white, @"rowBackgroundColor", 245 lightGray, @"alternateRowBackgroundColor", 246 247 lightYellow, @"toolTipColor", 248 black, @"toolTipTextColor", 249 250 nil]; 251 252 systemColors = RETAIN([NSColorList colorListNamed: @"System"]); 253 defaultSystemColors = [[NSColorList alloc] initWithName: @"System"]; 254 [NSColorList _setDefaultSystemColorList: defaultSystemColors]; 255 if (systemColors == nil) 256 { 257 ASSIGN(systemColors, defaultSystemColors); 258 } 259 260 { 261 NSEnumerator *enumerator; 262 NSString *key; 263 264 // Set up default system colors 265 266 enumerator = [colorStrings keyEnumerator]; 267 268 while ((key = (NSString *)[enumerator nextObject])) 269 { 270 NSColor *color; 271 272 if ((color = [systemColors colorWithKey: key]) == nil) 273 { 274 NSString *aColorString; 275 276 aColorString = [colorStrings objectForKey: key]; 277 color = [NSColorClass colorFromString: aColorString]; 278 279 NSCAssert1(color, @"couldn't get default system color %@", key); 280 [systemColors setColor: color forKey: key]; 281 } 282 if (defaultSystemColors != systemColors) 283 { 284 [defaultSystemColors setColor: color forKey: key]; 285 } 286 } 287 } 288 289 systemDict = [NSMutableDictionary new]; 290} 291 292static NSColor* 293systemColorWithName(NSString *name) 294{ 295 NSColor *col = [systemDict objectForKey: name]; 296 297 if (col == nil) 298 { 299 col = [NSColor colorWithCatalogName: @"System" colorName: name]; 300 [systemDict setObject: col forKey: name]; 301 } 302 303 return col; 304} 305 306/** 307 *<p>TODO NSColor description</p> 308 * 309 */ 310@implementation NSColor 311 312// 313// Class methods 314// 315+ (void) initialize 316{ 317 if (self == [NSColor class]) 318 { 319 NSColorClass = self; 320 321 // Set the version number 322 [self setVersion: 3]; 323 324 // ignore alpha by default 325 gnustep_gui_ignores_alpha = YES; 326 327 // Load or define the system colour list 328 initSystemColors(); 329 330 // ensure user defaults are loaded, then use them and watch for changes. 331 [self defaultsDidChange: nil]; 332 [[NSNotificationCenter defaultCenter] 333 addObserver: self 334 selector: @selector(defaultsDidChange:) 335 name: NSUserDefaultsDidChangeNotification 336 object: nil]; 337 // watch for themes which may provide new system color lists 338 [[NSNotificationCenter defaultCenter] 339 addObserver: self 340 selector: @selector(themeDidActivate:) 341 name: GSThemeDidActivateNotification 342 object: nil]; 343 } 344} 345 346/**<p>Creates and returns a new NSColor in a NSCalibratedRGBColorSpace space 347 name, with hue, saturation, brightness and alpha as specified. Valid values 348 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 349*/ 350+ (NSColor*) colorWithCalibratedHue: (CGFloat)hue 351 saturation: (CGFloat)saturation 352 brightness: (CGFloat)brightness 353 alpha: (CGFloat)alpha 354{ 355 id color; 356 357 color = [GSCalibratedRGBColor allocWithZone: NSDefaultMallocZone()]; 358 color = [color initWithCalibratedHue: hue 359 saturation: saturation 360 brightness: brightness 361 alpha: alpha]; 362 363 return AUTORELEASE(color); 364} 365 366 367/**<p>Creates and returns a new NSColor in a NSCalibratedRGBColorSpace space 368 name, with red, green, blue and alpha as specified. Valid values 369 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 370*/ 371+ (NSColor*) colorWithCalibratedRed: (CGFloat)red 372 green: (CGFloat)green 373 blue: (CGFloat)blue 374 alpha: (CGFloat)alpha 375{ 376 id color; 377 378 color = [GSCalibratedRGBColor allocWithZone: NSDefaultMallocZone()]; 379 color = [color initWithCalibratedRed: red 380 green: green 381 blue: blue 382 alpha: alpha]; 383 return AUTORELEASE(color); 384} 385 386 387/**<p>Creates and returns a new NSColor in a NSCalibratedWhiteColorSpace space 388 name, with red, green, blue and alpha as specified. Valid values 389 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 390*/ 391+ (NSColor*) colorWithCalibratedWhite: (CGFloat)white 392 alpha: (CGFloat)alpha 393{ 394 id color; 395 396 color = [GSCalibratedWhiteColor allocWithZone: NSDefaultMallocZone()] ; 397 color = [color initWithCalibratedWhite: white 398 alpha: alpha]; 399 400 return AUTORELEASE(color); 401} 402 403/** 404 * <p> TODO </p> 405 */ 406+ (NSColor*) colorWithCatalogName: (NSString *)listName 407 colorName: (NSString *)colorName 408{ 409 id color; 410 411 color = [GSNamedColor allocWithZone: NSDefaultMallocZone()] ; 412 color = [color initWithCatalogName: listName 413 colorName: colorName]; 414 415 return AUTORELEASE(color); 416} 417 418/**<p>Creates and returns a new NSColor in a NSDeviceCMYKColorSpace space 419 name, with cyan, magenta, yellow, black and alpha as specified. Valid values 420 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 421*/ 422+ (NSColor*) colorWithDeviceCyan: (CGFloat)cyan 423 magenta: (CGFloat)magenta 424 yellow: (CGFloat)yellow 425 black: (CGFloat)black 426 alpha: (CGFloat)alpha 427{ 428 id color; 429 430 color = [GSDeviceCMYKColor allocWithZone: NSDefaultMallocZone()]; 431 color = [color initWithDeviceCyan: cyan 432 magenta: magenta 433 yellow: yellow 434 black: black 435 alpha: alpha]; 436 437 return AUTORELEASE(color); 438} 439 440 441/**<p>Creates and returns a new NSColor in a NSDeviceCMYKColorSpace space 442 name, with hue, saturation, brightness and alpha as specified. Valid values 443 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 444*/ 445+ (NSColor*) colorWithDeviceHue: (CGFloat)hue 446 saturation: (CGFloat)saturation 447 brightness: (CGFloat)brightness 448 alpha: (CGFloat)alpha 449{ 450 id color; 451 452 color = [GSDeviceRGBColor allocWithZone: NSDefaultMallocZone()]; 453 color = [color initWithDeviceHue: hue 454 saturation: saturation 455 brightness: brightness 456 alpha: alpha]; 457 458 return AUTORELEASE(color); 459} 460 461/**<p>Creates and returns a new NSColor in a NSDeviceCMYKColorSpace space 462 name, with red, green, blue and alpha as specified. Valid values 463 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 464*/ 465+ (NSColor*) colorWithDeviceRed: (CGFloat)red 466 green: (CGFloat)green 467 blue: (CGFloat)blue 468 alpha: (CGFloat)alpha 469{ 470 id color; 471 472 color = [GSDeviceRGBColor allocWithZone: NSDefaultMallocZone()]; 473 color = [color initWithDeviceRed: red 474 green: green 475 blue: blue 476 alpha: alpha]; 477 478 return AUTORELEASE(color); 479} 480 481/**<p>Creates and returns a new NSColor in a NSDeviceWhiteColorSpace space 482 name, with red, green, blue and alpha as specified. Valid values 483 are the range 0.0 to 1.0. Out of range values will be clipped.</p> 484*/ 485+ (NSColor*) colorWithDeviceWhite: (CGFloat)white 486 alpha: (CGFloat)alpha 487{ 488 id color; 489 490 color = [GSDeviceWhiteColor allocWithZone: NSDefaultMallocZone()]; 491 color = [color initWithDeviceWhite: white 492 alpha: alpha]; 493 494 return AUTORELEASE(color); 495} 496 497+ (NSColor*) colorForControlTint: (NSControlTint)controlTint 498{ 499 switch (controlTint) 500 { 501 default: 502 case NSDefaultControlTint: 503 return [self colorForControlTint: [self currentControlTint]]; 504 case NSGraphiteControlTint: 505 // FIXME 506 case NSClearControlTint: 507 // FIXME 508 case NSBlueControlTint: 509 return [NSColor blueColor]; 510 } 511} 512 513+ (NSControlTint) currentControlTint 514{ 515 // FIXME: should be made a system setting 516 return NSBlueControlTint; 517} 518 519+ (NSColor*) colorWithPatternImage: (NSImage*)image 520{ 521 id color; 522 523 color = [GSPatternColor allocWithZone: NSDefaultMallocZone()]; 524 color = [color initWithPatternImage: image]; 525 526 return AUTORELEASE(color); 527} 528 529 530/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 531 with white and alpha values set as NSBlack and 1.0 respectively.</p> 532 <p>See Also : +colorWithCalibratedWhite:alpha:</p> 533*/ 534+ (NSColor*) blackColor 535{ 536 return [self colorWithCalibratedWhite: NSBlack alpha: 1.0]; 537} 538 539 540/**<p>Returns an NSColor in a NSCalibratedRGBColorSpace space name. 541 with red, green, blue and alpha values set as 0.0, 0.0, 1.0 and 1.0 542 respectively.</p><p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 543*/ 544+ (NSColor*) blueColor 545{ 546 return [self colorWithCalibratedRed: 0.0 547 green: 0.0 548 blue: 1.0 549 alpha: 1.0]; 550} 551 552/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 553 with red, green, blue and alpha values set as 0.6, 0.4, 0.2 and 1.0 554 respectively.</p><p>See Also: +colorWithCalibratedRed:green:blue:alpha:</p> 555*/ 556+ (NSColor*) brownColor 557{ 558 return [self colorWithCalibratedRed: 0.6 559 green: 0.4 560 blue: 0.2 561 alpha: 1.0]; 562} 563 564/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 565 with white and alpha values set as 0.0 and 1.0 respectively.</p> 566 <p>See Also : +colorWithCalibratedWhite:alpha:</p> 567*/ 568+ (NSColor*) clearColor 569{ 570 return [self colorWithCalibratedWhite: 0.0 alpha: 0.0]; 571} 572 573 574/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 575 with red, green, blue and alpha values set as 0.0, 1.0, 1.0 and 1.0 576 respectively.</p><p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 577*/ 578+ (NSColor*) cyanColor 579{ 580 return [self colorWithCalibratedRed: 0.0 581 green: 1.0 582 blue: 1.0 583 alpha: 1.0]; 584} 585 586/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 587 with white and alpha values set as NSDarkGray and 1.0 respectively. </p> 588 <p>See Also : +colorWithCalibratedWhite:alpha:</p> 589*/ 590+ (NSColor*) darkGrayColor 591{ 592 return [self colorWithCalibratedWhite: NSDarkGray alpha: 1.0]; 593} 594 595/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 596 with white and alpha values set as NSGray and 1.0 respectively. </p> 597 <p>See Also: +colorWithCalibratedWhite:alpha:</p> 598*/ 599+ (NSColor*) grayColor 600{ 601 return [self colorWithCalibratedWhite: NSGray alpha: 1.0]; 602} 603 604/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 605 with red, green, blue and alpha values set as 0.0, 1.0, 0.0 and 1.0 606 respectively </p><p>See Also: +colorWithCalibratedRed:green:blue:alpha:</p> 607*/ 608+ (NSColor*) greenColor 609{ 610 return [self colorWithCalibratedRed: 0.0 611 green: 1.0 612 blue: 0.0 613 alpha: 1.0]; 614} 615 616/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 617 with white and alpha values set as NSLightGray and 1.0 respectively </p> 618 <p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 619*/ 620+ (NSColor*) lightGrayColor 621{ 622 return [self colorWithCalibratedWhite: NSLightGray alpha: 1]; 623} 624 625/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 626 with red, green, blue and alpha values set as 1.0, 0.0, 1.0 and 1.0 627 respectively.</p><p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 628*/ 629+ (NSColor*) magentaColor 630{ 631 return [self colorWithCalibratedRed: 1.0 632 green: 0.0 633 blue: 1.0 634 alpha: 1.0]; 635} 636 637 638/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 639 with red, green, blue and alpha values set as 1.0, 0.5, 0.0 and 1.0 640 respectively.</p><p>See Also: +colorWithCalibratedRed:green:blue:alpha:</p> 641*/ 642+ (NSColor*) orangeColor 643{ 644 return [self colorWithCalibratedRed: 1.0 645 green: 0.5 646 blue: 0.0 647 alpha: 1.0]; 648} 649 650 651/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 652 with red, green, blue and alpha values set as 0.5, 0.0, 0.5 and 1.0 653 respectively.</p><p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 654*/ 655+ (NSColor*) purpleColor 656{ 657 return [self colorWithCalibratedRed: 0.5 658 green: 0.0 659 blue: 0.5 660 alpha: 1.0]; 661} 662 663 664/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 665 with red, green, blue and alpha values set as 1.0, 0.0, 0.0 and 1.0 666 respectively </p><p>See Also: +colorWithCalibratedRed:green:blue:alpha:</p> 667*/ 668+ (NSColor*) redColor 669{ 670 return [self colorWithCalibratedRed: 1.0 671 green: 0.0 672 blue: 0.0 673 alpha: 1.0]; 674} 675 676/**<p>Returns a NSColor in a NSCalibratedWhiteColorSpace space name. 677 with white and alpha values set as NSWhite and 1.0 respectively. </p> 678 <p>See Also : +colorWithCalibratedWhite:alpha:</p> 679*/ 680+ (NSColor*) whiteColor 681{ 682 return [self colorWithCalibratedWhite: NSWhite alpha: 1.0]; 683} 684 685 686/**<p>Returns a NSColor in a NSCalibratedRGBColorSpace space name. 687 with red, green, blue and alpha values set as 1.0, 0.0, 0.0 and 1.0 688 respectively.</p><p>See Also : +colorWithCalibratedRed:green:blue:alpha:</p> 689*/ 690+ (NSColor*) yellowColor 691{ 692 return [self colorWithCalibratedRed: 1.0 693 green: 1.0 694 blue: 0.0 695 alpha: 1.0]; 696} 697 698 699/** Returns whether TODO 700 *<p>See Also: +setIgnoresAlpha:</p> 701 */ 702+ (BOOL) ignoresAlpha 703{ 704 return gnustep_gui_ignores_alpha; 705} 706 707/** TODO 708 *<p>See Also: +ignoresAlpha</p> 709 */ 710+ (void) setIgnoresAlpha: (BOOL)flag 711{ 712 gnustep_gui_ignores_alpha = flag; 713} 714 715/**<p>Returns the NSColor on the NSPasteboard pasteBoard 716 or nil if it does not exists.</p><p>See Also: -writeToPasteboard:</p> 717 */ 718+ (NSColor*) colorFromPasteboard: (NSPasteboard *)pasteBoard 719{ 720 NSData *colorData = [pasteBoard dataForType: NSColorPboardType]; 721 722 // FIXME: This should better use the description format 723 if (colorData != nil) 724 return [NSUnarchiver unarchiveObjectWithData: colorData]; 725 726 return nil; 727} 728 729// 730// System colors stuff. 731// 732+ (NSColor*) alternateSelectedControlColor 733{ 734 return systemColorWithName(@"alternateSelectedControlColor"); 735} 736 737+ (NSColor*) alternateSelectedControlTextColor 738{ 739 return systemColorWithName(@"alternateSelectedControlTextColor"); 740} 741 742+ (NSColor*) controlBackgroundColor 743{ 744 return systemColorWithName(@"controlBackgroundColor"); 745} 746 747+ (NSColor*) controlColor 748{ 749 return systemColorWithName(@"controlColor"); 750} 751 752+ (NSColor*) controlDarkShadowColor 753{ 754 return systemColorWithName(@"controlDarkShadowColor"); 755} 756 757+ (NSColor*) controlHighlightColor 758{ 759 return systemColorWithName(@"controlHighlightColor"); 760} 761 762+ (NSColor*) controlLightHighlightColor 763{ 764 return systemColorWithName(@"controlLightHighlightColor"); 765} 766 767+ (NSColor*) controlShadowColor 768{ 769 return systemColorWithName(@"controlShadowColor"); 770} 771 772+ (NSColor*) controlTextColor 773{ 774 return systemColorWithName(@"controlTextColor"); 775} 776 777+ (NSColor*) disabledControlTextColor 778{ 779 return systemColorWithName(@"disabledControlTextColor"); 780} 781 782+ (NSColor*) gridColor 783{ 784 return systemColorWithName(@"gridColor"); 785} 786 787+ (NSColor*) headerColor 788{ 789 return systemColorWithName(@"headerColor"); 790} 791 792+ (NSColor*) headerTextColor 793{ 794 return systemColorWithName(@"headerTextColor"); 795} 796 797+ (NSColor*) highlightColor 798{ 799 return systemColorWithName(@"highlightColor"); 800} 801 802+ (NSColor*) keyboardFocusIndicatorColor 803{ 804 return systemColorWithName(@"keyboardFocusIndicatorColor"); 805} 806 807+ (NSColor*) knobColor 808{ 809 return systemColorWithName(@"knobColor"); 810} 811 812+ (NSColor*) labelColor 813{ 814 return systemColorWithName(@"labelColor"); 815} 816 817+ (NSColor*) quaternaryLabelColor 818{ 819 return systemColorWithName(@"quaternaryLabelColor"); 820} 821 822+ (NSColor*) scrollBarColor 823{ 824 return systemColorWithName(@"scrollBarColor"); 825} 826 827+ (NSColor*) secondaryLabelColor 828{ 829 return systemColorWithName(@"secondaryLabelColor"); 830} 831 832+ (NSColor*) secondarySelectedControlColor 833{ 834 return systemColorWithName(@"secondarySelectedControlColor"); 835} 836 837+ (NSColor*) selectedControlColor 838{ 839 return systemColorWithName(@"selectedControlColor"); 840} 841 842+ (NSColor*) selectedControlTextColor 843{ 844 return systemColorWithName(@"selectedControlTextColor"); 845} 846 847+ (NSColor*) selectedKnobColor 848{ 849 return systemColorWithName(@"selectedKnobColor"); 850} 851 852+ (NSColor*) selectedMenuItemColor 853{ 854 return systemColorWithName(@"selectedMenuItemColor"); 855} 856 857+ (NSColor*) selectedMenuItemTextColor 858{ 859 return systemColorWithName(@"selectedMenuItemTextColor"); 860} 861 862+ (NSColor*) selectedTextBackgroundColor 863{ 864 return systemColorWithName(@"selectedTextBackgroundColor"); 865} 866 867+ (NSColor*) selectedTextColor 868{ 869 return systemColorWithName(@"selectedTextColor"); 870} 871 872+ (NSColor*) shadowColor 873{ 874 return systemColorWithName(@"shadowColor"); 875} 876 877+ (NSColor*) tertiaryLabelColor 878{ 879 return systemColorWithName(@"tertiaryLabelColor"); 880} 881 882+ (NSColor*) textBackgroundColor 883{ 884 return systemColorWithName(@"textBackgroundColor"); 885} 886 887+ (NSColor*) textColor 888{ 889 return systemColorWithName(@"textColor"); 890} 891 892+ (NSColor*) toolTipColor 893{ 894 return systemColorWithName(@"toolTipColor"); 895} 896 897+ (NSColor*) toolTipTextColor 898{ 899 return systemColorWithName(@"toolTipTextColor"); 900} 901 902+ (NSColor *)windowBackgroundColor 903{ 904 return systemColorWithName(@"windowBackgroundColor"); 905} 906 907+ (NSColor*) windowFrameColor 908{ 909 return systemColorWithName(@"windowFrameColor"); 910} 911 912+ (NSColor*) windowFrameTextColor 913{ 914 return systemColorWithName(@"windowFrameTextColor"); 915} 916 917+ (NSArray*) controlAlternatingRowBackgroundColors 918{ 919 return [NSArray arrayWithObjects: systemColorWithName(@"rowBackgroundColor"), 920 systemColorWithName(@"alternateRowBackgroundColor"), nil]; 921} 922 923//////////////////////////////////////////////////////////// 924// 925// Instance methods 926// 927 928- (id) copyWithZone: (NSZone*)aZone 929{ 930 if (NSShouldRetainWithZone(self, aZone)) 931 { 932 return RETAIN(self); 933 } 934 else 935 { 936 return NSCopyObject(self, 0, aZone); 937 } 938} 939 940- (NSString*) description 941{ 942 [self subclassResponsibility: _cmd]; 943 return nil; 944} 945 946/**<p>Gets the cyan, magenta, yellow,black and alpha values from the NSColor. 947 Raises a NSInternalInconsistencyException if the NSColor is not a CYMK color 948 </p> 949 */ 950- (void) getCyan: (CGFloat*)cyan 951 magenta: (CGFloat*)magenta 952 yellow: (CGFloat*)yellow 953 black: (CGFloat*)black 954 alpha: (CGFloat*)alpha 955{ 956 [NSException raise: NSInternalInconsistencyException 957 format: @"Called getCyan:magenta:yellow:black:alpha: on non-CMYK colour"]; 958} 959 960/**<p>Gets the hue, saturation, brightness and alpha values from the NSColor. 961 Raises a NSInternalInconsistencyException if the NSColor is not a RGB color 962 </p> 963 */ 964- (void) getHue: (CGFloat*)hue 965 saturation: (CGFloat*)saturation 966 brightness: (CGFloat*)brightness 967 alpha: (CGFloat*)alpha 968{ 969 [NSException raise: NSInternalInconsistencyException 970 format: @"Called getHue:saturation:brightness:alpha: on non-RGB colour"]; 971} 972 973/**<p>Gets the red, green, blue and alpha values from the NSColor. 974 Raises a NSInternalInconsistencyException if the NSColor is not a RGB color 975 </p> 976 */ 977-(void) getRed: (CGFloat*)red 978 green: (CGFloat*)green 979 blue: (CGFloat*)blue 980 alpha: (CGFloat*)alpha 981{ 982 [NSException raise: NSInternalInconsistencyException 983 format: @"Called getRed:green:blue:alpha: on non-RGB colour"]; 984} 985 986/**<p>Gets the white alpha values from the NSColor. 987 Raises a NSInternalInconsistencyException if the NSColor is not a 988 greyscale color</p> 989 */ 990- (void) getWhite: (CGFloat*)white 991 alpha: (CGFloat*)alpha 992{ 993 [NSException raise: NSInternalInconsistencyException 994 format: @"Called getWhite:alpha: on non-grayscale colour"]; 995} 996 997- (BOOL) isEqual: (id)other 998{ 999 if (other == self) 1000 return YES; 1001 if ([other isKindOfClass: NSColorClass] == NO) 1002 return NO; 1003 else 1004 { 1005 [self subclassResponsibility: _cmd]; 1006 return NO; 1007 } 1008} 1009 1010/** <p>Returns the alpha component. </p> 1011 */ 1012- (CGFloat) alphaComponent 1013{ 1014 return 1.0; 1015} 1016 1017/** <p>Returns the black component. Raises a NSInternalInconsistencyException 1018 if NSColor is not a CMYK color.</p> 1019 */ 1020- (CGFloat) blackComponent 1021{ 1022 [NSException raise: NSInternalInconsistencyException 1023 format: @"Called blackComponent on non-CMYK colour"]; 1024 return 0.0; 1025} 1026 1027/** <p>Returns the blue component. Raises a NSInternalInconsistencyException 1028 if NSColor is not a RGB color.</p> 1029 */ 1030- (CGFloat) blueComponent 1031{ 1032 [NSException raise: NSInternalInconsistencyException 1033 format: @"Called blueComponent on non-RGB colour"]; 1034 return 0.0; 1035} 1036 1037/** <p>Returns the brightness component. Raises a 1038 NSInternalInconsistencyException if NSColor space is not a RGB color</p> 1039*/ 1040- (CGFloat) brightnessComponent 1041{ 1042 [NSException raise: NSInternalInconsistencyException 1043 format: @"Called brightnessComponent on non-RGB colour"]; 1044 return 0.0; 1045} 1046 1047- (NSString *) catalogNameComponent 1048{ 1049 [NSException raise: NSInternalInconsistencyException 1050 format: @"Called catalogNameComponent on colour with name"]; 1051 return nil; 1052} 1053 1054- (NSString *) colorNameComponent 1055{ 1056 [NSException raise: NSInternalInconsistencyException 1057 format: @"Called colorNameComponent on colour with name"]; 1058 return nil; 1059} 1060 1061/** <p>Returns the cyan component. Raises a NSInternalInconsistencyException 1062 if NSColor is not a CYMK color</p> 1063*/ 1064- (CGFloat) cyanComponent 1065{ 1066 [NSException raise: NSInternalInconsistencyException 1067 format: @"Called cyanComponent on non-CMYK colour"]; 1068 return 0.0; 1069} 1070 1071/** <p>Returns the green component. Raises a NSInternalInconsistencyException 1072 if NSColor is not a RGB color</p> 1073*/ 1074- (CGFloat) greenComponent 1075{ 1076 [NSException raise: NSInternalInconsistencyException 1077 format: @"Called greenComponent on non-RGB colour"]; 1078 return 0.0; 1079} 1080 1081/** <p>Returns the hue component. Raises a NSInternalInconsistencyException 1082 if NSColor is not a RGB color</p> 1083*/ 1084- (CGFloat) hueComponent 1085{ 1086 [NSException raise: NSInternalInconsistencyException 1087 format: @"Called hueComponent on non-RGB colour"]; 1088 return 0.0; 1089} 1090 1091- (NSString *) localizedCatalogNameComponent 1092{ 1093 [NSException raise: NSInternalInconsistencyException 1094 format: @"Called localizedCatalogNameComponent on colour with name"]; 1095 return nil; 1096} 1097 1098- (NSString *) localizedColorNameComponent 1099{ 1100 [NSException raise: NSInternalInconsistencyException 1101 format: @"Called localizedColorNameComponent on colour with name"]; 1102 return nil; 1103} 1104 1105/** <p>Returns the magenta component. Raises a 1106 NSInternalInconsistencyException if NSColor is not a CMYK color</p> 1107*/ 1108- (CGFloat) magentaComponent 1109{ 1110 [NSException raise: NSInternalInconsistencyException 1111 format: @"Called magentaComponent on non-CMYK colour"]; 1112 return 0.0; 1113} 1114 1115/** <p>Returns the red component. Raises a NSInternalInconsistencyException 1116 if NSColor is not a RGB color</p> 1117*/ 1118- (CGFloat) redComponent 1119{ 1120 [NSException raise: NSInternalInconsistencyException 1121 format: @"Called redComponent on non-RGB colour"]; 1122 return 0.0; 1123} 1124 1125/** <p>Returns the saturation component. Raises a 1126 NSInternalInconsistencyException if NSColor is not a RGB color</p> 1127*/ 1128- (CGFloat) saturationComponent 1129{ 1130 [NSException raise: NSInternalInconsistencyException 1131 format: @"Called saturationComponent on non-RGB colour"]; 1132 return 0.0; 1133} 1134 1135/** <p>Returns the white component. Raises a NSInternalInconsistencyException 1136 if NSColor is not a grayscale color</p> 1137*/ 1138- (CGFloat) whiteComponent 1139{ 1140 [NSException raise: NSInternalInconsistencyException 1141 format: @"Called whiteComponent on non-grayscale colour"]; 1142 return 0.0; 1143} 1144 1145- (NSImage*) patternImage 1146{ 1147 [NSException raise: NSInternalInconsistencyException 1148 format: @"Called patternImage on non-pattern colour"]; 1149 return nil; 1150} 1151 1152/** <p>Returns the yellow component. Raises a NSInternalInconsistencyException 1153 if NSColor is not a RGB color</p> 1154*/ 1155- (CGFloat) yellowComponent 1156{ 1157 [NSException raise: NSInternalInconsistencyException 1158 format: @"Called yellowComponent on non-CMYK colour"]; 1159 return 0.0; 1160} 1161 1162// 1163// Converting to Another Color Space 1164// 1165- (NSString *) colorSpaceName 1166{ 1167 [self subclassResponsibility: _cmd]; 1168 return nil; 1169} 1170 1171- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 1172{ 1173 return [self colorUsingColorSpaceName: colorSpace 1174 device: nil]; 1175} 1176 1177- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 1178 device: (NSDictionary *)deviceDescription 1179{ 1180 if (colorSpace == nil) 1181 { 1182 if (deviceDescription != nil) 1183 colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName]; 1184 if (colorSpace == nil) 1185 colorSpace = NSDeviceRGBColorSpace; 1186 } 1187 if ([colorSpace isEqualToString: [self colorSpaceName]]) 1188 { 1189 return self; 1190 } 1191 1192 if ([colorSpace isEqualToString: NSNamedColorSpace]) 1193 { 1194 // FIXME: We cannot convert to named color space. 1195 return nil; 1196 } 1197 1198 [self subclassResponsibility: _cmd]; 1199 1200 return nil; 1201} 1202 1203+ (NSColor *) colorWithColorSpace: (NSColorSpace *)space 1204 components: (const CGFloat *)comp 1205 count: (NSInteger)number 1206{ 1207 // FIXME 1208 if (space == [NSColorSpace genericRGBColorSpace] && (number == 4)) 1209 { 1210 return [self colorWithCalibratedRed: comp[0] 1211 green: comp[1] 1212 blue: comp[2] 1213 alpha: comp[3]]; 1214 } 1215 if (space == [NSColorSpace deviceRGBColorSpace] && (number == 4)) 1216 { 1217 return [self colorWithDeviceRed: comp[0] 1218 green: comp[1] 1219 blue: comp[2] 1220 alpha: comp[3]]; 1221 } 1222 if (space == [NSColorSpace genericGrayColorSpace] && (number == 2)) 1223 { 1224 return [NSColor colorWithCalibratedWhite: comp[0] alpha: comp[1]]; 1225 } 1226 if (space == [NSColorSpace deviceGrayColorSpace] && (number == 2)) 1227 { 1228 return [NSColor colorWithDeviceWhite: comp[0] alpha: comp[1]]; 1229 } 1230 if (space == [NSColorSpace genericCMYKColorSpace] && (number == 5)) 1231 { 1232 return [NSColor colorWithDeviceCyan: comp[0] 1233 magenta: comp[1] 1234 yellow: comp[2] 1235 black: comp[3] 1236 alpha: comp[4]]; 1237 } 1238 if (space == [NSColorSpace deviceCMYKColorSpace] && (number == 5)) 1239 { 1240 return [NSColor colorWithDeviceCyan: comp[0] 1241 magenta: comp[1] 1242 yellow: comp[2] 1243 black: comp[3] 1244 alpha: comp[4]]; 1245 } 1246 1247 return nil; 1248} 1249 1250/* 1251 FIXME: This method does it the wrong way around. We should store the 1252 actual colour space and get the colour space name from there. 1253*/ 1254- (NSColorSpace *) colorSpace 1255{ 1256 NSString *name = [self colorSpaceName]; 1257 1258 if ([name isEqualToString: NSCalibratedRGBColorSpace]) 1259 return [NSColorSpace genericRGBColorSpace]; 1260 if ([name isEqualToString: NSDeviceRGBColorSpace]) 1261 return [NSColorSpace deviceRGBColorSpace]; 1262 if ([name isEqualToString: NSCalibratedBlackColorSpace] 1263 || [name isEqualToString: NSCalibratedWhiteColorSpace]) 1264 return [NSColorSpace genericGrayColorSpace]; 1265 if ([name isEqualToString: NSDeviceBlackColorSpace] 1266 || [name isEqualToString: NSDeviceWhiteColorSpace]) 1267 return [NSColorSpace deviceGrayColorSpace]; 1268 if ([name isEqualToString: NSDeviceCMYKColorSpace]) 1269 return [NSColorSpace deviceCMYKColorSpace]; 1270 1271 return nil; 1272} 1273 1274- (NSColor *) colorUsingColorSpace: (NSColorSpace *)space 1275{ 1276 // FIXME 1277 NSString *colorSpaceName; 1278 1279 if (space == [self colorSpace]) 1280 { 1281 return self; 1282 } 1283 1284 switch ([space colorSpaceModel]) 1285 { 1286 default: 1287 case NSUnknownColorSpaceModel: 1288 return nil; 1289 case NSGrayColorSpaceModel: 1290 colorSpaceName = NSDeviceWhiteColorSpace; 1291 break; 1292 case NSRGBColorSpaceModel: 1293 colorSpaceName = NSDeviceRGBColorSpace; 1294 break; 1295 case NSCMYKColorSpaceModel: 1296 colorSpaceName = NSDeviceCMYKColorSpace; 1297 break; 1298 case NSLABColorSpaceModel: 1299 return nil; 1300 case NSDeviceNColorSpaceModel: 1301 return nil; 1302 } 1303 return [self colorUsingColorSpaceName: colorSpaceName 1304 device: nil]; 1305} 1306 1307- (NSUInteger) hash 1308{ 1309 int nums = [self numberOfComponents]; 1310 CGFloat floats[nums]; 1311 NSUInteger h = 0; 1312 unsigned i; 1313 1314 [self getComponents: &floats[0]]; 1315 for (i = 0; i < sizeof(floats); i++) 1316 { 1317 h = (h << 5) + h + *(uint8_t*)(((uintptr_t)&floats[0])+(i*sizeof(uint8_t))); 1318 } 1319 return h; 1320} 1321 1322- (NSInteger) numberOfComponents 1323{ 1324 [NSException raise: NSInternalInconsistencyException 1325 format: @"Called numberOfComponents on non-standard colour"]; 1326 return 0; 1327} 1328 1329- (void) getComponents: (CGFloat *)components 1330{ 1331 [NSException raise: NSInternalInconsistencyException 1332 format: @"Called getComponents: on non-standard colour"]; 1333} 1334 1335// 1336// Changing the Color 1337// 1338- (NSColor*) blendedColorWithFraction: (CGFloat)fraction 1339 ofColor: (NSColor*)aColor 1340{ 1341 NSColor *myColor = [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; 1342 NSColor *other = [aColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; 1343 CGFloat mr, mg, mb, ma, or, og, ob, oa, red, green, blue, alpha; 1344 1345 if (fraction <= 0.0) 1346 { 1347 return self; 1348 } 1349 1350 if (fraction >= 1.0) 1351 { 1352 return aColor; 1353 } 1354 1355 if (myColor == nil || other == nil) 1356 { 1357 return nil; 1358 } 1359 1360 [myColor getRed: &mr green: &mg blue: &mb alpha: &ma]; 1361 [other getRed: &or green: &og blue: &ob alpha: &oa]; 1362 red = fraction * or + (1 - fraction) * mr; 1363 green = fraction * og + (1 - fraction) * mg; 1364 blue = fraction * ob + (1 - fraction) * mb; 1365 alpha = fraction * oa + (1 - fraction) * ma; 1366 return [NSColorClass colorWithCalibratedRed: red 1367 green: green 1368 blue: blue 1369 alpha: alpha]; 1370} 1371 1372- (NSColor*) colorWithAlphaComponent: (CGFloat)alpha 1373{ 1374 return self; 1375} 1376 1377- (NSColor*) highlightWithLevel: (CGFloat)level 1378{ 1379 return [self blendedColorWithFraction: level 1380 ofColor: [NSColorClass highlightColor]]; 1381} 1382 1383- (NSColor*) shadowWithLevel: (CGFloat)level 1384{ 1385 return [self blendedColorWithFraction: level 1386 ofColor: [NSColorClass shadowColor]]; 1387} 1388 1389/**<p>Writes the NSColor into the NSPasteboard specified by pasteBoard</p> 1390 * <p>See Also: +colorFromPasteboard: </p> 1391 */ 1392- (void) writeToPasteboard: (NSPasteboard *)pasteBoard 1393{ 1394 // FIXME: We should better use the description 1395 NSData *colorData = [NSArchiver archivedDataWithRootObject: self]; 1396 1397 if (colorData != nil) 1398 [pasteBoard setData: colorData 1399 forType: NSColorPboardType]; 1400} 1401 1402// 1403// Drawing 1404// 1405- (void) drawSwatchInRect: (NSRect)rect 1406{ 1407 if ([self alphaComponent] < 1.0) 1408 { 1409 NSBezierPath *triangle = [NSBezierPath bezierPath]; 1410 1411 [[NSColor whiteColor] set]; 1412 NSRectFill(rect); 1413 1414 [triangle moveToPoint: NSMakePoint(rect.origin.x, 1415 rect.origin.y + rect.size.height)]; 1416 [triangle lineToPoint: NSMakePoint(rect.origin.x + rect.size.width, 1417 rect.origin.y + rect.size.height)]; 1418 [triangle lineToPoint: rect.origin]; 1419 [triangle closePath]; 1420 [[NSColor blackColor] set]; 1421 [triangle fill]; 1422 } 1423 1424 [self set]; 1425 NSRectFill(rect); 1426} 1427 1428- (void) set 1429{ 1430 // This is here to keep old code working 1431 [[self colorUsingColorSpaceName: NSDeviceRGBColorSpace] set]; 1432} 1433 1434- (void) setFill 1435{ 1436 [[self colorUsingColorSpaceName: NSDeviceRGBColorSpace] setFill]; 1437} 1438 1439- (void) setStroke 1440{ 1441 [[self colorUsingColorSpaceName: NSDeviceRGBColorSpace] setStroke]; 1442} 1443 1444// 1445// NSCoding protocol 1446// 1447- (Class) classForCoder 1448{ 1449 return NSColorClass; 1450} 1451 1452- (void) encodeWithCoder: (NSCoder*)aCoder 1453{ 1454 [self subclassResponsibility: _cmd]; 1455} 1456 1457- (id) initWithCoder: (NSCoder*)aDecoder 1458{ 1459 if ([aDecoder allowsKeyedCoding]) 1460 { 1461 int colorSpace = [aDecoder decodeIntForKey: @"NSColorSpace"]; 1462 1463 DESTROY(self); 1464 1465 if ((colorSpace == 1) || (colorSpace == 2)) 1466 { 1467 NSUInteger length; 1468 const uint8_t *data; 1469 double red = 0.0; 1470 double green = 0.0; 1471 double blue = 0.0; 1472 double alpha = 1.0; 1473 NSString *str; 1474 NSScanner *scanner; 1475 1476 if ([aDecoder containsValueForKey: @"NSRGB"]) 1477 { 1478 data = [aDecoder decodeBytesForKey: @"NSRGB" 1479 returnedLength: &length]; 1480 str = [[NSString alloc] initWithCString: (const char*)data 1481 length: length]; 1482 scanner = [[NSScanner alloc] initWithString: str]; 1483 [scanner scanDouble: &red]; 1484 [scanner scanDouble: &green]; 1485 [scanner scanDouble: &blue]; 1486 [scanner scanDouble: &alpha]; 1487 RELEASE(scanner); 1488 RELEASE(str); 1489 } 1490 1491 if (colorSpace == 1) 1492 { 1493 self = RETAIN([NSColor colorWithCalibratedRed: red 1494 green: green 1495 blue: blue 1496 alpha: alpha]); 1497 } 1498 else 1499 { 1500 self = RETAIN([NSColor colorWithDeviceRed: red 1501 green: green 1502 blue: blue 1503 alpha: alpha]); 1504 } 1505 } 1506 else if ((colorSpace == 3) || (colorSpace == 4)) 1507 { 1508 NSUInteger length; 1509 const uint8_t *data; 1510 double white = 0.0; 1511 double alpha = 1.0; 1512 NSString *str; 1513 NSScanner *scanner; 1514 1515 if ([aDecoder containsValueForKey: @"NSWhite"]) 1516 { 1517 data = [aDecoder decodeBytesForKey: @"NSWhite" 1518 returnedLength: &length]; 1519 str = [[NSString alloc] initWithCString: (const char*)data 1520 length: length]; 1521 scanner = [[NSScanner alloc] initWithString: str]; 1522 [scanner scanDouble: &white]; 1523 [scanner scanDouble: &alpha]; 1524 RELEASE(scanner); 1525 RELEASE(str); 1526 } 1527 1528 if (colorSpace == 3) 1529 { 1530 self = RETAIN([NSColor colorWithCalibratedWhite: white 1531 alpha: alpha]); 1532 } 1533 else 1534 { 1535 self = RETAIN([NSColor colorWithDeviceWhite: white 1536 alpha: alpha]); 1537 } 1538 } 1539 else if (colorSpace == 5) 1540 { 1541 NSUInteger length; 1542 const uint8_t *data; 1543 double cyan = 0.0; 1544 double yellow = 0.0; 1545 double magenta = 0.0; 1546 double black = 0.0; 1547 double alpha = 1.0; 1548 NSString *str; 1549 NSScanner *scanner; 1550 1551 if ([aDecoder containsValueForKey: @"NSCYMK"]) 1552 { 1553 data = [aDecoder decodeBytesForKey: @"NSCYMK" 1554 returnedLength: &length]; 1555 str = [[NSString alloc] initWithCString: (const char*)data 1556 length: length]; 1557 scanner = [[NSScanner alloc] initWithString: str]; 1558 [scanner scanDouble: &cyan]; 1559 [scanner scanDouble: &yellow]; 1560 [scanner scanDouble: &magenta]; 1561 [scanner scanDouble: &black]; 1562 [scanner scanDouble: &alpha]; 1563 RELEASE(scanner); 1564 RELEASE(str); 1565 } 1566 1567 self = RETAIN([NSColor colorWithDeviceCyan: cyan 1568 magenta: magenta 1569 yellow: yellow 1570 black: black 1571 alpha: alpha]); 1572 } 1573 else if (colorSpace == 6) 1574 { 1575 NSString *catalog = [aDecoder decodeObjectForKey: @"NSCatalogName"]; 1576 NSString *name = [aDecoder decodeObjectForKey: @"NSColorName"]; 1577 //NSColor *color = [aDecoder decodeObjectForKey: @"NSColor"]; 1578 1579 self = RETAIN([NSColor colorWithCatalogName: catalog 1580 colorName: name]); 1581 } 1582 else if (colorSpace == 10) 1583 { 1584 NSImage *image = [aDecoder decodeObjectForKey: @"NSImage"]; 1585 1586 self = RETAIN([NSColor colorWithPatternImage: image]); 1587 } 1588 1589 return self; 1590 } 1591 else if ([aDecoder versionForClassName: @"NSColor"] < 3) 1592 { 1593 float red; 1594 float green; 1595 float blue; 1596 float cyan; 1597 float magenta; 1598 float yellow; 1599 float black; 1600 float hue; 1601 float saturation; 1602 float brightness; 1603 float alpha; 1604 float white; 1605 1606 int active_component; 1607 int valid_components; 1608 NSString *colorspace_name; 1609 NSString *catalog_name; 1610 NSString *color_name; 1611 BOOL is_clear; 1612 1613 DESTROY(self); 1614 1615 // Version 1 1616 [aDecoder decodeValueOfObjCType: @encode(float) at: &red]; 1617 [aDecoder decodeValueOfObjCType: @encode(float) at: &green]; 1618 [aDecoder decodeValueOfObjCType: @encode(float) at: &blue]; 1619 [aDecoder decodeValueOfObjCType: @encode(float) at: &alpha]; 1620 [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &is_clear]; 1621 1622 // Version 2 1623 [aDecoder decodeValueOfObjCType: @encode(id) at: &colorspace_name]; 1624 [aDecoder decodeValueOfObjCType: @encode(id) at: &catalog_name]; 1625 [aDecoder decodeValueOfObjCType: @encode(id) at: &color_name]; 1626 [aDecoder decodeValueOfObjCType: @encode(float) at: &cyan]; 1627 [aDecoder decodeValueOfObjCType: @encode(float) at: &magenta]; 1628 [aDecoder decodeValueOfObjCType: @encode(float) at: &yellow]; 1629 [aDecoder decodeValueOfObjCType: @encode(float) at: &black]; 1630 [aDecoder decodeValueOfObjCType: @encode(float) at: &hue]; 1631 [aDecoder decodeValueOfObjCType: @encode(float) at: &saturation]; 1632 [aDecoder decodeValueOfObjCType: @encode(float) at: &brightness]; 1633 [aDecoder decodeValueOfObjCType: @encode(float) at: &white]; 1634 [aDecoder decodeValueOfObjCType: @encode(int) at: &active_component]; 1635 [aDecoder decodeValueOfObjCType: @encode(int) at: &valid_components]; 1636 1637 if ([colorspace_name isEqualToString: @"NSDeviceCMYKColorSpace"]) 1638 { 1639 self = [NSColorClass colorWithDeviceCyan: cyan 1640 magenta: magenta 1641 yellow: yellow 1642 black: black 1643 alpha: alpha]; 1644 } 1645 else if ([colorspace_name isEqualToString: @"NSDeviceWhiteColorSpace"]) 1646 { 1647 self = [NSColorClass colorWithDeviceWhite: white alpha: alpha]; 1648 } 1649 else if ([colorspace_name isEqualToString: 1650 @"NSCalibratedWhiteColorSpace"]) 1651 { 1652 self = [NSColorClass colorWithCalibratedWhite:white alpha: alpha]; 1653 } 1654 else if ([colorspace_name isEqualToString: @"NSDeviceRGBColorSpace"]) 1655 { 1656 self = [NSColorClass colorWithDeviceRed: red 1657 green: green 1658 blue: blue 1659 alpha: alpha]; 1660 } 1661 else if ([colorspace_name isEqualToString: @"NSCalibratedRGBColorSpace"]) 1662 { 1663 self = [NSColorClass colorWithCalibratedRed: red 1664 green: green 1665 blue: blue 1666 alpha: alpha]; 1667 } 1668 else if ([colorspace_name isEqualToString: @"NSNamedColorSpace"]) 1669 { 1670 self = [NSColorClass colorWithCatalogName: catalog_name 1671 colorName: color_name]; 1672 } 1673 1674 return RETAIN(self); 1675 } 1676 else 1677 { 1678 NSString *csName = [aDecoder decodeObject]; 1679 1680 RELEASE(self); 1681 if ([csName isEqualToString: @"NSDeviceCMYKColorSpace"]) 1682 { 1683 self = [GSDeviceCMYKColor alloc]; 1684 } 1685 else if ([csName isEqualToString: @"NSDeviceRGBColorSpace"]) 1686 { 1687 self = [GSDeviceRGBColor alloc]; 1688 } 1689 else if ([csName isEqualToString: @"NSDeviceWhiteColorSpace"]) 1690 { 1691 self = [GSDeviceWhiteColor alloc]; 1692 } 1693 else if ([csName isEqualToString: @"NSCalibratedWhiteColorSpace"]) 1694 { 1695 self = [GSCalibratedWhiteColor alloc]; 1696 } 1697 else if ([csName isEqualToString: @"NSCalibratedRGBColorSpace"]) 1698 { 1699 self = [GSCalibratedRGBColor alloc]; 1700 } 1701 else if ([csName isEqualToString: @"NSNamedColorSpace"]) 1702 { 1703 self = [GSNamedColor alloc]; 1704 } 1705 else 1706 { 1707 NSLog(@"Unknown colorspace name in decoded color"); 1708 return nil; 1709 } 1710 return [self initWithCoder: aDecoder]; 1711 } 1712} 1713 1714@end 1715 1716// 1717// Private methods 1718// 1719@implementation NSColor (GNUstepPrivate) 1720 1721+ (NSColor*) colorFromString: (NSString*)str 1722{ 1723 if ([str hasPrefix: @"{"]) 1724 { 1725 NSDictionary *dict; 1726 NSString *space; 1727 CGFloat alpha; 1728 1729 dict = [str propertyList]; 1730 if (dict == nil) 1731 return nil; 1732 if ((space = [dict objectForKey: @"ColorSpace"]) == nil) 1733 return nil; 1734 1735 str = [dict objectForKey: @"Alpha"]; 1736 if (str == nil || [str isEqualToString: @""]) 1737 { 1738 alpha = 1.0; 1739 } 1740 else 1741 { 1742 alpha = [str doubleValue]; 1743 } 1744 1745 if ([space isEqual: NSCalibratedWhiteColorSpace]) 1746 { 1747 CGFloat white = [[dict objectForKey: @"W"] doubleValue]; 1748 1749 return [self colorWithCalibratedWhite: white alpha: alpha]; 1750 } 1751 if ([space isEqual: NSCalibratedBlackColorSpace]) 1752 { 1753 CGFloat white = [[dict objectForKey: @"W"] doubleValue]; 1754 1755 return [self colorWithCalibratedWhite: white 1756 alpha: alpha]; 1757 } 1758 if ([space isEqual: NSCalibratedRGBColorSpace]) 1759 { 1760 if ([dict objectForKey: @"H"] != nil) 1761 { 1762 CGFloat hue = [[dict objectForKey: @"H"] doubleValue]; 1763 CGFloat saturation = [[dict objectForKey: @"S"] doubleValue]; 1764 CGFloat brightness = [[dict objectForKey: @"B"] doubleValue]; 1765 1766 return [self colorWithCalibratedHue: hue 1767 saturation: saturation 1768 brightness: brightness 1769 alpha: alpha]; 1770 } 1771 else 1772 { 1773 CGFloat red = [[dict objectForKey: @"R"] doubleValue]; 1774 CGFloat green = [[dict objectForKey: @"G"] doubleValue]; 1775 CGFloat blue = [[dict objectForKey: @"B"] doubleValue]; 1776 1777 return [self colorWithCalibratedRed: red 1778 green: green 1779 blue: blue 1780 alpha: alpha]; 1781 } 1782 } 1783 if ([space isEqual: NSDeviceCMYKColorSpace]) 1784 { 1785 CGFloat cyan = [[dict objectForKey: @"C"] doubleValue]; 1786 CGFloat magenta = [[dict objectForKey: @"M"] doubleValue]; 1787 CGFloat yellow = [[dict objectForKey: @"Y"] doubleValue]; 1788 CGFloat black = [[dict objectForKey: @"B"] doubleValue]; 1789 1790 return [self colorWithDeviceCyan: cyan 1791 magenta: magenta 1792 yellow: yellow 1793 black: black 1794 alpha: alpha]; 1795 } 1796 if ([space isEqual: NSNamedColorSpace]) 1797 { 1798 NSString *cat = [dict objectForKey: @"Catalog"]; 1799 NSString *col = [dict objectForKey: @"Color"]; 1800 1801 return [self colorWithCatalogName: cat 1802 colorName: col]; 1803 } 1804 } 1805 else if (str != nil) 1806 { 1807 double r, g, b; 1808 NSScanner *scanner = [[NSScanner alloc] initWithString: str]; 1809 1810 if ([scanner scanDouble: &r] && 1811 [scanner scanDouble: &g] && 1812 [scanner scanDouble: &b] && 1813 [scanner isAtEnd]) 1814 { 1815 RELEASE(scanner); 1816 return [self colorWithCalibratedRed: r 1817 green: g 1818 blue: b 1819 alpha: 1.0]; 1820 } 1821 1822 RELEASE(scanner); 1823 } 1824 1825 return nil; 1826} 1827 1828/* 1829 * Go through all the names of system colors - for each color where 1830 * there is a value in the defaults database, see if the current 1831 * value of the color differs from the old one. 1832 * Where there is a difference, update the color strings dictionary 1833 * and update the system colors list to contain the new color. 1834 * Finally, issue a notification if appropriate. 1835 */ 1836+ (void) defaultsDidChange: (NSNotification*)notification 1837{ 1838 NSUserDefaults *defs; 1839 NSEnumerator *enumerator; 1840 NSString *key; 1841 BOOL didChange = NO; 1842 1843 defs = [NSUserDefaults standardUserDefaults]; 1844 1845 enumerator = [colorStrings keyEnumerator]; 1846 while ((key = [enumerator nextObject]) != nil) 1847 { 1848 NSString *def = [[defs objectForKey: key] description]; 1849 1850 if (def != nil) 1851 { 1852 NSColor *old = [systemColors colorWithKey: key]; 1853 NSColor *color = [NSColor colorFromString: def]; 1854 1855 if (color == nil) 1856 { 1857 NSLog(@"System color '%@' has bad string rep - '%@'\n", 1858 key, def); 1859 } 1860 else if ([color isEqual: old] == NO) 1861 { 1862 didChange = YES; 1863 [colorStrings setObject: def forKey: key]; 1864 [systemColors setColor: color forKey: key]; 1865 // Refresh the cache for this named colour 1866 [[systemDict objectForKey: key] recache]; 1867 } 1868 } 1869 } 1870 1871 if (didChange) 1872 { 1873 [[NSNotificationCenter defaultCenter] 1874 postNotificationName: NSSystemColorsDidChangeNotification object: nil]; 1875 } 1876} 1877 1878/* 1879 * Handle activation of a new theme ... look for a 'System' color list 1880 * in the theme bundle and use it instead of the default system color 1881 * list if it is present. 1882 */ 1883+ (void) themeDidActivate: (NSNotification*)notification 1884{ 1885 GSTheme *theme = [notification object]; 1886 NSColorList *list = [theme colors]; 1887 NSEnumerator *enumerator; 1888 NSString *name; 1889 1890 if (list == nil) 1891 { 1892 list = defaultSystemColors; 1893 } 1894 NSAssert([[list name] isEqual: @"System"], NSInvalidArgumentException); 1895 [NSColorList _setThemeSystemColorList: list]; 1896 1897 /* We always update the system dictionary and send a notification, since 1898 * the theme may have given us a pre-existing color list, but have changed 1899 * one or more of the colors in it. 1900 */ 1901 list = [NSColorList colorListNamed: @"System"]; 1902 ASSIGN(systemColors, list); 1903 enumerator = [systemDict keyEnumerator]; 1904 while ((name = [enumerator nextObject]) != nil) 1905 { 1906 [[systemDict objectForKey: name] recache]; 1907 } 1908 [[NSNotificationCenter defaultCenter] 1909 postNotificationName: NSSystemColorsDidChangeNotification object: nil]; 1910} 1911 1912@end 1913 1914 1915// Named colours 1916@implementation GSNamedColor 1917 1918static NSMutableDictionary *namedColors = nil; 1919static NSRecursiveLock *namedColorLock = nil; 1920 1921+ (void) initialize 1922{ 1923 namedColorLock = [NSRecursiveLock new]; 1924 namedColors = [NSMutableDictionary new]; 1925} 1926 1927- (NSColor*) initWithCatalogName: (NSString *)listName 1928 colorName: (NSString *)colorName 1929{ 1930 NSMutableDictionary *d; 1931 NSColor *c; 1932 1933 _catalog_name = [listName copy]; 1934 _color_name = [colorName copy]; 1935 [namedColorLock lock]; 1936 d = [namedColors objectForKey: _catalog_name]; 1937 if (d == nil) 1938 { 1939 d = [NSMutableDictionary new]; 1940 [namedColors setObject: d forKey: _catalog_name]; 1941 [d release]; 1942 } 1943 c = [d objectForKey: _color_name]; 1944 if (c == nil) 1945 { 1946 [d setObject: self forKey: _color_name]; 1947 } 1948 else 1949 { 1950 [self release]; 1951 self = (GSNamedColor*)[c retain]; 1952 } 1953 [namedColorLock unlock]; 1954 return self; 1955} 1956 1957- (void) dealloc 1958{ 1959 RELEASE(_catalog_name); 1960 RELEASE(_color_name); 1961 RELEASE(_cached_name_space); 1962 RELEASE(_cached_color); 1963 [super dealloc]; 1964} 1965 1966- (NSString *) colorSpaceName 1967{ 1968 return NSNamedColorSpace; 1969} 1970 1971- (id) copyWithZone: (NSZone*)aZone 1972{ 1973 return RETAIN(self); 1974} 1975 1976- (NSString*) description 1977{ 1978 NSMutableString *desc; 1979 1980 /* 1981 * We encode information in a dictionary 1982 * format with meaningful keys. 1983 */ 1984 desc = [NSMutableString stringWithCapacity: 128]; 1985 [desc appendFormat: @"{ ColorSpace = \"%@\";", [self colorSpaceName]]; 1986 [desc appendFormat: @" Catalog = \"%@\";", _catalog_name]; 1987 [desc appendFormat: @" Color = \"%@\"; }", _color_name]; 1988 1989 return desc; 1990} 1991 1992- (NSString *) catalogNameComponent 1993{ 1994 return _catalog_name; 1995} 1996 1997- (NSString *) colorNameComponent 1998{ 1999 return _color_name; 2000} 2001 2002- (NSString *) localizedCatalogNameComponent 2003{ 2004 // FIXME: How do we localize? 2005 return NSLocalizedString(_catalog_name, @"colour list name"); 2006} 2007 2008- (NSString *) localizedColorNameComponent 2009{ 2010 // FIXME: How do we localize? 2011 return NSLocalizedString(_color_name, @"colour name"); 2012} 2013 2014- (NSUInteger) hash 2015{ 2016 return [_catalog_name hash] + [_color_name hash]; 2017} 2018 2019- (BOOL) isEqual: (id)other 2020{ 2021 if (other == self) 2022 return YES; 2023 if ([other isKindOfClass: [self class]] == NO 2024 || [[other catalogNameComponent] isEqualToString: _catalog_name] == NO 2025 || [[other colorNameComponent] isEqualToString: _color_name] == NO) 2026 { 2027 return NO; 2028 } 2029 return YES; 2030} 2031 2032- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 2033 device: (NSDictionary *)deviceDescription 2034{ 2035 NSColorList *list; 2036 NSColor *real; 2037 2038 if (colorSpace == nil) 2039 { 2040 if (deviceDescription != nil) 2041 colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName]; 2042 // FIXME: If the deviceDescription is nil, we should get it from the 2043 // current view or printer 2044 if (colorSpace == nil) 2045 colorSpace = NSCalibratedRGBColorSpace; 2046 } 2047 if ([colorSpace isEqualToString: [self colorSpaceName]]) 2048 { 2049 return self; 2050 } 2051 2052 // Is there a cache hit? 2053 // FIXME How would we detect that the cache has become invalid by a 2054 // change to the colour list? 2055 [namedColorLock lock]; 2056 if (NO == [colorSpace isEqualToString: _cached_name_space]) 2057 { 2058 list = [NSColorList colorListNamed: _catalog_name]; 2059 real = [list colorWithKey: _color_name]; 2060 ASSIGN(_cached_color, [real colorUsingColorSpaceName: colorSpace 2061 device: deviceDescription]); 2062 ASSIGN(_cached_name_space, colorSpace); 2063 } 2064 real = [[_cached_color retain] autorelease]; 2065 [namedColorLock unlock]; 2066 2067 return real; 2068} 2069 2070- (void) recache 2071{ 2072 [namedColorLock lock]; 2073 DESTROY(_cached_name_space); 2074 DESTROY(_cached_color); 2075 [namedColorLock unlock]; 2076} 2077 2078// 2079// NSCoding protocol 2080// 2081- (void) encodeWithCoder: (NSCoder*)aCoder 2082{ 2083 if ([aCoder allowsKeyedCoding]) 2084 { 2085 [aCoder encodeInt: 6 forKey: @"NSColorSpace"]; 2086 [aCoder encodeObject: _catalog_name forKey: @"NSCatalogName"]; 2087 [aCoder encodeObject: _color_name forKey: @"NSColorName"]; 2088 } 2089 else 2090 { 2091 [aCoder encodeObject: [self colorSpaceName]]; 2092 [aCoder encodeObject: _catalog_name]; 2093 [aCoder encodeObject: _color_name]; 2094 } 2095} 2096 2097- (id) initWithCoder: (NSCoder*)aDecoder 2098{ 2099 NSString *listName; 2100 NSString *colorName; 2101 2102 listName = [aDecoder decodeObject]; 2103 colorName = [aDecoder decodeObject]; 2104 return [self initWithCatalogName: listName 2105 colorName: colorName]; 2106} 2107 2108@end 2109 2110// Grayscale colours 2111@implementation GSWhiteColor 2112 2113- (CGFloat) alphaComponent 2114{ 2115 return _alpha_component; 2116} 2117 2118- (CGFloat) whiteComponent 2119{ 2120 return _white_component; 2121} 2122 2123- (void) getComponents: (CGFloat *)components; 2124{ 2125 components[0] = _white_component; 2126 components[1] = _alpha_component; 2127} 2128 2129- (NSInteger) numberOfComponents 2130{ 2131 return 2; 2132} 2133 2134- (NSString*) description 2135{ 2136 NSMutableString *desc; 2137 2138 /* 2139 * We encode information in a dictionary 2140 * format with meaningful keys. 2141 */ 2142 desc = [NSMutableString stringWithCapacity: 128]; 2143 [desc appendFormat: @"{ ColorSpace = \"%@\";", [self colorSpaceName]]; 2144 [desc appendFormat: @" W = \"%g\";", (double)_white_component]; 2145 [desc appendFormat: @" Alpha = \"%g\"; }", (double)_alpha_component]; 2146 2147 return desc; 2148} 2149 2150- (void) getWhite: (CGFloat*)white 2151 alpha: (CGFloat*)alpha 2152{ 2153 // Only set what is wanted 2154 if (white) 2155 *white = _white_component; 2156 if (alpha) 2157 *alpha = _alpha_component; 2158} 2159 2160- (BOOL) isEqual: (id)other 2161{ 2162 if (other == self) 2163 return YES; 2164 if ([other isKindOfClass: [self class]] == NO 2165 || [other whiteComponent] != _white_component 2166 || [other alphaComponent] != _alpha_component) 2167 { 2168 return NO; 2169 } 2170 return YES; 2171} 2172 2173- (NSColor*) colorWithAlphaComponent: (CGFloat)alpha 2174{ 2175 GSWhiteColor *aCopy; 2176 2177 if (alpha < 0.0) alpha = 0.0; 2178 else if (alpha > 1.0) alpha = 1.0; 2179 2180 if (alpha == _alpha_component) 2181 return self; 2182 2183 aCopy = (GSWhiteColor*)NSCopyObject(self, 0, NSDefaultMallocZone()); 2184 2185 if (aCopy) 2186 { 2187 aCopy->_alpha_component = alpha; 2188 } 2189 2190 return AUTORELEASE(aCopy); 2191} 2192 2193- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 2194 device: (NSDictionary *)deviceDescription 2195{ 2196 if (colorSpace == nil) 2197 { 2198 if (deviceDescription != nil) 2199 colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName]; 2200 if (colorSpace == nil) 2201 colorSpace = NSCalibratedRGBColorSpace; 2202 } 2203 if ([colorSpace isEqualToString: [self colorSpaceName]]) 2204 { 2205 return self; 2206 } 2207 2208 if ([colorSpace isEqualToString: NSNamedColorSpace]) 2209 { 2210 // FIXME: We cannot convert to named color space. 2211 return nil; 2212 } 2213 2214 if ([colorSpace isEqualToString: NSDeviceWhiteColorSpace] 2215 || [colorSpace isEqualToString: NSDeviceBlackColorSpace]) 2216 { 2217 return [NSColor colorWithDeviceWhite: _white_component 2218 alpha: _alpha_component]; 2219 } 2220 2221 if ([colorSpace isEqualToString: NSCalibratedWhiteColorSpace] 2222 || [colorSpace isEqualToString: NSCalibratedBlackColorSpace]) 2223 { 2224 return [NSColor colorWithCalibratedWhite: _white_component 2225 alpha: _alpha_component]; 2226 } 2227 2228 if ([colorSpace isEqualToString: NSCalibratedRGBColorSpace]) 2229 { 2230 return [NSColor colorWithCalibratedRed: _white_component 2231 green: _white_component 2232 blue: _white_component 2233 alpha: _alpha_component]; 2234 } 2235 2236 if ([colorSpace isEqualToString: NSDeviceRGBColorSpace]) 2237 { 2238 return [NSColor colorWithDeviceRed: _white_component 2239 green: _white_component 2240 blue: _white_component 2241 alpha: _alpha_component]; 2242 } 2243 2244 if ([colorSpace isEqualToString: NSDeviceCMYKColorSpace]) 2245 { 2246 return [NSColor colorWithDeviceCyan: 0.0 2247 magenta: 0.0 2248 yellow: 0.0 2249 black: 1.0 - _white_component 2250 alpha: _alpha_component]; 2251 } 2252 2253 return nil; 2254} 2255 2256- (void) set 2257{ 2258 // This should be in GSDeviceWhiteColor, but is here to keep old code working 2259 NSDebugLLog(@"NSColor", @"Gray %g\n", (double)_white_component); 2260 PSsetgray(_white_component); 2261 // Should we check the ignore flag here? 2262 PSsetalpha(_alpha_component); 2263} 2264 2265// 2266// NSCoding protocol 2267// 2268- (void) encodeWithCoder: (NSCoder*)aCoder 2269{ 2270 if ([aCoder allowsKeyedCoding]) 2271 { 2272 NSString *str; 2273 2274 if ([[self colorSpaceName] isEqualToString: NSCalibratedWhiteColorSpace]) 2275 { 2276 [aCoder encodeInt: 3 forKey: @"NSColorSpace"]; 2277 } 2278 else 2279 { 2280 [aCoder encodeInt: 4 forKey: @"NSColorSpace"]; 2281 } 2282 2283 if (_alpha_component == 1.0) 2284 { 2285 str = [[NSString alloc] initWithFormat: @"%g", (double)_white_component]; 2286 } 2287 else 2288 { 2289 str = [[NSString alloc] initWithFormat: @"%g %g", (double)_white_component, (double)_alpha_component]; 2290 } 2291 [aCoder encodeBytes: (const uint8_t*)[str cString] 2292 length: [str cStringLength] 2293 forKey: @"NSWhite"]; 2294 RELEASE(str); 2295 } 2296 else 2297 { 2298 float white = _white_component; 2299 float alpha = _alpha_component; 2300 [aCoder encodeObject: [self colorSpaceName]]; 2301 [aCoder encodeValueOfObjCType: @encode(float) at: &white]; 2302 [aCoder encodeValueOfObjCType: @encode(float) at: &alpha]; 2303 } 2304} 2305 2306- (id) initWithCoder: (NSCoder*)aDecoder 2307{ 2308 float white, alpha; 2309 [aDecoder decodeValueOfObjCType: @encode(float) at: &white]; 2310 [aDecoder decodeValueOfObjCType: @encode(float) at: &alpha]; 2311 _white_component = white; 2312 _alpha_component = alpha; 2313 return self; 2314} 2315 2316@end 2317 2318@implementation GSDeviceWhiteColor 2319 2320- (NSString *) colorSpaceName 2321{ 2322 return NSDeviceWhiteColorSpace; 2323} 2324 2325- (NSColor*) initWithDeviceWhite: (CGFloat)white 2326 alpha: (CGFloat)alpha 2327{ 2328 if (white < 0.0) white = 0.0; 2329 else if (white > 1.0) white = 1.0; 2330 _white_component = white; 2331 2332 if (alpha < 0.0) alpha = 0.0; 2333 else if (alpha > 1.0) alpha = 1.0; 2334 _alpha_component = alpha; 2335 2336 return self; 2337} 2338 2339@end 2340 2341@implementation GSCalibratedWhiteColor 2342 2343- (NSString *) colorSpaceName 2344{ 2345 return NSCalibratedWhiteColorSpace; 2346} 2347 2348- (NSColor*) initWithCalibratedWhite: (CGFloat)white 2349 alpha: (CGFloat)alpha 2350{ 2351 if (white < 0.0) white = 0.0; 2352 else if (white > 1.0) white = 1.0; 2353 _white_component = white; 2354 2355 if (alpha < 0.0) alpha = 0.0; 2356 else if (alpha > 1.0) alpha = 1.0; 2357 _alpha_component = alpha; 2358 2359 return self; 2360} 2361 2362@end 2363 2364@implementation GSDeviceCMYKColor 2365 2366- (NSColor*) initWithDeviceCyan: (CGFloat)cyan 2367 magenta: (CGFloat)magenta 2368 yellow: (CGFloat)yellow 2369 black: (CGFloat)black 2370 alpha: (CGFloat)alpha 2371{ 2372 if (cyan < 0.0) cyan = 0.0; 2373 else if (cyan > 1.0) cyan = 1.0; 2374 _cyan_component = cyan; 2375 2376 if (magenta < 0.0) magenta = 0.0; 2377 else if (magenta > 1.0) magenta = 1.0; 2378 _magenta_component = magenta; 2379 2380 if (yellow < 0.0) yellow = 0.0; 2381 else if (yellow > 1.0) yellow = 1.0; 2382 _yellow_component = yellow; 2383 2384 if (black < 0.0) black = 0.0; 2385 else if (black > 1.0) black = 1.0; 2386 _black_component = black; 2387 2388 if (alpha < 0.0) alpha = 0.0; 2389 else if (alpha > 1.0) alpha = 1.0; 2390 _alpha_component = alpha; 2391 2392 return self; 2393} 2394 2395- (NSString *) colorSpaceName 2396{ 2397 return NSDeviceCMYKColorSpace; 2398} 2399 2400- (CGFloat) alphaComponent 2401{ 2402 return _alpha_component; 2403} 2404 2405- (CGFloat) blackComponent 2406{ 2407 return _black_component; 2408} 2409 2410- (CGFloat) cyanComponent 2411{ 2412 return _cyan_component; 2413} 2414 2415- (CGFloat) magentaComponent 2416{ 2417 return _magenta_component; 2418} 2419 2420- (CGFloat) yellowComponent 2421{ 2422 return _yellow_component; 2423} 2424 2425- (void) getComponents: (CGFloat *)components; 2426{ 2427 components[0] = _cyan_component; 2428 components[1] = _magenta_component; 2429 components[2] = _yellow_component; 2430 components[3] = _black_component; 2431 components[4] = _alpha_component; 2432} 2433 2434- (NSInteger) numberOfComponents 2435{ 2436 return 5; 2437} 2438 2439- (NSString*) description 2440{ 2441 NSMutableString *desc; 2442 2443 /* 2444 * We encode information in a dictionary 2445 * format with meaningful keys. 2446 */ 2447 desc = [NSMutableString stringWithCapacity: 128]; 2448 [desc appendFormat: @"{ ColorSpace = \"%@\";", [self colorSpaceName]]; 2449 [desc appendFormat: @" C = \"%g\";", (double)_cyan_component]; 2450 [desc appendFormat: @" M = \"%g\";", (double)_magenta_component]; 2451 [desc appendFormat: @" Y = \"%g\";", (double)_yellow_component]; 2452 [desc appendFormat: @" K = \"%g\";", (double)_black_component]; 2453 [desc appendFormat: @" Alpha = \"%g\"; }", (double)_alpha_component]; 2454 2455 return desc; 2456} 2457 2458- (void) getCyan: (CGFloat*)cyan 2459 magenta: (CGFloat*)magenta 2460 yellow: (CGFloat*)yellow 2461 black: (CGFloat*)black 2462 alpha: (CGFloat*)alpha 2463{ 2464 // Only set what is wanted 2465 if (cyan) 2466 *cyan = _cyan_component; 2467 if (magenta) 2468 *magenta = _magenta_component; 2469 if (yellow) 2470 *yellow = _yellow_component; 2471 if (black) 2472 *black = _black_component; 2473 if (alpha) 2474 *alpha = _alpha_component; 2475} 2476 2477- (BOOL) isEqual: (id)other 2478{ 2479 if (other == self) 2480 return YES; 2481 if ([other isKindOfClass: [self class]] == NO 2482 || [other cyanComponent] != _cyan_component 2483 || [other magentaComponent] != _magenta_component 2484 || [other yellowComponent] != _yellow_component 2485 || [other blackComponent] != _black_component 2486 || [other alphaComponent] != _alpha_component) 2487 { 2488 return NO; 2489 } 2490 return YES; 2491} 2492 2493- (NSColor*) colorWithAlphaComponent: (CGFloat)alpha 2494{ 2495 GSDeviceCMYKColor *aCopy; 2496 2497 if (alpha < 0.0) alpha = 0.0; 2498 else if (alpha > 1.0) alpha = 1.0; 2499 2500 if (alpha == _alpha_component) 2501 return self; 2502 2503 aCopy = (GSDeviceCMYKColor*)NSCopyObject(self, 0, NSDefaultMallocZone()); 2504 2505 if (aCopy) 2506 { 2507 aCopy->_alpha_component = alpha; 2508 } 2509 2510 return AUTORELEASE(aCopy); 2511} 2512 2513- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 2514 device: (NSDictionary *)deviceDescription 2515{ 2516 if (colorSpace == nil) 2517 { 2518 if (deviceDescription != nil) 2519 colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName]; 2520 if (colorSpace == nil) 2521 colorSpace = NSCalibratedRGBColorSpace; 2522 } 2523 if ([colorSpace isEqualToString: [self colorSpaceName]]) 2524 { 2525 return self; 2526 } 2527 2528 if ([colorSpace isEqualToString: NSNamedColorSpace]) 2529 { 2530 // FIXME: We cannot convert to named color space. 2531 return nil; 2532 } 2533 2534 if ([colorSpace isEqualToString: NSCalibratedRGBColorSpace]) 2535 { 2536 double c = _cyan_component; 2537 double m = _magenta_component; 2538 double y = _yellow_component; 2539 double white = 1 - _black_component; 2540 2541 return [NSColor colorWithCalibratedRed: (c > white ? 0 : white - c) 2542 green: (m > white ? 0 : white - m) 2543 blue: (y > white ? 0 : white - y) 2544 alpha: _alpha_component]; 2545 } 2546 2547 if ([colorSpace isEqualToString: NSDeviceRGBColorSpace]) 2548 { 2549 double c = _cyan_component; 2550 double m = _magenta_component; 2551 double y = _yellow_component; 2552 double white = 1 - _black_component; 2553 2554 return [NSColor colorWithDeviceRed: (c > white ? 0 : white - c) 2555 green: (m > white ? 0 : white - m) 2556 blue: (y > white ? 0 : white - y) 2557 alpha: _alpha_component]; 2558 } 2559 2560 if ([colorSpace isEqualToString: NSCalibratedWhiteColorSpace] 2561 || [colorSpace isEqualToString: NSCalibratedBlackColorSpace]) 2562 { 2563 return [NSColor colorWithCalibratedWhite: 1 - _black_component - 2564 (_cyan_component + _magenta_component + _yellow_component)/3 2565 alpha: _alpha_component]; 2566 } 2567 2568 if ([colorSpace isEqualToString: NSDeviceWhiteColorSpace] 2569 || [colorSpace isEqualToString: NSDeviceBlackColorSpace]) 2570 { 2571 return [NSColor colorWithDeviceWhite: 1 - _black_component - 2572 (_cyan_component + _magenta_component + _yellow_component)/3 2573 alpha: _alpha_component]; 2574 } 2575 2576 return nil; 2577} 2578 2579- (void) set 2580{ 2581 NSDebugLLog(@"NSColor", @"CMYK %g %g %g %g\n", 2582 (double)_cyan_component, (double)_magenta_component, 2583 (double)_yellow_component, (double)_black_component); 2584 PSsetcmykcolor(_cyan_component, _magenta_component, 2585 _yellow_component, _black_component); 2586 2587 // Should we check the ignore flag here? 2588 PSsetalpha(_alpha_component); 2589} 2590 2591// 2592// NSCoding protocol 2593// 2594- (void) encodeWithCoder: (NSCoder*)aCoder 2595{ 2596 if ([aCoder allowsKeyedCoding]) 2597 { 2598 NSString *str; 2599 2600 [aCoder encodeInt: 5 forKey: @"NSColorSpace"]; 2601 if (_alpha_component == 1.0) 2602 { 2603 str = [[NSString alloc] initWithFormat: @"%g %g %g %g", (double)_cyan_component, 2604 (double)_magenta_component, (double)_yellow_component, 2605 (double)_black_component]; 2606 } 2607 else 2608 { 2609 str = [[NSString alloc] initWithFormat: @"%g %g %g %g %g", (double)_cyan_component, 2610 (double)_magenta_component, (double)_yellow_component, 2611 (double)_black_component, (double)_alpha_component]; 2612 } 2613 [aCoder encodeBytes: (const uint8_t*)[str cString] 2614 length: [str cStringLength] 2615 forKey: @"NSCYMK"]; 2616 RELEASE(str); 2617 } 2618 else 2619 { 2620 float c = _cyan_component; 2621 float m = _magenta_component; 2622 float y = _yellow_component; 2623 float k = _black_component; 2624 float a = _alpha_component; 2625 [aCoder encodeObject: [self colorSpaceName]]; 2626 [aCoder encodeValueOfObjCType: @encode(float) at: &c]; 2627 [aCoder encodeValueOfObjCType: @encode(float) at: &m]; 2628 [aCoder encodeValueOfObjCType: @encode(float) at: &y]; 2629 [aCoder encodeValueOfObjCType: @encode(float) at: &k]; 2630 [aCoder encodeValueOfObjCType: @encode(float) at: &a]; 2631 } 2632} 2633 2634- (id) initWithCoder: (NSCoder*)aDecoder 2635{ 2636 // FIXME: Implement keyed decoding! 2637 2638 float c, m, y, k, a; 2639 [aDecoder decodeValueOfObjCType: @encode(float) at: &c]; 2640 [aDecoder decodeValueOfObjCType: @encode(float) at: &m]; 2641 [aDecoder decodeValueOfObjCType: @encode(float) at: &y]; 2642 [aDecoder decodeValueOfObjCType: @encode(float) at: &k]; 2643 [aDecoder decodeValueOfObjCType: @encode(float) at: &a]; 2644 _cyan_component = c; 2645 _magenta_component = m; 2646 _yellow_component = y; 2647 _black_component = k; 2648 _alpha_component = a; 2649 2650 return self; 2651} 2652 2653@end 2654 2655// RGB/HSB colours 2656@implementation GSRGBColor 2657 2658- (CGFloat) alphaComponent 2659{ 2660 return _alpha_component; 2661} 2662 2663- (CGFloat) redComponent 2664{ 2665 return _red_component; 2666} 2667 2668- (CGFloat) greenComponent 2669{ 2670 return _green_component; 2671} 2672 2673- (CGFloat) blueComponent 2674{ 2675 return _blue_component; 2676} 2677 2678- (CGFloat) hueComponent 2679{ 2680 return _hue_component; 2681} 2682 2683- (CGFloat) saturationComponent 2684{ 2685 return _saturation_component; 2686} 2687 2688- (CGFloat) brightnessComponent 2689{ 2690 return _brightness_component; 2691} 2692 2693- (void) getComponents: (CGFloat *)components; 2694{ 2695 components[0] = _red_component; 2696 components[1] = _green_component; 2697 components[2] = _blue_component; 2698 components[3] = _alpha_component; 2699} 2700 2701- (NSInteger) numberOfComponents 2702{ 2703 return 4; 2704} 2705 2706- (void) getHue: (CGFloat*)hue 2707 saturation: (CGFloat*)saturation 2708 brightness: (CGFloat*)brightness 2709 alpha: (CGFloat*)alpha 2710{ 2711 // Only set what is wanted 2712 if (hue) 2713 *hue = _hue_component; 2714 if (saturation) 2715 *saturation = _saturation_component; 2716 if (brightness) 2717 *brightness = _brightness_component; 2718 if (alpha) 2719 *alpha = _alpha_component; 2720} 2721 2722- (void) getRed: (CGFloat*)red 2723 green: (CGFloat*)green 2724 blue: (CGFloat*)blue 2725 alpha: (CGFloat*)alpha 2726{ 2727 // Only set what is wanted 2728 if (red) 2729 *red = _red_component; 2730 if (green) 2731 *green = _green_component; 2732 if (blue) 2733 *blue = _blue_component; 2734 if (alpha) 2735 *alpha = _alpha_component; 2736} 2737 2738- (BOOL) isEqual: (id)other 2739{ 2740 if (other == self) 2741 return YES; 2742 if ([other isKindOfClass: [self class]] == NO 2743 || [other redComponent] != _red_component 2744 || [other greenComponent] != _green_component 2745 || [other blueComponent] != _blue_component 2746 || [other alphaComponent] != _alpha_component) 2747 { 2748 return NO; 2749 } 2750 return YES; 2751} 2752 2753- (NSColor*) colorWithAlphaComponent: (CGFloat)alpha 2754{ 2755 GSRGBColor *aCopy; 2756 2757 if (alpha < 0.0) alpha = 0.0; 2758 else if (alpha > 1.0) alpha = 1.0; 2759 2760 if (alpha == _alpha_component) 2761 return self; 2762 2763 aCopy = (GSRGBColor*)NSCopyObject(self, 0, NSDefaultMallocZone()); 2764 2765 if (aCopy) 2766 { 2767 aCopy->_alpha_component = alpha; 2768 } 2769 2770 return AUTORELEASE(aCopy); 2771} 2772 2773- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace 2774 device: (NSDictionary *)deviceDescription 2775{ 2776 if (colorSpace == nil) 2777 { 2778 if (deviceDescription != nil) 2779 colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName]; 2780 if (colorSpace == nil) 2781 colorSpace = NSCalibratedRGBColorSpace; 2782 } 2783 if ([colorSpace isEqualToString: [self colorSpaceName]]) 2784 { 2785 return self; 2786 } 2787 2788 if ([colorSpace isEqualToString: NSNamedColorSpace]) 2789 { 2790 // FIXME: We cannot convert to named color space. 2791 return nil; 2792 } 2793 2794 if ([colorSpace isEqualToString: NSCalibratedRGBColorSpace]) 2795 { 2796 return [NSColor colorWithCalibratedRed: _red_component 2797 green: _green_component 2798 blue: _blue_component 2799 alpha: _alpha_component]; 2800 } 2801 2802 if ([colorSpace isEqualToString: NSDeviceRGBColorSpace]) 2803 { 2804 return [NSColor colorWithDeviceRed: _red_component 2805 green: _green_component 2806 blue: _blue_component 2807 alpha: _alpha_component]; 2808 } 2809 2810 if ([colorSpace isEqualToString: NSCalibratedWhiteColorSpace] 2811 || [colorSpace isEqualToString: NSCalibratedBlackColorSpace]) 2812 { 2813 return [NSColor colorWithCalibratedWhite: 2814 (_red_component + _green_component + _blue_component)/3 2815 alpha: _alpha_component]; 2816 } 2817 2818 if ([colorSpace isEqualToString: NSDeviceWhiteColorSpace] 2819 || [colorSpace isEqualToString: NSDeviceBlackColorSpace]) 2820 { 2821 return [NSColor colorWithDeviceWhite: 2822 (_red_component + _green_component + _blue_component)/3 2823 alpha: _alpha_component]; 2824 } 2825 2826 if ([colorSpace isEqualToString: NSDeviceCMYKColorSpace]) 2827 { 2828 return [NSColor colorWithDeviceCyan: 1 - _red_component 2829 magenta: 1 - _green_component 2830 yellow: 1 - _blue_component 2831 black: 0.0 2832 alpha: _alpha_component]; 2833 } 2834 2835 return nil; 2836} 2837 2838- (NSString*) description 2839{ 2840 NSMutableString *desc; 2841 2842 /* 2843 * For a simple RGB color without alpha, we use a shorthand description 2844 * consisting of the three component values in a quoted string. 2845 */ 2846 if (_alpha_component == 1.0) 2847 return [NSString stringWithFormat: @"%g %g %g", 2848 (double)_red_component, (double)_green_component, (double)_blue_component]; 2849 2850 /* 2851 * For more complex color values - we encode information in a dictionary 2852 * format with meaningful keys. 2853 */ 2854 desc = [NSMutableString stringWithCapacity: 128]; 2855 [desc appendFormat: @"{ ColorSpace = \"%@\";", [self colorSpaceName]]; 2856 [desc appendFormat: @" R = \"%g\";", (double)_red_component]; 2857 [desc appendFormat: @" G = \"%g\";", (double)_green_component]; 2858 [desc appendFormat: @" B = \"%g\";", (double)_blue_component]; 2859 [desc appendFormat: @" Alpha = \"%g\"; }", (double)_alpha_component]; 2860 return desc; 2861} 2862 2863- (void) set 2864{ 2865 /* This should only be in GSDeviceRGBColor, 2866 * but is here to keep old code working. 2867 */ 2868 NSDebugLLog(@"NSColor", @"RGB %g %g %g\n", (double)_red_component, 2869 (double)_green_component, (double)_blue_component); 2870 PSsetrgbcolor(_red_component, _green_component, 2871 _blue_component); 2872 // Should we check the ignore flag here? 2873 PSsetalpha(_alpha_component); 2874} 2875 2876- (void) setFill 2877{ 2878 int num = [self numberOfComponents]; 2879 CGFloat values[num]; 2880 NSGraphicsContext *ctxt = GSCurrentContext(); 2881 2882 [ctxt GSSetFillColorspace: [self colorSpace]]; 2883 [self getComponents: values]; 2884 [ctxt GSSetFillColor: values]; 2885} 2886 2887- (void) setStroke 2888{ 2889 int num = [self numberOfComponents]; 2890 CGFloat values[num]; 2891 NSGraphicsContext *ctxt = GSCurrentContext(); 2892 2893 [ctxt GSSetStrokeColorspace: [self colorSpace]]; 2894 [self getComponents: values]; 2895 [ctxt GSSetStrokeColor: values]; 2896} 2897 2898// 2899// NSCoding protocol 2900// 2901- (void) encodeWithCoder: (NSCoder*)aCoder 2902{ 2903 if ([aCoder allowsKeyedCoding]) 2904 { 2905 NSString *str; 2906 2907 if ([[self colorSpaceName] isEqualToString: NSCalibratedRGBColorSpace]) 2908 { 2909 [aCoder encodeInt: 1 forKey: @"NSColorSpace"]; 2910 } 2911 else 2912 { 2913 [aCoder encodeInt: 2 forKey: @"NSColorSpace"]; 2914 } 2915 2916 if (_alpha_component == 1.0) 2917 { 2918 str = [[NSString alloc] initWithFormat: @"%g %g %g", (double)_red_component, 2919 (double)_green_component, (double)_blue_component]; 2920 } 2921 else 2922 { 2923 str = [[NSString alloc] initWithFormat: @"%g %g %g %g", (double)_red_component, 2924 (double)_green_component, (double)_blue_component, 2925 (double)_alpha_component]; 2926 } 2927 [aCoder encodeBytes: (const uint8_t*)[str cString] 2928 length: [str cStringLength] 2929 forKey: @"NSRGB"]; 2930 RELEASE(str); 2931 } 2932 else 2933 { 2934 float red = _red_component; 2935 float green = _green_component; 2936 float blue = _blue_component; 2937 float hue = _hue_component; 2938 float saturation = _saturation_component; 2939 float brightness = _brightness_component; 2940 float alpha = _alpha_component; 2941 [aCoder encodeObject: [self colorSpaceName]]; 2942 [aCoder encodeValueOfObjCType: @encode(float) at: &red]; 2943 [aCoder encodeValueOfObjCType: @encode(float) at: &green]; 2944 [aCoder encodeValueOfObjCType: @encode(float) at: &blue]; 2945 [aCoder encodeValueOfObjCType: @encode(float) at: &hue]; 2946 [aCoder encodeValueOfObjCType: @encode(float) at: &saturation]; 2947 [aCoder encodeValueOfObjCType: @encode(float) at: &brightness]; 2948 [aCoder encodeValueOfObjCType: @encode(float) at: &alpha]; 2949 } 2950} 2951 2952- (id) initWithCoder: (NSCoder*)aDecoder 2953{ 2954 float red, green, blue, hue, saturation, brightness, alpha; 2955 [aDecoder decodeValueOfObjCType: @encode(float) at: &red]; 2956 [aDecoder decodeValueOfObjCType: @encode(float) at: &green]; 2957 [aDecoder decodeValueOfObjCType: @encode(float) at: &blue]; 2958 [aDecoder decodeValueOfObjCType: @encode(float) at: &hue]; 2959 [aDecoder decodeValueOfObjCType: @encode(float) at: &saturation]; 2960 [aDecoder decodeValueOfObjCType: @encode(float) at: &brightness]; 2961 [aDecoder decodeValueOfObjCType: @encode(float) at: &alpha]; 2962 _red_component = red; 2963 _green_component = green; 2964 _blue_component = blue; 2965 _hue_component = hue; 2966 _saturation_component = saturation; 2967 _brightness_component = brightness; 2968 _alpha_component = alpha; 2969 return self; 2970} 2971 2972@end 2973 2974@implementation GSDeviceRGBColor 2975 2976- (NSString *) colorSpaceName 2977{ 2978 return NSDeviceRGBColorSpace; 2979} 2980 2981- (NSColor*) initWithDeviceRed: (CGFloat)red 2982 green: (CGFloat)green 2983 blue: (CGFloat)blue 2984 alpha: (CGFloat)alpha 2985{ 2986 if (red < 0.0) red = 0.0; 2987 else if (red > 1.0) red = 1.0; 2988 _red_component = red; 2989 2990 if (green < 0.0) green = 0.0; 2991 else if (green > 1.0) green = 1.0; 2992 _green_component = green; 2993 2994 if (blue < 0.0) blue = 0.0; 2995 else if (blue > 1.0) blue = 1.0; 2996 _blue_component = blue; 2997 2998 { 2999 CGFloat r = _red_component; 3000 CGFloat g = _green_component; 3001 CGFloat b = _blue_component; 3002 3003 if (r == g && r == b) 3004 { 3005 _hue_component = 0; 3006 _saturation_component = 0; 3007 _brightness_component = r; 3008 } 3009 else 3010 { 3011 double H; 3012 double V; 3013 double Temp; 3014 double diff; 3015 3016 V = (r > g ? r : g); 3017 V = (b > V ? b : V); 3018 Temp = (r < g ? r : g); 3019 Temp = (b < Temp ? b : Temp); 3020 diff = V - Temp; 3021 if (V == r) 3022 { 3023 H = (g - b)/diff; 3024 } 3025 else if (V == g) 3026 { 3027 H = (b - r)/diff + 2; 3028 } 3029 else 3030 { 3031 H = (r - g)/diff + 4; 3032 } 3033 if (H < 0) 3034 { 3035 H += 6; 3036 } 3037 _hue_component = H/6; 3038 _saturation_component = diff/V; 3039 _brightness_component = V; 3040 } 3041 } 3042 3043 if (alpha < 0.0) alpha = 0.0; 3044 else if (alpha > 1.0) alpha = 1.0; 3045 _alpha_component = alpha; 3046 3047 return self; 3048} 3049 3050- (NSColor*) initWithDeviceHue: (CGFloat)hue 3051 saturation: (CGFloat)saturation 3052 brightness: (CGFloat)brightness 3053 alpha: (CGFloat)alpha; 3054{ 3055 if (hue < 0.0) hue = 0.0; 3056 else if (hue > 1.0) hue = 1.0; 3057 _hue_component = hue; 3058 3059 if (saturation < 0.0) saturation = 0.0; 3060 else if (saturation > 1.0) saturation = 1.0; 3061 _saturation_component = saturation; 3062 3063 if (brightness < 0.0) brightness = 0.0; 3064 else if (brightness > 1.0) brightness = 1.0; 3065 _brightness_component = brightness; 3066 3067 { 3068 int I = (int)(hue * 6); 3069 double V = brightness; 3070 double S = saturation; 3071 double F = (hue * 6) - I; 3072 double M = V * (1 - S); 3073 double N = V * (1 - S * F); 3074 double K = M - N + V; 3075 double R, G, B; 3076 3077 switch (I) 3078 { 3079 default: R = V; G = K; B = M; break; 3080 case 1: R = N; G = V; B = M; break; 3081 case 2: R = M; G = V; B = K; break; 3082 case 3: R = M; G = N; B = V; break; 3083 case 4: R = K; G = M; B = V; break; 3084 case 5: R = V; G = M; B = N; break; 3085 } 3086 _red_component = (CGFloat)R; 3087 _green_component = (CGFloat)G; 3088 _blue_component = (CGFloat)B; 3089 } 3090 3091 if (alpha < 0.0) alpha = 0.0; 3092 else if (alpha > 1.0) alpha = 1.0; 3093 _alpha_component = alpha; 3094 3095 return self; 3096} 3097 3098@end 3099 3100@implementation GSCalibratedRGBColor 3101 3102- (NSString *) colorSpaceName 3103{ 3104 return NSCalibratedRGBColorSpace; 3105} 3106 3107- (NSColor*) initWithCalibratedRed: (CGFloat)red 3108 green: (CGFloat)green 3109 blue: (CGFloat)blue 3110 alpha: (CGFloat)alpha 3111{ 3112 if (red < 0.0) red = 0.0; 3113 else if (red > 1.0) red = 1.0; 3114 _red_component = red; 3115 3116 if (green < 0.0) green = 0.0; 3117 else if (green > 1.0) green = 1.0; 3118 _green_component = green; 3119 3120 if (blue < 0.0) blue = 0.0; 3121 else if (blue > 1.0) blue = 1.0; 3122 _blue_component = blue; 3123 3124 { 3125 CGFloat r = _red_component; 3126 CGFloat g = _green_component; 3127 CGFloat b = _blue_component; 3128 3129 if (r == g && r == b) 3130 { 3131 _hue_component = 0; 3132 _saturation_component = 0; 3133 _brightness_component = r; 3134 } 3135 else 3136 { 3137 double H; 3138 double V; 3139 double Temp; 3140 double diff; 3141 3142 V = (r > g ? r : g); 3143 V = (b > V ? b : V); 3144 Temp = (r < g ? r : g); 3145 Temp = (b < Temp ? b : Temp); 3146 diff = V - Temp; 3147 if (V == r) 3148 { 3149 H = (g - b)/diff; 3150 } 3151 else if (V == g) 3152 { 3153 H = (b - r)/diff + 2; 3154 } 3155 else 3156 { 3157 H = (r - g)/diff + 4; 3158 } 3159 if (H < 0) 3160 { 3161 H += 6; 3162 } 3163 _hue_component = H/6; 3164 _saturation_component = diff/V; 3165 _brightness_component = V; 3166 } 3167 } 3168 3169 if (alpha < 0.0) alpha = 0.0; 3170 else if (alpha > 1.0) alpha = 1.0; 3171 _alpha_component = alpha; 3172 3173 return self; 3174} 3175 3176- (NSColor*) initWithCalibratedHue: (CGFloat)hue 3177 saturation: (CGFloat)saturation 3178 brightness: (CGFloat)brightness 3179 alpha: (CGFloat)alpha; 3180{ 3181 if (hue < 0.0) hue = 0.0; 3182 else if (hue > 1.0) hue = 1.0; 3183 _hue_component = hue; 3184 3185 if (saturation < 0.0) saturation = 0.0; 3186 else if (saturation > 1.0) saturation = 1.0; 3187 _saturation_component = saturation; 3188 3189 if (brightness < 0.0) brightness = 0.0; 3190 else if (brightness > 1.0) brightness = 1.0; 3191 _brightness_component = brightness; 3192 3193 { 3194 int I = (int)(hue * 6); 3195 double V = brightness; 3196 double S = saturation; 3197 double F = (hue * 6) - I; 3198 double M = V * (1 - S); 3199 double N = V * (1 - S * F); 3200 double K = M - N + V; 3201 double R, G, B; 3202 3203 switch (I) 3204 { 3205 default: R = V; G = K; B = M; break; 3206 case 1: R = N; G = V; B = M; break; 3207 case 2: R = M; G = V; B = K; break; 3208 case 3: R = M; G = N; B = V; break; 3209 case 4: R = K; G = M; B = V; break; 3210 case 5: R = V; G = M; B = N; break; 3211 } 3212 _red_component = (CGFloat)R; 3213 _green_component = (CGFloat)G; 3214 _blue_component = (CGFloat)B; 3215 } 3216 3217 if (alpha < 0.0) alpha = 0.0; 3218 else if (alpha > 1.0) alpha = 1.0; 3219 _alpha_component = alpha; 3220 3221 return self; 3222} 3223 3224@end 3225 3226@implementation GSPatternColor 3227 3228- (NSColor*) initWithPatternImage: (NSImage*) pattern; 3229{ 3230 ASSIGN(_pattern, pattern); 3231 3232 return self; 3233} 3234 3235- (void) dealloc 3236{ 3237 RELEASE(_pattern); 3238 [super dealloc]; 3239} 3240 3241- (NSString *) colorSpaceName 3242{ 3243 return NSPatternColorSpace; 3244} 3245 3246- (NSImage*) patternImage 3247{ 3248 return _pattern; 3249} 3250 3251- (NSString*) description 3252{ 3253 NSMutableString *desc; 3254 3255 /* 3256 * We encode information in a dictionary 3257 * format with meaningful keys. 3258 */ 3259 desc = [NSMutableString stringWithCapacity: 128]; 3260 [desc appendFormat: @"{ ColorSpace = \"%@\";", [self colorSpaceName]]; 3261 [desc appendFormat: @" Pattern = \"%@\"; }", [_pattern description]]; 3262 3263 return desc; 3264} 3265 3266- (NSUInteger) hash 3267{ 3268 return [_pattern hash]; 3269} 3270 3271- (BOOL) isEqual: (id)other 3272{ 3273 if (other == self) 3274 return YES; 3275 if ([other isKindOfClass: [self class]] == NO 3276 || [[other patternImage] isEqual: _pattern] == NO) 3277 { 3278 return NO; 3279 } 3280 return YES; 3281} 3282 3283- (id) copyWithZone: (NSZone*)aZone 3284{ 3285 if (NSShouldRetainWithZone(self, aZone)) 3286 { 3287 return RETAIN(self); 3288 } 3289 else 3290 { 3291 GSPatternColor *aCopy = (GSPatternColor*)NSCopyObject(self, 0, aZone); 3292 3293 aCopy->_pattern = [_pattern copyWithZone: aZone]; 3294 return aCopy; 3295 } 3296} 3297 3298- (void) set 3299{ 3300 [GSCurrentContext() GSSetPatterColor: _pattern]; 3301} 3302 3303// 3304// NSCoding protocol 3305// 3306- (void) encodeWithCoder: (NSCoder*)aCoder 3307{ 3308 if ([aCoder allowsKeyedCoding]) 3309 { 3310 [aCoder encodeInt: 10 forKey: @"NSColorSpace"]; 3311 [aCoder encodeObject: _pattern forKey: @"NSImage"]; 3312 } 3313 else 3314 { 3315 [aCoder encodeObject: [self colorSpaceName]]; 3316 [aCoder encodeObject: _pattern]; 3317 } 3318} 3319 3320- (id) initWithCoder: (NSCoder*)aDecoder 3321{ 3322 [aDecoder decodeValueOfObjCType: @encode(id) at: &_pattern]; 3323 3324 return self; 3325} 3326 3327@end 3328 3329// 3330// Implementation of the NSCoder additions 3331// 3332@implementation NSCoder (NSCoderAdditions) 3333 3334// 3335// Converting an archived NXColor to an NSColor 3336// 3337- (NSColor*) decodeNXColor 3338{ 3339 // FIXME 3340 return nil; 3341} 3342 3343@end 3344