Permalink
Browse files

: initial version

  • Loading branch information...
paiv committed Feb 12, 2012
0 parents commit 7c78b1a97d663eef976697dd8ea4133677936454
Showing with 1,546 additions and 0 deletions.
  1. +48 −0 AngleGradient/AngleGradientLayer.h
  2. +198 −0 AngleGradient/AngleGradientLayer.m
  3. +48 −0 AngleGradientSample/AngleGradient/AngleGradientLayer.h
  4. +198 −0 AngleGradientSample/AngleGradient/AngleGradientLayer.m
  5. +337 −0 AngleGradientSample/AngleGradientSample.xcodeproj/project.pbxproj
  6. +7 −0 AngleGradientSample/AngleGradientSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  7. +40 −0 AngleGradientSample/AngleGradientSample/AngleGradientSample-Info.plist
  8. +14 −0 AngleGradientSample/AngleGradientSample/AngleGradientSample-Prefix.pch
  9. +14 −0 AngleGradientSample/AngleGradientSample/AppDelegate.h
  10. +75 −0 AngleGradientSample/AngleGradientSample/AppDelegate.m
  11. +10 −0 AngleGradientSample/AngleGradientSample/SampleController.h
  12. +127 −0 AngleGradientSample/AngleGradientSample/SampleController.m
  13. +10 −0 AngleGradientSample/AngleGradientSample/UserControl1.h
  14. +48 −0 AngleGradientSample/AngleGradientSample/UserControl1.m
  15. +10 −0 AngleGradientSample/AngleGradientSample/UserControl2.h
  16. +51 −0 AngleGradientSample/AngleGradientSample/UserControl2.m
  17. +10 −0 AngleGradientSample/AngleGradientSample/UserControl3.h
  18. +40 −0 AngleGradientSample/AngleGradientSample/UserControl3.m
  19. +11 −0 AngleGradientSample/AngleGradientSample/UserControl4.h
  20. +47 −0 AngleGradientSample/AngleGradientSample/UserControl4.m
  21. +10 −0 AngleGradientSample/AngleGradientSample/UserControl5.h
  22. +69 −0 AngleGradientSample/AngleGradientSample/UserControl5.m
  23. +11 −0 AngleGradientSample/AngleGradientSample/UserControl6.h
  24. +57 −0 AngleGradientSample/AngleGradientSample/UserControl6.m
  25. +2 −0 AngleGradientSample/AngleGradientSample/en.lproj/InfoPlist.strings
  26. +17 −0 AngleGradientSample/AngleGradientSample/main.m
  27. +37 −0 README.textile
  28. BIN screenshot.png
