linphone-ios/Classes/Utils/NinePatch/TUFullNinePatch.m
2012-07-27 15:17:01 +02:00

318 lines
No EOL
12 KiB
Objective-C
Executable file

//
// TUFullNinePatch.m
// NinePatch
//
// Copyright 2009 Tortuga 22, Inc. All rights reserved.
//
#import "TUFullNinePatch.h"
#import "TUNinePatchProtocols.h"
#import "UIImage-TUNinePatch.h"
@interface TUFullNinePatch ()
// Synthesized Properties
@property(nonatomic, retain, readwrite) UIImage *upperEdge;
@property(nonatomic, retain, readwrite) UIImage *lowerEdge;
@property(nonatomic, retain, readwrite) UIImage *leftEdge;
@property(nonatomic, retain, readwrite) UIImage *rightEdge;
@property(nonatomic, retain, readwrite) UIImage *upperLeftCorner;
@property(nonatomic, retain, readwrite) UIImage *lowerLeftCorner;
@property(nonatomic, retain, readwrite) UIImage *upperRightCorner;
@property(nonatomic, retain, readwrite) UIImage *lowerRightCorner;
@end
@implementation TUFullNinePatch
#pragma mark Synthesized Properties
@synthesize upperEdge = _upperEdge;
@synthesize lowerEdge = _lowerEdge;
@synthesize leftEdge = _leftEdge;
@synthesize rightEdge = _rightEdge;
@synthesize upperLeftCorner = _upperLeftCorner;
@synthesize lowerLeftCorner = _lowerLeftCorner;
@synthesize upperRightCorner = _upperRightCorner;
@synthesize lowerRightCorner = _lowerRightCorner;
#pragma mark NSCoding
-(id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
self.upperEdge = (UIImage *) [coder decodeObjectForKey:@"upperEdge"];
self.lowerEdge = (UIImage *) [coder decodeObjectForKey:@"lowerEdge"];
self.leftEdge = (UIImage *) [coder decodeObjectForKey:@"leftEdge"];
self.rightEdge = (UIImage *) [coder decodeObjectForKey:@"rightEdge"];
self.upperLeftCorner = (UIImage *) [coder decodeObjectForKey:@"upperLeftCorner"];
self.lowerLeftCorner = (UIImage *) [coder decodeObjectForKey:@"lowerLeftCorner"];
self.upperRightCorner = (UIImage *) [coder decodeObjectForKey:@"upperRightCorner"];
self.lowerRightCorner = (UIImage *) [coder decodeObjectForKey:@"lowerRightCorner"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeObject:self.upperEdge
forKey:@"upperEdge"];
[coder encodeObject:self.lowerEdge
forKey:@"lowerEdge"];
[coder encodeObject:self.leftEdge
forKey:@"leftEdge"];
[coder encodeObject:self.rightEdge
forKey:@"rightEdge"];
[coder encodeObject:self.upperLeftCorner
forKey:@"upperLeftCorner"];
[coder encodeObject:self.lowerLeftCorner
forKey:@"lowerLeftCorner"];
[coder encodeObject:self.upperRightCorner
forKey:@"upperRightCorner"];
[coder encodeObject:self.lowerRightCorner
forKey:@"lowerRightCorner"];
}
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithCenter:self.center
contentRegion:self.contentRegion
tileCenterVertically:self.tileCenterVertically
tileCenterHorizontally:self.tileCenterHorizontally
upperLeftCorner:self.upperLeftCorner
upperRightCorner:self.upperRightCorner
lowerLeftCorner:self.lowerLeftCorner
lowerRightCorner:self.lowerRightCorner
leftEdge:self.leftEdge
rightEdge:self.rightEdge
upperEdge:self.upperEdge
lowerEdge:self.lowerEdge];
}
#pragma mark Init + Dealloc
-(id)initWithCenter:(UIImage *)center contentRegion:(CGRect)contentRegion tileCenterVertically:(BOOL)tileCenterVertically tileCenterHorizontally:(BOOL)tileCenterHorizontally upperLeftCorner:(UIImage *)upperLeftCorner upperRightCorner:(UIImage *)upperRightCorner lowerLeftCorner:(UIImage *)lowerLeftCorner lowerRightCorner:(UIImage *)lowerRightCorner leftEdge:(UIImage *)leftEdge rightEdge:(UIImage *)rightEdge upperEdge:(UIImage *)upperEdge lowerEdge:(UIImage *)lowerEdge {
NPParameterAssertNotNilIsKindOfClass(upperLeftCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerLeftCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(upperRightCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerRightCorner,UIImage);
NPParameterAssertNotNilIsKindOfClass(leftEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(rightEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(upperEdge,UIImage);
NPParameterAssertNotNilIsKindOfClass(lowerEdge,UIImage);
if (self = [super initWithCenter:center
contentRegion:contentRegion
tileCenterVertically:tileCenterVertically
tileCenterHorizontally:tileCenterHorizontally]) {
self.upperEdge = upperEdge;
self.lowerEdge = lowerEdge;
self.leftEdge = leftEdge;
self.rightEdge = rightEdge;
self.upperLeftCorner = upperLeftCorner;
self.lowerLeftCorner = lowerLeftCorner;
self.upperRightCorner = upperRightCorner;
self.lowerRightCorner = lowerRightCorner;
}
return self;
}
#pragma mark
-(void)dealloc {
self.upperEdge = nil;
self.lowerEdge = nil;
self.leftEdge = nil;
self.rightEdge = nil;
self.upperLeftCorner = nil;
self.lowerLeftCorner = nil;
self.upperRightCorner = nil;
self.lowerRightCorner = nil;
[super dealloc];
}
#pragma mark Sanity-Checking Tools
-(BOOL)checkSizeSanityAgainstOriginalImage:(UIImage *)originalImage {
CGSize os = [originalImage size];
CGFloat ow = os.width;
CGFloat oh = os.height;
CGFloat tr = ([[self upperEdge] size].width + [[self upperLeftCorner] size].width + [[self upperRightCorner] size].width);
CGFloat mr = ([[self center] size].width + [[self leftEdge] size].width + [[self rightEdge] size].width);
CGFloat lr = ([[self lowerEdge] size].width + [[self lowerLeftCorner] size].width + [[self lowerRightCorner] size].width);
BOOL topRow = TUWithinEpsilon(1.0f,ow,tr);
BOOL midRow = TUWithinEpsilon(1.0f,ow,mr);
BOOL lowRow = TUWithinEpsilon(1.0f,ow,lr);
CGFloat lc = ([[self upperLeftCorner] size].height + [[self lowerLeftCorner] size].height + [[self leftEdge] size].height);
CGFloat mc = ([[self center] size].height + [[self upperEdge] size].height + [[self lowerEdge] size].height);
CGFloat rc = ([[self upperRightCorner] size].height + [[self lowerRightCorner] size].height + [[self rightEdge] size].height);
BOOL lCol = TUWithinEpsilon(1.0f,oh,lc);
BOOL mCol = TUWithinEpsilon(1.0f,oh,mc);
BOOL rCol = TUWithinEpsilon(1.0f,oh,rc);
BOOL sizesMatch = TUForceYesOrNo(midRow && topRow && lowRow && mCol && lCol && rCol);
DLog(@"SANITY sizesMatch: '%@.'",TUYesOrNoString(sizesMatch));
DLog(@"SANITY topRow: '%@', midRow:'%@, lowRow:'%@'.", TUYesOrNoString(topRow),TUYesOrNoString(midRow),TUYesOrNoString(lowRow));
DLog(@"SANITY lCol: '%@', mCol:'%@, rCol:'%@'.", TUYesOrNoString(lCol),TUYesOrNoString(mCol),TUYesOrNoString(rCol));
DLog(@"SANITY <ow: '%.1f', tr: '%.1f', mr: '%.1f', lr: '%.1f'>",ow,tr,mr,lr);
DLog(@"SANITY <oh: '%.1f', lc: '%.1f', mc: '%.1f', lc: '%.1f'>",oh,lc,mc,rc);
return sizesMatch;
}
#pragma mark TUNinePatch Overrides
-(void)drawInRect:(CGRect)rect {
NPSelfProperty(center);
NPSelfProperty(leftEdge);
NPSelfProperty(rightEdge);
NPSelfProperty(lowerEdge);
NPSelfProperty(upperEdge);
NPSelfProperty(upperLeftCorner);
NPSelfProperty(upperRightCorner);
NPSelfProperty(lowerLeftCorner);
NPSelfProperty(lowerRightCorner);
CGFloat leftEdgeWidth = [self leftEdgeWidth];
CGFloat rightEdgeWidth = [self rightEdgeWidth];
BOOL hasLeftEdge = (leftEdgeWidth > 0.0f)?(YES):(NO);
BOOL hasRightEdge = (rightEdgeWidth > 0.0f)?(YES):(NO);
CGFloat upperEdgeHeight = [self upperEdgeHeight];
CGFloat lowerEdgeHeight = [self lowerEdgeHeight];
BOOL hasUpperEdge = (upperEdgeHeight > 0.0f)?(YES):(NO);
BOOL hasLowerEdge = (lowerEdgeHeight > 0.0f)?(YES):(NO);
BOOL hasUpperLeftCorner = (hasLeftEdge && hasUpperEdge)?(YES):(NO);
BOOL hasUpperRightCorner = (hasRightEdge && hasUpperEdge)?(YES):(NO);
BOOL hasLowerLeftCorner = (hasLeftEdge && hasLowerEdge)?(YES):(NO);
BOOL hasLowerRightCorner = (hasRightEdge && hasLowerEdge)?(YES):(NO);
CGFloat contentWidth = TUTruncateAtZero(rect.size.width - (leftEdgeWidth + rightEdgeWidth));
CGFloat contentHeight = TUTruncateAtZero(rect.size.height - (upperEdgeHeight + lowerEdgeHeight));
BOOL hasContentWidth = (contentWidth > 0.0f)?(YES):(NO);
BOOL hasContentHeight = (contentWidth > 0.0f)?(YES):(NO);
if (hasContentWidth && hasContentHeight) {
[self.center drawInRect:CGRectMake(CGRectGetMinX(rect) + leftEdgeWidth, CGRectGetMinY(rect) + upperEdgeHeight, contentWidth, contentHeight)];
}
if (hasContentWidth) {
if (hasUpperEdge) {
[self.upperEdge drawInRect:CGRectMake(
CGRectGetMinX(rect) + leftEdgeWidth,
CGRectGetMinY(rect),
contentWidth,
upperEdgeHeight)];
}
if (hasLowerEdge) {
[self.lowerEdge drawInRect:CGRectMake(
CGRectGetMinX(rect) + leftEdgeWidth,
CGRectGetMaxY(rect) - lowerEdgeHeight,
contentWidth,
lowerEdgeHeight)];
}
}
if (hasContentHeight) {
if (hasLeftEdge) {
[self.leftEdge drawInRect:CGRectMake(
CGRectGetMinX(rect),
CGRectGetMinY(rect) + upperEdgeHeight,
leftEdgeWidth,
contentHeight)];
}
if (hasRightEdge) {
[self.rightEdge drawInRect:CGRectMake(
CGRectGetMaxX(rect) - rightEdgeWidth,
CGRectGetMinY(rect) + upperEdgeHeight,
rightEdgeWidth,
contentHeight)];
}
}
if (hasUpperLeftCorner && self.upperLeftCorner) {
[self.upperLeftCorner drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))];
}
if (hasUpperRightCorner && self.upperRightCorner) {
[self.upperRightCorner drawAtPoint:CGPointMake(CGRectGetMaxX(rect) - rightEdgeWidth, CGRectGetMinY(rect))];
}
if (hasLowerLeftCorner && self.lowerLeftCorner) {
[self.lowerLeftCorner drawAtPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect) - lowerEdgeHeight)];
}
if (hasLowerRightCorner && self.lowerRightCorner) {
[self.lowerRightCorner drawAtPoint:CGPointMake(CGRectGetMaxX(rect) - rightEdgeWidth, CGRectGetMaxY(rect) - lowerEdgeHeight)];
}
}
#pragma mark -
-(CGFloat)leftEdgeWidth {
return ((self.upperLeftCorner)?
([self.upperLeftCorner size].width):
(((self.lowerLeftCorner)?
([self.lowerLeftCorner size].width):(0.0f))));
}
-(CGFloat)rightEdgeWidth {
return ((self.upperRightCorner)?
([self.upperRightCorner size].width)
:(((self.lowerRightCorner)?
([self.lowerRightCorner size].width):(0.0f))));
}
-(CGFloat)upperEdgeHeight {
return ((self.upperLeftCorner)?
([self.upperLeftCorner size].height)
:(((self.upperRightCorner)?
([self.upperRightCorner size].height):(0.0f))));
}
-(CGFloat)lowerEdgeHeight {
return ((self.lowerLeftCorner)?
([self.lowerLeftCorner size].height)
:(((self.lowerRightCorner)?
([self.lowerRightCorner size].height):(0.0f))));
}
#pragma mark Customized Description Overrides
-(NSString *)descriptionPostfix {
return [NSString stringWithFormat:@"%@, self.upperEdge:<'%@'>, self.lowerEdge:<'%@'>, self.leftEdge:<'%@'>, self.rightEdge:<'%@'>, self.upperLeftCorner:<'%@'>, self.lowerLeftCorner:<'%@'>, self.upperRightCorner:<'%@'>, self.lowerRightCorner:<'%@'>",
[super descriptionPostfix],
self.upperEdge,
self.lowerEdge,
self.leftEdge,
self.rightEdge,
self.upperLeftCorner,
self.lowerLeftCorner,
self.upperRightCorner,
self.lowerRightCorner];
}
#pragma mark Image Logging
-(void)logExplodedImage {
CGFloat centerWidth = ((self.center)?(self.center.size.width):(0.0f));
CGFloat centerHeight = ((self.center)?(self.center.size.height):(0.0f));
CGSize mySize = CGSizeMake(
4.0f + (centerWidth + ([self leftEdgeWidth]) + ([self rightEdgeWidth])),
4.0f + (centerHeight + ([self upperEdgeHeight]) + ([self lowerEdgeHeight]))
);
UIGraphicsBeginImageContext(mySize);
[self.center drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 2.0f + [self upperEdgeHeight])];
[self.upperLeftCorner drawAtPoint:CGPointMake(0.0f, 0.0f)];
[self.leftEdge drawAtPoint:CGPointMake(0.0f, [self upperEdgeHeight] + 2.0f)];
[self.lowerLeftCorner drawAtPoint:CGPointMake(0.0f, [self upperEdgeHeight] + 4.0f + centerHeight)];
[self.upperEdge drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 0.0f)];
[self.upperRightCorner drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 0.0f)];
[self.rightEdge drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 2.0f + [self upperEdgeHeight])];
[self.lowerRightCorner drawAtPoint:CGPointMake(4.0f + [self leftEdgeWidth] + centerWidth, 4.0f + [self upperEdgeHeight] + centerHeight)];
[self.lowerEdge drawAtPoint:CGPointMake(2.0f + [self leftEdgeWidth], 4.0f + [self upperEdgeHeight] + centerHeight)];
IMLog(UIGraphicsGetImageFromCurrentImageContext(), @"explodedNinePatchImage");
UIGraphicsEndImageContext();
}
@end