diff --git a/Source/cairo/CairoGState.m b/Source/cairo/CairoGState.m index 8d34d510..c976ff12 100644 --- a/Source/cairo/CairoGState.m +++ b/Source/cairo/CairoGState.m @@ -1584,10 +1584,26 @@ - (void) drawGradient: (NSGradient*)gradient [gradient getColor: &color location: &location atIndex: i]; - red = [color redComponent]; - green = [color greenComponent]; - blue = [color blueComponent]; - alpha = [color alphaComponent]; + /* Ensure color is in an RGB-compatible colorspace to avoid + -redComponent/-greenComponent/-blueComponent raising + for non-RGB colors (patterns, color lists, etc.). Try + device RGB first, then calibrated RGB, and finally + fall back to a safe opaque black if conversion fails. */ + NSColor *rgbColor = [color colorUsingColorSpaceName: NSDeviceRGBColorSpace]; + if (!rgbColor) rgbColor = [color colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + if (!rgbColor) rgbColor = [NSColor colorWithCalibratedWhite:0.0 alpha:1.0]; + + @try { + red = [rgbColor redComponent]; + green = [rgbColor greenComponent]; + blue = [rgbColor blueComponent]; + alpha = [rgbColor alphaComponent]; + } @catch (NSException *ex) { + /* Last-resort safe defaults */ + red = green = blue = 0.0; + alpha = 1.0; + } + cairo_pattern_add_color_stop_rgba(cpattern, location, red, green, blue, alpha); } @@ -1629,39 +1645,28 @@ - (void) drawGradient: (NSGradient*)gradient double green; double blue; double alpha; - NSString *colorSpaceName; - + [gradient getColor: &color location: &location atIndex: i]; - colorSpaceName = [color colorSpaceName]; - if([NSCalibratedRGBColorSpace isEqualToString: colorSpaceName] || - [NSDeviceRGBColorSpace isEqualToString: colorSpaceName]) - { - red = [color redComponent]; - green = [color greenComponent]; - blue = [color blueComponent]; - alpha = [color alphaComponent]; - cairo_pattern_add_color_stop_rgba(cpattern, location, - red, green, blue, alpha); - } - else if([NSCalibratedWhiteColorSpace isEqualToString: colorSpaceName] || - [NSDeviceWhiteColorSpace isEqualToString: colorSpaceName] || - [NSCalibratedBlackColorSpace isEqualToString: colorSpaceName] || - [NSDeviceBlackColorSpace isEqualToString: colorSpaceName]) - { - red = [color whiteComponent]; - green = [color whiteComponent]; - blue = [color whiteComponent]; - alpha = [color alphaComponent]; - cairo_pattern_add_color_stop_rgba(cpattern, location, - red, green, blue, alpha); - } - else - { - NSLog(@"Cannot draw gradient for %@",colorSpaceName); - } + /* Normalize to RGB-compatible color before extracting components */ + NSColor *rgbColor = [color colorUsingColorSpaceName: NSDeviceRGBColorSpace]; + if (!rgbColor) rgbColor = [color colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + if (!rgbColor) rgbColor = [NSColor colorWithCalibratedWhite:0.0 alpha:1.0]; + + @try { + red = [rgbColor redComponent]; + green = [rgbColor greenComponent]; + blue = [rgbColor blueComponent]; + alpha = [rgbColor alphaComponent]; + } @catch (NSException *ex) { + red = green = blue = 0.0; + alpha = 1.0; + } + + cairo_pattern_add_color_stop_rgba(cpattern, location, + red, green, blue, alpha); } cairo_save(_ct); diff --git a/Tests/gradient/GNUmakefile b/Tests/gradient/GNUmakefile new file mode 100644 index 00000000..67e5d5a4 --- /dev/null +++ b/Tests/gradient/GNUmakefile @@ -0,0 +1,9 @@ +include $(GNUSTEP_MAKEFILES)/common.make + +TOOL_NAME = testgradient + +testgradient_OBJC_FILES = gradient_test.m + +testgradient_TOOL_LIBS = -lgnustep-gui -lgnustep-base + +include $(GNUSTEP_MAKEFILES)/tool.make diff --git a/Tests/gradient/gradient_test.m b/Tests/gradient/gradient_test.m new file mode 100644 index 00000000..bf510c5c --- /dev/null +++ b/Tests/gradient/gradient_test.m @@ -0,0 +1,31 @@ +#import +#import + +int main (int argc, const char * argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // Create a small pattern image and make a pattern color (non-RGB) + NSImage *pat = [[NSImage alloc] initWithSize:NSMakeSize(4,4)]; + [pat lockFocus]; + [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:1.0] setFill]; + NSRectFill(NSMakeRect(0,0,4,4)); + [pat unlockFocus]; + + NSColor *pattern = [NSColor colorWithPatternImage:pat]; + + NSGradient *g = [[NSGradient alloc] initWithStartingColor:pattern endingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:1.0]]; + + NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(100,100)]; + @try { + [img lockFocus]; + [g drawInRect:NSMakeRect(0,0,100,100) angle:90.0]; + [img unlockFocus]; + NSLog(@"OK: gradient drawn without exception"); + } @catch (NSException *ex) { + NSLog(@"FAIL: exception: %@", ex); + return 1; + } + + [pool drain]; + return 0; +}