Added ASTextNodeWordKerner support to ASTextNode

* Added a member to `ASTextKitAttributes` that is an optional delegate to the struct's NSLayoutManager.
* Changed ASTextNode to set this delegate to an instance of ASTextNodeWordKerner.
* Updated init method of `ASTextKitContext` to take an optional NSLayoutManager delegate
* Added the files in TextKit folder to the public headers (so we can include ASTextNodeTypes.h)
This commit is contained in:
rcancro
2016-01-28 08:38:22 -08:00
parent d433205e5a
commit 7f6f2fed11
10 changed files with 38 additions and 12 deletions

View File

@@ -13,6 +13,7 @@ Pod::Spec.new do |spec|
'AsyncDisplayKit/*.h', 'AsyncDisplayKit/*.h',
'AsyncDisplayKit/Details/**/*.h', 'AsyncDisplayKit/Details/**/*.h',
'AsyncDisplayKit/Layout/*.h', 'AsyncDisplayKit/Layout/*.h',
'AsyncDisplayKit/TextKit/*.h',
'Base/*.h' 'Base/*.h'
] ]

View File

@@ -137,7 +137,7 @@
254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; }; 254C6B731BF94DF4003EC431 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; };
254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */; }; 254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754B91BEE458E00737CA5 /* ASTextNodeWordKerner.h */; };
254C6B751BF94DF4003EC431 /* ASTextKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */; }; 254C6B751BF94DF4003EC431 /* ASTextKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BA1BEE458E00737CA5 /* ASTextKitHelpers.h */; };
254C6B761BF94DF4003EC431 /* ASTextNodeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */; }; 254C6B761BF94DF4003EC431 /* ASTextNodeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; };
254C6B771BF94DF4003EC431 /* ASTextKitAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754951BEE44CD00737CA5 /* ASTextKitAttributes.h */; }; 254C6B771BF94DF4003EC431 /* ASTextKitAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754951BEE44CD00737CA5 /* ASTextKitAttributes.h */; };
254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754961BEE44CD00737CA5 /* ASTextKitContext.h */; }; 254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754961BEE44CD00737CA5 /* ASTextKitContext.h */; };
254C6B791BF94DF4003EC431 /* ASTextKitEntityAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754981BEE44CD00737CA5 /* ASTextKitEntityAttribute.h */; }; 254C6B791BF94DF4003EC431 /* ASTextKitEntityAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754981BEE44CD00737CA5 /* ASTextKitEntityAttribute.h */; };

View File

@@ -21,6 +21,7 @@
#import "ASTextKitRenderer.h" #import "ASTextKitRenderer.h"
#import "ASTextKitRenderer+Positioning.h" #import "ASTextKitRenderer+Positioning.h"
#import "ASTextKitShadower.h" #import "ASTextKitShadower.h"
#import "ASTextNodeWordKerner.h"
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASEqualityHelpers.h" #import "ASEqualityHelpers.h"
@@ -74,7 +75,7 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
@end @end
@interface ASTextNode () <UIGestureRecognizerDelegate> @interface ASTextNode () <UIGestureRecognizerDelegate, NSLayoutManagerDelegate>
@end @end
@@ -100,6 +101,10 @@ static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncation
ASTextKitRenderer *_renderer; ASTextKitRenderer *_renderer;
UILongPressGestureRecognizer *_longPressGestureRecognizer; UILongPressGestureRecognizer *_longPressGestureRecognizer;
// Forwards NSLayoutManagerDelegate methods related to word kerning
ASTextNodeWordKerner *_wordKerner;
} }
@dynamic placeholderEnabled; @dynamic placeholderEnabled;
@@ -143,6 +148,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
// on the special placeholder behavior of ASTextNode. // on the special placeholder behavior of ASTextNode.
_placeholderColor = ASDisplayNodeDefaultPlaceholderColor(); _placeholderColor = ASDisplayNodeDefaultPlaceholderColor();
_placeholderInsets = UIEdgeInsetsMake(1.0, 0.0, 1.0, 0.0); _placeholderInsets = UIEdgeInsetsMake(1.0, 0.0, 1.0, 0.0);
_wordKerner = [[ASTextNodeWordKerner alloc] init];
} }
return self; return self;
@@ -257,6 +264,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
.maximumNumberOfLines = _maximumNumberOfLines, .maximumNumberOfLines = _maximumNumberOfLines,
.exclusionPaths = _exclusionPaths, .exclusionPaths = _exclusionPaths,
.minimumScaleFactor = _minimumScaleFactor, .minimumScaleFactor = _minimumScaleFactor,
.layoutManagerDelegate = _wordKerner,
}; };
} }

