Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASImageNode] Move to class method of displayWithParameters:isCancelled: for drawing #244

Merged
merged 2 commits into from
May 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
- Remove finalLayoutElement [Michael Schneider] (https://github.com/maicki)[#96](https://github.com/TextureGroup/Texture/pull/96)
- Add ASPageTable - A map table for fast retrieval of objects within a certain page [Huy Nguyen](https://github.com/nguyenhuy)
- [ASDisplayNode] Pass drawParameter in rendering context callbacks [Michael Schneider](https://github.com/maicki)[#248](https://github.com/TextureGroup/Texture/pull/248)
- [ASTextNode] Move to class method of drawRect:withParameters:isCancelled:isRasterizing: for drawing [Michael Schneider] (https://github.com/maicki)[#232](https://github.com/TextureGroup/Texture/pull/232)
10 changes: 6 additions & 4 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,9 @@ static struct ASDisplayNodeFlags GetASDisplayNodeFlags(Class c, ASDisplayNode *i
if (instance) {
flags.implementsDrawParameters = ([instance respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0);
flags.implementsInstanceDrawRect = ([instance respondsToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] ? 1 : 0);
flags.implementsInstanceImageDisplay = ([instance respondsToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0);
} else {
flags.implementsDrawParameters = ([c instancesRespondToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0);
flags.implementsInstanceDrawRect = ([c instancesRespondToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] ? 1 : 0);
flags.implementsInstanceImageDisplay = ([c instancesRespondToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0);
}
return flags;
}
Expand Down Expand Up @@ -832,6 +830,11 @@ - (void)setShouldAnimateSizeChanges:(BOOL)shouldAnimateSizeChanges
- (CGRect)threadSafeBounds
{
ASDN::MutexLocker l(__instanceLock__);
return [self _locked_threadSafeBounds];
}

- (CGRect)_locked_threadSafeBounds
{
return _threadSafeBounds;
}

Expand Down Expand Up @@ -2001,8 +2004,7 @@ - (BOOL)_implementsDisplay
{
ASDN::MutexLocker l(__instanceLock__);

return _flags.implementsDrawRect || _flags.implementsImageDisplay || _flags.rasterizesSubtree ||
_flags.implementsInstanceDrawRect || _flags.implementsInstanceImageDisplay;
return _flags.implementsDrawRect || _flags.implementsImageDisplay || _flags.rasterizesSubtree || _flags.implementsInstanceDrawRect;
}

// Track that a node will be displayed as part of the current node hierarchy.
Expand Down
152 changes: 79 additions & 73 deletions Source/ASImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,37 @@

#include <functional>

struct ASImageNodeDrawParameters {
BOOL opaque;
CGRect bounds;
CGFloat contentsScale;
UIColor *backgroundColor;
UIViewContentMode contentMode;
BOOL cropEnabled;
BOOL forceUpscaling;
CGSize forcedSize;
CGRect cropRect;
CGRect cropDisplayBounds;
asimagenode_modification_block_t imageModificationBlock;
ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext;
};
typedef void (^ASImageNodeDrawParametersBlock)(ASWeakMapEntry *entry);

@interface ASImageNodeDrawParameters : NSObject {
@package
UIImage *_image;
BOOL _opaque;
CGRect _bounds;
CGFloat _contentsScale;
UIColor *_backgroundColor;
UIViewContentMode _contentMode;
BOOL _cropEnabled;
BOOL _forceUpscaling;
CGSize _forcedSize;
CGRect _cropRect;
CGRect _cropDisplayBounds;
asimagenode_modification_block_t _imageModificationBlock;
ASDisplayNodeContextModifier _willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier _didDisplayNodeContentWithRenderingContext;
ASImageNodeDrawParametersBlock _didDrawBlock;
}

@end

@implementation ASImageNodeDrawParameters

@end

/**
* Contains all data that is needed to generate the content bitmap.
*/
@interface ASImageNodeContentsKey : NSObject {}
@interface ASImageNodeContentsKey : NSObject

@property (nonatomic, strong) UIImage *image;
@property CGSize backingSize;
Expand Down Expand Up @@ -137,7 +148,6 @@ @implementation ASImageNode
void (^_displayCompletionBlock)(BOOL canceled);

// Drawing
ASImageNodeDrawParameters _drawParameter;
ASTextNode *_debugLabelNode;

// Cropping.
Expand All @@ -151,17 +161,7 @@ @implementation ASImageNode
@synthesize image = _image;
@synthesize imageModificationBlock = _imageModificationBlock;

#pragma mark - NSObject

+ (void)initialize
{
[super initialize];

if (self != [ASImageNode class]) {
// Prevent custom drawing in subclasses
ASDisplayNodeAssert(!ASSubclassOverridesClassSelector([ASImageNode class], self, @selector(displayWithParameters:isCancelled:)), @"Subclass %@ must not override displayWithParameters:isCancelled: method. Custom drawing in %@ subclass is not supported.", NSStringFromClass(self), NSStringFromClass([ASImageNode class]));
}
}
#pragma mark - Lifecycle

- (instancetype)init
{
Expand Down Expand Up @@ -194,6 +194,8 @@ - (void)dealloc
[self invalidateAnimatedImage];
}

#pragma mark - Placeholder

- (UIImage *)placeholderImage
{
// FIXME: Replace this implementation with reusable CALayers that have .backgroundColor set.
Expand Down Expand Up @@ -290,57 +292,53 @@ - (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer
{
ASDN::MutexLocker l(__instanceLock__);

_drawParameter = {
.bounds = self.bounds,
.opaque = self.opaque,
.contentsScale = self.contentsScaleForDisplay,
.backgroundColor = self.backgroundColor,
.contentMode = self.contentMode,
.cropEnabled = _cropEnabled,
.forceUpscaling = _forceUpscaling,
.forcedSize = _forcedSize,
.cropRect = _cropRect,
.cropDisplayBounds = _cropDisplayBounds,
.imageModificationBlock = _imageModificationBlock,
.willDisplayNodeContentWithRenderingContext = _willDisplayNodeContentWithRenderingContext,
.didDisplayNodeContentWithRenderingContext = _didDisplayNodeContentWithRenderingContext
ASImageNodeDrawParameters *drawParameters = [[ASImageNodeDrawParameters alloc] init];
drawParameters->_image = [self _locked_Image];
drawParameters->_bounds = [self threadSafeBounds];
drawParameters->_opaque = self.opaque;
drawParameters->_contentsScale = _contentsScaleForDisplay;
drawParameters->_backgroundColor = self.backgroundColor;
drawParameters->_contentMode = self.contentMode;
drawParameters->_cropEnabled = _cropEnabled;
drawParameters->_forceUpscaling = _forceUpscaling;
drawParameters->_forcedSize = _forcedSize;
drawParameters->_cropRect = _cropRect;
drawParameters->_cropDisplayBounds = _cropDisplayBounds;
drawParameters->_imageModificationBlock = _imageModificationBlock;
drawParameters->_willDisplayNodeContentWithRenderingContext = _willDisplayNodeContentWithRenderingContext;
drawParameters->_didDisplayNodeContentWithRenderingContext = _didDisplayNodeContentWithRenderingContext;

// Hack for now to retain the weak entry that was created while this drawing happened
drawParameters->_didDrawBlock = ^(ASWeakMapEntry *entry){
ASDN::MutexLocker l(__instanceLock__);
_weakCacheEntry = entry;
};

return nil;
return drawParameters;
}

- (NSDictionary *)debugLabelAttributes
+ (UIImage *)displayWithParameters:(id<NSObject>)parameter isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled
{
return @{
NSFontAttributeName: [UIFont systemFontOfSize:15.0],
NSForegroundColorAttributeName: [UIColor redColor]
};
}
ASImageNodeDrawParameters *drawParameter = (ASImageNodeDrawParameters *)parameter;

- (UIImage *)displayWithParameters:(id<NSObject>)parameter isCancelled:(asdisplaynode_iscancelled_block_t)isCancelled
{
UIImage *image = self.image;
UIImage *image = drawParameter->_image;
if (image == nil) {
return nil;
}

__instanceLock__.lock();
ASImageNodeDrawParameters drawParameter = _drawParameter;
__instanceLock__.unlock();

CGRect drawParameterBounds = drawParameter.bounds;
BOOL forceUpscaling = drawParameter.forceUpscaling;
CGSize forcedSize = drawParameter.forcedSize;
BOOL cropEnabled = drawParameter.cropEnabled;
BOOL isOpaque = drawParameter.opaque;
UIColor *backgroundColor = drawParameter.backgroundColor;
UIViewContentMode contentMode = drawParameter.contentMode;
CGFloat contentsScale = drawParameter.contentsScale;
CGRect cropDisplayBounds = drawParameter.cropDisplayBounds;
CGRect cropRect = drawParameter.cropRect;
asimagenode_modification_block_t imageModificationBlock = drawParameter.imageModificationBlock;
ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext = drawParameter.willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext = drawParameter.didDisplayNodeContentWithRenderingContext;
CGRect drawParameterBounds = drawParameter->_bounds;
BOOL forceUpscaling = drawParameter->_forceUpscaling;
CGSize forcedSize = drawParameter->_forcedSize;
BOOL cropEnabled = drawParameter->_cropEnabled;
BOOL isOpaque = drawParameter->_opaque;
UIColor *backgroundColor = drawParameter->_backgroundColor;
UIViewContentMode contentMode = drawParameter->_contentMode;
CGFloat contentsScale = drawParameter->_contentsScale;
CGRect cropDisplayBounds = drawParameter->_cropDisplayBounds;
CGRect cropRect = drawParameter->_cropRect;
asimagenode_modification_block_t imageModificationBlock = drawParameter->_imageModificationBlock;
ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext = drawParameter->_willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext = drawParameter->_didDisplayNodeContentWithRenderingContext;

BOOL hasValidCropBounds = cropEnabled && !CGRectIsEmpty(cropDisplayBounds);
CGRect bounds = (hasValidCropBounds ? cropDisplayBounds : drawParameterBounds);
Expand Down Expand Up @@ -421,9 +419,9 @@ - (UIImage *)displayWithParameters:(id<NSObject>)parameter isCancelled:(asdispla
return nil;
}

__instanceLock__.lock();
_weakCacheEntry = entry; // Retain so that the entry remains in the weak cache
__instanceLock__.unlock();
if (drawParameter->_didDrawBlock) {
drawParameter->_didDrawBlock(entry);
}

return entry.value;
}
Expand All @@ -440,7 +438,6 @@ + (ASWeakMapEntry *)contentsForkey:(ASImageNodeContentsKey *)key drawParameters:
}
ASWeakMapEntry *entry = [cache entryForKey:key];
if (entry != nil) {
// cache hit
return entry;
}
}
Expand Down Expand Up @@ -713,6 +710,15 @@ - (void)layout
_debugLabelNode.frame = (CGRect) {debugLabelOrigin, debugLabelSize};
}
}

- (NSDictionary *)debugLabelAttributes
{
return @{
NSFontAttributeName: [UIFont systemFontOfSize:15.0],
NSForegroundColorAttributeName: [UIColor redColor]
};
}

@end

#pragma mark - Extras
Expand Down
6 changes: 0 additions & 6 deletions Source/Details/_ASDisplayLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,6 @@
*/
- (void)drawRect:(CGRect)bounds withParameters:(id <NSObject>)parameters isCancelled:(AS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing;

/**
* @abstract instance version of display class method
* @see displayWithParameters:isCancelled class method
*/
- (UIImage *)displayWithParameters:(id <NSObject>)parameters isCancelled:(AS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelled;

// Called on the main thread only

/**
Expand Down
6 changes: 3 additions & 3 deletions Source/Private/ASDisplayNode+AsyncDisplay.mm
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ - (asyncdisplaykit_async_transaction_operation_block_t)_displayBlockWithAsynchro
flags = _flags;

// We always create a graphics context, unless a -display method is used, OR if we are a subnode drawing into a rasterized parent.
BOOL shouldCreateGraphicsContext = (flags.implementsInstanceImageDisplay == NO && flags.implementsImageDisplay == NO && rasterizing == NO);
BOOL shouldCreateGraphicsContext = (flags.implementsImageDisplay == NO && rasterizing == NO);
BOOL shouldBeginRasterizing = (rasterizing == NO && flags.rasterizesSubtree);
BOOL usesInstanceMethodDisplay = (flags.implementsInstanceDrawRect || flags.implementsInstanceImageDisplay);
BOOL usesImageDisplay = (flags.implementsImageDisplay || flags.implementsInstanceImageDisplay);
BOOL usesInstanceMethodDisplay = (flags.implementsInstanceDrawRect);
BOOL usesImageDisplay = (flags.implementsImageDisplay);
BOOL usesDrawRect = (flags.implementsDrawRect || flags.implementsInstanceDrawRect);

if (usesImageDisplay == NO && usesDrawRect == NO && shouldBeginRasterizing == NO) {
Expand Down
1 change: 1 addition & 0 deletions Source/Private/ASDisplayNode+FrameworkPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ __unused static NSString * _Nonnull NSStringFromASHierarchyState(ASHierarchyStat

// Thread safe way to access the bounds of the node
@property (nonatomic, assign) CGRect threadSafeBounds;
- (CGRect)_locked_threadSafeBounds;

// delegate to inform of ASInterfaceState changes (used by ASNodeController)
@property (nonatomic, weak) id<ASInterfaceStateDelegate> interfaceStateDelegate;
Expand Down
1 change: 0 additions & 1 deletion Source/Private/ASDisplayNodeInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
// whether custom drawing is enabled
unsigned implementsInstanceDrawRect:1;
unsigned implementsDrawRect:1;
unsigned implementsInstanceImageDisplay:1;
unsigned implementsImageDisplay:1;
unsigned implementsDrawParameters:1;

Expand Down