Skip to content

Commit

Permalink
Revert "Add support for clipping only specific corners, add unit tests (
Browse files Browse the repository at this point in the history
TextureGroup#1415)"

This reverts commit fe1cb1c.
  • Loading branch information
Kevin Smith authored and wiseoldduck committed Jul 13, 2019
1 parent a074453 commit 7f11b92
Show file tree
Hide file tree
Showing 18 changed files with 42 additions and 170 deletions.
8 changes: 0 additions & 8 deletions Source/ASDisplayNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,14 +666,6 @@ AS_EXTERN NSInteger const ASDefaultDrawingPriority;
*/
@property CGFloat cornerRadius; // default=0.0

/** @abstract Which corners to mask when rounding corners.
*
* @note This option cannot be changed when using iOS < 11
* and using ASCornerRoundingTypeDefaultSlowCALayer. Use a different corner rounding type to implement not-all-corners
* rounding in prior versions of iOS.
*/
@property CACornerMask maskedCorners; // default=all corners.

@property BOOL clipsToBounds; // default==NO
@property (getter=isHidden) BOOL hidden; // default==NO
@property (getter=isOpaque) BOOL opaque; // default==YES
Expand Down
84 changes: 36 additions & 48 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ - (void)_initializeInstance

_contentsScaleForDisplay = ASScreenScale();
_drawingPriority = ASDefaultTransactionPriority;
_maskedCorners = kASCACornerAllCorners;

_primitiveTraitCollection = ASPrimitiveTraitCollectionMakeDefault();

Expand Down Expand Up @@ -1435,17 +1434,17 @@ - (void)recursivelySetNeedsDisplayAtScale:(CGFloat)contentsScale
- (void)_layoutClipCornersIfNeeded
{
ASDisplayNodeAssertMainThread();
if (_clipCornerLayers[0] == nil && _clipCornerLayers[1] == nil && _clipCornerLayers[2] == nil &&
_clipCornerLayers[3] == nil) {
if (_clipCornerLayers[0] == nil) {
return;
}

CGSize boundsSize = self.bounds.size;
for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) {
BOOL isTop = (idx == 0 || idx == 1);
BOOL isRight = (idx == 1 || idx == 3);
BOOL isRight = (idx == 1 || idx == 2);
if (_clipCornerLayers[idx]) {
_clipCornerLayers[idx].position = CGPointMake(isRight ? boundsSize.width : 0.0, isTop ? 0.0 : boundsSize.height);
// Note the Core Animation coordinates are reversed for y; 0 is at the bottom.
_clipCornerLayers[idx].position = CGPointMake(isRight ? boundsSize.width : 0.0, isTop ? boundsSize.height : 0.0);
[_layer addSublayer:_clipCornerLayers[idx]];
}
}
Expand All @@ -1455,16 +1454,11 @@ - (void)_updateClipCornerLayerContentsWithRadius:(CGFloat)radius backgroundColor
{
ASPerformBlockOnMainThread(^{
for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) {
// Skip corners that aren't clipped (we have already set up & torn down layers based on maskedCorners.)
if (_clipCornerLayers[idx] == nil) {
continue;
}

// Layers are, in order: Top Left, Top Right, Bottom Left, Bottom Right, which mirrors CACornerMask.
// Layers are, in order: Top Left, Top Right, Bottom Right, Bottom Left.
// anchorPoint is Bottom Left at 0,0 and Top Right at 1,1.
BOOL isTop = (idx == 0 || idx == 1);
BOOL isRight = (idx == 1 || idx == 3);

BOOL isRight = (idx == 1 || idx == 2);
CGSize size = CGSizeMake(radius + 1, radius + 1);
UIImage *newContents = ASGraphicsCreateImageWithOptions(size, NO, self.contentsScaleForDisplay, nil, nil, ^{
CGContextRef ctx = UIGraphicsGetCurrentContext();
Expand All @@ -1482,59 +1476,56 @@ - (void)_updateClipCornerLayerContentsWithRadius:(CGFloat)radius backgroundColor
});

// No lock needed, as _clipCornerLayers is only modified on the main thread.
unowned CALayer *clipCornerLayer = _clipCornerLayers[idx];
CALayer *clipCornerLayer = _clipCornerLayers[idx];
clipCornerLayer.contents = (id)(newContents.CGImage);
clipCornerLayer.bounds = CGRectMake(0.0, 0.0, size.width, size.height);
clipCornerLayer.anchorPoint = CGPointMake(isRight ? 1.0 : 0.0, isTop ? 0.0 : 1.0);
clipCornerLayer.anchorPoint = CGPointMake(isRight ? 1.0 : 0.0, isTop ? 1.0 : 0.0);
}
[self _layoutClipCornersIfNeeded];
});
}

