Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 311 lines (245 sloc) 7.471 kB
dc5be1c Initial check-in.
uli authored
1 //
2 // UKGradient.m
3 // GradientDrawing
4 //
5 // Created by Uli Kusterer on 24.10.04.
720b0e7 @uliwitness Added licensing information to the source files.
authored
6 // Copyright 2004 Uli Kusterer.
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
dc5be1c Initial check-in.
uli authored
26 //
27
28 #import "UKGradient.h"
29
30
31 @implementation UKGradient
32
33
34 -(id) init
35 {
36 self = [super init];
37 if( !self )
38 return nil;
39
40 direction = UKGradientFromTopLeft;
41 [self setStartColor: [NSColor darkGrayColor]];
42 [self setEndColor: [NSColor lightGrayColor]];
43
44 return self;
45 }
46
47
48 -(id) initWithStartColor: (NSColor*)start endColor: (NSColor*)end direction: (UKGradientDirection)d
49 {
50 self = [super init];
51 if( !self )
52 return nil;
53
54 direction = d;
55 [self setStartColor: [NSColor darkGrayColor]];
56 [self setEndColor: [NSColor lightGrayColor]];
57
58 return self;
59 }
60
61
62 -(id) initWithStartColor: (NSColor*)start endColor: (NSColor*)end direction: (UKGradientDirection)d
63 rect: (NSRect)box
64 {
65 self = [self initWithStartColor: start endColor: end direction: d];
66 if( !self )
67 return nil;
68
69 [self cacheForRect: box];
70
71 return self;
72 }
73
74
75
76 // ----------------------------------------------------------
77 // - dealloc:
78 // ----------------------------------------------------------
79 - (void) dealloc
80 {
81 [startColor release];
82 [endColor release];
83
84 startColor = nil;
85 endColor = nil;
86
87 [super dealloc];
88 }
89
90
91 // ----------------------------------------------------------
92 // - startColor:
93 // ----------------------------------------------------------
94 - (NSColor *) startColor
95 {
96 return startColor;
97 }
98
99 // ----------------------------------------------------------
100 // - setStartColor:
101 // ----------------------------------------------------------
102 - (void) setStartColor: (NSColor *) theStartColor
103 {
104 if (startColor != theStartColor)
105 {
106 [startColor release];
107 startColor = [theStartColor retain];
108 [self invalidateCache];
109 }
110 }
111
112 // ----------------------------------------------------------
113 // - endColor:
114 // ----------------------------------------------------------
115 - (NSColor *) endColor
116 {
117 return endColor;
118 }
119
120 // ----------------------------------------------------------
121 // - setEndColor:
122 // ----------------------------------------------------------
123 - (void) setEndColor: (NSColor *) theEndColor
124 {
125 if (endColor != theEndColor)
126 {
127 [endColor release];
128 endColor = [theEndColor retain];
129 [self invalidateCache];
130 }
131 }
132
133
134 -(void) setDirection: (UKGradientDirection)dir
135 {
136 direction = dir;
137 [self invalidateCache];
138 }
139
140
141 -(UKGradientDirection) direction
142 {
143 return direction;
144 }
145
146
147 -(BOOL) dontCache
148 {
149 return dontCache;
150 }
151
152
153 -(void) setDontCache: (BOOL)n
154 {
155 dontCache = n;
156 [self invalidateCache];
157 }
158
159
160 -(void) invalidateCache
161 {
162 if( cachedImage )
163 {
164 free( cachedImage );
165 cachedImage = NULL;
166 }
167 }
168
169
170
171
172 #define UKTRansformYCoord(n) ((direction != UKGradientFromTopLeft) ? (box.size.height -n) : n)
173
174 /*unsigned int UKBlendedRGBA( unsigned int c1, unsigned int c2, float frac )
175 {
176 int r = ((c1 & 0xFF000000) >> 24) *(1-frac) +((c2 & 0xFF000000) >> 24) *frac,
177 g = ((c1 & 0x00FF0000) >> 16) *(1-frac) +((c2 & 0x00FF0000) >> 16) *frac,
178 b = ((c1 & 0x0000FF00) >> 8) *(1-frac) +((c2 & 0x0000FF00) >> 8) *frac,
179 a = (c1 & 0x000000FF) *(1-frac) +(c2 & 0x000000FF) *frac;
180
181 return( (r << 24) | (g << 16) | (b << 8) | a );
182 }*/
183
184 #define UKRed(c1) ((c1 & 0xFF000000) >> 24)
185 #define UKGreen(c1) ((c1 & 0x00FF0000) >> 16)
186 #define UKBlue(c1) ((c1 & 0x0000FF00) >> 8)
187 #define UKAlpha(c1) (c1 & 0x000000FF)
188 #define UKUnRed(cm1) ((cm1 & 0xFF) << 24)
189 #define UKUnGreen(cm1) ((cm1 & 0xFF) << 16)
190 #define UKUnBlue(cm1) ((cm1 & 0xFF) << 8)
191 #define UKUnAlpha(cm1) (cm1 & 0xFF)
192 #define UKBlend(cm1,cm2,frac) ((int)(cm1 *(1-frac) +cm2 * frac))
193 #define UKBlendedRGBA( c1, c2, frac ) (UKUnRed(UKBlend(UKRed(c1),UKRed(c2),frac)) \
194 | UKUnGreen(UKBlend(UKGreen(c1),UKGreen(c2),frac)) \
195 | UKUnBlue(UKBlend(UKBlue(c1),UKBlue(c2),frac)) \
196 | UKUnAlpha(UKBlend(UKAlpha(c1),UKAlpha(c2),frac)))
197
198 -(void) drawAtPoint: (NSPoint)pos
199 {
200 NSRect box;
201
202 box.origin = pos;
203 box.size = cacheSize;
204
205 [self drawInRect: box];
206 }
207
208
209 -(void) drawInRect: (NSRect)box
210 {
211 int x,
212 y;
213 NSRect unitSquare = { {0, 0 }, { 1, 1 } };
214 float stepSize;
215
216 switch( direction )
217 {
218 case UKGradientFromLeft:
219 stepSize = 1 / box.size.width;
220 unitSquare.size.height = box.size.height;
221 for( x = 0; x < box.size.width; x++ )
222 {
223 float frac = stepSize * x;
224 unitSquare.origin.x = x +box.origin.x;
225 [[startColor blendedColorWithFraction: frac ofColor: endColor] set];
226 NSRectFill( unitSquare );
227 }
228 break;
229
230 case UKGradientFromTop:
231 stepSize = 1 / box.size.height;
232 unitSquare.size.width = box.size.width;
233 for( y = 0; y < box.size.height; y++ )
234 {
235 float frac = stepSize * y;
236 unitSquare.origin.y = y +box.origin.y;
237 [[endColor blendedColorWithFraction: frac ofColor: startColor] set]; // Reversed since coords go from bottom to top.
238 NSRectFill( unitSquare );
239 }
240 break;
241
242 case UKGradientFromTopLeft:
243 case UKGradientFromBotLeft:
244 {
245 if( !cachedImage
246 || ((cacheSize.height != box.size.height
247 || cacheSize.width != box.size.width) && dontCache) )
248 [self cacheForRect: box];
249
250 char** buffers[5] = { (unsigned char*)cachedImage, NULL };
251 NSDrawBitmap( box, cacheSize.width, cacheSize.height, 8, 4, 32, (cacheSize.width *sizeof(unsigned int)),
252 NO, YES, NSDeviceRGBColorSpace, buffers );
253
254 if( dontCache )
255 [self invalidateCache];
256 }
257 }
258 }
259
260 -(void) cacheForRect: (NSRect)box
261 {
262 [self invalidateCache];
263
264 unsigned int* buf = malloc( (box.size.width *box.size.height) * sizeof(unsigned int) );
265 unsigned int startRGBA = [startColor rgbaIntValue],
266 endRGBA = [endColor rgbaIntValue];
267 float stepSize = 1 / (box.size.width +box.size.height);
268 int x,
269 y;
270
271 for( x = 0; x < box.size.width; x++ )
272 {
273 for( y = 0; y < box.size.height; y++ )
274 {
275 float frac = stepSize * (x+ UKTRansformYCoord(y));
276 int currOffs = (y *box.size.width) +x;
277 unsigned int colorVal = UKBlendedRGBA( startRGBA, endRGBA, frac );
278 buf[currOffs] = colorVal;
279 }
280 }
281
282 cacheSize = box.size;
283 cachedImage = buf;
284 }
285
286 -(void) swapColors
287 {
288 NSColor* t = endColor;
289 endColor = startColor;
290 startColor = t;
291
292 [self invalidateCache]; // TODO: Just rotate cache 180 degrees instead!
293 }
294
295 @end
296
297
298 @implementation NSColor (UKRGBAIntValue)
299
300 -(unsigned int) rgbaIntValue
301 {
302 float r, g, b, a;
303 NSColor* rgbaColor = [self colorUsingColorSpaceName: NSDeviceRGBColorSpace];
304
305 [rgbaColor getRed: &r green: &g blue: &b alpha: &a];
306
307 return( ((int)(r * 255) << 24) | ((int)(g * 255) << 16) | ((int)(b * 255) << 8) | (int)(a * 255) );
308 }
309
310 @end
Something went wrong with that request. Please try again.