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

Revert "Optimize drawing code + add examples how to round corners (#996) #1055

Merged
merged 1 commit into from
Jul 31, 2018
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
16 changes: 8 additions & 8 deletions AsyncDisplayKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
509E68631B3AEDB4009B9150 /* ASCollectionViewLayoutController.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */; };
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.m */; };
509E68651B3AEDC5009B9150 /* CoreGraphics+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.mm */; };
509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */; };
636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBC452DA1C5BF64600B16017 /* NSArray+Diffing.mm */; };
636EA1A51C7FF4EF00EE152F /* ASDefaultPlayButton.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */; };
680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85DC1CE29AB700EDD713 /* ASNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -176,7 +176,7 @@
7AB338671C55B3460055FDE8 /* ASRelativeLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
7AB338691C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */; };
8021EC1D1D2B00B100799119 /* UIImage+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */; };
8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */; };
81E95C141D62639600336598 /* ASTextNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 81E95C131D62639600336598 /* ASTextNodeSnapshotTests.m */; };
83A7D95B1D44547700BF333E /* ASWeakMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A7D9591D44542100BF333E /* ASWeakMap.m */; };
83A7D95C1D44548100BF333E /* ASWeakMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A7D9581D44542100BF333E /* ASWeakMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -621,7 +621,7 @@
205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionViewLayoutController.h; sourceTree = "<group>"; };
205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewLayoutController.m; sourceTree = "<group>"; };
205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CoreGraphics+ASConvenience.h"; sourceTree = "<group>"; };
205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "CoreGraphics+ASConvenience.mm"; sourceTree = "<group>"; };
205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CoreGraphics+ASConvenience.m"; sourceTree = "<group>"; };
242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASBasicImageDownloaderTests.m; sourceTree = "<group>"; };
2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASCollectionViewFlowLayoutInspectorTests.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
254C6B511BF8FE6D003EC431 /* ASTextKitTruncationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextKitTruncationTests.mm; sourceTree = "<group>"; };
Expand Down Expand Up @@ -734,7 +734,7 @@
7A06A7391C35F08800FE8DAA /* ASRelativeLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRelativeLayoutSpec.h; sourceTree = "<group>"; };
7AB338681C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRelativeLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ASConvenience.h"; sourceTree = "<group>"; };
8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIImage+ASConvenience.mm"; sourceTree = "<group>"; };
8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ASConvenience.m"; sourceTree = "<group>"; };
81E95C131D62639600336598 /* ASTextNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTextNodeSnapshotTests.m; sourceTree = "<group>"; };
81EE384D1C8E94F000456208 /* ASRunLoopQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASRunLoopQueue.h; path = ../ASRunLoopQueue.h; sourceTree = "<group>"; };
81EE384E1C8E94F000456208 /* ASRunLoopQueue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASRunLoopQueue.mm; path = ../ASRunLoopQueue.mm; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1234,7 +1234,7 @@
68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */,
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */,
8021EC1A1D2B00B100799119 /* UIImage+ASConvenience.h */,
8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.mm */,
8021EC1B1D2B00B100799119 /* UIImage+ASConvenience.m */,
CC55A70B1E529FA200594372 /* UIResponder+AsyncDisplayKit.h */,
CC55A70C1E529FA200594372 /* UIResponder+AsyncDisplayKit.m */,
);
Expand Down Expand Up @@ -1422,7 +1422,7 @@
CC3B20871C3F7A5400798563 /* ASWeakSet.h */,
CC3B20881C3F7A5400798563 /* ASWeakSet.m */,
205F0E1F1B376416007741D0 /* CoreGraphics+ASConvenience.h */,
205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.mm */,
205F0E201B376416007741D0 /* CoreGraphics+ASConvenience.m */,
DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */,
DBC452DA1C5BF64600B16017 /* NSArray+Diffing.mm */,
CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */,
Expand Down Expand Up @@ -2405,7 +2405,7 @@
CCA282C51E9EAE630037E8B7 /* ASLayerBackingTipProvider.m in Sources */,
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.m in Sources */,
B35061F91B010EFD0018CF92 /* ASControlNode.mm in Sources */,
8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.mm in Sources */,
8021EC1F1D2B00B100799119 /* UIImage+ASConvenience.m in Sources */,
CCAA0B80206ADBF30057B336 /* ASRecursiveUnfairLock.m in Sources */,
CCBDDD0620C62A2D00CBA922 /* ASMainThreadDeallocation.mm in Sources */,
B35062181B010EFD0018CF92 /* ASDataController.mm in Sources */,
Expand Down Expand Up @@ -2504,7 +2504,7 @@
6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */,
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m in Sources */,
509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.mm in Sources */,
509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */,
254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */,
34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */,
254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.m in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
- Reduced binary size by disabling exception support (which we don't use.) [Adlai Holler](https://github.com/Adlai-Holler)
- Create and set delegate for clip corner layers within ASDisplayNode [Michael Schneider](https://github.com/maicki) [#1029](https://github.com/TextureGroup/Texture/pull/1029)
- Improve locking situation in ASVideoPlayerNode [Michael Schneider](https://github.com/maicki) [#1042](https://github.com/TextureGroup/Texture/pull/1042)
- Optimize drawing code + add examples how to round corners. [Michael Schneider](https://github.com/maicki)


## 2.7
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)
Expand Down
55 changes: 23 additions & 32 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
#import <AsyncDisplayKit/ASWeakProxy.h>
#import <AsyncDisplayKit/ASResponderChainEnumerator.h>
#import <AsyncDisplayKit/ASTipsController.h>
#import <AsyncDisplayKit/CoreGraphics+ASConvenience.h>

// Conditionally time these scopes to our debug ivars (only exist in debug/profile builds)
#if TIME_DISPLAYNODE_OPS
Expand Down Expand Up @@ -1509,7 +1508,7 @@ - (void)_pendingNodeDidDisplay:(ASDisplayNode *)node
__instanceLock__.lock();
if (_placeholderLayer.superlayer && !placeholderShouldPersist) {
void (^cleanupBlock)() = ^{
[self->_placeholderLayer removeFromSuperlayer];
[_placeholderLayer removeFromSuperlayer];
};

if (_placeholderFadeDuration > 0.0 && ASInterfaceStateIncludesVisible(self.interfaceState)) {
Expand Down Expand Up @@ -1667,29 +1666,24 @@ - (void)_updateClipCornerLayerContentsWithRadius:(CGFloat)radius backgroundColor
CGSize size = CGSizeMake(radius + 1, radius + 1);
ASGraphicsBeginImageContextWithOptions(size, NO, self.contentsScaleForDisplay);

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRef ctx = UIGraphicsGetCurrentContext();
if (isRight == YES) {
CGContextTranslateCTM(context, -radius + 1, 0);
CGContextTranslateCTM(ctx, -radius + 1, 0);
}
if (isTop == YES) {
CGContextTranslateCTM(context, 0, -radius + 1);
CGContextTranslateCTM(ctx, 0, -radius + 1);
}

CGMutablePathRef roundedPath = CGPathCreateMutable();
CGPathRef addedPath = ASCGRoundedPathCreate(CGRectMake(0, 0, radius * 2, radius * 2), radius);
CGPathAddPath(roundedPath, NULL, addedPath);
CGPathAddRect(roundedPath, NULL, CGRectMake(-1, -1, radius * 2 + 1, radius * 2 + 1));
CGContextAddPath(context, roundedPath);
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextEOFillPath(context);

// No lock needed, as _clipCornerLayers is only modified on the main thread.
_clipCornerLayers[idx].contents = (id)(ASGraphicsGetImageAndEndCurrentContext().CGImage);
_clipCornerLayers[idx].bounds = CGRectMake(0.0, 0.0, size.width, size.height);
_clipCornerLayers[idx].anchorPoint = CGPointMake(isRight ? 1.0 : 0.0, isTop ? 1.0 : 0.0);
UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, radius * 2, radius * 2) cornerRadius:radius];
[roundedRect setUsesEvenOddFillRule:YES];
[roundedRect appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(-1, -1, radius * 2 + 1, radius * 2 + 1)]];
[backgroundColor setFill];
[roundedRect fill];

CGPathRelease(addedPath);
CGPathRelease(roundedPath);
// No lock needed, as _clipCornerLayers is only modified on the main thread.
CALayer *clipCornerLayer = _clipCornerLayers[idx];
clipCornerLayer.contents = (id)(ASGraphicsGetImageAndEndCurrentContext().CGImage);
clipCornerLayer.bounds = CGRectMake(0.0, 0.0, size.width, size.height);
clipCornerLayer.anchorPoint = CGPointMake(isRight ? 1.0 : 0.0, isTop ? 1.0 : 0.0);
}
[self _layoutClipCornersIfNeeded];
});
Expand Down Expand Up @@ -1874,10 +1868,7 @@ - (void)didDisplayAsyncLayer:(_ASDisplayLayer *)layer
[self displayDidFinish];
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)displayWillStart {}
#pragma clang diagnostic pop
- (void)displayWillStartAsynchronously:(BOOL)asynchronously
{
ASDisplayNodeAssertMainThread();
Expand Down Expand Up @@ -2988,11 +2979,11 @@ - (void)didExitHierarchy
if (ASInterfaceStateIncludesVisible(self.pendingInterfaceState)) {
void(^exitVisibleInterfaceState)(void) = ^{
// This block intentionally retains self.
self->__instanceLock__.lock();
unsigned isStillInHierarchy = self->_flags.isInHierarchy;
BOOL isVisible = ASInterfaceStateIncludesVisible(self->_pendingInterfaceState);
ASInterfaceState newState = (self->_pendingInterfaceState & ~ASInterfaceStateVisible);
self->__instanceLock__.unlock();
__instanceLock__.lock();
unsigned isStillInHierarchy = _flags.isInHierarchy;
BOOL isVisible = ASInterfaceStateIncludesVisible(_pendingInterfaceState);
ASInterfaceState newState = (_pendingInterfaceState & ~ASInterfaceStateVisible);
__instanceLock__.unlock();
if (!isStillInHierarchy && isVisible) {
#if ENABLE_NEW_EXIT_HIERARCHY_BEHAVIOR
if (![self supportsRangeManagedInterfaceState]) {
Expand Down Expand Up @@ -3151,8 +3142,8 @@ - (void)applyPendingInterfaceState:(ASInterfaceState)newPendingState
[self setDisplaySuspended:YES];
//schedule clear contents on next runloop
dispatch_async(dispatch_get_main_queue(), ^{
ASDN::MutexLocker l(self->__instanceLock__);
if (ASInterfaceStateIncludesDisplay(self->_interfaceState) == NO) {
ASDN::MutexLocker l(__instanceLock__);
if (ASInterfaceStateIncludesDisplay(_interfaceState) == NO) {
[self clearContents];
}
});
Expand All @@ -3169,8 +3160,8 @@ - (void)applyPendingInterfaceState:(ASInterfaceState)newPendingState
[[self asyncLayer] cancelAsyncDisplay];
//schedule clear contents on next runloop
dispatch_async(dispatch_get_main_queue(), ^{
ASDN::MutexLocker l(self->__instanceLock__);
if (ASInterfaceStateIncludesDisplay(self->_interfaceState) == NO) {
ASDN::MutexLocker l(__instanceLock__);
if (ASInterfaceStateIncludesDisplay(_interfaceState) == NO) {
[self clearContents];
}
});
Expand Down
38 changes: 7 additions & 31 deletions Source/ASImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -737,43 +737,19 @@ asimagenode_modification_block_t ASImageNodeRoundBorderModificationBlock(CGFloat
{
return ^(UIImage *originalImage) {
ASGraphicsBeginImageContextWithOptions(originalImage.size, NO, originalImage.scale);

CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath *roundOutline = [UIBezierPath bezierPathWithOvalInRect:(CGRect){CGPointZero, originalImage.size}];

CGRect rect = (CGRect){CGPointZero, originalImage.size};
CGMutablePathRef path = CGPathCreateMutable();

CGPathAddEllipseInRect(path, NULL, rect);
CGContextAddPath(context, path);

// Make the image round
CGContextClip(context);

// Although drawAtPoint:blendMode: would consider the CTM already, we are using CGContext* functions for drawing
// the image instead calling drawAtPoint:blendMode. This will save use 50% of retain calls for the image
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextTranslateCTM(context, 0, CGRectGetMaxY(rect) + CGRectGetMinY(rect));
CGContextScaleCTM(context, originalImage.scale, -originalImage.scale);
CGContextSetAlpha(context, 1.0);
CGContextDrawImage(context, rect, originalImage.CGImage);
[roundOutline addClip];

CGPathRelease(path);
// Draw the original image
[originalImage drawAtPoint:CGPointZero blendMode:kCGBlendModeCopy alpha:1];

// Draw a border on top.
if (borderWidth > 0.0) {
// Begin a new path for the border
CGContextBeginPath(context);

CGFloat strokeThickness = borderWidth;
CGFloat strokeInset = floor((strokeThickness + 1.0f) / 2.0f) - 1.0f;
CGPathRef path = CGPathCreateWithEllipseInRect(CGRectInset(rect, strokeInset, strokeInset), NULL);
CGContextAddPath(context, path);

CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
CGContextSetLineWidth(context, borderWidth);
CGContextStrokePath(context);

CGPathRelease(path);
[borderColor setStroke];
[roundOutline setLineWidth:borderWidth];
[roundOutline stroke];
}

return ASGraphicsGetImageAndEndCurrentContext();
Expand Down
2 changes: 1 addition & 1 deletion Source/Base/ASBaseDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
#endif
#endif

#define AS_OVERLOADABLE __attribute__((overloadable))
#define ASOVERLOADABLE __attribute__((overloadable))


#if __has_attribute(noescape)
Expand Down
9 changes: 1 addition & 8 deletions Source/Details/CoreGraphics+ASConvenience.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

#import <Foundation/Foundation.h>

#import <CoreGraphics/CoreGraphics.h>
#import <tgmath.h>
#import <UIKit/UIBezierPath.h>

#import <AsyncDisplayKit/ASBaseDefines.h>

Expand Down Expand Up @@ -56,11 +56,4 @@ ASDISPLAYNODE_INLINE BOOL CGSizeEqualToSizeWithIn(CGSize size1, CGSize size2, CG
return fabs(size1.width - size2.width) < delta && fabs(size1.height - size2.height) < delta;
};

AS_OVERLOADABLE AS_WARN_UNUSED_RESULT AS_EXTERN CGPathRef ASCGRoundedPathCreate(CGRect rect, UIRectCorner corners, CGSize cornerRadii);

AS_OVERLOADABLE ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT CGPathRef ASCGRoundedPathCreate(CGRect rect, CGFloat cornerRadius) {
return ASCGRoundedPathCreate(rect, UIRectCornerAllCorners, CGSizeMake(cornerRadius, cornerRadius));
}


NS_ASSUME_NONNULL_END
19 changes: 19 additions & 0 deletions Source/Details/CoreGraphics+ASConvenience.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// CoreGraphics+ASConvenience.m
// Texture
//
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//

#import <AsyncDisplayKit/CoreGraphics+ASConvenience.h>

Loading