- (void)_setClipCornerLayersVisible:(CACornerMask)visibleCornerLayers
- (void)_setClipCornerLayersVisible:(BOOL)visible
{
ASPerformBlockOnMainThread(^{
ASDisplayNodeAssertMainThread();
for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) {
BOOL visible = (0 != (visibleCornerLayers & (1 << idx)));
if (visible == (_clipCornerLayers[idx] != nil)) {
continue;
} else if (visible) {
static ASDisplayNodeCornerLayerDelegate *clipCornerLayers;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
clipCornerLayers = [[ASDisplayNodeCornerLayerDelegate alloc] init];
});
_clipCornerLayers[idx] = [[CALayer alloc] init];
_clipCornerLayers[idx].zPosition = 99999;
_clipCornerLayers[idx].delegate = clipCornerLayers;
} else {
if (visible) {
for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) {
if (_clipCornerLayers[idx] == nil) {
static ASDisplayNodeCornerLayerDelegate *clipCornerLayers;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
clipCornerLayers = [[ASDisplayNodeCornerLayerDelegate alloc] init];
});
_clipCornerLayers[idx] = [[CALayer alloc] init];
_clipCornerLayers[idx].zPosition = 99999;
_clipCornerLayers[idx].delegate = clipCornerLayers;
}
}
[self _updateClipCornerLayerContentsWithRadius:_cornerRadius backgroundColor:self.backgroundColor];
} else {
for (int idx = 0; idx < NUM_CLIP_CORNER_LAYERS; idx++) {
[_clipCornerLayers[idx] removeFromSuperlayer];
_clipCornerLayers[idx] = nil;
}
}
[self _updateClipCornerLayerContentsWithRadius:_cornerRadius backgroundColor:self.backgroundColor];
});
}

