Share a singleton shadower for all cases when shadow isn't drawn, fix issues (#2511)

This commit is contained in:
Adlai Holler
2016-10-30 15:34:29 -07:00
committed by appleguy
parent 611894329a
commit 3eb7a307fa
8 changed files with 54 additions and 35 deletions

View File

@@ -102,10 +102,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
if (self = [super init]) {
// Load default values from superclass.
_shadowOffset = [super shadowOffset];
CGColorRef superColor = [super shadowColor];
if (superColor != NULL) {
_shadowColor = CGColorRetain(superColor);
}
_shadowColor = CGColorRetain([super shadowColor]);
_shadowOpacity = [super shadowOpacity];
_shadowRadius = [super shadowRadius];
@@ -140,10 +137,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
- (void)dealloc
{
if (_shadowColor != NULL) {
CGColorRelease(_shadowColor);
}
CGColorRelease(_shadowColor);
[self _invalidateRenderer];
if (_longPressGestureRecognizer) {
@@ -548,9 +543,6 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
CGContextTranslateCTM(context, _textContainerInset.left, _textContainerInset.top);
ASTextKitRenderer *renderer = [self _rendererWithBounds:drawParameterBounds];
UIEdgeInsets shadowPadding = [self shadowPaddingWithRenderer:renderer];
CGPoint boundsOrigin = drawParameterBounds.origin;
CGPoint textOrigin = CGPointMake(boundsOrigin.x - shadowPadding.left, boundsOrigin.y - shadowPadding.top);
// Fill background
if (backgroundColor != nil) {
@@ -558,12 +550,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
UIRectFillUsingBlendMode(CGContextGetClipBoundingBox(context), kCGBlendModeCopy);
}
// Draw shadow
[renderer.shadower setShadowInContext:context];
// Draw text
bounds.origin = textOrigin;
[renderer drawInContext:context bounds:bounds];
[renderer drawInContext:context bounds:drawParameterBounds];
CGContextRestoreGState(context);
}
@@ -1133,14 +1121,9 @@ static CGRect ASTextNodeAdjustRenderRectForShadowPadding(CGRect rendererRect, UI
{
ASDN::MutexLocker l(__instanceLock__);
if (_shadowColor != shadowColor) {
if (shadowColor != NULL) {
CGColorRetain(shadowColor);
}
if (_shadowColor != NULL) {
CGColorRelease(_shadowColor);
}
_shadowColor = shadowColor;
if (_shadowColor != shadowColor && CGColorEqualToColor(shadowColor, _shadowColor) == NO) {
CGColorRelease(_shadowColor);
_shadowColor = CGColorRetain(shadowColor);
_cachedShadowUIColor = [UIColor colorWithCGColor:shadowColor];
[self _invalidateRenderer];
[self setNeedsDisplay];

View File

@@ -59,7 +59,7 @@ struct ASTextKitAttributes {
/**
An array of UIBezierPath objects representing the exclusion paths inside the receiver's bounding rectangle. Default value: nil.
*/
NSArray *exclusionPaths;
NSArray<UIBezierPath *> *exclusionPaths;
/**
The shadow offset for any shadows applied to the text. The coordinate space for this is the same as UIKit, so a
positive width means towards the right, and a positive height means towards the bottom.

View File

@@ -68,10 +68,10 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
{
if (!_shadower) {
ASTextKitAttributes attributes = _attributes;
_shadower = [[ASTextKitShadower alloc] initWithShadowOffset:attributes.shadowOffset
shadowColor:attributes.shadowColor
shadowOpacity:attributes.shadowOpacity
shadowRadius:attributes.shadowRadius];
_shadower = [ASTextKitShadower shadowerWithShadowOffset:attributes.shadowOffset
shadowColor:attributes.shadowColor
shadowOpacity:attributes.shadowOpacity
shadowRadius:attributes.shadowRadius];
}
return _shadower;
}

View File

@@ -15,10 +15,10 @@
*/
@interface ASTextKitShadower : NSObject
- (instancetype)initWithShadowOffset:(CGSize)shadowOffset
shadowColor:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius;
+ (ASTextKitShadower *)shadowerWithShadowOffset:(CGSize)shadowOffset
shadowColor:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius;
/**
* @abstract The offset from the top-left corner at which the shadow starts.

View File

@@ -14,7 +14,9 @@
static inline CGSize _insetSize(CGSize size, UIEdgeInsets insets)
{
return UIEdgeInsetsInsetRect({.size = size}, insets).size;
size.width -= (insets.left + insets.right);
size.height -= (insets.top + insets.bottom);
return size;
}
static inline UIEdgeInsets _invertInsets(UIEdgeInsets insets)
@@ -31,6 +33,28 @@ static inline UIEdgeInsets _invertInsets(UIEdgeInsets insets)
UIEdgeInsets _calculatedShadowPadding;
}
+ (ASTextKitShadower *)shadowerWithShadowOffset:(CGSize)shadowOffset
shadowColor:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius
{
/**
* For all cases where no shadow is drawn, we share this singleton shadower to save resources.
*/
static dispatch_once_t onceToken;
static ASTextKitShadower *sharedNonShadower;
dispatch_once(&onceToken, ^{
sharedNonShadower = [[ASTextKitShadower alloc] initWithShadowOffset:CGSizeZero shadowColor:nil shadowOpacity:0 shadowRadius:0];
});
BOOL hasShadow = shadowOpacity > 0 && (shadowRadius > 0 || CGSizeEqualToSize(shadowOffset, CGSizeZero) == NO) && CGColorGetAlpha(shadowColor.CGColor) > 0;
if (hasShadow == NO) {
return sharedNonShadower;
} else {
return [[ASTextKitShadower alloc] initWithShadowOffset:shadowOffset shadowColor:shadowColor shadowOpacity:shadowOpacity shadowRadius:shadowRadius];
}
}
- (instancetype)initWithShadowOffset:(CGSize)shadowOffset
shadowColor:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
@@ -52,7 +76,7 @@ static inline UIEdgeInsets _invertInsets(UIEdgeInsets insets)
*/
- (BOOL)_shouldDrawShadow
{
return _shadowOpacity != 0.0 && _shadowColor != nil && (_shadowRadius != 0 || !CGSizeEqualToSize(_shadowOffset, CGSizeZero));
return _shadowOpacity != 0.0 && (_shadowRadius != 0 || !CGSizeEqualToSize(_shadowOffset, CGSizeZero)) && CGColorGetAlpha(_shadowColor.CGColor) > 0;
}
- (void)setShadowInContext:(CGContextRef)context

View File

@@ -92,4 +92,16 @@
ASSnapshotVerifyNode(textNode, nil);
}
- (void)testShadowing
{
ASTextNode *textNode = [[ASTextNode alloc] init];
textNode.attributedText = [[NSAttributedString alloc] initWithString:@"Quality is Important"];
textNode.shadowColor = [UIColor blackColor].CGColor;
textNode.shadowOpacity = 0.3;
textNode.shadowRadius = 3;
textNode.shadowOffset = CGSizeMake(0, 1);
[textNode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX))];
ASSnapshotVerifyNode(textNode, nil);
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB