libs-gui/Source/NSColor.m
Richard Frith-MacDonald 2fe9a3b83d Image caching improvements
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5406 72102866-910b-0410-8b05-ffd578937521
1999-12-07 21:30:04 +00:00

1681 lines
40 KiB
Objective-C

/*
NSColor.m
The colorful color class
Copyright (C) 1996, 1998 Free Software Foundation, Inc.
Author: Scott Christley <scottc@net-community.com>
Date: 1996
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <gnustep/gui/config.h>
#include <Foundation/NSString.h>
#include <Foundation/NSArchiver.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSUserDefaults.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSColorList.h>
#include <AppKit/NSColorPrivate.h>
#include <AppKit/NSPasteboard.h>
#include <AppKit/NSView.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/PSOperators.h>
NSString *NSSystemColorsDidChangeNotification =
@"NSSystemColorsDidChangeNotification";
@implementation NSColor
// Class variables
static BOOL gnustep_gui_ignores_alpha = YES;
static NSColorList *systemColors = nil;
static NSMutableDictionary *colorStrings = nil;
//
// Class methods
//
+ (void) initialize
{
if (self == [NSColor class])
{
NSString *white;
NSString *lightGray;
NSString *gray;
NSString *darkGray;
NSString *black;
// Set the version number
[self setVersion: 2];
// ignore alpha by default
gnustep_gui_ignores_alpha = YES;
// Set up a dictionary containing the names of all the system colors
// as keys and with colors in string format as values.
white = [NSString stringWithFormat: @"%f %f %f",
NSWhite, NSWhite, NSWhite];
lightGray = [NSString stringWithFormat: @"%f %f %f",
NSLightGray, NSLightGray, NSLightGray];
gray = [NSString stringWithFormat: @"%f %f %f",
NSGray, NSGray, NSGray];
darkGray = [NSString stringWithFormat: @"%f %f %f",
NSDarkGray, NSDarkGray, NSDarkGray];
black = [NSString stringWithFormat: @"%f %f %f",
NSBlack, NSBlack, NSBlack];
colorStrings = (NSMutableDictionary*)[[NSMutableDictionary
dictionaryWithObjectsAndKeys:
lightGray, @"controlBackgroundColor",
lightGray, @"controlColor",
lightGray, @"controlHighlightColor",
white, @"controlLightHighlightColor",
darkGray, @"controlShadowColor",
black, @"controlDarkShadowColor",
black, @"controlTextColor",
darkGray, @"disabledControlTextColor",
gray, @"gridColor",
white, @"highlightColor",
lightGray, @"knobColor",
gray, @"scrollBarColor",
white, @"selectedControlColor",
black, @"selectedControlTextColor",
white, @"selectedMenuItemColor",
black, @"selectedMenuItemTextColor",
lightGray, @"selectedTextBackgroundColor",
black, @"selectedTextColor",
lightGray, @"selectedKnobColor",
black, @"shadowColor",
white, @"textBackgroundColor",
black, @"textColor",
black, @"windowFrameColor",
white, @"windowFrameTextColor",
nil] retain];
// Set up default system colors
systemColors = [[NSColorList alloc] initWithName: @"System"];
// ensure user defaults are loaded, then use them and watch for changes.
[NSUserDefaults standardUserDefaults];
[self defaultsDidChange: nil];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(defaultsDidChange:)
name: NSUserDefaultsDidChangeNotification
object: nil];
}
}
//
// Creating an NSColor from Component Values
//
+ (NSColor*) colorWithCalibratedHue: (float)hue
saturation: (float)saturation
brightness: (float)brightness
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSCalibratedRGBColorSpace];
[c setActiveComponent: GNUSTEP_GUI_HSB_ACTIVE];
[c setHue: hue];
[c setSaturation: saturation];
[c setBrightness: brightness];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_HSB_ACTIVE];
return c;
}
+ (NSColor*) colorWithCalibratedRed: (float)red
green: (float)green
blue: (float)blue
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSCalibratedRGBColorSpace];
[c setActiveComponent: GNUSTEP_GUI_RGB_ACTIVE];
[c setRed: red];
[c setGreen: green];
[c setBlue: blue];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_RGB_ACTIVE];
return c;
}
+ (NSColor*) colorWithCalibratedWhite: (float)white
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSCalibratedWhiteColorSpace];
[c setActiveComponent: GNUSTEP_GUI_WHITE_ACTIVE];
[c setWhite: white];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_WHITE_ACTIVE];
return c;
}
+ (NSColor*) colorWithCatalogName: (NSString *)listName
colorName: (NSString *)colorName
{
return nil;
}
+ (NSColor*) colorWithDeviceCyan: (float)cyan
magenta: (float)magenta
yellow: (float)yellow
black: (float)black
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSDeviceCMYKColorSpace];
[c setActiveComponent: GNUSTEP_GUI_CMYK_ACTIVE];
[c setCyan: cyan];
[c setMagenta: magenta];
[c setYellow: yellow];
[c setBlack: black];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_CMYK_ACTIVE];
return c;
}
+ (NSColor*) colorWithDeviceHue: (float)hue
saturation: (float)saturation
brightness: (float)brightness
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSDeviceRGBColorSpace];
[c setActiveComponent: GNUSTEP_GUI_HSB_ACTIVE];
[c setHue: hue];
[c setSaturation: saturation];
[c setBrightness: brightness];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_HSB_ACTIVE];
return c;
}
+ (NSColor*) colorWithDeviceRed: (float)red
green: (float)green
blue: (float)blue
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSDeviceRGBColorSpace];
[c setActiveComponent: GNUSTEP_GUI_RGB_ACTIVE];
[c setRed: red];
[c setGreen: green];
[c setBlue: blue];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_RGB_ACTIVE];
return c;
}
+ (NSColor*) colorWithDeviceWhite: (float)white
alpha: (float)alpha
{
NSColor *c;
c = [[[self allocWithZone: NSDefaultMallocZone()] init] autorelease];
[c setColorSpaceName: NSDeviceWhiteColorSpace];
[c setActiveComponent: GNUSTEP_GUI_WHITE_ACTIVE];
[c setWhite: white];
[c setAlpha: alpha];
[c setValidComponents: GNUSTEP_GUI_WHITE_ACTIVE];
return c;
}
//
// Creating an NSColor With Preset Components
//
+ (NSColor*) blackColor
{
return [self colorWithCalibratedWhite: NSBlack alpha: 1.0];
}
+ (NSColor*) blueColor
{
return [self colorWithCalibratedRed: 0.0
green: 0.0
blue: 1.0
alpha: 1.0];
}
+ (NSColor*) brownColor
{
return [self colorWithCalibratedRed: 0.6
green: 0.4
blue: 0.2
alpha: 1.0];
}
+ (NSColor*) clearColor
{
NSColor *c;
c = [self colorWithCalibratedRed: 0.0
green: 0.0
blue: 0.0
alpha: 0.0];
[c setClear: YES];
return c;
}
+ (NSColor*) cyanColor
{
return [self colorWithCalibratedRed: 0.0
green: 1.0
blue: 1.0
alpha: 1.0];
}
+ (NSColor*) darkGrayColor
{
return [self colorWithCalibratedWhite: NSDarkGray alpha: 1.0];
}
+ (NSColor*) grayColor
{
return [self colorWithCalibratedWhite: NSGray alpha: 1.0];
}
+ (NSColor*) greenColor
{
return [self colorWithCalibratedRed: 0.0
green: 1.0
blue: 0.0
alpha: 1.0];
}
+ (NSColor*) lightGrayColor
{
return [self colorWithCalibratedWhite: NSLightGray alpha: 1];
}
+ (NSColor*) magentaColor
{
return [self colorWithCalibratedRed: 1.0
green: 0.0
blue: 1.0
alpha: 1.0];
}
+ (NSColor*) orangeColor;
{
return [self colorWithCalibratedRed: 1.0
green: 0.5
blue: 0.0
alpha: 1.0];
}
+ (NSColor*) purpleColor;
{
return [self colorWithCalibratedRed: 0.5
green: 0.0
blue: 0.5
alpha: 1.0];
}
+ (NSColor*) redColor;
{
return [self colorWithCalibratedRed: 1.0
green: 0.0
blue: 0.0
alpha: 1.0];
}
+ (NSColor*) whiteColor;
{
return [self colorWithCalibratedWhite: NSWhite alpha: 1.0];
}
+ (NSColor*) yellowColor
{
return [self colorWithCalibratedRed: 1.0
green: 1.0
blue: 0.0
alpha: 1.0];
}
//
// Ignoring Alpha Components
//
+ (BOOL) ignoresAlpha
{
return gnustep_gui_ignores_alpha;
}
+ (void) setIgnoresAlpha: (BOOL)flag
{
gnustep_gui_ignores_alpha = flag;
}
//
// Copying and Pasting
//
+ (NSColor*) colorFromPasteboard: (NSPasteboard *)pasteBoard
{
NSData *d = [pasteBoard dataForType: NSColorPboardType];
if (d)
return [NSUnarchiver unarchiveObjectWithData: d];
return nil;
}
//
// System colors stuff.
//
+ (NSColor*) controlBackgroundColor
{
NSColor *color = [systemColors colorWithKey: @"controlBackgroundColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlBackgroundColor"];
return color;
}
+ (NSColor*) controlColor
{
NSColor *color = [systemColors colorWithKey: @"controlColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlColor"];
return color;
}
+ (NSColor*) controlHighlightColor
{
NSColor *color = [systemColors colorWithKey: @"controlHighlightColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlHighlightColor"];
return color;
}
+ (NSColor*) controlLightHighlightColor
{
NSColor *color = [systemColors colorWithKey: @"controlLightHighlightColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlLightHighlightColor"];
return color;
}
+ (NSColor*) controlShadowColor
{
NSColor *color = [systemColors colorWithKey: @"controlShadowColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlShadowColor"];
return color;
}
+ (NSColor*) controlDarkShadowColor
{
NSColor *color = [systemColors colorWithKey: @"controlDarkShadowColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlDarkShadowColor"];
return color;
}
+ (NSColor*) controlTextColor
{
NSColor *color = [systemColors colorWithKey: @"controlTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"controlTextColor"];
return color;
}
+ (NSColor*) disabledControlTextColor
{
NSColor *color = [systemColors colorWithKey: @"disabledControlTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"disabledControlTextColor"];
return color;
}
+ (NSColor*) gridColor
{
NSColor *color = [systemColors colorWithKey: @"gridColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"gridColor"];
return color;
}
+ (NSColor*) highlightColor
{
NSColor *color = [systemColors colorWithKey: @"highlightColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"highlightColor"];
return color;
}
+ (NSColor*) knobColor
{
NSColor *color = [systemColors colorWithKey: @"knobColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"knobColor"];
return color;
}
+ (NSColor*) scrollBarColor
{
NSColor *color = [systemColors colorWithKey: @"scrollBarColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"scrollBarColor"];
return color;
}
+ (NSColor*) selectedControlColor
{
NSColor *color = [systemColors colorWithKey: @"selectedControlColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedControlColor"];
return color;
}
+ (NSColor*) selectedControlTextColor
{
NSColor *color = [systemColors colorWithKey: @"selectedControlTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedControlTextColor"];
return color;
}
+ (NSColor*) selectedMenuItemColor
{
NSColor *color = [systemColors colorWithKey: @"selectedMenuItemColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedMenuItemColor"];
return color;
}
+ (NSColor*) selectedMenuItemTextColor
{
NSColor *color = [systemColors colorWithKey: @"selectedMenuItemTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedMenuItemTextColor"];
return color;
}
+ (NSColor*) selectedTextBackgroundColor
{
NSColor *color = [systemColors colorWithKey: @"selectedTextBackgroundColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedTextBackgroundColor"];
return color;
}
+ (NSColor*) selectedTextColor
{
NSColor *color = [systemColors colorWithKey: @"selectedTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedTextColor"];
return color;
}
+ (NSColor*) selectedKnobColor
{
NSColor *color = [systemColors colorWithKey: @"selectedKnobColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"selectedKnobColor"];
return color;
}
+ (NSColor*) shadowColor
{
NSColor *color = [systemColors colorWithKey: @"shadowColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"shadowColor"];
return color;
}
+ (NSColor*) textBackgroundColor
{
NSColor *color = [systemColors colorWithKey: @"textBackgroundColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"textBackgroundColor"];
return color;
}
+ (NSColor*) textColor
{
NSColor *color = [systemColors colorWithKey: @"textColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"textColor"];
return color;
}
+ (NSColor*) windowFrameColor
{
NSColor *color = [systemColors colorWithKey: @"windowFrameColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"windowFrameColor"];
return color;
}
+ (NSColor*) windowFrameTextColor
{
NSColor *color = [systemColors colorWithKey: @"windowFrameTextColor"];
if (color == nil)
color = [NSColor systemColorWithName: @"windowFrameTextColor"];
return color;
}
////////////////////////////////////////////////////////////
//
// Instance methods
//
- init
{
[super init];
colorspace_name = @"";
catalog_name = @"";
color_name = @"";
return self;
}
- (id) copyWithZone: (NSZone*)aZone
{
if (NSShouldRetainWithZone(self, aZone))
{
return [self retain];
}
else
{
NSColor *aCopy = NSCopyObject(self, 0, aZone);
aCopy->colorspace_name = [colorspace_name copyWithZone: aZone];
aCopy->catalog_name = [catalog_name copyWithZone: aZone];
aCopy->color_name = [color_name copyWithZone: aZone];
return aCopy;
}
}
- (NSString*) description
{
NSMutableString *desc;
NSAssert(colorspace_name != nil, NSInternalInconsistencyException);
/*
* For a simple RGB color without alpha, we use a shorthand description
* consisting of the three componets values in a quoted string.
*/
if ([colorspace_name isEqualToString: NSCalibratedRGBColorSpace] &&
alpha_component == 1.0)
return [NSString stringWithFormat: @"\"%f %f %f\"",
RGB_component.red, RGB_component.green, RGB_component.blue];
/*
* For more complex color values - we encode information in a dictionary
* format with meaningful keys.
*/
desc = [NSMutableString stringWithCapacity: 128];
[desc appendFormat: @"{ ColorSpace = \"%@\";", colorspace_name];
if ([colorspace_name isEqual: NSCalibratedWhiteColorSpace])
{
[desc appendFormat: @" W = \"%f\";", white_component];
}
if ([colorspace_name isEqual: NSCalibratedBlackColorSpace])
{
[desc appendFormat: @" W = \"%f\";", white_component];
}
if ([colorspace_name isEqual: NSCalibratedRGBColorSpace])
{
if (active_component == GNUSTEP_GUI_HSB_ACTIVE)
{
[desc appendFormat: @" H = \"%f\";", HSB_component.hue];
[desc appendFormat: @" S = \"%f\";", HSB_component.saturation];
[desc appendFormat: @" B = \"%f\";", HSB_component.brightness];
}
else
{
[desc appendFormat: @" R = \"%f\";", RGB_component.red];
[desc appendFormat: @" G = \"%f\";", RGB_component.green];
[desc appendFormat: @" B = \"%f\";", RGB_component.blue];
}
}
if ([colorspace_name isEqual: NSDeviceWhiteColorSpace])
{
[desc appendFormat: @" W = \"%f\";", white_component];
}
if ([colorspace_name isEqual: NSDeviceBlackColorSpace])
{
[desc appendFormat: @" W = \"%f\";", white_component];
}
if ([colorspace_name isEqual: NSDeviceRGBColorSpace])
{
if (active_component == GNUSTEP_GUI_HSB_ACTIVE)
{
[desc appendFormat: @" H = \"%f\";", HSB_component.hue];
[desc appendFormat: @" S = \"%f\";", HSB_component.saturation];
[desc appendFormat: @" B = \"%f\";", HSB_component.brightness];
}
else
{
[desc appendFormat: @" R = \"%f\";", RGB_component.red];
[desc appendFormat: @" G = \"%f\";", RGB_component.green];
[desc appendFormat: @" B = \"%f\";", RGB_component.blue];
}
}
if ([colorspace_name isEqual: NSDeviceCMYKColorSpace])
{
[desc appendFormat: @" C = \"%f\";", CMYK_component.cyan];
[desc appendFormat: @" M = \"%f\";", CMYK_component.magenta];
[desc appendFormat: @" Y = \"%f\";", CMYK_component.yellow];
[desc appendFormat: @" K = \"%f\";", CMYK_component.black];
}
if ([colorspace_name isEqual: NSNamedColorSpace])
{
[desc appendFormat: @" Catalog = \"%@\";", catalog_name];
[desc appendFormat: @" Color = \"%@\";", color_name];
}
[desc appendFormat: @" Alpha = \"%f\"; }", alpha_component];
return desc;
}
//
// Retrieving a Set of Components
//
- (void) getCyan: (float*)cyan
magenta: (float*)magenta
yellow: (float*)yellow
black: (float*)black
alpha: (float*)alpha
{
if ((valid_components & GNUSTEP_GUI_CMYK_ACTIVE) == 0)
[self supportMaxColorSpaces];
// Only set what is wanted
// If not a CMYK color then you get bogus values
if (cyan)
*cyan = CMYK_component.cyan;
if (magenta)
*magenta = CMYK_component.magenta;
if (yellow)
*yellow = CMYK_component.yellow;
if (black)
*black = CMYK_component.black;
if (alpha)
*alpha = alpha_component;
}
- (void) getHue: (float*)hue
saturation: (float*)saturation
brightness: (float*)brightness
alpha: (float*)alpha
{
if ((valid_components & GNUSTEP_GUI_HSB_ACTIVE) == 0)
[self supportMaxColorSpaces];
// Only set what is wanted
// If not an HSB color then you get bogus values
if (hue)
*hue = HSB_component.hue;
if (saturation)
*saturation = HSB_component.saturation;
if (brightness)
*brightness = HSB_component.brightness;
if (alpha)
*alpha = alpha_component;
}
- (void) getRed: (float*)red
green: (float*)green
blue: (float*)blue
alpha: (float*)alpha
{
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
[self supportMaxColorSpaces];
// Only set what is wanted
// If not an RGB color then you get bogus values
if (red)
*red = RGB_component.red;
if (green)
*green = RGB_component.green;
if (blue)
*blue = RGB_component.blue;
if (alpha)
*alpha = alpha_component;
}
- (void) getWhite: (float*)white
alpha: (float*)alpha
{
if ((valid_components & GNUSTEP_GUI_WHITE_ACTIVE) == 0)
[self supportMaxColorSpaces];
// Only set what is wanted
// If not a grayscale color then you get bogus values
if (white)
*white = white_component;
if (alpha)
*alpha = alpha_component;
}
- (BOOL) isEqual: (id)other
{
if (other == self)
return YES;
if ([other isKindOfClass: [NSColor class]] == NO)
return NO;
else
{
NSColor *col = (NSColor*)other;
if (col->active_component != active_component)
return NO;
if (col->alpha_component != alpha_component)
return NO;
switch (active_component)
{
case GNUSTEP_GUI_RGB_ACTIVE:
if (col->RGB_component.red != RGB_component.red
|| col->RGB_component.green != RGB_component.green
|| col->RGB_component.blue != RGB_component.blue)
return NO;
return YES;
case GNUSTEP_GUI_CMYK_ACTIVE:
if (col->CMYK_component.cyan != CMYK_component.cyan
|| col->CMYK_component.magenta != CMYK_component.magenta
|| col->CMYK_component.yellow != CMYK_component.yellow
|| col->CMYK_component.black != CMYK_component.black)
return NO;
return YES;
case GNUSTEP_GUI_HSB_ACTIVE:
if (col->HSB_component.hue != HSB_component.hue
|| col->HSB_component.saturation != HSB_component.saturation
|| col->HSB_component.brightness != HSB_component.brightness)
return NO;
return YES;
case GNUSTEP_GUI_WHITE_ACTIVE:
if (col->white_component != white_component)
return NO;
return YES;
}
return NO;
}
}
//
// Retrieving Individual Components
//
- (float) alphaComponent
{
return alpha_component;
}
- (float) blackComponent
{
return CMYK_component.black;
}
- (float) blueComponent
{
return RGB_component.blue;
}
- (float) brightnessComponent
{
return HSB_component.brightness;
}
- (NSString *) catalogNameComponent
{
return catalog_name;
}
- (NSString *) colorNameComponent
{
return color_name;
}
- (float) cyanComponent
{
return CMYK_component.cyan;
}
- (float) greenComponent
{
return RGB_component.green;
}
- (float) hueComponent
{
return HSB_component.hue;
}
- (NSString *) localizedCatalogNameComponent
{
// +++ how do we localize?
return catalog_name;
}
- (NSString *) localizedColorNameComponent
{
// +++ how do we localize?
return color_name;
}
- (float) magentaComponent
{
return CMYK_component.magenta;
}
- (float) redComponent
{
return RGB_component.red;
}
- (float) saturationComponent
{
return HSB_component.saturation;
}
- (float) whiteComponent
{
return white_component;
}
- (float) yellowComponent
{
return CMYK_component.yellow;
}
//
// Converting to Another Color Space
//
- (NSString *) colorSpaceName
{
return colorspace_name;
}
- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace
{
if (colorSpace == nil)
{
colorSpace = NSCalibratedRGBColorSpace;
}
if ([colorSpace isEqualToString: colorspace_name])
{
return self;
}
[self supportMaxColorSpaces];
if ([colorSpace isEqualToString: NSCalibratedRGBColorSpace])
{
if (valid_components & GNUSTEP_GUI_RGB_ACTIVE)
{
NSColor *aCopy = [self copy];
if (aCopy)
{
aCopy->active_component = GNUSTEP_GUI_RGB_ACTIVE;
[aCopy setColorSpaceName: NSCalibratedRGBColorSpace];
}
return aCopy;
}
}
if ([colorSpace isEqualToString: NSCalibratedWhiteColorSpace])
{
if (valid_components & GNUSTEP_GUI_WHITE_ACTIVE)
{
NSColor *aCopy = [self copy];
if (aCopy)
{
aCopy->active_component = GNUSTEP_GUI_WHITE_ACTIVE;
[aCopy setColorSpaceName: NSCalibratedWhiteColorSpace];
}
return aCopy;
}
}
if ([colorSpace isEqualToString: NSCalibratedBlackColorSpace])
{
if (valid_components & GNUSTEP_GUI_WHITE_ACTIVE)
{
NSColor *aCopy = [self copy];
if (aCopy)
{
aCopy->active_component = GNUSTEP_GUI_WHITE_ACTIVE;
[aCopy setColorSpaceName: NSCalibratedBlackColorSpace];
}
return aCopy;
}
}
return nil;
}
- (NSColor*) colorUsingColorSpaceName: (NSString *)colorSpace
device: (NSDictionary *)deviceDescription
{
return nil;
}
//
// Changing the Color
//
- (NSColor*) blendedColorWithFraction: (float)fraction
ofColor: (NSColor*)aColor
{
NSColor *myColor = self;
NSColor *other = aColor;
float mr, mg, mb, or, og, ob, red, green, blue;
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
[self supportMaxColorSpaces];
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
myColor = [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
}
}
if ((aColor->valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
[aColor supportMaxColorSpaces];
if ((aColor->valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
other = [aColor colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
}
}
if (myColor == nil || other == nil)
{
return nil;
}
[myColor getRed: &mr green: &mg blue: &mb alpha: 0];
[other getRed: &or green: &og blue: &ob alpha: 0];
red = fraction * mr + (1 - fraction) * or;
green = fraction * mg + (1 - fraction) * og;
blue = fraction * mb + (1 - fraction) * ob;
return [NSColor colorWithCalibratedRed: red
green: green
blue: blue
alpha: 1.0];
}
- (NSColor*) colorWithAlphaComponent: (float)alpha
{
NSColor *aCopy = [self copy];
if (aCopy)
[aCopy setAlpha: alpha];
return aCopy;
}
- (NSColor*) highlightWithLevel: (float)level
{
return [self blendedColorWithFraction: level
ofColor: [NSColor highlightColor]];
}
- (NSColor*) shadowWithLevel: (float)level
{
return [self blendedColorWithFraction: level
ofColor: [NSColor shadowColor]];
}
//
// Copying and Pasting
//
- (void) writeToPasteboard: (NSPasteboard *)pasteBoard
{
NSData *d = [NSArchiver archivedDataWithRootObject: self];
if (d)
[pasteBoard setData: d forType: NSColorPboardType];
}
//
// Drawing
//
- (void) drawSwatchInRect: (NSRect)rect
{
[self set];
NSRectFill(rect);
}
- (void) set
{
switch (active_component)
{
case GNUSTEP_GUI_RGB_ACTIVE:
NSDebugLLog(@"NSColor", @"RGB %f %f %f\n", RGB_component.red,
RGB_component.green, RGB_component.blue);
PSsetrgbcolor(RGB_component.red, RGB_component.green,
RGB_component.blue);
break;
case GNUSTEP_GUI_CMYK_ACTIVE:
NSDebugLLog(@"NSColor", @"CMYK %f %f %f %f\n", CMYK_component.cyan,
CMYK_component.magenta,
CMYK_component.yellow, CMYK_component.black);
PSsetcmykcolor(CMYK_component.cyan, CMYK_component.magenta,
CMYK_component.yellow, CMYK_component.black);
break;
case GNUSTEP_GUI_HSB_ACTIVE:
NSDebugLLog(@"NSColor", @"HSB %f %f %f\n", HSB_component.hue,
HSB_component.saturation, HSB_component.brightness);
PSsethsbcolor(HSB_component.hue, HSB_component.saturation,
HSB_component.brightness);
break;
case GNUSTEP_GUI_WHITE_ACTIVE:
NSDebugLLog(@"NSColor", @"Gray %f\n", white_component);
PSsetgray(white_component);
}
PSsetalpha(alpha_component);
}
//
// Destroying
//
- (void) dealloc
{
[colorspace_name release];
[catalog_name release];
[color_name release];
[super dealloc];
}
//
// NSCoding protocol
//
- (void) encodeWithCoder: (NSCoder*)aCoder
{
// Version 1
[aCoder encodeValueOfObjCType: @encode(float) at: &RGB_component.red];
[aCoder encodeValueOfObjCType: @encode(float) at: &RGB_component.green];
[aCoder encodeValueOfObjCType: @encode(float) at: &RGB_component.blue];
[aCoder encodeValueOfObjCType: @encode(float) at: &alpha_component];
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &is_clear];
// Version 2
[aCoder encodeObject: colorspace_name];
[aCoder encodeObject: catalog_name];
[aCoder encodeObject: color_name];
[aCoder encodeValueOfObjCType: @encode(float) at: &CMYK_component.cyan];
[aCoder encodeValueOfObjCType: @encode(float) at: &CMYK_component.magenta];
[aCoder encodeValueOfObjCType: @encode(float) at: &CMYK_component.yellow];
[aCoder encodeValueOfObjCType: @encode(float) at: &CMYK_component.black];
[aCoder encodeValueOfObjCType: @encode(float) at: &HSB_component.hue];
[aCoder encodeValueOfObjCType: @encode(float) at: &HSB_component.saturation];
[aCoder encodeValueOfObjCType: @encode(float) at: &HSB_component.brightness];
[aCoder encodeValueOfObjCType: @encode(float) at: &white_component];
[aCoder encodeValueOfObjCType: @encode(int) at: &active_component];
[aCoder encodeValueOfObjCType: @encode(int) at: &valid_components];
}
- (id) initWithCoder: (NSCoder*)aDecoder
{
NSString *s;
// Version 1
[aDecoder decodeValueOfObjCType: @encode(float) at: &RGB_component.red];
[aDecoder decodeValueOfObjCType: @encode(float) at: &RGB_component.green];
[aDecoder decodeValueOfObjCType: @encode(float) at: &RGB_component.blue];
[aDecoder decodeValueOfObjCType: @encode(float) at: &alpha_component];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &is_clear];
// Get our class name
s = NSStringFromClass(isa);
// Version 2
// +++ Coding cannot return class version yet
// if ([aDecoder versionForClassName: s] > 1)
{
[aDecoder decodeValueOfObjCType: @encode(id) at: &colorspace_name];
[aDecoder decodeValueOfObjCType: @encode(id) at: &catalog_name];
[aDecoder decodeValueOfObjCType: @encode(id) at: &color_name];
[aDecoder decodeValueOfObjCType: @encode(float) at: &CMYK_component.cyan];
[aDecoder decodeValueOfObjCType: @encode(float) at: &CMYK_component.magenta];
[aDecoder decodeValueOfObjCType: @encode(float) at: &CMYK_component.yellow];
[aDecoder decodeValueOfObjCType: @encode(float) at: &CMYK_component.black];
[aDecoder decodeValueOfObjCType: @encode(float) at: &HSB_component.hue];
[aDecoder decodeValueOfObjCType: @encode(float) at: &HSB_component.saturation];
[aDecoder decodeValueOfObjCType: @encode(float) at: &HSB_component.brightness];
[aDecoder decodeValueOfObjCType: @encode(float) at: &white_component];
[aDecoder decodeValueOfObjCType: @encode(int) at: &active_component];
[aDecoder decodeValueOfObjCType: @encode(int) at: &valid_components];
}
return self;
}
@end
//
// Private methods
//
@implementation NSColor (GNUstepPrivate)
+ (NSColor*) colorFromString: (NSString*)str
{
if ([str hasPrefix: @"{"])
{
NSDictionary *dict;
NSString *space;
NSString *str;
float alpha;
dict = [str propertyList];
if (dict == nil)
return nil;
if ((space = [dict objectForKey: @"ColorSpace"]) == nil)
return nil;
str = [dict objectForKey: @"Alpha"];
if (str == nil || [str isEqualToString: @""])
{
alpha = 1.0;
}
else
{
alpha = [str floatValue];
}
if ([space isEqual: NSCalibratedWhiteColorSpace])
{
float white = [[dict objectForKey: @"W"] floatValue];
return [self colorWithCalibratedWhite: white alpha: alpha];
}
if ([space isEqual: NSCalibratedBlackColorSpace])
{
float white = [[dict objectForKey: @"W"] floatValue];
return [self colorWithCalibratedWhite: white
alpha: alpha];
}
if ([space isEqual: NSCalibratedRGBColorSpace])
{
if ([dict objectForKey: @"H"] != nil)
{
float hue = [[dict objectForKey: @"H"] floatValue];
float saturation = [[dict objectForKey: @"S"] floatValue];
float brightness = [[dict objectForKey: @"B"] floatValue];
return [self colorWithCalibratedHue: hue
saturation: saturation
brightness: brightness
alpha: alpha];
}
else
{
float red = [[dict objectForKey: @"R"] floatValue];
float green = [[dict objectForKey: @"G"] floatValue];
float blue = [[dict objectForKey: @"B"] floatValue];
return [self colorWithCalibratedRed: red
green: green
blue: blue
alpha: alpha];
}
}
if ([space isEqual: NSDeviceCMYKColorSpace])
{
float cyan = [[dict objectForKey: @"C"] floatValue];
float magenta = [[dict objectForKey: @"M"] floatValue];
float yellow = [[dict objectForKey: @"Y"] floatValue];
float black = [[dict objectForKey: @"B"] floatValue];
return [self colorWithDeviceCyan: cyan
magenta: magenta
yellow: yellow
black: black
alpha: alpha];
}
if ([space isEqual: NSNamedColorSpace])
{
NSString *cat = [dict objectForKey: @"Catalog"];
NSString *col = [dict objectForKey: @"Color"];
return [self colorWithCatalogName: cat
colorName: col];
}
}
else if (str)
{
const char *ptr = [str cString];
float r, g, b;
sscanf(ptr, "%f %f %f", &r, &g, &b);
return [self colorWithCalibratedRed: r
green: g
blue: b
alpha: 1.0];
}
return nil;
}
+ (NSColor*) systemColorWithName: (NSString*)name
{
NSColor *color;
NSString *rep = [colorStrings objectForKey: name];
if (rep == nil)
{
NSLog(@"Request for unknown system color - '%@'\n", name);
return nil;
}
color = [NSColor colorFromString: rep];
if (color == nil)
{
NSLog(@"System color '%@' has bad string rep - '%@'\n", name, rep);
return nil;
}
[systemColors setColor: color forKey: name];
return color;
}
/*
* Go through all the names of system colors - for each color where
* there is a value in the defaults database, see if the current
* istring value of the color differs from the old one.
* Where there is a difference, update the color strings dictionary
* and, where a color object exists, update the system colors list
* to contain the new color.
* Finally, issue a notification if appropriate.
*/
+ (void) defaultsDidChange: (NSNotification*)notification
{
NSUserDefaults *defs;
NSEnumerator *enumerator;
NSString *key;
BOOL didChange = NO;
defs = [NSUserDefaults standardUserDefaults];
enumerator = [colorStrings keyEnumerator];
while ((key = [enumerator nextObject]) != nil)
{
NSString *def = [defs stringForKey: key];
if (def != nil)
{
NSString *old = [colorStrings objectForKey: key];
if ([def isEqualToString: old] == NO)
{
NSColor *color;
didChange = YES;
[colorStrings setObject: def forKey: key];
color = [systemColors colorWithKey: key];
if (color != nil)
{
color = [NSColor colorFromString: def];
if (color == nil)
{
NSLog(@"System color '%@' has bad string rep - '%@'\n",
key, def);
}
else
{
[systemColors setColor: color forKey: key];
}
}
}
}
}
if (didChange)
{
[[NSNotificationCenter defaultCenter]
postNotificationName: NSSystemColorsDidChangeNotification object: nil];
}
}
- (void) setColorSpaceName: (NSString *)str
{
ASSIGN(colorspace_name, str);
}
/*
* Conversion algorithms taken from ghostscript.
*/
- (void) supportMaxColorSpaces
{
/*
* CMYK to RGB if required.
*/
if (valid_components & GNUSTEP_GUI_CMYK_ACTIVE)
{
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
if (CMYK_component.black == 0)
{
RGB_component.red = 1 - CMYK_component.cyan;
RGB_component.green = 1 - CMYK_component.magenta;
RGB_component.blue = 1 - CMYK_component.yellow;
}
else if (CMYK_component.black == 1)
{
RGB_component.red = 0;
RGB_component.green = 0;
RGB_component.blue = 0;
}
else
{
double c = CMYK_component.cyan;
double m = CMYK_component.magenta;
double y = CMYK_component.yellow;
double white = 1 - CMYK_component.black;
RGB_component.red = (c > white ? 0 : white - c);
RGB_component.green = (m > white ? 0 : white - m);
RGB_component.blue = (y > white ? 0 : white - y);
}
valid_components |= GNUSTEP_GUI_RGB_ACTIVE;
}
}
/*
* HSB to RGB if required
*/
if (valid_components & GNUSTEP_GUI_HSB_ACTIVE)
{
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
if (HSB_component.saturation == 0)
{
RGB_component.red = HSB_component.brightness;
RGB_component.green = HSB_component.brightness;
RGB_component.blue = HSB_component.brightness;
}
else
{
double h6 = HSB_component.hue * 6;
double V = HSB_component.brightness;
double S = HSB_component.saturation;
int I = (int)h6;
double F = h6 - I;
double M = V * (1 - S);
double N = V * (1 - S * F);
double K = M - N + V;
double R, G, B;
switch (I)
{
default: R = V; G = K; B = M; break;
case 1: R = N; G = V; B = M; break;
case 2: R = M; G = V; B = K; break;
case 3: R = M; G = N; B = V; break;
case 4: R = K; G = M; B = V; break;
case 5: R = V; G = M; B = N; break;
}
RGB_component.red = (float)R;
RGB_component.green = (float)G;
RGB_component.blue = (float)B;
}
valid_components |= GNUSTEP_GUI_RGB_ACTIVE;
}
}
/*
* White to RGB if required.
*/
if (valid_components & GNUSTEP_GUI_WHITE_ACTIVE)
{
if ((valid_components & GNUSTEP_GUI_RGB_ACTIVE) == 0)
{
RGB_component.red = white_component;
RGB_component.green = white_component;
RGB_component.blue = white_component;
valid_components |= GNUSTEP_GUI_RGB_ACTIVE;
}
}
if (valid_components & GNUSTEP_GUI_RGB_ACTIVE)
{
/*
* RGB to HSB if required.
*/
if ((valid_components & GNUSTEP_GUI_HSB_ACTIVE) == 0)
{
float r = RGB_component.red;
float g = RGB_component.green;
float b = RGB_component.blue;
if (r == g && r == b)
{
HSB_component.hue = 0;
HSB_component.saturation = 0;
HSB_component.brightness = r;
}
else
{
double H;
double V;
double Temp;
double diff;
V = (r > g ? r : g);
V = (b > V ? b : V);
Temp = (r > g ? r : g);
Temp = (b < Temp ? b : Temp);
diff = V - Temp;
if (V == r)
{
H = (g - b)/diff;
}
else if (V == g)
{
H = (b - r)/diff + 2;
}
else
{
H = (r - g)/diff + 4;
}
if (H < 0)
{
H += 6;
}
HSB_component.hue = H/6;
HSB_component.saturation = diff/V;
HSB_component.brightness = V;
}
valid_components |= GNUSTEP_GUI_HSB_ACTIVE;
}
/*
* RGB to white if required.
*/
if ((valid_components & GNUSTEP_GUI_WHITE_ACTIVE) == 0)
{
white_component = (RGB_component.red + RGB_component.green + RGB_component.blue)/3;
valid_components |= GNUSTEP_GUI_WHITE_ACTIVE;
}
}
}
- (void) setCatalogName: (NSString *)str
{
ASSIGN(catalog_name, str);
}
- (void) setColorName: (NSString *)str
{
ASSIGN(color_name, str);
}
// RGB component values
- (void) setRed: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
RGB_component.red = value;
}
- (void) setGreen: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
RGB_component.green = value;
}
- (void) setBlue: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
RGB_component.blue = value;
}
// CMYK component values
- (void) setCyan: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
CMYK_component.cyan = value;
}
- (void) setMagenta: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
CMYK_component.magenta = value;
}
- (void) setYellow: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
CMYK_component.yellow = value;
}
- (void) setBlack: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
CMYK_component.black = value;
}
// HSB component values
- (void) setHue: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
HSB_component.hue = value;
}
- (void) setSaturation: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
HSB_component.saturation = value;
}
- (void) setBrightness: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
HSB_component.brightness = value;
}
// Grayscale
- (void) setWhite: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
white_component = value;
}
- (void) setAlpha: (float)value
{
if (value < 0) value = 0;
if (value > 1) value = 1;
alpha_component = value;
}
- (void) setActiveComponent: (int)value
{
active_component = value;
}
- (void) setClear: (BOOL)flag
{
is_clear = flag;
}
- (void) setValidComponents: (int)value
{
valid_components = value;
}
@end
//
// Implementation of the NSCoder additions
//
@implementation NSCoder (NSCoderAdditions)
//
// Converting an Archived NXColor to an NSColor
//
- (NSColor*) decodeNXColor
{
return nil;
}
@end