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
18 changes: 12 additions & 6 deletions CTGradient.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

#import <Cocoa/Cocoa.h>

// CGFloat is only available in 10.5+
#ifndef CGFLOAT_DEFINED
typedef float CGFloat;
#define CGFLOAT_DEFINED
#endif

typedef struct _CTGradientElement
{
CGFloat red, green, blue, alpha;
Expand Down Expand Up @@ -51,23 +57,23 @@ typedef enum _CTBlendingMode
+ (id)rainbowGradient;
+ (id)hydrogenSpectrumGradient;

- (CTGradient *)gradientWithAlphaComponent:(float)alpha;
- (CTGradient *)gradientWithAlphaComponent:(CGFloat)alpha;

- (CTGradient *)addColorStop:(NSColor *)color atPosition:(float)position; //positions given relative to [0,1]
- (CTGradient *)addColorStop:(NSColor *)color atPosition:(CGFloat)position; //positions given relative to [0,1]
- (CTGradient *)removeColorStopAtIndex:(unsigned)index;
- (CTGradient *)removeColorStopAtPosition:(float)position;
- (CTGradient *)removeColorStopAtPosition:(CGFloat)position;

- (CTGradientBlendingMode)blendingMode;
- (NSColor *)colorStopAtIndex:(unsigned)index;
- (NSColor *)colorAtPosition:(float)position;
- (NSColor *)colorAtPosition:(CGFloat)position;


- (void)drawSwatchInRect:(NSRect)rect;
- (void)fillRect:(NSRect)rect angle:(float)angle; //fills rect with axial gradient
- (void)fillRect:(NSRect)rect angle:(CGFloat)angle; //fills rect with axial gradient
// angle in degrees
- (void)radialFillRect:(NSRect)rect; //fills rect with radial gradient
// gradient from center outwards
- (void)fillBezierPath:(NSBezierPath *)path angle:(float)angle;
- (void)fillBezierPath:(NSBezierPath *)path angle:(CGFloat)angle;
- (void)radialFillBezierPath:(NSBezierPath *)path;

@end
118 changes: 61 additions & 57 deletions CTGradient.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// Version: 1.8

#import "CTGradient.h"
#import <math.h>

@interface CTGradient (Private)
- (void)_commonInit;
Expand All @@ -18,16 +19,16 @@ - (void)addElement:(CTGradientElement*)newElement;
- (CTGradientElement *)elementAtIndex:(unsigned)index;

- (CTGradientElement)removeElementAtIndex:(unsigned)index;
- (CTGradientElement)removeElementAtPosition:(float)position;
- (CTGradientElement)removeElementAtPosition:(CGFloat)position;
@end

//C Fuctions for color blending
static void linearEvaluation (void *info, const float *in, float *out);
static void chromaticEvaluation(void *info, const float *in, float *out);
static void inverseChromaticEvaluation(void *info, const float *in, float *out);
static void transformRGB_HSV(float *components);
static void transformHSV_RGB(float *components);
static void resolveHSV(float *color1, float *color2);
static void linearEvaluation (void *info, const CGFloat *in, CGFloat *out);
static void chromaticEvaluation(void *info, const CGFloat *in, CGFloat *out);
static void inverseChromaticEvaluation(void *info, const CGFloat *in, CGFloat *out);
static void transformRGB_HSV(CGFloat *components);
static void transformHSV_RGB(CGFloat *components);
static void resolveHSV(CGFloat *color1, CGFloat *color2);


@implementation CTGradient
Expand All @@ -53,7 +54,7 @@ - (void)dealloc
{
CGFunctionRelease(gradientFunction);

CTGradientElement *elementToRemove = elementList;
CTGradientElement *elementToRemove;
while(elementList != nil)
{
elementToRemove = elementList;
Expand Down Expand Up @@ -89,11 +90,11 @@ - (void)encodeWithCoder:(NSCoder *)coder
CTGradientElement *currentElement = elementList;
while(currentElement != nil)
{
[coder encodeValueOfObjCType:@encode(float) at:&(currentElement->red)];
[coder encodeValueOfObjCType:@encode(float) at:&(currentElement->green)];
[coder encodeValueOfObjCType:@encode(float) at:&(currentElement->blue)];
[coder encodeValueOfObjCType:@encode(float) at:&(currentElement->alpha)];
[coder encodeValueOfObjCType:@encode(float) at:&(currentElement->position)];
[coder encodeValueOfObjCType:@encode(CGFloat) at:&(currentElement->red)];
[coder encodeValueOfObjCType:@encode(CGFloat) at:&(currentElement->green)];
[coder encodeValueOfObjCType:@encode(CGFloat) at:&(currentElement->blue)];
[coder encodeValueOfObjCType:@encode(CGFloat) at:&(currentElement->alpha)];
[coder encodeValueOfObjCType:@encode(CGFloat) at:&(currentElement->position)];

count++;
currentElement = currentElement->nextElement;
Expand All @@ -116,11 +117,11 @@ - (id)initWithCoder:(NSCoder *)coder
{
CTGradientElement newElement;

[coder decodeValueOfObjCType:@encode(float) at:&(newElement.red)];
[coder decodeValueOfObjCType:@encode(float) at:&(newElement.green)];
[coder decodeValueOfObjCType:@encode(float) at:&(newElement.blue)];
[coder decodeValueOfObjCType:@encode(float) at:&(newElement.alpha)];
[coder decodeValueOfObjCType:@encode(float) at:&(newElement.position)];
[coder decodeValueOfObjCType:@encode(CGFloat) at:&(newElement.red)];
[coder decodeValueOfObjCType:@encode(CGFloat) at:&(newElement.green)];
[coder decodeValueOfObjCType:@encode(CGFloat) at:&(newElement.blue)];
[coder decodeValueOfObjCType:@encode(CGFloat) at:&(newElement.alpha)];
[coder decodeValueOfObjCType:@encode(CGFloat) at:&(newElement.position)];

count--;
[self addElement:&newElement];
Expand Down Expand Up @@ -419,7 +420,7 @@ + (id)hydrogenSpectrumGradient
{
id newInstance = [[[self class] alloc] init];

struct {float hue; float position; float width;} colorBands[4];
struct {CGFloat hue; CGFloat position; CGFloat width;} colorBands[4];

colorBands[0].hue = 22;
colorBands[0].position = .145;
Expand All @@ -441,7 +442,7 @@ + (id)hydrogenSpectrumGradient
/////////////////////////////
for(i = 0; i < 4; i++)
{
float color[4];
CGFloat color[4];
color[0] = colorBands[i].hue - 180*colorBands[i].width;
color[1] = 1;
color[2] = 0.001;
Expand Down Expand Up @@ -495,7 +496,7 @@ + (id)hydrogenSpectrumGradient


#pragma mark Modification
- (CTGradient *)gradientWithAlphaComponent:(float)alpha
- (CTGradient *)gradientWithAlphaComponent:(CGFloat)alpha
{
id newInstance = [[[self class] alloc] init];

Expand Down Expand Up @@ -526,7 +527,7 @@ - (CTGradient *)gradientWithBlendingMode:(CTGradientBlendingMode)mode

//Adds a color stop with <color> at <position> in elementList
//(if two elements are at the same position then added imediatly after the one that was there already)
- (CTGradient *)addColorStop:(NSColor *)color atPosition:(float)position
- (CTGradient *)addColorStop:(NSColor *)color atPosition:(CGFloat)position
{
CTGradient *newGradient = [self copy];
CTGradientElement newGradientElement;
Expand All @@ -546,7 +547,7 @@ - (CTGradient *)addColorStop:(NSColor *)color atPosition:(float)position


//Removes the color stop at <position> from elementList
- (CTGradient *)removeColorStopAtPosition:(float)position
- (CTGradient *)removeColorStopAtPosition:(CGFloat)position
{
CTGradient *newGradient = [self copy];
CTGradientElement removedElement = [newGradient removeElementAtPosition:position];
Expand Down Expand Up @@ -593,9 +594,9 @@ - (NSColor *)colorStopAtIndex:(unsigned)index
return nil;
}

- (NSColor *)colorAtPosition:(float)position
- (NSColor *)colorAtPosition:(CGFloat)position
{
float components[4];
CGFloat components[4];

switch(blendingMode)
{
Expand Down Expand Up @@ -623,7 +624,7 @@ - (void)drawSwatchInRect:(NSRect)rect
[self fillRect:rect angle:45];
}

- (void)fillRect:(NSRect)rect angle:(float)angle
- (void)fillRect:(NSRect)rect angle:(CGFloat)angle
{
//First Calculate where the beginning and ending points should be
CGPoint startPoint;
Expand All @@ -641,14 +642,14 @@ - (void)fillRect:(NSRect)rect angle:(float)angle
}
else //ok, we'll do the calculations now
{
float x,y;
float sina, cosa, tana;
CGFloat x,y;
CGFloat sina, cosa, tana;

float length;
float deltax,
CGFloat length;
CGFloat deltax,
deltay;

float rangle = angle * pi/180; //convert the angle to radians
CGFloat rangle = angle * M_PI/180; //convert the angle to radians

if(fabsf(tan(rangle))<=1) //for range [-45,45], [135,225]
{
Expand All @@ -669,9 +670,9 @@ - (void)fillRect:(NSRect)rect angle:(float)angle
x = NSHeight(rect);
y = NSWidth(rect);

sina = sin(rangle - 90*pi/180);
cosa = cos(rangle - 90*pi/180);
tana = tan(rangle - 90*pi/180);
sina = sin(rangle - 90*M_PI/180);
cosa = cos(rangle - 90*M_PI/180);
tana = tan(rangle - 90*M_PI/180);

length = x/fabsf(cosa)+(y-x*fabsf(tana))*fabsf(sina);

Expand Down Expand Up @@ -704,8 +705,8 @@ - (void)fillRect:(NSRect)rect angle:(float)angle
- (void)radialFillRect:(NSRect)rect
{
CGPoint startPoint, endPoint;
float startRadius, endRadius;
float scalex, scaley, transx, transy;
CGFloat startRadius, endRadius;
CGFloat scalex, scaley, transx, transy;

startPoint = endPoint = CGPointMake(NSMidX(rect), NSMidY(rect));

Expand Down Expand Up @@ -747,7 +748,7 @@ - (void)radialFillRect:(NSRect)rect
CGContextRestoreGState(currentContext);
}

- (void)fillBezierPath:(NSBezierPath *)path angle:(float)angle
- (void)fillBezierPath:(NSBezierPath *)path angle:(CGFloat)angle
{
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
[currentContext saveGraphicsState];
Expand Down Expand Up @@ -881,7 +882,7 @@ - (CTGradientElement)removeElementAtIndex:(unsigned)index
return removedElement;
}

- (CTGradientElement)removeElementAtPosition:(float)position
- (CTGradientElement)removeElementAtPosition:(CGFloat)position
{
CTGradientElement removedElement;

Expand Down Expand Up @@ -950,9 +951,9 @@ - (CTGradientElement *)elementAtIndex:(unsigned)index;

#pragma mark Core Graphics
//////////////////////////////////////Blending Functions/////////////////////////////////////
void linearEvaluation (void *info, const float *in, float *out)
void linearEvaluation (void *info, const CGFloat *in, CGFloat *out)
{
float position = *in;
CGFloat position = *in;

if(*(CTGradientElement **)info == nil) //if elementList is empty return clear color
{
Expand Down Expand Up @@ -1028,9 +1029,9 @@ void linearEvaluation (void *info, const float *in, float *out)
// this we will add to the hue's angle (if we subtract we'll be doing the inverse
// chromatic...scroll down more for that). All we need to do is keep adding to the hue
// until we wrap around the colorwheel and get to color2.
void chromaticEvaluation(void *info, const float *in, float *out)
void chromaticEvaluation(void *info, const CGFloat *in, CGFloat *out)
{
float position = *in;
CGFloat position = *in;

if(*(CTGradientElement **)info == nil) //if elementList is empty return clear color
{
Expand All @@ -1042,8 +1043,8 @@ void chromaticEvaluation(void *info, const float *in, float *out)
CTGradientElement *color1 = *(CTGradientElement **)info;
CTGradientElement *color2 = color1->nextElement;

float c1[4];
float c2[4];
CGFloat c1[4];
CGFloat c2[4];

//make sure first color and second color are on other sides of position
while(color2 != nil && color2->position < position)
Expand Down Expand Up @@ -1116,9 +1117,9 @@ void chromaticEvaluation(void *info, const float *in, float *out)
// is strictly decreasing, that is we need to get from color1 to color2 by decreasing
// the 'angle' (i.e. 90� -> 180� would be done by subtracting 270� and getting -180�...
// which is equivalent to 180� mod 360�
void inverseChromaticEvaluation(void *info, const float *in, float *out)
void inverseChromaticEvaluation(void *info, const CGFloat *in, CGFloat *out)
{
float position = *in;
CGFloat position = *in;

if(*(CTGradientElement **)info == nil) //if elementList is empty return clear color
{
Expand All @@ -1130,8 +1131,8 @@ void inverseChromaticEvaluation(void *info, const float *in, float *out)
CTGradientElement *color1 = *(CTGradientElement **)info;
CTGradientElement *color2 = color1->nextElement;

float c1[4];
float c2[4];
CGFloat c1[4];
CGFloat c2[4];

//make sure first color and second color are on other sides of position
while(color2 != nil && color2->position < position)
Expand Down Expand Up @@ -1197,14 +1198,14 @@ void inverseChromaticEvaluation(void *info, const float *in, float *out)
}


void transformRGB_HSV(float *components) //H,S,B -> R,G,B
void transformRGB_HSV(CGFloat *components) //H,S,B -> R,G,B
{
float H, S, V;
float R = components[0],
CGFloat H, S, V;
CGFloat R = components[0],
G = components[1],
B = components[2];

float MAX = R > G ? (R > B ? R : B) : (G > B ? G : B),
CGFloat MAX = R > G ? (R > B ? R : B) : (G > B ? G : B),
MIN = R < G ? (R < B ? R : B) : (G < B ? G : B);

if(MAX == MIN)
Expand All @@ -1218,6 +1219,8 @@ void transformRGB_HSV(float *components) //H,S,B -> R,G,B
H = 60*(B-R)/(MAX-MIN)+120;
else if(MAX == B)
H = 60*(R-G)/(MAX-MIN)+240;
else
H = 0;

S = MAX == 0 ? 0 : 1 - MIN/MAX;
V = MAX;
Expand All @@ -1227,15 +1230,15 @@ void transformRGB_HSV(float *components) //H,S,B -> R,G,B
components[2] = V;
}

void transformHSV_RGB(float *components) //H,S,B -> R,G,B
void transformHSV_RGB(CGFloat *components) //H,S,B -> R,G,B
{
float R, G, B;
float H = fmodf(components[0],359), //map to [0,360)
CGFloat R, G, B;
CGFloat H = fmodf(components[0],359), //map to [0,360)
S = components[1],
V = components[2];

int Hi = (int)floorf(H/60.) % 6;
float f = H/60-Hi,
CGFloat f = H/60-Hi,
p = V*(1-S),
q = V*(1-f*S),
t = V*(1-(1-f)*S);
Expand All @@ -1248,14 +1251,15 @@ void transformHSV_RGB(float *components) //H,S,B -> R,G,B
case 3: R=p;G=q;B=V; break;
case 4: R=t;G=p;B=V; break;
case 5: R=V;G=p;B=q; break;
default: R=0;G=0;B=0; break;
}

components[0] = R;
components[1] = G;
components[2] = B;
}

void resolveHSV(float *color1, float *color2) //H value may be undefined (i.e. graycale color)
void resolveHSV(CGFloat *color1, CGFloat *color2) //H value may be undefined (i.e. graycale color)
{ // we want to fill it with a sensible value
if(isnan(color1[0]) && isnan(color2[0]))
color1[0] = color2[0] = 0;
Expand Down
2 changes: 1 addition & 1 deletion CTGradientView.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{
CTGradient *myGradient;

float angle;
CGFloat angle;
bool isRadial;
}

Expand Down
2 changes: 1 addition & 1 deletion CTGradientView.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ - (void)dealloc
[super dealloc];
}

- (bool)isOpaque
- (BOOL)isOpaque
{
return NO;
}
Expand Down