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

[ASCornerRounding] Introduce .cornerRoundingType: CALayer, Precomposited, or Clip Corners. #465

Merged
merged 9 commits into from
Sep 18, 2017

Conversation

appleguy
Copy link
Member

@appleguy appleguy commented Jul 23, 2017

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

Copy link
Member

@Adlai-Holler Adlai-Holler left a 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) {
Copy link
Member

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();
}
Copy link
Member

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;
Copy link
Member

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

@appleguy
Copy link
Member Author

@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?

@Adlai-Holler
Copy link
Member

@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;
Copy link
Contributor

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;

Copy link
Contributor

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?

@appleguy
Copy link
Member Author

appleguy commented Sep 6, 2017 via email

@appleguy
Copy link
Member Author

appleguy commented Sep 9, 2017 via email

@appleguy
Copy link
Member Author

appleguy commented Sep 18, 2017

@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.

Copy link
Member

@nguyenhuy nguyenhuy left a 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.

@nguyenhuy nguyenhuy merged commit e330e57 into master Sep 18, 2017
bernieperez pushed a commit to AtomTickets/Texture that referenced this pull request Apr 25, 2018
…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];
Copy link
Contributor

@bolsinga bolsinga Mar 15, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants