// // CTGradient.m // // Created by Chad Weider on 2/14/07. // Copyright (c) 2007 Chad Weider. // Some rights reserved: // // Version: 1.6 #import "CTGradient.h" //C Fuctions for color blending static void linearEvaluation (void *info, const float *in, float *out); @implementation CTGradient - (id)init { if(self = [super init]) { CGFunctionCallbacks evaluationCallbackInfo = {0 , &linearEvaluation, 0}; static const float input_value_range[2] = { 0, 1 }; static const float output_value_ranges[8] = { 0, 1, 0, 1, 0, 1, 0, 1 }; gradientFunction = CGFunctionCreate(&elementList, 1, input_value_range, 4, output_value_ranges, &evaluationCallbackInfo); } return self; } - (void)dealloc { CGFunctionRelease(gradientFunction); free(elementList->nextElement); free(elementToRemove); [super dealloc]; } + (id)gradientWithBeginningColor:(NSColor *)begin endingColor:(NSColor *)end { id newInstance = [[[self class] alloc] init]; CTGradientElement color1, color2; [[begin colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&color1.red green:&color1.green blue:&color1.blue alpha:&color1.alpha]; [[end colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&color2.red green:&color2.green blue:&color2.blue alpha:&color2.alpha]; [newInstance addElement:&color1]; [newInstance addElement:&color2]; return [newInstance autorelease]; } - (void)fillRect:(NSRect)rect { //First Calculate where the beginning and ending points should be CGPoint startPoint; CGPoint endPoint; startPoint = CGPointMake(NSMinX(rect), NSMinY(rect)); endPoint = CGPointMake(NSMinX(rect), NSMaxY(rect)); //Calls to CoreGraphics CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextSaveGState(currentContext); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); #else CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); #endif CGShadingRef myCGShading = CGShadingCreateAxial(colorspace, startPoint, endPoint, gradientFunction, false, false); CGContextClipToRect (currentContext, *(CGRect *)&rect); //This is where the action happens CGContextDrawShading(currentContext, myCGShading); CGShadingRelease(myCGShading); CGColorSpaceRelease(colorspace ); CGContextRestoreGState(currentContext); } - (void)addElement:(CTGradientElement *)newElement { if(elementList) { //inserting somewhere inside list elementList->nextElement = malloc(sizeof(CTGradientElement)); *(elementList->nextElement) = *newElement; elementList->nextElement->nextElement = 0; } else { //inserting at beginning of list elementList = malloc(sizeof(CTGradientElement)); *elementList = *newElement; elementList->nextElement = 0; } } void linearEvaluation (void *info, const float *in, float *out) { float position = *in; CTGradientElement *color1 = *(CTGradientElement **)info; CTGradientElement *color2 = color1->nextElement; out[0] = (color2->red - color1->red)*position + color1->red; out[1] = (color2->green - color1->green)*position + color1->green; out[2] = (color2->blue - color1->blue)*position + color1->blue; out[3] = (color2->alpha - color1->alpha)*position + color1->alpha; } @end