mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-03-21 14:50:24 +00:00
[AsyncDisplayKit+Utilities.h] Convenience methods for creating resizable circles & rounded rects. (#1811)
* [AsyncDisplayKit+Utilities.h] UIImage category for performant (optionally rounded) flat color stretchable images * treat clear background color as no background color (D99117) * add borderWidth * add several shorter methods per Scott's comment * rename files and add to AsyncDisplayKit.h * fix xcode project file * update commentse
This commit is contained in:
@@ -75,15 +75,17 @@
|
||||
#import <AsyncDisplayKit/ASLog.h>
|
||||
#import <AsyncDisplayKit/ASMutableAttributedStringBuilder.h>
|
||||
#import <AsyncDisplayKit/ASThread.h>
|
||||
#import <AsyncDisplayKit/CGRect+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.h>
|
||||
#import <AsyncDisplayKit/UICollectionViewLayout+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/UIView+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/ASRunLoopQueue.h>
|
||||
#import <AsyncDisplayKit/ASTextKitComponents.h>
|
||||
#import <AsyncDisplayKit/ASTraitCollection.h>
|
||||
#import <AsyncDisplayKit/ASVisibilityProtocols.h>
|
||||
|
||||
#import <AsyncDisplayKit/CGRect+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/NSMutableAttributedString+TextKitAdditions.h>
|
||||
#import <AsyncDisplayKit/UICollectionViewLayout+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/UIView+ASConvenience.h>
|
||||
#import <AsyncDisplayKit/UIImage+ASConvenience.h>
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASCollectionNode+Beta.h>
|
||||
|
||||
71
AsyncDisplayKit/UIImage+ASConvenience.h
Normal file
71
AsyncDisplayKit/UIImage+ASConvenience.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// UIImage+ASConvenience.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 6/24/16.
|
||||
//
|
||||
// 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 root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import <UIKit/UIImage.h>
|
||||
#import <UIKit/UIBezierPath.h>
|
||||
|
||||
// High-performance flat-colored, rounded-corner resizable images
|
||||
//
|
||||
// For "Baked-in Opaque" corners, set cornerColor equal to the color behind the rounded image object, e.g. the background color.
|
||||
// For "Baked-in Alpha" corners, set cornerColor = [UIColor clearColor]
|
||||
//
|
||||
// See http://asyncdisplaykit.org/docs/corner-rounding.html for an explanation.
|
||||
|
||||
@interface UIImage (ASDKAdditions)
|
||||
|
||||
/**
|
||||
* This generates a flat-color, rounded-corner resizeable image
|
||||
*
|
||||
* @param cornerRadius The radius of the rounded-corner
|
||||
* @param cornerColor The fill color of the corners (For Alpha corners use clearColor)
|
||||
* @param fillColor The fill color of the rounded-corner image
|
||||
*/
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor;
|
||||
|
||||
/**
|
||||
* This generates a flat-color, rounded-corner resizeable image with a border
|
||||
*
|
||||
* @param cornerRadius The radius of the rounded-corner
|
||||
* @param cornerColor The fill color of the corners (For Alpha corners use clearColor)
|
||||
* @param fillColor The fill color of the rounded-corner image
|
||||
* @param borderColor The border color. Set to nil for no border.
|
||||
* @param borderWidth The border width. Dummy value if borderColor = nil.
|
||||
*/
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor
|
||||
borderColor:(UIColor *)borderColor
|
||||
borderWidth:(CGFloat)borderWidth;
|
||||
|
||||
/**
|
||||
* This generates a flat-color, rounded-corner resizeable image with a border
|
||||
*
|
||||
* @param cornerRadius The radius of the rounded-corner
|
||||
* @param cornerColor The fill color of the corners (For Alpha corners use clearColor)
|
||||
* @param fillColor The fill color of the rounded-corner image
|
||||
* @param borderColor The border color. Set to nil for no border.
|
||||
* @param borderWidth The border width. Dummy value if borderColor = nil.
|
||||
* @param roundedCorners Select individual or multiple corners to round. Set to UIRectCornerAllCorners to round all 4 corners.
|
||||
* @param scale The number of pixels per point. Provide 0.0 to use the screen scale.
|
||||
*/
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor
|
||||
borderColor:(UIColor *)borderColor
|
||||
borderWidth:(CGFloat)borderWidth
|
||||
roundedCorners:(UIRectCorner)roundedCorners
|
||||
scale:(CGFloat)scale;
|
||||
|
||||
@end
|
||||
|
||||
131
AsyncDisplayKit/UIImage+ASConvenience.m
Normal file
131
AsyncDisplayKit/UIImage+ASConvenience.m
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// UIImage+ASConvenience.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Hannah Troisi on 6/24/16.
|
||||
//
|
||||
// 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 root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import "UIImage+ASConvenience.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@implementation UIImage (ASDKAdditions)
|
||||
|
||||
|
||||
|
||||
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor
|
||||
{
|
||||
return [self as_resizableRoundedImageWithCornerRadius:cornerRadius
|
||||
cornerColor:cornerColor
|
||||
fillColor:fillColor
|
||||
borderColor:nil
|
||||
borderWidth:1.0
|
||||
roundedCorners:UIRectCornerAllCorners
|
||||
scale:0.0];
|
||||
}
|
||||
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor
|
||||
borderColor:(UIColor *)borderColor
|
||||
borderWidth:(CGFloat)borderWidth
|
||||
{
|
||||
return [self as_resizableRoundedImageWithCornerRadius:cornerRadius
|
||||
cornerColor:cornerColor
|
||||
fillColor:fillColor
|
||||
borderColor:borderColor
|
||||
borderWidth:borderWidth
|
||||
roundedCorners:UIRectCornerAllCorners
|
||||
scale:0.0];
|
||||
}
|
||||
|
||||
+ (UIImage *)as_resizableRoundedImageWithCornerRadius:(CGFloat)cornerRadius
|
||||
cornerColor:(UIColor *)cornerColor
|
||||
fillColor:(UIColor *)fillColor
|
||||
borderColor:(UIColor *)borderColor
|
||||
borderWidth:(CGFloat)borderWidth
|
||||
roundedCorners:(UIRectCorner)roundedCorners
|
||||
scale:(CGFloat)scale
|
||||
{
|
||||
static NSCache *__pathCache = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
__pathCache = [[NSCache alloc] init];
|
||||
// UIBezierPath objects are fairly small and these are equally sized. 20 should be plenty for many different parameters.
|
||||
__pathCache.countLimit = 20;
|
||||
});
|
||||
|
||||
// Treat clear background color as no background color
|
||||
if ([cornerColor isEqual:[UIColor clearColor]]) {
|
||||
cornerColor = nil;
|
||||
}
|
||||
|
||||
CGFloat dimension = (cornerRadius * 2) + 1;
|
||||
CGRect bounds = CGRectMake(0, 0, dimension, dimension);
|
||||
|
||||
// This is a hack to make one NSNumber key out of the corners and cornerRadius
|
||||
if (roundedCorners == UIRectCornerAllCorners) {
|
||||
// UIRectCornerAllCorners is ~0, but below is equivalent and we can pack it into half an NSUInteger
|
||||
roundedCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight;
|
||||
}
|
||||
// Left half of NSUInteger is roundedCorners, right half is cornerRadius
|
||||
UInt64 pathKeyNSUInteger = (UInt64)roundedCorners << sizeof(Float32) * 8;
|
||||
Float32 floatCornerRadius = cornerRadius;
|
||||
pathKeyNSUInteger |= (NSUInteger)floatCornerRadius;
|
||||
|
||||
NSNumber *pathKey = [NSNumber numberWithUnsignedLongLong:pathKeyNSUInteger];
|
||||
|
||||
UIBezierPath *path = nil;
|
||||
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
|
||||
|
||||
@synchronized(__pathCache) {
|
||||
path = [__pathCache objectForKey:pathKey];
|
||||
if (!path) {
|
||||
path = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:roundedCorners cornerRadii:cornerRadii];
|
||||
[__pathCache setObject:path forKey:pathKey];
|
||||
}
|
||||
}
|
||||
|
||||
// We should probably check if the background color has any alpha component but that
|
||||
// might be expensive due to needing to check mulitple color spaces.
|
||||
UIGraphicsBeginImageContextWithOptions(bounds.size, cornerColor != nil, scale);
|
||||
|
||||
if (cornerColor) {
|
||||
[cornerColor setFill];
|
||||
// Copy "blend" mode is extra fast because it disregards any value currently in the buffer and overwrites directly.
|
||||
UIRectFillUsingBlendMode(bounds, kCGBlendModeCopy);
|
||||
}
|
||||
|
||||
[fillColor setFill];
|
||||
[path fill];
|
||||
|
||||
if (borderColor) {
|
||||
[borderColor setStroke];
|
||||
|
||||
// Inset border fully inside filled path (not halfway on each side of path)
|
||||
CGRect strokeRect = CGRectInset(bounds, borderWidth / 2.0, borderWidth / 2.0);
|
||||
|
||||
// It is rarer to have a stroke path, and our cache key only handles rounded rects for the exact-stretchable
|
||||
// size calculated by cornerRadius, so we won't bother caching this path. Profiling validates this decision.
|
||||
UIBezierPath *strokePath = [UIBezierPath bezierPathWithRoundedRect:strokeRect cornerRadius:cornerRadius];
|
||||
[strokePath setLineWidth:borderWidth];
|
||||
[strokePath stroke];
|
||||
}
|
||||
|
||||
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
UIEdgeInsets capInsets = UIEdgeInsetsMake(cornerRadius, cornerRadius, cornerRadius, cornerRadius);
|
||||
result = [result resizableImageWithCapInsets:capInsets resizingMode:UIImageResizingModeStretch];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user