OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/chrome/browser/ui/util/text_frame.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/mac/foundation_util.h" |
| 9 #import "base/mac/scoped_nsobject.h" |
| 10 |
| 11 #pragma mark - FramedLine |
| 12 |
| 13 @implementation FramedLine { |
| 14 // Backing object for property of the same name. |
| 15 base::scoped_nsprotocol<id> _line; |
| 16 } |
| 17 |
| 18 @synthesize stringRange = _stringRange; |
| 19 @synthesize origin = _origin; |
| 20 |
| 21 - (instancetype)initWithLine:(CTLineRef)line |
| 22 stringRange:(NSRange)stringRange |
| 23 origin:(CGPoint)origin { |
| 24 if ((self = [super init])) { |
| 25 DCHECK(line); |
| 26 // CTLines created by ManualTextFramers all have zero for their string range |
| 27 // locations, but its length should be equal to |stringRange|. |
| 28 NSRange lineRange; |
| 29 if (!base::mac::CFRangeToNSRange(CTLineGetStringRange(line), &lineRange)) { |
| 30 [self release]; |
| 31 return nil; |
| 32 } |
| 33 DCHECK_EQ(lineRange.length, stringRange.length); |
| 34 _line.reset([static_cast<id>(line) retain]); |
| 35 _stringRange = stringRange; |
| 36 _origin = origin; |
| 37 } |
| 38 return self; |
| 39 } |
| 40 |
| 41 - (NSString*)description { |
| 42 return [NSString stringWithFormat:@"%@ line:%@, stringRange:%@, origin:%@", |
| 43 [super description], _line.get(), |
| 44 NSStringFromRange(_stringRange), |
| 45 NSStringFromCGPoint(_origin)]; |
| 46 } |
| 47 |
| 48 - (CFIndex)lineOffsetForStringLocation:(NSUInteger)stringLocation { |
| 49 if (stringLocation < self.stringRange.location || |
| 50 stringLocation >= self.stringRange.location + self.stringRange.length) { |
| 51 return kCFNotFound; |
| 52 } |
| 53 NSRange lineRange; |
| 54 if (!base::mac::CFRangeToNSRange(CTLineGetStringRange(self.line), &lineRange)) |
| 55 return kCFNotFound; |
| 56 return lineRange.location + (stringLocation - self.stringRange.location); |
| 57 } |
| 58 |
| 59 #pragma mark Accessors |
| 60 |
| 61 - (CTLineRef)line { |
| 62 return static_cast<CTLineRef>(_line.get()); |
| 63 } |
| 64 |
| 65 @end |
| 66 |
| 67 #pragma mark - CoreTextTextFrame |
| 68 |
| 69 @interface CoreTextTextFrame () { |
| 70 // Backing object for property of the same name. |
| 71 base::scoped_nsobject<NSAttributedString> _string; |
| 72 base::scoped_nsprotocol<id> _frame; |
| 73 base::scoped_nsobject<NSMutableArray> _lines; |
| 74 } |
| 75 |
| 76 // The CTFrameRef passed on initializaton. |
| 77 @property(nonatomic, readonly) CTFrameRef frame; |
| 78 |
| 79 // Populates |lines| using |frame|. |
| 80 - (void)createFramedLines; |
| 81 |
| 82 @end |
| 83 |
| 84 @implementation CoreTextTextFrame |
| 85 |
| 86 @synthesize bounds = _bounds; |
| 87 |
| 88 - (instancetype)initWithString:(NSAttributedString*)string |
| 89 bounds:(CGRect)bounds |
| 90 frame:(CTFrameRef)frame { |
| 91 if ((self = [super self])) { |
| 92 DCHECK(string.string.length); |
| 93 _string.reset([string retain]); |
| 94 _bounds = bounds; |
| 95 DCHECK(frame); |
| 96 _frame.reset([static_cast<id>(frame) retain]); |
| 97 } |
| 98 return self; |
| 99 } |
| 100 |
| 101 #pragma mark Accessors |
| 102 |
| 103 - (NSAttributedString*)string { |
| 104 return _string.get(); |
| 105 } |
| 106 |
| 107 - (NSRange)framedRange { |
| 108 NSRange range; |
| 109 CFRange cfRange = CTFrameGetVisibleStringRange(self.frame); |
| 110 if (base::mac::CFRangeToNSRange(cfRange, &range)) |
| 111 return range; |
| 112 return NSMakeRange(NSNotFound, 0); |
| 113 } |
| 114 |
| 115 - (NSArray*)lines { |
| 116 if (!_lines) |
| 117 [self createFramedLines]; |
| 118 return _lines.get(); |
| 119 } |
| 120 |
| 121 - (CTFrameRef)frame { |
| 122 return static_cast<CTFrameRef>(_frame.get()); |
| 123 } |
| 124 |
| 125 #pragma mark Private |
| 126 |
| 127 - (void)createFramedLines { |
| 128 NSArray* lines = base::mac::CFToNSCast(CTFrameGetLines(self.frame)); |
| 129 CGPoint origins[lines.count]; |
| 130 CTFrameGetLineOrigins(self.frame, CFRangeMake(0, 0), origins); |
| 131 _lines.reset([[NSMutableArray alloc] initWithCapacity:lines.count]); |
| 132 for (NSUInteger line_idx = 0; line_idx < lines.count; ++line_idx) { |
| 133 CTLineRef line = static_cast<CTLineRef>(lines[line_idx]); |
| 134 NSRange stringRange; |
| 135 CFRange cfStringRange = CTLineGetStringRange(line); |
| 136 if (!base::mac::CFRangeToNSRange(cfStringRange, &stringRange)) |
| 137 break; |
| 138 base::scoped_nsobject<FramedLine> framedLine([[FramedLine alloc] |
| 139 initWithLine:line |
| 140 stringRange:stringRange |
| 141 origin:origins[line_idx]]); |
| 142 [_lines addObject:framedLine]; |
| 143 } |
| 144 } |
| 145 |
| 146 @end |
OLD | NEW |