Support any angle in CPGradient drawInRect:angle:.

This commit is contained in:
Alexander Ljungberg
2012-03-11 19:40:22 +00:00
parent ed1d77c86d
commit 5a0e1d7bb3
7 changed files with 589 additions and 207 deletions
+31 -4
View File
@@ -68,16 +68,43 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
- (void)drawInRect:(CGRect)rect angle:(float)angle
{
if (angle !== 0)
[CPException raise:CPInvalidArgumentException reason:@"angle != 0 not yet implemented"];
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ctx);
CGContextClipToRect(ctx, rect);
CGContextAddRect(ctx, rect);
[self drawFromPoint:rect.origin toPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect)) options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
var startPoint,
endPoint;
// Modulo of negative values doesn't work as expected in JS.
angle = ((angle % 360.0) + 360.0) % 360.0;
if (angle < 90.0)
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
else if (angle < 180.0)
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
else if (angle < 270.0)
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
else
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
// A line segment comes out of the starting point at the given angle, with the first colour
// at the starting point and the last at the end. To do what drawInRect: is supposed to do
// we want the opposite corner of the starting corner to just reach the final colour stop.
// So when the angle isn't a right angle, the segment has to extend beyond the edge of the
// rectangle just far enough. This is hard to describe without a picture but if we place
// another line through the opposite corner at -90 degrees, it'll cross through our
// gradient segment just where it should end and form a right triangle with the right edge.
// of the rect. One leg of this triangle is how far the gradient line should stick out,
// and the length of that leg is (in the first quadrant) width * cos(a) + height * sin(a).
var radians = PI * angle / 180.0,
length = ABS(CGRectGetWidth(rect) * COS(radians)) + ABS(CGRectGetHeight(rect) * SIN(radians));
endPoint = CGPointMake(startPoint.x + length * COS(radians),
startPoint.y + length * SIN(radians));
[self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
CGContextRestoreGState(ctx);
}
+60 -13
View File
@@ -18,6 +18,8 @@
@outlet CustomDrawView gradientView0;
@outlet CustomDrawView gradientView1;
@outlet CustomDrawView gradientView2;
@outlet CustomDrawView gradientView3;
}
- (void)awakeFromCib
@@ -29,6 +31,12 @@
var context = [[CPGraphicsContext currentContext] graphicsPort],
innerRect;
var grad0 = aView == gradientView0,
grad1 = aView == gradientView1,
grad2 = aView == gradientView2,
grad3 = aView == gradientView3,
isGradient = (grad0 || grad1 || grad2 || grad3);
if (aView === view1 || aView === view2)
{
var bounds = [aView bounds],
@@ -64,29 +72,49 @@
innerRect = CPDrawColorTiledRects(bounds, bounds, sides, colors);
}
else if (aView === gradientView0 || aView === gradientView1)
else if (isGradient)
{
var bounds = [aView bounds],
locations,
colors;
colors,
gradient;
if (aView === gradientView0)
if (grad1 || grad3)
{
locations = [0.0, 0.25, 0.50, 0.75, 1.0];
colors = [[CPColor blackColor], [CPColor redColor], [CPColor greenColor], [CPColor blueColor], [CPColor whiteColor]];
// Draw a pattern for the gradient to blend with.
strokeGrid(bounds);
}
if (grad0)
{
var locationsGrad0 = [ 0.0, 0.25, 0.50, 0.75, 1.0 ];
colors = [CPArray arrayWithObjects:[CPColor blackColor], [CPColor redColor], [CPColor greenColor], [CPColor blueColor], [CPColor whiteColor]];
gradient = [[CPGradient alloc] initWithColors:colors atLocations:locationsGrad0 colorSpace:[CPColorSpace sRGBColorSpace]];
[gradient drawInRect:bounds angle:0];
}
else if (grad1)
{
var mainColor = [CPColor orangeColor],
locationsGrad1 = [ 0.0, 0.45, 0.56, 1.0 ];
colors = [CPArray arrayWithObjects:[mainColor colorWithAlphaComponent:0.0], mainColor, mainColor, [mainColor colorWithAlphaComponent:0.0]];
gradient = [[CPGradient alloc] initWithColors:colors atLocations:locationsGrad1 colorSpace:[CPColorSpace sRGBColorSpace]];
[gradient drawInRect:bounds angle:90];
}
else if (grad2)
{
colors = [CPArray arrayWithObjects:[CPColor cyanColor], [CPColor magentaColor], [CPColor yellowColor], [CPColor blackColor]];
gradient = [[CPGradient alloc] initWithColors:colors];
[gradient drawInRect:bounds angle:225];
}
else
{
locations = [0.0, 0.35, 0.66, 1.0];
var mainColor = [CPColor blackColor];
colors = [[mainColor colorWithAlphaComponent:0.0], mainColor, mainColor, [mainColor colorWithAlphaComponent:0.0]];
}
var gradient = [[CPGradient alloc] initWithColors:colors atLocations:locations colorSpace:[CPColorSpace sRGBColorSpace]];
[gradient drawInRect:bounds angle:0];
colors = [CPArray arrayWithObjects:[[CPColor cyanColor] colorWithAlphaComponent:0.5], [CPColor magentaColor], [CPColor clearColor], [CPColor whiteColor]];
gradient = [[CPGradient alloc] initWithColors:colors];
[gradient drawInRect:bounds angle:-20];
}
}
if (!(aView === gradientView0 || aView === gradientView1))
if (!isGradient)
{
CGContextSetFillColor(context, [CPColor colorWithHexString:@"E1EAFF"]);
CGContextFillRect(context, innerRect);
@@ -108,3 +136,22 @@
}
@end
function strokeGrid(/* CGRect */ rect)
{
[CPBezierPath setDefaultLineWidth:1];
[[CPColor whiteColor] setFill];
[[[CPColor blueColor] colorWithAlphaComponent:0.5] setStroke];
var mx = CGRectGetMaxX(rect),
my = CGRectGetMaxY(rect);
[CPBezierPath fillRect:rect];
for (var x = rect.origin.x; x < mx; x += 6)
[CPBezierPath strokeLineFromPoint:CGPointMake(x + 0.5, rect.origin.y + 0.5) toPoint:CGPointMake(x + 0.5, my - 0.5)];
for (var y = rect.origin.y; y < my; y += 6)
[CPBezierPath strokeLineFromPoint:CGPointMake(rect.origin.x + 0.5, y + 0.5) toPoint:CGPointMake(mx - 0.5, y + 0.5)];
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB