|
4 | 4 | #import "StyleUtils.h" |
5 | 5 | #import "TextInsertionUtils.h" |
6 | 6 |
|
7 | | -@implementation OrderedListStyle |
| 7 | +@implementation OrderedListStyle { |
| 8 | + // we don't want to re-measure each marker's actual |
| 9 | + // width. We estimate the width with cached metrics instead |
| 10 | + UIFont *_cachedMarkerFont; |
| 11 | + CGFloat _cachedDigitWidth; |
| 12 | + CGFloat _cachedDotWidth; |
| 13 | +} |
8 | 14 |
|
9 | 15 | + (StyleType)getType { |
10 | 16 | return OrderedList; |
@@ -87,17 +93,35 @@ - (void)recalculateListsAroundEditedRange:(NSRange)range { |
87 | 93 | } |
88 | 94 | } |
89 | 95 |
|
| 96 | +- (void)ensureMarkerMetricsForFont:(UIFont *)font { |
| 97 | + if (_cachedMarkerFont != nil && [_cachedMarkerFont isEqual:font]) { |
| 98 | + return; |
| 99 | + } |
| 100 | + _cachedMarkerFont = font; |
| 101 | + NSDictionary *attrs = @{NSFontAttributeName : font}; |
| 102 | + _cachedDigitWidth = [@"0" sizeWithAttributes:attrs].width; |
| 103 | + _cachedDotWidth = [@"." sizeWithAttributes:attrs].width; |
| 104 | +} |
| 105 | + |
| 106 | +- (NSInteger)digitCountOf:(NSInteger)n { |
| 107 | + NSInteger count = 1; |
| 108 | + NSInteger value = MAX(n, 1); |
| 109 | + while (value >= 10) { |
| 110 | + value /= 10; |
| 111 | + count += 1; |
| 112 | + } |
| 113 | + return count; |
| 114 | +} |
| 115 | + |
90 | 116 | // computes the shared marker-column indent for a list of the given item |
91 | 117 | // count. The largest marker value equals the item count (numbering starts |
92 | 118 | // at 1); if its width overflows the configured margin we expand to fit it |
93 | 119 | - (CGFloat)headIndentForItemCount:(NSInteger)itemCount { |
94 | | - NSString *widestMarker = |
95 | | - [NSString stringWithFormat:@"%d.", (int)MAX(itemCount, 1)]; |
96 | | - CGFloat widestMarkerWidth = |
97 | | - [widestMarker sizeWithAttributes:@{ |
98 | | - NSFontAttributeName : [self.host.config orderedListMarkerFont] |
99 | | - }] |
100 | | - .width; |
| 120 | + UIFont *markerFont = [self.host.config orderedListMarkerFont]; |
| 121 | + [self ensureMarkerMetricsForFont:markerFont]; |
| 122 | + |
| 123 | + NSInteger digitCount = [self digitCountOf:itemCount]; |
| 124 | + CGFloat widestMarkerWidth = digitCount * _cachedDigitWidth + _cachedDotWidth; |
101 | 125 |
|
102 | 126 | CGFloat markerColumnWidth = |
103 | 127 | MAX([self.host.config orderedListMarginLeft], widestMarkerWidth); |
|
0 commit comments