Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
2026-07-12 Todd White <todd.white@thalion.global>

* Resources/ColorSpaces/sRGB2014.icc: The ICC sRGB v2 reference
profile, redistributed under the ICC licence.
* Resources/ColorSpaces/README: Its provenance and licence.
* Resources/GNUmakefile: Install the ColorSpaces resources.
* Source/NSColorSpace.m (-[NSColorSpace _loadICCProfileNamed:],
+[NSColorSpace genericRGBColorSpace]): Load the profile as a library
resource so the generic RGB space reports ICC profile data.
* Tests/gui/NSColorSpace/basic.m: Check the generic RGB profile data.

2026-07-12 Todd White <todd.white@thalion.global>

* Tests/gui/NSColorSpace/basic.m:
* Tests/gui/NSColorSpace/TestInfo:
Add tests for NSColorSpace: the model enum values, and the colour
space model, component count, name and singleton identity of the
standard colour spaces.

2026-07-12 Todd White <todd.white@thalion.global>

* Tests/gui/NSTextFieldCell/attributes.m:
Expand Down
10 changes: 10 additions & 0 deletions Resources/ColorSpaces/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ICC colour profiles used by NSColorSpace for the standard colour spaces.

sRGB2014.icc is the sRGB v2 reference profile published by the International
Color Consortium at https://registry.color.org/rgb-registry/srgbprofiles and
is redistributed here unmodified. The ICC makes its profiles available under
the following terms:

This profile is made available by the International Color Consortium, and
may be copied, distributed, embedded, made, used, and sold without
restriction.
Binary file added Resources/ColorSpaces/sRGB2014.icc
Binary file not shown.
2 changes: 2 additions & 0 deletions Resources/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ RESOURCE_SET_NAME = gui-resources
gui-resources_INSTALL_DIR = $(GNUSTEP_LIBRARY)/Libraries/gnustep-gui/Versions/$(GNUSTEP_GUI_MAJOR_VERSION).$(GNUSTEP_GUI_MINOR_VERSION)/Resources
gui-resources_LANGUAGES = English Italian Lojban Esperanto German French Spanish Korean Japanese Polish
gui-resources_LOCALIZED_RESOURCE_FILES = Localizable.strings
gui-resources_RESOURCE_DIRS = ColorSpaces
gui-resources_RESOURCE_FILES = ColorSpaces/sRGB2014.icc

include $(GNUSTEP_MAKEFILES)/resource-set.make

Expand Down
27 changes: 24 additions & 3 deletions Source/NSColorSpace.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
Boston, MA 02110-1301, USA.
*/

#import <Foundation/NSBundle.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import <Foundation/NSString.h>
Expand All @@ -39,13 +40,26 @@ - (id) _initWithColorSpaceModel: (NSColorSpaceModel)model
{
if ((self = [super init]))
{
// FIXME: Load corresponding data

_colorSpaceModel = model;
}
return self;
}

/* Loads the named ICC profile that ships as a gui library resource under
ColorSpaces, so a standard colour space can report its profile data. */
- (void) _loadICCProfileNamed: (NSString *)name
{
NSBundle *bundle = [NSBundle bundleForLibrary: @"gnustep-gui"];
NSString *path = [bundle pathForResource: name
ofType: @"icc"
inDirectory: @"ColorSpaces"];

if (path != nil)
{
ASSIGN(_iccData, [NSData dataWithContentsOfFile: path]);
}
}

#define COLORSPACE(model) \
static NSColorSpace *csp = nil; \
if (!csp) \
Expand Down Expand Up @@ -79,7 +93,14 @@ + (NSColorSpace *) genericGrayColorSpace

+ (NSColorSpace *) genericRGBColorSpace
{
COLORSPACE(NSRGBColorSpaceModel);
static NSColorSpace *csp = nil;

if (!csp)
{
csp = [[self alloc] _initWithColorSpaceModel: NSRGBColorSpaceModel];
[csp _loadICCProfileNamed: @"sRGB2014"];
}
return csp;
}

