diff options
author | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2009-03-16 14:30:25 +0000 |
---|---|---|
committer | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2009-03-16 14:30:25 +0000 |
commit | 1c1c70beb8fcba6bbcb3f6ca58215e646dca7888 (patch) | |
tree | e1c780c73efa2e6b439adb039da774d4730eb91b | |
parent | f14883b92b7df63f9b7c368d138a551c75c8c977 (diff) |
[Author: avi]
Add ability to create rounded rects with different radii for different corners.
R=dmaclach
-rw-r--r-- | AppKit/GTMNSBezierPath+RoundRect.h | 25 | ||||
-rw-r--r-- | AppKit/GTMNSBezierPath+RoundRect.m | 85 | ||||
-rw-r--r-- | AppKit/GTMNSBezierPath+RoundRectTest.m | 14 | ||||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff | bin | 10728 -> 11788 bytes | |||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff | bin | 10724 -> 11788 bytes | |||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff | bin | 10728 -> 11788 bytes |
6 files changed, 96 insertions, 28 deletions
diff --git a/AppKit/GTMNSBezierPath+RoundRect.h b/AppKit/GTMNSBezierPath+RoundRect.h index b0b48de..25f4605 100644 --- a/AppKit/GTMNSBezierPath+RoundRect.h +++ b/AppKit/GTMNSBezierPath+RoundRect.h @@ -37,6 +37,20 @@ + (NSBezierPath *)gtm_bezierPathWithRoundRect:(NSRect)rect cornerRadius:(CGFloat)radius; +/// Inscribe a round rectangle inside of rectangle |rect| with corner radii specified +// +// Args: +// rect: outer rectangle to inscribe into +// radius*: radii of the corners +// +// Returns: +// Auto released NSBezierPath ++ (NSBezierPath *)gtm_bezierPathWithRoundRect:(NSRect)rect + topLeftCornerRadius:(CGFloat)radiusTL + topRightCornerRadius:(CGFloat)radiusTR + bottomLeftCornerRadius:(CGFloat)radiusBL + bottomRightCornerRadius:(CGFloat)radiusBR; + /// Adds a path which is a round rectangle inscribed inside of rectangle |rect| with a corner radius of |radius| // // Args: @@ -45,4 +59,15 @@ // to be no larger than the smaller of half |rect|'s width or height - (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect cornerRadius:(CGFloat)radius; + +/// Adds a path which is a round rectangle inscribed inside of rectangle |rect| with a corner radii specified +// +// Args: +// rect: outer rectangle to inscribe into +// radius*: radii of the corners +- (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect + topLeftCornerRadius:(CGFloat)radiusTL + topRightCornerRadius:(CGFloat)radiusTR + bottomLeftCornerRadius:(CGFloat)radiusBL + bottomRightCornerRadius:(CGFloat)radiusBR; @end diff --git a/AppKit/GTMNSBezierPath+RoundRect.m b/AppKit/GTMNSBezierPath+RoundRect.m index d4e5050..806bd94 100644 --- a/AppKit/GTMNSBezierPath+RoundRect.m +++ b/AppKit/GTMNSBezierPath+RoundRect.m @@ -31,36 +31,69 @@ return bezier; } ++ (NSBezierPath *)gtm_bezierPathWithRoundRect:(NSRect)rect + topLeftCornerRadius:(CGFloat)radiusTL + topRightCornerRadius:(CGFloat)radiusTR + bottomLeftCornerRadius:(CGFloat)radiusBL + bottomRightCornerRadius:(CGFloat)radiusBR { + NSBezierPath *bezier = [NSBezierPath bezierPath]; + [bezier gtm_appendBezierPathWithRoundRect:rect + topLeftCornerRadius:radiusTL + topRightCornerRadius:radiusTR + bottomLeftCornerRadius:radiusBL + bottomRightCornerRadius:radiusBR]; + return bezier; +} - (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect cornerRadius:(CGFloat)radius { + if (radius > 0.0) { + // Clamp radius to be no larger than half the rect's width or height. + radius = MIN(radius, 0.5 * MIN(rect.size.width, rect.size.height)); + + [self gtm_appendBezierPathWithRoundRect:rect + topLeftCornerRadius:radius + topRightCornerRadius:radius + bottomLeftCornerRadius:radius + bottomRightCornerRadius:radius]; + } else { + // When radius <= 0.0, use plain rectangle. + [self appendBezierPathWithRect:rect]; + } +} + +- (void)gtm_appendBezierPathWithRoundRect:(NSRect)rect + topLeftCornerRadius:(CGFloat)radiusTL + topRightCornerRadius:(CGFloat)radiusTR + bottomLeftCornerRadius:(CGFloat)radiusBL + bottomRightCornerRadius:(CGFloat)radiusBR { + // Clamp radii to be at least zero. I'd like to clamp both TL+TR and BL+BR to + // be less than the width and TL+BL and TR+BR to be less than the height, but + // what to do if they're not? Do we scale them both evenly? + radiusTL = MAX(0, radiusTL); + radiusTR = MAX(0, radiusTR); + radiusBL = MAX(0, radiusBL); + radiusBR = MAX(0, radiusBR); + if (!NSIsEmptyRect(rect)) { - if (radius > 0.0) { - // Clamp radius to be no larger than half the rect's width or height. - radius = MIN(radius, 0.5 * MIN(rect.size.width, rect.size.height)); - - NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); - NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); - NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); - - [self moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))]; - [self appendBezierPathWithArcFromPoint:topLeft - toPoint:rect.origin - radius:radius]; - [self appendBezierPathWithArcFromPoint:rect.origin - toPoint:bottomRight - radius:radius]; - [self appendBezierPathWithArcFromPoint:bottomRight - toPoint:topRight - radius:radius]; - [self appendBezierPathWithArcFromPoint:topRight - toPoint:topLeft - radius:radius]; - [self closePath]; - } else { - // When radius <= 0.0, use plain rectangle. - [self appendBezierPathWithRect:rect]; - } + NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); + NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); + NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); + + [self moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))]; + [self appendBezierPathWithArcFromPoint:topLeft + toPoint:rect.origin + radius:radiusTL]; + [self appendBezierPathWithArcFromPoint:rect.origin + toPoint:bottomRight + radius:radiusBL]; + [self appendBezierPathWithArcFromPoint:bottomRight + toPoint:topRight + radius:radiusBR]; + [self appendBezierPathWithArcFromPoint:topRight + toPoint:topLeft + radius:radiusTR]; + [self closePath]; } } diff --git a/AppKit/GTMNSBezierPath+RoundRectTest.m b/AppKit/GTMNSBezierPath+RoundRectTest.m index 5bdf3a3..101460c 100644 --- a/AppKit/GTMNSBezierPath+RoundRectTest.m +++ b/AppKit/GTMNSBezierPath+RoundRectTest.m @@ -28,7 +28,7 @@ @implementation GTMNSBezierPath_RoundRectTest - (void)testRoundRects { - GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(490, 430), + GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(490, 500), @"GTMNSBezierPath+RoundRectTest", nil, nil); } @@ -95,7 +95,17 @@ [roundRect stroke]; theRects[j].origin.y += 35.0; } - } + } + + // Different radii + NSRect bigRect = NSMakeRect(50, 440, 200, 40); + NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:bigRect + topLeftCornerRadius:0.0 + topRightCornerRadius:5.0 + bottomLeftCornerRadius:10.0 + bottomRightCornerRadius:20.0]; + [roundRect setLineWidth:5.0]; + [roundRect stroke]; } diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff Binary files differindex ef22b6b..6e89cc1 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff Binary files differindex b165acf..6e89cc1 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff Binary files differindex ef22b6b..6e89cc1 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff |