Skip to content

Commit

Permalink
Some more enhanced work
Browse files Browse the repository at this point in the history
  • Loading branch information
maicki committed May 5, 2017
1 parent 4fcba0a commit 237fc2a
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 55 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- Simplified & optimized hashing code. [Adlai Holler](https://github.com/Adlai-Holler) [#86](https://github.com/TextureGroup/Texture/pull/86)
- Improve the performance & safety of ASDisplayNode subnodes. [Adlai Holler](https://github.com/Adlai-Holler) [#223](https://github.com/TextureGroup/Texture/pull/223)
- Remove finalLayoutElement [Michael Schneider] (https://github.com/maicki)[#96](https://github.com/TextureGroup/Texture/pull/96)
- [ASDisplayNode] Remove instance:-drawRect:withParameters:isCancelled:isRasterizing: (https://github.com/maicki)[#232](https://github.com/TextureGroup/Texture/pull/232)
5 changes: 5 additions & 0 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,11 @@ - (CGRect)threadSafeBounds
return _threadSafeBounds;
}

- (CGRect)_locked_threadSafeBounds
{
return _threadSafeBounds;
}

- (void)setThreadSafeBounds:(CGRect)newBounds
{
ASDN::MutexLocker l(__instanceLock__);
Expand Down
128 changes: 73 additions & 55 deletions Source/ASTextNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@
static const CGFloat ASTextNodeHighlightDarkOpacity = 0.22;
static NSString *ASTextNodeTruncationTokenAttributeName = @"ASTextNodeTruncationAttribute";

struct ASTextNodeDrawParameter {
CGRect bounds;
UIColor *backgroundColor;
};

#pragma mark - ASTextKitRenderer

@interface ASTextNodeRendererKey : NSObject
Expand Down Expand Up @@ -123,6 +118,44 @@ - (BOOL)isEqual:(ASTextNodeRendererKey *)object
return renderer;
}

#pragma mark - ASTextNodeDrawParametert

@interface ASTextNodeDrawParameter : NSObject {
std::unique_ptr<ASTextKitAttributes> _rendererAttributes;
}
@property (nonatomic, readonly, /*nullable*/) UIColor *backgroundColor;
@property (nonatomic, readonly) UIEdgeInsets textContainerInsets;

- (ASTextKitRenderer *)rendererForBounds:(CGRect)bounds;

@end

@implementation ASTextNodeDrawParameter

- (instancetype)initWithRendererAttributes:(ASTextKitAttributes)rendererAttributes
backgroundColor:(/*nullable*/ UIColor *)backgroundColor
textContainerInsets:(UIEdgeInsets)textContainerInsets
{
self = [super init];
if (self != nil) {
_rendererAttributes = ASDN::make_unique<ASTextKitAttributes>(rendererAttributes);
_backgroundColor = backgroundColor;
_textContainerInsets = textContainerInsets;
}
return self;
}

- (ASTextKitRenderer *)rendererForBounds:(CGRect)bounds
{
CGRect rect = UIEdgeInsetsInsetRect(bounds, self.textContainerInsets);
return rendererForAttributes(*_rendererAttributes.get(), rect.size);
}

@end


#pragma mark - ASTextNode

@interface ASTextNode () <UIGestureRecognizerDelegate>

@end
Expand All @@ -147,8 +180,6 @@ @implementation ASTextNode {
NSRange _highlightRange;
ASHighlightOverlayLayer *_activeHighlightLayer;

ASTextNodeDrawParameter _drawParameter;

UILongPressGestureRecognizer *_longPressGestureRecognizer;
}
@dynamic placeholderEnabled;
Expand Down Expand Up @@ -282,22 +313,29 @@ - (BOOL)supportsLayerBacking

- (ASTextKitRenderer *)_renderer
{
CGSize constrainedSize = self.threadSafeBounds.size;
return [self _rendererWithBoundsSlow:{.size = constrainedSize}];
ASDN::MutexLocker l(__instanceLock__);
return [self _locked_renderer];
}

- (ASTextKitRenderer *)_rendererWithBoundsSlow:(CGRect)bounds
- (ASTextKitRenderer *)_rendererWithBounds:(CGRect)bounds
{
ASDN::MutexLocker l(__instanceLock__);
bounds.size.width -= (_textContainerInset.left + _textContainerInset.right);
bounds.size.height -= (_textContainerInset.top + _textContainerInset.bottom);
return rendererForAttributes([self _rendererAttributes], bounds.size);
return [self _locked_rendererWithBounds:bounds];
}

- (ASTextKitAttributes)_rendererAttributes
- (ASTextKitRenderer *)_locked_renderer
{
return [self _locked_rendererWithBounds:[self _locked_threadSafeBounds]];
}

- (ASTextKitRenderer *)_locked_rendererWithBounds:(CGRect)bounds
{
bounds = UIEdgeInsetsInsetRect(bounds, _textContainerInset);
return rendererForAttributes([self _locked_rendererAttributes], bounds.size);
}

- (ASTextKitAttributes)_locked_rendererAttributes
{
ASDN::MutexLocker l(__instanceLock__);

return {
.attributedString = _attributedText,
.truncationAttributedString = [self _locked_composedTruncationText],
Expand Down Expand Up @@ -347,7 +385,7 @@ - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize

[self setNeedsDisplay];

ASTextKitRenderer *renderer = [self _rendererWithBoundsSlow:{.size = constrainedSize}];
ASTextKitRenderer *renderer = [self _locked_rendererWithBounds:{.size = constrainedSize}];
CGSize size = renderer.size;
if (_attributedText.length > 0) {
self.style.ascender = [[self class] ascenderWithAttributedString:_attributedText];
Expand Down Expand Up @@ -458,40 +496,27 @@ - (NSArray *)exclusionPaths

#pragma mark - Drawing

static NSString *ASTextNodeBackgroundColorDrawParameterKey = @"backgroundColor";
static NSString *ASTextNodeContainerInsetsDrawParameterKey = @"containerInsets";
static NSString *ASTextNodeRendererDrawParameterKey = @"renderer";

- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer
{
ASDN::MutexLocker l(__instanceLock__);

NSMutableDictionary *drawParameters = [[NSMutableDictionary alloc] init];
if (self.backgroundColor != nil) {
drawParameters[ASTextNodeBackgroundColorDrawParameterKey] = self.backgroundColor;
}
if (!UIEdgeInsetsEqualToEdgeInsets(_textContainerInset, UIEdgeInsetsZero)) {
drawParameters[ASTextNodeContainerInsetsDrawParameterKey] = [NSValue valueWithUIEdgeInsets:_textContainerInset];
}
drawParameters[ASTextNodeRendererDrawParameterKey] = [self _rendererWithBoundsSlow:self.bounds];
return drawParameters;

return [[ASTextNodeDrawParameter alloc] initWithRendererAttributes:[self _locked_rendererAttributes]
backgroundColor:self.backgroundColor
textContainerInsets:_textContainerInset];
}

+ (void)drawRect:(CGRect)bounds withParameters:(id)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing
{
UIColor *backgroundColor = isRasterizing ? nil : parameters[ASTextNodeBackgroundColorDrawParameterKey];
ASTextKitRenderer *renderer = parameters[ASTextNodeRendererDrawParameterKey];
UIEdgeInsets textContainerInset = UIEdgeInsetsZero;
NSValue *textContainerInsetValue = parameters[ASTextNodeContainerInsetsDrawParameterKey];
if (textContainerInsetValue) {
textContainerInset = [textContainerInsetValue UIEdgeInsetsValue];
}
ASTextNodeDrawParameter *drawParameter = (ASTextNodeDrawParameter *)parameters;
UIColor *backgroundColor = isRasterizing ? nil : drawParameter.backgroundColor;
UIEdgeInsets textContainerInsets = drawParameter.textContainerInsets;
ASTextKitRenderer *renderer = [drawParameter rendererForBounds:bounds];

CGContextRef context = UIGraphicsGetCurrentContext();
ASDisplayNodeAssert(context, @"This is no good without a context.");

CGContextSaveGState(context);
CGContextTranslateCTM(context, textContainerInset.left, textContainerInset.top);
CGContextTranslateCTM(context, textContainerInsets.left, textContainerInsets.top);

// Fill background
if (backgroundColor != nil) {
Expand Down Expand Up @@ -527,7 +552,7 @@ - (id)_linkAttributeValueAtPoint:(CGPoint)point

ASDN::MutexLocker l(__instanceLock__);

ASTextKitRenderer *renderer = [self _renderer];
ASTextKitRenderer *renderer = [self _locked_renderer];
NSRange visibleRange = renderer.firstVisibleRange;
NSAttributedString *attributedString = _attributedText;
NSRange clampedRange = NSIntersectionRange(visibleRange, NSMakeRange(0, attributedString.length));
Expand Down Expand Up @@ -833,7 +858,7 @@ - (NSArray *)_rectsForTextRange:(NSRange)textRange measureOption:(ASTextKitRende
{
ASDN::MutexLocker l(__instanceLock__);

NSArray *rects = [[self _renderer] rectsForTextRange:textRange measureOption:measureOption];
NSArray *rects = [[self _locked_renderer] rectsForTextRange:textRange measureOption:measureOption];
NSMutableArray *adjustedRects = [NSMutableArray array];

for (NSValue *rectValue in rects) {
Expand All @@ -851,15 +876,15 @@ - (CGRect)trailingRect
{
ASDN::MutexLocker l(__instanceLock__);

CGRect rect = [[self _renderer] trailingRect];
CGRect rect = [[self _locked_renderer] trailingRect];
return ASTextNodeAdjustRenderRectForShadowPadding(rect, self.shadowPadding);
}

- (CGRect)frameForTextRange:(NSRange)textRange
{
ASDN::MutexLocker l(__instanceLock__);

CGRect frame = [[self _renderer] frameForTextRange:textRange];
CGRect frame = [[self _locked_renderer] frameForTextRange:textRange];
return ASTextNodeAdjustRenderRectForShadowPadding(frame, self.shadowPadding);
}

Expand Down Expand Up @@ -889,7 +914,7 @@ - (UIImage *)placeholderImage
UIGraphicsBeginImageContext(size);
[self.placeholderColor setFill];

ASTextKitRenderer *renderer = [self _renderer];
ASTextKitRenderer *renderer = [self _locked_renderer];
NSRange visibleRange = renderer.firstVisibleRange;

// cap height is both faster and creates less subpixel blending
Expand Down Expand Up @@ -967,7 +992,7 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
NSRange visibleRange = NSMakeRange(0, 0);
{
ASDN::MutexLocker l(__instanceLock__);
visibleRange = [self _renderer].firstVisibleRange;
visibleRange = [self _locked_renderer].firstVisibleRange;
}
NSRange truncationMessageRange = [self _additionalTruncationMessageRangeWithVisibleRange:visibleRange];
[self _setHighlightRange:truncationMessageRange forAttributeName:ASTextNodeTruncationTokenAttributeName value:nil animated:YES];
Expand Down Expand Up @@ -1149,15 +1174,9 @@ - (void)setShadowRadius:(CGFloat)shadowRadius
}

- (UIEdgeInsets)shadowPadding
{
return [self shadowPaddingWithRenderer:[self _renderer]];
}

- (UIEdgeInsets)shadowPaddingWithRenderer:(ASTextKitRenderer *)renderer
{
ASDN::MutexLocker l(__instanceLock__);

return renderer.shadower.shadowPadding;
return [self _locked_renderer].shadower.shadowPadding;
}

#pragma mark - Truncation Message
Expand Down Expand Up @@ -1221,8 +1240,7 @@ - (BOOL)isTruncated
{
ASDN::MutexLocker l(__instanceLock__);

ASTextKitRenderer *renderer = [self _renderer];
return renderer.isTruncated;
return [[self _locked_renderer] isTruncated];
}

- (void)setPointSizeScaleFactors:(NSArray *)pointSizeScaleFactors
Expand Down Expand Up @@ -1258,7 +1276,7 @@ - (NSUInteger)lineCount
{
ASDN::MutexLocker l(__instanceLock__);

return [[self _renderer] lineCount];
return [[self _locked_renderer] lineCount];
}

#pragma mark - Truncation Message
Expand Down
10 changes: 10 additions & 0 deletions Source/Details/ASThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,4 +425,14 @@ namespace ASDN {

} // namespace ASDN

// Helper for creating a unique::ptr. Starting available C++14

namespace ASDN {
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}

#endif /* __cplusplus */
3 changes: 3 additions & 0 deletions Source/Private/ASDisplayNode+FrameworkPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ __unused static NSString * _Nonnull NSStringFromASHierarchyState(ASHierarchyStat
// Thread safe way to access the bounds of the node
@property (nonatomic, assign) CGRect threadSafeBounds;

// Returns the bounds of the node without reaching the view or layer
- (CGRect)_locked_threadSafeBounds;

// delegate to inform of ASInterfaceState changes (used by ASNodeController)
@property (nonatomic, weak) id<ASInterfaceStateDelegate> interfaceStateDelegate;

Expand Down

0 comments on commit 237fc2a

Please sign in to comment.