From 17628a5e4c81ab6ccc84cf689a5e09a7164a4a38 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 25 Apr 2000 20:26:51 +0000 Subject: [PATCH] colorspace support git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@6515 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 8 + Headers/gnustep/gui/NSGraphics.h | 26 ++- Headers/gnustep/gui/NSScreen.h | 51 +++--- Source/Functions.m | 190 ++++++++++++++++++++ Source/NSScreen.m | 298 ++++++++++++++++++++----------- Source/externs.m | 34 +++- Tools/Functions.m | 4 + 7 files changed, 470 insertions(+), 141 deletions(-) diff --git a/ChangeLog b/ChangeLog index a3fa585ea..2d19bbd25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2000-04-25 Richard Frith-Macdonald + + Patch by Gregory John Casamento edited to + conform to standards. Adds improved colorspace support. + Files modified - Headers/gnustep/gui/NSGraphics.h, + Headers/gnustep/gui/NSScreen.h, Source/Functions.m, Source/NSScreen.m, + Source/externs.m, Tools/Functions.m + 2000-04-25 Adam Fedor * Source/NSView.m (-_updateBoundsMatrix): New method from diff --git a/Headers/gnustep/gui/NSGraphics.h b/Headers/gnustep/gui/NSGraphics.h index 4a1267041..dcfeea344 100644 --- a/Headers/gnustep/gui/NSGraphics.h +++ b/Headers/gnustep/gui/NSGraphics.h @@ -31,9 +31,9 @@ @class NSString; @class NSColor; -// -// Colorspace Names -// +/* + * Colorspace Names + */ extern NSString *NSCalibratedWhiteColorSpace; extern NSString *NSCalibratedBlackColorSpace; extern NSString *NSCalibratedRGBColorSpace; @@ -46,6 +46,23 @@ extern NSString *NSCustomColorSpace; typedef int NSWindowDepth; +/* + * Color function externs + */ +extern const NSWindowDepth _GSGrayBitValue; +extern const NSWindowDepth _GSRGBBitValue; +extern const NSWindowDepth _GSCMYKBitValue; +extern const NSWindowDepth _GSCustomBitValue; +extern const NSWindowDepth _GSNamedBitValue; +extern const NSWindowDepth *_GSWindowDepths[7]; +extern const NSWindowDepth NSDefaultDepth; +extern const NSWindowDepth NSTwoBitGrayDepth; +extern const NSWindowDepth NSEightBitGrayDepth; +extern const NSWindowDepth NSEightBitRGBDepth; +extern const NSWindowDepth NSTwelveBitRGBDepth; +extern const NSWindowDepth GSSixteenBitRGBDepth; +extern const NSWindowDepth NSTwentyFourBitRGBDepth; + /* * Gray Values */ @@ -102,6 +119,8 @@ int NSBitsPerSampleFromDepth(NSWindowDepth depth); NSString *NSColorSpaceFromDepth(NSWindowDepth depth); int NSNumberOfColorComponents(NSString *colorSpaceName); BOOL NSPlanarFromDepth(NSWindowDepth depth); +NSWindowDepth GSWindowDepthForScreen(int screen); +const NSWindowDepth *GSAvailableDepthsForScreen(int screen); /* * Read the Color at a Screen Position @@ -146,6 +165,7 @@ void NSWindowList(int size, int list[]); NSArray* GSAllWindows(); NSWindow* GSWindowWithNumber(int num); + #endif #endif /* __NSGraphics_h__ */ diff --git a/Headers/gnustep/gui/NSScreen.h b/Headers/gnustep/gui/NSScreen.h index 45a1fdf1f..03617c9f3 100644 --- a/Headers/gnustep/gui/NSScreen.h +++ b/Headers/gnustep/gui/NSScreen.h @@ -3,10 +3,14 @@ Class representing monitors - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 2000 Free Software Foundation, Inc. - Author: Scott Christley + Author: Scott Christley Date: 1996 + + Fixes and updates made by + Author: Gregory John Casamento + Date: 2000 This file is part of the GNUstep GUI Library. @@ -38,28 +42,27 @@ @interface NSScreen : NSObject { - // Attributes - NSWindowDepth depth; - NSRect frame; - NSMutableDictionary *device_desc; +@private + NSWindowDepth _depth; + NSRect _frame; + int _screenNumber; - // Reserved for backend use - void *be_screen_reserved; + void *_reserved; } -// -// Creating NSScreen Instances -// -+ (NSScreen *)mainScreen; -+ (NSScreen *)deepestScreen; -+ (NSArray *)screens; +/* + * Creating NSScreen Instances + */ ++ (NSScreen*) mainScreen; ++ (NSScreen*) deepestScreen; ++ (NSArray*) screens; -// -// Reading Screen Information -// -- (NSWindowDepth)depth; -- (NSRect)frame; -- (NSDictionary *)deviceDescription; +/* + * Reading Screen Information + */ +- (NSWindowDepth) depth; +- (NSRect) frame; +- (NSDictionary*) deviceDescription; #ifndef STRICT_OPENSTEP - (const NSWindowDepth*) supportedWindowDepths; @@ -67,12 +70,4 @@ #endif @end - -#ifndef NO_GNUSTEP -// Need this definition for backend classes -@interface NSScreen (GNUstep) -- initWithDeviceDescription: (NSDictionary *)dict; -@end -#endif - #endif // _GNUstep_H_NSScreen diff --git a/Source/Functions.m b/Source/Functions.m index 6af0a9196..6ca31213d 100644 --- a/Source/Functions.m +++ b/Source/Functions.m @@ -32,6 +32,7 @@ #include #include #include +#include char **NSArgv = NULL; @@ -104,3 +105,192 @@ NSEventMaskFromType(NSEventType type) } return 0; } + +/* + * Color Functions + */ + +/* + * Get Information About Color Space and Window Depth + */ +const NSWindowDepth* +NSAvailableWindowDepths(void) +{ + /* + * Perhaps this is the only function which + * belongs in the backend. It should be possible + * to detect which depths the window server is capable + * of. + */ + return (const NSWindowDepth *)_GSWindowDepths; +} + +NSWindowDepth +NSBestDepth(NSString *colorSpace, int bitsPerSample, int bitsPerPixel, + BOOL planar, BOOL *exactMatch) +{ + int components = NSNumberOfColorComponents(colorSpace); + int index = 0; + const NSWindowDepth *depths = NSAvailableWindowDepths(); + NSWindowDepth bestDepth = NSDefaultDepth; + + *exactMatch = NO; + + if (components == 1) + { + for (index = 0; depths[index] != 0; index++) + { + NSWindowDepth depth = depths[index]; + + if (NSPlanarFromDepth(depth)) + { + bestDepth = depth; + if (NSBitsPerSampleFromDepth(depth) == bitsPerSample) + { + *exactMatch = YES; + } + } + } + } + else + { + for (index = 0; depths[index] != 0; index++) + { + NSWindowDepth depth = depths[index]; + + if (!NSPlanarFromDepth(depth)) + { + bestDepth = depth; + if (NSBitsPerSampleFromDepth(depth) == bitsPerSample) + { + *exactMatch = YES; + } + } + } + } + + return bestDepth; +} + +int +NSBitsPerPixelFromDepth(NSWindowDepth depth) +{ + int bps = NSBitsPerSampleFromDepth(depth); + int spp = 0; + + if (depth & _GSRGBBitValue) + { + spp = 3; + } + else if (depth & _GSCMYKBitValue) + { + spp = 4; + } + else if (depth & _GSGrayBitValue) + { + spp = 1; + } + return (spp * bps); +} + +int +NSBitsPerSampleFromDepth(NSWindowDepth depth) +{ + NSWindowDepth bitValue = 0; + + /* + * Test against colorspace bit. + * and out the bit to get the bps value. + */ + if (depth & _GSRGBBitValue) + { + bitValue = _GSRGBBitValue; + } + else if (depth & _GSCMYKBitValue) + { + bitValue = _GSCMYKBitValue; + } + else if (depth & _GSGrayBitValue) + { + bitValue = _GSGrayBitValue; + } + /* + * AND against the complement + * to extract the bps value. + */ + return (depth & ~(bitValue)); +} + +NSString* +NSColorSpaceFromDepth(NSWindowDepth depth) +{ + NSString *colorSpace = NSCalibratedWhiteColorSpace; + + /* + * Test against each of the possible colorspace bits + * and return the corresponding colorspace. + */ + if (depth == 0) + { + colorSpace = NSCalibratedBlackColorSpace; + } + else if (depth & _GSRGBBitValue) + { + colorSpace = NSCalibratedRGBColorSpace; + } + else if (depth & _GSCMYKBitValue) + { + colorSpace = NSDeviceCMYKColorSpace; + } + else if (depth & _GSGrayBitValue) + { + colorSpace = NSCalibratedWhiteColorSpace; + } + else if (depth & _GSNamedBitValue) + { + colorSpace = NSNamedColorSpace; + } + else if (depth & _GSCustomBitValue) + { + colorSpace = NSCustomColorSpace; + } + + return colorSpace; +} + +int +NSNumberOfColorComponents(NSString *colorSpaceName) +{ + int components = 1; + + /* + * These are the only exceptions to the above. + * All other colorspaces have as many bps as bpp. + */ + if ([colorSpaceName isEqualToString: NSCalibratedRGBColorSpace] + || [colorSpaceName isEqualToString: NSDeviceRGBColorSpace]) + { + components = 3; + } + else if ([colorSpaceName isEqualToString: NSDeviceCMYKColorSpace]) + { + components = 4; + } + return components; +} + +BOOL +NSPlanarFromDepth(NSWindowDepth depth) +{ + BOOL planar = NO; + + /* + * Only the grayscale depths are planar. + * All others are interleaved. + */ + if (depth & _GSGrayBitValue) + { + planar = YES; + } + return planar; +} diff --git a/Source/NSScreen.m b/Source/NSScreen.m index 64e261db5..613f11cbc 100644 --- a/Source/NSScreen.m +++ b/Source/NSScreen.m @@ -1,12 +1,16 @@ -/* +/* NSScreen.m Description... - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 2000 Free Software Foundation, Inc. Author: Scott Christley Date: 1996 + + Major modifications and updates + Author: Gregory John Casamento + Date: 2000 This file is part of the GNUstep GUI Library. @@ -27,129 +31,90 @@ */ #include -#include -#include +#include #include #include #include #include #include +#include - -static int * -_screen_numbers(void) +static int* +_screenNumbers(int *count) { - int count, *list; - NSGraphicsContext *ctxt = GSCurrentContext(); + int *list; + NSGraphicsContext *ctxt = GSCurrentContext(); - DPScountscreenlist(ctxt, 0, &count); - if (count == 0) - return NULL; - list = NSZoneMalloc(NSDefaultMallocZone(), (count+1)*sizeof(int)); - DPSscreenlist(ctxt, 0, count, list); + DPScountscreenlist(ctxt, 0, count); + + // If the list is empty quit... + if (*count == 0) + { + NSLog(@"Internal error: No screens detected."); + return NULL; // something is wrong. This shouldn't happen. + } + + list = NSZoneMalloc(NSDefaultMallocZone(), (*count+1)*sizeof(int)); + DPSscreenlist(ctxt, 0, *count, list); return list; } @implementation NSScreen -/* - * Class variables - */ -static NSScreen *mainScreen = nil; - -/* - * Class methods - */ -+ (void) initialize -{ - if (self == [NSScreen class]) - { - [self setVersion:1]; - } -} - -/* - * Creating NSScreen Instances - */ -+ (NSScreen*) mainScreen -{ - NSMutableDictionary *dict; - - if (mainScreen) - return mainScreen; - - dict = [NSMutableDictionary dictionary]; - [dict setObject: @"Main" forKey: @"NSScreenKeyName"]; - mainScreen = [[NSScreen alloc] initWithDeviceDescription: dict]; - return mainScreen; -} - -+ (NSScreen*) deepestScreen -{ - return [self mainScreen]; -} - -+ (NSArray*) screens -{ - return [NSArray arrayWithObject: [self mainScreen]]; -} - /* * Instance methods */ -- (id) initWithDeviceDescription: (NSDictionary*)dict -{ - int screen; - float x, y, w, h; - NSGraphicsContext *ctxt = GSCurrentContext(); - [super init]; - depth = 0; - frame = NSZeroRect; - if (dict) - device_desc = [dict mutableCopy]; - else - device_desc = [[NSMutableDictionary dictionary] retain]; +// NSScreen does not respond to the init method. +- (id) init +{ + [self doesNotRecognizeSelector: _cmd]; + return nil; +} + +// Get all of the infomation for a given screen. +- (id) _initWithScreenNumber: (int)screen +{ + float x, y, w, h; + NSGraphicsContext *ctxt = GSCurrentContext(); + int bitsPerPixel = 0; + + self = [super init]; + + // Initialize i-vars + _depth = 0; + _frame = NSZeroRect; + _screenNumber = 0; + + // Check for problems + if (screen < 0) + { + NSLog(@"Internal error: Invalid screen number %d\n",screen); + RELEASE(self); + return nil; + } if (ctxt == nil) { NSLog(@"Internal error: No current context\n"); - [self release]; + RELEASE(self); return nil; } if ([ctxt isDrawingToScreen] == NO) { NSLog(@"Internal error: trying to find screen with wrong context\n"); - [self release]; + RELEASE(self); return nil; } - if (!dict || [dict objectForKey: @"NSScreenKeyName"] == nil - || [[dict objectForKey: @"NSScreenKeyName"] isEqual: @"Main"]) - { - /* Assume the main screen is the one we started with */ - int *windows = _screen_numbers(); - screen = 0; - if (windows) - screen = windows[0]; - NSZoneFree(NSDefaultMallocZone(), windows); - } - else if ([dict objectForKey: @"NSScreenNumber"]) - { - screen = [[dict objectForKey: @"NSScreenNumber"] intValue]; - } - /* Special hack to get screen frame since window number of root window - is same as screen number */ + // Fill in all of the i-vars with appropriate values. + _screenNumber = screen; DPScurrentwindowbounds(ctxt, screen, &x, &y, &w, &h); - frame = NSMakeRect(x, y, w, h); - DPScurrentwindowdepth(ctxt, screen, &depth); - return self; -} + _frame = NSMakeRect(x, y, w, h); + _depth = GSWindowDepthForScreen(screen); -- (id) init -{ - return [self initWithDeviceDescription: NULL]; + return self; } /* @@ -157,34 +122,73 @@ static NSScreen *mainScreen = nil; */ - (NSWindowDepth) depth { - return depth; + return _depth; } - (NSRect) frame { - return frame; + return _frame; } - (NSDictionary*) deviceDescription { - NSDictionary *d = [[NSDictionary alloc] initWithDictionary: device_desc]; + NSMutableDictionary *devDesc = [[NSDictionary alloc] init]; + int bps = 0; + NSSize screenResolution; + NSString *colorSpaceName = nil; - return d; + /* + * Testing of this method on OS4.2 indicates that the + * dictionary is re-created every time this method is called. + */ + + // Set the screen number in the current object. + devDesc = [NSMutableDictionary new]; + [devDesc setObject: [NSNumber numberWithInt: _screenNumber] + forKey: @"NSScreenNumber"]; + + // This is assumed since we are in NSScreen. + [devDesc setObject: @"YES" forKey: NSDeviceIsScreen]; + + // Add the NSDeviceSize dictionary item + [devDesc setObject: [NSValue valueWithSize: _frame.size] + forKey: NSDeviceSize]; + + // Add the NSDeviceResolution dictionary item + screenResolution.width = 72; // This is a fixed value for screens. + screenResolution.height = 72; // All screens I checked under OS4.2 report 72. + [devDesc setObject: [NSValue valueWithSize: screenResolution] + forKey: NSDeviceResolution]; + + // Add the bits per sample entry + bps = NSBitsPerSampleFromDepth(_depth); + [devDesc setObject: [NSNumber numberWithInt: bps] + forKey: NSDeviceBitsPerSample]; + + // Add the color space entry. + colorSpaceName = NSColorSpaceFromDepth(_depth); + [devDesc setObject: colorSpaceName + forKey: NSDeviceColorSpaceName]; + + return [NSDictionary dictionaryWithDictionary: devDesc]; } // Mac OS X methods - (const NSWindowDepth*) supportedWindowDepths { - // Skeletal implementation - NSWindowDepth* retval = NSZoneMalloc([self zone], sizeof(NSWindowDepth)*2); - retval[1] = depth; - retval[2] = 0; - return retval; + /* + * Skeletal implementation + * NSWindowDepth* retval = NSZoneMalloc([self zone], sizeof(NSWindowDepth)*2); + * retval[1] = _depth; + * retval[2] = 0; + * return retval; + */ + return GSAvailableDepthsForScreen(_screenNumber); } - (NSRect) visibleFrame { - NSRect visFrame = frame; + NSRect visFrame = _frame; switch ([NSApp interfaceStyle]) { @@ -196,8 +200,94 @@ static NSScreen *mainScreen = nil; case NSNextStepInterfaceStyle: case NSNoInterfaceStyle: default: - return frame; + return _frame; } } +/* + * Class methods + */ + ++ (void) initialize +{ + if (self == [NSScreen class]) + { + [self setVersion:1]; + } +} + +// Creating NSScreen Instances ++ (NSScreen*) mainScreen +{ + int *windows = 0, count; + NSScreen *mainScreen = nil; + + // Initialize the window list. + windows = _screenNumbers(&count); + + // If the list is empty quit... + if (windows == NULL) + return nil; // something is wrong. This shouldn't happen. + + // main screen is always first in the array. + mainScreen = [[NSScreen alloc] _initWithScreenNumber: windows[0]]; + NSZoneFree(NSDefaultMallocZone(), windows); // free the list + + return mainScreen; +} + ++ (NSScreen*) deepestScreen +{ + NSArray *screenArray = [NSScreen screens]; + NSEnumerator *screenEnumerator = nil; + NSScreen *deepestScreen = nil, *screen = nil; + int maxBits = 0; + + // Iterate over the list of screens and find the + // one with the most depth. + screenEnumerator = [screenArray objectEnumerator]; + while ((screen = [screenEnumerator nextObject]) != nil) + { + int bits = 0; + + bits = [screen depth]; + + if (bits > maxBits) + { + maxBits = bits; + deepestScreen = screen; + } + } + + return deepestScreen; +} + ++ (NSArray*) screens +{ + int count = 0, index = 0, *windows = 0; + NSGraphicsContext *ctxt = GSCurrentContext(); + NSMutableArray *screenArray = [NSMutableArray array]; + + // Get the number of screens. + windows = _screenNumbers(&count); + + // If the list is empty quit... + if (windows == NULL) + return nil; // something is wrong. This shouldn't happen. + + // Iterate over the list + for (index = 0; index < count; index++) + { + NSScreen *screen = nil; + + screen = [[NSScreen alloc] _initWithScreenNumber: windows[index]]; + [screenArray addObject: screen]; + } + + NSZoneFree(NSDefaultMallocZone(), windows); // free the list + + return [NSArray arrayWithArray: screenArray]; +} @end + + diff --git a/Source/externs.m b/Source/externs.m index 6d3cbc80e..b684da506 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -160,12 +160,12 @@ NSString *NSAFMWeight = @"Weight"; NSString *NSAFMXHeight = @"XHeight"; // NSScreen Global device dictionary key strings -NSString *NSDeviceResolution = @"Resolution"; -NSString *NSDeviceColorSpaceName = @"ColorSpaceName"; -NSString *NSDeviceBitsPerSample = @"BitsPerSample"; -NSString *NSDeviceIsScreen = @"IsScreen"; -NSString *NSDeviceIsPrinter = @"IsPrinter"; -NSString *NSDeviceSize = @"Size"; +NSString *NSDeviceResolution = @"NSDeviceResolution"; +NSString *NSDeviceColorSpaceName = @"NSDeviceColorSpaceName"; +NSString *NSDeviceBitsPerSample = @"NSDeviceBitsPerSample"; +NSString *NSDeviceIsScreen = @"NSDeviceIsScreen"; +NSString *NSDeviceIsPrinter = @"NSDeviceIsPrinter"; +NSString *NSDeviceSize = @"NSDeviceSize"; // NSImageRep notifications NSString *NSImageRepRegistryChangedNotification = @@ -378,3 +378,25 @@ const float NSFontIdentityMatrix[] = {1, 0, 0, 1, 0, 0}; /* Drawing engine externs */ NSString *NSBackendContext = @"NSBackendContext"; +typedef int NSWindowDepth; + +/**** Color function externs ****/ +/* Since these are constants it was not possible + to do the OR directly. If you change the + _GS*BitValue numbers, please remember to + change the corresponding depth values */ +const NSWindowDepth _GSGrayBitValue = 256; +const NSWindowDepth _GSRGBBitValue = 512; +const NSWindowDepth _GSCMYKBitValue = 1024; +const NSWindowDepth _GSNamedBitValue = 2048; +const NSWindowDepth _GSCustomBitValue = 4096; +const NSWindowDepth NSDefaultDepth = 0; // GRAY = 256, RGB = 512 +const NSWindowDepth NSTwoBitGrayDepth = 258; // 0100000010 GRAY | 2bps +const NSWindowDepth NSEightBitGrayDepth = 264; // 0100001000 GRAY | 8bps +const NSWindowDepth NSEightBitRGBDepth = 514; // 1000000010 RGB | 2bps +const NSWindowDepth NSTwelveBitRGBDepth = 516; // 1000000100 RGB | 4bps +const NSWindowDepth GSSixteenBitRGBDepth = 517; // 1000000101 RGB | 5bps GNUstep specific +const NSWindowDepth NSTwentyFourBitRGBDepth = 520; // 1000001000 RGB | 8bps +const NSWindowDepth _GSWindowDepths[7] = { 258, 264, 514, 516, 517, 520, 0 }; + +/* End of color functions externs */ diff --git a/Tools/Functions.m b/Tools/Functions.m index b5bf6b1c4..54492c769 100644 --- a/Tools/Functions.m +++ b/Tools/Functions.m @@ -281,3 +281,7 @@ float NSLinkFrameThickness(void) return 0; } +// Color Functions +NSWindowDepth GSWindowDepthForScreen(int screen) {} + +const NSWindowDepth *GSAvailableDepthsForScreen(int screen) {}