- (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType
cornerRadius:(CGFloat)newCornerRadius
maskedCorners:(CACornerMask)newMaskedCorners
- (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType cornerRadius:(CGFloat)newCornerRadius
{
__instanceLock__.lock();
CGFloat oldCornerRadius = _cornerRadius;
ASCornerRoundingType oldRoundingType = _cornerRoundingType;
CACornerMask oldMaskedCorners = _maskedCorners;

_cornerRadius = newCornerRadius;
_cornerRoundingType = newRoundingType;
_maskedCorners = newMaskedCorners;
__instanceLock__.unlock();

ASPerformBlockOnMainThread(^{
ASDisplayNodeAssertMainThread();

if (oldRoundingType != newRoundingType || oldCornerRadius != newCornerRadius || oldMaskedCorners != newMaskedCorners) {
if (oldRoundingType != newRoundingType || oldCornerRadius != newCornerRadius) {
if (oldRoundingType == ASCornerRoundingTypeDefaultSlowCALayer) {
if (newRoundingType == ASCornerRoundingTypePrecomposited) {
self.layerCornerRadius = 0.0;
Expand All @@ -1546,16 +1537,14 @@ - (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType
}
else if (newRoundingType == ASCornerRoundingTypeClipping) {
self.layerCornerRadius = 0.0;
[self _setClipCornerLayersVisible:newMaskedCorners];
[self _setClipCornerLayersVisible:YES];
} else if (newRoundingType == ASCornerRoundingTypeDefaultSlowCALayer) {
self.layerCornerRadius = newCornerRadius;
self.layerMaskedCorners = newMaskedCorners;
}
}
else if (oldRoundingType == ASCornerRoundingTypePrecomposited) {
if (newRoundingType == ASCornerRoundingTypeDefaultSlowCALayer) {
self.layerCornerRadius = newCornerRadius;
self.layerMaskedCorners = newMaskedCorners;
[self setNeedsDisplay];
}
else if (newRoundingType == ASCornerRoundingTypePrecomposited) {
Expand All @@ -1564,23 +1553,22 @@ - (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType
[self setNeedsDisplay];
}
else if (newRoundingType == ASCornerRoundingTypeClipping) {
[self _setClipCornerLayersVisible:newMaskedCorners];
[self _setClipCornerLayersVisible:YES];
[self setNeedsDisplay];
}
}
else if (oldRoundingType == ASCornerRoundingTypeClipping) {
if (newRoundingType == ASCornerRoundingTypeDefaultSlowCALayer) {
self.layerCornerRadius = newCornerRadius;
[self _setClipCornerLayersVisible:kNilOptions];
[self _setClipCornerLayersVisible:NO];
}
else if (newRoundingType == ASCornerRoundingTypePrecomposited) {
[self _setClipCornerLayersVisible:kNilOptions];
[self _setClipCornerLayersVisible:NO];
[self displayImmediately];
}
else if (newRoundingType == ASCornerRoundingTypeClipping) {
// Clip corners already exist, but the radius and/or maskedCorners have changed.
// This method will add & remove them, and subsequently redraw them.
[self _setClipCornerLayersVisible:newMaskedCorners];
// Clip corners already exist, but the radius has changed.
[self _updateClipCornerLayerContentsWithRadius:newCornerRadius backgroundColor:self.backgroundColor];
}
}
}
Expand Down
1 change: 0 additions & 1 deletion Source/Details/UIView+ASConvenience.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) CGFloat zPosition;
@property (nonatomic) CGPoint anchorPoint;
@property (nonatomic) CGFloat cornerRadius;
@property (nonatomic) CACornerMask maskedCorners API_AVAILABLE(ios(11), tvos(11));
@property (nullable, nonatomic) id contents;
@property (nonatomic, copy) NSString *contentsGravity;
@property (nonatomic) CGRect contentsRect;
Expand Down
10 changes: 2 additions & 8 deletions Source/Private/ASDisplayNode+AsyncDisplay.mm
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,13 @@ - (void)__willDisplayNodeContentWithRenderingContext:(CGContextRef)context drawP
ASCornerRoundingType cornerRoundingType = _cornerRoundingType;
CGFloat cornerRadius = _cornerRadius;
ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext = _willDisplayNodeContentWithRenderingContext;
CACornerMask maskedCorners = _maskedCorners;
__instanceLock__.unlock();

if (cornerRoundingType == ASCornerRoundingTypePrecomposited && cornerRadius > 0.0) {
ASDisplayNodeAssert(context == UIGraphicsGetCurrentContext(), @"context is expected to be pushed on UIGraphics stack %@", self);
// TODO: This clip path should be removed if we are rasterizing.
CGRect boundingBox = CGContextGetClipBoundingBox(context);
CGSize radii = CGSizeMake(cornerRadius, cornerRadius);
[[UIBezierPath bezierPathWithRoundedRect:boundingBox byRoundingCorners:maskedCorners cornerRadii:radii] addClip];
[[UIBezierPath bezierPathWithRoundedRect:boundingBox cornerRadius:cornerRadius] addClip];
}

if (willDisplayNodeContentWithRenderingContext) {
Expand All @@ -310,7 +308,6 @@ - (void)__didDisplayNodeContentWithRenderingContext:(CGContextRef)context image:
CGFloat cornerRadius = _cornerRadius;
CGFloat contentsScale = _contentsScaleForDisplay;
ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext = _didDisplayNodeContentWithRenderingContext;
CACornerMask maskedCorners = _maskedCorners;
__instanceLock__.unlock();

if (context != NULL) {
Expand All @@ -336,10 +333,7 @@ - (void)__didDisplayNodeContentWithRenderingContext:(CGContextRef)context image:
ASDisplayNodeAssert(UIGraphicsGetCurrentContext(), @"context is expected to be pushed on UIGraphics stack %@", self);

UIBezierPath *roundedHole = [UIBezierPath bezierPathWithRect:bounds];
CGSize radii = CGSizeMake(cornerRadius * contentsScale, cornerRadius * contentsScale);
[roundedHole appendPath:[UIBezierPath bezierPathWithRoundedRect:bounds
byRoundingCorners:maskedCorners
cornerRadii:radii]];
[roundedHole appendPath:[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:cornerRadius * contentsScale]];
roundedHole.usesEvenOddFillRule = YES;

UIBezierPath *roundedPath = nil;
Expand Down
40 changes: 2 additions & 38 deletions Source/Private/ASDisplayNode+UIViewBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,7 @@ - (CGFloat)cornerRadius

- (void)setCornerRadius:(CGFloat)newCornerRadius
{
[self updateCornerRoundingWithType:self.cornerRoundingType
cornerRadius:newCornerRadius
maskedCorners:self.maskedCorners];
[self updateCornerRoundingWithType:self.cornerRoundingType cornerRadius:newCornerRadius];
}

- (ASCornerRoundingType)cornerRoundingType
Expand All @@ -221,20 +219,7 @@ - (ASCornerRoundingType)cornerRoundingType

- (void)setCornerRoundingType:(ASCornerRoundingType)newRoundingType
{
[self updateCornerRoundingWithType:newRoundingType cornerRadius:self.cornerRadius maskedCorners:self.maskedCorners];
}

- (CACornerMask)maskedCorners
{
AS::MutexLocker l(__instanceLock__);
return _maskedCorners;
}

- (void)setMaskedCorners:(CACornerMask)newMaskedCorners
{
[self updateCornerRoundingWithType:self.cornerRoundingType
cornerRadius:self.cornerRadius
maskedCorners:newMaskedCorners];
[self updateCornerRoundingWithType:newRoundingType cornerRadius:self.cornerRadius];
}

- (NSString *)contentsGravity
Expand Down Expand Up @@ -1017,27 +1002,6 @@ - (void)setLayerCornerRadius:(CGFloat)newLayerCornerRadius
_setToLayer(cornerRadius, newLayerCornerRadius);
}

- (CACornerMask)layerMaskedCorners
{
_bridge_prologue_read;
if (AS_AVAILABLE_IOS_TVOS(11, 11)) {
return _getFromLayer(maskedCorners);
} else {
return kASCACornerAllCorners;
}
}

- (void)setLayerMaskedCorners:(CACornerMask)newLayerMaskedCorners
{
_bridge_prologue_write;
if (AS_AVAILABLE_IOS_TVOS(11, 11)) {
_setToLayer(maskedCorners, newLayerMaskedCorners);
} else {
ASDisplayNodeAssert(newLayerMaskedCorners == kASCACornerAllCorners,
@"Cannot change maskedCorners property in iOS < 11 while using DefaultSlowCALayer rounding.");
}
}

- (BOOL)_locked_insetsLayoutMarginsFromSafeArea
{
DISABLED_ASAssertLocked(__instanceLock__);
Expand Down
12 changes: 2 additions & 10 deletions Source/Private/ASDisplayNodeInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest
#define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4

#define TIME_DISPLAYNODE_OPS 0 // If you're using this information frequently, try: (DEBUG || PROFILE)
static constexpr CACornerMask kASCACornerAllCorners =
kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner | kCALayerMaxXMaxYCorner;

#define NUM_CLIP_CORNER_LAYERS 4

Expand Down Expand Up @@ -225,7 +223,6 @@ static constexpr CACornerMask kASCACornerAllCorners =
// Corner Radius support
CGFloat _cornerRadius;
CALayer *_clipCornerLayers[NUM_CLIP_CORNER_LAYERS];
CACornerMask _maskedCorners;

ASDisplayNodeContextModifier _willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier _didDisplayNodeContentWithRenderingContext;
Expand Down Expand Up @@ -320,10 +317,8 @@ static constexpr CACornerMask kASCACornerAllCorners =
/// Display the node's view/layer immediately on the current thread, bypassing the background thread rendering. Will be deprecated.
- (void)displayImmediately;

/// Refreshes any precomposited or drawn clip corners, setting up state as required to transition corner config.
- (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType
cornerRadius:(CGFloat)newCornerRadius
maskedCorners:(CACornerMask)newMaskedCorners;
/// Refreshes any precomposited or drawn clip corners, setting up state as required to transition radius or rounding type.
- (void)updateCornerRoundingWithType:(ASCornerRoundingType)newRoundingType cornerRadius:(CGFloat)newCornerRadius;

/// Alternative initialiser for backing with a custom view class. Supports asynchronous display with _ASDisplayView subclasses.
- (instancetype)initWithViewClass:(Class)viewClass;
Expand Down Expand Up @@ -369,9 +364,6 @@ static constexpr CACornerMask kASCACornerAllCorners =

@property (nonatomic) CGFloat layerCornerRadius;

/// NOTE: Changing this to non-default under iOS < 11 will make an assertion (for the end user to see.)
@property (nonatomic) CACornerMask layerMaskedCorners;

- (BOOL)_locked_insetsLayoutMarginsFromSafeArea;

@end
Expand Down
14 changes: 0 additions & 14 deletions Source/Private/_ASPendingState.mm
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
int setPreservesSuperviewLayoutMargins:1;
int setInsetsLayoutMarginsFromSafeArea:1;
int setActions:1;
int setMaskedCorners : 1;
} ASPendingStateFlags;


Expand Down Expand Up @@ -225,7 +224,6 @@ ASDISPLAYNODE_INLINE void ASPendingStateApplyMetricsToLayer(_ASPendingState *sta
@synthesize preservesSuperviewLayoutMargins=preservesSuperviewLayoutMargins;
@synthesize insetsLayoutMarginsFromSafeArea=insetsLayoutMarginsFromSafeArea;
@synthesize actions=actions;
@synthesize maskedCorners = maskedCorners;

static CGColorRef blackColorRef = NULL;
static UIColor *defaultTintColor = nil;
Expand Down Expand Up @@ -463,12 +461,6 @@ - (void)setCornerRadius:(CGFloat)newCornerRadius
_stateToApplyFlags.setCornerRadius = YES;
}

- (void)setMaskedCorners:(CACornerMask)newMaskedCorners
{
maskedCorners = newMaskedCorners;
_stateToApplyFlags.setMaskedCorners = YES;
}

- (void)setContentMode:(UIViewContentMode)newContentMode
{
contentMode = newContentMode;
Expand Down Expand Up @@ -988,12 +980,6 @@ - (void)applyToLayer:(CALayer *)layer
if (flags.setCornerRadius)
layer.cornerRadius = cornerRadius;

if (AS_AVAILABLE_IOS_TVOS(11, 11)) {
if (flags.setMaskedCorners) {
layer.maskedCorners = maskedCorners;
}
}

if (flags.setContentMode)
layer.contentsGravity = ASDisplayNodeCAContentsGravityFromUIContentMode(contentMode);

Expand Down
Loading

0 comments on commit 7f11b92

Please sign in to comment.