forked from drewmccormack/BackToTheMac
-
Notifications
You must be signed in to change notification settings - Fork 1
/
MCImage.m
131 lines (94 loc) · 3.88 KB
/
MCImage.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// MCImage.m
// BackToTheMac
//
// Created by Drew McCormack on 30/08/10.
// Copyright (c) 2010 The Mental Faculty. All rights reserved.
//
#import "MCImage.h"
@interface MCStretchableImageRep : NSImageRep
{
@private
NSImage *_sourceImage;
NSArray *cachedSliceImages;
CGFloat leftCapWidth, topCapHeight;
}
- (id)initWithImage:(NSImage *)image;
@property CGFloat leftCapWidth, topCapHeight;
- (NSArray *)imageSlices;
@end
#pragma mark -
@implementation NSImage (MCStretchableImageExtensions)
-(NSImage *)stretchableImageWithLeftCapWidth:(CGFloat)leftCapWidth topCapHeight:(CGFloat)topCapHeight
{
MCStretchableImageRep *rep = [[MCStretchableImageRep alloc] initWithImage:self];
rep.topCapHeight = topCapHeight;
rep.leftCapWidth = leftCapWidth;
NSImage *result = [[NSImage alloc] initWithSize:[self size]];
[result addRepresentation:rep];
return result;
}
-(void)drawInRect:(NSRect)rect
{
[self drawInRect:rect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
}
- (CGFloat)leftCapWidth; { return 0.0f; }
- (CGFloat)topCapHeight; { return 0.0f; }
@end
#pragma mark -
@implementation MCStretchableImageRep
- (id)initWithImage:(NSImage *)image;
{
[self init];
_sourceImage = image;
[self setSize:[image size]];
return self;
}
@synthesize leftCapWidth, topCapHeight;
-(NSImage *)sliceFromRect:(NSRect)rect
{
NSImage *newImage = [[NSImage alloc] initWithSize:rect.size];
if ( newImage.isValid && rect.size.width > 0.0f && rect.size.height > 0.0f ) {
NSRect toRect = rect;
toRect.origin = NSZeroPoint;
[newImage lockFocus];
[_sourceImage drawInRect:toRect fromRect:rect operation:NSCompositeCopy fraction:1.0f];
[newImage unlockFocus];
}
return newImage;
}
-(NSArray *)imageSlices {
if ( cachedSliceImages ) return cachedSliceImages;
[self performSelectorOnMainThread:@selector(createImageSlices) withObject:nil waitUntilDone:YES];
return cachedSliceImages;
}
-(void)createImageSlices {
CGFloat rightCapWidth = MAX(1.0f, self.size.width - leftCapWidth - 1.0f);
CGFloat bottomCapHeight = MAX(1.0f, self.size.height - topCapHeight - 1.0f);
NSImage *topLeft = [self sliceFromRect:NSMakeRect(0.0f, bottomCapHeight+1.0f, leftCapWidth, topCapHeight)];
NSImage *topEdge = [self sliceFromRect:NSMakeRect(leftCapWidth, bottomCapHeight+1.0f, 1.0f, topCapHeight)];
NSImage *topRight = [self sliceFromRect:NSMakeRect(leftCapWidth+1.0f, bottomCapHeight+1.0f, rightCapWidth, topCapHeight)];
NSImage *leftEdge = [self sliceFromRect:NSMakeRect(0.0f, bottomCapHeight, leftCapWidth, 1.0f)];
NSImage *center = [self sliceFromRect:NSMakeRect(leftCapWidth, bottomCapHeight, 1.0f, 1.0f)];
NSImage *rightEdge = [self sliceFromRect:NSMakeRect(leftCapWidth+1.0f, bottomCapHeight, rightCapWidth, 1.0f)];
NSImage *bottomLeft = [self sliceFromRect:NSMakeRect(0.0f, 0.0f, leftCapWidth, bottomCapHeight)];
NSImage *bottomEdge = [self sliceFromRect:NSMakeRect(leftCapWidth, 0.0f, 1.0f, bottomCapHeight)];
NSImage *bottomRight = [self sliceFromRect:NSMakeRect(leftCapWidth+1.0f, 0.0f, rightCapWidth, bottomCapHeight)];
NSArray *slices = [NSArray arrayWithObjects:topLeft, topEdge, topRight, leftEdge, center, rightEdge, bottomLeft, bottomEdge, bottomRight, nil];
cachedSliceImages = slices;
}
- (BOOL)draw;
{
// This method should only be called if someone somehow calls -drawAtPoint: All other methods go through -drawInRect: which we've overriden
NSRect rect; rect.origin = NSZeroPoint; rect.size = [self size];
return [self drawInRect:rect];
}
- (BOOL)drawInRect:(NSRect)rect;
{
NSArray *slices = [self imageSlices];
#define S(i) [slices objectAtIndex:i]
NSDrawNinePartImage(rect, S(0), S(1), S(2), S(3), S(4), S(5), S(6), S(7), S(8),
NSCompositeCopy, 1.0f, NO);
return YES;
}
@end