-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[ASCornerRounding] Introduce .cornerRoundingType: CALayer, Precomposited, or Clip Corners. #465
Conversation
ca1f7e4
to
273025d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow this is one of my favorite diffs of all time! Great work, we'll be putting this to use in Pinterest in short order.
} | ||
- (void)__didDisplayNodeContentWithRenderingContext:(CGContextRef)context image:(UIImage **)image drawParameters:(id _Nullable)drawParameters backgroundColor:(UIColor *)backgroundColor borderWidth:(CGFloat)borderWidth borderColor:(CGColorRef)borderColor | ||
{ | ||
if (context == NULL && *image == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure whether you're looking for && image == NULL
or && *image == nil
here.
if (*image) { | ||
*image = UIGraphicsGetImageFromCurrentImageContext(); | ||
UIGraphicsEndImageContext(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be if (image)
? And should we ensure that we only end the image context if we created one above, and not if we were passed one? The context create-readimage-destroy behavior here seems a little unclear, for instance in the caller we will actually re-generate the image and overwrite it if the caller passed us a context.
@@ -319,4 +326,10 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo | |||
|
|||
@end | |||
|
|||
@interface ASDisplayNode (InternalPropertyBridge) | |||
|
|||
@property (nonatomic, assign) CGFloat layerCornerRadius; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be worth dropping a comment on this property explaining its distinction from .cornerRadius
? Seems obvious to us today but who knows tomorrow
@Adlai-Holler Thanks for the comments! I'll try to update this soon, although under a bit of a squeeze for time (not uncommon, just sayin' it like it is! :) ). I'll certainly address your comments before landing. Anything else you'd be looking for prior to an accept? |
@appleguy Nope! I've spoken now, so I'll forever hold my peace 💞 |
for (int idx = 0; idx < 4; idx++) { | ||
if (_clipCornerLayers[idx] == nil) { | ||
_clipCornerLayers[idx] = [[CALayer alloc] init]; | ||
_clipCornerLayers[idx].zPosition = 99999; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think following code will be better performance.
It reduce accessing to array.
CALayer *layer = [[CALayer alloc] init];
layer.zPosition = 99999;
layer.delegate = self;
_clipCornerLayers[idx] = layer;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@appleguy
Thanks! I understand.
Sorry, I may be misunderstanding about retain and release.
Does returning by subscript of NSArray not create a retain?
Thanks for the suggestion!
I think this will create a retain and release call. If so, this is actually
much more expensive than the single memory indirection / pointer lookup.
Note that this is a C array for performance, not an NSArray.
…On Wed, Sep 6, 2017 at 10:36 AM Hiroshi Kimura ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In Source/ASDisplayNode.mm
<#465 (comment)>:
> +
+ UIGraphicsEndImageContext();
+ }
+ [self _layoutClipCornersIfNeeded];
+ });
+}
+
+- (void)_setClipCornerLayersVisible:(BOOL)visible
+{
+ ASPerformBlockOnMainThread(^{
+ ASDisplayNodeAssertMainThread();
+ if (visible) {
+ for (int idx = 0; idx < 4; idx++) {
+ if (_clipCornerLayers[idx] == nil) {
+ _clipCornerLayers[idx] = [[CALayer alloc] init];
+ _clipCornerLayers[idx].zPosition = 99999;
I think following code will be better performance.
It reduce accessing to array.
CALayer *layer = [[CALayer alloc] init];
layer.zPosition = 99999;
layer.delegate = self;
_clipCornerLayers[idx] = layer;
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#465 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAigA7Fo3cPGrmAWJ31SeoBjcaA63zNlks5sftgkgaJpZM4OgYHw>
.
|
I don’t have the code in front of me, but is the array an NSArray? In an earlier version when I first wrote this, I was pretty sure it was a C array, but maybe I changed it before landing.
If it is an NSArray, it will be retained and autoreleased; if a C array, it won’t be retained at all.
The additional overhead comes from the variable reference. It will add another retain, and release call in addition to the retain + autorelease from the array access.
Although this isn’t a severe issue, I think the code is pretty acceptable as it is. However, we welcome any other suggestions or PRs, even just as cleanup / refactoring!!
… On Sep 6, 2017, at 10:48 AM, Hiroshi Kimura ***@***.***> wrote:
@muukii commented on this pull request.
In Source/ASDisplayNode.mm <#465 (comment)>:
> +
+ UIGraphicsEndImageContext();
+ }
+ [self _layoutClipCornersIfNeeded];
+ });
+}
+
+- (void)_setClipCornerLayersVisible:(BOOL)visible
+{
+ ASPerformBlockOnMainThread(^{
+ ASDisplayNodeAssertMainThread();
+ if (visible) {
+ for (int idx = 0; idx < 4; idx++) {
+ if (_clipCornerLayers[idx] == nil) {
+ _clipCornerLayers[idx] = [[CALayer alloc] init];
+ _clipCornerLayers[idx].zPosition = 99999;
@appleguy <https://github.com/appleguy>
Thanks! I understand.
Sorry, I may be misunderstanding about retain and release.
Does returning by subscript of NSArray not create a retain?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#465 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAigA3t5ss25Tc_53yGrBKDUl8Z4tJoeks5sftrdgaJpZM4OgYHw>.
|
@nguyenhuy @maicki @Adlai-Holler could I get an accept? Otherwise it won't let me land :(. Feel free to merge this at the same time, too! There are some good further improvements that could be made to this, but it is useful in its current state, and I won't have time to invest in an example project or other upgrades in the near future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepting per @Adlai-Holler's comments.
…ted, or Clip Corners. (TextureGroup#465) * [ASCornerRounding] Initial (untested) implementation of ASCornerRounding features. * [ASCornerRounding] Working version of both clip corners and precomposited corners. * [ASCornerRounding] Improve factoring and documentation of corner rounding features. * [ASCornerRounding] Some final fixups. * Add entry to changelog for .cornerRoundingType
|
||
CGFloat _cornerRadius; | ||
ASCornerRoundingType _cornerRoundingType; | ||
CALayer *_clipCornerLayers[4]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @appleguy Scott! How are these ObjC objects retained in this C array? Is there some ARC magic I'm clearly not aware of? -- Greg
For at least two years, we've gotten requests from the community to support alternatives to CALayer's .cornerRadius. Even on today's devices, this property still has a performance cost (including on early 64-bit SoCs, like the A7 and A8). In the cases where many views need to be rounded and exist on screens with movement, the overhead can become very significant.
This new ASCornerRounding property supports all of the modes described on the Texture website, with a minimal change in our API. This is achieved by using the .backgroundColor property to influence the mode where appropriate. In the future, I'll improve the logic to be able to detect certain undesired conditions, like non-opaque background with ClipCorner type.
http://texturegroup.org/docs/corner-rounding.html
This has already been tested with ASDKgram, including code that automatically advances through each of the corner rounding modes to ensure the transitions between them are smooth.
It would be great to get a review and work towards an accept soon, but before landing this, I'll add snapshot tests and look for opportunities to improve documentation. Suggestions welcome!
It is known that there is a subtle difference in rounding between the arc-based clip corners, and the iOS 7-style UIBezierPath precomposited corners. This is described here: https://www.paintcodeapp.com/blogpost/code-for-ios-7-rounded-rectangles . The difference is not noticeable for most use cases (and of these modes, Precomposited will be used the most, + already uses the newer style). Thus I feel confident revisiting this later for ClipCorner type.
Very brief search for some folks requesting guidance / samples / support for this:
facebookarchive/AsyncDisplayKit#1446
facebookarchive/AsyncDisplayKit#979