forked from gnachman/iTerm2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SharedCharacterRunData.m
116 lines (96 loc) · 3.51 KB
/
SharedCharacterRunData.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
//
// SharedCharacterRunData.m
// iTerm
//
// Created by George Nachman on 12/31/12.
//
//
#import "SharedCharacterRunData.h"
@interface SharedCharacterRunData ()
@property (nonatomic, assign) __weak unichar* codes; // Shared pointer to code point(s) for this char.
@property (nonatomic, assign) __weak CGSize* advances; // Shared pointer to advances for each code.
@property (nonatomic, assign) __weak CGGlyph* glyphs; // Shared pointer to glyphs for these chars (single code point only)
@property (nonatomic, assign) NSRange freeRange; // Unused space at the end of the arrays.
+ (SharedCharacterRunData *)sharedCharacterRunDataWithCapacity:(int)capacity;
// Mark a number of cells beginning at freeRange.location as used.
- (void)advance:(int)positions;
// Makes sure there is room for at least 'space' more codes/advances/glyphs beyond what is used.
// Allocates more space if necessary. Call this before writing to shared pointers and before
// calling -advance:.
- (void)reserve:(int)space;
@end
@implementation SharedCharacterRunData
@synthesize codes = codes_;
@synthesize advances = advances_;
@synthesize glyphs = glyphs_;
@synthesize freeRange = freeRange_;
+ (SharedCharacterRunData *)sharedCharacterRunDataWithCapacity:(int)capacity {
SharedCharacterRunData *data = [[[SharedCharacterRunData alloc] init] autorelease];
data->capacity_ = capacity;
data.codes = malloc(sizeof(unichar) * capacity);
data.advances = malloc(sizeof(CGSize) * capacity);
data.glyphs = malloc(sizeof(CGGlyph) * capacity);
data.freeRange = NSMakeRange(0, capacity);
return data;
}
- (void)dealloc {
free(codes_);
free(advances_);
free(glyphs_);
[super dealloc];
}
- (void)advance:(int)positions {
[self reserve:positions];
freeRange_.location += positions;
assert(freeRange_.length >= positions);
freeRange_.length -= positions;
}
- (void)reserve:(int)space {
if (freeRange_.length < space) {
int newSize = (capacity_ + space) * 2;
int growth = newSize - capacity_;
capacity_ = newSize;
freeRange_.length += growth;
codes_ = realloc(codes_, sizeof(unichar) * capacity_);
advances_ = realloc(advances_, sizeof(CGSize) * capacity_);
glyphs_ = realloc(glyphs_, sizeof(CGGlyph) * capacity_);
}
}
- (void)growAllocation:(NSRange *)range by:(int)growBy {
assert(growBy > 0);
if (!range->length) {
assert(!range->location);
int offset = freeRange_.location;
[self advance:growBy];
range->length = growBy;
range->location = offset;
} else {
assert(range->length >= 0);
assert(range->location + range->length == freeRange_.location);
[self advance:growBy];
range->length += growBy;
}
}
- (unichar *)codesInRange:(NSRange)range {
assert(range.location + range.length <= freeRange_.location);
return codes_ + range.location;
}
- (CGSize *)advancesInRange:(NSRange)range {
assert(range.location + range.length <= freeRange_.location);
return advances_ + range.location;
}
- (CGGlyph *)glyphsInRange:(NSRange)range {
assert(range.location + range.length <= freeRange_.location);
return glyphs_ + range.location;
}
- (void)advanceAllocation:(NSRange *)range by:(int)advanceBy {
assert(range->length >= advanceBy);
range->location += advanceBy;
range->length -= advanceBy;
}
- (void)truncateAllocation:(NSRange *)range toSize:(int)newSize {
assert(newSize <= range->length);
assert(newSize >= 0);
range->length = newSize;
}
@end