@@ -0,0 +1,48 @@
+//
+// The MIT License (MIT)
+//
+// Copyright (C) 2012 Pavel Ivashkov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+// and associated documentation files (the "Software"), to deal in the Software without restriction,
+// including without limitation the rights to use, copy, modify, merge, publish, distribute,
+// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// AngleGradientLayer.h
+// AngleGradientSample
+//
+// Created by Pavel Ivashkov on 2012-02-12.
+//
+
+#import <QuartzCore/QuartzCore.h>
+
+
+@interface AngleGradientLayer : CALayer
+
+/* The array of CGColorRef objects defining the color of each gradient
+ * stop. Defaults to nil. */
+
+@property(copy) NSArray *colors;
+
+/* An optional array of NSNumber objects defining the location of each
+ * gradient stop as a value in the range [0,1]. The values must be
+ * monotonically increasing. If a nil array is given, the stops are
+ * assumed to spread uniformly across the [0,1] range. When rendered,
+ * the colors are mapped to the output colorspace before being
+ * interpolated. Defaults to nil. */
+
+@property(copy) NSArray *locations;
+
+@end
@@ -0,0 +1,198 @@
+//
+// The MIT License (MIT)
+//
+// Copyright (C) 2012 Pavel Ivashkov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// AngleGradientLayer.m
+// AngleGradientSample
+//
+// Created by Pavel Ivashkov on 2012-02-12.
+//
+
+#import "AngleGradientLayer.h"
+
+#define byte unsigned char
+#define uint unsigned int
+#define F2CC(x) ((byte)(255 * x))
+#define RGBAF(r,g,b,a) (F2CC(r) << 24 | F2CC(g) << 16 | F2CC(b) << 8 | F2CC(a))
+#define RGBA(r,g,b,a) ((byte)r << 24 | (byte)g << 16 | (byte)b << 8 | (byte)a)
+#define RGBA_R(c) ((uint)c >> 24 & 255)
+#define RGBA_G(c) ((uint)c >> 16 & 255)
+#define RGBA_B(c) ((uint)c >> 8 & 255)
+#define RGBA_A(c) ((uint)c >> 0 & 255)
+
+@interface AngleGradientLayer()
+
+- (CGImageRef)newImageGradientInRect:(CGRect)rect;
+
+@end
+
+
+static void angleGradient(byte* data, int w, int h, int* colors, int colorCount, float* locations, int locationCount);
+
+
+@implementation AngleGradientLayer
+
+@synthesize colors = _colors;
+@synthesize locations = _locations;
+
+- (id)init
+{
+ if (!(self = [super init]))
+ return nil;
+
+ self.needsDisplayOnBoundsChange = YES;
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [_colors release];
+ [_locations release];
+ [super dealloc];
+}
+
+- (void)drawInContext:(CGContextRef)ctx
+{
+ CGContextSetFillColorWithColor(ctx, self.backgroundColor);
+ CGRect rect = CGContextGetClipBoundingBox(ctx);
+ CGContextFillRect(ctx, rect);
+
+ CGImageRef img = [self newImageGradientInRect:rect];
+ CGContextDrawImage(ctx, rect, img);
+ CGImageRelease(img);
+}
+
+- (CGImageRef)newImageGradientInRect:(CGRect)rect
+{
+ int w = CGRectGetWidth(rect);
+ int h = CGRectGetHeight(rect);
+ int bitsPerComponent = 8;
+ int bpp = 4 * bitsPerComponent / 8;
+ int byteCount = w * h * bpp;
+
+ int colorCount = self.colors.count;
+ int locationCount = 0;
+ int* colors = NULL;
+ float* locations = NULL;
+
+ if (colorCount > 0) {
+ colors = calloc(colorCount, bpp);
+ int *p = colors;
+ for (id cg in self.colors) {
+ float r, g, b, a;
+ UIColor *c = [[UIColor alloc] initWithCGColor:(CGColorRef)cg];
+ if (![c getRed:&r green:&g blue:&b alpha:&a]) {
+ if (![c getWhite:&r alpha:&a]) {
+ [c release];
+ continue;
+ }
+ g = b = r;
+ }
+ [c release];
+ *p++ = RGBAF(r, g, b, a);
+ }
+ }
+ if (self.locations.count > 0 && self.locations.count == colorCount) {
+ locationCount = self.locations.count;
+ locations = calloc(locationCount, sizeof(locations[0]));
+ float *p = locations;
+ for (NSNumber *n in self.locations) {
+ *p++ = [n floatValue];
+ }
+ }
+
+ byte* data = malloc(byteCount);
+ angleGradient(data, w, h, colors, colorCount, locations, locationCount);
+
+ if (colors) free(colors);
+ if (locations) free(locations);
+
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Little;
+ CGContextRef ctx = CGBitmapContextCreate(data, w, h, bitsPerComponent, w * bpp, colorSpace, bitmapInfo);
+ CGColorSpaceRelease(colorSpace);
+ CGImageRef img = CGBitmapContextCreateImage(ctx);
+ CGContextRelease(ctx);
+ free(data);
+ return img;
+}
+
+@end
+
+static inline byte blerp(byte a, byte b, float w)
+{
+ return a + w * (b - a);
+}
+static inline int lerp(int a, int b, float w)
+{
+ return RGBA(blerp(RGBA_R(a), RGBA_R(b), w),
+ blerp(RGBA_G(a), RGBA_G(b), w),
+ blerp(RGBA_B(a), RGBA_B(b), w),
+ blerp(RGBA_A(a), RGBA_A(b), w));
+}
+
+void angleGradient(byte* data, int w, int h, int* colors, int colorCount, float* locations, int locationCount)
+{
+ if (colorCount < 1) return;
+ if (locationCount > 0 && locationCount != colorCount) return;
+
+ int* p = (int*)data;
+ float centerX = (float)w / 2;
+ float centerY = (float)h / 2;
+
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++) {
+ float dirX = x - centerX;
+ float dirY = y - centerY;
+ float angle = atan2f(dirY, dirX);
+ if (dirY < 0) angle += 2 * M_PI;
+ angle /= 2 * M_PI;
+
+ int index = 0, nextIndex = 0;
+ float t = 0;
+
+ if (locationCount > 0) {
+ for (index = locationCount - 1; index >= 0; index--) {
+ if (angle >= locations[index]) {
+ break;
+ }
+ }
+ if (index >= locationCount) index = locationCount - 1;
+ nextIndex = index + 1;
+ if (nextIndex >= locationCount) nextIndex = locationCount - 1;
+ float ld = locations[nextIndex] - locations[index];
+ t = ld <= 0 ? 0 : (angle - locations[index]) / ld;
+ }
+ else {
+ t = angle * (colorCount - 1);
+ index = t;
+ t -= index;
+ nextIndex = index + 1;
+ if (nextIndex >= colorCount) nextIndex = colorCount - 1;
+ }
+
+ int lc = colors[index];
+ int rc = colors[nextIndex];
+ int color = lerp(lc, rc, t);
+ *p++ = color;
+ }
+}
@@ -0,0 +1,48 @@
+//
+// The MIT License (MIT)
+//
+// Copyright (C) 2012 Pavel Ivashkov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+// and associated documentation files (the "Software"), to deal in the Software without restriction,
+// including without limitation the rights to use, copy, modify, merge, publish, distribute,
+// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// AngleGradientLayer.h
+// AngleGradientSample
+//
+// Created by Pavel Ivashkov on 2012-02-12.
+//
+
+#import <QuartzCore/QuartzCore.h>
+
+
+@interface AngleGradientLayer : CALayer
+
+/* The array of CGColorRef objects defining the color of each gradient
+ * stop. Defaults to nil. */
+
+@property(copy) NSArray *colors;
+
+/* An optional array of NSNumber objects defining the location of each
+ * gradient stop as a value in the range [0,1]. The values must be
+ * monotonically increasing. If a nil array is given, the stops are
+ * assumed to spread uniformly across the [0,1] range. When rendered,
+ * the colors are mapped to the output colorspace before being
+ * interpolated. Defaults to nil. */
+
+@property(copy) NSArray *locations;
+
+@end
Oops, something went wrong.

0 comments on commit 7c78b1a

Please sign in to comment.