forked from mirrors/linphone-iphone
514 lines
No EOL
20 KiB
Objective-C
Executable file
514 lines
No EOL
20 KiB
Objective-C
Executable file
//
|
|
// TUNinePatch.m
|
|
// NinePatch
|
|
//
|
|
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
|
|
//
|
|
|
|
#import "TUNinePatch.h"
|
|
#import "TUVerticalNinePatch.h"
|
|
#import "TUHorizontalNinePatch.h"
|
|
#import "TUFullNinePatch.h"
|
|
#import "UIImage-TUNinePatch.h"
|
|
|
|
@interface TUNinePatch ()
|
|
|
|
@property(nonatomic, retain, readwrite) UIImage *center;
|
|
@property(nonatomic, assign, readwrite) CGRect contentRegion;
|
|
@property(nonatomic, assign, readwrite) BOOL tileCenterVertically;
|
|
@property(nonatomic, assign, readwrite) BOOL tileCenterHorizontally;
|
|
|
|
@end
|
|
|
|
|
|
@implementation TUNinePatch
|
|
|
|
#pragma mark Synthesized Properties
|
|
@synthesize center = _center;
|
|
@synthesize contentRegion = _contentRegion;
|
|
@synthesize tileCenterVertically = _tileCenterVertically;
|
|
@synthesize tileCenterHorizontally = _tileCenterHorizontally;
|
|
|
|
#pragma mark NSCoding
|
|
-(id)initWithCoder:(NSCoder *)coder {
|
|
NPAOInputLog(coder);
|
|
if (self = [super init]) {
|
|
self.center = (UIImage *)[coder decodeObjectForKey:@"center"];
|
|
self.contentRegion = [coder decodeCGRectForKey:@"contentRegion"];
|
|
self.tileCenterVertically = [coder decodeBoolForKey:@"tileCenterVertically"];
|
|
self.tileCenterHorizontally = [coder decodeBoolForKey:@"tileCenterHorizontally"];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)encodeWithCoder:(NSCoder *)coder {
|
|
NPAOInputLog(coder);
|
|
[coder encodeObject:self.center
|
|
forKey:@"center"];
|
|
|
|
[coder encodeCGRect:self.contentRegion
|
|
forKey:@"contentRegion"];
|
|
|
|
[coder encodeBool:self.tileCenterVertically
|
|
forKey:@"tileCenterVertically"];
|
|
|
|
[coder encodeBool:self.tileCenterHorizontally
|
|
forKey:@"tileCenterHorizontally"];
|
|
}
|
|
|
|
#pragma mark NSCopying
|
|
-(id)copyWithZone:(NSZone *)zone {
|
|
return [[[self class] allocWithZone:zone] initWithCenter:self.center
|
|
contentRegion:self.contentRegion
|
|
tileCenterVertically:self.tileCenterVertically
|
|
tileCenterHorizontally:self.tileCenterHorizontally];
|
|
}
|
|
|
|
#pragma mark Init + Dealloc
|
|
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion {
|
|
return [self initWithCenter:center
|
|
contentRegion:contentRegion
|
|
tileCenterVertically:NO
|
|
tileCenterHorizontally:NO];
|
|
}
|
|
|
|
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally {
|
|
NPAInputLog(@"[%@:<0x%x> initWithCenter:%@ contentRegion:%@ tileCenterVertically:%d tileCenterHorizontally:%d]", [self class], ((NSUInteger) self), center, NSStringFromCGRect(contentRegion), tileCenterVertically, tileCenterHorizontally);
|
|
NPParameterAssertNotNilIsKindOfClass(center, UIImage);
|
|
if (self = [super init]) {
|
|
self.center = center;
|
|
self.contentRegion = contentRegion;
|
|
self.tileCenterVertically = tileCenterVertically;
|
|
self.tileCenterHorizontally = tileCenterHorizontally;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma mark -
|
|
-(void)dealloc {
|
|
self.center = nil;
|
|
[super dealloc];
|
|
}
|
|
|
|
#pragma mark Convenience Constructors
|
|
+(id < TUNinePatch >)ninePatchWithNinePatchImage:(UIImage *)ninePatchImage {
|
|
NPAInputLog(@"ninePatchWithNinePatchImage:'%@'",ninePatchImage);
|
|
id < TUNinePatch > outPatch = nil;
|
|
if (ninePatchImage) {
|
|
@try {
|
|
outPatch = [self ninePatchWithImage:[ninePatchImage imageAsNinePatchImage]
|
|
stretchableRegion:[self stretchableRegionOfNinePatchImage:ninePatchImage]
|
|
contentRegion:[self contentRegionOfNinePatchImage:ninePatchImage]
|
|
tileCenterVertically:[self shouldTileCenterVerticallyForNinePatchImage:ninePatchImage]
|
|
tileCenterHorizontally:[self shouldTileCenterHorizontallyForNinePatchImage:ninePatchImage]];
|
|
}
|
|
@catch (NSException * e) {
|
|
NPLogException(e);
|
|
outPatch = nil;
|
|
}
|
|
}
|
|
NPAssertNilOrConformsToProtocol(outPatch,TUNinePatch);
|
|
NPOOutputLog(outPatch);
|
|
return outPatch;
|
|
}
|
|
|
|
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion {
|
|
NPAInputLog(@"ninePatchWithImage:'%@' stretchableRegion:'%@'",image,NSStringFromCGRect(stretchableRegion));
|
|
NPParameterAssertNotNilIsKindOfClass(image,UIImage);
|
|
return [self ninePatchWithImage:image
|
|
stretchableRegion:stretchableRegion
|
|
contentRegion:CGRectZero
|
|
tileCenterVertically:NO
|
|
tileCenterHorizontally:NO];
|
|
}
|
|
|
|
+(id < TUNinePatch >)ninePatchWithImage:(UIImage *)image stretchableRegion:(CGRect)stretchableRegion contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally {
|
|
NPAInputLog(@"ninePatchWithImage:'%@' stretchableRegion:'%@' contentRegion:'%@' tileCenterVertically:'%@' tileCenterHorizontally:'%@'",image,NSStringFromCGRect(stretchableRegion),NSStringFromCGRect(contentRegion),TUYesOrNoString(tileCenterVertically),TUYesOrNoString(tileCenterHorizontally));
|
|
NPParameterAssertNotNilIsKindOfClass(image,UIImage);
|
|
NPParameterAssert(stretchableRegion.origin.x >= 0.0f);
|
|
NPParameterAssert(stretchableRegion.origin.y >= 0.0f);
|
|
NPParameterAssert([image size].width >= stretchableRegion.origin.x + stretchableRegion.size.width);
|
|
NPParameterAssert([image size].height >= stretchableRegion.origin.y + stretchableRegion.size.height);
|
|
id < TUNinePatch > ninePatch = nil;
|
|
if (image) {
|
|
CGFloat imageWidth = [image size].width;
|
|
CGFloat imageHeight = [image size].height;
|
|
CGRect fixedStretchableRegion = stretchableRegion;
|
|
CGFloat stretchableRegionMinX = CGRectGetMinX(fixedStretchableRegion);
|
|
CGFloat stretchableRegionMinY = CGRectGetMinY(fixedStretchableRegion);
|
|
CGFloat stretchableRegionMaxX = CGRectGetMaxX(fixedStretchableRegion);
|
|
CGFloat stretchableRegionMaxY = CGRectGetMaxY(fixedStretchableRegion);
|
|
BOOL stretchesOnLeft = (stretchableRegionMinX > 0.0f)?(YES):(NO);
|
|
BOOL stretchesOnRight = (stretchableRegionMaxX < imageWidth)?(YES):(NO);
|
|
BOOL stretchesOnTop = (stretchableRegionMinY > 0.0f)?(YES):(NO);
|
|
BOOL stretchesOnBottom = (stretchableRegionMaxY < imageHeight)?(YES):(NO);
|
|
BOOL stretchesHorizontally = (stretchesOnLeft || stretchesOnRight)?(YES):(NO);
|
|
BOOL stretchesVertically = (stretchesOnTop || stretchesOnBottom)?(YES):(NO);
|
|
if (stretchesVertically && stretchesHorizontally) {
|
|
LLog(@"...the specified stretchable region stretches horizontally and vertically.");
|
|
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *upperLeftCorner = [image extractUpperLeftCornerForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *upperRightCorner = [image extractUpperRightCornerForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *lowerLeftCorner = [image extractLowerLeftCornerForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *lowerRightCorner = [image extractLowerRightCornerForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *leftEdge = [image extractLeftEdgeForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *rightEdge = [image extractRightEdgeForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *lowerEdge = [image extractLowerEdgeForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *upperEdge = [image extractUpperEdgeForStretchableRegion:fixedStretchableRegion];
|
|
|
|
// Mega-Block of size sanity checking
|
|
|
|
// Given that the only major bug encountered while developing this library
|
|
// proved to be a difficult-to-track-down source of off-by-one errors in
|
|
// the sizes of the slices, you can understand the paranoia here.
|
|
//
|
|
// Just remember to build with the assertion-checking off.
|
|
|
|
NPAssertCorrectSubimageWidthDecomposition(image, upperLeftCorner, upperEdge, upperRightCorner);
|
|
NPAssertCorrectSubimageWidthDecomposition(image, leftEdge, upperEdge, rightEdge);
|
|
NPAssertCorrectSubimageWidthDecomposition(image, lowerLeftCorner, lowerEdge, lowerRightCorner);
|
|
|
|
NPAssertCorrectSubimageHeightDecomposition(image, upperLeftCorner, leftEdge, lowerLeftCorner);
|
|
NPAssertCorrectSubimageHeightDecomposition(image, upperEdge, center, lowerEdge);
|
|
NPAssertCorrectSubimageHeightDecomposition(image, upperRightCorner, rightEdge, lowerRightCorner);
|
|
|
|
NPAssertWithinOne(([upperLeftCorner size].height), ([upperRightCorner size].height));
|
|
NPAssertWithinOne(([upperLeftCorner size].height), ([upperEdge size].height));
|
|
NPAssertWithinOne(([upperEdge size].height), ([upperRightCorner size].height));
|
|
|
|
NPAssertWithinOne(([leftEdge size].height), ([center size].height));
|
|
NPAssertWithinOne(([center size].height), ([rightEdge size].height));
|
|
NPAssertWithinOne(([rightEdge size].height), ([leftEdge size].height));
|
|
|
|
NPAssertWithinOne(([lowerLeftCorner size].height), ([lowerRightCorner size].height));
|
|
NPAssertWithinOne(([lowerRightCorner size].height), ([lowerEdge size].height));
|
|
NPAssertWithinOne(([lowerEdge size].height), ([lowerLeftCorner size].height));
|
|
|
|
NPAssertWithinOne(([upperLeftCorner size].width), ([leftEdge size].width));
|
|
NPAssertWithinOne(([leftEdge size].width), ([lowerLeftCorner size].width));
|
|
NPAssertWithinOne(([upperLeftCorner size].width), ([lowerLeftCorner size].width));
|
|
|
|
NPAssertWithinOne(([upperEdge size].width), ([center size].width));
|
|
NPAssertWithinOne(([center size].width), ([lowerEdge size].width));
|
|
NPAssertWithinOne(([upperEdge size].width), ([lowerEdge size].width));
|
|
|
|
NPAssertWithinOne(([upperRightCorner size].width), ([rightEdge size].width));
|
|
NPAssertWithinOne(([rightEdge size].width), ([lowerRightCorner size].width));
|
|
NPAssertWithinOne(([lowerRightCorner size].width), ([upperRightCorner size].width));
|
|
|
|
ninePatch = [[[TUFullNinePatch alloc] initWithCenter:center
|
|
contentRegion:contentRegion
|
|
tileCenterVertically:tileCenterVertically
|
|
tileCenterHorizontally:tileCenterHorizontally
|
|
upperLeftCorner:upperLeftCorner
|
|
upperRightCorner:upperRightCorner
|
|
lowerLeftCorner:lowerLeftCorner
|
|
lowerRightCorner:lowerRightCorner
|
|
leftEdge:leftEdge
|
|
rightEdge:rightEdge
|
|
upperEdge:upperEdge
|
|
lowerEdge:lowerEdge] autorelease];
|
|
} else if (stretchesVertically) {
|
|
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *upperEdge = [image extractUpperEdgeForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *lowerEdge = [image extractLowerEdgeForStretchableRegion:fixedStretchableRegion];
|
|
|
|
NPAssertCorrectSubimageHeightDecomposition(image,center,upperEdge,lowerEdge);
|
|
NPAssertWithinOne(([center size].width),([upperEdge size].width));
|
|
NPAssertWithinOne(([lowerEdge size].width),([upperEdge size].width));
|
|
NPAssertWithinOne(([center size].width),([lowerEdge size].width));
|
|
|
|
ninePatch = [[[TUVerticalNinePatch alloc] initWithCenter:center
|
|
contentRegion:contentRegion
|
|
tileCenterVertically:tileCenterVertically
|
|
tileCenterHorizontally:tileCenterHorizontally
|
|
upperEdge:upperEdge
|
|
lowerEdge:lowerEdge] autorelease];
|
|
} else if (stretchesHorizontally) {
|
|
UIImage *center = [image extractCenterForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *leftEdge = [image extractLeftEdgeForStretchableRegion:fixedStretchableRegion];
|
|
UIImage *rightEdge = [image extractRightEdgeForStretchableRegion:fixedStretchableRegion];
|
|
|
|
NPAssertCorrectSubimageWidthDecomposition(image, leftEdge, center, rightEdge);
|
|
NPAssertWithinOne(([center size].height),([leftEdge size].height));
|
|
NPAssertWithinOne(([center size].height),([rightEdge size].height));
|
|
NPAssertWithinOne(([leftEdge size].height),([rightEdge size].height));
|
|
|
|
ninePatch = [[[TUHorizontalNinePatch alloc] initWithCenter:center
|
|
contentRegion:contentRegion
|
|
tileCenterVertically:tileCenterVertically
|
|
tileCenterHorizontally:tileCenterHorizontally
|
|
leftEdge:leftEdge
|
|
rightEdge:rightEdge] autorelease];
|
|
} else {
|
|
ninePatch = [[[self alloc] initWithCenter:image
|
|
contentRegion:contentRegion
|
|
tileCenterVertically:tileCenterVertically
|
|
tileCenterHorizontally:tileCenterHorizontally] autorelease];
|
|
}
|
|
}
|
|
NPAssertNilOrConformsToProtocol(ninePatch,TUNinePatch);
|
|
NPOOutputLog(ninePatch);
|
|
return ninePatch;
|
|
}
|
|
|
|
#pragma mark Bundle Loading
|
|
+(id < TUNinePatch >)ninePatchNamed:(NSString *)filename {
|
|
NPParameterAssertNotNilIsKindOfClass(filename,NSString);
|
|
id < TUNinePatch > outPatch = nil;
|
|
if (filename) {
|
|
NSBundle *mainBundle = [NSBundle mainBundle];
|
|
if (mainBundle) {
|
|
NSString *filePath = [mainBundle pathForResource:[NSString stringWithFormat:@"%@.9",filename]
|
|
ofType:@"png"];
|
|
if (filePath) {
|
|
UIImage *ninepatch = [[UIImage alloc] initWithContentsOfFile:filePath];
|
|
if (ninepatch) {
|
|
@try {
|
|
outPatch = [self ninePatchWithNinePatchImage:ninepatch];
|
|
}
|
|
@catch (NSException * e) {
|
|
NPLogException(e);
|
|
outPatch = nil;
|
|
}
|
|
@finally {
|
|
[ninepatch release];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
NPAssertNilOrConformsToProtocol(outPatch,TUNinePatch);
|
|
NPOOutputLog(outPatch);
|
|
return outPatch;
|
|
}
|
|
|
|
#pragma mark Nine Patch Image Manipulation - High Level
|
|
+(CGRect)rectFromHorizontalRange:(NSRange)horizontalRange verticalRange:(NSRange)verticalRange {
|
|
NPAInputLog(@"rectFromHorizontalRange:'%@' verticalRange:'%@'",NSStringFromRange(horizontalRange),NSStringFromRange(verticalRange));
|
|
CGFloat minX = (TUIsNotFoundRange(horizontalRange))?(0.0f):((CGFloat) horizontalRange.location);
|
|
CGFloat width = (TUIsNotFoundRange(horizontalRange))?(0.0f):((CGFloat) horizontalRange.length);
|
|
CGFloat minY = (TUIsNotFoundRange(verticalRange)?(0.0f):((CGFloat) verticalRange.location));
|
|
CGFloat height = (TUIsNotFoundRange(verticalRange)?(0.0f):((CGFloat) verticalRange.length));
|
|
CGRect outRect = CGRectMake(minX,minY,width,height);
|
|
NPCGROutputLog(outRect);
|
|
return outRect;
|
|
}
|
|
|
|
+(CGRect)stretchableRegionOfNinePatchImage:(UIImage *)ninePatchImage {
|
|
NPAInputLog(@"stretchableRegionOfNinePatchImage:'%@'",ninePatchImage);
|
|
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
|
|
CGRect outRect = CGRectZero;
|
|
if (ninePatchImage) {
|
|
outRect = [self rectFromHorizontalRange:[ninePatchImage blackPixelRangeInUpperStrip]
|
|
verticalRange:[ninePatchImage blackPixelRangeInLeftStrip]];
|
|
}
|
|
NPCGROutputLog(outRect);
|
|
return outRect;
|
|
}
|
|
|
|
+(CGRect)contentRegionOfNinePatchImage:(UIImage *)ninePatchImage {
|
|
NPAInputLog(@"contentRegionOfNinePatchImage:'%@'",ninePatchImage);
|
|
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
|
|
CGRect outRect = CGRectZero;
|
|
if (ninePatchImage) {
|
|
outRect = [self rectFromHorizontalRange:[ninePatchImage blackPixelRangeInLowerStrip]
|
|
verticalRange:[ninePatchImage blackPixelRangeInRightStrip]];
|
|
}
|
|
NPCGROutputLog(outRect);
|
|
return outRect;
|
|
}
|
|
|
|
+(BOOL)shouldTileCenterHorizontallyForNinePatchImage:(UIImage *)ninePatchImage {
|
|
NPAInputLog(@"shouldTileCenterHorizontallyForNinePatchImage:'%@'",ninePatchImage);
|
|
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
|
|
BOOL shouldTileCenterHorizontallyForNinePatchImage = NO;
|
|
if (ninePatchImage) {
|
|
shouldTileCenterHorizontallyForNinePatchImage = [ninePatchImage upperLeftCornerIsBlackPixel];
|
|
}
|
|
NPBOutputLog(shouldTileCenterHorizontallyForNinePatchImage);
|
|
return shouldTileCenterHorizontallyForNinePatchImage;
|
|
}
|
|
|
|
+(BOOL)shouldTileCenterVerticallyForNinePatchImage:(UIImage *)ninePatchImage {
|
|
NPAInputLog(@"shouldTileCenterHorizontallyForNinePatchImage:'%@'",ninePatchImage);
|
|
NPParameterAssertNotNilIsKindOfClass(ninePatchImage,UIImage);
|
|
BOOL shouldTileCenterVerticallyForNinePatchImage = NO;
|
|
if (ninePatchImage) {
|
|
shouldTileCenterVerticallyForNinePatchImage = [ninePatchImage lowerLeftCornerIsBlackPixel];
|
|
}
|
|
NPBOutputLog(shouldTileCenterVerticallyForNinePatchImage);
|
|
return shouldTileCenterVerticallyForNinePatchImage;
|
|
}
|
|
|
|
#pragma mark Drawing Utility
|
|
-(void)drawInRect:(CGRect)rect {
|
|
if (self.center) {
|
|
if (self.tileCenterHorizontally && self.tileCenterVertically) {
|
|
[self.center drawAsPatternInRect:rect];
|
|
} else {
|
|
// NB: this behavior is not 100% accurate
|
|
// in that it only works right for tiling on and off
|
|
// half-tiling has to wait
|
|
[self.center drawInRect:rect];
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark Diagnostic Utilities
|
|
-(UIImage *)upperEdge {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)lowerEdge {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)leftEdge {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)rightEdge {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)upperLeftCorner {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)lowerLeftCorner {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)upperRightCorner {
|
|
return nil;
|
|
}
|
|
|
|
-(UIImage *)lowerRightCorner {
|
|
return nil;
|
|
}
|
|
|
|
#pragma mark TUNinePatch Protocol Methods - Drawing
|
|
-(void)inContext:(CGContextRef)context drawAtPoint:(CGPoint)point forContentOfSize:(CGSize)contentSize {
|
|
NPParameterAssert(context != nil);
|
|
NPAInputLog(@"inContext:'%@' drawAtPoint:'%@' forContentOfSize:'%@'",context,NSStringFromCGPoint(point),NSStringFromCGSize(contentSize));
|
|
CGSize size = [self sizeForContentOfSize:contentSize];
|
|
[self inContext:context
|
|
drawInRect:CGRectMake(point.x, point.y, size.width, size.height)];
|
|
}
|
|
|
|
-(void)inContext:(CGContextRef)context drawCenteredInRect:(CGRect)rect forContentOfSize:(CGSize)contentSize {
|
|
NPParameterAssert(context != nil);
|
|
NPAInputLog(@"inContext:'%@' drawCenteredInRect:'%@' forContentOfSize:'%@'",context,NSStringFromCGRect(rect),NSStringFromCGSize(contentSize));
|
|
CGSize size = [self sizeForContentOfSize:contentSize];
|
|
CGFloat xStart = floorf((CGRectGetWidth(rect) - size.width) * 0.5f);
|
|
CGFloat yStart = floorf((CGRectGetHeight(rect) - size.height) * 0.5f);
|
|
[self inContext:context
|
|
drawInRect:CGRectMake(xStart, yStart, size.width, size.height)];
|
|
}
|
|
|
|
-(void)inContext:(CGContextRef)context drawInRect:(CGRect)rect {
|
|
if (context) {
|
|
CGContextSaveGState(context);
|
|
CGContextBeginTransparencyLayer(context, nil);
|
|
@try {
|
|
[self drawInRect:rect];
|
|
}
|
|
@catch (NSException * e) {
|
|
NPLogException(e);
|
|
}
|
|
@finally {
|
|
CGContextEndTransparencyLayer(context);
|
|
CGContextRestoreGState(context);
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark TUNinePatch Protocol Methods - Image Construction
|
|
-(UIImage *)imageOfSize:(CGSize)size {
|
|
UIImage *image = nil;
|
|
UIGraphicsBeginImageContext(size);
|
|
[self drawInRect:CGRectMake(0.0f,0.0f,size.width,size.height)];
|
|
image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
return image;
|
|
}
|
|
|
|
#pragma mark TUNinePatch Protocol Methods - Sizing
|
|
-(BOOL)stretchesHorizontally {
|
|
return YES;
|
|
}
|
|
|
|
-(BOOL)stretchesVertically {
|
|
return YES;
|
|
}
|
|
|
|
#pragma mark -
|
|
-(CGFloat)minimumWidth {
|
|
CGFloat minimumWidth = 0.0f;
|
|
if (self.center) {
|
|
minimumWidth = [self.center size].width + self.rightEdgeWidth + self.leftEdgeWidth;
|
|
}
|
|
return minimumWidth;
|
|
}
|
|
|
|
-(CGFloat)minimumHeight {
|
|
CGFloat minimumHeight = 0.0f;
|
|
if (self.center) {
|
|
minimumHeight = [self.center size].height + self.upperEdgeHeight + self.lowerEdgeHeight;
|
|
}
|
|
return minimumHeight;
|
|
}
|
|
|
|
-(CGSize)minimumSize {
|
|
return CGSizeMake([self minimumWidth], [self minimumHeight]);
|
|
}
|
|
|
|
-(CGSize)sizeForContentOfSize:(CGSize)contentSize {
|
|
CGSize outSize = [self minimumSize];
|
|
CGFloat contentRegionWidth = CGRectGetWidth(self.contentRegion);
|
|
CGFloat contentRegionHeight = CGRectGetHeight(self.contentRegion);
|
|
if ((contentRegionWidth > 0.0f) || (contentRegionHeight > 0.0f)) {
|
|
// WE HAVE CONTENT REGION
|
|
outSize.width += (contentSize.width > contentRegionWidth)?(contentSize.width - contentRegionWidth):(0.0f);
|
|
outSize.height += (contentSize.height > contentRegionHeight)?(contentSize.height - contentRegionHeight):(0.0f);
|
|
} else {
|
|
// WE ONLY NEED A SIMPLE "WHICH IS BIGGER?" CHECK
|
|
outSize.width = (contentSize.width > outSize.width)?(contentSize.width):(outSize.width);
|
|
outSize.height = (contentSize.height > outSize.height)?(contentSize.height):(outSize.height);
|
|
}
|
|
return outSize;
|
|
}
|
|
|
|
-(CGPoint)upperLeftCornerForContentWhenDrawnAtPoint:(CGPoint)point {
|
|
return CGPointMake(point.x + CGRectGetMinX(self.contentRegion), point.y + CGRectGetMinY(self.contentRegion));
|
|
}
|
|
|
|
#pragma mark TUNinePatch Protocol Methods - Geometry
|
|
-(CGFloat)leftEdgeWidth {
|
|
return 0.0f;
|
|
}
|
|
|
|
-(CGFloat)rightEdgeWidth {
|
|
return 0.0f;
|
|
}
|
|
|
|
-(CGFloat)upperEdgeHeight {
|
|
return 0.0f;
|
|
}
|
|
|
|
-(CGFloat)lowerEdgeHeight {
|
|
return 0.0f;
|
|
}
|
|
|
|
#pragma mark Customized Description
|
|
-(NSString *)description {
|
|
return [NSString stringWithFormat:@"<%@>:( %@ )",[super description],[self descriptionPostfix]];
|
|
}
|
|
|
|
-(NSString *)descriptionPostfix {
|
|
return [NSString stringWithFormat:@"center:<'%@'>, contentRegion:<'%@'>", self.center, NSStringFromCGRect(self.contentRegion)];
|
|
}
|
|
|
|
|
|
@end |