2 // NSBezierPath_AMShading.m
3 // ------------------------
5 // Created by Andreas on 2005-06-01.
6 // Copyright 2005 Andreas Mayer. All rights reserved.
9 #import "NSBezierPath_AMShading.h"
12 @implementation NSBezierPath (AMShading)
14 static void linearShadedColor(void *info, const float *in, float *out)
17 *out++ = colors[0] + *in * colors[8];
18 *out++ = colors[1] + *in * colors[9];
19 *out++ = colors[2] + *in * colors[10];
20 *out++ = colors[3] + *in * colors[11];
23 static void bilinearShadedColor(void *info, const float *in, float *out)
26 float factor = (*in)*2.0;
30 *out++ = colors[0] + factor * colors[8];
31 *out++ = colors[1] + factor * colors[9];
32 *out++ = colors[2] + factor * colors[10];
33 *out++ = colors[3] + factor * colors[11];
36 - (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor
39 CGColorSpaceRef colorspace;
41 CGPoint startPoint = {0, 0};
42 CGPoint endPoint = {0, 0};
43 CGFunctionRef function;
44 float colors[12]; // pointer to color values
47 CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
49 NSColor *deviceDependentStartColor = [startColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
50 NSColor *deviceDependentEndColor = [endColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
52 // set up colors for gradient
53 colors[0] = [deviceDependentStartColor redComponent];
54 colors[1] = [deviceDependentStartColor greenComponent];
55 colors[2] = [deviceDependentStartColor blueComponent];
56 colors[3] = [deviceDependentStartColor alphaComponent];
58 colors[4] = [deviceDependentEndColor redComponent];
59 colors[5] = [deviceDependentEndColor greenComponent];
60 colors[6] = [deviceDependentEndColor blueComponent];
61 colors[7] = [deviceDependentEndColor alphaComponent];
63 // difference between start and end color for each color components
64 colors[8] = (colors[4]-colors[0]);
65 colors[9] = (colors[5]-colors[1]);
66 colors[10] = (colors[6]-colors[2]);
67 colors[11] = (colors[7]-colors[3]);
70 colorspace = CGColorSpaceCreateDeviceRGB();
72 size_t components = 1 + CGColorSpaceGetNumberOfComponents(colorspace);
73 static const float domain[2] = {0.0, 1.0};
74 static const float range[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
75 static const CGFunctionCallbacks callbacks = {0, &shadedColor, NULL};
77 // Create a CGFunctionRef that describes a function taking 1 input and kChannelsPerColor outputs.
78 function = CGFunctionCreate(colors, 1, domain, components, range, &callbacks);
81 startPoint.y=[self bounds].origin.y;
83 endPoint.y=NSMaxY([self bounds]);
85 shading = CGShadingCreateAxial(colorspace, startPoint, endPoint, function, NO, NO);
87 CGContextSaveGState(currentContext);
89 CGContextDrawShading(currentContext, shading);
90 CGContextRestoreGState(currentContext);
92 CGShadingRelease(shading);
93 CGFunctionRelease(function);
94 CGColorSpaceRelease(colorspace);
97 static const CGFunctionCallbacks callbacks = {0, &linearShadedColor, NULL};
99 [self customHorizontalFillWithCallbacks:callbacks firstColor:startColor secondColor:endColor];
102 - (void)bilinearGradientFillWithOuterColor:(NSColor *)outerColor innerColor:(NSColor *)innerColor
104 static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL};
106 [self customHorizontalFillWithCallbacks:callbacks firstColor:innerColor secondColor:outerColor];
109 - (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor
111 CGColorSpaceRef colorspace;
112 CGShadingRef shading;
113 CGPoint startPoint = {0, 0};
114 CGPoint endPoint = {0, 0};
115 CGFunctionRef function;
116 float colors[12]; // pointer to color values
119 CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
121 NSColor *deviceDependentFirstColor = [firstColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
122 NSColor *deviceDependentSecondColor = [secondColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
124 // set up colors for gradient
125 colors[0] = [deviceDependentFirstColor redComponent];
126 colors[1] = [deviceDependentFirstColor greenComponent];
127 colors[2] = [deviceDependentFirstColor blueComponent];
128 colors[3] = [deviceDependentFirstColor alphaComponent];
130 colors[4] = [deviceDependentSecondColor redComponent];
131 colors[5] = [deviceDependentSecondColor greenComponent];
132 colors[6] = [deviceDependentSecondColor blueComponent];
133 colors[7] = [deviceDependentSecondColor alphaComponent];
135 // difference between start and end color for each color components
136 colors[8] = (colors[4]-colors[0]);
137 colors[9] = (colors[5]-colors[1]);
138 colors[10] = (colors[6]-colors[2]);
139 colors[11] = (colors[7]-colors[3]);
142 colorspace = CGColorSpaceCreateDeviceRGB();
143 size_t components = 1 + CGColorSpaceGetNumberOfComponents(colorspace);
144 static const float domain[2] = {0.0, 1.0};
145 static const float range[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
146 //static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL};
148 // Create a CGFunctionRef that describes a function taking 1 input and kChannelsPerColor outputs.
149 function = CGFunctionCreate(colors, 1, domain, components, range, &functionCallbacks);
152 startPoint.y=[self bounds].origin.y;
154 endPoint.y=NSMaxY([self bounds]);
156 shading = CGShadingCreateAxial(colorspace, startPoint, endPoint, function, NO, NO);
158 CGContextSaveGState(currentContext);
160 CGContextDrawShading(currentContext, shading);
161 CGContextRestoreGState(currentContext);
163 CGShadingRelease(shading);
164 CGFunctionRelease(function);
165 CGColorSpaceRelease(colorspace);