mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-15 18:59:54 +00:00
Adds support for using UIGraphicsImageRenderer in ASTextNode. (#1384)
* Adds support for using UIGraphicsImageRenderer in ASTextNode. In many cases this reduces the backing store of text nodes by 1/2. * Guard for UIGraphicsRenderer availability. * Comma
This commit is contained in:
parent
872e89b772
commit
9b80eabd8f
@ -26,7 +26,8 @@
|
||||
"exp_skip_a11y_wait",
|
||||
"exp_new_default_cell_layout_mode",
|
||||
"exp_dispatch_apply",
|
||||
"exp_image_downloader_priority"
|
||||
"exp_image_downloader_priority",
|
||||
"exp_text_drawing"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ typedef NS_OPTIONS(NSUInteger, ASExperimentalFeatures) {
|
||||
ASExperimentalNewDefaultCellLayoutMode = 1 << 11, // exp_new_default_cell_layout_mode
|
||||
ASExperimentalDispatchApply = 1 << 12, // exp_dispatch_apply
|
||||
ASExperimentalImageDownloaderPriority = 1 << 13, // exp_image_downloader_priority
|
||||
ASExperimentalTextDrawing = 1 << 14, // exp_text_drawing
|
||||
ASExperimentalFeatureAll = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ NSArray<NSString *> *ASExperimentalFeaturesGetNames(ASExperimentalFeatures flags
|
||||
@"exp_skip_a11y_wait",
|
||||
@"exp_new_default_cell_layout_mode",
|
||||
@"exp_dispatch_apply",
|
||||
@"exp_image_downloader_priority"]));
|
||||
|
||||
@"exp_image_downloader_priority",
|
||||
@"exp_text_drawing"]));
|
||||
if (flags == ASExperimentalFeatureAll) {
|
||||
return allNames;
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#import <mutex>
|
||||
#import <tgmath.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASAvailability.h>
|
||||
#import <AsyncDisplayKit/_ASDisplayLayer.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
|
||||
@ -140,6 +141,9 @@ static ASTextKitRenderer *rendererForAttributes(ASTextKitAttributes attributes,
|
||||
ASTextKitAttributes _rendererAttributes;
|
||||
UIColor *_backgroundColor;
|
||||
UIEdgeInsets _textContainerInsets;
|
||||
CGFloat _contentScale;
|
||||
BOOL _opaque;
|
||||
CGRect _bounds;
|
||||
}
|
||||
@end
|
||||
|
||||
@ -148,12 +152,18 @@ static ASTextKitRenderer *rendererForAttributes(ASTextKitAttributes attributes,
|
||||
- (instancetype)initWithRendererAttributes:(ASTextKitAttributes)rendererAttributes
|
||||
backgroundColor:(/*nullable*/ UIColor *)backgroundColor
|
||||
textContainerInsets:(UIEdgeInsets)textContainerInsets
|
||||
contentScale:(CGFloat)contentScale
|
||||
opaque:(BOOL)opaque
|
||||
bounds:(CGRect)bounds
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_rendererAttributes = rendererAttributes;
|
||||
_backgroundColor = backgroundColor;
|
||||
_textContainerInsets = textContainerInsets;
|
||||
_contentScale = contentScale;
|
||||
_opaque = opaque;
|
||||
_bounds = bounds;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -526,31 +536,74 @@ static NSArray *DefaultLinkAttributeNames() {
|
||||
|
||||
return [[ASTextNodeDrawParameter alloc] initWithRendererAttributes:[self _locked_rendererAttributes]
|
||||
backgroundColor:self.backgroundColor
|
||||
textContainerInsets:_textContainerInset];
|
||||
textContainerInsets:_textContainerInset
|
||||
contentScale:_contentsScaleForDisplay
|
||||
opaque:self.isOpaque
|
||||
bounds:[self threadSafeBounds]];
|
||||
}
|
||||
|
||||
+ (void)drawRect:(CGRect)bounds withParameters:(id)parameters isCancelled:(NS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing
|
||||
+ (UIImage *)displayWithParameters:(id<NSObject>)parameters isCancelled:(NS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelled
|
||||
{
|
||||
ASTextNodeDrawParameter *drawParameter = (ASTextNodeDrawParameter *)parameters;
|
||||
UIColor *backgroundColor = (isRasterizing || drawParameter == nil) ? nil : drawParameter->_backgroundColor;
|
||||
|
||||
if (drawParameter->_bounds.size.width <= 0 || drawParameter->_bounds.size.height <= 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIImage *result = nil;
|
||||
UIColor *backgroundColor = drawParameter->_backgroundColor;
|
||||
UIEdgeInsets textContainerInsets = drawParameter ? drawParameter->_textContainerInsets : UIEdgeInsetsZero;
|
||||
ASTextKitRenderer *renderer = [drawParameter rendererForBounds:bounds];
|
||||
ASTextKitRenderer *renderer = [drawParameter rendererForBounds:drawParameter->_bounds];
|
||||
BOOL renderedWithGraphicsRenderer = NO;
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
ASDisplayNodeAssert(context, @"This is no good without a context.");
|
||||
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, textContainerInsets.left, textContainerInsets.top);
|
||||
|
||||
// Fill background
|
||||
if (backgroundColor != nil) {
|
||||
[backgroundColor setFill];
|
||||
UIRectFillUsingBlendMode(CGContextGetClipBoundingBox(context), kCGBlendModeCopy);
|
||||
if (AS_AVAILABLE_IOS_TVOS(10, 10)) {
|
||||
if (ASActivateExperimentalFeature(ASExperimentalTextDrawing)) {
|
||||
renderedWithGraphicsRenderer = YES;
|
||||
UIGraphicsImageRenderer *graphicsRenderer = [[UIGraphicsImageRenderer alloc] initWithSize:CGSizeMake(drawParameter->_bounds.size.width, drawParameter->_bounds.size.height)];
|
||||
result = [graphicsRenderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
|
||||
CGContextRef context = rendererContext.CGContext;
|
||||
ASDisplayNodeAssert(context, @"This is no good without a context.");
|
||||
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, textContainerInsets.left, textContainerInsets.top);
|
||||
|
||||
// Fill background
|
||||
if (backgroundColor != nil) {
|
||||
[backgroundColor setFill];
|
||||
UIRectFillUsingBlendMode(CGContextGetClipBoundingBox(context), kCGBlendModeCopy);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
[renderer drawInContext:context bounds:drawParameter->_bounds];
|
||||
CGContextRestoreGState(context);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
// Draw text
|
||||
[renderer drawInContext:context bounds:bounds];
|
||||
CGContextRestoreGState(context);
|
||||
if (!renderedWithGraphicsRenderer) {
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(drawParameter->_bounds.size.width, drawParameter->_bounds.size.height), drawParameter->_opaque, drawParameter->_contentScale);
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
ASDisplayNodeAssert(context, @"This is no good without a context.");
|
||||
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, textContainerInsets.left, textContainerInsets.top);
|
||||
|
||||
// Fill background
|
||||
if (backgroundColor != nil) {
|
||||
[backgroundColor setFill];
|
||||
UIRectFillUsingBlendMode(CGContextGetClipBoundingBox(context), kCGBlendModeCopy);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
[renderer drawInContext:context bounds:drawParameter->_bounds];
|
||||
CGContextRestoreGState(context);
|
||||
|
||||
result = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark - Attributes
|
||||
|
||||
@ -112,7 +112,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@summary Delegate override to provide new layer contents as a UIImage.
|
||||
@param parameters An object describing all of the properties you need to draw. Return this from -drawParametersForAsyncLayer:
|
||||
@param isCancelledBlock Execute this block to check whether the current drawing operation has been cancelled to avoid unnecessary work. A return value of YES means cancel drawing and return.
|
||||
@return A UIImage with contents that are ready to display on the main thread. Make sure that the image is already decoded before returning it here.
|
||||
@return A UIImage (backed by a CGImage) with contents that are ready to display on the main thread. Make sure that the image is already decoded before returning it here.
|
||||
*/
|
||||
+ (UIImage *)displayWithParameters:(nullable id<NSObject>)parameters
|
||||
isCancelled:(AS_NOESCAPE asdisplaynode_iscancelled_block_t)isCancelledBlock;
|
||||
|
||||
@ -31,7 +31,8 @@ static ASExperimentalFeatures features[] = {
|
||||
ASExperimentalSkipAccessibilityWait,
|
||||
ASExperimentalNewDefaultCellLayoutMode,
|
||||
ASExperimentalDispatchApply,
|
||||
ASExperimentalImageDownloaderPriority
|
||||
ASExperimentalImageDownloaderPriority,
|
||||
ASExperimentalTextDrawing
|
||||
};
|
||||
|
||||
@interface ASConfigurationTests : ASTestCase <ASConfigurationDelegate>
|
||||
@ -57,7 +58,8 @@ static ASExperimentalFeatures features[] = {
|
||||
@"exp_skip_a11y_wait",
|
||||
@"exp_new_default_cell_layout_mode",
|
||||
@"exp_dispatch_apply",
|
||||
@"exp_image_downloader_priority"
|
||||
@"exp_image_downloader_priority",
|
||||
@"exp_text_drawing"
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user