View File

@@ -89,6 +89,11 @@ struct ASTextKitAttributes {
A pointer to a function that that returns a custom layout manager subclass. If nil, defaults to NSLayoutManager. A pointer to a function that that returns a custom layout manager subclass. If nil, defaults to NSLayoutManager.
*/ */
NSLayoutManager *(*layoutManagerFactory)(void); NSLayoutManager *(*layoutManagerFactory)(void);
/**
An optional delegate for the NSLayoutManager
*/
id<NSLayoutManagerDelegate> layoutManagerDelegate;
/** /**
We provide an explicit copy function so we can use aggregate initializer syntax while providing copy semantics for We provide an explicit copy function so we can use aggregate initializer syntax while providing copy semantics for

View File

@@ -28,7 +28,8 @@
maximumNumberOfLines:(NSUInteger)maximumNumberOfLines maximumNumberOfLines:(NSUInteger)maximumNumberOfLines
exclusionPaths:(NSArray *)exclusionPaths exclusionPaths:(NSArray *)exclusionPaths
constrainedSize:(CGSize)constrainedSize constrainedSize:(CGSize)constrainedSize
layoutManagerFactory:(NSLayoutManager*(*)(void))layoutManagerFactory; layoutManagerFactory:(NSLayoutManager*(*)(void))layoutManagerFactory
layoutManagerDelegate:(id<NSLayoutManagerDelegate>)layoutManagerDelegate;
@property (nonatomic, assign, readwrite) CGSize constrainedSize; @property (nonatomic, assign, readwrite) CGSize constrainedSize;

View File

@@ -28,6 +28,7 @@
exclusionPaths:(NSArray *)exclusionPaths exclusionPaths:(NSArray *)exclusionPaths
constrainedSize:(CGSize)constrainedSize constrainedSize:(CGSize)constrainedSize
layoutManagerFactory:(NSLayoutManager*(*)(void))layoutManagerFactory layoutManagerFactory:(NSLayoutManager*(*)(void))layoutManagerFactory
layoutManagerDelegate:(id<NSLayoutManagerDelegate>)layoutManagerDelegate
{ {
if (self = [super init]) { if (self = [super init]) {
// Concurrently initialising TextKit components crashes (rdar://18448377) so we use a global lock. // Concurrently initialising TextKit components crashes (rdar://18448377) so we use a global lock.
@@ -37,6 +38,7 @@
_textStorage = (attributedString ? [[NSTextStorage alloc] initWithAttributedString:attributedString] : [[NSTextStorage alloc] init]); _textStorage = (attributedString ? [[NSTextStorage alloc] initWithAttributedString:attributedString] : [[NSTextStorage alloc] init]);
_layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[NSLayoutManager alloc] init]; _layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[NSLayoutManager alloc] init];
_layoutManager.usesFontLeading = NO; _layoutManager.usesFontLeading = NO;
_layoutManager.delegate = layoutManagerDelegate;
[_textStorage addLayoutManager:_layoutManager]; [_textStorage addLayoutManager:_layoutManager];
_textContainer = [[NSTextContainer alloc] initWithSize:constrainedSize]; _textContainer = [[NSTextContainer alloc] initWithSize:constrainedSize];
// We want the text laid out up to the very edges of the container. // We want the text laid out up to the very edges of the container.

View File

@@ -101,7 +101,8 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
maximumNumberOfLines:attributes.maximumNumberOfLines maximumNumberOfLines:attributes.maximumNumberOfLines
exclusionPaths:attributes.exclusionPaths exclusionPaths:attributes.exclusionPaths
constrainedSize:shadowConstrainedSize constrainedSize:shadowConstrainedSize
layoutManagerFactory:attributes.layoutManagerFactory]; layoutManagerFactory:attributes.layoutManagerFactory
layoutManagerDelegate:attributes.layoutManagerDelegate];
[self truncater]; [self truncater];
} }

View File

@@ -72,8 +72,8 @@
maximumNumberOfLines:1 maximumNumberOfLines:1
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedRect.size constrainedSize:constrainedRect.size
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
__block CGRect truncationUsedRect; __block CGRect truncationUsedRect;
[truncationContext performBlockWithLockedTextKitComponents:^(NSLayoutManager *truncationLayoutManager, NSTextStorage *truncationTextStorage, NSTextContainer *truncationTextContainer) { [truncationContext performBlockWithLockedTextKitComponents:^(NSLayoutManager *truncationLayoutManager, NSTextStorage *truncationTextStorage, NSTextContainer *truncationTextContainer) {

View File

@@ -42,7 +42,8 @@
maximumNumberOfLines:0 maximumNumberOfLines:0
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedSize constrainedSize:constrainedSize
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
__block NSRange textKitVisibleRange; __block NSRange textKitVisibleRange;
[context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [context performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
textKitVisibleRange = [layoutManager characterRangeForGlyphRange:[layoutManager glyphRangeForTextContainer:textContainer] textKitVisibleRange = [layoutManager characterRangeForGlyphRange:[layoutManager glyphRangeForTextContainer:textContainer]
@@ -63,7 +64,8 @@
maximumNumberOfLines:0 maximumNumberOfLines:0
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedSize constrainedSize:constrainedSize
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@""]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@""]];
@@ -85,7 +87,8 @@
maximumNumberOfLines:0 maximumNumberOfLines:0
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedSize constrainedSize:constrainedSize
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
@@ -108,7 +111,8 @@
maximumNumberOfLines:0 maximumNumberOfLines:0
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedSize constrainedSize:constrainedSize
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context ASTextKitTailTruncater *tailTruncater = [[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]; avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]];
@@ -132,7 +136,9 @@
maximumNumberOfLines:0 maximumNumberOfLines:0
exclusionPaths:nil exclusionPaths:nil
constrainedSize:constrainedSize constrainedSize:constrainedSize
layoutManagerFactory:nil]; layoutManagerFactory:nil
layoutManagerDelegate:nil];
XCTAssertNoThrow([[ASTextKitTailTruncater alloc] initWithContext:context XCTAssertNoThrow([[ASTextKitTailTruncater alloc] initWithContext:context
truncationAttributedString:[self _simpleTruncationAttributedString] truncationAttributedString:[self _simpleTruncationAttributedString]
avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]); avoidTailTruncationSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]);

View File

@@ -16,6 +16,7 @@
#import <AsyncDisplayKit/ASStackLayoutSpec.h> #import <AsyncDisplayKit/ASStackLayoutSpec.h>
#import <AsyncDisplayKit/ASInsetLayoutSpec.h> #import <AsyncDisplayKit/ASInsetLayoutSpec.h>
#import <AsyncDisplayKit/ASTextNodeTypes.h>
static const CGFloat kImageSize = 80.0f; static const CGFloat kImageSize = 80.0f;
static const CGFloat kOuterPadding = 16.0f; static const CGFloat kOuterPadding = 16.0f;
@@ -128,7 +129,8 @@ static const CGFloat kInnerPadding = 10.0f;
style.hyphenationFactor = 1.0; style.hyphenationFactor = 1.0;
return @{ NSFontAttributeName: font, return @{ NSFontAttributeName: font,
NSParagraphStyleAttributeName: style }; NSParagraphStyleAttributeName: style,
ASTextNodeWordKerningAttributeName : @.5};
} }
#if UseAutomaticLayout #if UseAutomaticLayout