From bf8b4d8b10b24f5dc8328b19a614b49d9288d8a6 Mon Sep 17 00:00:00 2001 From: Todd White Date: Sun, 12 Jul 2026 20:09:56 -0400 Subject: [PATCH 1/2] tests: add NSColorSpace tests Cover the model enum values, and the colour space model, component count, name and singleton identity of the standard colour spaces. --- ChangeLog | 8 ++++ Tests/gui/NSColorSpace/TestInfo | 0 Tests/gui/NSColorSpace/basic.m | 73 +++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 Tests/gui/NSColorSpace/TestInfo create mode 100644 Tests/gui/NSColorSpace/basic.m diff --git a/ChangeLog b/ChangeLog index 9944d98711..c7661bdf92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2026-07-12 Todd White + + * 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 * Tests/gui/NSTextFieldCell/attributes.m: diff --git a/Tests/gui/NSColorSpace/TestInfo b/Tests/gui/NSColorSpace/TestInfo new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/gui/NSColorSpace/basic.m b/Tests/gui/NSColorSpace/basic.m new file mode 100644 index 0000000000..b54eda632a --- /dev/null +++ b/Tests/gui/NSColorSpace/basic.m @@ -0,0 +1,73 @@ +/* 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 +#include +#include + +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("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; +} From e5557db410312055652f60fa0f2121856f946d7a Mon Sep 17 00:00:00 2001 From: Todd White Date: Sun, 12 Jul 2026 20:28:25 -0400 Subject: [PATCH 2/2] NSColorSpace: return ICC profile data for the generic RGB space The generic RGB colour space now reports an ICC profile, loaded from the ICC sRGB v2 reference profile that ships as a gui library resource. This is a first step; the generic gray and CMYK spaces can follow the same pattern with their own reference profiles. --- ChangeLog | 11 +++++++++++ Resources/ColorSpaces/README | 10 ++++++++++ Resources/ColorSpaces/sRGB2014.icc | Bin 0 -> 3024 bytes Resources/GNUmakefile | 2 ++ Source/NSColorSpace.m | 27 ++++++++++++++++++++++++--- Tests/gui/NSColorSpace/basic.m | 18 ++++++++++++++++++ 6 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 Resources/ColorSpaces/README create mode 100644 Resources/ColorSpaces/sRGB2014.icc diff --git a/ChangeLog b/ChangeLog index c7661bdf92..892e504162 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2026-07-12 Todd White + + * 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 * Tests/gui/NSColorSpace/basic.m: diff --git a/Resources/ColorSpaces/README b/Resources/ColorSpaces/README new file mode 100644 index 0000000000..e3cf40fef2 --- /dev/null +++ b/Resources/ColorSpaces/README @@ -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. diff --git a/Resources/ColorSpaces/sRGB2014.icc b/Resources/ColorSpaces/sRGB2014.icc new file mode 100644 index 0000000000000000000000000000000000000000..49afbfef10f22a1832590b68369d2f248ea553b9 GIT binary patch literal 3024 zcmb`Jc{r5o8^@pboqe;-klom~#=Z=)?<7n1RL0C;EQ4W?v`H$Qlq6e;oU(N2=!6`p zq_j9fq0&N*O8IqkN}I~>9j@P{b6vkb&vRYx^M3C8x$pP6pZoda{Q^K51jvAqCy}2f z2yl0zhlYjIaZeGKxM&3c7CSY0nf@_DE7pfmuw>n3hyBge}>zEF^|hhw$p<`Vm43NktlHVq|Q#Wc`bi=uVbDr*Q%R@mv7f?y!Y| z^kpAf^uhola$__g2b6(2&;bl!0xW?IZ~(5r3;2RS5C%2@Hi!j@Kmam8HrNI7Kmj-i zj(`eK4eCGxXa=pI9dv;!;5xVs2Ehmz2NPf#yasdN16Y6{2nSIhDkKM~K$?&~WCAfE zJIEDU3k5)7P$U!s@gX6U4ef>spkk;3s(~7yU!e=o73d~31U-Nzp&96J=nIU3$uJF8 zg0)~nm^L%}Fw^fA^LPfRE#29trw!<1r9Va{W&VMZ|1m=9PiRtBq$wZwX0 z!?1DKt=K~BF>DL=GIj_%g`LOYaB?_(oGs25$HJxI@^Iz2Gq_8*VcazC6P|=u!JFXS z@ZoqqJ_lclZ^U=whw(4)3j_&*Cc&EEOW+W;5Q+$OgigX8!ZcxlC`r^N+7bhaal~E3 zGGa6F8u1bF9f?FzBUzFBNj%a{QW@zi=>}<%^qDM0)+0NUBgjJX0rF|`W%2{^I|_xO zMRA~nQ_?60C=HaWlqZx=VpK5$F;6j$*bcEuu{N<`u{YubaZPbY@lE1c;-%u}#P5jD zN)RNpB%CE!65AyzB`!#eNz6-9C5m zB-1K0D)VKP(kjPQ+*SKmHLn_8^-)$q);f{g-OAzz_Y;h`d|sHYg9xK;6_V!z_NlCqM!QnFIH(p9BdWf^4$ z67?SSISmyJAB}8{CXI)h1Wl%9tmaY8KFyC>+FBu6d$roNUTVu~dunHC zH)%i8q3GD_r0CS@+|$MCGIis1kLeET!FuL;v3iwycl2R>3w@scG5w*{nAKLR`KxPJ zk1@y$M@BlMi7{y)W3bjB$DrNdjiH8NxZxqgKEv-u=0*udbw=aHQpR4!ImVsFf1Bu; zuuUpW?wL|d-As3wc9_03(>LRq9XGpgPBr&2-)r7u{>{SDLSWHsF=MG=8EIK%ImV{PDV}wr}Iu9ovod>IbU``xwyOJy9~HW zxdypbxIS@HbBl3na+`BEci-xM*#qO@?QzIs%u~se?b+Zt=Vj@&&8yd&?7iN*!u#1; zy|se1oj$OSm(O9JN9#1#@z=Hc0$)$x!@iIGwEa^2e)q@v`}tS;KMybt$PVaRPhG!x zedGEMflh%%f#X3sLBgP(VDaFH;D+FjAub`sArqm7q1!@lhslTW!aBln;lbgj!sj=* zZaA`GI>J06FJg3~_QuSOH#f;|O4xL9v-oD#=5vvl$dJg!$geD4RxN8j$}_4eYL4y9 zKFWU0ap072X1KQ8V(yD*+vwuxmoc_6hht`9?PE)0XL-)N3f|i|kGSf%kMX|or{fnB zLK0dM@rjX%7x+^Acz$n^a#Ci}P_lklKhhQM>Ze1S!z~VeUx}qcyyv{ZCOXTM)|?=uNAQsBb82-EmewD`>Q@4 z;~X14?r^-hTB*9A`pXI4iTgF~HEp$8wWTMqC(}uM0h$Hl62xH~9T@mugq#Md^!0-Nf$P?!`-4 zm*y`gU!J`Zb7iV$bIqdq~gGTRGoA)2d|5UxvdGp&}4uAE}h0aaC6}(;i zyYQXdyVLK@-uKM=%|H2&_+jB={wKLl^`Dua`@V#Hd9jf375BC5o9?&H@7~`ZEha85 z{-8k&JYAjX7RFW<77P=HG2Mk5%@QW0(M8J6IVmAYD4?%TX0f?+23;gpmIcJWHm~TE zsB!?>_W&UKaK(pgBT{F`Sk`1q_=ApIvi~>1Kja-poFc8Ycg2@f3jlK-0Mx-$UJPB7 zEaT{Co~CjhDoy^Z4|Cv`LizZ;q8ZSF~{&Hxtp1 zNS#T^TLiqA*fhE)KaDHkvqTlK5|(a9AgVDnNsz`9Ca$I)0svP6z_+5s#f6&1#cxP2P~!kx7XBBF2+<<| literal 0 HcmV?d00001 diff --git a/Resources/GNUmakefile b/Resources/GNUmakefile index fe5ce5e042..0f230a1033 100644 --- a/Resources/GNUmakefile +++ b/Resources/GNUmakefile @@ -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 diff --git a/Source/NSColorSpace.m b/Source/NSColorSpace.m index e6785a74d9..f72964abed 100644 --- a/Source/NSColorSpace.m +++ b/Source/NSColorSpace.m @@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA. */ +#import #import #import #import @@ -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) \ @@ -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 diff --git a/Tests/gui/NSColorSpace/basic.m b/Tests/gui/NSColorSpace/basic.m index b54eda632a..a16ec1c1f0 100644 --- a/Tests/gui/NSColorSpace/basic.m +++ b/Tests/gui/NSColorSpace/basic.m @@ -8,6 +8,7 @@ */ #include "Testing.h" #include +#include #include #include @@ -56,6 +57,23 @@ "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],