- (id) initWithColorSyncProfile: (void *)prof
Expand Down
Empty file.
91 changes: 91 additions & 0 deletions Tests/gui/NSColorSpace/basic.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* Coverage for NSColorSpace: the model enum values, and the colour space
* model, component count, name and singleton identity of the standard colour
* spaces. These are plain value objects and need no backend.
*
* The generic spaces on macOS carry an ICC profile and longer localized
* names; this class does not, so the ICC data and the exact name are not
* covered.
*/
#include "Testing.h"
#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSData.h>
#include <Foundation/NSString.h>
#include <AppKit/NSColorSpace.h>

int
main(int argc, char **argv)
{
CREATE_AUTORELEASE_POOL(arp);

START_SET("model enum values")
PASS(NSUnknownColorSpaceModel == -1 && NSGrayColorSpaceModel == 0
&& NSRGBColorSpaceModel == 1 && NSCMYKColorSpaceModel == 2
&& NSLABColorSpaceModel == 3 && NSDeviceNColorSpaceModel == 4,
"the NSColorSpaceModel values match AppKit");
END_SET("model enum values")

START_SET("generic colour spaces")
NSColorSpace *rgb = [NSColorSpace genericRGBColorSpace];
NSColorSpace *gray = [NSColorSpace genericGrayColorSpace];
NSColorSpace *cmyk = [NSColorSpace genericCMYKColorSpace];

PASS([rgb colorSpaceModel] == NSRGBColorSpaceModel
&& [rgb numberOfColorComponents] == 3,
"the generic RGB space is an RGB model with three components");
PASS([gray colorSpaceModel] == NSGrayColorSpaceModel
&& [gray numberOfColorComponents] == 1,
"the generic gray space is a gray model with one component");
PASS([cmyk colorSpaceModel] == NSCMYKColorSpaceModel
&& [cmyk numberOfColorComponents] == 4,
"the generic CMYK space is a CMYK model with four components");
PASS([rgb localizedName] != nil, "a colour space has a localized name");
END_SET("generic colour spaces")

START_SET("device colour spaces")
NSColorSpace *rgb = [NSColorSpace deviceRGBColorSpace];
NSColorSpace *gray = [NSColorSpace deviceGrayColorSpace];
NSColorSpace *cmyk = [NSColorSpace deviceCMYKColorSpace];

PASS([rgb colorSpaceModel] == NSRGBColorSpaceModel
&& [rgb numberOfColorComponents] == 3,
"the device RGB space is an RGB model with three components");
PASS([gray colorSpaceModel] == NSGrayColorSpaceModel
&& [gray numberOfColorComponents] == 1,
"the device gray space is a gray model with one component");
PASS([cmyk colorSpaceModel] == NSCMYKColorSpaceModel
&& [cmyk numberOfColorComponents] == 4,
"the device CMYK space is a CMYK model with four components");
END_SET("device colour spaces")

START_SET("generic RGB has an ICC profile")
NSData *icc = [[NSColorSpace genericRGBColorSpace] ICCProfileData];

PASS(icc != nil, "the generic RGB space reports ICC profile data");
if (icc != nil && [icc length] >= 40)
{
const unsigned char *b = [icc bytes];

PASS(b[36] == 'a' && b[37] == 'c' && b[38] == 's' && b[39] == 'p',
"the profile carries the acsp signature");
}
else
{
PASS(0, "the profile is long enough to hold a header");
}
END_SET("generic RGB has an ICC profile")

START_SET("standard spaces are shared")
PASS([NSColorSpace genericRGBColorSpace]
== [NSColorSpace genericRGBColorSpace],
"the generic RGB space is the same object each time");
PASS([NSColorSpace deviceRGBColorSpace]
== [NSColorSpace deviceRGBColorSpace],
"the device RGB space is the same object each time");
PASS([NSColorSpace genericRGBColorSpace]
!= [NSColorSpace deviceRGBColorSpace],
"the generic and device RGB spaces are different objects");
END_SET("standard spaces are shared")

DESTROY(arp);
return 0;
}
Loading