Skip to content

Instantly share code, notes, and snippets.

@cypres
Created February 8, 2012 14:27
Show Gist options
  • Save cypres/1769953 to your computer and use it in GitHub Desktop.
Save cypres/1769953 to your computer and use it in GitHub Desktop.
advanced manual 9 patching
//
// RedButton.h
// SkidtApp
//
// Created by Hans Duedal on 2/8/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RedButton : UIButton
@property (strong, nonatomic) UIImage *icon;
@end
//
// RedButton.m
// SkidtApp
//
// Created by Hans Duedal on 2/8/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "RedButton.h"
@implementation RedButton
/*
* Set up some constants
*/
static int leftCapWidth = 48;
static int rightCapWidth = 40;
static int topHeight = 11;
static int bottomHeight = 11;
// top/bottom repeat section
static int imageTopHeight = 23;
static int imageBottomHeight = 23;
static int imageSampleSize = 1;
// icon
static int iconIndent = 10;
static int iconSize = 32;
// title
static int titleTopMargin = -2;
static int titleLeftMargin = 5;
@synthesize icon;
-(void) awakeFromNib {
[self setBackgroundImage:nil forState:UIControlStateNormal];
UILabel *title = [self titleLabel];
[title setFont:[UIFont fontWithName:@"Dispatch Bold" size:[[title font] pointSize]]];
// Quickly remove icon to prevent "flash of unstyled content"
icon = [self imageForState:UIControlStateNormal];
[self setImage:nil forState:UIControlStateNormal];
// Title
[self setTitleEdgeInsets:UIEdgeInsetsMake(topHeight+titleTopMargin, leftCapWidth+titleLeftMargin, bottomHeight, rightCapWidth)];
}
/*
* Override drawRect to draw a scalable version of the button.
* Since this button requires multiple scalable areas it can't use the built-in features and must be drawn with Quartz 2D
* The drawing works by samling 15 different images, 5 for each of the 3 scalable areas of the button, which is then drawn.
*/
-(void) drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect bounds = [self bounds];
CGImageRef background = [[UIImage imageNamed:@"button.png"] CGImage];
// center section
int centerHeight = CGImageGetHeight(background)-imageTopHeight-imageBottomHeight-imageSampleSize-imageSampleSize;
// common calculations
int imageLowerY = CGImageGetHeight(background)-imageBottomHeight;
int imageRightX = CGImageGetWidth(background)-rightCapWidth*2;
/*
* Image sampling from source image
* Assume retina image so *2 coordinates
*/
// Stretch area
CGImageRef topPart = CGImageCreateWithImageInRect(background, CGRectMake(leftCapWidth*2, 0, imageSampleSize, imageTopHeight));
CGImageRef bottomPart = CGImageCreateWithImageInRect(background, CGRectMake(leftCapWidth*2, imageLowerY, imageSampleSize, imageBottomHeight));
CGImageRef upperstretch = CGImageCreateWithImageInRect(background, CGRectMake(leftCapWidth*2, imageTopHeight, imageSampleSize, imageSampleSize));
CGImageRef lowerstretch = CGImageCreateWithImageInRect(background, CGRectMake(leftCapWidth*2, imageLowerY-imageSampleSize, imageSampleSize, imageSampleSize));
CGImageRef centerPart = CGImageCreateWithImageInRect(background, CGRectMake(leftCapWidth*2, imageTopHeight, imageSampleSize, centerHeight));
// Right endcap
CGImageRef rightTop = CGImageCreateWithImageInRect(background, CGRectMake(imageRightX, 0, rightCapWidth*2, imageTopHeight));
CGImageRef rightBottom = CGImageCreateWithImageInRect(background, CGRectMake(imageRightX, imageLowerY, rightCapWidth*2, imageBottomHeight));
CGImageRef rightUpper = CGImageCreateWithImageInRect(background, CGRectMake(imageRightX, imageTopHeight, rightCapWidth*2, imageSampleSize));
CGImageRef rightLower = CGImageCreateWithImageInRect(background, CGRectMake(imageRightX, imageLowerY, rightCapWidth*2, imageSampleSize));
CGImageRef rightCenter = CGImageCreateWithImageInRect(background, CGRectMake(imageRightX, imageTopHeight, rightCapWidth*2, centerHeight));
// Left endcap
CGImageRef leftTop = CGImageCreateWithImageInRect(background, CGRectMake(0, 0, leftCapWidth*2, imageTopHeight));
CGImageRef leftBottom = CGImageCreateWithImageInRect(background, CGRectMake(0, imageLowerY, leftCapWidth*2, imageBottomHeight));
CGImageRef leftUpper = CGImageCreateWithImageInRect(background, CGRectMake(0, imageTopHeight, leftCapWidth*2, imageSampleSize));
CGImageRef leftLower = CGImageCreateWithImageInRect(background, CGRectMake(0, imageLowerY, leftCapWidth*2, imageSampleSize));
CGImageRef leftCenter = CGImageCreateWithImageInRect(background, CGRectMake(0, imageTopHeight, leftCapWidth*2, centerHeight));
/*
* Drawing
*/
// Fix flipped-y of Quartz 2D lib
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, CGRectGetHeight(bounds));
CGContextScaleCTM(context, 1.0, -1.0);
// Stretch area
CGRect stretchBounds = CGRectMake(leftCapWidth, 0, CGRectGetWidth(bounds)-leftCapWidth-rightCapWidth, CGRectGetHeight(bounds));
CGFloat center = CGRectGetMidY(bounds);
CGFloat minX = CGRectGetMinX(stretchBounds);
CGContextDrawImage(context, CGRectMake(minX, CGRectGetHeight(bounds)-topHeight, CGRectGetWidth(stretchBounds), topHeight), topPart);
CGContextDrawImage(context, CGRectMake(minX, 0, CGRectGetWidth(stretchBounds), bottomHeight), bottomPart);
CGContextDrawImage(context, CGRectMake(minX, center, CGRectGetWidth(stretchBounds), CGRectGetHeight(bounds)-topHeight-center), upperstretch);
CGContextDrawImage(context, CGRectMake(minX, bottomHeight, CGRectGetWidth(stretchBounds), center-bottomHeight), lowerstretch);
CGContextDrawImage(context, CGRectMake(minX, center-centerHeight/4, CGRectGetWidth(stretchBounds), centerHeight/2), centerPart);
// Right endcap
CGFloat maxX = CGRectGetMaxX(stretchBounds);
CGContextDrawImage(context, CGRectMake(maxX, CGRectGetHeight(bounds)-topHeight, rightCapWidth, topHeight), rightTop);
CGContextDrawImage(context, CGRectMake(maxX, 0, rightCapWidth, bottomHeight), rightBottom);
CGContextDrawImage(context, CGRectMake(maxX, center, rightCapWidth, CGRectGetHeight(bounds)-topHeight-center), rightUpper);
CGContextDrawImage(context, CGRectMake(maxX, bottomHeight, rightCapWidth, center-bottomHeight), rightLower);
CGContextDrawImage(context, CGRectMake(maxX, center-centerHeight/4, rightCapWidth, centerHeight/2), rightCenter);
// Left endcap
CGContextDrawImage(context, CGRectMake(0, CGRectGetHeight(bounds)-topHeight, leftCapWidth, topHeight), leftTop);
CGContextDrawImage(context, CGRectMake(0, 0, leftCapWidth, bottomHeight), leftBottom);
CGContextDrawImage(context, CGRectMake(0, center, leftCapWidth, CGRectGetHeight(bounds)-topHeight-center), leftUpper);
CGContextDrawImage(context, CGRectMake(0, bottomHeight, leftCapWidth, center-bottomHeight), leftLower);
CGContextDrawImage(context, CGRectMake(0, center-centerHeight/4, leftCapWidth, centerHeight/2), leftCenter);
// Restore state
CGContextRestoreGState(context);
/*
* Image disposal
*/
// Stretch area
CGImageRelease(topPart);
CGImageRelease(bottomPart);
CGImageRelease(upperstretch);
CGImageRelease(lowerstretch);
CGImageRelease(centerPart);
// Right endcap
CGImageRelease(rightTop);
CGImageRelease(rightBottom);
CGImageRelease(rightUpper);
CGImageRelease(rightLower);
CGImageRelease(rightCenter);
// Left endcap
CGImageRelease(leftTop);
CGImageRelease(leftBottom);
CGImageRelease(leftUpper);
CGImageRelease(leftLower);
CGImageRelease(leftCenter);
// Icon
[self.icon drawInRect:CGRectMake(iconIndent, center-iconSize/2, iconSize, iconSize)];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment