Merge pull request #1140 from rcancro/textNodeWordSpacing

[ASTextNode] Added ASTextNodeWordKerner support
This commit is contained in:
appleguy 2016-01-28 15:38:00 -08:00
commit 2c194fd924
10 changed files with 45 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;
ASDN::Mutex _wordKernerLock;
ASTextNodeWordKerner *_wordKerner;
} }
@dynamic placeholderEnabled; @dynamic placeholderEnabled;
@ -257,6 +262,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
.maximumNumberOfLines = _maximumNumberOfLines, .maximumNumberOfLines = _maximumNumberOfLines,
.exclusionPaths = _exclusionPaths, .exclusionPaths = _exclusionPaths,
.minimumScaleFactor = _minimumScaleFactor, .minimumScaleFactor = _minimumScaleFactor,
.layoutManagerDelegate = [self _wordKerner],
}; };
} }
@ -292,6 +298,15 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
} }
} }
- (ASTextNodeWordKerner *)_wordKerner
{
ASDN::MutexLocker l(_wordKernerLock);
if (_wordKerner == nil) {
_wordKerner = [[ASTextNodeWordKerner alloc] init];
}
return _wordKerner;
}
#pragma mark - Layout and Sizing #pragma mark - Layout and Sizing
- (BOOL)_needInvalidateRendererForBoundsSize:(CGSize)boundsSize - (BOOL)_needInvalidateRendererForBoundsSize:(CGSize)boundsSize

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

@ -30,6 +30,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.
@ -39,6 +40,7 @@
_textStorage = (attributedString ? [[NSTextStorage alloc] initWithAttributedString:attributedString] : [[NSTextStorage alloc] init]); _textStorage = (attributedString ? [[NSTextStorage alloc] initWithAttributedString:attributedString] : [[NSTextStorage alloc] init]);
_layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[ASLayoutManager alloc] init]; _layoutManager = layoutManagerFactory ? layoutManagerFactory() : [[ASLayoutManager 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